]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge remote-tracking branch 'edac-amd/for-next'
authorStephen Rothwell <sfr@canb.auug.org.au>
Thu, 12 Dec 2013 02:51:45 +0000 (13:51 +1100)
committerStephen Rothwell <sfr@canb.auug.org.au>
Thu, 12 Dec 2013 02:51:45 +0000 (13:51 +1100)
3251 files changed:
CREDITS
Documentation/DocBook/.gitignore
Documentation/DocBook/Makefile
Documentation/DocBook/kernel-api.tmpl
Documentation/DocBook/media/v4l/media-ioc-enum-links.xml
Documentation/DocBook/media/v4l/vidioc-expbuf.xml
Documentation/IRQ-domain.txt
Documentation/acpi/namespace.txt
Documentation/block/biodoc.txt
Documentation/block/biovecs.txt [new file with mode: 0644]
Documentation/cgroups/cgroups.txt
Documentation/device-mapper/cache.txt
Documentation/devicetree/bindings/arm/arm-boards
Documentation/devicetree/bindings/arm/atmel-aic.txt
Documentation/devicetree/bindings/arm/atmel-at91.txt
Documentation/devicetree/bindings/arm/gic.txt
Documentation/devicetree/bindings/arm/omap/mpu.txt
Documentation/devicetree/bindings/arm/pmu.txt
Documentation/devicetree/bindings/arm/samsung/exynos-adc.txt
Documentation/devicetree/bindings/ata/sata_rcar.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/at91-clock.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/exynos4-clock.txt
Documentation/devicetree/bindings/clock/exynos5250-clock.txt
Documentation/devicetree/bindings/clock/exynos5420-clock.txt
Documentation/devicetree/bindings/clock/exynos5440-clock.txt
Documentation/devicetree/bindings/clock/imx5-clock.txt
Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt
Documentation/devicetree/bindings/dma/ste-dma40.txt
Documentation/devicetree/bindings/gpio/8xxx_gpio.txt
Documentation/devicetree/bindings/gpio/gpio-lp3943.txt [new file with mode: 0644]
Documentation/devicetree/bindings/input/gpio-beeper.txt [new file with mode: 0644]
Documentation/devicetree/bindings/input/touchscreen/tsc2007.txt [new file with mode: 0644]
Documentation/devicetree/bindings/input/twl4030-pwrbutton.txt [new file with mode: 0644]
Documentation/devicetree/bindings/interrupt-controller/marvell,dove-pmu-intc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mfd/lp3943.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
Documentation/devicetree/bindings/mmc/ti-omap.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mtd/gpmi-nand.txt
Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt
Documentation/devicetree/bindings/net/davinci_emac.txt
Documentation/devicetree/bindings/net/fsl-fec.txt
Documentation/devicetree/bindings/net/phy.txt
Documentation/devicetree/bindings/net/smsc-lan91c111.txt
Documentation/devicetree/bindings/pinctrl/fsl,imx27-pinctrl.txt
Documentation/devicetree/bindings/pwm/pwm-lp3943.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/adi,axi-i2s.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/adi,axi-spdif-tx.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/bcm2835-i2s.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/cs42l52.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt
Documentation/devicetree/bindings/sound/max98090.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/nvidia,tegra-audio-max98090.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/simple-card.txt [new file with mode: 0644]
Documentation/devicetree/bindings/spi/nvidia,tegra20-spi.txt [deleted file]
Documentation/devicetree/bindings/spi/spi-bus.txt
Documentation/devicetree/bindings/tty/serial/renesas,sci-serial.txt [new file with mode: 0644]
Documentation/devicetree/bindings/vendor-prefixes.txt
Documentation/email-clients.txt
Documentation/filesystems/nfs/nfs41-server.txt
Documentation/gpio/00-INDEX [new file with mode: 0644]
Documentation/hwmon/it87
Documentation/io-mapping.txt
Documentation/kernel-parameters.txt
Documentation/kmsg/s390/zcrypt [new file with mode: 0644]
Documentation/md.txt
Documentation/memory-barriers.txt
Documentation/mic/mpssd/mpssd.c
Documentation/module-signing.txt [new file with mode: 0644]
Documentation/mtd/nand/pxa3xx-nand.txt [new file with mode: 0644]
Documentation/networking/ip-sysctl.txt
Documentation/networking/packet_mmap.txt
Documentation/networking/phy.txt
Documentation/networking/regulatory.txt
Documentation/networking/timestamping.txt
Documentation/networking/timestamping/.gitignore
Documentation/networking/timestamping/Makefile
Documentation/networking/timestamping/hwtstamp_config.c [new file with mode: 0644]
Documentation/rfkill.txt
Documentation/robust-futex-ABI.txt
Documentation/rt-mutex-design.txt
Documentation/spi/spi-summary
Documentation/static-keys.txt
Documentation/unaligned-memory-access.txt
Documentation/video4linux/omap4_camera.txt [new file with mode: 0644]
Documentation/x86/x86_64/boot-options.txt
Documentation/x86/x86_64/mm.txt
Documentation/zorro.txt
MAINTAINERS
Makefile
arch/arc/Kconfig
arch/arc/include/asm/smp.h
arch/arc/include/uapi/asm/unistd.h
arch/arc/kernel/perf_event.c
arch/arc/kernel/smp.c
arch/arc/plat-arcfpga/smp.c
arch/arm/Kconfig
arch/arm/Kconfig.debug
arch/arm/Makefile
arch/arm/arm-soc-for-next-contents.txt [new file with mode: 0644]
arch/arm/boot/compressed/Makefile
arch/arm/boot/dts/Makefile
arch/arm/boot/dts/am335x-base0033.dts
arch/arm/boot/dts/am335x-igep0033.dtsi
arch/arm/boot/dts/am3517-evm.dts
arch/arm/boot/dts/am3517.dtsi [new file with mode: 0644]
arch/arm/boot/dts/animeo_ip.dts
arch/arm/boot/dts/armada-370-db.dts
arch/arm/boot/dts/armada-370-mirabox.dts
arch/arm/boot/dts/armada-370-netgear-rn102.dts
arch/arm/boot/dts/armada-370-netgear-rn104.dts
arch/arm/boot/dts/armada-370-xp.dtsi
arch/arm/boot/dts/armada-xp-gp.dts
arch/arm/boot/dts/armada-xp-mv78230.dtsi
arch/arm/boot/dts/armada-xp-mv78260.dtsi
arch/arm/boot/dts/armada-xp-netgear-rn2120.dts [new file with mode: 0644]
arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts
arch/arm/boot/dts/at91-cosino.dtsi [new file with mode: 0644]
arch/arm/boot/dts/at91-cosino_mega2560.dts [new file with mode: 0644]
arch/arm/boot/dts/at91rm9200.dtsi
arch/arm/boot/dts/at91rm9200ek.dts
arch/arm/boot/dts/at91sam9263.dtsi
arch/arm/boot/dts/at91sam9263ek.dts
arch/arm/boot/dts/at91sam9g45.dtsi
arch/arm/boot/dts/at91sam9m10g45ek.dts
arch/arm/boot/dts/at91sam9x5_usart3.dtsi
arch/arm/boot/dts/bcm2835-rpi-b.dts
arch/arm/boot/dts/bcm2835.dtsi
arch/arm/boot/dts/cros5250-common.dtsi
arch/arm/boot/dts/dove-cubox.dts
arch/arm/boot/dts/dove.dtsi
arch/arm/boot/dts/emev2-kzm9d.dts
arch/arm/boot/dts/emev2.dtsi
arch/arm/boot/dts/exynos5.dtsi
arch/arm/boot/dts/exynos5250-arndale.dts
arch/arm/boot/dts/exynos5250-smdk5250.dts
arch/arm/boot/dts/exynos5250-snow.dts
arch/arm/boot/dts/exynos5250.dtsi
arch/arm/boot/dts/exynos5420-smdk5420.dts
arch/arm/boot/dts/exynos5420.dtsi
arch/arm/boot/dts/imx23-evk.dts
arch/arm/boot/dts/imx23-olinuxino.dts
arch/arm/boot/dts/imx23-stmp378x_devb.dts
arch/arm/boot/dts/imx25-eukrea-cpuimx25.dtsi [new file with mode: 0644]
arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard.dts [new file with mode: 0644]
arch/arm/boot/dts/imx25-pinfunc.h [new file with mode: 0644]
arch/arm/boot/dts/imx25-pingrp.h [new file with mode: 0644]
arch/arm/boot/dts/imx25.dtsi
arch/arm/boot/dts/imx27-apf27.dts
arch/arm/boot/dts/imx27-apf27dev.dts
arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts
arch/arm/boot/dts/imx27-phytec-phycard-s-som.dts
arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts
arch/arm/boot/dts/imx27-phytec-phycore-som.dtsi [moved from arch/arm/boot/dts/imx27-phytec-phycore-som.dts with 77% similarity]
arch/arm/boot/dts/imx27-pinfunc.h [new file with mode: 0644]
arch/arm/boot/dts/imx27-pingrp.h [new file with mode: 0644]
arch/arm/boot/dts/imx27.dtsi
arch/arm/boot/dts/imx28-apf28dev.dts
arch/arm/boot/dts/imx28-apx4devkit.dts
arch/arm/boot/dts/imx28-cfa10036.dts
arch/arm/boot/dts/imx28-cfa10037.dts
arch/arm/boot/dts/imx28-cfa10049.dts
arch/arm/boot/dts/imx28-cfa10057.dts
arch/arm/boot/dts/imx28-cfa10058.dts
arch/arm/boot/dts/imx28-duckbill.dts [new file with mode: 0644]
arch/arm/boot/dts/imx28-eukrea-mbmx283lc.dts [new file with mode: 0644]
arch/arm/boot/dts/imx28-eukrea-mbmx287lc.dts [new file with mode: 0644]
arch/arm/boot/dts/imx28-eukrea-mbmx28lc.dtsi [new file with mode: 0644]
arch/arm/boot/dts/imx28-evk.dts
arch/arm/boot/dts/imx28-m28cu3.dts
arch/arm/boot/dts/imx28-m28evk.dts
arch/arm/boot/dts/imx28-sps1.dts
arch/arm/boot/dts/imx28-tx28.dts
arch/arm/boot/dts/imx28.dtsi
arch/arm/boot/dts/imx50-evk.dts [new file with mode: 0644]
arch/arm/boot/dts/imx50-pinfunc.h [new file with mode: 0644]
arch/arm/boot/dts/imx50-pingrp.h [new file with mode: 0644]
arch/arm/boot/dts/imx50.dtsi [new file with mode: 0644]
arch/arm/boot/dts/imx51-apf51.dts
arch/arm/boot/dts/imx51-apf51dev.dts
arch/arm/boot/dts/imx51-babbage.dts
arch/arm/boot/dts/imx51-eukrea-cpuimx51.dtsi [new file with mode: 0644]
arch/arm/boot/dts/imx51-eukrea-mbimxsd51-baseboard.dts [new file with mode: 0644]
arch/arm/boot/dts/imx51-pingrp.h [new file with mode: 0644]
arch/arm/boot/dts/imx51.dtsi
arch/arm/boot/dts/imx53-ard.dts
arch/arm/boot/dts/imx53-evk.dts
arch/arm/boot/dts/imx53-m53evk.dts
arch/arm/boot/dts/imx53-mba53.dts
arch/arm/boot/dts/imx53-pingrp.h [new file with mode: 0644]
arch/arm/boot/dts/imx53-qsb.dts
arch/arm/boot/dts/imx53-smd.dts
arch/arm/boot/dts/imx53-tqma53.dtsi
arch/arm/boot/dts/imx53-tx53.dtsi
arch/arm/boot/dts/imx53-voipac-bsb.dts [new file with mode: 0644]
arch/arm/boot/dts/imx53-voipac-dmm-668.dtsi [new file with mode: 0644]
arch/arm/boot/dts/imx53.dtsi
arch/arm/boot/dts/imx6dl-gw51xx.dts [new file with mode: 0644]
arch/arm/boot/dts/imx6dl-gw52xx.dts [new file with mode: 0644]
arch/arm/boot/dts/imx6dl-gw53xx.dts [new file with mode: 0644]
arch/arm/boot/dts/imx6dl-gw54xx.dts [new file with mode: 0644]
arch/arm/boot/dts/imx6dl-pinfunc.h
arch/arm/boot/dts/imx6dl.dtsi
arch/arm/boot/dts/imx6q-arm2.dts
arch/arm/boot/dts/imx6q-cm-fx6.dts [new file with mode: 0644]
arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts [new file with mode: 0644]
arch/arm/boot/dts/imx6q-gw51xx.dts [new file with mode: 0644]
arch/arm/boot/dts/imx6q-gw52xx.dts [new file with mode: 0644]
arch/arm/boot/dts/imx6q-gw53xx.dts [new file with mode: 0644]
arch/arm/boot/dts/imx6q-gw5400-a.dts [new file with mode: 0644]
arch/arm/boot/dts/imx6q-gw54xx.dts [new file with mode: 0644]
arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi
arch/arm/boot/dts/imx6q-pinfunc.h
arch/arm/boot/dts/imx6q-sabrelite.dts
arch/arm/boot/dts/imx6q-sbc6x.dts
arch/arm/boot/dts/imx6q-udoo.dts
arch/arm/boot/dts/imx6q.dtsi
arch/arm/boot/dts/imx6qdl-gw51xx.dtsi [new file with mode: 0644]
arch/arm/boot/dts/imx6qdl-gw52xx.dtsi [new file with mode: 0644]
arch/arm/boot/dts/imx6qdl-gw53xx.dtsi [new file with mode: 0644]
arch/arm/boot/dts/imx6qdl-gw54xx.dtsi [new file with mode: 0644]
arch/arm/boot/dts/imx6qdl-pingrp.h [new file with mode: 0644]
arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
arch/arm/boot/dts/imx6qdl-sabresd.dtsi
arch/arm/boot/dts/imx6qdl-wandboard.dtsi
arch/arm/boot/dts/imx6qdl.dtsi
arch/arm/boot/dts/imx6sl-evk.dts
arch/arm/boot/dts/imx6sl-pingrp.h [new file with mode: 0644]
arch/arm/boot/dts/imx6sl.dtsi
arch/arm/boot/dts/integrator.dtsi
arch/arm/boot/dts/kirkwood-6281.dtsi
arch/arm/boot/dts/kirkwood-6282.dtsi
arch/arm/boot/dts/kirkwood-cloudbox.dts
arch/arm/boot/dts/kirkwood-db.dtsi
arch/arm/boot/dts/kirkwood-dns320.dts
arch/arm/boot/dts/kirkwood-dns325.dts
arch/arm/boot/dts/kirkwood-dnskw.dtsi
arch/arm/boot/dts/kirkwood-dockstar.dts
arch/arm/boot/dts/kirkwood-dreamplug.dts
arch/arm/boot/dts/kirkwood-goflexnet.dts
arch/arm/boot/dts/kirkwood-guruplug-server-plus.dts
arch/arm/boot/dts/kirkwood-ib62x0.dts
arch/arm/boot/dts/kirkwood-iconnect.dts
arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts
arch/arm/boot/dts/kirkwood-km_kirkwood.dts
arch/arm/boot/dts/kirkwood-lsxl.dtsi
arch/arm/boot/dts/kirkwood-mplcec4.dts
arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts
arch/arm/boot/dts/kirkwood-netgear_readynas_duo_v2.dts
arch/arm/boot/dts/kirkwood-netgear_readynas_nv+_v2.dts [new file with mode: 0644]
arch/arm/boot/dts/kirkwood-ns2-common.dtsi
arch/arm/boot/dts/kirkwood-ns2lite.dts
arch/arm/boot/dts/kirkwood-ns2max.dts
arch/arm/boot/dts/kirkwood-ns2mini.dts
arch/arm/boot/dts/kirkwood-nsa310-common.dtsi
arch/arm/boot/dts/kirkwood-nsa310.dts
arch/arm/boot/dts/kirkwood-nsa310a.dts
arch/arm/boot/dts/kirkwood-openblocks_a6.dts
arch/arm/boot/dts/kirkwood-openblocks_a7.dts
arch/arm/boot/dts/kirkwood-sheevaplug-common.dtsi
arch/arm/boot/dts/kirkwood-sheevaplug-esata.dts
arch/arm/boot/dts/kirkwood-sheevaplug.dts
arch/arm/boot/dts/kirkwood-topkick.dts
arch/arm/boot/dts/kirkwood-ts219-6281.dts
arch/arm/boot/dts/kirkwood-ts219-6282.dts
arch/arm/boot/dts/kirkwood.dtsi
arch/arm/boot/dts/omap-gpmc-smsc911x.dtsi
arch/arm/boot/dts/omap3-beagle-xm.dts
arch/arm/boot/dts/omap3-beagle.dts
arch/arm/boot/dts/omap3-igep.dtsi
arch/arm/boot/dts/omap3-igep0020.dts
arch/arm/boot/dts/omap3-igep0030.dts
arch/arm/boot/dts/omap3-n900.dts
arch/arm/boot/dts/omap3-n950-n9.dtsi
arch/arm/boot/dts/omap3.dtsi
arch/arm/boot/dts/omap34xx-hs.dtsi [new file with mode: 0644]
arch/arm/boot/dts/omap36xx-hs.dtsi [new file with mode: 0644]
arch/arm/boot/dts/omap4-panda-common.dtsi
arch/arm/boot/dts/omap4-sdp.dts
arch/arm/boot/dts/orion5x-lacie-ethernet-disk-mini-v2.dts
arch/arm/boot/dts/r7s72100-genmai-reference.dts [new file with mode: 0644]
arch/arm/boot/dts/r7s72100-genmai.dts
arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts
arch/arm/boot/dts/r8a73a4-ape6evm.dts
arch/arm/boot/dts/r8a73a4.dtsi
arch/arm/boot/dts/r8a7740-armadillo800eva-reference.dts
arch/arm/boot/dts/r8a7740-armadillo800eva.dts
arch/arm/boot/dts/r8a7740.dtsi
arch/arm/boot/dts/r8a7778-bockw-reference.dts
arch/arm/boot/dts/r8a7778-bockw.dts
arch/arm/boot/dts/r8a7778.dtsi
arch/arm/boot/dts/r8a7779-marzen-reference.dts
arch/arm/boot/dts/r8a7779-marzen.dts
arch/arm/boot/dts/r8a7779.dtsi
arch/arm/boot/dts/r8a7790-lager-reference.dts
arch/arm/boot/dts/r8a7790-lager.dts
arch/arm/boot/dts/r8a7790.dtsi
arch/arm/boot/dts/r8a7791-koelsch-reference.dts [new file with mode: 0644]
arch/arm/boot/dts/r8a7791-koelsch.dts
arch/arm/boot/dts/r8a7791.dtsi
arch/arm/boot/dts/sama5d3.dtsi
arch/arm/boot/dts/sama5d36.dtsi [new file with mode: 0644]
arch/arm/boot/dts/sama5d36ek.dts [new file with mode: 0644]
arch/arm/boot/dts/sama5d3_can.dtsi
arch/arm/boot/dts/sama5d3_emac.dtsi
arch/arm/boot/dts/sama5d3_gmac.dtsi
arch/arm/boot/dts/sama5d3_lcd.dtsi
arch/arm/boot/dts/sama5d3_mci2.dtsi
arch/arm/boot/dts/sama5d3_tcb1.dtsi
arch/arm/boot/dts/sama5d3_uart.dtsi
arch/arm/boot/dts/sama5d3xcm.dtsi
arch/arm/boot/dts/sama5d3xdm.dtsi
arch/arm/boot/dts/sh7372-mackerel.dts
arch/arm/boot/dts/sh73a0-kzm9g-reference.dts
arch/arm/boot/dts/sh73a0-kzm9g.dts
arch/arm/boot/dts/sh73a0.dtsi
arch/arm/boot/dts/socfpga.dtsi
arch/arm/boot/dts/st-pincfg.h
arch/arm/boot/dts/ste-dbx5x0.dtsi
arch/arm/boot/dts/ste-href-family-pinctrl.dtsi [new file with mode: 0644]
arch/arm/boot/dts/ste-href-stuib.dtsi
arch/arm/boot/dts/ste-href-tvk1281618.dtsi
arch/arm/boot/dts/ste-href.dtsi
arch/arm/boot/dts/ste-hrefprev60.dtsi
arch/arm/boot/dts/ste-hrefv60plus.dtsi
arch/arm/boot/dts/ste-nomadik-pinctrl.dtsi
arch/arm/boot/dts/ste-snowball.dts
arch/arm/boot/dts/stih415-pinctrl.dtsi
arch/arm/boot/dts/stih415.dtsi
arch/arm/boot/dts/stih416-pinctrl.dtsi
arch/arm/boot/dts/stih416.dtsi
arch/arm/boot/dts/stih41x-b2000.dtsi
arch/arm/boot/dts/stih41x-b2020.dtsi
arch/arm/boot/dts/tegra20-colibri-512.dtsi
arch/arm/boot/dts/vf610-cosmic.dts
arch/arm/boot/dts/vf610-pingrp.h [new file with mode: 0644]
arch/arm/boot/dts/vf610-twr.dts
arch/arm/boot/dts/vf610.dtsi
arch/arm/common/mcpm_entry.c
arch/arm/common/timer-sp.c
arch/arm/configs/ape6evm_defconfig
arch/arm/configs/armadillo800eva_defconfig
arch/arm/configs/bcm2835_defconfig
arch/arm/configs/bockw_defconfig
arch/arm/configs/exynos_defconfig
arch/arm/configs/genmai_defconfig [new file with mode: 0644]
arch/arm/configs/imx_v4_v5_defconfig
arch/arm/configs/imx_v6_v7_defconfig
arch/arm/configs/kirkwood_defconfig
arch/arm/configs/koelsch_defconfig
arch/arm/configs/kzm9d_defconfig
arch/arm/configs/kzm9g_defconfig
arch/arm/configs/lager_defconfig
arch/arm/configs/mackerel_defconfig
arch/arm/configs/marzen_defconfig
arch/arm/configs/multi_v7_defconfig
arch/arm/configs/mvebu_defconfig
arch/arm/configs/omap2plus_defconfig
arch/arm/configs/sunxi_defconfig
arch/arm/configs/u8500_defconfig
arch/arm/include/asm/cacheflush.h
arch/arm/include/asm/io.h
arch/arm/include/asm/mach/map.h
arch/arm/include/asm/pgtable-2level.h
arch/arm/include/asm/pgtable-3level.h
arch/arm/include/asm/pgtable.h
arch/arm/include/asm/xen/page.h
arch/arm/include/debug/imx-uart.h
arch/arm/include/debug/tegra.S
arch/arm/kernel/entry-v7m.S
arch/arm/kernel/etm.c
arch/arm/kernel/machine_kexec.c
arch/arm/kernel/process.c
arch/arm/kernel/relocate_kernel.S
arch/arm/kernel/setup.c
arch/arm/kernel/sigreturn_codes.S
arch/arm/kernel/smp.c
arch/arm/kernel/stacktrace.c
arch/arm/kernel/tcm.c
arch/arm/kernel/traps.c
arch/arm/lib/backtrace.S
arch/arm/lib/delay-loop.S
arch/arm/mach-at91/Kconfig
arch/arm/mach-at91/Kconfig.non_dt
arch/arm/mach-at91/Makefile
arch/arm/mach-at91/at91rm9200.c
arch/arm/mach-at91/at91rm9200_time.c
arch/arm/mach-at91/at91sam9260.c
arch/arm/mach-at91/at91sam9261.c
arch/arm/mach-at91/at91sam9263.c
arch/arm/mach-at91/at91sam926x_time.c
arch/arm/mach-at91/at91sam9g45.c
arch/arm/mach-at91/at91sam9n12.c
arch/arm/mach-at91/at91sam9rl.c
arch/arm/mach-at91/at91sam9x5.c
arch/arm/mach-at91/board-dt-sama5.c
arch/arm/mach-at91/clock.c
arch/arm/mach-at91/generic.h
arch/arm/mach-at91/include/mach/cpu.h
arch/arm/mach-at91/pm.c
arch/arm/mach-at91/pm.h
arch/arm/mach-at91/pm_slowclock.S
arch/arm/mach-at91/sama5d3.c
arch/arm/mach-at91/setup.c
arch/arm/mach-bcm2835/Kconfig
arch/arm/mach-clps711x/common.c
arch/arm/mach-davinci/devices-da8xx.c
arch/arm/mach-davinci/dm355.c
arch/arm/mach-davinci/dm365.c
arch/arm/mach-davinci/dm644x.c
arch/arm/mach-davinci/dm646x.c
arch/arm/mach-davinci/time.c
arch/arm/mach-dove/common.c
arch/arm/mach-ep93xx/Kconfig
arch/arm/mach-ep93xx/core.c
arch/arm/mach-ep93xx/include/mach/platform.h
arch/arm/mach-footbridge/common.c
arch/arm/mach-footbridge/dc21285.c
arch/arm/mach-footbridge/ebsa285.c
arch/arm/mach-highbank/highbank.c
arch/arm/mach-imx/Kconfig
arch/arm/mach-imx/Makefile
arch/arm/mach-imx/avic.c
arch/arm/mach-imx/clk-imx51-imx53.c
arch/arm/mach-imx/clk-imx6q.c
arch/arm/mach-imx/clk-imx6sl.c
arch/arm/mach-imx/clk-pllv1.c
arch/arm/mach-imx/clk-vf610.c
arch/arm/mach-imx/common.h
arch/arm/mach-imx/imx31-dt.c
arch/arm/mach-imx/imx51-dt.c
arch/arm/mach-imx/irq-common.h
arch/arm/mach-imx/mach-cpuimx35.c
arch/arm/mach-imx/mach-cpuimx51sd.c
arch/arm/mach-imx/mach-imx50.c [new file with mode: 0644]
arch/arm/mach-imx/mach-imx53.c
arch/arm/mach-imx/mach-imx6q.c
arch/arm/mach-imx/mach-imx6sl.c
arch/arm/mach-imx/mach-vf610.c
arch/arm/mach-imx/mm-imx5.c
arch/arm/mach-imx/time.c
arch/arm/mach-integrator/integrator_ap.c
arch/arm/mach-integrator/integrator_cp.c
arch/arm/mach-ixp4xx/common.c
arch/arm/mach-kirkwood/board-dt.c
arch/arm/mach-mmp/time.c
arch/arm/mach-msm/timer.c
arch/arm/mach-mvebu/coherency.c
arch/arm/mach-mvebu/coherency.h
arch/arm/mach-mvebu/common.h
arch/arm/mach-mvebu/hotplug.c
arch/arm/mach-mvebu/platsmp.c
arch/arm/mach-mvebu/pmsu.c
arch/arm/mach-mvebu/system-controller.c
arch/arm/mach-mxs/mach-mxs.c
arch/arm/mach-omap1/time.c
arch/arm/mach-omap2/board-generic.c
arch/arm/mach-omap2/dss-common.c
arch/arm/mach-omap2/io.c
arch/arm/mach-omap2/omap4-common.c
arch/arm/mach-omap2/omap_device.c
arch/arm/mach-omap2/omap_device.h
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/mach-omap2/omap_hwmod_54xx_data.c
arch/arm/mach-omap2/pdata-quirks.c
arch/arm/mach-omap2/powerdomain.c
arch/arm/mach-omap2/timer.c
arch/arm/mach-orion5x/board-dt.c
arch/arm/mach-orion5x/common.c
arch/arm/mach-orion5x/db88f5281-setup.c
arch/arm/mach-orion5x/irq.c
arch/arm/mach-orion5x/pci.c
arch/arm/mach-orion5x/rd88f5182-setup.c
arch/arm/mach-orion5x/terastation_pro2-setup.c
arch/arm/mach-orion5x/ts209-setup.c
arch/arm/mach-orion5x/ts78xx-setup.c
arch/arm/mach-pxa/time.c
arch/arm/mach-s3c64xx/Kconfig
arch/arm/mach-s3c64xx/Makefile
arch/arm/mach-s3c64xx/common.h
arch/arm/mach-s3c64xx/dma.c [deleted file]
arch/arm/mach-s3c64xx/include/mach/dma.h
arch/arm/mach-s3c64xx/pl080.c [new file with mode: 0644]
arch/arm/mach-sa1100/time.c
arch/arm/mach-shmobile/Kconfig
arch/arm/mach-shmobile/Makefile
arch/arm/mach-shmobile/Makefile.boot
arch/arm/mach-shmobile/board-ape6evm.c
arch/arm/mach-shmobile/board-armadillo800eva.c
arch/arm/mach-shmobile/board-bockw-reference.c
arch/arm/mach-shmobile/board-bockw.c
arch/arm/mach-shmobile/board-genmai-reference.c [new file with mode: 0644]
arch/arm/mach-shmobile/board-koelsch-reference.c [new file with mode: 0644]
arch/arm/mach-shmobile/board-koelsch.c
arch/arm/mach-shmobile/board-kzm9d.c [deleted file]
arch/arm/mach-shmobile/board-lager-reference.c
arch/arm/mach-shmobile/board-lager.c
arch/arm/mach-shmobile/board-mackerel.c
arch/arm/mach-shmobile/board-marzen.c
arch/arm/mach-shmobile/clock-r7s72100.c
arch/arm/mach-shmobile/clock-r8a73a4.c
arch/arm/mach-shmobile/clock-r8a7740.c
arch/arm/mach-shmobile/clock-r8a7778.c
arch/arm/mach-shmobile/clock-r8a7779.c
arch/arm/mach-shmobile/clock-r8a7790.c
arch/arm/mach-shmobile/clock-r8a7791.c
arch/arm/mach-shmobile/clock-sh7372.c
arch/arm/mach-shmobile/clock-sh73a0.c
arch/arm/mach-shmobile/include/mach/emev2.h
arch/arm/mach-shmobile/include/mach/r8a7778.h
arch/arm/mach-shmobile/include/mach/r8a7779.h
arch/arm/mach-shmobile/include/mach/r8a7791.h
arch/arm/mach-shmobile/setup-emev2.c
arch/arm/mach-shmobile/setup-r7s72100.c
arch/arm/mach-shmobile/setup-r8a73a4.c
arch/arm/mach-shmobile/setup-r8a7778.c
arch/arm/mach-shmobile/setup-r8a7779.c
arch/arm/mach-shmobile/setup-r8a7790.c
arch/arm/mach-shmobile/setup-r8a7791.c
arch/arm/mach-shmobile/setup-sh73a0.c
arch/arm/mach-shmobile/sh-gpio.h
arch/arm/mach-socfpga/Kconfig
arch/arm/mach-tegra/fuse.c
arch/arm/mach-tegra/iomap.h
arch/arm/mach-tegra/tegra.c
arch/arm/mach-u300/timer.c
arch/arm/mach-ux500/Makefile
arch/arm/mach-ux500/board-mop500-audio.c
arch/arm/mach-ux500/board-mop500-pins.c
arch/arm/mach-ux500/board-mop500-sdi.c
arch/arm/mach-ux500/board-mop500.c [deleted file]
arch/arm/mach-ux500/board-mop500.h
arch/arm/mach-ux500/cpu-db8500.c
arch/arm/mach-ux500/cpu.c
arch/arm/mach-ux500/devices-db8500.c [deleted file]
arch/arm/mach-ux500/devices-db8500.h [deleted file]
arch/arm/mach-ux500/devices.c [deleted file]
arch/arm/mach-ux500/devices.h [deleted file]
arch/arm/mach-ux500/setup.h
arch/arm/mach-ux500/timer.c
arch/arm/mm/Makefile
arch/arm/mm/cache-v7.S
arch/arm/mm/dma-mapping.c
arch/arm/mm/dump.c [new file with mode: 0644]
arch/arm/mm/init.c
arch/arm/mm/ioremap.c
arch/arm/mm/mmap.c
arch/arm/mm/mmu.c
arch/arm/mm/pgd.c
arch/arm/plat-iop/time.c
arch/arm/plat-omap/counter_32k.c
arch/arm/plat-omap/include/plat/dmtimer.h
arch/arm/plat-orion/common.c
arch/arm/plat-orion/time.c
arch/arm/plat-samsung/devs.c
arch/arm/plat-samsung/dma-ops.c
arch/arm/plat-samsung/include/plat/uncompress.h
arch/arm/plat-samsung/s5p-irq-eint.c
arch/arm/plat-versatile/sched-clock.c
arch/arm/xen/p2m.c
arch/arm64/Kconfig
arch/arm64/include/asm/io.h
arch/arm64/include/asm/pgtable-hwdef.h
arch/arm64/kernel/head.S
arch/arm64/mm/proc.S
arch/avr32/boards/favr-32/setup.c
arch/avr32/configs/atngw100_defconfig
arch/avr32/configs/atngw100_evklcd100_defconfig
arch/avr32/configs/atngw100_evklcd101_defconfig
arch/avr32/configs/atngw100_mrmt_defconfig
arch/avr32/configs/atngw100mkii_defconfig
arch/avr32/configs/atngw100mkii_evklcd100_defconfig
arch/avr32/configs/atngw100mkii_evklcd101_defconfig
arch/avr32/configs/atstk1002_defconfig
arch/avr32/configs/atstk1003_defconfig
arch/avr32/configs/atstk1004_defconfig
arch/avr32/configs/atstk1006_defconfig
arch/avr32/configs/favr-32_defconfig
arch/avr32/configs/hammerhead_defconfig
arch/avr32/configs/merisc_defconfig
arch/avr32/configs/mimc200_defconfig
arch/avr32/kernel/time.c
arch/avr32/mach-at32ap/pm.c
arch/c6x/include/asm/cache.h
arch/ia64/hp/common/aml_nfw.c
arch/m68k/Kconfig
arch/m68k/amiga/chipram.c
arch/m68k/amiga/config.c
arch/m68k/amiga/platform.c
arch/m68k/apollo/config.c
arch/m68k/atari/config.c
arch/m68k/atari/debug.c
arch/m68k/bvme6000/config.c
arch/m68k/configs/amiga_defconfig
arch/m68k/configs/apollo_defconfig
arch/m68k/configs/atari_defconfig
arch/m68k/configs/bvme6000_defconfig
arch/m68k/configs/hp300_defconfig
arch/m68k/configs/m5208evb_defconfig
arch/m68k/configs/m5249evb_defconfig
arch/m68k/configs/m5272c3_defconfig
arch/m68k/configs/m5275evb_defconfig
arch/m68k/configs/m5307c3_defconfig
arch/m68k/configs/m5407c3_defconfig
arch/m68k/configs/mac_defconfig
arch/m68k/configs/multi_defconfig
arch/m68k/configs/mvme147_defconfig
arch/m68k/configs/mvme16x_defconfig
arch/m68k/configs/q40_defconfig
arch/m68k/configs/sun3_defconfig
arch/m68k/configs/sun3x_defconfig
arch/m68k/emu/natfeat.c
arch/m68k/emu/nfblock.c
arch/m68k/hp300/config.c
arch/m68k/include/asm/amigahw.h
arch/m68k/include/asm/apollohw.h
arch/m68k/include/asm/atarihw.h
arch/m68k/include/asm/bootinfo.h
arch/m68k/include/asm/hp300hw.h
arch/m68k/include/asm/kexec.h [new file with mode: 0644]
arch/m68k/include/asm/macintosh.h
arch/m68k/include/asm/mc146818rtc.h
arch/m68k/include/asm/mvme16xhw.h
arch/m68k/include/asm/setup.h
arch/m68k/include/asm/timex.h
arch/m68k/include/uapi/asm/Kbuild
arch/m68k/include/uapi/asm/bootinfo-amiga.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/bootinfo-apollo.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/bootinfo-atari.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/bootinfo-hp300.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/bootinfo-mac.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/bootinfo-q40.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/bootinfo-vme.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/bootinfo.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/setup.h
arch/m68k/kernel/Makefile
arch/m68k/kernel/asm-offsets.c
arch/m68k/kernel/bootinfo_proc.c [new file with mode: 0644]
arch/m68k/kernel/head.S
arch/m68k/kernel/machine_kexec.c [new file with mode: 0644]
arch/m68k/kernel/relocate_kernel.S [new file with mode: 0644]
arch/m68k/kernel/setup_mm.c
arch/m68k/kernel/time.c
arch/m68k/mac/config.c
arch/m68k/mac/iop.c
arch/m68k/mac/misc.c
arch/m68k/mac/oss.c
arch/m68k/mac/psc.c
arch/m68k/mac/via.c
arch/m68k/mm/init.c
arch/m68k/mm/motorola.c
arch/m68k/mvme147/config.c
arch/m68k/mvme16x/config.c
arch/m68k/q40/config.c
arch/m68k/sun3/dvma.c
arch/m68k/sun3/mmu_emu.c
arch/m68k/sun3/sun3dvma.c
arch/m68k/sun3x/prom.c
arch/metag/include/asm/smp.h
arch/metag/kernel/dma.c
arch/metag/kernel/smp.c
arch/microblaze/Makefile
arch/microblaze/include/asm/sections.h
arch/microblaze/kernel/setup.c
arch/mips/ar7/setup.c
arch/mips/emma/markeins/setup.c
arch/mips/lasat/picvue_proc.c
arch/mips/netlogic/xlp/setup.c
arch/mips/netlogic/xlr/setup.c
arch/mips/sibyte/swarm/setup.c
arch/openrisc/kernel/entry.S
arch/openrisc/kernel/signal.c
arch/parisc/configs/c3000_defconfig
arch/parisc/configs/c8000_defconfig
arch/parisc/configs/generic-64bit_defconfig
arch/parisc/include/asm/serial.h
arch/parisc/kernel/hardware.c
arch/parisc/kernel/head.S
arch/parisc/kernel/sys_parisc.c
arch/parisc/kernel/unwind.c
arch/parisc/kernel/vmlinux.lds.S
arch/parisc/mm/init.c
arch/powerpc/Kconfig
arch/powerpc/boot/.gitignore
arch/powerpc/boot/dts/ac14xx.dts
arch/powerpc/boot/dts/kilauea.dts
arch/powerpc/boot/dts/mpc5121.dtsi
arch/powerpc/boot/dts/virtex440-ml507.dts
arch/powerpc/configs/52xx/cm5200_defconfig
arch/powerpc/configs/52xx/lite5200b_defconfig
arch/powerpc/configs/52xx/motionpro_defconfig
arch/powerpc/configs/52xx/pcm030_defconfig
arch/powerpc/configs/52xx/tqm5200_defconfig
arch/powerpc/configs/mpc5200_defconfig
arch/powerpc/configs/pasemi_defconfig
arch/powerpc/include/asm/bitops.h
arch/powerpc/include/asm/cache.h
arch/powerpc/include/asm/clk_interface.h [deleted file]
arch/powerpc/include/asm/code-patching.h
arch/powerpc/include/asm/cputable.h
arch/powerpc/include/asm/exception-64s.h
arch/powerpc/include/asm/hardirq.h
arch/powerpc/include/asm/io.h
arch/powerpc/include/asm/iommu.h
arch/powerpc/include/asm/lppaca.h
arch/powerpc/include/asm/mce.h [new file with mode: 0644]
arch/powerpc/include/asm/opal.h
arch/powerpc/include/asm/paca.h
arch/powerpc/include/asm/pgalloc-32.h
arch/powerpc/include/asm/pgalloc-64.h
arch/powerpc/include/asm/pgtable.h
arch/powerpc/include/asm/pte-hash64.h
arch/powerpc/include/asm/setup.h
arch/powerpc/include/asm/uprobes.h
arch/powerpc/kernel/Makefile
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/clock.c [deleted file]
arch/powerpc/kernel/cpu_setup_power.S
arch/powerpc/kernel/cputable.c
arch/powerpc/kernel/eeh.c
arch/powerpc/kernel/eeh_driver.c
arch/powerpc/kernel/entry_64.S
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/idle_power7.S
arch/powerpc/kernel/iommu.c
arch/powerpc/kernel/irq.c
arch/powerpc/kernel/machine_kexec.c
arch/powerpc/kernel/mce.c [new file with mode: 0644]
arch/powerpc/kernel/mce_power.c [new file with mode: 0644]
arch/powerpc/kernel/misc_32.S
arch/powerpc/kernel/misc_64.S
arch/powerpc/kernel/paca.c
arch/powerpc/kernel/setup_32.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/kernel/smp.c
arch/powerpc/kernel/sysfs.c
arch/powerpc/kernel/time.c
arch/powerpc/kernel/traps.c
arch/powerpc/kernel/uprobes.c
arch/powerpc/kvm/book3s_hv_ras.c
arch/powerpc/lib/code-patching.c
arch/powerpc/mm/hash_low_64.S
arch/powerpc/mm/hash_utils_64.c
arch/powerpc/mm/hugepage-hash64.c
arch/powerpc/mm/hugetlbpage-hash64.c
arch/powerpc/mm/pgtable.c
arch/powerpc/mm/pgtable_64.c
arch/powerpc/mm/tlb_nohash.c
arch/powerpc/platforms/512x/Kconfig
arch/powerpc/platforms/512x/Makefile
arch/powerpc/platforms/512x/clock-commonclk.c [new file with mode: 0644]
arch/powerpc/platforms/512x/clock.c [deleted file]
arch/powerpc/platforms/512x/mpc512x_shared.c
arch/powerpc/platforms/52xx/Kconfig
arch/powerpc/platforms/Kconfig.cputype
arch/powerpc/platforms/cell/beat_htab.c
arch/powerpc/platforms/powernv/Kconfig
arch/powerpc/platforms/powernv/Makefile
arch/powerpc/platforms/powernv/eeh-ioda.c
arch/powerpc/platforms/powernv/opal-flash.c
arch/powerpc/platforms/powernv/opal-memory-errors.c [new file with mode: 0644]
arch/powerpc/platforms/powernv/opal-rtc.c
arch/powerpc/platforms/powernv/opal-wrappers.S
arch/powerpc/platforms/powernv/opal.c
arch/powerpc/platforms/powernv/pci-ioda.c
arch/powerpc/platforms/powernv/pci-p5ioc2.c
arch/powerpc/platforms/powernv/pci.c
arch/powerpc/platforms/powernv/pci.h
arch/powerpc/platforms/ps3/spu.c
arch/powerpc/platforms/pseries/Kconfig
arch/powerpc/platforms/pseries/iommu.c
arch/powerpc/platforms/pseries/lpar.c
arch/powerpc/platforms/pseries/setup.c
arch/powerpc/sysdev/Kconfig
arch/powerpc/sysdev/axonram.c
arch/powerpc/sysdev/fsl_pci.c
arch/powerpc/sysdev/ppc4xx_ocm.c
arch/powerpc/xmon/xmon.c
arch/s390/Kconfig
arch/s390/crypto/aes_s390.c
arch/s390/include/asm/sclp.h
arch/s390/include/uapi/asm/zcrypt.h
arch/s390/kernel/asm-offsets.c
arch/s390/kernel/vdso.c
arch/s390/kernel/vdso32/clock_gettime.S
arch/s390/kernel/vdso64/clock_getres.S
arch/s390/kernel/vdso64/clock_gettime.S
arch/sh/boards/mach-ecovec24/setup.c
arch/sh/include/asm/hw_breakpoint.h
arch/sh/include/cpu-common/cpu/ubc.h [new file with mode: 0644]
arch/sh/include/cpu-sh2a/cpu/ubc.h [new file with mode: 0644]
arch/sh/kernel/cpu/sh2a/Makefile
arch/sh/kernel/cpu/sh2a/ubc.c [new file with mode: 0644]
arch/sh/kernel/hw_breakpoint.c
arch/sparc/kernel/kgdb_64.c
arch/um/Makefile
arch/um/kernel/sysrq.c
arch/x86/Kconfig
arch/x86/Makefile
arch/x86/boot/Makefile
arch/x86/boot/boot.h
arch/x86/boot/compressed/Makefile
arch/x86/boot/compressed/aslr.c [new file with mode: 0644]
arch/x86/boot/compressed/cmdline.c
arch/x86/boot/compressed/cpuflags.c [new file with mode: 0644]
arch/x86/boot/compressed/head_32.S
arch/x86/boot/compressed/head_64.S
arch/x86/boot/compressed/misc.c
arch/x86/boot/compressed/misc.h
arch/x86/boot/cpucheck.c
arch/x86/boot/cpuflags.c [new file with mode: 0644]
arch/x86/boot/cpuflags.h [new file with mode: 0644]
arch/x86/include/asm/archrandom.h
arch/x86/include/asm/atomic.h
arch/x86/include/asm/atomic64_64.h
arch/x86/include/asm/bitops.h
arch/x86/include/asm/efi.h
arch/x86/include/asm/local.h
arch/x86/include/asm/page.h
arch/x86/include/asm/page_32.h
arch/x86/include/asm/page_64_types.h
arch/x86/include/asm/pgtable-2level.h
arch/x86/include/asm/pgtable_64_types.h
arch/x86/include/asm/pgtable_types.h
arch/x86/include/asm/rmwcc.h
arch/x86/include/asm/trace/irq_vectors.h
arch/x86/kernel/apic/apic_flat_64.c
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/cpu/Makefile
arch/x86/kernel/cpu/perf_event_intel_rapl.c [new file with mode: 0644]
arch/x86/kernel/cpu/rdrand.c
arch/x86/kernel/reboot.c
arch/x86/kernel/setup.c
arch/x86/lib/copy_user_64.S
arch/x86/mm/hugetlbpage.c
arch/x86/mm/init_32.c
arch/x86/mm/pageattr.c
arch/x86/pci/mmconfig_32.c
arch/x86/platform/efi/early_printk.c
arch/x86/platform/efi/efi.c
arch/x86/platform/efi/efi_32.c
arch/x86/platform/efi/efi_64.c
arch/x86/platform/efi/efi_stub_64.S
arch/x86/platform/olpc/olpc-xo15-sci.c
arch/x86/tools/relocs.c
arch/xtensa/Kconfig
arch/xtensa/boot/dts/xtfpga.dtsi
arch/xtensa/include/asm/Kbuild
arch/xtensa/include/asm/barrier.h
arch/xtensa/include/asm/bitops.h
arch/xtensa/include/asm/cacheflush.h
arch/xtensa/include/asm/delay.h
arch/xtensa/include/asm/ftrace.h
arch/xtensa/include/asm/futex.h [new file with mode: 0644]
arch/xtensa/include/asm/irq.h
arch/xtensa/include/asm/mmu.h
arch/xtensa/include/asm/mmu_context.h
arch/xtensa/include/asm/mxregs.h [new file with mode: 0644]
arch/xtensa/include/asm/processor.h
arch/xtensa/include/asm/ptrace.h
arch/xtensa/include/asm/smp.h
arch/xtensa/include/asm/spinlock.h
arch/xtensa/include/asm/spinlock_types.h [new file with mode: 0644]
arch/xtensa/include/asm/timex.h
arch/xtensa/include/asm/tlbflush.h
arch/xtensa/include/asm/traps.h
arch/xtensa/include/asm/vectors.h
arch/xtensa/kernel/Makefile
arch/xtensa/kernel/head.S
arch/xtensa/kernel/irq.c
arch/xtensa/kernel/mxhead.S [new file with mode: 0644]
arch/xtensa/kernel/setup.c
arch/xtensa/kernel/smp.c [new file with mode: 0644]
arch/xtensa/kernel/time.c
arch/xtensa/kernel/traps.c
arch/xtensa/kernel/vmlinux.lds.S
arch/xtensa/mm/cache.c
arch/xtensa/mm/fault.c
arch/xtensa/mm/misc.S
arch/xtensa/mm/mmu.c
arch/xtensa/mm/tlb.c
arch/xtensa/platforms/iss/network.c
arch/xtensa/platforms/xtfpga/include/platform/hardware.h
arch/xtensa/variants/s6000/include/variant/irq.h
block/blk-cgroup.h
block/blk-core.c
block/blk-flush.c
block/blk-integrity.c
block/blk-lib.c
block/blk-map.c
block/blk-merge.c
block/blk-mq.c
block/blk-throttle.c
block/cfq-iosched.c
block/elevator.c
crypto/Makefile
crypto/algif_hash.c
crypto/algif_skcipher.c
crypto/authenc.c
crypto/ccm.c
crypto/memneq.c
crypto/pcrypt.c
crypto/tcrypt.c
crypto/testmgr.c
drivers/Makefile
drivers/acpi/ac.c
drivers/acpi/acpi_extlog.c
drivers/acpi/acpi_lpss.c
drivers/acpi/acpi_memhotplug.c
drivers/acpi/acpi_pad.c
drivers/acpi/acpi_processor.c
drivers/acpi/apei/einj.c
drivers/acpi/battery.c
drivers/acpi/blacklist.c
drivers/acpi/bus.c
drivers/acpi/button.c
drivers/acpi/container.c
drivers/acpi/custom_method.c
drivers/acpi/debugfs.c
drivers/acpi/device_pm.c
drivers/acpi/dock.c
drivers/acpi/ec.c
drivers/acpi/event.c
drivers/acpi/fan.c
drivers/acpi/glue.c
drivers/acpi/hed.c
drivers/acpi/internal.h
drivers/acpi/numa.c
drivers/acpi/osl.c
drivers/acpi/pci_irq.c
drivers/acpi/pci_link.c
drivers/acpi/pci_root.c
drivers/acpi/power.c
drivers/acpi/proc.c
drivers/acpi/processor_core.c
drivers/acpi/processor_idle.c
drivers/acpi/processor_perflib.c
drivers/acpi/processor_thermal.c
drivers/acpi/processor_throttling.c
drivers/acpi/sbshc.c
drivers/acpi/scan.c
drivers/acpi/sleep.c
drivers/acpi/sysfs.c
drivers/acpi/thermal.c
drivers/acpi/utils.c
drivers/acpi/video.c
drivers/acpi/wakeup.c
drivers/amba/bus.c
drivers/ata/ahci.c
drivers/ata/ahci_imx.c
drivers/ata/ata_generic.c
drivers/ata/libata-acpi.c
drivers/ata/libata-core.c
drivers/ata/libata-eh.c
drivers/ata/libata-scsi.c
drivers/ata/pata_acpi.c
drivers/ata/sata_rcar.c
drivers/atm/he.c
drivers/atm/solos-pci.c
drivers/bcma/host_pci.c
drivers/block/Makefile
drivers/block/aoe/aoe.h
drivers/block/aoe/aoecmd.c
drivers/block/brd.c
drivers/block/drbd/drbd_actlog.c
drivers/block/drbd/drbd_bitmap.c
drivers/block/drbd/drbd_main.c
drivers/block/drbd/drbd_receiver.c
drivers/block/drbd/drbd_req.c
drivers/block/drbd/drbd_req.h
drivers/block/drbd/drbd_worker.c
drivers/block/floppy.c
drivers/block/loop.c
drivers/block/mtip32xx/mtip32xx.c
drivers/block/nbd.c
drivers/block/nvme-core.c
drivers/block/pktcdvd.c
drivers/block/ps3disk.c
drivers/block/ps3vram.c
drivers/block/rbd.c
drivers/block/rsxx/dev.c
drivers/block/rsxx/dma.c
drivers/block/umem.c
drivers/block/xen-blkback/blkback.c
drivers/block/xen-blkfront.c
drivers/block/z2ram.c
drivers/bluetooth/ath3k.c
drivers/bluetooth/btmrvl_drv.h
drivers/bluetooth/btmrvl_main.c
drivers/bluetooth/btmrvl_sdio.c
drivers/bluetooth/btmrvl_sdio.h
drivers/bluetooth/btusb.c
drivers/bus/mvebu-mbus.c
drivers/cdrom/Makefile
drivers/cdrom/gdrom.c
drivers/char/Makefile
drivers/char/agp/Kconfig
drivers/char/agp/Makefile
drivers/char/agp/intel-agp.c
drivers/char/agp/intel-gtt.c
drivers/char/hpet.c
drivers/char/i8k.c
drivers/char/tpm/tpm_acpi.c
drivers/char/tpm/tpm_ppi.c
drivers/clk/Makefile
drivers/clk/at91/Makefile [new file with mode: 0644]
drivers/clk/at91/clk-main.c [new file with mode: 0644]
drivers/clk/at91/clk-master.c [new file with mode: 0644]
drivers/clk/at91/clk-peripheral.c [new file with mode: 0644]
drivers/clk/at91/clk-pll.c [new file with mode: 0644]
drivers/clk/at91/clk-plldiv.c [new file with mode: 0644]
drivers/clk/at91/clk-programmable.c [new file with mode: 0644]
drivers/clk/at91/clk-smd.c [new file with mode: 0644]
drivers/clk/at91/clk-system.c [new file with mode: 0644]
drivers/clk/at91/clk-usb.c [new file with mode: 0644]
drivers/clk/at91/clk-utmi.c [new file with mode: 0644]
drivers/clk/at91/pmc.c [new file with mode: 0644]
drivers/clk/at91/pmc.h [new file with mode: 0644]
drivers/clk/mvebu/Kconfig
drivers/clk/mvebu/Makefile
drivers/clk/mvebu/clk-corediv.c [new file with mode: 0644]
drivers/clk/mvebu/clk-cpu.c
drivers/clk/samsung/clk-s3c64xx.c
drivers/clocksource/Kconfig
drivers/clocksource/exynos_mct.c
drivers/clocksource/nomadik-mtu.c
drivers/clocksource/sh_mtu2.c
drivers/clocksource/sh_tmu.c
drivers/cpufreq/at32ap-cpufreq.c
drivers/cpufreq/cpufreq-cpu0.c
drivers/cpufreq/spear-cpufreq.c
drivers/cpuidle/cpuidle.c
drivers/crypto/Kconfig
drivers/crypto/Makefile
drivers/crypto/caam/caamalg.c
drivers/crypto/caam/jr.c
drivers/crypto/ccp/Kconfig [new file with mode: 0644]
drivers/crypto/ccp/Makefile [new file with mode: 0644]
drivers/crypto/ccp/ccp-crypto-aes-cmac.c [new file with mode: 0644]
drivers/crypto/ccp/ccp-crypto-aes-xts.c [new file with mode: 0644]
drivers/crypto/ccp/ccp-crypto-aes.c [new file with mode: 0644]
drivers/crypto/ccp/ccp-crypto-main.c [new file with mode: 0644]
drivers/crypto/ccp/ccp-crypto-sha.c [new file with mode: 0644]
drivers/crypto/ccp/ccp-crypto.h [new file with mode: 0644]
drivers/crypto/ccp/ccp-dev.c [new file with mode: 0644]
drivers/crypto/ccp/ccp-dev.h [new file with mode: 0644]
drivers/crypto/ccp/ccp-ops.c [new file with mode: 0644]
drivers/crypto/ccp/ccp-pci.c [new file with mode: 0644]
drivers/crypto/omap-aes.c
drivers/crypto/omap-sham.c
drivers/crypto/talitos.c
drivers/devfreq/exynos/exynos4_bus.c
drivers/dma/Kconfig
drivers/dma/amba-pl08x.c
drivers/dma/at_hdmac_regs.h
drivers/dma/dmaengine.c
drivers/dma/dmatest.c
drivers/dma/fsldma.c
drivers/dma/imx-sdma.c
drivers/dma/mmp_pdma.c
drivers/dma/mmp_tdma.c
drivers/dma/mv_xor.c
drivers/dma/of-dma.c
drivers/dma/pl330.c
drivers/dma/ppc4xx/adma.c
drivers/dma/s3c24xx-dma.c
drivers/dma/sh/rcar-hpbdma.c
drivers/dma/ste_dma40.c
drivers/dma/txx9dmac.c
drivers/extcon/extcon-arizona.c
drivers/extcon/extcon-class.c
drivers/firewire/sbp2.c
drivers/firmware/efi/efi-pstore.c
drivers/firmware/efi/efivars.c
drivers/firmware/efi/vars.c
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/gpio-davinci.c
drivers/gpio/gpio-lp3943.c [new file with mode: 0644]
drivers/gpio/gpio-mpc8xxx.c
drivers/gpio/gpiolib.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/exynos/exynos_drm_crtc.c
drivers/gpu/drm/exynos/exynos_drm_drv.c
drivers/gpu/drm/exynos/exynos_drm_fimd.c
drivers/gpu/drm/exynos/exynos_drm_g2d.c
drivers/gpu/drm/exynos/exynos_drm_gem.c
drivers/gpu/drm/exynos/exynos_drm_gem.h
drivers/gpu/drm/exynos/exynos_drm_ipp.c
drivers/gpu/drm/exynos/exynos_drm_ipp.h
drivers/gpu/drm/i915/Kconfig
drivers/gpu/drm/i915/dvo_ns2501.c
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_context.c
drivers/gpu/drm/i915/i915_gem_dmabuf.c
drivers/gpu/drm/i915/i915_gem_evict.c
drivers/gpu/drm/i915/i915_gem_execbuffer.c
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_gpu_error.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_suspend.c
drivers/gpu/drm/i915/i915_sysfs.c
drivers/gpu/drm/i915/i915_ums.c
drivers/gpu/drm/i915/intel_acpi.c
drivers/gpu/drm/i915/intel_bios.c
drivers/gpu/drm/i915/intel_bios.h
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_ddi.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_dsi.c
drivers/gpu/drm/i915/intel_dsi.h
drivers/gpu/drm/i915/intel_dsi_pll.c
drivers/gpu/drm/i915/intel_dvo.c
drivers/gpu/drm/i915/intel_fbdev.c
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_i2c.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_opregion.c
drivers/gpu/drm/i915/intel_panel.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/i915/intel_sdvo_regs.h
drivers/gpu/drm/i915/intel_sideband.c
drivers/gpu/drm/i915/intel_sprite.c
drivers/gpu/drm/i915/intel_uncore.c
drivers/gpu/drm/nouveau/Makefile
drivers/gpu/drm/nouveau/core/engine/device/nv50.c
drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c
drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c
drivers/gpu/drm/nouveau/core/engine/software/nv50.c
drivers/gpu/drm/nouveau/core/include/subdev/clock.h
drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c
drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/dispnv04/overlay.c
drivers/gpu/drm/nouveau/nouveau_acpi.c
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nv50_display.c
drivers/gpu/drm/radeon/atombios_i2c.c
drivers/gpu/drm/radeon/dce6_afmt.c
drivers/gpu/drm/radeon/ni_dpm.c
drivers/gpu/drm/radeon/r600_hdmi.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_acpi.c
drivers/gpu/drm/radeon/radeon_atombios.c
drivers/gpu/drm/radeon/radeon_cs.c
drivers/gpu/drm/radeon/radeon_drv.h
drivers/gpu/drm/radeon/radeon_gart.c
drivers/gpu/drm/radeon/radeon_pm.c
drivers/gpu/drm/radeon/radeon_trace.h
drivers/gpu/drm/radeon/reg_srcs/cayman
drivers/gpu/drm/radeon/reg_srcs/evergreen
drivers/gpu/drm/radeon/si.c
drivers/gpu/drm/tegra/drm.c
drivers/gpu/drm/tegra/drm.h
drivers/gpu/drm/tegra/fb.c
drivers/gpu/drm/tegra/rgb.c
drivers/gpu/drm/udl/udl_gem.c
drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
drivers/gpu/host1x/bus.c
drivers/gpu/host1x/hw/cdma_hw.c
drivers/gpu/host1x/hw/debug_hw.c
drivers/hid/Kconfig
drivers/hid/hid-core.c
drivers/hid/hid-ids.h
drivers/hid/hid-lg.c
drivers/hid/hid-multitouch.c
drivers/hid/hid-sensor-hub.c
drivers/hid/hid-sony.c
drivers/hid/i2c-hid/i2c-hid.c
drivers/hid/usbhid/hid-quirks.c
drivers/hid/usbhid/usbkbd.c
drivers/hv/vmbus_drv.c
drivers/hwmon/Kconfig
drivers/hwmon/acpi_power_meter.c
drivers/hwmon/asus_atk0110.c
drivers/hwmon/coretemp.c
drivers/hwmon/fam15h_power.c
drivers/hwmon/hih6130.c
drivers/hwmon/it87.c
drivers/hwmon/k10temp.c
drivers/hwmon/k8temp.c
drivers/hwmon/lm78.c
drivers/hwmon/lm90.c
drivers/hwmon/sis5595.c
drivers/hwmon/via686a.c
drivers/hwmon/vt8231.c
drivers/hwmon/w83l786ng.c
drivers/ide/buddha.c
drivers/ide/ide-acpi.c
drivers/idle/intel_idle.c
drivers/iio/common/hid-sensors/Kconfig
drivers/iio/common/hid-sensors/hid-sensor-trigger.c
drivers/iio/light/Kconfig
drivers/infiniband/Kconfig
drivers/infiniband/Makefile
drivers/infiniband/hw/usnic/Kconfig [new file with mode: 0644]
drivers/infiniband/hw/usnic/Makefile [new file with mode: 0644]
drivers/infiniband/hw/usnic/usnic.h [new file with mode: 0644]
drivers/infiniband/hw/usnic/usnic_abi.h [new file with mode: 0644]
drivers/infiniband/hw/usnic/usnic_common_pkt_hdr.h [new file with mode: 0644]
drivers/infiniband/hw/usnic/usnic_common_util.h [new file with mode: 0644]
drivers/infiniband/hw/usnic/usnic_debugfs.c [new file with mode: 0644]
drivers/infiniband/hw/usnic/usnic_debugfs.h [new file with mode: 0644]
drivers/infiniband/hw/usnic/usnic_fwd.c [new file with mode: 0644]
drivers/infiniband/hw/usnic/usnic_fwd.h [new file with mode: 0644]
drivers/infiniband/hw/usnic/usnic_ib.h [new file with mode: 0644]
drivers/infiniband/hw/usnic/usnic_ib_main.c [new file with mode: 0644]
drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c [new file with mode: 0644]
drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h [new file with mode: 0644]
drivers/infiniband/hw/usnic/usnic_ib_sysfs.c [new file with mode: 0644]
drivers/infiniband/hw/usnic/usnic_ib_sysfs.h [new file with mode: 0644]
drivers/infiniband/hw/usnic/usnic_ib_verbs.c [new file with mode: 0644]
drivers/infiniband/hw/usnic/usnic_ib_verbs.h [new file with mode: 0644]
drivers/infiniband/hw/usnic/usnic_log.h [new file with mode: 0644]
drivers/infiniband/hw/usnic/usnic_transport.c [new file with mode: 0644]
drivers/infiniband/hw/usnic/usnic_transport.h [new file with mode: 0644]
drivers/infiniband/hw/usnic/usnic_uiom.c [new file with mode: 0644]
drivers/infiniband/hw/usnic/usnic_uiom.h [new file with mode: 0644]
drivers/infiniband/hw/usnic/usnic_uiom_interval_tree.c [new file with mode: 0644]
drivers/infiniband/hw/usnic/usnic_uiom_interval_tree.h [new file with mode: 0644]
drivers/infiniband/hw/usnic/usnic_vnic.c [new file with mode: 0644]
drivers/infiniband/hw/usnic/usnic_vnic.h [new file with mode: 0644]
drivers/input/keyboard/Kconfig
drivers/input/keyboard/adp5520-keys.c
drivers/input/keyboard/adp5588-keys.c
drivers/input/keyboard/adp5589-keys.c
drivers/input/keyboard/bf54x-keys.c
drivers/input/keyboard/davinci_keyscan.c
drivers/input/keyboard/ep93xx_keypad.c
drivers/input/keyboard/imx_keypad.c
drivers/input/keyboard/lm8323.c
drivers/input/keyboard/lm8333.c
drivers/input/keyboard/max7359_keypad.c
drivers/input/keyboard/mcs_touchkey.c
drivers/input/keyboard/mpr121_touchkey.c
drivers/input/keyboard/nomadik-ske-keypad.c
drivers/input/keyboard/omap-keypad.c
drivers/input/keyboard/pxa930_rotary.c
drivers/input/keyboard/samsung-keypad.c
drivers/input/keyboard/sh_keysc.c
drivers/input/keyboard/tca6416-keypad.c
drivers/input/keyboard/tnetv107x-keypad.c
drivers/input/keyboard/twl4030_keypad.c
drivers/input/keyboard/w90p910_keypad.c
drivers/input/misc/Kconfig
drivers/input/misc/Makefile
drivers/input/misc/ad714x.c
drivers/input/misc/adxl34x.c
drivers/input/misc/atlas_btns.c
drivers/input/misc/bfin_rotary.c
drivers/input/misc/bma150.c
drivers/input/misc/cma3000_d0x.c
drivers/input/misc/gp2ap002a00f.c
drivers/input/misc/gpio-beeper.c [new file with mode: 0644]
drivers/input/misc/gpio_tilt_polled.c
drivers/input/misc/kxtj9.c
drivers/input/misc/pcf8574_keypad.c
drivers/input/misc/pwm-beeper.c
drivers/input/misc/twl4030-pwrbutton.c
drivers/input/misc/twl4030-vibra.c
drivers/input/mouse/alps.c
drivers/input/mouse/alps.h
drivers/input/mouse/elantech.c
drivers/input/mouse/gpio_mouse.c
drivers/input/mouse/pxa930_trkball.c
drivers/input/serio/ambakmi.c
drivers/input/serio/pcips2.c
drivers/input/serio/serio.c
drivers/input/tablet/wacom_sys.c
drivers/input/tablet/wacom_wac.c
drivers/input/tablet/wacom_wac.h
drivers/input/touchscreen/88pm860x-ts.c
drivers/input/touchscreen/ad7877.c
drivers/input/touchscreen/ad7879.c
drivers/input/touchscreen/ads7846.c
drivers/input/touchscreen/atmel_mxt_ts.c
drivers/input/touchscreen/atmel_tsadcc.c
drivers/input/touchscreen/cy8ctmg110_ts.c
drivers/input/touchscreen/cyttsp_core.c
drivers/input/touchscreen/da9034-ts.c
drivers/input/touchscreen/edt-ft5x06.c
drivers/input/touchscreen/eeti_ts.c
drivers/input/touchscreen/ili210x.c
drivers/input/touchscreen/mcs5000_ts.c
drivers/input/touchscreen/pixcir_i2c_ts.c
drivers/input/touchscreen/s3c2410_ts.c
drivers/input/touchscreen/st1232.c
drivers/input/touchscreen/sur40.c
drivers/input/touchscreen/tsc2005.c
drivers/input/touchscreen/tsc2007.c
drivers/input/touchscreen/ucb1400_ts.c
drivers/input/touchscreen/usbtouchscreen.c
drivers/input/touchscreen/wm97xx-core.c
drivers/iommu/amd_iommu_init.c
drivers/iommu/arm-smmu.c
drivers/iommu/intel_irq_remapping.c
drivers/irqchip/Kconfig
drivers/irqchip/Makefile
drivers/irqchip/exynos-combiner.c
drivers/irqchip/irq-dove.c [new file with mode: 0644]
drivers/irqchip/irq-gic.c
drivers/irqchip/irq-renesas-intc-irqpin.c
drivers/irqchip/irq-xtensa-mx.c [new file with mode: 0644]
drivers/irqchip/irq-xtensa-pic.c [new file with mode: 0644]
drivers/isdn/mISDN/Kconfig
drivers/leds/leds-pwm.c
drivers/macintosh/Kconfig
drivers/macintosh/windfarm_lm75_sensor.c
drivers/macintosh/windfarm_max6690_sensor.c
drivers/md/bcache/bcache.h
drivers/md/bcache/btree.c
drivers/md/bcache/debug.c
drivers/md/bcache/io.c
drivers/md/bcache/journal.c
drivers/md/bcache/movinggc.c
drivers/md/bcache/request.c
drivers/md/bcache/super.c
drivers/md/bcache/util.c
drivers/md/bcache/writeback.c
drivers/md/bcache/writeback.h
drivers/md/dm-bio-record.h
drivers/md/dm-bufio.c
drivers/md/dm-cache-policy-mq.c
drivers/md/dm-cache-target.c
drivers/md/dm-crypt.c
drivers/md/dm-delay.c
drivers/md/dm-flakey.c
drivers/md/dm-io.c
drivers/md/dm-linear.c
drivers/md/dm-raid1.c
drivers/md/dm-region-hash.c
drivers/md/dm-snap.c
drivers/md/dm-stats.c
drivers/md/dm-stripe.c
drivers/md/dm-switch.c
drivers/md/dm-table.c
drivers/md/dm-thin-metadata.c
drivers/md/dm-thin-metadata.h
drivers/md/dm-thin.c
drivers/md/dm-verity.c
drivers/md/dm.c
drivers/md/faulty.c
drivers/md/linear.c
drivers/md/md.c
drivers/md/multipath.c
drivers/md/persistent-data/dm-block-manager.c
drivers/md/persistent-data/dm-block-manager.h
drivers/md/persistent-data/dm-space-map-metadata.c
drivers/md/raid0.c
drivers/md/raid1.c
drivers/md/raid10.c
drivers/md/raid5.c
drivers/media/common/siano/smscoreapi.h
drivers/media/common/siano/smsdvb.h
drivers/media/dvb-core/dvb_demux.c
drivers/media/dvb-frontends/af9033.c
drivers/media/dvb-frontends/cx24117.c
drivers/media/dvb-frontends/cxd2820r_c.c
drivers/media/dvb-frontends/dib8000.c
drivers/media/dvb-frontends/drxk_hard.c
drivers/media/dvb-frontends/rtl2830.c
drivers/media/i2c/adv7183_regs.h
drivers/media/i2c/adv7604.c
drivers/media/i2c/adv7842.c
drivers/media/i2c/ir-kbd-i2c.c
drivers/media/i2c/lm3560.c
drivers/media/i2c/m5mols/m5mols_controls.c
drivers/media/i2c/mt9p031.c
drivers/media/i2c/s5c73m3/s5c73m3-core.c
drivers/media/i2c/s5c73m3/s5c73m3.h
drivers/media/i2c/saa7115.c
drivers/media/i2c/smiapp/smiapp-core.c
drivers/media/i2c/soc_camera/ov5642.c
drivers/media/i2c/ths7303.c
drivers/media/i2c/wm8775.c
drivers/media/media-entity.c
drivers/media/pci/bt8xx/bttv-driver.c
drivers/media/pci/cx18/cx18-driver.h
drivers/media/pci/cx23885/cx23885-417.c
drivers/media/pci/pluto2/pluto2.c
drivers/media/pci/saa7164/saa7164-core.c
drivers/media/platform/coda.c
drivers/media/platform/exynos4-is/fimc-capture.c
drivers/media/platform/exynos4-is/fimc-core.c
drivers/media/platform/exynos4-is/fimc-core.h
drivers/media/platform/exynos4-is/fimc-is-regs.c
drivers/media/platform/exynos4-is/fimc-is-regs.h
drivers/media/platform/exynos4-is/fimc-lite-reg.c
drivers/media/platform/exynos4-is/fimc-lite.c
drivers/media/platform/exynos4-is/fimc-m2m.c
drivers/media/platform/exynos4-is/media-dev.c
drivers/media/platform/exynos4-is/mipi-csis.c
drivers/media/platform/fsl-viu.c
drivers/media/platform/marvell-ccic/mmp-driver.c
drivers/media/platform/mem2mem_testdev.c
drivers/media/platform/omap3isp/isp.c
drivers/media/platform/omap3isp/ispccdc.c
drivers/media/platform/omap3isp/ispccp2.c
drivers/media/platform/omap3isp/ispcsi2.c
drivers/media/platform/omap3isp/isppreview.c
drivers/media/platform/omap3isp/ispresizer.c
drivers/media/platform/omap3isp/ispstat.c
drivers/media/platform/omap3isp/ispvideo.c
drivers/media/platform/s5p-g2d/g2d.c
drivers/media/platform/s5p-g2d/g2d.h
drivers/media/platform/s5p-jpeg/jpeg-core.c
drivers/media/platform/s5p-jpeg/jpeg-core.h
drivers/media/platform/s5p-mfc/regs-mfc.h
drivers/media/platform/s5p-mfc/s5p_mfc.c
drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
drivers/media/platform/s5p-tv/mixer.h
drivers/media/platform/s5p-tv/mixer_drv.c
drivers/media/platform/s5p-tv/mixer_video.c
drivers/media/platform/s5p-tv/sdo_drv.c
drivers/media/platform/soc_camera/omap1_camera.c
drivers/media/platform/vivi.c
drivers/media/platform/vsp1/vsp1_drv.c
drivers/media/platform/vsp1/vsp1_video.c
drivers/media/radio/radio-shark.c
drivers/media/radio/radio-shark2.c
drivers/media/radio/radio-si476x.c
drivers/media/radio/radio-tea5764.c
drivers/media/radio/tef6862.c
drivers/media/rc/imon.c
drivers/media/rc/redrat3.c
drivers/media/tuners/mt2063.c
drivers/media/tuners/tuner-xc2028-types.h
drivers/media/usb/cx231xx/cx231xx-cards.c
drivers/media/usb/dvb-usb-v2/af9035.c
drivers/media/usb/dvb-usb-v2/mxl111sf.c
drivers/media/usb/dvb-usb/technisat-usb2.c
drivers/media/usb/em28xx/em28xx-video.c
drivers/media/usb/gspca/gl860/gl860.c
drivers/media/usb/gspca/pac207.c
drivers/media/usb/gspca/pac7302.c
drivers/media/usb/gspca/stk1135.c
drivers/media/usb/gspca/stv0680.c
drivers/media/usb/gspca/sunplus.c
drivers/media/usb/gspca/zc3xx.c
drivers/media/usb/pwc/pwc-if.c
drivers/media/usb/usbtv/usbtv.c
drivers/media/usb/uvc/uvc_video.c
drivers/media/v4l2-core/v4l2-ctrls.c
drivers/media/v4l2-core/v4l2-mem2mem.c
drivers/media/v4l2-core/videobuf2-core.c
drivers/media/v4l2-core/videobuf2-dma-contig.c
drivers/media/v4l2-core/videobuf2-dma-sg.c
drivers/message/fusion/mptsas.c
drivers/mfd/88pm800.c
drivers/mfd/88pm805.c
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/ab8500-core.c
drivers/mfd/ab8500-debugfs.c
drivers/mfd/arizona-core.c
drivers/mfd/as3722.c
drivers/mfd/asic3.c
drivers/mfd/cros_ec.c
drivers/mfd/cros_ec_i2c.c
drivers/mfd/cros_ec_spi.c
drivers/mfd/cs5535-mfd.c
drivers/mfd/da9052-core.c
drivers/mfd/da9055-core.c
drivers/mfd/da9063-core.c
drivers/mfd/db8500-prcmu.c
drivers/mfd/htc-pasic3.c
drivers/mfd/intel_msic.c
drivers/mfd/janz-cmodio.c
drivers/mfd/jz4740-adc.c
drivers/mfd/lp3943.c [new file with mode: 0644]
drivers/mfd/lp8788.c
drivers/mfd/lpc_ich.c
drivers/mfd/lpc_sch.c
drivers/mfd/max14577.c [new file with mode: 0644]
drivers/mfd/max77686.c
drivers/mfd/max77693.c
drivers/mfd/max8907.c
drivers/mfd/max8925-core.c
drivers/mfd/max8997.c
drivers/mfd/max8998.c
drivers/mfd/mc13xxx-core.c
drivers/mfd/mc13xxx-spi.c
drivers/mfd/omap-usb-host.c
drivers/mfd/omap-usb-tll.c
drivers/mfd/pcf50633-core.c
drivers/mfd/rc5t583.c
drivers/mfd/rdc321x-southbridge.c
drivers/mfd/retu-mfd.c
drivers/mfd/rtl8411.c
drivers/mfd/rtsx_pcr.c
drivers/mfd/sec-core.c
drivers/mfd/sec-irq.c
drivers/mfd/sm501.c
drivers/mfd/sta2x11-mfd.c
drivers/mfd/stmpe.c
drivers/mfd/stmpe.h
drivers/mfd/tc3589x.c
drivers/mfd/tc6387xb.c
drivers/mfd/ti-ssp.c
drivers/mfd/timberdale.c
drivers/mfd/tps6507x.c
drivers/mfd/tps65090.c
drivers/mfd/tps65217.c
drivers/mfd/tps6586x.c
drivers/mfd/tps65910.c
drivers/mfd/tps65912-core.c
drivers/mfd/tps80031.c
drivers/mfd/twl-core.c
drivers/mfd/viperboard.c
drivers/mfd/vx855.c
drivers/mfd/wm5110-tables.c
drivers/mfd/wm831x-core.c
drivers/mfd/wm831x-i2c.c
drivers/mfd/wm831x-spi.c
drivers/mfd/wm8994-core.c
drivers/misc/enclosure.c
drivers/misc/mei/hw-me-regs.h
drivers/misc/mei/pci-me.c
drivers/misc/mic/card/mic_virtio.c
drivers/misc/mic/card/mic_virtio.h
drivers/misc/mic/host/mic_boot.c
drivers/misc/mic/host/mic_virtio.c
drivers/misc/mic/host/mic_x100.c
drivers/mmc/core/sdio_bus.c
drivers/mmc/host/mmci.c
drivers/mmc/host/omap.c
drivers/mtd/afs.c
drivers/mtd/ar7part.c
drivers/mtd/bcm47xxpart.c
drivers/mtd/bcm63xxpart.c
drivers/mtd/cmdlinepart.c
drivers/mtd/devices/m25p80.c
drivers/mtd/devices/ms02-nv.c
drivers/mtd/devices/mtd_dataflash.c
drivers/mtd/maps/pxa2xx-flash.c
drivers/mtd/maps/sun_uflash.c
drivers/mtd/mtdcore.c
drivers/mtd/mtdpart.c
drivers/mtd/nand/Kconfig
drivers/mtd/nand/denali_pci.c
drivers/mtd/nand/diskonchip.c
drivers/mtd/nand/gpmi-nand/gpmi-lib.c
drivers/mtd/nand/gpmi-nand/gpmi-nand.c
drivers/mtd/nand/gpmi-nand/gpmi-nand.h
drivers/mtd/nand/mpc5121_nfc.c
drivers/mtd/nand/mxc_nand.c
drivers/mtd/nand/nand_base.c
drivers/mtd/nand/pasemi_nand.c
drivers/mtd/nand/pxa3xx_nand.c
drivers/mtd/nand/sh_flctl.c
drivers/mtd/ofpart.c
drivers/mtd/redboot.c
drivers/mtd/tests/mtd_nandecctest.c
drivers/net/bonding/bond_alb.c
drivers/net/bonding/bond_alb.h
drivers/net/bonding/bond_main.c
drivers/net/bonding/bond_options.c
drivers/net/bonding/bond_sysfs.c
drivers/net/bonding/bonding.h
drivers/net/can/c_can/c_can.c
drivers/net/can/flexcan.c
drivers/net/can/mscan/mpc5xxx_can.c
drivers/net/can/sja1000/sja1000.c
drivers/net/ethernet/3com/3c59x.c
drivers/net/ethernet/8390/8390.h
drivers/net/ethernet/8390/apne.c
drivers/net/ethernet/8390/ax88796.c
drivers/net/ethernet/8390/axnet_cs.c
drivers/net/ethernet/8390/etherh.c
drivers/net/ethernet/8390/hydra.c
drivers/net/ethernet/8390/lib8390.c
drivers/net/ethernet/8390/mac8390.c
drivers/net/ethernet/8390/mcf8390.c
drivers/net/ethernet/8390/ne.c
drivers/net/ethernet/8390/ne2k-pci.c
drivers/net/ethernet/8390/pcnet_cs.c
drivers/net/ethernet/8390/smc-ultra.c
drivers/net/ethernet/8390/stnic.c
drivers/net/ethernet/8390/wd.c
drivers/net/ethernet/8390/zorro8390.c
drivers/net/ethernet/adi/bfin_mac.c
drivers/net/ethernet/aeroflex/greth.c
drivers/net/ethernet/allwinner/sun4i-emac.c
drivers/net/ethernet/amd/a2065.c
drivers/net/ethernet/amd/amd8111e.c
drivers/net/ethernet/amd/amd8111e.h
drivers/net/ethernet/amd/ariadne.c
drivers/net/ethernet/amd/au1000_eth.c
drivers/net/ethernet/amd/au1000_eth.h
drivers/net/ethernet/arc/emac.h
drivers/net/ethernet/arc/emac_main.c
drivers/net/ethernet/broadcom/bgmac.c
drivers/net/ethernet/broadcom/bgmac.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
drivers/net/ethernet/broadcom/sb1250-mac.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/broadcom/tg3.h
drivers/net/ethernet/brocade/bna/bnad.c
drivers/net/ethernet/cadence/macb.c
drivers/net/ethernet/cadence/macb.h
drivers/net/ethernet/chelsio/cxgb/common.h
drivers/net/ethernet/chelsio/cxgb/cphy.h
drivers/net/ethernet/chelsio/cxgb/cpl5_cmd.h
drivers/net/ethernet/chelsio/cxgb/cxgb2.c
drivers/net/ethernet/chelsio/cxgb/elmer0.h
drivers/net/ethernet/chelsio/cxgb/espi.c
drivers/net/ethernet/chelsio/cxgb/espi.h
drivers/net/ethernet/chelsio/cxgb/gmac.h
drivers/net/ethernet/chelsio/cxgb/mv88x201x.c
drivers/net/ethernet/chelsio/cxgb/pm3393.c
drivers/net/ethernet/chelsio/cxgb/regs.h
drivers/net/ethernet/chelsio/cxgb/sge.c
drivers/net/ethernet/chelsio/cxgb/sge.h
drivers/net/ethernet/chelsio/cxgb/subr.c
drivers/net/ethernet/chelsio/cxgb/suni1x10gexp_regs.h
drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/chelsio/cxgb4/sge.c
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
drivers/net/ethernet/chelsio/cxgb4vf/adapter.h
drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
drivers/net/ethernet/chelsio/cxgb4vf/sge.c
drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h
drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c
drivers/net/ethernet/emulex/benet/be.h
drivers/net/ethernet/emulex/benet/be_cmds.c
drivers/net/ethernet/emulex/benet/be_hw.h
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/freescale/fec.h
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/freescale/fec_ptp.c
drivers/net/ethernet/freescale/gianfar.c
drivers/net/ethernet/ibm/ehea/ehea_main.c
drivers/net/ethernet/ibm/ibmveth.c
drivers/net/ethernet/ibm/ibmveth.h
drivers/net/ethernet/intel/Kconfig
drivers/net/ethernet/intel/e1000/e1000.h
drivers/net/ethernet/intel/e1000/e1000_main.c
drivers/net/ethernet/intel/e1000e/netdev.c
drivers/net/ethernet/intel/i40e/i40e.h
drivers/net/ethernet/intel/i40e/i40e_adminq.c
drivers/net/ethernet/intel/i40e/i40e_adminq.h
drivers/net/ethernet/intel/i40e/i40e_common.c
drivers/net/ethernet/intel/i40e/i40e_debugfs.c
drivers/net/ethernet/intel/i40e/i40e_diag.c
drivers/net/ethernet/intel/i40e/i40e_diag.h
drivers/net/ethernet/intel/i40e/i40e_ethtool.c
drivers/net/ethernet/intel/i40e/i40e_lan_hmc.h
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/i40e/i40e_prototype.h
drivers/net/ethernet/intel/i40e/i40e_register.h
drivers/net/ethernet/intel/i40e/i40e_txrx.c
drivers/net/ethernet/intel/i40e/i40e_txrx.h
drivers/net/ethernet/intel/i40e/i40e_type.h
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
drivers/net/ethernet/intel/igb/e1000_82575.c
drivers/net/ethernet/intel/igb/e1000_defines.h
drivers/net/ethernet/intel/igb/e1000_hw.h
drivers/net/ethernet/intel/igb/igb.h
drivers/net/ethernet/intel/igb/igb_ethtool.c
drivers/net/ethernet/intel/igb/igb_hwmon.c
drivers/net/ethernet/intel/igb/igb_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
drivers/net/ethernet/lantiq_etop.c
drivers/net/ethernet/marvell/mv643xx_eth.c
drivers/net/ethernet/marvell/mvneta.c
drivers/net/ethernet/marvell/pxa168_eth.c
drivers/net/ethernet/mellanox/mlx4/alloc.c
drivers/net/ethernet/mellanox/mlx4/cq.c
drivers/net/ethernet/mellanox/mlx4/en_netdev.c
drivers/net/ethernet/mellanox/mlx4/en_selftest.c
drivers/net/ethernet/mellanox/mlx4/eq.c
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx4/mcg.c
drivers/net/ethernet/mellanox/mlx4/mlx4.h
drivers/net/ethernet/mellanox/mlx4/mr.c
drivers/net/ethernet/mellanox/mlx4/pd.c
drivers/net/ethernet/mellanox/mlx4/qp.c
drivers/net/ethernet/mellanox/mlx4/srq.c
drivers/net/ethernet/natsemi/macsonic.c
drivers/net/ethernet/natsemi/ns83820.c
drivers/net/ethernet/neterion/vxge/vxge-main.c
drivers/net/ethernet/netx-eth.c
drivers/net/ethernet/nvidia/forcedeth.c
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.c
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.h
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.c
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.h
drivers/net/ethernet/pasemi/pasemi_mac.c
drivers/net/ethernet/pasemi/pasemi_mac.h
drivers/net/ethernet/pasemi/pasemi_mac_ethtool.c
drivers/net/ethernet/qlogic/netxen/Makefile
drivers/net/ethernet/qlogic/netxen/netxen_nic.h
drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c
drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c
drivers/net/ethernet/qlogic/netxen/netxen_nic_hdr.h
drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c
drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.h
drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
drivers/net/ethernet/qlogic/qlge/qlge.h
drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c
drivers/net/ethernet/qlogic/qlge/qlge_main.c
drivers/net/ethernet/realtek/8139cp.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/ethernet/renesas/Kconfig
drivers/net/ethernet/renesas/sh_eth.c
drivers/net/ethernet/sfc/efx.c
drivers/net/ethernet/sfc/mcdi.c
drivers/net/ethernet/sfc/mcdi.h
drivers/net/ethernet/sfc/mcdi_mon.c
drivers/net/ethernet/sfc/net_driver.h
drivers/net/ethernet/sfc/nic.h
drivers/net/ethernet/sfc/ptp.c
drivers/net/ethernet/sfc/rx.c
drivers/net/ethernet/sis/sis900.c
drivers/net/ethernet/smsc/smc911x.c
drivers/net/ethernet/smsc/smc911x.h
drivers/net/ethernet/smsc/smc91x.c
drivers/net/ethernet/smsc/smc91x.h
drivers/net/ethernet/smsc/smsc911x.c
drivers/net/ethernet/smsc/smsc911x.h
drivers/net/ethernet/smsc/smsc9420.c
drivers/net/ethernet/smsc/smsc9420.h
drivers/net/ethernet/sun/cassini.c
drivers/net/ethernet/sun/cassini.h
drivers/net/ethernet/tehuti/tehuti.c
drivers/net/ethernet/ti/cpsw.c
drivers/net/ethernet/ti/davinci_emac.c
drivers/net/ethernet/tile/tilegx.c
drivers/net/ethernet/toshiba/tc35815.c
drivers/net/ethernet/tundra/tsi108_eth.h
drivers/net/ethernet/via/via-velocity.c
drivers/net/ethernet/xilinx/ll_temac_main.c
drivers/net/ethernet/xilinx/xilinx_axienet_main.c
drivers/net/ethernet/xilinx/xilinx_emaclite.c
drivers/net/ethernet/xircom/xirc2ps_cs.c
drivers/net/ethernet/xscale/ixp4xx_eth.c
drivers/net/fddi/defxx.c
drivers/net/fddi/skfp/skfddi.c
drivers/net/hamradio/mkiss.c
drivers/net/hippi/rrunner.c
drivers/net/hyperv/hyperv_net.h
drivers/net/hyperv/netvsc.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/hyperv/rndis_filter.c
drivers/net/ieee802154/at86rf230.c
drivers/net/ieee802154/mrf24j40.c
drivers/net/irda/au1k_ir.c
drivers/net/irda/esi-sir.c
drivers/net/irda/litelink-sir.c
drivers/net/irda/ma600-sir.c
drivers/net/irda/old_belkin-sir.c
drivers/net/irda/smsc-ircc2.c
drivers/net/irda/smsc-ircc2.h
drivers/net/irda/via-ircc.c
drivers/net/irda/via-ircc.h
drivers/net/irda/vlsi_ir.c
drivers/net/irda/vlsi_ir.h
drivers/net/macvlan.c
drivers/net/macvtap.c
drivers/net/phy/micrel.c
drivers/net/phy/phy.c
drivers/net/phy/phy_device.c
drivers/net/phy/spi_ks8995.c
drivers/net/phy/vitesse.c
drivers/net/ppp/ppp_mppe.c
drivers/net/team/team.c
drivers/net/tun.c
drivers/net/usb/asix.h
drivers/net/usb/asix_common.c
drivers/net/usb/asix_devices.c
drivers/net/usb/ax88172a.c
drivers/net/usb/ax88179_178a.c
drivers/net/usb/catc.c
drivers/net/usb/cdc_eem.c
drivers/net/usb/cdc_ether.c
drivers/net/usb/cdc_subset.c
drivers/net/usb/cx82310_eth.c
drivers/net/usb/gl620a.c
drivers/net/usb/int51x1.c
drivers/net/usb/kaweth.c
drivers/net/usb/lg-vl600.c
drivers/net/usb/mcs7830.c
drivers/net/usb/net1080.c
drivers/net/usb/plusb.c
drivers/net/usb/rndis_host.c
drivers/net/usb/sierra_net.c
drivers/net/usb/smsc75xx.c
drivers/net/usb/smsc75xx.h
drivers/net/usb/smsc95xx.c
drivers/net/usb/smsc95xx.h
drivers/net/usb/usbnet.c
drivers/net/usb/zaurus.c
drivers/net/virtio_net.c
drivers/net/vmxnet3/vmxnet3_drv.c
drivers/net/vxlan.c
drivers/net/wan/dscc4.c
drivers/net/wan/lmc/lmc_main.c
drivers/net/wan/pc300too.c
drivers/net/wan/pci200syn.c
drivers/net/wan/wanxl.c
drivers/net/wireless/ath/ath10k/ce.c
drivers/net/wireless/ath/ath10k/ce.h
drivers/net/wireless/ath/ath10k/core.c
drivers/net/wireless/ath/ath10k/core.h
drivers/net/wireless/ath/ath10k/debug.c
drivers/net/wireless/ath/ath10k/debug.h
drivers/net/wireless/ath/ath10k/htc.c
drivers/net/wireless/ath/ath10k/htt.c
drivers/net/wireless/ath/ath10k/htt.h
drivers/net/wireless/ath/ath10k/htt_rx.c
drivers/net/wireless/ath/ath10k/htt_tx.c
drivers/net/wireless/ath/ath10k/hw.h
drivers/net/wireless/ath/ath10k/mac.c
drivers/net/wireless/ath/ath10k/pci.c
drivers/net/wireless/ath/ath10k/pci.h
drivers/net/wireless/ath/ath10k/txrx.c
drivers/net/wireless/ath/ath10k/wmi.c
drivers/net/wireless/ath/ath10k/wmi.h
drivers/net/wireless/ath/ath5k/dma.c
drivers/net/wireless/ath/ath6kl/cfg80211.c
drivers/net/wireless/ath/ath9k/Kconfig
drivers/net/wireless/ath/ath9k/Makefile
drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
drivers/net/wireless/ath/ath9k/ar9003_buffalo_initvals.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k/ar9003_calib.c
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
drivers/net/wireless/ath/ath9k/ar9003_hw.c
drivers/net/wireless/ath/ath9k/ar9003_phy.c
drivers/net/wireless/ath/ath9k/ar9003_phy.h
drivers/net/wireless/ath/ath9k/ar9003_wow.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h
drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h
drivers/net/wireless/ath/ath9k/ar9340_initvals.h
drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h
drivers/net/wireless/ath/ath9k/ar9462_2p1_initvals.h
drivers/net/wireless/ath/ath9k/ar9485_initvals.h
drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h
drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h
drivers/net/wireless/ath/ath9k/ar9565_1p1_initvals.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/debug.c
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/hw.h
drivers/net/wireless/ath/ath9k/init.c
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/ath9k/pci.c
drivers/net/wireless/ath/ath9k/reg.h
drivers/net/wireless/ath/ath9k/tx99.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k/wow.c
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/ath/regd.c
drivers/net/wireless/ath/wcn36xx/hal.h
drivers/net/wireless/ath/wcn36xx/main.c
drivers/net/wireless/ath/wcn36xx/smd.c
drivers/net/wireless/ath/wcn36xx/wcn36xx.h
drivers/net/wireless/atmel.c
drivers/net/wireless/atmel.h
drivers/net/wireless/atmel_cs.c
drivers/net/wireless/atmel_pci.c
drivers/net/wireless/brcm80211/Kconfig
drivers/net/wireless/brcm80211/brcmfmac/Makefile
drivers/net/wireless/brcm80211/brcmfmac/bcdc.c [new file with mode: 0644]
drivers/net/wireless/brcm80211/brcmfmac/bcdc.h [new file with mode: 0644]
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
drivers/net/wireless/brcm80211/brcmfmac/dhd.h
drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c [deleted file]
drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h
drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h [deleted file]
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
drivers/net/wireless/brcm80211/brcmfmac/fweh.h
drivers/net/wireless/brcm80211/brcmfmac/fwil.c
drivers/net/wireless/brcm80211/brcmfmac/fwil.h
drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
drivers/net/wireless/brcm80211/brcmfmac/p2p.c
drivers/net/wireless/brcm80211/brcmfmac/proto.c [new file with mode: 0644]
drivers/net/wireless/brcm80211/brcmfmac/proto.h [new file with mode: 0644]
drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h
drivers/net/wireless/brcm80211/brcmfmac/usb.c
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
drivers/net/wireless/brcm80211/brcmsmac/channel.c
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
drivers/net/wireless/cw1200/cw1200_sdio.c
drivers/net/wireless/cw1200/scan.c
drivers/net/wireless/ipw2x00/ipw2100.c
drivers/net/wireless/ipw2x00/ipw2200.c
drivers/net/wireless/iwlegacy/3945-mac.c
drivers/net/wireless/iwlegacy/4965-mac.c
drivers/net/wireless/iwlegacy/common.c
drivers/net/wireless/iwlegacy/debug.c
drivers/net/wireless/iwlwifi/dvm/debugfs.c
drivers/net/wireless/iwlwifi/dvm/mac80211.c
drivers/net/wireless/iwlwifi/dvm/rs.h
drivers/net/wireless/iwlwifi/dvm/scan.c
drivers/net/wireless/iwlwifi/dvm/tx.c
drivers/net/wireless/iwlwifi/iwl-7000.c
drivers/net/wireless/iwlwifi/iwl-config.h
drivers/net/wireless/iwlwifi/iwl-csr.h
drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c
drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
drivers/net/wireless/iwlwifi/iwl-prph.h
drivers/net/wireless/iwlwifi/mvm/Makefile
drivers/net/wireless/iwlwifi/mvm/bt-coex.c
drivers/net/wireless/iwlwifi/mvm/d3.c
drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c [new file with mode: 0644]
drivers/net/wireless/iwlwifi/mvm/debugfs.c
drivers/net/wireless/iwlwifi/mvm/debugfs.h [new file with mode: 0644]
drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h
drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h
drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
drivers/net/wireless/iwlwifi/mvm/mac80211.c
drivers/net/wireless/iwlwifi/mvm/mvm.h
drivers/net/wireless/iwlwifi/mvm/nvm.c
drivers/net/wireless/iwlwifi/mvm/quota.c
drivers/net/wireless/iwlwifi/mvm/rs.c
drivers/net/wireless/iwlwifi/mvm/rs.h
drivers/net/wireless/iwlwifi/mvm/scan.c
drivers/net/wireless/iwlwifi/mvm/sta.c
drivers/net/wireless/iwlwifi/mvm/sta.h
drivers/net/wireless/iwlwifi/mvm/time-event.c
drivers/net/wireless/iwlwifi/mvm/tt.c
drivers/net/wireless/iwlwifi/mvm/tx.c
drivers/net/wireless/iwlwifi/mvm/utils.c
drivers/net/wireless/iwlwifi/pcie/drv.c
drivers/net/wireless/iwlwifi/pcie/internal.h
drivers/net/wireless/iwlwifi/pcie/rx.c
drivers/net/wireless/iwlwifi/pcie/trans.c
drivers/net/wireless/iwlwifi/pcie/tx.c
drivers/net/wireless/libertas/README
drivers/net/wireless/libertas/if_sdio.c
drivers/net/wireless/libertas/if_spi.c
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/mwifiex/11n_aggr.c
drivers/net/wireless/mwifiex/cfg80211.c
drivers/net/wireless/mwifiex/cmdevt.c
drivers/net/wireless/mwifiex/decl.h
drivers/net/wireless/mwifiex/fw.h
drivers/net/wireless/mwifiex/init.c
drivers/net/wireless/mwifiex/main.c
drivers/net/wireless/mwifiex/main.h
drivers/net/wireless/mwifiex/scan.c
drivers/net/wireless/mwifiex/sta_cmd.c
drivers/net/wireless/mwifiex/sta_cmdresp.c
drivers/net/wireless/mwifiex/sta_ioctl.c
drivers/net/wireless/mwifiex/sta_rx.c
drivers/net/wireless/mwifiex/sta_tx.c
drivers/net/wireless/mwifiex/txrx.c
drivers/net/wireless/mwifiex/uap_txrx.c
drivers/net/wireless/mwifiex/usb.c
drivers/net/wireless/mwifiex/util.c
drivers/net/wireless/p54/net2280.h
drivers/net/wireless/prism54/isl_38xx.c
drivers/net/wireless/prism54/isl_38xx.h
drivers/net/wireless/prism54/isl_ioctl.c
drivers/net/wireless/prism54/isl_ioctl.h
drivers/net/wireless/prism54/isl_oid.h
drivers/net/wireless/prism54/islpci_dev.c
drivers/net/wireless/prism54/islpci_dev.h
drivers/net/wireless/prism54/islpci_eth.c
drivers/net/wireless/prism54/islpci_eth.h
drivers/net/wireless/prism54/islpci_hotplug.c
drivers/net/wireless/prism54/islpci_mgt.c
drivers/net/wireless/prism54/islpci_mgt.h
drivers/net/wireless/prism54/oid_mgt.c
drivers/net/wireless/prism54/oid_mgt.h
drivers/net/wireless/prism54/prismcompat.h
drivers/net/wireless/ray_cs.c
drivers/net/wireless/rndis_wlan.c
drivers/net/wireless/rt2x00/rt2400pci.c
drivers/net/wireless/rt2x00/rt2400pci.h
drivers/net/wireless/rt2x00/rt2500pci.c
drivers/net/wireless/rt2x00/rt2500pci.h
drivers/net/wireless/rt2x00/rt2500usb.c
drivers/net/wireless/rt2x00/rt2500usb.h
drivers/net/wireless/rt2x00/rt2800.h
drivers/net/wireless/rt2x00/rt2800lib.c
drivers/net/wireless/rt2x00/rt2800lib.h
drivers/net/wireless/rt2x00/rt2800mmio.c
drivers/net/wireless/rt2x00/rt2800mmio.h
drivers/net/wireless/rt2x00/rt2800pci.c
drivers/net/wireless/rt2x00/rt2800pci.h
drivers/net/wireless/rt2x00/rt2800soc.c
drivers/net/wireless/rt2x00/rt2800usb.c
drivers/net/wireless/rt2x00/rt2800usb.h
drivers/net/wireless/rt2x00/rt2x00.h
drivers/net/wireless/rt2x00/rt2x00config.c
drivers/net/wireless/rt2x00/rt2x00crypto.c
drivers/net/wireless/rt2x00/rt2x00debug.c
drivers/net/wireless/rt2x00/rt2x00debug.h
drivers/net/wireless/rt2x00/rt2x00dev.c
drivers/net/wireless/rt2x00/rt2x00dump.h
drivers/net/wireless/rt2x00/rt2x00firmware.c
drivers/net/wireless/rt2x00/rt2x00leds.c
drivers/net/wireless/rt2x00/rt2x00leds.h
drivers/net/wireless/rt2x00/rt2x00lib.h
drivers/net/wireless/rt2x00/rt2x00link.c
drivers/net/wireless/rt2x00/rt2x00mac.c
drivers/net/wireless/rt2x00/rt2x00mmio.c
drivers/net/wireless/rt2x00/rt2x00mmio.h
drivers/net/wireless/rt2x00/rt2x00pci.c
drivers/net/wireless/rt2x00/rt2x00pci.h
drivers/net/wireless/rt2x00/rt2x00queue.c
drivers/net/wireless/rt2x00/rt2x00queue.h
drivers/net/wireless/rt2x00/rt2x00reg.h
drivers/net/wireless/rt2x00/rt2x00soc.c
drivers/net/wireless/rt2x00/rt2x00soc.h
drivers/net/wireless/rt2x00/rt2x00usb.c
drivers/net/wireless/rt2x00/rt2x00usb.h
drivers/net/wireless/rt2x00/rt61pci.c
drivers/net/wireless/rt2x00/rt61pci.h
drivers/net/wireless/rt2x00/rt73usb.c
drivers/net/wireless/rt2x00/rt73usb.h
drivers/net/wireless/rtl818x/rtl8187/dev.c
drivers/net/wireless/rtlwifi/base.c
drivers/net/wireless/rtlwifi/core.c
drivers/net/wireless/rtlwifi/pci.c
drivers/net/wireless/rtlwifi/regd.c
drivers/net/wireless/rtlwifi/rtl8188ee/dm.c
drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h
drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
drivers/net/wireless/rtlwifi/rtl8192cu/dm.c
drivers/net/wireless/rtlwifi/rtl8192cu/dm.h
drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
drivers/net/wireless/rtlwifi/rtl8192cu/phy.c
drivers/net/wireless/rtlwifi/rtl8192cu/rf.c
drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
drivers/net/wireless/rtlwifi/rtl8192cu/table.c
drivers/net/wireless/rtlwifi/stats.c
drivers/net/wireless/rtlwifi/usb.c
drivers/net/wireless/rtlwifi/wifi.h
drivers/net/wireless/ti/wl1251/acx.c
drivers/net/wireless/ti/wl12xx/scan.c
drivers/net/wireless/ti/wlcore/cmd.c
drivers/net/wireless/ti/wlcore/main.c
drivers/net/wireless/ti/wlcore/scan.c
drivers/net/wireless/zd1211rw/zd_chip.c
drivers/net/wireless/zd1211rw/zd_chip.h
drivers/net/wireless/zd1211rw/zd_def.h
drivers/net/wireless/zd1211rw/zd_mac.c
drivers/net/wireless/zd1211rw/zd_mac.h
drivers/net/wireless/zd1211rw/zd_rf.c
drivers/net/wireless/zd1211rw/zd_rf.h
drivers/net/wireless/zd1211rw/zd_rf_al2230.c
drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
drivers/net/wireless/zd1211rw/zd_rf_rf2959.c
drivers/net/wireless/zd1211rw/zd_rf_uw2453.c
drivers/net/wireless/zd1211rw/zd_usb.c
drivers/net/wireless/zd1211rw/zd_usb.h
drivers/net/xen-netback/common.h
drivers/net/xen-netback/interface.c
drivers/net/xen-netback/netback.c
drivers/net/xen-netback/xenbus.c
drivers/nfc/mei_phy.c
drivers/nfc/microread/i2c.c
drivers/nfc/microread/mei.c
drivers/nfc/microread/microread.c
drivers/nfc/microread/microread.h
drivers/nfc/nfcwilink.c
drivers/nfc/pn533.c
drivers/nfc/pn544/i2c.c
drivers/nfc/pn544/mei.c
drivers/nfc/pn544/pn544.c
drivers/nfc/pn544/pn544.h
drivers/of/base.c
drivers/of/irq.c
drivers/of/of_mdio.c
drivers/parport/parport_mfc3.c
drivers/pci/host/pci-mvebu.c
drivers/pci/hotplug/acpiphp_glue.c
drivers/pci/hotplug/acpiphp_ibm.c
drivers/pci/hotplug/pciehp.h
drivers/pci/ioapic.c
drivers/pci/pci-acpi.c
drivers/pci/pci-driver.c
drivers/pci/pci-label.c
drivers/pci/pci.c
drivers/pci/remove.c
drivers/phy/Kconfig
drivers/phy/phy-core.c
drivers/pinctrl/Kconfig
drivers/pinctrl/pinctrl-abx500.c
drivers/pinctrl/pinctrl-abx500.h
drivers/pinctrl/pinctrl-baytrail.c
drivers/pinctrl/pinctrl-imx1-core.c
drivers/pinctrl/pinctrl-nomadik.c
drivers/pinctrl/pinctrl-nomadik.h
drivers/pinctrl/pinctrl-rockchip.c
drivers/pinctrl/sh-pfc/pfc-r8a7740.c
drivers/pinctrl/sh-pfc/pfc-r8a7791.c
drivers/pinctrl/sh-pfc/pfc-sh7372.c
drivers/platform/x86/acer-wmi.c
drivers/platform/x86/asus-laptop.c
drivers/platform/x86/asus-wmi.c
drivers/platform/x86/classmate-laptop.c
drivers/platform/x86/dell-wmi-aio.c
drivers/platform/x86/dell-wmi.c
drivers/platform/x86/eeepc-laptop.c
drivers/platform/x86/eeepc-wmi.c
drivers/platform/x86/hp_accel.c
drivers/platform/x86/ideapad-laptop.c
drivers/platform/x86/intel-rst.c
drivers/platform/x86/intel-smartconnect.c
drivers/platform/x86/intel_menlow.c
drivers/platform/x86/intel_oaktrail.c
drivers/platform/x86/mxm-wmi.c
drivers/platform/x86/panasonic-laptop.c
drivers/platform/x86/pvpanic.c
drivers/platform/x86/samsung-q10.c
drivers/platform/x86/sony-laptop.c
drivers/platform/x86/tc1100-wmi.c
drivers/platform/x86/thinkpad_acpi.c
drivers/platform/x86/toshiba_acpi.c
drivers/platform/x86/toshiba_bluetooth.c
drivers/platform/x86/wmi.c
drivers/platform/x86/xo15-ebook.c
drivers/pnp/driver.c
drivers/pnp/pnpacpi/core.c
drivers/pnp/pnpacpi/pnpacpi.h
drivers/power/Kconfig
drivers/power/power_supply_core.c
drivers/powercap/powercap_sys.c
drivers/pwm/Kconfig
drivers/pwm/Makefile
drivers/pwm/pwm-lp3943.c [new file with mode: 0644]
drivers/regulator/ab8500.c
drivers/regulator/arizona-micsupp.c
drivers/regulator/as3722-regulator.c
drivers/regulator/core.c
drivers/regulator/db8500-prcmu.c
drivers/regulator/gpio-regulator.c
drivers/regulator/lp3971.c
drivers/regulator/lp3972.c
drivers/regulator/pcf50633-regulator.c
drivers/regulator/pfuze100-regulator.c
drivers/regulator/stw481x-vmmc.c
drivers/regulator/tps51632-regulator.c
drivers/regulator/tps6586x-regulator.c
drivers/s390/block/dasd_diag.c
drivers/s390/block/dasd_eckd.c
drivers/s390/block/dasd_fba.c
drivers/s390/block/dasd_genhd.c
drivers/s390/block/dcssblk.c
drivers/s390/block/scm_blk.c
drivers/s390/block/scm_blk_cluster.c
drivers/s390/block/xpram.c
drivers/s390/char/sclp_early.c
drivers/s390/cio/blacklist.c
drivers/s390/cio/chsc.c
drivers/s390/cio/css.c
drivers/s390/cio/css.h
drivers/s390/crypto/ap_bus.c
drivers/s390/crypto/ap_bus.h
drivers/s390/crypto/zcrypt_api.c
drivers/s390/crypto/zcrypt_api.h
drivers/s390/crypto/zcrypt_cex4.c
drivers/s390/crypto/zcrypt_error.h
drivers/s390/crypto/zcrypt_msgtype50.c
drivers/s390/crypto/zcrypt_msgtype6.c
drivers/s390/crypto/zcrypt_msgtype6.h
drivers/s390/crypto/zcrypt_pcica.c
drivers/s390/crypto/zcrypt_pcicc.c
drivers/scsi/3w-9xxx.c
drivers/scsi/3w-sas.c
drivers/scsi/3w-xxxx.c
drivers/scsi/Kconfig
drivers/scsi/a2091.c
drivers/scsi/a3000.c
drivers/scsi/a4000t.c
drivers/scsi/aacraid/linit.c
drivers/scsi/arcmsr/arcmsr_hba.c
drivers/scsi/bfa/bfa_fcs.h
drivers/scsi/bfa/bfa_fcs_lport.c
drivers/scsi/bfa/bfad_attr.c
drivers/scsi/gdth.c
drivers/scsi/gvp11.c
drivers/scsi/hosts.c
drivers/scsi/hpsa.c
drivers/scsi/ipr.c
drivers/scsi/ips.c
drivers/scsi/libsas/sas_ata.c
drivers/scsi/libsas/sas_expander.c
drivers/scsi/megaraid.c
drivers/scsi/megaraid/megaraid_mbox.c
drivers/scsi/megaraid/megaraid_sas_base.c
drivers/scsi/mpt2sas/mpt2sas_transport.c
drivers/scsi/mpt3sas/mpt3sas_transport.c
drivers/scsi/osd/osd_initiator.c
drivers/scsi/pm8001/pm8001_hwi.c
drivers/scsi/pm8001/pm8001_hwi.h
drivers/scsi/pm8001/pm8001_init.c
drivers/scsi/pm8001/pm8001_sas.c
drivers/scsi/pm8001/pm8001_sas.h
drivers/scsi/pm8001/pm80xx_hwi.c
drivers/scsi/pm8001/pm80xx_hwi.h
drivers/scsi/pmcraid.c
drivers/scsi/sd.c
drivers/scsi/sd_dif.c
drivers/scsi/storvsc_drv.c
drivers/scsi/zorro7xx.c
drivers/sfi/sfi_acpi.c
drivers/spi/Kconfig
drivers/spi/Makefile
drivers/spi/spi-atmel.c
drivers/spi/spi-bcm2835.c
drivers/spi/spi-bcm63xx-hsspi.c [new file with mode: 0644]
drivers/spi/spi-bcm63xx.c
drivers/spi/spi-coldfire-qspi.c
drivers/spi/spi-davinci.c
drivers/spi/spi-dw-pci.c
drivers/spi/spi-falcon.c
drivers/spi/spi-fsl-espi.c
drivers/spi/spi-gpio.c
drivers/spi/spi-mpc512x-psc.c
drivers/spi/spi-mxs.c
drivers/spi/spi-omap-100k.c
drivers/spi/spi-omap2-mcspi.c
drivers/spi/spi-orion.c
drivers/spi/spi-pxa2xx-pci.c
drivers/spi/spi-pxa2xx.c
drivers/spi/spi-rspi.c
drivers/spi/spi-sc18is602.c
drivers/spi/spi-sh-msiof.c
drivers/spi/spi-tegra114.c
drivers/spi/spi-tegra20-sflash.c
drivers/spi/spi-tegra20-slink.c
drivers/spi/spi-ti-qspi.c
drivers/spi/spi-topcliff-pch.c
drivers/spi/spi-txx9.c
drivers/spi/spi-xcomm.c
drivers/spi/spi.c
drivers/staging/lustre/lustre/llite/lloop.c
drivers/staging/media/Kconfig
drivers/staging/media/Makefile
drivers/staging/media/bcm2048/Kconfig [new file with mode: 0644]
drivers/staging/media/bcm2048/Makefile [new file with mode: 0644]
drivers/staging/media/bcm2048/TODO [new file with mode: 0644]
drivers/staging/media/bcm2048/radio-bcm2048.c [new file with mode: 0644]
drivers/staging/media/bcm2048/radio-bcm2048.h [new file with mode: 0644]
drivers/staging/media/omap4iss/Kconfig [new file with mode: 0644]
drivers/staging/media/omap4iss/Makefile [new file with mode: 0644]
drivers/staging/media/omap4iss/TODO [new file with mode: 0644]
drivers/staging/media/omap4iss/iss.c [new file with mode: 0644]
drivers/staging/media/omap4iss/iss.h [new file with mode: 0644]
drivers/staging/media/omap4iss/iss_csi2.c [new file with mode: 0644]
drivers/staging/media/omap4iss/iss_csi2.h [new file with mode: 0644]
drivers/staging/media/omap4iss/iss_csiphy.c [new file with mode: 0644]
drivers/staging/media/omap4iss/iss_csiphy.h [new file with mode: 0644]
drivers/staging/media/omap4iss/iss_ipipe.c [new file with mode: 0644]
drivers/staging/media/omap4iss/iss_ipipe.h [new file with mode: 0644]
drivers/staging/media/omap4iss/iss_ipipeif.c [new file with mode: 0644]
drivers/staging/media/omap4iss/iss_ipipeif.h [new file with mode: 0644]
drivers/staging/media/omap4iss/iss_regs.h [new file with mode: 0644]
drivers/staging/media/omap4iss/iss_resizer.c [new file with mode: 0644]
drivers/staging/media/omap4iss/iss_resizer.h [new file with mode: 0644]
drivers/staging/media/omap4iss/iss_video.c [new file with mode: 0644]
drivers/staging/media/omap4iss/iss_video.h [new file with mode: 0644]
drivers/staging/nvec/nvec.c
drivers/staging/quickstart/quickstart.c
drivers/staging/tidspbridge/rmgr/drv_interface.c
drivers/staging/zram/zram_drv.c
drivers/target/target_core_iblock.c
drivers/tty/n_tty.c
drivers/tty/serial/mpc52xx_uart.c
drivers/tty/serial/sh-sci.c
drivers/uio/uio.c
drivers/usb/chipidea/core.c
drivers/usb/chipidea/host.c
drivers/usb/chipidea/udc.c
drivers/usb/class/cdc-acm.c
drivers/usb/class/cdc-wdm.c
drivers/usb/core/hub.c
drivers/usb/core/usb-acpi.c
drivers/usb/dwc3/core.c
drivers/usb/dwc3/ep0.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/Kconfig
drivers/usb/gadget/atmel_usba_udc.c
drivers/usb/gadget/composite.c
drivers/usb/gadget/f_fs.c
drivers/usb/gadget/f_mass_storage.c
drivers/usb/gadget/pxa25x_udc.c
drivers/usb/gadget/s3c-hsotg.c
drivers/usb/gadget/storage_common.h
drivers/usb/gadget/tcm_usb_gadget.c
drivers/usb/gadget/zero.c
drivers/usb/host/fsl-mph-dr-of.c
drivers/usb/host/ohci-pxa27x.c
drivers/usb/host/r8a66597-hcd.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-ring.c
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_cppi41.c
drivers/usb/musb/musb_gadget.c
drivers/usb/phy/phy-am335x.c
drivers/usb/phy/phy-generic.c
drivers/usb/phy/phy-generic.h
drivers/usb/phy/phy-mxs-usb.c
drivers/usb/phy/phy-rcar-gen2-usb.c
drivers/usb/phy/phy-tegra-usb.c
drivers/usb/phy/phy-twl6030-usb.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/generic.c
drivers/usb/serial/mos7840.c
drivers/usb/serial/option.c
drivers/usb/serial/pl2303.c
drivers/usb/serial/spcp8x5.c
drivers/usb/serial/zte_ev.c
drivers/usb/wusbcore/devconnect.c
drivers/usb/wusbcore/security.c
drivers/usb/wusbcore/wusbhc.h
drivers/vhost/net.c
drivers/vhost/scsi.c
drivers/vhost/test.c
drivers/vhost/vhost.c
drivers/vhost/vhost.h
drivers/video/amifb.c
drivers/video/atmel_lcdfb.c
drivers/video/cirrusfb.c
drivers/video/kyro/fbdev.c
drivers/video/macfb.c
drivers/video/offb.c
drivers/video/omap2/displays-new/panel-sony-acx565akm.c
drivers/video/sh_mobile_meram.c
drivers/video/valkyriefb.c
drivers/video/vt8500lcdfb.c
drivers/virtio/virtio_balloon.c
drivers/virtio/virtio_pci.c
drivers/watchdog/alim1535_wdt.c
drivers/watchdog/alim7101_wdt.c
drivers/watchdog/bcm2835_wdt.c
drivers/watchdog/ep93xx_wdt.c
drivers/watchdog/hpwdt.c
drivers/watchdog/i6300esb.c
drivers/watchdog/ie6xx_wdt.c
drivers/watchdog/jz4740_wdt.c
drivers/watchdog/kempld_wdt.c
drivers/watchdog/max63xx_wdt.c
drivers/watchdog/nv_tco.c
drivers/watchdog/orion_wdt.c
drivers/watchdog/pcwd_pci.c
drivers/watchdog/pnx4008_wdt.c
drivers/watchdog/rt2880_wdt.c
drivers/watchdog/sc1200wdt.c
drivers/watchdog/shwdt.c
drivers/watchdog/softdog.c
drivers/watchdog/sp5100_tco.c
drivers/watchdog/stmp3xxx_rtc_wdt.c
drivers/watchdog/txx9wdt.c
drivers/watchdog/ux500_wdt.c
drivers/watchdog/via_wdt.c
drivers/watchdog/wdt_pci.c
drivers/xen/Kconfig
drivers/xen/grant-table.c
drivers/xen/swiotlb-xen.c
drivers/xen/xen-acpi-cpuhotplug.c
drivers/xen/xen-acpi-memhotplug.c
drivers/xen/xen-acpi-pad.c
drivers/xen/xen-acpi-processor.c
drivers/zorro/Makefile
drivers/zorro/names.c
drivers/zorro/proc.c
drivers/zorro/zorro-driver.c
drivers/zorro/zorro-sysfs.c
drivers/zorro/zorro.c
drivers/zorro/zorro.h
fs/9p/cache.c
fs/9p/vfs_file.c
fs/9p/vfs_inode.c
fs/9p/vfs_inode_dotl.c
fs/9p/xattr.c
fs/aio.c
fs/attr.c
fs/bio-integrity.c
fs/bio.c
fs/btrfs/check-integrity.c
fs/btrfs/check-integrity.h
fs/btrfs/compression.c
fs/btrfs/disk-io.c
fs/btrfs/extent_io.c
fs/btrfs/file-item.c
fs/btrfs/inode.c
fs/btrfs/raid56.c
fs/btrfs/scrub.c
fs/btrfs/volumes.c
fs/buffer.c
fs/ceph/file.c
fs/ceph/inode.c
fs/ceph/super.c
fs/ceph/super.h
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/inode.c
fs/cifs/link.c
fs/direct-io.c
fs/dlm/lowcomms.c
fs/eventpoll.c
fs/ext2/super.c
fs/ext4/ext4_jbd2.c
fs/ext4/extents.c
fs/ext4/inode.c
fs/ext4/mballoc.c
fs/ext4/page-io.c
fs/ext4/super.c
fs/f2fs/checkpoint.c
fs/f2fs/data.c
fs/f2fs/debug.c
fs/f2fs/dir.c
fs/f2fs/f2fs.h
fs/f2fs/file.c
fs/f2fs/gc.c
fs/f2fs/node.c
fs/f2fs/recovery.c
fs/f2fs/segment.c
fs/f2fs/segment.h
fs/f2fs/super.c
fs/f2fs/xattr.c
fs/fscache/page.c
fs/gfs2/aops.c
fs/gfs2/glops.c
fs/gfs2/incore.h
fs/gfs2/log.c
fs/gfs2/lops.c
fs/gfs2/meta_io.c
fs/gfs2/ops_fstype.c
fs/gfs2/quota.c
fs/gfs2/rgrp.c
fs/hfsplus/wrapper.c
fs/jbd2/journal.c
fs/jbd2/recovery.c
fs/jbd2/transaction.c
fs/jffs2/malloc.c
fs/jfs/jfs_logmgr.c
fs/jfs/jfs_metapage.c
fs/logfs/dev_bdev.c
fs/logfs/dev_mtd.c
fs/logfs/super.c
fs/mpage.c
fs/nfs/blocklayout/blocklayout.c
fs/nfs/blocklayout/blocklayout.h
fs/nfs/blocklayout/extents.c
fs/nfs/dns_resolve.c
fs/nfs/inode.c
fs/nfs/internal.h
fs/nfs/nfs4_fs.h
fs/nfs/nfs4client.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4xdr.c
fs/nfsd/nfs3xdr.c
fs/nfsd/nfs4xdr.c
fs/nfsd/nfscache.c
fs/nfsd/nfsxdr.c
fs/nilfs2/segbuf.c
fs/ocfs2/cluster/heartbeat.c
fs/pipe.c
fs/squashfs/file_direct.c
fs/sysfs/file.c
fs/xfs/xfs_aops.c
fs/xfs/xfs_bmap.c
fs/xfs/xfs_buf.c
fs/xfs/xfs_dir2_node.c
fs/xfs/xfs_dir2_sf.c
fs/xfs/xfs_discard.c
fs/xfs/xfs_fsops.c
fs/xfs/xfs_ialloc.c
fs/xfs/xfs_ioctl.c
fs/xfs/xfs_ioctl32.c
fs/xfs/xfs_iops.c
fs/xfs/xfs_log_recover.c
fs/xfs/xfs_qm.c
fs/xfs/xfs_qm.h
fs/xfs/xfs_qm_syscalls.c
fs/xfs/xfs_quota_priv.h [deleted file]
fs/xfs/xfs_trans_dquot.c
fs/xfs/xfs_vnode.h
include/acpi/acpi_bus.h
include/acpi/acpi_drivers.h
include/crypto/scatterwalk.h
include/dt-bindings/clk/at91.h [new file with mode: 0644]
include/dt-bindings/clock/imx5-clock.h [new file with mode: 0644]
include/dt-bindings/clock/imx6sl-clock.h
include/dt-bindings/clock/mpc512x-clock.h [new file with mode: 0644]
include/dt-bindings/clock/vf610-clock.h
include/dt-bindings/gpio/tegra-gpio.h
include/linux/acpi.h
include/linux/acpi_io.h
include/linux/ath9k_platform.h
include/linux/bio.h
include/linux/blk_types.h
include/linux/blkdev.h
include/linux/ccp.h [new file with mode: 0644]
include/linux/ceph/messenger.h
include/linux/cgroup.h
include/linux/clk-provider.h
include/linux/clk/at91_pmc.h [moved from arch/arm/mach-at91/include/mach/at91_pmc.h with 98% similarity]
include/linux/compiler-gcc.h
include/linux/compiler-intel.h
include/linux/compiler.h
include/linux/dm-io.h
include/linux/dmaengine.h
include/linux/efi.h
include/linux/etherdevice.h
include/linux/f2fs_fs.h
include/linux/ftrace_event.h
include/linux/gpio/driver.h
include/linux/hid-sensor-hub.h
include/linux/hid-sensor-ids.h
include/linux/i2c/tsc2007.h
include/linux/ide.h
include/linux/ieee80211.h
include/linux/inetdevice.h
include/linux/ipv6.h
include/linux/irqchip/xtensa-mx.h [new file with mode: 0644]
include/linux/irqchip/xtensa-pic.h [new file with mode: 0644]
include/linux/irqreturn.h
include/linux/iscsi_ibft.h
include/linux/kernel.h
include/linux/kexec.h
include/linux/mfd/abx500/ab8500-gpio.h [deleted file]
include/linux/mfd/abx500/ab8500.h
include/linux/mfd/arizona/registers.h
include/linux/mfd/lp3943.h [new file with mode: 0644]
include/linux/mfd/max14577-private.h [new file with mode: 0644]
include/linux/mfd/max14577.h [new file with mode: 0644]
include/linux/mfd/tps6586x.h
include/linux/micrel_phy.h
include/linux/mm.h
include/linux/module.h
include/linux/mtd/nand.h
include/linux/mtd/partitions.h
include/linux/net.h
include/linux/netdevice.h
include/linux/nfs4.h
include/linux/nfs_fs.h
include/linux/of_mtd.h
include/linux/pci.h
include/linux/pci_hotplug.h
include/linux/perf_event.h
include/linux/phy.h
include/linux/platform_data/clocksource-nomadik-mtu.h [deleted file]
include/linux/platform_data/davinci_asp.h
include/linux/platform_data/dma-imx-sdma.h
include/linux/platform_data/dma-imx.h
include/linux/platform_data/mtd-nand-pxa3xx.h
include/linux/platform_data/pinctrl-nomadik.h [deleted file]
include/linux/platform_data/pn544.h
include/linux/power_supply.h
include/linux/sched.h
include/linux/sctp.h
include/linux/serial_sci.h
include/linux/sfi_acpi.h
include/linux/skbuff.h
include/linux/sunrpc/rpc_pipe_fs.h
include/linux/sunrpc/svc.h
include/linux/tboot.h
include/linux/tracepoint.h
include/linux/uprobes.h
include/linux/usb.h
include/linux/usb/wusb.h
include/linux/vmpressure.h
include/linux/zorro.h
include/media/omap4iss.h [new file with mode: 0644]
include/media/v4l2-fh.h
include/media/v4l2-mem2mem.h
include/media/videobuf2-core.h
include/net/addrconf.h
include/net/bluetooth/bluetooth.h
include/net/bluetooth/hci.h
include/net/bluetooth/hci_core.h
include/net/bluetooth/l2cap.h
include/net/cfg80211.h
include/net/cipso_ipv4.h
include/net/dcbevent.h
include/net/dcbnl.h
include/net/dn_dev.h
include/net/flow.h
include/net/if_inet6.h
include/net/ip.h
include/net/ipv6.h
include/net/irda/discovery.h
include/net/irda/ircomm_core.h
include/net/irda/ircomm_event.h
include/net/irda/ircomm_lmp.h
include/net/irda/ircomm_param.h
include/net/irda/ircomm_ttp.h
include/net/irda/ircomm_tty.h
include/net/irda/ircomm_tty_attach.h
include/net/irda/irda_device.h
include/net/irda/irlap_event.h
include/net/irda/irlap_frame.h
include/net/irda/parameters.h
include/net/irda/qos.h
include/net/mac80211.h
include/net/mip6.h
include/net/neighbour.h
include/net/netlabel.h
include/net/netns/xfrm.h
include/net/nfc/hci.h
include/net/nfc/llc.h
include/net/nfc/nci.h
include/net/nfc/nci_core.h
include/net/nfc/nfc.h
include/net/ping.h
include/net/pkt_sched.h
include/net/regulatory.h
include/net/route.h
include/net/sctp/auth.h
include/net/sctp/checksum.h
include/net/sctp/command.h
include/net/sctp/constants.h
include/net/sctp/sctp.h
include/net/sctp/sm.h
include/net/sctp/structs.h
include/net/sctp/tsnmap.h
include/net/sctp/ulpevent.h
include/net/sctp/ulpqueue.h
include/net/sock.h
include/net/tc_act/tc_skbedit.h
include/net/tcp.h
include/net/xfrm.h
include/scsi/scsi_host.h
include/sound/cs42l52.h
include/sound/dmaengine_pcm.h
include/sound/hda_verbs.h [new file with mode: 0644]
include/sound/memalloc.h
include/sound/rcar_snd.h
include/sound/soc-dai.h
include/sound/soc-dapm.h
include/sound/soc.h
include/trace/events/bcache.h
include/trace/events/block.h
include/trace/events/f2fs.h
include/trace/ftrace.h
include/uapi/drm/i915_drm.h
include/uapi/linux/Kbuild
include/uapi/linux/eventpoll.h
include/uapi/linux/genetlink.h
include/uapi/linux/if_addr.h
include/uapi/linux/if_arp.h
include/uapi/linux/if_link.h
include/uapi/linux/if_packet.h
include/uapi/linux/input.h
include/uapi/linux/kexec.h
include/uapi/linux/media.h
include/uapi/linux/mic_common.h
include/uapi/linux/net_tstamp.h
include/uapi/linux/netfilter/xt_osf.h
include/uapi/linux/netlink_diag.h
include/uapi/linux/nl80211.h
include/uapi/linux/packet_diag.h
include/uapi/linux/sctp.h
include/uapi/linux/snmp.h
include/uapi/linux/sockios.h
include/uapi/linux/unix_diag.h
include/uapi/linux/zorro.h [new file with mode: 0644]
include/uapi/linux/zorro_ids.h [moved from include/linux/zorro_ids.h with 100% similarity]
include/uapi/sound/compress_offload.h
init/Kconfig
kernel/cgroup.c
kernel/cgroup_freezer.c
kernel/cpuset.c
kernel/events/core.c
kernel/events/uprobes.c
kernel/fork.c
kernel/irq/pm.c
kernel/kexec.c
kernel/locking/lockdep.c
kernel/padata.c
kernel/panic.c
kernel/params.c
kernel/power/block_io.c
kernel/power/hibernate.c
kernel/rcu/tree_plugin.h
kernel/sched/core.c
kernel/sched/cpuacct.c
kernel/sched/fair.c
kernel/sched/sched.h
kernel/softirq.c
kernel/time/tick-common.c
kernel/time/tick-sched.c
kernel/time/timekeeping.c
kernel/timer.c
kernel/trace/blktrace.c
kernel/trace/trace_event_perf.c
kernel/trace/trace_events.c
kernel/trace/trace_syscalls.c
kernel/workqueue.c
lib/Kconfig.debug
mm/bounce.c
mm/hugetlb_cgroup.c
mm/memcontrol.c
mm/mempolicy.c
mm/page_io.c
mm/vmpressure.c
net/802/hippi.c
net/9p/client.c
net/9p/trans_fd.c
net/9p/trans_virtio.c
net/batman-adv/main.h
net/bluetooth/6lowpan.c [new file with mode: 0644]
net/bluetooth/6lowpan.h [new file with mode: 0644]
net/bluetooth/Makefile
net/bluetooth/af_bluetooth.c
net/bluetooth/bnep/bnep.h
net/bluetooth/hci_core.c
net/bluetooth/hci_event.c
net/bluetooth/l2cap_core.c
net/bluetooth/l2cap_sock.c
net/bluetooth/mgmt.c
net/bluetooth/smp.c
net/bluetooth/smp.h
net/bridge/br_netlink.c
net/bridge/br_private.h
net/bridge/br_stp_bpdu.c
net/bridge/netfilter/ebt_vlan.c
net/ceph/messenger.c
net/compat.c
net/core/dev.c
net/core/dev_ioctl.c
net/core/drop_monitor.c
net/core/neighbour.c
net/core/net-sysfs.c
net/core/netprio_cgroup.c
net/core/pktgen.c
net/core/skbuff.c
net/core/sock.c
net/dcb/dcbevent.c
net/dcb/dcbnl.c
net/dccp/ipv4.c
net/dccp/ipv6.c
net/decnet/dn_dev.c
net/decnet/dn_neigh.c
net/decnet/dn_route.c
net/dns_resolver/dns_key.c
net/dns_resolver/dns_query.c
net/dns_resolver/internal.h
net/hsr/hsr_framereg.c
net/hsr/hsr_netlink.c
net/ieee802154/6lowpan.c
net/ieee802154/6lowpan.h
net/ieee802154/6lowpan_iphc.c [new file with mode: 0644]
net/ieee802154/Makefile
net/ipv4/af_inet.c
net/ipv4/arp.c
net/ipv4/cipso_ipv4.c
net/ipv4/datagram.c
net/ipv4/devinet.c
net/ipv4/fib_rules.c
net/ipv4/ip_sockglue.c
net/ipv4/ipmr.c
net/ipv4/netfilter/nf_nat_snmp_basic.c
net/ipv4/ping.c
net/ipv4/proc.c
net/ipv4/protocol.c
net/ipv4/raw.c
net/ipv4/sysctl_net_ipv4.c
net/ipv4/tcp.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_memcontrol.c
net/ipv4/tcp_offload.c
net/ipv4/tcp_output.c
net/ipv4/udp.c
net/ipv6/addrconf.c
net/ipv6/af_inet6.c
net/ipv6/ah6.c
net/ipv6/datagram.c
net/ipv6/esp6.c
net/ipv6/fib6_rules.c
net/ipv6/inet6_connection_sock.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_output.c
net/ipv6/ip6_tunnel.c
net/ipv6/ipcomp6.c
net/ipv6/ipv6_sockglue.c
net/ipv6/mip6.c
net/ipv6/ndisc.c
net/ipv6/ping.c
net/ipv6/protocol.c
net/ipv6/raw.c
net/ipv6/route.c
net/ipv6/sit.c
net/ipv6/syncookies.c
net/ipv6/tcp_ipv6.c
net/ipv6/tcpv6_offload.c
net/ipv6/tunnel6.c
net/ipv6/udp.c
net/ipv6/xfrm6_mode_ro.c
net/ipv6/xfrm6_tunnel.c
net/irda/af_irda.c
net/irda/discovery.c
net/irda/ircomm/ircomm_core.c
net/irda/ircomm/ircomm_event.c
net/irda/ircomm/ircomm_lmp.c
net/irda/ircomm/ircomm_param.c
net/irda/ircomm/ircomm_ttp.c
net/irda/ircomm/ircomm_tty.c
net/irda/ircomm/ircomm_tty_attach.c
net/irda/ircomm/ircomm_tty_ioctl.c
net/irda/irda_device.c
net/irda/irlap.c
net/irda/parameters.c
net/irda/qos.c
net/key/af_key.c
net/l2tp/l2tp_ip6.c
net/mac80211/cfg.c
net/mac80211/chan.c
net/mac80211/debugfs.c
net/mac80211/debugfs_sta.c
net/mac80211/ibss.c
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/key.c
net/mac80211/key.h
net/mac80211/main.c
net/mac80211/mesh.c
net/mac80211/mesh.h
net/mac80211/mesh_hwmp.c
net/mac80211/mesh_pathtbl.c
net/mac80211/mesh_plink.c
net/mac80211/mesh_ps.c
net/mac80211/mesh_sync.c
net/mac80211/mlme.c
net/mac80211/rate.h
net/mac80211/rc80211_minstrel.c
net/mac80211/rc80211_minstrel_ht.c
net/mac80211/rc80211_minstrel_ht_debugfs.c
net/mac80211/rx.c
net/mac80211/scan.c
net/mac80211/spectmgmt.c
net/mac80211/sta_info.c
net/mac80211/sta_info.h
net/mac80211/status.c
net/mac80211/trace.h
net/mac80211/tx.c
net/mac80211/util.c
net/mac80211/vht.c
net/mac80211/wpa.c
net/mac80211/wpa.h
net/netfilter/ipset/Kconfig
net/netfilter/ipset/ip_set_hash_netnet.c
net/netfilter/ipvs/ip_vs_nfct.c
net/netfilter/nf_tables_api.c
net/netfilter/xt_connmark.c
net/netfilter/xt_hashlimit.c
net/netfilter/xt_osf.c
net/netlabel/netlabel_addrlist.c
net/netlabel/netlabel_addrlist.h
net/netlabel/netlabel_cipso_v4.c
net/netlabel/netlabel_cipso_v4.h
net/netlabel/netlabel_domainhash.c
net/netlabel/netlabel_domainhash.h
net/netlabel/netlabel_kapi.c
net/netlabel/netlabel_mgmt.c
net/netlabel/netlabel_mgmt.h
net/netlabel/netlabel_unlabeled.c
net/netlabel/netlabel_unlabeled.h
net/netlabel/netlabel_user.c
net/netlabel/netlabel_user.h
net/netlink/genetlink.c
net/nfc/af_nfc.c
net/nfc/core.c
net/nfc/hci/command.c
net/nfc/hci/core.c
net/nfc/hci/hci.h
net/nfc/hci/hcp.c
net/nfc/hci/llc.c
net/nfc/hci/llc.h
net/nfc/hci/llc_nop.c
net/nfc/hci/llc_shdlc.c
net/nfc/llcp.h
net/nfc/llcp_commands.c
net/nfc/llcp_core.c
net/nfc/llcp_sock.c
net/nfc/nci/core.c
net/nfc/nci/data.c
net/nfc/nci/lib.c
net/nfc/nci/ntf.c
net/nfc/nci/rsp.c
net/nfc/netlink.c
net/nfc/nfc.h
net/nfc/rawsock.c
net/packet/af_packet.c
net/packet/internal.h
net/rds/ib_send.c
net/rfkill/core.c
net/sched/act_api.c
net/sched/act_csum.c
net/sched/act_gact.c
net/sched/act_ipt.c
net/sched/act_mirred.c
net/sched/act_nat.c
net/sched/act_pedit.c
net/sched/act_police.c
net/sched/act_simple.c
net/sched/act_skbedit.c
net/sched/cls_bpf.c
net/sched/cls_u32.c
net/sched/em_meta.c
net/sched/sch_api.c
net/sched/sch_cbq.c
net/sched/sch_dsmark.c
net/sched/sch_generic.c
net/sched/sch_htb.c
net/sched/sch_mq.c
net/sched/sch_mqprio.c
net/sched/sch_multiq.c
net/sched/sch_netem.c
net/sched/sch_sfq.c
net/sched/sch_tbf.c
net/sctp/associola.c
net/sctp/auth.c
net/sctp/bind_addr.c
net/sctp/chunk.c
net/sctp/command.c
net/sctp/debug.c
net/sctp/endpointola.c
net/sctp/input.c
net/sctp/inqueue.c
net/sctp/ipv6.c
net/sctp/objcnt.c
net/sctp/output.c
net/sctp/outqueue.c
net/sctp/primitive.c
net/sctp/proc.c
net/sctp/protocol.c
net/sctp/sm_make_chunk.c
net/sctp/sm_sideeffect.c
net/sctp/sm_statefuns.c
net/sctp/sm_statetable.c
net/sctp/socket.c
net/sctp/ssnmap.c
net/sctp/sysctl.c
net/sctp/transport.c
net/sctp/tsnmap.c
net/sctp/ulpevent.c
net/sctp/ulpqueue.c
net/socket.c
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/netns.h
net/sunrpc/rpc_pipe.c
net/sunrpc/sunrpc_syms.c
net/sunrpc/xprtsock.c
net/tipc/bcast.c
net/tipc/bearer.c
net/tipc/bearer.h
net/tipc/core.c
net/tipc/discover.c
net/tipc/eth_media.c
net/tipc/handler.c
net/tipc/ib_media.c
net/tipc/link.c
net/tipc/link.h
net/tipc/node.c
net/unix/af_unix.c
net/wireless/chan.c
net/wireless/core.c
net/wireless/core.h
net/wireless/genregdb.awk
net/wireless/ibss.c
net/wireless/mesh.c
net/wireless/mlme.c
net/wireless/nl80211.c
net/wireless/nl80211.h
net/wireless/rdev-ops.h
net/wireless/reg.c
net/wireless/reg.h
net/wireless/trace.h
net/x25/af_x25.c
net/x25/x25_dev.c
net/x25/x25_facilities.c
net/x25/x25_forward.c
net/x25/x25_in.c
net/x25/x25_link.c
net/x25/x25_subr.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_state.c
net/xfrm/xfrm_user.c
scripts/package/builddeb
scripts/recordmcount.pl
scripts/sortextable.c
security/device_cgroup.c
security/integrity/ima/ima.h
security/integrity/ima/ima_api.c
security/integrity/ima/ima_init.c
security/integrity/ima/ima_template.c
security/selinux/hooks.c
security/selinux/include/security.h
security/selinux/include/xfrm.h
security/selinux/netlabel.c
security/selinux/ss/constraint.h
security/selinux/ss/policydb.c
security/selinux/ss/policydb.h
security/selinux/ss/services.c
security/selinux/xfrm.c
sound/arm/aaci.c
sound/atmel/abdac.c
sound/firewire/dice.c
sound/pci/Kconfig
sound/pci/cs46xx/cs46xx.h
sound/pci/cs46xx/cs46xx_image.h [deleted file]
sound/pci/cs46xx/cs46xx_lib.c
sound/pci/cs46xx/imgs/cwc4630.h [deleted file]
sound/pci/cs46xx/imgs/cwcasync.h [deleted file]
sound/pci/cs46xx/imgs/cwcbinhack.h [deleted file]
sound/pci/cs46xx/imgs/cwcdma.asp [deleted file]
sound/pci/cs46xx/imgs/cwcdma.h [deleted file]
sound/pci/cs46xx/imgs/cwcsnoop.h [deleted file]
sound/pci/hda/Makefile
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_generic.c
sound/pci/hda/hda_generic.h
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_local.h
sound/pci/hda/patch_analog.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_via.c
sound/soc/Kconfig
sound/soc/Makefile
sound/soc/adi/Kconfig [new file with mode: 0644]
sound/soc/adi/Makefile [new file with mode: 0644]
sound/soc/adi/axi-i2s.c [new file with mode: 0644]
sound/soc/adi/axi-spdif.c [new file with mode: 0644]
sound/soc/atmel/atmel_ssc_dai.c
sound/soc/atmel/sam9x5_wm8731.c
sound/soc/bcm/Kconfig [new file with mode: 0644]
sound/soc/bcm/Makefile [new file with mode: 0644]
sound/soc/bcm/bcm2835-i2s.c [new file with mode: 0644]
sound/soc/cirrus/ep93xx-pcm.c
sound/soc/codecs/Kconfig
sound/soc/codecs/ad193x.c
sound/soc/codecs/adav80x.c
sound/soc/codecs/ak4641.c
sound/soc/codecs/ak4642.c
sound/soc/codecs/arizona.c
sound/soc/codecs/arizona.h
sound/soc/codecs/cs4271.c
sound/soc/codecs/cs42l52.c
sound/soc/codecs/da7210.c
sound/soc/codecs/hdmi.c
sound/soc/codecs/ssm2602.c
sound/soc/codecs/tlv320aic3x.c
sound/soc/codecs/uda1380.c
sound/soc/codecs/wm5110.c
sound/soc/codecs/wm8510.c
sound/soc/codecs/wm8523.c
sound/soc/codecs/wm8580.c
sound/soc/codecs/wm8711.c
sound/soc/codecs/wm8728.c
sound/soc/codecs/wm8731.c
sound/soc/codecs/wm8741.c
sound/soc/codecs/wm8750.c
sound/soc/codecs/wm8753.c
sound/soc/codecs/wm8776.c
sound/soc/codecs/wm8804.c
sound/soc/codecs/wm8900.c
sound/soc/codecs/wm8940.c
sound/soc/codecs/wm8962.c
sound/soc/codecs/wm8974.c
sound/soc/codecs/wm8985.c
sound/soc/codecs/wm8988.c
sound/soc/codecs/wm8990.c
sound/soc/codecs/wm8990.h
sound/soc/codecs/wm8991.c
sound/soc/codecs/wm8991.h
sound/soc/codecs/wm8994.c
sound/soc/codecs/wm8995.c
sound/soc/codecs/wm9081.c
sound/soc/codecs/wm_adsp.c
sound/soc/davinci/Kconfig
sound/soc/davinci/Makefile
sound/soc/davinci/davinci-evm.c
sound/soc/davinci/davinci-mcasp.c
sound/soc/davinci/davinci-mcasp.h
sound/soc/fsl/fsl_spdif.c
sound/soc/fsl/fsl_ssi.c
sound/soc/fsl/imx-pcm-dma.c
sound/soc/fsl/imx-pcm.h
sound/soc/fsl/imx-spdif.c
sound/soc/fsl/imx-ssi.c
sound/soc/fsl/imx-ssi.h
sound/soc/fsl/imx-wm8962.c
sound/soc/fsl/pcm030-audio-fabric.c
sound/soc/generic/simple-card.c
sound/soc/intel/Kconfig [moved from sound/soc/mid-x86/Kconfig with 100% similarity]
sound/soc/intel/Makefile [moved from sound/soc/mid-x86/Makefile with 100% similarity]
sound/soc/intel/mfld_machine.c [moved from sound/soc/mid-x86/mfld_machine.c with 100% similarity]
sound/soc/intel/sst_dsp.h [moved from sound/soc/mid-x86/sst_dsp.h with 100% similarity]
sound/soc/intel/sst_platform.c [moved from sound/soc/mid-x86/sst_platform.c with 100% similarity]
sound/soc/intel/sst_platform.h [moved from sound/soc/mid-x86/sst_platform.h with 100% similarity]
sound/soc/jz4740/Kconfig
sound/soc/jz4740/jz4740-i2s.c
sound/soc/jz4740/jz4740-pcm.c [deleted file]
sound/soc/jz4740/jz4740-pcm.h [deleted file]
sound/soc/jz4740/qi_lb60.c
sound/soc/kirkwood/kirkwood-i2s.c
sound/soc/mxs/mxs-pcm.c
sound/soc/mxs/mxs-pcm.h
sound/soc/mxs/mxs-saif.c
sound/soc/omap/mcbsp.c
sound/soc/omap/n810.c
sound/soc/omap/omap-dmic.c
sound/soc/omap/omap-mcpdm.c
sound/soc/sh/Kconfig
sound/soc/sh/fsi.c
sound/soc/sh/rcar/gen.c
sound/soc/sh/rcar/rsnd.h
sound/soc/sh/rcar/ssi.c
sound/soc/soc-core.c
sound/soc/soc-devres.c
sound/soc/soc-generic-dmaengine-pcm.c
sound/soc/soc-io.c
sound/soc/soc-pcm.c
sound/soc/spear/spear_pcm.c
sound/soc/tegra/Kconfig
sound/soc/tegra/Makefile
sound/soc/tegra/tegra20_i2s.c
sound/soc/tegra/tegra20_spdif.c
sound/soc/tegra/tegra30_i2s.c
sound/soc/tegra/tegra_max98090.c [new file with mode: 0644]
sound/spi/at73c213.c
sound/usb/mixer_quirks.c
tools/lib/lockdep/Makefile [new file with mode: 0644]
tools/lib/lockdep/common.c [new file with mode: 0644]
tools/lib/lockdep/include/liblockdep/common.h [new file with mode: 0644]
tools/lib/lockdep/include/liblockdep/mutex.h [new file with mode: 0644]
tools/lib/lockdep/include/liblockdep/rwlock.h [new file with mode: 0644]
tools/lib/lockdep/lockdep [new file with mode: 0755]
tools/lib/lockdep/lockdep.c [new file with mode: 0644]
tools/lib/lockdep/lockdep_internals.h [new file with mode: 0644]
tools/lib/lockdep/lockdep_states.h [new file with mode: 0644]
tools/lib/lockdep/preload.c [new file with mode: 0644]
tools/lib/lockdep/rbtree.c [new file with mode: 0644]
tools/lib/lockdep/run_tests.sh [new file with mode: 0644]
tools/lib/lockdep/tests/AA.c [new file with mode: 0644]
tools/lib/lockdep/tests/ABBA.c [new file with mode: 0644]
tools/lib/lockdep/tests/ABBCCA.c [new file with mode: 0644]
tools/lib/lockdep/tests/ABBCCDDA.c [new file with mode: 0644]
tools/lib/lockdep/tests/ABCABC.c [new file with mode: 0644]
tools/lib/lockdep/tests/ABCDBCDA.c [new file with mode: 0644]
tools/lib/lockdep/tests/ABCDBDDA.c [new file with mode: 0644]
tools/lib/lockdep/tests/WW.c [new file with mode: 0644]
tools/lib/lockdep/tests/common.h [new file with mode: 0644]
tools/lib/lockdep/tests/unlock_balance.c [new file with mode: 0644]
tools/lib/lockdep/uinclude/asm/hweight.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/asm/sections.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/bitops.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/compiler.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/debug_locks.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/delay.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/export.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/ftrace.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/gfp.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/hardirq.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/hash.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/interrupt.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/irqflags.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/kallsyms.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/kern_levels.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/kernel.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/kmemcheck.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/linkage.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/list.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/lockdep.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/module.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/mutex.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/poison.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/prefetch.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/proc_fs.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/rbtree.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/rbtree_augmented.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/rcu.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/seq_file.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/spinlock.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/stacktrace.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/stringify.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/types.h [new file with mode: 0644]
tools/lib/lockdep/uinclude/trace/events/lock.h [new file with mode: 0644]
tools/lib/traceevent/event-parse.c
tools/perf/Documentation/perf-record.txt
tools/perf/Documentation/perf-script.txt
tools/perf/Documentation/perf-timechart.txt
tools/perf/Documentation/perf-top.txt
tools/perf/Makefile
tools/perf/Makefile.perf
tools/perf/builtin-record.c
tools/perf/builtin-script.c
tools/perf/builtin-stat.c
tools/perf/builtin-timechart.c
tools/perf/builtin-top.c
tools/perf/builtin-trace.c
tools/perf/perf-completion.sh [moved from tools/perf/bash_completion with 65% similarity]
tools/perf/perf.h
tools/perf/tests/attr/test-record-no-inherit
tools/perf/util/event.c
tools/perf/util/evlist.c
tools/perf/util/evsel.c
tools/perf/util/evsel.h
tools/perf/util/header.c
tools/perf/util/parse-events.c
tools/perf/util/parse-options.c
tools/perf/util/parse-options.h
tools/perf/util/pmu.c
tools/perf/util/pmu.h
tools/perf/util/session.c
tools/perf/util/svghelper.c
tools/perf/util/svghelper.h
tools/perf/util/symbol.c
tools/perf/util/symbol.h
tools/perf/util/target.c
tools/perf/util/target.h
tools/perf/util/thread.c
tools/perf/util/thread.h
tools/power/cpupower/debug/kernel/cpufreq-test_tsc.c
tools/power/x86/turbostat/turbostat.c
tools/usb/Makefile

diff --git a/CREDITS b/CREDITS
index 4fc997d58ab2640a4b94fdcb1f363935f8a13395..4c7738f493570eb9d0c70e6db67c527bcbe6e691 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -655,6 +655,11 @@ S: Stanford University
 S: Stanford, California 94305
 S: USA
 
+N: Carlos Chinea
+E: carlos.chinea@nokia.com
+E: cch.devel@gmail.com
+D: Author of HSI Subsystem
+
 N: Randolph Chung
 E: tausq@debian.org
 D: Linux/PA-RISC hacker
index 720f245ceb1f34dcf2f01c9607291db14a118d40..7ebd5465d9277ce250d4cfd97c17295da75afb6a 100644 (file)
@@ -10,5 +10,6 @@
 *.out
 *.png
 *.gif
+*.svg
 media-indices.tmpl
 media-entities.tmpl
index bc3d9f8c0a9018fca305ce3d27920fb39be7c04a..0f9c6ff41aac5206eb470ef07d68553d067022f0 100644 (file)
@@ -54,6 +54,7 @@ htmldocs: $(HTML)
 
 MAN := $(patsubst %.xml, %.9, $(BOOKS))
 mandocs: $(MAN)
+       $(if $(wildcard $(obj)/man/*.9),gzip -f $(obj)/man/*.9)
 
 installmandocs: mandocs
        mkdir -p /usr/local/man/man9/
@@ -145,7 +146,7 @@ build_main_index = rm -rf $(main_idx); \
                   cat $(HTML) >> $(main_idx)
 
 quiet_cmd_db2html = HTML    $@
-      cmd_db2html = xmlto xhtml $(XMLTOFLAGS) -o $(patsubst %.html,%,$@) $< && \
+      cmd_db2html = xmlto html $(XMLTOFLAGS) -o $(patsubst %.html,%,$@) $< && \
                echo '<a HREF="$(patsubst %.html,%,$(notdir $@))/index.html"> \
         $(patsubst %.html,%,$(notdir $@))</a><p>' > $@
 
@@ -159,7 +160,7 @@ quiet_cmd_db2html = HTML    $@
             cp $(PNG-$(basename $(notdir $@))) $(patsubst %.html,%,$@); fi
 
 quiet_cmd_db2man = MAN     $@
-      cmd_db2man = if grep -q refentry $<; then xmlto man $(XMLTOFLAGS) -o $(obj)/man $< ; gzip -f $(obj)/man/*.9; fi
+      cmd_db2man = if grep -q refentry $<; then xmlto man $(XMLTOFLAGS) -o $(obj)/man $< ; fi
 %.9 : %.xml
        @(which xmlto > /dev/null 2>&1) || \
         (echo "*** You need to install xmlto ***"; \
index f75ab4c1b281119672df234624f1ae7aa80919c2..ecfd0ea406619b0a2c76071b2024c7219b9c7a6a 100644 (file)
@@ -109,6 +109,7 @@ X!Ilib/string.c
      <sect1><title>The Slab Cache</title>
 !Iinclude/linux/slab.h
 !Emm/slab.c
+!Emm/util.c
      </sect1>
      <sect1><title>User Space Memory Access</title>
 !Iarch/x86/include/asm/uaccess_32.h
index 355df43badc5d7dc34123f829bed0ef028c4539a..cf8548556c7dcb0d28cef102ae5cba261b122899 100644 (file)
            <entry>Output pad, relative to the entity. Output pads source data
            and are origins of links.</entry>
          </row>
+         <row>
+           <entry><constant>MEDIA_PAD_FL_MUST_CONNECT</constant></entry>
+           <entry>If this flag is set and the pad is linked to any other
+           pad, then at least one of those links must be enabled for the
+           entity to be able to stream. There could be temporary reasons
+           (e.g. device configuration dependent) for the pad to need
+           enabled links even when this flag isn't set; the absence of the
+           flag doesn't imply there is none.</entry>
+         </row>
        </tbody>
       </tgroup>
     </table>
index e287c8fc803b437ce34550ba88777183f66ca0cc..4165e7bfa4ff7560c0283213e53a54b1575ab2e8 100644 (file)
@@ -73,7 +73,8 @@ range from zero to the maximal number of valid planes for the currently active
 format. For the single-planar API, applications must set <structfield> plane
 </structfield> to zero.  Additional flags may be posted in the <structfield>
 flags </structfield> field.  Refer to a manual for open() for details.
-Currently only O_CLOEXEC is supported.  All other fields must be set to zero.
+Currently only O_CLOEXEC, O_RDONLY, O_WRONLY, and O_RDWR are supported.  All
+other fields must be set to zero.
 In the case of multi-planar API, every plane is exported separately using
 multiple <constant> VIDIOC_EXPBUF </constant> calls. </para>
 
@@ -170,8 +171,9 @@ multi-planar API. Otherwise this value must be set to zero. </entry>
            <entry>__u32</entry>
            <entry><structfield>flags</structfield></entry>
            <entry>Flags for the newly created file, currently only <constant>
-O_CLOEXEC </constant> is supported, refer to the manual of open() for more
-details.</entry>
+O_CLOEXEC </constant>, <constant>O_RDONLY</constant>, <constant>O_WRONLY
+</constant>, and <constant>O_RDWR</constant> are supported, refer to the manual
+of open() for more details.</entry>
          </row>
          <row>
            <entry>__s32</entry>
index 9bc95942ec22b9f4c721c7e9dda0189ba75689c7..03df71aeb38c000dd607b657f62ebb477753bf76 100644 (file)
@@ -141,7 +141,7 @@ will use a legacy domain only if an IRQ range is supplied by the
 system and will otherwise use a linear domain mapping. The semantics
 of this call are such that if an IRQ range is specified then
 descriptors will be allocated on-the-fly for it, and if no range is
-specified it will fall through to irq_domain_add_linear() which meand
+specified it will fall through to irq_domain_add_linear() which means
 *no* irq descriptors will be allocated.
 
 A typical use case for simple domains is where an irqchip provider
index 260f6a3661faff625aabda6bc3dc6ba9eda84012..1860cb3865c6b26474a2d07d3944a9858a9f07c6 100644 (file)
@@ -235,10 +235,6 @@ Wysocki <rafael.j.wysocki@intel.com>.
       named object's type in the second column).  In that case the object's
       directory in sysfs will contain the 'path' attribute whose value is
       the full path to the node from the namespace root.
-      struct acpi_device objects are created for the ACPI namespace nodes
-      whose _STA control methods return PRESENT or FUNCTIONING.  The power
-      resource nodes or nodes without _STA are assumed to be both PRESENT
-      and FUNCTIONING.
    F:
       The struct acpi_device object is created for a fixed hardware
       feature (as indicated by the fixed feature flag's name in the second
@@ -340,7 +336,7 @@ Wysocki <rafael.j.wysocki@intel.com>.
      | +-------------+-------+----------------+
      |   |
      |   | +- - - - - - - +- - - - - - +- - - - - - - -+
-     |   +-| PNP0C0D:00 | \_SB_.LID0 | acpi:PNP0C0D: |
+     |   +-| PNP0C0D:00 | \_SB_.LID0 | acpi:PNP0C0D: |
      |   | +- - - - - - - +- - - - - - +- - - - - - - -+
      |   |
      |   | +------------+------------+-----------------------+
@@ -390,6 +386,3 @@ Wysocki <rafael.j.wysocki@intel.com>.
             attribute (as described earlier in this document).
    NOTE: N/A indicates the device object does not have the 'path' or the
          'modalias' attribute.
-   NOTE: The PNP0C0D device listed above is highlighted (marked by "*")
-         to indicate it will be created only when its _STA methods return
-         PRESENT or FUNCTIONING.
index 8df5e8e6dceba06846042d0c6155fd4e986addd8..2101e718670d0248110caa4320e51e83c715fad2 100644 (file)
@@ -447,14 +447,13 @@ struct bio_vec {
  * main unit of I/O for the block layer and lower layers (ie drivers)
  */
 struct bio {
-       sector_t            bi_sector;
        struct bio          *bi_next;    /* request queue link */
        struct block_device *bi_bdev;   /* target device */
        unsigned long       bi_flags;    /* status, command, etc */
        unsigned long       bi_rw;       /* low bits: r/w, high: priority */
 
        unsigned int    bi_vcnt;     /* how may bio_vec's */
-       unsigned int    bi_idx;         /* current index into bio_vec array */
+       struct bvec_iter        bi_iter;        /* current index into bio_vec array */
 
        unsigned int    bi_size;     /* total size in bytes */
        unsigned short  bi_phys_segments; /* segments after physaddr coalesce*/
@@ -480,7 +479,7 @@ With this multipage bio design:
 - Code that traverses the req list can find all the segments of a bio
   by using rq_for_each_segment.  This handles the fact that a request
   has multiple bios, each of which can have multiple segments.
-- Drivers which can't process a large bio in one shot can use the bi_idx
+- Drivers which can't process a large bio in one shot can use the bi_iter
   field to keep track of the next bio_vec entry to process.
   (e.g a 1MB bio_vec needs to be handled in max 128kB chunks for IDE)
   [TBD: Should preferably also have a bi_voffset and bi_vlen to avoid modifying
@@ -589,7 +588,7 @@ driver should not modify these values. The block layer sets up the
 nr_sectors and current_nr_sectors fields (based on the corresponding
 hard_xxx values and the number of bytes transferred) and updates it on
 every transfer that invokes end_that_request_first. It does the same for the
-buffer, bio, bio->bi_idx fields too.
+buffer, bio, bio->bi_iter fields too.
 
 The buffer field is just a virtual address mapping of the current segment
 of the i/o buffer in cases where the buffer resides in low-memory. For high
diff --git a/Documentation/block/biovecs.txt b/Documentation/block/biovecs.txt
new file mode 100644 (file)
index 0000000..74a32ad
--- /dev/null
@@ -0,0 +1,111 @@
+
+Immutable biovecs and biovec iterators:
+=======================================
+
+Kent Overstreet <kmo@daterainc.com>
+
+As of 3.13, biovecs should never be modified after a bio has been submitted.
+Instead, we have a new struct bvec_iter which represents a range of a biovec -
+the iterator will be modified as the bio is completed, not the biovec.
+
+More specifically, old code that needed to partially complete a bio would
+update bi_sector and bi_size, and advance bi_idx to the next biovec. If it
+ended up partway through a biovec, it would increment bv_offset and decrement
+bv_len by the number of bytes completed in that biovec.
+
+In the new scheme of things, everything that must be mutated in order to
+partially complete a bio is segregated into struct bvec_iter: bi_sector,
+bi_size and bi_idx have been moved there; and instead of modifying bv_offset
+and bv_len, struct bvec_iter has bi_bvec_done, which represents the number of
+bytes completed in the current bvec.
+
+There are a bunch of new helper macros for hiding the gory details - in
+particular, presenting the illusion of partially completed biovecs so that
+normal code doesn't have to deal with bi_bvec_done.
+
+ * Driver code should no longer refer to biovecs directly; we now have
+   bio_iovec() and bio_iovec_iter() macros that return literal struct biovecs,
+   constructed from the raw biovecs but taking into account bi_bvec_done and
+   bi_size.
+
+   bio_for_each_segment() has been updated to take a bvec_iter argument
+   instead of an integer (that corresponded to bi_idx); for a lot of code the
+   conversion just required changing the types of the arguments to
+   bio_for_each_segment().
+
+ * Advancing a bvec_iter is done with bio_advance_iter(); bio_advance() is a
+   wrapper around bio_advance_iter() that operates on bio->bi_iter, and also
+   advances the bio integrity's iter if present.
+
+   There is a lower level advance function - bvec_iter_advance() - which takes
+   a pointer to a biovec, not a bio; this is used by the bio integrity code.
+
+What's all this get us?
+=======================
+
+Having a real iterator, and making biovecs immutable, has a number of
+advantages:
+
+ * Before, iterating over bios was very awkward when you weren't processing
+   exactly one bvec at a time - for example, bio_copy_data() in fs/bio.c,
+   which copies the contents of one bio into another. Because the biovecs
+   wouldn't necessarily be the same size, the old code was tricky convoluted -
+   it had to walk two different bios at the same time, keeping both bi_idx and
+   and offset into the current biovec for each.
+
+   The new code is much more straightforward - have a look. This sort of
+   pattern comes up in a lot of places; a lot of drivers were essentially open
+   coding bvec iterators before, and having common implementation considerably
+   simplifies a lot of code.
+
+ * Before, any code that might need to use the biovec after the bio had been
+   completed (perhaps to copy the data somewhere else, or perhaps to resubmit
+   it somewhere else if there was an error) had to save the entire bvec array
+   - again, this was being done in a fair number of places.
+
+ * Biovecs can be shared between multiple bios - a bvec iter can represent an
+   arbitrary range of an existing biovec, both starting and ending midway
+   through biovecs. This is what enables efficient splitting of arbitrary
+   bios. Note that this means we _only_ use bi_size to determine when we've
+   reached the end of a bio, not bi_vcnt - and the bio_iovec() macro takes
+   bi_size into account when constructing biovecs.
+
+ * Splitting bios is now much simpler. The old bio_split() didn't even work on
+   bios with more than a single bvec! Now, we can efficiently split arbitrary
+   size bios - because the new bio can share the old bio's biovec.
+
+   Care must be taken to ensure the biovec isn't freed while the split bio is
+   still using it, in case the original bio completes first, though. Using
+   bio_chain() when splitting bios helps with this.
+
+ * Submitting partially completed bios is now perfectly fine - this comes up
+   occasionally in stacking block drivers and various code (e.g. md and
+   bcache) had some ugly workarounds for this.
+
+   It used to be the case that submitting a partially completed bio would work
+   fine to _most_ devices, but since accessing the raw bvec array was the
+   norm, not all drivers would respect bi_idx and those would break. Now,
+   since all drivers _must_ go through the bvec iterator - and have been
+   audited to make sure they are - submitting partially completed bios is
+   perfectly fine.
+
+Other implications:
+===================
+
+ * Almost all usage of bi_idx is now incorrect and has been removed; instead,
+   where previously you would have used bi_idx you'd now use a bvec_iter,
+   probably passing it to one of the helper macros.
+
+   I.e. instead of using bio_iovec_idx() (or bio->bi_iovec[bio->bi_idx]), you
+   now use bio_iter_iovec(), which takes a bvec_iter and returns a
+   literal struct bio_vec - constructed on the fly from the raw biovec but
+   taking into account bi_bvec_done (and bi_size).
+
+ * bi_vcnt can't be trusted or relied upon by driver code - i.e. anything that
+   doesn't actually own the bio. The reason is twofold: firstly, it's not
+   actually needed for iterating over the bio anymore - we only use bi_size.
+   Secondly, when cloning a bio and reusing (a portion of) the original bio's
+   biovec, in order to calculate bi_vcnt for the new bio we'd have to iterate
+   over all the biovecs in the new bio - which is silly as it's not needed.
+
+   So, don't use bi_vcnt anymore.
index 638bf17ff86965a561b5cc258451ea53bd752f1a..821de56d15802c3e41a18d4aac41dbb64f272832 100644 (file)
@@ -24,7 +24,6 @@ CONTENTS:
   2.1 Basic Usage
   2.2 Attaching processes
   2.3 Mounting hierarchies by name
-  2.4 Notification API
 3. Kernel API
   3.1 Overview
   3.2 Synchronization
@@ -472,25 +471,6 @@ you give a subsystem a name.
 The name of the subsystem appears as part of the hierarchy description
 in /proc/mounts and /proc/<pid>/cgroups.
 
-2.4 Notification API
---------------------
-
-There is mechanism which allows to get notifications about changing
-status of a cgroup.
-
-To register a new notification handler you need to:
- - create a file descriptor for event notification using eventfd(2);
- - open a control file to be monitored (e.g. memory.usage_in_bytes);
- - write "<event_fd> <control_fd> <args>" to cgroup.event_control.
-   Interpretation of args is defined by control file implementation;
-
-eventfd will be woken up by control file implementation or when the
-cgroup is removed.
-
-To unregister a notification handler just close eventfd.
-
-NOTE: Support of notifications should be implemented for the control
-file. See documentation for the subsystem.
 
 3. Kernel API
 =============
index 274752f8bdf963b0f1757f2df446f6c5a503c6a5..719320b5ed3f36f476bd019781b774c3b4b8ace6 100644 (file)
@@ -266,10 +266,12 @@ E.g.
 Invalidation is removing an entry from the cache without writing it
 back.  Cache blocks can be invalidated via the invalidate_cblocks
 message, which takes an arbitrary number of cblock ranges.  Each cblock
-must be expressed as a decimal value, in the future a variant message
-that takes cblock ranges expressed in hexidecimal may be needed to
-better support efficient invalidation of larger caches.  The cache must
-be in passthrough mode when invalidate_cblocks is used.
+range's end value is "one past the end", meaning 5-10 expresses a range
+of values from 5 to 9.  Each cblock must be expressed as a decimal
+value, in the future a variant message that takes cblock ranges
+expressed in hexidecimal may be needed to better support efficient
+invalidation of larger caches.  The cache must be in passthrough mode
+when invalidate_cblocks is used.
 
    invalidate_cblocks [<cblock>|<cblock begin>-<cblock end>]*
 
index 5fac246a9530168fc42b378d7b37da9e694dbb91..3509707f932085a8380576ee4c6b63a453dab1a7 100644 (file)
@@ -14,6 +14,9 @@ Required nodes:
 - core-module: the root node to the Integrator platforms must have
   a core-module with regs and the compatible string
   "arm,core-module-integrator"
+- external-bus-interface: the root node to the Integrator platforms
+  must have an external bus interface with regs and the
+  compatible-string "arm,external-bus-interface"
 
   Required properties for the core module:
   - regs: the location and size of the core module registers, one
@@ -48,6 +51,11 @@ Required nodes:
                reg = <0x10000000 0x200>;
        };
 
+       ebi@12000000 {
+               compatible = "arm,external-bus-interface";
+               reg = <0x12000000 0x100>;
+       };
+
        syscon {
                compatible = "arm,integrator-ap-syscon";
                reg = <0x11000000 0x100>;
index ad031211b5b8291e51f43cf9cfe34a431164de87..2742e9cfd6b1166c18fff7cabe63f972aea92b49 100644 (file)
@@ -2,6 +2,7 @@
 
 Required properties:
 - compatible: Should be "atmel,<chip>-aic"
+  <chip> can be "at91rm9200" or "sama5d3"
 - interrupt-controller: Identifies the node as an interrupt controller.
 - interrupt-parent: For single AIC system, it is an empty property.
 - #interrupt-cells: The number of cells to define the interrupts. It should be 3.
index 1196290082d1ed176c03d3f985bf2539028b35c3..d2170e780f0bc431c89b181fd7369e930003b115 100644 (file)
@@ -50,7 +50,8 @@ Example:
        };
 
 RAMC SDRAM/DDR Controller required properties:
-- compatible: Should be "atmel,at91sam9260-sdramc",
+- compatible: Should be "atmel,at91rm9200-sdramc",
+                       "atmel,at91sam9260-sdramc",
                        "atmel,at91sam9g45-ddramc",
 - reg: Should contain registers location and length
   For at91sam9263 and at91sam9g45 you must specify 2 entries.
index 3dfb0c0384f572c45cc3df9e6fe92d6c6212bc89..bae0d87a38b2bb4c6577e2a597c0ac7f501d1b2b 100644 (file)
@@ -11,6 +11,7 @@ have PPIs or SGIs.
 Main node required properties:
 
 - compatible : should be one of:
+       "arm,gic-400"
        "arm,cortex-a15-gic"
        "arm,cortex-a9-gic"
        "arm,cortex-a7-gic"
index 1a5a42ce21bb0ac7480b07ca9aced96914c33910..83f405bde138a35f824f19ad27873982f8bc0325 100644 (file)
@@ -7,10 +7,18 @@ The MPU contain CPUs, GIC, L2 cache and a local PRCM.
 Required properties:
 - compatible : Should be "ti,omap3-mpu" for OMAP3
                Should be "ti,omap4-mpu" for OMAP4
+              Should be "ti,omap5-mpu" for OMAP5
 - ti,hwmods: "mpu"
 
 Examples:
 
+- For an OMAP5 SMP system:
+
+mpu {
+    compatible = "ti,omap5-mpu";
+    ti,hwmods = "mpu"
+};
+
 - For an OMAP4 SMP system:
 
 mpu {
index 343781b9f246773ce880f9427623ebbd12202f32..3e1e498fea96b357ff990f6fbb682dd43f5254cc 100644 (file)
@@ -7,6 +7,7 @@ representation in the device tree should be done as under:-
 Required properties:
 
 - compatible : should be one of
+       "arm,armv8-pmuv3"
        "arm,cortex-a15-pmu"
        "arm,cortex-a9-pmu"
        "arm,cortex-a8-pmu"
index 47ada1dff2165bfb836600e606adfd79ac7eca3a..5d49f2b37f68dfbd0f63e7e930c3a00b0ad5ac74 100644 (file)
@@ -49,7 +49,7 @@ adc@12D10000 {
        /* NTC thermistor is a hwmon device */
        ncp15wb473@0 {
                compatible = "ntc,ncp15wb473";
-               pullup-uV = <1800000>;
+               pullup-uv = <1800000>;
                pullup-ohm = <47000>;
                pulldown-ohm = <0>;
                io-channels = <&adc 4>;
diff --git a/Documentation/devicetree/bindings/ata/sata_rcar.txt b/Documentation/devicetree/bindings/ata/sata_rcar.txt
new file mode 100644 (file)
index 0000000..1e61113
--- /dev/null
@@ -0,0 +1,18 @@
+* Renesas R-Car SATA
+
+Required properties:
+- compatible           : should contain one of the following:
+                         - "renesas,sata-r8a7779" for R-Car H1
+                         - "renesas,sata-r8a7790" for R-Car H2
+                         - "renesas,sata-r8a7791" for R-Car M2
+- reg                  : address and length of the SATA registers;
+- interrupts           : must consist of one interrupt specifier.
+
+Example:
+
+sata: sata@fc600000 {
+       compatible = "renesas,sata-r8a7779";
+       reg = <0xfc600000 0x2000>;
+       interrupt-parent = <&gic>;
+       interrupts = <0 100 IRQ_TYPE_LEVEL_HIGH>;
+};
diff --git a/Documentation/devicetree/bindings/clock/at91-clock.txt b/Documentation/devicetree/bindings/clock/at91-clock.txt
new file mode 100644 (file)
index 0000000..cd5e239
--- /dev/null
@@ -0,0 +1,339 @@
+Device Tree Clock bindings for arch-at91
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be one of the following:
+       "atmel,at91rm9200-pmc" or
+       "atmel,at91sam9g45-pmc" or
+       "atmel,at91sam9n12-pmc" or
+       "atmel,at91sam9x5-pmc" or
+       "atmel,sama5d3-pmc":
+               at91 PMC (Power Management Controller)
+               All at91 specific clocks (clocks defined below) must be child
+               node of the PMC node.
+
+       "atmel,at91rm9200-clk-main":
+               at91 main oscillator
+
+       "atmel,at91rm9200-clk-master" or
+       "atmel,at91sam9x5-clk-master":
+               at91 master clock
+
+       "atmel,at91sam9x5-clk-peripheral" or
+       "atmel,at91rm9200-clk-peripheral":
+               at91 peripheral clocks
+
+       "atmel,at91rm9200-clk-pll" or
+       "atmel,at91sam9g45-clk-pll" or
+       "atmel,at91sam9g20-clk-pllb" or
+       "atmel,sama5d3-clk-pll":
+               at91 pll clocks
+
+       "atmel,at91sam9x5-clk-plldiv":
+               at91 plla divisor
+
+       "atmel,at91rm9200-clk-programmable" or
+       "atmel,at91sam9g45-clk-programmable" or
+       "atmel,at91sam9x5-clk-programmable":
+               at91 programmable clocks
+
+       "atmel,at91sam9x5-clk-smd":
+               at91 SMD (Soft Modem) clock
+
+       "atmel,at91rm9200-clk-system":
+               at91 system clocks
+
+       "atmel,at91rm9200-clk-usb" or
+       "atmel,at91sam9x5-clk-usb" or
+       "atmel,at91sam9n12-clk-usb":
+               at91 usb clock
+
+       "atmel,at91sam9x5-clk-utmi":
+               at91 utmi clock
+
+Required properties for PMC node:
+- reg : defines the IO memory reserved for the PMC.
+- #size-cells : shall be 0 (reg is used to encode clk id).
+- #address-cells : shall be 1 (reg is used to encode clk id).
+- interrupts : shall be set to PMC interrupt line.
+- interrupt-controller : tell that the PMC is an interrupt controller.
+- #interrupt-cells : must be set to 1. The first cell encodes the interrupt id,
+       and reflect the bit position in the PMC_ER/DR/SR registers.
+       You can use the dt macros defined in dt-bindings/clk/at91.h.
+       0 (AT91_PMC_MOSCS) -> main oscillator ready
+       1 (AT91_PMC_LOCKA) -> PLL A ready
+       2 (AT91_PMC_LOCKB) -> PLL B ready
+       3 (AT91_PMC_MCKRDY) -> master clock ready
+       6 (AT91_PMC_LOCKU) -> UTMI PLL clock ready
+       8 .. 15 (AT91_PMC_PCKRDY(id)) -> programmable clock ready
+       16 (AT91_PMC_MOSCSELS) -> main oscillator selected
+       17 (AT91_PMC_MOSCRCS) -> RC main oscillator stabilized
+       18 (AT91_PMC_CFDEV) -> clock failure detected
+
+For example:
+       pmc: pmc@fffffc00 {
+               compatible = "atmel,sama5d3-pmc";
+               interrupts = <1 4 7>;
+               interrupt-controller;
+               #interrupt-cells = <2>;
+               #size-cells = <0>;
+               #address-cells = <1>;
+
+               /* put at91 clocks here */
+       };
+
+Required properties for main clock:
+- interrupt-parent : must reference the PMC node.
+- interrupts : shall be set to "<0>".
+- #clock-cells : from common clock binding; shall be set to 0.
+- clocks (optional if clock-frequency is provided) : shall be the slow clock
+       phandle. This clock is used to calculate the main clock rate if
+       "clock-frequency" is not provided.
+- clock-frequency : the main oscillator frequency.Prefer the use of
+       "clock-frequency" over automatic clock rate calculation.
+
+For example:
+       main: mainck {
+               compatible = "atmel,at91rm9200-clk-main";
+               interrupt-parent = <&pmc>;
+               interrupts = <0>;
+               #clock-cells = <0>;
+               clocks = <&ck32k>;
+               clock-frequency = <18432000>;
+       };
+
+Required properties for master clock:
+- interrupt-parent : must reference the PMC node.
+- interrupts : shall be set to "<3>".
+- #clock-cells : from common clock binding; shall be set to 0.
+- clocks : shall be the master clock sources (see atmel datasheet) phandles.
+       e.g. "<&ck32k>, <&main>, <&plla>, <&pllb>".
+- atmel,clk-output-range : minimum and maximum clock frequency (two u32
+                          fields).
+          e.g. output = <0 133000000>; <=> 0 to 133MHz.
+- atmel,clk-divisors : master clock divisors table (four u32 fields).
+               0 <=> reserved value.
+               e.g. divisors = <1 2 4 6>;
+- atmel,master-clk-have-div3-pres : some SoC use the reserved value 7 in the
+                                   PRES field as CLOCK_DIV3 (e.g sam9x5).
+
+For example:
+       mck: mck {
+               compatible = "atmel,at91rm9200-clk-master";
+               interrupt-parent = <&pmc>;
+               interrupts = <3>;
+               #clock-cells = <0>;
+               atmel,clk-output-range = <0 133000000>;
+               atmel,clk-divisors = <1 2 4 0>;
+       };
+
+Required properties for peripheral clocks:
+- #size-cells : shall be 0 (reg is used to encode clk id).
+- #address-cells : shall be 1 (reg is used to encode clk id).
+- clocks : shall be the master clock phandle.
+       e.g. clocks = <&mck>;
+- name: device tree node describing a specific system clock.
+       * #clock-cells : from common clock binding; shall be set to 0.
+       * reg: peripheral id. See Atmel's datasheets to get a full
+         list of peripheral ids.
+       * atmel,clk-output-range : minimum and maximum clock frequency
+         (two u32 fields). Only valid on at91sam9x5-clk-peripheral
+         compatible IPs.
+
+For example:
+       periph: periphck {
+               compatible = "atmel,at91sam9x5-clk-peripheral";
+               #size-cells = <0>;
+               #address-cells = <1>;
+               clocks = <&mck>;
+
+               ssc0_clk {
+                       #clock-cells = <0>;
+                       reg = <2>;
+                       atmel,clk-output-range = <0 133000000>;
+               };
+
+               usart0_clk {
+                       #clock-cells = <0>;
+                       reg = <3>;
+                       atmel,clk-output-range = <0 66000000>;
+               };
+       };
+
+
+Required properties for pll clocks:
+- interrupt-parent : must reference the PMC node.
+- interrupts : shall be set to "<1>".
+- #clock-cells : from common clock binding; shall be set to 0.
+- clocks : shall be the main clock phandle.
+- reg : pll id.
+       0 -> PLL A
+       1 -> PLL B
+- atmel,clk-input-range : minimum and maximum source clock frequency (two u32
+                         fields).
+         e.g. input = <1 32000000>; <=> 1 to 32MHz.
+- #atmel,pll-clk-output-range-cells : number of cells reserved for pll output
+                                     range description. Sould be set to 2, 3
+                                     or 4.
+       * 1st and 2nd cells represent the frequency range (min-max).
+       * 3rd cell is optional and represents the OUT field value for the given
+         range.
+       * 4th cell is optional and represents the ICPLL field (PLLICPR
+         register)
+- atmel,pll-clk-output-ranges : pll output frequency ranges + optional parameter
+                               depending on #atmel,pll-output-range-cells
+                               property value.
+
+For example:
+       plla: pllack {
+               compatible = "atmel,at91sam9g45-clk-pll";
+               interrupt-parent = <&pmc>;
+               interrupts = <1>;
+               #clock-cells = <0>;
+               clocks = <&main>;
+               reg = <0>;
+               atmel,clk-input-range = <2000000 32000000>;
+               #atmel,pll-clk-output-range-cells = <4>;
+               atmel,pll-clk-output-ranges = <74500000 800000000 0 0
+                                              69500000 750000000 1 0
+                                              64500000 700000000 2 0
+                                              59500000 650000000 3 0
+                                              54500000 600000000 0 1
+                                              49500000 550000000 1 1
+                                              44500000 500000000 2 1
+                                              40000000 450000000 3 1>;
+       };
+
+Required properties for plldiv clocks (plldiv = pll / 2):
+- #clock-cells : from common clock binding; shall be set to 0.
+- clocks : shall be the plla clock phandle.
+
+The pll divisor is equal to 2 and cannot be changed.
+
+For example:
+       plladiv: plladivck {
+               compatible = "atmel,at91sam9x5-clk-plldiv";
+               #clock-cells = <0>;
+               clocks = <&plla>;
+       };
+
+Required properties for programmable clocks:
+- interrupt-parent : must reference the PMC node.
+- #size-cells : shall be 0 (reg is used to encode clk id).
+- #address-cells : shall be 1 (reg is used to encode clk id).
+- clocks : shall be the programmable clock source phandles.
+       e.g. clocks = <&clk32k>, <&main>, <&plla>, <&pllb>;
+- name: device tree node describing a specific prog clock.
+       * #clock-cells : from common clock binding; shall be set to 0.
+       * reg : programmable clock id (register offset from  PCKx
+                        register).
+       * interrupts : shall be set to "<(8 + id)>".
+
+For example:
+       prog: progck {
+               compatible = "atmel,at91sam9g45-clk-programmable";
+               #size-cells = <0>;
+               #address-cells = <1>;
+               interrupt-parent = <&pmc>;
+               clocks = <&clk32k>, <&main>, <&plladiv>, <&utmi>, <&mck>;
+
+               prog0 {
+                       #clock-cells = <0>;
+                       reg = <0>;
+                       interrupts = <8>;
+               };
+
+               prog1 {
+                       #clock-cells = <0>;
+                       reg = <1>;
+                       interrupts = <9>;
+               };
+       };
+
+
+Required properties for smd clock:
+- #clock-cells : from common clock binding; shall be set to 0.
+- clocks : shall be the smd clock source phandles.
+       e.g. clocks = <&plladiv>, <&utmi>;
+
+For example:
+       smd: smdck {
+               compatible = "atmel,at91sam9x5-clk-smd";
+               #clock-cells = <0>;
+               clocks = <&plladiv>, <&utmi>;
+       };
+
+Required properties for system clocks:
+- #size-cells : shall be 0 (reg is used to encode clk id).
+- #address-cells : shall be 1 (reg is used to encode clk id).
+- name: device tree node describing a specific system clock.
+       * #clock-cells : from common clock binding; shall be set to 0.
+       * reg: system clock id (bit position in SCER/SCDR/SCSR registers).
+             See Atmel's datasheet to get a full list of system clock ids.
+
+For example:
+       system: systemck {
+               compatible = "atmel,at91rm9200-clk-system";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               ddrck {
+                       #clock-cells = <0>;
+                       reg = <2>;
+                       clocks = <&mck>;
+               };
+
+               uhpck {
+                       #clock-cells = <0>;
+                       reg = <6>;
+                       clocks = <&usb>;
+               };
+
+               udpck {
+                       #clock-cells = <0>;
+                       reg = <7>;
+                       clocks = <&usb>;
+               };
+       };
+
+
+Required properties for usb clock:
+- #clock-cells : from common clock binding; shall be set to 0.
+- clocks : shall be the smd clock source phandles.
+       e.g. clocks = <&pllb>;
+- atmel,clk-divisors (only available for "atmel,at91rm9200-clk-usb"):
+       usb clock divisor table.
+       e.g. divisors = <1 2 4 0>;
+
+For example:
+       usb: usbck {
+               compatible = "atmel,at91sam9x5-clk-usb";
+               #clock-cells = <0>;
+               clocks = <&plladiv>, <&utmi>;
+       };
+
+       usb: usbck {
+               compatible = "atmel,at91rm9200-clk-usb";
+               #clock-cells = <0>;
+               clocks = <&pllb>;
+               atmel,clk-divisors = <1 2 4 0>;
+       };
+
+
+Required properties for utmi clock:
+- interrupt-parent : must reference the PMC node.
+- interrupts : shall be set to "<AT91_PMC_LOCKU IRQ_TYPE_LEVEL_HIGH>".
+- #clock-cells : from common clock binding; shall be set to 0.
+- clocks : shall be the main clock source phandle.
+
+For example:
+       utmi: utmick {
+               compatible = "atmel,at91sam9x5-clk-utmi";
+               interrupt-parent = <&pmc>;
+               interrupts = <AT91_PMC_LOCKU IRQ_TYPE_LEVEL_HIGH>;
+               #clock-cells = <0>;
+               clocks = <&main>;
+       };
index c6bf8a6c8f52856b95af14e1e85134a246c1a44b..a2ac2d9ac71a7d0e4566dbc872dc5d4bb771407b 100644 (file)
@@ -6,7 +6,7 @@ SoC's in the Exynos4 family.
 
 Required Properties:
 
-- comptible: should be one of the following.
+- compatible: should be one of the following.
   - "samsung,exynos4210-clock" - controller compatible with Exynos4210 SoC.
   - "samsung,exynos4412-clock" - controller compatible with Exynos4412 SoC.
 
index 24765c146e31d52ea4c732812c420ccdb5d3e670..46f5c791ea0df6e94e2ea6bd8ef26436231f8ebe 100644 (file)
@@ -5,7 +5,7 @@ controllers within the Exynos5250 SoC.
 
 Required Properties:
 
-- comptible: should be one of the following.
+- compatible: should be one of the following.
   - "samsung,exynos5250-clock" - controller compatible with Exynos5250 SoC.
 
 - reg: physical base address of the controller and length of memory mapped
index 32aa34ecad364f6d3d0c613c471ec5752096b6ba..458f34789e5d1aa6c6b6944d37f5dad4cfc22cf9 100644 (file)
@@ -5,7 +5,7 @@ controllers within the Exynos5420 SoC.
 
 Required Properties:
 
-- comptible: should be one of the following.
+- compatible: should be one of the following.
   - "samsung,exynos5420-clock" - controller compatible with Exynos5420 SoC.
 
 - reg: physical base address of the controller and length of memory mapped
index 4499e9966bc9727db13c46d1976db830690625a2..9955dc9c7d969f5cb0888dc8a6c352dc037d81cf 100644 (file)
@@ -5,7 +5,7 @@ controllers within the Exynos5440 SoC.
 
 Required Properties:
 
-- comptible: should be "samsung,exynos5440-clock".
+- compatible: should be "samsung,exynos5440-clock".
 
 - reg: physical base address of the controller and length of memory mapped
   region.
index 4c029a8739d3abae79c08ea1e100fc9b91efe642..cadc4d29ada6663716c5135f78adcc3df902ee8e 100644 (file)
@@ -7,197 +7,8 @@ Required properties:
 - #clock-cells: Should be <1>
 
 The clock consumer should specify the desired clock by having the clock
-ID in its "clocks" phandle cell.  The following is a full list of i.MX5
-clocks and IDs.
-
-       Clock                   ID
-       ---------------------------
-       dummy                   0
-       ckil                    1
-       osc                     2
-       ckih1                   3
-       ckih2                   4
-       ahb                     5
-       ipg                     6
-       axi_a                   7
-       axi_b                   8
-       uart_pred               9
-       uart_root               10
-       esdhc_a_pred            11
-       esdhc_b_pred            12
-       esdhc_c_s               13
-       esdhc_d_s               14
-       emi_sel                 15
-       emi_slow_podf           16
-       nfc_podf                17
-       ecspi_pred              18
-       ecspi_podf              19
-       usboh3_pred             20
-       usboh3_podf             21
-       usb_phy_pred            22
-       usb_phy_podf            23
-       cpu_podf                24
-       di_pred                 25
-       tve_s                   27
-       uart1_ipg_gate          28
-       uart1_per_gate          29
-       uart2_ipg_gate          30
-       uart2_per_gate          31
-       uart3_ipg_gate          32
-       uart3_per_gate          33
-       i2c1_gate               34
-       i2c2_gate               35
-       gpt_ipg_gate            36
-       pwm1_ipg_gate           37
-       pwm1_hf_gate            38
-       pwm2_ipg_gate           39
-       pwm2_hf_gate            40
-       gpt_hf_gate             41
-       fec_gate                42
-       usboh3_per_gate         43
-       esdhc1_ipg_gate         44
-       esdhc2_ipg_gate         45
-       esdhc3_ipg_gate         46
-       esdhc4_ipg_gate         47
-       ssi1_ipg_gate           48
-       ssi2_ipg_gate           49
-       ssi3_ipg_gate           50
-       ecspi1_ipg_gate         51
-       ecspi1_per_gate         52
-       ecspi2_ipg_gate         53
-       ecspi2_per_gate         54
-       cspi_ipg_gate           55
-       sdma_gate               56
-       emi_slow_gate           57
-       ipu_s                   58
-       ipu_gate                59
-       nfc_gate                60
-       ipu_di1_gate            61
-       vpu_s                   62
-       vpu_gate                63
-       vpu_reference_gate      64
-       uart4_ipg_gate          65
-       uart4_per_gate          66
-       uart5_ipg_gate          67
-       uart5_per_gate          68
-       tve_gate                69
-       tve_pred                70
-       esdhc1_per_gate         71
-       esdhc2_per_gate         72
-       esdhc3_per_gate         73
-       esdhc4_per_gate         74
-       usb_phy_gate            75
-       hsi2c_gate              76
-       mipi_hsc1_gate          77
-       mipi_hsc2_gate          78
-       mipi_esc_gate           79
-       mipi_hsp_gate           80
-       ldb_di1_div_3_5         81
-       ldb_di1_div             82
-       ldb_di0_div_3_5         83
-       ldb_di0_div             84
-       ldb_di1_gate            85
-       can2_serial_gate        86
-       can2_ipg_gate           87
-       i2c3_gate               88
-       lp_apm                  89
-       periph_apm              90
-       main_bus                91
-       ahb_max                 92
-       aips_tz1                93
-       aips_tz2                94
-       tmax1                   95
-       tmax2                   96
-       tmax3                   97
-       spba                    98
-       uart_sel                99
-       esdhc_a_sel             100
-       esdhc_b_sel             101
-       esdhc_a_podf            102
-       esdhc_b_podf            103
-       ecspi_sel               104
-       usboh3_sel              105
-       usb_phy_sel             106
-       iim_gate                107
-       usboh3_gate             108
-       emi_fast_gate           109
-       ipu_di0_gate            110
-       gpc_dvfs                111
-       pll1_sw                 112
-       pll2_sw                 113
-       pll3_sw                 114
-       ipu_di0_sel             115
-       ipu_di1_sel             116
-       tve_ext_sel             117
-       mx51_mipi               118
-       pll4_sw                 119
-       ldb_di1_sel             120
-       di_pll4_podf            121
-       ldb_di0_sel             122
-       ldb_di0_gate            123
-       usb_phy1_gate           124
-       usb_phy2_gate           125
-       per_lp_apm              126
-       per_pred1               127
-       per_pred2               128
-       per_podf                129
-       per_root                130
-       ssi_apm                 131
-       ssi1_root_sel           132
-       ssi2_root_sel           133
-       ssi3_root_sel           134
-       ssi_ext1_sel            135
-       ssi_ext2_sel            136
-       ssi_ext1_com_sel        137
-       ssi_ext2_com_sel        138
-       ssi1_root_pred          139
-       ssi1_root_podf          140
-       ssi2_root_pred          141
-       ssi2_root_podf          142
-       ssi_ext1_pred           143
-       ssi_ext1_podf           144
-       ssi_ext2_pred           145
-       ssi_ext2_podf           146
-       ssi1_root_gate          147
-       ssi2_root_gate          148
-       ssi3_root_gate          149
-       ssi_ext1_gate           150
-       ssi_ext2_gate           151
-       epit1_ipg_gate          152
-       epit1_hf_gate           153
-       epit2_ipg_gate          154
-       epit2_hf_gate           155
-       can_sel                 156
-       can1_serial_gate        157
-       can1_ipg_gate           158
-       owire_gate              159
-       gpu3d_s                 160
-       gpu2d_s                 161
-       gpu3d_gate              162
-       gpu2d_gate              163
-       garb_gate               164
-       cko1_sel                165
-       cko1_podf               166
-       cko1                    167
-       cko2_sel                168
-       cko2_podf               169
-       cko2                    170
-       srtc_gate               171
-       pata_gate               172
-       sata_gate               173
-       spdif_xtal_sel          174
-       spdif0_sel              175
-       spdif1_sel              176
-       spdif0_pred             177
-       spdif0_podf             178
-       spdif1_pred             179
-       spdif1_podf             180
-       spdif0_com_sel          181
-       spdif1_com_sel          182
-       spdif0_gate             183
-       spdif1_gate             184
-       spdif_ipg_gate          185
-       ocram                   186
+ID in its "clocks" phandle cell. See include/dt-bindings/clock/imx5-clock.h
+for the full list of i.MX5 clock IDs.
 
 Examples (for mx53):
 
@@ -212,7 +23,7 @@ can1: can@53fc8000 {
        compatible = "fsl,imx53-flexcan", "fsl,p1010-flexcan";
        reg = <0x53fc8000 0x4000>;
        interrupts = <82>;
-       clocks = <&clks 158>, <&clks 157>;
+       clocks = <&clks IMX5_CLK_CAN1_IPG_GATE>, <&clks IMX5_CLK_CAN1_SERIAL_GATE>;
        clock-names = "ipg", "per";
        status = "disabled";
 };
index 4fa814d3832124adb80f29ee777849739acbb7e4..68b83ecc385007216d391f1a0edf06527dad5fb9 100644 (file)
@@ -42,6 +42,7 @@ The full ID of peripheral types can be found below.
        19      IPU Memory
        20      ASRC
        21      ESAI
+       22      SSI Dual FIFO   (needs firmware ver >= 2)
 
 The third cell specifies the transfer priority as below.
 
index a8c21c256baa5afbcb4b1a43d150ca47a5c4e3ea..1f5729f106216ecb079af2c4912fd61e20098585 100644 (file)
@@ -50,6 +50,9 @@ Each dmas request consists of 4 cells:
         0x00000008: Use fixed channel:
                 Use automatic channel selection when unset
                 Use DMA request line number when set
+        0x00000010: Set channel as high priority:
+                Normal priority when unset
+                High priority when set
 
 Example:
 
index b0019eb5330ee8bdd0ee825255f1a26f13039980..798cfc9d3839c9a24405419a35c935e370a51967 100644 (file)
@@ -5,16 +5,42 @@ This is for the non-QE/CPM/GUTs GPIO controllers as found on
 
 Every GPIO controller node must have #gpio-cells property defined,
 this information will be used to translate gpio-specifiers.
+See bindings/gpio/gpio.txt for details of how to specify GPIO
+information for devices.
+
+The GPIO module usually is connected to the SoC's internal interrupt
+controller, see bindings/interrupt-controller/interrupts.txt (the
+interrupt client nodes section) for details how to specify this GPIO
+module's interrupt.
+
+The GPIO module may serve as another interrupt controller (cascaded to
+the SoC's internal interrupt controller).  See the interrupt controller
+nodes section in bindings/interrupt-controller/interrupts.txt for
+details.
 
 Required properties:
-- compatible : "fsl,<CHIP>-gpio" followed by "fsl,mpc8349-gpio" for
-  83xx, "fsl,mpc8572-gpio" for 85xx and "fsl,mpc8610-gpio" for 86xx.
-- #gpio-cells : Should be two. The first cell is the pin number and the
-  second cell is used to specify optional parameters (currently unused).
- - interrupts : Interrupt mapping for GPIO IRQ.
- - interrupt-parent : Phandle for the interrupt controller that
-   services interrupts for this device.
-- gpio-controller : Marks the port as GPIO controller.
+- compatible:          "fsl,<chip>-gpio" followed by "fsl,mpc8349-gpio"
+                       for 83xx, "fsl,mpc8572-gpio" for 85xx, or
+                       "fsl,mpc8610-gpio" for 86xx.
+- #gpio-cells:         Should be two. The first cell is the pin number
+                       and the second cell is used to specify optional
+                       parameters (currently unused).
+- interrupt-parent:    Phandle for the interrupt controller that
+                       services interrupts for this device.
+- interrupts:          Interrupt mapping for GPIO IRQ.
+- gpio-controller:     Marks the port as GPIO controller.
+
+Optional properties:
+- interrupt-controller:        Empty boolean property which marks the GPIO
+                       module as an IRQ controller.
+- #interrupt-cells:    Should be two.  Defines the number of integer
+                       cells required to specify an interrupt within
+                       this interrupt controller.  The first cell
+                       defines the pin number, the second cell
+                       defines additional flags (trigger type,
+                       trigger polarity).  Note that the available
+                       set of trigger conditions supported by the
+                       GPIO module depends on the actual SoC.
 
 Example of gpio-controller nodes for a MPC8347 SoC:
 
@@ -22,39 +48,27 @@ Example of gpio-controller nodes for a MPC8347 SoC:
                #gpio-cells = <2>;
                compatible = "fsl,mpc8347-gpio", "fsl,mpc8349-gpio";
                reg = <0xc00 0x100>;
-               interrupts = <74 0x8>;
                interrupt-parent = <&ipic>;
+               interrupts = <74 0x8>;
                gpio-controller;
+               interrupt-controller;
+               #interrupt-cells = <2>;
        };
 
        gpio2: gpio-controller@d00 {
                #gpio-cells = <2>;
                compatible = "fsl,mpc8347-gpio", "fsl,mpc8349-gpio";
                reg = <0xd00 0x100>;
-               interrupts = <75 0x8>;
                interrupt-parent = <&ipic>;
+               interrupts = <75 0x8>;
                gpio-controller;
        };
 
-See booting-without-of.txt for details of how to specify GPIO
-information for devices.
-
-To use GPIO pins as interrupt sources for peripherals, specify the
-GPIO controller as the interrupt parent and define GPIO number +
-trigger mode using the interrupts property, which is defined like
-this:
-
-interrupts = <number trigger>, where:
- - number: GPIO pin (0..31)
- - trigger: trigger mode:
-       2 = trigger on falling edge
-       3 = trigger on both edges
-
-Example of device using this is:
+Example of a peripheral using the GPIO module as an IRQ controller:
 
        funkyfpga@0 {
                compatible = "funky-fpga";
                ...
-               interrupts = <4 3>;
                interrupt-parent = <&gpio1>;
+               interrupts = <4 3>;
        };
diff --git a/Documentation/devicetree/bindings/gpio/gpio-lp3943.txt b/Documentation/devicetree/bindings/gpio/gpio-lp3943.txt
new file mode 100644 (file)
index 0000000..80fcb7d
--- /dev/null
@@ -0,0 +1,37 @@
+TI/National Semiconductor LP3943 GPIO controller
+
+Required properties:
+  - compatible: "ti,lp3943-gpio"
+  - gpio-controller: Marks the device node as a GPIO controller.
+  - #gpio-cells: Should be 2. See gpio.txt in this directory for a
+                 description of the cells format.
+
+Example:
+Simple LED controls with LP3943 GPIO controller
+
+&i2c4 {
+       lp3943@60 {
+               compatible = "ti,lp3943";
+               reg = <0x60>;
+
+               gpioex: gpio {
+                       compatible = "ti,lp3943-gpio";
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+       };
+};
+
+leds {
+       compatible = "gpio-leds";
+       indicator1 {
+               label = "indi1";
+               gpios = <&gpioex 9 GPIO_ACTIVE_LOW>;
+       };
+
+       indicator2 {
+               label = "indi2";
+               gpios = <&gpioex 10 GPIO_ACTIVE_LOW>;
+               default-state = "off";
+       };
+};
diff --git a/Documentation/devicetree/bindings/input/gpio-beeper.txt b/Documentation/devicetree/bindings/input/gpio-beeper.txt
new file mode 100644 (file)
index 0000000..a5086e3
--- /dev/null
@@ -0,0 +1,13 @@
+* GPIO beeper device tree bindings
+
+Register a beeper connected to GPIO pin.
+
+Required properties:
+- compatible:  Should be "gpio-beeper".
+- gpios:       From common gpio binding; gpio connection to beeper enable pin.
+
+Example:
+       beeper: beeper {
+               compatible = "gpio-beeper";
+               gpios = <&gpio3 23 GPIO_ACTIVE_HIGH>;
+       };
diff --git a/Documentation/devicetree/bindings/input/touchscreen/tsc2007.txt b/Documentation/devicetree/bindings/input/touchscreen/tsc2007.txt
new file mode 100644 (file)
index 0000000..ec365e1
--- /dev/null
@@ -0,0 +1,41 @@
+* Texas Instruments tsc2007 touchscreen controller
+
+Required properties:
+- compatible: must be "ti,tsc2007".
+- reg: I2C address of the chip.
+- ti,x-plate-ohms: X-plate resistance in ohms.
+
+Optional properties:
+- gpios: the interrupt gpio the chip is connected to (trough the penirq pin).
+  The penirq pin goes to low when the panel is touched.
+  (see GPIO binding[1] for more details).
+- interrupt-parent: the phandle for the gpio controller
+  (see interrupt binding[0]).
+- interrupts: (gpio) interrupt to which the chip is connected
+  (see interrupt binding[0]).
+- ti,max-rt: maximum pressure.
+- ti,fuzzx: specifies the absolute input fuzz x value.
+  If set, it will permit noise in the data up to +- the value given to the fuzz
+  parameter, that is used to filter noise from the event stream.
+- ti,fuzzy: specifies the absolute input fuzz y value.
+- ti,fuzzz: specifies the absolute input fuzz z value.
+- ti,poll-period: how much time to wait (in milliseconds) before reading again the
+  values from the tsc2007.
+
+[0]: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
+[1]: Documentation/devicetree/bindings/gpio/gpio.txt
+
+Example:
+       &i2c1 {
+               /* ... */
+               tsc2007@49 {
+                       compatible = "ti,tsc2007";
+                       reg = <0x49>;
+                       interrupt-parent = <&gpio4>;
+                       interrupts = <0x0 0x8>;
+                       gpios = <&gpio4 0 0>;
+                       ti,x-plate-ohms = <180>;
+               };
+
+               /* ... */
+       };
diff --git a/Documentation/devicetree/bindings/input/twl4030-pwrbutton.txt b/Documentation/devicetree/bindings/input/twl4030-pwrbutton.txt
new file mode 100644 (file)
index 0000000..c864a46
--- /dev/null
@@ -0,0 +1,21 @@
+Texas Instruments TWL family (twl4030) pwrbutton module
+
+This module is part of the TWL4030. For more details about the whole
+chip see Documentation/devicetree/bindings/mfd/twl-familly.txt.
+
+This module provides a simple power button event via an Interrupt.
+
+Required properties:
+- compatible: should be one of the following
+   - "ti,twl4030-pwrbutton": For controllers compatible with twl4030
+- interrupts: should be one of the following
+   - <8>: For controllers compatible with twl4030
+
+Example:
+
+&twl {
+       twl_pwrbutton: pwrbutton {
+               compatible = "ti,twl4030-pwrbutton";
+               interrupts = <8>;
+       };
+};
diff --git a/Documentation/devicetree/bindings/interrupt-controller/marvell,dove-pmu-intc.txt b/Documentation/devicetree/bindings/interrupt-controller/marvell,dove-pmu-intc.txt
new file mode 100644 (file)
index 0000000..1feb582
--- /dev/null
@@ -0,0 +1,17 @@
+Marvell Dove Power Management Unit interrupt controller
+
+Required properties:
+- compatible: shall be "marvell,dove-pmu-intc"
+- reg: base address of PMU interrupt registers starting with CAUSE register
+- interrupts: PMU interrupt of the main interrupt controller
+- interrupt-controller: identifies the node as an interrupt controller
+- #interrupt-cells: number of cells to encode an interrupt source, shall be 1
+
+Example:
+       pmu_intc: pmu-interrupt-ctrl@d0050 {
+               compatible = "marvell,dove-pmu-intc";
+               interrupt-controller;
+               #interrupt-cells = <1>;
+               reg = <0xd0050 0x8>;
+               interrupts = <33>;
+       };
diff --git a/Documentation/devicetree/bindings/mfd/lp3943.txt b/Documentation/devicetree/bindings/mfd/lp3943.txt
new file mode 100644 (file)
index 0000000..e8591d6
--- /dev/null
@@ -0,0 +1,33 @@
+TI/National Semiconductor LP3943 MFD driver
+
+Required properties:
+  - compatible: "ti,lp3943"
+  - reg: I2C slave address. From 0x60 to 0x67.
+
+LP3943 consists of two sub-devices, lp3943-gpio and lp3943-pwm.
+
+For the LP3943 GPIO properties please refer to:
+Documentation/devicetree/bindings/gpio/gpio-lp3943.txt
+
+For the LP3943 PWM properties please refer to:
+Documentation/devicetree/bindings/pwm/pwm-lp3943.txt
+
+Example:
+
+lp3943@60 {
+       compatible = "ti,lp3943";
+       reg = <0x60>;
+
+       gpioex: gpio {
+               compatible = "ti,lp3943-gpio";
+               gpio-controller;
+               #gpio-cells = <2>;
+       };
+
+       pwm3943: pwm {
+               compatible = "ti,lp3943-pwm";
+               #pwm-cells = <2>;
+               ti,pwm0 = <8 9 10>;
+               ti,pwm1 = <15>;
+       };
+};
index c67b975c89063f51fa20ae563f601c7c6113fe08..532b1d440abc15d1f1d1e61791b274a6ec8dafe0 100644 (file)
@@ -16,6 +16,8 @@ Required Properties:
          specific extensions.
        - "samsung,exynos5250-dw-mshc": for controllers with Samsung Exynos5250
          specific extensions.
+       - "samsung,exynos5420-dw-mshc": for controllers with Samsung Exynos5420
+         specific extensions.
 
 * samsung,dw-mshc-ciu-div: Specifies the divider value for the card interface
   unit (ciu) clock. This property is applicable only for Exynos5 SoC's and
diff --git a/Documentation/devicetree/bindings/mmc/ti-omap.txt b/Documentation/devicetree/bindings/mmc/ti-omap.txt
new file mode 100644 (file)
index 0000000..8de5799
--- /dev/null
@@ -0,0 +1,54 @@
+* TI MMC host controller for OMAP1 and 2420
+
+The MMC Host Controller on TI OMAP1 and 2420 family provides
+an interface for MMC, SD, and SDIO types of memory cards.
+
+This file documents differences between the core properties described
+by mmc.txt and the properties used by the omap mmc driver.
+
+Note that this driver will not work with omap2430 or later omaps,
+please see the omap hsmmc driver for the current omaps.
+
+Required properties:
+- compatible: Must be "ti,omap2420-mmc", for OMAP2420 controllers
+- ti,hwmods: For 2420, must be "msdi<n>", where n is controller
+  instance starting 1
+
+Examples:
+
+       msdi1: mmc@4809c000 {
+               compatible = "ti,omap2420-mmc";
+               ti,hwmods = "msdi1";
+               reg = <0x4809c000 0x80>;
+               interrupts = <83>;
+               dmas = <&sdma 61 &sdma 62>;
+               dma-names = "tx", "rx";
+       };
+
+* TI MMC host controller for OMAP1 and 2420
+
+The MMC Host Controller on TI OMAP1 and 2420 family provides
+an interface for MMC, SD, and SDIO types of memory cards.
+
+This file documents differences between the core properties described
+by mmc.txt and the properties used by the omap mmc driver.
+
+Note that this driver will not work with omap2430 or later omaps,
+please see the omap hsmmc driver for the current omaps.
+
+Required properties:
+- compatible: Must be "ti,omap2420-mmc", for OMAP2420 controllers
+- ti,hwmods: For 2420, must be "msdi<n>", where n is controller
+  instance starting 1
+
+Examples:
+
+       msdi1: mmc@4809c000 {
+               compatible = "ti,omap2420-mmc";
+               ti,hwmods = "msdi1";
+               reg = <0x4809c000 0x80>;
+               interrupts = <83>;
+               dmas = <&sdma 61 &sdma 62>;
+               dma-names = "tx", "rx";
+       };
+
index 551b2a179d016df4bd9bb8e611f38633d57d6640..458d5963468826647d2469c23f542bde3ffe047c 100644 (file)
@@ -17,6 +17,14 @@ Required properties:
 Optional properties:
   - nand-on-flash-bbt: boolean to enable on flash bbt option if not
                        present false
+  - fsl,use-minimum-ecc: Protect this NAND flash with the minimum ECC
+                       strength required. The required ECC strength is
+                       automatically discoverable for some flash
+                       (e.g., according to the ONFI standard).
+                       However, note that if this strength is not
+                       discoverable or this property is not enabled,
+                       the software may chooses an implementation-defined
+                       ECC scheme.
 
 The device tree may optionally contain sub-nodes describing partitions of the
 address space. See partition.txt for more detail.
index f1421e2bbab7387a87e1885794b9688780d6de73..86e0a5601ff5dfb05d9eeed35eb3e638ea58cc7b 100644 (file)
@@ -2,7 +2,9 @@ PXA3xx NAND DT bindings
 
 Required properties:
 
- - compatible:         Should be "marvell,pxa3xx-nand"
+ - compatible:         Should be set to one of the following:
+                       marvell,pxa3xx-nand
+                       marvell,armada370-nand
  - reg:                The register base for the controller
  - interrupts:         The interrupt to map
  - #address-cells:     Set to <1> if the node includes partitions
@@ -13,6 +15,8 @@ Optional properties:
  - marvell,nand-keep-config:   Set to keep the NAND controller config as set
                                by the bootloader
  - num-cs:                     Number of chipselect lines to usw
+ - nand-on-flash-bbt:          boolean to enable on flash bbt option if
+                               not present false
 
 Example:
 
index 48b259e29e873f71f3ccfd0a6877bffa609ebd39..bad381faf036e936d9d99a6baff5d1e053cc2cdd 100644 (file)
@@ -4,7 +4,7 @@ This file provides information, what the device node
 for the davinci_emac interface contains.
 
 Required properties:
-- compatible: "ti,davinci-dm6467-emac";
+- compatible: "ti,davinci-dm6467-emac" or "ti,am3517-emac"
 - reg: Offset and length of the register set for the device
 - ti,davinci-ctrl-reg-offset: offset to control register
 - ti,davinci-ctrl-mod-reg-offset: offset to control module register
index d5363922140322913e171fac6c98f7df2d0b0665..845ff848d8950b546e7243fbc9568847ed2f87ab 100644 (file)
@@ -15,6 +15,7 @@ Optional properties:
   only if property "phy-reset-gpios" is available.  Missing the property
   will have the duration be 1 millisecond.  Numbers greater than 1000 are
   invalid and 1 millisecond will be used instead.
+- phy-supply: regulator that powers the Ethernet PHY.
 
 Example:
 
@@ -25,4 +26,5 @@ ethernet@83fec000 {
        phy-mode = "mii";
        phy-reset-gpios = <&gpio2 14 0>; /* GPIO2_14 */
        local-mac-address = [00 04 9F 01 1B B9];
+       phy-supply = <&reg_fec_supply>;
 };
index 7cd18fbfcf71e702249d1f1aeada02611e2bed52..f648094abc35329bbb67114162e99ed289d90880 100644 (file)
@@ -22,6 +22,7 @@ Optional Properties:
   specifications. If neither of these are specified, the default is to
   assume clause 22. The compatible list may also contain other
   elements.
+- max-speed: Maximum PHY supported speed (10, 100, 1000...)
 
 Example:
 
index 953049b4248a71f4c242d56432730e5ae4c7fbc3..5a41a8658daa12087678a7d81f5f60038cbeddf8 100644 (file)
@@ -8,3 +8,7 @@ Required properties:
 Optional properties:
 - phy-device : phandle to Ethernet phy
 - local-mac-address : Ethernet mac address to use
+- reg-io-width : Mask of sizes (in bytes) of the IO accesses that
+  are supported on the device.  Valid value for SMSC LAN91c111 are
+  1, 2 or 4.  If it's omitted or invalid, the size would be 2 meaning
+  16-bit access only.
index 353eca0efbf83a3469542af53811e3c20255bcfe..d1706ea8257230121f2843bd7684faccd160198b 100644 (file)
@@ -52,12 +52,25 @@ Required properties for pin configuration node:
   CONFIG can be 0 or 1, meaning Pullup disable/enable.
 
 
+The iomux controller has gpio child nodes which are embedded in the iomux
+control registers. They have to be defined as child nodes of the iomux device
+node. If gpio subnodes are defined "#address-cells", "#size-cells" and "ranges"
+properties for the iomux device node are required.
 
 Example:
 
 iomuxc: iomuxc@10015000 {
        compatible = "fsl,imx27-iomuxc";
        reg = <0x10015000 0x600>;
+       #address-cells = <1>;
+       #size-cells = <1>;
+       ranges;
+
+       gpio1: gpio@10015000 {
+               ...
+       };
+
+       ...
 
        uart {
                pinctrl_uart1: uart-1 {
@@ -83,6 +96,15 @@ The above example using macros:
 iomuxc: iomuxc@10015000 {
        compatible = "fsl,imx27-iomuxc";
        reg = <0x10015000 0x600>;
+       #address-cells = <1>;
+       #size-cells = <1>;
+       ranges;
+
+       gpio1: gpio@10015000 {
+               ...
+       };
+
+       ...
 
        uart {
                pinctrl_uart1: uart-1 {
diff --git a/Documentation/devicetree/bindings/pwm/pwm-lp3943.txt b/Documentation/devicetree/bindings/pwm/pwm-lp3943.txt
new file mode 100644 (file)
index 0000000..7bd9d3b
--- /dev/null
@@ -0,0 +1,58 @@
+TI/National Semiconductor LP3943 PWM controller
+
+Required properties:
+  - compatible: "ti,lp3943-pwm"
+  - #pwm-cells: Should be 2. See pwm.txt in this directory for a
+                description of the cells format.
+                Note that this hardware limits the period length to the
+                range 6250~1600000.
+  - ti,pwm0 or ti,pwm1: Output pin number(s) for PWM channel 0 or 1.
+    0 = output 0
+    1 = output 1
+    .
+    .
+    15 = output 15
+
+Example:
+PWM 0 is for RGB LED brightness control
+PWM 1 is for brightness control of LP8557 backlight device
+
+&i2c3 {
+       lp3943@60 {
+               compatible = "ti,lp3943";
+               reg = <0x60>;
+
+               /*
+                * PWM 0 : output 8, 9 and 10
+                * PWM 1 : output 15
+                */
+               pwm3943: pwm {
+                       compatible = "ti,lp3943-pwm";
+                       #pwm-cells = <2>;
+                       ti,pwm0 = <8 9 10>;
+                       ti,pwm1 = <15>;
+               };
+       };
+
+};
+
+/* LEDs control with PWM 0 of LP3943 */
+pwmleds {
+       compatible = "pwm-leds";
+       rgb {
+               label = "indi::rgb";
+               pwms = <&pwm3943 0 10000>;
+               max-brightness = <255>;
+       };
+};
+
+&i2c4 {
+       /* Backlight control with PWM 1 of LP3943 */
+       backlight@2c {
+               compatible = "ti,lp8557";
+               reg = <0x2c>;
+
+               pwms = <&pwm3943 1 10000>;
+               pwm-names = "lp8557";
+       };
+};
diff --git a/Documentation/devicetree/bindings/sound/adi,axi-i2s.txt b/Documentation/devicetree/bindings/sound/adi,axi-i2s.txt
new file mode 100644 (file)
index 0000000..5875ca4
--- /dev/null
@@ -0,0 +1,31 @@
+ADI AXI-I2S controller
+
+Required properties:
+ - compatible : Must be "adi,axi-i2s-1.00.a"
+ - reg : Must contain I2S core's registers location and length
+ - clocks : Pairs of phandle and specifier referencing the controller's clocks.
+   The controller expects two clocks, the clock used for the AXI interface and
+   the clock used as the sampling rate reference clock sample.
+ - clock-names : "axi" for the clock to the AXI interface, "ref" for the sample
+   rate reference clock.
+ - dmas: Pairs of phandle and specifier for the DMA channels that are used by
+   the core. The core expects two dma channels, one for transmit and one for
+   receive.
+ - dma-names : "tx" for the transmit channel, "rx" for the receive channel.
+
+For more details on the 'dma', 'dma-names', 'clock' and 'clock-names' properties
+please check:
+       * resource-names.txt
+       * clock/clock-bindings.txt
+       * dma/dma.txt
+
+Example:
+
+       i2s: i2s@0x77600000 {
+               compatible = "adi,axi-i2s-1.00.a";
+               reg = <0x77600000 0x1000>;
+               clocks = <&clk 15>, <&audio_clock>;
+               clock-names = "axi", "ref";
+               dmas = <&ps7_dma 0>, <&ps7_dma 1>;
+               dma-names = "tx", "rx";
+       };
diff --git a/Documentation/devicetree/bindings/sound/adi,axi-spdif-tx.txt b/Documentation/devicetree/bindings/sound/adi,axi-spdif-tx.txt
new file mode 100644 (file)
index 0000000..46f3449
--- /dev/null
@@ -0,0 +1,30 @@
+ADI AXI-SPDIF controller
+
+Required properties:
+ - compatible : Must be "adi,axi-spdif-1.00.a"
+ - reg : Must contain SPDIF core's registers location and length
+ - clocks : Pairs of phandle and specifier referencing the controller's clocks.
+   The controller expects two clocks, the clock used for the AXI interface and
+   the clock used as the sampling rate reference clock sample.
+ - clock-names: "axi" for the clock to the AXI interface, "ref" for the sample
+   rate reference clock.
+ - dmas: Pairs of phandle and specifier for the DMA channel that is used by
+   the core. The core expects one dma channel for transmit.
+ - dma-names : Must be "tx"
+
+For more details on the 'dma', 'dma-names', 'clock' and 'clock-names' properties
+please check:
+       * resource-names.txt
+       * clock/clock-bindings.txt
+       * dma/dma.txt
+
+Example:
+
+       spdif: spdif@0x77400000 {
+               compatible = "adi,axi-spdif-tx-1.00.a";
+               reg = <0x77600000 0x1000>;
+               clocks = <&clk 15>, <&audio_clock>;
+               clock-names = "axi", "ref";
+               dmas = <&ps7_dma 0>;
+               dma-names = "tx";
+       };
diff --git a/Documentation/devicetree/bindings/sound/bcm2835-i2s.txt b/Documentation/devicetree/bindings/sound/bcm2835-i2s.txt
new file mode 100644 (file)
index 0000000..65783de
--- /dev/null
@@ -0,0 +1,25 @@
+* Broadcom BCM2835 SoC I2S/PCM module
+
+Required properties:
+- compatible: "brcm,bcm2835-i2s"
+- reg: A list of base address and size entries:
+       * The first entry should cover the PCM registers
+       * The second entry should cover the PCM clock registers
+- dmas: List of DMA controller phandle and DMA request line ordered pairs.
+- dma-names: Identifier string for each DMA request line in the dmas property.
+  These strings correspond 1:1 with the ordered pairs in dmas.
+
+  One of the DMA channels will be responsible for transmission (should be
+  named "tx") and one for reception (should be named "rx").
+
+Example:
+
+bcm2835_i2s: i2s@7e203000 {
+       compatible = "brcm,bcm2835-i2s";
+       reg = <0x7e203000 0x20>,
+             <0x7e101098 0x02>;
+
+       dmas = <&dma 2>,
+              <&dma 3>;
+       dma-names = "tx", "rx";
+};
diff --git a/Documentation/devicetree/bindings/sound/cs42l52.txt b/Documentation/devicetree/bindings/sound/cs42l52.txt
new file mode 100644 (file)
index 0000000..bc03c93
--- /dev/null
@@ -0,0 +1,46 @@
+CS42L52 audio CODEC
+
+Required properties:
+
+  - compatible : "cirrus,cs42l52"
+
+  - reg : the I2C address of the device for I2C
+
+Optional properties:
+
+  - cirrus,reset-gpio : GPIO controller's phandle and the number
+  of the GPIO used to reset the codec.
+
+  - cirrus,chgfreq-divisor : Values used to set the Charge Pump Frequency.
+  Allowable values of 0x00 through 0x0F. These are raw values written to the
+  register, not the actual frequency. The frequency is determined by the following.
+  Frequency = (64xFs)/(N+2)
+  N = chgfreq_val
+  Fs = Sample Rate (variable)
+
+  - cirrus,mica-differential-cfg : boolean, If present, then the MICA input is configured
+  as a differential input. If not present then the MICA input is configured as
+  Single-ended input. Single-ended mode allows for MIC1 or MIC2 muxing for input.
+
+  - cirrus,micb-differential-cfg : boolean, If present, then the MICB input is configured
+  as a differential input. If not present then the MICB input is configured as
+  Single-ended input. Single-ended mode allows for MIC1 or MIC2 muxing for input.
+
+  - cirrus,micbias-lvl: Set the output voltage level on the MICBIAS Pin
+  0 = 0.5 x VA
+  1 = 0.6 x VA
+  2 = 0.7 x VA
+  3 = 0.8 x VA
+  4 = 0.83 x VA
+  5 = 0.91 x VA
+
+Example:
+
+codec: codec@4a {
+       compatible = "cirrus,cs42l52";
+       reg = <0x4a>;
+       reset-gpio = <&gpio 10 0>;
+       cirrus,chgfreq-divisor = <0x05>;
+       cirrus.mica-differential-cfg;
+       cirrus,micbias-lvl = <5>;
+};
index ed785b3f67beacb6973ff1758b1b0d5b9b5f16dd..569b26c4a81ee25e1f141329f90903dcb28ab4e4 100644 (file)
@@ -4,7 +4,8 @@ Required properties:
 - compatible :
        "ti,dm646x-mcasp-audio" : for DM646x platforms
        "ti,da830-mcasp-audio"  : for both DA830 & DA850 platforms
-       "ti,am33xx-mcasp-audio" : for AM33xx platforms (AM33xx, TI81xx)
+       "ti,am33xx-mcasp-audio" : for AM33xx platforms (AM33xx, AM43xx, TI81xx)
+       "ti,dra7-mcasp-audio"   : for DRA7xx platforms
 
 - reg : Should contain reg specifiers for the entries in the reg-names property.
 - reg-names : Should contain:
@@ -36,7 +37,8 @@ Optional properties:
 - pinctrl-0: Should specify pin control group used for this controller.
 - pinctrl-names: Should contain only one value - "default", for more details
                 please refer to pinctrl-bindings.txt
-  
+- fck_parent : Should contain a valid clock name which will be used as parent
+              for the McASP fck
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/sound/max98090.txt b/Documentation/devicetree/bindings/sound/max98090.txt
new file mode 100644 (file)
index 0000000..e4c8b36
--- /dev/null
@@ -0,0 +1,43 @@
+MAX98090 audio CODEC
+
+This device supports I2C only.
+
+Required properties:
+
+- compatible : "maxim,max98090".
+
+- reg : The I2C address of the device.
+
+- interrupts : The CODEC's interrupt output.
+
+Pins on the device (for linking into audio routes):
+
+  * MIC1
+  * MIC2
+  * DMICL
+  * DMICR
+  * IN1
+  * IN2
+  * IN3
+  * IN4
+  * IN5
+  * IN6
+  * IN12
+  * IN34
+  * IN56
+  * HPL
+  * HPR
+  * SPKL
+  * SPKR
+  * RCVL
+  * RCVR
+  * MICBIAS
+
+Example:
+
+audio-codec@10 {
+       compatible = "maxim,max98090";
+       reg = <0x10>;
+       interrupt-parent = <&gpio>;
+       interrupts = <TEGRA_GPIO(H, 4) GPIO_ACTIVE_HIGH>;
+};
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-max98090.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-max98090.txt
new file mode 100644 (file)
index 0000000..9c7c55c
--- /dev/null
@@ -0,0 +1,51 @@
+NVIDIA Tegra audio complex, with MAX98090 CODEC
+
+Required properties:
+- compatible : "nvidia,tegra-audio-max98090"
+- clocks : Must contain an entry for each entry in clock-names.
+  See ../clocks/clock-bindings.txt for details.
+- clock-names : Must include the following entries:
+  - pll_a
+  - pll_a_out0
+  - mclk (The Tegra cdev1/extern1 clock, which feeds the CODEC's mclk)
+- nvidia,model : The user-visible name of this sound complex.
+- nvidia,audio-routing : A list of the connections between audio components.
+  Each entry is a pair of strings, the first being the connection's sink,
+  the second being the connection's source. Valid names for sources and
+  sinks are the MAX98090's pins (as documented in its binding), and the jacks
+  on the board:
+
+  * Headphones
+  * Speakers
+  * Mic Jack
+
+- nvidia,i2s-controller : The phandle of the Tegra I2S controller that's
+  connected to the CODEC.
+- nvidia,audio-codec : The phandle of the MAX98090 audio codec.
+
+Optional properties:
+- nvidia,hp-det-gpios : The GPIO that detect headphones are plugged in
+
+Example:
+
+sound {
+       compatible = "nvidia,tegra-audio-max98090-venice2",
+                    "nvidia,tegra-audio-max98090";
+       nvidia,model = "NVIDIA Tegra Venice2";
+
+       nvidia,audio-routing =
+               "Headphones", "HPR",
+               "Headphones", "HPL",
+               "Speakers", "SPKR",
+               "Speakers", "SPKL",
+               "Mic Jack", "MICBIAS",
+               "IN34", "Mic Jack";
+
+       nvidia,i2s-controller = <&tegra_i2s1>;
+       nvidia,audio-codec = <&acodec>;
+
+       clocks = <&tegra_car TEGRA124_CLK_PLL_A>,
+                <&tegra_car TEGRA124_CLK_PLL_A_OUT0>,
+                <&tegra_car TEGRA124_CLK_EXTERN1>;
+       clock-names = "pll_a", "pll_a_out0", "mclk";
+};
diff --git a/Documentation/devicetree/bindings/sound/simple-card.txt b/Documentation/devicetree/bindings/sound/simple-card.txt
new file mode 100644 (file)
index 0000000..769a346
--- /dev/null
@@ -0,0 +1,68 @@
+Simple-Card:
+
+Simple-Card specifies audio DAI connection of SoC <-> codec.
+
+Required properties:
+
+- compatible                           : "simple-audio-card"
+
+Optional properties:
+
+- simple-audio-card,format             : CPU/CODEC common audio format.
+                                       "i2s", "right_j", "left_j" , "dsp_a"
+                                       "dsp_b", "ac97", "pdm", "msb", "lsb"
+Required subnodes:
+
+- simple-audio-card,cpu                        : CPU   sub-node
+- simple-audio-card,codec              : CODEC sub-node
+
+Required CPU/CODEC subnodes properties:
+
+- sound-dai                            : phandle and port of CPU/CODEC
+
+Optional CPU/CODEC subnodes properties:
+
+- format                               : CPU/CODEC specific audio format if needed.
+                                         see simple-audio-card,format
+- frame-master                         : bool property. add this if subnode is frame master
+- bitclock-master                      : bool property. add this if subnode is bitclock master
+- bitclock-inversion                   : bool property. add this if subnode has clock inversion
+- frame-inversion                      : bool property. add this if subnode has frame inversion
+- clocks / system-clock-frequency      : specify subnode's clock if needed.
+                                         it can be specified via "clocks" if system has
+                                         clock node (= common clock), or "system-clock-frequency"
+                                         (if system doens't support common clock)
+
+Example:
+
+sound {
+       compatible = "simple-audio-card";
+       simple-audio-card,format = "left_j";
+
+       simple-audio-card,cpu {
+               sound-dai = <&sh_fsi2 0>;
+       };
+
+       simple-audio-card,codec {
+               sound-dai = <&ak4648>;
+               bitclock-master;
+               frame-master;
+               clocks = <&osc>;
+       };
+};
+
+&i2c0 {
+       ak4648: ak4648@12 {
+               #sound-dai-cells = <0>;
+               compatible = "asahi-kasei,ak4648";
+               reg = <0x12>;
+       };
+};
+
+sh_fsi2: sh_fsi2@ec230000 {
+       #sound-dai-cells = <1>;
+       compatible = "renesas,sh_fsi2";
+       reg = <0xec230000 0x400>;
+       interrupt-parent = <&gic>;
+       interrupts = <0 146 0x4>;
+};
diff --git a/Documentation/devicetree/bindings/spi/nvidia,tegra20-spi.txt b/Documentation/devicetree/bindings/spi/nvidia,tegra20-spi.txt
deleted file mode 100644 (file)
index 6b9e518..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-NVIDIA Tegra 2 SPI device
-
-Required properties:
-- compatible : should be "nvidia,tegra20-spi".
-- gpios : should specify GPIOs used for chipselect.
index 800dafe5b01b1b6cc0e6c8f4fcd6d9432c9d699f..e5a4d1b4acfe1efca8b0a41d5d736ddf8187f009 100644 (file)
@@ -67,7 +67,7 @@ only 1(SINGLE), 2(DUAL) and 4(QUAD).
 Dual/Quad mode is not allowed when 3-wire mode is used.
 
 If a gpio chipselect is used for the SPI slave the gpio number will be passed
-via the cs_gpio
+via the SPI master node cs-gpios property.
 
 SPI example for an MPC5200 SPI bus:
        spi@f00 {
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 (file)
index 0000000..6ad1adf
--- /dev/null
@@ -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;
+       };
index ce95ed1c6d3e26578eaca876aa0f7caf26fa101d..545e5b650285e71dc60f007119d0db1183abb576 100644 (file)
@@ -26,18 +26,22 @@ cortina     Cortina Systems, Inc.
 dallas Maxim Integrated Products (formerly Dallas Semiconductor)
 davicom        DAVICOM Semiconductor, Inc.
 denx   Denx Software Engineering
+dmo    Data Modul AG
 emmicro        EM Microelectronic
 epson  Seiko Epson Corp.
 est    ESTeem Wireless Modems
+eukrea  Eukréa Electromatique
 fsl    Freescale Semiconductor
 GEFanuc        GE Fanuc Intelligent Platforms Embedded Systems, Inc.
 gef    GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+gmt    Global Mixed-mode Technology, Inc.
 hisilicon      Hisilicon Limited.
 hp     Hewlett Packard
 ibm    International Business Machines (IBM)
 idt    Integrated Device Technologies, Inc.
 img    Imagination Technologies Ltd.
 intercontrol   Inter Control Group
+lg     LG Corporation
 linux  Linux-specific binding
 lsi    LSI Corp. (LSI Logic)
 marvell        Marvell Technology Group Ltd.
@@ -75,6 +79,7 @@ toshiba       Toshiba Corporation
 toumaz Toumaz
 v3     V3 Semiconductor
 via    VIA Technologies, Inc.
+voipac Voipac Technologies s.r.o.
 winbond Winbond Electronics corp.
 wlf    Wolfson Microelectronics
 wm     Wondermedia Technologies, Inc.
index 860c29a472adfc13af02641001bd03dfe04b9cb6..e9f5daccbd02e2d8e97b489faf372dbb307529d8 100644 (file)
@@ -104,7 +104,7 @@ Then from the "Message" menu item, select insert file and choose your patch.
 As an added bonus you can customise the message creation toolbar menu
 and put the "insert file" icon there.
 
-Make the the composer window wide enough so that no lines wrap. As of
+Make the composer window wide enough so that no lines wrap. As of
 KMail 1.13.5 (KDE 4.5.4), KMail will apply word wrapping when sending
 the email if the lines wrap in the composer window. Having word wrapping
 disabled in the Options menu isn't enough. Thus, if your patch has very
index 01c2db769791832b989b738d413cea2ecefcba68..b930ad08778000e43fd27c605fb50bd0f9d03d41 100644 (file)
@@ -5,11 +5,11 @@ Server support for minorversion 1 can be controlled using the
 by reading this file will contain either "+4.1" or "-4.1"
 correspondingly.
 
-Currently, server support for minorversion 1 is disabled by default.
-It can be enabled at run time by writing the string "+4.1" to
+Currently, server support for minorversion 1 is enabled by default.
+It can be disabled at run time by writing the string "-4.1" to
 the /proc/fs/nfsd/versions control file.  Note that to write this
-control file, the nfsd service must be taken down.  Use your user-mode
-nfs-utils to set this up; see rpc.nfsd(8)
+control file, the nfsd service must be taken down.  You can use rpc.nfsd
+for this; see rpc.nfsd(8).
 
 (Warning: older servers will interpret "+4.1" and "-4.1" as "+4" and
 "-4", respectively.  Therefore, code meant to work on both new and old
@@ -29,29 +29,6 @@ are still under development out of tree.
 See http://wiki.linux-nfs.org/wiki/index.php/PNFS_prototype_design
 for more information.
 
-The current implementation is intended for developers only: while it
-does support ordinary file operations on clients we have tested against
-(including the linux client), it is incomplete in ways which may limit
-features unexpectedly, cause known bugs in rare cases, or cause
-interoperability problems with future clients.  Known issues:
-
-       - gss support is questionable: currently mounts with kerberos
-         from a linux client are possible, but we aren't really
-         conformant with the spec (for example, we don't use kerberos
-         on the backchannel correctly).
-       - We do not support SSV, which provides security for shared
-         client-server state (thus preventing unauthorized tampering
-         with locks and opens, for example).  It is mandatory for
-         servers to support this, though no clients use it yet.
-
-In addition, some limitations are inherited from the current NFSv4
-implementation:
-
-       - Incomplete delegation enforcement: if a file is renamed or
-         unlinked by a local process, a client holding a delegation may
-         continue to indefinitely allow opens of the file under the old
-         name.
-
 The table below, taken from the NFSv4.1 document, lists
 the operations that are mandatory to implement (REQ), optional
 (OPT), and NFSv4.0 operations that are required not to implement (MNI)
@@ -169,6 +146,16 @@ NS*| CB_WANTS_CANCELLED      | OPT       | FDELG,      | Section 20.10 |
 
 Implementation notes:
 
+SSV:
+* The spec claims this is mandatory, but we don't actually know of any
+  implementations, so we're ignoring it for now.  The server returns
+  NFS4ERR_ENCR_ALG_UNSUPP on EXCHANGE_ID, which should be future-proof.
+
+GSS on the backchannel:
+* Again, theoretically required but not widely implemented (in
+  particular, the current Linux client doesn't request it).  We return
+  NFS4ERR_ENCR_ALG_UNSUPP on CREATE_SESSION.
+
 DELEGPURGE:
 * mandatory only for servers that support CLAIM_DELEGATE_PREV and/or
   CLAIM_DELEG_PREV_FH (which allows clients to keep delegations that
@@ -176,7 +163,6 @@ DELEGPURGE:
   now.
 
 EXCHANGE_ID:
-* only SP4_NONE state protection supported
 * implementation ids are ignored
 
 CREATE_SESSION:
diff --git a/Documentation/gpio/00-INDEX b/Documentation/gpio/00-INDEX
new file mode 100644 (file)
index 0000000..1de43ae
--- /dev/null
@@ -0,0 +1,14 @@
+00-INDEX
+       - This file
+gpio.txt
+       - Introduction to GPIOs and their kernel interfaces
+consumer.txt
+       - How to obtain and use GPIOs in a driver
+driver.txt
+       - How to write a GPIO driver
+board.txt
+       - How to assign GPIOs to a consumer device and a function
+sysfs.txt
+       - Information about the GPIO sysfs interface
+gpio-legacy.txt
+       - Historical documentation of the deprecated GPIO integer interface
index c263740f0cba83b5c3f17e95ecae83326da06458..0f5bba9aa02d47f49e8773623e3ae2c54f6c7957 100644 (file)
@@ -2,6 +2,10 @@ Kernel driver it87
 ==================
 
 Supported chips:
+  * IT8603E
+    Prefix: 'it8603'
+    Addresses scanned: from Super I/O config space (8 I/O ports)
+    Datasheet: Not publicly available
   * IT8705F
     Prefix: 'it87'
     Addresses scanned: from Super I/O config space (8 I/O ports)
@@ -90,7 +94,7 @@ motherboard models.
 Description
 -----------
 
-This driver implements support for the IT8705F, IT8712F, IT8716F,
+This driver implements support for the IT8603E, IT8705F, IT8712F, IT8716F,
 IT8718F, IT8720F, IT8721F, IT8726F, IT8728F, IT8758E, IT8771E, IT8772E,
 IT8782F, IT8783E/F, and SiS950 chips.
 
@@ -129,6 +133,10 @@ to userspace applications.
 The IT8728F, IT8771E, and IT8772E are considered compatible with the IT8721F,
 until a datasheet becomes available (hopefully.)
 
+The IT8603E is a custom design, hardware monitoring part is similar to
+IT8728F. It only supports 16-bit fan mode, the full speed mode of the
+fan is not supported (value 0 of pwmX_enable).
+
 Temperatures are measured in degrees Celsius. An alarm is triggered once
 when the Overtemperature Shutdown limit is crossed.
 
@@ -145,13 +153,16 @@ alarm is triggered if the voltage has crossed a programmable minimum or
 maximum limit. Note that minimum in this case always means 'closest to
 zero'; this is important for negative voltage measurements. All voltage
 inputs can measure voltages between 0 and 4.08 volts, with a resolution of
-0.016 volt (except IT8721F/IT8758E and IT8728F: 0.012 volt.) The battery
-voltage in8 does not have limit registers.
-
-On the IT8721F/IT8758E, IT8782F, and IT8783E/F, some voltage inputs are
-internal and scaled inside the chip (in7 (optional for IT8782F and IT8783E/F),
-in8 and optionally in3). The driver handles this transparently so user-space
-doesn't have to care.
+0.016 volt (except IT8603E, IT8721F/IT8758E and IT8728F: 0.012 volt.) The
+battery voltage in8 does not have limit registers.
+
+On the IT8603E, IT8721F/IT8758E, IT8782F, and IT8783E/F, some voltage inputs
+are internal and scaled inside the chip:
+* in3 (optional)
+* in7 (optional for IT8782F and IT8783E/F)
+* in8 (always)
+* in9 (relevant for IT8603E only)
+The driver handles this transparently so user-space doesn't have to care.
 
 The VID lines (IT8712F/IT8716F/IT8718F/IT8720F) encode the core voltage value:
 the voltage level your processor should work with. This is hardcoded by
index 473e43b2d588281efc95a3e5cde589e18d4eefa1..5ca78426f54c58d10e3fd0030ad51f6ccb2b5b9b 100644 (file)
@@ -38,7 +38,7 @@ maps are more efficient:
 
        void io_mapping_unmap_atomic(void *vaddr)
 
-               'vaddr' must be the the value returned by the last
+               'vaddr' must be the value returned by the last
                io_mapping_map_atomic_wc call. This unmaps the specified
                page and allows the task to sleep once again.
 
index 50680a59a2ff9a913e449a1d71ced9fab3004fe4..dcd65b14263441686dc0ebd4f74d69881366a082 100644 (file)
@@ -515,7 +515,14 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 
        cgroup_disable= [KNL] Disable a particular controller
                        Format: {name of the controller(s) to disable}
-                               {Currently supported controllers - "memory"}
+                       The effects of cgroup_disable=foo are:
+                       - foo isn't auto-mounted if you mount all cgroups in
+                         a single hierarchy
+                       - foo isn't visible as an individually mountable
+                         subsystem
+                       {Currently only "memory" controller deal with this and
+                       cut the overhead, others just disable the usage. So
+                       only cgroup_disable=memory is actually worthy}
 
        checkreqprot    [SELINUX] Set initial checkreqprot flag value.
                        Format: { "0" | "1" }
@@ -890,6 +897,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
        edd=            [EDD]
                        Format: {"off" | "on" | "skip[mbr]"}
 
+       efi=            [EFI]
+                       Format: { "old_map" }
+                       old_map [X86-64]: switch to the old ioremap-based EFI
+                       runtime services mapping. 32-bit still uses this one by
+                       default.
+
        efi_no_storage_paranoia [EFI; X86]
                        Using this parameter you can use more than 50% of
                        your efi variable storage. Use this parameter only if
@@ -1992,6 +2005,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
        noapic          [SMP,APIC] Tells the kernel to not make use of any
                        IOAPICs that may be present in the system.
 
+       nokaslr         [X86]
+                       Disable kernel base offset ASLR (Address Space
+                       Layout Randomization) if built into the kernel.
+
        noautogroup     Disable scheduler automatic task group creation.
 
        nobats          [PPC] Do not use BATs for mapping kernel lowmem
diff --git a/Documentation/kmsg/s390/zcrypt b/Documentation/kmsg/s390/zcrypt
new file mode 100644 (file)
index 0000000..7fb2087
--- /dev/null
@@ -0,0 +1,20 @@
+/*?
+ * Text: "Cryptographic device %x failed and was set offline\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: device index
+ * Description:
+ * A cryptographic device failed to process a cryptographic request.
+ * The cryptographic device driver could not correct the error and
+ * set the device offline. The application that issued the
+ * request received an indication that the request has failed.
+ * User action:
+ * Use the lszcrypt command to confirm that the cryptographic
+ * hardware is still configured to your LPAR or z/VM guest virtual
+ * machine. If the device is available to your Linux instance the
+ * command output contains a line that begins with 'card<device index>',
+ * where <device index> is the two-digit decimal number in the message text.
+ * After ensuring that the device is available, use the chzcrypt command to
+ * set it online again.
+ * If the error persists, contact your support organization.
+ */
index fbb2fcbf16b6088bdce40f16544d4eee7c48dcd9..f925666e4342bd115010b4ed095547e4235bcad8 100644 (file)
@@ -533,7 +533,7 @@ also have
       found.  The count in 'mismatch_cnt' is the number of sectors
       that were re-written, or (for 'check') would have been
       re-written.  As most raid levels work in units of pages rather
-      than sectors, this my be larger than the number of actual errors
+      than sectors, this may be larger than the number of actual errors
       by a factor of the number of sectors in a page.
 
    bitmap_set_bits
index c8c42e64e953b4cd47d23da125ac5e057d1c158d..020cccdbdd0ce9052d26b6dd4cd2bcef8dab7a4e 100644 (file)
@@ -500,7 +500,7 @@ odd-numbered bank is idle, one can see the new value of the pointer P (&B),
 but the old value of the variable B (2).
 
 
-Another example of where data dependency barriers might by required is where a
+Another example of where data dependency barriers might be required is where a
 number is read from memory and then used to calculate the index for an array
 access:
 
@@ -882,12 +882,12 @@ cache it for later use.
 
 Consider:
 
-       CPU 1                   CPU 2
+       CPU 1                   CPU 2
        ======================= =======================
-                               LOAD B
-                               DIVIDE          } Divide instructions generally
-                               DIVIDE          } take a long time to perform
-                               LOAD A
+                               LOAD B
+                               DIVIDE          } Divide instructions generally
+                               DIVIDE          } take a long time to perform
+                               LOAD A
 
 Which might appear as this:
 
@@ -910,13 +910,13 @@ Which might appear as this:
 Placing a read barrier or a data dependency barrier just before the second
 load:
 
-       CPU 1                   CPU 2
+       CPU 1                   CPU 2
        ======================= =======================
-                               LOAD B
-                               DIVIDE
-                               DIVIDE
+                               LOAD B
+                               DIVIDE
+                               DIVIDE
                                <read barrier>
-                               LOAD A
+                               LOAD A
 
 will force any value speculatively obtained to be reconsidered to an extent
 dependent on the type of barrier used.  If there was no change made to the
@@ -1887,8 +1887,8 @@ functions:
      space should suffice for PCI.
 
      [*] NOTE! attempting to load from the same location as was written to may
-        cause a malfunction - consider the 16550 Rx/Tx serial registers for
-        example.
+        cause a malfunction - consider the 16550 Rx/Tx serial registers for
+        example.
 
      Used with prefetchable I/O memory, an mmiowb() barrier may be required to
      force stores to be ordered.
@@ -1955,19 +1955,19 @@ barriers for the most part act at the interface between the CPU and its cache
                                  :
        +--------+    +--------+  :   +--------+    +-----------+
        |        |    |        |  :   |        |    |           |    +--------+
-       |  CPU   |    | Memory |  :   | CPU    |    |           |    |        |
-       |  Core  |--->| Access |----->| Cache  |<-->|           |    |        |
+       |  CPU   |    | Memory |  :   | CPU    |    |           |    |        |
+       |  Core  |--->| Access |----->| Cache  |<-->|           |    |        |
        |        |    | Queue  |  :   |        |    |           |--->| Memory |
-       |        |    |        |  :   |        |    |           |    |        |
-       +--------+    +--------+  :   +--------+    |           |    |        |
+       |        |    |        |  :   |        |    |           |    |        |
+       +--------+    +--------+  :   +--------+    |           |    |        |
                                  :                 | Cache     |    +--------+
                                  :                 | Coherency |
                                  :                 | Mechanism |    +--------+
        +--------+    +--------+  :   +--------+    |           |    |        |
        |        |    |        |  :   |        |    |           |    |        |
        |  CPU   |    | Memory |  :   | CPU    |    |           |--->| Device |
-       |  Core  |--->| Access |----->| Cache  |<-->|           |    |        |
-       |        |    | Queue  |  :   |        |    |           |    |        |
+       |  Core  |--->| Access |----->| Cache  |<-->|           |    |        |
+       |        |    | Queue  |  :   |        |    |           |    |        |
        |        |    |        |  :   |        |    |           |    +--------+
        +--------+    +--------+  :   +--------+    +-----------+
                                  :
@@ -2090,7 +2090,7 @@ CPU's caches by some other cache event:
        p = &v;         q = p;
                        <D:request p>
        <B:modify p=&v> <D:commit p=&v>
-                       <D:read p>
+                       <D:read p>
                        x = *q;
                        <C:read *q>     Reads from v before v updated in cache
                        <C:unbusy>
@@ -2115,7 +2115,7 @@ queue before processing any further requests:
        p = &v;         q = p;
                        <D:request p>
        <B:modify p=&v> <D:commit p=&v>
-                       <D:read p>
+                       <D:read p>
                        smp_read_barrier_depends()
                        <C:unbusy>
                        <C:commit v=2>
index 0c980ad40b17be5c34a271c87c7983e112620d6b..4d17487d5ad9e5b4f10008c6b817636fcae53494 100644 (file)
@@ -313,7 +313,7 @@ static struct mic_device_desc *get_device_desc(struct mic_info *mic, int type)
        int i;
        void *dp = get_dp(mic, type);
 
-       for (i = mic_aligned_size(struct mic_bootparam); i < PAGE_SIZE;
+       for (i = sizeof(struct mic_bootparam); i < PAGE_SIZE;
                i += mic_total_desc_size(d)) {
                d = dp + i;
 
@@ -445,8 +445,8 @@ init_vr(struct mic_info *mic, int fd, int type,
                __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);
+               le32toh(vr0->info->magic), MIC_MAGIC + type);
+       assert(le32toh(vr0->info->magic) == MIC_MAGIC + type);
        if (vr1) {
                vr1->va = (struct mic_vring *)
                        &va[MIC_DEVICE_PAGE_END + vr_size];
@@ -458,8 +458,8 @@ init_vr(struct mic_info *mic, int fd, int type,
                        __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);
+                       le32toh(vr1->info->magic), MIC_MAGIC + type + 1);
+               assert(le32toh(vr1->info->magic) == MIC_MAGIC + type + 1);
        }
 done:
        return va;
@@ -520,7 +520,7 @@ 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);
+       static __u8 vnet_buf[2][MAX_NET_PKT_SIZE] __attribute__ ((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]) } },
@@ -1412,6 +1412,12 @@ mic_config(void *arg)
        }
 
        do {
+               ret = lseek(fd, 0, SEEK_SET);
+               if (ret < 0) {
+                       mpsslog("%s: Failed to seek to file start '%s': %s\n",
+                               mic->name, pathname, strerror(errno));
+                       goto close_error1;
+               }
                ret = read(fd, value, sizeof(value));
                if (ret < 0) {
                        mpsslog("%s: Failed to read sysfs entry '%s': %s\n",
diff --git a/Documentation/module-signing.txt b/Documentation/module-signing.txt
new file mode 100644 (file)
index 0000000..c34815d
--- /dev/null
@@ -0,0 +1,240 @@
+                       ==============================
+                       KERNEL MODULE SIGNING FACILITY
+                       ==============================
+
+CONTENTS
+
+ - Overview.
+ - Configuring module signing.
+ - Generating signing keys.
+ - Public keys in the kernel.
+ - Manually signing modules.
+ - Signed modules and stripping.
+ - Loading signed modules.
+ - Non-valid signatures and unsigned modules.
+ - Administering/protecting the private key.
+
+
+========
+OVERVIEW
+========
+
+The kernel module signing facility cryptographically signs modules during
+installation and then checks the signature upon loading the module.  This
+allows increased kernel security by disallowing the loading of unsigned modules
+or modules signed with an invalid key.  Module signing increases security by
+making it harder to load a malicious module into the kernel.  The module
+signature checking is done by the kernel so that it is not necessary to have
+trusted userspace bits.
+
+This facility uses X.509 ITU-T standard certificates to encode the public keys
+involved.  The signatures are not themselves encoded in any industrial standard
+type.  The facility currently only supports the RSA public key encryption
+standard (though it is pluggable and permits others to be used).  The possible
+hash algorithms that can be used are SHA-1, SHA-224, SHA-256, SHA-384, and
+SHA-512 (the algorithm is selected by data in the signature).
+
+
+==========================
+CONFIGURING MODULE SIGNING
+==========================
+
+The module signing facility is enabled by going to the "Enable Loadable Module
+Support" section of the kernel configuration and turning on
+
+       CONFIG_MODULE_SIG       "Module signature verification"
+
+This has a number of options available:
+
+ (1) "Require modules to be validly signed" (CONFIG_MODULE_SIG_FORCE)
+
+     This specifies how the kernel should deal with a module that has a
+     signature for which the key is not known or a module that is unsigned.
+
+     If this is off (ie. "permissive"), then modules for which the key is not
+     available and modules that are unsigned are permitted, but the kernel will
+     be marked as being tainted.
+
+     If this is on (ie. "restrictive"), only modules that have a valid
+     signature that can be verified by a public key in the kernel's possession
+     will be loaded.  All other modules will generate an error.
+
+     Irrespective of the setting here, if the module has a signature block that
+     cannot be parsed, it will be rejected out of hand.
+
+
+ (2) "Automatically sign all modules" (CONFIG_MODULE_SIG_ALL)
+
+     If this is on then modules will be automatically signed during the
+     modules_install phase of a build.  If this is off, then the modules must
+     be signed manually using:
+
+       scripts/sign-file
+
+
+ (3) "Which hash algorithm should modules be signed with?"
+
+     This presents a choice of which hash algorithm the installation phase will
+     sign the modules with:
+
+       CONFIG_SIG_SHA1         "Sign modules with SHA-1"
+       CONFIG_SIG_SHA224       "Sign modules with SHA-224"
+       CONFIG_SIG_SHA256       "Sign modules with SHA-256"
+       CONFIG_SIG_SHA384       "Sign modules with SHA-384"
+       CONFIG_SIG_SHA512       "Sign modules with SHA-512"
+
+     The algorithm selected here will also be built into the kernel (rather
+     than being a module) so that modules signed with that algorithm can have
+     their signatures checked without causing a dependency loop.
+
+
+=======================
+GENERATING SIGNING KEYS
+=======================
+
+Cryptographic keypairs are required to generate and check signatures.  A
+private key is used to generate a signature and the corresponding public key is
+used to check it.  The private key is only needed during the build, after which
+it can be deleted or stored securely.  The public key gets built into the
+kernel so that it can be used to check the signatures as the modules are
+loaded.
+
+Under normal conditions, the kernel build will automatically generate a new
+keypair using openssl if one does not exist in the files:
+
+       signing_key.priv
+       signing_key.x509
+
+during the building of vmlinux (the public part of the key needs to be built
+into vmlinux) using parameters in the:
+
+       x509.genkey
+
+file (which is also generated if it does not already exist).
+
+It is strongly recommended that you provide your own x509.genkey file.
+
+Most notably, in the x509.genkey file, the req_distinguished_name section
+should be altered from the default:
+
+       [ req_distinguished_name ]
+       O = Magrathea
+       CN = Glacier signing key
+       emailAddress = slartibartfast@magrathea.h2g2
+
+The generated RSA key size can also be set with:
+
+       [ req ]
+       default_bits = 4096
+
+
+It is also possible to manually generate the key private/public files using the
+x509.genkey key generation configuration file in the root node of the Linux
+kernel sources tree and the openssl command.  The following is an example to
+generate the public/private key files:
+
+       openssl req -new -nodes -utf8 -sha256 -days 36500 -batch -x509 \
+          -config x509.genkey -outform DER -out signing_key.x509 \
+          -keyout signing_key.priv
+
+
+=========================
+PUBLIC KEYS IN THE KERNEL
+=========================
+
+The kernel contains a ring of public keys that can be viewed by root.  They're
+in a keyring called ".system_keyring" that can be seen by:
+
+       [root@deneb ~]# cat /proc/keys
+       ...
+       223c7853 I------     1 perm 1f030000     0     0 keyring   .system_keyring: 1
+       302d2d52 I------     1 perm 1f010000     0     0 asymmetri Fedora kernel signing key: d69a84e6bce3d216b979e9505b3e3ef9a7118079: X509.RSA a7118079 []
+       ...
+
+Beyond the public key generated specifically for module signing, any file
+placed in the kernel source root directory or the kernel build root directory
+whose name is suffixed with ".x509" will be assumed to be an X.509 public key
+and will be added to the keyring.
+
+Further, the architecture code may take public keys from a hardware store and
+add those in also (e.g. from the UEFI key database).
+
+Finally, it is possible to add additional public keys by doing:
+
+       keyctl padd asymmetric "" [.system_keyring-ID] <[key-file]
+
+e.g.:
+
+       keyctl padd asymmetric "" 0x223c7853 <my_public_key.x509
+
+Note, however, that the kernel will only permit keys to be added to
+.system_keyring _if_ the new key's X.509 wrapper is validly signed by a key
+that is already resident in the .system_keyring at the time the key was added.
+
+
+=========================
+MANUALLY SIGNING MODULES
+=========================
+
+To manually sign a module, use the scripts/sign-file tool available in
+the Linux kernel source tree.  The script requires 4 arguments:
+
+       1.  The hash algorithm (e.g., sha512)
+       2.  The private key filename
+       3.  The public key filename
+       4.  The kernel module to be signed
+
+The following is an example to sign a kernel module:
+
+       scripts/sign-file sha512 signkey.priv \
+               signkey.x509 module.ko
+
+The hash algorithm used does not have to match the one configured, but if it
+doesn't, you should make sure that hash algorithm is either built into the
+kernel or can be loaded without requiring itself.
+
+
+============================
+SIGNED MODULES AND STRIPPING
+============================
+
+A signed module has a digital signature simply appended at the end.  The string
+"~Module signature appended~." at the end of the module's file confirms that a
+signature is present but it does not confirm that the signature is valid!
+
+Signed modules are BRITTLE as the signature is outside of the defined ELF
+container.  Thus they MAY NOT be stripped once the signature is computed and
+attached.  Note the entire module is the signed payload, including any and all
+debug information present at the time of signing.
+
+
+======================
+LOADING SIGNED MODULES
+======================
+
+Modules are loaded with insmod, modprobe, init_module() or finit_module(),
+exactly as for unsigned modules as no processing is done in userspace.  The
+signature checking is all done within the kernel.
+
+
+=========================================
+NON-VALID SIGNATURES AND UNSIGNED MODULES
+=========================================
+
+If CONFIG_MODULE_SIG_FORCE is enabled or enforcemodulesig=1 is supplied on
+the kernel command line, the kernel will only load validly signed modules
+for which it has a public key.   Otherwise, it will also load modules that are
+unsigned.   Any module for which the kernel has a key, but which proves to have
+a signature mismatch will not be permitted to load.
+
+Any module that has an unparseable signature will be rejected.
+
+
+=========================================
+ADMINISTERING/PROTECTING THE PRIVATE KEY
+=========================================
+
+Since the private key is used to sign modules, viruses and malware could use
+the private key to sign modules and compromise the operating system.  The
+private key must be either destroyed or moved to a secure location and not kept
+in the root node of the kernel source tree.
diff --git a/Documentation/mtd/nand/pxa3xx-nand.txt b/Documentation/mtd/nand/pxa3xx-nand.txt
new file mode 100644 (file)
index 0000000..840fd41
--- /dev/null
@@ -0,0 +1,113 @@
+
+About this document
+===================
+
+Some notes about Marvell's NAND controller available in PXA and Armada 370/XP
+SoC (aka NFCv1 and NFCv2), with an emphasis on the latter.
+
+NFCv2 controller background
+===========================
+
+The controller has a 2176 bytes FIFO buffer. Therefore, in order to support
+larger pages, I/O operations on 4 KiB and 8 KiB pages is done with a set of
+chunked transfers.
+
+For instance, if we choose a 2048 data chunk and set "BCH" ECC (see below)
+we'll have this layout in the pages:
+
+  ------------------------------------------------------------------------------
+  | 2048B data | 32B spare | 30B ECC || 2048B data | 32B spare | 30B ECC | ... |
+  ------------------------------------------------------------------------------
+
+The driver reads the data and spare portions independently and builds an internal
+buffer with this layout (in the 4 KiB page case):
+
+  ------------------------------------------
+  |     4096B data     |     64B spare     |
+  ------------------------------------------
+
+Also, for the READOOB command the driver disables the ECC and reads a 'spare + ECC'
+OOB, one per chunk read.
+
+  -------------------------------------------------------------------
+  |     4096B data     |  32B spare | 30B ECC | 32B spare | 30B ECC |
+  -------------------------------------------------------------------
+
+So, in order to achieve reading (for instance), we issue several READ0 commands
+(with some additional controller-specific magic) and read two chunks of 2080B
+(2048 data + 32 spare) each.
+The driver accommodates this data to expose the NAND core a contiguous buffer
+(4096 data + spare) or (4096 + spare + ECC + spare + ECC).
+
+ECC
+===
+
+The controller has built-in hardware ECC capabilities. In addition it is
+configurable between two modes: 1) Hamming, 2) BCH.
+
+Note that the actual BCH mode: BCH-4 or BCH-8 will depend on the way
+the controller is configured to transfer the data.
+
+In the BCH mode the ECC code will be calculated for each transfered chunk
+and expected to be located (when reading/programming) right after the spare
+bytes as the figure above shows.
+
+So, repeating the above scheme, a 2048B data chunk will be followed by 32B
+spare, and then the ECC controller will read/write the ECC code (30B in
+this case):
+
+  ------------------------------------
+  | 2048B data | 32B spare | 30B ECC |
+  ------------------------------------
+
+If the ECC mode is 'BCH' then the ECC is *always* 30 bytes long.
+If the ECC mode is 'Hamming' the ECC is 6 bytes long, for each 512B block.
+So in Hamming mode, a 2048B page will have a 24B ECC.
+
+Despite all of the above, the controller requires the driver to only read or
+write in multiples of 8-bytes, because the data buffer is 64-bits.
+
+OOB
+===
+
+Because of the above scheme, and because the "spare" OOB is really located in
+the middle of a page, spare OOB cannot be read or write independently of the
+data area. In other words, in order to read the OOB (aka READOOB), the entire
+page (aka READ0) has to be read.
+
+In the same sense, in order to write to the spare OOB the driver has to write
+an *entire* page.
+
+Factory bad blocks handling
+===========================
+
+Given the ECC BCH requires to layout the device's pages in a split
+data/OOB/data/OOB way, the controller has a view of the flash page that's
+different from the specified (aka the manufacturer's) view. In other words,
+
+Factory view:
+
+  -----------------------------------------------
+  |                    Data           |x  OOB   |
+  -----------------------------------------------
+
+Driver's view:
+
+  -----------------------------------------------
+  |      Data      | OOB |      Data   x  | OOB |
+  -----------------------------------------------
+
+It can be seen from the above, that the factory bad block marker must be
+searched within the 'data' region, and not in the usual OOB region.
+
+In addition, this means under regular usage the driver will write such
+position (since it belongs to the data region) and every used block is
+likely to be marked as bad.
+
+For this reason, marking the block as bad in the OOB is explicitly
+disabled by using the NAND_BBT_NO_OOB_BBM option in the driver. The rationale
+for this is that there's no point in marking a block as bad, because good
+blocks are also 'marked as bad' (in the OOB BBM sense) under normal usage.
+
+Instead, the driver relies on the bad block table alone, and should only perform
+the bad block scan on the very first time (when the device hasn't been used).
index 3c12d9a7ed00391d5c3f49ef80d7b1ae9abc40fe..12ba2cd9f03d9ca101ccd4d37ebbe928e5334e23 100644 (file)
@@ -156,6 +156,16 @@ tcp_app_win - INTEGER
        buffer. Value 0 is special, it means that nothing is reserved.
        Default: 31
 
+tcp_autocorking - BOOLEAN
+       Enable TCP auto corking :
+       When applications do consecutive small write()/sendmsg() system calls,
+       we try to coalesce these small writes as much as possible, to lower
+       total amount of sent packets. This is done if at least one prior
+       packet for the flow is waiting in Qdisc queues or device transmit
+       queue. Applications can still use TCP_CORK for optimal behavior
+       when they know how/when to uncork their sockets.
+       Default : 1
+
 tcp_available_congestion_control - STRING
        Shows the available congestion control choices that are registered.
        More congestion control algorithms may be available as modules,
index c01223628a87ae5e522b714c8a3a86edda15dea5..4288ffafba9fb878e348a37d2dd1849849d5f5d7 100644 (file)
@@ -123,6 +123,16 @@ Transmission process is similar to capture as shown below.
 [shutdown]  close() --------> destruction of the transmission socket and
                               deallocation of all associated resources.
 
+Socket creation and destruction is also straight forward, and is done
+the same way as in capturing described in the previous paragraph:
+
+ int fd = socket(PF_PACKET, mode, 0);
+
+The protocol can optionally be 0 in case we only want to transmit
+via this socket, which avoids an expensive call to packet_rcv().
+In this case, you also need to bind(2) the TX_RING with sll_protocol = 0
+set. Otherwise, htons(ETH_P_ALL) or any other protocol, for example.
+
 Binding the socket to your network interface is mandatory (with zero copy) to
 know the header size of frames used in the circular buffer.
 
@@ -942,6 +952,27 @@ int main(int argc, char **argp)
        return 0;
 }
 
+-------------------------------------------------------------------------------
++ PACKET_QDISC_BYPASS
+-------------------------------------------------------------------------------
+
+If there is a requirement to load the network with many packets in a similar
+fashion as pktgen does, you might set the following option after socket
+creation:
+
+    int one = 1;
+    setsockopt(fd, SOL_PACKET, PACKET_QDISC_BYPASS, &one, sizeof(one));
+
+This has the side-effect, that packets sent through PF_PACKET will bypass the
+kernel's qdisc layer and are forcedly pushed to the driver directly. Meaning,
+packet are not buffered, tc disciplines are ignored, increased loss can occur
+and such packets are also not visible to other PF_PACKET sockets anymore. So,
+you have been warned; generally, this can be useful for stress testing various
+components of a system.
+
+On default, PACKET_QDISC_BYPASS is disabled and needs to be explicitly enabled
+on PF_PACKET sockets.
+
 -------------------------------------------------------------------------------
 + PACKET_TIMESTAMP
 -------------------------------------------------------------------------------
index d5b1a393524533557a4286a3e1c92cbb50eddd50..ebf2707194029b5f7a44a5f5b4c1c8166e6ac816 100644 (file)
@@ -255,7 +255,8 @@ Writing a PHY driver
 
    config_init: configures PHY into a sane state after a reset.
      For instance, a Davicom PHY requires descrambling disabled.
-   probe: Does any setup needed by the driver
+   probe: Allocate phy->priv, optionally refuse to bind.
+   PHY may not have been reset or had fixups run yet.
    suspend/resume: power management
    config_aneg: Changes the speed/duplex/negotiation settings
    read_status: Reads the current speed/duplex/negotiation settings
index 9551622d0a7b845fe982076b3657ef59ef1ed6b7..356f791af5747fe4a2e1f25dea588d8b371d3d5b 100644 (file)
@@ -159,10 +159,10 @@ struct ieee80211_regdomain mydriver_jp_regdom = {
                REG_RULE(2412-20, 2484+20, 40, 6, 20, 0),
                /* IEEE 802.11a, channels 34..48 */
                REG_RULE(5170-20, 5240+20, 40, 6, 20,
-                       NL80211_RRF_PASSIVE_SCAN),
+                       NL80211_RRF_NO_IR),
                /* IEEE 802.11a, channels 52..64 */
                REG_RULE(5260-20, 5320+20, 40, 6, 20,
-                       NL80211_RRF_NO_IBSS |
+                       NL80211_RRF_NO_IR|
                        NL80211_RRF_DFS),
        }
 };
index 98097d8cb910ba9d42f25e7860bec06e61a89faa..661d3c316a17721d787a8a601f3e9c8356e957be 100644 (file)
@@ -85,7 +85,7 @@ Filled in if SOF_TIMESTAMPING_SYS_HARDWARE is set. Requires support
 by the network device and will be empty without that support.
 
 
-SIOCSHWTSTAMP:
+SIOCSHWTSTAMP, SIOCGHWTSTAMP:
 
 Hardware time stamping must also be initialized for each device driver
 that is expected to do hardware time stamping. The parameter is defined in
@@ -115,6 +115,10 @@ Only a processes with admin rights may change the configuration. User
 space is responsible to ensure that multiple processes don't interfere
 with each other and that the settings are reset.
 
+Any process can read the actual configuration by passing this
+structure to ioctl(SIOCGHWTSTAMP) in the same way.  However, this has
+not been implemented in all drivers.
+
 /* possible values for hwtstamp_config->tx_type */
 enum {
        /*
@@ -157,7 +161,8 @@ DEVICE IMPLEMENTATION
 
 A driver which supports hardware time stamping must support the
 SIOCSHWTSTAMP ioctl and update the supplied struct hwtstamp_config with
-the actual values as described in the section on SIOCSHWTSTAMP.
+the actual values as described in the section on SIOCSHWTSTAMP.  It
+should also support SIOCGHWTSTAMP.
 
 Time stamps for received packets must be stored in the skb. To get a pointer
 to the shared time stamp structure of the skb call skb_hwtstamps(). Then
index 71e81eb2e22ff57dd99a4457a9eecc503f7e7656..a380159765ce68fa03e2b5563931894fe2e933cc 100644 (file)
@@ -1 +1,2 @@
 timestamping
+hwtstamp_config
index e79973443e9fdcbe096445f4a13b102435a20ac6..d934afc8306a495134bf24559c6ecbd94178f36f 100644 (file)
@@ -2,12 +2,13 @@
 obj- := dummy.o
 
 # List of programs to build
-hostprogs-y := timestamping
+hostprogs-y := timestamping hwtstamp_config
 
 # Tell kbuild to always build the programs
 always := $(hostprogs-y)
 
 HOSTCFLAGS_timestamping.o += -I$(objtree)/usr/include
+HOSTCFLAGS_hwtstamp_config.o += -I$(objtree)/usr/include
 
 clean:
-       rm -f timestamping
+       rm -f timestamping hwtstamp_config
diff --git a/Documentation/networking/timestamping/hwtstamp_config.c b/Documentation/networking/timestamping/hwtstamp_config.c
new file mode 100644 (file)
index 0000000..e8b685a
--- /dev/null
@@ -0,0 +1,134 @@
+/* Test program for SIOC{G,S}HWTSTAMP
+ * Copyright 2013 Solarflare Communications
+ * Author: Ben Hutchings
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+
+#include <linux/if.h>
+#include <linux/net_tstamp.h>
+#include <linux/sockios.h>
+
+static int
+lookup_value(const char **names, int size, const char *name)
+{
+       int value;
+
+       for (value = 0; value < size; value++)
+               if (names[value] && strcasecmp(names[value], name) == 0)
+                       return value;
+
+       return -1;
+}
+
+static const char *
+lookup_name(const char **names, int size, int value)
+{
+       return (value >= 0 && value < size) ? names[value] : NULL;
+}
+
+static void list_names(FILE *f, const char **names, int size)
+{
+       int value;
+
+       for (value = 0; value < size; value++)
+               if (names[value])
+                       fprintf(f, "    %s\n", names[value]);
+}
+
+static const char *tx_types[] = {
+#define TX_TYPE(name) [HWTSTAMP_TX_ ## name] = #name
+       TX_TYPE(OFF),
+       TX_TYPE(ON),
+       TX_TYPE(ONESTEP_SYNC)
+#undef TX_TYPE
+};
+#define N_TX_TYPES ((int)(sizeof(tx_types) / sizeof(tx_types[0])))
+
+static const char *rx_filters[] = {
+#define RX_FILTER(name) [HWTSTAMP_FILTER_ ## name] = #name
+       RX_FILTER(NONE),
+       RX_FILTER(ALL),
+       RX_FILTER(SOME),
+       RX_FILTER(PTP_V1_L4_EVENT),
+       RX_FILTER(PTP_V1_L4_SYNC),
+       RX_FILTER(PTP_V1_L4_DELAY_REQ),
+       RX_FILTER(PTP_V2_L4_EVENT),
+       RX_FILTER(PTP_V2_L4_SYNC),
+       RX_FILTER(PTP_V2_L4_DELAY_REQ),
+       RX_FILTER(PTP_V2_L2_EVENT),
+       RX_FILTER(PTP_V2_L2_SYNC),
+       RX_FILTER(PTP_V2_L2_DELAY_REQ),
+       RX_FILTER(PTP_V2_EVENT),
+       RX_FILTER(PTP_V2_SYNC),
+       RX_FILTER(PTP_V2_DELAY_REQ),
+#undef RX_FILTER
+};
+#define N_RX_FILTERS ((int)(sizeof(rx_filters) / sizeof(rx_filters[0])))
+
+static void usage(void)
+{
+       fputs("Usage: hwtstamp_config if_name [tx_type rx_filter]\n"
+             "tx_type is any of (case-insensitive):\n",
+             stderr);
+       list_names(stderr, tx_types, N_TX_TYPES);
+       fputs("rx_filter is any of (case-insensitive):\n", stderr);
+       list_names(stderr, rx_filters, N_RX_FILTERS);
+}
+
+int main(int argc, char **argv)
+{
+       struct ifreq ifr;
+       struct hwtstamp_config config;
+       const char *name;
+       int sock;
+
+       if ((argc != 2 && argc != 4) || (strlen(argv[1]) >= IFNAMSIZ)) {
+               usage();
+               return 2;
+       }
+
+       if (argc == 4) {
+               config.flags = 0;
+               config.tx_type = lookup_value(tx_types, N_TX_TYPES, argv[2]);
+               config.rx_filter = lookup_value(rx_filters, N_RX_FILTERS, argv[3]);
+               if (config.tx_type < 0 || config.rx_filter < 0) {
+                       usage();
+                       return 2;
+               }
+       }
+
+       sock = socket(AF_INET, SOCK_DGRAM, 0);
+       if (sock < 0) {
+               perror("socket");
+               return 1;
+       }
+
+       strcpy(ifr.ifr_name, argv[1]);
+       ifr.ifr_data = (caddr_t)&config;
+
+       if (ioctl(sock, (argc == 2) ? SIOCGHWTSTAMP : SIOCSHWTSTAMP, &ifr)) {
+               perror("ioctl");
+               return 1;
+       }
+
+       printf("flags = %#x\n", config.flags);
+       name = lookup_name(tx_types, N_TX_TYPES, config.tx_type);
+       if (name)
+               printf("tx_type = %s\n", name);
+       else
+               printf("tx_type = %d\n", config.tx_type);
+       name = lookup_name(rx_filters, N_RX_FILTERS, config.rx_filter);
+       if (name)
+               printf("rx_filter = %s\n", name);
+       else
+               printf("rx_filter = %d\n", config.rx_filter);
+
+       return 0;
+}
index 03c9d9299c6b1fb55ed48f89f146d4029b323f22..f430004df73c06eb9b8a3f595899cf078360a88d 100644 (file)
@@ -71,7 +71,7 @@ To create an rfkill driver, driver's Kconfig needs to have
        depends on RFKILL || !RFKILL
 
 to ensure the driver cannot be built-in when rfkill is modular. The !RFKILL
-case allows the driver to be built when rfkill is not configured, which which
+case allows the driver to be built when rfkill is not configured, which
 case all rfkill API can still be used but will be provided by static inlines
 which compile to almost nothing.
 
index fd1cd8aae4eb584b3b963a884f477f22cd037b2d..16eb314f56cc45ce923d9354960bdf67ea4e6b98 100644 (file)
@@ -146,8 +146,8 @@ On removal:
  1) set the 'list_op_pending' word to the address of the 'lock entry'
     to be removed,
  2) remove the lock entry for this lock from the 'head' list,
2) release the futex lock, and
2) clear the 'lock_op_pending' word.
3) release the futex lock, and
4) clear the 'lock_op_pending' word.
 
 On exit, the kernel will consider the address stored in
 'list_op_pending' and the address of each 'lock word' found by walking
index a5bcd7f5c33fb4d1d818c35b2044b0382179d013..8666070d31896eeb0c54f820189b14d95bd1833d 100644 (file)
@@ -30,7 +30,7 @@ is something called unbounded priority inversion.  That is when the high
 priority process is prevented from running by a lower priority process for
 an undetermined amount of time.
 
-The classic example of unbounded priority inversion is were you have three
+The classic example of unbounded priority inversion is where you have three
 processes, let's call them processes A, B, and C, where A is the highest
 priority process, C is the lowest, and B is in between. A tries to grab a lock
 that C owns and must wait and lets C run to release the lock. But in the
index f21edb9834137ac91a9d1e6789c612ef07deb8c1..f72e0d1e0da852ac3e89e97f8bd0c22055d66608 100644 (file)
@@ -34,7 +34,7 @@ SPI slave functions are usually not interoperable between vendors
   - It may also be used to stream data in either direction (half duplex),
     or both of them at the same time (full duplex).
 
-  - Some devices may use eight bit words.  Others may different word
+  - Some devices may use eight bit words.  Others may use different word
     lengths, such as streams of 12-bit or 20-bit digital samples.
 
   - Words are usually sent with their most significant bit (MSB) first,
@@ -121,7 +121,7 @@ active.  So the master must set the clock to inactive before selecting
 a slave, and the slave can tell the chosen polarity by sampling the
 clock level when its select line goes active.  That's why many devices
 support for example both modes 0 and 3:  they don't care about polarity,
-and alway clock data in/out on rising clock edges.
+and always clock data in/out on rising clock edges.
 
 
 How do these driver programming interfaces work?
@@ -139,7 +139,7 @@ a command and then reading its response.
 
 There are two types of SPI driver, here called:
 
-  Controller drivers ... controllers may be built in to System-On-Chip
+  Controller drivers ... controllers may be built into System-On-Chip
        processors, and often support both Master and Slave roles.
        These drivers touch hardware registers and may use DMA.
        Or they can be PIO bitbangers, needing just GPIO pins.
@@ -548,7 +548,7 @@ SPI MASTER METHODS
     DEPRECATED METHODS
 
     master->transfer(struct spi_device *spi, struct spi_message *message)
-       This must not sleep. Its responsibility is arrange that the
+       This must not sleep. Its responsibility is to arrange that the
        transfer happens and its complete() callback is issued. The two
        will normally happen later, after other transfers complete, and
        if the controller is idle it will need to be kickstarted. This
index 9f5263d3152ccff97605234c8b0fe0417b160c59..c4407a41b0fc066b750ed5013db196ba3343bece 100644 (file)
@@ -116,7 +116,7 @@ The branch(es) can then be switched via:
        static_key_slow_dec(&key);
 
 Thus, 'static_key_slow_inc()' means 'make the branch true', and
-'static_key_slow_dec()' means 'make the the branch false' with appropriate
+'static_key_slow_dec()' means 'make the branch false' with appropriate
 reference counting. For example, if the key is initialized true, a
 static_key_slow_dec(), will switch the branch to false. And a subsequent
 static_key_slow_inc(), will change the branch back to true. Likewise, if the
@@ -236,7 +236,7 @@ label case adds:
 
 If we then include the padding bytes, the jump label code saves, 16 total bytes
 of instruction memory for this small function. In this case the non-jump label
-function is 80 bytes long. Thus, we have have saved 20% of the instruction
+function is 80 bytes long. Thus, we have saved 20% of the instruction
 footprint. We can in fact improve this even further, since the 5-byte no-op
 really can be a 2-byte no-op since we can reach the branch with a 2-byte jmp.
 However, we have not yet implemented optimal no-op sizes (they are currently
index f866c72291bf4ce2e29a9a6ffd1c40ac740d4bb7..a445da098bc6e5aa733cd55ca2ee8b4a5f04dc2c 100644 (file)
@@ -137,24 +137,34 @@ Code that causes unaligned access
 =================================
 
 With the above in mind, let's move onto a real life example of a function
-that can cause an unaligned memory access. The following function adapted
+that can cause an unaligned memory access. The following function taken
 from include/linux/etherdevice.h is an optimized routine to compare two
 ethernet MAC addresses for equality.
 
-unsigned int compare_ether_addr(const u8 *addr1, const u8 *addr2)
+bool ether_addr_equal(const u8 *addr1, const u8 *addr2)
 {
-       const u16 *a = (const u16 *) addr1;
-       const u16 *b = (const u16 *) addr2;
+#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+       u32 fold = ((*(const u32 *)addr1) ^ (*(const u32 *)addr2)) |
+                  ((*(const u16 *)(addr1 + 4)) ^ (*(const u16 *)(addr2 + 4)));
+
+       return fold == 0;
+#else
+       const u16 *a = (const u16 *)addr1;
+       const u16 *b = (const u16 *)addr2;
        return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) != 0;
+#endif
 }
 
-In the above function, the reference to a[0] causes 2 bytes (16 bits) to
-be read from memory starting at address addr1. Think about what would happen
-if addr1 was an odd address such as 0x10003. (Hint: it'd be an unaligned
-access.)
+In the above function, when the hardware has efficient unaligned access
+capability, there is no issue with this code.  But when the hardware isn't
+able to access memory on arbitrary boundaries, the reference to a[0] causes
+2 bytes (16 bits) to be read from memory starting at address addr1.
+
+Think about what would happen if addr1 was an odd address such as 0x10003.
+(Hint: it'd be an unaligned access.)
 
 Despite the potential unaligned access problems with the above function, it
-is included in the kernel anyway but is understood to only work on
+is included in the kernel anyway but is understood to only work normally on
 16-bit-aligned addresses. It is up to the caller to ensure this alignment or
 not use this function at all. This alignment-unsafe function is still useful
 as it is a decent optimization for the cases when you can ensure alignment,
diff --git a/Documentation/video4linux/omap4_camera.txt b/Documentation/video4linux/omap4_camera.txt
new file mode 100644 (file)
index 0000000..25d9b40
--- /dev/null
@@ -0,0 +1,60 @@
+                              OMAP4 ISS Driver
+                              ================
+
+Introduction
+------------
+
+The OMAP44XX family of chips contains the Imaging SubSystem (a.k.a. ISS),
+Which contains several components that can be categorized in 3 big groups:
+
+- Interfaces (2 Interfaces: CSI2-A & CSI2-B/CCP2)
+- ISP (Image Signal Processor)
+- SIMCOP (Still Image Coprocessor)
+
+For more information, please look in [1] for latest version of:
+       "OMAP4430 Multimedia Device Silicon Revision 2.x"
+
+As of Revision AB, the ISS is described in detail in section 8.
+
+This driver is supporting _only_ the CSI2-A/B interfaces for now.
+
+It makes use of the Media Controller framework [2], and inherited most of the
+code from OMAP3 ISP driver (found under drivers/media/platform/omap3isp/*),
+except that it doesn't need an IOMMU now for ISS buffers memory mapping.
+
+Supports usage of MMAP buffers only (for now).
+
+Tested platforms
+----------------
+
+- OMAP4430SDP, w/ ES2.1 GP & SEVM4430-CAM-V1-0 (Contains IMX060 & OV5640, in
+  which only the last one is supported, outputting YUV422 frames).
+
+- TI Blaze MDP, w/ OMAP4430 ES2.2 EMU (Contains 1 IMX060 & 2 OV5650 sensors, in
+  which only the OV5650 are supported, outputting RAW10 frames).
+
+- PandaBoard, Rev. A2, w/ OMAP4430 ES2.1 GP & OV adapter board, tested with
+  following sensors:
+  * OV5640
+  * OV5650
+
+- Tested on mainline kernel:
+
+       http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=summary
+
+  Tag: v3.3 (commit c16fa4f2ad19908a47c63d8fa436a1178438c7e7)
+
+File list
+---------
+drivers/staging/media/omap4iss/
+include/media/omap4iss.h
+
+References
+----------
+
+[1] http://focus.ti.com/general/docs/wtbu/wtbudocumentcenter.tsp?navigationId=12037&templateId=6123#62
+[2] http://lwn.net/Articles/420485/
+[3] http://www.spinics.net/lists/linux-media/msg44370.html
+--
+Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
+Copyright (C) 2012, Texas Instruments
index 1228b22e142b2c5da2f749cb7922b357209c01a0..5223479291a295e7b248661d28c14ea8a33b3eaa 100644 (file)
@@ -78,14 +78,6 @@ APICs
 
    no_timer_check Don't check the IO-APIC timer. This can work around
                 problems with incorrect timer initialization on some boards.
-
-   apicmaintimer Run time keeping from the local APIC timer instead
-                 of using the PIT/HPET interrupt for this. This is useful
-                 when the PIT/HPET interrupts are unreliable.
-
-   noapicmaintimer  Don't do time keeping using the APIC timer.
-                Useful when this option was auto selected, but doesn't work.
-
    apicpmtimer
                 Do APIC timer calibration using the pmtimer. Implies
                 apicmaintimer. Useful when your PIT timer is totally
@@ -144,11 +136,6 @@ Non Executable Mappings
   on      Enable(default)
   off     Disable
 
-SMP
-
-  additional_cpus=NUM Allow NUM more CPUs for hotplug
-                (defaults are specified by the BIOS, see Documentation/x86/x86_64/cpu-hotplug-spec)
-
 NUMA
 
   numa=off     Only set up a single NUMA node spanning all memory.
@@ -289,16 +276,6 @@ Debugging
 
   kstack=N     Print N words from the kernel stack in oops dumps.
 
-  pagefaulttrace  Dump all page faults. Only useful for extreme debugging
-               and will create a lot of output.
-
-  call_trace=[old|both|newfallback|new]
-               old: use old inexact backtracer
-               new: use new exact dwarf2 unwinder
-               both: print entries from both
-               newfallback: use new unwinder but fall back to old if it gets
-                       stuck (default)
-
 Miscellaneous
 
        nogbpages
index 881582f75c9ceb14e6eaacc48f3edecef31b3e3a..c584a51add15ad1ca8033207e46bf497abb33570 100644 (file)
@@ -28,4 +28,11 @@ reference.
 Current X86-64 implementations only support 40 bits of address space,
 but we support up to 46 bits. This expands into MBZ space in the page tables.
 
+->trampoline_pgd:
+
+We map EFI runtime services in the aforementioned PGD in the virtual
+range of 64Gb (arbitrarily set, can be raised if needed)
+
+0xffffffef00000000 - 0xffffffff00000000
+
 -Andi Kleen, Jul 2004
index d5829d14774a676e3f2ae93602756f2f2df8c4cb..90a64d52bea2f33464f86e4dc93954b2bc105f50 100644 (file)
@@ -95,8 +95,9 @@ The treatment of these regions depends on the type of Zorro space:
 -------------
 
 linux/include/linux/zorro.h
-linux/include/asm-{m68k,ppc}/zorro.h
-linux/include/linux/zorro_ids.h
+linux/include/uapi/linux/zorro.h
+linux/include/uapi/linux/zorro_ids.h
+linux/arch/m68k/include/asm/zorro.h
 linux/drivers/zorro
 /proc/bus/zorro
 
index f216db8470227446313fc15b75b8501835bd6cf4..832d606e6c03d0554990ee561e088db89396784d 100644 (file)
@@ -539,6 +539,13 @@ F: drivers/tty/serial/altera_jtaguart.c
 F:     include/linux/altera_uart.h
 F:     include/linux/altera_jtaguart.h
 
+AMD CRYPTOGRAPHIC COPROCESSOR (CCP) DRIVER
+M:     Tom Lendacky <thomas.lendacky@amd.com>
+L:     linux-crypto@vger.kernel.org
+S:     Supported
+F:     drivers/crypto/ccp/
+F:     include/linux/ccp.h
+
 AMD FAM15H PROCESSOR POWER MONITORING DRIVER
 M:     Andreas Herrmann <herrmann.der.user@googlemail.com>
 L:     lm-sensors@lm-sensors.org
@@ -1458,17 +1465,6 @@ T:       git git://github.com/kvalo/ath.git
 S:     Supported
 F:     drivers/net/wireless/ath/ath6kl/
 
-ATHEROS ATH9K WIRELESS DRIVER
-M:     "Luis R. Rodriguez" <mcgrof@qca.qualcomm.com>
-M:     Jouni Malinen <jouni@qca.qualcomm.com>
-M:     Vasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com>
-M:     Senthil Balasubramanian <senthilb@qca.qualcomm.com>
-L:     linux-wireless@vger.kernel.org
-L:     ath9k-devel@lists.ath9k.org
-W:     http://wireless.kernel.org/en/users/Drivers/ath9k
-S:     Supported
-F:     drivers/net/wireless/ath/ath9k/
-
 WILOCITY WIL6210 WIRELESS DRIVER
 M:     Vladimir Kondratiev <qca_vkondrat@qca.qualcomm.com>
 L:     linux-wireless@vger.kernel.org
@@ -1934,7 +1930,8 @@ S:        Maintained
 F:     drivers/gpio/gpio-bt8xx.c
 
 BTRFS FILE SYSTEM
-M:     Chris Mason <chris.mason@fusionio.com>
+M:     Chris Mason <clm@fb.com>
+M:     Josef Bacik <jbacik@fb.com>
 L:     linux-btrfs@vger.kernel.org
 W:     http://btrfs.wiki.kernel.org/
 Q:     http://patchwork.kernel.org/project/linux-btrfs/list/
@@ -2137,7 +2134,8 @@ S:        Maintained
 F:     Documentation/zh_CN/
 
 CHIPIDEA USB HIGH SPEED DUAL ROLE CONTROLLER
-M:     Alexander Shishkin <alexander.shishkin@linux.intel.com>
+M:     Peter Chen <Peter.Chen@freescale.com>
+T:     git://github.com/hzpeterchen/linux-usb.git
 L:     linux-usb@vger.kernel.org
 S:     Maintained
 F:     drivers/usb/chipidea/
@@ -2156,6 +2154,11 @@ M:       Nishank Trivedi <nistrive@cisco.com>
 S:     Supported
 F:     drivers/net/ethernet/cisco/enic/
 
+CISCO VIC LOW LATENCY NIC DRIVER
+M:      Upinder Malhi <umalhi@cisco.com>
+S:      Supported
+F:      drivers/infiniband/hw/usnic
+
 CIRRUS LOGIC EP93XX ETHERNET DRIVER
 M:     Hartley Sweeten <hsweeten@visionengravers.com>
 L:     netdev@vger.kernel.org
@@ -4043,12 +4046,26 @@ W:      http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi
 S:     Maintained
 F:     fs/hpfs/
 
+HSI SUBSYSTEM
+M:     Sebastian Reichel <sre@debian.org>
+S:     Maintained
+F:     Documentation/ABI/testing/sysfs-bus-hsi
+F:     drivers/hsi/
+F:     include/linux/hsi/
+F:     include/uapi/linux/hsi/
+
 HSO 3G MODEM DRIVER
 M:     Jan Dumon <j.dumon@option.com>
 W:     http://www.pharscape.org
 S:     Maintained
 F:     drivers/net/usb/hso.c
 
+HSR NETWORK PROTOCOL
+M:     Arvid Brodin <arvid.brodin@alten.se>
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     net/hsr/
+
 HTCPEN TOUCHSCREEN DRIVER
 M:     Pau Oliva Fora <pof@eslack.org>
 L:     linux-input@vger.kernel.org
@@ -4455,10 +4472,8 @@ M:       Bruce Allan <bruce.w.allan@intel.com>
 M:     Carolyn Wyborny <carolyn.wyborny@intel.com>
 M:     Don Skidmore <donald.c.skidmore@intel.com>
 M:     Greg Rose <gregory.v.rose@intel.com>
-M:     Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
 M:     Alex Duyck <alexander.h.duyck@intel.com>
 M:     John Ronciak <john.ronciak@intel.com>
-M:     Tushar Dave <tushar.n.dave@intel.com>
 L:     e1000-devel@lists.sourceforge.net
 W:     http://www.intel.com/support/feedback.htm
 W:     http://e1000.sourceforge.net/
@@ -5117,6 +5132,11 @@ F:       drivers/lguest/
 F:     include/linux/lguest*.h
 F:     tools/lguest/
 
+LIBLOCKDEP
+M:     Sasha Levin <sasha.levin@oracle.com>
+S:     Maintained
+F:     tools/lib/lockdep/
+
 LINUX FOR IBM pSERIES (RS/6000)
 M:     Paul Mackerras <paulus@au.ibm.com>
 W:     http://www.ibm.com/linux/ltc/projects/ppc
@@ -5261,7 +5281,7 @@ S:        Maintained
 F:     Documentation/lockdep*.txt
 F:     Documentation/lockstat.txt
 F:     include/linux/lockdep.h
-F:     kernel/lockdep*
+F:     kernel/locking/
 
 LOGICAL DISK MANAGER SUPPORT (LDM, Windows 2000/XP/Vista Dynamic Disks)
 M:     "Richard Russon (FlatCap)" <ldm@flatcap.org>
@@ -5973,10 +5993,10 @@ F:      drivers/nfc/
 F:     include/linux/platform_data/pn544.h
 
 NFS, SUNRPC, AND LOCKD CLIENTS
-M:     Trond Myklebust <Trond.Myklebust@netapp.com>
+M:     Trond Myklebust <trond.myklebust@primarydata.com>
 L:     linux-nfs@vger.kernel.org
 W:     http://client.linux-nfs.org
-T:     git git://git.linux-nfs.org/pub/linux/nfs-2.6.git
+T:     git git://git.linux-nfs.org/projects/trondmy/linux-nfs.git
 S:     Maintained
 F:     fs/lockd/
 F:     fs/nfs/
@@ -6228,7 +6248,7 @@ F:        drivers/i2c/busses/i2c-ocores.c
 
 OPEN FIRMWARE AND FLATTENED DEVICE TREE
 M:     Grant Likely <grant.likely@linaro.org>
-M:     Rob Herring <rob.herring@calxeda.com>
+M:     Rob Herring <robh+dt@kernel.org>
 L:     devicetree@vger.kernel.org
 W:     http://fdt.secretlab.ca
 T:     git git://git.secretlab.ca/git/linux-2.6.git
@@ -6240,11 +6260,11 @@ K:      of_get_property
 K:     of_match_table
 
 OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS
-M:     Rob Herring <rob.herring@calxeda.com>
+M:     Rob Herring <robh+dt@kernel.org>
 M:     Pawel Moll <pawel.moll@arm.com>
 M:     Mark Rutland <mark.rutland@arm.com>
-M:     Stephen Warren <swarren@wwwdotorg.org>
 M:     Ian Campbell <ijc+devicetree@hellion.org.uk>
+M:     Kumar Gala <galak@codeaurora.org>
 L:     devicetree@vger.kernel.org
 S:     Maintained
 F:     Documentation/devicetree/
@@ -6922,6 +6942,14 @@ T:       git git://linuxtv.org/anttip/media_tree.git
 S:     Maintained
 F:     drivers/media/tuners/qt1010*
 
+QUALCOMM ATHEROS ATH9K WIRELESS DRIVER
+M:     QCA ath9k Development <ath9k-devel@qca.qualcomm.com>
+L:     linux-wireless@vger.kernel.org
+L:     ath9k-devel@lists.ath9k.org
+W:     http://wireless.kernel.org/en/users/Drivers/ath9k
+S:     Supported
+F:     drivers/net/wireless/ath/ath9k/
+
 QUALCOMM ATHEROS ATH10K WIRELESS DRIVER
 M:     Kalle Valo <kvalo@qca.qualcomm.com>
 L:     ath10k@lists.infradead.org
@@ -7385,7 +7413,6 @@ S:        Maintained
 F:     kernel/sched/
 F:     include/linux/sched.h
 F:     include/uapi/linux/sched.h
-F:     kernel/wait.c
 F:     include/linux/wait.h
 
 SCORE ARCHITECTURE
@@ -8563,12 +8590,11 @@ S:      Maintained
 F:     sound/soc/codecs/twl4030*
 
 TI WILINK WIRELESS DRIVERS
-M:     Luciano Coelho <luca@coelho.fi>
 L:     linux-wireless@vger.kernel.org
 W:     http://wireless.kernel.org/en/users/Drivers/wl12xx
 W:     http://wireless.kernel.org/en/users/Drivers/wl1251
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx.git
-S:     Maintained
+S:     Orphan
 F:     drivers/net/wireless/ti/
 F:     include/linux/wl12xx.h
 
@@ -9530,7 +9556,7 @@ F:        drivers/xen/*swiotlb*
 
 XFS FILESYSTEM
 P:     Silicon Graphics Inc
-M:     Dave Chinner <dchinner@fromorbit.com>
+M:     Dave Chinner <david@fromorbit.com>
 M:     Ben Myers <bpm@sgi.com>
 M:     xfs@oss.sgi.com
 L:     xfs@oss.sgi.com
index 2c88e44a1dd4d9dbf726ab1f071db8accb805884..890392f1c7c004d8c089938025655ad3317713b6 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 13
 SUBLEVEL = 0
-EXTRAVERSION = -rc2
+EXTRAVERSION = -rc3
 NAME = One Giant Leap for Frogkind
 
 # *DOCUMENTATION*
index 2ee0c9bfd0325537a5d9299649abac4992b722f5..9063ae6553ccb7a0a220b8db667ac770627addbf 100644 (file)
@@ -8,6 +8,7 @@
 
 config ARC
        def_bool y
+       select BUILDTIME_EXTABLE_SORT
        select CLONE_BACKWARDS
        # ARC Busybox based initramfs absolutely relies on DEVTMPFS for /dev
        select DEVTMPFS if !INITRAMFS_SOURCE=""
index eefc29f08cdbe4ba0ea3f4b12d8f1234d59c0527..5d06eee43ea9a18ddd8876ac66c7c6d5fed29ec6 100644 (file)
@@ -46,14 +46,14 @@ extern int smp_ipi_irq_setup(int cpu, int irq);
  *
  * @info:              SoC SMP specific info for /proc/cpuinfo etc
  * @cpu_kick:          For Master to kickstart a cpu (optionally at a PC)
- * @ipi_send:          To send IPI to a @cpumask
- * @ips_clear:         To clear IPI received by @cpu at @irq
+ * @ipi_send:          To send IPI to a @cpu
+ * @ips_clear:         To clear IPI received at @irq
  */
 struct plat_smp_ops {
        const char      *info;
        void            (*cpu_kick)(int cpu, unsigned long pc);
-       void            (*ipi_send)(void *callmap);
-       void            (*ipi_clear)(int cpu, int irq);
+       void            (*ipi_send)(int cpu);
+       void            (*ipi_clear)(int irq);
 };
 
 /* TBD: stop exporting it for direct population by platform */
index 6f30484f34b78c5fa5052e68bbcbd3b4280a193f..68125dd766c68feeb9de6715c9d1694ed24e5491 100644 (file)
@@ -8,6 +8,9 @@
 
 /******** no-legacy-syscalls-ABI *******/
 
+#ifndef _UAPI_ASM_ARC_UNISTD_H
+#define _UAPI_ASM_ARC_UNISTD_H
+
 #define __ARCH_WANT_SYS_EXECVE
 #define __ARCH_WANT_SYS_CLONE
 #define __ARCH_WANT_SYS_VFORK
@@ -32,3 +35,5 @@ __SYSCALL(__NR_arc_gettls, sys_arc_gettls)
 /* Generic syscall (fs/filesystems.c - lost in asm-generic/unistd.h */
 #define __NR_sysfs             (__NR_arch_specific_syscall + 3)
 __SYSCALL(__NR_sysfs, sys_sysfs)
+
+#endif
index e46d81f709797a868b7cc68cc81ef71277a0f070..63177e4cb66d0d3a323b3e53081d4caaf2550ac0 100644 (file)
@@ -79,9 +79,9 @@ static int arc_pmu_cache_event(u64 config)
        cache_result    = (config >> 16) & 0xff;
        if (cache_type >= PERF_COUNT_HW_CACHE_MAX)
                return -EINVAL;
-       if (cache_type >= PERF_COUNT_HW_CACHE_OP_MAX)
+       if (cache_op >= PERF_COUNT_HW_CACHE_OP_MAX)
                return -EINVAL;
-       if (cache_type >= PERF_COUNT_HW_CACHE_RESULT_MAX)
+       if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
                return -EINVAL;
 
        ret = arc_pmu_cache_map[cache_type][cache_op][cache_result];
index c2f9ebbc38f61f819a0194fcc08de77ebdb5beb4..40859e5619f914115ba010641094aa3a3ca5a8b3 100644 (file)
@@ -197,51 +197,65 @@ int __init setup_profiling_timer(unsigned int multiplier)
 /*              Inter Processor Interrupt Handling                           */
 /*****************************************************************************/
 
-/*
- * structures for inter-processor calls
- * A Collection of single bit ipi messages
- *
- */
-
-/*
- * TODO_rajesh investigate tlb message types.
- * IPI Timer not needed because each ARC has an individual Interrupting Timer
- */
 enum ipi_msg_type {
-       IPI_NOP = 0,
+       IPI_EMPTY = 0,
        IPI_RESCHEDULE = 1,
        IPI_CALL_FUNC,
-       IPI_CPU_STOP
+       IPI_CPU_STOP,
 };
 
-struct ipi_data {
-       unsigned long bits;
-};
+/*
+ * In arches with IRQ for each msg type (above), receiver can use IRQ-id  to
+ * figure out what msg was sent. For those which don't (ARC has dedicated IPI
+ * IRQ), the msg-type needs to be conveyed via per-cpu data
+ */
 
-static DEFINE_PER_CPU(struct ipi_data, ipi_data);
+static DEFINE_PER_CPU(unsigned long, ipi_data);
 
-static void ipi_send_msg(const struct cpumask *callmap, enum ipi_msg_type msg)
+static void ipi_send_msg_one(int cpu, enum ipi_msg_type msg)
 {
+       unsigned long __percpu *ipi_data_ptr = per_cpu_ptr(&ipi_data, cpu);
+       unsigned long old, new;
        unsigned long flags;
-       unsigned int cpu;
+
+       pr_debug("%d Sending msg [%d] to %d\n", smp_processor_id(), msg, cpu);
 
        local_irq_save(flags);
 
-       for_each_cpu(cpu, callmap) {
-               struct ipi_data *ipi = &per_cpu(ipi_data, cpu);
-               set_bit(msg, &ipi->bits);
-       }
+       /*
+        * Atomically write new msg bit (in case others are writing too),
+        * and read back old value
+        */
+       do {
+               new = old = *ipi_data_ptr;
+               new |= 1U << msg;
+       } while (cmpxchg(ipi_data_ptr, old, new) != old);
 
-       /* Call the platform specific cross-CPU call function  */
-       if (plat_smp_ops.ipi_send)
-               plat_smp_ops.ipi_send((void *)callmap);
+       /*
+        * Call the platform specific IPI kick function, but avoid if possible:
+        * Only do so if there's no pending msg from other concurrent sender(s).
+        * Otherwise, recevier will see this msg as well when it takes the
+        * IPI corresponding to that msg. This is true, even if it is already in
+        * IPI handler, because !@old means it has not yet dequeued the msg(s)
+        * so @new msg can be a free-loader
+        */
+       if (plat_smp_ops.ipi_send && !old)
+               plat_smp_ops.ipi_send(cpu);
 
        local_irq_restore(flags);
 }
 
+static void ipi_send_msg(const struct cpumask *callmap, enum ipi_msg_type msg)
+{
+       unsigned int cpu;
+
+       for_each_cpu(cpu, callmap)
+               ipi_send_msg_one(cpu, msg);
+}
+
 void smp_send_reschedule(int cpu)
 {
-       ipi_send_msg(cpumask_of(cpu), IPI_RESCHEDULE);
+       ipi_send_msg_one(cpu, IPI_RESCHEDULE);
 }
 
 void smp_send_stop(void)
@@ -254,7 +268,7 @@ void smp_send_stop(void)
 
 void arch_send_call_function_single_ipi(int cpu)
 {
-       ipi_send_msg(cpumask_of(cpu), IPI_CALL_FUNC);
+       ipi_send_msg_one(cpu, IPI_CALL_FUNC);
 }
 
 void arch_send_call_function_ipi_mask(const struct cpumask *mask)
@@ -265,33 +279,29 @@ void arch_send_call_function_ipi_mask(const struct cpumask *mask)
 /*
  * ipi_cpu_stop - handle IPI from smp_send_stop()
  */
-static void ipi_cpu_stop(unsigned int cpu)
+static void ipi_cpu_stop(void)
 {
        machine_halt();
 }
 
-static inline void __do_IPI(unsigned long *ops, struct ipi_data *ipi, int cpu)
+static inline void __do_IPI(unsigned long msg)
 {
-       unsigned long msg = 0;
+       switch (msg) {
+       case IPI_RESCHEDULE:
+               scheduler_ipi();
+               break;
 
-       do {
-               msg = find_next_bit(ops, BITS_PER_LONG, msg+1);
+       case IPI_CALL_FUNC:
+               generic_smp_call_function_interrupt();
+               break;
 
-               switch (msg) {
-               case IPI_RESCHEDULE:
-                       scheduler_ipi();
-                       break;
-
-               case IPI_CALL_FUNC:
-                       generic_smp_call_function_interrupt();
-                       break;
-
-               case IPI_CPU_STOP:
-                       ipi_cpu_stop(cpu);
-                       break;
-               }
-       } while (msg < BITS_PER_LONG);
+       case IPI_CPU_STOP:
+               ipi_cpu_stop();
+               break;
 
+       default:
+               pr_warn("IPI with unexpected msg %ld\n", msg);
+       }
 }
 
 /*
@@ -300,19 +310,25 @@ static inline void __do_IPI(unsigned long *ops, struct ipi_data *ipi, int cpu)
  */
 irqreturn_t do_IPI(int irq, void *dev_id)
 {
-       int cpu = smp_processor_id();
-       struct ipi_data *ipi = &per_cpu(ipi_data, cpu);
-       unsigned long ops;
+       unsigned long pending;
+
+       pr_debug("IPI [%ld] received on cpu %d\n",
+                *this_cpu_ptr(&ipi_data), smp_processor_id());
 
        if (plat_smp_ops.ipi_clear)
-               plat_smp_ops.ipi_clear(cpu, irq);
+               plat_smp_ops.ipi_clear(irq);
 
        /*
-        * XXX: is this loop really needed
-        * And do we need to move ipi_clean inside
+        * "dequeue" the msg corresponding to this IPI (and possibly other
+        * piggybacked msg from elided IPIs: see ipi_send_msg_one() above)
         */
-       while ((ops = xchg(&ipi->bits, 0)) != 0)
-               __do_IPI(&ops, ipi, cpu);
+       pending = xchg(this_cpu_ptr(&ipi_data), 0);
+
+       do {
+               unsigned long msg = __ffs(pending);
+               __do_IPI(msg);
+               pending &= ~(1U << msg);
+       } while (pending);
 
        return IRQ_HANDLED;
 }
index 91b55349a5f8a9d82a9f59de19aaf8ee68b1a706..8a12741f5f7ab79668212259036fe0c2872bb037 100644 (file)
@@ -88,18 +88,14 @@ void iss_model_init_smp(unsigned int cpu)
        smp_ipi_irq_setup(cpu, IDU_INTERRUPT_0 + cpu);
 }
 
-static void iss_model_ipi_send(void *arg)
+static void iss_model_ipi_send(int cpu)
 {
-       struct cpumask *callmap = arg;
-       unsigned int cpu;
-
-       for_each_cpu(cpu, callmap)
-               idu_irq_assert(cpu);
+       idu_irq_assert(cpu);
 }
 
-static void iss_model_ipi_clear(int cpu, int irq)
+static void iss_model_ipi_clear(int irq)
 {
-       idu_irq_clear(IDU_INTERRUPT_0 + cpu);
+       idu_irq_clear(IDU_INTERRUPT_0 + smp_processor_id());
 }
 
 void iss_model_init_early_smp(void)
index c1f1a7eee953de4378b1f74bd4907c969f96dceb..e33c719c7fb7696ee1ee194b5f9766a82a8f8f4b 100644 (file)
@@ -644,8 +644,9 @@ config ARCH_MSM
          stack and controls some vital subsystems
          (clock and power control, etc).
 
-config ARCH_SHMOBILE
-       bool "Renesas SH-Mobile / R-Mobile"
+config ARCH_SHMOBILE_LEGACY
+       bool "Renesas ARM SoCs (non-multiplatform)"
+       select ARCH_SHMOBILE
        select ARM_PATCH_PHYS_VIRT
        select CLKDEV_LOOKUP
        select GENERIC_CLOCKEVENTS
@@ -660,7 +661,9 @@ config ARCH_SHMOBILE
        select PM_GENERIC_DOMAINS if PM
        select SPARSE_IRQ
        help
-         Support for Renesas's SH-Mobile and R-Mobile ARM platforms.
+         Support for Renesas ARM SoC platforms using a non-multiplatform
+         kernel. This includes the SH-Mobile, R-Mobile, EMMA-Mobile, R-Car
+         and RZ families.
 
 config ARCH_RPC
        bool "RiscPC"
@@ -723,11 +726,13 @@ config ARCH_S3C64XX
        bool "Samsung S3C64XX"
        select ARCH_HAS_CPUFREQ
        select ARCH_REQUIRE_GPIOLIB
+       select ARM_AMBA
        select ARM_VIC
        select CLKDEV_LOOKUP
        select CLKSRC_SAMSUNG_PWM
        select COMMON_CLK
        select CPU_V6
+       select CPU_V6K
        select GENERIC_CLOCKEVENTS
        select GPIO_SAMSUNG
        select HAVE_S3C2410_I2C if I2C
@@ -1611,7 +1616,7 @@ config HZ_FIXED
        default 200 if ARCH_EBSA110 || ARCH_S3C24XX || ARCH_S5P64X0 || \
                ARCH_S5PV210 || ARCH_EXYNOS4
        default AT91_TIMER_HZ if ARCH_AT91
-       default SHMOBILE_TIMER_HZ if ARCH_SHMOBILE
+       default SHMOBILE_TIMER_HZ if ARCH_SHMOBILE_LEGACY
        default 0
 
 choice
@@ -1796,8 +1801,8 @@ config ARCH_WANT_GENERAL_HUGETLB
 source "mm/Kconfig"
 
 config FORCE_MAX_ZONEORDER
-       int "Maximum zone order" if ARCH_SHMOBILE
-       range 11 64 if ARCH_SHMOBILE
+       int "Maximum zone order" if ARCH_SHMOBILE_LEGACY
+       range 11 64 if ARCH_SHMOBILE_LEGACY
        default "12" if SOC_AM33XX
        default "9" if SA1111
        default "11"
index 5765abf5ce84576d8de31df83d709160905d7b19..9d7e057618bd4f78a50ae356f9e7f6999e3a5018 100644 (file)
@@ -2,6 +2,18 @@ menu "Kernel hacking"
 
 source "lib/Kconfig.debug"
 
+config ARM_PTDUMP
+       bool "Export kernel pagetable layout to userspace via debugfs"
+       depends on DEBUG_KERNEL
+       select DEBUG_FS
+       ---help---
+         Say Y here if you want to show the kernel pagetable layout in a
+         debugfs file. This information is only useful for kernel developers
+         who are working in architecture specific areas of the kernel.
+         It is probably not a good idea to enable this feature in a production
+         kernel.
+         If in doubt, say "N"
+
 config STRICT_DEVMEM
        bool "Filter access to /dev/mem"
        depends on MMU
@@ -255,6 +267,13 @@ choice
                  Say Y here if you want kernel low-level debugging support
                  on i.MX35.
 
+       config DEBUG_IMX50_UART
+               bool "i.MX50 Debug UART"
+               depends on SOC_IMX50
+               help
+                 Say Y here if you want kernel low-level debugging support
+                 on i.MX50.
+
        config DEBUG_IMX51_UART
                bool "i.MX51 Debug UART"
                depends on SOC_IMX51
@@ -897,6 +916,7 @@ config DEBUG_IMX_UART_PORT
                                                DEBUG_IMX21_IMX27_UART || \
                                                DEBUG_IMX31_UART || \
                                                DEBUG_IMX35_UART || \
+                                               DEBUG_IMX50_UART || \
                                                DEBUG_IMX51_UART || \
                                                DEBUG_IMX53_UART || \
                                                DEBUG_IMX6Q_UART || \
@@ -931,6 +951,7 @@ config DEBUG_LL_INCLUDE
                                 DEBUG_IMX21_IMX27_UART || \
                                 DEBUG_IMX31_UART || \
                                 DEBUG_IMX35_UART || \
+                                DEBUG_IMX50_UART || \
                                 DEBUG_IMX51_UART || \
                                 DEBUG_IMX53_UART ||\
                                 DEBUG_IMX6Q_UART || \
@@ -1150,4 +1171,15 @@ config PID_IN_CONTEXTIDR
          additional instructions during context switch. Say Y here only if you
          are planning to use hardware trace tools with this kernel.
 
+config DEBUG_SET_MODULE_RONX
+       bool "Set loadable kernel module data as NX and text as RO"
+       depends on MODULES
+       ---help---
+         This option helps catch unintended modifications to loadable
+         kernel module's text and read-only data. It also prevents execution
+         of module data. Such protection may interfere with run-time code
+         patching and dynamic kernel tracing - and they might also protect
+         against certain classes of kernel exploits.
+         If in doubt, say "N".
+
 endmenu
index c99b1086d83dfa8c0c407bab392ff5bb12927ab5..1edf8ebd8494967d8466c79ecbb79cfcc266e3b7 100644 (file)
@@ -190,7 +190,6 @@ machine-$(CONFIG_ARCH_S5PC100)              += s5pc100
 machine-$(CONFIG_ARCH_S5PV210)         += s5pv210
 machine-$(CONFIG_ARCH_SA1100)          += sa1100
 machine-$(CONFIG_ARCH_SHMOBILE)        += shmobile
-machine-$(CONFIG_ARCH_SHMOBILE_MULTI)  += shmobile
 machine-$(CONFIG_ARCH_SIRF)            += prima2
 machine-$(CONFIG_ARCH_SOCFPGA)         += socfpga
 machine-$(CONFIG_ARCH_STI)             += sti
diff --git a/arch/arm/arm-soc-for-next-contents.txt b/arch/arm/arm-soc-for-next-contents.txt
new file mode 100644 (file)
index 0000000..808f151
--- /dev/null
@@ -0,0 +1,49 @@
+Contents of arm-soc branches contained in for-next
+
+
+next/cleanup
+       renesas/cleanup
+               git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git tags/renesas-cleanup-for-v3.14
+       mvebu/soc
+               git://git.infradead.org/linux-mvebu.git tags/mvebu-soc-3.14
+       at91/sama5-ccf
+               git://github.com/at91linux/linux-at91.git tags/at91-cleanup
+
+next/soc
+       patches
+               ARM: ep93xx: remove deprecated IRQF_DISABLED
+               ARM: ep93xx: use soc bus
+       soc/sched_clock
+               local branch: rebased onto tip/timers-core-for-linus for dependencies
+       patch
+               ARM: at91: sama5d3: add support for sama5d36 chip
+
+next/dt
+       ux500/dt
+               git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson tags/ux500-devicetree-v3.14-1
+       mvebu/dt
+               git://git.infradead.org/linux-mvebu.git tags/mvebu-dt-3.14
+       sti/dt
+               http://git.stlinux.com/devel/kernel/linux-sti.git tags/DT-for-v3.14-part-1
+       mvebu/dt-2
+               git://git.infradead.org/linux-mvebu.git tags/mvebu-dt-3.14-2            
+       patch
+               ARM: at91: sama5d3/dt: add sama5d36ek dts files (based on next/cleanup for dependencies)
+       at91/dt
+               git://github.com/at91linux/linux-at91.git tags/at91-dt
+       integrator/dt
+               git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-integrator.git tags/integrator-v3.14-1
+
+next/boards
+       renesas/defconfig
+               git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git tags/renesas-defconfig-for-v3.14
+       mvebu/defconfig
+               git://git.infradead.org/linux-mvebu.git tags/mvebu-defconfig-3.14
+       patch
+               ARM: multi_v7_defconfig: Fix STi support
+
+next/drivers
+       mvebu/drivers
+               git://git.infradead.org/linux-mvebu.git tags/mvebu-drivers-3.14
+       samsung/s3c64xx-dmaengine
+               git://git.kernel.org/pub/scm/linux/kernel/git/broonie/misc.git tags/s3c64xx-dmaengine
index e7190bb5998e149906a4763e815712953c7421f5..f54d5a25c7ee1c0b7803c94179bc5c30f7d7d66b 100644 (file)
@@ -64,7 +64,7 @@ else
 endif
 endif
 
-ifeq ($(CONFIG_ARCH_SHMOBILE),y)
+ifeq ($(CONFIG_ARCH_SHMOBILE_LEGACY),y)
 OBJS           += head-shmobile.o
 endif
 
index d57c1a65b24f981fb25c62aa58c73c1fedd84ab8..342d16d4dc847f6776a1da37150651d4a3d70d9e 100644 (file)
@@ -30,6 +30,7 @@ dtb-$(CONFIG_ARCH_AT91) += pm9g45.dtb
 dtb-$(CONFIG_ARCH_AT91) += at91sam9n12ek.dtb
 # sam9x5
 dtb-$(CONFIG_ARCH_AT91) += at91-ariag25.dtb
+dtb-$(CONFIG_ARCH_AT91) += at91-cosino_mega2560.dtb
 dtb-$(CONFIG_ARCH_AT91) += at91sam9g15ek.dtb
 dtb-$(CONFIG_ARCH_AT91) += at91sam9g25ek.dtb
 dtb-$(CONFIG_ARCH_AT91) += at91sam9g35ek.dtb
@@ -40,6 +41,8 @@ dtb-$(CONFIG_ARCH_AT91)       += sama5d31ek.dtb
 dtb-$(CONFIG_ARCH_AT91)        += sama5d33ek.dtb
 dtb-$(CONFIG_ARCH_AT91)        += sama5d34ek.dtb
 dtb-$(CONFIG_ARCH_AT91)        += sama5d35ek.dtb
+dtb-$(CONFIG_ARCH_AT91)        += sama5d36ek.dtb
+
 dtb-$(CONFIG_ARCH_ATLAS6) += atlas6-evb.dtb
 dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rpi-b.dtb
 dtb-$(CONFIG_ARCH_BCM_MOBILE) += bcm11351-brt.dtb \
@@ -90,6 +93,7 @@ dtb-$(CONFIG_ARCH_KIRKWOOD) += kirkwood-cloudbox.dtb \
        kirkwood-mplcec4.dtb \
        kirkwood-mv88f6281gtw-ge.dtb \
        kirkwood-netgear_readynas_duo_v2.dtb \
+       kirkwood-netgear_readynas_nv+_v2.dtb \
        kirkwood-ns2.dtb \
        kirkwood-ns2lite.dtb \
        kirkwood-ns2max.dtb \
@@ -114,32 +118,47 @@ dtb-$(CONFIG_ARCH_MVEBU) += armada-370-db.dtb \
        armada-xp-axpwifiap.dtb \
        armada-xp-db.dtb \
        armada-xp-gp.dtb \
+       armada-xp-netgear-rn2120.dtb \
        armada-xp-matrix.dtb \
        armada-xp-openblocks-ax3-4.dtb
 dtb-$(CONFIG_ARCH_MXC) += \
+       imx25-eukrea-mbimxsd25-baseboard.dtb \
        imx25-karo-tx25.dtb \
        imx25-pdk.dtb \
        imx27-apf27.dtb \
        imx27-apf27dev.dtb \
        imx27-pdk.dtb \
-       imx27-phytec-phycore-som.dtb \
        imx27-phytec-phycore-rdk.dtb \
        imx27-phytec-phycard-s-som.dtb \
        imx27-phytec-phycard-s-rdk.dtb \
        imx31-bug.dtb \
+       imx50-evk.dtb \
        imx51-apf51.dtb \
        imx51-apf51dev.dtb \
        imx51-babbage.dtb \
+       imx51-eukrea-mbimxsd51-baseboard.dtb \
        imx53-ard.dtb \
        imx53-evk.dtb \
        imx53-m53evk.dtb \
        imx53-mba53.dtb \
        imx53-qsb.dtb \
        imx53-smd.dtb \
+       imx53-voipac-bsb.dtb \
+       imx6dl-gw51xx.dtb \
+       imx6dl-gw52xx.dtb \
+       imx6dl-gw53xx.dtb \
+       imx6dl-gw54xx.dtb \
        imx6dl-sabreauto.dtb \
        imx6dl-sabresd.dtb \
        imx6dl-wandboard.dtb \
        imx6q-arm2.dtb \
+       imx6q-cm-fx6.dtb \
+       imx6q-dmo-edmqmx6.dtb \
+       imx6q-gw51xx.dtb \
+       imx6q-gw52xx.dtb \
+       imx6q-gw53xx.dtb \
+       imx6q-gw5400-a.dtb \
+       imx6q-gw54xx.dtb \
        imx6q-phytec-pbab01.dtb \
        imx6q-sabreauto.dtb \
        imx6q-sabrelite.dtb \
@@ -163,6 +182,9 @@ dtb-$(CONFIG_ARCH_MXS) += imx23-evk.dtb \
        imx28-cfa10056.dtb \
        imx28-cfa10057.dtb \
        imx28-cfa10058.dtb \
+       imx28-duckbill.dtb \
+       imx28-eukrea-mbmx283lc.dtb \
+       imx28-eukrea-mbmx287lc.dtb \
        imx28-evk.dtb \
        imx28-m28cu3.dtb \
        imx28-m28evk.dtb \
@@ -216,8 +238,9 @@ dtb-$(CONFIG_ARCH_U8500) += ste-snowball.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 \
+dtb-$(CONFIG_ARCH_SHMOBILE_LEGACY) += emev2-kzm9d.dtb \
        r7s72100-genmai.dtb \
+       r7s72100-genmai-reference.dtb \
        r8a7740-armadillo800eva.dtb \
        r8a7778-bockw.dtb \
        r8a7778-bockw-reference.dtb \
@@ -225,6 +248,7 @@ dtb-$(CONFIG_ARCH_SHMOBILE) += emev2-kzm9d.dtb \
        r8a7779-marzen.dtb \
        r8a7779-marzen-reference.dtb \
        r8a7791-koelsch.dtb \
+       r8a7791-koelsch-reference.dtb \
        r8a7790-lager.dtb \
        r8a7790-lager-reference.dtb \
        sh73a0-kzm9g.dtb \
@@ -232,7 +256,9 @@ dtb-$(CONFIG_ARCH_SHMOBILE) += emev2-kzm9d.dtb \
        r8a73a4-ape6evm.dtb \
        r8a73a4-ape6evm-reference.dtb \
        sh7372-mackerel.dtb
-dtb-$(CONFIG_ARCH_SHMOBILE_MULTI) += emev2-kzm9d.dtb
+dtb-$(CONFIG_ARCH_SHMOBILE_MULTI) += emev2-kzm9d.dtb \
+       r7s72100-genmai-reference.dtb \
+       r8a7791-koelsch-reference.dtb
 dtb-$(CONFIG_ARCH_SOCFPGA) += socfpga_arria5_socdk.dtb \
        socfpga_cyclone5_socdk.dtb \
        socfpga_cyclone5_sockit.dtb \
index b4f95c2bbf74696577b544fd69bd41ed94dda4a9..72a9b3fc425111ec9924fb47defeffee169672e2 100644 (file)
 / {
        model = "IGEP COM AM335x on AQUILA Expansion";
        compatible = "isee,am335x-base0033", "isee,am335x-igep0033", "ti,am33xx";
+
+       hdmi {
+               compatible = "ti,tilcdc,slave";
+               i2c = <&i2c0>;
+               pinctrl-names = "default", "off";
+               pinctrl-0 = <&nxp_hdmi_pins>;
+               pinctrl-1 = <&nxp_hdmi_off_pins>;
+               status = "okay";
+       };
+
+       leds_base {
+               pinctrl-names = "default";
+               pinctrl-0 = <&leds_base_pins>;
+
+               compatible = "gpio-leds";
+
+               led@0 {
+                       label = "base:red:user";
+                       gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>;   /* gpio1_21 */
+                       default-state = "off";
+               };
+
+               led@1 {
+                       label = "base:green:user";
+                       gpios = <&gpio2 0 GPIO_ACTIVE_HIGH>;    /* gpio2_0 */
+                       default-state = "off";
+               };
+       };
+};
+
+&am33xx_pinmux {
+       nxp_hdmi_pins: pinmux_nxp_hdmi_pins {
+               pinctrl-single,pins = <
+                       0x1b0 (PIN_OUTPUT | MUX_MODE3)  /* xdma_event_intr0.clkout1 */
+                       0xa0 (PIN_OUTPUT | MUX_MODE0)   /* lcd_data0 */
+                       0xa4 (PIN_OUTPUT | MUX_MODE0)   /* lcd_data1 */
+                       0xa8 (PIN_OUTPUT | MUX_MODE0)   /* lcd_data2 */
+                       0xac (PIN_OUTPUT | MUX_MODE0)   /* lcd_data3 */
+                       0xb0 (PIN_OUTPUT | MUX_MODE0)   /* lcd_data4 */
+                       0xb4 (PIN_OUTPUT | MUX_MODE0)   /* lcd_data5 */
+                       0xb8 (PIN_OUTPUT | MUX_MODE0)   /* lcd_data6 */
+                       0xbc (PIN_OUTPUT | MUX_MODE0)   /* lcd_data7 */
+                       0xc0 (PIN_OUTPUT | MUX_MODE0)   /* lcd_data8 */
+                       0xc4 (PIN_OUTPUT | MUX_MODE0)   /* lcd_data9 */
+                       0xc8 (PIN_OUTPUT | MUX_MODE0)   /* lcd_data10 */
+                       0xcc (PIN_OUTPUT | MUX_MODE0)   /* lcd_data11 */
+                       0xd0 (PIN_OUTPUT | MUX_MODE0)   /* lcd_data12 */
+                       0xd4 (PIN_OUTPUT | MUX_MODE0)   /* lcd_data13 */
+                       0xd8 (PIN_OUTPUT | MUX_MODE0)   /* lcd_data14 */
+                       0xdc (PIN_OUTPUT | MUX_MODE0)   /* lcd_data15 */
+                       0xe0 (PIN_OUTPUT | MUX_MODE0)   /* lcd_vsync */
+                       0xe4 (PIN_OUTPUT | MUX_MODE0)   /* lcd_hsync */
+                       0xe8 (PIN_OUTPUT | MUX_MODE0)   /* lcd_pclk */
+                       0xec (PIN_OUTPUT | MUX_MODE0)   /* lcd_ac_bias_en */
+               >;
+       };
+       nxp_hdmi_off_pins: pinmux_nxp_hdmi_off_pins {
+               pinctrl-single,pins = <
+                       0x1b0 (PIN_OUTPUT | MUX_MODE3)  /* xdma_event_intr0.clkout1 */
+               >;
+       };
+
+       leds_base_pins: pinmux_leds_base_pins {
+               pinctrl-single,pins = <
+                       0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE7)  /* gpmc_a5.gpio1_21 */
+                       0x88 (PIN_OUTPUT_PULLDOWN | MUX_MODE7)  /* gpmc_csn3.gpio2_0 */
+               >;
+       };
+};
+
+&lcdc {
+       status = "okay";
+};
+
+&i2c0 {
+       eeprom: eeprom@50 {
+               compatible = "at,24c256";
+               reg = <0x50>;
+       };
 };
index 6196244793113cfb8c0aac21dcf2259558174ed6..7063311a58d96785dd297f89b982970a59a185bb 100644 (file)
        pinctrl-0 = <&uart0_pins>;
 };
 
+&usb {
+       status = "okay";
+
+       control@44e10000 {
+               status = "okay";
+       };
+
+       usb-phy@47401300 {
+               status = "okay";
+       };
+
+       usb-phy@47401b00 {
+               status = "okay";
+       };
+
+       usb@47401000 {
+               status = "okay";
+       };
+
+       usb@47401800 {
+               status = "okay";
+               dr_mode = "host";
+       };
+
+       dma-controller@07402000  {
+               status = "okay";
+       };
+};
+
 #include "tps65910.dtsi"
 
 &tps {
index e99dfaf70052f3dd993aa93588b6e47470befee2..03fcbf0a88a8ef24565257d32be79ab75dd4aa79 100644 (file)
@@ -7,11 +7,11 @@
  */
 /dts-v1/;
 
-#include "omap34xx.dtsi"
+#include "am3517.dtsi"
 
 / {
-       model = "TI AM3517 EVM (AM3517/05)";
-       compatible = "ti,am3517-evm", "ti,omap3";
+       model = "TI AM3517 EVM (AM3517/05 TMDSEVM3517)";
+       compatible = "ti,am3517-evm", "ti,am3517", "ti,omap3";
 
        memory {
                device_type = "memory";
diff --git a/arch/arm/boot/dts/am3517.dtsi b/arch/arm/boot/dts/am3517.dtsi
new file mode 100644 (file)
index 0000000..2fbe02f
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Device Tree Source for am3517 SoC
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * 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.
+ */
+
+#include "omap3.dtsi"
+
+/ {
+       aliases {
+               serial3 = &uart4;
+       };
+
+       ocp {
+               am35x_otg_hs: am35x_otg_hs@5c040000 {
+                       compatible = "ti,omap3-musb";
+                       ti,hwmods = "am35x_otg_hs";
+                       status = "disabled";
+                       reg = <0x5c040000 0x1000>;
+                       interrupts = <71>;
+                       interrupt-names = "mc";
+               };
+
+               davinci_emac: ethernet@0x5c000000 {
+                       compatible = "ti,am3517-emac";
+                       ti,hwmods = "davinci_emac";
+                       status = "disabled";
+                       reg = <0x5c000000 0x30000>;
+                       interrupts = <67 68 69 70>;
+                       ti,davinci-ctrl-reg-offset = <0x10000>;
+                       ti,davinci-ctrl-mod-reg-offset = <0>;
+                       ti,davinci-ctrl-ram-offset = <0x20000>;
+                       ti,davinci-ctrl-ram-size = <0x2000>;
+                       ti,davinci-rmii-en = /bits/ 8 <1>;
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+               };
+
+               davinci_mdio: ethernet@0x5c030000 {
+                       compatible = "ti,davinci_mdio";
+                       ti,hwmods = "davinci_mdio";
+                       status = "disabled";
+                       reg = <0x5c030000 0x1000>;
+                       bus_freq = <1000000>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               uart4: serial@4809e000 {
+                       compatible = "ti,omap3-uart";
+                       ti,hwmods = "uart4";
+                       status = "disabled";
+                       reg = <0x4809e000 0x400>;
+                       interrupts = <84>;
+                       dmas = <&sdma 55 &sdma 54>;
+                       dma-names = "tx", "rx";
+                       clock-frequency = <48000000>;
+               };
+       };
+};
index 3a1de9eb51112f2eb0c6eb00b5b20026985800b5..3c4f6d983cbd4c32175373ad8a3d0740098f8149 100644 (file)
                        nand-on-flash-bbt;
                        status = "okay";
 
-                       at91bootstrap@0 {
-                               label = "at91bootstrap";
-                               reg = <0x0 0x8000>;
-                       };
-
-                       barebox@8000 {
+                       barebox@0 {
                                label = "barebox";
-                               reg = <0x8000 0x40000>;
-                       };
-
-                       bareboxenv@48000 {
-                               label = "bareboxenv";
-                               reg = <0x48000 0x8000>;
-                       };
-
-                       user_block@0x50000 {
-                               label = "user_block";
-                               reg = <0x50000 0xb0000>;
+                               reg = <0x0 0x58000>;
                        };
 
-                       kernel@100000 {
-                               label = "kernel";
-                               reg = <0x100000 0x1b0000>;
+                       u_boot_env@58000 {
+                               label = "u_boot_env";
+                               reg = <0x58000 0x8000>;
                        };
 
-                       root@2b0000 {
-                               label = "root";
-                               reg = <0x2b0000 0x1D50000>;
+                       ubi@60000 {
+                               label = "ubi";
+                               reg = <0x60000 0x1FA0000>;
                        };
                };
 
index 90ce29dbe119e4680b6f7b9b61d177319d8251c1..08a56bcfc7248704b34ad1789418308819b3bcbf 100644 (file)
                                        spi-max-frequency = <50000000>;
                                };
                        };
+               };
 
-                       pcie-controller {
+               pcie-controller {
+                       status = "okay";
+                       /*
+                        * The two PCIe units are accessible through
+                        * both standard PCIe slots and mini-PCIe
+                        * slots on the board.
+                        */
+                       pcie@1,0 {
+                               /* Port 0, Lane 0 */
+                               status = "okay";
+                       };
+                       pcie@2,0 {
+                               /* Port 1, Lane 0 */
                                status = "okay";
-                               /*
-                                * The two PCIe units are accessible through
-                                * both standard PCIe slots and mini-PCIe
-                                * slots on the board.
-                                */
-                               pcie@1,0 {
-                                       /* Port 0, Lane 0 */
-                                       status = "okay";
-                               };
-                               pcie@2,0 {
-                                       /* Port 1, Lane 0 */
-                                       status = "okay";
-                               };
                        };
                };
        };
index 2471d9da767bfad77a4419c20d17407473e704fb..944e8785b30833ea34ace20884c6844a7d3cfe15 100644 (file)
                                green_pwr_led {
                                        label = "mirabox:green:pwr";
                                        gpios = <&gpio1 31 1>;
-                                       linux,default-trigger = "heartbeat";
+                                       default-state = "keep";
                                };
 
                                blue_stat_led {
                                        label = "mirabox:blue:stat";
                                        gpios = <&gpio2 0 1>;
-                                       linux,default-trigger = "cpu0";
+                                       default-state = "off";
                                };
 
                                green_stat_led {
                                        reg = <0x25>;
                                };
                        };
+
+                       nand@d0000 {
+                               status = "okay";
+                               num-cs = <1>;
+                               marvell,nand-keep-config;
+                               marvell,nand-enable-arbiter;
+                               nand-on-flash-bbt;
+
+                               partition@0 {
+                                       label = "U-Boot";
+                                       reg = <0 0x400000>;
+                               };
+                               partition@400000 {
+                                       label = "Linux";
+                                       reg = <0x400000 0x400000>;
+                               };
+                               partition@800000 {
+                                       label = "Filesystem";
+                                       reg = <0x800000 0x3f800000>;
+                               };
+                       };
                };
        };
 };
index 8ac2ac1f69cc0d6f50101c815fada7c9183ce9d8..6a7383f24c7caba8e629d940c3c74ddd58c9a0d6 100644 (file)
@@ -11,6 +11,8 @@
 
 /dts-v1/;
 
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
 #include "armada-370.dtsi"
 
 / {
@@ -62,6 +64,7 @@
                                        marvell,pins = "mpp57";
                                        marvell,function = "gpio";
                                };
+
                                sata1_led_pin: sata1-led-pin {
                                        marvell,pins = "mpp15";
                                        marvell,function = "gpio";
                                        marvell,function = "gpio";
                                };
 
+                               backup_button_pin: backup-button-pin {
+                                       marvell,pins = "mpp58";
+                                       marvell,function = "gpio";
+                               };
+
+                               power_button_pin: power-button-pin {
+                                       marvell,pins = "mpp62";
+                                       marvell,function = "gpio";
+                               };
+
+                               reset_button_pin: reset-button-pin {
+                                       marvell,pins = "mpp6";
+                                       marvell,function = "gpio";
+                               };
+
                                poweroff: poweroff {
                                        marvell,pins = "mpp8";
                                        marvell,function = "gpio";
                        };
 
                        mdio {
-                               phy0: ethernet-phy@0 {
+                               phy0: ethernet-phy@0 { /* Marvell 88E1318 */
                                        reg = <0>;
                                };
                        };
                                        pwm_polarity = <0>;
                                };
                        };
+
+                       nand@d0000 {
+                               status = "okay";
+                               num-cs = <1>;
+                               marvell,nand-keep-config;
+                               marvell,nand-enable-arbiter;
+                               nand-on-flash-bbt;
+
+                               partition@0 {
+                                       label = "u-boot";
+                                       reg = <0x0000000 0x180000>;  /* 1.5MB */
+                                       read-only;
+                               };
+
+                               partition@180000 {
+                                       label = "u-boot-env";
+                                       reg = <0x180000 0x20000>;    /* 128KB */
+                                       read-only;
+                               };
+
+                               partition@200000 {
+                                       label = "uImage";
+                                       reg = <0x0200000 0x600000>;    /* 6MB */
+                               };
+
+                               partition@800000 {
+                                       label = "minirootfs";
+                                       reg = <0x0800000 0x400000>;    /* 4MB */
+                               };
+
+                               /* Last MB is for the BBT, i.e. not writable */
+                               partition@c00000 {
+                                       label = "ubifs";
+                                       reg = <0x0c00000 0x7400000>; /* 116MB */
+                               };
+                       };
                };
        };
 
        clocks {
-              #address-cells = <1>;
-              #size-cells = <0>;
-
-              g762_clk: fixedclk {
+              g762_clk: g762-oscillator {
                         compatible = "fixed-clock";
                         #clock-cells = <0>;
                         clock-frequency = <8192>;
               };
        };
 
-       gpio_leds {
+       gpio-leds {
                compatible = "gpio-leds";
-               pinctrl-0 = < &power_led_pin
-                             &sata1_led_pin
-                             &sata2_led_pin
-                             &backup_led_pin >;
+               pinctrl-0 = <&power_led_pin
+                            &sata1_led_pin
+                            &sata2_led_pin
+                            &backup_led_pin>;
                pinctrl-names = "default";
 
-               blue_power_led {
+               blue-power-led {
                        label = "rn102:blue:pwr";
-                       gpios = <&gpio1 25 1>;  /* GPIO 57 Active Low */
-                       linux,default-trigger = "heartbeat";
+                       gpios = <&gpio1 25 GPIO_ACTIVE_LOW>;
+                       default-state = "keep";
                };
 
-               green_sata1_led {
+               green-sata1-led {
                        label = "rn102:green:sata1";
-                       gpios = <&gpio0 15 1>;  /* GPIO 15 Active Low */
+                       gpios = <&gpio0 15 GPIO_ACTIVE_LOW>;
                        default-state = "on";
                };
 
-               green_sata2_led {
+               green-sata2-led {
                        label = "rn102:green:sata2";
-                       gpios = <&gpio0 14 1>;   /* GPIO 14 Active Low */
+                       gpios = <&gpio0 14 GPIO_ACTIVE_LOW>;
                        default-state = "on";
                };
 
-               green_backup_led {
+               green-backup-led {
                        label = "rn102:green:backup";
-                       gpios = <&gpio1 24 1>;   /* GPIO 56 Active Low */
+                       gpios = <&gpio1 24 GPIO_ACTIVE_LOW>;
                        default-state = "on";
                };
        };
 
-       gpio_keys {
+       gpio-keys {
                compatible = "gpio-keys";
-               #address-cells = <1>;
-               #size-cells = <0>;
+               pinctrl-0 = <&power_button_pin
+                            &reset_button_pin
+                            &backup_button_pin>;
+               pinctrl-names = "default";
 
-               button@1 {
+               power-button {
                        label = "Power Button";
-                       linux,code = <116>;     /* KEY_POWER */
-                       gpios = <&gpio1 30 0>;
+                       linux,code = <KEY_POWER>;
+                       gpios = <&gpio1 30 GPIO_ACTIVE_HIGH>;
                };
 
-               button@2 {
+               reset-button {
                        label = "Reset Button";
-                       linux,code = <0x198>;   /* KEY_RESTART */
-                       gpios = <&gpio0 6 1>;
+                       linux,code = <KEY_RESTART>;
+                       gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
                };
 
-               button@3 {
+               backup-button {
                        label = "Backup Button";
-                       linux,code = <133>;     /* KEY_COPY */
-                       gpios = <&gpio1 26 1>;
+                       linux,code = <KEY_COPY>;
+                       gpios = <&gpio1 26 GPIO_ACTIVE_LOW>;
                };
        };
 
-       gpio_poweroff {
+       gpio-poweroff {
                compatible = "gpio-poweroff";
                pinctrl-0 = <&poweroff>;
                pinctrl-names = "default";
-               gpios = <&gpio0 8 1>;
+               gpios = <&gpio0 8 GPIO_ACTIVE_LOW>;
        };
-
 };
index b0b32f5fbeb473c6a44275db69e2b27928648a58..272e2e2fc58fff00c7bb084508ed8c08fc0b3dde 100644 (file)
@@ -11,6 +11,8 @@
 
 /dts-v1/;
 
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
 #include "armada-370.dtsi"
 
 / {
                                        marvell,function = "gpio";
                                };
 
-                               backup_key_pin: backup-key-pin {
+                               backup_button_pin: backup-button-pin {
                                        marvell,pins = "mpp52";
                                        marvell,function = "gpio";
                                };
 
-                               power_key_pin: power-key-pin {
+                               power_button_pin: power-button-pin {
                                        marvell,pins = "mpp62";
                                        marvell,function = "gpio";
                                };
                                        marvell,function = "gpio";
                                };
 
-                               reset_key_pin: reset-key-pin {
+                               reset_button_pin: reset-button-pin {
                                        marvell,pins = "mpp65";
                                        marvell,function = "gpio";
                                };
                        };
 
                        mdio {
-                               phy0: ethernet-phy@0 {
+                               phy0: ethernet-phy@0 { /* Marvell 88E1318 */
                                        reg = <0>;
                                };
 
-                               phy1: ethernet-phy@1 {
+                               phy1: ethernet-phy@1 { /* Marvell 88E1318 */
                                        reg = <1>;
                                };
                        };
                                        fan_startv = <1>;
                                        pwm_polarity = <0>;
                                };
+
+                               pca9554: pca9554@23 {
+                                       compatible = "nxp,pca9554";
+                                       gpio-controller;
+                                       #gpio-cells = <2>;
+                                       reg = <0x23>;
+                               };
+                       };
+
+                       nand@d0000 {
+                               status = "okay";
+                               num-cs = <1>;
+                               marvell,nand-keep-config;
+                               marvell,nand-enable-arbiter;
+                               nand-on-flash-bbt;
+
+                               partition@0 {
+                                       label = "u-boot";
+                                       reg = <0x0000000 0x180000>;  /* 1.5MB */
+                                       read-only;
+                               };
+
+                               partition@180000 {
+                                       label = "u-boot-env";
+                                       reg = <0x180000 0x20000>;    /* 128KB */
+                                       read-only;
+                               };
+
+                               partition@200000 {
+                                       label = "uImage";
+                                       reg = <0x0200000 0x600000>;    /* 6MB */
+                               };
+
+                               partition@800000 {
+                                       label = "minirootfs";
+                                       reg = <0x0800000 0x400000>;    /* 4MB */
+                               };
+
+                               /* Last MB is for the BBT, i.e. not writable */
+                               partition@c00000 {
+                                       label = "ubifs";
+                                       reg = <0x0c00000 0x7400000>; /* 116MB */
+                               };
                        };
                };
        };
 
        clocks {
-              #address-cells = <1>;
-              #size-cells = <0>;
-
-              g762_clk: fixedclk {
+              g762_clk: g762-oscillator {
                         compatible = "fixed-clock";
                         #clock-cells = <0>;
                         clock-frequency = <8192>;
               };
        };
 
-       gpio_leds {
+       gpio-leds {
                compatible = "gpio-leds";
                pinctrl-0 = <&backup_led_pin &power_led_pin>;
                pinctrl-names = "default";
 
-               blue_backup_led {
+               blue-backup-led {
                        label = "rn104:blue:backup";
-                       gpios = <&gpio1 31 0>;   /* GPIO 63 Active High */
+                       gpios = <&gpio1 31 GPIO_ACTIVE_HIGH>;
                        default-state = "off";
                };
 
-               blue_power_led {
+               blue-power-led {
                        label = "rn104:blue:pwr";
-                       gpios = <&gpio2 0 1>;    /* GPIO 64 Active Low */
+                       gpios = <&gpio2 0 GPIO_ACTIVE_LOW>;
                        linux,default-trigger = "keep";
                };
+
+               blue-sata1-led {
+                       label = "rn104:blue:sata1";
+                       gpios = <&pca9554 0 GPIO_ACTIVE_LOW>;
+                       default-state = "off";
+               };
+
+               blue-sata2-led {
+                       label = "rn104:blue:sata2";
+                       gpios = <&pca9554 1 GPIO_ACTIVE_LOW>;
+                       default-state = "off";
+               };
+
+               blue-sata3-led {
+                       label = "rn104:blue:sata3";
+                       gpios = <&pca9554 2 GPIO_ACTIVE_LOW>;
+                       default-state = "off";
+               };
+
+               blue-sata4-led {
+                       label = "rn104:blue:sata4";
+                       gpios = <&pca9554 3 GPIO_ACTIVE_LOW>;
+                       default-state = "off";
+               };
        };
 
-       gpio_keys {
+       gpio-keys {
                compatible = "gpio-keys";
-               #address-cells = <1>;
-               #size-cells = <0>;
-               pinctrl-0 = <&backup_key_pin
-                            &power_key_pin
-                            &reset_key_pin>;
+               pinctrl-0 = <&backup_button_pin
+                            &power_button_pin
+                            &reset_button_pin>;
                pinctrl-names = "default";
 
-               button@1 {
+               backup-button {
                        label = "Backup Button";
-                       linux,code = <133>;     /* KEY_COPY */
-                       gpios = <&gpio1 20 1>;
+                       linux,code = <KEY_COPY>;
+                       gpios = <&gpio1 20 GPIO_ACTIVE_LOW>;
                };
 
-               button@2 {
+               power-button {
                        label = "Power Button";
-                       linux,code = <116>;     /* KEY_POWER */
-                       gpios = <&gpio1 30 0>;
+                       linux,code = <KEY_POWER>;
+                       gpios = <&gpio1 30 GPIO_ACTIVE_HIGH>;
                };
 
-               button@3 {
+               reset-button {
                        label = "Reset Button";
-                       linux,code = <0x198>;   /* KEY_RESTART */
-                       gpios = <&gpio2 1 1>;
+                       linux,code = <KEY_RESTART>;
+                       gpios = <&gpio2 1 GPIO_ACTIVE_LOW>;
                };
        };
 
-       gpio_poweroff {
+       gpio-poweroff {
                compatible = "gpio-poweroff";
                pinctrl-0 = <&poweroff>;
                pinctrl-names = "default";
-               gpios = <&gpio1 28 1>;
+               gpios = <&gpio1 28 GPIO_ACTIVE_LOW>;
        };
 };
index 00d6a798c705b9b04408a8d28af70cd7b7cc6868..45839e53538e9c05e4005603c586abd650a3c744 100644 (file)
 
                        coherency-fabric@20200 {
                                compatible = "marvell,coherency-fabric";
-                               reg = <0x20200 0xb0>, <0x21810 0x1c>;
+                               reg = <0x20200 0xb0>, <0x21010 0x1c>;
                        };
 
                        serial@12000 {
                                status = "disabled";
                        };
 
+                       nand@d0000 {
+                               compatible = "marvell,armada370-nand";
+                               reg = <0xd0000 0x54>;
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               interrupts = <113>;
+                               clocks = <&coredivclk 0>;
+                               status = "disabled";
+                       };
                };
        };
 
index 2298e4a910e230748dda13cb70cab55713932a10..274e2ad5f51c67114b99786c0c4356971cdec492 100644 (file)
                                        spi-max-frequency = <108000000>;
                                };
                        };
+
+                       nand@d0000 {
+                               status = "okay";
+                               num-cs = <1>;
+                               marvell,nand-keep-config;
+                               marvell,nand-enable-arbiter;
+                               nand-on-flash-bbt;
+                       };
                };
        };
 };
index 3f5e6121c730a21ae2079acff268da2be20518ef..98335fb34b7ad5a11d9f40b6564bddc161431455 100644 (file)
@@ -47,7 +47,7 @@
                /*
                 * MV78230 has 2 PCIe units Gen2.0: One unit can be
                 * configured as x4 or quad x1 lanes. One unit is
-                * x4/x1.
+                * x1 only.
                 */
                pcie-controller {
                        compatible = "marvell,armada-xp-pcie";
 
                        ranges =
                               <0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000   /* Port 0.0 registers */
-                               0x82000000 0 0x42000 MBUS_ID(0xf0, 0x01) 0x42000 0 0x00002000   /* Port 2.0 registers */
                                0x82000000 0 0x44000 MBUS_ID(0xf0, 0x01) 0x44000 0 0x00002000   /* Port 0.1 registers */
                                0x82000000 0 0x48000 MBUS_ID(0xf0, 0x01) 0x48000 0 0x00002000   /* Port 0.2 registers */
                                0x82000000 0 0x4c000 MBUS_ID(0xf0, 0x01) 0x4c000 0 0x00002000   /* Port 0.3 registers */
+                               0x82000000 0 0x80000 MBUS_ID(0xf0, 0x01) 0x80000 0 0x00002000   /* Port 1.0 registers */
                                0x82000000 0x1 0       MBUS_ID(0x04, 0xe8) 0 1 0 /* Port 0.0 MEM */
                                0x81000000 0x1 0       MBUS_ID(0x04, 0xe0) 0 1 0 /* Port 0.0 IO  */
                                0x82000000 0x2 0       MBUS_ID(0x04, 0xd8) 0 1 0 /* Port 0.1 MEM */
@@ -74,8 +74,8 @@
                                0x81000000 0x3 0       MBUS_ID(0x04, 0xb0) 0 1 0 /* Port 0.2 IO  */
                                0x82000000 0x4 0       MBUS_ID(0x04, 0x78) 0 1 0 /* Port 0.3 MEM */
                                0x81000000 0x4 0       MBUS_ID(0x04, 0x70) 0 1 0 /* Port 0.3 IO  */
-                               0x82000000 0x9 0       MBUS_ID(0x04, 0xf8) 0 1 0 /* Port 2.0 MEM */
-                               0x81000000 0x9 0       MBUS_ID(0x04, 0xf0) 0 1 0 /* Port 2.0 IO  */>;
+                               0x82000000 0x5 0       MBUS_ID(0x08, 0xe8) 0 1 0 /* Port 1.0 MEM */
+                               0x81000000 0x5 0       MBUS_ID(0x08, 0xe0) 0 1 0 /* Port 1.0 IO  */>;
 
                        pcie@1,0 {
                                device_type = "pci";
                                status = "disabled";
                        };
 
-                       pcie@9,0 {
+                       pcie@5,0 {
                                device_type = "pci";
-                               assigned-addresses = <0x82000800 0 0x42000 0 0x2000>;
-                               reg = <0x4800 0 0 0 0>;
+                               assigned-addresses = <0x82000800 0 0x80000 0 0x2000>;
+                               reg = <0x2800 0 0 0 0>;
                                #address-cells = <3>;
                                #size-cells = <2>;
                                #interrupt-cells = <1>;
-                               ranges = <0x82000000 0 0 0x82000000 0x9 0 1 0
-                                         0x81000000 0 0 0x81000000 0x9 0 1 0>;
+                               ranges = <0x82000000 0 0 0x82000000 0x5 0 1 0
+                                         0x81000000 0 0 0x81000000 0x5 0 1 0>;
                                interrupt-map-mask = <0 0 0 0>;
-                               interrupt-map = <0 0 0 0 &mpic 99>;
-                               marvell,pcie-port = <2>;
+                               interrupt-map = <0 0 0 0 &mpic 62>;
+                               marvell,pcie-port = <1>;
                                marvell,pcie-lane = <0>;
-                               clocks = <&gateclk 26>;
+                               clocks = <&gateclk 9>;
                                status = "disabled";
                        };
                };
index 3e9fd1353f895d6778972e95518850268ef6eb4e..66609684d41b59ef701530fd2076553ffc4e9b6b 100644 (file)
@@ -48,7 +48,7 @@
                /*
                 * MV78260 has 3 PCIe units Gen2.0: Two units can be
                 * configured as x4 or quad x1 lanes. One unit is
-                * x4/x1.
+                * x4 only.
                 */
                pcie-controller {
                        compatible = "marvell,armada-xp-pcie";
@@ -68,7 +68,9 @@
                                0x82000000 0 0x48000 MBUS_ID(0xf0, 0x01) 0x48000 0 0x00002000   /* Port 0.2 registers */
                                0x82000000 0 0x4c000 MBUS_ID(0xf0, 0x01) 0x4c000 0 0x00002000   /* Port 0.3 registers */
                                0x82000000 0 0x80000 MBUS_ID(0xf0, 0x01) 0x80000 0 0x00002000   /* Port 1.0 registers */
-                               0x82000000 0 0x82000 MBUS_ID(0xf0, 0x01) 0x82000 0 0x00002000   /* Port 3.0 registers */
+                               0x82000000 0 0x84000 MBUS_ID(0xf0, 0x01) 0x84000 0 0x00002000   /* Port 1.1 registers */
+                               0x82000000 0 0x88000 MBUS_ID(0xf0, 0x01) 0x88000 0 0x00002000   /* Port 1.2 registers */
+                               0x82000000 0 0x8c000 MBUS_ID(0xf0, 0x01) 0x8c000 0 0x00002000   /* Port 1.3 registers */
                                0x82000000 0x1 0     MBUS_ID(0x04, 0xe8) 0 1 0 /* Port 0.0 MEM */
                                0x81000000 0x1 0     MBUS_ID(0x04, 0xe0) 0 1 0 /* Port 0.0 IO  */
                                0x82000000 0x2 0     MBUS_ID(0x04, 0xd8) 0 1 0 /* Port 0.1 MEM */
                                0x81000000 0x3 0     MBUS_ID(0x04, 0xb0) 0 1 0 /* Port 0.2 IO  */
                                0x82000000 0x4 0     MBUS_ID(0x04, 0x78) 0 1 0 /* Port 0.3 MEM */
                                0x81000000 0x4 0     MBUS_ID(0x04, 0x70) 0 1 0 /* Port 0.3 IO  */
-                               0x82000000 0x9 0     MBUS_ID(0x08, 0xe8) 0 1 0 /* Port 1.0 MEM */
-                               0x81000000 0x9 0     MBUS_ID(0x08, 0xe0) 0 1 0 /* Port 1.0 IO  */
-                               0x82000000 0xa 0     MBUS_ID(0x08, 0xf8) 0 1 0 /* Port 3.0 MEM */
-                               0x81000000 0xa 0     MBUS_ID(0x08, 0xf0) 0 1 0 /* Port 3.0 IO  */>;
+
+                               0x82000000 0x5 0     MBUS_ID(0x08, 0xe8) 0 1 0 /* Port 1.0 MEM */
+                               0x81000000 0x5 0     MBUS_ID(0x08, 0xe0) 0 1 0 /* Port 1.0 IO  */
+                               0x82000000 0x6 0     MBUS_ID(0x08, 0xd8) 0 1 0 /* Port 1.1 MEM */
+                               0x81000000 0x6 0     MBUS_ID(0x08, 0xd0) 0 1 0 /* Port 1.1 IO  */
+                               0x82000000 0x7 0     MBUS_ID(0x08, 0xb8) 0 1 0 /* Port 1.2 MEM */
+                               0x81000000 0x7 0     MBUS_ID(0x08, 0xb0) 0 1 0 /* Port 1.2 IO  */
+                               0x82000000 0x8 0     MBUS_ID(0x08, 0x78) 0 1 0 /* Port 1.3 MEM */
+                               0x81000000 0x8 0     MBUS_ID(0x08, 0x70) 0 1 0 /* Port 1.3 IO  */
+
+                               0x82000000 0x9 0     MBUS_ID(0x04, 0xf8) 0 1 0 /* Port 2.0 MEM */
+                               0x81000000 0x9 0     MBUS_ID(0x04, 0xf0) 0 1 0 /* Port 2.0 IO  */>;
 
                        pcie@1,0 {
                                device_type = "pci";
                                #address-cells = <3>;
                                #size-cells = <2>;
                                #interrupt-cells = <1>;
-                                ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
-                                          0x81000000 0 0 0x81000000 0x2 0 1 0>;
+                               ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
+                                         0x81000000 0 0 0x81000000 0x2 0 1 0>;
                                interrupt-map-mask = <0 0 0 0>;
                                interrupt-map = <0 0 0 0 &mpic 59>;
                                marvell,pcie-port = <0>;
                                status = "disabled";
                        };
 
-                       pcie@9,0 {
+                       pcie@5,0 {
                                device_type = "pci";
-                               assigned-addresses = <0x82000800 0 0x42000 0 0x2000>;
-                               reg = <0x4800 0 0 0 0>;
+                               assigned-addresses = <0x82000800 0 0x80000 0 0x2000>;
+                               reg = <0x2800 0 0 0 0>;
                                #address-cells = <3>;
                                #size-cells = <2>;
                                #interrupt-cells = <1>;
-                               ranges = <0x82000000 0 0 0x82000000 0x9 0 1 0
-                                         0x81000000 0 0 0x81000000 0x9 0 1 0>;
+                               ranges = <0x82000000 0 0 0x82000000 0x5 0 1 0
+                                         0x81000000 0 0 0x81000000 0x5 0 1 0>;
                                interrupt-map-mask = <0 0 0 0>;
-                               interrupt-map = <0 0 0 0 &mpic 99>;
-                               marvell,pcie-port = <2>;
+                               interrupt-map = <0 0 0 0 &mpic 62>;
+                               marvell,pcie-port = <1>;
                                marvell,pcie-lane = <0>;
-                               clocks = <&gateclk 26>;
+                               clocks = <&gateclk 9>;
                                status = "disabled";
                        };
 
-                       pcie@10,0 {
+                       pcie@6,0 {
                                device_type = "pci";
-                               assigned-addresses = <0x82000800 0 0x82000 0 0x2000>;
-                               reg = <0x5000 0 0 0 0>;
+                               assigned-addresses = <0x82000800 0 0x84000 0 0x2000>;
+                               reg = <0x3000 0 0 0 0>;
                                #address-cells = <3>;
                                #size-cells = <2>;
                                #interrupt-cells = <1>;
-                               ranges = <0x82000000 0 0 0x82000000 0xa 0 1 0
-                                         0x81000000 0 0 0x81000000 0xa 0 1 0>;
+                               ranges = <0x82000000 0 0 0x82000000 0x6 0 1 0
+                                         0x81000000 0 0 0x81000000 0x6 0 1 0>;
                                interrupt-map-mask = <0 0 0 0>;
-                               interrupt-map = <0 0 0 0 &mpic 103>;
-                               marvell,pcie-port = <3>;
+                               interrupt-map = <0 0 0 0 &mpic 63>;
+                               marvell,pcie-port = <1>;
+                               marvell,pcie-lane = <1>;
+                               clocks = <&gateclk 10>;
+                               status = "disabled";
+                       };
+
+                       pcie@7,0 {
+                               device_type = "pci";
+                               assigned-addresses = <0x82000800 0 0x88000 0 0x2000>;
+                               reg = <0x3800 0 0 0 0>;
+                               #address-cells = <3>;
+                               #size-cells = <2>;
+                               #interrupt-cells = <1>;
+                               ranges = <0x82000000 0 0 0x82000000 0x7 0 1 0
+                                         0x81000000 0 0 0x81000000 0x7 0 1 0>;
+                               interrupt-map-mask = <0 0 0 0>;
+                               interrupt-map = <0 0 0 0 &mpic 64>;
+                               marvell,pcie-port = <1>;
+                               marvell,pcie-lane = <2>;
+                               clocks = <&gateclk 11>;
+                               status = "disabled";
+                       };
+
+                       pcie@8,0 {
+                               device_type = "pci";
+                               assigned-addresses = <0x82000800 0 0x8c000 0 0x2000>;
+                               reg = <0x4000 0 0 0 0>;
+                               #address-cells = <3>;
+                               #size-cells = <2>;
+                               #interrupt-cells = <1>;
+                               ranges = <0x82000000 0 0 0x82000000 0x8 0 1 0
+                                         0x81000000 0 0 0x81000000 0x8 0 1 0>;
+                               interrupt-map-mask = <0 0 0 0>;
+                               interrupt-map = <0 0 0 0 &mpic 65>;
+                               marvell,pcie-port = <1>;
+                               marvell,pcie-lane = <3>;
+                               clocks = <&gateclk 12>;
+                               status = "disabled";
+                       };
+
+                       pcie@9,0 {
+                               device_type = "pci";
+                               assigned-addresses = <0x82000800 0 0x42000 0 0x2000>;
+                               reg = <0x4800 0 0 0 0>;
+                               #address-cells = <3>;
+                               #size-cells = <2>;
+                               #interrupt-cells = <1>;
+                               ranges = <0x82000000 0 0 0x82000000 0x9 0 1 0
+                                         0x81000000 0 0 0x81000000 0x9 0 1 0>;
+                               interrupt-map-mask = <0 0 0 0>;
+                               interrupt-map = <0 0 0 0 &mpic 99>;
+                               marvell,pcie-port = <2>;
                                marvell,pcie-lane = <0>;
-                               clocks = <&gateclk 27>;
+                               clocks = <&gateclk 26>;
                                status = "disabled";
                        };
                };
diff --git a/arch/arm/boot/dts/armada-xp-netgear-rn2120.dts b/arch/arm/boot/dts/armada-xp-netgear-rn2120.dts
new file mode 100644 (file)
index 0000000..f048b4e
--- /dev/null
@@ -0,0 +1,322 @@
+/*
+ * Device Tree file for NETGEAR ReadyNAS 2120
+ *
+ * Copyright (C) 2013, Arnaud EBALARD <arno@natisbad.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.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
+#include "armada-xp-mv78230.dtsi"
+
+/ {
+       model = "NETGEAR ReadyNAS 2120";
+       compatible = "netgear,readynas-2120", "marvell,armadaxp-mv78230", "marvell,armadaxp", "marvell,armada-370-xp";
+
+       chosen {
+               bootargs = "console=ttyS0,115200 earlyprintk";
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0 0x00000000 0 0x80000000>; /* 2GB */
+       };
+
+       soc {
+               ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xd0000000 0x100000
+                         MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000>;
+
+               pcie-controller {
+                       status = "okay";
+
+                       /* Connected to first Marvell 88SE9170 SATA controller */
+                       pcie@1,0 {
+                               /* Port 0, Lane 0 */
+                               status = "okay";
+                       };
+
+                       /* Connected to second Marvell 88SE9170 SATA controller */
+                       pcie@2,0 {
+                               /* Port 0, Lane 1 */
+                               status = "okay";
+                       };
+
+                       /* Connected to Fresco Logic FL1009 USB 3.0 controller */
+                       pcie@5,0 {
+                               /* Port 1, Lane 0 */
+                               status = "okay";
+                       };
+               };
+
+               internal-regs {
+                       pinctrl {
+                               poweroff: poweroff {
+                                       marvell,pins = "mpp42";
+                                       marvell,function = "gpio";
+                               };
+
+                               power_button_pin: power-button-pin {
+                                       marvell,pins = "mpp27";
+                                       marvell,function = "gpio";
+                               };
+
+                               reset_button_pin: reset-button-pin {
+                                       marvell,pins = "mpp41";
+                                       marvell,function = "gpio";
+                               };
+
+                               sata1_led_pin: sata1-led-pin {
+                                       marvell,pins = "mpp31";
+                                       marvell,function = "gpio";
+                               };
+
+                               sata2_led_pin: sata2-led-pin {
+                                       marvell,pins = "mpp40";
+                                       marvell,function = "gpio";
+                               };
+
+                               sata3_led_pin: sata3-led-pin {
+                                       marvell,pins = "mpp44";
+                                       marvell,function = "gpio";
+                               };
+
+                               sata4_led_pin: sata4-led-pin {
+                                       marvell,pins = "mpp47";
+                                       marvell,function = "gpio";
+                               };
+
+                               sata1_power_pin: sata1-power-pin {
+                                       marvell,pins = "mpp24";
+                                       marvell,function = "gpio";
+                               };
+
+                               sata2_power_pin: sata2-power-pin {
+                                       marvell,pins = "mpp25";
+                                       marvell,function = "gpio";
+                               };
+
+                               sata3_power_pin: sata3-power-pin {
+                                       marvell,pins = "mpp26";
+                                       marvell,function = "gpio";
+                               };
+
+                               sata4_power_pin: sata4-power-pin {
+                                       marvell,pins = "mpp28";
+                                       marvell,function = "gpio";
+                               };
+
+                               sata1_pres_pin: sata1-pres-pin {
+                                       marvell,pins = "mpp32";
+                                       marvell,function = "gpio";
+                               };
+
+                               sata2_pres_pin: sata2-pres-pin {
+                                       marvell,pins = "mpp33";
+                                       marvell,function = "gpio";
+                               };
+
+                               sata3_pres_pin: sata3-pres-pin {
+                                       marvell,pins = "mpp34";
+                                       marvell,function = "gpio";
+                               };
+
+                               sata4_pres_pin: sata4-pres-pin {
+                                       marvell,pins = "mpp35";
+                                       marvell,function = "gpio";
+                               };
+
+                               err_led_pin: err-led-pin {
+                                       marvell,pins = "mpp45";
+                                       marvell,function = "gpio";
+                               };
+                       };
+
+                       serial@12000 {
+                               clocks = <&coreclk 0>;
+                               status = "okay";
+                       };
+
+                       mdio {
+                               phy0: ethernet-phy@0 { /* Marvell 88E1318 */
+                                       reg = <0>;
+                               };
+
+                               phy1: ethernet-phy@1 { /* Marvell 88E1318 */
+                                       reg = <1>;
+                               };
+                       };
+
+                       ethernet@70000 {
+                               status = "okay";
+                               phy = <&phy0>;
+                               phy-mode = "rgmii-id";
+                       };
+
+                       ethernet@74000 {
+                               status = "okay";
+                               phy = <&phy1>;
+                               phy-mode = "rgmii-id";
+                       };
+
+                       /* Front USB 2.0 port */
+                       usb@50000 {
+                               status = "okay";
+                       };
+
+                       i2c@11000 {
+                               compatible = "marvell,mv64xxx-i2c";
+                               clock-frequency = <400000>;
+                               status = "okay";
+
+                               /* Controller for rear fan #1 of 3 (Protechnic
+                                * MGT4012XB-O20, 8000RPM) near eSATA port */
+                               g762_fan1: g762@3e {
+                                       compatible = "gmt,g762";
+                                       reg = <0x3e>;
+                                       clocks = <&g762_clk>; /* input clock */
+                                       fan_gear_mode = <0>;
+                                       fan_startv = <1>;
+                                       pwm_polarity = <0>;
+                               };
+
+                               /*  Controller for rear (center) fan #2 of 3 */
+                               g762_fan2: g762@48 {
+                                       compatible = "gmt,g762";
+                                       reg = <0x48>;
+                                       clocks = <&g762_clk>; /* input clock */
+                                       fan_gear_mode = <0>;
+                                       fan_startv = <1>;
+                                       pwm_polarity = <0>;
+                               };
+
+                               /*  Controller for rear fan #3 of 3 */
+                               g762_fan3: g762@49 {
+                                       compatible = "gmt,g762";
+                                       reg = <0x49>;
+                                       clocks = <&g762_clk>; /* input clock */
+                                       fan_gear_mode = <0>;
+                                       fan_startv = <1>;
+                                       pwm_polarity = <0>;
+                               };
+
+                               /* Temperature sensor */
+                               g751: g751@4c {
+                                       compatible = "gmt,g751";
+                                       reg = <0x4c>;
+                               };
+                       };
+
+                       nand@d0000 {
+                               status = "okay";
+                               num-cs = <1>;
+                               marvell,nand-keep-config;
+                               marvell,nand-enable-arbiter;
+                               nand-on-flash-bbt;
+
+                               partition@0 {
+                                       label = "u-boot";
+                                       reg = <0x0000000 0x180000>;  /* 1.5MB */
+                                       read-only;
+                               };
+
+                               partition@180000 {
+                                       label = "u-boot-env";
+                                       reg = <0x180000 0x20000>;    /* 128KB */
+                                       read-only;
+                               };
+
+                               partition@200000 {
+                                       label = "uImage";
+                                       reg = <0x0200000 0x600000>;    /* 6MB */
+                               };
+
+                               partition@800000 {
+                                       label = "minirootfs";
+                                       reg = <0x0800000 0x400000>;    /* 4MB */
+                               };
+
+                               /* Last MB is for the BBT, i.e. not writable */
+                               partition@c00000 {
+                                       label = "ubifs";
+                                       reg = <0x0c00000 0x7400000>; /* 116MB */
+                               };
+                       };
+               };
+       };
+
+       clocks {
+              g762_clk: g762-oscillator {
+                        compatible = "fixed-clock";
+                        #clock-cells = <0>;
+                        clock-frequency = <32768>;
+              };
+       };
+
+       gpio-leds {
+               compatible = "gpio-leds";
+               pinctrl-0 = <&sata1_led_pin &sata2_led_pin &err_led_pin
+                            &sata3_led_pin &sata4_led_pin>;
+               pinctrl-names = "default";
+
+               red-sata1-led {
+                       label = "rn2120:red:sata1";
+                       gpios = <&gpio0 31 GPIO_ACTIVE_HIGH>;
+                       default-state = "off";
+               };
+
+               red-sata2-led {
+                       label = "rn2120:red:sata2";
+                       gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>;
+                       default-state = "off";
+               };
+
+               red-sata3-led {
+                       label = "rn2120:red:sata3";
+                       gpios = <&gpio1 12 GPIO_ACTIVE_HIGH>;
+                       default-state = "off";
+               };
+
+               red-sata4-led {
+                       label = "rn2120:red:sata4";
+                       gpios = <&gpio1 15 GPIO_ACTIVE_HIGH>;
+                       default-state = "off";
+               };
+
+               red-err-led {
+                       label = "rn2120:red:err";
+                       gpios = <&gpio1 13 GPIO_ACTIVE_LOW>;
+                       default-state = "off";
+               };
+       };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+               pinctrl-0 = <&power_button_pin &reset_button_pin>;
+               pinctrl-names = "default";
+
+               power-button {
+                       label = "Power Button";
+                       linux,code = <KEY_POWER>;
+                       gpios = <&gpio0 27 GPIO_ACTIVE_HIGH>;
+               };
+
+               reset-button {
+                       label = "Reset Button";
+                       linux,code = <KEY_RESTART>;
+                       gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
+               };
+       };
+
+       gpio-poweroff {
+               compatible = "gpio-poweroff";
+               pinctrl-0 = <&poweroff>;
+               pinctrl-names = "default";
+               gpios = <&gpio1 10 GPIO_ACTIVE_LOW>;
+       };
+};
index 5695afcc04bf1a7fa7fa13024acd8bb794464ed5..99bcf76e6953d3e0af3e72fe6372cdecdfbecb1f 100644 (file)
                                green_led {
                                        label = "green_led";
                                        gpios = <&gpio1 21 1>;
-                                       default-state = "off";
-                                       linux,default-trigger = "heartbeat";
+                                       default-state = "keep";
                                };
                        };
 
diff --git a/arch/arm/boot/dts/at91-cosino.dtsi b/arch/arm/boot/dts/at91-cosino.dtsi
new file mode 100644 (file)
index 0000000..2093c4d
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * at91-cosino.dtsi - Device Tree file for Cosino core module
+ *
+ * Copyright (C) 2013 - Rodolfo Giometti <giometti@linux.it>
+ *                     HCE Engineering
+ *
+ * Derived from at91sam9x5ek.dtsi by:
+ *     Copyright (C) 2012 Atmel,
+ *     2012 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include "at91sam9g35.dtsi"
+
+/ {
+       model = "HCE Cosino core module";
+       compatible = "hce,cosino", "atmel,at91sam9x5", "atmel,at91sam9";
+
+       chosen {
+               bootargs = "console=ttyS0,115200 root=/dev/mmcblk0p2 rw rootfstype=ext3 rootwait";
+       };
+
+       memory {
+               reg = <0x20000000 0x8000000>;
+       };
+
+       clocks {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               main_clock: clock@0 {
+                       compatible = "atmel,osc", "fixed-clock";
+                       clock-frequency = <12000000>;
+               };
+       };
+
+       ahb {
+               apb {
+                       mmc0: mmc@f0008000 {
+                               pinctrl-0 = <
+                                       &pinctrl_board_mmc0
+                                       &pinctrl_mmc0_slot0_clk_cmd_dat0
+                                       &pinctrl_mmc0_slot0_dat1_3>;
+                               status = "okay";
+                               slot@0 {
+                                       reg = <0>;
+                                       bus-width = <4>;
+                                       cd-gpios = <&pioD 15 GPIO_ACTIVE_HIGH>;
+                               };
+                       };
+
+                       dbgu: serial@fffff200 {
+                               status = "okay";
+                       };
+
+                       usart0: serial@f801c000 {
+                               status = "okay";
+                       };
+
+                       i2c0: i2c@f8010000 {
+                               status = "okay";
+                       };
+
+                       adc0: adc@f804c000 {
+                               atmel,adc-clock-rate = <1000000>;
+                               atmel,adc-ts-wires = <4>;
+                               atmel,adc-ts-pressure-threshold = <10000>;
+                               status = "okay";
+                       };
+
+                       pinctrl@fffff400 {
+                               mmc0 {
+                                       pinctrl_board_mmc0: mmc0-board {
+                                               atmel,pins =
+                                                       <AT91_PIOD 15 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH>;  /* PD15 gpio CD pin pull up and deglitch */
+                                       };
+                               };
+                       };
+
+                       watchdog@fffffe40 {
+                               status = "okay";
+                       };
+               };
+
+               nand0: nand@40000000 {
+                       nand-bus-width = <8>;
+                       nand-ecc-mode = "hw";
+                       atmel,has-pmecc;        /* Enable PMECC */
+                       atmel,pmecc-cap = <4>;
+                       atmel,pmecc-sector-size = <512>;
+                       nand-on-flash-bbt;
+                       status = "okay";
+
+                       at91bootstrap@0 {
+                               label = "at91bootstrap";
+                               reg = <0x0 0x40000>;
+                       };
+
+                       uboot@40000 {
+                               label = "u-boot";
+                               reg = <0x40000 0x80000>;
+                       };
+
+                       ubootenv@c0000 {
+                               label = "U-Boot Env";
+                               reg = <0xc0000 0x140000>;
+                       };
+
+                       kernel@200000 {
+                               label = "kernel";
+                               reg = <0x200000 0x600000>;
+                       };
+
+                       rootfs@800000 {
+                               label = "rootfs";
+                               reg = <0x800000 0x0f800000>;
+                       };
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/at91-cosino_mega2560.dts b/arch/arm/boot/dts/at91-cosino_mega2560.dts
new file mode 100644 (file)
index 0000000..f9415dd
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * at91-cosino_mega2560.dts - Device Tree file for Cosino board with
+ *                           Mega 2560 extension
+ *
+ * Copyright (C) 2013 - Rodolfo Giometti <giometti@linux.it>
+ *                     HCE Engineering
+ *
+ * Derived from at91sam9g35ek.dts by:
+ *     Copyright (C) 2012 Atmel,
+ *      2012 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+/dts-v1/;
+#include "at91-cosino.dtsi"
+
+/ {
+       model = "HCE Cosino Mega 2560";
+       compatible = "hce,cosino_mega2560", "atmel,at91sam9x5", "atmel,at91sam9";
+
+       ahb {
+               apb {
+                       macb0: ethernet@f802c000 {
+                               phy-mode = "rmii";
+                               status = "okay";
+                       };
+
+                       adc0: adc@f804c000 {
+                               atmel,adc-clock-rate = <1000000>;
+                               atmel,adc-ts-wires = <4>;
+                               atmel,adc-ts-pressure-threshold = <10000>;
+                               status = "okay";
+                       };
+
+
+                       tsadcc: tsadcc@f804c000 {
+                               status = "okay";
+                       };
+
+                       rtc@fffffeb0 {
+                               status = "okay";
+                       };
+
+                       usart1: serial@f8020000 {
+                               status = "okay";
+                       };
+
+                       usart2: serial@f8024000 {
+                               status = "okay";
+                       };
+
+                       usb2: gadget@f803c000 {
+                               atmel,vbus-gpio = <&pioB 16 GPIO_ACTIVE_HIGH>;
+                               status = "okay";
+                       };
+
+                       mmc1: mmc@f000c000 {
+                               pinctrl-0 = <
+                                       &pinctrl_mmc1_slot0_clk_cmd_dat0
+                                       &pinctrl_mmc1_slot0_dat1_3>;
+                               status = "okay";
+                               slot@0 {
+                                       reg = <0>;
+                                       bus-width = <4>;
+                                       non-removable;
+                               };
+                       };
+               };
+
+               usb0: ohci@00600000 {
+                       status = "okay";
+                       num-ports = <3>;
+                       atmel,vbus-gpio = <0 /* &pioD 18 GPIO_ACTIVE_LOW */
+                                          &pioD 19 GPIO_ACTIVE_LOW
+                                          &pioD 20 GPIO_ACTIVE_LOW
+                                         >;
+               };
+
+               usb1: ehci@00700000 {
+                       status = "okay";
+               };
+       };
+};
index f77065506f1e63df9183ac1309a5788ed4714cb7..c61b16fba79babaa5c6e2a4dd4fb51b09e27d379 100644 (file)
                                                         AT91_PIOA 18 AT91_PERIPH_A AT91_PINCTRL_NONE>; /* PA18 periph A */
                                        };
 
-                                       pinctrl_uart0_rts: uart0_rts-0 {
+                                       pinctrl_uart0_cts: uart0_cts-0 {
                                                atmel,pins =
                                                        <AT91_PIOA 20 AT91_PERIPH_A AT91_PINCTRL_NONE>; /* PA20 periph A */
                                        };
 
-                                       pinctrl_uart0_cts: uart0_cts-0 {
+                                       pinctrl_uart0_rts: uart0_rts-0 {
                                                atmel,pins =
                                                        <AT91_PIOA 21 AT91_PERIPH_A AT91_PINCTRL_NONE>; /* PA21 periph A */
                                        };
index d2d72c3b44c42bd45060dcc3b4566cb624c9b7f1..df6b0aa0e4ddd6388110a655c14b1ad889eb6bf0 100644 (file)
 
        ahb {
                apb {
-                       dbgu: serial@fffff200 {
+                       usb1: gadget@fffb0000 {
+                               atmel,vbus-gpio = <&pioD 4 GPIO_ACTIVE_HIGH>;
+                               atmel,pullup-gpio = <&pioD 5 GPIO_ACTIVE_HIGH>;
                                status = "okay";
                        };
 
+                       macb0: ethernet@fffbc000 {
+                               phy-mode = "rmii";
+                               status = "okay";
+
+                               phy0: ethernet-phy {
+                                       interrupt-parent = <&pioC>;
+                                       interrupts = <4 IRQ_TYPE_EDGE_BOTH>;
+                               };
+                       };
+
                        usart1: serial@fffc4000 {
                                pinctrl-0 =
                                                <&pinctrl_uart1
                                status = "okay";
                        };
 
-                       macb0: ethernet@fffbc000 {
-                               phy-mode = "rmii";
-                               status = "okay";
-                       };
-
-                       usb1: gadget@fffb0000 {
-                               atmel,vbus-gpio = <&pioD 4 GPIO_ACTIVE_HIGH>;
-                               status = "okay";
-                       };
-
                        spi0: spi@fffe0000 {
                                status = "okay";
                                cs-gpios = <&pioA 3 0>, <0>, <0>, <0>;
                                        reg = <0>;
                                };
                        };
+
+                       dbgu: serial@fffff200 {
+                               status = "okay";
+                       };
                };
 
                usb0: ohci@00300000 {
                        num-ports = <2>;
                        status = "okay";
                };
+
+               nor_flash@10000000 {
+                       compatible = "cfi-flash";
+                       reg = <0x10000000 0x800000>;
+                       linux,mtd-name = "physmap-flash.0";
+                       bank-width = <2>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+
+                       barebox@0 {
+                               label = "barebox";
+                               reg = <0x00000 0x40000>;
+                       };
+
+                       bareboxenv@40000 {
+                               label = "bareboxenv";
+                               reg = <0x40000 0x10000>;
+                       };
+
+                       kernel@50000 {
+                               label = "kernel";
+                               reg = <0x50000 0x300000>;
+                       };
+
+                       root@350000  {
+                               label = "root";
+                               reg = <0x350000 0x4B0000>;
+                       };
+               };
        };
 
        leds {
index d5bd65f7460258daa91bb4a5227071b2b67fc5de..22e255ab6963a7e61b332424bc3b43e56e6f121e 100644 (file)
                                        };
                                };
 
+                               fb {
+                                       pinctrl_fb: fb-0 {
+                                               atmel,pins =
+                                                       <AT91_PIOC 1 AT91_PERIPH_A AT91_PINCTRL_NONE    /* PC1 periph A */
+                                                        AT91_PIOC 2 AT91_PERIPH_A AT91_PINCTRL_NONE    /* PC2 periph A */
+                                                        AT91_PIOC 3 AT91_PERIPH_A AT91_PINCTRL_NONE    /* PC3 periph A */
+                                                        AT91_PIOB 9 AT91_PERIPH_B AT91_PINCTRL_NONE    /* PB9 periph B */
+                                                        AT91_PIOC 6 AT91_PERIPH_A AT91_PINCTRL_NONE    /* PC6 periph A */
+                                                        AT91_PIOC 7 AT91_PERIPH_A AT91_PINCTRL_NONE    /* PC7 periph A */
+                                                        AT91_PIOC 8 AT91_PERIPH_A AT91_PINCTRL_NONE    /* PC8 periph A */
+                                                        AT91_PIOC 9 AT91_PERIPH_A AT91_PINCTRL_NONE    /* PC9 periph A */
+                                                        AT91_PIOC 10 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PC10 periph A */
+                                                        AT91_PIOC 11 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PC11 periph A */
+                                                        AT91_PIOC 14 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PC14 periph A */
+                                                        AT91_PIOC 15 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PC15 periph A */
+                                                        AT91_PIOC 16 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PC16 periph A */
+                                                        AT91_PIOC 12 AT91_PERIPH_B AT91_PINCTRL_NONE   /* PC12 periph B */
+                                                        AT91_PIOC 18 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PC18 periph A */
+                                                        AT91_PIOC 19 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PC19 periph A */
+                                                        AT91_PIOC 22 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PC22 periph A */
+                                                        AT91_PIOC 23 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PC23 periph A */
+                                                        AT91_PIOC 24 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PC24 periph A */
+                                                        AT91_PIOC 17 AT91_PERIPH_B AT91_PINCTRL_NONE   /* PC17 periph B */
+                                                        AT91_PIOC 26 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PC26 periph A */
+                                                        AT91_PIOC 27 AT91_PERIPH_A AT91_PINCTRL_NONE>; /* PC27 periph A */
+                                       };
+                               };
+
                                pioA: gpio@fffff200 {
                                        compatible = "atmel,at91rm9200-gpio";
                                        reg = <0xfffff200 0x200>;
                        };
                };
 
+               fb0: fb@0x00700000 {
+                       compatible = "atmel,at91sam9263-lcdc";
+                       reg = <0x00700000 0x1000>;
+                       interrupts = <26 IRQ_TYPE_LEVEL_HIGH 3>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_fb>;
+                       status = "disabled";
+               };
+
                nand0: nand@40000000 {
                        compatible = "atmel,at91rm9200-nand";
                        #address-cells = <1>;
index 70f835b55c0bd91bb07949bf309ca674264bc82e..15009c9f229328957221a7b536de9ce3c0e8e630 100644 (file)
                        };
                };
 
+               fb0: fb@0x00700000 {
+                       display = <&display0>;
+                       status = "okay";
+
+                       display0: display {
+                               bits-per-pixel = <16>;
+                               atmel,lcdcon-backlight;
+                               atmel,dmacon = <0x1>;
+                               atmel,lcdcon2 = <0x80008002>;
+                               atmel,guard-time = <1>;
+
+                               display-timings {
+                                       native-mode = <&timing0>;
+                                       timing0: timing0 {
+                                               clock-frequency = <4965000>;
+                                               hactive = <240>;
+                                               vactive = <320>;
+                                               hback-porch = <1>;
+                                               hfront-porch = <33>;
+                                               vback-porch = <1>;
+                                               vfront-porch = <0>;
+                                               hsync-len = <5>;
+                                               vsync-len = <1>;
+                                               hsync-active = <1>;
+                                               vsync-active = <1>;
+                                       };
+                               };
+                       };
+               };
+
                nand0: nand@40000000 {
                        nand-bus-width = <8>;
                        nand-ecc-mode = "soft";
index c3e514837074c1874412e88cb294fd4ec976a2ba..d7af9ecb85d247326dd24f37f00a05fa771a27fd 100644 (file)
                                        };
                                };
 
+                               i2c0 {
+                                       pinctrl_i2c0: i2c0-0 {
+                                               atmel,pins =
+                                                       <AT91_PIOA 21 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PA21 periph A TWCK0 */
+                                                        AT91_PIOA 20 AT91_PERIPH_A AT91_PINCTRL_NONE>; /* PA20 periph A TWD0 */
+                                       };
+                               };
+
+                               i2c1 {
+                                       pinctrl_i2c1: i2c1-0 {
+                                               atmel,pins =
+                                                       <AT91_PIOB 11 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PB11 periph A TWCK1 */
+                                                        AT91_PIOB 10 AT91_PERIPH_A AT91_PINCTRL_NONE>; /* PB10 periph A TWD1 */
+                                       };
+                               };
+
                                usart0 {
                                        pinctrl_usart0: usart0-0 {
                                                atmel,pins =
                                        };
                                };
 
+                               fb {
+                                       pinctrl_fb: fb-0 {
+                                               atmel,pins =
+                                                       <AT91_PIOE 0 AT91_PERIPH_A AT91_PINCTRL_NONE    /* PE0 periph A */
+                                                        AT91_PIOE 2 AT91_PERIPH_A AT91_PINCTRL_NONE    /* PE2 periph A */
+                                                        AT91_PIOE 3 AT91_PERIPH_A AT91_PINCTRL_NONE    /* PE3 periph A */
+                                                        AT91_PIOE 4 AT91_PERIPH_A AT91_PINCTRL_NONE    /* PE4 periph A */
+                                                        AT91_PIOE 5 AT91_PERIPH_A AT91_PINCTRL_NONE    /* PE5 periph A */
+                                                        AT91_PIOE 6 AT91_PERIPH_A AT91_PINCTRL_NONE    /* PE6 periph A */
+                                                        AT91_PIOE 7 AT91_PERIPH_A AT91_PINCTRL_NONE    /* PE7 periph A */
+                                                        AT91_PIOE 8 AT91_PERIPH_A AT91_PINCTRL_NONE    /* PE8 periph A */
+                                                        AT91_PIOE 9 AT91_PERIPH_A AT91_PINCTRL_NONE    /* PE9 periph A */
+                                                        AT91_PIOE 10 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PE10 periph A */
+                                                        AT91_PIOE 11 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PE11 periph A */
+                                                        AT91_PIOE 12 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PE12 periph A */
+                                                        AT91_PIOE 13 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PE13 periph A */
+                                                        AT91_PIOE 14 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PE14 periph A */
+                                                        AT91_PIOE 15 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PE15 periph A */
+                                                        AT91_PIOE 16 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PE16 periph A */
+                                                        AT91_PIOE 17 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PE17 periph A */
+                                                        AT91_PIOE 18 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PE18 periph A */
+                                                        AT91_PIOE 19 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PE19 periph A */
+                                                        AT91_PIOE 20 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PE20 periph A */
+                                                        AT91_PIOE 21 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PE21 periph A */
+                                                        AT91_PIOE 22 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PE22 periph A */
+                                                        AT91_PIOE 23 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PE23 periph A */
+                                                        AT91_PIOE 24 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PE24 periph A */
+                                                        AT91_PIOE 25 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PE25 periph A */
+                                                        AT91_PIOE 26 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PE26 periph A */
+                                                        AT91_PIOE 27 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PE27 periph A */
+                                                        AT91_PIOE 28 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PE28 periph A */
+                                                        AT91_PIOE 29 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PE29 periph A */
+                                                        AT91_PIOE 30 AT91_PERIPH_A AT91_PINCTRL_NONE>; /* PE30 periph A */
+                                       };
+                               };
+
                                pioA: gpio@fffff200 {
                                        compatible = "atmel,at91rm9200-gpio";
                                        reg = <0xfffff200 0x200>;
                                compatible = "atmel,at91sam9g10-i2c";
                                reg = <0xfff84000 0x100>;
                                interrupts = <12 IRQ_TYPE_LEVEL_HIGH 6>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_i2c0>;
                                #address-cells = <1>;
                                #size-cells = <0>;
                                status = "disabled";
                                compatible = "atmel,at91sam9g10-i2c";
                                reg = <0xfff88000 0x100>;
                                interrupts = <13 IRQ_TYPE_LEVEL_HIGH 6>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_i2c1>;
                                #address-cells = <1>;
                                #size-cells = <0>;
                                status = "disabled";
                                compatible = "atmel,hsmci";
                                reg = <0xfff80000 0x600>;
                                interrupts = <11 IRQ_TYPE_LEVEL_HIGH 0>;
+                               pinctrl-names = "default";
                                dmas = <&dma 1 AT91_DMA_CFG_PER_ID(0)>;
                                dma-names = "rxtx";
                                #address-cells = <1>;
                                compatible = "atmel,hsmci";
                                reg = <0xfffd0000 0x600>;
                                interrupts = <29 IRQ_TYPE_LEVEL_HIGH 0>;
+                               pinctrl-names = "default";
                                dmas = <&dma 1 AT91_DMA_CFG_PER_ID(13)>;
                                dma-names = "rxtx";
                                #address-cells = <1>;
                        };
                };
 
+               fb0: fb@0x00500000 {
+                       compatible = "atmel,at91sam9g45-lcdc";
+                       reg = <0x00500000 0x1000>;
+                       interrupts = <23 IRQ_TYPE_LEVEL_HIGH 3>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_fb>;
+                       status = "disabled";
+               };
+
                nand0: nand@40000000 {
                        compatible = "atmel,at91rm9200-nand";
                        #address-cells = <1>;
index a4b00e5c61c09faca05f8e5b9e2604394982cba8..7b76dbde8c41d900919279d8c2ed40c487493348 100644 (file)
                        };
                };
 
+               fb0: fb@0x00500000 {
+                       display = <&display0>;
+                       status = "okay";
+
+                       display0: display {
+                               bits-per-pixel = <32>;
+                               atmel,lcdcon-backlight;
+                               atmel,dmacon = <0x1>;
+                               atmel,lcdcon2 = <0x80008002>;
+                               atmel,guard-time = <9>;
+                               atmel,lcd-wiring-mode = "RGB";
+
+                               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>;
+                                       };
+                               };
+                       };
+               };
+
                nand0: nand@40000000 {
                        nand-bus-width = <8>;
                        nand-ecc-mode = "soft";
index 2347e9563cef62bc760a94c6be2ba2d940cd8c89..6801106fa1f8a0fee541e33da838a15033ddb33c 100644 (file)
 #include <dt-bindings/interrupt-controller/irq.h>
 
 / {
+       aliases {
+               serial4 = &usart3;
+       };
+
        ahb {
                apb {
                        pinctrl@fffff400 {
index 6e9deb786a7d1e4d6a19ee5a1613da8dde882bc0..2a3b1c1313a0c474bed0c681fea43029ba8fe20d 100644 (file)
 
 &gpio {
        pinctrl-names = "default";
-       pinctrl-0 = <&alt0 &alt3>;
+       pinctrl-0 = <&gpioout &alt0 &alt3>;
+
+       gpioout: gpioout {
+               brcm,pins = <6>;
+               brcm,function = <1>; /* GPIO out */
+       };
 
        alt0: alt0 {
-               brcm,pins = <0 1 2 3 4 5 7 8 9 10 11 14 15 40 45>;
+               brcm,pins = <0 1 2 3 4 5 7 8 9 10 11 14 15 40 45>;
                brcm,function = <4>; /* alt0 */
        };
 
index aa537ed13f0a578ade79e74c62a56302f1d65437..b021c96d3ba18225660185b037b5a5e1d65f68d5 100644 (file)
                        clocks = <&clk_mmc>;
                        status = "disabled";
                };
+
+               usb {
+                       compatible = "brcm,bcm2835-usb";
+                       reg = <0x7e980000 0x10000>;
+                       interrupts = <1 9>;
+               };
        };
 
        clocks {
index 9b186ac06c8ba2fbeff30f9bd58f6ca797e1b05d..42cef0a8ce95e31ada8a27a72cfc8edf965244ee 100644 (file)
                };
        };
 
-       dwmmc0@12200000 {
+       mmc@12200000 {
                num-slots = <1>;
                supports-highspeed;
                broken-cd;
                };
        };
 
-       dwmmc1@12210000 {
+       mmc@12210000 {
                status = "disabled";
        };
 
-       dwmmc2@12220000 {
+       mmc@12220000 {
                num-slots = <1>;
                supports-highspeed;
                fifo-depth = <0x80>;
                };
        };
 
-       dwmmc3@12230000 {
+       mmc@12230000 {
                num-slots = <1>;
                supports-highspeed;
                broken-cd;
index 8349a248eceaf242f8a079e6c565af109ee69708..7a70f4ca502a1665fa21cb31360d2869cbd3617c 100644 (file)
@@ -23,7 +23,7 @@
                power {
                        label = "Power";
                        gpios = <&gpio0 18 1>;
-                       linux,default-trigger = "default-on";
+                       default-state = "keep";
                };
        };
 
index 113a8bc7bee73649a33cc3e212336536f47399b3..db24b41a5264072dc74d39d2497b1be72e8a2d93 100644 (file)
                                marvell,#interrupts = <5>;
                        };
 
+                       pmu_intc: pmu-interrupt-ctrl@d0050 {
+                               compatible = "marvell,dove-pmu-intc";
+                               interrupt-controller;
+                               #interrupt-cells = <1>;
+                               reg = <0xd0050 0x8>;
+                               interrupts = <33>;
+                               marvell,#interrupts = <7>;
+                       };
+
                        core_clk: core-clocks@d0214 {
                                compatible = "marvell,dove-core-clock";
                                reg = <0xd0214 0x4>;
                        rtc: real-time-clock@d8500 {
                                compatible = "marvell,orion-rtc";
                                reg = <0xd8500 0x20>;
+                               interrupt-parent = <&pmu_intc>;
+                               interrupts = <5>;
                        };
 
                        crypto: crypto-engine@30000 {
                                status = "disabled";
 
                                ethphy: ethernet-phy {
-                                       device-type = "ethernet-phy";
+                                       device_type = "ethernet-phy";
                                        /* set phy address in board file */
                                };
                        };
index 861aa7d6fc7dbc480c0b9d6b185d6a291d38fcd2..50ccd151091e23d3acbec986bb3a321181b987b5 100644 (file)
@@ -9,7 +9,10 @@
  */
 /dts-v1/;
 
-/include/ "emev2.dtsi"
+#include "emev2.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/irq.h>
 
 / {
        model = "EMEV2 KZM9D Board";
                reg = <0x20000000 0x10000>;
                phy-mode = "mii";
                interrupt-parent = <&gpio0>;
-               interrupts = <1 1>;     /* active high */
+               interrupts = <1 IRQ_TYPE_EDGE_RISING>;
                reg-io-width = <4>;
                smsc,irq-active-high;
                smsc,irq-push-pull;
                vddvario-supply = <&reg_1p8v>;
                vdd33a-supply = <&reg_3p3v>;
        };
+
+       gpio_keys {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               button@1 {
+                       debounce_interval = <50>;
+                       wakeup = <1>;
+                       label = "DSW2-1";
+                       linux,code = <KEY_1>;
+                       gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>;
+               };
+               button@2 {
+                       debounce_interval = <50>;
+                       wakeup = <1>;
+                       label = "DSW2-2";
+                       linux,code = <KEY_2>;
+                       gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>;
+               };
+               button@3 {
+                       debounce_interval = <50>;
+                       wakeup = <1>;
+                       label = "DSW2-3";
+                       linux,code = <KEY_3>;
+                       gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>;
+               };
+               button@4 {
+                       debounce_interval = <50>;
+                       wakeup = <1>;
+                       label = "DSW2-4";
+                       linux,code = <KEY_4>;
+                       gpios = <&gpio0 17 GPIO_ACTIVE_HIGH>;
+               };
+       };
 };
index 9063a4434d6a59b26e3bac76e24f1643bc6121e8..e37985fa10e2b6aca96f047f788f9674ddf0bf9f 100644 (file)
@@ -8,7 +8,8 @@
  * kind, whether express or implied.
  */
 
-/include/ "skeleton.dtsi"
+#include "skeleton.dtsi"
+#include <dt-bindings/interrupt-controller/irq.h>
 
 / {
        compatible = "renesas,emev2";
 
        pmu {
                compatible = "arm,cortex-a9-pmu";
-               interrupts = <0 120 4>,
-                            <0 121 4>;
+               interrupts = <0 120 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 121 IRQ_TYPE_LEVEL_HIGH>;
+       };
+
+       smu@e0110000 {
+               compatible = "renesas,emev2-smu";
+               reg = <0xe0110000 0x10000>;
+               #address-cells = <2>;
+               #size-cells = <0>;
+
+               c32ki: c32ki {
+                       compatible = "fixed-clock";
+                       clock-frequency = <32768>;
+                       #clock-cells = <0>;
+               };
+               pll3_fo: pll3_fo {
+                       compatible = "fixed-factor-clock";
+                       clocks = <&c32ki>;
+                       clock-div = <1>;
+                       clock-mult = <7000>;
+                       #clock-cells = <0>;
+               };
+               usia_u0_sclkdiv: usia_u0_sclkdiv {
+                       compatible = "renesas,emev2-smu-clkdiv";
+                       reg = <0x610 0>;
+                       clocks = <&pll3_fo>;
+                       #clock-cells = <0>;
+               };
+               usib_u1_sclkdiv: usib_u1_sclkdiv {
+                       compatible = "renesas,emev2-smu-clkdiv";
+                       reg = <0x65c 0>;
+                       clocks = <&pll3_fo>;
+                       #clock-cells = <0>;
+               };
+               usib_u2_sclkdiv: usib_u2_sclkdiv {
+                       compatible = "renesas,emev2-smu-clkdiv";
+                       reg = <0x65c 16>;
+                       clocks = <&pll3_fo>;
+                       #clock-cells = <0>;
+               };
+               usib_u3_sclkdiv: usib_u3_sclkdiv {
+                       compatible = "renesas,emev2-smu-clkdiv";
+                       reg = <0x660 0>;
+                       clocks = <&pll3_fo>;
+                       #clock-cells = <0>;
+               };
+               usia_u0_sclk: usia_u0_sclk {
+                       compatible = "renesas,emev2-smu-gclk";
+                       reg = <0x4a0 1>;
+                       clocks = <&usia_u0_sclkdiv>;
+                       #clock-cells = <0>;
+               };
+               usib_u1_sclk: usib_u1_sclk {
+                       compatible = "renesas,emev2-smu-gclk";
+                       reg = <0x4b8 1>;
+                       clocks = <&usib_u1_sclkdiv>;
+                       #clock-cells = <0>;
+               };
+               usib_u2_sclk: usib_u2_sclk {
+                       compatible = "renesas,emev2-smu-gclk";
+                       reg = <0x4bc 1>;
+                       clocks = <&usib_u2_sclkdiv>;
+                       #clock-cells = <0>;
+               };
+               usib_u3_sclk: usib_u3_sclk {
+                       compatible = "renesas,emev2-smu-gclk";
+                       reg = <0x4c0 1>;
+                       clocks = <&usib_u3_sclkdiv>;
+                       #clock-cells = <0>;
+               };
+               sti_sclk: sti_sclk {
+                       compatible = "renesas,emev2-smu-gclk";
+                       reg = <0x528 1>;
+                       clocks = <&c32ki>;
+                       #clock-cells = <0>;
+               };
        };
 
        sti@e0180000 {
                compatible = "renesas,em-sti";
                reg = <0xe0180000 0x54>;
-               interrupts = <0 125 0>;
+               interrupts = <0 125 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&sti_sclk>;
+               clock-names = "sclk";
        };
 
        uart@e1020000 {
                compatible = "renesas,em-uart";
                reg = <0xe1020000 0x38>;
-               interrupts = <0 8 0>;
+               interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&usia_u0_sclk>;
+               clock-names = "sclk";
        };
 
        uart@e1030000 {
                compatible = "renesas,em-uart";
                reg = <0xe1030000 0x38>;
-               interrupts = <0 9 0>;
+               interrupts = <0 9 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&usib_u1_sclk>;
+               clock-names = "sclk";
        };
 
        uart@e1040000 {
                compatible = "renesas,em-uart";
                reg = <0xe1040000 0x38>;
-               interrupts = <0 10 0>;
+               interrupts = <0 10 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&usib_u2_sclk>;
+               clock-names = "sclk";
        };
 
        uart@e1050000 {
                compatible = "renesas,em-uart";
                reg = <0xe1050000 0x38>;
-               interrupts = <0 11 0>;
+               interrupts = <0 11 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&usib_u3_sclk>;
+               clock-names = "sclk";
        };
 
        gpio0: gpio@e0050000 {
                compatible = "renesas,em-gio";
                reg = <0xe0050000 0x2c>, <0xe0050040 0x20>;
-               interrupts = <0 67 0>, <0 68 0>;
+               interrupts = <0 67 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 68 IRQ_TYPE_LEVEL_HIGH>;
                gpio-controller;
                #gpio-cells = <2>;
                ngpios = <32>;
        gpio1: gpio@e0050080 {
                compatible = "renesas,em-gio";
                reg = <0xe0050080 0x2c>, <0xe00500c0 0x20>;
-               interrupts = <0 69 0>, <0 70 0>;
+               interrupts = <0 69 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 70 IRQ_TYPE_LEVEL_HIGH>;
                gpio-controller;
                #gpio-cells = <2>;
                ngpios = <32>;
        gpio2: gpio@e0050100 {
                compatible = "renesas,em-gio";
                reg = <0xe0050100 0x2c>, <0xe0050140 0x20>;
-               interrupts = <0 71 0>, <0 72 0>;
+               interrupts = <0 71 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 72 IRQ_TYPE_LEVEL_HIGH>;
                gpio-controller;
                #gpio-cells = <2>;
                ngpios = <32>;
        gpio3: gpio@e0050180 {
                compatible = "renesas,em-gio";
                reg = <0xe0050180 0x2c>, <0xe00501c0 0x20>;
-               interrupts = <0 73 0>, <0 74 0>;
+               interrupts = <0 73 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 74 IRQ_TYPE_LEVEL_HIGH>;
                gpio-controller;
                #gpio-cells = <2>;
                ngpios = <32>;
        gpio4: gpio@e0050200 {
                compatible = "renesas,em-gio";
                reg = <0xe0050200 0x2c>, <0xe0050240 0x20>;
-               interrupts = <0 75 0>, <0 76 0>;
+               interrupts = <0 75 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 76 IRQ_TYPE_LEVEL_HIGH>;
                gpio-controller;
                #gpio-cells = <2>;
                ngpios = <31>;
index 074739d39e2db04490c3575fbb2131519f6cf53d..e52b038a7a1171ac1559b86b5d3a18cdfb144ff8 100644 (file)
                interrupts = <1 9 0xf04>;
        };
 
-       dwmmc_0: dwmmc0@12200000 {
-               compatible = "samsung,exynos5250-dw-mshc";
-               interrupts = <0 75 0>;
-               #address-cells = <1>;
-               #size-cells = <0>;
-       };
-
-       dwmmc_1: dwmmc1@12210000 {
-               compatible = "samsung,exynos5250-dw-mshc";
-               interrupts = <0 76 0>;
-               #address-cells = <1>;
-               #size-cells = <0>;
-       };
-
-       dwmmc_2: dwmmc2@12220000 {
-               compatible = "samsung,exynos5250-dw-mshc";
-               interrupts = <0 77 0>;
-               #address-cells = <1>;
-               #size-cells = <0>;
-       };
-
        serial@12C00000 {
                compatible = "samsung,exynos4210-uart";
                reg = <0x12C00000 0x100>;
index 684527087aa4cc2bdc8da3c3f801a1626f3d9439..b77a37ec81c25b89affa2f90d8ef7007b0d4072a 100644 (file)
                status = "disabled";
        };
 
-       dwmmc_0: dwmmc0@12200000 {
+       mmc_0: mmc@12200000 {
+               status = "okay";
                num-slots = <1>;
                supports-highspeed;
                broken-cd;
-               fifo-depth = <0x80>;
                card-detect-delay = <200>;
                samsung,dw-mshc-ciu-div = <3>;
                samsung,dw-mshc-sdr-timing = <2 3>;
                };
        };
 
-       dwmmc_1: dwmmc1@12210000 {
-               status = "disabled";
-       };
-
-       dwmmc_2: dwmmc2@12220000 {
+       mmc_2: mmc@12220000 {
+               status = "okay";
                num-slots = <1>;
                supports-highspeed;
-               fifo-depth = <0x80>;
                card-detect-delay = <200>;
                samsung,dw-mshc-ciu-div = <3>;
                samsung,dw-mshc-sdr-timing = <2 3>;
                };
        };
 
-       dwmmc_3: dwmmc3@12230000 {
-               status = "disabled";
-       };
-
        i2s0: i2s@03830000 {
                status = "okay";
        };
index f86d56760a45a0f42692f5636376c899f81edbc3..13746dfb20aae1307f4ec9ef7636d89a83cb173a 100644 (file)
                };
        };
 
-       dwmmc0@12200000 {
+       mmc@12200000 {
+               status = "okay";
                num-slots = <1>;
                supports-highspeed;
                broken-cd;
-               fifo-depth = <0x80>;
                card-detect-delay = <200>;
                samsung,dw-mshc-ciu-div = <3>;
                samsung,dw-mshc-sdr-timing = <2 3>;
                };
        };
 
-       dwmmc1@12210000 {
-               status = "disabled";
-       };
-
-       dwmmc2@12220000 {
+       mmc@12220000 {
+               status = "okay";
                num-slots = <1>;
                supports-highspeed;
-               fifo-depth = <0x80>;
                card-detect-delay = <200>;
                samsung,dw-mshc-ciu-div = <3>;
                samsung,dw-mshc-sdr-timing = <2 3>;
                };
        };
 
-       dwmmc3@12230000 {
-               status = "disabled";
-       };
-
        spi_0: spi@12d20000 {
                status = "disabled";
        };
index fd711e245e8d311f392bedfed7bb48dee4d4b7e6..a9395c426db44a7ddaeefd3b56040928a8f06e2f 100644 (file)
         * On Snow we've got SIP WiFi and so can keep drive strengths low to
         * reduce EMI.
         */
-       dwmmc3@12230000 {
+       mmc@12230000 {
                slot@0 {
                        pinctrl-names = "default";
                        pinctrl-0 = <&sd3_clk &sd3_cmd &sd3_bus4>;
index 9db5047812f3d6c05a36643abbea0e1fb33e8195..b98ffc3a5fe289514a661cd5b5b7099c1c044be5 100644 (file)
                gsc1 = &gsc_1;
                gsc2 = &gsc_2;
                gsc3 = &gsc_3;
-               mshc0 = &dwmmc_0;
-               mshc1 = &dwmmc_1;
-               mshc2 = &dwmmc_2;
-               mshc3 = &dwmmc_3;
+               mshc0 = &mmc_0;
+               mshc1 = &mmc_1;
+               mshc2 = &mmc_2;
+               mshc3 = &mmc_3;
                i2c0 = &i2c_0;
                i2c1 = &i2c_1;
                i2c2 = &i2c_2;
                pinctrl-0 = <&spi2_bus>;
        };
 
-       dwmmc_0: dwmmc0@12200000 {
+       mmc_0: mmc@12200000 {
+               compatible = "samsung,exynos5250-dw-mshc";
+               interrupts = <0 75 0>;
+               #address-cells = <1>;
+               #size-cells = <0>;
                reg = <0x12200000 0x1000>;
                clocks = <&clock 280>, <&clock 139>;
                clock-names = "biu", "ciu";
+               fifo-depth = <0x80>;
+               status = "disabled";
        };
 
-       dwmmc_1: dwmmc1@12210000 {
+       mmc_1: mmc@12210000 {
+               compatible = "samsung,exynos5250-dw-mshc";
+               interrupts = <0 76 0>;
+               #address-cells = <1>;
+               #size-cells = <0>;
                reg = <0x12210000 0x1000>;
                clocks = <&clock 281>, <&clock 140>;
                clock-names = "biu", "ciu";
+               fifo-depth = <0x80>;
+               status = "disabled";
        };
 
-       dwmmc_2: dwmmc2@12220000 {
+       mmc_2: mmc@12220000 {
+               compatible = "samsung,exynos5250-dw-mshc";
+               interrupts = <0 77 0>;
+               #address-cells = <1>;
+               #size-cells = <0>;
                reg = <0x12220000 0x1000>;
                clocks = <&clock 282>, <&clock 141>;
                clock-names = "biu", "ciu";
+               fifo-depth = <0x80>;
+               status = "disabled";
        };
 
-       dwmmc_3: dwmmc3@12230000 {
+       mmc_3: mmc@12230000 {
                compatible = "samsung,exynos5250-dw-mshc";
                reg = <0x12230000 0x1000>;
                interrupts = <0 78 0>;
                #size-cells = <0>;
                clocks = <&clock 283>, <&clock 142>;
                clock-names = "biu", "ciu";
+               fifo-depth = <0x80>;
+               status = "disabled";
        };
 
        i2s0: i2s@03830000 {
index 79524c74c60354344bd9026b67614ce414ffbe31..fb5a1e25c632d3a4cbb3544e5e44ee67a0c1d8aa 100644 (file)
                };
        };
 
+       mmc@12200000 {
+               status = "okay";
+               broken-cd;
+               supports-highspeed;
+               card-detect-delay = <200>;
+               samsung,dw-mshc-ciu-div = <3>;
+               samsung,dw-mshc-sdr-timing = <0 4>;
+               samsung,dw-mshc-ddr-timing = <0 2>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
+
+               slot@0 {
+                       reg = <0>;
+                       bus-width = <8>;
+               };
+       };
+
+       mmc@12220000 {
+               status = "okay";
+               supports-highspeed;
+               card-detect-delay = <200>;
+               samsung,dw-mshc-ciu-div = <3>;
+               samsung,dw-mshc-sdr-timing = <2 3>;
+               samsung,dw-mshc-ddr-timing = <1 2>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus4>;
+
+               slot@0 {
+                       reg = <0>;
+                       bus-width = <4>;
+               };
+       };
+
        dp-controller@145B0000 {
                pinctrl-names = "default";
                pinctrl-0 = <&dp_hpd>;
index 09aa06cb3d3af77be582328167c25f8735a09fb2..b1fa334ec6d71c4031a3e691226e80935b900f9d 100644 (file)
@@ -22,6 +22,9 @@
        compatible = "samsung,exynos5420";
 
        aliases {
+               mshc0 = &mmc_0;
+               mshc1 = &mmc_1;
+               mshc2 = &mmc_2;
                pinctrl0 = &pinctrl_0;
                pinctrl1 = &pinctrl_1;
                pinctrl2 = &pinctrl_2;
@@ -31,6 +34,8 @@
                i2c1 = &i2c_1;
                i2c2 = &i2c_2;
                i2c3 = &i2c_3;
+               gsc0 = &gsc_0;
+               gsc1 = &gsc_1;
        };
 
        cpus {
                        reg = <0x3>;
                        clock-frequency = <1800000000>;
                };
+
+               cpu4: cpu@100 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a7";
+                       reg = <0x100>;
+                       clock-frequency = <1000000000>;
+               };
+
+               cpu5: cpu@101 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a7";
+                       reg = <0x101>;
+                       clock-frequency = <1000000000>;
+               };
+
+               cpu6: cpu@102 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a7";
+                       reg = <0x102>;
+                       clock-frequency = <1000000000>;
+               };
+
+               cpu7: cpu@103 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a7";
+                       reg = <0x103>;
+                       clock-frequency = <1000000000>;
+               };
        };
 
        clock: clock-controller@10010000 {
                clock-names = "mfc";
        };
 
+       mmc_0: mmc@12200000 {
+               compatible = "samsung,exynos5420-dw-mshc-smu";
+               interrupts = <0 75 0>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               reg = <0x12200000 0x2000>;
+               clocks = <&clock 351>, <&clock 132>;
+               clock-names = "biu", "ciu";
+               fifo-depth = <0x40>;
+               status = "disabled";
+       };
+
+       mmc_1: mmc@12210000 {
+               compatible = "samsung,exynos5420-dw-mshc-smu";
+               interrupts = <0 76 0>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               reg = <0x12210000 0x2000>;
+               clocks = <&clock 352>, <&clock 133>;
+               clock-names = "biu", "ciu";
+               fifo-depth = <0x40>;
+               status = "disabled";
+       };
+
+       mmc_2: mmc@12220000 {
+               compatible = "samsung,exynos5420-dw-mshc";
+               interrupts = <0 77 0>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               reg = <0x12220000 0x1000>;
+               clocks = <&clock 353>, <&clock 134>;
+               clock-names = "biu", "ciu";
+               fifo-depth = <0x40>;
+               status = "disabled";
+       };
+
        mct@101C0000 {
                compatible = "samsung,exynos4210-mct";
                reg = <0x101C0000 0x800>;
                interrupt-controller;
                #interrups-cells = <1>;
                interrupt-parent = <&mct_map>;
-               interrupts = <0>, <1>, <2>, <3>, <4>, <5>, <6>, <7>;
+               interrupts = <0>, <1>, <2>, <3>, <4>, <5>, <6>, <7>,
+                               <8>, <9>, <10>, <11>;
                clocks = <&clock 1>, <&clock 315>;
                clock-names = "fin_pll", "mct";
 
                                        <4 &gic 0 120 0>,
                                        <5 &gic 0 121 0>,
                                        <6 &gic 0 122 0>,
-                                       <7 &gic 0 123 0>;
+                                       <7 &gic 0 123 0>,
+                                       <8 &gic 0 128 0>,
+                                       <9 &gic 0 129 0>,
+                                       <10 &gic 0 130 0>,
+                                       <11 &gic 0 131 0>;
                };
        };
 
                clocks = <&clock 431>, <&clock 143>;
                clock-names = "mixer", "sclk_hdmi";
        };
+
+       gsc_0: video-scaler@13e00000 {
+               compatible = "samsung,exynos5-gsc";
+               reg = <0x13e00000 0x1000>;
+               interrupts = <0 85 0>;
+               clocks = <&clock 465>;
+               clock-names = "gscl";
+               samsung,power-domain = <&gsc_pd>;
+       };
+
+       gsc_1: video-scaler@13e10000 {
+               compatible = "samsung,exynos5-gsc";
+               reg = <0x13e10000 0x1000>;
+               interrupts = <0 86 0>;
+               clocks = <&clock 466>;
+               clock-names = "gscl";
+               samsung,power-domain = <&gsc_pd>;
+       };
 };
index 1f026adefd451e594628d1855acf949f9cd7d7cf..a33f66c11b73edbf3671f02017e7780704c36b05 100644 (file)
 
        regulators {
                compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
 
-               reg_vddio_sd0: vddio-sd0 {
+               reg_vddio_sd0: regulator@0 {
                        compatible = "regulator-fixed";
+                       reg = <0>;
                        regulator-name = "vddio-sd0";
                        regulator-min-microvolt = <3300000>;
                        regulator-max-microvolt = <3300000>;
                        gpio = <&gpio1 29 0>;
                };
 
-               reg_lcd_3v3: lcd-3v3 {
+               reg_lcd_3v3: regulator@1 {
                        compatible = "regulator-fixed";
+                       reg = <1>;
                        regulator-name = "lcd-3v3";
                        regulator-min-microvolt = <3300000>;
                        regulator-max-microvolt = <3300000>;
index 526bfdbd87f9f84f08747c6c045c059a657d2cbc..7e6eef2488e807c12c36aaebfd3e64b076f7622f 100644 (file)
 
        regulators {
                compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
 
-               reg_usb0_vbus: usb0_vbus {
+               reg_usb0_vbus: regulator@0 {
                        compatible = "regulator-fixed";
+                       reg = <0>;
                        regulator-name = "usb0_vbus";
                        regulator-min-microvolt = <5000000>;
                        regulator-max-microvolt = <5000000>;
index cb64e2b191ea1ae48098c1c79ced4afe6f57b521..455169e99d49b5ad5388e8122012f3f6f6e27f72 100644 (file)
 
        regulators {
                compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
 
-               reg_vddio_sd0: vddio-sd0 {
+               reg_vddio_sd0: regulator@0 {
                        compatible = "regulator-fixed";
+                       reg = <0>;
                        regulator-name = "vddio-sd0";
                        regulator-min-microvolt = <3300000>;
                        regulator-max-microvolt = <3300000>;
diff --git a/arch/arm/boot/dts/imx25-eukrea-cpuimx25.dtsi b/arch/arm/boot/dts/imx25-eukrea-cpuimx25.dtsi
new file mode 100644 (file)
index 0000000..8abd45a
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2013 Eukréa Electromatique <denis@eukrea.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.
+ */
+
+#include "imx25.dtsi"
+
+/ {
+       model = "Eukrea CPUIMX25";
+       compatible = "eukrea,cpuimx25", "fsl,imx25";
+
+       memory {
+               reg = <0x80000000 0x4000000>; /* 64M */
+       };
+};
+
+&fec {
+       phy-mode = "rmii";
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_fec>;
+       status = "okay";
+};
+
+&i2c1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c1>;
+       status = "okay";
+
+       pcf8563@51 {
+               compatible = "nxp,pcf8563";
+               reg = <0x51>;
+       };
+};
+
+&iomuxc {
+       imx25-eukrea-cpuimx25 {
+               pinctrl_fec: fecgrp {
+                       fsl,pins = <MX25_FEC_PINGRP1>;
+               };
+
+               pinctrl_i2c1: i2c1grp {
+                       fsl,pins = <MX25_I2C1_PINGRP1>;
+               };
+       };
+};
+
+&nfc {
+       nand-bus-width = <8>;
+       nand-ecc-mode = "hw";
+       nand-on-flash-bbt;
+       status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard.dts b/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard.dts
new file mode 100644 (file)
index 0000000..30073f8
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2013 Eukréa Electromatique <denis@eukrea.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.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include "imx25-eukrea-cpuimx25.dtsi"
+
+/ {
+       model = "Eukrea MBIMXSD25";
+       compatible = "eukrea,mbimxsd25-baseboard", "eukrea,cpuimx25", "fsl,imx25";
+
+       gpio_keys {
+               compatible = "gpio-keys";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_gpiokeys>;
+
+               bp1 {
+                       label = "BP1";
+                       gpios = <&gpio3 18 GPIO_ACTIVE_LOW>;
+                       linux,code = <BTN_MISC>;
+                       gpio-key,wakeup;
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_gpioled>;
+
+               led1 {
+                       label = "led1";
+                       gpios = <&gpio3 19 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "heartbeat";
+               };
+       };
+
+       sound {
+               compatible = "eukrea,asoc-tlv320";
+               eukrea,model = "imx25-eukrea-tlv320aic23";
+               ssi-controller = <&ssi1>;
+               fsl,mux-int-port = <1>;
+               fsl,mux-ext-port = <5>;
+       };
+};
+
+&audmux {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_audmux>;
+       status = "okay";
+};
+
+&esdhc1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_esdhc1>;
+       cd-gpios = <&gpio1 20>;
+       status = "okay";
+};
+
+&i2c1 {
+       tlv320aic23: codec@1a {
+               compatible = "ti,tlv320aic23";
+               reg = <0x1a>;
+       };
+};
+
+&iomuxc {
+       imx25-eukrea-mbimxsd25-baseboard {
+               pinctrl_audmux: audmuxgrp {
+                       fsl,pins = <MX25_AUDMUX_PINGRP1>;
+               };
+
+               pinctrl_esdhc1: esdhc1grp {
+                       fsl,pins = <MX25_ESDHC1_PINGRP1>;
+               };
+
+               pinctrl_gpiokeys: gpiokeysgrp {
+                       fsl,pins = <MX25_PAD_VSTBY_ACK__GPIO_3_18 0x80000000>;
+               };
+
+               pinctrl_gpioled: gpioledgrp {
+                       fsl,pins = <MX25_PAD_POWER_FAIL__GPIO_3_19 0x80000000>;
+               };
+
+               pinctrl_lcdc: lcdcgrp {
+                       fsl,pins = <MX25_LCDC_PINGRP1>;
+               };
+
+               pinctrl_uart1: uart1grp {
+                       fsl,pins = <MX25_UART1_PINGRP1>;
+               };
+
+               pinctrl_uart2: uart2grp {
+                       fsl,pins = <MX25_UART2_PINGRP1>;
+               };
+       };
+};
+
+&ssi1 {
+       codec-handle = <&tlv320aic23>;
+       fsl,mode = "i2s-slave";
+       status = "okay";
+};
+
+&uart1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart1>;
+       fsl,uart-has-rtscts;
+       status = "okay";
+};
+
+&uart2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart2>;
+       fsl,uart-has-rtscts;
+       status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx25-pinfunc.h b/arch/arm/boot/dts/imx25-pinfunc.h
new file mode 100644 (file)
index 0000000..9238a95
--- /dev/null
@@ -0,0 +1,494 @@
+/*
+ * Copyright 2013 Eukréa Electromatique <denis@eukrea.com>
+ * Based on imx35-pinfunc.h in the same directory Which is:
+ * 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.
+ *
+ */
+
+#ifndef __DTS_IMX25_PINFUNC_H
+#define __DTS_IMX25_PINFUNC_H
+
+/*
+ * The pin function ID is a tuple of
+ * <mux_reg conf_reg input_reg mux_mode input_val>
+ */
+
+#define MX25_PAD_A10__A10                      0x008 0x000 0x000 0x00 0x000
+#define MX25_PAD_A10__GPIO_4_0                 0x008 0x000 0x000 0x05 0x000
+
+#define MX25_PAD_A13__A13                      0x00c 0x22C 0x000 0x00 0x000
+#define MX25_PAD_A13__GPIO_4_1                 0x00c 0x22C 0x000 0x05 0x000
+
+#define MX25_PAD_A14__A14                      0x010 0x230 0x000 0x10 0x000
+#define MX25_PAD_A14__GPIO_2_0                 0x010 0x230 0x000 0x15 0x000
+
+#define MX25_PAD_A15__A15                      0x014 0x234 0x000 0x10 0x000
+#define MX25_PAD_A15__GPIO_2_1                 0x014 0x234 0x000 0x15 0x000
+
+#define MX25_PAD_A16__A16                      0x018 0x000 0x000 0x10 0x000
+#define MX25_PAD_A16__GPIO_2_2                 0x018 0x000 0x000 0x15 0x000
+
+#define MX25_PAD_A17__A17                      0x01c 0x238 0x000 0x10 0x000
+#define MX25_PAD_A17__GPIO_2_3                 0x01c 0x238 0x000 0x15 0x000
+
+#define MX25_PAD_A18__A18                      0x020 0x23c 0x000 0x10 0x000
+#define MX25_PAD_A18__GPIO_2_4                 0x020 0x23c 0x000 0x15 0x000
+#define MX25_PAD_A18__FEC_COL                  0x020 0x23c 0x504 0x17 0x000
+
+#define MX25_PAD_A19__A19                      0x024 0x240 0x000 0x10 0x000
+#define MX25_PAD_A19__FEC_RX_ER                        0x024 0x240 0x518 0x17 0x000
+#define MX25_PAD_A19__GPIO_2_5                 0x024 0x240 0x000 0x15 0x000
+
+#define MX25_PAD_A20__A20                      0x028 0x244 0x000 0x10 0x000
+#define MX25_PAD_A20__GPIO_2_6                 0x028 0x244 0x000 0x15 0x000
+#define MX25_PAD_A20__FEC_RDATA2               0x028 0x244 0x50c 0x17 0x000
+
+#define MX25_PAD_A21__A21                      0x02c 0x248 0x000 0x10 0x000
+#define MX25_PAD_A21__GPIO_2_7                 0x02c 0x248 0x000 0x15 0x000
+#define MX25_PAD_A21__FEC_RDATA3               0x02c 0x248 0x510 0x17 0x000
+
+#define MX25_PAD_A22__A22                      0x030 0x000 0x000 0x10 0x000
+#define MX25_PAD_A22__GPIO_2_8                 0x030 0x000 0x000 0x15 0x000
+
+#define MX25_PAD_A23__A23                      0x034 0x24c 0x000 0x10 0x000
+#define MX25_PAD_A23__GPIO_2_9                 0x034 0x24c 0x000 0x15 0x000
+
+#define MX25_PAD_A24__A24                      0x038 0x250 0x000 0x10 0x000
+#define MX25_PAD_A24__GPIO_2_10                        0x038 0x250 0x000 0x15 0x000
+#define MX25_PAD_A24__FEC_RX_CLK               0x038 0x250 0x514 0x17 0x000
+
+#define MX25_PAD_A25__A25                      0x03c 0x254 0x000 0x10 0x000
+#define MX25_PAD_A25__GPIO_2_11                        0x03c 0x254 0x000 0x15 0x000
+#define MX25_PAD_A25__FEC_CRS                  0x03c 0x254 0x508 0x17 0x000
+
+#define MX25_PAD_EB0__EB0                      0x040 0x258 0x000 0x10 0x000
+#define MX25_PAD_EB0__AUD4_TXD                 0x040 0x258 0x464 0x14 0x000
+#define MX25_PAD_EB0__GPIO_2_12                        0x040 0x258 0x000 0x15 0x000
+
+#define MX25_PAD_EB1__EB1                      0x044 0x25c 0x000 0x10 0x000
+#define MX25_PAD_EB1__AUD4_RXD                 0x044 0x25c 0x460 0x14 0x000
+#define MX25_PAD_EB1__GPIO_2_13                        0x044 0x25c 0x000 0x15 0x000
+
+#define MX25_PAD_OE__OE                                0x048 0x260 0x000 0x10 0x000
+#define MX25_PAD_OE__AUD4_TXC                  0x048 0x260 0x000 0x14 0x000
+#define MX25_PAD_OE__GPIO_2_14                 0x048 0x260 0x000 0x15 0x000
+
+#define MX25_PAD_CS0__CS0                      0x04c 0x000 0x000 0x00 0x000
+#define MX25_PAD_CS0__GPIO_4_2                 0x04c 0x000 0x000 0x05 0x000
+
+#define MX25_PAD_CS1__CS1                      0x050 0x000 0x000 0x00 0x000
+#define MX25_PAD_CS1__NF_CE3                   0x050 0x000 0x000 0x01 0x000
+#define MX25_PAD_CS1__GPIO_4_3                 0x050 0x000 0x000 0x05 0x000
+
+#define MX25_PAD_CS4__CS4                      0x054 0x264 0x000 0x10 0x000
+#define MX25_PAD_CS4__NF_CE1                   0x054 0x264 0x000 0x01 0x000
+#define MX25_PAD_CS4__UART5_CTS                        0x054 0x264 0x000 0x13 0x000
+#define MX25_PAD_CS4__GPIO_3_20                        0x054 0x264 0x000 0x15 0x000
+
+#define MX25_PAD_CS5__CS5                      0x058 0x268 0x000 0x10 0x000
+#define MX25_PAD_CS5__NF_CE2                   0x058 0x268 0x000 0x01 0x000
+#define MX25_PAD_CS5__UART5_RTS                        0x058 0x268 0x574 0x13 0x000
+#define MX25_PAD_CS5__GPIO_3_21                        0x058 0x268 0x000 0x15 0x000
+
+#define MX25_PAD_NF_CE0__NF_CE0                        0x05c 0x26c 0x000 0x10 0x000
+#define MX25_PAD_NF_CE0__GPIO_3_22             0x05c 0x26c 0x000 0x15 0x000
+
+#define MX25_PAD_ECB__ECB                      0x060 0x270 0x000 0x10 0x000
+#define MX25_PAD_ECB__UART5_TXD_MUX            0x060 0x270 0x000 0x13 0x000
+#define MX25_PAD_ECB__GPIO_3_23                        0x060 0x270 0x000 0x15 0x000
+
+#define MX25_PAD_LBA__LBA                      0x064 0x274 0x000 0x10 0x000
+#define MX25_PAD_LBA__UART5_RXD_MUX            0x064 0x274 0x578 0x13 0x000
+#define MX25_PAD_LBA__GPIO_3_24                        0x064 0x274 0x000 0x15 0x000
+
+#define MX25_PAD_BCLK__BCLK                    0x068 0x000 0x000 0x00 0x000
+#define MX25_PAD_BCLK__GPIO_4_4                        0x068 0x000 0x000 0x05 0x000
+
+#define MX25_PAD_RW__RW                                0x06c 0x278 0x000 0x10 0x000
+#define MX25_PAD_RW__AUD4_TXFS                 0x06c 0x278 0x474 0x14 0x000
+#define MX25_PAD_RW__GPIO_3_25                 0x06c 0x278 0x000 0x15 0x000
+
+#define MX25_PAD_NFWE_B__NFWE_B                        0x070 0x000 0x000 0x10 0x000
+#define MX25_PAD_NFWE_B__GPIO_3_26             0x070 0x000 0x000 0x15 0x000
+
+#define MX25_PAD_NFRE_B__NFRE_B                        0x074 0x000 0x000 0x10 0x000
+#define MX25_PAD_NFRE_B__GPIO_3_27             0x074 0x000 0x000 0x15 0x000
+
+#define MX25_PAD_NFALE__NFALE                  0x078 0x000 0x000 0x10 0x000
+#define MX25_PAD_NFALE__GPIO_3_28              0x078 0x000 0x000 0x15 0x000
+
+#define MX25_PAD_NFCLE__NFCLE                  0x07c 0x000 0x000 0x10 0x000
+#define MX25_PAD_NFCLE__GPIO_3_29              0x07c 0x000 0x000 0x15 0x000
+
+#define MX25_PAD_NFWP_B__NFWP_B                        0x080 0x000 0x000 0x10 0x000
+#define MX25_PAD_NFWP_B__GPIO_3_30             0x080 0x000 0x000 0x15 0x000
+
+#define MX25_PAD_NFRB__NFRB                    0x084 0x27c 0x000 0x10 0x000
+#define MX25_PAD_NFRB__GPIO_3_31               0x084 0x27c 0x000 0x15 0x000
+
+#define MX25_PAD_D15__D15                      0x088 0x280 0x000 0x00 0x000
+#define MX25_PAD_D15__LD16                     0x088 0x280 0x000 0x01 0x000
+#define MX25_PAD_D15__GPIO_4_5                 0x088 0x280 0x000 0x05 0x000
+
+#define MX25_PAD_D14__D14                      0x08c 0x284 0x000 0x00 0x000
+#define MX25_PAD_D14__LD17                     0x08c 0x284 0x000 0x01 0x000
+#define MX25_PAD_D14__GPIO_4_6                 0x08c 0x284 0x000 0x05 0x000
+
+#define MX25_PAD_D13__D13                      0x090 0x288 0x000 0x00 0x000
+#define MX25_PAD_D13__LD18                     0x090 0x288 0x000 0x01 0x000
+#define MX25_PAD_D13__GPIO_4_7                 0x090 0x288 0x000 0x05 0x000
+
+#define MX25_PAD_D12__D12                      0x094 0x28c 0x000 0x00 0x000
+#define MX25_PAD_D12__GPIO_4_8                 0x094 0x28c 0x000 0x05 0x000
+
+#define MX25_PAD_D11__D11                      0x098 0x290 0x000 0x00 0x000
+#define MX25_PAD_D11__GPIO_4_9                 0x098 0x290 0x000 0x05 0x000
+
+#define MX25_PAD_D10__D10                      0x09c 0x294 0x000 0x00 0x000
+#define MX25_PAD_D10__GPIO_4_10                        0x09c 0x294 0x000 0x05 0x000
+#define MX25_PAD_D10__USBOTG_OC                        0x09c 0x294 0x57c 0x06 0x000
+
+#define MX25_PAD_D9__D9                                0x0a0 0x298 0x000 0x00 0x000
+#define MX25_PAD_D9__GPIO_4_11                 0x0a0 0x298 0x000 0x05 0x000
+#define MX25_PAD_D9__USBH2_PWR                 0x0a0 0x298 0x000 0x06 0x000
+
+#define MX25_PAD_D8__D8                                0x0a4 0x29c 0x000 0x00 0x000
+#define MX25_PAD_D8__GPIO_4_12                 0x0a4 0x29c 0x000 0x05 0x000
+#define MX25_PAD_D8__USBH2_OC                  0x0a4 0x29c 0x580 0x06 0x000
+
+#define MX25_PAD_D7__D7                                0x0a8 0x2a0 0x000 0x00 0x000
+#define MX25_PAD_D7__GPIO_4_13                 0x0a8 0x2a0 0x000 0x05 0x000
+
+#define MX25_PAD_D6__D6                                0x0ac 0x2a4 0x000 0x00 0x000
+#define MX25_PAD_D6__GPIO_4_14                 0x0ac 0x2a4 0x000 0x05 0x000
+
+#define MX25_PAD_D5__D5                                0x0b0 0x2a8 0x000 0x00 0x000
+#define MX25_PAD_D5__GPIO_4_15                 0x0b0 0x2a8 0x000 0x05 0x000
+
+#define MX25_PAD_D4__D4                                0x0b4 0x2ac 0x000 0x00 0x000
+#define MX25_PAD_D4__GPIO_4_16                 0x0b4 0x2ac 0x000 0x05 0x000
+
+#define MX25_PAD_D3__D3                                0x0b8 0x2b0 0x000 0x00 0x000
+#define MX25_PAD_D3__GPIO_4_17                 0x0b8 0x2b0 0x000 0x05 0x000
+
+#define MX25_PAD_D2__D2                                0x0bc 0x2b4 0x000 0x00 0x000
+#define MX25_PAD_D2__GPIO_4_18                 0x0bc 0x2b4 0x000 0x05 0x000
+
+#define MX25_PAD_D1__D1                                0x0c0 0x2b8 0x000 0x00 0x000
+#define MX25_PAD_D1__GPIO_4_19                 0x0c0 0x2b8 0x000 0x05 0x000
+
+#define MX25_PAD_D0__D0                                0x0c4 0x2bc 0x000 0x00 0x000
+#define MX25_PAD_D0__GPIO_4_20                 0x0c4 0x2bc 0x000 0x05 0x000
+
+#define MX25_PAD_LD0__LD0                      0x0c8 0x2c0 0x000 0x10 0x000
+#define MX25_PAD_LD0__CSI_D0                   0x0c8 0x2c0 0x488 0x12 0x000
+#define MX25_PAD_LD0__GPIO_2_15                        0x0c8 0x2c0 0x000 0x15 0x000
+
+#define MX25_PAD_LD1__LD1                      0x0cc 0x2c4 0x000 0x10 0x000
+#define MX25_PAD_LD1__CSI_D1                   0x0cc 0x2c4 0x48c 0x12 0x000
+#define MX25_PAD_LD1__GPIO_2_16                        0x0cc 0x2c4 0x000 0x15 0x000
+
+#define MX25_PAD_LD2__LD2                      0x0d0 0x2c8 0x000 0x10 0x000
+#define MX25_PAD_LD2__GPIO_2_17                        0x0d0 0x2c8 0x000 0x15 0x000
+
+#define MX25_PAD_LD3__LD3                      0x0d4 0x2cc 0x000 0x10 0x000
+#define MX25_PAD_LD3__GPIO_2_18                        0x0d4 0x2cc 0x000 0x15 0x000
+
+#define MX25_PAD_LD4__LD4                      0x0d8 0x2d0 0x000 0x10 0x000
+#define MX25_PAD_LD4__GPIO_2_19                        0x0d8 0x2d0 0x000 0x15 0x000
+
+#define MX25_PAD_LD5__LD5                      0x0dc 0x2d4 0x000 0x10 0x000
+#define MX25_PAD_LD5__GPIO_1_19                        0x0dc 0x2d4 0x000 0x15 0x000
+
+#define MX25_PAD_LD6__LD6                      0x0e0 0x2d8 0x000 0x10 0x000
+#define MX25_PAD_LD6__GPIO_1_20                        0x0e0 0x2d8 0x000 0x15 0x000
+
+#define MX25_PAD_LD7__LD7                      0x0e4 0x2dc 0x000 0x10 0x000
+#define MX25_PAD_LD7__GPIO_1_21                        0x0e4 0x2dc 0x000 0x15 0x000
+
+#define MX25_PAD_LD8__LD8                      0x0e8 0x2e0 0x000 0x10 0x000
+#define MX25_PAD_LD8__FEC_TX_ERR               0x0e8 0x2e0 0x000 0x15 0x000
+
+#define MX25_PAD_LD9__LD9                      0x0ec 0x2e4 0x000 0x10 0x000
+#define MX25_PAD_LD9__FEC_COL                  0x0ec 0x2e4 0x504 0x15 0x001
+
+#define MX25_PAD_LD10__LD10                    0x0f0 0x2e8 0x000 0x10 0x000
+#define MX25_PAD_LD10__FEC_RX_ER               0x0f0 0x2e8 0x518 0x15 0x001
+
+#define MX25_PAD_LD11__LD11                    0x0f4 0x2ec 0x000 0x10 0x000
+#define MX25_PAD_LD11__FEC_RDATA2              0x0f4 0x2ec 0x50c 0x15 0x001
+
+#define MX25_PAD_LD12__LD12                    0x0f8 0x2f0 0x000 0x10 0x000
+#define MX25_PAD_LD12__FEC_RDATA3              0x0f8 0x2f0 0x510 0x15 0x001
+
+#define MX25_PAD_LD13__LD13                    0x0fc 0x2f4 0x000 0x10 0x000
+#define MX25_PAD_LD13__FEC_TDATA2              0x0fc 0x2f4 0x000 0x15 0x000
+
+#define MX25_PAD_LD14__LD14                    0x100 0x2f8 0x000 0x10 0x000
+#define MX25_PAD_LD14__FEC_TDATA3              0x100 0x2f8 0x000 0x15 0x000
+
+#define MX25_PAD_LD15__LD15                    0x104 0x2fc 0x000 0x10 0x000
+#define MX25_PAD_LD15__FEC_RX_CLK              0x104 0x2fc 0x514 0x15 0x001
+
+#define MX25_PAD_HSYNC__HSYNC                  0x108 0x300 0x000 0x10 0x000
+#define MX25_PAD_HSYNC__GPIO_1_22              0x108 0x300 0x000 0x15 0x000
+
+#define MX25_PAD_VSYNC__VSYNC                  0x10c 0x304 0x000 0x10 0x000
+#define MX25_PAD_VSYNC__GPIO_1_23              0x10c 0x304 0x000 0x15 0x000
+
+#define MX25_PAD_LSCLK__LSCLK                  0x110 0x308 0x000 0x10 0x000
+#define MX25_PAD_LSCLK__GPIO_1_24              0x110 0x308 0x000 0x15 0x000
+
+#define MX25_PAD_OE_ACD__OE_ACD                        0x114 0x30c 0x000 0x10 0x000
+#define MX25_PAD_OE_ACD__GPIO_1_25             0x114 0x30c 0x000 0x15 0x000
+
+#define MX25_PAD_CONTRAST__CONTRAST            0x118 0x310 0x000 0x10 0x000
+#define MX25_PAD_CONTRAST__PWM4_PWMO           0x118 0x310 0x000 0x14 0x000
+#define MX25_PAD_CONTRAST__FEC_CRS             0x118 0x310 0x508 0x15 0x001
+
+#define MX25_PAD_PWM__PWM                      0x11c 0x314 0x000 0x10 0x000
+#define MX25_PAD_PWM__GPIO_1_26                        0x11c 0x314 0x000 0x15 0x000
+#define MX25_PAD_PWM__USBH2_OC                 0x11c 0x314 0x580 0x16 0x001
+
+#define MX25_PAD_CSI_D2__CSI_D2                        0x120 0x318 0x000 0x10 0x000
+#define MX25_PAD_CSI_D2__UART5_RXD_MUX         0x120 0x318 0x578 0x11 0x001
+#define MX25_PAD_CSI_D2__GPIO_1_27             0x120 0x318 0x000 0x15 0x000
+#define MX25_PAD_CSI_D2__CSPI3_MOSI            0x120 0x318 0x000 0x17 0x000
+
+#define MX25_PAD_CSI_D3__CSI_D3                        0x124 0x31c 0x000 0x10 0x000
+#define MX25_PAD_CSI_D3__GPIO_1_28             0x124 0x31c 0x000 0x15 0x000
+#define MX25_PAD_CSI_D3__CSPI3_MISO            0x124 0x31c 0x4b4 0x17 0x001
+
+#define MX25_PAD_CSI_D4__CSI_D4                        0x128 0x320 0x000 0x10 0x000
+#define MX25_PAD_CSI_D4__UART5_RTS             0x128 0x320 0x574 0x11 0x001
+#define MX25_PAD_CSI_D4__GPIO_1_29             0x128 0x320 0x000 0x15 0x000
+#define MX25_PAD_CSI_D4__CSPI3_SCLK            0x128 0x320 0x000 0x17 0x000
+
+#define MX25_PAD_CSI_D5__CSI_D5                        0x12c 0x324 0x000 0x10 0x000
+#define MX25_PAD_CSI_D5__GPIO_1_30             0x12c 0x324 0x000 0x15 0x000
+#define MX25_PAD_CSI_D5__CSPI3_RDY             0x12c 0x324 0x000 0x17 0x000
+
+#define MX25_PAD_CSI_D6__CSI_D6                        0x130 0x328 0x000 0x10 0x000
+#define MX25_PAD_CSI_D6__GPIO_1_31             0x130 0x328 0x000 0x15 0x000
+
+#define MX25_PAD_CSI_D7__CSI_D7                        0x134 0x32c 0x000 0x10 0x000
+#define MX25_PAD_CSI_D7__GPIO_1_6              0x134 0x32c 0x000 0x15 0x000
+
+#define MX25_PAD_CSI_D8__CSI_D8                        0x138 0x330 0x000 0x10 0x000
+#define MX25_PAD_CSI_D8__GPIO_1_7              0x138 0x330 0x000 0x15 0x000
+
+#define MX25_PAD_CSI_D9__CSI_D9                        0x13c 0x334 0x000 0x10 0x000
+#define MX25_PAD_CSI_D9__GPIO_4_21             0x13c 0x334 0x000 0x15 0x000
+
+#define MX25_PAD_CSI_MCLK__CSI_MCLK            0x140 0x338 0x000 0x10 0x000
+#define MX25_PAD_CSI_MCLK__GPIO_1_8            0x140 0x338 0x000 0x15 0x000
+
+#define MX25_PAD_CSI_VSYNC__CSI_VSYNC          0x144 0x33c 0x000 0x10 0x000
+#define MX25_PAD_CSI_VSYNC__GPIO_1_9           0x144 0x33c 0x000 0x15 0x000
+
+#define MX25_PAD_CSI_HSYNC__CSI_HSYNC          0x148 0x340 0x000 0x10 0x000
+#define MX25_PAD_CSI_HSYNC__GPIO_1_10          0x148 0x340 0x000 0x15 0x000
+
+#define MX25_PAD_CSI_PIXCLK__CSI_PIXCLK                0x14c 0x344 0x000 0x10 0x000
+#define MX25_PAD_CSI_PIXCLK__GPIO_1_11         0x14c 0x344 0x000 0x15 0x000
+
+#define MX25_PAD_I2C1_CLK__I2C1_CLK            0x150 0x348 0x000 0x10 0x000
+#define MX25_PAD_I2C1_CLK__GPIO_1_12           0x150 0x348 0x000 0x15 0x000
+
+#define MX25_PAD_I2C1_DAT__I2C1_DAT            0x154 0x34c 0x000 0x10 0x000
+#define MX25_PAD_I2C1_DAT__GPIO_1_13           0x154 0x34c 0x000 0x15 0x000
+
+#define MX25_PAD_CSPI1_MOSI__CSPI1_MOSI                0x158 0x350 0x000 0x10 0x000
+#define MX25_PAD_CSPI1_MOSI__GPIO_1_14         0x158 0x350 0x000 0x15 0x000
+
+#define MX25_PAD_CSPI1_MISO__CSPI1_MISO                0x15c 0x354 0x000 0x10 0x000
+#define MX25_PAD_CSPI1_MISO__GPIO_1_15         0x15c 0x354 0x000 0x15 0x000
+
+#define MX25_PAD_CSPI1_SS0__CSPI1_SS0          0x160 0x358 0x000 0x10 0x000
+#define MX25_PAD_CSPI1_SS0__GPIO_1_16          0x160 0x358 0x000 0x15 0x000
+
+#define MX25_PAD_CSPI1_SS1__CSPI1_SS1          0x164 0x35c 0x000 0x10 0x000
+#define MX25_PAD_CSPI1_SS1__GPIO_1_17          0x164 0x35c 0x000 0x15 0x000
+
+#define MX25_PAD_CSPI1_SCLK__CSPI1_SCLK                0x168 0x360 0x000 0x10 0x000
+#define MX25_PAD_CSPI1_SCLK__GPIO_1_18         0x168 0x360 0x000 0x15 0x000
+
+#define MX25_PAD_CSPI1_RDY__CSPI1_RDY          0x16c 0x364 0x000 0x10 0x000
+#define MX25_PAD_CSPI1_RDY__GPIO_2_22          0x16c 0x364 0x000 0x15 0x000
+
+#define MX25_PAD_UART1_RXD__UART1_RXD          0x170 0x368 0x000 0x10 0x000
+#define MX25_PAD_UART1_RXD__GPIO_4_22          0x170 0x368 0x000 0x15 0x000
+
+#define MX25_PAD_UART1_TXD__UART1_TXD          0x174 0x36c 0x000 0x10 0x000
+#define MX25_PAD_UART1_TXD__GPIO_4_23          0x174 0x36c 0x000 0x15 0x000
+
+#define MX25_PAD_UART1_RTS__UART1_RTS          0x178 0x370 0x000 0x10 0x000
+#define MX25_PAD_UART1_RTS__CSI_D0             0x178 0x370 0x488 0x11 0x001
+#define MX25_PAD_UART1_RTS__GPIO_4_24          0x178 0x370 0x000 0x15 0x000
+
+#define MX25_PAD_UART1_CTS__UART1_CTS          0x17c 0x374 0x000 0x10 0x000
+#define MX25_PAD_UART1_CTS__CSI_D1             0x17c 0x374 0x48c 0x11 0x001
+#define MX25_PAD_UART1_CTS__GPIO_4_25          0x17c 0x374 0x000 0x15 0x000
+
+#define MX25_PAD_UART2_RXD__UART2_RXD          0x180 0x378 0x000 0x10 0x000
+#define MX25_PAD_UART2_RXD__GPIO_4_26          0x180 0x378 0x000 0x15 0x000
+
+#define MX25_PAD_UART2_TXD__UART2_TXD          0x184 0x37c 0x000 0x10 0x000
+#define MX25_PAD_UART2_TXD__GPIO_4_27          0x184 0x37c 0x000 0x15 0x000
+
+#define MX25_PAD_UART2_RTS__UART2_RTS          0x188 0x380 0x000 0x10 0x000
+#define MX25_PAD_UART2_RTS__FEC_COL            0x188 0x380 0x504 0x12 0x002
+#define MX25_PAD_UART2_RTS__GPIO_4_28          0x188 0x380 0x000 0x15 0x000
+
+#define MX25_PAD_UART2_CTS__FEC_RX_ER          0x18c 0x384 0x518 0x12 0x002
+#define MX25_PAD_UART2_CTS__UART2_CTS          0x18c 0x384 0x000 0x10 0x000
+#define MX25_PAD_UART2_CTS__GPIO_4_29          0x18c 0x384 0x000 0x15 0x000
+
+#define MX25_PAD_SD1_CMD__SD1_CMD              0x190 0x388 0x000 0x10 0x000
+#define MX25_PAD_SD1_CMD__FEC_RDATA2           0x190 0x388 0x50c 0x12 0x002
+#define MX25_PAD_SD1_CMD__GPIO_2_23            0x190 0x388 0x000 0x15 0x000
+
+#define MX25_PAD_SD1_CLK__SD1_CLK              0x194 0x38c 0x000 0x10 0x000
+#define MX25_PAD_SD1_CLK__FEC_RDATA3           0x194 0x38c 0x510 0x12 0x002
+#define MX25_PAD_SD1_CLK__GPIO_2_24            0x194 0x38c 0x000 0x15 0x000
+
+#define MX25_PAD_SD1_DATA0__SD1_DATA0          0x198 0x390 0x000 0x10 0x000
+#define MX25_PAD_SD1_DATA0__GPIO_2_25          0x198 0x390 0x000 0x15 0x000
+
+#define MX25_PAD_SD1_DATA1__SD1_DATA1          0x19c 0x394 0x000 0x10 0x000
+#define MX25_PAD_SD1_DATA1__AUD7_RXD           0x19c 0x394 0x478 0x13 0x000
+#define MX25_PAD_SD1_DATA1__GPIO_2_26          0x19c 0x394 0x000 0x15 0x000
+
+#define MX25_PAD_SD1_DATA2__SD1_DATA2          0x1a0 0x398 0x000 0x10 0x000
+#define MX25_PAD_SD1_DATA2__FEC_RX_CLK         0x1a0 0x398 0x514 0x15 0x002
+#define MX25_PAD_SD1_DATA2__GPIO_2_27          0x1a0 0x398 0x000 0x15 0x000
+
+#define MX25_PAD_SD1_DATA3__SD1_DATA3          0x1a4 0x39c 0x000 0x10 0x000
+#define MX25_PAD_SD1_DATA3__FEC_CRS            0x1a4 0x39c 0x508 0x10 0x002
+#define MX25_PAD_SD1_DATA3__GPIO_2_28          0x1a4 0x39c 0x000 0x15 0x000
+
+#define MX25_PAD_KPP_ROW0__KPP_ROW0            0x1a8 0x3a0 0x000 0x10 0x000
+#define MX25_PAD_KPP_ROW0__GPIO_2_29           0x1a8 0x3a0 0x000 0x15 0x000
+
+#define MX25_PAD_KPP_ROW1__KPP_ROW1            0x1ac 0x3a4 0x000 0x10 0x000
+#define MX25_PAD_KPP_ROW1__GPIO_2_30           0x1ac 0x3a4 0x000 0x15 0x000
+
+#define MX25_PAD_KPP_ROW2__KPP_ROW2            0x1b0 0x3a8 0x000 0x10 0x000
+#define MX25_PAD_KPP_ROW2__CSI_D0              0x1b0 0x3a8 0x488 0x13 0x002
+#define MX25_PAD_KPP_ROW2__GPIO_2_31           0x1b0 0x3a8 0x000 0x15 0x000
+
+#define MX25_PAD_KPP_ROW3__KPP_ROW3            0x1b4 0x3ac 0x000 0x10 0x000
+#define MX25_PAD_KPP_ROW3__CSI_LD1             0x1b4 0x3ac 0x48c 0x13 0x002
+#define MX25_PAD_KPP_ROW3__GPIO_3_0            0x1b4 0x3ac 0x000 0x15 0x000
+
+#define MX25_PAD_KPP_COL0__KPP_COL0            0x1b8 0x3b0 0x000 0x10 0x000
+#define MX25_PAD_KPP_COL0__UART4_RXD_MUX       0x1b8 0x3b0 0x570 0x11 0x001
+#define MX25_PAD_KPP_COL0__AUD5_TXD            0x1b8 0x3b0 0x000 0x12 0x000
+#define MX25_PAD_KPP_COL0__GPIO_3_1            0x1b8 0x3b0 0x000 0x15 0x000
+
+#define MX25_PAD_KPP_COL1__KPP_COL1            0x1bc 0x3b4 0x000 0x10 0x000
+#define MX25_PAD_KPP_COL1__UART4_TXD_MUX       0x1bc 0x3b4 0x000 0x11 0x000
+#define MX25_PAD_KPP_COL1__AUD5_RXD            0x1bc 0x3b4 0x000 0x12 0x000
+#define MX25_PAD_KPP_COL1__GPIO_3_2            0x1bc 0x3b4 0x000 0x15 0x000
+
+#define MX25_PAD_KPP_COL2__KPP_COL2            0x1c0 0x3b8 0x000 0x10 0x000
+#define MX25_PAD_KPP_COL2__UART4_RTS           0x1c0 0x3b8 0x000 0x11 0x000
+#define MX25_PAD_KPP_COL2__AUD5_TXC            0x1c0 0x3b8 0x000 0x12 0x000
+#define MX25_PAD_KPP_COL2__GPIO_3_3            0x1c0 0x3b8 0x000 0x15 0x000
+
+#define MX25_PAD_KPP_COL3__KPP_COL3            0x1c4 0x3bc 0x000 0x10 0x000
+#define MX25_PAD_KPP_COL3__UART4_CTS           0x1c4 0x3bc 0x000 0x11 0x000
+#define MX25_PAD_KPP_COL3__AUD5_TXFS           0x1c4 0x3bc 0x000 0x12 0x000
+#define MX25_PAD_KPP_COL3__GPIO_3_4            0x1c4 0x3bc 0x000 0x15 0x000
+
+#define MX25_PAD_FEC_MDC__FEC_MDC              0x1c8 0x3c0 0x000 0x10 0x000
+#define MX25_PAD_FEC_MDC__AUD4_TXD             0x1c8 0x3c0 0x464 0x12 0x001
+#define MX25_PAD_FEC_MDC__GPIO_3_5             0x1c8 0x3c0 0x000 0x15 0x000
+
+#define MX25_PAD_FEC_MDIO__FEC_MDIO            0x1cc 0x3c4 0x000 0x10 0x000
+#define MX25_PAD_FEC_MDIO__AUD4_RXD            0x1cc 0x3c4 0x460 0x12 0x001
+#define MX25_PAD_FEC_MDIO__GPIO_3_6            0x1cc 0x3c4 0x000 0x15 0x000
+
+#define MX25_PAD_FEC_TDATA0__FEC_TDATA0                0x1d0 0x3c8 0x000 0x10 0x000
+#define MX25_PAD_FEC_TDATA0__GPIO_3_7          0x1d0 0x3c8 0x000 0x15 0x000
+
+#define MX25_PAD_FEC_TDATA1__FEC_TDATA1                0x1d4 0x3cc 0x000 0x10 0x000
+#define MX25_PAD_FEC_TDATA1__AUD4_TXFS         0x1d4 0x3cc 0x474 0x12 0x001
+#define MX25_PAD_FEC_TDATA1__GPIO_3_8          0x1d4 0x3cc 0x000 0x15 0x000
+
+#define MX25_PAD_FEC_TX_EN__FEC_TX_EN          0x1d8 0x3d0 0x000 0x10 0x000
+#define MX25_PAD_FEC_TX_EN__GPIO_3_9           0x1d8 0x3d0 0x000 0x15 0x000
+
+#define MX25_PAD_FEC_RDATA0__FEC_RDATA0                0x1dc 0x3d4 0x000 0x10 0x000
+#define MX25_PAD_FEC_RDATA0__GPIO_3_10         0x1dc 0x3d4 0x000 0x15 0x000
+
+#define MX25_PAD_FEC_RDATA1__FEC_RDATA1                0x1e0 0x3d8 0x000 0x10 0x000
+#define MX25_PAD_FEC_RDATA1__GPIO_3_11         0x1e0 0x3d8 0x000 0x15 0x000
+
+#define MX25_PAD_FEC_RX_DV__FEC_RX_DV          0x1e4 0x3dc 0x000 0x10 0x000
+#define MX25_PAD_FEC_RX_DV__CAN2_RX            0x1e4 0x3dc 0x484 0x14 0x000
+#define MX25_PAD_FEC_RX_DV__GPIO_3_12          0x1e4 0x3dc 0x000 0x15 0x000
+
+#define MX25_PAD_FEC_TX_CLK__FEC_TX_CLK                0x1e8 0x3e0 0x000 0x10 0x000
+#define MX25_PAD_FEC_TX_CLK__GPIO_3_13         0x1e8 0x3e0 0x000 0x15 0x000
+
+#define MX25_PAD_RTCK__RTCK                    0x1ec 0x3e4 0x000 0x10 0x000
+#define MX25_PAD_RTCK__OWIRE                   0x1ec 0x3e4 0x000 0x11 0x000
+#define MX25_PAD_RTCK__GPIO_3_14               0x1ec 0x3e4 0x000 0x15 0x000
+
+#define MX25_PAD_DE_B__DE_B                    0x1f0 0x3ec 0x000 0x10 0x000
+#define MX25_PAD_DE_B__GPIO_2_20               0x1f0 0x3ec 0x000 0x15 0x000
+
+#define MX25_PAD_TDO__TDO                      0x000 0x3e8 0x000 0x00 0x000
+
+#define MX25_PAD_GPIO_A__GPIO_A                        0x1f4 0x3f0 0x000 0x10 0x000
+#define MX25_PAD_GPIO_A__CAN1_TX               0x1f4 0x3f0 0x000 0x16 0x000
+#define MX25_PAD_GPIO_A__USBOTG_PWR            0x1f4 0x3f0 0x000 0x12 0x000
+
+#define MX25_PAD_GPIO_B__GPIO_B                        0x1f8 0x3f4 0x000 0x10 0x000
+#define MX25_PAD_GPIO_B__CAN1_RX               0x1f8 0x3f4 0x480 0x16 0x001
+#define MX25_PAD_GPIO_B__USBOTG_OC             0x1f8 0x3f4 0x57c 0x12 0x001
+
+#define MX25_PAD_GPIO_C__GPIO_C                        0x1fc 0x3f8 0x000 0x10 0x000
+#define MX25_PAD_GPIO_C__CAN2_TX               0x1fc 0x3f8 0x000 0x16 0x000
+
+#define MX25_PAD_GPIO_D__GPIO_D                        0x200 0x3fc 0x000 0x10 0x000
+#define MX25_PAD_GPIO_E__LD16                  0x204 0x400 0x000 0x02 0x000
+#define MX25_PAD_GPIO_D__CAN2_RX               0x200 0x3fc 0x484 0x16 0x001
+
+#define MX25_PAD_GPIO_E__GPIO_E                        0x204 0x400 0x000 0x10 0x000
+#define MX25_PAD_GPIO_F__LD17                  0x208 0x404 0x000 0x02 0x000
+#define MX25_PAD_GPIO_E__AUD7_TXD              0x204 0x400 0x000 0x14 0x000
+
+#define MX25_PAD_GPIO_F__GPIO_F                        0x208 0x404 0x000 0x10 0x000
+#define MX25_PAD_GPIO_F__AUD7_TXC              0x208 0x404 0x000 0x14 0x000
+
+#define MX25_PAD_EXT_ARMCLK__EXT_ARMCLK                0x20c 0x000 0x000 0x10 0x000
+#define MX25_PAD_EXT_ARMCLK__GPIO_3_15         0x20c 0x000 0x000 0x15 0x000
+
+#define MX25_PAD_UPLL_BYPCLK__UPLL_BYPCLK      0x210 0x000 0x000 0x10 0x000
+#define MX25_PAD_UPLL_BYPCLK__GPIO_3_16                0x210 0x000 0x000 0x15 0x000
+
+#define MX25_PAD_VSTBY_REQ__VSTBY_REQ          0x214 0x408 0x000 0x10 0x000
+#define MX25_PAD_VSTBY_REQ__AUD7_TXFS          0x214 0x408 0x000 0x14 0x000
+#define MX25_PAD_VSTBY_REQ__GPIO_3_17          0x214 0x408 0x000 0x15 0x000
+#define MX25_PAD_VSTBY_ACK__VSTBY_ACK          0x218 0x40c 0x000 0x10 0x000
+#define MX25_PAD_VSTBY_ACK__GPIO_3_18          0x218 0x40c 0x000 0x15 0x000
+
+#define MX25_PAD_POWER_FAIL__POWER_FAIL                0x21c 0x410 0x000 0x10 0x000
+#define MX25_PAD_POWER_FAIL__AUD7_RXD          0x21c 0x410 0x478 0x14 0x001
+#define MX25_PAD_POWER_FAIL__GPIO_3_19         0x21c 0x410 0x000 0x15 0x000
+
+#define MX25_PAD_CLKO__CLKO                    0x220 0x414 0x000 0x10 0x000
+#define MX25_PAD_CLKO__GPIO_2_21               0x220 0x414 0x000 0x15 0x000
+
+#define MX25_PAD_BOOT_MODE0__BOOT_MODE0                0x224 0x000 0x000 0x00 0x000
+#define MX25_PAD_BOOT_MODE0__GPIO_4_30         0x224 0x000 0x000 0x05 0x000
+#define MX25_PAD_BOOT_MODE1__BOOT_MODE1                0x228 0x000 0x000 0x00 0x000
+#define MX25_PAD_BOOT_MODE1__GPIO_4_31         0x228 0x000 0x000 0x05 0x000
+
+#endif /* __DTS_IMX25_PINFUNC_H */
diff --git a/arch/arm/boot/dts/imx25-pingrp.h b/arch/arm/boot/dts/imx25-pingrp.h
new file mode 100644 (file)
index 0000000..4a35a63
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2013 Eukréa Electromatique <denis@eukrea.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __DTS_IMX25_PINGRP_H
+#define __DTS_IMX25_PINGRP_H
+
+#include "imx25-pinfunc.h"
+
+#define MX25_AUDMUX_PINGRP1 \
+       MX25_PAD_KPP_COL3__AUD5_TXFS                    0xe0 \
+       MX25_PAD_KPP_COL2__AUD5_TXC                     0xe0 \
+       MX25_PAD_KPP_COL1__AUD5_RXD                     0xe0 \
+       MX25_PAD_KPP_COL0__AUD5_TXD                     0xe0
+
+#define MX25_ESDHC1_PINGRP1 \
+       MX25_PAD_SD1_CMD__SD1_CMD                       0x400000c0 \
+       MX25_PAD_SD1_CLK__SD1_CLK                       0x400000c0 \
+       MX25_PAD_SD1_DATA0__SD1_DATA0                   0x400000c0 \
+       MX25_PAD_SD1_DATA1__SD1_DATA1                   0x400000c0 \
+       MX25_PAD_SD1_DATA2__SD1_DATA2                   0x400000c0 \
+       MX25_PAD_SD1_DATA3__SD1_DATA3                   0x400000c0
+
+#define MX25_FEC_PINGRP1 \
+       MX25_PAD_FEC_MDC__FEC_MDC                       0x80000000 \
+       MX25_PAD_FEC_MDIO__FEC_MDIO                     0x400001e0 \
+       MX25_PAD_FEC_TDATA0__FEC_TDATA0                 0x80000000 \
+       MX25_PAD_FEC_TDATA1__FEC_TDATA1                 0x80000000 \
+       MX25_PAD_FEC_TX_EN__FEC_TX_EN                   0x80000000 \
+       MX25_PAD_FEC_RDATA0__FEC_RDATA0                 0x80000000 \
+       MX25_PAD_FEC_RDATA1__FEC_RDATA1                 0x80000000 \
+       MX25_PAD_FEC_RX_DV__FEC_RX_DV                   0x80000000 \
+       MX25_PAD_FEC_TX_CLK__FEC_TX_CLK                 0x1c0
+
+#define MX25_I2C1_PINGRP1 \
+       MX25_PAD_I2C1_CLK__I2C1_CLK                     0x80000000 \
+       MX25_PAD_I2C1_DAT__I2C1_DAT                     0x80000000
+
+#define MX25_LCDC_PINGRP1 \
+       MX25_PAD_LD0__LD0                               0x1 \
+       MX25_PAD_LD1__LD1                               0x1 \
+       MX25_PAD_LD2__LD2                               0x1 \
+       MX25_PAD_LD3__LD3                               0x1 \
+       MX25_PAD_LD4__LD4                               0x1 \
+       MX25_PAD_LD5__LD5                               0x1 \
+       MX25_PAD_LD6__LD6                               0x1 \
+       MX25_PAD_LD7__LD7                               0x1 \
+       MX25_PAD_LD8__LD8                               0x1 \
+       MX25_PAD_LD9__LD9                               0x1 \
+       MX25_PAD_LD10__LD10                             0x1 \
+       MX25_PAD_LD11__LD11                             0x1 \
+       MX25_PAD_LD12__LD12                             0x1 \
+       MX25_PAD_LD13__LD13                             0x1 \
+       MX25_PAD_LD14__LD14                             0x1 \
+       MX25_PAD_LD15__LD15                             0x1 \
+       MX25_PAD_GPIO_E__LD16                           0x1 \
+       MX25_PAD_GPIO_F__LD17                           0x1 \
+       MX25_PAD_HSYNC__HSYNC                           0x80000000 \
+       MX25_PAD_VSYNC__VSYNC                           0x80000000 \
+       MX25_PAD_LSCLK__LSCLK                           0x80000000 \
+       MX25_PAD_OE_ACD__OE_ACD                         0x80000000 \
+       MX25_PAD_CONTRAST__CONTRAST                     0x80000000
+
+#define MX25_UART1_PINGRP1 \
+       MX25_PAD_UART1_RTS__UART1_RTS                   0xe0 \
+       MX25_PAD_UART1_CTS__UART1_CTS                   0xe0 \
+       MX25_PAD_UART1_TXD__UART1_TXD                   0x80000000 \
+       MX25_PAD_UART1_RXD__UART1_RXD                   0xc0
+
+#define MX25_UART2_PINGRP1 \
+       MX25_PAD_UART2_RXD__UART2_RXD                   0x80000000 \
+       MX25_PAD_UART2_TXD__UART2_TXD                   0x80000000 \
+       MX25_PAD_UART2_RTS__UART2_RTS                   0x80000000 \
+       MX25_PAD_UART2_CTS__UART2_CTS                   0x80000000
+
+#endif /* __DTS_IMX25_PINGRP_H */
index 737ed5da8f715fec5180c60a6bdd33e9c6fefc9a..9e9e3b8a690b913cf46ba8edda925561847f8a29 100644 (file)
@@ -10,6 +10,7 @@
  */
 
 #include "skeleton.dtsi"
+#include "imx25-pingrp.h"
 
 / {
        aliases {
                                status = "disabled";
                        };
 
-                       iomuxc@43fac000{
+                       iomuxc: iomuxc@43fac000 {
                                compatible = "fsl,imx25-iomuxc";
                                reg = <0x43fac000 0x4000>;
                        };
 
-                       audmux@43fb0000 {
+                       audmux: audmux@43fb0000 {
                                compatible = "fsl,imx25-audmux", "fsl,imx31-audmux";
                                reg = <0x43fb0000 0x4000>;
                                status = "disabled";
                                compatible = "fsl,imx25-ssi", "fsl,imx21-ssi";
                                reg = <0x50014000 0x4000>;
                                interrupts = <11>;
+                               clocks = <&clks 118>;
+                               clock-names = "ipg";
+                               dmas = <&sdma 24 1 0>,
+                                      <&sdma 25 1 0>;
+                               dma-names = "rx", "tx";
                                status = "disabled";
                        };
 
                                compatible = "fsl,imx25-ssi", "fsl,imx21-ssi";
                                reg = <0x50034000 0x4000>;
                                interrupts = <12>;
+                               clocks = <&clks 117>;
+                               clock-names = "ipg";
+                               dmas = <&sdma 28 1 0>,
+                                      <&sdma 29 1 0>;
+                               dma-names = "rx", "tx";
                                status = "disabled";
                        };
 
                                #interrupt-cells = <2>;
                        };
 
-                       sdma@53fd4000 {
+                       sdma: sdma@53fd4000 {
                                compatible = "fsl,imx25-sdma", "fsl,imx35-sdma";
                                reg = <0x53fd4000 0x4000>;
                                clocks = <&clks 112>, <&clks 68>;
                                clock-names = "ipg", "ahb";
                                #dma-cells = <3>;
                                interrupts = <34>;
+                               fsl,sdma-ram-script-name = "imx/sdma/sdma-imx25.bin";
                        };
 
                        wdog@53fdc000 {
index ba4c6df08ece2ec6e4cd0ce05437b61ffe407b2d..8bc75c70ec10128caa38ed6b1cdbdf4a9ae90964 100644 (file)
        };
 };
 
+&iomuxc {
+       imx27-apf27 {
+               pinctrl_fec1: fec1grp {
+                       fsl,pins = <MX27_FEC1_PINGRP1>;
+               };
+
+               pinctrl_uart1: uart1grp {
+                       fsl,pins = <MX27_UART1_PINGRP1>;
+               };
+       };
+};
+
 &uart1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart1>;
        status = "okay";
 };
 
 &fec {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_fec1>;
        status = "okay";
 };
 
index 47c8c26012e4d24661124f15ff8396f428136797..2555d80d1750b21733335010558002c8d1d2222b 100644 (file)
                bits-per-pixel = <16>;  /* non-standard but required */
                fsl,pcr = <0xfae80083>; /* non-standard but required */
                display-timings {
-                       timing0: 640x480 {
+                       timing0: 800x480 {
                                clock-frequency = <33000033>;
                                hactive = <800>;
-                               vactive = <640>;
+                               vactive = <480>;
                                hback-porch = <96>;
                                hfront-porch = <96>;
                                vback-porch = <20>;
 
        gpio-keys {
                compatible = "gpio-keys";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_gpio_keys>;
 
                user-key {
                        label = "user";
-                       gpios = <&gpio6 13 0>;
+                       gpios = <&gpio6 13 GPIO_ACTIVE_HIGH>;
                        linux,code = <276>; /* BTN_EXTRA */
                };
        };
 
        leds {
                compatible = "gpio-leds";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_gpio_leds>;
 
                user {
                        label = "Heartbeat";
-                       gpios = <&gpio6 14 0>;
+                       gpios = <&gpio6 14 GPIO_ACTIVE_HIGH>;
                        linux,default-trigger = "heartbeat";
                };
        };
 
 &cspi1 {
        fsl,spi-num-chipselects = <1>;
-       cs-gpios = <&gpio4 28 1>;
+       cs-gpios = <&gpio4 28 GPIO_ACTIVE_LOW>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_cspi1 &pinctrl_cspi1_cs>;
        status = "okay";
 };
 
 &cspi2 {
        fsl,spi-num-chipselects = <3>;
-       cs-gpios = <&gpio4 21 1>, <&gpio4 27 1>,
-                       <&gpio2 17 1>;
+       cs-gpios = <&gpio4 21 GPIO_ACTIVE_LOW>,
+                  <&gpio4 27 GPIO_ACTIVE_LOW>,
+                  <&gpio2 17 GPIO_ACTIVE_LOW>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_cspi2 &pinctrl_cspi2_cs>;
        status = "okay";
 };
 
 &fb {
        display = <&display>;
        fsl,dmacr = <0x00020010>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_imxfb1>;
        status = "okay";
 };
 
 &i2c1 {
        clock-frequency = <400000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c1>;
        status = "okay";
 
        rtc@68 {
 };
 
 &i2c2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c2>;
        status = "okay";
 };
+
+&iomuxc {
+       imx27-apf27dev {
+               pinctrl_cspi1: cspi1grp {
+                       fsl,pins = <MX27_CSPI1_PINGRP1>;
+               };
+
+               pinctrl_cspi1_cs: cspi1csgrp {
+                       fsl,pins = <MX27_PAD_CSPI1_SS0__GPIO4_28 0x0>;
+               };
+
+               pinctrl_cspi2: cspi2grp {
+                       fsl,pins = <MX27_CSPI2_PINGRP1>;
+               };
+
+               pinctrl_cspi2_cs: cspi2csgrp {
+                       fsl,pins = <
+                               MX27_PAD_CSI_D5__GPIO2_17 0x0
+                               MX27_PAD_CSPI2_SS0__GPIO4_21 0x0
+                               MX27_PAD_CSPI1_SS1__GPIO4_27 0x0
+                       >;
+               };
+
+               pinctrl_gpio_leds: gpioledsgrp {
+                       fsl,pins = <MX27_PAD_PC_VS1__GPIO6_14 0x0>;
+               };
+
+               pinctrl_gpio_keys: gpiokeysgrp {
+                       fsl,pins = <MX27_PAD_PC_VS2__GPIO6_13 0x0>;
+               };
+
+               pinctrl_imxfb1: imxfbgrp {
+                       fsl,pins = <MX27_FB_PINGRP1>;
+               };
+
+               pinctrl_i2c1: i2c1grp {
+                       fsl,pins = <MX27_I2C1_PINGRP1>;
+               };
+
+               pinctrl_i2c2: i2c2grp {
+                       fsl,pins = <MX27_I2C2_PINGRP1>;
+               };
+
+               pinctrl_pwm: pwmgrp {
+                       fsl,pins = <MX27_PWM_PINGRP1>;
+               };
+
+               pinctrl_sdhc2: sdhc2grp {
+                       fsl,pins = <MX27_SDHC2_PINGRP1>;
+               };
+
+               pinctrl_sdhc2_cd: sdhc2cdgrp {
+                       fsl,pins = <MX27_PAD_TOUT__GPIO3_14 0x0>;
+               };
+       };
+};
+
+&sdhci2 {
+       bus-width = <4>;
+       cd-gpios = <&gpio3 14 GPIO_ACTIVE_HIGH>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_sdhc2 &pinctrl_sdhc2_cd>;
+       status = "okay";
+};
+
+&pwm {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_pwm>;
+};
index 5a31c776513f5705e94a5f1a5f306740e898c201..0d65023968cc56d2f2242c60e897ab2cfeae512d 100644 (file)
 
        regulators {
                compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
 
-               reg_3v3: 3v3 {
+               reg_3v3: regulator@0 {
                        compatible = "regulator-fixed";
+                       reg = <0>;
                        regulator-name = "3V3";
                        regulator-min-microvolt = <3300000>;
                        regulator-max-microvolt = <3300000>;
@@ -54,6 +57,8 @@
 };
 
 &i2c1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c1>;
        status = "okay";
 
        rtc@51 {
        };
 };
 
+&iomuxc {
+       imx27-phycard-s-rdk {
+               pinctrl_i2c1: i2c1grp {
+                       fsl,pins = <MX27_I2C2_PINGRP1>;
+               };
+
+               pinctrl_owire1: owire1grp {
+                       fsl,pins = <MX27_OWIRE1_PINGRP1>;
+               };
+
+               pinctrl_uart1: uart1grp {
+                       fsl,pins = <
+                               MX27_UART1_PINGRP1
+                               MX27_UART1_RTSCTS_PINGRP1
+                       >;
+               };
+
+               pinctrl_uart2: uart2grp {
+                       fsl,pins = <
+                               MX27_UART2_PINGRP1
+                               MX27_UART2_RTSCTS_PINGRP1
+                       >;
+               };
+
+               pinctrl_uart3: uart3grp {
+                       fsl,pins = <
+                               MX27_UART3_PINGRP1
+                               MX27_UART3_RTSCTS_PINGRP1
+                       >;
+               };
+       };
+};
+
 &owire {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_owire1>;
        status = "okay";
 };
 
 &sdhci2 {
-       cd-gpios = <&gpio3 29 0>;
+       cd-gpios = <&gpio3 29 GPIO_ACTIVE_HIGH>;
        status = "okay";
 };
 
 &uart1 {
        fsl,uart-has-rtscts;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart1>;
        status = "okay";
 };
 
 &uart2 {
        fsl,uart-has-rtscts;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart2>;
        status = "okay";
 };
 
 &uart3 {
        fsl,uart-has-rtscts;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart3>;
        status = "okay";
 };
index c8d57d1d074362e14c91113cc8cbf42079724ffe..db8c09511f571260a6b9909832400bfc8e018fbe 100644 (file)
 
 &cspi1 {
        fsl,spi-num-chipselects = <2>;
-       cs-gpios = <&gpio4 28 0>,
-               <&gpio4 27 0>;
+       cs-gpios = <&gpio4 28 GPIO_ACTIVE_HIGH>,
+                  <&gpio4 27 GPIO_ACTIVE_HIGH>;
        status = "okay";
 };
 
+&iomuxc {
+       imx27-phycard-s-som {
+               pinctrl_fec1: fec1grp {
+                       fsl,pins = <MX27_FEC1_PINGRP1>;
+               };
+
+               pinctrl_i2c2: i2c2grp {
+                       fsl,pins = <MX27_I2C2_PINGRP1>;
+               };
+       };
+};
+
 &fec {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_fec1>;
        status = "okay";
 };
 
 &i2c2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c2>;
        status = "okay";
 
        at24@52 {
index 0fc6551786c6817216045c8ddfc86a6c5790d58e..7ada054c82e6f27e2c8a24e95df051b1e2d50632 100644 (file)
@@ -7,7 +7,7 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
-#include "imx27-phytec-phycore-som.dts"
+#include "imx27-phytec-phycore-som.dtsi"
 
 / {
        model = "Phytec pcm970";
 
 &cspi1 {
        fsl,spi-num-chipselects = <2>;
-       cs-gpios = <&gpio4 28 0>, <&gpio4 27 0>;
+       cs-gpios = <&gpio4 28 GPIO_ACTIVE_HIGH>,
+                  <&gpio4 27 GPIO_ACTIVE_LOW>;
+};
+
+&i2c1 {
+       clock-frequency = <400000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c1>;
+       status = "okay";
+
+       camgpio: pca9536@41 {
+               compatible = "nxp,pca9536";
+               reg = <0x41>;
+               gpio-controller;
+               #gpio-cells = <2>;
+       };
+};
+
+&iomuxc {
+       imx27_phycore_rdk {
+               pinctrl_i2c1: i2c1grp {
+                       /* Add pullup to DATA line */
+                       fsl,pins = <
+                               MX27_PAD_I2C_DATA__I2C_DATA     0x1
+                               MX27_PAD_I2C_CLK__I2C_CLK       0x0
+                       >;
+               };
+
+               pinctrl_uart1: uart1grp {
+                       fsl,pins = <
+                               MX27_UART1_PINGRP1
+                               MX27_UART1_RTSCTS_PINGRP1
+                       >;
+               };
+
+               pinctrl_uart2: uart2grp {
+                       fsl,pins = <
+                               MX27_UART2_PINGRP1
+                               MX27_UART2_RTSCTS_PINGRP1
+                       >;
+               };
+       };
 };
 
 &sdhci2 {
        bus-width = <4>;
-       cd-gpios = <&gpio3 29 0>;
-       wp-gpios = <&gpio3 28 0>;
+       cd-gpios = <&gpio3 29 GPIO_ACTIVE_HIGH>;
+       wp-gpios = <&gpio3 28 GPIO_ACTIVE_HIGH>;
        vmmc-supply = <&vmmc1_reg>;
        status = "okay";
 };
 
 &uart1 {
        fsl,uart-has-rtscts;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart1>;
+       status = "okay";
 };
 
 &uart2 {
        fsl,uart-has-rtscts;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart2>;
        status = "okay";
 };
 
@@ -41,7 +87,7 @@
                compatible = "nxp,sja1000";
                reg = <4 0x00000000 0x00000100>;
                interrupt-parent = <&gpio5>;
-               interrupts = <19 0x2>;
+               interrupts = <19 IRQ_TYPE_EDGE_FALLING>;
                nxp,external-clock-frequency = <16000000>;
                nxp,tx-output-config = <0x16>;
                nxp,no-comparator-bypass;
similarity index 77%
rename from arch/arm/boot/dts/imx27-phytec-phycore-som.dts
rename to arch/arm/boot/dts/imx27-phytec-phycore-som.dtsi
index 4ec402c389457f6e5416dc573459127fd4128de7..7087a4f920ef1d32905782da3d00977b450f1385 100644 (file)
        memory {
                reg = <0xa0000000 0x08000000>;
        };
+
+       regulators {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               reg_3v3: regulator@0 {
+                       compatible = "regulator-fixed";
+                       reg = <0>;
+                       regulator-name = "3V3";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+               };
+       };
 };
 
 &audmux {
 };
 
 &cspi1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_cspi1>;
        fsl,spi-num-chipselects = <1>;
-       cs-gpios = <&gpio4 28 0>;
+       cs-gpios = <&gpio4 28 GPIO_ACTIVE_HIGH>;
        status = "okay";
 
        pmic: mc13783@0 {
@@ -48,7 +64,7 @@
                spi-max-frequency = <20000000>;
                reg = <0>;
                interrupt-parent = <&gpio2>;
-               interrupts = <23 0x4>;
+               interrupts = <23 IRQ_TYPE_LEVEL_HIGH>;
                fsl,mc13xxx-uses-adc;
                fsl,mc13xxx-uses-rtc;
 
 };
 
 &fec {
-       phy-reset-gpios = <&gpio3 30 0>;
+       phy-mode = "mii";
+       phy-reset-gpios = <&gpio3 30 GPIO_ACTIVE_HIGH>;
+       phy-supply = <&reg_3v3>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_fec1>;
        status = "okay";
 };
 
 &i2c2 {
        clock-frequency = <400000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c2>;
        status = "okay";
 
        at24@52 {
        };
 };
 
+&iomuxc {
+       imx27_phycore_som {
+               pinctrl_cspi1: cspi1grp {
+                       fsl,pins = <
+                               MX27_CSPI1_PINGRP1
+                               MX27_PAD_CSPI1_SS0__GPIO4_28    0x0 /* SPI1 CS0 */
+                               MX27_PAD_USB_PWR__GPIO2_23      0x0 /* PMIC IRQ */
+                       >;
+               };
+
+               pinctrl_fec1: fec1grp {
+                       fsl,pins = <
+                               MX27_FEC1_PINGRP1
+                               MX27_PAD_SSI3_TXDAT__GPIO3_30   0x0 /* FEC RST */
+                       >;
+               };
+
+               pinctrl_i2c2: i2c2grp {
+                       fsl,pins = <MX27_I2C2_PINGRP1>;
+               };
+       };
+};
+
 &nfc {
        nand-bus-width = <8>;
        nand-ecc-mode = "hw";
-       status = "okay";
-};
-
-&uart1 {
+       nand-on-flash-bbt;
        status = "okay";
 };
 
diff --git a/arch/arm/boot/dts/imx27-pinfunc.h b/arch/arm/boot/dts/imx27-pinfunc.h
new file mode 100644 (file)
index 0000000..f5387b4
--- /dev/null
@@ -0,0 +1,526 @@
+/*
+ * Copyright 2013 Markus Pargmann <mpa@pengutronix.de>, Pengutronix
+ *
+ * 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 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef __DTS_IMX27_PINFUNC_H
+#define __DTS_IMX27_PINFUNC_H
+
+/*
+ * The pin function ID is a tuple of
+ * <pin mux_id>
+ * mux_id consists of
+ * function + (direction << 2) + (gpio_oconf << 4) + (gpio_iconfa << 8) + (gpio_iconfb << 10)
+ *
+ * function:      0 - Primary function
+ *                1 - Alternate function
+ *                2 - GPIO
+ * direction:     0 - Input
+ *                1 - Output
+ * gpio_oconf:    0 - A_IN
+ *                1 - B_IN
+ *                2 - C_IN
+ *                3 - Data Register
+ * gpio_iconfa/b: 0 - GPIO_IN
+ *                1 - Interrupt Status Register
+ *                2 - 0
+ *                3 - 1
+ *
+ * 'pin' is an integer between 0 and 0xbf. imx27 has 6 ports with 32 configurable
+ * configurable pins each. 'pin' is PORT * 32 + PORT_PIN, PORT_PIN is the pin
+ * number on the specific port (between 0 and 31).
+ */
+
+#define MX27_PAD_USBH2_CLK__USBH2_CLK                      0x00 0x000
+#define MX27_PAD_USBH2_CLK__GPIO1_0                        0x00 0x032
+#define MX27_PAD_USBH2_DIR__USBH2_DIR                      0x01 0x000
+#define MX27_PAD_USBH2_DIR__GPIO1_1                        0x01 0x032
+#define MX27_PAD_USBH2_DATA7__USBH2_DATA7                  0x02 0x004
+#define MX27_PAD_USBH2_DATA7__GPIO1_2                      0x02 0x032
+#define MX27_PAD_USBH2_NXT__USBH2_NXT                      0x03 0x000
+#define MX27_PAD_USBH2_NXT__GPIO1_3                        0x03 0x032
+#define MX27_PAD_USBH2_STP__USBH2_STP                      0x04 0x004
+#define MX27_PAD_USBH2_STP__GPIO1_4                        0x04 0x032
+#define MX27_PAD_LSCLK__LSCLK                              0x05 0x004
+#define MX27_PAD_LSCLK__GPIO1_5                            0x05 0x032
+#define MX27_PAD_LD0__LD0                                  0x06 0x004
+#define MX27_PAD_LD0__GPIO1_6                              0x06 0x032
+#define MX27_PAD_LD1__LD1                                  0x07 0x004
+#define MX27_PAD_LD1__GPIO1_7                              0x07 0x032
+#define MX27_PAD_LD2__LD2                                  0x08 0x004
+#define MX27_PAD_LD2__GPIO1_8                              0x08 0x032
+#define MX27_PAD_LD3__LD3                                  0x09 0x004
+#define MX27_PAD_LD3__GPIO1_9                              0x09 0x032
+#define MX27_PAD_LD4__LD4                                  0x0a 0x004
+#define MX27_PAD_LD4__GPIO1_10                             0x0a 0x032
+#define MX27_PAD_LD5__LD5                                  0x0b 0x004
+#define MX27_PAD_LD5__GPIO1_11                             0x0b 0x032
+#define MX27_PAD_LD6__LD6                                  0x0c 0x004
+#define MX27_PAD_LD6__GPIO1_12                             0x0c 0x032
+#define MX27_PAD_LD7__LD7                                  0x0d 0x004
+#define MX27_PAD_LD7__GPIO1_13                             0x0d 0x032
+#define MX27_PAD_LD8__LD8                                  0x0e 0x004
+#define MX27_PAD_LD8__GPIO1_14                             0x0e 0x032
+#define MX27_PAD_LD9__LD9                                  0x0f 0x004
+#define MX27_PAD_LD9__GPIO1_15                             0x0f 0x032
+#define MX27_PAD_LD10__LD10                                0x10 0x004
+#define MX27_PAD_LD10__GPIO1_16                            0x10 0x032
+#define MX27_PAD_LD11__LD11                                0x11 0x004
+#define MX27_PAD_LD11__GPIO1_17                            0x11 0x032
+#define MX27_PAD_LD12__LD12                                0x12 0x004
+#define MX27_PAD_LD12__GPIO1_18                            0x12 0x032
+#define MX27_PAD_LD13__LD13                                0x13 0x004
+#define MX27_PAD_LD13__GPIO1_19                            0x13 0x032
+#define MX27_PAD_LD14__LD14                                0x14 0x004
+#define MX27_PAD_LD14__GPIO1_20                            0x14 0x032
+#define MX27_PAD_LD15__LD15                                0x15 0x004
+#define MX27_PAD_LD15__GPIO1_21                            0x15 0x032
+#define MX27_PAD_LD16__LD16                                0x16 0x004
+#define MX27_PAD_LD16__GPIO1_22                            0x16 0x032
+#define MX27_PAD_LD17__LD17                                0x17 0x004
+#define MX27_PAD_LD17__GPIO1_23                            0x17 0x032
+#define MX27_PAD_REV__REV                                  0x18 0x004
+#define MX27_PAD_REV__GPIO1_24                             0x18 0x032
+#define MX27_PAD_CLS__CLS                                  0x19 0x004
+#define MX27_PAD_CLS__GPIO1_25                             0x19 0x032
+#define MX27_PAD_PS__PS                                    0x1a 0x004
+#define MX27_PAD_PS__GPIO1_26                              0x1a 0x032
+#define MX27_PAD_SPL_SPR__SPL_SPR                          0x1b 0x004
+#define MX27_PAD_SPL_SPR__GPIO1_27                         0x1b 0x032
+#define MX27_PAD_HSYNC__HSYNC                              0x1c 0x004
+#define MX27_PAD_HSYNC__GPIO1_28                           0x1c 0x032
+#define MX27_PAD_VSYNC__VSYNC                              0x1d 0x004
+#define MX27_PAD_VSYNC__GPIO1_29                           0x1d 0x032
+#define MX27_PAD_CONTRAST__CONTRAST                        0x1e 0x004
+#define MX27_PAD_CONTRAST__GPIO1_30                        0x1e 0x032
+#define MX27_PAD_OE_ACD__OE_ACD                            0x1f 0x004
+#define MX27_PAD_OE_ACD__GPIO1_31                          0x1f 0x032
+#define MX27_PAD_UNUSED0__UNUSED0                          0x20 0x004
+#define MX27_PAD_UNUSED0__GPIO2_0                          0x20 0x032
+#define MX27_PAD_UNUSED1__UNUSED1                          0x21 0x004
+#define MX27_PAD_UNUSED1__GPIO2_1                          0x21 0x032
+#define MX27_PAD_UNUSED2__UNUSED2                          0x22 0x004
+#define MX27_PAD_UNUSED2__GPIO2_2                          0x22 0x032
+#define MX27_PAD_UNUSED3__UNUSED3                          0x23 0x004
+#define MX27_PAD_UNUSED3__GPIO2_3                          0x23 0x032
+#define MX27_PAD_SD2_D0__SD2_D0                            0x24 0x004
+#define MX27_PAD_SD2_D0__MSHC_DATA0                        0x24 0x005
+#define MX27_PAD_SD2_D0__GPIO2_4                           0x24 0x032
+#define MX27_PAD_SD2_D1__SD2_D1                            0x25 0x004
+#define MX27_PAD_SD2_D1__MSHC_DATA1                        0x25 0x005
+#define MX27_PAD_SD2_D1__GPIO2_5                           0x25 0x032
+#define MX27_PAD_SD2_D2__SD2_D2                            0x26 0x004
+#define MX27_PAD_SD2_D2__MSHC_DATA2                        0x26 0x005
+#define MX27_PAD_SD2_D2__GPIO2_6                           0x26 0x032
+#define MX27_PAD_SD2_D3__SD2_D3                            0x27 0x004
+#define MX27_PAD_SD2_D3__MSHC_DATA3                        0x27 0x005
+#define MX27_PAD_SD2_D3__GPIO2_7                           0x27 0x032
+#define MX27_PAD_SD2_CMD__SD2_CMD                          0x28 0x004
+#define MX27_PAD_SD2_CMD__MSHC_BS                          0x28 0x005
+#define MX27_PAD_SD2_CMD__GPIO2_8                          0x28 0x032
+#define MX27_PAD_SD2_CLK__SD2_CLK                          0x29 0x004
+#define MX27_PAD_SD2_CLK__MSHC_SCLK                        0x29 0x005
+#define MX27_PAD_SD2_CLK__GPIO2_9                          0x29 0x032
+#define MX27_PAD_CSI_D0__CSI_D0                            0x2a 0x000
+#define MX27_PAD_CSI_D0__UART6_TXD                         0x2a 0x005
+#define MX27_PAD_CSI_D0__GPIO2_10                          0x2a 0x032
+#define MX27_PAD_CSI_D1__CSI_D1                            0x2b 0x000
+#define MX27_PAD_CSI_D1__UART6_RXD                         0x2b 0x001
+#define MX27_PAD_CSI_D1__GPIO2_11                          0x2b 0x032
+#define MX27_PAD_CSI_D2__CSI_D2                            0x2c 0x000
+#define MX27_PAD_CSI_D2__UART6_CTS                         0x2c 0x005
+#define MX27_PAD_CSI_D2__GPIO2_12                          0x2c 0x032
+#define MX27_PAD_CSI_D3__CSI_D3                            0x2d 0x000
+#define MX27_PAD_CSI_D3__UART6_RTS                         0x2d 0x001
+#define MX27_PAD_CSI_D3__GPIO2_13                          0x2d 0x032
+#define MX27_PAD_CSI_D4__CSI_D4                            0x2e 0x000
+#define MX27_PAD_CSI_D4__GPIO2_14                          0x2e 0x032
+#define MX27_PAD_CSI_MCLK__CSI_MCLK                        0x2f 0x004
+#define MX27_PAD_CSI_MCLK__GPIO2_15                        0x2f 0x032
+#define MX27_PAD_CSI_PIXCLK__CSI_PIXCLK                    0x30 0x000
+#define MX27_PAD_CSI_PIXCLK__GPIO2_16                      0x30 0x032
+#define MX27_PAD_CSI_D5__CSI_D5                            0x31 0x000
+#define MX27_PAD_CSI_D5__GPIO2_17                          0x31 0x032
+#define MX27_PAD_CSI_D6__CSI_D6                            0x32 0x000
+#define MX27_PAD_CSI_D6__UART5_TXD                         0x32 0x005
+#define MX27_PAD_CSI_D6__GPIO2_18                          0x32 0x032
+#define MX27_PAD_CSI_D7__CSI_D7                            0x33 0x000
+#define MX27_PAD_CSI_D7__UART5_RXD                         0x33 0x001
+#define MX27_PAD_CSI_D7__GPIO2_19                          0x33 0x032
+#define MX27_PAD_CSI_VSYNC__CSI_VSYNC                      0x34 0x000
+#define MX27_PAD_CSI_VSYNC__UART5_CTS                      0x34 0x005
+#define MX27_PAD_CSI_VSYNC__GPIO2_20                       0x34 0x032
+#define MX27_PAD_CSI_HSYNC__CSI_HSYNC                      0x35 0x000
+#define MX27_PAD_CSI_HSYNC__UART5_RTS                      0x35 0x001
+#define MX27_PAD_CSI_HSYNC__GPIO2_21                       0x35 0x032
+#define MX27_PAD_USBH1_SUSP__USBH1_SUSP                    0x36 0x004
+#define MX27_PAD_USBH1_SUSP__GPIO2_22                      0x36 0x032
+#define MX27_PAD_USB_PWR__USB_PWR                          0x37 0x004
+#define MX27_PAD_USB_PWR__GPIO2_23                         0x37 0x032
+#define MX27_PAD_USB_OC_B__USB_OC_B                        0x38 0x000
+#define MX27_PAD_USB_OC_B__GPIO2_24                        0x38 0x032
+#define MX27_PAD_USBH1_RCV__USBH1_RCV                      0x39 0x004
+#define MX27_PAD_USBH1_RCV__GPIO2_25                       0x39 0x032
+#define MX27_PAD_USBH1_FS__USBH1_FS                        0x3a 0x004
+#define MX27_PAD_USBH1_FS__UART4_RTS                       0x3a 0x001
+#define MX27_PAD_USBH1_FS__GPIO2_26                        0x3a 0x032
+#define MX27_PAD_USBH1_OE_B__USBH1_OE_B                    0x3b 0x004
+#define MX27_PAD_USBH1_OE_B__GPIO2_27                      0x3b 0x032
+#define MX27_PAD_USBH1_TXDM__USBH1_TXDM                    0x3c 0x004
+#define MX27_PAD_USBH1_TXDM__UART4_TXD                     0x3c 0x005
+#define MX27_PAD_USBH1_TXDM__GPIO2_28                      0x3c 0x032
+#define MX27_PAD_USBH1_TXDP__USBH1_TXDP                    0x3d 0x004
+#define MX27_PAD_USBH1_TXDP__UART4_CTS                     0x3d 0x005
+#define MX27_PAD_USBH1_TXDP__GPIO2_29                      0x3d 0x032
+#define MX27_PAD_USBH1_RXDM__USBH1_RXDM                    0x3e 0x004
+#define MX27_PAD_USBH1_RXDM__GPIO2_30                      0x3e 0x032
+#define MX27_PAD_USBH1_RXDP__USBH1_RXDP                    0x3f 0x004
+#define MX27_PAD_USBH1_RXDP__UART4_RXD                     0x3f 0x001
+#define MX27_PAD_USBH1_RXDP__GPIO2_31                      0x3f 0x032
+#define MX27_PAD_UNUSED4__UNUSED4                          0x40 0x004
+#define MX27_PAD_UNUSED4__GPIO3_0                          0x40 0x032
+#define MX27_PAD_UNUSED5__UNUSED5                          0x41 0x004
+#define MX27_PAD_UNUSED5__GPIO3_1                          0x41 0x032
+#define MX27_PAD_UNUSED6__UNUSED6                          0x42 0x004
+#define MX27_PAD_UNUSED6__GPIO3_2                          0x42 0x032
+#define MX27_PAD_UNUSED7__UNUSED7                          0x43 0x004
+#define MX27_PAD_UNUSED7__GPIO3_3                          0x43 0x032
+#define MX27_PAD_UNUSED8__UNUSED8                          0x44 0x004
+#define MX27_PAD_UNUSED8__GPIO3_4                          0x44 0x032
+#define MX27_PAD_I2C2_SDA__I2C2_SDA                        0x45 0x004
+#define MX27_PAD_I2C2_SDA__GPIO3_5                         0x45 0x032
+#define MX27_PAD_I2C2_SCL__I2C2_SCL                        0x46 0x004
+#define MX27_PAD_I2C2_SCL__GPIO3_6                         0x46 0x032
+#define MX27_PAD_USBOTG_DATA5__USBOTG_DATA5                0x47 0x004
+#define MX27_PAD_USBOTG_DATA5__GPIO3_7                     0x47 0x032
+#define MX27_PAD_USBOTG_DATA6__USBOTG_DATA6                0x48 0x004
+#define MX27_PAD_USBOTG_DATA6__GPIO3_8                     0x48 0x032
+#define MX27_PAD_USBOTG_DATA0__USBOTG_DATA0                0x49 0x004
+#define MX27_PAD_USBOTG_DATA0__GPIO3_9                     0x49 0x032
+#define MX27_PAD_USBOTG_DATA2__USBOTG_DATA2                0x4a 0x004
+#define MX27_PAD_USBOTG_DATA2__GPIO3_10                    0x4a 0x032
+#define MX27_PAD_USBOTG_DATA1__USBOTG_DATA1                0x4b 0x004
+#define MX27_PAD_USBOTG_DATA1__GPIO3_11                    0x4b 0x032
+#define MX27_PAD_USBOTG_DATA4__USBOTG_DATA4                0x4c 0x004
+#define MX27_PAD_USBOTG_DATA4__GPIO3_12                    0x4c 0x032
+#define MX27_PAD_USBOTG_DATA3__USBOTG_DATA3                0x4d 0x004
+#define MX27_PAD_USBOTG_DATA3__GPIO3_13                    0x4d 0x032
+#define MX27_PAD_TOUT__TOUT                                0x4e 0x004
+#define MX27_PAD_TOUT__GPIO3_14                            0x4e 0x032
+#define MX27_PAD_TIN__TIN                                  0x4f 0x000
+#define MX27_PAD_TIN__GPIO3_15                             0x4f 0x032
+#define MX27_PAD_SSI4_FS__SSI4_FS                          0x50 0x004
+#define MX27_PAD_SSI4_FS__GPIO3_16                         0x50 0x032
+#define MX27_PAD_SSI4_RXDAT__SSI4_RXDAT                    0x51 0x004
+#define MX27_PAD_SSI4_RXDAT__GPIO3_17                      0x51 0x032
+#define MX27_PAD_SSI4_TXDAT__SSI4_TXDAT                    0x52 0x004
+#define MX27_PAD_SSI4_TXDAT__GPIO3_18                      0x52 0x032
+#define MX27_PAD_SSI4_CLK__SSI4_CLK                        0x53 0x004
+#define MX27_PAD_SSI4_CLK__GPIO3_19                        0x53 0x032
+#define MX27_PAD_SSI1_FS__SSI1_FS                          0x54 0x004
+#define MX27_PAD_SSI1_FS__GPIO3_20                         0x54 0x032
+#define MX27_PAD_SSI1_RXDAT__SSI1_RXDAT                    0x55 0x004
+#define MX27_PAD_SSI1_RXDAT__GPIO3_21                      0x55 0x032
+#define MX27_PAD_SSI1_TXDAT__SSI1_TXDAT                    0x56 0x004
+#define MX27_PAD_SSI1_TXDAT__GPIO3_22                      0x56 0x032
+#define MX27_PAD_SSI1_CLK__SSI1_CLK                        0x57 0x004
+#define MX27_PAD_SSI1_CLK__GPIO3_23                        0x57 0x032
+#define MX27_PAD_SSI2_FS__SSI2_FS                          0x58 0x004
+#define MX27_PAD_SSI2_FS__GPT5_TOUT                        0x58 0x005
+#define MX27_PAD_SSI2_FS__GPIO3_24                         0x58 0x032
+#define MX27_PAD_SSI2_RXDAT__SSI2_RXDAT                    0x59 0x004
+#define MX27_PAD_SSI2_RXDAT__GPTS_TIN                      0x59 0x001
+#define MX27_PAD_SSI2_RXDAT__GPIO3_25                      0x59 0x032
+#define MX27_PAD_SSI2_TXDAT__SSI2_TXDAT                    0x5a 0x004
+#define MX27_PAD_SSI2_TXDAT__GPT4_TOUT                     0x5a 0x005
+#define MX27_PAD_SSI2_TXDAT__GPIO3_26                      0x5a 0x032
+#define MX27_PAD_SSI2_CLK__SSI2_CLK                        0x5b 0x004
+#define MX27_PAD_SSI2_CLK__GPT4_TIN                        0x5b 0x001
+#define MX27_PAD_SSI2_CLK__GPIO3_27                        0x5b 0x032
+#define MX27_PAD_SSI3_FS__SSI3_FS                          0x5c 0x004
+#define MX27_PAD_SSI3_FS__SLCDC2_D0                        0x5c 0x001
+#define MX27_PAD_SSI3_FS__GPIO3_28                         0x5c 0x032
+#define MX27_PAD_SSI3_RXDAT__SSI3_RXDAT                    0x5d 0x004
+#define MX27_PAD_SSI3_RXDAT__SLCDC2_RS                     0x5d 0x001
+#define MX27_PAD_SSI3_RXDAT__GPIO3_29                      0x5d 0x032
+#define MX27_PAD_SSI3_TXDAT__SSI3_TXDAT                    0x5e 0x004
+#define MX27_PAD_SSI3_TXDAT__SLCDC2_CS                     0x5e 0x001
+#define MX27_PAD_SSI3_TXDAT__GPIO3_30                      0x5e 0x032
+#define MX27_PAD_SSI3_CLK__SSI3_CLK                        0x5f 0x004
+#define MX27_PAD_SSI3_CLK__SLCDC2_CLK                      0x5f 0x001
+#define MX27_PAD_SSI3_CLK__GPIO3_31                        0x5f 0x032
+#define MX27_PAD_SD3_CMD__SD3_CMD                          0x60 0x004
+#define MX27_PAD_SD3_CMD__FEC_TXD0                         0x60 0x006
+#define MX27_PAD_SD3_CMD__GPIO4_0                          0x60 0x032
+#define MX27_PAD_SD3_CLK__SD3_CLK                          0x61 0x004
+#define MX27_PAD_SD3_CLK__ETMTRACEPKT15                    0x61 0x005
+#define MX27_PAD_SD3_CLK__FEC_TXD1                         0x61 0x006
+#define MX27_PAD_SD3_CLK__GPIO4_1                          0x61 0x032
+#define MX27_PAD_ATA_DATA0__ATA_DATA0                      0x62 0x004
+#define MX27_PAD_ATA_DATA0__SD3_D0                         0x62 0x005
+#define MX27_PAD_ATA_DATA0__FEC_TXD2                       0x62 0x006
+#define MX27_PAD_ATA_DATA0__GPIO4_2                        0x62 0x032
+#define MX27_PAD_ATA_DATA1__ATA_DATA1                      0x63 0x004
+#define MX27_PAD_ATA_DATA1__SD3_D1                         0x63 0x005
+#define MX27_PAD_ATA_DATA1__FEC_TXD3                       0x63 0x006
+#define MX27_PAD_ATA_DATA1__GPIO4_3                        0x63 0x032
+#define MX27_PAD_ATA_DATA2__ATA_DATA2                      0x64 0x004
+#define MX27_PAD_ATA_DATA2__SD3_D2                         0x64 0x005
+#define MX27_PAD_ATA_DATA2__FEC_RX_ER                      0x64 0x002
+#define MX27_PAD_ATA_DATA2__GPIO4_4                        0x64 0x032
+#define MX27_PAD_ATA_DATA3__ATA_DATA3                      0x65 0x004
+#define MX27_PAD_ATA_DATA3__SD3_D3                         0x65 0x005
+#define MX27_PAD_ATA_DATA3__FEC_RXD1                       0x65 0x002
+#define MX27_PAD_ATA_DATA3__GPIO4_5                        0x65 0x032
+#define MX27_PAD_ATA_DATA4__ATA_DATA4                      0x66 0x004
+#define MX27_PAD_ATA_DATA4__ETMTRACEPKT14                  0x66 0x005
+#define MX27_PAD_ATA_DATA4__FEC_RXD2                       0x66 0x002
+#define MX27_PAD_ATA_DATA4__GPIO4_6                        0x66 0x032
+#define MX27_PAD_ATA_DATA5__ATA_DATA5                      0x67 0x004
+#define MX27_PAD_ATA_DATA5__ETMTRACEPKT13                  0x67 0x005
+#define MX27_PAD_ATA_DATA5__FEC_RXD3                       0x67 0x002
+#define MX27_PAD_ATA_DATA5__GPIO4_7                        0x67 0x032
+#define MX27_PAD_ATA_DATA6__ATA_DATA6                      0x68 0x004
+#define MX27_PAD_ATA_DATA6__FEC_MDIO                       0x68 0x005
+#define MX27_PAD_ATA_DATA6__GPIO4_8                        0x68 0x032
+#define MX27_PAD_ATA_DATA7__ATA_DATA7                      0x69 0x004
+#define MX27_PAD_ATA_DATA7__ETMTRACEPKT12                  0x69 0x005
+#define MX27_PAD_ATA_DATA7__FEC_MDC                        0x69 0x006
+#define MX27_PAD_ATA_DATA7__GPIO4_9                        0x69 0x032
+#define MX27_PAD_ATA_DATA8__ATA_DATA8                      0x6a 0x004
+#define MX27_PAD_ATA_DATA8__ETMTRACEPKT11                  0x6a 0x005
+#define MX27_PAD_ATA_DATA8__FEC_CRS                        0x6a 0x002
+#define MX27_PAD_ATA_DATA8__GPIO4_10                       0x6a 0x032
+#define MX27_PAD_ATA_DATA9__ATA_DATA9                      0x6b 0x004
+#define MX27_PAD_ATA_DATA9__ETMTRACEPKT10                  0x6b 0x005
+#define MX27_PAD_ATA_DATA9__FEC_TX_CLK                     0x6b 0x002
+#define MX27_PAD_ATA_DATA9__GPIO4_11                       0x6b 0x032
+#define MX27_PAD_ATA_DATA10__ATA_DATA10                    0x6c 0x004
+#define MX27_PAD_ATA_DATA10__ETMTRACEPKT9                  0x6c 0x005
+#define MX27_PAD_ATA_DATA10__FEC_RXD0                      0x6c 0x002
+#define MX27_PAD_ATA_DATA10__GPIO4_12                      0x6c 0x032
+#define MX27_PAD_ATA_DATA11__ATA_DATA11                    0x6d 0x004
+#define MX27_PAD_ATA_DATA11__ETMTRACEPKT8                  0x6d 0x005
+#define MX27_PAD_ATA_DATA11__FEC_RX_DV                     0x6d 0x002
+#define MX27_PAD_ATA_DATA11__GPIO4_13                      0x6d 0x032
+#define MX27_PAD_ATA_DATA12__ATA_DATA12                    0x6e 0x004
+#define MX27_PAD_ATA_DATA12__ETMTRACEPKT7                  0x6e 0x005
+#define MX27_PAD_ATA_DATA12__FEC_RX_CLK                    0x6e 0x002
+#define MX27_PAD_ATA_DATA12__GPIO4_14                      0x6e 0x032
+#define MX27_PAD_ATA_DATA13__ATA_DATA13                    0x6f 0x004
+#define MX27_PAD_ATA_DATA13__ETMTRACEPKT6                  0x6f 0x005
+#define MX27_PAD_ATA_DATA13__FEC_COL                       0x6f 0x002
+#define MX27_PAD_ATA_DATA13__GPIO4_15                      0x6f 0x032
+#define MX27_PAD_ATA_DATA14__ATA_DATA14                    0x70 0x004
+#define MX27_PAD_ATA_DATA14__ETMTRACEPKT5                  0x70 0x005
+#define MX27_PAD_ATA_DATA14__FEC_TX_ER                     0x70 0x006
+#define MX27_PAD_ATA_DATA14__GPIO4_16                      0x70 0x032
+#define MX27_PAD_I2C_DATA__I2C_DATA                        0x71 0x004
+#define MX27_PAD_I2C_DATA__GPIO4_17                        0x71 0x032
+#define MX27_PAD_I2C_CLK__I2C_CLK                          0x72 0x004
+#define MX27_PAD_I2C_CLK__GPIO4_18                         0x72 0x032
+#define MX27_PAD_CSPI2_SS2__CSPI2_SS2                      0x73 0x004
+#define MX27_PAD_CSPI2_SS2__USBH2_DATA4                    0x73 0x005
+#define MX27_PAD_CSPI2_SS2__GPIO4_19                       0x73 0x032
+#define MX27_PAD_CSPI2_SS1__CSPI2_SS1                      0x74 0x004
+#define MX27_PAD_CSPI2_SS1__USBH2_DATA3                    0x74 0x005
+#define MX27_PAD_CSPI2_SS1__GPIO4_20                       0x74 0x032
+#define MX27_PAD_CSPI2_SS0__CSPI2_SS0                      0x75 0x004
+#define MX27_PAD_CSPI2_SS0__USBH2_DATA6                    0x75 0x005
+#define MX27_PAD_CSPI2_SS0__GPIO4_21                       0x75 0x032
+#define MX27_PAD_CSPI2_SCLK__CSPI2_SCLK                    0x76 0x004
+#define MX27_PAD_CSPI2_SCLK__USBH2_DATA0                   0x76 0x005
+#define MX27_PAD_CSPI2_SCLK__GPIO4_22                      0x76 0x032
+#define MX27_PAD_CSPI2_MISO__CSPI2_MISO                    0x77 0x004
+#define MX27_PAD_CSPI2_MISO__USBH2_DATA2                   0x77 0x005
+#define MX27_PAD_CSPI2_MISO__GPIO4_23                      0x77 0x032
+#define MX27_PAD_CSPI2_MOSI__CSPI2_MOSI                    0x78 0x004
+#define MX27_PAD_CSPI2_MOSI__USBH2_DATA1                   0x78 0x005
+#define MX27_PAD_CSPI2_MOSI__GPIO4_24                      0x78 0x032
+#define MX27_PAD_CSPI1_RDY__CSPI1_RDY                      0x79 0x000
+#define MX27_PAD_CSPI1_RDY__GPIO4_25                       0x79 0x032
+#define MX27_PAD_CSPI1_SS2__CSPI1_SS2                      0x7a 0x004
+#define MX27_PAD_CSPI1_SS2__USBH2_DATA5                    0x7a 0x005
+#define MX27_PAD_CSPI1_SS2__GPIO4_26                       0x7a 0x032
+#define MX27_PAD_CSPI1_SS1__CSPI1_SS1                      0x7b 0x004
+#define MX27_PAD_CSPI1_SS1__GPIO4_27                       0x7b 0x032
+#define MX27_PAD_CSPI1_SS0__CSPI1_SS0                      0x7c 0x004
+#define MX27_PAD_CSPI1_SS0__GPIO4_28                       0x7c 0x032
+#define MX27_PAD_CSPI1_SCLK__CSPI1_SCLK                    0x7d 0x004
+#define MX27_PAD_CSPI1_SCLK__GPIO4_29                      0x7d 0x032
+#define MX27_PAD_CSPI1_MISO__CSPI1_MISO                    0x7e 0x004
+#define MX27_PAD_CSPI1_MISO__GPIO4_30                      0x7e 0x032
+#define MX27_PAD_CSPI1_MOSI__CSPI1_MOSI                    0x7f 0x004
+#define MX27_PAD_CSPI1_MOSI__GPIO4_31                      0x7f 0x032
+#define MX27_PAD_USBOTG_NXT__USBOTG_NXT                    0x80 0x000
+#define MX27_PAD_USBOTG_NXT__KP_COL6A                      0x80 0x005
+#define MX27_PAD_USBOTG_NXT__GPIO5_0                       0x80 0x032
+#define MX27_PAD_USBOTG_STP__USBOTG_STP                    0x81 0x004
+#define MX27_PAD_USBOTG_STP__KP_ROW6A                      0x81 0x005
+#define MX27_PAD_USBOTG_STP__GPIO5_1                       0x81 0x032
+#define MX27_PAD_USBOTG_DIR__USBOTG_DIR                    0x82 0x000
+#define MX27_PAD_USBOTG_DIR__KP_ROW7A                      0x82 0x005
+#define MX27_PAD_USBOTG_DIR__GPIO5_2                       0x82 0x032
+#define MX27_PAD_UART2_CTS__UART2_CTS                      0x83 0x004
+#define MX27_PAD_UART2_CTS__KP_COL7                        0x83 0x005
+#define MX27_PAD_UART2_CTS__GPIO5_3                        0x83 0x032
+#define MX27_PAD_UART2_RTS__UART2_RTS                      0x84 0x000
+#define MX27_PAD_UART2_RTS__KP_ROW7                        0x84 0x005
+#define MX27_PAD_UART2_RTS__GPIO5_4                        0x84 0x032
+#define MX27_PAD_PWMO__PWMO                                0x85 0x004
+#define MX27_PAD_PWMO__GPIO5_5                             0x85 0x032
+#define MX27_PAD_UART2_TXD__UART2_TXD                      0x86 0x004
+#define MX27_PAD_UART2_TXD__KP_COL6                        0x86 0x005
+#define MX27_PAD_UART2_TXD__GPIO5_6                        0x86 0x032
+#define MX27_PAD_UART2_RXD__UART2_RXD                      0x87 0x000
+#define MX27_PAD_UART2_RXD__KP_ROW6                        0x87 0x005
+#define MX27_PAD_UART2_RXD__GPIO5_7                        0x87 0x032
+#define MX27_PAD_UART3_TXD__UART3_TXD                      0x88 0x004
+#define MX27_PAD_UART3_TXD__GPIO5_8                        0x88 0x032
+#define MX27_PAD_UART3_RXD__UART3_RXD                      0x89 0x000
+#define MX27_PAD_UART3_RXD__GPIO5_9                        0x89 0x032
+#define MX27_PAD_UART3_CTS__UART3_CTS                      0x8a 0x004
+#define MX27_PAD_UART3_CTS__GPIO5_10                       0x8a 0x032
+#define MX27_PAD_UART3_RTS__UART3_RTS                      0x8b 0x000
+#define MX27_PAD_UART3_RTS__GPIO5_11                       0x8b 0x032
+#define MX27_PAD_UART1_TXD__UART1_TXD                      0x8c 0x004
+#define MX27_PAD_UART1_TXD__GPIO5_12                       0x8c 0x032
+#define MX27_PAD_UART1_RXD__UART1_RXD                      0x8d 0x000
+#define MX27_PAD_UART1_RXD__GPIO5_13                       0x8d 0x032
+#define MX27_PAD_UART1_CTS__UART1_CTS                      0x8e 0x004
+#define MX27_PAD_UART1_CTS__GPIO5_14                       0x8e 0x032
+#define MX27_PAD_UART1_RTS__UART1_RTS                      0x8f 0x000
+#define MX27_PAD_UART1_RTS__GPIO5_15                       0x8f 0x032
+#define MX27_PAD_RTCK__RTCK                                0x90 0x004
+#define MX27_PAD_RTCK__OWIRE                               0x90 0x005
+#define MX27_PAD_RTCK__GPIO5_16                            0x90 0x032
+#define MX27_PAD_RESET_OUT_B__RESET_OUT_B                  0x91 0x004
+#define MX27_PAD_RESET_OUT_B__GPIO5_17                     0x91 0x032
+#define MX27_PAD_SD1_D0__SD1_D0                            0x92 0x004
+#define MX27_PAD_SD1_D0__CSPI3_MISO                        0x92 0x001
+#define MX27_PAD_SD1_D0__GPIO5_18                          0x92 0x032
+#define MX27_PAD_SD1_D1__SD1_D1                            0x93 0x004
+#define MX27_PAD_SD1_D1__GPIO5_19                          0x93 0x032
+#define MX27_PAD_SD1_D2__SD1_D2                            0x94 0x004
+#define MX27_PAD_SD1_D2__GPIO5_20                          0x94 0x032
+#define MX27_PAD_SD1_D3__SD1_D3                            0x95 0x004
+#define MX27_PAD_SD1_D3__CSPI3_SS                          0x95 0x005
+#define MX27_PAD_SD1_D3__GPIO5_21                          0x95 0x032
+#define MX27_PAD_SD1_CMD__SD1_CMD                          0x96 0x004
+#define MX27_PAD_SD1_CMD__CSPI3_MOSI                       0x96 0x005
+#define MX27_PAD_SD1_CMD__GPIO5_22                         0x96 0x032
+#define MX27_PAD_SD1_CLK__SD1_CLK                          0x97 0x004
+#define MX27_PAD_SD1_CLK__CSPI3_SCLK                       0x97 0x005
+#define MX27_PAD_SD1_CLK__GPIO5_23                         0x97 0x032
+#define MX27_PAD_USBOTG_CLK__USBOTG_CLK                    0x98 0x000
+#define MX27_PAD_USBOTG_CLK__GPIO5_24                      0x98 0x032
+#define MX27_PAD_USBOTG_DATA7__USBOTG_DATA7                0x99 0x004
+#define MX27_PAD_USBOTG_DATA7__GPIO5_25                    0x99 0x032
+#define MX27_PAD_UNUSED9__UNUSED9                          0x9a 0x004
+#define MX27_PAD_UNUSED9__GPIO5_26                         0x9a 0x032
+#define MX27_PAD_UNUSED10__UNUSED10                        0x9b 0x004
+#define MX27_PAD_UNUSED10__GPIO5_27                        0x9b 0x032
+#define MX27_PAD_UNUSED11__UNUSED11                        0x9c 0x004
+#define MX27_PAD_UNUSED11__GPIO5_28                        0x9c 0x032
+#define MX27_PAD_UNUSED12__UNUSED12                        0x9d 0x004
+#define MX27_PAD_UNUSED12__GPIO5_29                        0x9d 0x032
+#define MX27_PAD_UNUSED13__UNUSED13                        0x9e 0x004
+#define MX27_PAD_UNUSED13__GPIO5_30                        0x9e 0x032
+#define MX27_PAD_UNUSED14__UNUSED14                        0x9f 0x004
+#define MX27_PAD_UNUSED14__GPIO5_31                        0x9f 0x032
+#define MX27_PAD_NFRB__NFRB                                0xa0 0x000
+#define MX27_PAD_NFRB__ETMTRACEPKT3                        0xa0 0x005
+#define MX27_PAD_NFRB__GPIO6_0                             0xa0 0x032
+#define MX27_PAD_NFCLE__NFCLE                              0xa1 0x004
+#define MX27_PAD_NFCLE__ETMTRACEPKT0                       0xa1 0x005
+#define MX27_PAD_NFCLE__GPIO6_1                            0xa1 0x032
+#define MX27_PAD_NFWP_B__NFWP_B                            0xa2 0x004
+#define MX27_PAD_NFWP_B__ETMTRACEPKT1                      0xa2 0x005
+#define MX27_PAD_NFWP_B__GPIO6_2                           0xa2 0x032
+#define MX27_PAD_NFCE_B__NFCE_B                            0xa3 0x004
+#define MX27_PAD_NFCE_B__ETMTRACEPKT2                      0xa3 0x005
+#define MX27_PAD_NFCE_B__GPIO6_3                           0xa3 0x032
+#define MX27_PAD_NFALE__NFALE                              0xa4 0x004
+#define MX27_PAD_NFALE__ETMPIPESTAT0                       0xa4 0x005
+#define MX27_PAD_NFALE__GPIO6_4                            0xa4 0x032
+#define MX27_PAD_NFRE_B__NFRE_B                            0xa5 0x004
+#define MX27_PAD_NFRE_B__ETMPIPESTAT1                      0xa5 0x005
+#define MX27_PAD_NFRE_B__GPIO6_5                           0xa5 0x032
+#define MX27_PAD_NFWE_B__NFWE_B                            0xa6 0x004
+#define MX27_PAD_NFWE_B__ETMPIPESTAT2                      0xa6 0x005
+#define MX27_PAD_NFWE_B__GPIO6_6                           0xa6 0x032
+#define MX27_PAD_PC_POE__PC_POE                            0xa7 0x004
+#define MX27_PAD_PC_POE__ATA_BUFFER_EN                     0xa7 0x005
+#define MX27_PAD_PC_POE__GPIO6_7                           0xa7 0x032
+#define MX27_PAD_PC_RW_B__PC_RW_B                          0xa8 0x004
+#define MX27_PAD_PC_RW_B__ATA_IORDY                        0xa8 0x001
+#define MX27_PAD_PC_RW_B__GPIO6_8                          0xa8 0x032
+#define MX27_PAD_IOIS16__IOIS16                            0xa9 0x000
+#define MX27_PAD_IOIS16__ATA_INTRQ                         0xa9 0x001
+#define MX27_PAD_IOIS16__GPIO6_9                           0xa9 0x032
+#define MX27_PAD_PC_RST__PC_RST                            0xaa 0x004
+#define MX27_PAD_PC_RST__ATA_RESET_B                       0xaa 0x005
+#define MX27_PAD_PC_RST__GPIO6_10                          0xaa 0x032
+#define MX27_PAD_PC_BVD2__PC_BVD2                          0xab 0x000
+#define MX27_PAD_PC_BVD2__ATA_DMACK                        0xab 0x005
+#define MX27_PAD_PC_BVD2__GPIO6_11                         0xab 0x032
+#define MX27_PAD_PC_BVD1__PC_BVD1                          0xac 0x000
+#define MX27_PAD_PC_BVD1__ATA_DMARQ                        0xac 0x001
+#define MX27_PAD_PC_BVD1__GPIO6_12                         0xac 0x032
+#define MX27_PAD_PC_VS2__PC_VS2                            0xad 0x000
+#define MX27_PAD_PC_VS2__ATA_DA0                           0xad 0x005
+#define MX27_PAD_PC_VS2__GPIO6_13                          0xad 0x032
+#define MX27_PAD_PC_VS1__PC_VS1                            0xae 0x000
+#define MX27_PAD_PC_VS1__ATA_DA1                           0xae 0x005
+#define MX27_PAD_PC_VS1__GPIO6_14                          0xae 0x032
+#define MX27_PAD_CLKO__CLKO                                0xaf 0x004
+#define MX27_PAD_CLKO__GPIO6_15                            0xaf 0x032
+#define MX27_PAD_PC_PWRON__PC_PWRON                        0xb0 0x000
+#define MX27_PAD_PC_PWRON__ATA_DA2                         0xb0 0x005
+#define MX27_PAD_PC_PWRON__GPIO6_16                        0xb0 0x032
+#define MX27_PAD_PC_READY__PC_READY                        0xb1 0x000
+#define MX27_PAD_PC_READY__ATA_CS0                         0xb1 0x005
+#define MX27_PAD_PC_READY__GPIO6_17                        0xb1 0x032
+#define MX27_PAD_PC_WAIT_B__PC_WAIT_B                      0xb2 0x000
+#define MX27_PAD_PC_WAIT_B__ATA_CS1                        0xb2 0x005
+#define MX27_PAD_PC_WAIT_B__GPIO6_18                       0xb2 0x032
+#define MX27_PAD_PC_CD2_B__PC_CD2_B                        0xb3 0x000
+#define MX27_PAD_PC_CD2_B__ATA_DIOW                        0xb3 0x005
+#define MX27_PAD_PC_CD2_B__GPIO6_19                        0xb3 0x032
+#define MX27_PAD_PC_CD1_B__PC_CD1_B                        0xb4 0x000
+#define MX27_PAD_PC_CD1_B__ATA_DIOR                        0xb4 0x005
+#define MX27_PAD_PC_CD1_B__GPIO6_20                        0xb4 0x032
+#define MX27_PAD_CS4_B__CS4_B                              0xb5 0x004
+#define MX27_PAD_CS4_B__ETMTRACESYNC                       0xb5 0x005
+#define MX27_PAD_CS4_B__GPIO6_21                           0xb5 0x032
+#define MX27_PAD_CS5_B__CS5_B                              0xb6 0x004
+#define MX27_PAD_CS5_B__ETMTRACECLK                        0xb6 0x005
+#define MX27_PAD_CS5_B__GPIO6_22                           0xb6 0x032
+#define MX27_PAD_ATA_DATA15__ATA_DATA15                    0xb7 0x004
+#define MX27_PAD_ATA_DATA15__ETMTRACEPKT4                  0xb7 0x005
+#define MX27_PAD_ATA_DATA15__FEC_TX_EN                     0xb7 0x006
+#define MX27_PAD_ATA_DATA15__GPIO6_23                      0xb7 0x032
+#define MX27_PAD_UNUSED15__UNUSED15                        0xb8 0x004
+#define MX27_PAD_UNUSED15__GPIO6_24                        0xb8 0x032
+#define MX27_PAD_UNUSED16__UNUSED16                        0xb9 0x004
+#define MX27_PAD_UNUSED16__GPIO6_25                        0xb9 0x032
+#define MX27_PAD_UNUSED17__UNUSED17                        0xba 0x004
+#define MX27_PAD_UNUSED17__GPIO6_26                        0xba 0x032
+#define MX27_PAD_UNUSED18__UNUSED18                        0xbb 0x004
+#define MX27_PAD_UNUSED18__GPIO6_27                        0xbb 0x032
+#define MX27_PAD_UNUSED19__UNUSED19                        0xbc 0x004
+#define MX27_PAD_UNUSED19__GPIO6_28                        0xbc 0x032
+#define MX27_PAD_UNUSED20__UNUSED20                        0xbd 0x004
+#define MX27_PAD_UNUSED20__GPIO6_29                        0xbd 0x032
+#define MX27_PAD_UNUSED21__UNUSED21                        0xbe 0x004
+#define MX27_PAD_UNUSED21__GPIO6_30                        0xbe 0x032
+#define MX27_PAD_UNUSED22__UNUSED22                        0xbf 0x004
+#define MX27_PAD_UNUSED22__GPIO6_31                        0xbf 0x032
+
+#endif /* __DTS_IMX27_PINFUNC_H */
diff --git a/arch/arm/boot/dts/imx27-pingrp.h b/arch/arm/boot/dts/imx27-pingrp.h
new file mode 100644 (file)
index 0000000..edc1e90
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2013 Markus Pargmann <mpa@pengutronix.de>, Pengutronix
+ *
+ * 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 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __DTS_IMX27_PINGRP_H
+#define __DTS_IMX27_PINGRP_H
+
+#include "imx27-pinfunc.h"
+
+#define MX27_CSPI1_PINGRP1 \
+       MX27_PAD_CSPI1_MISO__CSPI1_MISO 0x0 \
+       MX27_PAD_CSPI1_MOSI__CSPI1_MOSI 0x0 \
+       MX27_PAD_CSPI1_SCLK__CSPI1_SCLK 0x0
+
+#define MX27_CSPI2_PINGRP1 \
+       MX27_PAD_CSPI2_MISO__CSPI2_MISO 0x0 \
+       MX27_PAD_CSPI2_MOSI__CSPI2_MOSI 0x0 \
+       MX27_PAD_CSPI2_SCLK__CSPI2_SCLK 0x0
+
+#define MX27_CSPI3_PINGRP1 \
+       MX27_PAD_SD1_CLK__CSPI3_SCLK 0x0 \
+       MX27_PAD_SD1_D0__CSPI3_MISO 0x0 \
+       MX27_PAD_SD1_CMD__CSPI3_MOSI 0x0
+
+#define MX27_FB_PINGRP1 \
+       MX27_PAD_CLS__CLS 0x0 \
+       MX27_PAD_CONTRAST__CONTRAST 0x0 \
+       MX27_PAD_LD0__LD0 0x0 \
+       MX27_PAD_LD1__LD1 0x0 \
+       MX27_PAD_LD2__LD2 0x0 \
+       MX27_PAD_LD3__LD3 0x0 \
+       MX27_PAD_LD4__LD4 0x0 \
+       MX27_PAD_LD5__LD5 0x0 \
+       MX27_PAD_LD6__LD6 0x0 \
+       MX27_PAD_LD7__LD7 0x0 \
+       MX27_PAD_LD8__LD8 0x0 \
+       MX27_PAD_LD9__LD9 0x0 \
+       MX27_PAD_LD10__LD10 0x0 \
+       MX27_PAD_LD11__LD11 0x0 \
+       MX27_PAD_LD12__LD12 0x0 \
+       MX27_PAD_LD13__LD13 0x0 \
+       MX27_PAD_LD14__LD14 0x0 \
+       MX27_PAD_LD15__LD15 0x0 \
+       MX27_PAD_LD16__LD16 0x0 \
+       MX27_PAD_LD17__LD17 0x0 \
+       MX27_PAD_LSCLK__LSCLK 0x0 \
+       MX27_PAD_OE_ACD__OE_ACD 0x0 \
+       MX27_PAD_PS__PS 0x0 \
+       MX27_PAD_REV__REV 0x0 \
+       MX27_PAD_SPL_SPR__SPL_SPR 0x0 \
+       MX27_PAD_HSYNC__HSYNC 0x0 \
+       MX27_PAD_VSYNC__VSYNC 0x0
+
+#define MX27_FEC1_PINGRP1 \
+       MX27_PAD_SD3_CMD__FEC_TXD0 0x0 \
+       MX27_PAD_SD3_CLK__FEC_TXD1 0x0 \
+       MX27_PAD_ATA_DATA0__FEC_TXD2 0x0 \
+       MX27_PAD_ATA_DATA1__FEC_TXD3 0x0 \
+       MX27_PAD_ATA_DATA2__FEC_RX_ER 0x0 \
+       MX27_PAD_ATA_DATA3__FEC_RXD1 0x0 \
+       MX27_PAD_ATA_DATA4__FEC_RXD2 0x0 \
+       MX27_PAD_ATA_DATA5__FEC_RXD3 0x0 \
+       MX27_PAD_ATA_DATA6__FEC_MDIO 0x0 \
+       MX27_PAD_ATA_DATA7__FEC_MDC 0x0 \
+       MX27_PAD_ATA_DATA8__FEC_CRS 0x0 \
+       MX27_PAD_ATA_DATA9__FEC_TX_CLK 0x0 \
+       MX27_PAD_ATA_DATA10__FEC_RXD0 0x0 \
+       MX27_PAD_ATA_DATA11__FEC_RX_DV 0x0 \
+       MX27_PAD_ATA_DATA12__FEC_RX_CLK 0x0 \
+       MX27_PAD_ATA_DATA13__FEC_COL 0x0 \
+       MX27_PAD_ATA_DATA14__FEC_TX_ER 0x0 \
+       MX27_PAD_ATA_DATA15__FEC_TX_EN 0x0
+
+#define MX27_I2C1_PINGRP1 \
+       MX27_PAD_I2C_DATA__I2C_DATA 0x0 \
+       MX27_PAD_I2C_CLK__I2C_CLK 0x0
+
+#define MX27_I2C2_PINGRP1 \
+       MX27_PAD_I2C2_SDA__I2C2_SDA 0x0 \
+       MX27_PAD_I2C2_SCL__I2C2_SCL 0x0
+
+#define MX27_OWIRE1_PINGRP1 \
+       MX27_PAD_RTCK__OWIRE 0x0
+
+#define MX27_PWM_PINGRP1 \
+       MX27_PAD_PWMO__PWMO 0x0
+
+#define MX27_SDHC1_PINGRP1 \
+       MX27_PAD_SD1_CLK__SD1_CLK \
+       MX27_PAD_SD1_CMD__SD1_CMD \
+       MX27_PAD_SD1_D0__SD1_D0 \
+       MX27_PAD_SD1_D1__SD1_D1 \
+       MX27_PAD_SD1_D2__SD1_D2 \
+       MX27_PAD_SD1_D3__SD1_D3
+
+#define MX27_SDHC2_PINGRP1 \
+       MX27_PAD_SD2_CLK__SD2_CLK \
+       MX27_PAD_SD2_CMD__SD2_CMD \
+       MX27_PAD_SD2_D0__SD2_D0 \
+       MX27_PAD_SD2_D1__SD2_D1 \
+       MX27_PAD_SD2_D2__SD2_D2 \
+       MX27_PAD_SD2_D3__SD2_D3
+
+#define MX27_SDHC3_PINGRP1 \
+       MX27_PAD_SD3_CLK__SD3_CLK \
+       MX27_PAD_SD3_CMD__SD3_CMD \
+       MX27_PAD_SD3_D0__SD3_D0 \
+       MX27_PAD_SD3_D1__SD3_D1 \
+       MX27_PAD_SD3_D2__SD3_D2 \
+       MX27_PAD_SD3_D3__SD3_D3
+
+#define MX27_UART1_PINGRP1 \
+       MX27_PAD_UART1_TXD__UART1_TXD 0x0 \
+       MX27_PAD_UART1_RXD__UART1_RXD 0x0
+
+#define MX27_UART1_RTSCTS_PINGRP1 \
+       MX27_PAD_UART1_CTS__UART1_CTS 0x0 \
+       MX27_PAD_UART1_RTS__UART1_RTS 0x0
+
+#define MX27_UART2_PINGRP1 \
+       MX27_PAD_UART2_TXD__UART2_TXD 0x0 \
+       MX27_PAD_UART2_RXD__UART2_RXD 0x0
+
+#define MX27_UART2_RTSCTS_PINGRP1 \
+       MX27_PAD_UART2_CTS__UART2_CTS 0x0 \
+       MX27_PAD_UART2_RTS__UART2_RTS 0x0
+
+#define MX27_UART3_PINGRP1 \
+       MX27_PAD_UART3_TXD__UART3_TXD 0x0 \
+       MX27_PAD_UART3_RXD__UART3_RXD 0x0
+
+#define MX27_UART3_RTSCTS_PINGRP1 \
+       MX27_PAD_UART3_CTS__UART3_CTS 0x0 \
+       MX27_PAD_UART3_RTS__UART3_RTS 0x0
+
+#endif /* __DTS_IMX27_PINGRP_H */
index 826231eb44466f9187a564b3a587c7b18d686b28..63b1b3291c1db121b97a193baeb20d21bb0832db 100644 (file)
@@ -10,6 +10,9 @@
  */
 
 #include "skeleton.dtsi"
+#include "imx27-pingrp.h"
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/gpio/gpio.h>
 
 / {
        aliases {
                                status = "disabled";
                        };
 
-                       gpio1: gpio@10015000 {
-                               compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
-                               reg = <0x10015000 0x100>;
-                               interrupts = <8>;
-                               gpio-controller;
-                               #gpio-cells = <2>;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                       };
-
-                       gpio2: gpio@10015100 {
-                               compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
-                               reg = <0x10015100 0x100>;
-                               interrupts = <8>;
-                               gpio-controller;
-                               #gpio-cells = <2>;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                       };
-
-                       gpio3: gpio@10015200 {
-                               compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
-                               reg = <0x10015200 0x100>;
-                               interrupts = <8>;
-                               gpio-controller;
-                               #gpio-cells = <2>;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                       };
-
-                       gpio4: gpio@10015300 {
-                               compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
-                               reg = <0x10015300 0x100>;
-                               interrupts = <8>;
-                               gpio-controller;
-                               #gpio-cells = <2>;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                       };
-
-                       gpio5: gpio@10015400 {
-                               compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
-                               reg = <0x10015400 0x100>;
-                               interrupts = <8>;
-                               gpio-controller;
-                               #gpio-cells = <2>;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                       };
-
-                       gpio6: gpio@10015500 {
-                               compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
-                               reg = <0x10015500 0x100>;
-                               interrupts = <8>;
-                               gpio-controller;
-                               #gpio-cells = <2>;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
+                       iomuxc: iomuxc@10015000 {
+                               compatible = "fsl,imx27-iomuxc";
+                               reg = <0x10015000 0x600>;
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges;
+
+                               gpio1: gpio@10015000 {
+                                       compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
+                                       reg = <0x10015000 0x100>;
+                                       interrupts = <8>;
+                                       gpio-controller;
+                                       #gpio-cells = <2>;
+                                       interrupt-controller;
+                                       #interrupt-cells = <2>;
+                               };
+
+                               gpio2: gpio@10015100 {
+                                       compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
+                                       reg = <0x10015100 0x100>;
+                                       interrupts = <8>;
+                                       gpio-controller;
+                                       #gpio-cells = <2>;
+                                       interrupt-controller;
+                                       #interrupt-cells = <2>;
+                               };
+
+                               gpio3: gpio@10015200 {
+                                       compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
+                                       reg = <0x10015200 0x100>;
+                                       interrupts = <8>;
+                                       gpio-controller;
+                                       #gpio-cells = <2>;
+                                       interrupt-controller;
+                                       #interrupt-cells = <2>;
+                               };
+
+                               gpio4: gpio@10015300 {
+                                       compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
+                                       reg = <0x10015300 0x100>;
+                                       interrupts = <8>;
+                                       gpio-controller;
+                                       #gpio-cells = <2>;
+                                       interrupt-controller;
+                                       #interrupt-cells = <2>;
+                               };
+
+                               gpio5: gpio@10015400 {
+                                       compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
+                                       reg = <0x10015400 0x100>;
+                                       interrupts = <8>;
+                                       gpio-controller;
+                                       #gpio-cells = <2>;
+                                       interrupt-controller;
+                                       #interrupt-cells = <2>;
+                               };
+
+                               gpio6: gpio@10015500 {
+                                       compatible = "fsl,imx27-gpio", "fsl,imx21-gpio";
+                                       reg = <0x10015500 0x100>;
+                                       interrupts = <8>;
+                                       gpio-controller;
+                                       #gpio-cells = <2>;
+                                       interrupt-controller;
+                                       #interrupt-cells = <2>;
+                               };
                        };
 
                        audmux: audmux@10016000 {
index e2efd8d89c4fb82bca3602274380c7a81a515518..334dea58e17ecf2466ee954f9aa17197d91298ed 100644 (file)
                                        fsl,voltage = <MXS_VOLTAGE_HIGH>;
                                        fsl,pull-up = <MXS_PULL_DISABLE>;
                                };
+
+                               usb0_otg_apf28dev: otg-apf28dev@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               MX28_PAD_LCD_D23__GPIO_1_23
+                                       >;
+                                       fsl,drive-strength = <MXS_DRIVE_4mA>;
+                                       fsl,voltage = <MXS_VOLTAGE_HIGH>;
+                                       fsl,pull-up = <MXS_PULL_DISABLE>;
+                               };
                        };
 
                        lcdif@80030000 {
 
        ahb@80080000 {
                usb0: usb@80080000 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&usb0_otg_apf28dev>;
                        vbus-supply = <&reg_usb0_vbus>;
                        status = "okay";
                };
 
        regulators {
                compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
 
-               reg_usb0_vbus: usb0_vbus {
+               reg_usb0_vbus: regulator@0 {
                        compatible = "regulator-fixed";
+                       reg = <0>;
                        regulator-name = "usb0_vbus";
                        regulator-min-microvolt = <5000000>;
                        regulator-max-microvolt = <5000000>;
                        gpio = <&gpio1 23 1>;
+                       enable-active-high;
                };
        };
 
index 6f254ca816cbd42b3ff80d61c3bfdb86c6f8438d..e1ce9179db63b612839a85d35b5122fd3fd4dd59 100644 (file)
 
        regulators {
                compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
 
-               reg_3p3v: 3p3v {
+               reg_3p3v: regulator@0 {
                        compatible = "regulator-fixed";
+                       reg = <0>;
                        regulator-name = "3P3V";
                        regulator-min-microvolt = <3300000>;
                        regulator-max-microvolt = <3300000>;
index cabb6171a19d925c214442daa47473a6a2be31a5..ae7c3390e65a5ddc6210c4d256b406719e624d14 100644 (file)
                usb0: usb@80080000 {
                        pinctrl-names = "default";
                        pinctrl-0 = <&usb0_otg_cfa10036>;
+                       dr_mode = "peripheral";
+                       phy_type = "utmi";
                        status = "okay";
                };
        };
index f93e9a700e52b39287ff6761cf9c2ffdc21ea617..e5beaa58bb40262fcd42297615f476a9881eff17 100644 (file)
@@ -54,7 +54,7 @@
        ahb@80080000 {
                usb1: usb@80090000 {
                        vbus-supply = <&reg_usb1_vbus>;
-                       pinctrl-0 = <&usbphy1_pins_a>;
+                       pinctrl-0 = <&usb1_pins_a>;
                        pinctrl-names = "default";
                        status = "okay";
                };
 
        regulators {
                compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
 
-               reg_usb1_vbus: usb1_vbus {
+               reg_usb1_vbus: regulator@0 {
                        compatible = "regulator-fixed";
+                       reg = <0>;
                        pinctrl-names = "default";
                        pinctrl-0 = <&usb_pins_cfa10037>;
                        regulator-name = "usb1_vbus";
index 7087b4bf6a8f88e5748a70747af337de3524a5c0..7d51459de5e82038d391ce03c115410787815482 100644 (file)
                                i2c-parent = <&i2c1>;
 
                                i2c@0 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
                                        reg = <0>;
+
+                                       adc0: nau7802@2a {
+                                               compatible = "nuvoton,nau7802";
+                                               reg = <0x2a>;
+                                               nuvoton,vldo = <3000>;
+                                       };
                                };
 
                                i2c@1 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
                                        reg = <1>;
+
+                                       adc1: nau7802@2a {
+                                               compatible = "nuvoton,nau7802";
+                                               reg = <0x2a>;
+                                               nuvoton,vldo = <3000>;
+                                       };
                                };
 
                                i2c@2 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
                                        reg = <2>;
+
+                                       adc2: nau7802@2a {
+                                               compatible = "nuvoton,nau7802";
+                                               reg = <0x2a>;
+                                               nuvoton,vldo = <3000>;
+                                       };
                                };
 
                                i2c@3 {
        ahb@80080000 {
                usb1: usb@80090000 {
                        vbus-supply = <&reg_usb1_vbus>;
-                       pinctrl-0 = <&usbphy1_pins_a>;
+                       pinctrl-0 = <&usb1_pins_a>;
                        pinctrl-names = "default";
                        status = "okay";
                };
 
        regulators {
                compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
 
-               reg_usb1_vbus: usb1_vbus {
+               reg_usb1_vbus: regulator@0 {
                        compatible = "regulator-fixed";
+                       reg = <0>;
                        pinctrl-names = "default";
                        pinctrl-0 = <&usb_pins_cfa10049>;
                        regulator-name = "usb1_vbus";
index 3c1312885ae0dafc1642e30d27a58cc3cf49d12b..c4e00ce4b6daf19b2cdb0ead0c299899b154a1dd 100644 (file)
        ahb@80080000 {
                usb1: usb@80090000 {
                        vbus-supply = <&reg_usb1_vbus>;
-                       pinctrl-0 = <&usbphy1_pins_a>;
+                       pinctrl-0 = <&usb1_pins_a>;
                        pinctrl-names = "default";
                        status = "okay";
                };
 
        regulators {
                compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
 
-               reg_usb1_vbus: usb1_vbus {
+               reg_usb1_vbus: regulator@0 {
                        compatible = "regulator-fixed";
+                       reg = <0>;
                        pinctrl-names = "default";
                        pinctrl-0 = <&usb_pins_cfa10057>;
                        regulator-name = "usb1_vbus";
index 2469d34df0ae1499de3236f13e180969dd78eed7..7c9cc783f0d1a4c93d4385aabaab508c786dc465 100644 (file)
        ahb@80080000 {
                usb1: usb@80090000 {
                        vbus-supply = <&reg_usb1_vbus>;
-                       pinctrl-0 = <&usbphy1_pins_a>;
+                       pinctrl-0 = <&usb1_pins_a>;
                        pinctrl-names = "default";
                        status = "okay";
                };
 
        regulators {
                compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
 
-               reg_usb1_vbus: usb1_vbus {
+               reg_usb1_vbus: regulator@0 {
                        pinctrl-names = "default";
                        pinctrl-0 = <&usb_pins_cfa10058>;
                        compatible = "regulator-fixed";
+                       reg = <0>;
                        regulator-name = "usb1_vbus";
                        regulator-min-microvolt = <5000000>;
                        regulator-max-microvolt = <5000000>;
diff --git a/arch/arm/boot/dts/imx28-duckbill.dts b/arch/arm/boot/dts/imx28-duckbill.dts
new file mode 100644 (file)
index 0000000..5f326c1
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2013 Michael Heimpold <mhei@heimpold.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 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx28.dtsi"
+
+/ {
+       model = "I2SE Duckbill";
+       compatible = "i2se,duckbill", "fsl,imx28";
+
+       memory {
+               reg = <0x40000000 0x08000000>;
+       };
+
+       apb@80000000 {
+               apbh@80000000 {
+                       ssp0: ssp@80010000 {
+                               compatible = "fsl,imx28-mmc";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&mmc0_8bit_pins_a
+                                       &mmc0_cd_cfg &mmc0_sck_cfg>;
+                               bus-width = <8>;
+                               vmmc-supply = <&reg_3p3v>;
+                               status = "okay";
+                       };
+
+                       pinctrl@80018000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&hog_pins_a>;
+
+                               hog_pins_a: hog@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               MX28_PAD_ENET0_RX_CLK__GPIO_4_13 /* PHY Reset */
+                                       >;
+                                       fsl,drive-strength = <MXS_DRIVE_4mA>;
+                                       fsl,voltage = <MXS_VOLTAGE_HIGH>;
+                                       fsl,pull-up = <MXS_PULL_DISABLE>;
+                               };
+
+                               led_pins_a: led_gpio@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               MX28_PAD_AUART1_RX__GPIO_3_4
+                                               MX28_PAD_AUART1_TX__GPIO_3_5
+                                       >;
+                                       fsl,drive-strength = <MXS_DRIVE_4mA>;
+                                       fsl,voltage = <MXS_VOLTAGE_HIGH>;
+                                       fsl,pull-up = <MXS_PULL_DISABLE>;
+                               };
+                       };
+               };
+
+               apbx@80040000 {
+                       duart: serial@80074000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&duart_pins_a>;
+                               status = "okay";
+                       };
+
+                       usbphy0: usbphy@8007c000 {
+                               status = "okay";
+                       };
+               };
+       };
+
+       ahb@80080000 {
+               usb0: usb@80080000 {
+                       status = "okay";
+               };
+
+               mac0: ethernet@800f0000 {
+                       phy-mode = "rmii";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&mac0_pins_a>;
+                       phy-supply = <&reg_3p3v>;
+                       phy-reset-gpios = <&gpio4 13 0>;
+                       phy-reset-duration = <100>;
+                       status = "okay";
+               };
+       };
+
+       regulators {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               reg_3p3v: regulator@0 {
+                       compatible = "regulator-fixed";
+                       reg = <0>;
+                       regulator-name = "3P3V";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+               pinctrl-names = "default";
+               pinctrl-0 = <&led_pins_a>;
+
+               status {
+                       label = "duckbill:green:status";
+                       gpios = <&gpio3 5 0>;
+               };
+
+               failure {
+                       label = "duckbill:red:status";
+                       gpios = <&gpio3 4 0>;
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/imx28-eukrea-mbmx283lc.dts b/arch/arm/boot/dts/imx28-eukrea-mbmx283lc.dts
new file mode 100644 (file)
index 0000000..7c1572c
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2013 Eukréa Electromatique <eric@eukrea.com>
+ * Copyright 2013 Eukréa Electromatique <denis@eukrea.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.
+ */
+
+/*
+ * Module contains : i.MX282 + 64MB DDR2 + NAND + Ethernet PHY + RTC
+ */
+
+/dts-v1/;
+#include "imx28-eukrea-mbmx28lc.dtsi"
+
+/ {
+       model = "Eukrea Electromatique MBMX283LC";
+       compatible = "eukrea,mbmx283lc", "eukrea,mbmx28lc", "fsl,imx28";
+
+       memory {
+               reg = <0x40000000 0x04000000>;
+       };
+};
+
+&gpmi {
+       pinctrl-names = "default";
+       pinctrl-0 = <&gpmi_pins_a>;
+       status = "okay";
+};
+
+&i2c0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c0_pins_a>;
+       status = "okay";
+
+       pcf8563: rtc@51 {
+               compatible = "nxp,pcf8563";
+               reg = <0x51>;
+       };
+};
+
+
+&mac0 {
+       phy-mode = "rmii";
+       pinctrl-names = "default";
+       pinctrl-0 = <&mac0_pins_a>;
+       phy-reset-gpios = <&gpio4 13 GPIO_ACTIVE_LOW>;
+       status = "okay";
+};
+
+&pinctrl{
+       pinctrl-names = "default";
+       pinctrl-0 = <&hog_pins_cpuimx283>;
+
+       hog_pins_cpuimx283: hog-cpuimx283@0 {
+               reg = <0>;
+               fsl,pinmux-ids = <
+                       MX28_PAD_ENET0_RX_CLK__GPIO_4_13
+                       MX28_PAD_ENET0_TX_CLK__GPIO_4_5
+               >;
+               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-eukrea-mbmx287lc.dts b/arch/arm/boot/dts/imx28-eukrea-mbmx287lc.dts
new file mode 100644 (file)
index 0000000..e773144
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2013 Eukréa Electromatique <eric@eukrea.com>
+ * Copyright 2013 Eukréa Electromatique <denis@eukrea.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.
+ */
+
+/*
+ * Module contains : i.MX287 + 128MB DDR2 + NAND + 2 x Ethernet PHY + RTC
+ */
+
+#include "imx28-eukrea-mbmx283lc.dts"
+
+/ {
+       model = "Eukrea Electromatique MBMX287LC";
+       compatible = "eukrea,mbmx287lc", "eukrea,mbmx283lc", "eukrea,mbmx28lc", "fsl,imx28";
+
+       memory {
+               reg = <0x40000000 0x08000000>;
+       };
+};
+
+&mac1 {
+       phy-mode = "rmii";
+       pinctrl-names = "default";
+       pinctrl-0 = <&mac1_pins_a>;
+       phy-reset-gpios = <&gpio3 27 GPIO_ACTIVE_HIGH>;
+       status = "okay";
+};
+
+&pinctrl {
+       pinctrl-names = "default";
+       pinctrl-0 = <&hog_pins_cpuimx283 &hog_pins_cpuimx287>;
+       hog_pins_cpuimx287: hog-cpuimx287@0 {
+               reg = <0>;
+               fsl,pinmux-ids = <
+                       MX28_PAD_SPDIF__GPIO_3_27
+               >;
+               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-eukrea-mbmx28lc.dtsi b/arch/arm/boot/dts/imx28-eukrea-mbmx28lc.dtsi
new file mode 100644 (file)
index 0000000..927b391
--- /dev/null
@@ -0,0 +1,326 @@
+/*
+ * Copyright 2013 Eukréa Electromatique <eric@eukrea.com>
+ * Copyright 2013 Eukréa Electromatique <denis@eukrea.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.
+ */
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
+#include "imx28.dtsi"
+
+/ {
+       model = "Eukrea Electromatique MBMX28LC";
+       compatible = "eukrea,mbmx28lc", "fsl,imx28";
+
+       backlight {
+               compatible = "pwm-backlight";
+               pwms = <&pwm 4 1000000>;
+               brightness-levels = <0 25 50 75 100 125 150 175 200 225 255>;
+               default-brightness-level = <10>;
+       };
+
+       button-sw3 {
+               compatible = "gpio-keys";
+               pinctrl-names = "default";
+               pinctrl-0 = <&gpio_button_sw3_pins_mbmx28lc>;
+
+               sw3 {
+                       label = "SW3";
+                       gpios = <&gpio1 21 GPIO_ACTIVE_LOW>;
+                       linux,code = <BTN_MISC>;
+                       gpio-key,wakeup;
+               };
+       };
+
+       button-sw4 {
+               compatible = "gpio-keys";
+               pinctrl-names = "default";
+               pinctrl-0 = <&gpio_button_sw4_pins_mbmx28lc>;
+
+               sw4 {
+                       label = "SW4";
+                       gpios = <&gpio1 20 GPIO_ACTIVE_LOW>;
+                       linux,code = <BTN_MISC>;
+                       gpio-key,wakeup;
+               };
+       };
+
+       led-d6 {
+               compatible = "gpio-leds";
+               pinctrl-names = "default";
+               pinctrl-0 = <&led_d6_pins_mbmx28lc>;
+
+               led1 {
+                       label = "d6";
+                       gpios = <&gpio1 23 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "heartbeat";
+               };
+       };
+
+       led-d7 {
+               compatible = "gpio-leds";
+               pinctrl-names = "default";
+               pinctrl-0 = <&led_d7_pins_mbmx28lc>;
+
+               led1 {
+                       label = "d7";
+                       gpios = <&gpio1 22 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "default-on";
+               };
+       };
+
+       regulators {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               reg_3p3v: regulator@0 {
+                       compatible = "regulator-fixed";
+                       regulator-name = "3P3V";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+               };
+
+               reg_lcd_3v3: regulator@1 {
+                       compatible = "regulator-fixed";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&reg_lcd_3v3_pins_mbmx28lc>;
+                       regulator-name = "lcd-3v3";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       gpio = <&gpio3 30 GPIO_ACTIVE_HIGH>;
+                       enable-active-high;
+               };
+
+               reg_usb0_vbus: regulator@2 {
+                       compatible = "regulator-fixed";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&reg_usb0_vbus_pins_mbmx28lc>;
+                       regulator-name = "usb0_vbus";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       gpio = <&gpio1 18 GPIO_ACTIVE_HIGH>;
+                       enable-active-high;
+               };
+
+               reg_usb1_vbus: regulator@3 {
+                       compatible = "regulator-fixed";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&reg_usb1_vbus_pins_mbmx28lc>;
+                       regulator-name = "usb1_vbus";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       gpio = <&gpio1 19 GPIO_ACTIVE_HIGH>;
+                       enable-active-high;
+               };
+       };
+
+       sound {
+               compatible = "fsl,imx28-mbmx28lc-sgtl5000",
+                            "fsl,mxs-audio-sgtl5000";
+               model = "imx28-mbmx28lc-sgtl5000";
+               saif-controllers = <&saif0 &saif1>;
+               audio-codec = <&sgtl5000>;
+       };
+};
+
+&duart {
+       pinctrl-names = "default";
+       pinctrl-0 = <&duart_4pins_a>;
+       status = "okay";
+};
+
+&i2c0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c0_pins_a>;
+       status = "okay";
+
+       sgtl5000: codec@0a {
+               compatible = "fsl,sgtl5000";
+               reg = <0x0a>;
+               VDDA-supply = <&reg_3p3v>;
+               VDDIO-supply = <&reg_3p3v>;
+               clocks = <&saif0>;
+       };
+};
+
+&lcdif {
+       pinctrl-names = "default";
+       pinctrl-0 = <&lcdif_18bit_pins_a &lcdif_pins_mbmx28lc>;
+       lcd-supply = <&reg_lcd_3v3>;
+       display = <&display0>;
+       status = "okay";
+
+       display0: display0 {
+               model = "43WVF1G-0";
+               bits-per-pixel = <16>;
+               bus-width = <18>;
+
+               display-timings {
+                       native-mode = <&timing0>;
+                       timing0: timing0 {
+                               clock-frequency = <9072000>;
+                               hactive = <480>;
+                               vactive = <272>;
+                               hback-porch = <10>;
+                               hfront-porch = <5>;
+                               vback-porch = <8>;
+                               vfront-porch = <8>;
+                               hsync-len = <40>;
+                               vsync-len = <10>;
+                               hsync-active = <0>;
+                               vsync-active = <0>;
+                               de-active = <1>;
+                               pixelclk-active = <1>;
+                       };
+               };
+       };
+};
+
+&lradc {
+       fsl,lradc-touchscreen-wires = <4>;
+       status = "okay";
+};
+
+&pinctrl {
+       gpio_button_sw3_pins_mbmx28lc: gpio-button-sw3-mbmx28lc@0 {
+               reg = <0>;
+               fsl,pinmux-ids = <
+                       MX28_PAD_LCD_D21__GPIO_1_21
+               >;
+               fsl,drive-strength = <MXS_DRIVE_4mA>;
+               fsl,voltage = <MXS_VOLTAGE_HIGH>;
+               fsl,pull-up = <MXS_PULL_DISABLE>;
+       };
+
+       gpio_button_sw4_pins_mbmx28lc: gpio-button-sw4-mbmx28lc@0 {
+               reg = <0>;
+               fsl,pinmux-ids = <
+                       MX28_PAD_LCD_D20__GPIO_1_20
+               >;
+               fsl,drive-strength = <MXS_DRIVE_4mA>;
+               fsl,voltage = <MXS_VOLTAGE_HIGH>;
+               fsl,pull-up = <MXS_PULL_DISABLE>;
+       };
+
+       lcdif_pins_mbmx28lc: lcdif-mbmx28lc@0 {
+               reg = <0>;
+               fsl,pinmux-ids = <
+                       MX28_PAD_LCD_VSYNC__LCD_VSYNC
+                       MX28_PAD_LCD_HSYNC__LCD_HSYNC
+                       MX28_PAD_LCD_DOTCLK__LCD_DOTCLK
+                       MX28_PAD_LCD_ENABLE__LCD_ENABLE
+               >;
+               fsl,drive-strength = <MXS_DRIVE_4mA>;
+               fsl,voltage = <MXS_VOLTAGE_HIGH>;
+               fsl,pull-up = <MXS_PULL_DISABLE>;
+       };
+
+       led_d6_pins_mbmx28lc: led-d6-mbmx28lc@0 {
+               reg = <0>;
+               fsl,pinmux-ids = <
+                       MX28_PAD_LCD_D23__GPIO_1_23
+               >;
+               fsl,drive-strength = <MXS_DRIVE_4mA>;
+               fsl,voltage = <MXS_VOLTAGE_HIGH>;
+               fsl,pull-up = <MXS_PULL_DISABLE>;
+       };
+
+       led_d7_pins_mbmx28lc: led-d7-mbmx28lc@0 {
+               reg = <0>;
+               fsl,pinmux-ids = <
+                       MX28_PAD_LCD_D22__GPIO_1_22
+               >;
+               fsl,drive-strength = <MXS_DRIVE_4mA>;
+               fsl,voltage = <MXS_VOLTAGE_HIGH>;
+               fsl,pull-up = <MXS_PULL_DISABLE>;
+       };
+
+       reg_lcd_3v3_pins_mbmx28lc: lcd-3v3-mbmx28lc@0 {
+               reg = <0>;
+               fsl,pinmux-ids = <
+                       MX28_PAD_LCD_RESET__GPIO_3_30
+               >;
+               fsl,drive-strength = <MXS_DRIVE_4mA>;
+               fsl,voltage = <MXS_VOLTAGE_HIGH>;
+               fsl,pull-up = <MXS_PULL_DISABLE>;
+       };
+
+       reg_usb0_vbus_pins_mbmx28lc: reg-usb0-vbus-mbmx28lc@0 {
+               reg = <0>;
+               fsl,pinmux-ids = <
+                       MX28_PAD_LCD_D18__GPIO_1_18
+               >;
+               fsl,drive-strength = <MXS_DRIVE_4mA>;
+               fsl,voltage = <MXS_VOLTAGE_HIGH>;
+               fsl,pull-up = <MXS_PULL_DISABLE>;
+       };
+
+       reg_usb1_vbus_pins_mbmx28lc: reg-usb1-vbus-mbmx28lc@0 {
+               reg = <0>;
+               fsl,pinmux-ids = <
+                       MX28_PAD_LCD_D19__GPIO_1_19
+               >;
+               fsl,drive-strength = <MXS_DRIVE_4mA>;
+               fsl,voltage = <MXS_VOLTAGE_HIGH>;
+               fsl,pull-up = <MXS_PULL_DISABLE>;
+       };
+};
+
+&pwm {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pwm4_pins_a>;
+       status = "okay";
+};
+
+&saif0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&saif0_pins_a>;
+       status = "okay";
+};
+
+&saif1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&saif1_pins_a>;
+       fsl,saif-master = <&saif0>;
+       status = "okay";
+};
+
+&ssp0 {
+       compatible = "fsl,imx28-mmc";
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc0_4bit_pins_a &mmc0_cd_cfg &mmc0_sck_cfg>;
+       bus-width = <4>;
+       cd-inverted;
+       status = "okay";
+};
+
+&usb0 {
+       disable-over-current;
+       vbus-supply = <&reg_usb0_vbus>;
+       status = "okay";
+       pinctrl-names = "default";
+       pinctrl-0 = <&usb0_id_pins_b>;
+};
+
+&usb1 {
+       vbus-supply = <&reg_usb1_vbus>;
+       status = "okay";
+};
+
+&usbphy0 {
+       status = "okay";
+};
+
+&usbphy1 {
+       status = "okay";
+};
index 4267c2b05d600ac8bfb9cf2612a3b72977d7dc0e..e4cc44c98585f415744e30a41fd4d066797043a3 100644 (file)
                        i2c0: i2c@80058000 {
                                pinctrl-names = "default";
                                pinctrl-0 = <&i2c0_pins_a>;
+                               clock-frequency = <400000>;
                                status = "okay";
 
                                sgtl5000: codec@0a {
 
        regulators {
                compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
 
-               reg_3p3v: 3p3v {
+               reg_3p3v: regulator@0 {
                        compatible = "regulator-fixed";
+                       reg = <0>;
                        regulator-name = "3P3V";
                        regulator-min-microvolt = <3300000>;
                        regulator-max-microvolt = <3300000>;
                        regulator-always-on;
                };
 
-               reg_vddio_sd0: vddio-sd0 {
+               reg_vddio_sd0: regulator@1 {
                        compatible = "regulator-fixed";
+                       reg = <1>;
                        regulator-name = "vddio-sd0";
                        regulator-min-microvolt = <3300000>;
                        regulator-max-microvolt = <3300000>;
                        gpio = <&gpio3 28 0>;
                };
 
-               reg_fec_3v3: fec-3v3 {
+               reg_fec_3v3: regulator@2 {
                        compatible = "regulator-fixed";
+                       reg = <2>;
                        regulator-name = "fec-3v3";
                        regulator-min-microvolt = <3300000>;
                        regulator-max-microvolt = <3300000>;
                        gpio = <&gpio2 15 0>;
                };
 
-               reg_usb0_vbus: usb0_vbus {
+               reg_usb0_vbus: regulator@3 {
                        compatible = "regulator-fixed";
+                       reg = <3>;
                        regulator-name = "usb0_vbus";
                        regulator-min-microvolt = <5000000>;
                        regulator-max-microvolt = <5000000>;
                        enable-active-high;
                };
 
-               reg_usb1_vbus: usb1_vbus {
+               reg_usb1_vbus: regulator@4 {
                        compatible = "regulator-fixed";
+                       reg = <4>;
                        regulator-name = "usb1_vbus";
                        regulator-min-microvolt = <5000000>;
                        regulator-max-microvolt = <5000000>;
                        enable-active-high;
                };
 
-               reg_lcd_3v3: lcd-3v3 {
+               reg_lcd_3v3: regulator@5 {
                        compatible = "regulator-fixed";
+                       reg = <5>;
                        regulator-name = "lcd-3v3";
                        regulator-min-microvolt = <3300000>;
                        regulator-max-microvolt = <3300000>;
                        enable-active-high;
                };
 
-               reg_can_3v3: can-3v3 {
+               reg_can_3v3: regulator@6 {
                        compatible = "regulator-fixed";
+                       reg = <6>;
                        regulator-name = "can-3v3";
                        regulator-min-microvolt = <3300000>;
                        regulator-max-microvolt = <3300000>;
index d3958da60bd72e95052ff08af73a46b83b461c58..15f3b39716e8602b1fe5d0184ccdf26bf6161b39 100644 (file)
                usb1: usb@80090000 {
                        vbus-supply = <&reg_usb1_vbus>;
                        pinctrl-names = "default";
-                       pinctrl-0 = <&usbphy1_pins_a>;
+                       pinctrl-0 = <&usb1_pins_a>;
                        disable-over-current;
                        status = "okay";
                };
 
        regulators {
                compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
 
-               reg_3p3v: 3p3v {
+               reg_3p3v: regulator@0 {
                        compatible = "regulator-fixed";
+                       reg = <0>;
                        regulator-name = "3P3V";
                        regulator-min-microvolt = <3300000>;
                        regulator-max-microvolt = <3300000>;
                        regulator-always-on;
                };
 
-               reg_vddio_sd0: vddio-sd0 {
+               reg_vddio_sd0: regulator@1 {
                        compatible = "regulator-fixed";
+                       reg = <1>;
                        regulator-name = "vddio-sd0";
                        regulator-min-microvolt = <3300000>;
                        regulator-max-microvolt = <3300000>;
                        gpio = <&gpio3 29 0>;
                };
 
-               reg_vddio_sd1: vddio-sd1 {
+               reg_vddio_sd1: regulator@2 {
                        compatible = "regulator-fixed";
+                       reg = <2>;
                        regulator-name = "vddio-sd1";
                        regulator-min-microvolt = <3300000>;
                        regulator-max-microvolt = <3300000>;
                        gpio = <&gpio2 19 0>;
                };
 
-               reg_usb1_vbus: usb1_vbus {
+               reg_usb1_vbus: regulator@3 {
                        compatible = "regulator-fixed";
+                       reg = <3>;
                        regulator-name = "usb1_vbus";
                        regulator-min-microvolt = <5000000>;
                        regulator-max-microvolt = <5000000>;
index 8e2477fbe1d70963d583973ed4c46a6554c99104..8536b0db9018e8b580d502f8e7a52e9770743590 100644 (file)
                usb0: usb@80080000 {
                        vbus-supply = <&reg_usb0_vbus>;
                        pinctrl-names = "default";
-                       pinctrl-0 = <&usbphy0_pins_a>;
+                       pinctrl-0 = <&usb0_pins_a>;
                        status = "okay";
                };
 
                usb1: usb@80090000 {
                        vbus-supply = <&reg_usb1_vbus>;
                        pinctrl-names = "default";
-                       pinctrl-0 = <&usbphy1_pins_a>;
+                       pinctrl-0 = <&usb1_pins_a>;
                        status = "okay";
                };
 
 
        regulators {
                compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
 
-               reg_3p3v: 3p3v {
+               reg_3p3v: regulator@0 {
                        compatible = "regulator-fixed";
+                       reg = <0>;
                        regulator-name = "3P3V";
                        regulator-min-microvolt = <3300000>;
                        regulator-max-microvolt = <3300000>;
                        regulator-always-on;
                };
 
-               reg_vddio_sd0: vddio-sd0 {
+               reg_vddio_sd0: regulator@1 {
                        compatible = "regulator-fixed";
+                       reg = <1>;
                        regulator-name = "vddio-sd0";
                        regulator-min-microvolt = <3300000>;
                        regulator-max-microvolt = <3300000>;
                        gpio = <&gpio3 28 0>;
                };
 
-               reg_usb0_vbus: usb0_vbus {
+               reg_usb0_vbus: regulator@2 {
                        compatible = "regulator-fixed";
+                       reg = <2>;
                        regulator-name = "usb0_vbus";
                        regulator-min-microvolt = <5000000>;
                        regulator-max-microvolt = <5000000>;
                        gpio = <&gpio3 12 0>;
                };
 
-               reg_usb1_vbus: usb1_vbus {
+               reg_usb1_vbus: regulator@3 {
                        compatible = "regulator-fixed";
+                       reg = <3>;
                        regulator-name = "usb1_vbus";
                        regulator-min-microvolt = <5000000>;
                        regulator-max-microvolt = <5000000>;
index 4870f07bf56a86423c6a910a5c86ce6fce1624a4..0ce3cb8e7914ecebdaccd0b576bdd2f3420329e8 100644 (file)
                usb0: usb@80080000 {
                        vbus-supply = <&reg_usb0_vbus>;
                        pinctrl-names = "default";
-                       pinctrl-0 = <&usbphy0_pins_b>;
+                       pinctrl-0 = <&usb0_pins_b>;
                        status = "okay";
                };
 
 
        regulators {
                compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
 
-               reg_usb0_vbus: usb0_vbus {
+               reg_usb0_vbus: regulator@0 {
                        compatible = "regulator-fixed";
+                       reg = <0>;
                        regulator-name = "usb0_vbus";
                        regulator-min-microvolt = <5000000>;
                        regulator-max-microvolt = <5000000>;
index be5a0550d58c3312d37f36e04c937d5739c7f181..3c54e8d152e6dccabeaf61b79506c8ae5e6534fc 100644 (file)
 
        regulators {
                compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
 
-               reg_usb0_vbus: usb0_vbus {
+               reg_usb0_vbus: regulator@0 {
                        compatible = "regulator-fixed";
+                       reg = <0>;
                        regulator-name = "usb0_vbus";
                        regulator-min-microvolt = <5000000>;
                        regulator-max-microvolt = <5000000>;
@@ -53,8 +56,9 @@
                        enable-active-high;
                };
 
-               reg_usb1_vbus: usb1_vbus {
+               reg_usb1_vbus: regulator@1 {
                        compatible = "regulator-fixed";
+                       reg = <1>;
                        regulator-name = "usb1_vbus";
                        regulator-min-microvolt = <5000000>;
                        regulator-max-microvolt = <5000000>;
                        enable-active-high;
                };
 
-               reg_2p5v: 2p5v {
+               reg_2p5v: regulator@2 {
                        compatible = "regulator-fixed";
+                       reg = <2>;
                        regulator-name = "2P5V";
                        regulator-min-microvolt = <2500000>;
                        regulator-max-microvolt = <2500000>;
                        regulator-always-on;
                };
 
-               reg_3p3v: 3p3v {
+               reg_3p3v: regulator@3 {
                        compatible = "regulator-fixed";
+                       reg = <3>;
                        regulator-name = "3P3V";
                        regulator-min-microvolt = <3300000>;
                        regulator-max-microvolt = <3300000>;
                        regulator-always-on;
                };
 
-               reg_can_xcvr: can-xcvr {
+               reg_can_xcvr: regulator@4 {
                        compatible = "regulator-fixed";
+                       reg = <4>;
                        regulator-name = "CAN XCVR";
                        regulator-min-microvolt = <3300000>;
                        regulator-max-microvolt = <3300000>;
@@ -89,8 +96,9 @@
                        pinctrl-0 = <&tx28_flexcan_xcvr_pins>;
                };
 
-               reg_lcd: lcd-power {
+               reg_lcd: regulator@5 {
                        compatible = "regulator-fixed";
+                       reg = <5>;
                        regulator-name = "LCD POWER";
                        regulator-min-microvolt = <3300000>;
                        regulator-max-microvolt = <3300000>;
                        enable-active-high;
                };
 
-               reg_lcd_reset: lcd-reset {
+               reg_lcd_reset: regulator@6 {
                        compatible = "regulator-fixed";
+                       reg = <6>;
                        regulator-name = "LCD RESET";
                        regulator-min-microvolt = <3300000>;
                        regulator-max-microvolt = <3300000>;
index cda19c8b0a470ecb6900255c8a9eb17b85bdf9dc..8a2a70d24d148ad6eade597920fc91983cee5120 100644 (file)
                                        fsl,pull-up = <MXS_PULL_DISABLE>;
                                };
 
+                               auart2_pins_a: auart2-pins@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               MX28_PAD_AUART2_RX__AUART2_RX
+                                               MX28_PAD_AUART2_TX__AUART2_TX
+                                               MX28_PAD_AUART2_CTS__AUART2_CTS
+                                               MX28_PAD_AUART2_RTS__AUART2_RTS
+                                       >;
+                                       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 = <
                                        fsl,pull-up = <MXS_PULL_DISABLE>;
                                };
 
+                               lcdif_18bit_pins_a: lcdif-18bit@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               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 = <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 = <
                                        fsl,pull-up = <MXS_PULL_DISABLE>;
                                };
 
-                               usbphy0_pins_a: usbphy0@0 {
+                               usb0_pins_a: usb0@0 {
                                        reg = <0>;
                                        fsl,pinmux-ids = <
                                                MX28_PAD_SSP2_SS2__USB0_OVERCURRENT
                                        fsl,pull-up = <MXS_PULL_DISABLE>;
                                };
 
-                               usbphy0_pins_b: usbphy0@1 {
+                               usb0_pins_b: usb0@1 {
                                        reg = <1>;
                                        fsl,pinmux-ids = <
                                                MX28_PAD_AUART1_CTS__USB0_OVERCURRENT
                                        fsl,pull-up = <MXS_PULL_DISABLE>;
                                };
 
-                               usbphy1_pins_a: usbphy1@0 {
+                               usb1_pins_a: usb1@0 {
                                        reg = <0>;
                                        fsl,pinmux-ids = <
                                                MX28_PAD_SSP2_SS1__USB1_OVERCURRENT
                                        fsl,voltage = <MXS_VOLTAGE_HIGH>;
                                        fsl,pull-up = <MXS_PULL_ENABLE>;
                                };
+
+                               usb0_id_pins_b: usb0id1@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               MX28_PAD_PWM2__USB0_ID
+                                       >;
+                                       fsl,drive-strength = <MXS_DRIVE_12mA>;
+                                       fsl,voltage = <MXS_VOLTAGE_HIGH>;
+                                       fsl,pull-up = <MXS_PULL_ENABLE>;
+                               };
+
                        };
 
                        digctl: digctl@8001c000 {
                                                20 21 22 23 24 25>;
                                status = "disabled";
                                clocks = <&clks 41>;
+                               #io-channel-cells = <1>;
                        };
 
                        spdif: spdif@80054000 {
diff --git a/arch/arm/boot/dts/imx50-evk.dts b/arch/arm/boot/dts/imx50-evk.dts
new file mode 100644 (file)
index 0000000..a859264
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2013 Greg Ungerer <gerg@uclinux.org>
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx50.dtsi"
+
+/ {
+       model = "Freescale i.MX50 Evaluation Kit";
+       compatible = "fsl,imx50-evk", "fsl,imx50";
+
+       memory {
+               reg = <0x70000000 0x80000000>;
+       };
+};
+
+&cspi {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_cspi>;
+       fsl,spi-num-chipselects = <2>;
+       cs-gpios = <&gpio4 11 0>, <&gpio4 13 0>;
+       status = "okay";
+
+       flash: m25p32@1 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "m25p32", "m25p80";
+               spi-max-frequency = <25000000>;
+               reg = <1>;
+
+               partition@0 {
+                       label = "bootloader";
+                       reg = <0x0 0x100000>;
+                       read-only;
+               };
+
+               partition@100000 {
+                       label = "kernel";
+                       reg = <0x100000 0x300000>;
+               };
+       };
+};
+
+&fec {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_fec>;
+       phy-mode = "rmii";
+       phy-reset-gpios = <&gpio4 12 0>;
+       status = "okay";
+};
+
+&iomuxc {
+       imx50-evk {
+               pinctrl_cspi: cspigrp {
+                       fsl,pins = <MX50_CSPI_PINGRP1>;
+               };
+
+               pinctrl_fec: fecgrp {
+                       fsl,pins = <MX50_FEC_PINGRP1>;
+               };
+
+               pinctrl_uart1: uart1grp {
+                       fsl,pins = <MX50_UART1_PINGRP1>;
+               };
+       };
+};
+
+&uart1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart1>;
+       status = "okay";
+};
+
+&usbh1 {
+       status = "okay";
+};
+
+&usbh2 {
+       status = "okay";
+};
+
+&usbh3 {
+       status = "okay";
+};
+
+&usbotg {
+       status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx50-pinfunc.h b/arch/arm/boot/dts/imx50-pinfunc.h
new file mode 100644 (file)
index 0000000..97e6e7f
--- /dev/null
@@ -0,0 +1,923 @@
+/*
+ * Copyright 2013 Greg Ungerer <gerg@uclinux.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 __DTS_IMX50_PINFUNC_H
+#define __DTS_IMX50_PINFUNC_H
+
+/*
+ * The pin function ID is a tuple of
+ * <mux_reg conf_reg input_reg mux_mode input_val>
+ */
+#define MX50_PAD_KEY_COL0__KPP_COL_0                           0x020 0x2cc 0x000 0x0 0x0
+#define MX50_PAD_KEY_COL0__GPIO4_0                             0x020 0x2cc 0x000 0x1 0x0
+#define MX50_PAD_KEY_COL0__EIM_NANDF_CLE                       0x020 0x2cc 0x000 0x2 0x0
+#define MX50_PAD_KEY_COL0__CTI_TRIGIN7                         0x020 0x2cc 0x000 0x6 0x0
+#define MX50_PAD_KEY_COL0__USBPHY1_TXREADY                     0x020 0x2cc 0x000 0x7 0x0
+#define MX50_PAD_KEY_ROW0__KPP_ROW_0                           0x024 0x2d0 0x000 0x0 0x0
+#define MX50_PAD_KEY_ROW0__GPIO4_1                             0x024 0x2d0 0x000 0x1 0x0
+#define MX50_PAD_KEY_ROW0__EIM_NANDF_ALE                       0x024 0x2d0 0x000 0x2 0x0
+#define MX50_PAD_KEY_ROW0__CTI_TRIGIN_ACK7                     0x024 0x2d0 0x000 0x6 0x0
+#define MX50_PAD_KEY_ROW0__USBPHY1_RXVALID                     0x024 0x2d0 0x000 0x7 0x0
+#define MX50_PAD_KEY_COL1__KPP_COL_1                           0x028 0x2d4 0x000 0x0 0x0
+#define MX50_PAD_KEY_COL1__GPIO4_2                             0x028 0x2d4 0x000 0x1 0x0
+#define MX50_PAD_KEY_COL1__EIM_NANDF_CEN_0                     0x028 0x2d4 0x000 0x2 0x0
+#define MX50_PAD_KEY_COL1__CTI_TRIGOUT_ACK6                    0x028 0x2d4 0x000 0x6 0x0
+#define MX50_PAD_KEY_COL1__USBPHY1_RXACTIVE                    0x028 0x2d4 0x000 0x7 0x0
+#define MX50_PAD_KEY_ROW1__KPP_ROW_1                           0x02c 0x2d8 0x000 0x0 0x0
+#define MX50_PAD_KEY_ROW1__GPIO4_3                             0x02c 0x2d8 0x000 0x1 0x0
+#define MX50_PAD_KEY_ROW1__EIM_NANDF_CEN_1                     0x02c 0x2d8 0x000 0x2 0x0
+#define MX50_PAD_KEY_ROW1__CTI_TRIGOUT_ACK7                    0x02c 0x2d8 0x000 0x6 0x0
+#define MX50_PAD_KEY_ROW1__USBPHY1_RXERROR                     0x02c 0x2d8 0x000 0x7 0x0
+#define MX50_PAD_KEY_COL2__KPP_COL_1                           0x030 0x2dc 0x000 0x0 0x0
+#define MX50_PAD_KEY_COL2__GPIO4_4                             0x030 0x2dc 0x000 0x1 0x0
+#define MX50_PAD_KEY_COL2__EIM_NANDF_CEN_2                     0x030 0x2dc 0x000 0x2 0x0
+#define MX50_PAD_KEY_COL2__CTI_TRIGOUT6                                0x030 0x2dc 0x000 0x6 0x0
+#define MX50_PAD_KEY_COL2__USBPHY1_SIECLOCK                    0x030 0x2dc 0x000 0x7 0x0
+#define MX50_PAD_KEY_ROW2__KPP_ROW_2                           0x034 0x2e0 0x000 0x0 0x0
+#define MX50_PAD_KEY_ROW2__GPIO4_5                             0x034 0x2e0 0x000 0x1 0x0
+#define MX50_PAD_KEY_ROW2__EIM_NANDF_CEN_3                     0x034 0x2e0 0x000 0x2 0x0
+#define MX50_PAD_KEY_ROW2__CTI_TRIGOUT7                                0x034 0x2e0 0x000 0x6 0x0
+#define MX50_PAD_KEY_ROW2__USBPHY1_LINESTATE_0                 0x034 0x2e0 0x000 0x7 0x0
+#define MX50_PAD_KEY_COL3__KPP_COL_2                           0x038 0x2e4 0x000 0x0 0x0
+#define MX50_PAD_KEY_COL3__GPIO4_6                             0x038 0x2e4 0x000 0x1 0x0
+#define MX50_PAD_KEY_COL3__EIM_NANDF_READY0                    0x038 0x2e4 0x7b4 0x2 0x0
+#define MX50_PAD_KEY_COL3__SDMA_EXT_EVENT_0                    0x038 0x2e4 0x7b8 0x6 0x0
+#define MX50_PAD_KEY_COL3__USBPHY1_LINESTATE_1                 0x038 0x2e4 0x000 0x7 0x0
+#define MX50_PAD_KEY_ROW3__KPP_ROW_3                           0x03c 0x2e8 0x000 0x0 0x0
+#define MX50_PAD_KEY_ROW3__GPIO4_7                             0x03c 0x2e8 0x000 0x1 0x0
+#define MX50_PAD_KEY_ROW3__EIM_NANDF_DQS                       0x03c 0x2e8 0x7b0 0x2 0x0
+#define MX50_PAD_KEY_ROW3__SDMA_EXT_EVENT_1                    0x03c 0x2e8 0x7bc 0x6 0x0
+#define MX50_PAD_KEY_ROW3__USBPHY1_VBUSVALID                   0x03c 0x2e8 0x000 0x7 0x0
+#define MX50_PAD_I2C1_SCL__I2C1_SCL                            0x040 0x2ec 0x000 0x0 0x0
+#define MX50_PAD_I2C1_SCL__GPIO6_18                            0x040 0x2ec 0x000 0x1 0x0
+#define MX50_PAD_I2C1_SCL__UART2_TXD_MUX                       0x040 0x2ec 0x7cc 0x2 0x0
+#define MX50_PAD_I2C1_SDA__I2C1_SDA                            0x044 0x2f0 0x000 0x0 0x0
+#define MX50_PAD_I2C1_SDA__GPIO6_19                            0x044 0x2f0 0x000 0x1 0x0
+#define MX50_PAD_I2C1_SDA__UART2_RXD_MUX                       0x044 0x2f0 0x7cc 0x2 0x1
+#define MX50_PAD_I2C2_SCL__I2C2_SCL                            0x048 0x2f4 0x000 0x0 0x0
+#define MX50_PAD_I2C2_SCL__GPIO6_20                            0x048 0x2f4 0x000 0x1 0x0
+#define MX50_PAD_I2C2_SCL__UART2_CTS                           0x048 0x2f4 0x000 0x2 0x0
+#define MX50_PAD_I2C2_SDA__I2C2_SDA                            0x04c 0x2f8 0x000 0x0 0x0
+#define MX50_PAD_I2C2_SDA__GPIO6_21                            0x04c 0x2f8 0x000 0x1 0x0
+#define MX50_PAD_I2C2_SDA__UART2_RTS                           0x04c 0x2f8 0x7c8 0x2 0x1
+#define MX50_PAD_I2C3_SCL__I2C3_SCL                            0x050 0x2fc 0x000 0x0 0x0
+#define MX50_PAD_I2C3_SCL__GPIO6_22                            0x050 0x2fc 0x000 0x1 0x0
+#define MX50_PAD_I2C3_SCL__FEC_MDC                             0x050 0x2fc 0x000 0x2 0x0
+#define MX50_PAD_I2C3_SCL__GPC_PMIC_RDY                                0x050 0x2fc 0x000 0x3 0x0
+#define MX50_PAD_I2C3_SCL__GPT_CAPIN1                          0x050 0x2fc 0x000 0x5 0x0
+#define MX50_PAD_I2C3_SCL__OBSERVE_MUX_OBSRV_INT_OUT0          0x050 0x2fc 0x000 0x6 0x0
+#define MX50_PAD_I2C3_SCL__USBOH1_USBOTG_OC                    0x050 0x2fc 0x7e8 0x7 0x0
+#define MX50_PAD_I2C3_SDA__I2C3_SDA                            0x054 0x300 0x000 0x0 0x0
+#define MX50_PAD_I2C3_SDA__GPIO6_23                            0x054 0x300 0x000 0x1 0x0
+#define MX50_PAD_I2C3_SDA__FEC_MDIO                            0x054 0x300 0x774 0x2 0x0
+#define MX50_PAD_I2C3_SDA__TZIC_PWRFAIL_INT                    0x054 0x300 0x000 0x3 0x0
+#define MX50_PAD_I2C3_SDA__SRTC_ALARM_DEB                      0x054 0x300 0x000 0x4 0x0
+#define MX50_PAD_I2C3_SDA__GPT_CAPIN2                          0x054 0x300 0x000 0x5 0x0
+#define MX50_PAD_I2C3_SDA__OBSERVE_MUX_OBSRV_INT_OUT1          0x054 0x300 0x000 0x6 0x0
+#define MX50_PAD_I2C3_SDA__USBOH1_USBOTG_PWR                   0x054 0x300 0x000 0x7 0x0
+#define MX50_PAD_PWM1__PWM1_PWMO                               0x058 0x304 0x000 0x0 0x0
+#define MX50_PAD_PWM1__GPIO6_24                                        0x058 0x304 0x000 0x1 0x0
+#define MX50_PAD_PWM1__USBOH1_USBOTG_OC                                0x058 0x304 0x7e8 0x2 0x1
+#define MX50_PAD_PWM1__GPT_CMPOUT1                             0x058 0x304 0x000 0x5 0x0
+#define MX50_PAD_PWM1__OBSERVE_MUX_OBSRV_INT_OUT2              0x058 0x304 0x000 0x6 0x0
+#define MX50_PAD_PWM1__SJC_FAIL                                        0x058 0x304 0x000 0x7 0x0
+#define MX50_PAD_PWM2__PWM2_PWMO                               0x05c 0x308 0x000 0x0 0x0
+#define MX50_PAD_PWM2__GPIO6_25                                        0x05c 0x308 0x000 0x1 0x0
+#define MX50_PAD_PWM2__USBOH1_USBOTG_PWR                       0x05c 0x308 0x000 0x2 0x0
+#define MX50_PAD_PWM2__GPT_CMPOUT2                             0x05c 0x308 0x000 0x5 0x0
+#define MX50_PAD_PWM2__OBSERVE_MUX_OBSRV_INT_OUT3              0x05c 0x308 0x000 0x6 0x0
+#define MX50_PAD_PWM2__SRC_ANY_PU_RST                          0x05c 0x308 0x000 0x7 0x0
+#define MX50_PAD_OWIRE__OWIRE_LINE                             0x060 0x30c 0x000 0x0 0x0
+#define MX50_PAD_OWIRE__GPIO6_26                               0x060 0x30c 0x000 0x1 0x0
+#define MX50_PAD_OWIRE__USBOH1_USBH1_OC                                0x060 0x30c 0x000 0x2 0x0
+#define MX50_PAD_OWIRE__CCM_SSI_EXT1_CLK                       0x060 0x30c 0x000 0x3 0x0
+#define MX50_PAD_OWIRE__EPDC_PWRIRQ                            0x060 0x30c 0x000 0x4 0x0
+#define MX50_PAD_OWIRE__GPT_CMPOUT3                            0x060 0x30c 0x000 0x5 0x0
+#define MX50_PAD_OWIRE__OBSERVE_MUX_OBSRV_INT_OUT4             0x060 0x30c 0x000 0x6 0x0
+#define MX50_PAD_OWIRE__SJC_JTAG_ACT                           0x060 0x30c 0x000 0x7 0x0
+#define MX50_PAD_EPITO__EPIT1_EPITO                            0x064 0x310 0x000 0x0 0x0
+#define MX50_PAD_EPITO__GPIO6_27                               0x064 0x310 0x000 0x1 0x0
+#define MX50_PAD_EPITO__USBOH1_USBH1_PWR                       0x064 0x310 0x000 0x2 0x0
+#define MX50_PAD_EPITO__CCM_SSI_EXT2_CLK                       0x064 0x310 0x000 0x3 0x0
+#define MX50_PAD_EPITO__DPLLIP1_TOG_EN                         0x064 0x310 0x000 0x4 0x0
+#define MX50_PAD_EPITO__GPT_CLK_IN                             0x064 0x310 0x000 0x5 0x0
+#define MX50_PAD_EPITO__PMU_IRQ_B                              0x064 0x310 0x000 0x6 0x0
+#define MX50_PAD_EPITO__SJC_DE_B                               0x064 0x310 0x000 0x7 0x0
+#define MX50_PAD_WDOG__WDOG1_WDOG_B                            0x068 0x314 0x000 0x0 0x0
+#define MX50_PAD_WDOG__GPIO6_28                                        0x068 0x314 0x000 0x1 0x0
+#define MX50_PAD_WDOG__WDOG1_WDOG_RST_B_DEB                    0x068 0x314 0x000 0x2 0x0
+#define MX50_PAD_WDOG__CCM_XTAL32K                             0x068 0x314 0x000 0x6 0x0
+#define MX50_PAD_WDOG__SJC_DONE                                        0x068 0x314 0x000 0x7 0x0
+#define MX50_PAD_SSI_TXFS__AUDMUX_AUD3_TXFS                    0x06c 0x318 0x000 0x0 0x0
+#define MX50_PAD_SSI_TXFS__GPIO6_0                             0x06c 0x318 0x000 0x1 0x0
+#define MX50_PAD_SSI_TXFS__SRC_BT_FUSE_RSV_1                   0x06c 0x318 0x000 0x6 0x0
+#define MX50_PAD_SSI_TXFS__USBPHY1_DATAOUT_8                   0x06c 0x318 0x000 0x7 0x0
+#define MX50_PAD_SSI_TXC__AUDMUX_AUD3_TXC                      0x070 0x31c 0x000 0x0 0x0
+#define MX50_PAD_SSI_TXC__GPIO6_1                              0x070 0x31c 0x000 0x1 0x0
+#define MX50_PAD_SSI_TXC__SRC_BT_FUSE_RSV_0                    0x070 0x31c 0x000 0x6 0x0
+#define MX50_PAD_SSI_TXC__USBPHY1_DATAOUT_9                    0x070 0x31c 0x000 0x7 0x0
+#define MX50_PAD_SSI_TXD__AUDMUX_AUD3_TXD                      0x074 0x320 0x000 0x0 0x0
+#define MX50_PAD_SSI_TXD__GPIO6_2                              0x074 0x320 0x000 0x1 0x0
+#define MX50_PAD_SSI_TXD__CSPI_RDY                             0x074 0x320 0x6e8 0x4 0x0
+#define MX50_PAD_SSI_TXD__USBPHY1_DATAOUT_10                   0x074 0x320 0x000 0x7 0x0
+#define MX50_PAD_SSI_RXD__AUDMUX_AUD3_RXD                      0x078 0x324 0x000 0x0 0x0
+#define MX50_PAD_SSI_RXD__GPIO6_3                              0x078 0x324 0x000 0x1 0x0
+#define MX50_PAD_SSI_RXD__CSPI_SS3                             0x078 0x324 0x6f4 0x4 0x0
+#define MX50_PAD_SSI_RXD__USBPHY1_DATAOUT_11                   0x078 0x324 0x000 0x7 0x0
+#define MX50_PAD_SSI_RXFS__AUDMUX_AUD3_RXFS                    0x07c 0x328 0x000 0x0 0x0
+#define MX50_PAD_SSI_RXFS__GPIO6_4                             0x07c 0x328 0x000 0x1 0x0
+#define MX50_PAD_SSI_RXFS__UART5_TXD_MUX                       0x07c 0x328 0x7e4 0x2 0x0
+#define MX50_PAD_SSI_RXFS__EIM_WEIM_D_6                                0x07c 0x328 0x804 0x3 0x0
+#define MX50_PAD_SSI_RXFS__CSPI_SS2                            0x07c 0x328 0x6f0 0x4 0x0
+#define MX50_PAD_SSI_RXFS__FEC_COL                             0x07c 0x328 0x770 0x5 0x0
+#define MX50_PAD_SSI_RXFS__FEC_MDC                             0x07c 0x328 0x000 0x6 0x0
+#define MX50_PAD_SSI_RXFS__USBPHY1_DATAOUT_12                  0x07c 0x328 0x000 0x7 0x0
+#define MX50_PAD_SSI_RXC__AUDMUX_AUD3_RXC                      0x080 0x32c 0x000 0x0 0x0
+#define MX50_PAD_SSI_RXC__GPIO6_5                              0x080 0x32c 0x000 0x1 0x0
+#define MX50_PAD_SSI_RXC__UART5_RXD_MUX                                0x080 0x32c 0x7e4 0x2 0x1
+#define MX50_PAD_SSI_RXC__EIM_WEIM_D_7                         0x080 0x32c 0x808 0x3 0x0
+#define MX50_PAD_SSI_RXC__CSPI_SS1                             0x080 0x32c 0x6ec 0x4 0x0
+#define MX50_PAD_SSI_RXC__FEC_RX_CLK                           0x080 0x32c 0x780 0x5 0x0
+#define MX50_PAD_SSI_RXC__FEC_MDIO                             0x080 0x32c 0x774 0x6 0x1
+#define MX50_PAD_SSI_RXC__USBPHY1_DATAOUT_13                   0x080 0x32c 0x000 0x7 0x0
+#define MX50_PAD_UART1_TXD__UART1_TXD_MUX                      0x084 0x330 0x7c4 0x0 0x0
+#define MX50_PAD_UART1_TXD__GPIO6_6                            0x084 0x330 0x000 0x1 0x0
+#define MX50_PAD_UART1_TXD__USBPHY1_DATAOUT_14                 0x084 0x330 0x000 0x7 0x0
+#define MX50_PAD_UART1_RXD__UART1_RXD_MUX                      0x088 0x334 0x7c4 0x0 0x1
+#define MX50_PAD_UART1_RXD__GPIO6_7                            0x088 0x334 0x000 0x1 0x0
+#define MX50_PAD_UART1_RXD__USBPHY1_DATAOUT_15                 0x088 0x334 0x000 0x7 0x0
+#define MX50_PAD_UART1_CTS__UART1_CTS                          0x08c 0x338 0x000 0x0 0x0
+#define MX50_PAD_UART1_CTS__GPIO6_8                            0x08c 0x338 0x000 0x1 0x0
+#define MX50_PAD_UART1_CTS__UART5_TXD_MUX                      0x08c 0x338 0x7e4 0x2 0x2
+#define MX50_PAD_UART1_CTS__ESDHC4_DAT4                                0x08c 0x338 0x760 0x4 0x0
+#define MX50_PAD_UART1_CTS__ESDHC4_CMD                         0x08c 0x338 0x74c 0x5 0x0
+#define MX50_PAD_UART1_CTS__USBPHY2_DATAOUT_8                  0x08c 0x338 0x000 0x7 0x0
+#define MX50_PAD_UART1_RTS__UART1_RTS                          0x090 0x33c 0x7c0 0x0 0x3
+#define MX50_PAD_UART1_RTS__GPIO6_9                            0x090 0x33c 0x000 0x1 0x0
+#define MX50_PAD_UART1_RTS__UART5_RXD_MUX                      0x090 0x33c 0x7e4 0x2 0x3
+#define MX50_PAD_UART1_RTS__ESDHC4_DAT5                                0x090 0x33c 0x764 0x4 0x0
+#define MX50_PAD_UART1_RTS__ESDHC4_CLK                         0x090 0x33c 0x748 0x5 0x0
+#define MX50_PAD_UART1_RTS__USBPHY2_DATAOUT_9                  0x090 0x33c 0x000 0x7 0x0
+#define MX50_PAD_UART2_TXD__UART2_TXD_MUX                      0x094 0x340 0x7cc 0x0 0x2
+#define MX50_PAD_UART2_TXD__GPIO6_10                           0x094 0x340 0x000 0x1 0x0
+#define MX50_PAD_UART2_TXD__ESDHC4_DAT6                                0x094 0x340 0x768 0x4 0x0
+#define MX50_PAD_UART2_TXD__ESDHC4_DAT4                                0x094 0x340 0x760 0x5 0x1
+#define MX50_PAD_UART2_TXD__USBPHY2_DATAOUT_10                 0x094 0x340 0x000 0x7 0x0
+#define MX50_PAD_UART2_RXD__UART2_RXD_MUX                      0x098 0x344 0x7cc 0x0 0x3
+#define MX50_PAD_UART2_RXD__GPIO6_11                           0x098 0x344 0x000 0x1 0x0
+#define MX50_PAD_UART2_RXD__ESDHC4_DAT7                                0x098 0x344 0x76c 0x4 0x0
+#define MX50_PAD_UART2_RXD__ESDHC4_DAT5                                0x098 0x344 0x764 0x5 0x1
+#define MX50_PAD_UART2_RXD__USBPHY2_DATAOUT_11                 0x098 0x344 0x000 0x7 0x0
+#define MX50_PAD_UART2_CTS__UART2_CTS                          0x09c 0x348 0x000 0x0 0x0
+#define MX50_PAD_UART2_CTS__GPIO6_12                           0x09c 0x348 0x000 0x1 0x0
+#define MX50_PAD_UART2_CTS__ESDHC4_CMD                         0x09c 0x348 0x74c 0x4 0x1
+#define MX50_PAD_UART2_CTS__ESDHC4_DAT6                                0x09c 0x348 0x768 0x5 0x1
+#define MX50_PAD_UART2_CTS__USBPHY2_DATAOUT_12                 0x09c 0x348 0x000 0x7 0x0
+#define MX50_PAD_UART2_RTS__UART2_RTS                          0x0a0 0x34c 0x7c8 0x0 0x2
+#define MX50_PAD_UART2_RTS__GPIO6_13                           0x0a0 0x34c 0x000 0x1 0x0
+#define MX50_PAD_UART2_RTS__ESDHC4_CLK                         0x0a0 0x34c 0x748 0x4 0x1
+#define MX50_PAD_UART2_RTS__ESDHC4_DAT7                                0x0a0 0x34c 0x76c 0x5 0x1
+#define MX50_PAD_UART2_RTS__USBPHY2_DATAOUT_13                 0x0a0 0x34c 0x000 0x7 0x0
+#define MX50_PAD_UART3_TXD__UART3_TXD_MUX                      0x0a4 0x350 0x7d4 0x0 0x0
+#define MX50_PAD_UART3_TXD__GPIO6_14                           0x0a4 0x350 0x000 0x1 0x0
+#define MX50_PAD_UART3_TXD__ESDHC1_DAT4                                0x0a4 0x350 0x000 0x3 0x0
+#define MX50_PAD_UART3_TXD__ESDHC4_DAT0                                0x0a4 0x350 0x000 0x4 0x0
+#define MX50_PAD_UART3_TXD__ESDHC2_WP                          0x0a4 0x350 0x744 0x5 0x0
+#define MX50_PAD_UART3_TXD__EIM_WEIM_D_12                      0x0a4 0x350 0x81c 0x6 0x0
+#define MX50_PAD_UART3_TXD__USBPHY2_DATAOUT_14                 0x0a4 0x350 0x000 0x7 0x0
+#define MX50_PAD_UART3_RXD__UART3_RXD_MUX                      0x0a8 0x354 0x7d4 0x0 0x1
+#define MX50_PAD_UART3_RXD__GPIO6_15                           0x0a8 0x354 0x000 0x1 0x0
+#define MX50_PAD_UART3_RXD__ESDHC1_DAT5                                0x0a8 0x354 0x000 0x3 0x0
+#define MX50_PAD_UART3_RXD__ESDHC4_DAT1                                0x0a8 0x354 0x754 0x4 0x0
+#define MX50_PAD_UART3_RXD__ESDHC2_CD                          0x0a8 0x354 0x740 0x5 0x0
+#define MX50_PAD_UART3_RXD__EIM_WEIM_D_13                      0x0a8 0x354 0x820 0x6 0x0
+#define MX50_PAD_UART3_RXD__USBPHY2_DATAOUT_15                 0x0a8 0x354 0x000 0x7 0x0
+#define MX50_PAD_UART4_TXD__UART4_TXD_MUX                      0x0ac 0x358 0x7dc 0x0 0x0
+#define MX50_PAD_UART4_TXD__GPIO6_16                           0x0ac 0x358 0x000 0x1 0x0
+#define MX50_PAD_UART4_TXD__UART3_CTS                          0x0ac 0x358 0x7d0 0x2 0x0
+#define MX50_PAD_UART4_TXD__ESDHC1_DAT6                                0x0ac 0x358 0x000 0x3 0x0
+#define MX50_PAD_UART4_TXD__ESDHC4_DAT2                                0x0ac 0x358 0x758 0x4 0x0
+#define MX50_PAD_UART4_TXD__ESDHC2_LCTL                                0x0ac 0x358 0x000 0x5 0x0
+#define MX50_PAD_UART4_TXD__EIM_WEIM_D_14                      0x0ac 0x358 0x824 0x6 0x0
+#define MX50_PAD_UART4_RXD__UART4_RXD_MUX                      0x0b0 0x35c 0x7dc 0x0 0x1
+#define MX50_PAD_UART4_RXD__GPIO6_17                           0x0b0 0x35c 0x000 0x1 0x0
+#define MX50_PAD_UART4_RXD__UART3_RTS                          0x0b0 0x35c 0x7d0 0x2 0x1
+#define MX50_PAD_UART4_RXD__ESDHC1_DAT7                                0x0b0 0x35c 0x000 0x3 0x0
+#define MX50_PAD_UART4_RXD__ESDHC4_DAT3                                0x0b0 0x35c 0x75c 0x4 0x0
+#define MX50_PAD_UART4_RXD__ESDHC1_LCTL                                0x0b0 0x35c 0x000 0x5 0x0
+#define MX50_PAD_UART4_RXD__EIM_WEIM_D_15                      0x0b0 0x35c 0x828 0x6 0x0
+#define MX50_PAD_CSPI_SCLK__CSPI_SCLK                          0x0b4 0x360 0x000 0x0 0x0
+#define MX50_PAD_CSPI_SCLK__GPIO4_8                            0x0b4 0x360 0x000 0x1 0x0
+#define MX50_PAD_CSPI_MOSI__CSPI_MOSI                          0x0b8 0x364 0x000 0x0 0x0
+#define MX50_PAD_CSPI_MOSI__GPIO4_9                            0x0b8 0x364 0x000 0x1 0x0
+#define MX50_PAD_CSPI_MISO__CSPI_MISO                          0x0bc 0x368 0x000 0x0 0x0
+#define MX50_PAD_CSPI_MISO__GPIO4_10                           0x0bc 0x368 0x000 0x1 0x0
+#define MX50_PAD_CSPI_SS0__CSPI_SS0                            0x0c0 0x36c 0x000 0x0 0x0
+#define MX50_PAD_CSPI_SS0__GPIO4_11                            0x0c0 0x36c 0x000 0x1 0x0
+#define MX50_PAD_ECSPI1_SCLK__ECSPI1_SCLK                      0x0c4 0x370 0x000 0x0 0x0
+#define MX50_PAD_ECSPI1_SCLK__GPIO4_12                         0x0c4 0x370 0x000 0x1 0x0
+#define MX50_PAD_ECSPI1_SCLK__CSPI_RDY                         0x0c4 0x370 0x6e8 0x2 0x1
+#define MX50_PAD_ECSPI1_SCLK__ECSPI2_RDY                       0x0c4 0x370 0x000 0x3 0x0
+#define MX50_PAD_ECSPI1_SCLK__UART3_RTS                                0x0c4 0x370 0x7d0 0x4 0x2
+#define MX50_PAD_ECSPI1_SCLK__EPDC_SDCE_6                      0x0c4 0x370 0x000 0x5 0x0
+#define MX50_PAD_ECSPI1_SCLK__EIM_WEIM_D_8                     0x0c4 0x370 0x80c 0x7 0x0
+#define MX50_PAD_ECSPI1_MOSI__ECSPI1_MOSI                      0x0c8 0x374 0x000 0x0 0x0
+#define MX50_PAD_ECSPI1_MOSI__GPIO4_13                         0x0c8 0x374 0x000 0x1 0x0
+#define MX50_PAD_ECSPI1_MOSI__CSPI_SS1                         0x0c8 0x374 0x6ec 0x2 0x1
+#define MX50_PAD_ECSPI1_MOSI__ECSPI2_SS1                       0x0c8 0x374 0x000 0x3 0x0
+#define MX50_PAD_ECSPI1_MOSI__UART3_CTS                                0x0c8 0x374 0x000 0x4 0x0
+#define MX50_PAD_ECSPI1_MOSI__EPDC_SDCE_7                      0x0c8 0x374 0x000 0x5 0x0
+#define MX50_PAD_ECSPI1_MOSI__EIM_WEIM_D_9                     0x0c8 0x374 0x810 0x7 0x0
+#define MX50_PAD_ECSPI1_MISO__ECSPI1_MISO                      0x0cc 0x378 0x000 0x0 0x0
+#define MX50_PAD_ECSPI1_MISO__GPIO4_14                         0x0cc 0x378 0x000 0x1 0x0
+#define MX50_PAD_ECSPI1_MISO__CSPI_SS2                         0x0cc 0x378 0x6f0 0x2 0x1
+#define MX50_PAD_ECSPI1_MISO__ECSPI2_SS2                       0x0cc 0x378 0x000 0x3 0x0
+#define MX50_PAD_ECSPI1_MISO__UART4_RTS                                0x0cc 0x378 0x7d8 0x4 0x0
+#define MX50_PAD_ECSPI1_MISO__EPDC_SDCE_8                      0x0cc 0x378 0x000 0x5 0x0
+#define MX50_PAD_ECSPI1_MISO__EIM_WEIM_D_10                    0x0cc 0x378 0x814 0x7 0x0
+#define MX50_PAD_ECSPI1_SS0__ECSPI1_SS0                                0x0d0 0x37c 0x000 0x0 0x0
+#define MX50_PAD_ECSPI1_SS0__GPIO4_15                          0x0d0 0x37c 0x000 0x1 0x0
+#define MX50_PAD_ECSPI1_SS0__CSPI_SS3                          0x0d0 0x37c 0x6f4 0x2 0x1
+#define MX50_PAD_ECSPI1_SS0__ECSPI2_SS3                                0x0d0 0x37c 0x000 0x3 0x0
+#define MX50_PAD_ECSPI1_SS0__UART4_CTS                         0x0d0 0x37c 0x000 0x4 0x0
+#define MX50_PAD_ECSPI1_SS0__EPDC_SDCE_9                       0x0d0 0x37c 0x000 0x5 0x0
+#define MX50_PAD_ECSPI1_SS0__EIM_WEIM_D_11                     0x0d0 0x37c 0x818 0x7 0x0
+#define MX50_PAD_ECSPI2_SCLK__ECSPI2_SCLK                      0x0d4 0x380 0x000 0x0 0x0
+#define MX50_PAD_ECSPI2_SCLK__GPIO4_16                         0x0d4 0x380 0x000 0x1 0x0
+#define MX50_PAD_ECSPI2_SCLK__ELCDIF_WR_RWN                    0x0d4 0x380 0x000 0x2 0x0
+#define MX50_PAD_ECSPI2_SCLK__ECSPI1_RDY                       0x0d4 0x380 0x000 0x3 0x0
+#define MX50_PAD_ECSPI2_SCLK__UART5_RTS                                0x0d4 0x380 0x7e0 0x4 0x0
+#define MX50_PAD_ECSPI2_SCLK__ELCDIF_DOTCLK                    0x0d4 0x380 0x000 0x5 0x0
+#define MX50_PAD_ECSPI2_SCLK__EIM_NANDF_CEN_4                  0x0d4 0x380 0x000 0x6 0x0
+#define MX50_PAD_ECSPI2_SCLK__EIM_WEIM_D_8                     0x0d4 0x380 0x80c 0x7 0x1
+#define MX50_PAD_ECSPI2_MOSI__ECSPI2_MOSI                      0x0d8 0x384 0x000 0x0 0x0
+#define MX50_PAD_ECSPI2_MOSI__GPIO4_17                         0x0d8 0x384 0x000 0x1 0x0
+#define MX50_PAD_ECSPI2_MOSI__ELCDIF_RE_E                      0x0d8 0x384 0x000 0x2 0x0
+#define MX50_PAD_ECSPI2_MOSI__ECSPI1_SS1                       0x0d8 0x384 0x000 0x3 0x0
+#define MX50_PAD_ECSPI2_MOSI__UART5_CTS                                0x0d8 0x384 0x7e0 0x4 0x1
+#define MX50_PAD_ECSPI2_MOSI__ELCDIF_ENABLE                    0x0d8 0x384 0x000 0x5 0x0
+#define MX50_PAD_ECSPI2_MOSI__EIM_NANDF_CEN_5                  0x0d8 0x384 0x000 0x6 0x0
+#define MX50_PAD_ECSPI2_MOSI__EIM_WEIM_D_9                     0x0d8 0x384 0x810 0x7 0x1
+#define MX50_PAD_ECSPI2_MISO__ECSPI2_MISO                      0x0dc 0x388 0x000 0x0 0x0
+#define MX50_PAD_ECSPI2_MISO__GPIO4_18                         0x0dc 0x388 0x000 0x1 0x0
+#define MX50_PAD_ECSPI2_MISO__ELCDIF_RS                                0x0dc 0x388 0x000 0x2 0x0
+#define MX50_PAD_ECSPI2_MISO__ECSPI1_SS2                       0x0dc 0x388 0x000 0x3 0x0
+#define MX50_PAD_ECSPI2_MISO__UART5_TXD_MUX                    0x0dc 0x388 0x7e4 0x4 0x4
+#define MX50_PAD_ECSPI2_MISO__ELCDIF_VSYNC                     0x0dc 0x388 0x73c 0x5 0x0
+#define MX50_PAD_ECSPI2_MISO__EIM_NANDF_CEN_6                  0x0dc 0x388 0x000 0x6 0x0
+#define MX50_PAD_ECSPI2_MISO__EIM_WEIM_D_10                    0x0dc 0x388 0x814 0x7 0x1
+#define MX50_PAD_ECSPI2_SS0__ECSPI2_SS0                                0x0e0 0x38c 0x000 0x0 0x0
+#define MX50_PAD_ECSPI2_SS0__GPIO4_19                          0x0e0 0x38c 0x000 0x1 0x0
+#define MX50_PAD_ECSPI2_SS0__ELCDIF_CS                         0x0e0 0x38c 0x000 0x2 0x0
+#define MX50_PAD_ECSPI2_SS0__ECSPI2_SS3                                0x0e0 0x38c 0x000 0x3 0x0
+#define MX50_PAD_ECSPI2_SS0__UART5_RXD_MUX                     0x0e0 0x38c 0x7e4 0x4 0x5
+#define MX50_PAD_ECSPI2_SS0__ELCDIF_HSYNC                      0x0e0 0x38c 0x6f8 0x5 0x0
+#define MX50_PAD_ECSPI2_SS0__EIM_NANDF_CEN_7                   0x0e0 0x38c 0x000 0x6 0x0
+#define MX50_PAD_ECSPI2_SS0__EIM_WEIM_D_11                     0x0e0 0x38c 0x818 0x7 0x1
+#define MX50_PAD_SD1_CLK__ESDHC1_CLK                           0x0e4 0x390 0x000 0x0 0x0
+#define MX50_PAD_SD1_CLK__GPIO5_0                              0x0e4 0x390 0x000 0x1 0x0
+#define MX50_PAD_SD1_CLK__CCM_CLKO                             0x0e4 0x390 0x000 0x7 0x0
+#define MX50_PAD_SD1_CMD__ESDHC1_CMD                           0x0e8 0x394 0x000 0x0 0x0
+#define MX50_PAD_SD1_CMD__GPIO5_1                              0x0e8 0x394 0x000 0x1 0x0
+#define MX50_PAD_SD1_CMD__CCM_CLKO2                            0x0e8 0x394 0x000 0x7 0x0
+#define MX50_PAD_SD1_D0__ESDHC1_DAT0                           0x0ec 0x398 0x000 0x0 0x0
+#define MX50_PAD_SD1_D0__GPIO5_2                               0x0ec 0x398 0x000 0x1 0x0
+#define MX50_PAD_SD1_D0__CCM_PLL1_BYP                          0x0ec 0x398 0x6dc 0x7 0x0
+#define MX50_PAD_SD1_D1__ESDHC1_DAT1                           0x0f0 0x39c 0x000 0x0 0x0
+#define MX50_PAD_SD1_D1__GPIO5_3                               0x0f0 0x39c 0x000 0x1 0x0
+#define MX50_PAD_SD1_D1__CCM_PLL2_BYP                          0x0f0 0x39c 0x000 0x7 0x0
+#define MX50_PAD_SD1_D2__ESDHC1_DAT2                           0x0f4 0x3a0 0x000 0x0 0x0
+#define MX50_PAD_SD1_D2__GPIO5_4                               0x0f4 0x3a0 0x000 0x1 0x0
+#define MX50_PAD_SD1_D2__CCM_PLL3_BYP                          0x0f4 0x3a0 0x6e4 0x7 0x0
+#define MX50_PAD_SD1_D3__ESDHC1_DAT3                           0x0f8 0x3a4 0x000 0x0 0x0
+#define MX50_PAD_SD1_D3__GPIO5_5                               0x0f8 0x3a4 0x000 0x1 0x0
+#define MX50_PAD_SD2_CLK__ESDHC2_CLK                           0x0fc 0x3a8 0x000 0x0 0x0
+#define MX50_PAD_SD2_CLK__GPIO5_6                              0x0fc 0x3a8 0x000 0x1 0x0
+#define MX50_PAD_SD2_CLK__MSHC_SCLK                            0x0fc 0x3a8 0x000 0x2 0x0
+#define MX50_PAD_SD2_CMD__ESDHC2_CMD                           0x100 0x3ac 0x000 0x0 0x0
+#define MX50_PAD_SD2_CMD__GPIO5_7                              0x100 0x3ac 0x000 0x1 0x0
+#define MX50_PAD_SD2_CMD__MSHC_BS                              0x100 0x3ac 0x000 0x2 0x0
+#define MX50_PAD_SD2_D0__ESDHC2_DAT0                           0x104 0x3b0 0x000 0x0 0x0
+#define MX50_PAD_SD2_D0__GPIO5_8                               0x104 0x3b0 0x000 0x1 0x0
+#define MX50_PAD_SD2_D0__MSHC_DATA_0                           0x104 0x3b0 0x000 0x2 0x0
+#define MX50_PAD_SD2_D0__KPP_COL_4                             0x104 0x3b0 0x790 0x3 0x0
+#define MX50_PAD_SD2_D1__ESDHC2_DAT1                           0x108 0x3b4 0x000 0x0 0x0
+#define MX50_PAD_SD2_D1__GPIO5_9                               0x108 0x3b4 0x000 0x1 0x0
+#define MX50_PAD_SD2_D1__MSHC_DATA_1                           0x108 0x3b4 0x000 0x2 0x0
+#define MX50_PAD_SD2_D1__KPP_ROW_4                             0x108 0x3b4 0x7a0 0x3 0x0
+#define MX50_PAD_SD2_D2__ESDHC2_DAT2                           0x10c 0x3b8 0x000 0x0 0x0
+#define MX50_PAD_SD2_D2__GPIO5_10                              0x10c 0x3b8 0x000 0x1 0x0
+#define MX50_PAD_SD2_D2__MSHC_DATA_2                           0x10c 0x3b8 0x000 0x2 0x0
+#define MX50_PAD_SD2_D2__KPP_COL_5                             0x10c 0x3b8 0x794 0x3 0x0
+#define MX50_PAD_SD2_D3__ESDHC2_DAT3                           0x110 0x3bc 0x000 0x0 0x0
+#define MX50_PAD_SD2_D3__GPIO5_11                              0x110 0x3bc 0x000 0x1 0x0
+#define MX50_PAD_SD2_D3__MSHC_DATA_3                           0x110 0x3bc 0x000 0x2 0x0
+#define MX50_PAD_SD2_D3__KPP_ROW_5                             0x110 0x3bc 0x7a4 0x3 0x0
+#define MX50_PAD_SD2_D4__ESDHC2_DAT4                           0x114 0x3c0 0x000 0x0 0x0
+#define MX50_PAD_SD2_D4__GPIO5_12                              0x114 0x3c0 0x000 0x1 0x0
+#define MX50_PAD_SD2_D4__AUDMUX_AUD4_RXFS                      0x114 0x3c0 0x6d0 0x2 0x0
+#define MX50_PAD_SD2_D4__KPP_COL_6                             0x114 0x3c0 0x798 0x3 0x0
+#define MX50_PAD_SD2_D4__EIM_WEIM_D_0                          0x114 0x3c0 0x7ec 0x4 0x0
+#define MX50_PAD_SD2_D4__CCM_CCM_OUT_0                         0x114 0x3c0 0x000 0x7 0x0
+#define MX50_PAD_SD2_D5__ESDHC2_DAT5                           0x118 0x3c4 0x000 0x0 0x0
+#define MX50_PAD_SD2_D5__GPIO5_13                              0x118 0x3c4 0x000 0x1 0x0
+#define MX50_PAD_SD2_D5__AUDMUX_AUD4_RXC                       0x118 0x3c4 0x6cc 0x2 0x0
+#define MX50_PAD_SD2_D5__KPP_ROW_6                             0x118 0x3c4 0x7a8 0x3 0x0
+#define MX50_PAD_SD2_D5__EIM_WEIM_D_1                          0x118 0x3c4 0x7f0 0x4 0x0
+#define MX50_PAD_SD2_D5__CCM_CCM_OUT_1                         0x118 0x3c4 0x000 0x7 0x0
+#define MX50_PAD_SD2_D6__ESDHC2_DAT6                           0x11c 0x3c8 0x000 0x0 0x0
+#define MX50_PAD_SD2_D6__GPIO5_14                              0x11c 0x3c8 0x000 0x1 0x0
+#define MX50_PAD_SD2_D6__AUDMUX_AUD4_RXD                       0x11c 0x3c8 0x6c4 0x2 0x0
+#define MX50_PAD_SD2_D6__KPP_COL_7                             0x11c 0x3c8 0x79c 0x3 0x0
+#define MX50_PAD_SD2_D6__EIM_WEIM_D_2                          0x11c 0x3c8 0x7f4 0x4 0x0
+#define MX50_PAD_SD2_D6__CCM_CCM_OUT_2                         0x11c 0x3c8 0x000 0x7 0x0
+#define MX50_PAD_SD2_D7__ESDHC2_DAT7                           0x120 0x3cc 0x000 0x0 0x0
+#define MX50_PAD_SD2_D7__GPIO5_15                              0x120 0x3cc 0x000 0x1 0x0
+#define MX50_PAD_SD2_D7__AUDMUX_AUD4_TXFS                      0x120 0x3cc 0x6d8 0x2 0x0
+#define MX50_PAD_SD2_D7__KPP_ROW_7                             0x120 0x3cc 0x7ac 0x3 0x0
+#define MX50_PAD_SD2_D7__EIM_WEIM_D_3                          0x120 0x3cc 0x7f8 0x4 0x0
+#define MX50_PAD_SD2_D7__CCM_STOP                              0x120 0x3cc 0x000 0x7 0x0
+#define MX50_PAD_SD2_WP__ESDHC2_WP                             0x124 0x3d0 0x744 0x0 0x1
+#define MX50_PAD_SD2_WP__GPIO5_16                              0x124 0x3d0 0x000 0x1 0x0
+#define MX50_PAD_SD2_WP__AUDMUX_AUD4_TXD                       0x124 0x3d0 0x6c8 0x2 0x0
+#define MX50_PAD_SD2_WP__EIM_WEIM_D_4                          0x124 0x3d0 0x7fc 0x4 0x0
+#define MX50_PAD_SD2_WP__CCM_WAIT                              0x124 0x3d0 0x000 0x7 0x0
+#define MX50_PAD_SD2_CD__ESDHC2_CD                             0x128 0x3d4 0x740 0x0 0x1
+#define MX50_PAD_SD2_CD__GPIO5_17                              0x128 0x3d4 0x000 0x1 0x0
+#define MX50_PAD_SD2_CD__AUDMUX_AUD4_TXC                       0x128 0x3d4 0x6d4 0x2 0x0
+#define MX50_PAD_SD2_CD__EIM_WEIM_D_5                          0x128 0x3d4 0x800 0x4 0x0
+#define MX50_PAD_SD2_CD__CCM_REF_EN_B                          0x128 0x3d4 0x000 0x7 0x0
+#define MX50_PAD_DISP_D0__ELCDIF_DAT_0                         0x12c 0x40c 0x6fc 0x0 0x0
+#define MX50_PAD_DISP_D0__GPIO2_0                              0x12c 0x40c 0x000 0x1 0x0
+#define MX50_PAD_DISP_D0__FEC_TX_CLK                           0x12c 0x40c 0x78c 0x2 0x0
+#define MX50_PAD_DISP_D0__EIM_WEIM_A_16                                0x12c 0x40c 0x000 0x3 0x0
+#define MX50_PAD_DISP_D0__SDMA_DEBUG_PC_0                      0x12c 0x40c 0x000 0x6 0x0
+#define MX50_PAD_DISP_D0__USBPHY1_VSTATUS_0                    0x12c 0x40c 0x000 0x7 0x0
+#define MX50_PAD_DISP_D1__ELCDIF_DAT_1                         0x130 0x410 0x700 0x0 0x0
+#define MX50_PAD_DISP_D1__GPIO2_1                              0x130 0x410 0x000 0x1 0x0
+#define MX50_PAD_DISP_D1__FEC_RX_ERR                           0x130 0x410 0x788 0x2 0x0
+#define MX50_PAD_DISP_D1__EIM_WEIM_A_17                                0x130 0x410 0x000 0x3 0x0
+#define MX50_PAD_DISP_D1__SDMA_DEBUG_PC_1                      0x130 0x410 0x000 0x6 0x0
+#define MX50_PAD_DISP_D1__USBPHY1_VSTATUS_1                    0x130 0x410 0x000 0x7 0x0
+#define MX50_PAD_DISP_D2__ELCDIF_DAT_2                         0x134 0x414 0x704 0x0 0x0
+#define MX50_PAD_DISP_D2__GPIO2_2                              0x134 0x414 0x000 0x1 0x0
+#define MX50_PAD_DISP_D2__FEC_RX_DV                            0x134 0x414 0x784 0x2 0x0
+#define MX50_PAD_DISP_D2__EIM_WEIM_A_18                                0x134 0x414 0x000 0x3 0x0
+#define MX50_PAD_DISP_D2__SDMA_DEBUG_PC_2                      0x134 0x414 0x000 0x6 0x0
+#define MX50_PAD_DISP_D2__USBPHY1_VSTATUS_2                    0x134 0x414 0x000 0x7 0x0
+#define MX50_PAD_DISP_D3__ELCDIF_DAT_3                         0x138 0x418 0x708 0x0 0x0
+#define MX50_PAD_DISP_D3__GPIO2_3                              0x138 0x418 0x000 0x1 0x0
+#define MX50_PAD_DISP_D3__FEC_RDATA_1                          0x138 0x418 0x77c 0x2 0x0
+#define MX50_PAD_DISP_D3__EIM_WEIM_A_19                                0x138 0x418 0x000 0x3 0x0
+#define MX50_PAD_DISP_D3__FEC_COL                              0x138 0x418 0x770 0x4 0x1
+#define MX50_PAD_DISP_D3__SDMA_DEBUG_PC_3                      0x138 0x418 0x000 0x6 0x0
+#define MX50_PAD_DISP_D3__USBPHY1_VSTATUS_3                    0x138 0x418 0x000 0x7 0x0
+#define MX50_PAD_DISP_D4__ELCDIF_DAT_4                         0x13c 0x41c 0x70c 0x0 0x0
+#define MX50_PAD_DISP_D4__GPIO2_4                              0x13c 0x41c 0x000 0x1 0x0
+#define MX50_PAD_DISP_D4__FEC_RDATA_0                          0x13c 0x41c 0x778 0x2 0x0
+#define MX50_PAD_DISP_D4__EIM_WEIM_A_20                                0x13c 0x41c 0x000 0x3 0x0
+#define MX50_PAD_DISP_D4__SDMA_DEBUG_PC_4                      0x13c 0x41c 0x000 0x6 0x0
+#define MX50_PAD_DISP_D4__USBPHY1_VSTATUS_4                    0x13c 0x41c 0x000 0x7 0x0
+#define MX50_PAD_DISP_D5__ELCDIF_DAT_5                         0x140 0x420 0x710 0x0 0x0
+#define MX50_PAD_DISP_D5__GPIO2_5                              0x140 0x420 0x000 0x1 0x0
+#define MX50_PAD_DISP_D5__FEC_TX_EN                            0x140 0x420 0x000 0x2 0x0
+#define MX50_PAD_DISP_D5__EIM_WEIM_A_21                                0x140 0x420 0x000 0x3 0x0
+#define MX50_PAD_DISP_D5__SDMA_DEBUG_PC_5                      0x140 0x420 0x000 0x6 0x0
+#define MX50_PAD_DISP_D5__USBPHY1_VSTATUS_5                    0x140 0x420 0x000 0x7 0x0
+#define MX50_PAD_DISP_D6__ELCDIF_DAT_6                         0x144 0x424 0x714 0x0 0x0
+#define MX50_PAD_DISP_D6__GPIO2_6                              0x144 0x424 0x000 0x1 0x0
+#define MX50_PAD_DISP_D6__FEC_TDATA_1                          0x144 0x424 0x000 0x2 0x0
+#define MX50_PAD_DISP_D6__EIM_WEIM_A_22                                0x144 0x424 0x000 0x3 0x0
+#define MX50_PAD_DISP_D6__FEC_RX_CLK                           0x144 0x424 0x780 0x4 0x1
+#define MX50_PAD_DISP_D6__SDMA_DEBUG_PC_6                      0x144 0x424 0x000 0x6 0x0
+#define MX50_PAD_DISP_D6__USBPHY1_VSTATUS_6                    0x144 0x424 0x000 0x7 0x0
+#define MX50_PAD_DISP_D7__ELCDIF_DAT_7                         0x148 0x428 0x718 0x0 0x0
+#define MX50_PAD_DISP_D7__GPIO2_7                              0x148 0x428 0x000 0x1 0x0
+#define MX50_PAD_DISP_D7__FEC_TDATA_0                          0x148 0x428 0x000 0x2 0x0
+#define MX50_PAD_DISP_D7__EIM_WEIM_A_23                                0x148 0x428 0x000 0x3 0x0
+#define MX50_PAD_DISP_D7__SDMA_DEBUG_PC_7                      0x148 0x428 0x000 0x6 0x0
+#define MX50_PAD_DISP_D7__USBPHY1_VSTATUS_7                    0x148 0x428 0x000 0x7 0x0
+#define MX50_PAD_DISP_WR__ELCDIF_WR_RWN                                0x14c 0x42c 0x000 0x0 0x0
+#define MX50_PAD_DISP_WR__GPIO2_16                             0x14c 0x42c 0x000 0x1 0x0
+#define MX50_PAD_DISP_WR__ELCDIF_DOTCLK                                0x14c 0x42c 0x000 0x2 0x0
+#define MX50_PAD_DISP_WR__EIM_WEIM_A_24                                0x14c 0x42c 0x000 0x3 0x0
+#define MX50_PAD_DISP_WR__SDMA_DEBUG_PC_8                      0x14c 0x42c 0x000 0x6 0x0
+#define MX50_PAD_DISP_WR__USBPHY1_AVALID                       0x14c 0x42c 0x000 0x7 0x0
+#define MX50_PAD_DISP_RD__ELCDIF_RD_E                          0x150 0x430 0x000 0x0 0x0
+#define MX50_PAD_DISP_RD__GPIO2_19                             0x150 0x430 0x000 0x1 0x0
+#define MX50_PAD_DISP_RD__ELCDIF_ENABLE                                0x150 0x430 0x000 0x2 0x0
+#define MX50_PAD_DISP_RD__EIM_WEIM_A_25                                0x150 0x430 0x000 0x3 0x0
+#define MX50_PAD_DISP_RD__SDMA_DEBUG_PC_9                      0x150 0x430 0x000 0x6 0x0
+#define MX50_PAD_DISP_RD__USBPHY1_BVALID                       0x150 0x430 0x000 0x7 0x0
+#define MX50_PAD_DISP_RS__ELCDIF_RS                            0x154 0x434 0x000 0x0 0x0
+#define MX50_PAD_DISP_RS__GPIO2_17                             0x154 0x434 0x000 0x1 0x0
+#define MX50_PAD_DISP_RS__ELCDIF_VSYNC                         0x154 0x434 0x73c 0x2 0x1
+#define MX50_PAD_DISP_RS__EIM_WEIM_A_26                                0x154 0x434 0x000 0x3 0x0
+#define MX50_PAD_DISP_RS__SDMA_DEBUG_PC_10                     0x154 0x434 0x000 0x6 0x0
+#define MX50_PAD_DISP_RS__USBPHY1_ENDSESSION                   0x154 0x434 0x000 0x7 0x0
+#define MX50_PAD_DISP_CS__ELCDIF_CS                            0x158 0x438 0x000 0x0 0x0
+#define MX50_PAD_DISP_CS__GPIO2_21                             0x158 0x438 0x000 0x1 0x0
+#define MX50_PAD_DISP_CS__ELCDIF_HSYNC                         0x158 0x438 0x6f8 0x2 0x1
+#define MX50_PAD_DISP_CS__EIM_WEIM_A_27                                0x158 0x438 0x000 0x3 0x0
+#define MX50_PAD_DISP_CS__EIM_WEIM_CS_3                                0x158 0x438 0x000 0x4 0x0
+#define MX50_PAD_DISP_CS__SDMA_DEBUG_PC_11                     0x158 0x438 0x000 0x6 0x0
+#define MX50_PAD_DISP_CS__USBPHY1_IDDIG                                0x158 0x438 0x000 0x7 0x0
+#define MX50_PAD_DISP_BUSY__ELCDIF_BUSY                                0x15c 0x43c 0x6f8 0x0 0x2
+#define MX50_PAD_DISP_BUSY__GPIO2_18                           0x15c 0x43c 0x000 0x1 0x0
+#define MX50_PAD_DISP_BUSY__EIM_WEIM_CS_3                      0x15c 0x43c 0x000 0x4 0x0
+#define MX50_PAD_DISP_BUSY__SDMA_DEBUG_PC_12                   0x15c 0x43c 0x000 0x6 0x0
+#define MX50_PAD_DISP_BUSY__USBPHY2_HOSTDISCONNECT             0x15c 0x43c 0x000 0x7 0x0
+#define MX50_PAD_DISP_RESET__ELCDIF_RESET                      0x160 0x440 0x000 0x0 0x0
+#define MX50_PAD_DISP_RESET__GPIO2_20                          0x160 0x440 0x000 0x1 0x0
+#define MX50_PAD_DISP_RESET__EIM_WEIM_CS_3                     0x160 0x440 0x000 0x4 0x0
+#define MX50_PAD_DISP_RESET__SDMA_DEBUG_PC_13                  0x160 0x440 0x000 0x6 0x0
+#define MX50_PAD_DISP_RESET__USBPHY2_BISTOK                    0x160 0x440 0x000 0x7 0x0
+#define MX50_PAD_SD3_CMD__ESDHC3_CMD                           0x164 0x444 0x000 0x0 0x0
+#define MX50_PAD_SD3_CMD__GPIO5_18                             0x164 0x444 0x000 0x1 0x0
+#define MX50_PAD_SD3_CMD__EIM_NANDF_WRN                                0x164 0x444 0x000 0x2 0x0
+#define MX50_PAD_SD3_CMD__SSP_CMD                              0x164 0x444 0x000 0x3 0x0
+#define MX50_PAD_SD3_CLK__ESDHC3_CLK                           0x168 0x448 0x000 0x0 0x0
+#define MX50_PAD_SD3_CLK__GPIO5_19                             0x168 0x448 0x000 0x1 0x0
+#define MX50_PAD_SD3_CLK__EIM_NANDF_RDN                                0x168 0x448 0x000 0x2 0x0
+#define MX50_PAD_SD3_CLK__SSP_CLK                              0x168 0x448 0x000 0x3 0x0
+#define MX50_PAD_SD3_D0__ESDHC3_DAT0                           0x16c 0x44c 0x000 0x0 0x0
+#define MX50_PAD_SD3_D0__GPIO5_20                              0x16c 0x44c 0x000 0x1 0x0
+#define MX50_PAD_SD3_D0__EIM_NANDF_D_4                         0x16c 0x44c 0x000 0x2 0x0
+#define MX50_PAD_SD3_D0__SSP_D0                                        0x16c 0x44c 0x000 0x3 0x0
+#define MX50_PAD_SD3_D0__CCM_PLL1_BYP                          0x16c 0x44c 0x6dc 0x7 0x1
+#define MX50_PAD_SD3_D1__ESDHC3_DAT1                           0x170 0x450 0x000 0x0 0x0
+#define MX50_PAD_SD3_D1__GPIO5_21                              0x170 0x450 0x000 0x1 0x0
+#define MX50_PAD_SD3_D1__EIM_NANDF_D_5                         0x170 0x450 0x000 0x2 0x0
+#define MX50_PAD_SD3_D1__SSP_D1                                        0x170 0x450 0x000 0x3 0x0
+#define MX50_PAD_SD3_D1__CCM_PLL2_BYP                          0x170 0x450 0x000 0x7 0x0
+#define MX50_PAD_SD3_D2__ESDHC3_DAT2                           0x174 0x454 0x000 0x0 0x0
+#define MX50_PAD_SD3_D2__GPIO5_22                              0x174 0x454 0x000 0x1 0x0
+#define MX50_PAD_SD3_D2__EIM_NANDF_D_6                         0x174 0x454 0x000 0x2 0x0
+#define MX50_PAD_SD3_D2__SSP_D2                                        0x174 0x454 0x000 0x3 0x0
+#define MX50_PAD_SD3_D2__CCM_PLL3_BYP                          0x174 0x454 0x6e4 0x7 0x1
+#define MX50_PAD_SD3_D3__ESDHC3_DAT3                           0x178 0x458 0x000 0x0 0x0
+#define MX50_PAD_SD3_D3__GPIO5_23                              0x178 0x458 0x000 0x1 0x0
+#define MX50_PAD_SD3_D3__EIM_NANDF_D_7                         0x178 0x458 0x000 0x2 0x0
+#define MX50_PAD_SD3_D3__SSP_D3                                        0x178 0x458 0x000 0x3 0x0
+#define MX50_PAD_SD3_D4__ESDHC3_DAT4                           0x17c 0x45c 0x000 0x0 0x0
+#define MX50_PAD_SD3_D4__GPIO5_24                              0x17c 0x45c 0x000 0x1 0x0
+#define MX50_PAD_SD3_D4__EIM_NANDF_D_0                         0x17c 0x45c 0x000 0x2 0x0
+#define MX50_PAD_SD3_D4__SSP_D4                                        0x17c 0x45c 0x000 0x3 0x0
+#define MX50_PAD_SD3_D5__ESDHC3_DAT5                           0x180 0x460 0x000 0x0 0x0
+#define MX50_PAD_SD3_D5__GPIO5_25                              0x180 0x460 0x000 0x1 0x0
+#define MX50_PAD_SD3_D5__EIM_NANDF_D_1                         0x180 0x460 0x000 0x2 0x0
+#define MX50_PAD_SD3_D5__SSP_D5                                        0x180 0x460 0x000 0x3 0x0
+#define MX50_PAD_SD3_D6__ESDHC3_DAT6                           0x184 0x464 0x000 0x0 0x0
+#define MX50_PAD_SD3_D6__GPIO5_26                              0x184 0x464 0x000 0x1 0x0
+#define MX50_PAD_SD3_D6__EIM_NANDF_D_2                         0x184 0x464 0x000 0x2 0x0
+#define MX50_PAD_SD3_D6__SSP_D6                                        0x184 0x464 0x000 0x3 0x0
+#define MX50_PAD_SD3_D7__ESDHC3_DAT7                           0x188 0x468 0x000 0x0 0x0
+#define MX50_PAD_SD3_D7__GPIO5_27                              0x188 0x468 0x000 0x1 0x0
+#define MX50_PAD_SD3_D7__EIM_NANDF_D_3                         0x188 0x468 0x000 0x2 0x0
+#define MX50_PAD_SD3_D7__SSP_D7                                        0x188 0x468 0x000 0x3 0x0
+#define MX50_PAD_SD3_WP__ESDHC3_WP                             0x18c 0x46C 0x000 0x0 0x0
+#define MX50_PAD_SD3_WP__GPIO5_28                              0x18c 0x46C 0x000 0x1 0x0
+#define MX50_PAD_SD3_WP__EIM_NANDF_RESETN                      0x18c 0x46C 0x000 0x2 0x0
+#define MX50_PAD_SD3_WP__SSP_CD                                        0x18c 0x46C 0x000 0x3 0x0
+#define MX50_PAD_SD3_WP__ESDHC4_LCTL                           0x18c 0x46C 0x000 0x4 0x0
+#define MX50_PAD_SD3_WP__EIM_WEIM_CS_3                         0x18c 0x46C 0x000 0x5 0x0
+#define MX50_PAD_DISP_D8__ELCDIF_DAT_8                         0x190 0x470 0x71c 0x0 0x0
+#define MX50_PAD_DISP_D8__GPIO2_8                              0x190 0x470 0x000 0x1 0x0
+#define MX50_PAD_DISP_D8__EIM_NANDF_CLE                                0x190 0x470 0x000 0x2 0x0
+#define MX50_PAD_DISP_D8__ESDHC1_LCTL                          0x190 0x470 0x000 0x3 0x0
+#define MX50_PAD_DISP_D8__ESDHC4_CMD                           0x190 0x470 0x74c 0x4 0x2
+#define MX50_PAD_DISP_D8__KPP_COL_4                            0x190 0x470 0x790 0x5 0x1
+#define MX50_PAD_DISP_D8__FEC_TX_CLK                           0x190 0x470 0x78c 0x6 0x1
+#define MX50_PAD_DISP_D8__USBPHY1_DATAOUT_0                    0x190 0x470 0x000 0x7 0x0
+#define MX50_PAD_DISP_D9__ELCDIF_DAT_9                         0x194 0x474 0x720 0x0 0x0
+#define MX50_PAD_DISP_D9__GPIO2_9                              0x194 0x474 0x000 0x1 0x0
+#define MX50_PAD_DISP_D9__EIM_NANDF_ALE                                0x194 0x474 0x000 0x2 0x0
+#define MX50_PAD_DISP_D9__ESDHC2_LCTL                          0x194 0x474 0x000 0x3 0x0
+#define MX50_PAD_DISP_D9__ESDHC4_CLK                           0x194 0x474 0x748 0x4 0x2
+#define MX50_PAD_DISP_D9__KPP_ROW_4                            0x194 0x474 0x7a0 0x5 0x1
+#define MX50_PAD_DISP_D9__FEC_RX_ER                            0x194 0x474 0x788 0x6 0x1
+#define MX50_PAD_DISP_D9__USBPHY1_DATAOUT_1                    0x194 0x474 0x000 0x7 0x0
+#define MX50_PAD_DISP_D10__ELCDIF_DAT_10                       0x198 0x478 0x724 0x0 0x0
+#define MX50_PAD_DISP_D10__GPIO2_10                            0x198 0x478 0x000 0x1 0x0
+#define MX50_PAD_DISP_D10__EIM_NANDF_CEN_0                     0x198 0x478 0x000 0x2 0x0
+#define MX50_PAD_DISP_D10__ESDHC3_LCTL                         0x198 0x478 0x000 0x3 0x0
+#define MX50_PAD_DISP_D10__ESDHC4_DAT0                         0x198 0x478 0x000 0x4 0x0
+#define MX50_PAD_DISP_D10__KPP_COL_5                           0x198 0x478 0x794 0x5 0x1
+#define MX50_PAD_DISP_D10__FEC_RX_DV                           0x198 0x478 0x784 0x6 0x1
+#define MX50_PAD_DISP_D10__USBPHY1_DATAOUT_2                   0x198 0x478 0x000 0x7 0x0
+#define MX50_PAD_DISP_D11__ELCDIF_DAT_11                       0x19c 0x47c 0x728 0x0 0x0
+#define MX50_PAD_DISP_D11__GPIO2_11                            0x19c 0x47c 0x000 0x1 0x0
+#define MX50_PAD_DISP_D11__EIM_NANDF_CEN_1                     0x19c 0x47c 0x000 0x2 0x0
+#define MX50_PAD_DISP_D11__ESDHC4_DAT1                         0x19c 0x47c 0x754 0x4 0x1
+#define MX50_PAD_DISP_D11__KPP_ROW_5                           0x19c 0x47c 0x7a4 0x5 0x1
+#define MX50_PAD_DISP_D11__FEC_RDATA_1                         0x19c 0x47c 0x77c 0x6 0x1
+#define MX50_PAD_DISP_D11__USBPHY1_DATAOUT_3                   0x19c 0x47c 0x000 0x7 0x0
+#define MX50_PAD_DISP_D12__ELCDIF_DAT_12                       0x1a0 0x480 0x72c 0x0 0x0
+#define MX50_PAD_DISP_D12__GPIO2_12                            0x1a0 0x480 0x000 0x1 0x0
+#define MX50_PAD_DISP_D12__EIM_NANDF_CEN_2                     0x1a0 0x480 0x000 0x2 0x0
+#define MX50_PAD_DISP_D12__ESDHC1_CD                           0x1a0 0x480 0x000 0x3 0x0
+#define MX50_PAD_DISP_D12__ESDHC4_DAT2                         0x1a0 0x480 0x758 0x4 0x1
+#define MX50_PAD_DISP_D12__KPP_COL_6                           0x1a0 0x480 0x798 0x5 0x1
+#define MX50_PAD_DISP_D12__FEC_RDATA_0                         0x1a0 0x480 0x778 0x6 0x1
+#define MX50_PAD_DISP_D12__USBPHY1_DATAOUT_4                   0x1a0 0x480 0x000 0x7 0x0
+#define MX50_PAD_DISP_D13__ELCDIF_DAT_13                       0x1a4 0x484 0x730 0x0 0x0
+#define MX50_PAD_DISP_D13__GPIO2_13                            0x1a4 0x484 0x000 0x1 0x0
+#define MX50_PAD_DISP_D13__EIM_NANDF_CEN_3                     0x1a4 0x484 0x000 0x2 0x0
+#define MX50_PAD_DISP_D13__ESDHC3_CD                           0x1a4 0x484 0x000 0x3 0x0
+#define MX50_PAD_DISP_D13__ESDHC4_DAT3                         0x1a4 0x484 0x75c 0x4 0x1
+#define MX50_PAD_DISP_D13__KPP_ROW_6                           0x1a4 0x484 0x7a8 0x5 0x1
+#define MX50_PAD_DISP_D13__FEC_TX_EN                           0x1a4 0x484 0x000 0x6 0x0
+#define MX50_PAD_DISP_D13__USBPHY1_DATAOUT_5                   0x1a4 0x484 0x000 0x7 0x0
+#define MX50_PAD_DISP_D14__ELCDIF_DAT_14                       0x1a8 0x488 0x734 0x0 0x0
+#define MX50_PAD_DISP_D14__GPIO2_14                            0x1a8 0x488 0x000 0x1 0x0
+#define MX50_PAD_DISP_D14__EIM_NANDF_READY0                    0x1a8 0x488 0x7b4 0x2 0x1
+#define MX50_PAD_DISP_D14__ESDHC1_WP                           0x1a8 0x488 0x000 0x3 0x0
+#define MX50_PAD_DISP_D14__ESDHC4_WP                           0x1a8 0x488 0x000 0x4 0x0
+#define MX50_PAD_DISP_D14__KPP_COL_7                           0x1a8 0x488 0x79c 0x5 0x1
+#define MX50_PAD_DISP_D14__FEC_TDATA_1                         0x1a8 0x488 0x000 0x6 0x0
+#define MX50_PAD_DISP_D14__USBPHY1_DATAOUT_6                   0x1a8 0x488 0x000 0x7 0x0
+#define MX50_PAD_DISP_D15__ELCDIF_DAT_15                       0x1ac 0x48c 0x738 0x0 0x0
+#define MX50_PAD_DISP_D15__GPIO2_15                            0x1ac 0x48c 0x000 0x1 0x0
+#define MX50_PAD_DISP_D15__EIM_NANDF_DQS                       0x1ac 0x48c 0x7b0 0x2 0x1
+#define MX50_PAD_DISP_D15__ESDHC3_RST                          0x1ac 0x48c 0x000 0x3 0x0
+#define MX50_PAD_DISP_D15__ESDHC4_CD                           0x1ac 0x48c 0x000 0x4 0x0
+#define MX50_PAD_DISP_D15__KPP_ROW_7                           0x1ac 0x48c 0x7ac 0x5 0x1
+#define MX50_PAD_DISP_D15__FEC_TDATA_0                         0x1ac 0x48c 0x000 0x6 0x0
+#define MX50_PAD_DISP_D15__USBPHY1_DATAOUT_7                   0x1ac 0x48c 0x000 0x7 0x0
+#define MX50_PAD_EPDC_D0__EPDC_SDDO_0                          0x1b0 0x54c 0x000 0x0 0x0
+#define MX50_PAD_EPDC_D0__GPIO3_0                              0x1b0 0x54c 0x000 0x1 0x0
+#define MX50_PAD_EPDC_D0__EIM_WEIM_D_0                         0x1b0 0x54c 0x7ec 0x2 0x1
+#define MX50_PAD_EPDC_D0__ELCDIF_RS                            0x1b0 0x54c 0x000 0x3 0x0
+#define MX50_PAD_EPDC_D0__ELCDIF_DOTCLK                                0x1b0 0x54c 0x000 0x4 0x0
+#define MX50_PAD_EPDC_D0__SDMA_DEBUG_EVT_CHN_LINES_0           0x1b0 0x54c 0x000 0x6 0x0
+#define MX50_PAD_EPDC_D0__USBPHY2_DATAOUT_0                    0x1b0 0x54c 0x000 0x7 0x0
+#define MX50_PAD_EPDC_D1__EPDC_SDDO_1                          0x1b4 0x550 0x000 0x0 0x0
+#define MX50_PAD_EPDC_D1__GPIO3_1                              0x1b4 0x550 0x000 0x1 0x0
+#define MX50_PAD_EPDC_D1__EIM_WEIM_D_1                         0x1b4 0x550 0x7f0 0x2 0x1
+#define MX50_PAD_EPDC_D1__ELCDIF_CS                            0x1b4 0x550 0x000 0x3 0x0
+#define MX50_PAD_EPDC_D1__ELCDIF_ENABLE                                0x1b4 0x550 0x000 0x4 0x0
+#define MX50_PAD_EPDC_D1__SDMA_DEBUG_EVT_CHN_LINES_1           0x1b4 0x550 0x000 0x6 0x0
+#define MX50_PAD_EPDC_D1__USBPHY2_DATAOUT_1                    0x1b4 0x550 0x000 0x7 0x0
+#define MX50_PAD_EPDC_D2__EPDC_SDDO_2                          0x1b8 0x554 0x000 0x0 0x0
+#define MX50_PAD_EPDC_D2__GPIO3_2                              0x1b8 0x554 0x000 0x1 0x0
+#define MX50_PAD_EPDC_D2__EIM_WEIM_D_2                         0x1b8 0x554 0x7f4 0x2 0x1
+#define MX50_PAD_EPDC_D2__ELCDIF_WR_RWN                                0x1b8 0x554 0x000 0x3 0x0
+#define MX50_PAD_EPDC_D2__ELCDIF_VSYNC                         0x1b8 0x554 0x73c 0x4 0x2
+#define MX50_PAD_EPDC_D2__SDMA_DEBUG_EVT_CHN_LINES_2           0x1b8 0x554 0x000 0x6 0x0
+#define MX50_PAD_EPDC_D2__USBPHY2_DATAOUT_2                    0x1b8 0x554 0x000 0x7 0x0
+#define MX50_PAD_EPDC_D3__EPDC_SDDO_3                          0x1bc 0x558 0x000 0x0 0x0
+#define MX50_PAD_EPDC_D3__GPIO3_3                              0x1bc 0x558 0x000 0x1 0x0
+#define MX50_PAD_EPDC_D3__EIM_WEIM_D_3                         0x1bc 0x558 0x7f8 0x2 0x1
+#define MX50_PAD_EPDC_D3__ELCDIF_RD_E                          0x1bc 0x558 0x000 0x3 0x0
+#define MX50_PAD_EPDC_D3__ELCDIF_HSYNC                         0x1bc 0x558 0x6f8 0x4 0x3
+#define MX50_PAD_EPDC_D3__SDMA_DEBUG_EVT_CHN_LINES_3           0x1bc 0x558 0x000 0x6 0x0
+#define MX50_PAD_EPDC_D3__USBPHY2_DATAOUT_3                    0x1bc 0x558 0x000 0x7 0x0
+#define MX50_PAD_EPDC_D4__EPDC_SDDO_4                          0x1c0 0x55c 0x000 0x0 0x0
+#define MX50_PAD_EPDC_D4__GPIO3_4                              0x1c0 0x55c 0x000 0x1 0x0
+#define MX50_PAD_EPDC_D4__EIM_WEIM_D_4                         0x1c0 0x55c 0x7fc 0x2 0x1
+#define MX50_PAD_EPDC_D4__SDMA_DEBUG_EVT_CHN_LINES_4           0x1c0 0x55c 0x000 0x6 0x0
+#define MX50_PAD_EPDC_D4__USBPHY2_DATAOUT_4                    0x1c0 0x55c 0x000 0x7 0x0
+#define MX50_PAD_EPDC_D5__EPDC_SDDO_5                          0x1c4 0x560 0x000 0x0 0x0
+#define MX50_PAD_EPDC_D5__GPIO3_5                              0x1c4 0x560 0x000 0x1 0x0
+#define MX50_PAD_EPDC_D5__EIM_WEIM_D_5                         0x1c4 0x560 0x800 0x2 0x1
+#define MX50_PAD_EPDC_D5__SDMA_DEBUG_EVT_CHN_LINES_5           0x1c4 0x560 0x000 0x6 0x0
+#define MX50_PAD_EPDC_D5__USBPHY2_DATAOUT_5                    0x1c4 0x560 0x000 0x7 0x0
+#define MX50_PAD_EPDC_D6__EPDC_SDDO_6                          0x1c8 0x564 0x000 0x0 0x0
+#define MX50_PAD_EPDC_D6__GPIO3_6                              0x1c8 0x564 0x000 0x1 0x0
+#define MX50_PAD_EPDC_D6__EIM_WEIM_D_6                         0x1c8 0x564 0x804 0x2 0x1
+#define MX50_PAD_EPDC_D6__SDMA_DEBUG_EVT_CHN_LINES_6           0x1c8 0x564 0x000 0x6 0x0
+#define MX50_PAD_EPDC_D6__USBPHY2_DATAOUT_6                    0x1c8 0x564 0x000 0x7 0x0
+#define MX50_PAD_EPDC_D7__EPDC_SDDO_7                          0x1cc 0x568 0x000 0x0 0x0
+#define MX50_PAD_EPDC_D7__GPIO3_7                              0x1cc 0x568 0x000 0x1 0x0
+#define MX50_PAD_EPDC_D7__EIM_WEIM_D_7                         0x1cc 0x568 0x808 0x2 0x1
+#define MX50_PAD_EPDC_D7__SDMA_DEBUG_EVT_CHN_LINES_7           0x1cc 0x568 0x000 0x6 0x0
+#define MX50_PAD_EPDC_D7__USBPHY2_DATAOUT_7                    0x1cc 0x568 0x000 0x7 0x0
+#define MX50_PAD_EPDC_D8__EPDC_SDDO_8                          0x1d0 0x56c 0x000 0x0 0x0
+#define MX50_PAD_EPDC_D8__GPIO3_8                              0x1d0 0x56c 0x000 0x1 0x0
+#define MX50_PAD_EPDC_D8__EIM_WEIM_D_8                         0x1d0 0x56c 0x80c 0x2 0x2
+#define MX50_PAD_EPDC_D8__ELCDIF_DAT_24                                0x1d0 0x56c 0x000 0x3 0x0
+#define MX50_PAD_EPDC_D8__SDMA_DEBUG_MATCHED_DMBUS             0x1d0 0x56c 0x000 0x6 0x0
+#define MX50_PAD_EPDC_D8__USBPHY2_VSTATUS_0                    0x1d0 0x56c 0x000 0x7 0x0
+#define MX50_PAD_EPDC_D9__EPDC_SDDO_9                          0x1d4 0x570 0x000 0x0 0x0
+#define MX50_PAD_EPDC_D9__GPIO3_9                              0x1d4 0x570 0x000 0x1 0x0
+#define MX50_PAD_EPDC_D9__EIM_WEIM_D_9                         0x1d4 0x570 0x810 0x2 0x2
+#define MX50_PAD_EPDC_D9__ELCDIF_DAT_25                                0x1d4 0x570 0x000 0x3 0x0
+#define MX50_PAD_EPDC_D9__SDMA_DEBUG_EVENT_CHANNEL_SEL         0x1d4 0x570 0x000 0x6 0x0
+#define MX50_PAD_EPDC_D9__USBPHY2_VSTATUS_1                    0x1d4 0x570 0x000 0x7 0x0
+#define MX50_PAD_EPDC_D10__EPDC_SDDO_10                                0x1d8 0x574 0x000 0x0 0x0
+#define MX50_PAD_EPDC_D10__GPIO3_10                            0x1d8 0x574 0x000 0x1 0x0
+#define MX50_PAD_EPDC_D10__EIM_WEIM_D_10                       0x1d8 0x574 0x814 0x2 0x2
+#define MX50_PAD_EPDC_D10__ELCDIF_DAT_26                       0x1d8 0x574 0x000 0x3 0x0
+#define MX50_PAD_EPDC_D10__SDMA_DEBUG_EVENT_CHANNEL_0          0x1d8 0x574 0x000 0x6 0x0
+#define MX50_PAD_EPDC_D10__USBPHY2_VSTATUS_2                   0x1d8 0x574 0x000 0x7 0x0
+#define MX50_PAD_EPDC_D11__EPDC_SDDO_11                                0x1dc 0x578 0x000 0x0 0x0
+#define MX50_PAD_EPDC_D11__GPIO3_11                            0x1dc 0x578 0x000 0x1 0x0
+#define MX50_PAD_EPDC_D11__EIM_WEIM_D_11                       0x1dc 0x578 0x818 0x2 0x2
+#define MX50_PAD_EPDC_D11__ELCDIF_DAT_27                       0x1dc 0x578 0x000 0x3 0x0
+#define MX50_PAD_EPDC_D11__SDMA_DEBUG_EVENT_CHANNEL_1          0x1dc 0x578 0x000 0x6 0x0
+#define MX50_PAD_EPDC_D11__USBPHY2_VSTATUS_3                   0x1dc 0x578 0x000 0x7 0x0
+#define MX50_PAD_EPDC_D12__EPDC_SDDO_12                                0x1e0 0x57c 0x000 0x0 0x0
+#define MX50_PAD_EPDC_D12__GPIO3_12                            0x1e0 0x57c 0x000 0x1 0x0
+#define MX50_PAD_EPDC_D12__EIM_WEIM_D_12                       0x1e0 0x57c 0x81c 0x2 0x1
+#define MX50_PAD_EPDC_D12__ELCDIF_DAT_28                       0x1e0 0x57c 0x000 0x3 0x0
+#define MX50_PAD_EPDC_D12__SDMA_DEBUG_EVENT_CHANNEL_2          0x1e0 0x57c 0x000 0x6 0x0
+#define MX50_PAD_EPDC_D12__USBPHY2_VSTATUS_4                   0x1e0 0x57c 0x000 0x7 0x0
+#define MX50_PAD_EPDC_D13__EPDC_SDDO_13                                0x1e4 0x580 0x000 0x0 0x0
+#define MX50_PAD_EPDC_D13__GPIO3_13                            0x1e4 0x580 0x000 0x1 0x0
+#define MX50_PAD_EPDC_D13__EIM_WEIM_D_13                       0x1e4 0x580 0x820 0x2 0x1
+#define MX50_PAD_EPDC_D13__ELCDIF_DAT_29                       0x1e4 0x580 0x000 0x3 0x0
+#define MX50_PAD_EPDC_D13__SDMA_DEBUG_EVENT_CHANNEL_3          0x1e4 0x580 0x000 0x6 0x0
+#define MX50_PAD_EPDC_D13__USBPHY2_VSTATUS_5                   0x1e4 0x580 0x000 0x7 0x0
+#define MX50_PAD_EPDC_D14__EPDC_SDDO_14                                0x1e8 0x584 0x000 0x0 0x0
+#define MX50_PAD_EPDC_D14__GPIO3_14                            0x1e8 0x584 0x000 0x1 0x0
+#define MX50_PAD_EPDC_D14__EIM_WEIM_D_14                       0x1e8 0x584 0x824 0x2 0x1
+#define MX50_PAD_EPDC_D14__ELCDIF_DAT_30                       0x1e8 0x584 0x000 0x3 0x0
+#define MX50_PAD_EPDC_D14__AUDMUX_AUD6_TXD                     0x1e8 0x584 0x000 0x4 0x0
+#define MX50_PAD_EPDC_D14__SDMA_DEBUG_EVENT_CHANNEL_4          0x1e8 0x584 0x000 0x6 0x0
+#define MX50_PAD_EPDC_D14__USBPHY2_VSTATUS_6                   0x1e8 0x584 0x000 0x7 0x0
+#define MX50_PAD_EPDC_D15__EPDC_SDDO_15                                0x1ec 0x588 0x000 0x0 0x0
+#define MX50_PAD_EPDC_D15__GPIO3_15                            0x1ec 0x588 0x000 0x1 0x0
+#define MX50_PAD_EPDC_D15__EIM_WEIM_D_15                       0x1ec 0x588 0x828 0x2 0x1
+#define MX50_PAD_EPDC_D15__ELCDIF_DAT_31                       0x1ec 0x588 0x000 0x3 0x0
+#define MX50_PAD_EPDC_D15__AUDMUX_AUD6_TXC                     0x1ec 0x588 0x000 0x4 0x0
+#define MX50_PAD_EPDC_D15__SDMA_DEBUG_EVENT_CHANNEL_5          0x1ec 0x588 0x000 0x6 0x0
+#define MX50_PAD_EPDC_D15__USBPHY2_VSTATUS_7                   0x1ec 0x588 0x000 0x7 0x0
+#define MX50_PAD_EPDC_GDCLK__EPDC_GDCLK                                0x1f0 0x58c 0x000 0x0 0x0
+#define MX50_PAD_EPDC_GDCLK__GPIO3_16                          0x1f0 0x58c 0x000 0x1 0x0
+#define MX50_PAD_EPDC_GDCLK__EIM_WEIM_D_16                     0x1f0 0x58c 0x000 0x2 0x0
+#define MX50_PAD_EPDC_GDCLK__ELCDIF_DAT_16                     0x1f0 0x58c 0x000 0x3 0x0
+#define MX50_PAD_EPDC_GDCLK__AUDMUX_AUD6_TXFS                  0x1f0 0x58c 0x000 0x4 0x0
+#define MX50_PAD_EPDC_GDCLK__SDMA_DEBUG_CORE_STATE_0           0x1f0 0x58c 0x000 0x6 0x0
+#define MX50_PAD_EPDC_GDCLK__USBPHY2_BISTOK                    0x1f0 0x58c 0x000 0x7 0x0
+#define MX50_PAD_EPDC_GDSP__EPCD_GDSP                          0x1f4 0x590 0x000 0x0 0x0
+#define MX50_PAD_EPDC_GDSP__GPIO3_17                           0x1f4 0x590 0x000 0x1 0x0
+#define MX50_PAD_EPDC_GDSP__EIM_WEIM_D_17                      0x1f4 0x590 0x000 0x2 0x0
+#define MX50_PAD_EPDC_GDSP__ELCDIF_DAT_17                      0x1f4 0x590 0x000 0x3 0x0
+#define MX50_PAD_EPDC_GDSP__AUDMUX_AUD6_RXD                    0x1f4 0x590 0x000 0x4 0x0
+#define MX50_PAD_EPDC_GDSP__SDMA_DEBUG_CORE_STATE_1            0x1f4 0x590 0x000 0x6 0x0
+#define MX50_PAD_EPDC_GDSP__USBPHY2_BVALID                     0x1f4 0x590 0x000 0x7 0x0
+#define MX50_PAD_EPDC_GDOE__EPCD_GDOE                          0x1f8 0x594 0x000 0x0 0x0
+#define MX50_PAD_EPDC_GDOE__GPIO3_18                           0x1f8 0x594 0x000 0x1 0x0
+#define MX50_PAD_EPDC_GDOE__EIM_WEIM_D_18                      0x1f8 0x594 0x000 0x2 0x0
+#define MX50_PAD_EPDC_GDOE__ELCDIF_DAT_18                      0x1f8 0x594 0x000 0x3 0x0
+#define MX50_PAD_EPDC_GDOE__AUDMUX_AUD6_RXC                    0x1f8 0x594 0x000 0x4 0x0
+#define MX50_PAD_EPDC_GDOE__SDMA_DEBUG_CORE_STATE_2            0x1f8 0x594 0x000 0x6 0x0
+#define MX50_PAD_EPDC_GDOE__USBPHY2_ENDSESSION                 0x1f8 0x594 0x000 0x7 0x0
+#define MX50_PAD_EPDC_GDRL__EPCD_GDRL                          0x1fc 0x598 0x000 0x0 0x0
+#define MX50_PAD_EPDC_GDRL__GPIO3_19                           0x1fc 0x598 0x000 0x1 0x0
+#define MX50_PAD_EPDC_GDRL__EIM_WEIM_D_19                      0x1f8 0x598 0x000 0x2 0x0
+#define MX50_PAD_EPDC_GDRL__ELCDIF_DAT_19                      0x1fc 0x598 0x000 0x3 0x0
+#define MX50_PAD_EPDC_GDRL__AUDMUX_AUD6_RXFS                   0x1fc 0x598 0x000 0x4 0x0
+#define MX50_PAD_EPDC_GDRL__SDMA_DEBUG_CORE_STATE_3            0x1fc 0x598 0x000 0x6 0x0
+#define MX50_PAD_EPDC_GDRL__USBPHY2_IDDIG                      0x1fc 0x598 0x000 0x7 0x0
+#define MX50_PAD_EPDC_SDCLK__EPCD_SDCLK                                0x200 0x59c 0x000 0x0 0x0
+#define MX50_PAD_EPDC_SDCLK__GPIO3_20                          0x200 0x59c 0x000 0x1 0x0
+#define MX50_PAD_EPDC_SDCLK__EIM_WEIM_D_20                     0x200 0x59c 0x000 0x2 0x0
+#define MX50_PAD_EPDC_SDCLK__ELCDIF_DAT_20                     0x200 0x59c 0x000 0x3 0x0
+#define MX50_PAD_EPDC_SDCLK__AUDMUX_AUD5_TXD                   0x200 0x59c 0x000 0x4 0x0
+#define MX50_PAD_EPDC_SDCLK__SDMA_DEBUG_BUS_DEVICE_0           0x200 0x59c 0x000 0x6 0x0
+#define MX50_PAD_EPDC_SDCLK__USBPHY2_HOSTDISCONNECT            0x200 0x59c 0x000 0x7 0x0
+#define MX50_PAD_EPDC_SDOEZ__EPCD_SDOEZ                                0x204 0x5a0 0x000 0x0 0x0
+#define MX50_PAD_EPDC_SDOEZ__GPIO3_21                          0x204 0x5a0 0x000 0x1 0x0
+#define MX50_PAD_EPDC_SDOEZ__EIM_WEIM_D_21                     0x204 0x5a0 0x000 0x2 0x0
+#define MX50_PAD_EPDC_SDOEZ__ELCDIF_DAT_21                     0x204 0x5a0 0x000 0x3 0x0
+#define MX50_PAD_EPDC_SDOEZ__AUDMUX_AUD5_TXC                   0x204 0x5a0 0x000 0x4 0x0
+#define MX50_PAD_EPDC_SDOEZ__SDMA_DEBUG_BUS_DEVICE_1           0x204 0x5a0 0x000 0x6 0x0
+#define MX50_PAD_EPDC_SDOEZ__USBPHY2_TXREADY                   0x204 0x5a0 0x000 0x7 0x0
+#define MX50_PAD_EPDC_SDOED__EPCD_SDOED                                0x208 0x5a4 0x000 0x0 0x0
+#define MX50_PAD_EPDC_SDOED__GPIO3_22                          0x208 0x5a4 0x000 0x1 0x0
+#define MX50_PAD_EPDC_SDOED__EIM_WEIM_D_22                     0x208 0x5a4 0x000 0x2 0x0
+#define MX50_PAD_EPDC_SDOED__ELCDIF_DAT_22                     0x208 0x5a4 0x000 0x3 0x0
+#define MX50_PAD_EPDC_SDOED__AUDMUX_AUD5_TXFS                  0x208 0x5a4 0x000 0x4 0x0
+#define MX50_PAD_EPDC_SDOED__SDMA_DEBUG_BUS_DEVICE_2           0x208 0x5a4 0x000 0x6 0x0
+#define MX50_PAD_EPDC_SDOED__USBPHY2_RXVALID                   0x208 0x5a4 0x000 0x7 0x0
+#define MX50_PAD_EPDC_SDOE__EPCD_SDOE                          0x20c 0x5a8 0x000 0x0 0x0
+#define MX50_PAD_EPDC_SDOE__GPIO3_23                           0x20c 0x5a8 0x000 0x1 0x0
+#define MX50_PAD_EPDC_SDOE__EIM_WEIM_D_23                      0x20c 0x5a8 0x000 0x2 0x0
+#define MX50_PAD_EPDC_SDOE__ELCDIF_DAT_23                      0x20c 0x5a8 0x000 0x3 0x0
+#define MX50_PAD_EPDC_SDOE__AUDMUX_AUD5_RXD                    0x20c 0x5a8 0x000 0x4 0x0
+#define MX50_PAD_EPDC_SDOE__SDMA_DEBUG_BUS_DEVICE_3            0x20c 0x5a8 0x000 0x6 0x0
+#define MX50_PAD_EPDC_SDOE__USBPHY2_RXACTIVE                   0x20c 0x5a8 0x000 0x7 0x0
+#define MX50_PAD_EPDC_SDLE__EPCD_SDLE                          0x210 0x5ac 0x000 0x0 0x0
+#define MX50_PAD_EPDC_SDLE__GPIO3_24                           0x210 0x5ac 0x000 0x1 0x0
+#define MX50_PAD_EPDC_SDLE__EIM_WEIM_D_24                      0x210 0x5ac 0x000 0x2 0x0
+#define MX50_PAD_EPDC_SDLE__ELCDIF_DAT_8                       0x210 0x5ac 0x71c 0x3 0x1
+#define MX50_PAD_EPDC_SDLE__AUDMUX_AUD5_RXC                    0x210 0x5ac 0x000 0x4 0x0
+#define MX50_PAD_EPDC_SDLE__SDMA_DEBUG_BUS_DEVICE_4            0x210 0x5ac 0x000 0x6 0x0
+#define MX50_PAD_EPDC_SDLE__USBPHY2_RXERROR                    0x210 0x5ac 0x000 0x7 0x0
+#define MX50_PAD_EPDC_SDCLKN__EPCD_SDCLKN                      0x214 0x5b0 0x000 0x0 0x0
+#define MX50_PAD_EPDC_SDCLKN__GPIO3_25                         0x214 0x5b0 0x000 0x1 0x0
+#define MX50_PAD_EPDC_SDCLKN__EIM_WEIM_D_25                    0x214 0x5b0 0x000 0x2 0x0
+#define MX50_PAD_EPDC_SDCLKN__ELCDIF_DAT_9                     0x214 0x5b0 0x720 0x3 0x1
+#define MX50_PAD_EPDC_SDCLKN__AUDMUX_AUD5_RXFS                 0x214 0x5b0 0x000 0x4 0x0
+#define MX50_PAD_EPDC_SDCLKN__SDMA_DEBUG_BUS_ERROR             0x214 0x5b0 0x000 0x6 0x0
+#define MX50_PAD_EPDC_SDCLKN__USBPHY2_SIECLOCK                 0x214 0x5b0 0x000 0x7 0x0
+#define MX50_PAD_EPDC_SDSHR__EPCD_SDSHR                                0x218 0x5b4 0x000 0x0 0x0
+#define MX50_PAD_EPDC_SDSHR__GPIO3_26                          0x218 0x5b4 0x000 0x1 0x0
+#define MX50_PAD_EPDC_SDSHR__EIM_WEIM_D_26                     0x218 0x5b4 0x000 0x2 0x0
+#define MX50_PAD_EPDC_SDSHR__ELCDIF_DAT_10                     0x218 0x5b4 0x724 0x3 0x1
+#define MX50_PAD_EPDC_SDSHR__AUDMUX_AUD4_TXD                   0x218 0x5b4 0x6c8 0x4 0x1
+#define MX50_PAD_EPDC_SDSHR__SDMA_DEBUG_BUS_RWB                        0x218 0x5b4 0x000 0x6 0x0
+#define MX50_PAD_EPDC_SDSHR__USBPHY2_LINESTATE_0               0x218 0x5b4 0x000 0x7 0x0
+#define MX50_PAD_EPDC_PWRCOM__EPCD_PWRCOM                      0x21c 0x5b8 0x000 0x0 0x0
+#define MX50_PAD_EPDC_PWRCOM__GPIO3_27                         0x21c 0x5b8 0x000 0x1 0x0
+#define MX50_PAD_EPDC_PWRCOM__EIM_WEIM_D_27                    0x21c 0x5b8 0x000 0x2 0x0
+#define MX50_PAD_EPDC_PWRCOM__ELCDIF_DAT_11                    0x21c 0x5b8 0x728 0x3 0x1
+#define MX50_PAD_EPDC_PWRCOM__AUDMUX_AUD4_TXC                  0x21c 0x5b8 0x6d4 0x4 0x1
+#define MX50_PAD_EPDC_PWRCOM__SDMA_DEBUG_CORE_RUN              0x21c 0x5b8 0x000 0x6 0x0
+#define MX50_PAD_EPDC_PWRCOM__USBPHY2_LINESTATE_1              0x21c 0x5b8 0x000 0x7 0x0
+#define MX50_PAD_EPDC_PWRSTAT__EPCD_PWRSTAT                    0x220 0x5bc 0x000 0x0 0x0
+#define MX50_PAD_EPDC_PWRSTAT__GPIO3_28                                0x220 0x5bc 0x000 0x1 0x0
+#define MX50_PAD_EPDC_PWRSTAT__EIM_WEIM_D_28                   0x220 0x5bc 0x000 0x2 0x0
+#define MX50_PAD_EPDC_PWRSTAT__ELCDIF_DAT_12                   0x220 0x5bc 0x72c 0x3 0x1
+#define MX50_PAD_EPDC_PWRSTAT__AUDMUX_AUD4_TXFS                        0x220 0x5bc 0x6d8 0x4 0x1
+#define MX50_PAD_EPDC_PWRSTAT__SDMA_DEBUG_MODE                 0x220 0x5bc 0x000 0x6 0x0
+#define MX50_PAD_EPDC_PWRSTAT__USBPHY2_VBUSVALID               0x220 0x5bc 0x000 0x7 0x0
+#define MX50_PAD_EPDC_PWRCTRL0__EPCD_PWRCTRL0                  0x224 0x5c0 0x000 0x0 0x0
+#define MX50_PAD_EPDC_PWRCTRL0__GPIO3_29                       0x224 0x5c0 0x000 0x1 0x0
+#define MX50_PAD_EPDC_PWRCTRL0__EIM_WEIM_D_29                  0x224 0x5c0 0x000 0x2 0x0
+#define MX50_PAD_EPDC_PWRCTRL0__ELCDIF_DAT_13                  0x224 0x5c0 0x730 0x3 0x1
+#define MX50_PAD_EPDC_PWRCTRL0__AUDMUX_AUD4_RXD                        0x224 0x5c0 0x6c4 0x4 0x1
+#define MX50_PAD_EPDC_PWRCTRL0__SDMA_DEBUG_RTBUFFER_WRITE      0x224 0x5c0 0x000 0x6 0x0
+#define MX50_PAD_EPDC_PWRCTRL0__USBPHY2_AVALID                 0x224 0x5c0 0x000 0x7 0x0
+#define MX50_PAD_EPDC_PWRCTRL1__EPCD_PWRCTRL1                  0x228 0x5c4 0x000 0x0 0x0
+#define MX50_PAD_EPDC_PWRCTRL1__GPIO3_30                       0x228 0x5c4 0x000 0x1 0x0
+#define MX50_PAD_EPDC_PWRCTRL1__EIM_WEIM_D_30                  0x228 0x5c4 0x000 0x2 0x0
+#define MX50_PAD_EPDC_PWRCTRL1__ELCDIF_DAT_14                  0x228 0x5c4 0x734 0x3 0x1
+#define MX50_PAD_EPDC_PWRCTRL1__AUDMUX_AUD4_RXC                        0x228 0x5c4 0x6cc 0x4 0x1
+#define MX50_PAD_EPDC_PWRCTRL1__SDMA_DEBUG_YIELD               0x228 0x5c4 0x000 0x6 0x0
+#define MX50_PAD_EPDC_PWRCTRL1__USBPHY1_ONBIST                 0x228 0x5c4 0x000 0x7 0x0
+#define MX50_PAD_EPDC_PWRCTRL2__EPCD_PWRCTRL2                  0x22c 0x5c8 0x000 0x0 0x0
+#define MX50_PAD_EPDC_PWRCTRL2__GPIO3_31                       0x22c 0x5c8 0x000 0x1 0x0
+#define MX50_PAD_EPDC_PWRCTRL2__EIM_WEIM_D_31                  0x22c 0x5c8 0x000 0x2 0x0
+#define MX50_PAD_EPDC_PWRCTRL2__ELCDIF_DAT_15                  0x22c 0x5c8 0x738 0x3 0x1
+#define MX50_PAD_EPDC_PWRCTRL2__AUDMUX_AUD4_RXFS               0x22c 0x5c8 0x6d0 0x4 0x1
+#define MX50_PAD_EPDC_PWRCTRL2__SDMA_EXT_EVENT_0               0x22c 0x5c8 0x7b8 0x6 0x1
+#define MX50_PAD_EPDC_PWRCTRL2__USBPHY2_ONBIST                 0x22c 0x5c8 0x000 0x7 0x0
+#define MX50_PAD_EPDC_PWRCTRL3__EPCD_PWRCTRL3                  0x230 0x5cc 0x000 0x0 0x0
+#define MX50_PAD_EPDC_PWRCTRL3__GPIO4_20                       0x230 0x5cc 0x000 0x1 0x0
+#define MX50_PAD_EPDC_PWRCTRL3__EIM_WEIM_EB_2                  0x230 0x5cc 0x000 0x2 0x0
+#define MX50_PAD_EPDC_PWRCTRL3__SDMA_EXT_EVENT_1               0x230 0x5cc 0x7bc 0x6 0x1
+#define MX50_PAD_EPDC_PWRCTRL3__USBPHY1_BISTOK                 0x230 0x5cc 0x000 0x7 0x0
+#define MX50_PAD_EPDC_VCOM0__EPCD_VCOM_0                       0x234 0x5d0 0x000 0x0 0x0
+#define MX50_PAD_EPDC_VCOM0__GPIO4_21                          0x234 0x5d0 0x000 0x1 0x0
+#define MX50_PAD_EPDC_VCOM0__EIM_WEIM_EB_3                     0x234 0x5d0 0x000 0x2 0x0
+#define MX50_PAD_EPDC_VCOM0__USBPHY2_BISTOK                    0x234 0x5d0 0x000 0x7 0x0
+#define MX50_PAD_EPDC_VCOM1__EPCD_VCOM_1                       0x238 0x5d4 0x000 0x0 0x0
+#define MX50_PAD_EPDC_VCOM1__GPIO4_22                          0x238 0x5d4 0x000 0x1 0x0
+#define MX50_PAD_EPDC_VCOM1__EIM_WEIM_CS_3                     0x238 0x5d4 0x000 0x2 0x0
+#define MX50_PAD_EPDC_BDR0__EPCD_BDR_0                         0x23c 0x5d8 0x000 0x0 0x0
+#define MX50_PAD_EPDC_BDR0__GPIO4_23                           0x23c 0x5d8 0x000 0x1 0x0
+#define MX50_PAD_EPDC_BDR0__ELCDIF_DAT_7                       0x23c 0x5d8 0x718 0x3 0x1
+#define MX50_PAD_EPDC_BDR1__EPCD_BDR_1                         0x240 0x5dc 0x000 0x0 0x0
+#define MX50_PAD_EPDC_BDR1__GPIO4_24                           0x240 0x5dc 0x000 0x1 0x0
+#define MX50_PAD_EPDC_BDR1__ELCDIF_DAT_6                       0x240 0x5dc 0x714 0x3 0x1
+#define MX50_PAD_EPDC_SDCE0__EPCD_SDCE_0                       0x244 0x5e0 0x000 0x0 0x0
+#define MX50_PAD_EPDC_SDCE0__GPIO4_25                          0x244 0x5e0 0x000 0x1 0x0
+#define MX50_PAD_EPDC_SDCE0__ELCDIF_DAT_5                      0x244 0x5e0 0x710 0x3 0x1
+#define MX50_PAD_EPDC_SDCE1__EPCD_SDCE_1                       0x248 0x5e4 0x000 0x0 0x0
+#define MX50_PAD_EPDC_SDCE1__GPIO4_26                          0x248 0x5e4 0x000 0x1 0x0
+#define MX50_PAD_EPDC_SDCE1__ELCDIF_DAT_4                      0x248 0x5e4 0x70c 0x3 0x0
+#define MX50_PAD_EPDC_SDCE2__EPCD_SDCE_2                       0x24c 0x5e8 0x000 0x0 0x0
+#define MX50_PAD_EPDC_SDCE2__GPIO4_27                          0x24c 0x5e8 0x000 0x1 0x0
+#define MX50_PAD_EPDC_SDCE2__ELCDIF_DAT_3                      0x24c 0x5e8 0x708 0x3 0x1
+#define MX50_PAD_EPDC_SDCE3__EPCD_SDCE_3                       0x250 0x5ec 0x000 0x0 0x0
+#define MX50_PAD_EPDC_SDCE3__GPIO4_28                          0x250 0x5ec 0x000 0x1 0x0
+#define MX50_PAD_EPDC_SDCE3__ELCDIF_DAT_2                      0x250 0x5ec 0x704 0x3 0x1
+#define MX50_PAD_EPDC_SDCE4__EPCD_SDCE_4                       0x254 0x5f0 0x000 0x0 0x0
+#define MX50_PAD_EPDC_SDCE4__GPIO4_29                          0x254 0x5f0 0x000 0x1 0x0
+#define MX50_PAD_EPDC_SDCE4__ELCDIF_DAT_1                      0x254 0x5f0 0x700 0x3 0x1
+#define MX50_PAD_EPDC_SDCE5__EPCD_SDCE_5                       0x258 0x5f4 0x000 0x0 0x0
+#define MX50_PAD_EPDC_SDCE5__GPIO4_30                          0x258 0x5f4 0x000 0x1 0x0
+#define MX50_PAD_EPDC_SDCE5__ELCDIF_DAT_0                      0x258 0x5f4 0x6fc 0x3 0x1
+#define MX50_PAD_EIM_DA0__EIM_WEIM_A_0                         0x25c 0x5f8 0x000 0x0 0x0
+#define MX50_PAD_EIM_DA0__GPIO1_0                              0x25c 0x5f8 0x000 0x1 0x0
+#define MX50_PAD_EIM_DA0__KPP_COL_4                            0x25c 0x5f8 0x790 0x3 0x2
+#define MX50_PAD_EIM_DA0__TPIU_TRACE_0                         0x25c 0x5f8 0x000 0x6 0x0
+#define MX50_PAD_EIM_DA0__SRC_BT_CFG1_0                                0x25c 0x5f8 0x000 0x7 0x0
+#define MX50_PAD_EIM_DA1__EIM_WEIM_A_1                         0x260 0x5fc 0x000 0x0 0x0
+#define MX50_PAD_EIM_DA1__GPIO1_1                              0x260 0x5fc 0x000 0x1 0x0
+#define MX50_PAD_EIM_DA1__KPP_ROW_4                            0x260 0x5fc 0x7a0 0x3 0x2
+#define MX50_PAD_EIM_DA1__TPIU_TRACE_1                         0x260 0x5fc 0x000 0x6 0x0
+#define MX50_PAD_EIM_DA1__SRC_BT_CFG1_1                                0x260 0x5fc 0x000 0x7 0x0
+#define MX50_PAD_EIM_DA2__EIM_WEIM_A_2                         0x264 0x600 0x000 0x0 0x0
+#define MX50_PAD_EIM_DA2__GPIO1_2                              0x264 0x600 0x000 0x1 0x0
+#define MX50_PAD_EIM_DA2__KPP_COL_5                            0x264 0x600 0x794 0x3 0x2
+#define MX50_PAD_EIM_DA2__TPIU_TRACE_2                         0x264 0x600 0x000 0x6 0x0
+#define MX50_PAD_EIM_DA2__SRC_BT_CFG1_2                                0x264 0x600 0x000 0x7 0x0
+#define MX50_PAD_EIM_DA3__EIM_WEIM_A_3                         0x268 0x604 0x000 0x0 0x0
+#define MX50_PAD_EIM_DA3__GPIO1_3                              0x268 0x604 0x000 0x1 0x0
+#define MX50_PAD_EIM_DA3__KPP_ROW_5                            0x268 0x604 0x7a4 0x3 0x2
+#define MX50_PAD_EIM_DA3__TPIU_TRACE_3                         0x268 0x604 0x000 0x6 0x0
+#define MX50_PAD_EIM_DA3__SRC_BT_CFG1_3                                0x268 0x604 0x000 0x7 0x0
+#define MX50_PAD_EIM_DA4__EIM_WEIM_A_4                         0x26c 0x608 0x000 0x0 0x0
+#define MX50_PAD_EIM_DA4__GPIO1_4                              0x26c 0x608 0x000 0x1 0x0
+#define MX50_PAD_EIM_DA4__KPP_COL_6                            0x26c 0x608 0x798 0x3 0x2
+#define MX50_PAD_EIM_DA4__TPIU_TRACE_4                         0x26c 0x608 0x000 0x6 0x0
+#define MX50_PAD_EIM_DA4__SRC_BT_CFG1_4                                0x26c 0x608 0x000 0x7 0x0
+#define MX50_PAD_EIM_DA5__EIM_WEIM_A_5                         0x270 0x60c 0x000 0x0 0x0
+#define MX50_PAD_EIM_DA5__GPIO1_5                              0x270 0x60c 0x000 0x1 0x0
+#define MX50_PAD_EIM_DA5__KPP_ROW_6                            0x270 0x60c 0x7a8 0x3 0x2
+#define MX50_PAD_EIM_DA5__TPIU_TRACE_5                         0x270 0x60c 0x000 0x6 0x0
+#define MX50_PAD_EIM_DA5__SRC_BT_CFG1_5                                0x270 0x60c 0x000 0x7 0x0
+#define MX50_PAD_EIM_DA6__EIM_WEIM_A_6                         0x274 0x610 0x000 0x0 0x0
+#define MX50_PAD_EIM_DA6__GPIO1_6                              0x274 0x610 0x000 0x1 0x0
+#define MX50_PAD_EIM_DA6__KPP_COL_7                            0x274 0x610 0x79c 0x3 0x2
+#define MX50_PAD_EIM_DA6__TPIU_TRACE_6                         0x274 0x610 0x000 0x6 0x0
+#define MX50_PAD_EIM_DA6__SRC_BT_CFG1_6                                0x274 0x610 0x000 0x7 0x0
+#define MX50_PAD_EIM_DA7__EIM_WEIM_A_7                         0x278 0x614 0x000 0x0 0x0
+#define MX50_PAD_EIM_DA7__GPIO1_7                              0x278 0x614 0x000 0x1 0x0
+#define MX50_PAD_EIM_DA7__KPP_ROW_7                            0x278 0x614 0x7ac 0x3 0x2
+#define MX50_PAD_EIM_DA7__TPIU_TRACE_7                         0x278 0x614 0x000 0x6 0x0
+#define MX50_PAD_EIM_DA7__SRC_BT_CFG1_7                                0x278 0x614 0x000 0x7 0x0
+#define MX50_PAD_EIM_DA8__EIM_WEIM_A_8                         0x27c 0x618 0x000 0x0 0x0
+#define MX50_PAD_EIM_DA8__GPIO1_8                              0x27c 0x618 0x000 0x1 0x0
+#define MX50_PAD_EIM_DA8__EIM_NANDF_CLE                                0x27c 0x618 0x000 0x2 0x0
+#define MX50_PAD_EIM_DA8__TPIU_TRACE_8                         0x27c 0x618 0x000 0x6 0x0
+#define MX50_PAD_EIM_DA8__SRC_BT_CFG2_0                                0x27c 0x618 0x000 0x7 0x0
+#define MX50_PAD_EIM_DA9__EIM_WEIM_A_9                         0x280 0x61c 0x000 0x0 0x0
+#define MX50_PAD_EIM_DA9__GPIO1_9                              0x280 0x61c 0x000 0x1 0x0
+#define MX50_PAD_EIM_DA9__EIM_NANDF_ALE                                0x280 0x61c 0x000 0x2 0x0
+#define MX50_PAD_EIM_DA9__TPIU_TRACE_9                         0x280 0x61c 0x000 0x6 0x0
+#define MX50_PAD_EIM_DA9__SRC_BT_CFG2_1                                0x280 0x61c 0x000 0x7 0x0
+#define MX50_PAD_EIM_DA10__EIM_WEIM_A_10                       0x284 0x620 0x000 0x0 0x0
+#define MX50_PAD_EIM_DA10__GPIO1_10                            0x284 0x620 0x000 0x1 0x0
+#define MX50_PAD_EIM_DA10__EIM_NANDF_CEN_0                     0x284 0x620 0x000 0x2 0x0
+#define MX50_PAD_EIM_DA10__TPIU_TRACE_10                       0x284 0x620 0x000 0x6 0x0
+#define MX50_PAD_EIM_DA10__SRC_BT_CFG2_2                       0x284 0x620 0x000 0x7 0x0
+#define MX50_PAD_EIM_DA11__EIM_WEIM_A_11                       0x288 0x624 0x000 0x0 0x0
+#define MX50_PAD_EIM_DA11__GPIO1_11                            0x288 0x624 0x000 0x1 0x0
+#define MX50_PAD_EIM_DA11__EIM_NANDF_CEN_1                     0x288 0x624 0x000 0x2 0x0
+#define MX50_PAD_EIM_DA11__TPIU_TRACE_11                       0x288 0x624 0x000 0x6 0x0
+#define MX50_PAD_EIM_DA11__SRC_BT_CFG2_3                       0x288 0x624 0x000 0x7 0x0
+#define MX50_PAD_EIM_DA12__EIM_WEIM_A_12                       0x28c 0x628 0x000 0x0 0x0
+#define MX50_PAD_EIM_DA12__GPIO1_12                            0x28c 0x628 0x000 0x1 0x0
+#define MX50_PAD_EIM_DA12__EIM_NANDF_CEN_2                     0x28c 0x628 0x000 0x2 0x0
+#define MX50_PAD_EIM_DA12__EPDC_SDCE_6                         0x28c 0x628 0x000 0x3 0x0
+#define MX50_PAD_EIM_DA12__TPIU_TRACE_12                       0x28c 0x628 0x000 0x6 0x0
+#define MX50_PAD_EIM_DA12__SRC_BT_CFG2_4                       0x28c 0x628 0x000 0x7 0x0
+#define MX50_PAD_EIM_DA13__EIM_WEIM_A_13                       0x290 0x62c 0x000 0x0 0x0
+#define MX50_PAD_EIM_DA13__GPIO1_13                            0x290 0x62c 0x000 0x1 0x0
+#define MX50_PAD_EIM_DA13__EIM_NANDF_CEN_3                     0x290 0x62c 0x000 0x2 0x0
+#define MX50_PAD_EIM_DA13__EPDC_SDCE_7                         0x290 0x62c 0x000 0x3 0x0
+#define MX50_PAD_EIM_DA13__TPIU_TRACE_13                       0x290 0x62c 0x000 0x6 0x0
+#define MX50_PAD_EIM_DA13__SRC_BT_CFG2_5                       0x290 0x62c 0x000 0x7 0x0
+#define MX50_PAD_EIM_DA14__EIM_WEIM_A_14                       0x294 0x630 0x000 0x0 0x0
+#define MX50_PAD_EIM_DA14__GPIO1_14                            0x294 0x630 0x000 0x1 0x0
+#define MX50_PAD_EIM_DA14__EIM_NANDF_READY0                    0x294 0x630 0x7b4 0x2 0x2
+#define MX50_PAD_EIM_DA14__EPDC_SDCE_8                         0x294 0x630 0x000 0x3 0x0
+#define MX50_PAD_EIM_DA14__TPIU_TRACE_14                       0x294 0x630 0x000 0x6 0x0
+#define MX50_PAD_EIM_DA14__SRC_BT_CFG2_6                       0x294 0x630 0x000 0x7 0x0
+#define MX50_PAD_EIM_DA15__EIM_WEIM_A_15                       0x298 0x634 0x000 0x0 0x0
+#define MX50_PAD_EIM_DA15__GPIO1_15                            0x298 0x634 0x000 0x1 0x0
+#define MX50_PAD_EIM_DA15__EIM_NANDF_DQS                       0x298 0x634 0x7b0 0x2 0x2
+#define MX50_PAD_EIM_DA15__EPDC_SDCE_9                         0x298 0x634 0x000 0x3 0x0
+#define MX50_PAD_EIM_DA15__TPIU_TRACE_15                       0x298 0x634 0x000 0x6 0x0
+#define MX50_PAD_EIM_DA15__SRC_BT_CFG2_7                       0x298 0x634 0x000 0x7 0x0
+#define MX50_PAD_EIM_CS2__EIM_WEIM_CS_2                                0x29c 0x638 0x000 0x0 0x0
+#define MX50_PAD_EIM_CS2__GPIO1_16                             0x29c 0x638 0x000 0x1 0x0
+#define MX50_PAD_EIM_CS2__EIM_WEIM_A_27                                0x29c 0x638 0x000 0x2 0x0
+#define MX50_PAD_EIM_CS2__TPIU_TRCLK                           0x29c 0x638 0x000 0x6 0x0
+#define MX50_PAD_EIM_CS2__SRC_BT_CFG3_0                                0x29c 0x638 0x000 0x7 0x0
+#define MX50_PAD_EIM_CS1__EIM_WEIM_CS_1                                0x2a0 0x63c 0x000 0x0 0x0
+#define MX50_PAD_EIM_CS1__GPIO1_17                             0x2a0 0x63c 0x000 0x1 0x0
+#define MX50_PAD_EIM_CS1__TPIU_TRCTL                           0x2a0 0x63c 0x000 0x6 0x0
+#define MX50_PAD_EIM_CS1__SRC_BT_CFG3_1                                0x2a0 0x63c 0x000 0x7 0x0
+#define MX50_PAD_EIM_CS0__EIM_WEIM_CS_0                                0x2a4 0x640 0x000 0x0 0x0
+#define MX50_PAD_EIM_CS0__GPIO1_18                             0x2a4 0x640 0x000 0x1 0x0
+#define MX50_PAD_EIM_CS0__SRC_BT_CFG3_2                                0x2a4 0x640 0x000 0x7 0x0
+#define MX50_PAD_EIM_EB0__EIM_WEIM_EB_0                                0x2a8 0x644 0x000 0x0 0x0
+#define MX50_PAD_EIM_EB0__GPIO1_19                             0x2a8 0x644 0x000 0x1 0x0
+#define MX50_PAD_EIM_EB0__SRC_BT_CFG3_3                                0x2a8 0x644 0x000 0x7 0x0
+#define MX50_PAD_EIM_EB1__EIM_WEIM_EB_1                                0x2ac 0x648 0x000 0x0 0x0
+#define MX50_PAD_EIM_EB1__GPIO1_20                             0x2ac 0x648 0x000 0x1 0x0
+#define MX50_PAD_EIM_EB1__SRC_BT_CFG3_4                                0x2ac 0x648 0x000 0x7 0x0
+#define MX50_PAD_EIM_WAIT__EIM_WEIM_WAIT                       0x2b0 0x64c 0x000 0x0 0x0
+#define MX50_PAD_EIM_WAIT__GPIO1_21                            0x2b0 0x64c 0x000 0x1 0x0
+#define MX50_PAD_EIM_WAIT__EIM_WEIM_DTACK_B                    0x2b0 0x64c 0x000 0x2 0x0
+#define MX50_PAD_EIM_WAIT__SRC_BT_CFG3_5                       0x2b0 0x64c 0x000 0x7 0x0
+#define MX50_PAD_EIM_BCLK__EIM_WEIM_BCLK                       0x2b4 0x650 0x000 0x0 0x0
+#define MX50_PAD_EIM_BCLK__GPIO1_22                            0x2b4 0x650 0x000 0x1 0x0
+#define MX50_PAD_EIM_BCLK__SRC_BT_CFG3_6                       0x2b4 0x650 0x000 0x7 0x0
+#define MX50_PAD_EIM_RDY__EIM_WEIM_RDY                         0x2b8 0x654 0x000 0x0 0x0
+#define MX50_PAD_EIM_RDY__GPIO1_23                             0x2b8 0x654 0x000 0x1 0x0
+#define MX50_PAD_EIM_RDY__SRC_BT_CFG3_7                                0x2b8 0x654 0x000 0x7 0x0
+#define MX50_PAD_EIM_OE__EIM_WEIM_OE                           0x2bc 0x658 0x000 0x0 0x0
+#define MX50_PAD_EIM_OE__GPIO1_24                              0x2bc 0x658 0x000 0x1 0x0
+#define MX50_PAD_EIM_OE__INT_BOOT                              0x2bc 0x658 0x000 0x7 0x0
+#define MX50_PAD_EIM_RW__EIM_WEIM_RW                           0x2c0 0x65c 0x000 0x0 0x0
+#define MX50_PAD_EIM_RW__GPIO1_25                              0x2c0 0x65c 0x000 0x1 0x0
+#define MX50_PAD_EIM_RW__SYSTEM_RST                            0x2c0 0x65c 0x000 0x7 0x0
+#define MX50_PAD_EIM_LBA__EIM_WEIM_LBA                         0x2c4 0x660 0x000 0x0 0x0
+#define MX50_PAD_EIM_LBA__GPIO1_26                             0x2c4 0x660 0x000 0x1 0x0
+#define MX50_PAD_EIM_LBA__TESTER_ACK                           0x2c4 0x660 0x000 0x7 0x0
+#define MX50_PAD_EIM_CRE__EIM_WEIM_CRE                         0x2c8 0x664 0x000 0x0 0x0
+#define MX50_PAD_EIM_CRE__GPIO1_27                             0x2c8 0x664 0x000 0x1 0x0
+
+#endif /* __DTS_IMX50_PINFUNC_H */
diff --git a/arch/arm/boot/dts/imx50-pingrp.h b/arch/arm/boot/dts/imx50-pingrp.h
new file mode 100644 (file)
index 0000000..0f4ce8c
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 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.
+ *
+ */
+
+#ifndef __DTS_IMX50_PINGRP_H
+#define __DTS_IMX50_PINGRP_H
+
+#include "imx50-pinfunc.h"
+
+#define MX50_CSPI_PINGRP1 \
+       MX50_PAD_CSPI_SCLK__CSPI_SCLK                   0x00 \
+       MX50_PAD_CSPI_MISO__CSPI_MISO                   0x00 \
+       MX50_PAD_CSPI_MOSI__CSPI_MOSI                   0x00 \
+       MX50_PAD_CSPI_SS0__GPIO4_11                     0xc4 \
+       MX50_PAD_ECSPI1_MOSI__CSPI_SS1                  0xf4
+
+#define MX50_ECSPI1_PINGRP1 \
+       MX50_PAD_ECSPI1_SCLK__ECSPI1_SCLK               0x00 \
+       MX50_PAD_ECSPI1_SS0__ECSPI1_SS0                 0x00 \
+       MX50_PAD_ECSPI1_MISO__ECSPI1_MISO               0x00 \
+       MX50_PAD_ECSPI1_MOSI__ECSPI1_MOSI               0x00
+
+#define MX50_ESDHC1_PINGRP1 \
+       MX50_PAD_SD1_D0__ESDHC1_DAT0                    0x1d4 \
+       MX50_PAD_SD1_D1__ESDHC1_DAT1                    0x1d4 \
+       MX50_PAD_SD1_D2__ESDHC1_DAT2                    0x1d4 \
+       MX50_PAD_SD1_D3__ESDHC1_DAT3                    0x1d4 \
+       MX50_PAD_SD1_CMD__ESDHC1_CMD                    0x1e4 \
+       MX50_PAD_SD1_CLK__ESDHC1_CLK                    0xd4
+
+#define MX50_ESDHC1_PINGRP2 \
+       MX50_PAD_SD1_D0__ESDHC1_DAT0                    0x1d4 \
+       MX50_PAD_SD1_D1__ESDHC1_DAT1                    0x1d4 \
+       MX50_PAD_SD1_D2__ESDHC1_DAT2                    0x1d4 \
+       MX50_PAD_SD1_D3__ESDHC1_DAT3                    0x1d4 \
+       MX50_PAD_UART3_TXD__ESDHC1_DAT4                 0x1d4 \
+       MX50_PAD_UART3_RXD__ESDHC1_DAT5                 0x1d4 \
+       MX50_PAD_UART4_TXD__ESDHC1_DAT6                 0x1d4 \
+       MX50_PAD_UART4_RXD__ESDHC1_DAT7                 0x1d4 \
+       MX50_PAD_SD1_CMD__ESDHC1_CMD                    0x14 \
+       MX50_PAD_SD1_CLK__ESDHC1_CLK                    0xd4
+
+#define MX50_ESDHC2_PINGRP1 \
+       MX50_PAD_SD2_CMD__ESDHC2_CMD                    0x1e4 \
+       MX50_PAD_SD2_CLK__ESDHC2_CLK                    0xd4 \
+       MX50_PAD_SD2_D0__ESDHC2_DAT0                    0x1d4 \
+       MX50_PAD_SD2_D1__ESDHC2_DAT1                    0x1d4 \
+       MX50_PAD_SD2_D2__ESDHC2_DAT2                    0x1d4 \
+       MX50_PAD_SD2_D3__ESDHC2_DAT3                    0x1d4 \
+       MX50_PAD_SD2_D4__ESDHC2_DAT4                    0x1d4 \
+       MX50_PAD_SD2_D5__ESDHC2_DAT5                    0x1d4 \
+       MX50_PAD_SD2_D6__ESDHC2_DAT6                    0x1d4 \
+       MX50_PAD_SD2_D7__ESDHC2_DAT7                    0x1d4
+
+#define MX50_ESDHC3_PINGRP1 \
+       MX50_PAD_SD3_D0__ESDHC3_DAT0                    0x1d4 \
+       MX50_PAD_SD3_D1__ESDHC3_DAT1                    0x1d4 \
+       MX50_PAD_SD3_D2__ESDHC3_DAT2                    0x1d4 \
+       MX50_PAD_SD3_D3__ESDHC3_DAT3                    0x1d4 \
+       MX50_PAD_SD3_D4__ESDHC3_DAT4                    0x1d4 \
+       MX50_PAD_SD3_D5__ESDHC3_DAT5                    0x1d4 \
+       MX50_PAD_SD3_D6__ESDHC3_DAT6                    0x1d4 \
+       MX50_PAD_SD3_D7__ESDHC3_DAT7                    0x1d4 \
+       MX50_PAD_SD3_CMD__ESDHC3_CMD                    0x1e4 \
+       MX50_PAD_SD3_CLK__ESDHC3_CLK                    0xd4
+
+#define MX50_FEC_PINGRP1 \
+       MX50_PAD_SSI_RXFS__FEC_MDC                      0x80 \
+       MX50_PAD_SSI_RXC__FEC_MDIO                      0x80 \
+       MX50_PAD_DISP_D0__FEC_TX_CLK                    0x80 \
+       MX50_PAD_DISP_D1__FEC_RX_ERR                    0x80 \
+       MX50_PAD_DISP_D2__FEC_RX_DV                     0x80 \
+       MX50_PAD_DISP_D3__FEC_RDATA_1                   0x80 \
+       MX50_PAD_DISP_D4__FEC_RDATA_0                   0x80 \
+       MX50_PAD_DISP_D5__FEC_TX_EN                     0x80 \
+       MX50_PAD_DISP_D6__FEC_TDATA_1                   0x80 \
+       MX50_PAD_DISP_D7__FEC_TDATA_0                   0x80
+
+#define MX50_FEC_PINGRP2 \
+       MX50_PAD_I2C3_SCL__FEC_MDC                      0x80 \
+       MX50_PAD_I2C3_SDA__FEC_MDIO                     0x80 \
+       MX50_PAD_DISP_D0__FEC_TX_CLK                    0x80 \
+       MX50_PAD_DISP_D10__FEC_RX_DV                    0x80 \
+       MX50_PAD_DISP_D11__FEC_RDATA_1                  0x80 \
+       MX50_PAD_DISP_D12__FEC_RDATA_0                  0x80 \
+       MX50_PAD_DISP_D13__FEC_TX_EN                    0x80 \
+       MX50_PAD_DISP_D14__FEC_TDATA_1                  0x80 \
+       MX50_PAD_DISP_D15__FEC_TDATA_0                  0x80
+
+#define MX50_I2C1_PINGRP1 \
+       MX50_PAD_I2C1_SDA__I2C1_SDA                     0x12c \
+       MX50_PAD_I2C1_SCL__I2C1_SCL                     0x12c
+
+#define MX50_I2C2_PINGRP1 \
+       MX50_PAD_I2C2_SDA__I2C2_SDA                     0x12c \
+       MX50_PAD_I2C2_SCL__I2C2_SCL                     0x12c
+
+#define MX50_I2C3_PINGRP1 \
+       MX50_PAD_I2C3_SDA__I2C3_SDA                     0x12c \
+       MX50_PAD_I2C3_SCL__I2C3_SCL                     0x12c
+
+#define MX50_OWIRE_PINGRP1 \
+       MX50_PAD_OWIRE__OWIRE_LINE                      0x84
+
+#define MX50_UART1_PINGRP1 \
+       MX50_PAD_UART1_TXD__UART1_TXD_MUX               0x1e4 \
+       MX50_PAD_UART1_RXD__UART1_RXD_MUX               0x1e4 \
+       MX50_PAD_UART1_RTS__UART1_RTS                   0x1e4 \
+       MX50_PAD_UART1_CTS__UART1_CTS                   0x1e4
+
+#define MX50_UART2_PINGRP1 \
+       MX50_PAD_UART2_TXD__UART2_TXD_MUX               0x1e4 \
+       MX50_PAD_UART2_RXD__UART2_RXD_MUX               0x1e4 \
+       MX50_PAD_UART2_RTS__UART2_RTS                   0x1e4 \
+       MX50_PAD_UART2_CTS__UART2_CTS                   0x1e4
+
+#define MX50_UART2_PINGRP2 \
+       MX50_PAD_I2C1_SCL__UART2_TXD_MUX                0x1e4 \
+       MX50_PAD_I2C1_SDA__UART2_RXD_MUX                0x1e4 \
+       MX50_PAD_I2C2_SDA__UART2_RTS                    0x1e4 \
+       MX50_PAD_I2C2_SCL__UART2_CTS                    0x1e4
+
+#define MX50_UART3_PINGRP1 \
+       MX50_PAD_UART3_TXD__UART3_TXD_MUX               0x1e4 \
+       MX50_PAD_UART3_RXD__UART3_RXD_MUX               0x1e4 \
+       MX50_PAD_ECSPI1_SCLK__UART3_RTS                 0x1e4 \
+       MX50_PAD_ECSPI1_MOSI__UART3_CTS                 0x1e4
+
+#define MX50_UART4_PINGRP1 \
+       MX50_PAD_UART4_TXD__UART4_TXD_MUX               0x1e4 \
+       MX50_PAD_UART4_RXD__UART4_RXD_MUX               0x1e4 \
+       MX50_PAD_ECSPI1_MISO__UART4_RTS                 0x1e4 \
+       MX50_PAD_ECSPI1_SS0__UART4_CTS                  0x1e4
+
+#define MX50_UART5_PINGRP1 \
+       MX50_PAD_ECSPI2_MISO__UART5_TXD_MUX             0x1e4 \
+       MX50_PAD_ECSPI2_SS0__UART5_RXD_MUX              0x1e4 \
+       MX50_PAD_ECSPI2_SCLK__UART5_RTS                 0x1e4 \
+       MX50_PAD_ECSPI2_MOSI__UART5_CTS                 0x1e4
+
+#endif /* __DTS_IMX50_PINGRP_H */
diff --git a/arch/arm/boot/dts/imx50.dtsi b/arch/arm/boot/dts/imx50.dtsi
new file mode 100644 (file)
index 0000000..01c0499
--- /dev/null
@@ -0,0 +1,475 @@
+/*
+ * Copyright 2013 Greg Ungerer <gerg@uclinux.org>
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include "skeleton.dtsi"
+#include "imx50-pingrp.h"
+#include <dt-bindings/clock/imx5-clock.h>
+
+/ {
+       aliases {
+               gpio0 = &gpio1;
+               gpio1 = &gpio2;
+               gpio2 = &gpio3;
+               gpio3 = &gpio4;
+               gpio4 = &gpio5;
+               gpio5 = &gpio6;
+               serial0 = &uart1;
+               serial1 = &uart2;
+               serial2 = &uart3;
+               serial3 = &uart4;
+               serial4 = &uart5;
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               cpu@0 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a8";
+                       reg = <0x0>;
+               };
+       };
+
+       tzic: tz-interrupt-controller@0fffc000 {
+               compatible = "fsl,imx50-tzic", "fsl,imx53-tzic", "fsl,tzic";
+               interrupt-controller;
+               #interrupt-cells = <1>;
+               reg = <0x0fffc000 0x4000>;
+       };
+
+       clocks {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               ckil {
+                       compatible = "fsl,imx-ckil", "fixed-clock";
+                       clock-frequency = <32768>;
+               };
+
+               ckih1 {
+                       compatible = "fsl,imx-ckih1", "fixed-clock";
+                       clock-frequency = <22579200>;
+               };
+
+               ckih2 {
+                       compatible = "fsl,imx-ckih2", "fixed-clock";
+                       clock-frequency = <0>;
+               };
+
+               osc {
+                       compatible = "fsl,imx-osc", "fixed-clock";
+                       clock-frequency = <24000000>;
+               };
+       };
+
+       soc {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "simple-bus";
+               interrupt-parent = <&tzic>;
+               ranges;
+
+               aips@50000000 { /* AIPS1 */
+                       compatible = "fsl,aips-bus", "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       reg = <0x50000000 0x10000000>;
+                       ranges;
+
+                       spba@50000000 {
+                               compatible = "fsl,spba-bus", "simple-bus";
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               reg = <0x50000000 0x40000>;
+                               ranges;
+
+                               esdhc1: esdhc@50004000 {
+                                       compatible = "fsl,imx50-esdhc";
+                                       reg = <0x50004000 0x4000>;
+                                       interrupts = <1>;
+                                       clocks = <&clks IMX5_CLK_ESDHC1_IPG_GATE>,
+                                                <&clks IMX5_CLK_DUMMY>,
+                                                <&clks IMX5_CLK_ESDHC1_PER_GATE>;
+                                       clock-names = "ipg", "ahb", "per";
+                                       bus-width = <4>;
+                                       status = "disabled";
+                               };
+
+                               esdhc2: esdhc@50008000 {
+                                       compatible = "fsl,imx50-esdhc";
+                                       reg = <0x50008000 0x4000>;
+                                       interrupts = <2>;
+                                       clocks = <&clks IMX5_CLK_ESDHC2_IPG_GATE>,
+                                                <&clks IMX5_CLK_DUMMY>,
+                                                <&clks IMX5_CLK_ESDHC2_PER_GATE>;
+                                       clock-names = "ipg", "ahb", "per";
+                                       bus-width = <4>;
+                                       status = "disabled";
+                               };
+
+                               uart3: serial@5000c000 {
+                                       compatible = "fsl,imx50-uart", "fsl,imx21-uart";
+                                       reg = <0x5000c000 0x4000>;
+                                       interrupts = <33>;
+                                       clocks = <&clks IMX5_CLK_UART3_IPG_GATE>,
+                                                <&clks IMX5_CLK_UART3_PER_GATE>;
+                                       clock-names = "ipg", "per";
+                                       status = "disabled";
+                               };
+
+                               ecspi1: ecspi@50010000 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       compatible = "fsl,imx50-ecspi", "fsl,imx51-ecspi";
+                                       reg = <0x50010000 0x4000>;
+                                       interrupts = <36>;
+                                       clocks = <&clks IMX5_CLK_ECSPI1_IPG_GATE>,
+                                                <&clks IMX5_CLK_ECSPI1_PER_GATE>;
+                                       clock-names = "ipg", "per";
+                                       status = "disabled";
+                               };
+
+                               ssi2: ssi@50014000 {
+                                       compatible = "fsl,imx50-ssi", "fsl,imx21-ssi";
+                                       reg = <0x50014000 0x4000>;
+                                       interrupts = <30>;
+                                       clocks = <&clks IMX5_CLK_SSI2_IPG_GATE>;
+                                       fsl,fifo-depth = <15>;
+                                       fsl,ssi-dma-events = <25 24 23 22>; /* TX0 RX0 TX1 RX1 */
+                                       status = "disabled";
+                               };
+
+                               esdhc3: esdhc@50020000 {
+                                       compatible = "fsl,imx50-esdhc";
+                                       reg = <0x50020000 0x4000>;
+                                       interrupts = <3>;
+                                       clocks = <&clks IMX5_CLK_ESDHC3_IPG_GATE>,
+                                                <&clks IMX5_CLK_DUMMY>,
+                                                <&clks IMX5_CLK_ESDHC3_PER_GATE>;
+                                       clock-names = "ipg", "ahb", "per";
+                                       bus-width = <4>;
+                                       status = "disabled";
+                               };
+
+                               esdhc4: esdhc@50024000 {
+                                       compatible = "fsl,imx50-esdhc";
+                                       reg = <0x50024000 0x4000>;
+                                       interrupts = <4>;
+                                       clocks = <&clks IMX5_CLK_ESDHC4_IPG_GATE>,
+                                                <&clks IMX5_CLK_DUMMY>,
+                                                <&clks IMX5_CLK_ESDHC4_PER_GATE>;
+                                       clock-names = "ipg", "ahb", "per";
+                                       bus-width = <4>;
+                                       status = "disabled";
+                               };
+                       };
+
+                       usbotg: usb@53f80000 {
+                               compatible = "fsl,imx50-usb", "fsl,imx27-usb";
+                               reg = <0x53f80000 0x0200>;
+                               interrupts = <18>;
+                               clocks = <&clks IMX5_CLK_USB_PHY1_GATE>;
+                               status = "disabled";
+                       };
+
+                       usbh1: usb@53f80200 {
+                               compatible = "fsl,imx50-usb", "fsl,imx27-usb";
+                               reg = <0x53f80200 0x0200>;
+                               interrupts = <14>;
+                               clocks = <&clks IMX5_CLK_USB_PHY2_GATE>;
+                               status = "disabled";
+                       };
+
+                       usbh2: usb@53f80400 {
+                               compatible = "fsl,imx50-usb", "fsl,imx27-usb";
+                               reg = <0x53f80400 0x0200>;
+                               interrupts = <16>;
+                               clocks = <&clks IMX5_CLK_USBOH3_GATE>;
+                               status = "disabled";
+                       };
+
+                       usbh3: usb@53f80600 {
+                               compatible = "fsl,imx50-usb", "fsl,imx27-usb";
+                               reg = <0x53f80600 0x0200>;
+                               interrupts = <17>;
+                               clocks = <&clks IMX5_CLK_USBOH3_GATE>;
+                               status = "disabled";
+                       };
+
+                       gpio1: gpio@53f84000 {
+                               compatible = "fsl,imx50-gpio", "fsl,imx35-gpio";
+                               reg = <0x53f84000 0x4000>;
+                               interrupts = <50 51>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                       };
+
+                       gpio2: gpio@53f88000 {
+                               compatible = "fsl,imx50-gpio", "fsl,imx35-gpio";
+                               reg = <0x53f88000 0x4000>;
+                               interrupts = <52 53>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                       };
+
+                       gpio3: gpio@53f8c000 {
+                               compatible = "fsl,imx50-gpio", "fsl,imx35-gpio";
+                               reg = <0x53f8c000 0x4000>;
+                               interrupts = <54 55>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                       };
+
+                       gpio4: gpio@53f90000 {
+                               compatible = "fsl,imx50-gpio", "fsl,imx35-gpio";
+                               reg = <0x53f90000 0x4000>;
+                               interrupts = <56 57>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                       };
+
+                       wdog1: wdog@53f98000 {
+                               compatible = "fsl,imx50-wdt", "fsl,imx21-wdt";
+                               reg = <0x53f98000 0x4000>;
+                               interrupts = <58>;
+                               clocks = <&clks IMX5_CLK_DUMMY>;
+                       };
+
+                       gpt: timer@53fa0000 {
+                               compatible = "fsl,imx50-gpt", "fsl,imx31-gpt";
+                               reg = <0x53fa0000 0x4000>;
+                               interrupts = <39>;
+                               clocks = <&clks IMX5_CLK_GPT_IPG_GATE>,
+                                        <&clks IMX5_CLK_GPT_HF_GATE>;
+                               clock-names = "ipg", "per";
+                       };
+
+                       iomuxc: iomuxc@53fa8000 {
+                               compatible = "fsl,imx50-iomuxc", "fsl,imx53-iomuxc";
+                               reg = <0x53fa8000 0x4000>;
+                       };
+
+                       gpr: iomuxc-gpr@53fa8000 {
+                               compatible = "fsl,imx50-iomuxc-gpr", "syscon";
+                               reg = <0x53fa8000 0xc>;
+                       };
+
+                       pwm1: pwm@53fb4000 {
+                               #pwm-cells = <2>;
+                               compatible = "fsl,imx50-pwm", "fsl,imx27-pwm";
+                               reg = <0x53fb4000 0x4000>;
+                               clocks = <&clks IMX5_CLK_PWM1_IPG_GATE>,
+                                        <&clks IMX5_CLK_PWM1_HF_GATE>;
+                               clock-names = "ipg", "per";
+                               interrupts = <61>;
+                       };
+
+                       pwm2: pwm@53fb8000 {
+                               #pwm-cells = <2>;
+                               compatible = "fsl,imx50-pwm", "fsl,imx27-pwm";
+                               reg = <0x53fb8000 0x4000>;
+                               clocks = <&clks IMX5_CLK_PWM2_IPG_GATE>,
+                                        <&clks IMX5_CLK_PWM2_HF_GATE>;
+                               clock-names = "ipg", "per";
+                               interrupts = <94>;
+                       };
+
+                       uart1: serial@53fbc000 {
+                               compatible = "fsl,imx50-uart", "fsl,imx21-uart";
+                               reg = <0x53fbc000 0x4000>;
+                               interrupts = <31>;
+                               clocks = <&clks IMX5_CLK_UART1_IPG_GATE>,
+                                        <&clks IMX5_CLK_UART1_PER_GATE>;
+                               clock-names = "ipg", "per";
+                               status = "disabled";
+                       };
+
+                       uart2: serial@53fc0000 {
+                               compatible = "fsl,imx50-uart", "fsl,imx21-uart";
+                               reg = <0x53fc0000 0x4000>;
+                               interrupts = <32>;
+                               clocks = <&clks IMX5_CLK_UART2_IPG_GATE>,
+                                        <&clks IMX5_CLK_UART2_PER_GATE>;
+                               clock-names = "ipg", "per";
+                               status = "disabled";
+                       };
+
+                       src: src@53fd0000 {
+                               compatible = "fsl,imx50-src", "fsl,imx51-src";
+                               reg = <0x53fd0000 0x4000>;
+                               #reset-cells = <1>;
+                       };
+
+                       clks: ccm@53fd4000{
+                               compatible = "fsl,imx50-ccm";
+                               reg = <0x53fd4000 0x4000>;
+                               interrupts = <0 71 0x04 0 72 0x04>;
+                               #clock-cells = <1>;
+                       };
+
+                       gpio5: gpio@53fdc000 {
+                               compatible = "fsl,imx50-gpio", "fsl,imx35-gpio";
+                               reg = <0x53fdc000 0x4000>;
+                               interrupts = <103 104>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                       };
+
+                       gpio6: gpio@53fe0000 {
+                               compatible = "fsl,imx50-gpio", "fsl,imx35-gpio";
+                               reg = <0x53fe0000 0x4000>;
+                               interrupts = <105 106>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                       };
+
+                       i2c3: i2c@53fec000 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               compatible = "fsl,imx50-i2c", "fsl,imx21-i2c";
+                               reg = <0x53fec000 0x4000>;
+                               interrupts = <64>;
+                               clocks = <&clks IMX5_CLK_I2C3_GATE>;
+                               status = "disabled";
+                       };
+
+                       uart4: serial@53ff0000 {
+                               compatible = "fsl,imx50-uart", "fsl,imx21-uart";
+                               reg = <0x53ff0000 0x4000>;
+                               interrupts = <13>;
+                               clocks = <&clks IMX5_CLK_UART4_IPG_GATE>,
+                                        <&clks IMX5_CLK_UART4_PER_GATE>;
+                               clock-names = "ipg", "per";
+                               status = "disabled";
+                       };
+               };
+
+               aips@60000000 { /* AIPS2 */
+                       compatible = "fsl,aips-bus", "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       reg = <0x60000000 0x10000000>;
+                       ranges;
+
+                       uart5: serial@63f90000 {
+                               compatible = "fsl,imx50-uart", "fsl,imx21-uart";
+                               reg = <0x63f90000 0x4000>;
+                               interrupts = <86>;
+                               clocks = <&clks IMX5_CLK_UART5_IPG_GATE>,
+                                        <&clks IMX5_CLK_UART5_PER_GATE>;
+                               clock-names = "ipg", "per";
+                               status = "disabled";
+                       };
+
+                       owire: owire@63fa4000 {
+                               compatible = "fsl,imx50-owire", "fsl,imx21-owire";
+                               reg = <0x63fa4000 0x4000>;
+                               clocks = <&clks IMX5_CLK_OWIRE_GATE>;
+                               status = "disabled";
+                       };
+
+                       ecspi2: ecspi@63fac000 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               compatible = "fsl,imx50-ecspi", "fsl,imx51-ecspi";
+                               reg = <0x63fac000 0x4000>;
+                               interrupts = <37>;
+                               clocks = <&clks IMX5_CLK_ECSPI2_IPG_GATE>,
+                                        <&clks IMX5_CLK_ECSPI2_PER_GATE>;
+                               clock-names = "ipg", "per";
+                               status = "disabled";
+                       };
+
+                       sdma: sdma@63fb0000 {
+                               compatible = "fsl,imx50-sdma", "fsl,imx35-sdma";
+                               reg = <0x63fb0000 0x4000>;
+                               interrupts = <6>;
+                               clocks = <&clks IMX5_CLK_SDMA_GATE>,
+                                        <&clks IMX5_CLK_SDMA_GATE>;
+                               clock-names = "ipg", "ahb";
+                               fsl,sdma-ram-script-name = "imx/sdma/sdma-imx50.bin";
+                       };
+
+                       cspi: cspi@63fc0000 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               compatible = "fsl,imx50-cspi", "fsl,imx35-cspi";
+                               reg = <0x63fc0000 0x4000>;
+                               interrupts = <38>;
+                               clocks = <&clks IMX5_CLK_CSPI_IPG_GATE>,
+                                        <&clks IMX5_CLK_CSPI_IPG_GATE>;
+                               clock-names = "ipg", "per";
+                               status = "disabled";
+                       };
+
+                       i2c2: i2c@63fc4000 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               compatible = "fsl,imx50-i2c", "fsl,imx21-i2c";
+                               reg = <0x63fc4000 0x4000>;
+                               interrupts = <63>;
+                               clocks = <&clks IMX5_CLK_I2C2_GATE>;
+                               status = "disabled";
+                       };
+
+                       i2c1: i2c@63fc8000 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               compatible = "fsl,imx50-i2c", "fsl,imx21-i2c";
+                               reg = <0x63fc8000 0x4000>;
+                               interrupts = <62>;
+                               clocks = <&clks IMX5_CLK_I2C1_GATE>;
+                               status = "disabled";
+                       };
+
+                       ssi1: ssi@63fcc000 {
+                               compatible = "fsl,imx50-ssi", "fsl,imx21-ssi";
+                               reg = <0x63fcc000 0x4000>;
+                               interrupts = <29>;
+                               clocks = <&clks IMX5_CLK_SSI1_IPG_GATE>;
+                               fsl,fifo-depth = <15>;
+                               fsl,ssi-dma-events = <29 28 27 26>; /* TX0 RX0 TX1 RX1 */
+                               status = "disabled";
+                       };
+
+                       audmux: audmux@63fd0000 {
+                               compatible = "fsl,imx50-audmux", "fsl,imx31-audmux";
+                               reg = <0x63fd0000 0x4000>;
+                               status = "disabled";
+                       };
+
+                       fec: ethernet@63fec000 {
+                               compatible = "fsl,imx53-fec", "fsl,imx25-fec";
+                               reg = <0x63fec000 0x4000>;
+                               interrupts = <87>;
+                               clocks = <&clks IMX5_CLK_FEC_GATE>,
+                                        <&clks IMX5_CLK_FEC_GATE>,
+                                        <&clks IMX5_CLK_FEC_GATE>;
+                               clock-names = "ipg", "ahb", "ptp";
+                               status = "disabled";
+                       };
+               };
+       };
+};
index b3606993f2e8db4e4327305f52fddec70249e9f3..80840daf83c6b714043a8e20f992b68355887993 100644 (file)
 
 &fec {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_fec_2>;
+       pinctrl-0 = <&pinctrl_fec>;
        phy-mode = "mii";
-       phy-reset-gpios = <&gpio3 0 0>;
+       phy-reset-gpios = <&gpio3 0 GPIO_ACTIVE_HIGH>;
        phy-reset-duration = <1>;
        status = "okay";
 };
 
+&iomuxc {
+       imx51-apf51 {
+               pinctrl_fec: fecgrp {
+                       fsl,pins = <MX51_FEC_PINGRP2>;
+               };
+
+               pinctrl_uart3: uart3grp {
+                       fsl,pins = <MX51_UART3_PINGRP2>;
+               };
+       };
+};
+
 &nfc {
        nand-bus-width = <8>;
        nand-ecc-mode = "hw";
@@ -50,6 +62,6 @@
 
 &uart3 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_uart3_2>;
+       pinctrl-0 = <&pinctrl_uart3>;
        status = "okay";
 };
index 5a7f552786a112dadff76c0d664fc6fb682f7ccf..f36a3aa115f87410a61803c7f86ad5e1d0336623 100644 (file)
@@ -21,7 +21,7 @@
                crtcs = <&ipu 0>;
                interface-pix-fmt = "bgr666";
                pinctrl-names = "default";
-               pinctrl-0 = <&pinctrl_ipu_disp1_1>;
+               pinctrl-0 = <&pinctrl_ipu_disp1>;
 
                display-timings {
                        lw700 {
@@ -48,7 +48,7 @@
 
                user-key {
                        label = "user";
-                       gpios = <&gpio1 3 0>;
+                       gpios = <&gpio1 3 GPIO_ACTIVE_HIGH>;
                        linux,code = <256>; /* BTN_0 */
                };
        };
@@ -58,7 +58,7 @@
 
                user {
                        label = "Heartbeat";
-                       gpios = <&gpio1 2 0>;
+                       gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
                        linux,default-trigger = "heartbeat";
                };
        };
 
 &ecspi1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_ecspi1_1>;
+       pinctrl-0 = <&pinctrl_ecspi1>;
        fsl,spi-num-chipselects = <2>;
-       cs-gpios = <&gpio4 24 0>, <&gpio4 25 0>;
+       cs-gpios = <&gpio4 24 GPIO_ACTIVE_HIGH>,
+                  <&gpio4 25 GPIO_ACTIVE_HIGH>;
        status = "okay";
 };
 
 &ecspi2 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_ecspi2_1>;
+       pinctrl-0 = <&pinctrl_ecspi2>;
        fsl,spi-num-chipselects = <2>;
-       cs-gpios = <&gpio3 28 1>, <&gpio3 27 1>;
+       cs-gpios = <&gpio3 28 GPIO_ACTIVE_LOW>,
+                  <&gpio3 27 GPIO_ACTIVE_LOW>;
        status = "okay";
 };
 
 &esdhc1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_esdhc1_1>;
-       cd-gpios = <&gpio2 29 0>;
+       pinctrl-0 = <&pinctrl_esdhc1>;
+       cd-gpios = <&gpio2 29 GPIO_ACTIVE_HIGH>;
        bus-width = <4>;
        status = "okay";
 };
 
 &esdhc2 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_esdhc2_1>;
+       pinctrl-0 = <&pinctrl_esdhc2>;
        bus-width = <4>;
        non-removable;
        status = "okay";
 
 &i2c2 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_i2c2_2>;
+       pinctrl-0 = <&pinctrl_i2c2>;
        status = "okay";
 };
 
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_hog>;
 
-       hog {
+       imx51-apf51dev {
                pinctrl_hog: hoggrp {
                        fsl,pins = <
                                MX51_PAD_EIM_EB2__GPIO2_22   0x0C5
                                MX51_PAD_GPIO1_3__GPIO1_3    0x0C5
                        >;
                };
+
+               pinctrl_ecspi1: ecspi1grp {
+                       fsl,pins = <MX51_ECSPI1_PINGRP1>;
+               };
+
+               pinctrl_ecspi2: ecspi2grp {
+                       fsl,pins = <MX51_ECSPI2_PINGRP1>;
+               };
+
+               pinctrl_esdhc1: esdhc1grp {
+                       fsl,pins = <MX51_ESDHC1_PINGRP1>;
+               };
+
+               pinctrl_esdhc2: esdhc2grp {
+                       fsl,pins = <MX51_ESDHC2_PINGRP1>;
+               };
+
+               pinctrl_i2c2: i2c2grp {
+                       fsl,pins = <MX51_I2C2_PINGRP2>;
+               };
+
+               pinctrl_ipu_disp1: ipudisp1grp {
+                       fsl,pins = <MX51_IPU_DISP1_PINGRP1>;
+               };
        };
 };
index be1407cf5abd1b1479e55fbfeac48be44dc90d4c..483178a4401795d235e2ed893a4977fc9a1dcb9a 100644 (file)
@@ -26,7 +26,7 @@
                crtcs = <&ipu 0>;
                interface-pix-fmt = "rgb24";
                pinctrl-names = "default";
-               pinctrl-0 = <&pinctrl_ipu_disp1_1>;
+               pinctrl-0 = <&pinctrl_ipu_disp1>;
                display-timings {
                        native-mode = <&timing0>;
                        timing0: dvi {
@@ -48,7 +48,7 @@
                crtcs = <&ipu 1>;
                interface-pix-fmt = "rgb565";
                pinctrl-names = "default";
-               pinctrl-0 = <&pinctrl_ipu_disp2_1>;
+               pinctrl-0 = <&pinctrl_ipu_disp2>;
                status = "disabled";
                display-timings {
                        native-mode = <&timing1>;
@@ -75,7 +75,7 @@
 
                power {
                        label = "Power Button";
-                       gpios = <&gpio2 21 0>;
+                       gpios = <&gpio2 21 GPIO_ACTIVE_HIGH>;
                        linux,code = <116>; /* KEY_POWER */
                        gpio-key,wakeup;
                };
                        reg=<0>;
                        #clock-cells = <0>;
                        clock-frequency = <26000000>;
-                       gpios = <&gpio4 26 1>;
+                       gpios = <&gpio4 26 GPIO_ACTIVE_LOW>;
                };
        };
 };
 
 &esdhc1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_esdhc1_1>;
+       pinctrl-0 = <&pinctrl_esdhc1>;
        fsl,cd-controller;
        fsl,wp-controller;
        status = "okay";
 
 &esdhc2 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_esdhc2_1>;
-       cd-gpios = <&gpio1 6 0>;
-       wp-gpios = <&gpio1 5 0>;
+       pinctrl-0 = <&pinctrl_esdhc2>;
+       cd-gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>;
+       wp-gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>;
        status = "okay";
 };
 
 &uart3 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_uart3_1 &pinctrl_uart3_rtscts_1>;
+       pinctrl-0 = <&pinctrl_uart3 &pinctrl_uart3_rtscts>;
        fsl,uart-has-rtscts;
        status = "okay";
 };
 
 &ecspi1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_ecspi1_1>;
+       pinctrl-0 = <&pinctrl_ecspi1>;
        fsl,spi-num-chipselects = <2>;
-       cs-gpios = <&gpio4 24 0>, <&gpio4 25 0>;
+       cs-gpios = <&gpio4 24 GPIO_ACTIVE_HIGH>,
+                  <&gpio4 25 GPIO_ACTIVE_LOW>;
        status = "okay";
 
        pmic: mc13892@0 {
                spi-cs-high;
                reg = <0>;
                interrupt-parent = <&gpio1>;
-               interrupts = <8 0x4>;
+               interrupts = <8 IRQ_TYPE_LEVEL_HIGH>;
 
                regulators {
                        sw1_reg: sw1 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_hog>;
 
-       hog {
+       imx51-babbage {
                pinctrl_hog: hoggrp {
                        fsl,pins = <
                                MX51_PAD_GPIO1_0__SD1_CD     0x20d5
                                MX51_PAD_CSPI1_RDY__GPIO4_26 0x80000000
                        >;
                };
+
+               pinctrl_audmux: audmuxgrp {
+                       fsl,pins = <MX51_AUDMUX_PINGRP1>;
+               };
+
+               pinctrl_ecspi1: ecspi1grp {
+                       fsl,pins = <MX51_ECSPI1_PINGRP1>;
+               };
+
+               pinctrl_esdhc1: esdhc1grp {
+                       fsl,pins = <MX51_ESDHC1_PINGRP1>;
+               };
+
+               pinctrl_esdhc2: esdhc2grp {
+                       fsl,pins = <MX51_ESDHC2_PINGRP1>;
+               };
+
+               pinctrl_fec: fecgrp {
+                       fsl,pins = <
+                               MX51_FEC_PINGRP1
+                               MX51_PAD_EIM_A20__GPIO2_14 0x85 /* Reset */
+                       >;
+               };
+
+               pinctrl_i2c2: i2c2grp {
+                       fsl,pins = <MX51_I2C2_PINGRP1>;
+               };
+
+               pinctrl_ipu_disp1: ipudisp1grp {
+                       fsl,pins = <MX51_IPU_DISP1_PINGRP1>;
+               };
+
+               pinctrl_ipu_disp2: ipudisp2grp {
+                       fsl,pins = <MX51_IPU_DISP2_PINGRP1>;
+               };
+
+               pinctrl_kpp: kppgrp {
+                       fsl,pins = <MX51_KPP_PINGRP1>;
+               };
+
+               pinctrl_uart1: uart1grp {
+                       fsl,pins = <MX51_UART1_PINGRP1>;
+               };
+
+               pinctrl_uart1_rtscts: uart1rtsctsgrp {
+                       fsl,pins = <MX51_UART1_RTSCTS_PINGRP1>;
+               };
+
+               pinctrl_uart2: uart2grp {
+                       fsl,pins = <MX51_UART2_PINGRP1>;
+               };
+
+               pinctrl_uart3: uart3grp {
+                       fsl,pins = <MX51_UART3_PINGRP1>;
+               };
+
+               pinctrl_uart3_rtscts: uart3rtsctsgrp {
+                       fsl,pins = <MX51_UART3_RTSCTS_PINGRP1>;
+               };
        };
 };
 
 &uart1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_uart1_1 &pinctrl_uart1_rtscts_1>;
+       pinctrl-0 = <&pinctrl_uart1 &pinctrl_uart1_rtscts>;
        fsl,uart-has-rtscts;
        status = "okay";
 };
 
 &uart2 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_uart2_1>;
+       pinctrl-0 = <&pinctrl_uart2>;
        status = "okay";
 };
 
 &i2c2 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_i2c2_1>;
+       pinctrl-0 = <&pinctrl_i2c2>;
        status = "okay";
 
        sgtl5000: codec@0a {
 
 &audmux {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_audmux_1>;
+       pinctrl-0 = <&pinctrl_audmux>;
        status = "okay";
 };
 
 &fec {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_fec_1>;
+       pinctrl-0 = <&pinctrl_fec>;
        phy-mode = "mii";
+       phy-reset-gpios = <&gpio2 14 GPIO_ACTIVE_LOW>;
+       phy-reset-duration = <1>;
        status = "okay";
 };
 
 &kpp {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_kpp_1>;
+       pinctrl-0 = <&pinctrl_kpp>;
        linux,keymap = <0x00000067      /* KEY_UP */
                        0x0001006c      /* KEY_DOWN */
                        0x00020072      /* KEY_VOLUMEDOWN */
diff --git a/arch/arm/boot/dts/imx51-eukrea-cpuimx51.dtsi b/arch/arm/boot/dts/imx51-eukrea-cpuimx51.dtsi
new file mode 100644 (file)
index 0000000..b22841a
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2013 Eukréa Electromatique <denis@eukrea.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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include "imx51.dtsi"
+
+/ {
+       model = "Eukrea CPUIMX51";
+       compatible = "eukrea,cpuimx51", "fsl,imx51";
+
+       memory {
+               reg = <0x90000000 0x10000000>; /* 256M */
+       };
+};
+
+&fec {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_fec>;
+       status = "okay";
+};
+
+&i2c1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c1>;
+       status = "okay";
+
+       pcf8563@51 {
+               compatible = "nxp,pcf8563";
+               reg = <0x51>;
+       };
+};
+
+&iomuxc {
+       imx51-eukrea {
+               pinctrl_tsc2007_1: tsc2007grp-1 {
+                       fsl,pins = <
+                               MX51_PAD_GPIO_NAND__GPIO_NAND 0x1f5
+                               MX51_PAD_NANDF_D8__GPIO4_0 0x1f5
+                       >;
+               };
+
+               pinctrl_fec: fecgrp {
+                       fsl,pins = <MX51_FEC_PINGRP2>;
+               };
+
+               pinctrl_i2c1: i2c1grp {
+                       fsl,pins = <MX51_I2C1_PINGRP1>;
+               };
+       };
+};
+
+&nfc {
+       nand-bus-width = <8>;
+       nand-ecc-mode = "hw";
+       nand-on-flash-bbt;
+       status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx51-eukrea-mbimxsd51-baseboard.dts b/arch/arm/boot/dts/imx51-eukrea-mbimxsd51-baseboard.dts
new file mode 100644 (file)
index 0000000..6774c66
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2013 Eukréa Electromatique <denis@eukrea.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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+/dts-v1/;
+#include "imx51-eukrea-cpuimx51.dtsi"
+
+/ {
+       model = "Eukrea CPUIMX51";
+       compatible = "eukrea,mbimxsd51","eukrea,cpuimx51", "fsl,imx51";
+
+       gpio_keys {
+               compatible = "gpio-keys";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_gpiokeys_1>;
+
+               button-1 {
+                       label = "BP1";
+                       gpios = <&gpio3 31 GPIO_ACTIVE_LOW>;
+                       linux,code = <256>;
+                       gpio-key,wakeup;
+                       linux,input-type = <1>;
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_gpioled>;
+
+               led1 {
+                       label = "led1";
+                       gpios = <&gpio3 30 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "heartbeat";
+               };
+       };
+
+       sound {
+               compatible = "eukrea,asoc-tlv320";
+               eukrea,model = "imx51-eukrea-tlv320aic23";
+               ssi-controller = <&ssi2>;
+               fsl,mux-int-port = <2>;
+               fsl,mux-ext-port = <3>;
+       };
+};
+
+&audmux {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_audmux>;
+       status = "okay";
+};
+
+&esdhc1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_esdhc1 &pinctrl_esdhc1_cd>;
+       fsl,cd-controller;
+       status = "okay";
+};
+
+&i2c1 {
+       tlv320aic23: codec@1a {
+               compatible = "ti,tlv320aic23";
+               reg = <0x1a>;
+       };
+};
+
+&iomuxc {
+       imx51-eukrea {
+               pinctrl_audmux: audmuxgrp {
+                       fsl,pins = <MX51_AUDMUX_PINGRP1>;
+               };
+
+               pinctrl_esdhc1: esdhc1grp {
+                       fsl,pins = <MX51_ESDHC1_PINGRP1>;
+               };
+
+               pinctrl_uart1: uart1grp {
+                       fsl,pins = <MX51_UART1_PINGRP1>;
+               };
+
+               pinctrl_uart3: uart3grp {
+                       fsl,pins = <MX51_UART3_PINGRP2>;
+               };
+
+               pinctrl_uart3_rtscts: uart3rtsctsgrp {
+                       fsl,pins = <MX51_UART3_RTSCTS_PINGRP2>;
+               };
+
+               pinctrl_backlight_1: backlightgrp-1 {
+                       fsl,pins = <
+                               MX51_PAD_DI1_D1_CS__GPIO3_4 0x1f5
+                       >;
+               };
+
+               pinctrl_esdhc1_cd: esdhc1_cd {
+                       fsl,pins = <
+                               MX51_PAD_GPIO1_0__SD1_CD 0x20d5
+                       >;
+               };
+
+               pinctrl_gpiokeys_1: gpiokeysgrp-1 {
+                       fsl,pins = <
+                               MX51_PAD_NANDF_D9__GPIO3_31 0x1f5
+                       >;
+               };
+
+               pinctrl_gpioled: gpioledgrp-1 {
+                       fsl,pins = <
+                               MX51_PAD_NANDF_D10__GPIO3_30 0x80000000
+                       >;
+               };
+
+               pinctrl_reg_lcd_3v3: reg_lcd_3v3 {
+                       fsl,pins = <
+                               MX51_PAD_CSI1_D9__GPIO3_13 0x1f5
+                       >;
+               };
+       };
+};
+
+&ssi2 {
+       codec-handle = <&tlv320aic23>;
+       fsl,mode = "i2s-slave";
+       status = "okay";
+};
+
+&uart1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart1>;
+       fsl,uart-has-rtscts;
+       status = "okay";
+};
+
+&uart3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart3 &pinctrl_uart3_rtscts>;
+       fsl,uart-has-rtscts;
+       status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx51-pingrp.h b/arch/arm/boot/dts/imx51-pingrp.h
new file mode 100644 (file)
index 0000000..f63267b
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 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.
+ *
+ */
+
+#ifndef __DTS_IMX51_PINGRP_H
+#define __DTS_IMX51_PINGRP_H
+
+#include "imx51-pinfunc.h"
+
+#define MX51_AUDMUX_PINGRP1 \
+       MX51_PAD_AUD3_BB_TXD__AUD3_TXD                  0x80000000 \
+       MX51_PAD_AUD3_BB_RXD__AUD3_RXD                  0x80000000 \
+       MX51_PAD_AUD3_BB_CK__AUD3_TXC                   0x80000000 \
+       MX51_PAD_AUD3_BB_FS__AUD3_TXFS                  0x80000000
+
+#define MX51_FEC_PINGRP1 \
+       MX51_PAD_EIM_EB2__FEC_MDIO                      0x80000000 \
+       MX51_PAD_EIM_EB3__FEC_RDATA1                    0x80000000 \
+       MX51_PAD_EIM_CS2__FEC_RDATA2                    0x80000000 \
+       MX51_PAD_EIM_CS3__FEC_RDATA3                    0x80000000 \
+       MX51_PAD_EIM_CS4__FEC_RX_ER                     0x80000000 \
+       MX51_PAD_EIM_CS5__FEC_CRS                       0x80000000 \
+       MX51_PAD_NANDF_RB2__FEC_COL                     0x80000000 \
+       MX51_PAD_NANDF_RB3__FEC_RX_CLK                  0x80000000 \
+       MX51_PAD_NANDF_D9__FEC_RDATA0                   0x80000000 \
+       MX51_PAD_NANDF_D8__FEC_TDATA0                   0x80000000 \
+       MX51_PAD_NANDF_CS2__FEC_TX_ER                   0x80000000 \
+       MX51_PAD_NANDF_CS3__FEC_MDC                     0x80000000 \
+       MX51_PAD_NANDF_CS4__FEC_TDATA1                  0x80000000 \
+       MX51_PAD_NANDF_CS5__FEC_TDATA2                  0x80000000 \
+       MX51_PAD_NANDF_CS6__FEC_TDATA3                  0x80000000 \
+       MX51_PAD_NANDF_CS7__FEC_TX_EN                   0x80000000 \
+       MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK              0x80000000
+
+#define MX51_FEC_PINGRP2 \
+       MX51_PAD_DI_GP3__FEC_TX_ER                      0x80000000 \
+       MX51_PAD_DI2_PIN4__FEC_CRS                      0x80000000 \
+       MX51_PAD_DI2_PIN2__FEC_MDC                      0x80000000 \
+       MX51_PAD_DI2_PIN3__FEC_MDIO                     0x80000000 \
+       MX51_PAD_DI2_DISP_CLK__FEC_RDATA1               0x80000000 \
+       MX51_PAD_DI_GP4__FEC_RDATA2                     0x80000000 \
+       MX51_PAD_DISP2_DAT0__FEC_RDATA3                 0x80000000 \
+       MX51_PAD_DISP2_DAT1__FEC_RX_ER                  0x80000000 \
+       MX51_PAD_DISP2_DAT6__FEC_TDATA1                 0x80000000 \
+       MX51_PAD_DISP2_DAT7__FEC_TDATA2                 0x80000000 \
+       MX51_PAD_DISP2_DAT8__FEC_TDATA3                 0x80000000 \
+       MX51_PAD_DISP2_DAT9__FEC_TX_EN                  0x80000000 \
+       MX51_PAD_DISP2_DAT10__FEC_COL                   0x80000000 \
+       MX51_PAD_DISP2_DAT11__FEC_RX_CLK                0x80000000 \
+       MX51_PAD_DISP2_DAT12__FEC_RX_DV                 0x80000000 \
+       MX51_PAD_DISP2_DAT13__FEC_TX_CLK                0x80000000 \
+       MX51_PAD_DISP2_DAT14__FEC_RDATA0                0x80000000 \
+       MX51_PAD_DISP2_DAT15__FEC_TDATA0                0x80000000
+
+#define MX51_ECSPI1_PINGRP1 \
+       MX51_PAD_CSPI1_MISO__ECSPI1_MISO                0x185 \
+       MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI                0x185 \
+       MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK                0x185
+
+#define MX51_ECSPI2_PINGRP1 \
+       MX51_PAD_NANDF_RB3__ECSPI2_MISO                 0x185 \
+       MX51_PAD_NANDF_D15__ECSPI2_MOSI                 0x185 \
+       MX51_PAD_NANDF_RB2__ECSPI2_SCLK                 0x185
+
+#define MX51_ESDHC1_PINGRP1 \
+       MX51_PAD_SD1_CMD__SD1_CMD                       0x400020d5 \
+       MX51_PAD_SD1_CLK__SD1_CLK                       0x20d5 \
+       MX51_PAD_SD1_DATA0__SD1_DATA0                   0x20d5 \
+       MX51_PAD_SD1_DATA1__SD1_DATA1                   0x20d5 \
+       MX51_PAD_SD1_DATA2__SD1_DATA2                   0x20d5 \
+       MX51_PAD_SD1_DATA3__SD1_DATA3                   0x20d5
+
+#define MX51_ESDHC2_PINGRP1 \
+       MX51_PAD_SD2_CMD__SD2_CMD                       0x400020d5 \
+       MX51_PAD_SD2_CLK__SD2_CLK                       0x20d5 \
+       MX51_PAD_SD2_DATA0__SD2_DATA0                   0x20d5 \
+       MX51_PAD_SD2_DATA1__SD2_DATA1                   0x20d5 \
+       MX51_PAD_SD2_DATA2__SD2_DATA2                   0x20d5 \
+       MX51_PAD_SD2_DATA3__SD2_DATA3                   0x20d5
+
+#define MX51_I2C1_PINGRP1 \
+       MX51_PAD_SD2_CMD__I2C1_SCL                      0x400001ed \
+       MX51_PAD_SD2_CLK__I2C1_SDA                      0x400001ed
+
+#define MX51_I2C2_PINGRP1 \
+       MX51_PAD_KEY_COL4__I2C2_SCL                     0x400001ed \
+       MX51_PAD_KEY_COL5__I2C2_SDA                     0x400001ed
+
+#define MX51_I2C2_PINGRP2 \
+       MX51_PAD_EIM_D27__I2C2_SCL                      0x400001ed \
+       MX51_PAD_EIM_D24__I2C2_SDA                      0x400001ed
+
+#define MX51_I2C2_PINGRP3 \
+       MX51_PAD_GPIO1_2__I2C2_SCL                      0x400001ed \
+       MX51_PAD_GPIO1_3__I2C2_SDA                      0x400001ed
+
+#define MX51_IPU_DISP1_PINGRP1 \
+       MX51_PAD_DISP1_DAT0__DISP1_DAT0                 0x5 \
+       MX51_PAD_DISP1_DAT1__DISP1_DAT1                 0x5 \
+       MX51_PAD_DISP1_DAT2__DISP1_DAT2                 0x5 \
+       MX51_PAD_DISP1_DAT3__DISP1_DAT3                 0x5 \
+       MX51_PAD_DISP1_DAT4__DISP1_DAT4                 0x5 \
+       MX51_PAD_DISP1_DAT5__DISP1_DAT5                 0x5 \
+       MX51_PAD_DISP1_DAT6__DISP1_DAT6                 0x5 \
+       MX51_PAD_DISP1_DAT7__DISP1_DAT7                 0x5 \
+       MX51_PAD_DISP1_DAT8__DISP1_DAT8                 0x5 \
+       MX51_PAD_DISP1_DAT9__DISP1_DAT9                 0x5 \
+       MX51_PAD_DISP1_DAT10__DISP1_DAT10               0x5 \
+       MX51_PAD_DISP1_DAT11__DISP1_DAT11               0x5 \
+       MX51_PAD_DISP1_DAT12__DISP1_DAT12               0x5 \
+       MX51_PAD_DISP1_DAT13__DISP1_DAT13               0x5 \
+       MX51_PAD_DISP1_DAT14__DISP1_DAT14               0x5 \
+       MX51_PAD_DISP1_DAT15__DISP1_DAT15               0x5 \
+       MX51_PAD_DISP1_DAT16__DISP1_DAT16               0x5 \
+       MX51_PAD_DISP1_DAT17__DISP1_DAT17               0x5 \
+       MX51_PAD_DISP1_DAT18__DISP1_DAT18               0x5 \
+       MX51_PAD_DISP1_DAT19__DISP1_DAT19               0x5 \
+       MX51_PAD_DISP1_DAT20__DISP1_DAT20               0x5 \
+       MX51_PAD_DISP1_DAT21__DISP1_DAT21               0x5 \
+       MX51_PAD_DISP1_DAT22__DISP1_DAT22               0x5 \
+       MX51_PAD_DISP1_DAT23__DISP1_DAT23               0x5 \
+       MX51_PAD_DI1_PIN2__DI1_PIN2                     0x5 \
+       MX51_PAD_DI1_PIN3__DI1_PIN3                     0x5
+
+#define MX51_IPU_DISP2_PINGRP1 \
+       MX51_PAD_DISP2_DAT0__DISP2_DAT0                 0x5 \
+       MX51_PAD_DISP2_DAT1__DISP2_DAT1                 0x5 \
+       MX51_PAD_DISP2_DAT2__DISP2_DAT2                 0x5 \
+       MX51_PAD_DISP2_DAT3__DISP2_DAT3                 0x5 \
+       MX51_PAD_DISP2_DAT4__DISP2_DAT4                 0x5 \
+       MX51_PAD_DISP2_DAT5__DISP2_DAT5                 0x5 \
+       MX51_PAD_DISP2_DAT6__DISP2_DAT6                 0x5 \
+       MX51_PAD_DISP2_DAT7__DISP2_DAT7                 0x5 \
+       MX51_PAD_DISP2_DAT8__DISP2_DAT8                 0x5 \
+       MX51_PAD_DISP2_DAT9__DISP2_DAT9                 0x5 \
+       MX51_PAD_DISP2_DAT10__DISP2_DAT10               0x5 \
+       MX51_PAD_DISP2_DAT11__DISP2_DAT11               0x5 \
+       MX51_PAD_DISP2_DAT12__DISP2_DAT12               0x5 \
+       MX51_PAD_DISP2_DAT13__DISP2_DAT13               0x5 \
+       MX51_PAD_DISP2_DAT14__DISP2_DAT14               0x5 \
+       MX51_PAD_DISP2_DAT15__DISP2_DAT15               0x5 \
+       MX51_PAD_DI2_PIN2__DI2_PIN2                     0x5 \
+       MX51_PAD_DI2_PIN3__DI2_PIN3                     0x5 \
+       MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK             0x5 \
+       MX51_PAD_DI_GP4__DI2_PIN15                      0x5
+
+#define MX51_KPP_PINGRP1 \
+       MX51_PAD_KEY_ROW0__KEY_ROW0                     0xe0 \
+       MX51_PAD_KEY_ROW1__KEY_ROW1                     0xe0 \
+       MX51_PAD_KEY_ROW2__KEY_ROW2                     0xe0 \
+       MX51_PAD_KEY_ROW3__KEY_ROW3                     0xe0 \
+       MX51_PAD_KEY_COL0__KEY_COL0                     0xe8 \
+       MX51_PAD_KEY_COL1__KEY_COL1                     0xe8 \
+       MX51_PAD_KEY_COL2__KEY_COL2                     0xe8 \
+       MX51_PAD_KEY_COL3__KEY_COL3                     0xe8
+
+#define MX51_PATA_PINGRP1 \
+       MX51_PAD_NANDF_WE_B__PATA_DIOW                  0x2004 \
+       MX51_PAD_NANDF_RE_B__PATA_DIOR                  0x2004 \
+       MX51_PAD_NANDF_ALE__PATA_BUFFER_EN              0x2004 \
+       MX51_PAD_NANDF_CLE__PATA_RESET_B                0x2004 \
+       MX51_PAD_NANDF_WP_B__PATA_DMACK                 0x2004 \
+       MX51_PAD_NANDF_RB0__PATA_DMARQ                  0x2004 \
+       MX51_PAD_NANDF_RB1__PATA_IORDY                  0x2004 \
+       MX51_PAD_GPIO_NAND__PATA_INTRQ                  0x2004 \
+       MX51_PAD_NANDF_CS2__PATA_CS_0                   0x2004 \
+       MX51_PAD_NANDF_CS3__PATA_CS_1                   0x2004 \
+       MX51_PAD_NANDF_CS4__PATA_DA_0                   0x2004 \
+       MX51_PAD_NANDF_CS5__PATA_DA_1                   0x2004 \
+       MX51_PAD_NANDF_CS6__PATA_DA_2                   0x2004 \
+       MX51_PAD_NANDF_D15__PATA_DATA15                 0x2004 \
+       MX51_PAD_NANDF_D14__PATA_DATA14                 0x2004 \
+       MX51_PAD_NANDF_D13__PATA_DATA13                 0x2004 \
+       MX51_PAD_NANDF_D12__PATA_DATA12                 0x2004 \
+       MX51_PAD_NANDF_D11__PATA_DATA11                 0x2004 \
+       MX51_PAD_NANDF_D10__PATA_DATA10                 0x2004 \
+       MX51_PAD_NANDF_D9__PATA_DATA9                   0x2004 \
+       MX51_PAD_NANDF_D8__PATA_DATA8                   0x2004 \
+       MX51_PAD_NANDF_D7__PATA_DATA7                   0x2004 \
+       MX51_PAD_NANDF_D6__PATA_DATA6                   0x2004 \
+       MX51_PAD_NANDF_D5__PATA_DATA5                   0x2004 \
+       MX51_PAD_NANDF_D4__PATA_DATA4                   0x2004 \
+       MX51_PAD_NANDF_D3__PATA_DATA3                   0x2004 \
+       MX51_PAD_NANDF_D2__PATA_DATA2                   0x2004 \
+       MX51_PAD_NANDF_D1__PATA_DATA1                   0x2004 \
+       MX51_PAD_NANDF_D0__PATA_DATA0                   0x2004
+
+#define MX51_UART1_PINGRP1 \
+       MX51_PAD_UART1_RXD__UART1_RXD                   0x1c5 \
+       MX51_PAD_UART1_TXD__UART1_TXD                   0x1c5
+
+#define MX51_UART1_RTSCTS_PINGRP1 \
+       MX51_PAD_UART1_RTS__UART1_RTS                   0x1c5 \
+       MX51_PAD_UART1_CTS__UART1_CTS                   0x1c5
+
+#define MX51_UART2_PINGRP1 \
+       MX51_PAD_UART2_RXD__UART2_RXD                   0x1c5 \
+       MX51_PAD_UART2_TXD__UART2_TXD                   0x1c5
+
+#define MX51_UART3_PINGRP1 \
+       MX51_PAD_EIM_D25__UART3_RXD                     0x1c5 \
+       MX51_PAD_EIM_D26__UART3_TXD                     0x1c5
+
+#define MX51_UART3_RTSCTS_PINGRP1 \
+       MX51_PAD_EIM_D27__UART3_RTS                     0x1c5 \
+       MX51_PAD_EIM_D24__UART3_CTS                     0x1c5
+
+#define MX51_UART3_PINGRP2 \
+       MX51_PAD_UART3_RXD__UART3_RXD                   0x1c5 \
+       MX51_PAD_UART3_TXD__UART3_TXD                   0x1c5
+
+#define MX51_UART3_RTSCTS_PINGRP2 \
+       MX51_PAD_KEY_COL4__UART3_RTS                    0x1c5 \
+       MX51_PAD_KEY_COL5__UART3_CTS                    0x1c5
+
+#define MX51_USBH1_PINGRP1 \
+       MX51_PAD_USBH1_DATA0__USBH1_DATA0               0x1e5 \
+       MX51_PAD_USBH1_DATA1__USBH1_DATA1               0x1e5 \
+       MX51_PAD_USBH1_DATA2__USBH1_DATA2               0x1e5 \
+       MX51_PAD_USBH1_DATA3__USBH1_DATA3               0x1e5 \
+       MX51_PAD_USBH1_DATA4__USBH1_DATA4               0x1e5 \
+       MX51_PAD_USBH1_DATA5__USBH1_DATA5               0x1e5 \
+       MX51_PAD_USBH1_DATA6__USBH1_DATA6               0x1e5 \
+       MX51_PAD_USBH1_DATA7__USBH1_DATA7               0x1e5 \
+       MX51_PAD_USBH1_CLK__USBH1_CLK                   0x1e5 \
+       MX51_PAD_USBH1_DIR__USBH1_DIR                   0x1e5 \
+       MX51_PAD_USBH1_NXT__USBH1_NXT                   0x1e5 \
+       MX51_PAD_USBH1_STP__USBH1_STP                   0x1e5
+
+#define MX51_USBH2_PINGRP1 \
+       MX51_PAD_EIM_D16__USBH2_DATA0                   0x1e5 \
+       MX51_PAD_EIM_D17__USBH2_DATA1                   0x1e5 \
+       MX51_PAD_EIM_D18__USBH2_DATA2                   0x1e5 \
+       MX51_PAD_EIM_D19__USBH2_DATA3                   0x1e5 \
+       MX51_PAD_EIM_D20__USBH2_DATA4                   0x1e5 \
+       MX51_PAD_EIM_D21__USBH2_DATA5                   0x1e5 \
+       MX51_PAD_EIM_D22__USBH2_DATA6                   0x1e5 \
+       MX51_PAD_EIM_D23__USBH2_DATA7                   0x1e5 \
+       MX51_PAD_EIM_A24__USBH2_CLK                     0x1e5 \
+       MX51_PAD_EIM_A25__USBH2_DIR                     0x1e5 \
+       MX51_PAD_EIM_A27__USBH2_NXT                     0x1e5 \
+       MX51_PAD_EIM_A26__USBH2_STP                     0x1e5
+
+#endif /* __DTS_IMX51_PINGRP_H */
index 4bcdd3ad15e524d95cb553b47fc6f61e5eef9a3a..61a2552747a322508caff97fa2d261f24b25b014 100644 (file)
  */
 
 #include "skeleton.dtsi"
-#include "imx51-pinfunc.h"
+#include "imx51-pingrp.h"
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/clock/imx5-clock.h>
+#include <dt-bindings/gpio/gpio.h>
 
 / {
        aliases {
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
-               cpu@0 {
+               cpu: cpu@0 {
                        device_type = "cpu";
                        compatible = "arm,cortex-a8";
                        reg = <0>;
-                       clock-latency = <61036>; /* two CLK32 periods */
-                       clocks = <&clks 24>;
+                       clock-latency = <62500>;
+                       clocks = <&clks IMX5_CLK_CPU_PODF>;
                        clock-names = "cpu";
                        operating-points = <
-                               /* kHz  uV (No regulator support) */
-                               160000  0
-                               800000  0
+                               166000  1000000
+                               600000  1050000
+                               800000  1100000
                        >;
+                       voltage-tolerance = <5>;
+               };
+       };
+
+       usbphy {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "simple-bus";
+
+               usbphy0: usbphy@0 {
+                       compatible = "usb-nop-xceiv";
+                       reg = <0>;
+                       clocks = <&clks IMX5_CLK_USB_PHY_GATE>;
+                       clock-names = "main_clk";
                };
        };
 
                        compatible = "fsl,imx51-ipu";
                        reg = <0x40000000 0x20000000>;
                        interrupts = <11 10>;
-                       clocks = <&clks 59>, <&clks 110>, <&clks 61>;
+                       clocks = <&clks IMX5_CLK_IPU_GATE>,
+                                <&clks IMX5_CLK_IPU_DI0_GATE>,
+                                <&clks IMX5_CLK_IPU_DI1_GATE>;
                        clock-names = "bus", "di0", "di1";
                        resets = <&src 2>;
                };
                                        compatible = "fsl,imx51-esdhc";
                                        reg = <0x70004000 0x4000>;
                                        interrupts = <1>;
-                                       clocks = <&clks 44>, <&clks 0>, <&clks 71>;
+                                       clocks = <&clks IMX5_CLK_ESDHC1_IPG_GATE>,
+                                                <&clks IMX5_CLK_DUMMY>,
+                                                <&clks IMX5_CLK_ESDHC1_PER_GATE>;
                                        clock-names = "ipg", "ahb", "per";
                                        status = "disabled";
                                };
                                        compatible = "fsl,imx51-esdhc";
                                        reg = <0x70008000 0x4000>;
                                        interrupts = <2>;
-                                       clocks = <&clks 45>, <&clks 0>, <&clks 72>;
+                                       clocks = <&clks IMX5_CLK_ESDHC2_IPG_GATE>,
+                                                <&clks IMX5_CLK_DUMMY>,
+                                                <&clks IMX5_CLK_ESDHC2_PER_GATE>;
                                        clock-names = "ipg", "ahb", "per";
                                        bus-width = <4>;
                                        status = "disabled";
                                        compatible = "fsl,imx51-uart", "fsl,imx21-uart";
                                        reg = <0x7000c000 0x4000>;
                                        interrupts = <33>;
-                                       clocks = <&clks 32>, <&clks 33>;
+                                       clocks = <&clks IMX5_CLK_UART3_IPG_GATE>,
+                                                <&clks IMX5_CLK_UART3_PER_GATE>;
                                        clock-names = "ipg", "per";
                                        status = "disabled";
                                };
                                        compatible = "fsl,imx51-ecspi";
                                        reg = <0x70010000 0x4000>;
                                        interrupts = <36>;
-                                       clocks = <&clks 51>, <&clks 52>;
+                                       clocks = <&clks IMX5_CLK_ECSPI1_IPG_GATE>,
+                                                <&clks IMX5_CLK_ECSPI1_PER_GATE>;
                                        clock-names = "ipg", "per";
                                        status = "disabled";
                                };
                                        compatible = "fsl,imx51-ssi", "fsl,imx21-ssi";
                                        reg = <0x70014000 0x4000>;
                                        interrupts = <30>;
-                                       clocks = <&clks 49>;
-                                       dmas = <&sdma 24 1 0>,
-                                              <&sdma 25 1 0>;
+                                       clocks = <&clks IMX5_CLK_SSI2_IPG_GATE>;
+                                       dmas = <&sdma 24 22 0>,
+                                              <&sdma 25 22 0>;
                                        dma-names = "rx", "tx";
                                        fsl,fifo-depth = <15>;
                                        fsl,ssi-dma-events = <25 24 23 22>; /* TX0 RX0 TX1 RX1 */
                                        compatible = "fsl,imx51-esdhc";
                                        reg = <0x70020000 0x4000>;
                                        interrupts = <3>;
-                                       clocks = <&clks 46>, <&clks 0>, <&clks 73>;
+                                       clocks = <&clks IMX5_CLK_ESDHC3_IPG_GATE>,
+                                                <&clks IMX5_CLK_DUMMY>,
+                                                <&clks IMX5_CLK_ESDHC3_PER_GATE>;
                                        clock-names = "ipg", "ahb", "per";
                                        bus-width = <4>;
                                        status = "disabled";
                                        compatible = "fsl,imx51-esdhc";
                                        reg = <0x70024000 0x4000>;
                                        interrupts = <4>;
-                                       clocks = <&clks 47>, <&clks 0>, <&clks 74>;
+                                       clocks = <&clks IMX5_CLK_ESDHC4_IPG_GATE>,
+                                                <&clks IMX5_CLK_DUMMY>,
+                                                <&clks IMX5_CLK_ESDHC4_PER_GATE>;
                                        clock-names = "ipg", "ahb", "per";
                                        bus-width = <4>;
                                        status = "disabled";
                                };
                        };
 
-                       usbphy0: usbphy@0 {
-                               compatible = "usb-nop-xceiv";
-                               clocks = <&clks 75>;
-                               clock-names = "main_clk";
-                               status = "okay";
-                       };
-
                        usbotg: usb@73f80000 {
                                compatible = "fsl,imx51-usb", "fsl,imx27-usb";
                                reg = <0x73f80000 0x0200>;
                                interrupts = <18>;
-                               clocks = <&clks 108>;
+                               clocks = <&clks IMX5_CLK_USBOH3_GATE>;
                                fsl,usbmisc = <&usbmisc 0>;
                                fsl,usbphy = <&usbphy0>;
                                status = "disabled";
                                compatible = "fsl,imx51-usb", "fsl,imx27-usb";
                                reg = <0x73f80200 0x0200>;
                                interrupts = <14>;
-                               clocks = <&clks 108>;
+                               clocks = <&clks IMX5_CLK_USBOH3_GATE>;
                                fsl,usbmisc = <&usbmisc 1>;
                                status = "disabled";
                        };
                                compatible = "fsl,imx51-usb", "fsl,imx27-usb";
                                reg = <0x73f80400 0x0200>;
                                interrupts = <16>;
-                               clocks = <&clks 108>;
+                               clocks = <&clks IMX5_CLK_USBOH3_GATE>;
                                fsl,usbmisc = <&usbmisc 2>;
                                status = "disabled";
                        };
                                compatible = "fsl,imx51-usb", "fsl,imx27-usb";
                                reg = <0x73f80600 0x0200>;
                                interrupts = <17>;
-                               clocks = <&clks 108>;
+                               clocks = <&clks IMX5_CLK_USBOH3_GATE>;
                                fsl,usbmisc = <&usbmisc 3>;
                                status = "disabled";
                        };
                                #index-cells = <1>;
                                compatible = "fsl,imx51-usbmisc";
                                reg = <0x73f80800 0x200>;
-                               clocks = <&clks 108>;
+                               clocks = <&clks IMX5_CLK_USBOH3_GATE>;
                        };
 
                        gpio1: gpio@73f84000 {
                                compatible = "fsl,imx51-kpp", "fsl,imx21-kpp";
                                reg = <0x73f94000 0x4000>;
                                interrupts = <60>;
-                               clocks = <&clks 0>;
+                               clocks = <&clks IMX5_CLK_DUMMY>;
                                status = "disabled";
                        };
 
                                compatible = "fsl,imx51-wdt", "fsl,imx21-wdt";
                                reg = <0x73f98000 0x4000>;
                                interrupts = <58>;
-                               clocks = <&clks 0>;
+                               clocks = <&clks IMX5_CLK_DUMMY>;
                        };
 
                        wdog2: wdog@73f9c000 {
                                compatible = "fsl,imx51-wdt", "fsl,imx21-wdt";
                                reg = <0x73f9c000 0x4000>;
                                interrupts = <59>;
-                               clocks = <&clks 0>;
+                               clocks = <&clks IMX5_CLK_DUMMY>;
                                status = "disabled";
                        };
 
                                compatible = "fsl,imx51-gpt", "fsl,imx31-gpt";
                                reg = <0x73fa0000 0x4000>;
                                interrupts = <39>;
-                               clocks = <&clks 36>, <&clks 41>;
+                               clocks = <&clks IMX5_CLK_GPT_IPG_GATE>,
+                                        <&clks IMX5_CLK_GPT_HF_GATE>;
                                clock-names = "ipg", "per";
                        };
 
                                #pwm-cells = <2>;
                                compatible = "fsl,imx51-pwm", "fsl,imx27-pwm";
                                reg = <0x73fb4000 0x4000>;
-                               clocks = <&clks 37>, <&clks 38>;
+                               clocks = <&clks IMX5_CLK_PWM1_IPG_GATE>,
+                                        <&clks IMX5_CLK_PWM1_HF_GATE>;
                                clock-names = "ipg", "per";
                                interrupts = <61>;
                        };
                                #pwm-cells = <2>;
                                compatible = "fsl,imx51-pwm", "fsl,imx27-pwm";
                                reg = <0x73fb8000 0x4000>;
-                               clocks = <&clks 39>, <&clks 40>;
+                               clocks = <&clks IMX5_CLK_PWM2_IPG_GATE>,
+                                        <&clks IMX5_CLK_PWM2_HF_GATE>;
                                clock-names = "ipg", "per";
                                interrupts = <94>;
                        };
                                compatible = "fsl,imx51-uart", "fsl,imx21-uart";
                                reg = <0x73fbc000 0x4000>;
                                interrupts = <31>;
-                               clocks = <&clks 28>, <&clks 29>;
+                               clocks = <&clks IMX5_CLK_UART1_IPG_GATE>,
+                                        <&clks IMX5_CLK_UART1_PER_GATE>;
                                clock-names = "ipg", "per";
                                status = "disabled";
                        };
                                compatible = "fsl,imx51-uart", "fsl,imx21-uart";
                                reg = <0x73fc0000 0x4000>;
                                interrupts = <32>;
-                               clocks = <&clks 30>, <&clks 31>;
+                               clocks = <&clks IMX5_CLK_UART2_IPG_GATE>,
+                                        <&clks IMX5_CLK_UART2_PER_GATE>;
                                clock-names = "ipg", "per";
                                status = "disabled";
                        };
                                compatible = "fsl,imx51-iim", "fsl,imx27-iim";
                                reg = <0x83f98000 0x4000>;
                                interrupts = <69>;
-                               clocks = <&clks 107>;
+                               clocks = <&clks IMX5_CLK_IIM_GATE>;
                        };
 
                        owire: owire@83fa4000 {
                                compatible = "fsl,imx51-owire", "fsl,imx21-owire";
                                reg = <0x83fa4000 0x4000>;
                                interrupts = <88>;
-                               clocks = <&clks 159>;
+                               clocks = <&clks IMX5_CLK_OWIRE_GATE>;
                                status = "disabled";
                        };
 
                                compatible = "fsl,imx51-ecspi";
                                reg = <0x83fac000 0x4000>;
                                interrupts = <37>;
-                               clocks = <&clks 53>, <&clks 54>;
+                               clocks = <&clks IMX5_CLK_ECSPI2_IPG_GATE>,
+                                        <&clks IMX5_CLK_ECSPI2_PER_GATE>;
                                clock-names = "ipg", "per";
                                status = "disabled";
                        };
                                compatible = "fsl,imx51-sdma", "fsl,imx35-sdma";
                                reg = <0x83fb0000 0x4000>;
                                interrupts = <6>;
-                               clocks = <&clks 56>, <&clks 56>;
+                               clocks = <&clks IMX5_CLK_SDMA_GATE>,
+                                        <&clks IMX5_CLK_SDMA_GATE>;
                                clock-names = "ipg", "ahb";
                                #dma-cells = <3>;
                                fsl,sdma-ram-script-name = "imx/sdma/sdma-imx51.bin";
                                compatible = "fsl,imx51-cspi", "fsl,imx35-cspi";
                                reg = <0x83fc0000 0x4000>;
                                interrupts = <38>;
-                               clocks = <&clks 55>, <&clks 55>;
+                               clocks = <&clks IMX5_CLK_CSPI_IPG_GATE>,
+                                        <&clks IMX5_CLK_CSPI_IPG_GATE>;
                                clock-names = "ipg", "per";
                                status = "disabled";
                        };
                                compatible = "fsl,imx51-i2c", "fsl,imx21-i2c";
                                reg = <0x83fc4000 0x4000>;
                                interrupts = <63>;
-                               clocks = <&clks 35>;
+                               clocks = <&clks IMX5_CLK_I2C2_GATE>;
                                status = "disabled";
                        };
 
                                compatible = "fsl,imx51-i2c", "fsl,imx21-i2c";
                                reg = <0x83fc8000 0x4000>;
                                interrupts = <62>;
-                               clocks = <&clks 34>;
+                               clocks = <&clks IMX5_CLK_I2C1_GATE>;
                                status = "disabled";
                        };
 
                                compatible = "fsl,imx51-ssi", "fsl,imx21-ssi";
                                reg = <0x83fcc000 0x4000>;
                                interrupts = <29>;
-                               clocks = <&clks 48>;
+                               clocks = <&clks IMX5_CLK_SSI1_IPG_GATE>;
                                dmas = <&sdma 28 0 0>,
                                       <&sdma 29 0 0>;
                                dma-names = "rx", "tx";
                        audmux: audmux@83fd0000 {
                                compatible = "fsl,imx51-audmux", "fsl,imx31-audmux";
                                reg = <0x83fd0000 0x4000>;
+                               clocks = <&clks IMX5_CLK_DUMMY>;
+                               clock-names = "audmux";
                                status = "disabled";
                        };
 
                                #size-cells = <1>;
                                compatible = "fsl,imx51-weim";
                                reg = <0x83fda000 0x1000>;
-                               clocks = <&clks 57>;
+                               clocks = <&clks IMX5_CLK_EMI_SLOW_GATE>;
                                ranges = <
                                        0 0 0xb0000000 0x08000000
                                        1 0 0xb8000000 0x08000000
                                compatible = "fsl,imx51-nand";
                                reg = <0x83fdb000 0x1000 0xcfff0000 0x10000>;
                                interrupts = <8>;
-                               clocks = <&clks 60>;
+                               clocks = <&clks IMX5_CLK_NFC_GATE>;
                                status = "disabled";
                        };
 
                                compatible = "fsl,imx51-pata", "fsl,imx27-pata";
                                reg = <0x83fe0000 0x4000>;
                                interrupts = <70>;
-                               clocks = <&clks 172>;
+                               clocks = <&clks IMX5_CLK_PATA_GATE>;
                                status = "disabled";
                        };
 
                                compatible = "fsl,imx51-ssi", "fsl,imx21-ssi";
                                reg = <0x83fe8000 0x4000>;
                                interrupts = <96>;
-                               clocks = <&clks 50>;
+                               clocks = <&clks IMX5_CLK_SSI3_IPG_GATE>;
                                dmas = <&sdma 46 0 0>,
                                       <&sdma 47 0 0>;
                                dma-names = "rx", "tx";
                                compatible = "fsl,imx51-fec", "fsl,imx27-fec";
                                reg = <0x83fec000 0x4000>;
                                interrupts = <87>;
-                               clocks = <&clks 42>, <&clks 42>, <&clks 42>;
+                               clocks = <&clks IMX5_CLK_FEC_GATE>,
+                                        <&clks IMX5_CLK_FEC_GATE>,
+                                        <&clks IMX5_CLK_FEC_GATE>;
                                clock-names = "ipg", "ahb", "ptp";
                                status = "disabled";
                        };
                };
        };
 };
-
-&iomuxc {
-       audmux {
-               pinctrl_audmux_1: audmuxgrp-1 {
-                       fsl,pins = <
-                               MX51_PAD_AUD3_BB_TXD__AUD3_TXD 0x80000000
-                               MX51_PAD_AUD3_BB_RXD__AUD3_RXD 0x80000000
-                               MX51_PAD_AUD3_BB_CK__AUD3_TXC  0x80000000
-                               MX51_PAD_AUD3_BB_FS__AUD3_TXFS 0x80000000
-                       >;
-               };
-       };
-
-       fec {
-               pinctrl_fec_1: fecgrp-1 {
-                       fsl,pins = <
-                               MX51_PAD_EIM_EB2__FEC_MDIO         0x80000000
-                               MX51_PAD_EIM_EB3__FEC_RDATA1       0x80000000
-                               MX51_PAD_EIM_CS2__FEC_RDATA2       0x80000000
-                               MX51_PAD_EIM_CS3__FEC_RDATA3       0x80000000
-                               MX51_PAD_EIM_CS4__FEC_RX_ER        0x80000000
-                               MX51_PAD_EIM_CS5__FEC_CRS          0x80000000
-                               MX51_PAD_NANDF_RB2__FEC_COL        0x80000000
-                               MX51_PAD_NANDF_RB3__FEC_RX_CLK     0x80000000
-                               MX51_PAD_NANDF_D9__FEC_RDATA0      0x80000000
-                               MX51_PAD_NANDF_D8__FEC_TDATA0      0x80000000
-                               MX51_PAD_NANDF_CS2__FEC_TX_ER      0x80000000
-                               MX51_PAD_NANDF_CS3__FEC_MDC        0x80000000
-                               MX51_PAD_NANDF_CS4__FEC_TDATA1     0x80000000
-                               MX51_PAD_NANDF_CS5__FEC_TDATA2     0x80000000
-                               MX51_PAD_NANDF_CS6__FEC_TDATA3     0x80000000
-                               MX51_PAD_NANDF_CS7__FEC_TX_EN      0x80000000
-                               MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK 0x80000000
-                       >;
-               };
-
-               pinctrl_fec_2: fecgrp-2 {
-                       fsl,pins = <
-                               MX51_PAD_DI_GP3__FEC_TX_ER        0x80000000
-                               MX51_PAD_DI2_PIN4__FEC_CRS        0x80000000
-                               MX51_PAD_DI2_PIN2__FEC_MDC        0x80000000
-                               MX51_PAD_DI2_PIN3__FEC_MDIO       0x80000000
-                               MX51_PAD_DI2_DISP_CLK__FEC_RDATA1 0x80000000
-                               MX51_PAD_DI_GP4__FEC_RDATA2       0x80000000
-                               MX51_PAD_DISP2_DAT0__FEC_RDATA3   0x80000000
-                               MX51_PAD_DISP2_DAT1__FEC_RX_ER    0x80000000
-                               MX51_PAD_DISP2_DAT6__FEC_TDATA1   0x80000000
-                               MX51_PAD_DISP2_DAT7__FEC_TDATA2   0x80000000
-                               MX51_PAD_DISP2_DAT8__FEC_TDATA3   0x80000000
-                               MX51_PAD_DISP2_DAT9__FEC_TX_EN    0x80000000
-                               MX51_PAD_DISP2_DAT10__FEC_COL     0x80000000
-                               MX51_PAD_DISP2_DAT11__FEC_RX_CLK  0x80000000
-                               MX51_PAD_DISP2_DAT12__FEC_RX_DV   0x80000000
-                               MX51_PAD_DISP2_DAT13__FEC_TX_CLK  0x80000000
-                               MX51_PAD_DISP2_DAT14__FEC_RDATA0  0x80000000
-                               MX51_PAD_DISP2_DAT15__FEC_TDATA0  0x80000000
-                       >;
-               };
-       };
-
-       ecspi1 {
-               pinctrl_ecspi1_1: ecspi1grp-1 {
-                       fsl,pins = <
-                               MX51_PAD_CSPI1_MISO__ECSPI1_MISO 0x185
-                               MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI 0x185
-                               MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK 0x185
-                       >;
-               };
-       };
-
-       ecspi2 {
-               pinctrl_ecspi2_1: ecspi2grp-1 {
-                       fsl,pins = <
-                               MX51_PAD_NANDF_RB3__ECSPI2_MISO 0x185
-                               MX51_PAD_NANDF_D15__ECSPI2_MOSI 0x185
-                               MX51_PAD_NANDF_RB2__ECSPI2_SCLK 0x185
-                       >;
-               };
-       };
-
-       esdhc1 {
-               pinctrl_esdhc1_1: esdhc1grp-1 {
-                       fsl,pins = <
-                               MX51_PAD_SD1_CMD__SD1_CMD     0x400020d5
-                               MX51_PAD_SD1_CLK__SD1_CLK     0x20d5
-                               MX51_PAD_SD1_DATA0__SD1_DATA0 0x20d5
-                               MX51_PAD_SD1_DATA1__SD1_DATA1 0x20d5
-                               MX51_PAD_SD1_DATA2__SD1_DATA2 0x20d5
-                               MX51_PAD_SD1_DATA3__SD1_DATA3 0x20d5
-                       >;
-               };
-       };
-
-       esdhc2 {
-               pinctrl_esdhc2_1: esdhc2grp-1 {
-                       fsl,pins = <
-                               MX51_PAD_SD2_CMD__SD2_CMD     0x400020d5
-                               MX51_PAD_SD2_CLK__SD2_CLK     0x20d5
-                               MX51_PAD_SD2_DATA0__SD2_DATA0 0x20d5
-                               MX51_PAD_SD2_DATA1__SD2_DATA1 0x20d5
-                               MX51_PAD_SD2_DATA2__SD2_DATA2 0x20d5
-                               MX51_PAD_SD2_DATA3__SD2_DATA3 0x20d5
-                       >;
-               };
-       };
-
-       i2c2 {
-               pinctrl_i2c2_1: i2c2grp-1 {
-                       fsl,pins = <
-                               MX51_PAD_KEY_COL4__I2C2_SCL 0x400001ed
-                               MX51_PAD_KEY_COL5__I2C2_SDA 0x400001ed
-                       >;
-               };
-
-               pinctrl_i2c2_2: i2c2grp-2 {
-                       fsl,pins = <
-                               MX51_PAD_EIM_D27__I2C2_SCL 0x400001ed
-                               MX51_PAD_EIM_D24__I2C2_SDA 0x400001ed
-                       >;
-               };
-
-               pinctrl_i2c2_3: i2c2grp-3 {
-                       fsl,pins = <
-                               MX51_PAD_GPIO1_2__I2C2_SCL 0x400001ed
-                               MX51_PAD_GPIO1_3__I2C2_SDA 0x400001ed
-                       >;
-               };
-       };
-
-       ipu_disp1 {
-               pinctrl_ipu_disp1_1: ipudisp1grp-1 {
-                       fsl,pins = <
-                               MX51_PAD_DISP1_DAT0__DISP1_DAT0   0x5
-                               MX51_PAD_DISP1_DAT1__DISP1_DAT1   0x5
-                               MX51_PAD_DISP1_DAT2__DISP1_DAT2   0x5
-                               MX51_PAD_DISP1_DAT3__DISP1_DAT3   0x5
-                               MX51_PAD_DISP1_DAT4__DISP1_DAT4   0x5
-                               MX51_PAD_DISP1_DAT5__DISP1_DAT5   0x5
-                               MX51_PAD_DISP1_DAT6__DISP1_DAT6   0x5
-                               MX51_PAD_DISP1_DAT7__DISP1_DAT7   0x5
-                               MX51_PAD_DISP1_DAT8__DISP1_DAT8   0x5
-                               MX51_PAD_DISP1_DAT9__DISP1_DAT9   0x5
-                               MX51_PAD_DISP1_DAT10__DISP1_DAT10 0x5
-                               MX51_PAD_DISP1_DAT11__DISP1_DAT11 0x5
-                               MX51_PAD_DISP1_DAT12__DISP1_DAT12 0x5
-                               MX51_PAD_DISP1_DAT13__DISP1_DAT13 0x5
-                               MX51_PAD_DISP1_DAT14__DISP1_DAT14 0x5
-                               MX51_PAD_DISP1_DAT15__DISP1_DAT15 0x5
-                               MX51_PAD_DISP1_DAT16__DISP1_DAT16 0x5
-                               MX51_PAD_DISP1_DAT17__DISP1_DAT17 0x5
-                               MX51_PAD_DISP1_DAT18__DISP1_DAT18 0x5
-                               MX51_PAD_DISP1_DAT19__DISP1_DAT19 0x5
-                               MX51_PAD_DISP1_DAT20__DISP1_DAT20 0x5
-                               MX51_PAD_DISP1_DAT21__DISP1_DAT21 0x5
-                               MX51_PAD_DISP1_DAT22__DISP1_DAT22 0x5
-                               MX51_PAD_DISP1_DAT23__DISP1_DAT23 0x5
-                               MX51_PAD_DI1_PIN2__DI1_PIN2       0x5 /* hsync */
-                               MX51_PAD_DI1_PIN3__DI1_PIN3       0x5 /* vsync */
-                       >;
-               };
-       };
-
-       ipu_disp2 {
-               pinctrl_ipu_disp2_1: ipudisp2grp-1 {
-                       fsl,pins = <
-                               MX51_PAD_DISP2_DAT0__DISP2_DAT0     0x5
-                               MX51_PAD_DISP2_DAT1__DISP2_DAT1     0x5
-                               MX51_PAD_DISP2_DAT2__DISP2_DAT2     0x5
-                               MX51_PAD_DISP2_DAT3__DISP2_DAT3     0x5
-                               MX51_PAD_DISP2_DAT4__DISP2_DAT4     0x5
-                               MX51_PAD_DISP2_DAT5__DISP2_DAT5     0x5
-                               MX51_PAD_DISP2_DAT6__DISP2_DAT6     0x5
-                               MX51_PAD_DISP2_DAT7__DISP2_DAT7     0x5
-                               MX51_PAD_DISP2_DAT8__DISP2_DAT8     0x5
-                               MX51_PAD_DISP2_DAT9__DISP2_DAT9     0x5
-                               MX51_PAD_DISP2_DAT10__DISP2_DAT10   0x5
-                               MX51_PAD_DISP2_DAT11__DISP2_DAT11   0x5
-                               MX51_PAD_DISP2_DAT12__DISP2_DAT12   0x5
-                               MX51_PAD_DISP2_DAT13__DISP2_DAT13   0x5
-                               MX51_PAD_DISP2_DAT14__DISP2_DAT14   0x5
-                               MX51_PAD_DISP2_DAT15__DISP2_DAT15   0x5
-                               MX51_PAD_DI2_PIN2__DI2_PIN2         0x5 /* hsync */
-                               MX51_PAD_DI2_PIN3__DI2_PIN3         0x5 /* vsync */
-                               MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK 0x5 /* CLK */
-                               MX51_PAD_DI_GP4__DI2_PIN15          0x5 /* DE */
-                       >;
-               };
-       };
-
-       kpp {
-               pinctrl_kpp_1: kppgrp-1 {
-                       fsl,pins = <
-                               MX51_PAD_KEY_ROW0__KEY_ROW0 0xe0
-                               MX51_PAD_KEY_ROW1__KEY_ROW1 0xe0
-                               MX51_PAD_KEY_ROW2__KEY_ROW2 0xe0
-                               MX51_PAD_KEY_ROW3__KEY_ROW3 0xe0
-                               MX51_PAD_KEY_COL0__KEY_COL0 0xe8
-                               MX51_PAD_KEY_COL1__KEY_COL1 0xe8
-                               MX51_PAD_KEY_COL2__KEY_COL2 0xe8
-                               MX51_PAD_KEY_COL3__KEY_COL3 0xe8
-                       >;
-               };
-       };
-
-       pata {
-               pinctrl_pata_1: patagrp-1 {
-                       fsl,pins = <
-                               MX51_PAD_NANDF_WE_B__PATA_DIOW     0x2004
-                               MX51_PAD_NANDF_RE_B__PATA_DIOR     0x2004
-                               MX51_PAD_NANDF_ALE__PATA_BUFFER_EN 0x2004
-                               MX51_PAD_NANDF_CLE__PATA_RESET_B   0x2004
-                               MX51_PAD_NANDF_WP_B__PATA_DMACK    0x2004
-                               MX51_PAD_NANDF_RB0__PATA_DMARQ     0x2004
-                               MX51_PAD_NANDF_RB1__PATA_IORDY     0x2004
-                               MX51_PAD_GPIO_NAND__PATA_INTRQ     0x2004
-                               MX51_PAD_NANDF_CS2__PATA_CS_0      0x2004
-                               MX51_PAD_NANDF_CS3__PATA_CS_1      0x2004
-                               MX51_PAD_NANDF_CS4__PATA_DA_0      0x2004
-                               MX51_PAD_NANDF_CS5__PATA_DA_1      0x2004
-                               MX51_PAD_NANDF_CS6__PATA_DA_2      0x2004
-                               MX51_PAD_NANDF_D15__PATA_DATA15    0x2004
-                               MX51_PAD_NANDF_D14__PATA_DATA14    0x2004
-                               MX51_PAD_NANDF_D13__PATA_DATA13    0x2004
-                               MX51_PAD_NANDF_D12__PATA_DATA12    0x2004
-                               MX51_PAD_NANDF_D11__PATA_DATA11    0x2004
-                               MX51_PAD_NANDF_D10__PATA_DATA10    0x2004
-                               MX51_PAD_NANDF_D9__PATA_DATA9      0x2004
-                               MX51_PAD_NANDF_D8__PATA_DATA8      0x2004
-                               MX51_PAD_NANDF_D7__PATA_DATA7      0x2004
-                               MX51_PAD_NANDF_D6__PATA_DATA6     0x2004
-                               MX51_PAD_NANDF_D5__PATA_DATA5     0x2004
-                               MX51_PAD_NANDF_D4__PATA_DATA4     0x2004
-                               MX51_PAD_NANDF_D3__PATA_DATA3     0x2004
-                               MX51_PAD_NANDF_D2__PATA_DATA2     0x2004
-                               MX51_PAD_NANDF_D1__PATA_DATA1     0x2004
-                               MX51_PAD_NANDF_D0__PATA_DATA0     0x2004
-                       >;
-               };
-       };
-
-       uart1 {
-               pinctrl_uart1_1: uart1grp-1 {
-                       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
-                       >;
-               };
-       };
-
-       uart2 {
-               pinctrl_uart2_1: uart2grp-1 {
-                       fsl,pins = <
-                               MX51_PAD_UART2_RXD__UART2_RXD 0x1c5
-                               MX51_PAD_UART2_TXD__UART2_TXD 0x1c5
-                       >;
-               };
-       };
-
-       uart3 {
-               pinctrl_uart3_1: uart3grp-1 {
-                       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
-                       >;
-               };
-
-               pinctrl_uart3_2: uart3grp-2 {
-                       fsl,pins = <
-                               MX51_PAD_UART3_RXD__UART3_RXD 0x1c5
-                               MX51_PAD_UART3_TXD__UART3_TXD 0x1c5
-                       >;
-               };
-       };
-
-       usbh1 {
-               pinctrl_usbh1_1: usbh1grp-1 {
-                       fsl,pins = <
-                               MX51_PAD_USBH1_DATA0__USBH1_DATA0 0x1e5
-                               MX51_PAD_USBH1_DATA1__USBH1_DATA1 0x1e5
-                               MX51_PAD_USBH1_DATA2__USBH1_DATA2 0x1e5
-                               MX51_PAD_USBH1_DATA3__USBH1_DATA3 0x1e5
-                               MX51_PAD_USBH1_DATA4__USBH1_DATA4 0x1e5
-                               MX51_PAD_USBH1_DATA5__USBH1_DATA5 0x1e5
-                               MX51_PAD_USBH1_DATA6__USBH1_DATA6 0x1e5
-                               MX51_PAD_USBH1_DATA7__USBH1_DATA7 0x1e5
-                               MX51_PAD_USBH1_CLK__USBH1_CLK     0x1e5
-                               MX51_PAD_USBH1_DIR__USBH1_DIR     0x1e5
-                               MX51_PAD_USBH1_NXT__USBH1_NXT     0x1e5
-                               MX51_PAD_USBH1_STP__USBH1_STP     0x1e5
-                       >;
-               };
-       };
-
-       usbh2 {
-               pinctrl_usbh2_1: usbh2grp-1 {
-                       fsl,pins = <
-                               MX51_PAD_EIM_D16__USBH2_DATA0 0x1e5
-                               MX51_PAD_EIM_D17__USBH2_DATA1 0x1e5
-                               MX51_PAD_EIM_D18__USBH2_DATA2 0x1e5
-                               MX51_PAD_EIM_D19__USBH2_DATA3 0x1e5
-                               MX51_PAD_EIM_D20__USBH2_DATA4 0x1e5
-                               MX51_PAD_EIM_D21__USBH2_DATA5 0x1e5
-                               MX51_PAD_EIM_D22__USBH2_DATA6 0x1e5
-                               MX51_PAD_EIM_D23__USBH2_DATA7 0x1e5
-                               MX51_PAD_EIM_A24__USBH2_CLK   0x1e5
-                               MX51_PAD_EIM_A25__USBH2_DIR   0x1e5
-                               MX51_PAD_EIM_A27__USBH2_NXT   0x1e5
-                               MX51_PAD_EIM_A26__USBH2_STP   0x1e5
-                       >;
-               };
-       };
-};
index 174f86938c89c6917b0eccfa13b799cb9c8917ec..2bd97c3783a9f2ec36d96232ce02eaa7895a80ee 100644 (file)
 
        regulators {
                compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
 
-               reg_3p3v: 3p3v {
+               reg_3p3v: regulator@0 {
                        compatible = "regulator-fixed";
+                       reg = <0>;
                        regulator-name = "3P3V";
                        regulator-min-microvolt = <3300000>;
                        regulator-max-microvolt = <3300000>;
 
 &esdhc1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_esdhc1_2>;
+       pinctrl-0 = <&pinctrl_esdhc1>;
        cd-gpios = <&gpio1 1 0>;
        wp-gpios = <&gpio1 9 0>;
        status = "okay";
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_hog>;
 
-       hog {
+       imx53-ard {
                pinctrl_hog: hoggrp {
                        fsl,pins = <
                                MX53_PAD_GPIO_1__GPIO1_1             0x80000000
                                MX53_PAD_EIM_CS1__EMI_WEIM_CS_1      0x80000000
                        >;
                };
+
+               pinctrl_esdhc1: esdhc1grp {
+                       fsl,pins = <MX53_ESDHC1_PINGRP2>;
+               };
+
+               pinctrl_uart1: uart1grp {
+                       fsl,pins = <MX53_UART1_PINGRP2>;
+               };
        };
 };
 
 &uart1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_uart1_2>;
+       pinctrl-0 = <&pinctrl_uart1>;
        status = "okay";
 };
index 801fda728ed68528049d08a5f860e5d428121db1..214ac2e1802a779373607aabd04ac765fce4d610 100644 (file)
@@ -34,7 +34,7 @@
 
 &esdhc1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_esdhc1_1>;
+       pinctrl-0 = <&pinctrl_esdhc1>;
        cd-gpios = <&gpio3 13 0>;
        wp-gpios = <&gpio3 14 0>;
        status = "okay";
@@ -42,7 +42,7 @@
 
 &ecspi1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_ecspi1_1>;
+       pinctrl-0 = <&pinctrl_ecspi1>;
        fsl,spi-num-chipselects = <2>;
        cs-gpios = <&gpio2 30 0>, <&gpio3 19 0>;
        status = "okay";
@@ -69,7 +69,7 @@
 
 &esdhc3 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_esdhc3_1>;
+       pinctrl-0 = <&pinctrl_esdhc3>;
        cd-gpios = <&gpio3 11 0>;
        wp-gpios = <&gpio3 12 0>;
        status = "okay";
@@ -79,7 +79,7 @@
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_hog>;
 
-       hog {
+       imx53-evk {
                pinctrl_hog: hoggrp {
                        fsl,pins = <
                                MX53_PAD_EIM_EB2__GPIO2_30  0x80000000
                                MX53_PAD_PATA_DA_1__GPIO7_7 0x80000000
                        >;
                };
+
+               pinctrl_ecspi1: ecspi1grp {
+                       fsl,pins = <MX53_ECSPI1_PINGRP1>;
+               };
+
+               pinctrl_esdhc1: esdhc1grp {
+                       fsl,pins = <MX53_ESDHC1_PINGRP1>;
+               };
+
+               pinctrl_esdhc3: esdhc3grp {
+                       fsl,pins = <MX53_ESDHC3_PINGRP1>;
+               };
+
+               pinctrl_fec: fecgrp {
+                       fsl,pins = <MX53_FEC_PINGRP1>;
+               };
+
+               pinctrl_i2c2: i2c2grp {
+                       fsl,pins = <MX53_I2C2_PINGRP1>;
+               };
+
+               pinctrl_uart1: uart1grp {
+                       fsl,pins = <MX53_UART1_PINGRP1>;
+               };
        };
 };
 
 &uart1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_uart1_1>;
+       pinctrl-0 = <&pinctrl_uart1>;
        status = "okay";
 };
 
 &i2c2 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_i2c2_1>;
+       pinctrl-0 = <&pinctrl_i2c2>;
        status = "okay";
 
        pmic: mc13892@08 {
 
 &fec {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_fec_1>;
+       pinctrl-0 = <&pinctrl_fec>;
        phy-mode = "rmii";
        phy-reset-gpios = <&gpio7 6 0>;
        status = "okay";
index 7d304d02ed384e744c4789e3329ccdd80e103ac6..c623774ba3864fd3558c2f67bc2657784c33d144 100644 (file)
@@ -26,7 +26,7 @@
                        crtcs = <&ipu 1>;
                        interface-pix-fmt = "bgr666";
                        pinctrl-names = "default";
-                       pinctrl-0 = <&pinctrl_ipu_disp2_1>;
+                       pinctrl-0 = <&pinctrl_ipu_disp1>;
 
                        display-timings {
                                800x480p60 {
@@ -51,6 +51,7 @@
                pwms = <&pwm1 0 3000>;
                brightness-levels = <0 4 8 16 32 64 128 255>;
                default-brightness-level = <6>;
+               power-supply = <&reg_backlight>;
        };
 
        leds {
 
        regulators {
                compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
 
-               reg_3p2v: 3p2v {
+               reg_3p2v: regulator@0 {
                        compatible = "regulator-fixed";
+                       reg = <0>;
                        regulator-name = "3P2V";
                        regulator-min-microvolt = <3200000>;
                        regulator-max-microvolt = <3200000>;
                        regulator-always-on;
                };
+
+
+               reg_backlight: regulator@1 {
+                       compatible = "regulator-fixed";
+                       reg = <1>;
+                       regulator-name = "lcd-supply";
+                       regulator-min-microvolt = <3200000>;
+                       regulator-max-microvolt = <3200000>;
+                       regulator-always-on;
+               };
+
+               reg_usbh1_vbus: regulator@3 {
+                       compatible = "regulator-fixed";
+                       reg = <3>;
+                       regulator-name = "vbus";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       gpio = <&gpio1 2 0>;
+                       enable-active-low;
+               };
        };
 
        sound {
 
 &audmux {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_audmux_2>;
+       pinctrl-0 = <&pinctrl_audmux>;
        status = "okay";
 };
 
 &can1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_can1_3>;
+       pinctrl-0 = <&pinctrl_can1>;
        status = "okay";
 };
 
 &can2 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_can2_1>;
+       pinctrl-0 = <&pinctrl_can2>;
        status = "okay";
 };
 
 &esdhc1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_esdhc1_1>;
+       pinctrl-0 = <&pinctrl_esdhc1>;
        cd-gpios = <&gpio1 1 0>;
        wp-gpios = <&gpio1 9 0>;
        status = "okay";
 
 &fec {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_fec_1>;
+       pinctrl-0 = <&pinctrl_fec>;
        phy-mode = "rmii";
        status = "okay";
 };
 
 &i2c1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_i2c1_2>;
+       pinctrl-0 = <&pinctrl_i2c1>;
        status = "okay";
 
        sgtl5000: codec@0a {
                reg = <0x0a>;
                VDDA-supply = <&reg_3p2v>;
                VDDIO-supply = <&reg_3p2v>;
-               clocks = <&clks 150>;
+               clocks = <&clks IMX5_CLK_SSI_EXT1_GATE>;
        };
 };
 
 &i2c2 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_i2c2_2>;
+       pinctrl-0 = <&pinctrl_i2c2>;
        clock-frequency = <400000>;
        status = "okay";
 
 
 &i2c3 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_i2c3_1>;
+       pinctrl-0 = <&pinctrl_i2c3>;
        status = "okay";
 };
 
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_hog>;
 
-       hog {
+       imx53-m53evk {
                pinctrl_hog: hoggrp {
                        fsl,pins = <
                                MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK       0x80000000
                                MX53_PAD_EIM_EB3__GPIO2_31              0x80000000
                                MX53_PAD_PATA_DA_0__GPIO7_6             0x80000000
-                               MX53_PAD_DISP0_DAT8__PWM1_PWMO          0x5
-
+                               MX53_PAD_GPIO_2__GPIO1_2                0x80000000
+                               MX53_PAD_GPIO_3__USBOH3_USBH1_OC        0x80000000
                        >;
                };
 
                                MX53_PAD_PATA_DATA9__GPIO2_9            0x80000000
                        >;
                };
+
+               pinctrl_audmux: audmuxgrp {
+                       fsl,pins = <MX53_AUDMUX_PINGRP2>;
+               };
+
+               pinctrl_can1: can1grp {
+                       fsl,pins = <MX53_CAN1_PINGRP3>;
+               };
+
+               pinctrl_can2: can2grp {
+                       fsl,pins = <MX53_CAN2_PINGRP1>;
+               };
+
+               pinctrl_esdhc1: esdhc1grp {
+                       fsl,pins = <MX53_ESDHC1_PINGRP1>;
+               };
+
+               pinctrl_fec: fecgrp {
+                       fsl,pins = <MX53_FEC_PINGRP1>;
+               };
+
+               pinctrl_i2c1: i2c1grp {
+                       fsl,pins = <MX53_I2C1_PINGRP2>;
+               };
+
+               pinctrl_i2c2: i2c2grp {
+                       fsl,pins = <MX53_I2C2_PINGRP2>;
+               };
+
+               pinctrl_i2c3: i2c3grp {
+                       fsl,pins = <MX53_I2C3_PINGRP1>;
+               };
+
+               pinctrl_ipu_disp1: ipudisp1grp {
+                       fsl,pins = <MX53_IPU_DISP1_PINGRP1>;
+               };
+
+               pinctrl_nand: nandgrp {
+                       fsl,pins = <MX53_NAND_PINGRP1>;
+               };
+
+               pinctrl_pwm1: pwm1grp {
+                       fsl,pins = <MX53_PWM1_PINGRP1>;
+               };
+
+               pinctrl_uart1: uart1grp {
+                       fsl,pins = <MX53_UART1_PINGRP2>;
+               };
+
+               pinctrl_uart2: uart2grp {
+                       fsl,pins = <MX53_UART2_PINGRP1>;
+               };
+
+               pinctrl_uart3: uart3grp {
+                       fsl,pins = <MX53_UART3_PINGRP1>;
+               };
        };
 };
 
 &nfc {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_nand_1>;
+       pinctrl-0 = <&pinctrl_nand>;
        nand-bus-width = <8>;
        nand-ecc-mode = "hw";
        status = "okay";
 
 &pwm1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_pwm1_1>;
+       pinctrl-0 = <&pinctrl_pwm1>;
+       status = "okay";
+};
+
+&sata {
        status = "okay";
 };
 
 
 &uart1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_uart1_2>;
+       pinctrl-0 = <&pinctrl_uart1>;
        status = "okay";
 };
 
 &uart2 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_uart2_1>;
+       pinctrl-0 = <&pinctrl_uart2>;
        status = "okay";
 };
 
 &uart3 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_uart3_1>;
+       pinctrl-0 = <&pinctrl_uart3>;
+       status = "okay";
+};
+
+&usbh1 {
+       vbus-supply = <&reg_usbh1_vbus>;
+       phy_type = "utmi";
+       status = "okay";
+};
+
+&usbotg {
+       dr_mode = "peripheral";
        status = "okay";
 };
index a630902679410f9a4f356ab430a3199bf3ac852b..0358366c5a175ec4d9a955d29820c88bebe6c8d5 100644 (file)
        model = "TQ MBa53 starter kit";
        compatible = "tq,mba53", "tq,tqma53", "fsl,imx53";
 
-       reg_backlight: fixed@0 {
-               compatible = "regulator-fixed";
-               regulator-name = "lcd-supply";
-               gpio = <&gpio2 5 0>;
-               startup-delay-us = <5000>;
-               enable-active-low;
-       };
-
        backlight {
                compatible = "pwm-backlight";
                pwms = <&pwm2 0 50000>;
                status = "disabled";
        };
 
-       reg_3p2v: 3p2v {
-               compatible = "regulator-fixed";
-               regulator-name = "3P2V";
-               regulator-min-microvolt = <3200000>;
-               regulator-max-microvolt = <3200000>;
-               regulator-always-on;
+       regulators {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               reg_backlight: regulator@0 {
+                       compatible = "regulator-fixed";
+                       reg = <0>;
+                       regulator-name = "lcd-supply";
+                       gpio = <&gpio2 5 0>;
+                       startup-delay-us = <5000>;
+                       enable-active-low;
+               };
+
+               reg_3p2v: regulator@1 {
+                       compatible = "regulator-fixed";
+                       reg = <1>;
+                       regulator-name = "3P2V";
+                       regulator-min-microvolt = <3200000>;
+                       regulator-max-microvolt = <3200000>;
+                       regulator-always-on;
+               };
        };
 
        sound {
 &audmux {
        status = "okay";
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_audmux_1>;
+       pinctrl-0 = <&pinctrl_audmux>;
 };
 
 &i2c2 {
        codec: sgtl5000@a {
                compatible = "fsl,sgtl5000";
                reg = <0x0a>;
-               clocks = <&clks 150>;
+               clocks = <&clks IMX5_CLK_SSI_EXT1_GATE>;
                VDDA-supply = <&reg_3p2v>;
                VDDIO-supply = <&reg_3p2v>;
        };
diff --git a/arch/arm/boot/dts/imx53-pingrp.h b/arch/arm/boot/dts/imx53-pingrp.h
new file mode 100644 (file)
index 0000000..ac8e73d
--- /dev/null
@@ -0,0 +1,352 @@
+/*
+ * Copyright (C) 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.
+ *
+ */
+
+#ifndef __DTS_IMX53_PINGRP_H
+#define __DTS_IMX53_PINGRP_H
+
+#include "imx53-pinfunc.h"
+
+#define MX53_AUDMUX_PINGRP1 \
+       MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC              0x80000000 \
+       MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD              0x80000000 \
+       MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS             0x80000000 \
+       MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD              0x80000000
+
+#define MX53_AUDMUX_PINGRP2 \
+       MX53_PAD_SD2_DATA3__AUDMUX_AUD4_TXC             0x80000000 \
+       MX53_PAD_SD2_DATA2__AUDMUX_AUD4_TXD             0x80000000 \
+       MX53_PAD_SD2_DATA1__AUDMUX_AUD4_TXFS            0x80000000 \
+       MX53_PAD_SD2_DATA0__AUDMUX_AUD4_RXD             0x80000000
+
+#define MX53_AUDMUX_PINGRP3 \
+       MX53_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC             0x80000000 \
+       MX53_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD             0x80000000 \
+       MX53_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS            0x80000000 \
+       MX53_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD             0x80000000
+
+#define MX53_CAN1_PINGRP1 \
+       MX53_PAD_PATA_INTRQ__CAN1_TXCAN                 0x80000000 \
+       MX53_PAD_PATA_DIOR__CAN1_RXCAN                  0x80000000
+
+#define MX53_CAN1_PINGRP2 \
+       MX53_PAD_KEY_COL2__CAN1_TXCAN                   0x80000000 \
+       MX53_PAD_KEY_ROW2__CAN1_RXCAN                   0x80000000
+
+#define MX53_CAN1_PINGRP3 \
+       MX53_PAD_GPIO_7__CAN1_TXCAN                     0x80000000 \
+       MX53_PAD_GPIO_8__CAN1_RXCAN                     0x80000000
+
+#define MX53_CAN2_PINGRP1 \
+       MX53_PAD_KEY_COL4__CAN2_TXCAN                   0x80000000 \
+       MX53_PAD_KEY_ROW4__CAN2_RXCAN                   0x80000000
+
+
+#define MX53_CSI_PINGRP1 \
+       MX53_PAD_CSI0_DATA_EN__IPU_CSI0_DATA_EN         0x1d5 \
+       MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC             0x1d5 \
+       MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC              0x1d5 \
+       MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK           0x1d5 \
+       MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19              0x1d5 \
+       MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18              0x1d5 \
+       MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17              0x1d5 \
+       MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16              0x1d5 \
+       MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15              0x1d5 \
+       MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14              0x1d5 \
+       MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13              0x1d5 \
+       MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12              0x1d5 \
+       MX53_PAD_CSI0_DAT11__IPU_CSI0_D_11              0x1d5 \
+       MX53_PAD_CSI0_DAT10__IPU_CSI0_D_10              0x1d5 \
+       MX53_PAD_CSI0_DAT9__IPU_CSI0_D_9                0x1d5 \
+       MX53_PAD_CSI0_DAT8__IPU_CSI0_D_8                0x1d5 \
+       MX53_PAD_CSI0_DAT7__IPU_CSI0_D_7                0x1d5 \
+       MX53_PAD_CSI0_DAT6__IPU_CSI0_D_6                0x1d5 \
+       MX53_PAD_CSI0_DAT5__IPU_CSI0_D_5                0x1d5 \
+       MX53_PAD_CSI0_DAT4__IPU_CSI0_D_4                0x1d5 \
+       MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK           0x1d5
+
+#define MX53_CSI_PINGRP2 \
+       MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC             0x1d5 \
+       MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC              0x1d5 \
+       MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK           0x1d5 \
+       MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19              0x1d5 \
+       MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18              0x1d5 \
+       MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17              0x1d5 \
+       MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16              0x1d5 \
+       MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15              0x1d5 \
+       MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14              0x1d5 \
+       MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13              0x1d5 \
+       MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12              0x1d5
+
+#define MX53_CSPI_PINGRP1 \
+       MX53_PAD_SD1_DATA0__CSPI_MISO                   0x1d5 \
+       MX53_PAD_SD1_CMD__CSPI_MOSI                     0x1d5 \
+       MX53_PAD_SD1_CLK__CSPI_SCLK                     0x1d5
+
+#define MX53_CSPI_PINGRP2 \
+       MX53_PAD_EIM_D22__CSPI_MISO                     0x1d5 \
+       MX53_PAD_EIM_D28__CSPI_MOSI                     0x1d5 \
+       MX53_PAD_EIM_D21__CSPI_SCLK                     0x1d5
+
+#define MX53_ECSPI1_PINGRP1 \
+       MX53_PAD_EIM_D16__ECSPI1_SCLK                   0x80000000 \
+       MX53_PAD_EIM_D17__ECSPI1_MISO                   0x80000000 \
+       MX53_PAD_EIM_D18__ECSPI1_MOSI                   0x80000000
+
+#define MX53_ECSPI1_PINGRP2 \
+       MX53_PAD_GPIO_19__ECSPI1_RDY                    0x80000000 \
+       MX53_PAD_EIM_EB2__ECSPI1_SS0                    0x80000000 \
+       MX53_PAD_EIM_D16__ECSPI1_SCLK                   0x80000000 \
+       MX53_PAD_EIM_D17__ECSPI1_MISO                   0x80000000 \
+       MX53_PAD_EIM_D18__ECSPI1_MOSI                   0x80000000 \
+       MX53_PAD_EIM_D19__ECSPI1_SS1                    0x80000000
+
+#define MX53_ECSPI2_PINGRP1 \
+       MX53_PAD_EIM_OE__ECSPI2_MISO                    0x80000000 \
+       MX53_PAD_EIM_CS1__ECSPI2_MOSI                   0x80000000 \
+       MX53_PAD_EIM_CS0__ECSPI2_SCLK                   0x80000000
+
+#define MX53_ESDHC1_PINGRP1 \
+       MX53_PAD_SD1_DATA0__ESDHC1_DAT0                 0x1d5 \
+       MX53_PAD_SD1_DATA1__ESDHC1_DAT1                 0x1d5 \
+       MX53_PAD_SD1_DATA2__ESDHC1_DAT2                 0x1d5 \
+       MX53_PAD_SD1_DATA3__ESDHC1_DAT3                 0x1d5 \
+       MX53_PAD_SD1_CMD__ESDHC1_CMD                    0x1d5 \
+       MX53_PAD_SD1_CLK__ESDHC1_CLK                    0x1d5
+
+#define MX53_ESDHC1_PINGRP2 \
+       MX53_PAD_SD1_DATA0__ESDHC1_DAT0                 0x1d5 \
+       MX53_PAD_SD1_DATA1__ESDHC1_DAT1                 0x1d5 \
+       MX53_PAD_SD1_DATA2__ESDHC1_DAT2                 0x1d5 \
+       MX53_PAD_SD1_DATA3__ESDHC1_DAT3                 0x1d5 \
+       MX53_PAD_PATA_DATA8__ESDHC1_DAT4                0x1d5 \
+       MX53_PAD_PATA_DATA9__ESDHC1_DAT5                0x1d5 \
+       MX53_PAD_PATA_DATA10__ESDHC1_DAT6               0x1d5 \
+       MX53_PAD_PATA_DATA11__ESDHC1_DAT7               0x1d5 \
+       MX53_PAD_SD1_CMD__ESDHC1_CMD                    0x1d5 \
+       MX53_PAD_SD1_CLK__ESDHC1_CLK                    0x1d5
+
+#define MX53_ESDHC2_PINGRP1 \
+       MX53_PAD_SD2_CMD__ESDHC2_CMD                    0x1d5 \
+       MX53_PAD_SD2_CLK__ESDHC2_CLK                    0x1d5 \
+       MX53_PAD_SD2_DATA0__ESDHC2_DAT0                 0x1d5 \
+       MX53_PAD_SD2_DATA1__ESDHC2_DAT1                 0x1d5 \
+       MX53_PAD_SD2_DATA2__ESDHC2_DAT2                 0x1d5 \
+       MX53_PAD_SD2_DATA3__ESDHC2_DAT3                 0x1d5
+
+#define MX53_ESDHC3_PINGRP1 \
+       MX53_PAD_PATA_DATA8__ESDHC3_DAT0                0x1d5 \
+       MX53_PAD_PATA_DATA9__ESDHC3_DAT1                0x1d5 \
+       MX53_PAD_PATA_DATA10__ESDHC3_DAT2               0x1d5 \
+       MX53_PAD_PATA_DATA11__ESDHC3_DAT3               0x1d5 \
+       MX53_PAD_PATA_DATA0__ESDHC3_DAT4                0x1d5 \
+       MX53_PAD_PATA_DATA1__ESDHC3_DAT5                0x1d5 \
+       MX53_PAD_PATA_DATA2__ESDHC3_DAT6                0x1d5 \
+       MX53_PAD_PATA_DATA3__ESDHC3_DAT7                0x1d5 \
+       MX53_PAD_PATA_RESET_B__ESDHC3_CMD               0x1d5 \
+       MX53_PAD_PATA_IORDY__ESDHC3_CLK                 0x1d5
+
+#define MX53_FEC_PINGRP1 \
+       MX53_PAD_FEC_MDC__FEC_MDC                       0x80000000 \
+       MX53_PAD_FEC_MDIO__FEC_MDIO                     0x80000000 \
+       MX53_PAD_FEC_REF_CLK__FEC_TX_CLK                0x80000000 \
+       MX53_PAD_FEC_RX_ER__FEC_RX_ER                   0x80000000 \
+       MX53_PAD_FEC_CRS_DV__FEC_RX_DV                  0x80000000 \
+       MX53_PAD_FEC_RXD1__FEC_RDATA_1                  0x80000000 \
+       MX53_PAD_FEC_RXD0__FEC_RDATA_0                  0x80000000 \
+       MX53_PAD_FEC_TX_EN__FEC_TX_EN                   0x80000000 \
+       MX53_PAD_FEC_TXD1__FEC_TDATA_1                  0x80000000 \
+       MX53_PAD_FEC_TXD0__FEC_TDATA_0                  0x80000000
+
+#define MX53_FEC_PINGRP2 \
+       MX53_PAD_FEC_MDC__FEC_MDC                       0x80000000 \
+       MX53_PAD_FEC_MDIO__FEC_MDIO                     0x80000000 \
+       MX53_PAD_FEC_REF_CLK__FEC_TX_CLK                0x80000000 \
+       MX53_PAD_FEC_RX_ER__FEC_RX_ER                   0x80000000 \
+       MX53_PAD_FEC_CRS_DV__FEC_RX_DV                  0x80000000 \
+       MX53_PAD_FEC_RXD1__FEC_RDATA_1                  0x80000000 \
+       MX53_PAD_FEC_RXD0__FEC_RDATA_0                  0x80000000 \
+       MX53_PAD_FEC_TX_EN__FEC_TX_EN                   0x80000000 \
+       MX53_PAD_FEC_TXD1__FEC_TDATA_1                  0x80000000 \
+       MX53_PAD_FEC_TXD0__FEC_TDATA_0                  0x80000000 \
+       MX53_PAD_KEY_ROW1__FEC_COL                      0x80000000 \
+       MX53_PAD_KEY_COL3__FEC_CRS                      0x80000000 \
+       MX53_PAD_KEY_COL2__FEC_RDATA_2                  0x80000000 \
+       MX53_PAD_KEY_COL0__FEC_RDATA_3                  0x80000000 \
+       MX53_PAD_KEY_COL1__FEC_RX_CLK                   0x80000000 \
+       MX53_PAD_KEY_ROW2__FEC_TDATA_2                  0x80000000 \
+       MX53_PAD_GPIO_19__FEC_TDATA_3                   0x80000000 \
+       MX53_PAD_KEY_ROW0__FEC_TX_ER                    0x80000000
+
+#define MX53_I2C1_PINGRP1 \
+       MX53_PAD_CSI0_DAT8__I2C1_SDA                    0xc0000000 \
+       MX53_PAD_CSI0_DAT9__I2C1_SCL                    0xc0000000
+
+#define MX53_I2C1_PINGRP2 \
+       MX53_PAD_EIM_D21__I2C1_SCL                      0xc0000000 \
+       MX53_PAD_EIM_D28__I2C1_SDA                      0xc0000000
+
+#define MX53_I2C2_PINGRP1 \
+       MX53_PAD_KEY_ROW3__I2C2_SDA                     0xc0000000 \
+       MX53_PAD_KEY_COL3__I2C2_SCL                     0xc0000000
+
+#define MX53_I2C2_PINGRP2 \
+       MX53_PAD_EIM_D16__I2C2_SDA                      0xc0000000 \
+       MX53_PAD_EIM_EB2__I2C2_SCL                      0xc0000000
+
+#define MX53_I2C3_PINGRP1 \
+       MX53_PAD_GPIO_6__I2C3_SDA                       0xc0000000 \
+       MX53_PAD_GPIO_5__I2C3_SCL                       0xc0000000
+
+#define MX53_I2C3_PINGRP2 \
+       MX53_PAD_GPIO_3__I2C3_SCL                       0xc0000000 \
+       MX53_PAD_GPIO_6__I2C3_SDA                       0xc0000000
+
+#define MX53_IPU_DISP0_PINGRP1 \
+       MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK         0x5 \
+       MX53_PAD_DI0_PIN15__IPU_DI0_PIN15               0x5 \
+       MX53_PAD_DI0_PIN2__IPU_DI0_PIN2                 0x5 \
+       MX53_PAD_DI0_PIN3__IPU_DI0_PIN3                 0x5 \
+       MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0            0x5 \
+       MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1            0x5 \
+       MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2            0x5 \
+       MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3            0x5 \
+       MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4            0x5 \
+       MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5            0x5 \
+       MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6            0x5 \
+       MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7            0x5 \
+       MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8            0x5 \
+       MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9            0x5 \
+       MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10          0x5 \
+       MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11          0x5 \
+       MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12          0x5 \
+       MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13          0x5 \
+       MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14          0x5 \
+       MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15          0x5 \
+       MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16          0x5 \
+       MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17          0x5 \
+       MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18          0x5 \
+       MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19          0x5 \
+       MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20          0x5 \
+       MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21          0x5 \
+       MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22          0x5 \
+       MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23          0x5
+
+#define MX53_IPU_DISP1_PINGRP1 \
+       MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0               0x5 \
+       MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1               0x5 \
+       MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2               0x5 \
+       MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3               0x5 \
+       MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4               0x5 \
+       MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5               0x5 \
+       MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6               0x5 \
+       MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7               0x5 \
+       MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8               0x5 \
+       MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9               0x5 \
+       MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10              0x5 \
+       MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11              0x5 \
+       MX53_PAD_EIM_A17__IPU_DISP1_DAT_12              0x5 \
+       MX53_PAD_EIM_A18__IPU_DISP1_DAT_13              0x5 \
+       MX53_PAD_EIM_A19__IPU_DISP1_DAT_14              0x5 \
+       MX53_PAD_EIM_A20__IPU_DISP1_DAT_15              0x5 \
+       MX53_PAD_EIM_A21__IPU_DISP1_DAT_16              0x5 \
+       MX53_PAD_EIM_A22__IPU_DISP1_DAT_17              0x5 \
+       MX53_PAD_EIM_A23__IPU_DISP1_DAT_18              0x5 \
+       MX53_PAD_EIM_A24__IPU_DISP1_DAT_19              0x5 \
+       MX53_PAD_EIM_D31__IPU_DISP1_DAT_20              0x5 \
+       MX53_PAD_EIM_D30__IPU_DISP1_DAT_21              0x5 \
+       MX53_PAD_EIM_D26__IPU_DISP1_DAT_22              0x5 \
+       MX53_PAD_EIM_D27__IPU_DISP1_DAT_23              0x5 \
+       MX53_PAD_EIM_A16__IPU_DI1_DISP_CLK              0x5 \
+       MX53_PAD_EIM_DA13__IPU_DI1_D0_CS                0x5 \
+       MX53_PAD_EIM_DA14__IPU_DI1_D1_CS                0x5 \
+       MX53_PAD_EIM_DA15__IPU_DI1_PIN1                 0x5 \
+       MX53_PAD_EIM_DA11__IPU_DI1_PIN2                 0x5 \
+       MX53_PAD_EIM_DA12__IPU_DI1_PIN3                 0x5 \
+       MX53_PAD_EIM_A25__IPU_DI1_PIN12                 0x5 \
+       MX53_PAD_EIM_DA10__IPU_DI1_PIN15                0x5
+
+#define MX53_IPU_DISP2_PINGRP1 \
+       MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0             0x80000000 \
+       MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1             0x80000000 \
+       MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2             0x80000000 \
+       MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3             0x80000000 \
+       MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK             0x80000000 \
+       MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0             0x80000000 \
+       MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1             0x80000000 \
+       MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2             0x80000000 \
+       MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3             0x80000000 \
+       MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK             0x80000000
+
+#define MX53_NAND_PINGRP1 \
+       MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B             0x4 \
+       MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B             0x4 \
+       MX53_PAD_NANDF_CLE__EMI_NANDF_CLE               0x4 \
+       MX53_PAD_NANDF_ALE__EMI_NANDF_ALE               0x4 \
+       MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B             0xe0 \
+       MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0              0xe0 \
+       MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0              0x4 \
+       MX53_PAD_PATA_DATA0__EMI_NANDF_D_0              0xa4 \
+       MX53_PAD_PATA_DATA1__EMI_NANDF_D_1              0xa4 \
+       MX53_PAD_PATA_DATA2__EMI_NANDF_D_2              0xa4 \
+       MX53_PAD_PATA_DATA3__EMI_NANDF_D_3              0xa4 \
+       MX53_PAD_PATA_DATA4__EMI_NANDF_D_4              0xa4 \
+       MX53_PAD_PATA_DATA5__EMI_NANDF_D_5              0xa4 \
+       MX53_PAD_PATA_DATA6__EMI_NANDF_D_6              0xa4 \
+       MX53_PAD_PATA_DATA7__EMI_NANDF_D_7              0xa4
+
+#define MX53_OWIRE_PINGRP1 \
+       MX53_PAD_GPIO_18__OWIRE_LINE                    0x80000000
+
+#define MX53_PWM1_PINGRP1 \
+       MX53_PAD_DISP0_DAT8__PWM1_PWMO                  0x5
+
+#define MX53_PWM2_PINGRP1 \
+       MX53_PAD_GPIO_1__PWM2_PWMO                      0x80000000
+
+#define MX53_UART1_PINGRP1 \
+       MX53_PAD_CSI0_DAT10__UART1_TXD_MUX              0x1e4 \
+       MX53_PAD_CSI0_DAT11__UART1_RXD_MUX              0x1e4
+
+#define MX53_UART1_PINGRP2 \
+       MX53_PAD_PATA_DIOW__UART1_TXD_MUX               0x1e4 \
+       MX53_PAD_PATA_DMACK__UART1_RXD_MUX              0x1e4
+
+#define MX53_UART1_PINGRP3 \
+       MX53_PAD_PATA_RESET_B__UART1_CTS                0x1c5 \
+       MX53_PAD_PATA_IORDY__UART1_RTS                  0x1c5
+
+#define MX53_UART2_PINGRP1 \
+       MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX          0x1e4 \
+       MX53_PAD_PATA_DMARQ__UART2_TXD_MUX              0x1e4
+
+#define MX53_UART2_PINGRP2 \
+       MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX          0x1c5 \
+       MX53_PAD_PATA_DMARQ__UART2_TXD_MUX              0x1c5 \
+       MX53_PAD_PATA_DIOR__UART2_RTS                   0x1c5 \
+       MX53_PAD_PATA_INTRQ__UART2_CTS                  0x1c5
+
+#define MX53_UART3_PINGRP1 \
+       MX53_PAD_PATA_CS_0__UART3_TXD_MUX               0x1e4 \
+       MX53_PAD_PATA_CS_1__UART3_RXD_MUX               0x1e4 \
+       MX53_PAD_PATA_DA_1__UART3_CTS                   0x1e4 \
+       MX53_PAD_PATA_DA_2__UART3_RTS                   0x1e4
+
+#define MX53_UART3_PINGRP2 \
+       MX53_PAD_PATA_CS_0__UART3_TXD_MUX               0x1e4 \
+       MX53_PAD_PATA_CS_1__UART3_RXD_MUX               0x1e4
+
+#define MX53_UART4_PINGRP1 \
+       MX53_PAD_KEY_COL0__UART4_TXD_MUX                0x1e4 \
+       MX53_PAD_KEY_ROW0__UART4_RXD_MUX                0x1e4
+
+#define MX53_UART5_PINGRP1 \
+       MX53_PAD_KEY_COL1__UART5_TXD_MUX                0x1e4 \
+       MX53_PAD_KEY_ROW1__UART5_RXD_MUX                0x1e4
+
+#endif /* __DTS_IMX53_PINGRP_H */
index 91a5935a4aacd63879f2f2104f546d6f41bb7e60..4c04459c45251c8e5c9f4fa1783f933d29456028 100644 (file)
@@ -26,7 +26,7 @@
                crtcs = <&ipu 0>;
                interface-pix-fmt = "rgb565";
                pinctrl-names = "default";
-               pinctrl-0 = <&pinctrl_ipu_disp0_1>;
+               pinctrl-0 = <&pinctrl_ipu_disp0>;
                status = "disabled";
                display-timings {
                        claawvga {
 
        regulators {
                compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
 
-               reg_3p2v: 3p2v {
+               reg_3p2v: regulator@0 {
                        compatible = "regulator-fixed";
+                       reg = <0>;
                        regulator-name = "3P2V";
                        regulator-min-microvolt = <3200000>;
                        regulator-max-microvolt = <3200000>;
                        regulator-always-on;
                };
 
-               reg_usb_vbus: usb_vbus {
+               reg_usb_vbus: regulator@1 {
                        compatible = "regulator-fixed";
+                       reg = <1>;
                        regulator-name = "usb_vbus";
                        regulator-min-microvolt = <5000000>;
                        regulator-max-microvolt = <5000000>;
 
 &esdhc1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_esdhc1_1>;
+       pinctrl-0 = <&pinctrl_esdhc1>;
        status = "okay";
 };
 
 
 &esdhc3 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_esdhc3_1>;
+       pinctrl-0 = <&pinctrl_esdhc3>;
        cd-gpios = <&gpio3 11 0>;
        wp-gpios = <&gpio3 12 0>;
        bus-width = <8>;
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_hog>;
 
-       hog {
+       imx53-qsb {
                pinctrl_hog: hoggrp {
                        fsl,pins = <
                                MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK 0x80000000
                                MX53_PAD_PATA_DA_1__GPIO7_7 0x80000000
                        >;
                };
-       };
 
+               pinctrl_audmux: audmuxgrp {
+                       fsl,pins = <MX53_AUDMUX_PINGRP1>;
+               };
+
+               pinctrl_esdhc1: esdhc1grp {
+                       fsl,pins = <MX53_ESDHC1_PINGRP1>;
+               };
+
+               pinctrl_esdhc3: esdhc3grp {
+                       fsl,pins = <MX53_ESDHC3_PINGRP1>;
+               };
+
+               pinctrl_fec: fecgrp {
+                       fsl,pins = <MX53_FEC_PINGRP1>;
+               };
+
+               pinctrl_i2c1: i2c1grp {
+                       fsl,pins = <MX53_I2C1_PINGRP1>;
+               };
+
+               pinctrl_i2c2: i2c2grp {
+                       fsl,pins = <MX53_I2C2_PINGRP1>;
+               };
+
+               pinctrl_ipu_disp0: ipudisp0grp {
+                       fsl,pins = <MX53_IPU_DISP0_PINGRP1>;
+               };
+
+               pinctrl_uart1: uart1grp {
+                       fsl,pins = <MX53_UART1_PINGRP1>;
+               };
+       };
 };
 
 &uart1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_uart1_1>;
+       pinctrl-0 = <&pinctrl_uart1>;
        status = "okay";
 };
 
 &i2c2 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_i2c2_1>;
+       pinctrl-0 = <&pinctrl_i2c2>;
        status = "okay";
 
        sgtl5000: codec@0a {
                reg = <0x0a>;
                VDDA-supply = <&reg_3p2v>;
                VDDIO-supply = <&reg_3p2v>;
-               clocks = <&clks 150>;
+               clocks = <&clks IMX5_CLK_SSI_EXT1_GATE>;
        };
 };
 
 &i2c1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_i2c1_1>;
+       pinctrl-0 = <&pinctrl_i2c1>;
        status = "okay";
 
        accelerometer: mma8450@1c {
 
 &audmux {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_audmux_1>;
+       pinctrl-0 = <&pinctrl_audmux>;
        status = "okay";
 };
 
 &fec {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_fec_1>;
+       pinctrl-0 = <&pinctrl_fec>;
        phy-mode = "rmii";
        phy-reset-gpios = <&gpio7 6 0>;
        status = "okay";
 };
 
+&sata {
+       status = "okay";
+};
+
 &vpu {
        status = "okay";
 };
index a9b6e10de0a5f52ebadb707e1f99179e6e19ae88..e84decfb05d0b9e64ed1374a0fd3ffdd390421fc 100644 (file)
@@ -40,7 +40,7 @@
 
 &esdhc1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_esdhc1_1>;
+       pinctrl-0 = <&pinctrl_esdhc1>;
        cd-gpios = <&gpio3 13 0>;
        wp-gpios = <&gpio4 11 0>;
        status = "okay";
 
 &esdhc2 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_esdhc2_1>;
+       pinctrl-0 = <&pinctrl_esdhc2>;
        non-removable;
        status = "okay";
 };
 
 &uart3 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_uart3_1>;
+       pinctrl-0 = <&pinctrl_uart3>;
        fsl,uart-has-rtscts;
        status = "okay";
 };
 
 &ecspi1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_ecspi1_1>;
+       pinctrl-0 = <&pinctrl_ecspi1>;
        fsl,spi-num-chipselects = <2>;
        cs-gpios = <&gpio2 30 0>, <&gpio3 19 0>;
        status = "okay";
@@ -95,7 +95,7 @@
 
 &esdhc3 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_esdhc3_1>;
+       pinctrl-0 = <&pinctrl_esdhc3>;
        non-removable;
        status = "okay";
 };
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_hog>;
 
-       hog {
+       imx53-smd {
                pinctrl_hog: hoggrp {
                        fsl,pins = <
                                MX53_PAD_PATA_DATA14__GPIO2_14 0x80000000
                                MX53_PAD_PATA_DA_0__GPIO7_6    0x80000000
                        >;
                };
+
+               pinctrl_ecspi1: ecspi1grp {
+                       fsl,pins = <MX53_ECSPI1_PINGRP1>;
+               };
+
+               pinctrl_esdhc1: esdhc1grp {
+                       fsl,pins = <MX53_ESDHC1_PINGRP1>;
+               };
+
+               pinctrl_esdhc2: esdhc2grp {
+                       fsl,pins = <MX53_ESDHC2_PINGRP1>;
+               };
+
+               pinctrl_esdhc3: esdhc3grp {
+                       fsl,pins = <MX53_ESDHC3_PINGRP1>;
+               };
+
+               pinctrl_fec: fecgrp {
+                       fsl,pins = <MX53_FEC_PINGRP1>;
+               };
+
+               pinctrl_i2c1: i2c1grp {
+                       fsl,pins = <MX53_I2C1_PINGRP1>;
+               };
+
+               pinctrl_i2c2: i2c2grp {
+                       fsl,pins = <MX53_I2C2_PINGRP1>;
+               };
+
+               pinctrl_uart1: uart1grp {
+                       fsl,pins = <MX53_UART1_PINGRP1>;
+               };
+
+               pinctrl_uart2: uart2grp {
+                       fsl,pins = <MX53_UART2_PINGRP1>;
+               };
+
+               pinctrl_uart3: uart3grp {
+                       fsl,pins = <MX53_UART3_PINGRP1>;
+               };
        };
 };
 
 &uart1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_uart1_1>;
+       pinctrl-0 = <&pinctrl_uart1>;
        status = "okay";
 };
 
 &uart2 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_uart2_1>;
+       pinctrl-0 = <&pinctrl_uart2>;
        status = "okay";
 };
 
 &i2c2 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_i2c2_1>;
+       pinctrl-0 = <&pinctrl_i2c2>;
        status = "okay";
 
        codec: sgtl5000@0a {
 
 &i2c1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_i2c1_1>;
+       pinctrl-0 = <&pinctrl_i2c1>;
        status = "okay";
 
        accelerometer: mma8450@1c {
 
 &fec {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_fec_1>;
+       pinctrl-0 = <&pinctrl_fec>;
        phy-mode = "rmii";
        phy-reset-gpios = <&gpio7 6 0>;
        status = "okay";
index abd72af545bf0409ce9556afdb47dcffbf8fcea0..b6483c9a0b9994147ebd78798322ab804d41e13e 100644 (file)
 
        regulators {
                compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
 
-               reg_3p3v: 3p3v {
+               reg_3p3v: regulator@0 {
                        compatible = "regulator-fixed";
+                       reg = <0>;
                        regulator-name = "3P3V";
                        regulator-min-microvolt = <3300000>;
                        regulator-max-microvolt = <3300000>;
@@ -35,8 +38,8 @@
 
 &esdhc2 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_esdhc2_1>,
-                   <&pinctrl_tqma53_esdhc2_2>;
+       pinctrl-0 = <&pinctrl_esdhc2>,
+                   <&pinctrl_esdhc2_cdwp>;
        vmmc-supply = <&reg_3p3v>;
        wp-gpios = <&gpio1 2 0>;
        cd-gpios = <&gpio1 4 0>;
 
 &uart3 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_uart3_2>;
+       pinctrl-0 = <&pinctrl_uart3>;
        status = "disabled";
 };
 
 &ecspi1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_ecspi1_1>;
+       pinctrl-0 = <&pinctrl_ecspi1>;
        fsl,spi-num-chipselects = <4>;
        cs-gpios = <&gpio2 30 0>, <&gpio3 19 0>,
                   <&gpio3 24 0>, <&gpio3 25 0>;
@@ -60,7 +63,7 @@
 
 &esdhc3 { /* EMMC */
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_esdhc3_1>;
+       pinctrl-0 = <&pinctrl_esdhc3>;
        vmmc-supply = <&reg_3p3v>;
        non-removable;
        bus-width = <8>;
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_hog>;
 
-       esdhc2_2 {
-               pinctrl_tqma53_esdhc2_2: esdhc2-tqma53-grp2 {
-                       fsl,pins = <
-                               MX53_PAD_GPIO_4__GPIO1_4        0x80000000 /* SD2_CD */
-                               MX53_PAD_GPIO_2__GPIO1_2        0x80000000 /* SD2_WP */
-                       >;
-               };
-       };
-
-       i2s {
-               pinctrl_i2s_1: i2s-grp1 {
-                       fsl,pins = <
-                                MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC  0x80000000 /* I2S_SCLK */
-                                MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD  0x80000000 /* I2S_DOUT */
-                                MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS 0x80000000 /* I2S_LRCLK */
-                                MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD  0x80000000 /* I2S_DIN */
-                       >;
-               };
-       };
-
-       hog {
+       imx53-tqma53 {
                pinctrl_hog: hoggrp {
                        fsl,pins = <
                                 MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK 0x80000000 /* SSI_MCLK */
                                 MX53_PAD_GPIO_1__PWM2_PWMO      0x80000000 /* LCD_CONTRAST */
                        >;
                };
+
+               pinctrl_audmux: audmuxgrp {
+                       fsl,pins = <MX53_AUDMUX_PINGRP1>;
+               };
+
+               pinctrl_can1: can1grp {
+                       fsl,pins = <MX53_CAN1_PINGRP2>;
+               };
+
+               pinctrl_can2: can2grp {
+                       fsl,pins = <MX53_CAN2_PINGRP1>;
+               };
+
+               pinctrl_cspi: cspigrp {
+                       fsl,pins = <MX53_CSPI_PINGRP1>;
+               };
+
+               pinctrl_ecspi1: ecspi1grp {
+                       fsl,pins = <MX53_ECSPI1_PINGRP1>;
+               };
+
+               pinctrl_esdhc2: esdhc2grp {
+                       fsl,pins = <MX53_ESDHC2_PINGRP1>;
+               };
+
+               pinctrl_esdhc2_cdwp: esdhc2cdwp {
+                       fsl,pins = <
+                               MX53_PAD_GPIO_4__GPIO1_4        0x80000000 /* SD2_CD */
+                               MX53_PAD_GPIO_2__GPIO1_2        0x80000000 /* SD2_WP */
+                       >;
+               };
+
+               pinctrl_esdhc3: esdhc3grp {
+                       fsl,pins = <MX53_ESDHC3_PINGRP1>;
+               };
+
+               pinctrl_fec: fecgrp {
+                       fsl,pins = <MX53_FEC_PINGRP1>;
+               };
+
+               pinctrl_i2c2: i2c2grp {
+                       fsl,pins = <MX53_I2C2_PINGRP1>;
+               };
+
+               pinctrl_i2c3: i2c3grp {
+                       fsl,pins = <MX53_I2C3_PINGRP1>;
+               };
+
+               pinctrl_uart1: uart1grp {
+                       fsl,pins = <MX53_UART1_PINGRP2>;
+               };
+
+               pinctrl_uart2: uart2grp {
+                       fsl,pins = <MX53_UART2_PINGRP1>;
+               };
+
+               pinctrl_uart3: uart3grp {
+                       fsl,ps = <MX53_UART3_PINGRP2>;
+               };
        };
 };
 
 &uart1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_uart1_2>;
+       pinctrl-0 = <&pinctrl_uart1>;
        fsl,uart-has-rtscts;
        status = "disabled";
 };
 
 &uart2 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_uart2_1>;
+       pinctrl-0 = <&pinctrl_uart2>;
        status = "disabled";
 };
 
 &can1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_can1_2>;
+       pinctrl-0 = <&pinctrl_can1>;
        status = "disabled";
 };
 
 &can2 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_can2_1>;
+       pinctrl-0 = <&pinctrl_can2>;
        status = "disabled";
 };
 
 &i2c3 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_i2c3_1>;
+       pinctrl-0 = <&pinctrl_i2c3>;
        status = "disabled";
 };
 
 &cspi {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_cspi_1>;
+       pinctrl-0 = <&pinctrl_cspi>;
        fsl,spi-num-chipselects = <3>;
        cs-gpios = <&gpio1 18 0>, <&gpio1 19 0>,
                   <&gpio1 21 0>;
 
 &i2c2 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_i2c2_1>;
+       pinctrl-0 = <&pinctrl_i2c2>;
        status = "okay";
 
        pmic: mc34708@8 {
 
 &fec {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_fec_1>;
+       pinctrl-0 = <&pinctrl_fec>;
        phy-mode = "rmii";
        status = "disabled";
 };
index f494766700a3d7b48e735ce1dc79fa550036c7a2..db4255c8e7e8a8dc42643da5ec2fa97599ef6bde 100644 (file)
 
        regulators {
                compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
 
-               reg_3p3v: 3p3v {
+               reg_3p3v: regulator@0 {
                        compatible = "regulator-fixed";
+                       reg = <0>;
                        regulator-name = "3P3V";
                        regulator-min-microvolt = <3300000>;
                        regulator-max-microvolt = <3300000>;
diff --git a/arch/arm/boot/dts/imx53-voipac-bsb.dts b/arch/arm/boot/dts/imx53-voipac-bsb.dts
new file mode 100644 (file)
index 0000000..61244cf
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2013 Rostislav Lisovy <lisovy@gmail.com>, PiKRON s.r.o.
+ *
+ * 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 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx53-voipac-dmm-668.dtsi"
+
+/ {
+       sound {
+               compatible = "fsl,imx53-voipac-sgtl5000",
+                            "fsl,imx-audio-sgtl5000";
+               model = "imx53-voipac-sgtl5000";
+               ssi-controller = <&ssi2>;
+               audio-codec = <&sgtl5000>;
+               audio-routing =
+                       "Headphone Jack", "HP_OUT";
+               mux-int-port = <2>;
+               mux-ext-port = <5>;
+       };
+
+       leds {
+               compatible = "gpio-leds";
+               pinctrl-names = "default";
+               pinctrl-0 = <&led_pin_gpio>;
+
+               led1 {
+                       label = "led-red";
+                       gpios = <&gpio3 29 0>;
+                       default-state = "off";
+               };
+
+               led2 {
+                       label = "led-orange";
+                       gpios = <&gpio2 31 0>;
+                       default-state = "off";
+               };
+       };
+};
+
+&iomuxc {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_hog>;
+
+       imx53-voipac {
+               pinctrl_hog: hoggrp {
+                       fsl,pins = <
+                               /* SD2_CD */
+                               MX53_PAD_EIM_D25__GPIO3_25      0x80000000
+                               /* SD2_WP */
+                               MX53_PAD_EIM_A19__GPIO2_19      0x80000000
+                       >;
+               };
+
+               led_pin_gpio: led_gpio {
+                       fsl,pins = <
+                               MX53_PAD_EIM_D29__GPIO3_29      0x80000000
+                               MX53_PAD_EIM_EB3__GPIO2_31      0x80000000
+                       >;
+               };
+
+               /* Keyboard controller */
+               pinctrl_kpp_1: kppgrp-1 {
+                       fsl,pins = <
+                               MX53_PAD_GPIO_9__KPP_COL_6      0xe8
+                               MX53_PAD_GPIO_4__KPP_COL_7      0xe8
+                               MX53_PAD_KEY_COL2__KPP_COL_2    0xe8
+                               MX53_PAD_KEY_COL3__KPP_COL_3    0xe8
+                               MX53_PAD_KEY_COL4__KPP_COL_4    0xe8
+                               MX53_PAD_GPIO_2__KPP_ROW_6      0xe0
+                               MX53_PAD_GPIO_5__KPP_ROW_7      0xe0
+                               MX53_PAD_KEY_ROW2__KPP_ROW_2    0xe0
+                               MX53_PAD_KEY_ROW3__KPP_ROW_3    0xe0
+                               MX53_PAD_KEY_ROW4__KPP_ROW_4    0xe0
+                       >;
+               };
+
+               pinctrl_audmux: audmuxgrp {
+                       fsl,pins = <MX53_AUDMUX_PINGRP1>;
+               };
+
+               pinctrl_esdhc2: esdhc2grp {
+                       fsl,pins = <MX53_ESDHC2_PINGRP1>;
+               };
+
+               pinctrl_i2c3: i2c3grp {
+                       fsl,pins = <MX53_I2C3_PINGRP2>;
+               };
+       };
+};
+
+&audmux {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_audmux>; /* SSI1 */
+       status = "okay";
+};
+
+&esdhc2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_esdhc2>;
+       cd-gpios = <&gpio3 25 0>;
+       wp-gpios = <&gpio2 19 0>;
+       vmmc-supply = <&reg_3p3v>;
+       status = "okay";
+};
+
+&i2c3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c3>;
+       status = "okay";
+
+       sgtl5000: codec@0a {
+               compatible = "fsl,sgtl5000";
+               reg = <0x0a>;
+               VDDA-supply = <&reg_3p3v>;
+               VDDIO-supply = <&reg_3p3v>;
+               clocks = <&clks 150>;
+       };
+};
+
+&kpp {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_kpp_1>;
+       linux,keymap = <
+                       0x0203003b      /* KEY_F1 */
+                       0x0603003c      /* KEY_F2 */
+                       0x0207003d      /* KEY_F3 */
+                       0x0607003e      /* KEY_F4 */
+                       >;
+       keypad,num-rows = <8>;
+       keypad,num-columns = <1>;
+       status = "okay";
+};
+
+&ssi2 {
+       fsl,mode = "i2s-slave";
+       status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx53-voipac-dmm-668.dtsi b/arch/arm/boot/dts/imx53-voipac-dmm-668.dtsi
new file mode 100644 (file)
index 0000000..04a2895
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * Copyright 2013 Rostislav Lisovy <lisovy@gmail.com>, PiKRON s.r.o.
+ *
+ * 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 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include "imx53.dtsi"
+
+/ {
+       model = "Voipac i.MX53 X53-DMM-668";
+       compatible = "voipac,imx53-dmm-668", "fsl,imx53";
+
+       memory@70000000 {
+               device_type = "memory";
+               reg = <0x70000000 0x20000000>;
+       };
+
+       memory@b0000000 {
+               device_type = "memory";
+               reg = <0xb0000000 0x20000000>;
+       };
+
+       regulators {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               reg_3p3v: regulator@0 {
+                       compatible = "regulator-fixed";
+                       reg = <0>;
+                       regulator-name = "3P3V";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+               };
+
+               reg_usb_vbus: regulator@1 {
+                       compatible = "regulator-fixed";
+                       reg = <1>;
+                       regulator-name = "usb_vbus";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       gpio = <&gpio3 31 0>; /* PEN */
+                       enable-active-high;
+               };
+       };
+};
+
+&iomuxc {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_hog>;
+
+       imx53-voipac {
+               pinctrl_hog: hoggrp {
+                       fsl,pins = <
+                               /* Make DA9053 regulator functional */
+                               MX53_PAD_GPIO_16__GPIO7_11      0x80000000
+                               /* FEC Power enable */
+                               MX53_PAD_GPIO_11__GPIO4_1       0x80000000
+                               /* FEC RST */
+                               MX53_PAD_GPIO_12__GPIO4_2       0x80000000
+                       >;
+               };
+
+               pinctrl_ecspi1: ecspi1grp {
+                       fsl,pins = <MX53_ECSPI1_PINGRP1>;
+               };
+
+               pinctrl_fec: fecgrp {
+                       fsl,pins = <MX53_FEC_PINGRP1>;
+               };
+
+               pinctrl_i2c1: i2c1grp {
+                       fsl,pins = <MX53_I2C1_PINGRP2>;
+               };
+
+               pinctrl_uart1: uart1grp {
+                       fsl,pins = <MX53_UART1_PINGRP2>;
+               };
+
+               pinctrl_nand: nandgrp {
+                       fsl,pins = <MX53_NAND_PINGRP1>;
+               };
+       };
+};
+
+&ecspi1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_ecspi1>;
+       fsl,spi-num-chipselects = <4>;
+       cs-gpios = <&gpio2 30 0>, <&gpio3 19 0>, <&gpio2 16 0>, <&gpio2 17 0>;
+       status = "okay";
+};
+
+&fec {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_fec>;
+       phy-mode = "rmii";
+       phy-reset-gpios = <&gpio4 2 0>;
+       status = "okay";
+};
+
+&i2c1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c1>;
+       status = "okay";
+
+       pmic: dialog@48 {
+               compatible = "dlg,da9053-aa", "dlg,da9052";
+               reg = <0x48>;
+               interrupt-parent = <&gpio7>;
+               interrupts = <11 0x8>; /* low-level active IRQ at GPIO7_11 */
+
+               regulators {
+                       buck1_reg: buck1 {
+                               regulator-name = "BUCKCORE";
+                               regulator-min-microvolt = <1200000>;
+                               regulator-max-microvolt = <1400000>;
+                               regulator-always-on;
+                       };
+
+                       buck2_reg: buck2 {
+                               regulator-name = "BUCKPRO";
+                               regulator-min-microvolt = <900000>;
+                               regulator-max-microvolt = <1350000>;
+                               regulator-always-on;
+                       };
+
+                       buck3_reg: buck3 {
+                               regulator-name = "BUCKMEM";
+                               regulator-min-microvolt = <1420000>;
+                               regulator-max-microvolt = <1580000>;
+                               regulator-always-on;
+                       };
+
+                       buck4_reg: buck4 {
+                               regulator-name = "BUCKPERI";
+                               regulator-min-microvolt = <2370000>;
+                               regulator-max-microvolt = <2630000>;
+                               regulator-always-on;
+                       };
+
+                       ldo1_reg: ldo1 {
+                               regulator-name = "ldo1_1v3";
+                               regulator-min-microvolt = <1250000>;
+                               regulator-max-microvolt = <1350000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       ldo2_reg: ldo2 {
+                               regulator-name = "ldo2_1v3";
+                               regulator-min-microvolt = <1250000>;
+                               regulator-max-microvolt = <1350000>;
+                               regulator-always-on;
+                       };
+
+                       ldo3_reg: ldo3 {
+                               regulator-name = "ldo3_3v3";
+                               regulator-min-microvolt = <3250000>;
+                               regulator-max-microvolt = <3350000>;
+                               regulator-always-on;
+                       };
+
+                       ldo4_reg: ldo4 {
+                               regulator-name = "ldo4_2v775";
+                               regulator-min-microvolt = <2770000>;
+                               regulator-max-microvolt = <2780000>;
+                               regulator-always-on;
+                       };
+
+                       ldo5_reg: ldo5 {
+                               regulator-name = "ldo5_3v3";
+                               regulator-min-microvolt = <3250000>;
+                               regulator-max-microvolt = <3350000>;
+                               regulator-always-on;
+                       };
+
+                       ldo6_reg: ldo6 {
+                               regulator-name = "ldo6_1v3";
+                               regulator-min-microvolt = <1250000>;
+                               regulator-max-microvolt = <1350000>;
+                               regulator-always-on;
+                       };
+
+                       ldo7_reg: ldo7 {
+                               regulator-name = "ldo7_2v75";
+                               regulator-min-microvolt = <2700000>;
+                               regulator-max-microvolt = <2800000>;
+                               regulator-always-on;
+                       };
+
+                       ldo8_reg: ldo8 {
+                               regulator-name = "ldo8_1v8";
+                               regulator-min-microvolt = <1750000>;
+                               regulator-max-microvolt = <1850000>;
+                               regulator-always-on;
+                       };
+
+                       ldo9_reg: ldo9 {
+                               regulator-name = "ldo9_1v5";
+                               regulator-min-microvolt = <1450000>;
+                               regulator-max-microvolt = <1550000>;
+                               regulator-always-on;
+                       };
+
+                       ldo10_reg: ldo10 {
+                               regulator-name = "ldo10_1v3";
+                               regulator-min-microvolt = <1250000>;
+                               regulator-max-microvolt = <1350000>;
+                               regulator-always-on;
+                       };
+               };
+       };
+};
+
+&nfc {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_nand>;
+       nand-bus-width = <8>;
+       nand-ecc-mode = "hw";
+       status = "okay";
+};
+
+&uart1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart1>;
+       status = "okay";
+};
+
+&usbh1 {
+       vbus-supply = <&reg_usb_vbus>;
+       phy_type = "utmi";
+       status = "okay";
+};
index 4307e80b2d2e386e53d48ee2080ca66df625565f..175a94cff749e2077969b3878902fcd26f783225 100644 (file)
@@ -11,7 +11,8 @@
  */
 
 #include "skeleton.dtsi"
-#include "imx53-pinfunc.h"
+#include "imx53-pingrp.h"
+#include <dt-bindings/clock/imx5-clock.h>
 
 / {
        aliases {
                interrupt-parent = <&tzic>;
                ranges;
 
+               sata: sata@10000000 {
+                       compatible = "fsl,imx53-ahci";
+                       reg = <0x10000000 0x1000>;
+                       interrupts = <28>;
+                       clocks = <&clks IMX5_CLK_SATA_GATE>,
+                                <&clks IMX5_CLK_SATA_REF>,
+                                <&clks IMX5_CLK_AHB>;
+                       clock-names = "sata_gate", "sata_ref", "ahb";
+                       status = "disabled";
+               };
+
                ipu: ipu@18000000 {
                        #crtc-cells = <1>;
                        compatible = "fsl,imx53-ipu";
                        reg = <0x18000000 0x080000000>;
                        interrupts = <11 10>;
-                       clocks = <&clks 59>, <&clks 110>, <&clks 61>;
+                       clocks = <&clks IMX5_CLK_IPU_GATE>,
+                                <&clks IMX5_CLK_IPU_DI0_GATE>,
+                                <&clks IMX5_CLK_IPU_DI1_GATE>;
                        clock-names = "bus", "di0", "di1";
                        resets = <&src 2>;
                };
                                        compatible = "fsl,imx53-esdhc";
                                        reg = <0x50004000 0x4000>;
                                        interrupts = <1>;
-                                       clocks = <&clks 44>, <&clks 0>, <&clks 71>;
+                                       clocks = <&clks IMX5_CLK_ESDHC1_IPG_GATE>,
+                                                <&clks IMX5_CLK_DUMMY>,
+                                                <&clks IMX5_CLK_ESDHC1_PER_GATE>;
                                        clock-names = "ipg", "ahb", "per";
                                        bus-width = <4>;
                                        status = "disabled";
                                        compatible = "fsl,imx53-esdhc";
                                        reg = <0x50008000 0x4000>;
                                        interrupts = <2>;
-                                       clocks = <&clks 45>, <&clks 0>, <&clks 72>;
+                                       clocks = <&clks IMX5_CLK_ESDHC2_IPG_GATE>,
+                                                <&clks IMX5_CLK_DUMMY>,
+                                                <&clks IMX5_CLK_ESDHC2_PER_GATE>;
                                        clock-names = "ipg", "ahb", "per";
                                        bus-width = <4>;
                                        status = "disabled";
                                        compatible = "fsl,imx53-uart", "fsl,imx21-uart";
                                        reg = <0x5000c000 0x4000>;
                                        interrupts = <33>;
-                                       clocks = <&clks 32>, <&clks 33>;
+                                       clocks = <&clks IMX5_CLK_UART3_IPG_GATE>,
+                                                <&clks IMX5_CLK_UART3_PER_GATE>;
                                        clock-names = "ipg", "per";
                                        status = "disabled";
                                };
                                        compatible = "fsl,imx53-ecspi", "fsl,imx51-ecspi";
                                        reg = <0x50010000 0x4000>;
                                        interrupts = <36>;
-                                       clocks = <&clks 51>, <&clks 52>;
+                                       clocks = <&clks IMX5_CLK_ECSPI1_IPG_GATE>,
+                                                <&clks IMX5_CLK_ECSPI1_PER_GATE>;
                                        clock-names = "ipg", "per";
                                        status = "disabled";
                                };
                                        compatible = "fsl,imx53-ssi", "fsl,imx21-ssi";
                                        reg = <0x50014000 0x4000>;
                                        interrupts = <30>;
-                                       clocks = <&clks 49>;
-                                       dmas = <&sdma 24 1 0>,
-                                              <&sdma 25 1 0>;
+                                       clocks = <&clks IMX5_CLK_SSI2_IPG_GATE>;
+                                       dmas = <&sdma 24 22 0>,
+                                              <&sdma 25 22 0>;
                                        dma-names = "rx", "tx";
                                        fsl,fifo-depth = <15>;
                                        fsl,ssi-dma-events = <25 24 23 22>; /* TX0 RX0 TX1 RX1 */
                                        compatible = "fsl,imx53-esdhc";
                                        reg = <0x50020000 0x4000>;
                                        interrupts = <3>;
-                                       clocks = <&clks 46>, <&clks 0>, <&clks 73>;
+                                       clocks = <&clks IMX5_CLK_ESDHC3_IPG_GATE>,
+                                                <&clks IMX5_CLK_DUMMY>,
+                                                <&clks IMX5_CLK_ESDHC3_PER_GATE>;
                                        clock-names = "ipg", "ahb", "per";
                                        bus-width = <4>;
                                        status = "disabled";
                                        compatible = "fsl,imx53-esdhc";
                                        reg = <0x50024000 0x4000>;
                                        interrupts = <4>;
-                                       clocks = <&clks 47>, <&clks 0>, <&clks 74>;
+                                       clocks = <&clks IMX5_CLK_ESDHC4_IPG_GATE>,
+                                                <&clks IMX5_CLK_DUMMY>,
+                                                <&clks IMX5_CLK_ESDHC4_PER_GATE>;
                                        clock-names = "ipg", "ahb", "per";
                                        bus-width = <4>;
                                        status = "disabled";
 
                        usbphy0: usbphy@0 {
                                compatible = "usb-nop-xceiv";
-                               clocks = <&clks 124>;
+                               clocks = <&clks IMX5_CLK_USB_PHY1_GATE>;
                                clock-names = "main_clk";
                                status = "okay";
                        };
 
                        usbphy1: usbphy@1 {
                                compatible = "usb-nop-xceiv";
-                               clocks = <&clks 125>;
+                               clocks = <&clks IMX5_CLK_USB_PHY2_GATE>;
                                clock-names = "main_clk";
                                status = "okay";
                        };
                                compatible = "fsl,imx53-usb", "fsl,imx27-usb";
                                reg = <0x53f80000 0x0200>;
                                interrupts = <18>;
-                               clocks = <&clks 108>;
+                               clocks = <&clks IMX5_CLK_USBOH3_GATE>;
                                fsl,usbmisc = <&usbmisc 0>;
                                fsl,usbphy = <&usbphy0>;
                                status = "disabled";
                                compatible = "fsl,imx53-usb", "fsl,imx27-usb";
                                reg = <0x53f80200 0x0200>;
                                interrupts = <14>;
-                               clocks = <&clks 108>;
+                               clocks = <&clks IMX5_CLK_USBOH3_GATE>;
                                fsl,usbmisc = <&usbmisc 1>;
                                fsl,usbphy = <&usbphy1>;
                                status = "disabled";
                                compatible = "fsl,imx53-usb", "fsl,imx27-usb";
                                reg = <0x53f80400 0x0200>;
                                interrupts = <16>;
-                               clocks = <&clks 108>;
+                               clocks = <&clks IMX5_CLK_USBOH3_GATE>;
                                fsl,usbmisc = <&usbmisc 2>;
                                status = "disabled";
                        };
                                compatible = "fsl,imx53-usb", "fsl,imx27-usb";
                                reg = <0x53f80600 0x0200>;
                                interrupts = <17>;
-                               clocks = <&clks 108>;
+                               clocks = <&clks IMX5_CLK_USBOH3_GATE>;
                                fsl,usbmisc = <&usbmisc 3>;
                                status = "disabled";
                        };
                                #index-cells = <1>;
                                compatible = "fsl,imx53-usbmisc";
                                reg = <0x53f80800 0x200>;
-                               clocks = <&clks 108>;
+                               clocks = <&clks IMX5_CLK_USBOH3_GATE>;
                        };
 
                        gpio1: gpio@53f84000 {
                                #interrupt-cells = <2>;
                        };
 
+                       kpp: kpp@53f94000 {
+                               compatible = "fsl,imx53-kpp", "fsl,imx21-kpp";
+                               reg = <0x53f94000 0x4000>;
+                               interrupts = <60>;
+                               clocks = <&clks IMX5_CLK_DUMMY>;
+                               status = "disabled";
+                       };
+
                        wdog1: wdog@53f98000 {
                                compatible = "fsl,imx53-wdt", "fsl,imx21-wdt";
                                reg = <0x53f98000 0x4000>;
                                interrupts = <58>;
-                               clocks = <&clks 0>;
+                               clocks = <&clks IMX5_CLK_DUMMY>;
                        };
 
                        wdog2: wdog@53f9c000 {
                                compatible = "fsl,imx53-wdt", "fsl,imx21-wdt";
                                reg = <0x53f9c000 0x4000>;
                                interrupts = <59>;
-                               clocks = <&clks 0>;
+                               clocks = <&clks IMX5_CLK_DUMMY>;
                                status = "disabled";
                        };
 
                                compatible = "fsl,imx53-gpt", "fsl,imx31-gpt";
                                reg = <0x53fa0000 0x4000>;
                                interrupts = <39>;
-                               clocks = <&clks 36>, <&clks 41>;
+                               clocks = <&clks IMX5_CLK_GPT_IPG_GATE>,
+                                        <&clks IMX5_CLK_GPT_HF_GATE>;
                                clock-names = "ipg", "per";
                        };
 
                        iomuxc: iomuxc@53fa8000 {
                                compatible = "fsl,imx53-iomuxc";
                                reg = <0x53fa8000 0x4000>;
-
-                               audmux {
-                                       pinctrl_audmux_1: audmuxgrp-1 {
-                                               fsl,pins = <
-                                                       MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC  0x80000000
-                                                       MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD  0x80000000
-                                                       MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS 0x80000000
-                                                       MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD  0x80000000
-                                               >;
-                                       };
-
-                                       pinctrl_audmux_2: audmuxgrp-2 {
-                                               fsl,pins = <
-                                                       MX53_PAD_SD2_DATA3__AUDMUX_AUD4_TXC     0x80000000
-                                                       MX53_PAD_SD2_DATA2__AUDMUX_AUD4_TXD     0x80000000
-                                                       MX53_PAD_SD2_DATA1__AUDMUX_AUD4_TXFS    0x80000000
-                                                       MX53_PAD_SD2_DATA0__AUDMUX_AUD4_RXD     0x80000000
-                                               >;
-                                       };
-
-                                       pinctrl_audmux_3: audmuxgrp-3 {
-                                               fsl,pins = <
-                                                       MX53_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC     0x80000000
-                                                       MX53_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD     0x80000000
-                                                       MX53_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS    0x80000000
-                                                       MX53_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD     0x80000000
-                                               >;
-                                       };
-                               };
-
-                               fec {
-                                       pinctrl_fec_1: fecgrp-1 {
-                                               fsl,pins = <
-                                                       MX53_PAD_FEC_MDC__FEC_MDC        0x80000000
-                                                       MX53_PAD_FEC_MDIO__FEC_MDIO      0x80000000
-                                                       MX53_PAD_FEC_REF_CLK__FEC_TX_CLK 0x80000000
-                                                       MX53_PAD_FEC_RX_ER__FEC_RX_ER    0x80000000
-                                                       MX53_PAD_FEC_CRS_DV__FEC_RX_DV   0x80000000
-                                                       MX53_PAD_FEC_RXD1__FEC_RDATA_1   0x80000000
-                                                       MX53_PAD_FEC_RXD0__FEC_RDATA_0   0x80000000
-                                                       MX53_PAD_FEC_TX_EN__FEC_TX_EN    0x80000000
-                                                       MX53_PAD_FEC_TXD1__FEC_TDATA_1   0x80000000
-                                                       MX53_PAD_FEC_TXD0__FEC_TDATA_0   0x80000000
-                                               >;
-                                       };
-
-                                       pinctrl_fec_2: fecgrp-2 {
-                                               fsl,pins = <
-                                                       MX53_PAD_FEC_MDC__FEC_MDC        0x80000000
-                                                       MX53_PAD_FEC_MDIO__FEC_MDIO      0x80000000
-                                                       MX53_PAD_FEC_REF_CLK__FEC_TX_CLK 0x80000000
-                                                       MX53_PAD_FEC_RX_ER__FEC_RX_ER    0x80000000
-                                                       MX53_PAD_FEC_CRS_DV__FEC_RX_DV   0x80000000
-                                                       MX53_PAD_FEC_RXD1__FEC_RDATA_1   0x80000000
-                                                       MX53_PAD_FEC_RXD0__FEC_RDATA_0   0x80000000
-                                                       MX53_PAD_FEC_TX_EN__FEC_TX_EN    0x80000000
-                                                       MX53_PAD_FEC_TXD1__FEC_TDATA_1   0x80000000
-                                                       MX53_PAD_FEC_TXD0__FEC_TDATA_0   0x80000000
-                                                       MX53_PAD_KEY_ROW1__FEC_COL       0x80000000
-                                                       MX53_PAD_KEY_COL3__FEC_CRS       0x80000000
-                                                       MX53_PAD_KEY_COL2__FEC_RDATA_2   0x80000000
-                                                       MX53_PAD_KEY_COL0__FEC_RDATA_3   0x80000000
-                                                       MX53_PAD_KEY_COL1__FEC_RX_CLK    0x80000000
-                                                       MX53_PAD_KEY_ROW2__FEC_TDATA_2   0x80000000
-                                                       MX53_PAD_GPIO_19__FEC_TDATA_3    0x80000000
-                                                       MX53_PAD_KEY_ROW0__FEC_TX_ER     0x80000000
-                                               >;
-                                       };
-                               };
-
-                               csi {
-                                       pinctrl_csi_1: csigrp-1 {
-                                               fsl,pins = <
-                                                       MX53_PAD_CSI0_DATA_EN__IPU_CSI0_DATA_EN 0x1d5
-                                                       MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC     0x1d5
-                                                       MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC      0x1d5
-                                                       MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK   0x1d5
-                                                       MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19      0x1d5
-                                                       MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18      0x1d5
-                                                       MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17      0x1d5
-                                                       MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16      0x1d5
-                                                       MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15      0x1d5
-                                                       MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14      0x1d5
-                                                       MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13      0x1d5
-                                                       MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12      0x1d5
-                                                       MX53_PAD_CSI0_DAT11__IPU_CSI0_D_11      0x1d5
-                                                       MX53_PAD_CSI0_DAT10__IPU_CSI0_D_10      0x1d5
-                                                       MX53_PAD_CSI0_DAT9__IPU_CSI0_D_9        0x1d5
-                                                       MX53_PAD_CSI0_DAT8__IPU_CSI0_D_8        0x1d5
-                                                       MX53_PAD_CSI0_DAT7__IPU_CSI0_D_7        0x1d5
-                                                       MX53_PAD_CSI0_DAT6__IPU_CSI0_D_6        0x1d5
-                                                       MX53_PAD_CSI0_DAT5__IPU_CSI0_D_5        0x1d5
-                                                       MX53_PAD_CSI0_DAT4__IPU_CSI0_D_4        0x1d5
-                                                       MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK   0x1d5
-                                               >;
-                                       };
-
-                                       pinctrl_csi_2: csigrp-2 {
-                                               fsl,pins = <
-                                                       MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC     0x1d5
-                                                       MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC      0x1d5
-                                                       MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK   0x1d5
-                                                       MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19      0x1d5
-                                                       MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18      0x1d5
-                                                       MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17      0x1d5
-                                                       MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16      0x1d5
-                                                       MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15      0x1d5
-                                                       MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14      0x1d5
-                                                       MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13      0x1d5
-                                                       MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12      0x1d5
-                                               >;
-                                       };
-                               };
-
-                               cspi {
-                                       pinctrl_cspi_1: cspigrp-1 {
-                                               fsl,pins = <
-                                                       MX53_PAD_SD1_DATA0__CSPI_MISO 0x1d5
-                                                       MX53_PAD_SD1_CMD__CSPI_MOSI   0x1d5
-                                                       MX53_PAD_SD1_CLK__CSPI_SCLK   0x1d5
-                                               >;
-                                       };
-
-                                       pinctrl_cspi_2: cspigrp-2 {
-                                               fsl,pins = <
-                                                       MX53_PAD_EIM_D22__CSPI_MISO 0x1d5
-                                                       MX53_PAD_EIM_D28__CSPI_MOSI 0x1d5
-                                                       MX53_PAD_EIM_D21__CSPI_SCLK 0x1d5
-                                               >;
-                                       };
-                               };
-
-                               ecspi1 {
-                                       pinctrl_ecspi1_1: ecspi1grp-1 {
-                                               fsl,pins = <
-                                                       MX53_PAD_EIM_D16__ECSPI1_SCLK 0x80000000
-                                                       MX53_PAD_EIM_D17__ECSPI1_MISO 0x80000000
-                                                       MX53_PAD_EIM_D18__ECSPI1_MOSI 0x80000000
-                                               >;
-                                       };
-
-                                       pinctrl_ecspi1_2: ecspi1grp-2 {
-                                               fsl,pins = <
-                                                       MX53_PAD_GPIO_19__ECSPI1_RDY    0x80000000
-                                                       MX53_PAD_EIM_EB2__ECSPI1_SS0    0x80000000
-                                                       MX53_PAD_EIM_D16__ECSPI1_SCLK   0x80000000
-                                                       MX53_PAD_EIM_D17__ECSPI1_MISO   0x80000000
-                                                       MX53_PAD_EIM_D18__ECSPI1_MOSI   0x80000000
-                                                       MX53_PAD_EIM_D19__ECSPI1_SS1    0x80000000
-                                               >;
-                                       };
-                               };
-
-                               ecspi2 {
-                                       pinctrl_ecspi2_1: ecspi2grp-1 {
-                                               fsl,pins = <
-                                                       MX53_PAD_EIM_OE__ECSPI2_MISO  0x80000000
-                                                       MX53_PAD_EIM_CS1__ECSPI2_MOSI 0x80000000
-                                                       MX53_PAD_EIM_CS0__ECSPI2_SCLK 0x80000000
-                                               >;
-                                       };
-                               };
-
-                               esdhc1 {
-                                       pinctrl_esdhc1_1: esdhc1grp-1 {
-                                               fsl,pins = <
-                                                       MX53_PAD_SD1_DATA0__ESDHC1_DAT0 0x1d5
-                                                       MX53_PAD_SD1_DATA1__ESDHC1_DAT1 0x1d5
-                                                       MX53_PAD_SD1_DATA2__ESDHC1_DAT2 0x1d5
-                                                       MX53_PAD_SD1_DATA3__ESDHC1_DAT3 0x1d5
-                                                       MX53_PAD_SD1_CMD__ESDHC1_CMD    0x1d5
-                                                       MX53_PAD_SD1_CLK__ESDHC1_CLK    0x1d5
-                                               >;
-                                       };
-
-                                       pinctrl_esdhc1_2: esdhc1grp-2 {
-                                               fsl,pins = <
-                                                       MX53_PAD_SD1_DATA0__ESDHC1_DAT0   0x1d5
-                                                       MX53_PAD_SD1_DATA1__ESDHC1_DAT1   0x1d5
-                                                       MX53_PAD_SD1_DATA2__ESDHC1_DAT2   0x1d5
-                                                       MX53_PAD_SD1_DATA3__ESDHC1_DAT3   0x1d5
-                                                       MX53_PAD_PATA_DATA8__ESDHC1_DAT4  0x1d5
-                                                       MX53_PAD_PATA_DATA9__ESDHC1_DAT5  0x1d5
-                                                       MX53_PAD_PATA_DATA10__ESDHC1_DAT6 0x1d5
-                                                       MX53_PAD_PATA_DATA11__ESDHC1_DAT7 0x1d5
-                                                       MX53_PAD_SD1_CMD__ESDHC1_CMD      0x1d5
-                                                       MX53_PAD_SD1_CLK__ESDHC1_CLK      0x1d5
-                                               >;
-                                       };
-                               };
-
-                               esdhc2 {
-                                       pinctrl_esdhc2_1: esdhc2grp-1 {
-                                               fsl,pins = <
-                                                       MX53_PAD_SD2_CMD__ESDHC2_CMD    0x1d5
-                                                       MX53_PAD_SD2_CLK__ESDHC2_CLK    0x1d5
-                                                       MX53_PAD_SD2_DATA0__ESDHC2_DAT0 0x1d5
-                                                       MX53_PAD_SD2_DATA1__ESDHC2_DAT1 0x1d5
-                                                       MX53_PAD_SD2_DATA2__ESDHC2_DAT2 0x1d5
-                                                       MX53_PAD_SD2_DATA3__ESDHC2_DAT3 0x1d5
-                                               >;
-                                       };
-                               };
-
-                               esdhc3 {
-                                       pinctrl_esdhc3_1: esdhc3grp-1 {
-                                               fsl,pins = <
-                                                       MX53_PAD_PATA_DATA8__ESDHC3_DAT0  0x1d5
-                                                       MX53_PAD_PATA_DATA9__ESDHC3_DAT1  0x1d5
-                                                       MX53_PAD_PATA_DATA10__ESDHC3_DAT2 0x1d5
-                                                       MX53_PAD_PATA_DATA11__ESDHC3_DAT3 0x1d5
-                                                       MX53_PAD_PATA_DATA0__ESDHC3_DAT4  0x1d5
-                                                       MX53_PAD_PATA_DATA1__ESDHC3_DAT5  0x1d5
-                                                       MX53_PAD_PATA_DATA2__ESDHC3_DAT6  0x1d5
-                                                       MX53_PAD_PATA_DATA3__ESDHC3_DAT7  0x1d5
-                                                       MX53_PAD_PATA_RESET_B__ESDHC3_CMD 0x1d5
-                                                       MX53_PAD_PATA_IORDY__ESDHC3_CLK   0x1d5
-                                               >;
-                                       };
-                               };
-
-                               can1 {
-                                       pinctrl_can1_1: can1grp-1 {
-                                               fsl,pins = <
-                                                       MX53_PAD_PATA_INTRQ__CAN1_TXCAN 0x80000000
-                                                       MX53_PAD_PATA_DIOR__CAN1_RXCAN  0x80000000
-                                               >;
-                                       };
-
-                                       pinctrl_can1_2: can1grp-2 {
-                                               fsl,pins = <
-                                                       MX53_PAD_KEY_COL2__CAN1_TXCAN 0x80000000
-                                                       MX53_PAD_KEY_ROW2__CAN1_RXCAN 0x80000000
-                                               >;
-                                       };
-
-                                       pinctrl_can1_3: can1grp-3 {
-                                               fsl,pins = <
-                                                       MX53_PAD_GPIO_7__CAN1_TXCAN     0x80000000
-                                                       MX53_PAD_GPIO_8__CAN1_RXCAN     0x80000000
-                                               >;
-                                       };
-                               };
-
-                               can2 {
-                                       pinctrl_can2_1: can2grp-1 {
-                                               fsl,pins = <
-                                                       MX53_PAD_KEY_COL4__CAN2_TXCAN 0x80000000
-                                                       MX53_PAD_KEY_ROW4__CAN2_RXCAN 0x80000000
-                                               >;
-                                       };
-                               };
-
-                               i2c1 {
-                                       pinctrl_i2c1_1: i2c1grp-1 {
-                                               fsl,pins = <
-                                                       MX53_PAD_CSI0_DAT8__I2C1_SDA 0xc0000000
-                                                       MX53_PAD_CSI0_DAT9__I2C1_SCL 0xc0000000
-                                               >;
-                                       };
-
-                                       pinctrl_i2c1_2: i2c1grp-2 {
-                                               fsl,pins = <
-                                                       MX53_PAD_EIM_D21__I2C1_SCL      0xc0000000
-                                                       MX53_PAD_EIM_D28__I2C1_SDA      0xc0000000
-                                               >;
-                                       };
-                               };
-
-                               i2c2 {
-                                       pinctrl_i2c2_1: i2c2grp-1 {
-                                               fsl,pins = <
-                                                       MX53_PAD_KEY_ROW3__I2C2_SDA 0xc0000000
-                                                       MX53_PAD_KEY_COL3__I2C2_SCL 0xc0000000
-                                               >;
-                                       };
-
-                                       pinctrl_i2c2_2: i2c2grp-2 {
-                                               fsl,pins = <
-                                                       MX53_PAD_EIM_D16__I2C2_SDA      0xc0000000
-                                                       MX53_PAD_EIM_EB2__I2C2_SCL      0xc0000000
-                                               >;
-                                       };
-                               };
-
-                               i2c3 {
-                                       pinctrl_i2c3_1: i2c3grp-1 {
-                                               fsl,pins = <
-                                                       MX53_PAD_GPIO_6__I2C3_SDA 0xc0000000
-                                                       MX53_PAD_GPIO_5__I2C3_SCL 0xc0000000
-                                               >;
-                                       };
-                               };
-
-                               ipu_disp0 {
-                                       pinctrl_ipu_disp0_1: ipudisp0grp-1 {
-                                               fsl,pins = <
-                                               MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK 0x5
-                                               MX53_PAD_DI0_PIN15__IPU_DI0_PIN15               0x5
-                                               MX53_PAD_DI0_PIN2__IPU_DI0_PIN2         0x5
-                                               MX53_PAD_DI0_PIN3__IPU_DI0_PIN3                 0x5
-                                               MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0            0x5
-                                               MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1            0x5
-                                               MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2            0x5
-                                               MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3            0x5
-                                               MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4            0x5
-                                               MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5            0x5
-                                               MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6            0x5
-                                               MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7            0x5
-                                               MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8            0x5
-                                               MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9            0x5
-                                               MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10          0x5
-                                               MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11          0x5
-                                               MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12          0x5
-                                               MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13          0x5
-                                               MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14          0x5
-                                               MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15          0x5
-                                               MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16          0x5
-                                               MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17          0x5
-                                               MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18          0x5
-                                               MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19          0x5
-                                               MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20          0x5
-                                               MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21          0x5
-                                               MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22          0x5
-                                               MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23          0x5
-                                               >;
-                                       };
-                               };
-
-                               ipu_disp1 {
-                                       pinctrl_ipu_disp1_1: ipudisp1grp-1 {
-                                               fsl,pins = <
-                                                       MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0       0x5
-                                                       MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1       0x5
-                                                       MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2       0x5
-                                                       MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3       0x5
-                                                       MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4       0x5
-                                                       MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5       0x5
-                                                       MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6       0x5
-                                                       MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7       0x5
-                                                       MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8       0x5
-                                                       MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9       0x5
-                                                       MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10      0x5
-                                                       MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11      0x5
-                                                       MX53_PAD_EIM_A17__IPU_DISP1_DAT_12      0x5
-                                                       MX53_PAD_EIM_A18__IPU_DISP1_DAT_13      0x5
-                                                       MX53_PAD_EIM_A19__IPU_DISP1_DAT_14      0x5
-                                                       MX53_PAD_EIM_A20__IPU_DISP1_DAT_15      0x5
-                                                       MX53_PAD_EIM_A21__IPU_DISP1_DAT_16      0x5
-                                                       MX53_PAD_EIM_A22__IPU_DISP1_DAT_17      0x5
-                                                       MX53_PAD_EIM_A23__IPU_DISP1_DAT_18      0x5
-                                                       MX53_PAD_EIM_A24__IPU_DISP1_DAT_19      0x5
-                                                       MX53_PAD_EIM_D31__IPU_DISP1_DAT_20      0x5
-                                                       MX53_PAD_EIM_D30__IPU_DISP1_DAT_21      0x5
-                                                       MX53_PAD_EIM_D26__IPU_DISP1_DAT_22      0x5
-                                                       MX53_PAD_EIM_D27__IPU_DISP1_DAT_23      0x5
-                                                       MX53_PAD_EIM_A16__IPU_DI1_DISP_CLK      0x5
-                                                       MX53_PAD_EIM_DA13__IPU_DI1_D0_CS        0x5
-                                                       MX53_PAD_EIM_DA14__IPU_DI1_D1_CS        0x5
-                                                       MX53_PAD_EIM_DA15__IPU_DI1_PIN1         0x5
-                                                       MX53_PAD_EIM_DA11__IPU_DI1_PIN2         0x5
-                                                       MX53_PAD_EIM_DA12__IPU_DI1_PIN3         0x5
-                                                       MX53_PAD_EIM_A25__IPU_DI1_PIN12         0x5
-                                                       MX53_PAD_EIM_DA10__IPU_DI1_PIN15        0x5
-                                               >;
-                                       };
-                               };
-
-                               ipu_disp2 {
-                                       pinctrl_ipu_disp2_1: ipudisp2grp-1 {
-                                               fsl,pins = <
-                                                       MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0     0x80000000
-                                                       MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1     0x80000000
-                                                       MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2     0x80000000
-                                                       MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3     0x80000000
-                                                       MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK     0x80000000
-                                                       MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0     0x80000000
-                                                       MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1     0x80000000
-                                                       MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2     0x80000000
-                                                       MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3     0x80000000
-                                                       MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK     0x80000000
-                                               >;
-                                       };
-                               };
-
-                               nand {
-                                       pinctrl_nand_1: nandgrp-1 {
-                                               fsl,pins = <
-                                                       MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B     0x4
-                                                       MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B     0x4
-                                                       MX53_PAD_NANDF_CLE__EMI_NANDF_CLE       0x4
-                                                       MX53_PAD_NANDF_ALE__EMI_NANDF_ALE       0x4
-                                                       MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B     0xe0
-                                                       MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0      0xe0
-                                                       MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0      0x4
-                                                       MX53_PAD_PATA_DATA0__EMI_NANDF_D_0      0xa4
-                                                       MX53_PAD_PATA_DATA1__EMI_NANDF_D_1      0xa4
-                                                       MX53_PAD_PATA_DATA2__EMI_NANDF_D_2      0xa4
-                                                       MX53_PAD_PATA_DATA3__EMI_NANDF_D_3      0xa4
-                                                       MX53_PAD_PATA_DATA4__EMI_NANDF_D_4      0xa4
-                                                       MX53_PAD_PATA_DATA5__EMI_NANDF_D_5      0xa4
-                                                       MX53_PAD_PATA_DATA6__EMI_NANDF_D_6      0xa4
-                                                       MX53_PAD_PATA_DATA7__EMI_NANDF_D_7      0xa4
-                                               >;
-                                       };
-                               };
-
-                               owire {
-                                       pinctrl_owire_1: owiregrp-1 {
-                                               fsl,pins = <
-                                                       MX53_PAD_GPIO_18__OWIRE_LINE 0x80000000
-                                               >;
-                                       };
-                               };
-
-                               pwm1 {
-                                       pinctrl_pwm1_1: pwm1grp-1 {
-                                               fsl,pins = <
-                                                       MX53_PAD_DISP0_DAT8__PWM1_PWMO  0x5
-                                               >;
-                                       };
-                               };
-
-                               pwm2 {
-                                       pinctrl_pwm2_1: pwm2grp-1 {
-                                               fsl,pins = <
-                                                       MX53_PAD_GPIO_1__PWM2_PWMO      0x80000000
-                                               >;
-                                       };
-                               };
-
-                               uart1 {
-                                       pinctrl_uart1_1: uart1grp-1 {
-                                               fsl,pins = <
-                                                       MX53_PAD_CSI0_DAT10__UART1_TXD_MUX 0x1e4
-                                                       MX53_PAD_CSI0_DAT11__UART1_RXD_MUX 0x1e4
-                                               >;
-                                       };
-
-                                       pinctrl_uart1_2: uart1grp-2 {
-                                               fsl,pins = <
-                                                       MX53_PAD_PATA_DIOW__UART1_TXD_MUX  0x1e4
-                                                       MX53_PAD_PATA_DMACK__UART1_RXD_MUX 0x1e4
-                                               >;
-                                       };
-
-                                       pinctrl_uart1_3: uart1grp-3 {
-                                               fsl,pins = <
-                                                       MX53_PAD_PATA_RESET_B__UART1_CTS 0x1c5
-                                                       MX53_PAD_PATA_IORDY__UART1_RTS   0x1c5
-                                               >;
-                                       };
-                               };
-
-                               uart2 {
-                                       pinctrl_uart2_1: uart2grp-1 {
-                                               fsl,pins = <
-                                                       MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX 0x1e4
-                                                       MX53_PAD_PATA_DMARQ__UART2_TXD_MUX     0x1e4
-                                               >;
-                                       };
-
-                                       pinctrl_uart2_2: uart2grp-2 {
-                                               fsl,pins = <
-                                                       MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX  0x1c5
-                                                       MX53_PAD_PATA_DMARQ__UART2_TXD_MUX      0x1c5
-                                                       MX53_PAD_PATA_DIOR__UART2_RTS           0x1c5
-                                                       MX53_PAD_PATA_INTRQ__UART2_CTS          0x1c5
-                                               >;
-                                       };
-                               };
-
-                               uart3 {
-                                       pinctrl_uart3_1: uart3grp-1 {
-                                               fsl,pins = <
-                                                       MX53_PAD_PATA_CS_0__UART3_TXD_MUX 0x1e4
-                                                       MX53_PAD_PATA_CS_1__UART3_RXD_MUX 0x1e4
-                                                       MX53_PAD_PATA_DA_1__UART3_CTS     0x1e4
-                                                       MX53_PAD_PATA_DA_2__UART3_RTS     0x1e4
-                                               >;
-                                       };
-
-                                       pinctrl_uart3_2: uart3grp-2 {
-                                               fsl,pins = <
-                                                       MX53_PAD_PATA_CS_0__UART3_TXD_MUX 0x1e4
-                                                       MX53_PAD_PATA_CS_1__UART3_RXD_MUX 0x1e4
-                                               >;
-                                       };
-
-                               };
-
-                               uart4 {
-                                       pinctrl_uart4_1: uart4grp-1 {
-                                               fsl,pins = <
-                                                       MX53_PAD_KEY_COL0__UART4_TXD_MUX 0x1e4
-                                                       MX53_PAD_KEY_ROW0__UART4_RXD_MUX 0x1e4
-                                               >;
-                                       };
-                               };
-
-                               uart5 {
-                                       pinctrl_uart5_1: uart5grp-1 {
-                                               fsl,pins = <
-                                                       MX53_PAD_KEY_COL1__UART5_TXD_MUX 0x1e4
-                                                       MX53_PAD_KEY_ROW1__UART5_RXD_MUX 0x1e4
-                                               >;
-                                       };
-                               };
                        };
 
                        gpr: iomuxc-gpr@53fa8000 {
                                compatible = "fsl,imx53-ldb";
                                reg = <0x53fa8008 0x4>;
                                gpr = <&gpr>;
-                               clocks = <&clks 122>, <&clks 120>,
-                                        <&clks 115>, <&clks 116>,
-                                        <&clks 123>, <&clks 85>;
+                               clocks = <&clks IMX5_CLK_LDB_DI0_SEL>,
+                                        <&clks IMX5_CLK_LDB_DI1_SEL>,
+                                        <&clks IMX5_CLK_IPU_DI0_SEL>,
+                                        <&clks IMX5_CLK_IPU_DI1_SEL>,
+                                        <&clks IMX5_CLK_LDB_DI0_GATE>,
+                                        <&clks IMX5_CLK_LDB_DI1_GATE>;
                                clock-names = "di0_pll", "di1_pll",
                                              "di0_sel", "di1_sel",
                                              "di0", "di1";
                                #pwm-cells = <2>;
                                compatible = "fsl,imx53-pwm", "fsl,imx27-pwm";
                                reg = <0x53fb4000 0x4000>;
-                               clocks = <&clks 37>, <&clks 38>;
+                               clocks = <&clks IMX5_CLK_PWM1_IPG_GATE>,
+                                        <&clks IMX5_CLK_PWM1_HF_GATE>;
                                clock-names = "ipg", "per";
                                interrupts = <61>;
                        };
                                #pwm-cells = <2>;
                                compatible = "fsl,imx53-pwm", "fsl,imx27-pwm";
                                reg = <0x53fb8000 0x4000>;
-                               clocks = <&clks 39>, <&clks 40>;
+                               clocks = <&clks IMX5_CLK_PWM2_IPG_GATE>,
+                                        <&clks IMX5_CLK_PWM2_HF_GATE>;
                                clock-names = "ipg", "per";
                                interrupts = <94>;
                        };
                                compatible = "fsl,imx53-uart", "fsl,imx21-uart";
                                reg = <0x53fbc000 0x4000>;
                                interrupts = <31>;
-                               clocks = <&clks 28>, <&clks 29>;
+                               clocks = <&clks IMX5_CLK_UART1_IPG_GATE>,
+                                        <&clks IMX5_CLK_UART1_PER_GATE>;
                                clock-names = "ipg", "per";
                                status = "disabled";
                        };
                                compatible = "fsl,imx53-uart", "fsl,imx21-uart";
                                reg = <0x53fc0000 0x4000>;
                                interrupts = <32>;
-                               clocks = <&clks 30>, <&clks 31>;
+                               clocks = <&clks IMX5_CLK_UART2_IPG_GATE>,
+                                        <&clks IMX5_CLK_UART2_PER_GATE>;
                                clock-names = "ipg", "per";
                                status = "disabled";
                        };
                                compatible = "fsl,imx53-flexcan", "fsl,p1010-flexcan";
                                reg = <0x53fc8000 0x4000>;
                                interrupts = <82>;
-                               clocks = <&clks 158>, <&clks 157>;
+                               clocks = <&clks IMX5_CLK_CAN1_IPG_GATE>,
+                                        <&clks IMX5_CLK_CAN1_SERIAL_GATE>;
                                clock-names = "ipg", "per";
                                status = "disabled";
                        };
                                compatible = "fsl,imx53-flexcan", "fsl,p1010-flexcan";
                                reg = <0x53fcc000 0x4000>;
                                interrupts = <83>;
-                               clocks = <&clks 87>, <&clks 86>;
+                               clocks = <&clks IMX5_CLK_CAN2_IPG_GATE>,
+                                        <&clks IMX5_CLK_CAN2_SERIAL_GATE>;
                                clock-names = "ipg", "per";
                                status = "disabled";
                        };
                                compatible = "fsl,imx53-i2c", "fsl,imx21-i2c";
                                reg = <0x53fec000 0x4000>;
                                interrupts = <64>;
-                               clocks = <&clks 88>;
+                               clocks = <&clks IMX5_CLK_I2C3_GATE>;
                                status = "disabled";
                        };
 
                                compatible = "fsl,imx53-uart", "fsl,imx21-uart";
                                reg = <0x53ff0000 0x4000>;
                                interrupts = <13>;
-                               clocks = <&clks 65>, <&clks 66>;
+                               clocks = <&clks IMX5_CLK_UART4_IPG_GATE>,
+                                        <&clks IMX5_CLK_UART4_PER_GATE>;
                                clock-names = "ipg", "per";
                                status = "disabled";
                        };
                                compatible = "fsl,imx53-iim", "fsl,imx27-iim";
                                reg = <0x63f98000 0x4000>;
                                interrupts = <69>;
-                               clocks = <&clks 107>;
+                               clocks = <&clks IMX5_CLK_IIM_GATE>;
                        };
 
                        uart5: serial@63f90000 {
                                compatible = "fsl,imx53-uart", "fsl,imx21-uart";
                                reg = <0x63f90000 0x4000>;
                                interrupts = <86>;
-                               clocks = <&clks 67>, <&clks 68>;
+                               clocks = <&clks IMX5_CLK_UART5_IPG_GATE>,
+                                        <&clks IMX5_CLK_UART5_PER_GATE>;
                                clock-names = "ipg", "per";
                                status = "disabled";
                        };
                        owire: owire@63fa4000 {
                                compatible = "fsl,imx53-owire", "fsl,imx21-owire";
                                reg = <0x63fa4000 0x4000>;
-                               clocks = <&clks 159>;
+                               clocks = <&clks IMX5_CLK_OWIRE_GATE>;
                                status = "disabled";
                        };
 
                                compatible = "fsl,imx53-ecspi", "fsl,imx51-ecspi";
                                reg = <0x63fac000 0x4000>;
                                interrupts = <37>;
-                               clocks = <&clks 53>, <&clks 54>;
+                               clocks = <&clks IMX5_CLK_ECSPI2_IPG_GATE>,
+                                        <&clks IMX5_CLK_ECSPI2_PER_GATE>;
                                clock-names = "ipg", "per";
                                status = "disabled";
                        };
                                compatible = "fsl,imx53-sdma", "fsl,imx35-sdma";
                                reg = <0x63fb0000 0x4000>;
                                interrupts = <6>;
-                               clocks = <&clks 56>, <&clks 56>;
+                               clocks = <&clks IMX5_CLK_SDMA_GATE>,
+                                        <&clks IMX5_CLK_SDMA_GATE>;
                                clock-names = "ipg", "ahb";
                                #dma-cells = <3>;
                                fsl,sdma-ram-script-name = "imx/sdma/sdma-imx53.bin";
                                compatible = "fsl,imx53-cspi", "fsl,imx35-cspi";
                                reg = <0x63fc0000 0x4000>;
                                interrupts = <38>;
-                               clocks = <&clks 55>, <&clks 55>;
+                               clocks = <&clks IMX5_CLK_CSPI_IPG_GATE>,
+                                        <&clks IMX5_CLK_CSPI_IPG_GATE>;
                                clock-names = "ipg", "per";
                                status = "disabled";
                        };
                                compatible = "fsl,imx53-i2c", "fsl,imx21-i2c";
                                reg = <0x63fc4000 0x4000>;
                                interrupts = <63>;
-                               clocks = <&clks 35>;
+                               clocks = <&clks IMX5_CLK_I2C2_GATE>;
                                status = "disabled";
                        };
 
                                compatible = "fsl,imx53-i2c", "fsl,imx21-i2c";
                                reg = <0x63fc8000 0x4000>;
                                interrupts = <62>;
-                               clocks = <&clks 34>;
+                               clocks = <&clks IMX5_CLK_I2C1_GATE>;
                                status = "disabled";
                        };
 
                                compatible = "fsl,imx53-ssi", "fsl,imx21-ssi";
                                reg = <0x63fcc000 0x4000>;
                                interrupts = <29>;
-                               clocks = <&clks 48>;
+                               clocks = <&clks IMX5_CLK_SSI1_IPG_GATE>;
                                dmas = <&sdma 28 0 0>,
                                       <&sdma 29 0 0>;
                                dma-names = "rx", "tx";
                                compatible = "fsl,imx53-nand";
                                reg = <0x63fdb000 0x1000 0xf7ff0000 0x10000>;
                                interrupts = <8>;
-                               clocks = <&clks 60>;
+                               clocks = <&clks IMX5_CLK_NFC_GATE>;
                                status = "disabled";
                        };
 
                                compatible = "fsl,imx53-ssi", "fsl,imx21-ssi";
                                reg = <0x63fe8000 0x4000>;
                                interrupts = <96>;
-                               clocks = <&clks 50>;
+                               clocks = <&clks IMX5_CLK_SSI3_IPG_GATE>;
                                dmas = <&sdma 46 0 0>,
                                       <&sdma 47 0 0>;
                                dma-names = "rx", "tx";
                                compatible = "fsl,imx53-fec", "fsl,imx25-fec";
                                reg = <0x63fec000 0x4000>;
                                interrupts = <87>;
-                               clocks = <&clks 42>, <&clks 42>, <&clks 42>;
+                               clocks = <&clks IMX5_CLK_FEC_GATE>,
+                                        <&clks IMX5_CLK_FEC_GATE>,
+                                        <&clks IMX5_CLK_FEC_GATE>;
                                clock-names = "ipg", "ahb", "ptp";
                                status = "disabled";
                        };
                                compatible = "fsl,imx53-tve";
                                reg = <0x63ff0000 0x1000>;
                                interrupts = <92>;
-                               clocks = <&clks 69>, <&clks 116>;
+                               clocks = <&clks IMX5_CLK_TVE_GATE>,
+                                        <&clks IMX5_CLK_IPU_DI1_SEL>;
                                clock-names = "tve", "di_sel";
                                crtcs = <&ipu 1>;
                                status = "disabled";
                                compatible = "fsl,imx53-vpu";
                                reg = <0x63ff4000 0x1000>;
                                interrupts = <9>;
-                               clocks = <&clks 63>, <&clks 63>;
+                               clocks = <&clks IMX5_CLK_VPU_GATE>,
+                                        <&clks IMX5_CLK_VPU_GATE>;
                                clock-names = "per", "ahb";
                                iram = <&ocram>;
                                status = "disabled";
                ocram: sram@f8000000 {
                        compatible = "mmio-sram";
                        reg = <0xf8000000 0x20000>;
-                       clocks = <&clks 186>;
+                       clocks = <&clks IMX5_CLK_OCRAM>;
                };
        };
 };
diff --git a/arch/arm/boot/dts/imx6dl-gw51xx.dts b/arch/arm/boot/dts/imx6dl-gw51xx.dts
new file mode 100644 (file)
index 0000000..4bd055f
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2013 Gateworks Corporation
+ *
+ * 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 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-gw51xx.dtsi"
+
+/ {
+       model = "Gateworks Ventana i.MX6 DualLite GW51XX";
+       compatible = "gw,imx6dl-gw51xx", "gw,ventana", "fsl,imx6dl";
+};
diff --git a/arch/arm/boot/dts/imx6dl-gw52xx.dts b/arch/arm/boot/dts/imx6dl-gw52xx.dts
new file mode 100644 (file)
index 0000000..c913605
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2013 Gateworks Corporation
+ *
+ * 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 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-gw52xx.dtsi"
+
+/ {
+       model = "Gateworks Ventana i.MX6 DualLite GW52XX";
+       compatible = "gw,imx6dl-gw52xx", "gw,ventana", "fsl,imx6dl";
+};
diff --git a/arch/arm/boot/dts/imx6dl-gw53xx.dts b/arch/arm/boot/dts/imx6dl-gw53xx.dts
new file mode 100644 (file)
index 0000000..61818a1
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2013 Gateworks Corporation
+ *
+ * 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 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-gw53xx.dtsi"
+
+/ {
+       model = "Gateworks Ventana i.MX6 DualLite GW53XX";
+       compatible = "gw,imx6dl-gw53xx", "gw,ventana", "fsl,imx6dl";
+};
diff --git a/arch/arm/boot/dts/imx6dl-gw54xx.dts b/arch/arm/boot/dts/imx6dl-gw54xx.dts
new file mode 100644 (file)
index 0000000..ab38b67
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2013 Gateworks Corporation
+ *
+ * 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 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-gw54xx.dtsi"
+
+/ {
+       model = "Gateworks Ventana i.MX6 DualLite GW54XX";
+       compatible = "gw,imx6dl-gw54xx", "gw,ventana", "fsl,imx6dl";
+};
index b81a7a4ebab6758926143ebd51d59b033a51df23..7499eee1dc923f3d28698bb173ae458711a9b62d 100644 (file)
 #define MX6QDL_PAD_RGMII_TXC__GPIO6_IO19            0x2d8 0x6c0 0x000 0x5 0x0
 #define MX6QDL_PAD_RGMII_TXC__XTALOSC_REF_CLK_24M   0x2d8 0x6c0 0x000 0x7 0x0
 #define MX6QDL_PAD_SD1_CLK__SD1_CLK                 0x2dc 0x6c4 0x928 0x0 0x1
+#define MX6QDL_PAD_SD1_CLK__OSC32K_32K_OUT          0x2dc 0x6c4 0x000 0x2 0x0
 #define MX6QDL_PAD_SD1_CLK__GPT_CLKIN               0x2dc 0x6c4 0x000 0x3 0x0
 #define MX6QDL_PAD_SD1_CLK__GPIO1_IO20              0x2dc 0x6c4 0x000 0x5 0x0
 #define MX6QDL_PAD_SD1_CMD__SD1_CMD                 0x2e0 0x6c8 0x000 0x0 0x0
index 9e8ae118fdd4e6c6c1df48a0b4a66c20e0504ae6..b2f2699e6dcaa0cfa3dd7bbaad1e678ee3993b5d 100644 (file)
@@ -8,7 +8,9 @@
  *
  */
 
+#include <dt-bindings/interrupt-controller/irq.h>
 #include "imx6dl-pinfunc.h"
+#include "imx6qdl-pingrp.h"
 #include "imx6qdl.dtsi"
 
 / {
 
                        pxp: pxp@020f0000 {
                                reg = <0x020f0000 0x4000>;
-                               interrupts = <0 98 0x04>;
+                               interrupts = <0 98 IRQ_TYPE_LEVEL_HIGH>;
                        };
 
                        epdc: epdc@020f4000 {
                                reg = <0x020f4000 0x4000>;
-                               interrupts = <0 97 0x04>;
+                               interrupts = <0 97 IRQ_TYPE_LEVEL_HIGH>;
                        };
 
                        lcdif: lcdif@020f8000 {
                                reg = <0x020f8000 0x4000>;
-                               interrupts = <0 39 0x04>;
+                               interrupts = <0 39 IRQ_TYPE_LEVEL_HIGH>;
                        };
                };
 
@@ -65,7 +67,7 @@
                                #size-cells = <0>;
                                compatible = "fsl,imx1-i2c";
                                reg = <0x021f8000 0x4000>;
-                               interrupts = <0 35 0x04>;
+                               interrupts = <0 35 IRQ_TYPE_LEVEL_HIGH>;
                                status = "disabled";
                        };
                };
index edf1bd9671642e9230b61d71c55a18a7b7c2a554..9c00b739dc3024371263c0195909647eff1369ae 100644 (file)
 
        regulators {
                compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
 
-               reg_3p3v: 3p3v {
+               reg_3p3v: regulator@0 {
                        compatible = "regulator-fixed";
+                       reg = <0>;
                        regulator-name = "3P3V";
                        regulator-min-microvolt = <3300000>;
                        regulator-max-microvolt = <3300000>;
                        regulator-always-on;
                };
+
+               reg_usb_otg_vbus: regulator@1 {
+                       compatible = "regulator-fixed";
+                       reg = <1>;
+                       regulator-name = "usb_otg_vbus";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       gpio = <&gpio3 22 0>;
+                       enable-active-high;
+               };
        };
 
        leds {
@@ -46,7 +59,7 @@
 
 &gpmi {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_gpmi_nand_1>;
+       pinctrl-0 = <&pinctrl_gpmi_nand>;
        status = "disabled"; /* gpmi nand conflicts with SD */
 };
 
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_hog>;
 
-       hog {
+       imx6q-arm2 {
                pinctrl_hog: hoggrp {
                        fsl,pins = <
                                MX6QDL_PAD_EIM_D25__GPIO3_IO25 0x80000000
                        >;
                };
-       };
 
-       arm2 {
-               pinctrl_usdhc3_arm2: usdhc3grp-arm2 {
+               pinctrl_enet: enetgrp {
+                       fsl,pins = <MX6QDL_ENET_PINGRP2>;
+               };
+
+               pinctrl_gpmi_nand: gpminandgrp {
+                       fsl,pins = <MX6QDL_GPMI_NAND_PINGRP1>;
+               };
+
+               pinctrl_uart2: uart2grp {
+                       fsl,pins = <MX6QDL_UART2_PINGRP2>;
+               };
+
+               pinctrl_uart4: uart4grp {
+                       fsl,pins = <MX6QDL_UART4_PINGRP1>;
+               };
+
+               pinctrl_usbotg: usbotggrp {
+                       fsl,pins = <MX6QDL_USBOTG_PINGRP1>;
+               };
+
+               pinctrl_usdhc3: usdhc3grp {
+                       fsl,pins = <MX6QDL_USDHC3_PINGRP_D8>;
+               };
+
+               pinctrl_usdhc3_cdwp: usdhc3cdwp {
                        fsl,pins = <
                                MX6QDL_PAD_NANDF_CS0__GPIO6_IO11 0x80000000
                                MX6QDL_PAD_NANDF_CS1__GPIO6_IO14 0x80000000
                        >;
                };
+
+               pinctrl_usdhc4: usdhc4grp {
+                       fsl,pins = <MX6QDL_USDHC4_PINGRP_D8>;
+               };
        };
 };
 
 &fec {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_enet_2>;
+       pinctrl-0 = <&pinctrl_enet>;
        phy-mode = "rgmii";
        status = "okay";
 };
 
+&usbotg {
+       vbus-supply = <&reg_usb_otg_vbus>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usbotg>;
+       disable-over-current;
+       status = "okay";
+};
+
 &usdhc3 {
        cd-gpios = <&gpio6 11 0>;
        wp-gpios = <&gpio6 14 0>;
        vmmc-supply = <&reg_3p3v>;
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_usdhc3_1
-                    &pinctrl_usdhc3_arm2>;
+       pinctrl-0 = <&pinctrl_usdhc3
+                    &pinctrl_usdhc3_cdwp>;
        status = "okay";
 };
 
        non-removable;
        vmmc-supply = <&reg_3p3v>;
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_usdhc4_1>;
+       pinctrl-0 = <&pinctrl_usdhc4>;
        status = "okay";
 };
 
 &uart2 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_uart2_2>;
+       pinctrl-0 = <&pinctrl_uart2>;
        fsl,dte-mode;
        fsl,uart-has-rtscts;
        status = "okay";
 
 &uart4 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_uart4_1>;
+       pinctrl-0 = <&pinctrl_uart4>;
        status = "okay";
 };
diff --git a/arch/arm/boot/dts/imx6q-cm-fx6.dts b/arch/arm/boot/dts/imx6q-cm-fx6.dts
new file mode 100644 (file)
index 0000000..1a8ee79
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2013 CompuLab Ltd.
+ *
+ * Author: Valentin Raevsky <valentin@compulab.co.il>
+ *
+ * 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 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+
+/ {
+       model = "CompuLab CM-FX6";
+       compatible = "compulab,cm-fx6", "fsl,imx6q";
+
+       memory {
+               reg = <0x10000000 0x80000000>;
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               heartbeat-led {
+                       label = "Heartbeat";
+                       gpios = <&gpio2 31 0>;
+                       linux,default-trigger = "heartbeat";
+               };
+       };
+};
+
+&fec {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_enet>;
+       phy-mode = "rgmii";
+       status = "okay";
+};
+
+&gpmi {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_gpmi_nand>;
+       status = "okay";
+};
+
+&iomuxc {
+       imx6q-cm-fx6 {
+               pinctrl_enet: enetgrp {
+                       fsl,pins = <MX6QDL_ENET_PINGRP1>;
+               };
+
+               pinctrl_gpmi_nand: gpminandgrp {
+                       fsl,pins = <MX6QDL_GPMI_NAND_PINGRP1>;
+               };
+
+               pinctrl_uart4: uart4grp {
+                       fsl,pins = <MX6QDL_UART4_PINGRP1>;
+               };
+       };
+};
+
+&uart4 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart4>;
+       status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts b/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts
new file mode 100644 (file)
index 0000000..84f5143
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2013 Data Modul AG
+ *
+ * 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 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+
+#include "imx6q.dtsi"
+
+/ {
+       model = "Data Modul eDM-QMX6 Board";
+       compatible = "dmo,imx6q-edmqmx6", "fsl,imx6q";
+
+       aliases {
+               gpio7 = &stmpe_gpio;
+       };
+
+       memory {
+               reg = <0x10000000 0x80000000>;
+       };
+
+       regulators {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               reg_3p3v: regulator@0 {
+                       compatible = "regulator-fixed";
+                       reg = <0>;
+                       regulator-name = "3P3V";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+               };
+
+               reg_usb_otg_vbus: regulator@1 {
+                       compatible = "regulator-fixed";
+                       reg = <1>;
+                       regulator-name = "usb_otg_vbus";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       gpio = <&gpio7 12 0>;
+               };
+
+               reg_usb_host1: regulator@2 {
+                       compatible = "regulator-fixed";
+                       reg = <2>;
+                       regulator-name = "usb_host1_en";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       gpio = <&gpio3 31 0>;
+                       enable-active-high;
+               };
+       };
+};
+
+&fec {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_enet>;
+       phy-mode = "rgmii";
+       phy-reset-gpios = <&gpio3 23 0>;
+       status = "okay";
+};
+
+&i2c2 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c2
+                    &pinctrl_stmpe>;
+       status = "okay";
+
+       stmpe: stmpe1601@40 {
+               compatible = "st,stmpe1601";
+               reg = <0x40>;
+               interrupts = <30 0>;
+               interrupt-parent = <&gpio3>;
+
+               stmpe_gpio: stmpe_gpio {
+                       compatible = "st,stmpe-gpio";
+               };
+       };
+
+       temp1: ad7414@4c {
+               compatible = "ad,ad7414";
+               reg = <0x4c>;
+       };
+
+       temp2: ad7414@4d {
+               compatible = "ad,ad7414";
+               reg = <0x4d>;
+       };
+
+       rtc: m41t62@68 {
+               compatible = "stm,m41t62";
+               reg = <0x68>;
+       };
+};
+
+&iomuxc {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_hog>;
+
+       imx6q-dmo-edmqmx6 {
+               pinctrl_hog: hoggrp {
+                       fsl,pins = <
+                               MX6QDL_PAD_EIM_A16__GPIO2_IO22 0x80000000
+                               MX6QDL_PAD_EIM_A17__GPIO2_IO21 0x80000000
+                       >;
+               };
+
+               pinctrl_enet: enetgrp {
+                       fsl,pins = <MX6QDL_ENET_PINGRP1>;
+               };
+
+               pinctrl_i2c2: i2c2grp {
+                       fsl,pins = <MX6QDL_I2C2_PINGRP3>;
+               };
+
+               pinctrl_stmpe: stmpegrp {
+                       fsl,pins = <MX6QDL_PAD_EIM_D30__GPIO3_IO30 0x80000000>;
+               };
+
+               pinctrl_uart1: uart1grp {
+                       fsl,pins = <MX6QDL_UART1_PINGRP2>;
+               };
+
+               pinctrl_uart2: uart2grp {
+                       fsl,pins = <MX6QDL_UART2_PINGRP1>;
+               };
+
+               pinctrl_usbotg: usbotggrp {
+                       fsl,pins = <MX6QDL_USBOTG_PINGRP1>;
+               };
+
+               pinctrl_usdhc3: usdhc3grp {
+                       fsl,pins = <MX6QDL_USDHC3_PINGRP_D4>;
+               };
+       };
+};
+
+&uart1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart1>;
+       status = "okay";
+};
+
+&uart2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart2>;
+       status = "okay";
+};
+
+&usbh1 {
+       vbus-supply = <&reg_usb_host1>;
+       disable-over-current;
+       status = "okay";
+};
+
+&usbotg {
+       vbus-supply = <&reg_usb_otg_vbus>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usbotg>;
+       disable-over-current;
+       status = "okay";
+};
+
+&usdhc3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usdhc3>;
+       vmmc-supply = <&reg_3p3v>;
+       status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6q-gw51xx.dts b/arch/arm/boot/dts/imx6q-gw51xx.dts
new file mode 100644 (file)
index 0000000..af4929a
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2013 Gateworks Corporation
+ *
+ * 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 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-gw54xx.dtsi"
+
+/ {
+       model = "Gateworks Ventana i.MX6 Quad GW51XX";
+       compatible = "gw,imx6q-gw51xx", "gw,ventana", "fsl,imx6q";
+};
diff --git a/arch/arm/boot/dts/imx6q-gw52xx.dts b/arch/arm/boot/dts/imx6q-gw52xx.dts
new file mode 100644 (file)
index 0000000..5f71ddb
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2013 Gateworks Corporation
+ *
+ * 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 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-gw52xx.dtsi"
+
+/ {
+       model = "Gateworks Ventana i.MX6 Quad GW52XX";
+       compatible = "gw,imx6q-gw52xx", "gw,ventana", "fsl,imx6q";
+};
+
+&sata {
+       status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6q-gw53xx.dts b/arch/arm/boot/dts/imx6q-gw53xx.dts
new file mode 100644 (file)
index 0000000..360c316
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2013 Gateworks Corporation
+ *
+ * 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 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-gw53xx.dtsi"
+
+/ {
+       model = "Gateworks Ventana i.MX6 Quad GW53XX";
+       compatible = "gw,imx6q-gw53xx", "gw,ventana", "fsl,imx6q";
+};
+
+&sata {
+       status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6q-gw5400-a.dts b/arch/arm/boot/dts/imx6q-gw5400-a.dts
new file mode 100644 (file)
index 0000000..5f76342
--- /dev/null
@@ -0,0 +1,493 @@
+/*
+ * Copyright 2013 Gateworks Corporation
+ *
+ * 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 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+
+/ {
+       model = "Gateworks Ventana GW5400-A";
+       compatible = "gw,imx6q-gw5400-a", "gw,ventana", "fsl,imx6q";
+
+       /* these are used by bootloader for disabling nodes */
+       aliases {
+               ethernet0 = &fec;
+               ethernet1 = &eth1;
+               i2c0 = &i2c1;
+               i2c1 = &i2c2;
+               i2c2 = &i2c3;
+               led0 = &led0;
+               led1 = &led1;
+               led2 = &led2;
+               sky2 = &eth1;
+               ssi0 = &ssi1;
+               spi0 = &ecspi1;
+               usb0 = &usbh1;
+               usb1 = &usbotg;
+               usdhc2 = &usdhc3;
+       };
+
+       chosen {
+               bootargs = "console=ttymxc1,115200";
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               led0: user1 {
+                       label = "user1";
+                       gpios = <&gpio4 6 0>; /* 102 -> MX6_PANLEDG */
+                       default-state = "on";
+                       linux,default-trigger = "heartbeat";
+               };
+
+               led1: user2 {
+                       label = "user2";
+                       gpios = <&gpio4 10 0>; /* 106 -> MX6_PANLEDR */
+                       default-state = "off";
+               };
+
+               led2: user3 {
+                       label = "user3";
+                       gpios = <&gpio4 15 1>; /* 111 -> MX6_LOCLED# */
+                       default-state = "off";
+               };
+       };
+
+       memory {
+               reg = <0x10000000 0x40000000>;
+       };
+
+       pps {
+               compatible = "pps-gpio";
+               gpios = <&gpio1 5 0>;
+               status = "okay";
+       };
+
+       regulators {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               reg_1p0v: regulator@0 {
+                       compatible = "regulator-fixed";
+                       reg = <0>;
+                       regulator-name = "1P0V";
+                       regulator-min-microvolt = <1000000>;
+                       regulator-max-microvolt = <1000000>;
+                       regulator-always-on;
+               };
+
+               reg_3p3v: regulator@1 {
+                       compatible = "regulator-fixed";
+                       reg = <1>;
+                       regulator-name = "3P3V";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+               };
+
+               reg_usb_h1_vbus: regulator@2 {
+                       compatible = "regulator-fixed";
+                       reg = <2>;
+                       regulator-name = "usb_h1_vbus";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       regulator-always-on;
+               };
+
+               reg_usb_otg_vbus: regulator@3 {
+                       compatible = "regulator-fixed";
+                       reg = <3>;
+                       regulator-name = "usb_otg_vbus";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       gpio = <&gpio3 22 0>;
+                       enable-active-high;
+               };
+       };
+
+       sound {
+               compatible = "fsl,imx6q-sabrelite-sgtl5000",
+                            "fsl,imx-audio-sgtl5000";
+               model = "imx6q-sabrelite-sgtl5000";
+               ssi-controller = <&ssi1>;
+               audio-codec = <&codec>;
+               audio-routing =
+                       "MIC_IN", "Mic Jack",
+                       "Mic Jack", "Mic Bias",
+                       "Headphone Jack", "HP_OUT";
+               mux-int-port = <1>;
+               mux-ext-port = <4>;
+       };
+};
+
+&audmux {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_audmux>;
+       status = "okay";
+};
+
+&ecspi1 {
+       fsl,spi-num-chipselects = <1>;
+       cs-gpios = <&gpio3 19 0>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_ecspi1>;
+       status = "okay";
+
+       flash: m25p80@0 {
+               compatible = "sst,w25q256";
+               spi-max-frequency = <30000000>;
+               reg = <0>;
+       };
+};
+
+&fec {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_enet>;
+       phy-mode = "rgmii";
+       phy-reset-gpios = <&gpio1 30 0>;
+       status = "okay";
+};
+
+&i2c1 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c1>;
+       status = "okay";
+
+       eeprom1: eeprom@50 {
+               compatible = "atmel,24c02";
+               reg = <0x50>;
+               pagesize = <16>;
+       };
+
+       eeprom2: eeprom@51 {
+               compatible = "atmel,24c02";
+               reg = <0x51>;
+               pagesize = <16>;
+       };
+
+       eeprom3: eeprom@52 {
+               compatible = "atmel,24c02";
+               reg = <0x52>;
+               pagesize = <16>;
+       };
+
+       eeprom4: eeprom@53 {
+               compatible = "atmel,24c02";
+               reg = <0x53>;
+               pagesize = <16>;
+       };
+
+       gpio: pca9555@23 {
+               compatible = "nxp,pca9555";
+               reg = <0x23>;
+               gpio-controller;
+               #gpio-cells = <2>;
+       };
+
+       hwmon: gsc@29 {
+               compatible = "gw,gsp";
+               reg = <0x29>;
+       };
+
+       rtc: ds1672@68 {
+               compatible = "dallas,ds1672";
+               reg = <0x68>;
+       };
+};
+
+&i2c2 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c2>;
+       status = "okay";
+
+       pmic: pfuze100@08 {
+               compatible = "fsl,pfuze100";
+               reg = <0x08>;
+
+               regulators {
+                       sw1a_reg: sw1ab {
+                               regulator-min-microvolt = <300000>;
+                               regulator-max-microvolt = <1875000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                               regulator-ramp-delay = <6250>;
+                       };
+
+                       sw1c_reg: sw1c {
+                               regulator-min-microvolt = <300000>;
+                               regulator-max-microvolt = <1875000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                               regulator-ramp-delay = <6250>;
+                       };
+
+                       sw2_reg: sw2 {
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <3950000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       sw3a_reg: sw3a {
+                               regulator-min-microvolt = <400000>;
+                               regulator-max-microvolt = <1975000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       sw3b_reg: sw3b {
+                               regulator-min-microvolt = <400000>;
+                               regulator-max-microvolt = <1975000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       sw4_reg: sw4 {
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <3300000>;
+                       };
+
+                       swbst_reg: swbst {
+                               regulator-min-microvolt = <5000000>;
+                               regulator-max-microvolt = <5150000>;
+                       };
+
+                       snvs_reg: vsnvs {
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <3000000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       vref_reg: vrefddr {
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       vgen1_reg: vgen1 {
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <1550000>;
+                       };
+
+                       vgen2_reg: vgen2 {
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <1550000>;
+                       };
+
+                       vgen3_reg: vgen3 {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3300000>;
+                       };
+
+                       vgen4_reg: vgen4 {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-always-on;
+                       };
+
+                       vgen5_reg: vgen5 {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-always-on;
+                       };
+
+                       vgen6_reg: vgen6 {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-always-on;
+                       };
+               };
+       };
+
+       pciswitch: pex8609@3f {
+               compatible = "plx,pex8609";
+               reg = <0x3f>;
+       };
+
+       pciclkgen: si52147@6b {
+               compatible = "sil,si52147";
+               reg = <0x6b>;
+       };
+};
+
+&i2c3 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c3>;
+       status = "okay";
+
+       accelerometer: mma8450@1c {
+               compatible = "fsl,mma8450";
+               reg = <0x1c>;
+       };
+
+       codec: sgtl5000@0a {
+               compatible = "fsl,sgtl5000";
+               reg = <0x0a>;
+               clocks = <&clks 201>;
+               VDDA-supply = <&sw4_reg>;
+               VDDIO-supply = <&reg_3p3v>;
+       };
+
+       hdmiin: adv7611@4c {
+               compatible = "adi,adv7611";
+               reg = <0x4c>;
+       };
+
+       touchscreen: egalax_ts@04 {
+               compatible = "eeti,egalax_ts";
+               reg = <0x04>;
+               interrupt-parent = <&gpio7>;
+               interrupts = <12 2>; /* gpio7_12 active low */
+               wakeup-gpios = <&gpio7 12 0>;
+       };
+
+       videoout: adv7393@2a {
+               compatible = "adi,adv7393";
+               reg = <0x2a>;
+       };
+
+       videoin: adv7180@20 {
+               compatible = "adi,adv7180";
+               reg = <0x20>;
+       };
+};
+
+&iomuxc {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_hog>;
+
+       imx6q-gw5400-a {
+               pinctrl_hog: hoggrp {
+                       fsl,pins = <
+                               MX6QDL_PAD_EIM_D22__GPIO3_IO22    0x80000000 /* OTG_PWR_EN */
+                               MX6QDL_PAD_EIM_D19__GPIO3_IO19    0x80000000 /* SPINOR_CS0# */
+                               MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28 0x80000000 /* PCIE IRQ */
+                               MX6QDL_PAD_ENET_TXD1__GPIO1_IO29  0x80000000 /* PCIE RST */
+                               MX6QDL_PAD_GPIO_0__CCM_CLKO1      0x000130b0 /* AUD4_MCK */
+                               MX6QDL_PAD_GPIO_5__GPIO1_IO05     0x80000000 /* GPS_PPS */
+                               MX6QDL_PAD_GPIO_17__GPIO7_IO12    0x80000000 /* TOUCH_IRQ# */
+                               MX6QDL_PAD_KEY_COL0__GPIO4_IO06   0x80000000 /* user1 led */
+                               MX6QDL_PAD_KEY_COL2__GPIO4_IO10   0x80000000 /* user2 led */
+                               MX6QDL_PAD_KEY_ROW4__GPIO4_IO15   0x80000000 /* user3 led */
+                               MX6QDL_PAD_SD1_DAT0__GPIO1_IO16   0x80000000 /* USBHUB_RST# */
+                               MX6QDL_PAD_SD1_DAT3__GPIO1_IO21   0x80000000 /* MIPI_DIO */
+                        >;
+               };
+
+               pinctrl_audmux: audmuxgrp {
+                       fsl,pins = <MX6QDL_AUDMUX_PINGRP1>;
+               };
+
+               pinctrl_ecspi1: ecspi1grp {
+                       fsl,pins = <MX6QDL_ECSPI1_PINGRP1>;
+               };
+
+               pinctrl_enet: enetgrp {
+                       fsl,pins = <MX6QDL_ENET_PINGRP1>;
+               };
+
+               pinctrl_i2c1: i2c1grp {
+                       fsl,pins = <MX6QDL_I2C1_PINGRP1>;
+               };
+
+               pinctrl_i2c2: i2c2grp {
+                       fsl,pins = <MX6QDL_I2C2_PINGRP2>;
+               };
+
+               pinctrl_i2c3: i2c3grp {
+                       fsl,pins = <MX6QDL_I2C3_PINGRP2>;
+               };
+
+               pinctrl_uart1: uart1grp {
+                       fsl,pins = <MX6QDL_UART1_PINGRP2>;
+               };
+
+               pinctrl_uart2: uart2grp {
+                       fsl,pins = <MX6QDL_UART2_PINGRP3>;
+               };
+
+               pinctrl_uart5: uart5grp {
+                       fsl,pins = <MX6QDL_UART5_PINGRP1>;
+               };
+
+               pinctrl_usbotg: usbotggrp {
+                       fsl,pins = <MX6QDL_USBOTG_PINGRP1>;
+               };
+
+               pinctrl_usdhc3: usdhc3grp {
+                       fsl,pins = <MX6QDL_USDHC3_PINGRP_D4>;
+               };
+       };
+};
+
+&ldb {
+       status = "okay";
+       lvds-channel@0 {
+               crtcs = <&ipu1 0>, <&ipu1 1>, <&ipu2 0>, <&ipu2 1>;
+       };
+};
+
+&pcie {
+       reset-gpio = <&gpio1 29 0>;
+       status = "okay";
+
+       eth1: sky2@8 { /* MAC/PHY on bus 8 */
+               compatible = "marvell,sky2";
+       };
+};
+
+&ssi1 {
+       fsl,mode = "i2s-slave";
+       status = "okay";
+};
+
+&uart1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart1>;
+       status = "okay";
+};
+
+&uart2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart2>;
+       status = "okay";
+};
+
+&uart5 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart5>;
+       status = "okay";
+};
+
+&usbotg {
+       vbus-supply = <&reg_usb_otg_vbus>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usbotg>;
+       disable-over-current;
+       status = "okay";
+};
+
+&usbh1 {
+       vbus-supply = <&reg_usb_h1_vbus>;
+       status = "okay";
+};
+
+&usdhc3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usdhc3>;
+       cd-gpios = <&gpio7 0 0>;
+       vmmc-supply = <&reg_3p3v>;
+       status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6q-gw54xx.dts b/arch/arm/boot/dts/imx6q-gw54xx.dts
new file mode 100644 (file)
index 0000000..ab518d6
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2013 Gateworks Corporation
+ *
+ * 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 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-gw54xx.dtsi"
+
+/ {
+       model = "Gateworks Ventana i.MX6 Quad GW54XX";
+       compatible = "gw,imx6q-gw54xx", "gw,ventana", "fsl,imx6q";
+};
+
+&sata {
+       status = "okay";
+};
index 1a3b50d4d8fa4632afb7e8bc28a215b389f50e26..05b4796b1318d9b865cb60ca16114b7a92f05682 100644 (file)
@@ -22,7 +22,7 @@
 
 &ecspi3 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_ecspi3_1>;
+       pinctrl-0 = <&pinctrl_ecspi3>;
        status = "okay";
        fsl,spi-num-chipselects = <1>;
        cs-gpios = <&gpio4 24 0>;
@@ -36,7 +36,7 @@
 
 &i2c1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_i2c1_1>;
+       pinctrl-0 = <&pinctrl_i2c1>;
        status = "okay";
 
        eeprom@50 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_hog>;
 
-       hog {
+       imx6q-phytec-pfla02 {
                pinctrl_hog: hoggrp {
                        fsl,pins = <
                                MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x80000000
                                MX6QDL_PAD_DI0_PIN15__GPIO4_IO17  0x80000000 /* PMIC interrupt */
                        >;
                };
-       };
 
-       pfla02 {
-               pinctrl_usdhc3_pfla02: usdhc3grp-pfla02 {
+               pinctrl_ecspi3: ecspi3grp {
+                       fsl,pins = <MX6QDL_ECSPI3_PINGRP1>;
+               };
+
+               pinctrl_enet: enetgrp {
+                       fsl,pins = <MX6QDL_ENET_PINGRP3>;
+               };
+
+               pinctrl_i2c1: i2c1grp {
+                       fsl,pins = <MX6QDL_I2C1_PINGRP1>;
+               };
+
+               pinctrl_uart4: uart4grp {
+                       fsl,pins = <MX6QDL_UART4_PINGRP1>;
+               };
+
+               pinctrl_usdhc2: usdhc2grp {
+                       fsl,pins = <MX6QDL_USDHC2_PINGRP_D4>;
+               };
+
+               pinctrl_usdhc3: usdhc3grp {
+                       fsl,pins = <MX6QDL_USDHC3_PINGRP_D4>;
+               };
+
+               pinctrl_usdhc3_cdwp: usdhc3cdwp {
                        fsl,pins = <
                                MX6QDL_PAD_ENET_RXD0__GPIO1_IO27 0x80000000
                                MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000
 
 &fec {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_enet_3>;
+       pinctrl-0 = <&pinctrl_enet>;
        phy-mode = "rgmii";
        phy-reset-gpios = <&gpio3 23 0>;
        status = "disabled";
 
 &uart4 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_uart4_1>;
+       pinctrl-0 = <&pinctrl_uart4>;
        status = "disabled";
 };
 
 &usdhc2 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_usdhc2_2>;
+       pinctrl-0 = <&pinctrl_usdhc2>;
        cd-gpios = <&gpio1 4 0>;
        wp-gpios = <&gpio1 2 0>;
        status = "disabled";
 
 &usdhc3 {
         pinctrl-names = "default";
-        pinctrl-0 = <&pinctrl_usdhc3_2
-                    &pinctrl_usdhc3_pfla02>;
+        pinctrl-0 = <&pinctrl_usdhc3
+                    &pinctrl_usdhc3_cdwp>;
         cd-gpios = <&gpio1 27 0>;
         wp-gpios = <&gpio1 29 0>;
         status = "disabled";
index 97ed0816a6e0c749b5bccd2562b2cbe8655ff326..e5834b2110cf40dc0e2830c23512732a65602573 100644 (file)
 #define MX6QDL_PAD_SD1_DAT2__WDOG1_RESET_B_DEB      0x34c 0x734 0x000 0x6 0x0
 #define MX6QDL_PAD_SD1_CLK__SD1_CLK                 0x350 0x738 0x000 0x0 0x0
 #define MX6QDL_PAD_SD1_CLK__ECSPI5_SCLK             0x350 0x738 0x828 0x1 0x0
+#define MX6QDL_PAD_SD1_CLK__OSC32K_32K_OUT          0x350 0x738 0x000 0x2 0x0
 #define MX6QDL_PAD_SD1_CLK__GPT_CLKIN               0x350 0x738 0x000 0x3 0x0
 #define MX6QDL_PAD_SD1_CLK__GPIO1_IO20              0x350 0x738 0x000 0x5 0x0
 #define MX6QDL_PAD_SD2_CLK__SD2_CLK                 0x354 0x73c 0x000 0x0 0x0
index f004913f7d80a1f2c0df7b229f7a011b17399818..fca8f22091466d204f2670081af858b04d3a477e 100644 (file)
 
        regulators {
                compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
 
-               reg_2p5v: 2p5v {
+               reg_2p5v: regulator@0 {
                        compatible = "regulator-fixed";
+                       reg = <0>;
                        regulator-name = "2P5V";
                        regulator-min-microvolt = <2500000>;
                        regulator-max-microvolt = <2500000>;
                        regulator-always-on;
                };
 
-               reg_3p3v: 3p3v {
+               reg_3p3v: regulator@1 {
                        compatible = "regulator-fixed";
+                       reg = <1>;
                        regulator-name = "3P3V";
                        regulator-min-microvolt = <3300000>;
                        regulator-max-microvolt = <3300000>;
                        regulator-always-on;
                };
 
-               reg_usb_otg_vbus: usb_otg_vbus {
+               reg_usb_otg_vbus: regulator@2 {
                        compatible = "regulator-fixed";
+                       reg = <2>;
                        regulator-name = "usb_otg_vbus";
                        regulator-min-microvolt = <5000000>;
                        regulator-max-microvolt = <5000000>;
 };
 
 &audmux {
-       status = "okay";
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_audmux_1>;
+       pinctrl-0 = <&pinctrl_audmux>;
+       status = "okay";
 };
 
 &ecspi1 {
        fsl,spi-num-chipselects = <1>;
        cs-gpios = <&gpio3 19 0>;
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_ecspi1_1>;
+       pinctrl-0 = <&pinctrl_ecspi1>;
        status = "okay";
 
        flash: m25p80@0 {
 
 &fec {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_enet_1>;
+       pinctrl-0 = <&pinctrl_enet>;
        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>;
+       pinctrl-0 = <&pinctrl_i2c1>;
+       status = "okay";
 
        codec: sgtl5000@0a {
                compatible = "fsl,sgtl5000";
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_hog>;
 
-       hog {
+       imx6q-sabrelite {
                pinctrl_hog: hoggrp {
                        fsl,pins = <
                                MX6QDL_PAD_NANDF_D6__GPIO2_IO06 0x80000000
                                MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x80000000
                                MX6QDL_PAD_SD3_DAT4__GPIO7_IO01 0x1f0b0
                                MX6QDL_PAD_GPIO_0__CCM_CLKO1    0x80000000
-                               MX6QDL_PAD_EIM_D23__GPIO3_IO23  0x80000000
                        >;
                };
+
+               pinctrl_audmux: audmuxgrp {
+                       fsl,pins = <MX6QDL_AUDMUX_PINGRP1>;
+               };
+
+               pinctrl_ecspi1: ecspi1grp {
+                       fsl,pins = <MX6QDL_ECSPI1_PINGRP1>;
+               };
+
+               pinctrl_enet: enetgrp {
+                       fsl,pins = <MX6QDL_ENET_PINGRP1>;
+               };
+
+               pinctrl_i2c1: i2c1grp {
+                       fsl,pins = <MX6QDL_I2C1_PINGRP1>;
+               };
+
+               pinctrl_uart2: uart2grp {
+                       fsl,pins = <MX6QDL_UART2_PINGRP1>;
+               };
+
+               pinctrl_usbotg: usbotggrp {
+                       fsl,pins = <MX6QDL_USBOTG_PINGRP1>;
+               };
+
+               pinctrl_usdhc3: usdhc3grp {
+                       fsl,pins = <MX6QDL_USDHC3_PINGRP_D4>;
+               };
+
+               pinctrl_usdhc4: usdhc4grp {
+                       fsl,pins = <MX6QDL_USDHC4_PINGRP_D4>;
+               };
        };
 };
 
 };
 
 &uart2 {
-       status = "okay";
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_uart2_1>;
+       pinctrl-0 = <&pinctrl_uart2>;
+       status = "okay";
 };
 
 &usbh1 {
 &usbotg {
        vbus-supply = <&reg_usb_otg_vbus>;
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_usbotg_1>;
+       pinctrl-0 = <&pinctrl_usbotg>;
        disable-over-current;
        status = "okay";
 };
 
 &usdhc3 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_usdhc3_2>;
+       pinctrl-0 = <&pinctrl_usdhc3>;
        cd-gpios = <&gpio7 0 0>;
        wp-gpios = <&gpio7 1 0>;
        vmmc-supply = <&reg_3p3v>;
 
 &usdhc4 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_usdhc4_2>;
+       pinctrl-0 = <&pinctrl_usdhc4>;
        cd-gpios = <&gpio2 6 0>;
        wp-gpios = <&gpio2 7 0>;
        vmmc-supply = <&reg_3p3v>;
index ee6addf149af988aa560ee3fdc54a3dc27817c36..852675a489ac7899dafbc8b26b3fb9b19acc4a3f 100644 (file)
        };
 };
 
+
 &fec {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_enet_1>;
+       pinctrl-0 = <&pinctrl_enet>;
        phy-mode = "rgmii";
        status = "okay";
 };
 
+&iomuxc {
+       imx6q-sbc6x {
+               pinctrl_enet: enetgrp {
+                       fsl,pins = <MX6QDL_ENET_PINGRP1>;
+               };
+
+               pinctrl_uart1: uart1grp {
+                       fsl,pins = <MX6QDL_UART1_PINGRP1>;
+               };
+
+               pinctrl_usbotg: usbotggrp {
+                       fsl,pins = <MX6QDL_USBOTG_PINGRP1>;
+               };
+
+               pinctrl_usdhc3: usdhc3grp {
+                       fsl,pins = <MX6QDL_USDHC3_PINGRP_D4>;
+               };
+       };
+};
+
 &uart1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_uart1_1>;
+       pinctrl-0 = <&pinctrl_uart1>;
        status = "okay";
 };
 
 &usbotg {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_usbotg_1>;
+       pinctrl-0 = <&pinctrl_usbotg>;
        disable-over-current;
        status = "okay";
 };
 
 &usdhc3 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_usdhc3_2>;
+       pinctrl-0 = <&pinctrl_usdhc3>;
        status = "okay";
 };
index 6e1ccdc019a74c1c5416ac06fbc01c4c17b5f489..47a5eda0770717c25eb7e742c787b49c34999cf2 100644 (file)
        };
 };
 
+&fec {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_enet>;
+       phy-mode = "rgmii";
+       status = "okay";
+};
+
+&iomuxc {
+       imx6q-udoo {
+               pinctrl_enet: enetgrp {
+                       fsl,pins = <MX6QDL_ENET_PINGRP1>;
+               };
+
+               pinctrl_uart2: uart2grp {
+                       fsl,pins = <MX6QDL_UART2_PINGRP1>;
+               };
+
+               pinctrl_usdhc3: usdhc3grp {
+                       fsl,pins = <MX6QDL_USDHC3_PINGRP_D4>;
+               };
+       };
+};
+
 &sata {
        status = "okay";
 };
 
 &uart2 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_uart2_1>;
+       pinctrl-0 = <&pinctrl_uart2>;
        status = "okay";
 };
 
 &usdhc3 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_usdhc3_2>;
+       pinctrl-0 = <&pinctrl_usdhc3>;
        non-removable;
        status = "okay";
 };
index f024ef28b34b9373895dbbb913c475eebb33298a..101c434660d28b93dc62236a0661b79ced0d9dff 100644 (file)
@@ -8,7 +8,9 @@
  *
  */
 
+#include <dt-bindings/interrupt-controller/irq.h>
 #include "imx6q-pinfunc.h"
+#include "imx6qdl-pingrp.h"
 #include "imx6qdl.dtsi"
 
 / {
@@ -74,7 +76,7 @@
                                        #size-cells = <0>;
                                        compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
                                        reg = <0x02018000 0x4000>;
-                                       interrupts = <0 35 0x04>;
+                                       interrupts = <0 35 IRQ_TYPE_LEVEL_HIGH>;
                                        clocks = <&clks 116>, <&clks 116>;
                                        clock-names = "ipg", "per";
                                        status = "disabled";
                sata: sata@02200000 {
                        compatible = "fsl,imx6q-ahci";
                        reg = <0x02200000 0x4000>;
-                       interrupts = <0 39 0x04>;
+                       interrupts = <0 39 IRQ_TYPE_LEVEL_HIGH>;
                        clocks =  <&clks 154>, <&clks 187>, <&clks 105>;
                        clock-names = "sata", "sata_ref", "ahb";
                        status = "disabled";
                        #crtc-cells = <1>;
                        compatible = "fsl,imx6q-ipu";
                        reg = <0x02800000 0x400000>;
-                       interrupts = <0 8 0x4 0 7 0x4>;
+                       interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>,
+                                    <0 7 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&clks 133>, <&clks 134>, <&clks 137>;
                        clock-names = "bus", "di0", "di1";
                        resets = <&src 4>;
diff --git a/arch/arm/boot/dts/imx6qdl-gw51xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw51xx.dtsi
new file mode 100644 (file)
index 0000000..fb29da0
--- /dev/null
@@ -0,0 +1,317 @@
+/*
+ * Copyright 2013 Gateworks Corporation
+ *
+ * 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 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/ {
+       /* these are used by bootloader for disabling nodes */
+       aliases {
+               can0 = &can1;
+               ethernet0 = &fec;
+               led0 = &led0;
+               led1 = &led1;
+               nand = &gpmi;
+               usb0 = &usbh1;
+               usb1 = &usbotg;
+       };
+
+       chosen {
+               bootargs = "console=ttymxc1,115200";
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               led0: user1 {
+                       label = "user1";
+                       gpios = <&gpio4 6 0>; /* 102 -> MX6_PANLEDG */
+                       default-state = "on";
+                       linux,default-trigger = "heartbeat";
+               };
+
+               led1: user2 {
+                       label = "user2";
+                       gpios = <&gpio4 7 0>; /* 103 -> MX6_PANLEDR */
+                       default-state = "off";
+               };
+       };
+
+       memory {
+               reg = <0x10000000 0x20000000>;
+       };
+
+       pps {
+               compatible = "pps-gpio";
+               gpios = <&gpio1 26 0>;
+               status = "okay";
+       };
+
+       regulators {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               reg_3p3v: regulator@0 {
+                       compatible = "regulator-fixed";
+                       reg = <0>;
+                       regulator-name = "3P3V";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+               };
+
+               reg_5p0v: regulator@1 {
+                       compatible = "regulator-fixed";
+                       reg = <1>;
+                       regulator-name = "5P0V";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       regulator-always-on;
+               };
+
+               reg_usb_otg_vbus: regulator@2 {
+                       compatible = "regulator-fixed";
+                       reg = <2>;
+                       regulator-name = "usb_otg_vbus";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       gpio = <&gpio3 22 0>;
+                       enable-active-high;
+               };
+       };
+};
+
+&fec {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_enet>;
+       phy-mode = "rgmii";
+       phy-reset-gpios = <&gpio1 30 0>;
+       status = "okay";
+};
+
+&gpmi {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_gpmi_nand>;
+       status = "okay";
+};
+
+&i2c1 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c1>;
+       status = "okay";
+
+       eeprom1: eeprom@50 {
+               compatible = "atmel,24c02";
+               reg = <0x50>;
+               pagesize = <16>;
+       };
+
+       eeprom2: eeprom@51 {
+               compatible = "atmel,24c02";
+               reg = <0x51>;
+               pagesize = <16>;
+       };
+
+       eeprom3: eeprom@52 {
+               compatible = "atmel,24c02";
+               reg = <0x52>;
+               pagesize = <16>;
+       };
+
+       eeprom4: eeprom@53 {
+               compatible = "atmel,24c02";
+               reg = <0x53>;
+               pagesize = <16>;
+       };
+
+       gpio: pca9555@23 {
+               compatible = "nxp,pca9555";
+               reg = <0x23>;
+               gpio-controller;
+               #gpio-cells = <2>;
+       };
+
+       hwmon: gsc@29 {
+               compatible = "gw,gsp";
+               reg = <0x29>;
+       };
+
+       rtc: ds1672@68 {
+               compatible = "dallas,ds1672";
+               reg = <0x68>;
+       };
+};
+
+&i2c2 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c2>;
+       status = "okay";
+
+       pmic: ltc3676@3c {
+               compatible = "ltc,ltc3676";
+               reg = <0x3c>;
+
+               regulators {
+                       sw1_reg: ltc3676__sw1 {
+                               regulator-min-microvolt = <1175000>;
+                               regulator-max-microvolt = <1175000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       sw2_reg: ltc3676__sw2 {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       sw3_reg: ltc3676__sw3 {
+                               regulator-min-microvolt = <1175000>;
+                               regulator-max-microvolt = <1175000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       sw4_reg: ltc3676__sw4 {
+                               regulator-min-microvolt = <1500000>;
+                               regulator-max-microvolt = <1500000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       ldo2_reg: ltc3676__ldo2 {
+                               regulator-min-microvolt = <2500000>;
+                               regulator-max-microvolt = <2500000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       ldo4_reg: ltc3676__ldo4 {
+                               regulator-min-microvolt = <3000000>;
+                               regulator-max-microvolt = <3000000>;
+                       };
+               };
+       };
+};
+
+&i2c3 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c3>;
+       status = "okay";
+
+       videoin: adv7180@20 {
+               compatible = "adi,adv7180";
+               reg = <0x20>;
+       };
+};
+
+&iomuxc {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_hog>;
+
+       imx6qdl-gw51xx {
+               pinctrl_hog: hoggrp {
+                       fsl,pins = <
+                               MX6QDL_PAD_EIM_A19__GPIO2_IO19   0x80000000 /* MEZZ_DIO0 */
+                               MX6QDL_PAD_EIM_A20__GPIO2_IO18   0x80000000 /* MEZZ_DIO1 */
+                               MX6QDL_PAD_EIM_D22__GPIO3_IO22   0x80000000 /* OTG_PWR_EN */
+                               MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x80000000 /* GPS_PPS */
+                               MX6QDL_PAD_ENET_TXD0__GPIO1_IO30 0x80000000 /* PHY Reset */
+                               MX6QDL_PAD_GPIO_0__GPIO1_IO00    0x80000000 /* PCIE_RST# */
+                               MX6QDL_PAD_KEY_COL0__GPIO4_IO06  0x80000000 /* user1 led */
+                               MX6QDL_PAD_KEY_ROW0__GPIO4_IO07  0x80000000 /* user2 led */
+                        >;
+               };
+
+               pinctrl_enet: enetgrp {
+                       fsl,pins = <MX6QDL_ENET_PINGRP1>;
+               };
+
+               pinctrl_gpmi_nand: gpminandgrp {
+                       fsl,pins = <MX6QDL_GPMI_NAND_PINGRP1_NODQS>;
+               };
+
+               pinctrl_i2c1: i2c1grp {
+                       fsl,pins = <MX6QDL_I2C1_PINGRP1>;
+               };
+
+               pinctrl_i2c2: i2c2grp {
+                       fsl,pins = <MX6QDL_I2C2_PINGRP2>;
+               };
+
+               pinctrl_i2c3: i2c3grp {
+                       fsl,pins = <MX6QDL_I2C3_PINGRP2>;
+               };
+
+               pinctrl_uart1: uart1grp {
+                       fsl,pins = <MX6QDL_UART1_PINGRP2>;
+               };
+
+               pinctrl_uart2: uart2grp {
+                       fsl,pins = <MX6QDL_UART2_PINGRP3>;
+               };
+
+               pinctrl_uart3: uart3grp {
+                       fsl,pins = <MX6QDL_UART3_PINGRP3>;
+               };
+
+               pinctrl_uart5: uart5grp {
+                       fsl,pins = <MX6QDL_UART5_PINGRP1>;
+               };
+
+               pinctrl_usbotg: usbotggrp {
+                       fsl,pins = <MX6QDL_USBOTG_PINGRP1>;
+               };
+       };
+};
+
+&pcie {
+       reset-gpio = <&gpio1 0 0>;
+       status = "okay";
+};
+
+&uart1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart1>;
+       status = "okay";
+};
+
+&uart2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart2>;
+       status = "okay";
+};
+
+&uart3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart3>;
+       status = "okay";
+};
+
+&uart5 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart5>;
+       status = "okay";
+};
+
+&usbotg {
+       vbus-supply = <&reg_usb_otg_vbus>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usbotg>;
+       disable-over-current;
+       status = "okay";
+};
+
+&usbh1 {
+       status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
new file mode 100644 (file)
index 0000000..a6c77b5
--- /dev/null
@@ -0,0 +1,424 @@
+/*
+ * Copyright 2013 Gateworks Corporation
+ *
+ * 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 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/ {
+       /* these are used by bootloader for disabling nodes */
+       aliases {
+               ethernet0 = &fec;
+               led0 = &led0;
+               led1 = &led1;
+               led2 = &led2;
+               nand = &gpmi;
+               ssi0 = &ssi1;
+               usb0 = &usbh1;
+               usb1 = &usbotg;
+               usdhc2 = &usdhc3;
+       };
+
+       chosen {
+               bootargs = "console=ttymxc1,115200";
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               led0: user1 {
+                       label = "user1";
+                       gpios = <&gpio4 6 0>; /* 102 -> MX6_PANLEDG */
+                       default-state = "on";
+                       linux,default-trigger = "heartbeat";
+               };
+
+               led1: user2 {
+                       label = "user2";
+                       gpios = <&gpio4 7 0>; /* 103 -> MX6_PANLEDR */
+                       default-state = "off";
+               };
+
+               led2: user3 {
+                       label = "user3";
+                       gpios = <&gpio4 15 1>; /* 111 - MX6_LOCLED# */
+                       default-state = "off";
+               };
+       };
+
+       memory {
+               reg = <0x10000000 0x20000000>;
+       };
+
+       pps {
+               compatible = "pps-gpio";
+               gpios = <&gpio1 26 0>;
+               status = "okay";
+       };
+
+       regulators {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               reg_1p0v: regulator@0 {
+                       compatible = "regulator-fixed";
+                       reg = <0>;
+                       regulator-name = "1P0V";
+                       regulator-min-microvolt = <1000000>;
+                       regulator-max-microvolt = <1000000>;
+                       regulator-always-on;
+               };
+
+               /* remove this fixed regulator once ltc3676__sw2 driver available */
+               reg_1p8v: regulator@1 {
+                       compatible = "regulator-fixed";
+                       reg = <1>;
+                       regulator-name = "1P8V";
+                       regulator-min-microvolt = <1800000>;
+                       regulator-max-microvolt = <1800000>;
+                       regulator-always-on;
+               };
+
+               reg_3p3v: regulator@2 {
+                       compatible = "regulator-fixed";
+                       reg = <2>;
+                       regulator-name = "3P3V";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+               };
+
+               reg_5p0v: regulator@3 {
+                       compatible = "regulator-fixed";
+                       reg = <3>;
+                       regulator-name = "5P0V";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       regulator-always-on;
+               };
+
+               reg_usb_otg_vbus: regulator@4 {
+                       compatible = "regulator-fixed";
+                       reg = <4>;
+                       regulator-name = "usb_otg_vbus";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       gpio = <&gpio3 22 0>;
+                       enable-active-high;
+               };
+       };
+
+       sound {
+               compatible = "fsl,imx6q-sabrelite-sgtl5000",
+                            "fsl,imx-audio-sgtl5000";
+               model = "imx6q-sabrelite-sgtl5000";
+               ssi-controller = <&ssi1>;
+               audio-codec = <&codec>;
+               audio-routing =
+                       "MIC_IN", "Mic Jack",
+                       "Mic Jack", "Mic Bias",
+                       "Headphone Jack", "HP_OUT";
+               mux-int-port = <1>;
+               mux-ext-port = <4>;
+       };
+};
+
+&audmux {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_audmux>;
+       status = "okay";
+};
+
+&fec {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_enet>;
+       phy-mode = "rgmii";
+       phy-reset-gpios = <&gpio1 30 0>;
+       status = "okay";
+};
+
+&gpmi {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_gpmi_nand>;
+       status = "okay";
+};
+
+&i2c1 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c1>;
+       status = "okay";
+
+       eeprom1: eeprom@50 {
+               compatible = "atmel,24c02";
+               reg = <0x50>;
+               pagesize = <16>;
+       };
+
+       eeprom2: eeprom@51 {
+               compatible = "atmel,24c02";
+               reg = <0x51>;
+               pagesize = <16>;
+       };
+
+       eeprom3: eeprom@52 {
+               compatible = "atmel,24c02";
+               reg = <0x52>;
+               pagesize = <16>;
+       };
+
+       eeprom4: eeprom@53 {
+               compatible = "atmel,24c02";
+               reg = <0x53>;
+               pagesize = <16>;
+       };
+
+       gpio: pca9555@23 {
+               compatible = "nxp,pca9555";
+               reg = <0x23>;
+               gpio-controller;
+               #gpio-cells = <2>;
+       };
+
+       hwmon: gsc@29 {
+               compatible = "gw,gsp";
+               reg = <0x29>;
+       };
+
+       rtc: ds1672@68 {
+               compatible = "dallas,ds1672";
+               reg = <0x68>;
+       };
+};
+
+&i2c2 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c2>;
+       status = "okay";
+
+       pciswitch: pex8609@3f {
+               compatible = "plx,pex8609";
+               reg = <0x3f>;
+       };
+
+       pmic: ltc3676@3c {
+               compatible = "ltc,ltc3676";
+               reg = <0x3c>;
+
+               regulators {
+                       sw1_reg: ltc3676__sw1 {
+                               regulator-min-microvolt = <1175000>;
+                               regulator-max-microvolt = <1175000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       sw2_reg: ltc3676__sw2 {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       sw3_reg: ltc3676__sw3 {
+                               regulator-min-microvolt = <1175000>;
+                               regulator-max-microvolt = <1175000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       sw4_reg: ltc3676__sw4 {
+                               regulator-min-microvolt = <1500000>;
+                               regulator-max-microvolt = <1500000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       ldo2_reg: ltc3676__ldo2 {
+                               regulator-min-microvolt = <2500000>;
+                               regulator-max-microvolt = <2500000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       ldo3_reg: ltc3676__ldo3 {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       ldo4_reg: ltc3676__ldo4 {
+                               regulator-min-microvolt = <3000000>;
+                               regulator-max-microvolt = <3000000>;
+                       };
+               };
+       };
+};
+
+&i2c3 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c3>;
+       status = "okay";
+
+       accelerometer: fxos8700@1e {
+               compatible = "fsl,fxos8700";
+               reg = <0x13>;
+       };
+
+       codec: sgtl5000@0a {
+               compatible = "fsl,sgtl5000";
+               reg = <0x0a>;
+               clocks = <&clks 169>;
+               VDDA-supply = <&reg_1p8v>;
+               VDDIO-supply = <&reg_3p3v>;
+       };
+
+       touchscreen: egalax_ts@04 {
+               compatible = "eeti,egalax_ts";
+               reg = <0x04>;
+               interrupt-parent = <&gpio7>;
+               interrupts = <12 2>; /* gpio7_12 active low */
+               wakeup-gpios = <&gpio7 12 0>;
+       };
+
+       videoin: adv7180@20 {
+               compatible = "adi,adv7180";
+               reg = <0x20>;
+       };
+};
+
+&iomuxc {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_hog>;
+
+       imx6qdl-gw52xx {
+               pinctrl_hog: hoggrp {
+                       fsl,pins = <
+                               MX6QDL_PAD_EIM_A19__GPIO2_IO19   0x80000000 /* MEZZ_DIO0 */
+                               MX6QDL_PAD_EIM_A20__GPIO2_IO18   0x80000000 /* MEZZ_DIO1 */
+                               MX6QDL_PAD_EIM_D22__GPIO3_IO22   0x80000000 /* OTG_PWR_EN */
+                               MX6QDL_PAD_EIM_D31__GPIO3_IO31   0x80000000 /* VIDDEC_PDN# */
+                               MX6QDL_PAD_ENET_TXD0__GPIO1_IO30 0x80000000 /* PHY Reset */
+                               MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000 /* PCIE_RST# */
+                               MX6QDL_PAD_ENET_RXD0__GPIO1_IO27 0x80000000 /* GPS_PWDN */
+                               MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x80000000 /* GPS_PPS */
+                               MX6QDL_PAD_GPIO_0__CCM_CLKO1     0x000130b0 /* AUD4_MCK */
+                               MX6QDL_PAD_GPIO_2__GPIO1_IO02    0x80000000 /* USB_SEL_PCI */
+                               MX6QDL_PAD_GPIO_17__GPIO7_IO12   0x80000000 /* TOUCH_IRQ# */
+                               MX6QDL_PAD_KEY_COL0__GPIO4_IO06  0x80000000 /* user1 led */
+                               MX6QDL_PAD_KEY_ROW0__GPIO4_IO07  0x80000000 /* user2 led */
+                               MX6QDL_PAD_KEY_ROW4__GPIO4_IO15  0x80000000 /* user3 led */
+                               MX6QDL_PAD_SD2_CMD__GPIO1_IO11   0x80000000 /* LVDS_TCH# */
+                               MX6QDL_PAD_SD3_DAT5__GPIO7_IO00  0x80000000 /* SD3_CD# */
+                               MX6QDL_PAD_SD4_DAT3__GPIO2_IO11  0x80000000 /* UART2_EN# */
+                        >;
+               };
+
+               pinctrl_audmux: audmuxgrp {
+                       fsl,pins = <MX6QDL_AUDMUX_PINGRP1>;
+               };
+
+               pinctrl_enet: enetgrp {
+                       fsl,pins = <MX6QDL_ENET_PINGRP1>;
+               };
+
+               pinctrl_gpmi_nand: gpminandgrp {
+                       fsl,pins = <MX6QDL_GPMI_NAND_PINGRP1_NODQS>;
+               };
+
+               pinctrl_i2c1: i2c1grp {
+                       fsl,pins = <MX6QDL_I2C1_PINGRP1>;
+               };
+
+               pinctrl_i2c2: i2c2grp {
+                       fsl,pins = <MX6QDL_I2C2_PINGRP2>;
+               };
+
+               pinctrl_i2c3: i2c3grp {
+                       fsl,pins = <MX6QDL_I2C3_PINGRP2>;
+               };
+
+               pinctrl_uart1: uart1grp {
+                       fsl,pins = <MX6QDL_UART1_PINGRP2>;
+               };
+
+               pinctrl_uart2: uart2grp {
+                       fsl,pins = <MX6QDL_UART2_PINGRP3>;
+               };
+
+               pinctrl_uart5: uart5grp {
+                       fsl,pins = <MX6QDL_UART5_PINGRP1>;
+               };
+
+               pinctrl_usbotg: usbotggrp {
+                       fsl,pins = <MX6QDL_USBOTG_PINGRP1>;
+               };
+
+               pinctrl_usdhc3: usdhc3grp {
+                       fsl,pins = <MX6QDL_USDHC3_PINGRP_D4>;
+               };
+       };
+};
+
+&ldb {
+       status = "okay";
+       lvds-channel@0 {
+               crtcs = <&ipu1 0>, <&ipu1 1>;
+       };
+};
+
+&pcie {
+       reset-gpio = <&gpio1 29 0>;
+       status = "okay";
+};
+
+&ssi1 {
+       fsl,mode = "i2s-slave";
+       status = "okay";
+};
+
+&uart1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart1>;
+       status = "okay";
+};
+
+&uart2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart2>;
+       status = "okay";
+};
+
+&uart5 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart5>;
+       status = "okay";
+};
+
+&usbotg {
+       vbus-supply = <&reg_usb_otg_vbus>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usbotg>;
+       disable-over-current;
+       status = "okay";
+};
+
+&usbh1 {
+       status = "okay";
+};
+
+&usdhc3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usdhc3>;
+       cd-gpios = <&gpio7 0 0>;
+       vmmc-supply = <&reg_3p3v>;
+       status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi
new file mode 100644 (file)
index 0000000..35028a5
--- /dev/null
@@ -0,0 +1,484 @@
+/*
+ * Copyright 2013 Gateworks Corporation
+ *
+ * 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 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/ {
+       /* these are used by bootloader for disabling nodes */
+       aliases {
+               can0 = &can1;
+               ethernet0 = &fec;
+               ethernet1 = &eth1;
+               led0 = &led0;
+               led1 = &led1;
+               led2 = &led2;
+               nand = &gpmi;
+               sky2 = &eth1;
+               ssi0 = &ssi1;
+               usb0 = &usbh1;
+               usb1 = &usbotg;
+               usdhc2 = &usdhc3;
+       };
+
+       chosen {
+               bootargs = "console=ttymxc1,115200";
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               led0: user1 {
+                       label = "user1";
+                       gpios = <&gpio4 6 0>; /* 102 -> MX6_PANLEDG */
+                       default-state = "on";
+                       linux,default-trigger = "heartbeat";
+               };
+
+               led1: user2 {
+                       label = "user2";
+                       gpios = <&gpio4 7 0>; /* 103 -> MX6_PANLEDR */
+                       default-state = "off";
+               };
+
+               led2: user3 {
+                       label = "user3";
+                       gpios = <&gpio4 15 1>; /* 111 -> MX6_LOCLED# */
+                       default-state = "off";
+               };
+       };
+
+       memory {
+               reg = <0x10000000 0x40000000>;
+       };
+
+       pps {
+               compatible = "pps-gpio";
+               gpios = <&gpio1 26 0>;
+               status = "okay";
+       };
+
+       regulators {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               reg_1p0v: regulator@0 {
+                       compatible = "regulator-fixed";
+                       reg = <0>;
+                       regulator-name = "1P0V";
+                       regulator-min-microvolt = <1000000>;
+                       regulator-max-microvolt = <1000000>;
+                       regulator-always-on;
+               };
+
+               /* remove when pmic 1p8 regulator available */
+               reg_1p8v: regulator@1 {
+                       compatible = "regulator-fixed";
+                       reg = <1>;
+                       regulator-name = "1P8V";
+                       regulator-min-microvolt = <1800000>;
+                       regulator-max-microvolt = <1800000>;
+                       regulator-always-on;
+               };
+
+               reg_3p3v: regulator@2 {
+                       compatible = "regulator-fixed";
+                       reg = <2>;
+                       regulator-name = "3P3V";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+               };
+
+               reg_usb_h1_vbus: regulator@3 {
+                       compatible = "regulator-fixed";
+                       reg = <3>;
+                       regulator-name = "usb_h1_vbus";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       regulator-always-on;
+               };
+
+               reg_usb_otg_vbus: regulator@4 {
+                       compatible = "regulator-fixed";
+                       reg = <4>;
+                       regulator-name = "usb_otg_vbus";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       gpio = <&gpio3 22 0>;
+                       enable-active-high;
+               };
+       };
+
+       sound {
+               compatible = "fsl,imx6q-sabrelite-sgtl5000",
+                            "fsl,imx-audio-sgtl5000";
+               model = "imx6q-sabrelite-sgtl5000";
+               ssi-controller = <&ssi1>;
+               audio-codec = <&codec>;
+               audio-routing =
+                       "MIC_IN", "Mic Jack",
+                       "Mic Jack", "Mic Bias",
+                       "Headphone Jack", "HP_OUT";
+               mux-int-port = <1>;
+               mux-ext-port = <4>;
+       };
+};
+
+&audmux {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_audmux>;
+       status = "okay";
+};
+
+&can1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_flexcan1>;
+       status = "okay";
+};
+
+&fec {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_enet>;
+       phy-mode = "rgmii";
+       phy-reset-gpios = <&gpio1 30 0>;
+       status = "okay";
+};
+
+&gpmi {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_gpmi_nand>;
+       status = "okay";
+};
+
+&i2c1 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c1>;
+       status = "okay";
+
+       eeprom1: eeprom@50 {
+               compatible = "atmel,24c02";
+               reg = <0x50>;
+               pagesize = <16>;
+       };
+
+       eeprom2: eeprom@51 {
+               compatible = "atmel,24c02";
+               reg = <0x51>;
+               pagesize = <16>;
+       };
+
+       eeprom3: eeprom@52 {
+               compatible = "atmel,24c02";
+               reg = <0x52>;
+               pagesize = <16>;
+       };
+
+       eeprom4: eeprom@53 {
+               compatible = "atmel,24c02";
+               reg = <0x53>;
+               pagesize = <16>;
+       };
+
+       gpio: pca9555@23 {
+               compatible = "nxp,pca9555";
+               reg = <0x23>;
+               gpio-controller;
+               #gpio-cells = <2>;
+       };
+
+       hwmon: gsc@29 {
+               compatible = "gw,gsp";
+               reg = <0x29>;
+       };
+
+       rtc: ds1672@68 {
+               compatible = "dallas,ds1672";
+               reg = <0x68>;
+       };
+};
+
+&i2c2 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c2>;
+       status = "okay";
+
+       pciclkgen: si53156@6b {
+               compatible = "sil,si53156";
+               reg = <0x6b>;
+       };
+
+       pciswitch: pex8606@3f {
+               compatible = "plx,pex8606";
+               reg = <0x3f>;
+       };
+
+       pmic: ltc3676@3c {
+               compatible = "ltc,ltc3676";
+               reg = <0x3c>;
+
+               regulators {
+                       /* VDD_SOC */
+                       sw1_reg: ltc3676__sw1 {
+                               regulator-min-microvolt = <1175000>;
+                               regulator-max-microvolt = <1175000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       /* VDD_1P8 */
+                       sw2_reg: ltc3676__sw2 {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       /* VDD_ARM */
+                       sw3_reg: ltc3676__sw3 {
+                               regulator-min-microvolt = <1175000>;
+                               regulator-max-microvolt = <1175000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       /* VDD_DDR */
+                       sw4_reg: ltc3676__sw4 {
+                               regulator-min-microvolt = <1500000>;
+                               regulator-max-microvolt = <1500000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       /* VDD_2P5 */
+                       ldo2_reg: ltc3676__ldo2 {
+                               regulator-min-microvolt = <2500000>;
+                               regulator-max-microvolt = <2500000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       /* VDD_1P8 */
+                       ldo3_reg: ltc3676__ldo3 {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       /* VDD_HIGH */
+                       ldo4_reg: ltc3676__ldo4 {
+                               regulator-min-microvolt = <3000000>;
+                               regulator-max-microvolt = <3000000>;
+                       };
+               };
+       };
+};
+
+&i2c3 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c3>;
+       status = "okay";
+
+       accelerometer: fxos8700@1e {
+               compatible = "fsl,fxos8700";
+               reg = <0x1e>;
+       };
+
+       codec: sgtl5000@0a {
+               compatible = "fsl,sgtl5000";
+               reg = <0x0a>;
+               clocks = <&clks 201>;
+               VDDA-supply = <&reg_1p8v>;
+               VDDIO-supply = <&reg_3p3v>;
+       };
+
+       hdmiin: adv7611@4c {
+               compatible = "adi,adv7611";
+               reg = <0x4c>;
+       };
+
+       touchscreen: egalax_ts@04 {
+               compatible = "eeti,egalax_ts";
+               reg = <0x04>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <11 2>; /* gpio1_11 active low */
+               wakeup-gpios = <&gpio1 11 0>;
+       };
+
+       videoout: adv7393@2a {
+               compatible = "adi,adv7393";
+               reg = <0x2a>;
+       };
+
+       videoin: adv7180@20 {
+               compatible = "adi,adv7180";
+               reg = <0x20>;
+       };
+};
+
+&iomuxc {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_hog>;
+
+       imx6qdl-gw53xx {
+               pinctrl_hog: hoggrp {
+                       fsl,pins = <
+                               MX6QDL_PAD_EIM_A19__GPIO2_IO19    0x80000000 /* PCIE6EXP_DIO0 */
+                               MX6QDL_PAD_EIM_A20__GPIO2_IO18    0x80000000 /* PCIE6EXP_DIO1 */
+                               MX6QDL_PAD_EIM_D22__GPIO3_IO22    0x80000000 /* OTG_PWR_EN */
+                               MX6QDL_PAD_ENET_RXD0__GPIO1_IO27  0x80000000 /* GPS_SHDN */
+                               MX6QDL_PAD_ENET_RXD1__GPIO1_IO26  0x80000000 /* GPS_PPS */
+                               MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28 0x80000000 /* PCIE IRQ */
+                               MX6QDL_PAD_ENET_TXD1__GPIO1_IO29  0x80000000 /* PCIE RST */
+                               MX6QDL_PAD_GPIO_0__CCM_CLKO1      0x000130b0 /* AUD4_MCK */
+                               MX6QDL_PAD_GPIO_2__GPIO1_IO02     0x80000000 /* CAN_STBY */
+                               MX6QDL_PAD_GPIO_8__GPIO1_IO08     0x80000000 /* PMIC_IRQ# */
+                               MX6QDL_PAD_GPIO_9__GPIO1_IO09     0x80000000 /* HUB_RST# */
+                               MX6QDL_PAD_GPIO_17__GPIO7_IO12    0x80000000 /* PCIE_WDIS# */
+                               MX6QDL_PAD_GPIO_19__GPIO4_IO05    0x80000000 /* ACCEL_IRQ# */
+                               MX6QDL_PAD_KEY_COL0__GPIO4_IO06   0x80000000 /* user1 led */
+                               MX6QDL_PAD_KEY_COL4__GPIO4_IO14   0x80000000 /* USBOTG_OC# */
+                               MX6QDL_PAD_KEY_ROW0__GPIO4_IO07   0x80000000 /* user2 led */
+                               MX6QDL_PAD_KEY_ROW4__GPIO4_IO15   0x80000000 /* user3 led */
+                               MX6QDL_PAD_SD2_CMD__GPIO1_IO11    0x80000000 /* TOUCH_IRQ# */
+                               MX6QDL_PAD_SD3_DAT5__GPIO7_IO00   0x80000000 /* SD3_DET# */
+                        >;
+               };
+
+               pinctrl_audmux: audmuxgrp {
+                       fsl,pins = <MX6QDL_AUDMUX_PINGRP1>;
+               };
+
+               pinctrl_enet: enetgrp {
+                       fsl,pins = <MX6QDL_ENET_PINGRP1>;
+               };
+
+               pinctrl_flexcan1: flexcan1grp {
+                       fsl,pins = <MX6QDL_FLEXCAN1_PINGRP1>;
+               };
+
+               pinctrl_gpmi_nand: gpminandgrp {
+                       fsl,pins = <MX6QDL_GPMI_NAND_PINGRP1_NODQS>;
+               };
+
+               pinctrl_i2c1: i2c1grp {
+                       fsl,pins = <MX6QDL_I2C1_PINGRP1>;
+               };
+
+               pinctrl_i2c2: i2c2grp {
+                       fsl,pins = <MX6QDL_I2C2_PINGRP2>;
+               };
+
+               pinctrl_i2c3: i2c3grp {
+                       fsl,pins = <MX6QDL_I2C3_PINGRP2>;
+               };
+
+               pinctrl_uart1: uart1grp {
+                       fsl,pins = <MX6QDL_UART1_PINGRP2>;
+               };
+
+               pinctrl_uart2: uart2grp {
+                       fsl,pins = <MX6QDL_UART2_PINGRP3>;
+               };
+
+               pinctrl_uart5: uart5grp {
+                       fsl,pins = <MX6QDL_UART5_PINGRP1>;
+               };
+
+               pinctrl_usbotg: usbotggrp {
+                       fsl,pins = <MX6QDL_USBOTG_PINGRP1>;
+               };
+
+               pinctrl_usdhc3: usdhc3grp {
+                       fsl,pins = <MX6QDL_USDHC3_PINGRP_D4>;
+               };
+       };
+};
+
+&ldb {
+       status = "okay";
+
+       lvds-channel@1 {
+               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>;
+                       };
+               };
+       };
+};
+
+&pcie {
+       reset-gpio = <&gpio1 29 0>;
+       status = "okay";
+
+       eth1: sky2@8 { /* MAC/PHY on bus 8 */
+               compatible = "marvell,sky2";
+       };
+};
+
+&ssi1 {
+       fsl,mode = "i2s-slave";
+       status = "okay";
+};
+
+&uart1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart1>;
+       status = "okay";
+};
+
+&uart2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart2>;
+       status = "okay";
+};
+
+&uart5 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart5>;
+       status = "okay";
+};
+
+&usbotg {
+       vbus-supply = <&reg_usb_otg_vbus>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usbotg>;
+       disable-over-current;
+       status = "okay";
+};
+
+&usbh1 {
+       vbus-supply = <&reg_usb_h1_vbus>;
+       status = "okay";
+};
+
+&usdhc3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usdhc3>;
+       cd-gpios = <&gpio7 0 0>;
+       vmmc-supply = <&reg_3p3v>;
+       status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi
new file mode 100644 (file)
index 0000000..34b26b9
--- /dev/null
@@ -0,0 +1,511 @@
+/*
+ * Copyright 2013 Gateworks Corporation
+ *
+ * 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 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/ {
+       /* these are used by bootloader for disabling nodes */
+       aliases {
+               can0 = &can1;
+               ethernet0 = &fec;
+               ethernet1 = &eth1;
+               led0 = &led0;
+               led1 = &led1;
+               led2 = &led2;
+               nand = &gpmi;
+               sky2 = &eth1;
+               ssi0 = &ssi1;
+               usb0 = &usbh1;
+               usb1 = &usbotg;
+               usdhc2 = &usdhc3;
+       };
+
+       chosen {
+               bootargs = "console=ttymxc1,115200";
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               led0: user1 {
+                       label = "user1";
+                       gpios = <&gpio4 6 0>; /* 102 -> MX6_PANLEDG */
+                       default-state = "on";
+                       linux,default-trigger = "heartbeat";
+               };
+
+               led1: user2 {
+                       label = "user2";
+                       gpios = <&gpio4 7 0>; /* 103 -> MX6_PANLEDR */
+                       default-state = "off";
+               };
+
+               led2: user3 {
+                       label = "user3";
+                       gpios = <&gpio4 15 1>; /* 111 -> MX6_LOCLED# */
+                       default-state = "off";
+               };
+       };
+
+       memory {
+               reg = <0x10000000 0x40000000>;
+       };
+
+       pps {
+               compatible = "pps-gpio";
+               gpios = <&gpio1 26 0>;
+               status = "okay";
+       };
+
+       regulators {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               reg_1p0v: regulator@0 {
+                       compatible = "regulator-fixed";
+                       reg = <0>;
+                       regulator-name = "1P0V";
+                       regulator-min-microvolt = <1000000>;
+                       regulator-max-microvolt = <1000000>;
+                       regulator-always-on;
+               };
+
+               reg_3p3v: regulator@1 {
+                       compatible = "regulator-fixed";
+                       reg = <1>;
+                       regulator-name = "3P3V";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+               };
+
+               reg_usb_h1_vbus: regulator@2 {
+                       compatible = "regulator-fixed";
+                       reg = <2>;
+                       regulator-name = "usb_h1_vbus";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       regulator-always-on;
+               };
+
+               reg_usb_otg_vbus: regulator@3 {
+                       compatible = "regulator-fixed";
+                       reg = <3>;
+                       regulator-name = "usb_otg_vbus";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       gpio = <&gpio3 22 0>;
+                       enable-active-high;
+               };
+       };
+
+       sound {
+               compatible = "fsl,imx6q-sabrelite-sgtl5000",
+                            "fsl,imx-audio-sgtl5000";
+               model = "imx6q-sabrelite-sgtl5000";
+               ssi-controller = <&ssi1>;
+               audio-codec = <&codec>;
+               audio-routing =
+                       "MIC_IN", "Mic Jack",
+                       "Mic Jack", "Mic Bias",
+                       "Headphone Jack", "HP_OUT";
+               mux-int-port = <1>;
+               mux-ext-port = <4>;
+       };
+};
+
+&audmux {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_audmux>; /* AUD4<->sgtl5000 */
+       status = "okay";
+};
+
+&can1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_flexcan1>;
+       status = "okay";
+};
+
+&fec {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_enet>;
+       phy-mode = "rgmii";
+       phy-reset-gpios = <&gpio1 30 0>;
+       status = "okay";
+};
+
+&gpmi {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_gpmi_nand>;
+       status = "okay";
+};
+
+&i2c1 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c1>;
+       status = "okay";
+
+       eeprom1: eeprom@50 {
+               compatible = "atmel,24c02";
+               reg = <0x50>;
+               pagesize = <16>;
+       };
+
+       eeprom2: eeprom@51 {
+               compatible = "atmel,24c02";
+               reg = <0x51>;
+               pagesize = <16>;
+       };
+
+       eeprom3: eeprom@52 {
+               compatible = "atmel,24c02";
+               reg = <0x52>;
+               pagesize = <16>;
+       };
+
+       eeprom4: eeprom@53 {
+               compatible = "atmel,24c02";
+               reg = <0x53>;
+               pagesize = <16>;
+       };
+
+       gpio: pca9555@23 {
+               compatible = "nxp,pca9555";
+               reg = <0x23>;
+               gpio-controller;
+               #gpio-cells = <2>;
+       };
+
+       hwmon: gsc@29 {
+               compatible = "gw,gsp";
+               reg = <0x29>;
+       };
+
+       rtc: ds1672@68 {
+               compatible = "dallas,ds1672";
+               reg = <0x68>;
+       };
+};
+
+&i2c2 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c2>;
+       status = "okay";
+
+       pmic: pfuze100@08 {
+               compatible = "fsl,pfuze100";
+               reg = <0x08>;
+
+               regulators {
+                       sw1a_reg: sw1ab {
+                               regulator-min-microvolt = <300000>;
+                               regulator-max-microvolt = <1875000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                               regulator-ramp-delay = <6250>;
+                       };
+
+                       sw1c_reg: sw1c {
+                               regulator-min-microvolt = <300000>;
+                               regulator-max-microvolt = <1875000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                               regulator-ramp-delay = <6250>;
+                       };
+
+                       sw2_reg: sw2 {
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <3950000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       sw3a_reg: sw3a {
+                               regulator-min-microvolt = <400000>;
+                               regulator-max-microvolt = <1975000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       sw3b_reg: sw3b {
+                               regulator-min-microvolt = <400000>;
+                               regulator-max-microvolt = <1975000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       sw4_reg: sw4 {
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <3300000>;
+                       };
+
+                       swbst_reg: swbst {
+                               regulator-min-microvolt = <5000000>;
+                               regulator-max-microvolt = <5150000>;
+                       };
+
+                       snvs_reg: vsnvs {
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <3000000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       vref_reg: vrefddr {
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       vgen1_reg: vgen1 {
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <1550000>;
+                       };
+
+                       vgen2_reg: vgen2 {
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <1550000>;
+                       };
+
+                       vgen3_reg: vgen3 {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3300000>;
+                       };
+
+                       vgen4_reg: vgen4 {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-always-on;
+                       };
+
+                       vgen5_reg: vgen5 {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-always-on;
+                       };
+
+                       vgen6_reg: vgen6 {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-always-on;
+                       };
+               };
+       };
+
+       pciswitch: pex8609@3f {
+               compatible = "plx,pex8609";
+               reg = <0x3f>;
+       };
+
+       pciclkgen: si52147@6b {
+               compatible = "sil,si52147";
+               reg = <0x6b>;
+       };
+};
+
+&i2c3 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c3>;
+       status = "okay";
+
+       accelerometer: fxos8700@1e {
+               compatible = "fsl,fxos8700";
+               reg = <0x1e>;
+       };
+
+       codec: sgtl5000@0a {
+               compatible = "fsl,sgtl5000";
+               reg = <0x0a>;
+               clocks = <&clks 201>;
+               VDDA-supply = <&sw4_reg>;
+               VDDIO-supply = <&reg_3p3v>;
+       };
+
+       hdmiin: adv7611@4c {
+               compatible = "adi,adv7611";
+               reg = <0x4c>;
+       };
+
+       touchscreen: egalax_ts@04 {
+               compatible = "eeti,egalax_ts";
+               reg = <0x04>;
+               interrupt-parent = <&gpio7>;
+               interrupts = <12 2>; /* gpio7_12 active low */
+               wakeup-gpios = <&gpio7 12 0>;
+       };
+
+       videoout: adv7393@2a {
+               compatible = "adi,adv7393";
+               reg = <0x2a>;
+       };
+
+       videoin: adv7180@20 {
+               compatible = "adi,adv7180";
+               reg = <0x20>;
+       };
+};
+
+&iomuxc {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_hog>;
+
+       imx6qdl-gw54xx {
+               pinctrl_hog: hoggrp {
+                       fsl,pins = <
+                               MX6QDL_PAD_EIM_D22__GPIO3_IO22    0x80000000 /* OTG_PWR_EN */
+                               MX6QDL_PAD_EIM_D19__GPIO3_IO19    0x80000000 /* SPINOR_CS0# */
+                               MX6QDL_PAD_ENET_RXD1__GPIO1_IO26  0x80000000 /* GPS_PPS */
+                               MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28 0x80000000 /* PCIE IRQ */
+                               MX6QDL_PAD_ENET_TXD1__GPIO1_IO29  0x80000000 /* PCIE RST */
+                               MX6QDL_PAD_GPIO_0__CCM_CLKO1      0x000130b0 /* AUD4_MCK */
+                               MX6QDL_PAD_GPIO_2__GPIO1_IO02     0x80000000 /* CAN_STBY */
+                               MX6QDL_PAD_GPIO_17__GPIO7_IO12    0x80000000 /* TOUCH_IRQ# */
+                               MX6QDL_PAD_KEY_COL0__GPIO4_IO06   0x80000000 /* user1 led */
+                               MX6QDL_PAD_KEY_ROW0__GPIO4_IO07   0x80000000 /* user2 led */
+                               MX6QDL_PAD_KEY_ROW4__GPIO4_IO15   0x80000000 /* user3 led */
+                               MX6QDL_PAD_SD1_DAT0__GPIO1_IO16   0x80000000 /* USBHUB_RST# */
+                               MX6QDL_PAD_SD1_DAT3__GPIO1_IO21   0x80000000 /* MIPI_DIO */
+                        >;
+               };
+
+               pinctrl_audmux: audmuxgrp {
+                       fsl,pins = <MX6QDL_AUDMUX_PINGRP1>;
+               };
+
+               pinctrl_enet: enetgrp {
+                       fsl,pins = <MX6QDL_ENET_PINGRP1>;
+               };
+
+               pinctrl_flexcan1: flexcan1grp {
+                       fsl,pins = <MX6QDL_FLEXCAN1_PINGRP1>;
+               };
+
+               pinctrl_gpmi_nand: gpminandgrp {
+                       fsl,pins = <MX6QDL_GPMI_NAND_PINGRP1_NODQS>;
+               };
+
+               pinctrl_i2c1: i2c1grp {
+                       fsl,pins = <MX6QDL_I2C1_PINGRP1>;
+               };
+
+               pinctrl_i2c2: i2c2grp {
+                       fsl,pins = <MX6QDL_I2C2_PINGRP2>;
+               };
+
+               pinctrl_i2c3: i2c3grp {
+                       fsl,pins = <MX6QDL_I2C3_PINGRP2>;
+               };
+
+               pinctrl_uart1: uart1grp {
+                       fsl,pins = <MX6QDL_UART1_PINGRP2>;
+               };
+
+               pinctrl_uart2: uart2grp {
+                       fsl,pins = <MX6QDL_UART2_PINGRP3>;
+               };
+
+               pinctrl_uart5: uart5grp {
+                       fsl,pins = <MX6QDL_UART5_PINGRP1>;
+               };
+
+               pinctrl_usbotg: usbotggrp {
+                       fsl,pins = <MX6QDL_USBOTG_PINGRP1>;
+               };
+
+               pinctrl_usdhc3: usdhc3grp {
+                       fsl,pins = <MX6QDL_USDHC3_PINGRP_D4>;
+               };
+       };
+};
+
+&ldb {
+       status = "okay";
+
+       lvds-channel@1 {
+               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>;
+                       };
+               };
+       };
+};
+
+&pcie {
+       reset-gpio = <&gpio1 29 0>;
+       status = "okay";
+
+       eth1: sky2@8 { /* MAC/PHY on bus 8 */
+               compatible = "marvell,sky2";
+       };
+};
+
+&ssi1 {
+       fsl,mode = "i2s-slave";
+       status = "okay";
+};
+
+&ssi2 {
+       fsl,mode = "i2s-slave";
+       status = "okay";
+};
+
+&uart1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart1>;
+       status = "okay";
+};
+
+&uart2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart2>;
+       status = "okay";
+};
+
+&uart5 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart5>;
+       status = "okay";
+};
+
+&usbotg {
+       vbus-supply = <&reg_usb_otg_vbus>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usbotg>;
+       disable-over-current;
+       status = "okay";
+};
+
+&usbh1 {
+       vbus-supply = <&reg_usb_h1_vbus>;
+       status = "okay";
+};
+
+&usdhc3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usdhc3>;
+       cd-gpios = <&gpio7 0 0>;
+       vmmc-supply = <&reg_3p3v>;
+       status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6qdl-pingrp.h b/arch/arm/boot/dts/imx6qdl-pingrp.h
new file mode 100644 (file)
index 0000000..8d71b13
--- /dev/null
@@ -0,0 +1,526 @@
+/*
+ * Copyright (C) 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.
+ *
+ */
+
+#ifndef __DTS_IMX6QDL_PINGRP_H
+#define __DTS_IMX6QDL_PINGRP_H
+
+#define MX6QDL_AUDMUX_PINGRP1 \
+       MX6QDL_PAD_SD2_DAT0__AUD4_RXD                   0x130b0 \
+       MX6QDL_PAD_SD2_DAT3__AUD4_TXC                   0x130b0 \
+       MX6QDL_PAD_SD2_DAT2__AUD4_TXD                   0x110b0 \
+       MX6QDL_PAD_SD2_DAT1__AUD4_TXFS                  0x130b0
+
+#define MX6QDL_AUDMUX_PINGRP2 \
+       MX6QDL_PAD_CSI0_DAT7__AUD3_RXD                  0x130b0 \
+       MX6QDL_PAD_CSI0_DAT4__AUD3_TXC                  0x130b0 \
+       MX6QDL_PAD_CSI0_DAT5__AUD3_TXD                  0x110b0 \
+       MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS                 0x130b0
+
+#define MX6QDL_AUDMUX_PINGRP3 \
+       MX6QDL_PAD_DISP0_DAT16__AUD5_TXC                0x130b0 \
+       MX6QDL_PAD_DISP0_DAT18__AUD5_TXFS               0x130b0 \
+       MX6QDL_PAD_DISP0_DAT19__AUD5_RXD                0x130b0 \
+
+#define MX6QDL_AUDMUX_PINGRP4 \
+       MX6QDL_PAD_EIM_D24__AUD5_RXFS                   0x130b0 \
+       MX6QDL_PAD_EIM_D25__AUD5_RXC                    0x130b0 \
+       MX6QDL_PAD_DISP0_DAT19__AUD5_RXD                0x130b0
+
+#define MX6QDL_ECSPI1_PINGRP1 \
+       MX6QDL_PAD_EIM_D17__ECSPI1_MISO                 0x100b1 \
+       MX6QDL_PAD_EIM_D18__ECSPI1_MOSI                 0x100b1 \
+       MX6QDL_PAD_EIM_D16__ECSPI1_SCLK                 0x100b1
+
+#define MX6QDL_ECSPI1_PINGRP2 \
+       MX6QDL_PAD_KEY_COL1__ECSPI1_MISO                0x100b1 \
+       MX6QDL_PAD_KEY_ROW0__ECSPI1_MOSI                0x100b1 \
+       MX6QDL_PAD_KEY_COL0__ECSPI1_SCLK                0x100b1
+
+#define MX6QDL_ECSPI3_PINGRP1 \
+       MX6QDL_PAD_DISP0_DAT2__ECSPI3_MISO              0x100b1 \
+       MX6QDL_PAD_DISP0_DAT1__ECSPI3_MOSI              0x100b1 \
+       MX6QDL_PAD_DISP0_DAT0__ECSPI3_SCLK              0x100b1
+
+#define MX6QDL_ENET_PINGRP1 \
+       MX6QDL_PAD_ENET_MDIO__ENET_MDIO                 0x1b0b0 \
+       MX6QDL_PAD_ENET_MDC__ENET_MDC                   0x1b0b0 \
+       MX6QDL_PAD_RGMII_TXC__RGMII_TXC                 0x1b0b0 \
+       MX6QDL_PAD_RGMII_TD0__RGMII_TD0                 0x1b0b0 \
+       MX6QDL_PAD_RGMII_TD1__RGMII_TD1                 0x1b0b0 \
+       MX6QDL_PAD_RGMII_TD2__RGMII_TD2                 0x1b0b0 \
+       MX6QDL_PAD_RGMII_TD3__RGMII_TD3                 0x1b0b0 \
+       MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL           0x1b0b0 \
+       MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK            0x1b0b0 \
+       MX6QDL_PAD_RGMII_RXC__RGMII_RXC                 0x1b0b0 \
+       MX6QDL_PAD_RGMII_RD0__RGMII_RD0                 0x1b0b0 \
+       MX6QDL_PAD_RGMII_RD1__RGMII_RD1                 0x1b0b0 \
+       MX6QDL_PAD_RGMII_RD2__RGMII_RD2                 0x1b0b0 \
+       MX6QDL_PAD_RGMII_RD3__RGMII_RD3                 0x1b0b0 \
+       MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL           0x1b0b0 \
+       MX6QDL_PAD_GPIO_16__ENET_REF_CLK                0x4001b0a8
+
+#define MX6QDL_ENET_PINGRP2 \
+       MX6QDL_PAD_KEY_COL1__ENET_MDIO                  0x1b0b0 \
+       MX6QDL_PAD_KEY_COL2__ENET_MDC                   0x1b0b0 \
+       MX6QDL_PAD_RGMII_TXC__RGMII_TXC                 0x1b0b0 \
+       MX6QDL_PAD_RGMII_TD0__RGMII_TD0                 0x1b0b0 \
+       MX6QDL_PAD_RGMII_TD1__RGMII_TD1                 0x1b0b0 \
+       MX6QDL_PAD_RGMII_TD2__RGMII_TD2                 0x1b0b0 \
+       MX6QDL_PAD_RGMII_TD3__RGMII_TD3                 0x1b0b0 \
+       MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL           0x1b0b0 \
+       MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK            0x1b0b0 \
+       MX6QDL_PAD_RGMII_RXC__RGMII_RXC                 0x1b0b0 \
+       MX6QDL_PAD_RGMII_RD0__RGMII_RD0                 0x1b0b0 \
+       MX6QDL_PAD_RGMII_RD1__RGMII_RD1                 0x1b0b0 \
+       MX6QDL_PAD_RGMII_RD2__RGMII_RD2                 0x1b0b0 \
+       MX6QDL_PAD_RGMII_RD3__RGMII_RD3                 0x1b0b0 \
+       MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL           0x1b0b0
+
+#define MX6QDL_ENET_PINGRP3 \
+       MX6QDL_PAD_ENET_MDIO__ENET_MDIO                 0x1b0b0 \
+       MX6QDL_PAD_ENET_MDC__ENET_MDC                   0x1b0b0 \
+       MX6QDL_PAD_RGMII_TXC__RGMII_TXC                 0x1b0b0 \
+       MX6QDL_PAD_RGMII_TD0__RGMII_TD0                 0x1b0b0 \
+       MX6QDL_PAD_RGMII_TD1__RGMII_TD1                 0x1b0b0 \
+       MX6QDL_PAD_RGMII_TD2__RGMII_TD2                 0x1b0b0 \
+       MX6QDL_PAD_RGMII_TD3__RGMII_TD3                 0x1b0b0 \
+       MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL           0x1b0b0 \
+       MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK            0x1b0b0 \
+       MX6QDL_PAD_RGMII_RXC__RGMII_RXC                 0x1b0b0 \
+       MX6QDL_PAD_RGMII_RD0__RGMII_RD0                 0x1b0b0 \
+       MX6QDL_PAD_RGMII_RD1__RGMII_RD1                 0x1b0b0 \
+       MX6QDL_PAD_RGMII_RD2__RGMII_RD2                 0x1b0b0 \
+       MX6QDL_PAD_RGMII_RD3__RGMII_RD3                 0x1b0b0 \
+       MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL           0x1b0b0 \
+       MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN               0x1b0b0
+
+#define MX6QDL_ESAI_PINGRP1 \
+       MX6QDL_PAD_ENET_RXD0__ESAI_TX_HF_CLK            0x1b030 \
+       MX6QDL_PAD_ENET_CRS_DV__ESAI_TX_CLK             0x1b030 \
+       MX6QDL_PAD_ENET_RXD1__ESAI_TX_FS                0x1b030 \
+       MX6QDL_PAD_ENET_TX_EN__ESAI_TX3_RX2             0x1b030 \
+       MX6QDL_PAD_ENET_TXD1__ESAI_TX2_RX3              0x1b030 \
+       MX6QDL_PAD_ENET_TXD0__ESAI_TX4_RX1              0x1b030 \
+       MX6QDL_PAD_ENET_MDC__ESAI_TX5_RX0               0x1b030 \
+       MX6QDL_PAD_NANDF_CS2__ESAI_TX0                  0x1b030 \
+       MX6QDL_PAD_NANDF_CS3__ESAI_TX1                  0x1b030
+
+#define MX6QDL_ESAI_PINGRP2 \
+       MX6QDL_PAD_ENET_CRS_DV__ESAI_TX_CLK             0x1b030 \
+       MX6QDL_PAD_ENET_RXD1__ESAI_TX_FS                0x1b030 \
+       MX6QDL_PAD_ENET_TX_EN__ESAI_TX3_RX2             0x1b030 \
+       MX6QDL_PAD_GPIO_5__ESAI_TX2_RX3                 0x1b030 \
+       MX6QDL_PAD_ENET_TXD0__ESAI_TX4_RX1              0x1b030 \
+       MX6QDL_PAD_ENET_MDC__ESAI_TX5_RX0               0x1b030 \
+       MX6QDL_PAD_GPIO_17__ESAI_TX0                    0x1b030 \
+       MX6QDL_PAD_NANDF_CS3__ESAI_TX1                  0x1b030 \
+       MX6QDL_PAD_ENET_MDIO__ESAI_RX_CLK               0x1b030 \
+       MX6QDL_PAD_GPIO_9__ESAI_RX_FS                   0x1b030
+
+#define MX6QDL_FLEXCAN1_PINGRP1 \
+       MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX                0x80000000 \
+       MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX                0x80000000
+
+#define MX6QDL_FLEXCAN1_PINGRP2 \
+       MX6QDL_PAD_GPIO_7__FLEXCAN1_TX                  0x80000000 \
+       MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX                0x80000000
+
+#define MX6QDL_FLEXCAN2_PINGRP1 \
+       MX6QDL_PAD_KEY_COL4__FLEXCAN2_TX                0x80000000 \
+       MX6QDL_PAD_KEY_ROW4__FLEXCAN2_RX                0x80000000
+
+#define MX6QDL_GPMI_NAND_PINGRP1 \
+       MX6QDL_PAD_NANDF_CLE__NAND_CLE                  0xb0b1 \
+       MX6QDL_PAD_NANDF_ALE__NAND_ALE                  0xb0b1 \
+       MX6QDL_PAD_NANDF_WP_B__NAND_WP_B                0xb0b1 \
+       MX6QDL_PAD_NANDF_RB0__NAND_READY_B              0xb000 \
+       MX6QDL_PAD_NANDF_CS0__NAND_CE0_B                0xb0b1 \
+       MX6QDL_PAD_NANDF_CS1__NAND_CE1_B                0xb0b1 \
+       MX6QDL_PAD_SD4_CMD__NAND_RE_B                   0xb0b1 \
+       MX6QDL_PAD_SD4_CLK__NAND_WE_B                   0xb0b1 \
+       MX6QDL_PAD_NANDF_D0__NAND_DATA00                0xb0b1 \
+       MX6QDL_PAD_NANDF_D1__NAND_DATA01                0xb0b1 \
+       MX6QDL_PAD_NANDF_D2__NAND_DATA02                0xb0b1 \
+       MX6QDL_PAD_NANDF_D3__NAND_DATA03                0xb0b1 \
+       MX6QDL_PAD_NANDF_D4__NAND_DATA04                0xb0b1 \
+       MX6QDL_PAD_NANDF_D5__NAND_DATA05                0xb0b1 \
+       MX6QDL_PAD_NANDF_D6__NAND_DATA06                0xb0b1 \
+       MX6QDL_PAD_NANDF_D7__NAND_DATA07                0xb0b1 \
+       MX6QDL_PAD_SD4_DAT0__NAND_DQS                   0x00b1
+
+#define MX6QDL_GPMI_NAND_PINGRP1_NODQS \
+       MX6QDL_PAD_NANDF_CLE__NAND_CLE                  0xb0b1 \
+       MX6QDL_PAD_NANDF_ALE__NAND_ALE                  0xb0b1 \
+       MX6QDL_PAD_NANDF_WP_B__NAND_WP_B                0xb0b1 \
+       MX6QDL_PAD_NANDF_RB0__NAND_READY_B              0xb000 \
+       MX6QDL_PAD_NANDF_CS0__NAND_CE0_B                0xb0b1 \
+       MX6QDL_PAD_NANDF_CS1__NAND_CE1_B                0xb0b1 \
+       MX6QDL_PAD_SD4_CMD__NAND_RE_B                   0xb0b1 \
+       MX6QDL_PAD_SD4_CLK__NAND_WE_B                   0xb0b1 \
+       MX6QDL_PAD_NANDF_D0__NAND_DATA00                0xb0b1 \
+       MX6QDL_PAD_NANDF_D1__NAND_DATA01                0xb0b1 \
+       MX6QDL_PAD_NANDF_D2__NAND_DATA02                0xb0b1 \
+       MX6QDL_PAD_NANDF_D3__NAND_DATA03                0xb0b1 \
+       MX6QDL_PAD_NANDF_D4__NAND_DATA04                0xb0b1 \
+       MX6QDL_PAD_NANDF_D5__NAND_DATA05                0xb0b1 \
+       MX6QDL_PAD_NANDF_D6__NAND_DATA06                0xb0b1 \
+       MX6QDL_PAD_NANDF_D7__NAND_DATA07                0xb0b1
+
+#define MX6QDL_HDMI_HDCP_PINGRP1 \
+       MX6QDL_PAD_KEY_COL3__HDMI_TX_DDC_SCL            0x4001b8b1 \
+       MX6QDL_PAD_KEY_ROW3__HDMI_TX_DDC_SDA            0x4001b8b1
+
+#define MX6QDL_HDMI_HDCP_PINGRP2 \
+       MX6QDL_PAD_EIM_EB2__HDMI_TX_DDC_SCL             0x4001b8b1 \
+       MX6QDL_PAD_EIM_D16__HDMI_TX_DDC_SDA             0x4001b8b1
+
+#define MX6QDL_HDMI_HDCP_PINGRP3 \
+       MX6QDL_PAD_EIM_EB2__HDMI_TX_DDC_SCL             0x4001b8b1 \
+       MX6QDL_PAD_KEY_ROW3__HDMI_TX_DDC_SDA            0x4001b8b1
+
+#define MX6QDL_HDMI_CEC_PINGRP1 \
+       MX6QDL_PAD_EIM_A25__HDMI_TX_CEC_LINE            0x1f8b0
+
+#define MX6QDL_HDMI_CEC_PINGRP2 \
+       MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE           0x1f8b0
+
+#define MX6QDL_I2C1_PINGRP1 \
+       MX6QDL_PAD_EIM_D21__I2C1_SCL                    0x4001b8b1 \
+       MX6QDL_PAD_EIM_D28__I2C1_SDA                    0x4001b8b1
+
+#define MX6QDL_I2C1_PINGRP2 \
+       MX6QDL_PAD_CSI0_DAT8__I2C1_SDA                  0x4001b8b1 \
+       MX6QDL_PAD_CSI0_DAT9__I2C1_SCL                  0x4001b8b1
+
+#define MX6QDL_I2C2_PINGRP1 \
+       MX6QDL_PAD_EIM_EB2__I2C2_SCL                    0x4001b8b1 \
+       MX6QDL_PAD_EIM_D16__I2C2_SDA                    0x4001b8b1
+
+#define MX6QDL_I2C2_PINGRP2 \
+       MX6QDL_PAD_KEY_COL3__I2C2_SCL                   0x4001b8b1 \
+       MX6QDL_PAD_KEY_ROW3__I2C2_SDA                   0x4001b8b1
+
+#define MX6QDL_I2C2_PINGRP3 \
+       MX6QDL_PAD_EIM_EB2__I2C2_SCL                    0x4001b8b1 \
+       MX6QDL_PAD_KEY_ROW3__I2C2_SDA                   0x4001b8b1
+
+#define MX6QDL_I2C3_PINGRP1 \
+       MX6QDL_PAD_EIM_D17__I2C3_SCL                    0x4001b8b1 \
+       MX6QDL_PAD_EIM_D18__I2C3_SDA                    0x4001b8b1
+
+#define MX6QDL_I2C3_PINGRP2 \
+       MX6QDL_PAD_GPIO_3__I2C3_SCL                     0x4001b8b1 \
+       MX6QDL_PAD_GPIO_6__I2C3_SDA                     0x4001b8b1
+
+#define MX6QDL_I2C3_PINGRP3 \
+       MX6QDL_PAD_GPIO_5__I2C3_SCL                     0x4001b8b1 \
+       MX6QDL_PAD_GPIO_16__I2C3_SDA                    0x4001b8b1
+
+#define MX6QDL_I2C3_PINGRP4 \
+       MX6QDL_PAD_GPIO_3__I2C3_SCL                     0x4001b8b1 \
+       MX6QDL_PAD_EIM_D18__I2C3_SDA                    0x4001b8b1
+
+#define MX6QDL_IPU1_PINGRP1 \
+       MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK      0x10 \
+       MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15            0x10 \
+       MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02             0x10 \
+       MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03             0x10 \
+       MX6QDL_PAD_DI0_PIN4__IPU1_DI0_PIN04             0x80000000 \
+       MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00        0x10 \
+       MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01        0x10 \
+       MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02        0x10 \
+       MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03        0x10 \
+       MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04        0x10 \
+       MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05        0x10 \
+       MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06        0x10 \
+       MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07        0x10 \
+       MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08        0x10 \
+       MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09        0x10 \
+       MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10       0x10 \
+       MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11       0x10 \
+       MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12       0x10 \
+       MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13       0x10 \
+       MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14       0x10 \
+       MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15       0x10 \
+       MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16       0x10 \
+       MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17       0x10 \
+       MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18       0x10 \
+       MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19       0x10 \
+       MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20       0x10 \
+       MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21       0x10 \
+       MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22       0x10 \
+       MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23       0x10
+
+/* parallel camera */
+#define MX6QDL_IPU1_PINGRP2 \
+       MX6QDL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12         0x80000000 \
+       MX6QDL_PAD_CSI0_DAT13__IPU1_CSI0_DATA13         0x80000000 \
+       MX6QDL_PAD_CSI0_DAT14__IPU1_CSI0_DATA14         0x80000000 \
+       MX6QDL_PAD_CSI0_DAT15__IPU1_CSI0_DATA15         0x80000000 \
+       MX6QDL_PAD_CSI0_DAT16__IPU1_CSI0_DATA16         0x80000000 \
+       MX6QDL_PAD_CSI0_DAT17__IPU1_CSI0_DATA17         0x80000000 \
+       MX6QDL_PAD_CSI0_DAT18__IPU1_CSI0_DATA18         0x80000000 \
+       MX6QDL_PAD_CSI0_DAT19__IPU1_CSI0_DATA19         0x80000000 \
+       MX6QDL_PAD_CSI0_DATA_EN__IPU1_CSI0_DATA_EN      0x80000000 \
+       MX6QDL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK        0x80000000 \
+       MX6QDL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC           0x80000000 \
+       MX6QDL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC          0x80000000
+
+/* parallel port 16-bit */
+#define MX6QDL_IPU1_PINGRP3 \
+       MX6QDL_PAD_CSI0_DAT4__IPU1_CSI0_DATA04          0x80000000 \
+       MX6QDL_PAD_CSI0_DAT5__IPU1_CSI0_DATA05          0x80000000 \
+       MX6QDL_PAD_CSI0_DAT6__IPU1_CSI0_DATA06          0x80000000 \
+       MX6QDL_PAD_CSI0_DAT7__IPU1_CSI0_DATA07          0x80000000 \
+       MX6QDL_PAD_CSI0_DAT8__IPU1_CSI0_DATA08          0x80000000 \
+       MX6QDL_PAD_CSI0_DAT9__IPU1_CSI0_DATA09          0x80000000 \
+       MX6QDL_PAD_CSI0_DAT10__IPU1_CSI0_DATA10         0x80000000 \
+       MX6QDL_PAD_CSI0_DAT11__IPU1_CSI0_DATA11         0x80000000 \
+       MX6QDL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12         0x80000000 \
+       MX6QDL_PAD_CSI0_DAT13__IPU1_CSI0_DATA13         0x80000000 \
+       MX6QDL_PAD_CSI0_DAT14__IPU1_CSI0_DATA14         0x80000000 \
+       MX6QDL_PAD_CSI0_DAT15__IPU1_CSI0_DATA15         0x80000000 \
+       MX6QDL_PAD_CSI0_DAT16__IPU1_CSI0_DATA16         0x80000000 \
+       MX6QDL_PAD_CSI0_DAT17__IPU1_CSI0_DATA17         0x80000000 \
+       MX6QDL_PAD_CSI0_DAT18__IPU1_CSI0_DATA18         0x80000000 \
+       MX6QDL_PAD_CSI0_DAT19__IPU1_CSI0_DATA19         0x80000000 \
+       MX6QDL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK        0x80000000 \
+       MX6QDL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC           0x80000000 \
+       MX6QDL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC          0x80000000
+
+#define MX6QDL_MLB_PINGRP1 \
+       MX6QDL_PAD_GPIO_3__MLB_CLK                      0x71 \
+       MX6QDL_PAD_GPIO_6__MLB_SIG                      0x71 \
+       MX6QDL_PAD_GPIO_2__MLB_DATA                     0x71
+
+#define MX6QDL_MLB_PINGRP2 \
+       MX6QDL_PAD_ENET_TXD1__MLB_CLK                   0x71 \
+       MX6QDL_PAD_GPIO_6__MLB_SIG                      0x71 \
+       MX6QDL_PAD_GPIO_2__MLB_DATA                     0x71
+
+#define MX6QDL_PWM1_PINGRP1 \
+       MX6QDL_PAD_SD1_DAT3__PWM1_OUT                   0x1b0b1
+
+#define MX6QDL_PWM3_PINGRP1 \
+       MX6QDL_PAD_SD4_DAT1__PWM3_OUT                   0x1b0b1
+
+#define MX6QDL_SPDIF_PINGRP1 \
+       MX6QDL_PAD_KEY_COL3__SPDIF_IN                   0x1b0b0
+
+#define MX6QDL_SPDIF_PINGRP2 \
+       MX6QDL_PAD_GPIO_16__SPDIF_IN                    0x1b0b0 \
+       MX6QDL_PAD_GPIO_17__SPDIF_OUT                   0x1b0b0
+
+#define MX6QDL_SPDIF_PINGRP3 \
+       MX6QDL_PAD_ENET_RXD0__SPDIF_OUT                 0x1b0b0
+
+#define MX6QDL_UART1_PINGRP1 \
+       MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA            0x1b0b1 \
+       MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA            0x1b0b1
+
+#define MX6QDL_UART1_PINGRP2 \
+       MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA              0x1b0b1 \
+       MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA              0x1b0b1
+
+#define MX6QDL_UART2_PINGRP1 \
+       MX6QDL_PAD_EIM_D26__UART2_TX_DATA               0x1b0b1 \
+       MX6QDL_PAD_EIM_D27__UART2_RX_DATA               0x1b0b1
+
+/* DTE mode */
+#define MX6QDL_UART2_PINGRP2 \
+       MX6QDL_PAD_EIM_D26__UART2_RX_DATA               0x1b0b1 \
+       MX6QDL_PAD_EIM_D27__UART2_TX_DATA               0x1b0b1 \
+       MX6QDL_PAD_EIM_D28__UART2_DTE_CTS_B             0x1b0b1 \
+       MX6QDL_PAD_EIM_D29__UART2_DTE_RTS_B             0x1b0b1
+
+#define MX6QDL_UART2_PINGRP3 \
+       MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA              0x1b0b1 \
+       MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA              0x1b0b1
+
+#define MX6QDL_UART3_PINGRP1 \
+       MX6QDL_PAD_SD4_CLK__UART3_RX_DATA               0x1b0b1 \
+       MX6QDL_PAD_SD4_CMD__UART3_TX_DATA               0x1b0b1 \
+       MX6QDL_PAD_EIM_D30__UART3_CTS_B                 0x1b0b1 \
+       MX6QDL_PAD_EIM_EB3__UART3_RTS_B                 0x1b0b1
+
+#define MX6QDL_UART3_PINGRP2 \
+       MX6QDL_PAD_EIM_D24__UART3_TX_DATA               0x1b0b1 \
+       MX6QDL_PAD_EIM_D25__UART3_RX_DATA               0x1b0b1 \
+       MX6QDL_PAD_EIM_D23__UART3_CTS_B                 0x1b0b1 \
+       MX6QDL_PAD_EIM_EB3__UART3_RTS_B                 0x1b0b1
+
+#define MX6QDL_UART3_PINGRP3 \
+       MX6QDL_PAD_EIM_D24__UART3_TX_DATA               0x1b0b1 \
+       MX6QDL_PAD_EIM_D25__UART3_RX_DATA               0x1b0b1
+
+#define MX6QDL_UART4_PINGRP1 \
+       MX6QDL_PAD_KEY_COL0__UART4_TX_DATA              0x1b0b1 \
+       MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA              0x1b0b1
+
+#define MX6QDL_UART5_PINGRP1 \
+       MX6QDL_PAD_KEY_COL1__UART5_TX_DATA              0x1b0b1 \
+       MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA              0x1b0b1
+
+#define MX6QDL_USBOTG_PINGRP1 \
+       MX6QDL_PAD_GPIO_1__USB_OTG_ID                   0x17059
+
+#define MX6QDL_USBOTG_PINGRP2 \
+       MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID               0x17059
+
+#define MX6QDL_USBH2_PINGRP1 \
+       MX6QDL_PAD_RGMII_TXC__USB_H2_DATA               0x40013030 \
+       MX6QDL_PAD_RGMII_TX_CTL__USB_H2_STROBE          0x40013030
+
+#define MX6QDL_USBH2_PINGRP2 \
+       MX6QDL_PAD_RGMII_TX_CTL__USB_H2_STROBE          0x40017030
+
+#define MX6QDL_USBH3_PINGRP1 \
+       MX6QDL_PAD_RGMII_RX_CTL__USB_H3_DATA            0x40013030 \
+       MX6QDL_PAD_RGMII_RXC__USB_H3_STROBE             0x40013030
+
+#define MX6QDL_USBH3_PINGRP2 \
+       MX6QDL_PAD_RGMII_RXC__USB_H3_STROBE             0x40017030
+
+#define MX6QDL_USDHC1_D4(pad, pad_data3, pad_clk)      \
+       MX6QDL_PAD_SD1_CMD__SD1_CMD                     pad \
+       MX6QDL_PAD_SD1_CLK__SD1_CLK                     pad_clk \
+       MX6QDL_PAD_SD1_DAT0__SD1_DATA0                  pad \
+       MX6QDL_PAD_SD1_DAT1__SD1_DATA1                  pad \
+       MX6QDL_PAD_SD1_DAT2__SD1_DATA2                  pad \
+       MX6QDL_PAD_SD1_DAT3__SD1_DATA3                  pad_data3
+
+#define MX6QDL_USDHC1_D8(pad, pad_data3, pad_clk)      \
+       MX6QDL_USDHC1_D4(pad, pad_data3, pad_clk)       \
+       MX6QDL_PAD_NANDF_D0__SD1_DATA4                  pad \
+       MX6QDL_PAD_NANDF_D1__SD1_DATA5                  pad \
+       MX6QDL_PAD_NANDF_D2__SD1_DATA6                  pad \
+       MX6QDL_PAD_NANDF_D3__SD1_DATA7                  pad
+
+#define MX6QDL_USDHC2_D4(pad, pad_data3, pad_clk)      \
+       MX6QDL_PAD_SD2_CMD__SD2_CMD                     pad \
+       MX6QDL_PAD_SD2_CLK__SD2_CLK                     pad_clk \
+       MX6QDL_PAD_SD2_DAT0__SD2_DATA0                  pad \
+       MX6QDL_PAD_SD2_DAT1__SD2_DATA1                  pad \
+       MX6QDL_PAD_SD2_DAT2__SD2_DATA2                  pad \
+       MX6QDL_PAD_SD2_DAT3__SD2_DATA3                  pad_data3
+
+#define MX6QDL_USDHC2_D8(pad, pad_data3, pad_clk)      \
+       MX6QDL_USDHC2_D4(pad, pad_data3, pad_clk)       \
+       MX6QDL_PAD_NANDF_D4__SD2_DATA4                  pad \
+       MX6QDL_PAD_NANDF_D5__SD2_DATA5                  pad \
+       MX6QDL_PAD_NANDF_D6__SD2_DATA6                  pad \
+       MX6QDL_PAD_NANDF_D7__SD2_DATA7                  pad
+
+#define MX6QDL_USDHC3_D4(pad, pad_data3, pad_clk)      \
+       MX6QDL_PAD_SD3_CMD__SD3_CMD                     pad \
+       MX6QDL_PAD_SD3_CLK__SD3_CLK                     pad_clk \
+       MX6QDL_PAD_SD3_DAT0__SD3_DATA0                  pad \
+       MX6QDL_PAD_SD3_DAT1__SD3_DATA1                  pad \
+       MX6QDL_PAD_SD3_DAT2__SD3_DATA2                  pad \
+       MX6QDL_PAD_SD3_DAT3__SD3_DATA3                  pad_data3
+
+#define MX6QDL_USDHC3_D8(pad, pad_data3, pad_clk)      \
+       MX6QDL_USDHC3_D4(pad, pad_data3, pad_clk)       \
+       MX6QDL_PAD_SD3_DAT4__SD3_DATA4                  pad \
+       MX6QDL_PAD_SD3_DAT5__SD3_DATA5                  pad \
+       MX6QDL_PAD_SD3_DAT6__SD3_DATA6                  pad \
+       MX6QDL_PAD_SD3_DAT7__SD3_DATA7                  pad
+
+#define MX6QDL_USDHC4_D4(pad, pad_data3, pad_clk)      \
+       MX6QDL_PAD_SD4_CMD__SD4_CMD                     pad \
+       MX6QDL_PAD_SD4_CLK__SD4_CLK                     pad_clk \
+       MX6QDL_PAD_SD4_DAT0__SD4_DATA0                  pad \
+       MX6QDL_PAD_SD4_DAT1__SD4_DATA1                  pad \
+       MX6QDL_PAD_SD4_DAT2__SD4_DATA2                  pad \
+       MX6QDL_PAD_SD4_DAT3__SD4_DATA3                  pad_data3
+
+#define MX6QDL_USDHC4_D8(pad, pad_data3, pad_clk)      \
+       MX6QDL_USDHC4_D4(pad, pad_data3, pad_clk)       \
+       MX6QDL_PAD_SD4_DAT4__SD4_DATA4                  pad \
+       MX6QDL_PAD_SD4_DAT5__SD4_DATA5                  pad \
+       MX6QDL_PAD_SD4_DAT6__SD4_DATA6                  pad \
+       MX6QDL_PAD_SD4_DAT7__SD4_DATA7                  pad
+
+#define MX6QDL_USDHC1_PINGRP_D4               MX6QDL_USDHC1_D4(0x17059,0x17059,0x10059)
+#define MX6QDL_USDHC1_PINGRP_D4_100MHZ MX6QDL_USDHC1_D4(0x170b9,0x170b9,0x100b9)
+#define MX6QDL_USDHC1_PINGRP_D4_200MHZ MX6QDL_USDHC1_D4(0x170f9,0x170f9,0x100f9)
+#define MX6QDL_USDHC1_PINGRP_D8               MX6QDL_USDHC1_D8(0x17059,0x17059,0x10059)
+#define MX6QDL_USDHC1_PINGRP_D8_100MHZ MX6QDL_USDHC1_D8(0x170b9,0x170b9,0x100b9)
+#define MX6QDL_USDHC1_PINGRP_D8_200MHZ MX6QDL_USDHC1_D8(0x170f9,0x170f9,0x100f9)
+
+#define MX6QDL_USDHC2_PINGRP_D4               MX6QDL_USDHC2_D4(0x17059,0x17059,0x10059)
+#define MX6QDL_USDHC2_PINGRP_D4_100MHZ MX6QDL_USDHC2_D4(0x170b9,0x170b9,0x100b9)
+#define MX6QDL_USDHC2_PINGRP_D4_200MHZ MX6QDL_USDHC2_D4(0x170f9,0x170f9,0x100f9)
+#define MX6QDL_USDHC2_PINGRP_D8               MX6QDL_USDHC2_D8(0x17059,0x17059,0x10059)
+#define MX6QDL_USDHC2_PINGRP_D8_100MHZ MX6QDL_USDHC2_D8(0x170b9,0x170b9,0x100b9)
+#define MX6QDL_USDHC2_PINGRP_D8_200MHZ MX6QDL_USDHC2_D8(0x170f9,0x170f9,0x100f9)
+
+#define MX6QDL_USDHC3_PINGRP_D4               MX6QDL_USDHC3_D4(0x17059,0x17059,0x10059)
+#define MX6QDL_USDHC3_PINGRP_D4_100MHZ MX6QDL_USDHC3_D4(0x170b9,0x170b9,0x100b9)
+#define MX6QDL_USDHC3_PINGRP_D4_200MHZ MX6QDL_USDHC3_D4(0x170f9,0x170f9,0x100f9)
+#define MX6QDL_USDHC3_PINGRP_D8               MX6QDL_USDHC3_D8(0x17059,0x17059,0x10059)
+#define MX6QDL_USDHC3_PINGRP_D8_100MHZ MX6QDL_USDHC3_D8(0x170b9,0x170b9,0x100b9)
+#define MX6QDL_USDHC3_PINGRP_D8_200MHZ MX6QDL_USDHC3_D8(0x170f9,0x170f9,0x100f9)
+
+#define MX6QDL_USDHC4_PINGRP_D4               MX6QDL_USDHC4_D4(0x17059,0x17059,0x10059)
+#define MX6QDL_USDHC4_PINGRP_D4_100MHZ MX6QDL_USDHC4_D4(0x170b9,0x170b9,0x100b9)
+#define MX6QDL_USDHC4_PINGRP_D4_200MHZ MX6QDL_USDHC4_D4(0x170f9,0x170f9,0x100f9)
+#define MX6QDL_USDHC4_PINGRP_D8               MX6QDL_USDHC4_D8(0x17059,0x17059,0x10059)
+#define MX6QDL_USDHC4_PINGRP_D8_100MHZ MX6QDL_USDHC4_D8(0x170b9,0x170b9,0x100b9)
+#define MX6QDL_USDHC4_PINGRP_D8_200MHZ MX6QDL_USDHC4_D8(0x170f9,0x170f9,0x100f9)
+
+#define MX6QDL_WEIM_CS0_PINGRP1 \
+       MX6QDL_PAD_EIM_CS0__EIM_CS0_B                   0xb0b1
+
+#define MX6QDL_WEIM_NOR_PINGRP1 \
+       MX6QDL_PAD_EIM_OE__EIM_OE_B                     0xb0b1 \
+       MX6QDL_PAD_EIM_RW__EIM_RW                       0xb0b1 \
+       MX6QDL_PAD_EIM_WAIT__EIM_WAIT_B                 0xb060 \
+       MX6QDL_PAD_EIM_D16__EIM_DATA16                  0x1b0b0 \
+       MX6QDL_PAD_EIM_D17__EIM_DATA17                  0x1b0b0 \
+       MX6QDL_PAD_EIM_D18__EIM_DATA18                  0x1b0b0 \
+       MX6QDL_PAD_EIM_D19__EIM_DATA19                  0x1b0b0 \
+       MX6QDL_PAD_EIM_D20__EIM_DATA20                  0x1b0b0 \
+       MX6QDL_PAD_EIM_D21__EIM_DATA21                  0x1b0b0 \
+       MX6QDL_PAD_EIM_D22__EIM_DATA22                  0x1b0b0 \
+       MX6QDL_PAD_EIM_D23__EIM_DATA23                  0x1b0b0 \
+       MX6QDL_PAD_EIM_D24__EIM_DATA24                  0x1b0b0 \
+       MX6QDL_PAD_EIM_D25__EIM_DATA25                  0x1b0b0 \
+       MX6QDL_PAD_EIM_D26__EIM_DATA26                  0x1b0b0 \
+       MX6QDL_PAD_EIM_D27__EIM_DATA27                  0x1b0b0 \
+       MX6QDL_PAD_EIM_D28__EIM_DATA28                  0x1b0b0 \
+       MX6QDL_PAD_EIM_D29__EIM_DATA29                  0x1b0b0 \
+       MX6QDL_PAD_EIM_D30__EIM_DATA30                  0x1b0b0 \
+       MX6QDL_PAD_EIM_D31__EIM_DATA31                  0x1b0b0 \
+       MX6QDL_PAD_EIM_A23__EIM_ADDR23                  0xb0b1 \
+       MX6QDL_PAD_EIM_A22__EIM_ADDR22                  0xb0b1 \
+       MX6QDL_PAD_EIM_A21__EIM_ADDR21                  0xb0b1 \
+       MX6QDL_PAD_EIM_A20__EIM_ADDR20                  0xb0b1 \
+       MX6QDL_PAD_EIM_A19__EIM_ADDR19                  0xb0b1 \
+       MX6QDL_PAD_EIM_A18__EIM_ADDR18                  0xb0b1 \
+       MX6QDL_PAD_EIM_A17__EIM_ADDR17                  0xb0b1 \
+       MX6QDL_PAD_EIM_A16__EIM_ADDR16                  0xb0b1 \
+       MX6QDL_PAD_EIM_DA15__EIM_AD15                   0xb0b1 \
+       MX6QDL_PAD_EIM_DA14__EIM_AD14                   0xb0b1 \
+       MX6QDL_PAD_EIM_DA13__EIM_AD13                   0xb0b1 \
+       MX6QDL_PAD_EIM_DA12__EIM_AD12                   0xb0b1 \
+       MX6QDL_PAD_EIM_DA11__EIM_AD11                   0xb0b1 \
+       MX6QDL_PAD_EIM_DA10__EIM_AD10                   0xb0b1 \
+       MX6QDL_PAD_EIM_DA9__EIM_AD09                    0xb0b1 \
+       MX6QDL_PAD_EIM_DA8__EIM_AD08                    0xb0b1 \
+       MX6QDL_PAD_EIM_DA7__EIM_AD07                    0xb0b1 \
+       MX6QDL_PAD_EIM_DA6__EIM_AD06                    0xb0b1 \
+       MX6QDL_PAD_EIM_DA5__EIM_AD05                    0xb0b1 \
+       MX6QDL_PAD_EIM_DA4__EIM_AD04                    0xb0b1 \
+       MX6QDL_PAD_EIM_DA3__EIM_AD03                    0xb0b1 \
+       MX6QDL_PAD_EIM_DA2__EIM_AD02                    0xb0b1 \
+       MX6QDL_PAD_EIM_DA1__EIM_AD01                    0xb0b1 \
+       MX6QDL_PAD_EIM_DA0__EIM_AD00                    0xb0b1
+
+#endif /* __DTS_IMX6QDL_PINGRP_H */
index ff6f1e8f2dd9bfa54a6387998421f1ac8877c841..a526796fdaacc6ecf6ebfe03342cf9f81a00acbe 100644 (file)
@@ -20,7 +20,7 @@
        fsl,spi-num-chipselects = <1>;
        cs-gpios = <&gpio3 19 0>;
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_ecspi1_1 &pinctrl_ecspi1_sabreauto>;
+       pinctrl-0 = <&pinctrl_ecspi1 &pinctrl_ecspi1_cs>;
        status = "disabled"; /* pin conflict with WEIM NOR */
 
        flash: m25p80@0 {
 
 &fec {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_enet_2>;
+       pinctrl-0 = <&pinctrl_enet>;
        phy-mode = "rgmii";
        status = "okay";
 };
 
 &gpmi {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_gpmi_nand_1>;
+       pinctrl-0 = <&pinctrl_gpmi_nand>;
        status = "okay";
 };
 
@@ -49,7 +49,7 @@
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_hog>;
 
-       hog {
+       imx6qdl-sabreauto {
                pinctrl_hog: hoggrp {
                        fsl,pins = <
                                MX6QDL_PAD_NANDF_CS2__GPIO6_IO15 0x80000000
                                MX6QDL_PAD_GPIO_18__SD3_VSELECT 0x17059
                        >;
                };
-       };
 
-       ecspi1 {
-               pinctrl_ecspi1_sabreauto: ecspi1-sabreauto {
+               pinctrl_ecspi1: ecspi1grp {
+                       fsl,pins = <MX6QDL_ECSPI1_PINGRP1>;
+               };
+
+               pinctrl_ecspi1_cs: ecspi1cs {
                        fsl,pins = <
                                MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x80000000
                        >;
                };
+
+               pinctrl_enet: enetgrp {
+                       fsl,pins = <MX6QDL_ENET_PINGRP2>;
+               };
+
+               pinctrl_gpmi_nand: gpminandgrp {
+                       fsl,pins = <MX6QDL_GPMI_NAND_PINGRP1>;
+               };
+
+               pinctrl_uart4: uart4grp {
+                       fsl,pins = <MX6QDL_UART4_PINGRP1>;
+               };
+
+               pinctrl_usdhc3: usdhc3grp {
+                       fsl,pins = <MX6QDL_USDHC3_PINGRP_D8>;
+               };
+
+               pinctrl_usdhc3_100mhz: usdhc3grp100mhz {
+                       fsl,pins = <MX6QDL_USDHC3_PINGRP_D8_100MHZ>;
+               };
+
+               pinctrl_usdhc3_200mhz: usdhc3grp200mhz {
+                       fsl,pins = <MX6QDL_USDHC3_PINGRP_D8_200MHZ>;
+               };
+
+               pinctrl_weim_cs0: weimcs0grp {
+                       fsl,pins = <MX6QDL_WEIM_CS0_PINGRP1>;
+               };
+
+               pinctrl_weim_nor: weimnorgrp {
+                       fsl,pins = <MX6QDL_WEIM_NOR_PINGRP1>;
+               };
        };
 };
 
 &uart4 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_uart4_1>;
+       pinctrl-0 = <&pinctrl_uart4>;
        status = "okay";
 };
 
 &usdhc3 {
        pinctrl-names = "default", "state_100mhz", "state_200mhz";
-       pinctrl-0 = <&pinctrl_usdhc3_1>;
-       pinctrl-1 = <&pinctrl_usdhc3_1_100mhz>;
-       pinctrl-2 = <&pinctrl_usdhc3_1_200mhz>;
+       pinctrl-0 = <&pinctrl_usdhc3>;
+       pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
+       pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
        cd-gpios = <&gpio6 15 0>;
        wp-gpios = <&gpio1 13 0>;
        status = "okay";
 
 &weim {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_weim_nor_1 &pinctrl_weim_cs0_1>;
+       pinctrl-0 = <&pinctrl_weim_nor &pinctrl_weim_cs0>;
        #address-cells = <2>;
        #size-cells = <1>;
        ranges = <0 0 0x08000000 0x08000000>;
index e75e11b36dffec5ea9e695c01d8f66ac35b83dee..570767f8c8313c74ce4a163848c1988e1d2e65aa 100644 (file)
 
        regulators {
                compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
 
-               reg_usb_otg_vbus: usb_otg_vbus {
+               reg_usb_otg_vbus: regulator@0 {
                        compatible = "regulator-fixed";
+                       reg = <0>;
                        regulator-name = "usb_otg_vbus";
                        regulator-min-microvolt = <5000000>;
                        regulator-max-microvolt = <5000000>;
@@ -27,8 +30,9 @@
                        enable-active-high;
                };
 
-               reg_usb_h1_vbus: usb_h1_vbus {
+               reg_usb_h1_vbus: regulator@1 {
                        compatible = "regulator-fixed";
+                       reg = <1>;
                        regulator-name = "usb_h1_vbus";
                        regulator-min-microvolt = <5000000>;
                        regulator-max-microvolt = <5000000>;
@@ -36,8 +40,9 @@
                        enable-active-high;
                };
 
-               reg_audio: wm8962_supply {
+               reg_audio: regulator@2 {
                        compatible = "regulator-fixed";
+                       reg = <2>;
                        regulator-name = "wm8962-supply";
                        gpio = <&gpio4 10 0>;
                        enable-active-high;
@@ -92,7 +97,7 @@
 
 &audmux {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_audmux_2>;
+       pinctrl-0 = <&pinctrl_audmux>;
        status = "okay";
 };
 
        fsl,spi-num-chipselects = <1>;
        cs-gpios = <&gpio4 9 0>;
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_ecspi1_2>;
+       pinctrl-0 = <&pinctrl_ecspi1>;
        status = "okay";
 
        flash: m25p80@0 {
 
 &fec {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_enet_1>;
+       pinctrl-0 = <&pinctrl_enet>;
        phy-mode = "rgmii";
        phy-reset-gpios = <&gpio1 25 0>;
        status = "okay";
 &i2c1 {
        clock-frequency = <100000>;
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_i2c1_2>;
+       pinctrl-0 = <&pinctrl_i2c1>;
        status = "okay";
 
        codec: wm8962@1a {
 &i2c3 {
        clock-frequency = <100000>;
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_i2c3_2>;
+       pinctrl-0 = <&pinctrl_i2c3>;
        status = "okay";
 
        egalax_ts@04 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_hog>;
 
-       hog {
+       imx6qdl-sabresd {
                pinctrl_hog: hoggrp {
                        fsl,pins = <
                                MX6QDL_PAD_GPIO_4__GPIO1_IO04   0x80000000
                                MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25 0x80000000
                        >;
                };
+
+               pinctrl_audmux: audmuxgrp {
+                       fsl,pins = <MX6QDL_AUDMUX_PINGRP2>;
+               };
+
+               pinctrl_ecspi1: ecspi1grp {
+                       fsl,pins = <MX6QDL_ECSPI1_PINGRP2>;
+               };
+
+               pinctrl_enet: enetgrp {
+                       fsl,pins = <MX6QDL_ENET_PINGRP1>;
+               };
+
+               pinctrl_i2c1: i2c1grp {
+                       fsl,pins = <MX6QDL_I2C1_PINGRP2>;
+               };
+
+               pinctrl_i2c3: i2c3grp {
+                       fsl,pins = <MX6QDL_I2C3_PINGRP2>;
+               };
+
+               pinctrl_pwm1: pwm1grp {
+                       fsl,pins = <MX6QDL_PWM1_PINGRP1>;
+               };
+
+               pinctrl_uart1: uart1grp {
+                       fsl,pins = <MX6QDL_UART1_PINGRP1>;
+               };
+
+               pinctrl_usbotg: usbotggrp {
+                       fsl,pins = <MX6QDL_USBOTG_PINGRP2>;
+               };
+
+               pinctrl_usdhc2: usdhc2grp {
+                       fsl,pins = <MX6QDL_USDHC2_PINGRP_D8>;
+               };
+
+               pinctrl_usdhc3: usdhc3grp {
+                       fsl,pins = <MX6QDL_USDHC3_PINGRP_D8>;
+               };
        };
 };
 
 
 &pwm1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_pwm0_1>;
+       pinctrl-0 = <&pinctrl_pwm1>;
        status = "okay";
 };
 
 
 &uart1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_uart1_1>;
+       pinctrl-0 = <&pinctrl_uart1>;
        status = "okay";
 };
 
 &usbotg {
        vbus-supply = <&reg_usb_otg_vbus>;
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_usbotg_2>;
+       pinctrl-0 = <&pinctrl_usbotg>;
        disable-over-current;
        status = "okay";
 };
 
 &usdhc2 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_usdhc2_1>;
+       pinctrl-0 = <&pinctrl_usdhc2>;
        bus-width = <8>;
        cd-gpios = <&gpio2 2 0>;
        wp-gpios = <&gpio2 3 0>;
 
 &usdhc3 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_usdhc3_1>;
+       pinctrl-0 = <&pinctrl_usdhc3>;
        bus-width = <8>;
        cd-gpios = <&gpio2 0 0>;
        wp-gpios = <&gpio2 1 0>;
index 35f54792916795dd85d77624289d94ee3ab97811..88894b13ccd23e96702b27501c012a8f3aa1921a 100644 (file)
 / {
        regulators {
                compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
 
-               reg_2p5v: 2p5v {
+               reg_2p5v: regulator@0 {
                        compatible = "regulator-fixed";
+                       reg = <0>;
                        regulator-name = "2P5V";
                        regulator-min-microvolt = <2500000>;
                        regulator-max-microvolt = <2500000>;
                        regulator-always-on;
                };
 
-               reg_3p3v: 3p3v {
+               reg_3p3v: regulator@1 {
                        compatible = "regulator-fixed";
+                       reg = <1>;
                        regulator-name = "3P3V";
                        regulator-min-microvolt = <3300000>;
                        regulator-max-microvolt = <3300000>;
 
 &audmux {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_audmux_2>;
+       pinctrl-0 = <&pinctrl_audmux>;
        status = "okay";
 };
 
 &i2c2 {
        clock-frequency = <100000>;
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_i2c2_2>;
+       pinctrl-0 = <&pinctrl_i2c2>;
        status = "okay";
 
        codec: sgtl5000@0a {
@@ -77,7 +81,7 @@
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_hog>;
 
-       hog {
+       imx6qdl-wandboard {
                pinctrl_hog: hoggrp {
                        fsl,pins = <
                                MX6QDL_PAD_GPIO_0__CCM_CLKO1     0x130b0
                                MX6QDL_PAD_EIM_D29__GPIO3_IO29   0x80000000
                        >;
                };
+
+               pinctrl_audmux: audmuxgrp {
+                       fsl,pins = <MX6QDL_AUDMUX_PINGRP2>;
+               };
+
+               pinctrl_enet: enetgrp {
+                       fsl,pins = <MX6QDL_ENET_PINGRP1>;
+               };
+
+               pinctrl_i2c2: i2c2grp {
+                       fsl,pins = <MX6QDL_I2C2_PINGRP2>;
+               };
+
+               pinctrl_spdif: spdifgrp {
+                       fsl,pins = <MX6QDL_SPDIF_PINGRP3>;
+               };
+
+               pinctrl_uart1: uart1grp {
+                       fsl,pins = <MX6QDL_UART1_PINGRP1>;
+               };
+
+               pinctrl_uart3: uart3grp {
+                       fsl,pins = <MX6QDL_UART3_PINGRP2>;
+               };
+
+               pinctrl_usbotg: usbotggrp {
+                       fsl,pins = <MX6QDL_USBOTG_PINGRP1>;
+               };
+
+               pinctrl_usdhc1: usdhc1grp {
+                       fsl,pins = <MX6QDL_USDHC1_PINGRP_D4>;
+               };
+
+               pinctrl_usdhc2: usdhc2grp {
+                       fsl,pins = <MX6QDL_USDHC2_PINGRP_D4>;
+               };
+
+               pinctrl_usdhc3: usdhc3grp {
+                       fsl,pins = <MX6QDL_USDHC3_PINGRP_D4>;
+               };
        };
 };
 
 &fec {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_enet_1>;
+       pinctrl-0 = <&pinctrl_enet>;
        phy-mode = "rgmii";
        phy-reset-gpios = <&gpio3 29 0>;
        status = "okay";
 
 &spdif {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_spdif_3>;
+       pinctrl-0 = <&pinctrl_spdif>;
        status = "okay";
 };
 
 
 &uart1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_uart1_1>;
+       pinctrl-0 = <&pinctrl_uart1>;
        status = "okay";
 };
 
 &uart3 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_uart3_2>;
+       pinctrl-0 = <&pinctrl_uart3>;
        fsl,uart-has-rtscts;
        status = "okay";
 };
 
 &usbotg {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_usbotg_1>;
+       pinctrl-0 = <&pinctrl_usbotg>;
        disable-over-current;
        dr_mode = "peripheral";
        status = "okay";
 
 &usdhc1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_usdhc1_2>;
+       pinctrl-0 = <&pinctrl_usdhc1>;
        cd-gpios = <&gpio1 2 0>;
        status = "okay";
 };
 
 &usdhc2 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_usdhc2_2>;
+       pinctrl-0 = <&pinctrl_usdhc2>;
        non-removable;
        status = "okay";
 };
 
 &usdhc3 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_usdhc3_2>;
+       pinctrl-0 = <&pinctrl_usdhc3>;
        cd-gpios = <&gpio3 9 0>;
        status = "okay";
 };
index fb28b2ecb1db37a28a9effbd7bea591ace78554a..16f69741177e78bec158f064fa963f7c3b7cfe6b 100644 (file)
                dma_apbh: dma-apbh@00110000 {
                        compatible = "fsl,imx6q-dma-apbh", "fsl,imx28-dma-apbh";
                        reg = <0x00110000 0x2000>;
-                       interrupts = <0 13 0x04>, <0 13 0x04>, <0 13 0x04>, <0 13 0x04>;
+                       interrupts = <0 13 IRQ_TYPE_LEVEL_HIGH>,
+                                    <0 13 IRQ_TYPE_LEVEL_HIGH>,
+                                    <0 13 IRQ_TYPE_LEVEL_HIGH>,
+                                    <0 13 IRQ_TYPE_LEVEL_HIGH>;
                        interrupt-names = "gpmi0", "gpmi1", "gpmi2", "gpmi3";
                        #dma-cells = <1>;
                        dma-channels = <4>;
@@ -88,7 +91,7 @@
                        #size-cells = <1>;
                        reg = <0x00112000 0x2000>, <0x00114000 0x2000>;
                        reg-names = "gpmi-nand", "bch";
-                       interrupts = <0 15 0x04>;
+                       interrupts = <0 15 IRQ_TYPE_LEVEL_HIGH>;
                        interrupt-names = "bch";
                        clocks = <&clks 152>, <&clks 153>, <&clks 151>,
                                 <&clks 150>, <&clks 149>;
                L2: l2-cache@00a02000 {
                        compatible = "arm,pl310-cache";
                        reg = <0x00a02000 0x1000>;
-                       interrupts = <0 92 0x04>;
+                       interrupts = <0 92 IRQ_TYPE_LEVEL_HIGH>;
                        cache-unified;
                        cache-level = <2>;
                        arm,tag-latency = <4 2 3>;
                                  0x81000000 0 0          0x01f80000 0 0x00010000 /* downstream I/O */
                                  0x82000000 0 0x01000000 0x01000000 0 0x00f00000>; /* non-prefetchable memory */
                        num-lanes = <1>;
-                       interrupts = <0 123 0x04>;
+                       interrupts = <0 123 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&clks 189>, <&clks 187>, <&clks 206>, <&clks 144>;
                        clock-names = "pcie_ref_125m", "sata_ref_100m", "lvds_gate", "pcie_axi";
                        status = "disabled";
 
                pmu {
                        compatible = "arm,cortex-a9-pmu";
-                       interrupts = <0 94 0x04>;
+                       interrupts = <0 94 IRQ_TYPE_LEVEL_HIGH>;
                };
 
                aips-bus@02000000 { /* AIPS1 */
                                spdif: spdif@02004000 {
                                        compatible = "fsl,imx35-spdif";
                                        reg = <0x02004000 0x4000>;
-                                       interrupts = <0 52 0x04>;
+                                       interrupts = <0 52 IRQ_TYPE_LEVEL_HIGH>;
                                        dmas = <&sdma 14 18 0>,
                                               <&sdma 15 18 0>;
                                        dma-names = "rx", "tx";
                                        #size-cells = <0>;
                                        compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
                                        reg = <0x02008000 0x4000>;
-                                       interrupts = <0 31 0x04>;
+                                       interrupts = <0 31 IRQ_TYPE_LEVEL_HIGH>;
                                        clocks = <&clks 112>, <&clks 112>;
                                        clock-names = "ipg", "per";
                                        status = "disabled";
                                        #size-cells = <0>;
                                        compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
                                        reg = <0x0200c000 0x4000>;
-                                       interrupts = <0 32 0x04>;
+                                       interrupts = <0 32 IRQ_TYPE_LEVEL_HIGH>;
                                        clocks = <&clks 113>, <&clks 113>;
                                        clock-names = "ipg", "per";
                                        status = "disabled";
                                        #size-cells = <0>;
                                        compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
                                        reg = <0x02010000 0x4000>;
-                                       interrupts = <0 33 0x04>;
+                                       interrupts = <0 33 IRQ_TYPE_LEVEL_HIGH>;
                                        clocks = <&clks 114>, <&clks 114>;
                                        clock-names = "ipg", "per";
                                        status = "disabled";
                                        #size-cells = <0>;
                                        compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
                                        reg = <0x02014000 0x4000>;
-                                       interrupts = <0 34 0x04>;
+                                       interrupts = <0 34 IRQ_TYPE_LEVEL_HIGH>;
                                        clocks = <&clks 115>, <&clks 115>;
                                        clock-names = "ipg", "per";
                                        status = "disabled";
                                uart1: serial@02020000 {
                                        compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
                                        reg = <0x02020000 0x4000>;
-                                       interrupts = <0 26 0x04>;
+                                       interrupts = <0 26 IRQ_TYPE_LEVEL_HIGH>;
                                        clocks = <&clks 160>, <&clks 161>;
                                        clock-names = "ipg", "per";
                                        dmas = <&sdma 25 4 0>, <&sdma 26 4 0>;
 
                                esai: esai@02024000 {
                                        reg = <0x02024000 0x4000>;
-                                       interrupts = <0 51 0x04>;
+                                       interrupts = <0 51 IRQ_TYPE_LEVEL_HIGH>;
                                };
 
                                ssi1: ssi@02028000 {
                                        compatible = "fsl,imx6q-ssi","fsl,imx21-ssi";
                                        reg = <0x02028000 0x4000>;
-                                       interrupts = <0 46 0x04>;
+                                       interrupts = <0 46 IRQ_TYPE_LEVEL_HIGH>;
                                        clocks = <&clks 178>;
-                                       dmas = <&sdma 37 1 0>,
-                                              <&sdma 38 1 0>;
+                                       dmas = <&sdma 37 22 0>,
+                                              <&sdma 38 22 0>;
                                        dma-names = "rx", "tx";
                                        fsl,fifo-depth = <15>;
                                        fsl,ssi-dma-events = <38 37>;
                                ssi2: ssi@0202c000 {
                                        compatible = "fsl,imx6q-ssi","fsl,imx21-ssi";
                                        reg = <0x0202c000 0x4000>;
-                                       interrupts = <0 47 0x04>;
+                                       interrupts = <0 47 IRQ_TYPE_LEVEL_HIGH>;
                                        clocks = <&clks 179>;
-                                       dmas = <&sdma 41 1 0>,
-                                              <&sdma 42 1 0>;
+                                       dmas = <&sdma 41 22 0>,
+                                              <&sdma 42 22 0>;
                                        dma-names = "rx", "tx";
                                        fsl,fifo-depth = <15>;
                                        fsl,ssi-dma-events = <42 41>;
                                ssi3: ssi@02030000 {
                                        compatible = "fsl,imx6q-ssi","fsl,imx21-ssi";
                                        reg = <0x02030000 0x4000>;
-                                       interrupts = <0 48 0x04>;
+                                       interrupts = <0 48 IRQ_TYPE_LEVEL_HIGH>;
                                        clocks = <&clks 180>;
-                                       dmas = <&sdma 45 1 0>,
-                                              <&sdma 46 1 0>;
+                                       dmas = <&sdma 45 22 0>,
+                                              <&sdma 46 22 0>;
                                        dma-names = "rx", "tx";
                                        fsl,fifo-depth = <15>;
                                        fsl,ssi-dma-events = <46 45>;
 
                                asrc: asrc@02034000 {
                                        reg = <0x02034000 0x4000>;
-                                       interrupts = <0 50 0x04>;
+                                       interrupts = <0 50 IRQ_TYPE_LEVEL_HIGH>;
                                };
 
                                spba@0203c000 {
 
                        vpu: vpu@02040000 {
                                reg = <0x02040000 0x3c000>;
-                               interrupts = <0 3 0x04 0 12 0x04>;
+                               interrupts = <0 3 IRQ_TYPE_LEVEL_HIGH>,
+                                            <0 12 IRQ_TYPE_LEVEL_HIGH>;
                        };
 
                        aipstz@0207c000 { /* AIPSTZ1 */
                                #pwm-cells = <2>;
                                compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
                                reg = <0x02080000 0x4000>;
-                               interrupts = <0 83 0x04>;
+                               interrupts = <0 83 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks 62>, <&clks 145>;
                                clock-names = "ipg", "per";
                        };
                                #pwm-cells = <2>;
                                compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
                                reg = <0x02084000 0x4000>;
-                               interrupts = <0 84 0x04>;
+                               interrupts = <0 84 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks 62>, <&clks 146>;
                                clock-names = "ipg", "per";
                        };
                                #pwm-cells = <2>;
                                compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
                                reg = <0x02088000 0x4000>;
-                               interrupts = <0 85 0x04>;
+                               interrupts = <0 85 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks 62>, <&clks 147>;
                                clock-names = "ipg", "per";
                        };
                                #pwm-cells = <2>;
                                compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
                                reg = <0x0208c000 0x4000>;
-                               interrupts = <0 86 0x04>;
+                               interrupts = <0 86 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks 62>, <&clks 148>;
                                clock-names = "ipg", "per";
                        };
                        can1: flexcan@02090000 {
                                compatible = "fsl,imx6q-flexcan";
                                reg = <0x02090000 0x4000>;
-                               interrupts = <0 110 0x04>;
+                               interrupts = <0 110 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks 108>, <&clks 109>;
                                clock-names = "ipg", "per";
+                               status = "disabled";
                        };
 
                        can2: flexcan@02094000 {
                                compatible = "fsl,imx6q-flexcan";
                                reg = <0x02094000 0x4000>;
-                               interrupts = <0 111 0x04>;
+                               interrupts = <0 111 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks 110>, <&clks 111>;
                                clock-names = "ipg", "per";
+                               status = "disabled";
                        };
 
                        gpt: gpt@02098000 {
                                compatible = "fsl,imx6q-gpt", "fsl,imx31-gpt";
                                reg = <0x02098000 0x4000>;
-                               interrupts = <0 55 0x04>;
+                               interrupts = <0 55 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks 119>, <&clks 120>;
                                clock-names = "ipg", "per";
                        };
                        gpio1: gpio@0209c000 {
                                compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
                                reg = <0x0209c000 0x4000>;
-                               interrupts = <0 66 0x04 0 67 0x04>;
+                               interrupts = <0 66 IRQ_TYPE_LEVEL_HIGH>,
+                                            <0 67 IRQ_TYPE_LEVEL_HIGH>;
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
                        gpio2: gpio@020a0000 {
                                compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
                                reg = <0x020a0000 0x4000>;
-                               interrupts = <0 68 0x04 0 69 0x04>;
+                               interrupts = <0 68 IRQ_TYPE_LEVEL_HIGH>,
+                                            <0 69 IRQ_TYPE_LEVEL_HIGH>;
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
                        gpio3: gpio@020a4000 {
                                compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
                                reg = <0x020a4000 0x4000>;
-                               interrupts = <0 70 0x04 0 71 0x04>;
+                               interrupts = <0 70 IRQ_TYPE_LEVEL_HIGH>,
+                                            <0 71 IRQ_TYPE_LEVEL_HIGH>;
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
                        gpio4: gpio@020a8000 {
                                compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
                                reg = <0x020a8000 0x4000>;
-                               interrupts = <0 72 0x04 0 73 0x04>;
+                               interrupts = <0 72 IRQ_TYPE_LEVEL_HIGH>,
+                                            <0 73 IRQ_TYPE_LEVEL_HIGH>;
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
                        gpio5: gpio@020ac000 {
                                compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
                                reg = <0x020ac000 0x4000>;
-                               interrupts = <0 74 0x04 0 75 0x04>;
+                               interrupts = <0 74 IRQ_TYPE_LEVEL_HIGH>,
+                                            <0 75 IRQ_TYPE_LEVEL_HIGH>;
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
                        gpio6: gpio@020b0000 {
                                compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
                                reg = <0x020b0000 0x4000>;
-                               interrupts = <0 76 0x04 0 77 0x04>;
+                               interrupts = <0 76 IRQ_TYPE_LEVEL_HIGH>,
+                                            <0 77 IRQ_TYPE_LEVEL_HIGH>;
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
                        gpio7: gpio@020b4000 {
                                compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
                                reg = <0x020b4000 0x4000>;
-                               interrupts = <0 78 0x04 0 79 0x04>;
+                               interrupts = <0 78 IRQ_TYPE_LEVEL_HIGH>,
+                                            <0 79 IRQ_TYPE_LEVEL_HIGH>;
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
 
                        kpp: kpp@020b8000 {
                                reg = <0x020b8000 0x4000>;
-                               interrupts = <0 82 0x04>;
+                               interrupts = <0 82 IRQ_TYPE_LEVEL_HIGH>;
                        };
 
                        wdog1: wdog@020bc000 {
                                compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt";
                                reg = <0x020bc000 0x4000>;
-                               interrupts = <0 80 0x04>;
+                               interrupts = <0 80 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks 0>;
                        };
 
                        wdog2: wdog@020c0000 {
                                compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt";
                                reg = <0x020c0000 0x4000>;
-                               interrupts = <0 81 0x04>;
+                               interrupts = <0 81 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks 0>;
                                status = "disabled";
                        };
                        clks: ccm@020c4000 {
                                compatible = "fsl,imx6q-ccm";
                                reg = <0x020c4000 0x4000>;
-                               interrupts = <0 87 0x04 0 88 0x04>;
+                               interrupts = <0 87 IRQ_TYPE_LEVEL_HIGH>,
+                                            <0 88 IRQ_TYPE_LEVEL_HIGH>;
                                #clock-cells = <1>;
                        };
 
                        anatop: anatop@020c8000 {
                                compatible = "fsl,imx6q-anatop", "syscon", "simple-bus";
                                reg = <0x020c8000 0x1000>;
-                               interrupts = <0 49 0x04 0 54 0x04 0 127 0x04>;
+                               interrupts = <0 49 IRQ_TYPE_LEVEL_HIGH>,
+                                            <0 54 IRQ_TYPE_LEVEL_HIGH>,
+                                            <0 127 IRQ_TYPE_LEVEL_HIGH>;
 
                                regulator-1p1@110 {
                                        compatible = "fsl,anatop-regulator";
 
                        tempmon: tempmon {
                                compatible = "fsl,imx6q-tempmon";
-                               interrupts = <0 49 0x04>;
+                               interrupts = <0 49 IRQ_TYPE_LEVEL_HIGH>;
                                fsl,tempmon = <&anatop>;
                                fsl,tempmon-data = <&ocotp>;
                        };
                        usbphy1: usbphy@020c9000 {
                                compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy";
                                reg = <0x020c9000 0x1000>;
-                               interrupts = <0 44 0x04>;
+                               interrupts = <0 44 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks 182>;
                        };
 
                        usbphy2: usbphy@020ca000 {
                                compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy";
                                reg = <0x020ca000 0x1000>;
-                               interrupts = <0 45 0x04>;
+                               interrupts = <0 45 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks 183>;
                        };
 
                                snvs-rtc-lp@34 {
                                        compatible = "fsl,sec-v4.0-mon-rtc-lp";
                                        reg = <0x34 0x58>;
-                                       interrupts = <0 19 0x04 0 20 0x04>;
+                                       interrupts = <0 19 IRQ_TYPE_LEVEL_HIGH>,
+                                                    <0 20 IRQ_TYPE_LEVEL_HIGH>;
                                };
                        };
 
                        epit1: epit@020d0000 { /* EPIT1 */
                                reg = <0x020d0000 0x4000>;
-                               interrupts = <0 56 0x04>;
+                               interrupts = <0 56 IRQ_TYPE_LEVEL_HIGH>;
                        };
 
                        epit2: epit@020d4000 { /* EPIT2 */
                                reg = <0x020d4000 0x4000>;
-                               interrupts = <0 57 0x04>;
+                               interrupts = <0 57 IRQ_TYPE_LEVEL_HIGH>;
                        };
 
                        src: src@020d8000 {
                                compatible = "fsl,imx6q-src", "fsl,imx51-src";
                                reg = <0x020d8000 0x4000>;
-                               interrupts = <0 91 0x04 0 96 0x04>;
+                               interrupts = <0 91 IRQ_TYPE_LEVEL_HIGH>,
+                                            <0 96 IRQ_TYPE_LEVEL_HIGH>;
                                #reset-cells = <1>;
                        };
 
                        gpc: gpc@020dc000 {
                                compatible = "fsl,imx6q-gpc";
                                reg = <0x020dc000 0x4000>;
-                               interrupts = <0 89 0x04 0 90 0x04>;
+                               interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>,
+                                            <0 90 IRQ_TYPE_LEVEL_HIGH>;
                        };
 
                        gpr: iomuxc-gpr@020e0000 {
                        iomuxc: iomuxc@020e0000 {
                                compatible = "fsl,imx6dl-iomuxc", "fsl,imx6q-iomuxc";
                                reg = <0x020e0000 0x4000>;
-
-                               audmux {
-                                       pinctrl_audmux_1: audmux-1 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_SD2_DAT0__AUD4_RXD  0x80000000
-                                                       MX6QDL_PAD_SD2_DAT3__AUD4_TXC  0x80000000
-                                                       MX6QDL_PAD_SD2_DAT2__AUD4_TXD  0x80000000
-                                                       MX6QDL_PAD_SD2_DAT1__AUD4_TXFS 0x80000000
-                                               >;
-                                       };
-
-                                       pinctrl_audmux_2: audmux-2 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_CSI0_DAT7__AUD3_RXD  0x80000000
-                                                       MX6QDL_PAD_CSI0_DAT4__AUD3_TXC  0x80000000
-                                                       MX6QDL_PAD_CSI0_DAT5__AUD3_TXD  0x80000000
-                                                       MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x80000000
-                                               >;
-                                       };
-
-                                       pinctrl_audmux_3: audmux-3 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_DISP0_DAT16__AUD5_TXC  0x80000000
-                                                       MX6QDL_PAD_DISP0_DAT18__AUD5_TXFS 0x80000000
-                                                       MX6QDL_PAD_DISP0_DAT19__AUD5_RXD  0x80000000
-                                               >;
-                                       };
-                               };
-
-                               ecspi1 {
-                                       pinctrl_ecspi1_1: ecspi1grp-1 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1
-                                                       MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1
-                                                       MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1
-                                               >;
-                                       };
-
-                                       pinctrl_ecspi1_2: ecspi1grp-2 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_KEY_COL1__ECSPI1_MISO 0x100b1
-                                                       MX6QDL_PAD_KEY_ROW0__ECSPI1_MOSI 0x100b1
-                                                       MX6QDL_PAD_KEY_COL0__ECSPI1_SCLK 0x100b1
-                                               >;
-                                       };
-                               };
-
-                               ecspi3 {
-                                       pinctrl_ecspi3_1: ecspi3grp-1 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_DISP0_DAT2__ECSPI3_MISO 0x100b1
-                                                       MX6QDL_PAD_DISP0_DAT1__ECSPI3_MOSI 0x100b1
-                                                       MX6QDL_PAD_DISP0_DAT0__ECSPI3_SCLK 0x100b1
-                                               >;
-                                       };
-                               };
-
-                               enet {
-                                       pinctrl_enet_1: enetgrp-1 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_ENET_MDIO__ENET_MDIO       0x1b0b0
-                                                       MX6QDL_PAD_ENET_MDC__ENET_MDC         0x1b0b0
-                                                       MX6QDL_PAD_RGMII_TXC__RGMII_TXC       0x1b0b0
-                                                       MX6QDL_PAD_RGMII_TD0__RGMII_TD0       0x1b0b0
-                                                       MX6QDL_PAD_RGMII_TD1__RGMII_TD1       0x1b0b0
-                                                       MX6QDL_PAD_RGMII_TD2__RGMII_TD2       0x1b0b0
-                                                       MX6QDL_PAD_RGMII_TD3__RGMII_TD3       0x1b0b0
-                                                       MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
-                                                       MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK  0x1b0b0
-                                                       MX6QDL_PAD_RGMII_RXC__RGMII_RXC       0x1b0b0
-                                                       MX6QDL_PAD_RGMII_RD0__RGMII_RD0       0x1b0b0
-                                                       MX6QDL_PAD_RGMII_RD1__RGMII_RD1       0x1b0b0
-                                                       MX6QDL_PAD_RGMII_RD2__RGMII_RD2       0x1b0b0
-                                                       MX6QDL_PAD_RGMII_RD3__RGMII_RD3       0x1b0b0
-                                                       MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
-                                                       MX6QDL_PAD_GPIO_16__ENET_REF_CLK      0x4001b0a8
-                                               >;
-                                       };
-
-                                       pinctrl_enet_2: enetgrp-2 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_KEY_COL1__ENET_MDIO        0x1b0b0
-                                                       MX6QDL_PAD_KEY_COL2__ENET_MDC         0x1b0b0
-                                                       MX6QDL_PAD_RGMII_TXC__RGMII_TXC       0x1b0b0
-                                                       MX6QDL_PAD_RGMII_TD0__RGMII_TD0       0x1b0b0
-                                                       MX6QDL_PAD_RGMII_TD1__RGMII_TD1       0x1b0b0
-                                                       MX6QDL_PAD_RGMII_TD2__RGMII_TD2       0x1b0b0
-                                                       MX6QDL_PAD_RGMII_TD3__RGMII_TD3       0x1b0b0
-                                                       MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
-                                                       MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK  0x1b0b0
-                                                       MX6QDL_PAD_RGMII_RXC__RGMII_RXC       0x1b0b0
-                                                       MX6QDL_PAD_RGMII_RD0__RGMII_RD0       0x1b0b0
-                                                       MX6QDL_PAD_RGMII_RD1__RGMII_RD1       0x1b0b0
-                                                       MX6QDL_PAD_RGMII_RD2__RGMII_RD2       0x1b0b0
-                                                       MX6QDL_PAD_RGMII_RD3__RGMII_RD3       0x1b0b0
-                                                       MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
-                                               >;
-                                       };
-
-                                       pinctrl_enet_3: enetgrp-3 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_ENET_MDIO__ENET_MDIO       0x1b0b0
-                                                       MX6QDL_PAD_ENET_MDC__ENET_MDC         0x1b0b0
-                                                       MX6QDL_PAD_RGMII_TXC__RGMII_TXC       0x1b0b0
-                                                       MX6QDL_PAD_RGMII_TD0__RGMII_TD0       0x1b0b0
-                                                       MX6QDL_PAD_RGMII_TD1__RGMII_TD1       0x1b0b0
-                                                       MX6QDL_PAD_RGMII_TD2__RGMII_TD2       0x1b0b0
-                                                       MX6QDL_PAD_RGMII_TD3__RGMII_TD3       0x1b0b0
-                                                       MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
-                                                       MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK  0x1b0b0
-                                                       MX6QDL_PAD_RGMII_RXC__RGMII_RXC       0x1b0b0
-                                                       MX6QDL_PAD_RGMII_RD0__RGMII_RD0       0x1b0b0
-                                                       MX6QDL_PAD_RGMII_RD1__RGMII_RD1       0x1b0b0
-                                                       MX6QDL_PAD_RGMII_RD2__RGMII_RD2       0x1b0b0
-                                                       MX6QDL_PAD_RGMII_RD3__RGMII_RD3       0x1b0b0
-                                                       MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
-                                                       MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN     0x1b0b0
-                                               >;
-                                       };
-                               };
-
-                               esai {
-                                       pinctrl_esai_1: esaigrp-1 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_ENET_RXD0__ESAI_TX_HF_CLK 0x1b030
-                                                       MX6QDL_PAD_ENET_CRS_DV__ESAI_TX_CLK  0x1b030
-                                                       MX6QDL_PAD_ENET_RXD1__ESAI_TX_FS     0x1b030
-                                                       MX6QDL_PAD_ENET_TX_EN__ESAI_TX3_RX2  0x1b030
-                                                       MX6QDL_PAD_ENET_TXD1__ESAI_TX2_RX3   0x1b030
-                                                       MX6QDL_PAD_ENET_TXD0__ESAI_TX4_RX1   0x1b030
-                                                       MX6QDL_PAD_ENET_MDC__ESAI_TX5_RX0    0x1b030
-                                                       MX6QDL_PAD_NANDF_CS2__ESAI_TX0       0x1b030
-                                                       MX6QDL_PAD_NANDF_CS3__ESAI_TX1       0x1b030
-                                               >;
-                                       };
-
-                                       pinctrl_esai_2: esaigrp-2 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_ENET_CRS_DV__ESAI_TX_CLK 0x1b030
-                                                       MX6QDL_PAD_ENET_RXD1__ESAI_TX_FS    0x1b030
-                                                       MX6QDL_PAD_ENET_TX_EN__ESAI_TX3_RX2 0x1b030
-                                                       MX6QDL_PAD_GPIO_5__ESAI_TX2_RX3     0x1b030
-                                                       MX6QDL_PAD_ENET_TXD0__ESAI_TX4_RX1  0x1b030
-                                                       MX6QDL_PAD_ENET_MDC__ESAI_TX5_RX0   0x1b030
-                                                       MX6QDL_PAD_GPIO_17__ESAI_TX0        0x1b030
-                                                       MX6QDL_PAD_NANDF_CS3__ESAI_TX1      0x1b030
-                                                       MX6QDL_PAD_ENET_MDIO__ESAI_RX_CLK   0x1b030
-                                                       MX6QDL_PAD_GPIO_9__ESAI_RX_FS       0x1b030
-                                               >;
-                                       };
-                               };
-
-                               flexcan1 {
-                                       pinctrl_flexcan1_1: flexcan1grp-1 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x80000000
-                                                       MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX 0x80000000
-                                               >;
-                                       };
-
-                                       pinctrl_flexcan1_2: flexcan1grp-2 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_GPIO_7__FLEXCAN1_TX   0x80000000
-                                                       MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x80000000
-                                               >;
-                                       };
-                               };
-
-                               flexcan2 {
-                                       pinctrl_flexcan2_1: flexcan2grp-1 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_KEY_COL4__FLEXCAN2_TX 0x80000000
-                                                       MX6QDL_PAD_KEY_ROW4__FLEXCAN2_RX 0x80000000
-                                               >;
-                                       };
-                               };
-
-                               gpmi-nand {
-                                       pinctrl_gpmi_nand_1: gpmi-nand-1 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_NANDF_CLE__NAND_CLE     0xb0b1
-                                                       MX6QDL_PAD_NANDF_ALE__NAND_ALE     0xb0b1
-                                                       MX6QDL_PAD_NANDF_WP_B__NAND_WP_B   0xb0b1
-                                                       MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000
-                                                       MX6QDL_PAD_NANDF_CS0__NAND_CE0_B   0xb0b1
-                                                       MX6QDL_PAD_NANDF_CS1__NAND_CE1_B   0xb0b1
-                                                       MX6QDL_PAD_SD4_CMD__NAND_RE_B      0xb0b1
-                                                       MX6QDL_PAD_SD4_CLK__NAND_WE_B      0xb0b1
-                                                       MX6QDL_PAD_NANDF_D0__NAND_DATA00   0xb0b1
-                                                       MX6QDL_PAD_NANDF_D1__NAND_DATA01   0xb0b1
-                                                       MX6QDL_PAD_NANDF_D2__NAND_DATA02   0xb0b1
-                                                       MX6QDL_PAD_NANDF_D3__NAND_DATA03   0xb0b1
-                                                       MX6QDL_PAD_NANDF_D4__NAND_DATA04   0xb0b1
-                                                       MX6QDL_PAD_NANDF_D5__NAND_DATA05   0xb0b1
-                                                       MX6QDL_PAD_NANDF_D6__NAND_DATA06   0xb0b1
-                                                       MX6QDL_PAD_NANDF_D7__NAND_DATA07   0xb0b1
-                                                       MX6QDL_PAD_SD4_DAT0__NAND_DQS      0x00b1
-                                               >;
-                                       };
-                               };
-
-                               hdmi_hdcp {
-                                       pinctrl_hdmi_hdcp_1: hdmihdcpgrp-1 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_KEY_COL3__HDMI_TX_DDC_SCL 0x4001b8b1
-                                                       MX6QDL_PAD_KEY_ROW3__HDMI_TX_DDC_SDA 0x4001b8b1
-                                               >;
-                                       };
-
-                                       pinctrl_hdmi_hdcp_2: hdmihdcpgrp-2 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_EIM_EB2__HDMI_TX_DDC_SCL 0x4001b8b1
-                                                       MX6QDL_PAD_EIM_D16__HDMI_TX_DDC_SDA 0x4001b8b1
-                                               >;
-                                       };
-
-                                       pinctrl_hdmi_hdcp_3: hdmihdcpgrp-3 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_EIM_EB2__HDMI_TX_DDC_SCL  0x4001b8b1
-                                                       MX6QDL_PAD_KEY_ROW3__HDMI_TX_DDC_SDA 0x4001b8b1
-                                               >;
-                                       };
-                               };
-
-                               hdmi_cec {
-                                       pinctrl_hdmi_cec_1: hdmicecgrp-1 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_EIM_A25__HDMI_TX_CEC_LINE 0x1f8b0
-                                               >;
-                                       };
-
-                                       pinctrl_hdmi_cec_2: hdmicecgrp-2 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE 0x1f8b0
-                                               >;
-                                       };
-                               };
-
-                               i2c1 {
-                                       pinctrl_i2c1_1: i2c1grp-1 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
-                                                       MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
-                                               >;
-                                       };
-
-                                       pinctrl_i2c1_2: i2c1grp-2 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_CSI0_DAT8__I2C1_SDA 0x4001b8b1
-                                                       MX6QDL_PAD_CSI0_DAT9__I2C1_SCL 0x4001b8b1
-                                               >;
-                                       };
-                               };
-
-                               i2c2 {
-                                       pinctrl_i2c2_1: i2c2grp-1 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_EIM_EB2__I2C2_SCL 0x4001b8b1
-                                                       MX6QDL_PAD_EIM_D16__I2C2_SDA 0x4001b8b1
-                                               >;
-                                       };
-
-                                       pinctrl_i2c2_2: i2c2grp-2 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
-                                                       MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
-                                               >;
-                                       };
-
-                                       pinctrl_i2c2_3: i2c2grp-3 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_EIM_EB2__I2C2_SCL  0x4001b8b1
-                                                       MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
-                                               >;
-                                       };
-                               };
-
-                               i2c3 {
-                                       pinctrl_i2c3_1: i2c3grp-1 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_EIM_D17__I2C3_SCL 0x4001b8b1
-                                                       MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1
-                                               >;
-                                       };
-
-                                       pinctrl_i2c3_2: i2c3grp-2 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1
-                                                       MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1
-                                               >;
-                                       };
-
-                                       pinctrl_i2c3_3: i2c3grp-3 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_GPIO_5__I2C3_SCL  0x4001b8b1
-                                                       MX6QDL_PAD_GPIO_16__I2C3_SDA 0x4001b8b1
-                                               >;
-                                       };
-
-                                       pinctrl_i2c3_4: i2c3grp-4 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_GPIO_3__I2C3_SCL  0x4001b8b1
-                                                       MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1
-                                               >;
-                                       };
-                               };
-
-                               ipu1 {
-                                       pinctrl_ipu1_1: ipu1grp-1 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10
-                                                       MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15       0x10
-                                                       MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02        0x10
-                                                       MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03        0x10
-                                                       MX6QDL_PAD_DI0_PIN4__IPU1_DI0_PIN04        0x80000000
-                                                       MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00   0x10
-                                                       MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01   0x10
-                                                       MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02   0x10
-                                                       MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03   0x10
-                                                       MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04   0x10
-                                                       MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05   0x10
-                                                       MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06   0x10
-                                                       MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07   0x10
-                                                       MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08   0x10
-                                                       MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09   0x10
-                                                       MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10  0x10
-                                                       MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11  0x10
-                                                       MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12  0x10
-                                                       MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13  0x10
-                                                       MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14  0x10
-                                                       MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15  0x10
-                                                       MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16  0x10
-                                                       MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17  0x10
-                                                       MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18  0x10
-                                                       MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19  0x10
-                                                       MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20  0x10
-                                                       MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21  0x10
-                                                       MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22  0x10
-                                                       MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23  0x10
-                                               >;
-                                       };
-
-                                       pinctrl_ipu1_2: ipu1grp-2 { /* parallel camera */
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12    0x80000000
-                                                       MX6QDL_PAD_CSI0_DAT13__IPU1_CSI0_DATA13    0x80000000
-                                                       MX6QDL_PAD_CSI0_DAT14__IPU1_CSI0_DATA14    0x80000000
-                                                       MX6QDL_PAD_CSI0_DAT15__IPU1_CSI0_DATA15    0x80000000
-                                                       MX6QDL_PAD_CSI0_DAT16__IPU1_CSI0_DATA16    0x80000000
-                                                       MX6QDL_PAD_CSI0_DAT17__IPU1_CSI0_DATA17    0x80000000
-                                                       MX6QDL_PAD_CSI0_DAT18__IPU1_CSI0_DATA18    0x80000000
-                                                       MX6QDL_PAD_CSI0_DAT19__IPU1_CSI0_DATA19    0x80000000
-                                                       MX6QDL_PAD_CSI0_DATA_EN__IPU1_CSI0_DATA_EN 0x80000000
-                                                       MX6QDL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK   0x80000000
-                                                       MX6QDL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC      0x80000000
-                                                       MX6QDL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC     0x80000000
-                                               >;
-                                       };
-
-                                       pinctrl_ipu1_3: ipu1grp-3 { /* parallel port 16-bit */
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_CSI0_DAT4__IPU1_CSI0_DATA04   0x80000000
-                                                       MX6QDL_PAD_CSI0_DAT5__IPU1_CSI0_DATA05   0x80000000
-                                                       MX6QDL_PAD_CSI0_DAT6__IPU1_CSI0_DATA06   0x80000000
-                                                       MX6QDL_PAD_CSI0_DAT7__IPU1_CSI0_DATA07   0x80000000
-                                                       MX6QDL_PAD_CSI0_DAT8__IPU1_CSI0_DATA08   0x80000000
-                                                       MX6QDL_PAD_CSI0_DAT9__IPU1_CSI0_DATA09   0x80000000
-                                                       MX6QDL_PAD_CSI0_DAT10__IPU1_CSI0_DATA10  0x80000000
-                                                       MX6QDL_PAD_CSI0_DAT11__IPU1_CSI0_DATA11  0x80000000
-                                                       MX6QDL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12  0x80000000
-                                                       MX6QDL_PAD_CSI0_DAT13__IPU1_CSI0_DATA13  0x80000000
-                                                       MX6QDL_PAD_CSI0_DAT14__IPU1_CSI0_DATA14  0x80000000
-                                                       MX6QDL_PAD_CSI0_DAT15__IPU1_CSI0_DATA15  0x80000000
-                                                       MX6QDL_PAD_CSI0_DAT16__IPU1_CSI0_DATA16  0x80000000
-                                                       MX6QDL_PAD_CSI0_DAT17__IPU1_CSI0_DATA17  0x80000000
-                                                       MX6QDL_PAD_CSI0_DAT18__IPU1_CSI0_DATA18  0x80000000
-                                                       MX6QDL_PAD_CSI0_DAT19__IPU1_CSI0_DATA19  0x80000000
-                                                       MX6QDL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK 0x80000000
-                                                       MX6QDL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC    0x80000000
-                                                       MX6QDL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC   0x80000000
-                                               >;
-                                       };
-                               };
-
-                               mlb {
-                                       pinctrl_mlb_1: mlbgrp-1 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_GPIO_3__MLB_CLK  0x71
-                                                       MX6QDL_PAD_GPIO_6__MLB_SIG  0x71
-                                                       MX6QDL_PAD_GPIO_2__MLB_DATA 0x71
-                                               >;
-                                       };
-
-                                       pinctrl_mlb_2: mlbgrp-2 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_ENET_TXD1__MLB_CLK 0x71
-                                                       MX6QDL_PAD_GPIO_6__MLB_SIG    0x71
-                                                       MX6QDL_PAD_GPIO_2__MLB_DATA   0x71
-                                               >;
-                                       };
-                               };
-
-                               pwm0 {
-                                       pinctrl_pwm0_1: pwm0grp-1 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_SD1_DAT3__PWM1_OUT 0x1b0b1
-                                               >;
-                                       };
-                               };
-
-                               pwm3 {
-                                       pinctrl_pwm3_1: pwm3grp-1 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_SD4_DAT1__PWM3_OUT 0x1b0b1
-                                               >;
-                                       };
-                               };
-
-                               spdif {
-                                       pinctrl_spdif_1: spdifgrp-1 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_KEY_COL3__SPDIF_IN 0x1b0b0
-                                               >;
-                                       };
-
-                                       pinctrl_spdif_2: spdifgrp-2 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_GPIO_16__SPDIF_IN  0x1b0b0
-                                                       MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x1b0b0
-                                               >;
-                                       };
-
-                                       pinctrl_spdif_3: spdifgrp-3 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_ENET_RXD0__SPDIF_OUT 0x1b0b0
-                                               >;
-                                       };
-                               };
-
-                               uart1 {
-                                       pinctrl_uart1_1: uart1grp-1 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1
-                                                       MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1
-                                               >;
-                                       };
-                               };
-
-                               uart2 {
-                                       pinctrl_uart2_1: uart2grp-1 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1
-                                                       MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1
-                                               >;
-                                       };
-
-                                       pinctrl_uart2_2: uart2grp-2 { /* DTE mode */
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_EIM_D26__UART2_RX_DATA   0x1b0b1
-                                                       MX6QDL_PAD_EIM_D27__UART2_TX_DATA   0x1b0b1
-                                                       MX6QDL_PAD_EIM_D28__UART2_DTE_CTS_B 0x1b0b1
-                                                       MX6QDL_PAD_EIM_D29__UART2_DTE_RTS_B 0x1b0b1
-                                               >;
-                                       };
-                               };
-
-                               uart3 {
-                                       pinctrl_uart3_1: uart3grp-1 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_SD4_CLK__UART3_RX_DATA 0x1b0b1
-                                                       MX6QDL_PAD_SD4_CMD__UART3_TX_DATA 0x1b0b1
-                                                       MX6QDL_PAD_EIM_D30__UART3_CTS_B   0x1b0b1
-                                                       MX6QDL_PAD_EIM_EB3__UART3_RTS_B   0x1b0b1
-                                               >;
-                                       };
-
-                                       pinctrl_uart3_2: uart3grp-2 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1
-                                                       MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1
-                                                       MX6QDL_PAD_EIM_D23__UART3_CTS_B   0x1b0b1
-                                                       MX6QDL_PAD_EIM_EB3__UART3_RTS_B   0x1b0b1
-                                               >;
-                                       };
-                               };
-
-                               uart4 {
-                                       pinctrl_uart4_1: uart4grp-1 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1
-                                                       MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1
-                                               >;
-                                       };
-                               };
-
-                               usbotg {
-                                       pinctrl_usbotg_1: usbotggrp-1 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
-                                               >;
-                                       };
-
-                                       pinctrl_usbotg_2: usbotggrp-2 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059
-                                               >;
-                                       };
-                               };
-
-                               usbh2 {
-                                       pinctrl_usbh2_1: usbh2grp-1 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_RGMII_TXC__USB_H2_DATA      0x40013030
-                                                       MX6QDL_PAD_RGMII_TX_CTL__USB_H2_STROBE 0x40013030
-                                               >;
-                                       };
-
-                                       pinctrl_usbh2_2: usbh2grp-2 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_RGMII_TX_CTL__USB_H2_STROBE 0x40017030
-                                               >;
-                                       };
-                               };
-
-                               usbh3 {
-                                       pinctrl_usbh3_1: usbh3grp-1 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_RGMII_RX_CTL__USB_H3_DATA 0x40013030
-                                                       MX6QDL_PAD_RGMII_RXC__USB_H3_STROBE  0x40013030
-                                               >;
-                                       };
-
-                                       pinctrl_usbh3_2: usbh3grp-2 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_RGMII_RXC__USB_H3_STROBE 0x40017030
-                                               >;
-                                       };
-                               };
-
-                               usdhc1 {
-                                       pinctrl_usdhc1_1: usdhc1grp-1 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_SD1_CMD__SD1_CMD    0x17059
-                                                       MX6QDL_PAD_SD1_CLK__SD1_CLK    0x10059
-                                                       MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17059
-                                                       MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17059
-                                                       MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17059
-                                                       MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17059
-                                                       MX6QDL_PAD_NANDF_D0__SD1_DATA4 0x17059
-                                                       MX6QDL_PAD_NANDF_D1__SD1_DATA5 0x17059
-                                                       MX6QDL_PAD_NANDF_D2__SD1_DATA6 0x17059
-                                                       MX6QDL_PAD_NANDF_D3__SD1_DATA7 0x17059
-                                               >;
-                                       };
-
-                                       pinctrl_usdhc1_2: usdhc1grp-2 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_SD1_CMD__SD1_CMD    0x17059
-                                                       MX6QDL_PAD_SD1_CLK__SD1_CLK    0x10059
-                                                       MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17059
-                                                       MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17059
-                                                       MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17059
-                                                       MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17059
-                                               >;
-                                       };
-                               };
-
-                               usdhc2 {
-                                       pinctrl_usdhc2_1: usdhc2grp-1 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_SD2_CMD__SD2_CMD    0x17059
-                                                       MX6QDL_PAD_SD2_CLK__SD2_CLK    0x10059
-                                                       MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
-                                                       MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
-                                                       MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
-                                                       MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
-                                                       MX6QDL_PAD_NANDF_D4__SD2_DATA4 0x17059
-                                                       MX6QDL_PAD_NANDF_D5__SD2_DATA5 0x17059
-                                                       MX6QDL_PAD_NANDF_D6__SD2_DATA6 0x17059
-                                                       MX6QDL_PAD_NANDF_D7__SD2_DATA7 0x17059
-                                               >;
-                                       };
-
-                                       pinctrl_usdhc2_2: usdhc2grp-2 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_SD2_CMD__SD2_CMD    0x17059
-                                                       MX6QDL_PAD_SD2_CLK__SD2_CLK    0x10059
-                                                       MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
-                                                       MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
-                                                       MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
-                                                       MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
-                                               >;
-                                       };
-                               };
-
-                               usdhc3 {
-                                       pinctrl_usdhc3_1: usdhc3grp-1 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_SD3_CMD__SD3_CMD    0x17059
-                                                       MX6QDL_PAD_SD3_CLK__SD3_CLK    0x10059
-                                                       MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
-                                                       MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
-                                                       MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
-                                                       MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
-                                                       MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x17059
-                                                       MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x17059
-                                                       MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x17059
-                                                       MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x17059
-                                               >;
-                                       };
-
-                                       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
-                                                       MX6QDL_PAD_SD3_CLK__SD3_CLK    0x10059
-                                                       MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
-                                                       MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
-                                                       MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
-                                                       MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
-                                               >;
-                                       };
-                               };
-
-                               usdhc4 {
-                                       pinctrl_usdhc4_1: usdhc4grp-1 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_SD4_CMD__SD4_CMD    0x17059
-                                                       MX6QDL_PAD_SD4_CLK__SD4_CLK    0x10059
-                                                       MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
-                                                       MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
-                                                       MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
-                                                       MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
-                                                       MX6QDL_PAD_SD4_DAT4__SD4_DATA4 0x17059
-                                                       MX6QDL_PAD_SD4_DAT5__SD4_DATA5 0x17059
-                                                       MX6QDL_PAD_SD4_DAT6__SD4_DATA6 0x17059
-                                                       MX6QDL_PAD_SD4_DAT7__SD4_DATA7 0x17059
-                                               >;
-                                       };
-
-                                       pinctrl_usdhc4_2: usdhc4grp-2 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_SD4_CMD__SD4_CMD    0x17059
-                                                       MX6QDL_PAD_SD4_CLK__SD4_CLK    0x10059
-                                                       MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
-                                                       MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
-                                                       MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
-                                                       MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
-                                               >;
-                                       };
-                               };
-
-                               weim {
-                                       pinctrl_weim_cs0_1: weim_cs0grp-1 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_EIM_CS0__EIM_CS0_B   0xb0b1
-                                               >;
-                                       };
-
-                                       pinctrl_weim_nor_1: weim_norgrp-1 {
-                                               fsl,pins = <
-                                                       MX6QDL_PAD_EIM_OE__EIM_OE_B     0xb0b1
-                                                       MX6QDL_PAD_EIM_RW__EIM_RW       0xb0b1
-                                                       MX6QDL_PAD_EIM_WAIT__EIM_WAIT_B 0xb060
-                                                       /* data */
-                                                       MX6QDL_PAD_EIM_D16__EIM_DATA16 0x1b0b0
-                                                       MX6QDL_PAD_EIM_D17__EIM_DATA17 0x1b0b0
-                                                       MX6QDL_PAD_EIM_D18__EIM_DATA18 0x1b0b0
-                                                       MX6QDL_PAD_EIM_D19__EIM_DATA19 0x1b0b0
-                                                       MX6QDL_PAD_EIM_D20__EIM_DATA20 0x1b0b0
-                                                       MX6QDL_PAD_EIM_D21__EIM_DATA21 0x1b0b0
-                                                       MX6QDL_PAD_EIM_D22__EIM_DATA22 0x1b0b0
-                                                       MX6QDL_PAD_EIM_D23__EIM_DATA23 0x1b0b0
-                                                       MX6QDL_PAD_EIM_D24__EIM_DATA24 0x1b0b0
-                                                       MX6QDL_PAD_EIM_D25__EIM_DATA25 0x1b0b0
-                                                       MX6QDL_PAD_EIM_D26__EIM_DATA26 0x1b0b0
-                                                       MX6QDL_PAD_EIM_D27__EIM_DATA27 0x1b0b0
-                                                       MX6QDL_PAD_EIM_D28__EIM_DATA28 0x1b0b0
-                                                       MX6QDL_PAD_EIM_D29__EIM_DATA29 0x1b0b0
-                                                       MX6QDL_PAD_EIM_D30__EIM_DATA30 0x1b0b0
-                                                       MX6QDL_PAD_EIM_D31__EIM_DATA31 0x1b0b0
-                                                       /* address */
-                                                       MX6QDL_PAD_EIM_A23__EIM_ADDR23 0xb0b1
-                                                       MX6QDL_PAD_EIM_A22__EIM_ADDR22 0xb0b1
-                                                       MX6QDL_PAD_EIM_A21__EIM_ADDR21 0xb0b1
-                                                       MX6QDL_PAD_EIM_A20__EIM_ADDR20 0xb0b1
-                                                       MX6QDL_PAD_EIM_A19__EIM_ADDR19 0xb0b1
-                                                       MX6QDL_PAD_EIM_A18__EIM_ADDR18 0xb0b1
-                                                       MX6QDL_PAD_EIM_A17__EIM_ADDR17 0xb0b1
-                                                       MX6QDL_PAD_EIM_A16__EIM_ADDR16 0xb0b1
-                                                       MX6QDL_PAD_EIM_DA15__EIM_AD15  0xb0b1
-                                                       MX6QDL_PAD_EIM_DA14__EIM_AD14  0xb0b1
-                                                       MX6QDL_PAD_EIM_DA13__EIM_AD13  0xb0b1
-                                                       MX6QDL_PAD_EIM_DA12__EIM_AD12  0xb0b1
-                                                       MX6QDL_PAD_EIM_DA11__EIM_AD11  0xb0b1
-                                                       MX6QDL_PAD_EIM_DA10__EIM_AD10  0xb0b1
-                                                       MX6QDL_PAD_EIM_DA9__EIM_AD09   0xb0b1
-                                                       MX6QDL_PAD_EIM_DA8__EIM_AD08   0xb0b1
-                                                       MX6QDL_PAD_EIM_DA7__EIM_AD07   0xb0b1
-                                                       MX6QDL_PAD_EIM_DA6__EIM_AD06   0xb0b1
-                                                       MX6QDL_PAD_EIM_DA5__EIM_AD05   0xb0b1
-                                                       MX6QDL_PAD_EIM_DA4__EIM_AD04   0xb0b1
-                                                       MX6QDL_PAD_EIM_DA3__EIM_AD03   0xb0b1
-                                                       MX6QDL_PAD_EIM_DA2__EIM_AD02   0xb0b1
-                                                       MX6QDL_PAD_EIM_DA1__EIM_AD01   0xb0b1
-                                                       MX6QDL_PAD_EIM_DA0__EIM_AD00   0xb0b1
-                                               >;
-                                       };
-                               };
                        };
 
                        ldb: ldb@020e0008 {
 
                        dcic1: dcic@020e4000 {
                                reg = <0x020e4000 0x4000>;
-                               interrupts = <0 124 0x04>;
+                               interrupts = <0 124 IRQ_TYPE_LEVEL_HIGH>;
                        };
 
                        dcic2: dcic@020e8000 {
                                reg = <0x020e8000 0x4000>;
-                               interrupts = <0 125 0x04>;
+                               interrupts = <0 125 IRQ_TYPE_LEVEL_HIGH>;
                        };
 
                        sdma: sdma@020ec000 {
                                compatible = "fsl,imx6q-sdma", "fsl,imx35-sdma";
                                reg = <0x020ec000 0x4000>;
-                               interrupts = <0 2 0x04>;
+                               interrupts = <0 2 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks 155>, <&clks 155>;
                                clock-names = "ipg", "ahb";
                                #dma-cells = <3>;
 
                        caam@02100000 {
                                reg = <0x02100000 0x40000>;
-                               interrupts = <0 105 0x04 0 106 0x04>;
+                               interrupts = <0 105 IRQ_TYPE_LEVEL_HIGH>,
+                                            <0 106 IRQ_TYPE_LEVEL_HIGH>;
                        };
 
                        aipstz@0217c000 { /* AIPSTZ2 */
                        usbotg: usb@02184000 {
                                compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
                                reg = <0x02184000 0x200>;
-                               interrupts = <0 43 0x04>;
+                               interrupts = <0 43 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks 162>;
                                fsl,usbphy = <&usbphy1>;
                                fsl,usbmisc = <&usbmisc 0>;
                        usbh1: usb@02184200 {
                                compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
                                reg = <0x02184200 0x200>;
-                               interrupts = <0 40 0x04>;
+                               interrupts = <0 40 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks 162>;
                                fsl,usbphy = <&usbphy2>;
                                fsl,usbmisc = <&usbmisc 1>;
                        usbh2: usb@02184400 {
                                compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
                                reg = <0x02184400 0x200>;
-                               interrupts = <0 41 0x04>;
+                               interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks 162>;
                                fsl,usbmisc = <&usbmisc 2>;
                                status = "disabled";
                        usbh3: usb@02184600 {
                                compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
                                reg = <0x02184600 0x200>;
-                               interrupts = <0 42 0x04>;
+                               interrupts = <0 42 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks 162>;
                                fsl,usbmisc = <&usbmisc 3>;
                                status = "disabled";
                        fec: ethernet@02188000 {
                                compatible = "fsl,imx6q-fec";
                                reg = <0x02188000 0x4000>;
-                               interrupts = <0 118 0x04 0 119 0x04>;
+                               interrupts = <0 118 IRQ_TYPE_LEVEL_HIGH>,
+                                            <0 119 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks 117>, <&clks 117>, <&clks 190>;
                                clock-names = "ipg", "ahb", "ptp";
                                status = "disabled";
 
                        mlb@0218c000 {
                                reg = <0x0218c000 0x4000>;
-                               interrupts = <0 53 0x04 0 117 0x04 0 126 0x04>;
+                               interrupts = <0 53 IRQ_TYPE_LEVEL_HIGH>,
+                                            <0 117 IRQ_TYPE_LEVEL_HIGH>,
+                                            <0 126 IRQ_TYPE_LEVEL_HIGH>;
                        };
 
                        usdhc1: usdhc@02190000 {
                                compatible = "fsl,imx6q-usdhc";
                                reg = <0x02190000 0x4000>;
-                               interrupts = <0 22 0x04>;
+                               interrupts = <0 22 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks 163>, <&clks 163>, <&clks 163>;
                                clock-names = "ipg", "ahb", "per";
                                bus-width = <4>;
                        usdhc2: usdhc@02194000 {
                                compatible = "fsl,imx6q-usdhc";
                                reg = <0x02194000 0x4000>;
-                               interrupts = <0 23 0x04>;
+                               interrupts = <0 23 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks 164>, <&clks 164>, <&clks 164>;
                                clock-names = "ipg", "ahb", "per";
                                bus-width = <4>;
                        usdhc3: usdhc@02198000 {
                                compatible = "fsl,imx6q-usdhc";
                                reg = <0x02198000 0x4000>;
-                               interrupts = <0 24 0x04>;
+                               interrupts = <0 24 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks 165>, <&clks 165>, <&clks 165>;
                                clock-names = "ipg", "ahb", "per";
                                bus-width = <4>;
                        usdhc4: usdhc@0219c000 {
                                compatible = "fsl,imx6q-usdhc";
                                reg = <0x0219c000 0x4000>;
-                               interrupts = <0 25 0x04>;
+                               interrupts = <0 25 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks 166>, <&clks 166>, <&clks 166>;
                                clock-names = "ipg", "ahb", "per";
                                bus-width = <4>;
                                #size-cells = <0>;
                                compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
                                reg = <0x021a0000 0x4000>;
-                               interrupts = <0 36 0x04>;
+                               interrupts = <0 36 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks 125>;
                                status = "disabled";
                        };
                                #size-cells = <0>;
                                compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
                                reg = <0x021a4000 0x4000>;
-                               interrupts = <0 37 0x04>;
+                               interrupts = <0 37 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks 126>;
                                status = "disabled";
                        };
                                #size-cells = <0>;
                                compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
                                reg = <0x021a8000 0x4000>;
-                               interrupts = <0 38 0x04>;
+                               interrupts = <0 38 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks 127>;
                                status = "disabled";
                        };
                        weim: weim@021b8000 {
                                compatible = "fsl,imx6q-weim";
                                reg = <0x021b8000 0x4000>;
-                               interrupts = <0 14 0x04>;
+                               interrupts = <0 14 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks 196>;
                        };
 
 
                        tzasc@021d0000 { /* TZASC1 */
                                reg = <0x021d0000 0x4000>;
-                               interrupts = <0 108 0x04>;
+                               interrupts = <0 108 IRQ_TYPE_LEVEL_HIGH>;
                        };
 
                        tzasc@021d4000 { /* TZASC2 */
                                reg = <0x021d4000 0x4000>;
-                               interrupts = <0 109 0x04>;
+                               interrupts = <0 109 IRQ_TYPE_LEVEL_HIGH>;
                        };
 
                        audmux: audmux@021d8000 {
                                status = "disabled";
                        };
 
-                       mipi@021dc000 { /* MIPI-CSI */
+                       mipi_csi: mipi@021dc000 {
                                reg = <0x021dc000 0x4000>;
                        };
 
 
                        vdoa@021e4000 {
                                reg = <0x021e4000 0x4000>;
-                               interrupts = <0 18 0x04>;
+                               interrupts = <0 18 IRQ_TYPE_LEVEL_HIGH>;
                        };
 
                        uart2: serial@021e8000 {
                                compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
                                reg = <0x021e8000 0x4000>;
-                               interrupts = <0 27 0x04>;
+                               interrupts = <0 27 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks 160>, <&clks 161>;
                                clock-names = "ipg", "per";
                                dmas = <&sdma 27 4 0>, <&sdma 28 4 0>;
                        uart3: serial@021ec000 {
                                compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
                                reg = <0x021ec000 0x4000>;
-                               interrupts = <0 28 0x04>;
+                               interrupts = <0 28 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks 160>, <&clks 161>;
                                clock-names = "ipg", "per";
                                dmas = <&sdma 29 4 0>, <&sdma 30 4 0>;
                        uart4: serial@021f0000 {
                                compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
                                reg = <0x021f0000 0x4000>;
-                               interrupts = <0 29 0x04>;
+                               interrupts = <0 29 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks 160>, <&clks 161>;
                                clock-names = "ipg", "per";
                                dmas = <&sdma 31 4 0>, <&sdma 32 4 0>;
                        uart5: serial@021f4000 {
                                compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
                                reg = <0x021f4000 0x4000>;
-                               interrupts = <0 30 0x04>;
+                               interrupts = <0 30 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks 160>, <&clks 161>;
                                clock-names = "ipg", "per";
                                dmas = <&sdma 33 4 0>, <&sdma 34 4 0>;
                        #crtc-cells = <1>;
                        compatible = "fsl,imx6q-ipu";
                        reg = <0x02400000 0x400000>;
-                       interrupts = <0 6 0x4 0 5 0x4>;
+                       interrupts = <0 6 IRQ_TYPE_LEVEL_HIGH>,
+                                    <0 5 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&clks 130>, <&clks 131>, <&clks 132>;
                        clock-names = "bus", "di0", "di1";
                        resets = <&src 2>;
index cc68e19c51631666e8241fbc1d4965a18605ca28..f5e4513ebfc3be074263d633cba08b04fba428af 100644 (file)
 
        regulators {
                compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
 
-               reg_usb_otg1_vbus: usb_otg1_vbus {
+               reg_usb_otg1_vbus: regulator@0 {
                        compatible = "regulator-fixed";
+                       reg = <0>;
                        regulator-name = "usb_otg1_vbus";
                        regulator-min-microvolt = <5000000>;
                        regulator-max-microvolt = <5000000>;
@@ -30,8 +33,9 @@
                        enable-active-high;
                };
 
-               reg_usb_otg2_vbus: usb_otg2_vbus {
+               reg_usb_otg2_vbus: regulator@1 {
                        compatible = "regulator-fixed";
+                       reg = <1>;
                        regulator-name = "usb_otg2_vbus";
                        regulator-min-microvolt = <5000000>;
                        regulator-max-microvolt = <5000000>;
@@ -45,7 +49,7 @@
        fsl,spi-num-chipselects = <1>;
        cs-gpios = <&gpio4 11 0>;
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_ecspi1_1>;
+       pinctrl-0 = <&pinctrl_ecspi1>;
        status = "okay";
 
        flash: m25p80@0 {
@@ -59,7 +63,7 @@
 
 &fec {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_fec_1>;
+       pinctrl-0 = <&pinctrl_fec>;
        phy-mode = "rmii";
        status = "okay";
 };
@@ -68,7 +72,7 @@
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_hog>;
 
-       hog {
+       imx6sl-evk {
                pinctrl_hog: hoggrp {
                        fsl,pins = <
                                MX6SL_PAD_KEY_ROW7__GPIO4_IO07    0x17059
                                MX6SL_PAD_KEY_COL5__GPIO4_IO02  0x80000000
                        >;
                };
+
+               pinctrl_ecspi1: ecspi1grp {
+                       fsl,pins = <MX6SL_ECSPI1_PINGRP1>;
+               };
+
+               pinctrl_fec: fecgrp {
+                       fsl,pins = <MX6SL_FEC_PINGRP1>;
+               };
+
+               pinctrl_uart1: uart1grp {
+                       fsl,pins = <MX6SL_UART1_PINGRP1>;
+               };
+
+               pinctrl_usbotg1: usbotg1grp {
+                       fsl,pins = <MX6SL_USBOTG1_PINGRP1>;
+               };
+
+               pinctrl_usdhc1: usdhc1grp {
+                       fsl,pins = <MX6SL_USDHC1_PINGRP_D8>;
+               };
+
+               pinctrl_usdhc1_100mhz: usdhc1grp100mhz {
+                       fsl,pins = <MX6SL_USDHC1_PINGRP_D8_100MHZ>;
+               };
+
+               pinctrl_usdhc1_200mhz: usdhc1grp200mhz {
+                       fsl,pins = <MX6SL_USDHC1_PINGRP_D8_200MHZ>;
+               };
+
+               pinctrl_usdhc2: usdhc2grp {
+                       fsl,pins = <MX6SL_USDHC2_PINGRP_D4>;
+               };
+
+               pinctrl_usdhc2_100mhz: usdhc2grp100mhz {
+                       fsl,pins = <MX6SL_USDHC2_PINGRP_D4_100MHZ>;
+               };
+
+               pinctrl_usdhc2_200mhz: usdhc2grp200mhz {
+                       fsl,pins = <MX6SL_USDHC2_PINGRP_D4_200MHZ>;
+               };
+
+               pinctrl_usdhc3: usdhc3grp {
+                       fsl,pins = <MX6SL_USDHC3_PINGRP_D4>;
+               };
+
+               pinctrl_usdhc3_100mhz: usdhc3grp100mhz {
+                       fsl,pins = <MX6SL_USDHC3_PINGRP_D4_100MHZ>;
+               };
+
+               pinctrl_usdhc3_200mhz: usdhc3grp200mhz {
+                       fsl,pins = <MX6SL_USDHC3_PINGRP_D4_200MHZ>;
+               };
        };
 };
 
 &uart1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_uart1_1>;
+       pinctrl-0 = <&pinctrl_uart1>;
        status = "okay";
 };
 
 &usbotg1 {
        vbus-supply = <&reg_usb_otg1_vbus>;
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_usbotg1_1>;
+       pinctrl-0 = <&pinctrl_usbotg1>;
        disable-over-current;
        status = "okay";
 };
 
 &usdhc1 {
        pinctrl-names = "default", "state_100mhz", "state_200mhz";
-       pinctrl-0 = <&pinctrl_usdhc1_1>;
-       pinctrl-1 = <&pinctrl_usdhc1_1_100mhz>;
-       pinctrl-2 = <&pinctrl_usdhc1_1_200mhz>;
+       pinctrl-0 = <&pinctrl_usdhc1>;
+       pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
+       pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
        bus-width = <8>;
        cd-gpios = <&gpio4 7 0>;
        wp-gpios = <&gpio4 6 0>;
 
 &usdhc2 {
        pinctrl-names = "default", "state_100mhz", "state_200mhz";
-       pinctrl-0 = <&pinctrl_usdhc2_1>;
-       pinctrl-1 = <&pinctrl_usdhc2_1_100mhz>;
-       pinctrl-2 = <&pinctrl_usdhc2_1_200mhz>;
+       pinctrl-0 = <&pinctrl_usdhc2>;
+       pinctrl-1 = <&pinctrl_usdhc2_100mhz>;
+       pinctrl-2 = <&pinctrl_usdhc2_200mhz>;
        cd-gpios = <&gpio5 0 0>;
        wp-gpios = <&gpio4 29 0>;
        status = "okay";
 
 &usdhc3 {
        pinctrl-names = "default", "state_100mhz", "state_200mhz";
-       pinctrl-0 = <&pinctrl_usdhc3_1>;
-       pinctrl-1 = <&pinctrl_usdhc3_1_100mhz>;
-       pinctrl-2 = <&pinctrl_usdhc3_1_200mhz>;
+       pinctrl-0 = <&pinctrl_usdhc3>;
+       pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
+       pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
        cd-gpios = <&gpio3 22 0>;
        status = "okay";
 };
diff --git a/arch/arm/boot/dts/imx6sl-pingrp.h b/arch/arm/boot/dts/imx6sl-pingrp.h
new file mode 100644 (file)
index 0000000..ead26d4
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 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.
+ *
+ */
+
+#ifndef __DTS_IMX6SL_PINGRP_H
+#define __DTS_IMX6SL_PINGRP_H
+
+#define MX6SL_ECSPI1_PINGRP1 \
+       MX6SL_PAD_ECSPI1_MISO__ECSPI1_MISO              0x100b1 \
+       MX6SL_PAD_ECSPI1_MOSI__ECSPI1_MOSI              0x100b1 \
+       MX6SL_PAD_ECSPI1_SCLK__ECSPI1_SCLK              0x100b1
+
+#define MX6SL_FEC_PINGRP1 \
+       MX6SL_PAD_FEC_MDC__FEC_MDC                      0x1b0b0 \
+       MX6SL_PAD_FEC_MDIO__FEC_MDIO                    0x1b0b0 \
+       MX6SL_PAD_FEC_CRS_DV__FEC_RX_DV                 0x1b0b0 \
+       MX6SL_PAD_FEC_RXD0__FEC_RX_DATA0                0x1b0b0 \
+       MX6SL_PAD_FEC_RXD1__FEC_RX_DATA1                0x1b0b0 \
+       MX6SL_PAD_FEC_TX_EN__FEC_TX_EN                  0x1b0b0 \
+       MX6SL_PAD_FEC_TXD0__FEC_TX_DATA0                0x1b0b0 \
+       MX6SL_PAD_FEC_TXD1__FEC_TX_DATA1                0x1b0b0 \
+       MX6SL_PAD_FEC_REF_CLK__FEC_REF_OUT              0x4001b0a8
+
+#define MX6SL_UART1_PINGRP1 \
+       MX6SL_PAD_UART1_RXD__UART1_RX_DATA              0x1b0b1 \
+       MX6SL_PAD_UART1_TXD__UART1_TX_DATA              0x1b0b1
+
+#define MX6SL_USBOTG1_PINGRP1 \
+       MX6SL_PAD_EPDC_PWRCOM__USB_OTG1_ID              0x17059
+
+#define MX6SL_USBOTG1_PINGRP2 \
+       MX6SL_PAD_FEC_RXD0__USB_OTG1_ID                 0x17059
+
+#define MX6SL_USBOTG1_PINGRP3 \
+       MX6SL_PAD_LCD_DAT1__USB_OTG1_ID                 0x17059
+
+#define MX6SL_USBOTG1_PINGRP4 \
+       MX6SL_PAD_REF_CLK_32K__USB_OTG1_ID              0x17059
+
+#define MX6SL_USBOTG1_PINGRP5 \
+       MX6SL_PAD_SD3_DAT0__USB_OTG1_ID                 0x17059
+
+#define MX6SL_USBOTG2_PINGRP1 \
+       MX6SL_PAD_ECSPI1_SCLK__USB_OTG2_OC              0x17059
+
+#define MX6SL_USBOTG2_PINGRP2 \
+       MX6SL_PAD_ECSPI2_SCLK__USB_OTG2_OC              0x17059
+
+#define MX6SL_USBOTG2_PINGRP3 \
+       MX6SL_PAD_KEY_ROW5__USB_OTG2_OC                 0x17059
+
+#define MX6SL_USBOTG2_PINGRP4 \
+       MX6SL_PAD_SD3_DAT2__USB_OTG2_OC                 0x17059
+
+#define MX6SL_USDHC1_D4(pad, pad_data3, pad_clk)       \
+       MX6SL_PAD_SD1_CMD__SD1_CMD                      pad \
+       MX6SL_PAD_SD1_CLK__SD1_CLK                      pad_clk \
+       MX6SL_PAD_SD1_DAT0__SD1_DATA0                   pad \
+       MX6SL_PAD_SD1_DAT1__SD1_DATA1                   pad \
+       MX6SL_PAD_SD1_DAT2__SD1_DATA2                   pad \
+       MX6SL_PAD_SD1_DAT3__SD1_DATA3                   pad_data3
+
+#define MX6SL_USDHC1_D8(pad, pad_data3, pad_clk)       \
+       MX6SL_USDHC1_D4(pad, pad_data3, pad_clk)        \
+       MX6SL_PAD_SD1_DAT4__SD1_DATA4                   pad \
+       MX6SL_PAD_SD1_DAT5__SD1_DATA5                   pad \
+       MX6SL_PAD_SD1_DAT6__SD1_DATA6                   pad \
+       MX6SL_PAD_SD1_DAT7__SD1_DATA7                   pad
+
+#define MX6SL_USDHC2_D4(pad, pad_data3, pad_clk)       \
+       MX6SL_PAD_SD2_CMD__SD2_CMD                      pad \
+       MX6SL_PAD_SD2_CLK__SD2_CLK                      pad_clk \
+       MX6SL_PAD_SD2_DAT0__SD2_DATA0                   pad \
+       MX6SL_PAD_SD2_DAT1__SD2_DATA1                   pad \
+       MX6SL_PAD_SD2_DAT2__SD2_DATA2                   pad \
+       MX6SL_PAD_SD2_DAT3__SD2_DATA3                   pad_data3
+
+#define MX6SL_USDHC2_D8(pad, pad_data3, pad_clk)       \
+       MX6SL_USDHC2_D4(pad, pad_data3, pad_clk)        \
+       MX6SL_PAD_SD2_DAT4__SD2_DATA4                   pad \
+       MX6SL_PAD_SD2_DAT5__SD2_DATA5                   pad \
+       MX6SL_PAD_SD2_DAT6__SD2_DATA6                   pad \
+       MX6SL_PAD_SD2_DAT7__SD2_DATA7                   pad
+
+#define MX6SL_USDHC3_D4(pad, pad_data3, pad_clk)       \
+       MX6SL_PAD_SD3_CMD__SD3_CMD                      pad \
+       MX6SL_PAD_SD3_CLK__SD3_CLK                      pad_clk \
+       MX6SL_PAD_SD3_DAT0__SD3_DATA0                   pad \
+       MX6SL_PAD_SD3_DAT1__SD3_DATA1                   pad \
+       MX6SL_PAD_SD3_DAT2__SD3_DATA2                   pad \
+       MX6SL_PAD_SD3_DAT3__SD3_DATA3                   pad_data3
+
+#define MX6SL_USDHC3_D8(pad, pad_data3, pad_clk)       \
+       MX6SL_USDHC3_D4(pad, pad_data3, pad_clk)        \
+       MX6SL_PAD_SD2_DAT4__SD3_DATA4                   pad \
+       MX6SL_PAD_SD2_DAT5__SD3_DATA5                   pad \
+       MX6SL_PAD_SD2_DAT6__SD3_DATA6                   pad \
+       MX6SL_PAD_SD2_DAT7__SD3_DATA7                   pad
+
+#define MX6SL_USDHC4_D4(pad, pad_data3, pad_clk)       \
+       MX6SL_PAD_EPDC_BDR1__SD4_CMD                    pad \
+       MX6SL_PAD_EPDC_BDR0__SD4_CLK                    pad_clk \
+       MX6SL_PAD_EPDC_PWRCOM__SD4_DATA0                pad \
+       MX6SL_PAD_EPDC_PWRINT__SD4_DATA1                pad \
+       MX6SL_PAD_EPDC_PWRSTAT__SD4_DATA2               pad \
+       MX6SL_PAD_EPDC_PWRWAKEUP__SD4_DATA3             pad_data3
+
+#define MX6SL_USDHC4_D8(pad, pad_data3, pad_clk)       \
+       MX6SL_USDHC4_D4(pad, pad_data3, pad_clk)        \
+       MX6SL_PAD_KEY_COL7__SD4_DATA4                   pad \
+       MX6SL_PAD_KEY_ROW7__SD4_DATA5                   pad \
+       MX6SL_PAD_KEY_COL3__SD4_DATA6                   pad \
+       MX6SL_PAD_KEY_ROW3__SD4_DATA7                   pad
+
+#define MX6SL_USDHC1_PINGRP_D4       MX6SL_USDHC1_D4(0x17059, 0x17059, 0x10059)
+#define MX6SL_USDHC1_PINGRP_D4_100MHZ MX6SL_USDHC1_D4(0x170b9, 0x170b9, 0x100b9)
+#define MX6SL_USDHC1_PINGRP_D4_200MHZ MX6SL_USDHC1_D4(0x170f9, 0x170f9, 0x100f9)
+#define MX6SL_USDHC1_PINGRP_D8       MX6SL_USDHC1_D8(0x17059, 0x17059, 0x10059)
+#define MX6SL_USDHC1_PINGRP_D8_100MHZ MX6SL_USDHC1_D8(0x170b9, 0x170b9, 0x100b9)
+#define MX6SL_USDHC1_PINGRP_D8_200MHZ MX6SL_USDHC1_D8(0x170f9, 0x170f9, 0x100f9)
+
+#define MX6SL_USDHC2_PINGRP_D4       MX6SL_USDHC2_D4(0x17059, 0x17059, 0x10059)
+#define MX6SL_USDHC2_PINGRP_D4_100MHZ MX6SL_USDHC2_D4(0x170b9, 0x170b9, 0x100b9)
+#define MX6SL_USDHC2_PINGRP_D4_200MHZ MX6SL_USDHC2_D4(0x170f9, 0x170f9, 0x100f9)
+#define MX6SL_USDHC2_PINGRP_D8       MX6SL_USDHC2_D8(0x17059, 0x17059, 0x10059)
+#define MX6SL_USDHC2_PINGRP_D8_100MHZ MX6SL_USDHC2_D8(0x170b9, 0x170b9, 0x100b9)
+#define MX6SL_USDHC2_PINGRP_D8_200MHZ MX6SL_USDHC2_D8(0x170f9, 0x170f9, 0x100f9)
+
+#define MX6SL_USDHC3_PINGRP_D4       MX6SL_USDHC3_D4(0x17059, 0x17059, 0x10059)
+#define MX6SL_USDHC3_PINGRP_D4_100MHZ MX6SL_USDHC3_D4(0x170b9, 0x170b9, 0x100b9)
+#define MX6SL_USDHC3_PINGRP_D4_200MHZ MX6SL_USDHC3_D4(0x170f9, 0x170f9, 0x100f9)
+#define MX6SL_USDHC3_PINGRP_D8       MX6SL_USDHC3_D8(0x17059, 0x17059, 0x10059)
+#define MX6SL_USDHC3_PINGRP_D8_100MHZ MX6SL_USDHC3_D8(0x170b9, 0x170b9, 0x100b9)
+#define MX6SL_USDHC3_PINGRP_D8_200MHZ MX6SL_USDHC3_D8(0x170f9, 0x170f9, 0x100f9)
+
+#define MX6SL_USDHC4_PINGRP_D4       MX6SL_USDHC4_D4(0x17059, 0x17059, 0x10059)
+#define MX6SL_USDHC4_PINGRP_D4_100MHZ MX6SL_USDHC4_D4(0x170b9, 0x170b9, 0x100b9)
+#define MX6SL_USDHC4_PINGRP_D4_200MHZ MX6SL_USDHC4_D4(0x170f9, 0x170f9, 0x100f9)
+#define MX6SL_USDHC4_PINGRP_D8       MX6SL_USDHC4_D8(0x17059, 0x17059, 0x10059)
+#define MX6SL_USDHC4_PINGRP_D8_100MHZ MX6SL_USDHC4_D8(0x170b9, 0x170b9, 0x100b9)
+#define MX6SL_USDHC4_PINGRP_D8_200MHZ MX6SL_USDHC4_D8(0x170f9, 0x170f9, 0x100f9)
+
+#endif /* __DTS_IMX6SL_PINGRP_H */
index 28558f1aaf2da8e67cb6b191f2d11e7964518b59..b526118b6fe92da9f69344ed80481d8c77d6ffb1 100644 (file)
@@ -7,8 +7,10 @@
  *
  */
 
+#include <dt-bindings/interrupt-controller/irq.h>
 #include "skeleton.dtsi"
 #include "imx6sl-pinfunc.h"
+#include "imx6sl-pingrp.h"
 #include <dt-bindings/clock/imx6sl-clock.h>
 
 / {
@@ -76,7 +78,7 @@
                L2: l2-cache@00a02000 {
                        compatible = "arm,pl310-cache";
                        reg = <0x00a02000 0x1000>;
-                       interrupts = <0 92 0x04>;
+                       interrupts = <0 92 IRQ_TYPE_LEVEL_HIGH>;
                        cache-unified;
                        cache-level = <2>;
                        arm,tag-latency = <4 2 3>;
@@ -85,7 +87,7 @@
 
                pmu {
                        compatible = "arm,cortex-a9-pmu";
-                       interrupts = <0 94 0x04>;
+                       interrupts = <0 94 IRQ_TYPE_LEVEL_HIGH>;
                };
 
                aips1: aips-bus@02000000 {
 
                                spdif: spdif@02004000 {
                                        reg = <0x02004000 0x4000>;
-                                       interrupts = <0 52 0x04>;
+                                       interrupts = <0 52 IRQ_TYPE_LEVEL_HIGH>;
                                };
 
                                ecspi1: ecspi@02008000 {
                                        #size-cells = <0>;
                                        compatible = "fsl,imx6sl-ecspi", "fsl,imx51-ecspi";
                                        reg = <0x02008000 0x4000>;
-                                       interrupts = <0 31 0x04>;
+                                       interrupts = <0 31 IRQ_TYPE_LEVEL_HIGH>;
                                        clocks = <&clks IMX6SL_CLK_ECSPI1>,
                                                 <&clks IMX6SL_CLK_ECSPI1>;
                                        clock-names = "ipg", "per";
                                        #size-cells = <0>;
                                        compatible = "fsl,imx6sl-ecspi", "fsl,imx51-ecspi";
                                        reg = <0x0200c000 0x4000>;
-                                       interrupts = <0 32 0x04>;
+                                       interrupts = <0 32 IRQ_TYPE_LEVEL_HIGH>;
                                        clocks = <&clks IMX6SL_CLK_ECSPI2>,
                                                 <&clks IMX6SL_CLK_ECSPI2>;
                                        clock-names = "ipg", "per";
                                        #size-cells = <0>;
                                        compatible = "fsl,imx6sl-ecspi", "fsl,imx51-ecspi";
                                        reg = <0x02010000 0x4000>;
-                                       interrupts = <0 33 0x04>;
+                                       interrupts = <0 33 IRQ_TYPE_LEVEL_HIGH>;
                                        clocks = <&clks IMX6SL_CLK_ECSPI3>,
                                                 <&clks IMX6SL_CLK_ECSPI3>;
                                        clock-names = "ipg", "per";
                                        #size-cells = <0>;
                                        compatible = "fsl,imx6sl-ecspi", "fsl,imx51-ecspi";
                                        reg = <0x02014000 0x4000>;
-                                       interrupts = <0 34 0x04>;
+                                       interrupts = <0 34 IRQ_TYPE_LEVEL_HIGH>;
                                        clocks = <&clks IMX6SL_CLK_ECSPI4>,
                                                 <&clks IMX6SL_CLK_ECSPI4>;
                                        clock-names = "ipg", "per";
                                        compatible = "fsl,imx6sl-uart",
                                                   "fsl,imx6q-uart", "fsl,imx21-uart";
                                        reg = <0x02018000 0x4000>;
-                                       interrupts = <0 30 0x04>;
+                                       interrupts = <0 30 IRQ_TYPE_LEVEL_HIGH>;
                                        clocks = <&clks IMX6SL_CLK_UART>,
                                                 <&clks IMX6SL_CLK_UART_SERIAL>;
                                        clock-names = "ipg", "per";
                                        compatible = "fsl,imx6sl-uart",
                                                   "fsl,imx6q-uart", "fsl,imx21-uart";
                                        reg = <0x02020000 0x4000>;
-                                       interrupts = <0 26 0x04>;
+                                       interrupts = <0 26 IRQ_TYPE_LEVEL_HIGH>;
                                        clocks = <&clks IMX6SL_CLK_UART>,
                                                 <&clks IMX6SL_CLK_UART_SERIAL>;
                                        clock-names = "ipg", "per";
                                        compatible = "fsl,imx6sl-uart",
                                                   "fsl,imx6q-uart", "fsl,imx21-uart";
                                        reg = <0x02024000 0x4000>;
-                                       interrupts = <0 27 0x04>;
+                                       interrupts = <0 27 IRQ_TYPE_LEVEL_HIGH>;
                                        clocks = <&clks IMX6SL_CLK_UART>,
                                                 <&clks IMX6SL_CLK_UART_SERIAL>;
                                        clock-names = "ipg", "per";
                                ssi1: ssi@02028000 {
                                        compatible = "fsl,imx6sl-ssi","fsl,imx21-ssi";
                                        reg = <0x02028000 0x4000>;
-                                       interrupts = <0 46 0x04>;
+                                       interrupts = <0 46 IRQ_TYPE_LEVEL_HIGH>;
                                        clocks = <&clks IMX6SL_CLK_SSI1>;
-                                       dmas = <&sdma 37 1 0>,
-                                              <&sdma 38 1 0>;
+                                       dmas = <&sdma 37 22 0>,
+                                              <&sdma 38 22 0>;
                                        dma-names = "rx", "tx";
                                        fsl,fifo-depth = <15>;
                                        status = "disabled";
                                ssi2: ssi@0202c000 {
                                        compatible = "fsl,imx6sl-ssi","fsl,imx21-ssi";
                                        reg = <0x0202c000 0x4000>;
-                                       interrupts = <0 47 0x04>;
+                                       interrupts = <0 47 IRQ_TYPE_LEVEL_HIGH>;
                                        clocks = <&clks IMX6SL_CLK_SSI2>;
-                                       dmas = <&sdma 41 1 0>,
-                                              <&sdma 42 1 0>;
+                                       dmas = <&sdma 41 22 0>,
+                                              <&sdma 42 22 0>;
                                        dma-names = "rx", "tx";
                                        fsl,fifo-depth = <15>;
                                        status = "disabled";
                                ssi3: ssi@02030000 {
                                        compatible = "fsl,imx6sl-ssi","fsl,imx21-ssi";
                                        reg = <0x02030000 0x4000>;
-                                       interrupts = <0 48 0x04>;
+                                       interrupts = <0 48 IRQ_TYPE_LEVEL_HIGH>;
                                        clocks = <&clks IMX6SL_CLK_SSI3>;
-                                       dmas = <&sdma 45 1 0>,
-                                              <&sdma 46 1 0>;
+                                       dmas = <&sdma 45 22 0>,
+                                              <&sdma 46 22 0>;
                                        dma-names = "rx", "tx";
                                        fsl,fifo-depth = <15>;
                                        status = "disabled";
                                        compatible = "fsl,imx6sl-uart",
                                                   "fsl,imx6q-uart", "fsl,imx21-uart";
                                        reg = <0x02034000 0x4000>;
-                                       interrupts = <0 28 0x04>;
+                                       interrupts = <0 28 IRQ_TYPE_LEVEL_HIGH>;
                                        clocks = <&clks IMX6SL_CLK_UART>,
                                                 <&clks IMX6SL_CLK_UART_SERIAL>;
                                        clock-names = "ipg", "per";
                                        compatible = "fsl,imx6sl-uart",
                                                   "fsl,imx6q-uart", "fsl,imx21-uart";
                                        reg = <0x02038000 0x4000>;
-                                       interrupts = <0 29 0x04>;
+                                       interrupts = <0 29 IRQ_TYPE_LEVEL_HIGH>;
                                        clocks = <&clks IMX6SL_CLK_UART>,
                                                 <&clks IMX6SL_CLK_UART_SERIAL>;
                                        clock-names = "ipg", "per";
                                #pwm-cells = <2>;
                                compatible = "fsl,imx6sl-pwm", "fsl,imx27-pwm";
                                reg = <0x02080000 0x4000>;
-                               interrupts = <0 83 0x04>;
+                               interrupts = <0 83 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6SL_CLK_PWM1>,
                                         <&clks IMX6SL_CLK_PWM1>;
                                clock-names = "ipg", "per";
                                #pwm-cells = <2>;
                                compatible = "fsl,imx6sl-pwm", "fsl,imx27-pwm";
                                reg = <0x02084000 0x4000>;
-                               interrupts = <0 84 0x04>;
+                               interrupts = <0 84 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6SL_CLK_PWM2>,
                                         <&clks IMX6SL_CLK_PWM2>;
                                clock-names = "ipg", "per";
                                #pwm-cells = <2>;
                                compatible = "fsl,imx6sl-pwm", "fsl,imx27-pwm";
                                reg = <0x02088000 0x4000>;
-                               interrupts = <0 85 0x04>;
+                               interrupts = <0 85 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6SL_CLK_PWM3>,
                                         <&clks IMX6SL_CLK_PWM3>;
                                clock-names = "ipg", "per";
                                #pwm-cells = <2>;
                                compatible = "fsl,imx6sl-pwm", "fsl,imx27-pwm";
                                reg = <0x0208c000 0x4000>;
-                               interrupts = <0 86 0x04>;
+                               interrupts = <0 86 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6SL_CLK_PWM4>,
                                         <&clks IMX6SL_CLK_PWM4>;
                                clock-names = "ipg", "per";
                        gpt: gpt@02098000 {
                                compatible = "fsl,imx6sl-gpt";
                                reg = <0x02098000 0x4000>;
-                               interrupts = <0 55 0x04>;
+                               interrupts = <0 55 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6SL_CLK_GPT>,
                                         <&clks IMX6SL_CLK_GPT_SERIAL>;
                                clock-names = "ipg", "per";
                        gpio1: gpio@0209c000 {
                                compatible = "fsl,imx6sl-gpio", "fsl,imx35-gpio";
                                reg = <0x0209c000 0x4000>;
-                               interrupts = <0 66 0x04 0 67 0x04>;
+                               interrupts = <0 66 IRQ_TYPE_LEVEL_HIGH>,
+                                            <0 67 IRQ_TYPE_LEVEL_HIGH>;
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
                        gpio2: gpio@020a0000 {
                                compatible = "fsl,imx6sl-gpio", "fsl,imx35-gpio";
                                reg = <0x020a0000 0x4000>;
-                               interrupts = <0 68 0x04 0 69 0x04>;
+                               interrupts = <0 68 IRQ_TYPE_LEVEL_HIGH>,
+                                            <0 69 IRQ_TYPE_LEVEL_HIGH>;
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
                        gpio3: gpio@020a4000 {
                                compatible = "fsl,imx6sl-gpio", "fsl,imx35-gpio";
                                reg = <0x020a4000 0x4000>;
-                               interrupts = <0 70 0x04 0 71 0x04>;
+                               interrupts = <0 70 IRQ_TYPE_LEVEL_HIGH>,
+                                            <0 71 IRQ_TYPE_LEVEL_HIGH>;
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
                        gpio4: gpio@020a8000 {
                                compatible = "fsl,imx6sl-gpio", "fsl,imx35-gpio";
                                reg = <0x020a8000 0x4000>;
-                               interrupts = <0 72 0x04 0 73 0x04>;
+                               interrupts = <0 72 IRQ_TYPE_LEVEL_HIGH>,
+                                            <0 73 IRQ_TYPE_LEVEL_HIGH>;
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
                        gpio5: gpio@020ac000 {
                                compatible = "fsl,imx6sl-gpio", "fsl,imx35-gpio";
                                reg = <0x020ac000 0x4000>;
-                               interrupts = <0 74 0x04 0 75 0x04>;
+                               interrupts = <0 74 IRQ_TYPE_LEVEL_HIGH>,
+                                            <0 75 IRQ_TYPE_LEVEL_HIGH>;
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
 
                        kpp: kpp@020b8000 {
                                reg = <0x020b8000 0x4000>;
-                               interrupts = <0 82 0x04>;
+                               interrupts = <0 82 IRQ_TYPE_LEVEL_HIGH>;
                        };
 
                        wdog1: wdog@020bc000 {
                                compatible = "fsl,imx6sl-wdt", "fsl,imx21-wdt";
                                reg = <0x020bc000 0x4000>;
-                               interrupts = <0 80 0x04>;
+                               interrupts = <0 80 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6SL_CLK_DUMMY>;
                        };
 
                        wdog2: wdog@020c0000 {
                                compatible = "fsl,imx6sl-wdt", "fsl,imx21-wdt";
                                reg = <0x020c0000 0x4000>;
-                               interrupts = <0 81 0x04>;
+                               interrupts = <0 81 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6SL_CLK_DUMMY>;
                                status = "disabled";
                        };
                        clks: ccm@020c4000 {
                                compatible = "fsl,imx6sl-ccm";
                                reg = <0x020c4000 0x4000>;
-                               interrupts = <0 87 0x04 0 88 0x04>;
+                               interrupts = <0 87 IRQ_TYPE_LEVEL_HIGH>,
+                                            <0 88 IRQ_TYPE_LEVEL_HIGH>;
                                #clock-cells = <1>;
                        };
 
                                             "fsl,imx6q-anatop",
                                             "syscon", "simple-bus";
                                reg = <0x020c8000 0x1000>;
-                               interrupts = <0 49 0x04 0 54 0x04 0 127 0x04>;
+                               interrupts = <0 49 IRQ_TYPE_LEVEL_HIGH>,
+                                            <0 54 IRQ_TYPE_LEVEL_HIGH>,
+                                            <0 127 IRQ_TYPE_LEVEL_HIGH>;
 
                                regulator-1p1@110 {
                                        compatible = "fsl,anatop-regulator";
                        usbphy1: usbphy@020c9000 {
                                compatible = "fsl,imx6sl-usbphy", "fsl,imx23-usbphy";
                                reg = <0x020c9000 0x1000>;
-                               interrupts = <0 44 0x04>;
+                               interrupts = <0 44 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6SL_CLK_USBPHY1>;
                        };
 
                        usbphy2: usbphy@020ca000 {
                                compatible = "fsl,imx6sl-usbphy", "fsl,imx23-usbphy";
                                reg = <0x020ca000 0x1000>;
-                               interrupts = <0 45 0x04>;
+                               interrupts = <0 45 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6SL_CLK_USBPHY2>;
                        };
 
                                snvs-rtc-lp@34 {
                                        compatible = "fsl,sec-v4.0-mon-rtc-lp";
                                        reg = <0x34 0x58>;
-                                       interrupts = <0 19 0x04 0 20 0x04>;
+                                       interrupts = <0 19 IRQ_TYPE_LEVEL_HIGH>,
+                                                    <0 20 IRQ_TYPE_LEVEL_HIGH>;
                                };
                        };
 
                        epit1: epit@020d0000 {
                                reg = <0x020d0000 0x4000>;
-                               interrupts = <0 56 0x04>;
+                               interrupts = <0 56 IRQ_TYPE_LEVEL_HIGH>;
                        };
 
                        epit2: epit@020d4000 {
                                reg = <0x020d4000 0x4000>;
-                               interrupts = <0 57 0x04>;
+                               interrupts = <0 57 IRQ_TYPE_LEVEL_HIGH>;
                        };
 
                        src: src@020d8000 {
                                compatible = "fsl,imx6sl-src", "fsl,imx51-src";
                                reg = <0x020d8000 0x4000>;
-                               interrupts = <0 91 0x04 0 96 0x04>;
+                               interrupts = <0 91 IRQ_TYPE_LEVEL_HIGH>,
+                                            <0 96 IRQ_TYPE_LEVEL_HIGH>;
                                #reset-cells = <1>;
                        };
 
                        gpc: gpc@020dc000 {
                                compatible = "fsl,imx6sl-gpc", "fsl,imx6q-gpc";
                                reg = <0x020dc000 0x4000>;
-                               interrupts = <0 89 0x04>;
+                               interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>;
                        };
 
                        gpr: iomuxc-gpr@020e0000 {
                        iomuxc: iomuxc@020e0000 {
                                compatible = "fsl,imx6sl-iomuxc";
                                reg = <0x020e0000 0x4000>;
-
-                               ecspi1 {
-                                       pinctrl_ecspi1_1: ecspi1grp-1 {
-                                               fsl,pins = <
-                                                       MX6SL_PAD_ECSPI1_MISO__ECSPI1_MISO 0x100b1
-                                                       MX6SL_PAD_ECSPI1_MOSI__ECSPI1_MOSI 0x100b1
-                                                       MX6SL_PAD_ECSPI1_SCLK__ECSPI1_SCLK 0x100b1
-                                               >;
-                                       };
-                               };
-
-                               fec {
-                                       pinctrl_fec_1: fecgrp-1 {
-                                               fsl,pins = <
-                                                       MX6SL_PAD_FEC_MDC__FEC_MDC         0x1b0b0
-                                                       MX6SL_PAD_FEC_MDIO__FEC_MDIO       0x1b0b0
-                                                       MX6SL_PAD_FEC_CRS_DV__FEC_RX_DV    0x1b0b0
-                                                       MX6SL_PAD_FEC_RXD0__FEC_RX_DATA0   0x1b0b0
-                                                       MX6SL_PAD_FEC_RXD1__FEC_RX_DATA1   0x1b0b0
-                                                       MX6SL_PAD_FEC_TX_EN__FEC_TX_EN     0x1b0b0
-                                                       MX6SL_PAD_FEC_TXD0__FEC_TX_DATA0   0x1b0b0
-                                                       MX6SL_PAD_FEC_TXD1__FEC_TX_DATA1   0x1b0b0
-                                                       MX6SL_PAD_FEC_REF_CLK__FEC_REF_OUT 0x4001b0a8
-                                               >;
-                                       };
-                               };
-
-                               uart1 {
-                                       pinctrl_uart1_1: uart1grp-1 {
-                                               fsl,pins = <
-                                                       MX6SL_PAD_UART1_RXD__UART1_RX_DATA 0x1b0b1
-                                                       MX6SL_PAD_UART1_TXD__UART1_TX_DATA 0x1b0b1
-                                               >;
-                                       };
-                               };
-
-                               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 = <
-                                                       MX6SL_PAD_SD1_CMD__SD1_CMD    0x17059
-                                                       MX6SL_PAD_SD1_CLK__SD1_CLK    0x10059
-                                                       MX6SL_PAD_SD1_DAT0__SD1_DATA0 0x17059
-                                                       MX6SL_PAD_SD1_DAT1__SD1_DATA1 0x17059
-                                                       MX6SL_PAD_SD1_DAT2__SD1_DATA2 0x17059
-                                                       MX6SL_PAD_SD1_DAT3__SD1_DATA3 0x17059
-                                                       MX6SL_PAD_SD1_DAT4__SD1_DATA4 0x17059
-                                                       MX6SL_PAD_SD1_DAT5__SD1_DATA5 0x17059
-                                                       MX6SL_PAD_SD1_DAT6__SD1_DATA6 0x17059
-                                                       MX6SL_PAD_SD1_DAT7__SD1_DATA7 0x17059
-                                               >;
-                                       };
-
-                                       pinctrl_usdhc1_1_100mhz: usdhc1grp-1-100mhz {
-                                               fsl,pins = <
-                                                       MX6SL_PAD_SD1_CMD__SD1_CMD 0x170b9
-                                                       MX6SL_PAD_SD1_CLK__SD1_CLK 0x100b9
-                                                       MX6SL_PAD_SD1_DAT0__SD1_DATA0 0x170b9
-                                                       MX6SL_PAD_SD1_DAT1__SD1_DATA1 0x170b9
-                                                       MX6SL_PAD_SD1_DAT2__SD1_DATA2 0x170b9
-                                                       MX6SL_PAD_SD1_DAT3__SD1_DATA3 0x170b9
-                                                       MX6SL_PAD_SD1_DAT4__SD1_DATA4 0x170b9
-                                                       MX6SL_PAD_SD1_DAT5__SD1_DATA5 0x170b9
-                                                       MX6SL_PAD_SD1_DAT6__SD1_DATA6 0x170b9
-                                                       MX6SL_PAD_SD1_DAT7__SD1_DATA7 0x170b9
-                                               >;
-                                       };
-
-                                       pinctrl_usdhc1_1_200mhz: usdhc1grp-1-200mhz {
-                                               fsl,pins = <
-                                                       MX6SL_PAD_SD1_CMD__SD1_CMD 0x170f9
-                                                       MX6SL_PAD_SD1_CLK__SD1_CLK 0x100f9
-                                                       MX6SL_PAD_SD1_DAT0__SD1_DATA0 0x170f9
-                                                       MX6SL_PAD_SD1_DAT1__SD1_DATA1 0x170f9
-                                                       MX6SL_PAD_SD1_DAT2__SD1_DATA2 0x170f9
-                                                       MX6SL_PAD_SD1_DAT3__SD1_DATA3 0x170f9
-                                                       MX6SL_PAD_SD1_DAT4__SD1_DATA4 0x170f9
-                                                       MX6SL_PAD_SD1_DAT5__SD1_DATA5 0x170f9
-                                                       MX6SL_PAD_SD1_DAT6__SD1_DATA6 0x170f9
-                                                       MX6SL_PAD_SD1_DAT7__SD1_DATA7 0x170f9
-                                               >;
-                                       };
-
-
-                               };
-
-                               usdhc2 {
-                                       pinctrl_usdhc2_1: usdhc2grp-1 {
-                                               fsl,pins = <
-                                                       MX6SL_PAD_SD2_CMD__SD2_CMD    0x17059
-                                                       MX6SL_PAD_SD2_CLK__SD2_CLK    0x10059
-                                                       MX6SL_PAD_SD2_DAT0__SD2_DATA0 0x17059
-                                                       MX6SL_PAD_SD2_DAT1__SD2_DATA1 0x17059
-                                                       MX6SL_PAD_SD2_DAT2__SD2_DATA2 0x17059
-                                                       MX6SL_PAD_SD2_DAT3__SD2_DATA3 0x17059
-                                               >;
-                                       };
-
-                                       pinctrl_usdhc2_1_100mhz: usdhc2grp-1-100mhz {
-                                               fsl,pins = <
-                                                       MX6SL_PAD_SD2_CMD__SD2_CMD    0x170b9
-                                                       MX6SL_PAD_SD2_CLK__SD2_CLK    0x100b9
-                                                       MX6SL_PAD_SD2_DAT0__SD2_DATA0 0x170b9
-                                                       MX6SL_PAD_SD2_DAT1__SD2_DATA1 0x170b9
-                                                       MX6SL_PAD_SD2_DAT2__SD2_DATA2 0x170b9
-                                                       MX6SL_PAD_SD2_DAT3__SD2_DATA3 0x170b9
-                                               >;
-                                       };
-
-                                       pinctrl_usdhc2_1_200mhz: usdhc2grp-1-200mhz {
-                                               fsl,pins = <
-                                                       MX6SL_PAD_SD2_CMD__SD2_CMD    0x170f9
-                                                       MX6SL_PAD_SD2_CLK__SD2_CLK    0x100f9
-                                                       MX6SL_PAD_SD2_DAT0__SD2_DATA0 0x170f9
-                                                       MX6SL_PAD_SD2_DAT1__SD2_DATA1 0x170f9
-                                                       MX6SL_PAD_SD2_DAT2__SD2_DATA2 0x170f9
-                                                       MX6SL_PAD_SD2_DAT3__SD2_DATA3 0x170f9
-                                               >;
-                                       };
-
-                               };
-
-                               usdhc3 {
-                                       pinctrl_usdhc3_1: usdhc3grp-1 {
-                                               fsl,pins = <
-                                                       MX6SL_PAD_SD3_CMD__SD3_CMD    0x17059
-                                                       MX6SL_PAD_SD3_CLK__SD3_CLK    0x10059
-                                                       MX6SL_PAD_SD3_DAT0__SD3_DATA0 0x17059
-                                                       MX6SL_PAD_SD3_DAT1__SD3_DATA1 0x17059
-                                                       MX6SL_PAD_SD3_DAT2__SD3_DATA2 0x17059
-                                                       MX6SL_PAD_SD3_DAT3__SD3_DATA3 0x17059
-                                               >;
-                                       };
-
-                                       pinctrl_usdhc3_1_100mhz: usdhc3grp-1-100mhz {
-                                               fsl,pins = <
-                                                       MX6SL_PAD_SD3_CMD__SD3_CMD    0x170b9
-                                                       MX6SL_PAD_SD3_CLK__SD3_CLK    0x100b9
-                                                       MX6SL_PAD_SD3_DAT0__SD3_DATA0 0x170b9
-                                                       MX6SL_PAD_SD3_DAT1__SD3_DATA1 0x170b9
-                                                       MX6SL_PAD_SD3_DAT2__SD3_DATA2 0x170b9
-                                                       MX6SL_PAD_SD3_DAT3__SD3_DATA3 0x170b9
-                                               >;
-                                       };
-
-                                       pinctrl_usdhc3_1_200mhz: usdhc3grp-1-200mhz {
-                                               fsl,pins = <
-                                                       MX6SL_PAD_SD3_CMD__SD3_CMD    0x170f9
-                                                       MX6SL_PAD_SD3_CLK__SD3_CLK    0x100f9
-                                                       MX6SL_PAD_SD3_DAT0__SD3_DATA0 0x170f9
-                                                       MX6SL_PAD_SD3_DAT1__SD3_DATA1 0x170f9
-                                                       MX6SL_PAD_SD3_DAT2__SD3_DATA2 0x170f9
-                                                       MX6SL_PAD_SD3_DAT3__SD3_DATA3 0x170f9
-                                               >;
-                                       };
-                               };
                        };
 
                        csi: csi@020e4000 {
                                reg = <0x020e4000 0x4000>;
-                               interrupts = <0 7 0x04>;
+                               interrupts = <0 7 IRQ_TYPE_LEVEL_HIGH>;
                        };
 
                        spdc: spdc@020e8000 {
                                reg = <0x020e8000 0x4000>;
-                               interrupts = <0 6 0x04>;
+                               interrupts = <0 6 IRQ_TYPE_LEVEL_HIGH>;
                        };
 
                        sdma: sdma@020ec000 {
                                compatible = "fsl,imx6sl-sdma", "fsl,imx35-sdma";
                                reg = <0x020ec000 0x4000>;
-                               interrupts = <0 2 0x04>;
+                               interrupts = <0 2 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6SL_CLK_SDMA>,
                                         <&clks IMX6SL_CLK_SDMA>;
                                clock-names = "ipg", "ahb";
 
                        pxp: pxp@020f0000 {
                                reg = <0x020f0000 0x4000>;
-                               interrupts = <0 98 0x04>;
+                               interrupts = <0 98 IRQ_TYPE_LEVEL_HIGH>;
                        };
 
                        epdc: epdc@020f4000 {
                                reg = <0x020f4000 0x4000>;
-                               interrupts = <0 97 0x04>;
+                               interrupts = <0 97 IRQ_TYPE_LEVEL_HIGH>;
                        };
 
                        lcdif: lcdif@020f8000 {
                                reg = <0x020f8000 0x4000>;
-                               interrupts = <0 39 0x04>;
+                               interrupts = <0 39 IRQ_TYPE_LEVEL_HIGH>;
                        };
 
                        dcp: dcp@020fc000 {
                                reg = <0x020fc000 0x4000>;
-                               interrupts = <0 99 0x04>;
+                               interrupts = <0 99 IRQ_TYPE_LEVEL_HIGH>;
                        };
                };
 
                        usbotg1: usb@02184000 {
                                compatible = "fsl,imx6sl-usb", "fsl,imx27-usb";
                                reg = <0x02184000 0x200>;
-                               interrupts = <0 43 0x04>;
+                               interrupts = <0 43 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6SL_CLK_USBOH3>;
                                fsl,usbphy = <&usbphy1>;
                                fsl,usbmisc = <&usbmisc 0>;
                        usbotg2: usb@02184200 {
                                compatible = "fsl,imx6sl-usb", "fsl,imx27-usb";
                                reg = <0x02184200 0x200>;
-                               interrupts = <0 42 0x04>;
+                               interrupts = <0 42 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6SL_CLK_USBOH3>;
                                fsl,usbphy = <&usbphy2>;
                                fsl,usbmisc = <&usbmisc 1>;
                        usbh: usb@02184400 {
                                compatible = "fsl,imx6sl-usb", "fsl,imx27-usb";
                                reg = <0x02184400 0x200>;
-                               interrupts = <0 40 0x04>;
+                               interrupts = <0 40 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6SL_CLK_USBOH3>;
                                fsl,usbmisc = <&usbmisc 2>;
                                status = "disabled";
                        fec: ethernet@02188000 {
                                compatible = "fsl,imx6sl-fec", "fsl,imx25-fec";
                                reg = <0x02188000 0x4000>;
-                               interrupts = <0 114 0x04>;
+                               interrupts = <0 114 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6SL_CLK_ENET_REF>,
                                         <&clks IMX6SL_CLK_ENET_REF>;
                                clock-names = "ipg", "ahb";
                        usdhc1: usdhc@02190000 {
                                compatible = "fsl,imx6sl-usdhc", "fsl,imx6q-usdhc";
                                reg = <0x02190000 0x4000>;
-                               interrupts = <0 22 0x04>;
+                               interrupts = <0 22 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6SL_CLK_USDHC1>,
                                         <&clks IMX6SL_CLK_USDHC1>,
                                         <&clks IMX6SL_CLK_USDHC1>;
                        usdhc2: usdhc@02194000 {
                                compatible = "fsl,imx6sl-usdhc", "fsl,imx6q-usdhc";
                                reg = <0x02194000 0x4000>;
-                               interrupts = <0 23 0x04>;
+                               interrupts = <0 23 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6SL_CLK_USDHC2>,
                                         <&clks IMX6SL_CLK_USDHC2>,
                                         <&clks IMX6SL_CLK_USDHC2>;
                        usdhc3: usdhc@02198000 {
                                compatible = "fsl,imx6sl-usdhc", "fsl,imx6q-usdhc";
                                reg = <0x02198000 0x4000>;
-                               interrupts = <0 24 0x04>;
+                               interrupts = <0 24 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6SL_CLK_USDHC3>,
                                         <&clks IMX6SL_CLK_USDHC3>,
                                         <&clks IMX6SL_CLK_USDHC3>;
                        usdhc4: usdhc@0219c000 {
                                compatible = "fsl,imx6sl-usdhc", "fsl,imx6q-usdhc";
                                reg = <0x0219c000 0x4000>;
-                               interrupts = <0 25 0x04>;
+                               interrupts = <0 25 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6SL_CLK_USDHC4>,
                                         <&clks IMX6SL_CLK_USDHC4>,
                                         <&clks IMX6SL_CLK_USDHC4>;
                                #size-cells = <0>;
                                compatible = "fsl,imx6sl-i2c", "fsl,imx21-i2c";
                                reg = <0x021a0000 0x4000>;
-                               interrupts = <0 36 0x04>;
+                               interrupts = <0 36 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6SL_CLK_I2C1>;
                                status = "disabled";
                        };
                                #size-cells = <0>;
                                compatible = "fsl,imx6sl-i2c", "fsl,imx21-i2c";
                                reg = <0x021a4000 0x4000>;
-                               interrupts = <0 37 0x04>;
+                               interrupts = <0 37 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6SL_CLK_I2C2>;
                                status = "disabled";
                        };
                                #size-cells = <0>;
                                compatible = "fsl,imx6sl-i2c", "fsl,imx21-i2c";
                                reg = <0x021a8000 0x4000>;
-                               interrupts = <0 38 0x04>;
+                               interrupts = <0 38 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6SL_CLK_I2C3>;
                                status = "disabled";
                        };
 
                        rngb: rngb@021b4000 {
                                reg = <0x021b4000 0x4000>;
-                               interrupts = <0 5 0x04>;
+                               interrupts = <0 5 IRQ_TYPE_LEVEL_HIGH>;
                        };
 
                        weim: weim@021b8000 {
                                reg = <0x021b8000 0x4000>;
-                               interrupts = <0 14 0x04>;
+                               interrupts = <0 14 IRQ_TYPE_LEVEL_HIGH>;
                        };
 
                        ocotp: ocotp@021bc000 {
index 0f06f8687b0bb46581be1b75dce84a4f93e303e5..88e3d477bf16394b0f789d855cabea0ae6217b9e 100644 (file)
                reg = <0x10000000 0x200>;
        };
 
+       ebi@12000000 {
+               compatible = "arm,external-bus-interface";
+               reg = <0x12000000 0x100>;
+       };
+
        timer@13000000 {
                reg = <0x13000000 0x100>;
                interrupt-parent = <&pic>;
index 650ef30e1856f9591f32a445f279489c82b22b68..e4e1968dfca8abe05defd5ebe6ced71cbe88df95 100644 (file)
@@ -97,6 +97,8 @@
                        reg = <0x90000 0x200>;
                        interrupts = <28>;
                        clocks = <&gate_clk 4>;
+                       pinctrl-0 = <&pmx_sdio>;
+                       pinctrl-names = "default";
                        bus-width = <4>;
                        cap-sdio-irq;
                        cap-sd-highspeed;
index 3933a331ddc2ed8d8f71b58c4cc7389e7e860220..f010c21220bf8dd485cb1dd3cdee0f881223b23f 100644 (file)
                        reg = <0x90000 0x200>;
                        interrupts = <28>;
                        clocks = <&gate_clk 4>;
+                       pinctrl-0 = <&pmx_sdio>;
+                       pinctrl-names = "default";
                        bus-width = <4>;
                        cap-sdio-irq;
                        cap-sd-highspeed;
index 142b9cd3b4541d9fbc8205ad2770c2084a6dfee3..bb4df405527c825b8dbfb7df8ba3c5330f8163c0 100644 (file)
@@ -66,8 +66,8 @@
 
                button@1 {
                        label = "Power push button";
-                       linux,code = <116>;
-                       gpios = <&gpio0 16 1>;
+                       linux,code = <KEY_POWER>;
+                       gpios = <&gpio0 16 GPIO_ACTIVE_LOW>;
                };
        };
 
 
                red-fail {
                        label = "cloudbox:red:fail";
-                       gpios = <&gpio0 14 0>;
+                       gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>;
                };
                blue-sata {
                        label = "cloudbox:blue:sata";
-                       gpios = <&gpio0 15 0>;
+                       gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>;
                };
        };
 
        gpio_poweroff {
                compatible = "gpio-poweroff";
-               gpios = <&gpio0 17 0>;
+               gpios = <&gpio0 17 GPIO_ACTIVE_HIGH>;
        };
 };
 
index 053aa20fb30f88a0e13be1878e9d9d6ba241c4c2..afebc157031828ddd850a6186cbdfb5e6e42b869 100644 (file)
@@ -51,8 +51,8 @@
                mvsdio@90000 {
                        pinctrl-0 = <&pmx_sdio_gpios>;
                        pinctrl-names = "default";
-                       wp-gpios = <&gpio1 5 0>;
-                       cd-gpios = <&gpio1 6 0>;
+                       wp-gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>;
+                       cd-gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>;
                        status = "okay";
                };
        };
index e112ca62d978e9ccdedfb37d06bec0b8fe036de8..bf7fe8ab88f4353d0e1688d7fdf8cbd9718e1f7e 100644 (file)
 
                blue-power {
                        label = "dns320:blue:power";
-                       gpios = <&gpio0 26 1>; /* GPIO 26 Active Low */
-                       linux,default-trigger = "default-on";
+                       gpios = <&gpio0 26 GPIO_ACTIVE_LOW>;
+                       default-state = "keep";
                };
                blue-usb {
                        label = "dns320:blue:usb";
-                       gpios = <&gpio1 11 1>; /* GPIO 43 Active Low */
+                       gpios = <&gpio1 11 GPIO_ACTIVE_LOW>;
                };
                orange-l_hdd {
                        label = "dns320:orange:l_hdd";
-                       gpios = <&gpio0 28 1>; /* GPIO 28 Active Low */
+                       gpios = <&gpio0 28 GPIO_ACTIVE_LOW>;
                };
                orange-r_hdd {
                        label = "dns320:orange:r_hdd";
-                       gpios = <&gpio0 27 1>; /* GPIO 27 Active Low */
+                       gpios = <&gpio0 27 GPIO_ACTIVE_LOW>;
                };
                orange-usb {
                        label = "dns320:orange:usb";
-                       gpios = <&gpio1 3 1>; /* GPIO 35 Active Low */
+                       gpios = <&gpio1 3 GPIO_ACTIVE_LOW>; /* GPIO 35 */
                };
        };
 
index 5119fb8a8eb6203c5743294246bdd62731da7523..cb9978c652f2d1635b762e5aa3ef09097aa0b79e 100644 (file)
 
                white-power {
                        label = "dns325:white:power";
-                       gpios = <&gpio0 26 1>; /* GPIO 26 Active Low */
-                       linux,default-trigger = "default-on";
+                       gpios = <&gpio0 26 GPIO_ACTIVE_LOW>;
+                       default-state = "keep";
                };
                white-usb {
                        label = "dns325:white:usb";
-                       gpios = <&gpio1 11 1>; /* GPIO 43 Active Low */
+                       gpios = <&gpio1 11 GPIO_ACTIVE_LOW>; /* GPIO 43 */
                };
                red-l_hdd {
                        label = "dns325:red:l_hdd";
-                       gpios = <&gpio0 28 1>; /* GPIO 28 Active Low */
+                       gpios = <&gpio0 28 GPIO_ACTIVE_LOW>;
                };
                red-r_hdd {
                        label = "dns325:red:r_hdd";
-                       gpios = <&gpio0 27 1>; /* GPIO 27 Active Low */
+                       gpios = <&gpio0 27 GPIO_ACTIVE_LOW>;
                };
                red-usb {
                        label = "dns325:red:usb";
-                       gpios = <&gpio0 29 1>; /* GPIO 29 Active Low */
+                       gpios = <&gpio0 29 GPIO_ACTIVE_LOW>;
                };
        };
 
index aefa375a550d3ac0e7615cd76ba50e83c99ac094..12087566ac6de1ba640f8875390ec125c5dec7a1 100644 (file)
 
                button@1 {
                        label = "Power button";
-                       linux,code = <116>;
-                       gpios = <&gpio1 2 1>;
+                       linux,code = <KEY_POWER>;
+                       gpios = <&gpio1 2 GPIO_ACTIVE_LOW>;
                };
                button@2 {
                        label = "USB unmount button";
-                       linux,code = <161>;
-                       gpios = <&gpio1 15 1>;
+                       linux,code = <KEY_EJECTCD>;
+                       gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
                };
                button@3 {
                        label = "Reset button";
-                       linux,code = <0x198>;
-                       gpios = <&gpio1 16 1>;
+                       linux,code = <KEY_RESTART>;
+                       gpios = <&gpio1 16 GPIO_ACTIVE_LOW>;
                };
        };
 
@@ -35,8 +35,8 @@
                compatible = "gpio-fan";
                pinctrl-0 = <&pmx_fan_high_speed &pmx_fan_low_speed>;
                pinctrl-names = "default";
-               gpios = <&gpio1 14 1
-                        &gpio1 13 1>;
+               gpios = <&gpio1 14 GPIO_ACTIVE_LOW
+                        &gpio1 13 GPIO_ACTIVE_LOW>;
                gpio-fan,speed-map = <0    0
                                      3000 1
                                      6000 2>;
@@ -46,7 +46,7 @@
                compatible = "gpio-poweroff";
                pinctrl-0 = <&pmx_power_off>;
                pinctrl-names = "default";
-               gpios = <&gpio1 4 0>;
+               gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>;
        };
 
        ocp@f1000000 {
index 33ff368fbfa5696353353fc5151b4fefd7cc6198..2a41c75c5c21f4118a8db5662602452632c84eeb 100644 (file)
 
                health {
                        label = "status:green:health";
-                       gpios = <&gpio1 14 1>;
-                       linux,default-trigger = "default-on";
+                       gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
+                       default-state = "keep";
                };
                fault {
                        label = "status:orange:fault";
-                       gpios = <&gpio1 15 1>;
+                       gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
                };
        };
        regulators {
index 6f62af99c9cbebe4da42d000c6ae28c34054e52f..a7558375e06f15ec08a3194145314edb11964072 100644 (file)
 
                bluetooth {
                        label = "dreamplug:blue:bluetooth";
-                       gpios = <&gpio1 15 1>;
+                       gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
                };
                wifi {
                        label = "dreamplug:green:wifi";
-                       gpios = <&gpio1 16 1>;
+                       gpios = <&gpio1 16 GPIO_ACTIVE_LOW>;
                };
                wifi-ap {
                        label = "dreamplug:green:wifi_ap";
-                       gpios = <&gpio1 17 1>;
+                       gpios = <&gpio1 17 GPIO_ACTIVE_LOW>;
                };
        };
 };
index a43bebb251102fbbfcde84e58f1955ce52f5de5b..c2e512953570a729717999f046924496fc2aa223 100644 (file)
 
                health {
                        label = "status:green:health";
-                       gpios = <&gpio1 14 1>;
-                       linux,default-trigger = "default-on";
+                       gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
+                       default-state = "keep";
                };
                fault {
                        label = "status:orange:fault";
-                       gpios = <&gpio1 15 1>;
+                       gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
                };
                left0 {
                        label = "status:white:left0";
-                       gpios = <&gpio1 10 0>;
+                       gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>;
                };
                left1 {
                        label = "status:white:left1";
-                       gpios = <&gpio1 11 0>;
+                       gpios = <&gpio1 11 GPIO_ACTIVE_HIGH>;
                };
                left2 {
                        label = "status:white:left2";
-                       gpios = <&gpio1 12 0>;
+                       gpios = <&gpio1 12 GPIO_ACTIVE_HIGH>;
                };
                left3 {
                        label = "status:white:left3";
-                       gpios = <&gpio1 13 0>;
+                       gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
                };
                right0 {
                        label = "status:white:right0";
-                       gpios = <&gpio1 6 0>;
+                       gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>;
                };
                right1 {
                        label = "status:white:right1";
-                       gpios = <&gpio1 7 0>;
+                       gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
                };
                right2 {
                        label = "status:white:right2";
-                       gpios = <&gpio1 8 0>;
+                       gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>;
                };
                right3 {
                        label = "status:white:right3";
-                       gpios = <&gpio1 9 0>;
+                       gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>;
                };
        };
        regulators {
                        enable-active-high;
                        regulator-always-on;
                        regulator-boot-on;
-                       gpio = <&gpio0 29 0>;
+                       gpio = <&gpio0 29 GPIO_ACTIVE_HIGH>;
                };
        };
 };
index d30a91a5047d6939c2dfdd69989bde39c359f9b7..0b557d5cb723823ddce68e5261488c2e815bd45a 100644 (file)
                        nr-ports = <1>;
                };
 
+               /* AzureWave AW-GH381 WiFi/BT */
                mvsdio@90000 {
                        status = "okay";
-                       /* No CD or WP GPIOs */
-                       broken-cd;
+                       non-removable;
                };
        };
 
 
                health-r {
                        label = "guruplug:red:health";
-                       gpios = <&gpio1 14 1>;
+                       gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
                };
                health-g {
                        label = "guruplug:green:health";
-                       gpios = <&gpio1 15 1>;
+                       gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
                };
                wmode-r {
                        label = "guruplug:red:wmode";
-                       gpios = <&gpio1 16 1>;
+                       gpios = <&gpio1 16 GPIO_ACTIVE_LOW>;
                };
                wmode-g {
                        label = "guruplug:green:wmode";
-                       gpios = <&gpio1 17 1>;
+                       gpios = <&gpio1 17 GPIO_ACTIVE_LOW>;
                };
        };
 };
index c5fb02f7ebc3e33107ac067d46a6394d6c21b27d..6ccc78866e6dc97b14884c521eb7b93ec9c5a942 100644 (file)
 
                button@1 {
                        label = "USB Copy";
-                       linux,code = <133>;
-                       gpios = <&gpio0 29 1>;
+                       linux,code = <KEY_COPY>;
+                       gpios = <&gpio0 29 GPIO_ACTIVE_LOW>;
                };
                button@2 {
                        label = "Reset";
-                       linux,code = <0x198>;
-                       gpios = <&gpio0 28 1>;
+                       linux,code = <KEY_RESTART>;
+                       gpios = <&gpio0 28 GPIO_ACTIVE_LOW>;
                };
        };
 
 
                green-os {
                        label = "ib62x0:green:os";
-                       gpios = <&gpio0 25 0>;
-                       linux,default-trigger = "default-on";
+                       gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>;
+                       default-state = "keep";
                };
                red-os {
                        label = "ib62x0:red:os";
-                       gpios = <&gpio0 22 0>;
+                       gpios = <&gpio0 22 GPIO_ACTIVE_HIGH>;
                };
                usb-copy {
                        label = "ib62x0:red:usb_copy";
-                       gpios = <&gpio0 27 0>;
+                       gpios = <&gpio0 27 GPIO_ACTIVE_HIGH>;
                };
        };
 
@@ -98,7 +98,7 @@
                compatible = "gpio-poweroff";
                pinctrl-0 = <&pmx_power_off>;
                pinctrl-names = "default";
-               gpios = <&gpio0 24 0>;
+               gpios = <&gpio0 24 GPIO_ACTIVE_HIGH>;
        };
 };
 
index 4a62b206f680b4c1261a404ce16ce26fb498f6c0..f7636291de77bbec296f632c528bebd7303d7ec4 100644 (file)
 
                led-level {
                        label = "led_level";
-                       gpios = <&gpio1 9 0>;
-                       linux,default-trigger = "default-on";
+                       gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>;
+                       default-state = "on";
                };
                power-blue {
                        label = "power:blue";
-                       gpios = <&gpio1 10 0>;
-                       linux,default-trigger = "timer";
+                       gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>;
+                       default-state = "keep";
                };
                power-red {
                        label = "power:red";
-                       gpios = <&gpio1 11 0>;
+                       gpios = <&gpio1 11 GPIO_ACTIVE_HIGH>;
                };
                usb1 {
                        label = "usb1:blue";
-                       gpios = <&gpio1 12 0>;
+                       gpios = <&gpio1 12 GPIO_ACTIVE_HIGH>;
                };
                usb2 {
                        label = "usb2:blue";
-                       gpios = <&gpio1 13 0>;
+                       gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
                };
                usb3 {
                        label = "usb3:blue";
-                       gpios = <&gpio1 14 0>;
+                       gpios = <&gpio1 14 GPIO_ACTIVE_HIGH>;
                };
                usb4 {
                        label = "usb4:blue";
-                       gpios = <&gpio1 15 0>;
+                       gpios = <&gpio1 15 GPIO_ACTIVE_HIGH>;
                };
                otb {
                        label = "otb:blue";
-                       gpios = <&gpio1 16 0>;
+                       gpios = <&gpio1 16 GPIO_ACTIVE_HIGH>;
                };
        };
 
 
                button@1 {
                        label = "OTB Button";
-                       linux,code = <133>;
-                       gpios = <&gpio1 3 1>;
+                       linux,code = <KEY_COPY>;
+                       gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;
                        debounce-interval = <100>;
                };
                button@2 {
                        label = "Reset";
-                       linux,code = <0x198>;
-                       gpios = <&gpio0 12 1>;
+                       linux,code = <KEY_RESTART>;
+                       gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
                        debounce-interval = <100>;
                };
        };
index d15395d671ededf4caf501518bb1e33ffba0cba8..589000631b5a581e23a9afa8b469c2c513e7ff59 100644 (file)
 
                power_led {
                        label = "status:white:power_led";
-                       gpios = <&gpio0 16 0>;
-                       linux,default-trigger = "default-on";
+                       gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>;
+                       default-state = "keep";
                };
                rebuild_led {
                        label = "status:white:rebuild_led";
-                       gpios = <&gpio1 4 0>;
+                       gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>;
                };
                health_led {
                        label = "status:red:health_led";
-                       gpios = <&gpio1 5 0>;
+                       gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>;
                };
                backup_led {
                        label = "status:blue:backup_led";
-                       gpios = <&gpio0 15 0>;
+                       gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>;
                };
        };
        gpio-keys {
 
                Power {
                        label = "Power Button";
-                       linux,code = <116>;
-                       gpios = <&gpio0 14 1>;
+                       linux,code = <KEY_POWER>;
+                       gpios = <&gpio0 14 GPIO_ACTIVE_LOW>;
                };
                Reset {
                        label = "Reset Button";
-                       linux,code = <0x198>;
-                       gpios = <&gpio0 12 1>;
+                       linux,code = <KEY_RESTART>;
+                       gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
                };
                OTB {
                        label = "OTB Button";
-                       linux,code = <133>;
-                       gpios = <&gpio1 3 1>;
+                       linux,code = <KEY_COPY>;
+                       gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;
                };
        };
 };
index cd44f37e54b5b7fb81f6c53f966abc9e3e511c8e..5b5808ebc6e0771a521ac9e4e72eac78149149df 100644 (file)
@@ -38,8 +38,8 @@
 
        i2c@0 {
                compatible = "i2c-gpio";
-               gpios = < &gpio0 8 0            /* sda */
-                       &gpio0 9 0 >;           /* scl */
+               gpios = < &gpio0 8 GPIO_ACTIVE_HIGH             /* sda */
+                         &gpio0 9 GPIO_ACTIVE_HIGH>;           /* scl */
                i2c-gpio,delay-us = <2>;        /* ~100 kHz */
        };
 };
index 4e8f9e42c5929135e05109142bcec7100ed83d02..fc1cd3b7b9687c190fc27122cee71aabc2dd8208 100644 (file)
 
                button@1 {
                        label = "Function Button";
-                       linux,code = <357>;
-                       gpios = <&gpio1 9 1>;
+                       linux,code = <KEY_OPTION>;
+                       gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
                };
                button@2 {
                        label = "Power-on Switch";
-                       linux,code = <0>;
+                       linux,code = <KEY_RESERVED>;
                        linux,input-type = <5>;
-                       gpios = <&gpio1 10 1>;
+                       gpios = <&gpio1 10 GPIO_ACTIVE_LOW>;
                };
                button@3 {
                        label = "Power-auto Switch";
-                       linux,code = <1>;
+                       linux,code = <KEY_ESC>;
                        linux,input-type = <5>;
-                       gpios = <&gpio1 11 1>;
+                       gpios = <&gpio1 11 GPIO_ACTIVE_LOW>;
                };
        };
 
 
                led@1 {
                        label = "lsxl:blue:func";
-                       gpios = <&gpio1 4 1>;
+                       gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
                };
 
                led@2 {
                        label = "lsxl:red:alarm";
-                       gpios = <&gpio1 5 1>;
+                       gpios = <&gpio1 5 GPIO_ACTIVE_LOW>;
                };
 
                led@3 {
                        label = "lsxl:amber:info";
-                       gpios = <&gpio1 6 1>;
+                       gpios = <&gpio1 6 GPIO_ACTIVE_LOW>;
                };
 
                led@4 {
                        label = "lsxl:blue:power";
-                       gpios = <&gpio1 7 1>;
-                       linux,default-trigger = "default-on";
+                       gpios = <&gpio1 7 GPIO_ACTIVE_LOW>;
+                       default-state = "keep";
                };
 
                led@5 {
                        label = "lsxl:red:func";
-                       gpios = <&gpio1 16 1>;
+                       gpios = <&gpio1 16 GPIO_ACTIVE_LOW>;
                };
        };
 
                compatible = "gpio-fan";
                pinctrl-0 = <&pmx_fan_low &pmx_fan_high &pmx_fan_lock>;
                pinctrl-names = "default";
-               gpios = <&gpio0 19 1
-                        &gpio0 18 1>;
+               gpios = <&gpio0 19 GPIO_ACTIVE_LOW
+                        &gpio0 18 GPIO_ACTIVE_LOW>;
                gpio-fan,speed-map = <0    3
                                      1500 2
                                      3250 1
                                      5000 0>;
-               alarm-gpios = <&gpio1 8 0>;
+               alarm-gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>;
        };
 
        restart_poweroff {
index 6c1ec2786e6e2f77c334292bab84b4e24d4cfef6..c20607cd7d7c774d7819b6cb2aba522cc2bad3eb 100644 (file)
                        pinctrl-0 = <&pmx_sdio &pmx_sdio_cd>;
                        pinctrl-names = "default";
                        status = "okay";
-                       cd-gpios = <&gpio1 15 1>;
+                       cd-gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
                        /* No WP GPIO */
                };
        };
 
                health {
                        label = "status:green:health";
-                       gpios = <&gpio0 7 1>;
+                       gpios = <&gpio0 7 GPIO_ACTIVE_LOW>;
                };
 
                user1o {
                        label = "user1:orange";
-                       gpios = <&gpio1 8 1>;
+                       gpios = <&gpio1 8 GPIO_ACTIVE_LOW>;
                        default-state = "on";
                };
 
                user1g {
                        label = "user1:green";
-                       gpios = <&gpio1 9 1>;
+                       gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
                        default-state = "on";
                };
 
                user0o {
                        label = "user0:orange";
-                       gpios = <&gpio1 12 1>;
+                       gpios = <&gpio1 12 GPIO_ACTIVE_LOW>;
                        default-state = "on";
                };
 
                user0g {
                        label = "user0:green";
-                       gpios = <&gpio1 13 1>;
+                       gpios = <&gpio1 13 GPIO_ACTIVE_LOW>;
                        default-state = "on";
                };
 
                misc {
                        label = "status:orange:misc";
-                       gpios = <&gpio1 14 1>;
+                       gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
                        default-state = "on";
                };
 
index 6317e1d088b3e16b89df5e9620c19f053ac34451..dc86429756d79787a780946668e2a80cd50fa893 100644 (file)
 
                green-status {
                        label = "gtw:green:Status";
-                       gpios = <&gpio0 20 0>;
+                       gpios = <&gpio0 20 GPIO_ACTIVE_HIGH>;
                };
 
                red-status {
                        label = "gtw:red:Status";
-                       gpios = <&gpio0 21 0>;
+                       gpios = <&gpio0 21 GPIO_ACTIVE_HIGH>;
                };
 
                green-usb {
                        label = "gtw:green:USB";
-                       gpios = <&gpio0 12 0>;
+                       gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>;
                };
        };
 
 
                button@1 {
                        label = "SWR Button";
-                       linux,code = <0x198>; /* KEY_RESTART */
-                       gpios = <&gpio1 15 1>;
+                       linux,code = <KEY_RESTART>;
+                       gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
                };
                button@2 {
                        label = "WPS Button";
-                       linux,code = <0x211>; /* KEY_WPS_BUTTON */
-                       gpios = <&gpio1 14 1>;
+                       linux,code = <KEY_WPS_BUTTON>;
+                       gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
                };
        };
 };
index e6a102cf424cd646d9e121acd2b821ea46bb81be..4d2a8db9ab77b40b1145c84e5209960efa7cb7ce 100644 (file)
@@ -1,3 +1,14 @@
+/*
+ * Device Tree file for NETGEAR ReadyNAS Duo v2
+ *
+ * Copyright (C) 2013, Arnaud EBALARD <arno@natisbad.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.
+ */
+
 /dts-v1/;
 
 #include "kirkwood.dtsi"
                                marvell,pins = "mpp47";
                                marvell,function = "gpio";
                        };
+
                        pmx_button_backup: pmx-button-backup {
                                marvell,pins = "mpp45";
                                marvell,function = "gpio";
                        };
+
                        pmx_button_reset: pmx-button-reset {
                                marvell,pins = "mpp13";
                                marvell,function = "gpio";
                        };
+
                        pmx_led_blue_power: pmx-led-blue-power {
                                marvell,pins = "mpp31";
                                marvell,function = "gpio";
                        };
+
                        pmx_led_blue_activity: pmx-led-blue-activity {
                                marvell,pins = "mpp38";
                                marvell,function = "gpio";
                        };
+
                        pmx_led_blue_disk1: pmx-led-blue-disk1 {
                                marvell,pins = "mpp23";
                                marvell,function = "gpio";
                        };
+
                        pmx_led_blue_disk2: pmx-led-blue-disk2 {
                                marvell,pins = "mpp22";
                                marvell,function = "gpio";
                        };
+
                        pmx_led_blue_backup: pmx-led-blue-backup {
                                marvell,pins = "mpp29";
                                marvell,function = "gpio";
                        };
+
+                       pmx_poweroff: pmx-poweroff {
+                               marvell,pins = "mpp30";
+                               marvell,function = "gpio";
+                       };
                };
 
                clocks {
-                      #address-cells = <1>;
-                      #size-cells = <0>;
-
-                      g762_clk: fixedclk {
+                      g762_clk: g762-oscillator {
                                 compatible = "fixed-clock";
                                 #clock-cells = <0>;
                                 clock-frequency = <8192>;
 
                power_led {
                        label = "status:blue:power_led";
-                       gpios = <&gpio0 31 1>;   /* GPIO 31 Active Low */
-                       linux,default-trigger = "default-on";
+                       gpios = <&gpio0 31 GPIO_ACTIVE_LOW>;
+                       default-state = "keep";
                };
+
                activity_led {
                        label = "status:blue:activity_led";
-                       gpios = <&gpio1 6 1>;    /* GPIO 38 Active Low */
+                       gpios = <&gpio1 6 GPIO_ACTIVE_LOW>;
                };
+
                disk1_led {
                        label = "status:blue:disk1_led";
-                       gpios = <&gpio0 23 1>;   /* GPIO 23 Active Low */
+                       gpios = <&gpio0 23 GPIO_ACTIVE_LOW>;
                };
+
                disk2_led {
                        label = "status:blue:disk2_led";
-                       gpios = <&gpio0 22 1>;   /* GPIO 22 Active Low */
+                       gpios = <&gpio0 22 GPIO_ACTIVE_LOW>;
                };
+
                backup_led {
                        label = "status:blue:backup_led";
-                       gpios = <&gpio0 29 1>;   /* GPIO 29 Active Low*/
+                       gpios = <&gpio0 29 GPIO_ACTIVE_LOW>;
                };
        };
 
-       gpio_keys {
+       gpio-keys {
                compatible = "gpio-keys";
-               #address-cells = <1>;
-               #size-cells = <0>;
                pinctrl-0 = <&pmx_button_power &pmx_button_backup
                             &pmx_button_reset>;
                pinctrl-names = "default";
 
-               button@1 {
+               power-button {
                        label = "Power Button";
-                       linux,code = <116>;     /* KEY_POWER */
-                       gpios = <&gpio1 15 1>;
+                       linux,code = <KEY_POWER>;
+                       gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
                };
-               button@2 {
+
+               reset-button {
                        label = "Reset Button";
-                       linux,code = <0x198>;   /* KEY_RESTART */
-                       gpios = <&gpio0 13 1>;
+                       linux,code = <KEY_RESTART>;
+                       gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
                };
-               button@3 {
+
+               backup-button {
                        label = "Backup Button";
-                       linux,code = <133>;     /* KEY_COPY */
-                       gpios = <&gpio1 13 1>;
+                       linux,code = <KEY_COPY>;
+                       gpios = <&gpio1 13 GPIO_ACTIVE_LOW>;
                };
        };
 
-        regulators {
-                compatible = "simple-bus";
-                #address-cells = <1>;
-                #size-cells = <0>;
-
-                usb_power: regulator@1 {
-                        compatible = "regulator-fixed";
-                        reg = <1>;
-                        regulator-name = "USB 3.0 Power";
-                        regulator-min-microvolt = <5000000>;
-                        regulator-max-microvolt = <5000000>;
-                        enable-active-high;
-                        regulator-always-on;
-                        regulator-boot-on;
-                        gpio = <&gpio1 14 0>;
-                };
-        };
+       gpio-poweroff {
+               compatible = "gpio-poweroff";
+               pinctrl-0 = <&pmx_poweroff>;
+               pinctrl-names = "default";
+               gpios = <&gpio0 30 GPIO_ACTIVE_LOW>;
+       };
+
+       regulators {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               usb3_regulator: usb3-regulator {
+                       compatible = "regulator-fixed";
+                       reg = <1>;
+                       regulator-name = "USB 3.0 Power";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       enable-active-high;
+                       regulator-always-on;
+                       regulator-boot-on;
+                       gpio = <&gpio1 14 GPIO_ACTIVE_HIGH>;
+               };
+       };
 };
 
 &nand {
 &mdio {
        status = "okay";
 
-       ethphy0: ethernet-phy@0 {
+       ethphy0: ethernet-phy@0 { /* Marvell 88E1318 */
                device_type = "ethernet-phy";
                reg = <0>;
        };
diff --git a/arch/arm/boot/dts/kirkwood-netgear_readynas_nv+_v2.dts b/arch/arm/boot/dts/kirkwood-netgear_readynas_nv+_v2.dts
new file mode 100644 (file)
index 0000000..7c8a0d9
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+ * Device Tree file for NETGEAR ReadyNAS NV+ v2
+ *
+ * Copyright (C) 2013, Arnaud EBALARD <arno@natisbad.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.
+ */
+
+/dts-v1/;
+
+#include "kirkwood.dtsi"
+#include "kirkwood-6282.dtsi"
+
+/ {
+       model = "NETGEAR ReadyNAS NV+ v2";
+       compatible = "netgear,readynas-nv+-v2", "netgear,readynas", "marvell,kirkwood-88f6282", "marvell,kirkwood";
+
+       memory { /* 256 MB */
+               device_type = "memory";
+               reg = <0x00000000 0x10000000>;
+       };
+
+       chosen {
+               bootargs = "console=ttyS0,115200n8 earlyprintk";
+       };
+
+       mbus {
+               pcie-controller {
+                       status = "okay";
+
+                       /* Connected to NEC uPD720200 USB 3.0 controller */
+                       pcie@1,0 {
+                               /* Port 0, Lane 0 */
+                               status = "okay";
+                       };
+               };
+       };
+
+       ocp@f1000000 {
+               pinctrl: pinctrl@10000 {
+                       pmx_button_power: pmx-button-power {
+                               marvell,pins = "mpp47";
+                               marvell,function = "gpio";
+                       };
+
+                       pmx_button_backup: pmx-button-backup {
+                               marvell,pins = "mpp45";
+                               marvell,function = "gpio";
+                       };
+
+                       pmx_button_reset: pmx-button-reset {
+                               marvell,pins = "mpp13";
+                               marvell,function = "gpio";
+                       };
+
+                       pmx_led_blue_power: pmx-led-blue-power {
+                               marvell,pins = "mpp31";
+                               marvell,function = "gpio";
+                       };
+
+                       pmx_led_blue_backup: pmx-led-blue-backup {
+                               marvell,pins = "mpp22";
+                               marvell,function = "gpio";
+                       };
+
+                       pmx_led_blue_disk1: pmx-led-blue-disk1 {
+                               marvell,pins = "mpp20";
+                               marvell,function = "gpio";
+                       };
+
+                       pmx_led_blue_disk2: pmx-led-blue-disk2 {
+                               marvell,pins = "mpp23";
+                               marvell,function = "gpio";
+                       };
+
+                       pmx_led_blue_disk3: pmx-led-blue-disk3 {
+                               marvell,pins = "mpp24";
+                               marvell,function = "gpio";
+                       };
+
+                       pmx_led_blue_disk4: pmx-led-blue-disk4 {
+                               marvell,pins = "mpp29";
+                               marvell,function = "gpio";
+                       };
+
+                       pmx_poweroff: pmx-poweroff {
+                               marvell,pins = "mpp30";
+                               marvell,function = "gpio";
+                       };
+               };
+
+               clocks {
+                      g762_clk: g762-oscillator {
+                                compatible = "fixed-clock";
+                                #clock-cells = <0>;
+                                clock-frequency = <8192>;
+                      };
+               };
+
+               i2c@11000 {
+                       status = "okay";
+
+                       rs5c372a: rs5c372a@32 {
+                               compatible = "ricoh,rs5c372a";
+                               reg = <0x32>;
+                       };
+
+                       g762: g762@3e {
+                               compatible = "gmt,g762";
+                               reg = <0x3e>;
+                               clocks = <&g762_clk>; /* input clock */
+                               fan_gear_mode = <0>;
+                               fan_startv = <1>;
+                               pwm_polarity = <0>;
+                       };
+               };
+
+               serial@12000 {
+                       pinctrl-0 = <&pmx_uart0>;
+                       pinctrl-names = "default";
+                       status = "okay";
+               };
+
+               sata@80000 { /* Connected to Marvell 88SM4140 SATA port multiplier */
+                       status = "okay";
+                       nr-ports = <1>;
+               };
+       };
+
+       gpio-leds {
+               compatible = "gpio-leds";
+               pinctrl-0 = < &pmx_led_blue_power &pmx_led_blue_backup
+                             &pmx_led_blue_disk1 &pmx_led_blue_disk2
+                             &pmx_led_blue_disk3 &pmx_led_blue_disk3 >;
+               pinctrl-names = "default";
+
+               power_led {
+                       label = "status:blue:power_led";
+                       gpios = <&gpio0 31 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "default-on";
+               };
+
+               backup_led {
+                       label = "status:blue:backup_led";
+                       gpios = <&gpio0 22 GPIO_ACTIVE_LOW>;
+               };
+
+               disk1_led {
+                       label = "status:blue:disk1_led";
+                       gpios = <&gpio0 20 GPIO_ACTIVE_LOW>;
+               };
+
+               disk2_led {
+                       label = "status:blue:disk2_led";
+                       gpios = <&gpio0 23 GPIO_ACTIVE_LOW>;
+               };
+
+               disk3_led {
+                       label = "status:blue:disk3_led";
+                       gpios = <&gpio0 24 GPIO_ACTIVE_LOW>;
+               };
+
+               disk4_led {
+                       label = "status:blue:disk4_led";
+                       gpios = <&gpio0 29 GPIO_ACTIVE_LOW>;
+               };
+       };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+               pinctrl-0 = <&pmx_button_power &pmx_button_backup
+                            &pmx_button_reset>;
+               pinctrl-names = "default";
+
+               power-button {
+                       label = "Power Button";
+                       linux,code = <KEY_POWER>;
+                       gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
+               };
+
+               reset-button {
+                       label = "Reset Button";
+                       linux,code = <KEY_RESTART>;
+                       gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
+               };
+
+               backup-button {
+                       label = "Backup Button";
+                       linux,code = <KEY_COPY>;
+                       gpios = <&gpio1 13 GPIO_ACTIVE_LOW>;
+               };
+       };
+
+       gpio-poweroff {
+               compatible = "gpio-poweroff";
+               pinctrl-0 = <&pmx_poweroff>;
+               pinctrl-names = "default";
+               gpios = <&gpio0 30 GPIO_ACTIVE_LOW>;
+       };
+
+       regulators {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               usb3_regulator: usb3-regulator {
+                       compatible = "regulator-fixed";
+                       reg = <1>;
+                       regulator-name = "USB 3.0 Power";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       enable-active-high;
+                       regulator-always-on;
+                       regulator-boot-on;
+                       gpio = <&gpio1 14 GPIO_ACTIVE_HIGH>;
+               };
+       };
+};
+
+&nand {
+       status = "okay";
+
+       partition@0 {
+               label = "u-boot";
+               reg = <0x0000000 0x180000>;
+               read-only;
+       };
+
+       partition@180000 {
+               label = "u-boot-env";
+               reg = <0x180000 0x20000>;
+       };
+
+       partition@200000 {
+               label = "uImage";
+               reg = <0x0200000 0x600000>;
+       };
+
+       partition@800000 {
+               label = "minirootfs";
+               reg = <0x0800000 0x1000000>;
+       };
+
+       partition@1800000 {
+               label = "jffs2";
+               reg = <0x1800000 0x6800000>;
+       };
+};
+
+&mdio {
+       status = "okay";
+
+       ethphy0: ethernet-phy@0 { /* Marvell 88E1318 */
+               device_type = "ethernet-phy";
+               reg = <0>;
+       };
+};
+
+&eth0 {
+       status = "okay";
+
+       ethernet0-port@0 {
+               phy-handle = <&ethphy0>;
+       };
+};
index 2fcb82e208288e6f0d9e72afc7d7650a2ec946aa..ae1ccbe41029d32d8da5cb8e7722fffcb1b5b1e1 100644 (file)
@@ -64,8 +64,8 @@
 
                button@1 {
                        label = "Power push button";
-                       linux,code = <116>;
-                       gpios = <&gpio1 0 0>;
+                       linux,code = <KEY_POWER>;
+                       gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>;
                };
        };
 
 
                red-fail {
                        label = "ns2:red:fail";
-                       gpios = <&gpio0 12 0>;
+                       gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>;
                };
        };
 
        gpio_poweroff {
                compatible = "gpio-poweroff";
-               gpios = <&gpio0 31 0>;
+               gpios = <&gpio0 31 GPIO_ACTIVE_HIGH>;
        };
 
 };
index 279607093cdbdbda0c0c80207256ab156272e334..1f2ca60d8b3d46f283672b93af35772a852797c9 100644 (file)
@@ -25,8 +25,8 @@
 
                blue-sata {
                        label = "ns2:blue:sata";
-                       gpios = <&gpio0 30 1>;
-                       linux,default-trigger = "default-on";
+                       gpios = <&gpio0 30 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "ide-disk";
                };
        };
 };
index defdc77fb5506bdb7b3bf7260685cf266b077af6..72c78d0b1116112cb224676073c57d534359a6b5 100644 (file)
 
        gpio_fan {
                compatible = "gpio-fan";
-               gpios = <&gpio0 22 1
-                        &gpio0  7 1
-                        &gpio1  1 1
-                        &gpio0 23 1>;
+               gpios = <&gpio0 22 GPIO_ACTIVE_LOW
+                        &gpio0  7 GPIO_ACTIVE_LOW
+                        &gpio1  1 GPIO_ACTIVE_LOW
+                        &gpio0 23 GPIO_ACTIVE_LOW>;
                gpio-fan,speed-map =
                        <   0  0
                         1500 15
@@ -36,7 +36,7 @@
                         3300 10
                         4300  9
                         5500  8>;
-               alarm-gpios = <&gpio0 25 1>;
+               alarm-gpios = <&gpio0 25 GPIO_ACTIVE_LOW>;
        };
 
        ns2-leds {
index adbafdd909915841aae8825de27265026d842672..c441bf62c09fcfa9cab080b00eeb0e76129c31d0 100644 (file)
 
        gpio_fan {
                compatible = "gpio-fan";
-               gpios = <&gpio0 22 1
-                        &gpio0  7 1
-                        &gpio1  1 1
-                        &gpio0 23 1>;
+               gpios = <&gpio0 22 GPIO_ACTIVE_LOW
+                        &gpio0  7 GPIO_ACTIVE_LOW
+                        &gpio1  1 GPIO_ACTIVE_LOW
+                        &gpio0 23 GPIO_ACTIVE_LOW>;
                gpio-fan,speed-map =
                        <   0  0
                         3000 15
@@ -37,7 +37,7 @@
                         7140 10
                         7980  9
                         9200  8>;
-               alarm-gpios = <&gpio0 25 1>;
+               alarm-gpios = <&gpio0 25 GPIO_ACTIVE_LOW>;
        };
 
        ns2-leds {
index e3f915defd3da6174ad0e1829cf1be0c15e38f80..aa78c2d11fe738fc843f716bd1a6f98ff1054a5b 100644 (file)
@@ -40,7 +40,7 @@
                compatible = "gpio-poweroff";
                pinctrl-0 = <&pmx_pwr_off>;
                pinctrl-names = "default";
-               gpios = <&gpio1 16 0>;
+               gpios = <&gpio1 16 GPIO_ACTIVE_HIGH>;
        };
 
        regulators {
@@ -58,7 +58,7 @@
                        regulator-max-microvolt = <5000000>;
                        regulator-always-on;
                        regulator-boot-on;
-                       gpio = <&gpio0 21 0>;
+                       gpio = <&gpio0 21 GPIO_ACTIVE_HIGH>;
                };
        };
 };
index b5418bcaeccead3b1313074c5ebf885d5f8f0e49..03fa24cf334468ff66095883b64ac5b76ae6bc42 100644 (file)
 
                button@1 {
                        label = "Power Button";
-                       linux,code = <116>;
-                       gpios = <&gpio1 14 0>;
+                       linux,code = <KEY_POWER>;
+                       gpios = <&gpio1 14 GPIO_ACTIVE_HIGH>;
                };
                button@2 {
                        label = "Copy Button";
-                       linux,code = <133>;
-                       gpios = <&gpio1 5 1>;
+                       linux,code = <KEY_COPY>;
+                       gpios = <&gpio1 5 GPIO_ACTIVE_LOW>;
                };
                button@3 {
                        label = "Reset Button";
-                       linux,code = <0x198>;
-                       gpios = <&gpio1 4 1>;
+                       linux,code = <KEY_RESTART>;
+                       gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
                };
        };
 
 
                green-sys {
                        label = "nsa310:green:sys";
-                       gpios = <&gpio0 28 0>;
+                       gpios = <&gpio0 28 GPIO_ACTIVE_HIGH>;
                };
                red-sys {
                        label = "nsa310:red:sys";
-                       gpios = <&gpio0 29 0>;
+                       gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>;
                };
                green-hdd {
                        label = "nsa310:green:hdd";
-                       gpios = <&gpio1 9 0>;
+                       gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>;
                };
                red-hdd {
                        label = "nsa310:red:hdd";
-                       gpios = <&gpio1 10 0>;
+                       gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>;
                };
                green-esata {
                        label = "nsa310:green:esata";
-                       gpios = <&gpio0 12 0>;
+                       gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>;
                };
                red-esata {
                        label = "nsa310:red:esata";
-                       gpios = <&gpio0 13 0>;
+                       gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>;
                };
                green-usb {
                        label = "nsa310:green:usb";
-                       gpios = <&gpio0 15 0>;
+                       gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>;
                };
                red-usb {
                        label = "nsa310:red:usb";
-                       gpios = <&gpio0 16 0>;
+                       gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>;
                };
                green-copy {
                        label = "nsa310:green:copy";
-                       gpios = <&gpio1 7 0>;
+                       gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
                };
                red-copy {
                        label = "nsa310:red:copy";
-                       gpios = <&gpio1 8 0>;
+                       gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>;
                };
        };
 };
index ab0212b0e6f58629e593cd6a4e2dbecb5957c166..a5e77945286776940aa38d363ad08bc081e85e3b 100644 (file)
 
                button@1 {
                        label = "Power Button";
-                       linux,code = <116>;
-                       gpios = <&gpio1 14 0>;
+                       linux,code = <KEY_POWER>;
+                       gpios = <&gpio1 14 GPIO_ACTIVE_HIGH>;
                };
                button@2 {
                        label = "Copy Button";
-                       linux,code = <133>;
-                       gpios = <&gpio1 5 1>;
+                       linux,code = <KEY_COPY>;
+                       gpios = <&gpio1 5 GPIO_ACTIVE_LOW>;
                };
                button@3 {
                        label = "Reset Button";
-                       linux,code = <0x198>;
-                       gpios = <&gpio1 4 1>;
+                       linux,code = <KEY_RESTART>;
+                       gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
                };
        };
 
 
                green-sys {
                        label = "nsa310:green:sys";
-                       gpios = <&gpio0 28 0>;
+                       gpios = <&gpio0 28 GPIO_ACTIVE_HIGH>;
                };
                red-sys {
                        label = "nsa310:red:sys";
-                       gpios = <&gpio0 29 0>;
+                       gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>;
                };
                green-hdd {
                        label = "nsa310:green:hdd";
-                       gpios = <&gpio1 9 0>;
+                       gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>;
                };
                red-hdd {
                        label = "nsa310:red:hdd";
-                       gpios = <&gpio1 10 0>;
+                       gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>;
                };
                green-esata {
                        label = "nsa310:green:esata";
-                       gpios = <&gpio0 12 0>;
+                       gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>;
                };
                red-esata {
                        label = "nsa310:red:esata";
-                       gpios = <&gpio0 13 0>;
+                       gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>;
                };
                green-usb {
                        label = "nsa310:green:usb";
-                       gpios = <&gpio0 15 0>;
+                       gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>;
                };
                green-copy {
                        label = "nsa310:green:copy";
-                       gpios = <&gpio1 7 0>;
+                       gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
                };
                red-copy {
                        label = "nsa310:red:copy";
-                       gpios = <&gpio1 8 0>;
+                       gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>;
                };
        };
 };
index f0e3d213604c975b760173bc854d624d68e38ccd..5c6a4f1b4e93270137e988caa113da3ecce0c4cf 100644 (file)
 
                led-red {
                        label = "obsa6:red:stat";
-                       gpios = <&gpio1 9 1>;
+                       gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
                };
 
                led-green {
                        label = "obsa6:green:stat";
-                       gpios = <&gpio1 10 1>;
+                       gpios = <&gpio1 10 GPIO_ACTIVE_LOW>;
                };
 
                led-yellow {
                        label = "obsa6:yellow:stat";
-                       gpios = <&gpio1 11 1>;
+                       gpios = <&gpio1 11 GPIO_ACTIVE_LOW>;
                };
         };
 
 
                button@1 {
                        label = "Init Button";
-                       linux,code = <116>;
-                       gpios = <&gpio1 6 0>;
+                       linux,code = <KEY_POWER>;
+                       gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>;
                };
        };
 };
index 851fb2a60f20bd7c34401accd522cf6c38aeea67..c054ef61cff5996ae2eeee39259b7a76433c875c 100644 (file)
 
                led-red {
                        label = "obsa7:red:stat";
-                       gpios = <&gpio1 9 1>;
+                       gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
                };
 
                led-green {
                        label = "obsa7:green:stat";
-                       gpios = <&gpio1 10 1>;
+                       gpios = <&gpio1 10 GPIO_ACTIVE_LOW>;
                };
 
                led-yellow {
                        label = "obsa7:yellow:stat";
-                       gpios = <&gpio1 11 1>;
+                       gpios = <&gpio1 11 GPIO_ACTIVE_LOW>;
                };
         };
 
 
                button@1 {
                        label = "Init Button";
-                       linux,code = <116>;
-                       gpios = <&gpio1 6 0>;
+                       linux,code = <KEY_POWER>;
+                       gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>;
                };
        };
 };
index 1173d7fb31b23f9e11565a45592fcb99f17e41bf..7b1cd993e891126fdc4f08e445b7371f890e1ff3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * kirkwood-sheevaplug-common.dts - Common parts for Sheevaplugs
+ * kirkwood-sheevaplug-common.dtsi - Common parts for Sheevaplugs
  *
  * Copyright (C) 2013 Simon Baatz <gmbnomis@gmail.com>
  *
index eac6a21f3b1f0b2402bf58c341b96f25945e455a..e2b4ea4f9e10726dc8cd3182277e1f2aeb7516ff 100644 (file)
@@ -24,8 +24,8 @@
                        pinctrl-0 = <&pmx_sdio &pmx_sdio_cd &pmx_sdio_wp>;
                        pinctrl-names = "default";
                        status = "okay";
-                       cd-gpios = <&gpio1 12 1>;
-                       wp-gpios = <&gpio1 15 0>;
+                       cd-gpios = <&gpio1 12 GPIO_ACTIVE_LOW>;
+                       wp-gpios = <&gpio1 15 GPIO_ACTIVE_HIGH>;
                };
        };
 
@@ -36,8 +36,8 @@
 
                health {
                        label = "sheevaplug:blue:health";
-                       gpios = <&gpio1 17 1>;
-                       linux,default-trigger = "default-on";
+                       gpios = <&gpio1 17 GPIO_ACTIVE_LOW>;
+                       default-state = "keep";
                };
        };
 };
index bb61918313dbf8c495b546273b34b6401c3ba8be..82f6abf120fd33b0f6a093b390483545e41db0af 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * kirkwood-sheevaplug-esata.dts - Device tree file for Sheevaplug
+ * kirkwood-sheevaplug.dts - Device tree file for Sheevaplug
  *
  * Copyright (C) 2013 Simon Baatz <gmbnomis@gmail.com>
  *
 
                health {
                        label = "sheevaplug:blue:health";
-                       gpios = <&gpio1 17 1>;
-                       linux,default-trigger = "default-on";
+                       gpios = <&gpio1 17 GPIO_ACTIVE_LOW>;
+                       default-state = "keep";
                };
 
                misc {
                        label = "sheevaplug:red:misc";
-                       gpios = <&gpio1 14 1>;
+                       gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
                };
        };
 };
index 320da677b9847e94f0aba2bcc634bd90890686a6..40d6adf678ca1193fc6966090b5757b052336016 100644 (file)
 
                disk {
                        label = "topkick:yellow:disk";
-                       gpios = <&gpio0 21 1>;
+                       gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;
                        linux,default-trigger = "ide-disk";
                };
                system2 {
                        label = "topkick:red:system";
-                       gpios = <&gpio1 5 1>;
+                       gpios = <&gpio1 5 GPIO_ACTIVE_LOW>;
                };
                system {
                        label = "topkick:blue:system";
-                       gpios = <&gpio1 6 1>;
+                       gpios = <&gpio1 6 GPIO_ACTIVE_LOW>;
                        default-state = "on";
                };
                wifi {
                        label = "topkick:green:wifi";
-                       gpios = <&gpio1 7 1>;
+                       gpios = <&gpio1 7 GPIO_ACTIVE_LOW>;
                };
                wifi2 {
                        label = "topkick:yellow:wifi";
-                       gpios = <&gpio1 16 1>;
+                       gpios = <&gpio1 16 GPIO_ACTIVE_LOW>;
                };
        };
        regulators {
index f755bc1dc604b16b97bd889c1605540875e7080a..c17ae45e19be3ffc33f500e172e3a6e04c439b10 100644 (file)
 
                button@1 {
                        label = "USB Copy";
-                       linux,code = <133>;
-                       gpios = <&gpio0 15 1>;
+                       linux,code = <KEY_COPY>;
+                       gpios = <&gpio0 15 GPIO_ACTIVE_LOW>;
                };
                button@2 {
                        label = "Reset";
-                       linux,code = <0x198>;
-                       gpios = <&gpio0 16 1>;
+                       linux,code = <KEY_RESTART>;
+                       gpios = <&gpio0 16 GPIO_ACTIVE_LOW>;
                };
        };
 };
index 345562f7589182975d27ae5e95b1e4319bc7f843..0713d072758a1e22a30b86bf3921cdc806cf6b61 100644 (file)
 
                button@1 {
                        label = "USB Copy";
-                       linux,code = <133>;
-                       gpios = <&gpio1 11 1>;
+                       linux,code = <KEY_COPY>;
+                       gpios = <&gpio1 11 GPIO_ACTIVE_LOW>;
                };
                button@2 {
                        label = "Reset";
-                       linux,code = <0x198>;
-                       gpios = <&gpio1 5 1>;
+                       linux,code = <KEY_RESTART>;
+                       gpios = <&gpio1 5 GPIO_ACTIVE_LOW>;
                };
        };
 };
index 8b73c80f1dad40995be65547ee5caa4a4fbffdaa..dd58a25a4166e4fd774cdc6276dbafcee81c7d64 100644 (file)
@@ -1,4 +1,6 @@
 /include/ "skeleton.dtsi"
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
 
 #define MBUS_ID(target,attributes) (((target) << 24) | ((attributes) << 16))
 
index 9c18adf788f774101daa7a7ee4389cfb235bd561..f577b7df9a29e4f5f4e74ca86aef4b4ba61ceb87 100644 (file)
@@ -44,8 +44,8 @@
                gpmc,wr-access-ns = <186>;
                gpmc,cycle2cycle-samecsen;
                gpmc,cycle2cycle-diffcsen;
-               vmmc-supply = <&vddvario>;
-               vmmc_aux-supply = <&vdd33a>;
+               vddvario-supply = <&vddvario>;
+               vdd33a-supply = <&vdd33a>;
                reg-io-width = <4>;
                smsc,save-mac-address;
        };
index 31a632f7effbf239f298ff3619cdacdc5587356e..df33a50bc070b508fd8dacd8a3c72f645c18d3e0 100644 (file)
 &usbhsehci {
        phys = <0 &hsusb2_phy>;
 };
+
+&vaux2 {
+       regulator-name = "usb_1v8";
+       regulator-min-microvolt = <1800000>;
+       regulator-max-microvolt = <1800000>;
+       regulator-always-on;
+};
index fa532aaacc68943989241b92a6e31743e3e854fe..3ba4a625ea5b9714ce4371e8a9637c108349158c 100644 (file)
                vcc-supply = <&hsusb2_power>;
        };
 
+       sound {
+               compatible = "ti,omap-twl4030";
+               ti,model = "omap3beagle";
+
+               ti,mcbsp = <&mcbsp2>;
+               ti,codec = <&twl_audio>;
+       };
+
        gpio_keys {
                compatible = "gpio-keys";
 
                reg = <0x48>;
                interrupts = <7>; /* SYS_NIRQ cascaded to intc */
                interrupt-parent = <&intc>;
+
+               twl_audio: audio {
+                       compatible = "ti,twl4030-audio";
+                       codec {
+                       };
+               };
        };
 };
 
        mode = <3>;
        power = <50>;
 };
+
+&vaux2 {
+       regulator-name = "vdd_ehci";
+       regulator-min-microvolt = <1800000>;
+       regulator-max-microvolt = <1800000>;
+       regulator-always-on;
+};
index ba1e58b7b7e35ddbdf4825853cf72cef6a951939..165aaf7591ba8ef51856474d85db8754710a33ed 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Device Tree Source for IGEP Technology devices
+ * Common device tree for IGEP boards based on AM/DM37x
  *
  * Copyright (C) 2012 Javier Martinez Canillas <javier@collabora.co.uk>
  * Copyright (C) 2012 Enric Balletbo i Serra <eballetbo@gmail.com>
@@ -10,7 +10,7 @@
  */
 /dts-v1/;
 
-#include "omap34xx.dtsi"
+#include "omap36xx.dtsi"
 
 / {
        memory {
                ti,mcbsp = <&mcbsp2>;
                ti,codec = <&twl_audio>;
        };
+
+       vdd33: regulator-vdd33 {
+               compatible = "regulator-fixed";
+               regulator-name = "vdd33";
+               regulator-always-on;
+       };
+
+       lbee1usjyc_vmmc: lbee1usjyc_vmmc {
+               pinctrl-names = "default";
+               pinctrl-0 = <&lbee1usjyc_pins>;
+               compatible = "regulator-fixed";
+               regulator-name = "regulator-lbee1usjyc";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               gpio = <&gpio5 10 GPIO_ACTIVE_HIGH>;    /* gpio_138 WIFI_PDN */
+               startup-delay-us = <10000>;
+               enable-active-high;
+               vin-supply = <&vdd33>;
+       };
 };
 
 &omap3_pmx_core {
                >;
        };
 
+       /* WiFi/BT combo */
+       lbee1usjyc_pins: pinmux_lbee1usjyc_pins {
+               pinctrl-single,pins = <
+                       0x136 (PIN_OUTPUT | MUX_MODE4)  /* sdmmc2_dat5.gpio_137 */
+                       0x138 (PIN_OUTPUT | MUX_MODE4)  /* sdmmc2_dat6.gpio_138 */
+                       0x13a (PIN_OUTPUT | MUX_MODE4)  /* sdmmc2_dat7.gpio_139 */
+               >;
+       };
+
        mcbsp2_pins: pinmux_mcbsp2_pins {
                pinctrl-single,pins = <
                        0x10c (PIN_INPUT | MUX_MODE0)           /* mcbsp2_fsx.mcbsp2_fsx */
                        0x11a (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc1_dat1.sdmmc1_dat1 */
                        0x11c (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc1_dat2.sdmmc1_dat2 */
                        0x11e (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc1_dat3.sdmmc1_dat3 */
-                       0x120 (PIN_INPUT | MUX_MODE0)           /* sdmmc1_dat4.sdmmc1_dat4 */
-                       0x122 (PIN_INPUT | MUX_MODE0)           /* sdmmc1_dat5.sdmmc1_dat5 */
-                       0x124 (PIN_INPUT | MUX_MODE0)           /* sdmmc1_dat6.sdmmc1_dat6 */
-                       0x126 (PIN_INPUT | MUX_MODE0)           /* sdmmc1_dat7.sdmmc1_dat7 */
+               >;
+       };
+
+       mmc2_pins: pinmux_mmc2_pins {
+               pinctrl-single,pins = <
+                       0x128 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_clk.sdmmc2_clk */
+                       0x12a (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_cmd.sdmmc2_cmd */
+                       0x12c (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_dat0.sdmmc2_dat0 */
+                       0x12e (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_dat1.sdmmc2_dat1 */
+                       0x130 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_dat2.sdmmc2_dat2 */
+                       0x132 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_dat3.sdmmc2_dat3 */
                >;
        };
 
                >;
        };
 
+       i2c1_pins: pinmux_i2c1_pins {
+               pinctrl-single,pins = <
+                       0x18a (PIN_INPUT | MUX_MODE0)   /* i2c1_scl.i2c1_scl */
+                       0x18c (PIN_INPUT | MUX_MODE0)   /* i2c1_sda.i2c1_sda */
+               >;
+       };
+
+       i2c2_pins: pinmux_i2c2_pins {
+               pinctrl-single,pins = <
+                       0x18e (PIN_INPUT | MUX_MODE0)   /* i2c2_scl.i2c2_scl */
+                       0x190 (PIN_INPUT | MUX_MODE0)   /* i2c2_sda.i2c2_sda */
+               >;
+       };
+
+       i2c3_pins: pinmux_i2c3_pins {
+               pinctrl-single,pins = <
+                       0x192 (PIN_INPUT | MUX_MODE0)   /* i2c3_scl.i2c3_scl */
+                       0x194 (PIN_INPUT | MUX_MODE0)   /* i2c3_sda.i2c3_sda */
+               >;
+       };
+
        leds_pins: pinmux_leds_pins { };
 };
 
 &i2c1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c1_pins>;
        clock-frequency = <2600000>;
 
        twl: twl@48 {
 #include "twl4030_omap3.dtsi"
 
 &i2c2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c2_pins>;
        clock-frequency = <400000>;
 };
 
+&i2c3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c3_pins>;
+};
+
 &mcbsp2 {
        pinctrl-names = "default";
        pinctrl-0 = <&mcbsp2_pins>;
       pinctrl-0 = <&mmc1_pins>;
       vmmc-supply = <&vmmc1>;
       vmmc_aux-supply = <&vsim>;
-      bus-width = <8>;
+      bus-width = <4>;
 };
 
 &mmc2 {
-       status = "disabled";
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc2_pins>;
+       vmmc-supply = <&lbee1usjyc_vmmc>;
+       bus-width = <4>;
+       non-removable;
 };
 
 &mmc3 {
index d5cc792672501012f2a368b4d27b17bbb7669d95..1c7e74d2d2bc7bd03f1a970cea9442f715c0f3eb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Device Tree Source for IGEPv2 board
+ * Device Tree Source for IGEPv2 Rev. (TI OMAP AM/DM37x)
  *
  * Copyright (C) 2012 Javier Martinez Canillas <javier@collabora.co.uk>
  * Copyright (C) 2012 Enric Balletbo i Serra <eballetbo@gmail.com>
@@ -13,7 +13,7 @@
 #include "omap-gpmc-smsc911x.dtsi"
 
 / {
-       model = "IGEPv2";
+       model = "IGEPv2 (TI OMAP AM/DM37x)";
        compatible = "isee,omap3-igep0020", "ti,omap3";
 
        leds {
@@ -67,6 +67,8 @@
        pinctrl-names = "default";
        pinctrl-0 = <
                &hsusbb1_pins
+               &tfp410_pins
+               &dss_pins
        >;
 
        hsusbb1_pins: pinmux_hsusbb1_pins {
                        0x5ba (PIN_INPUT_PULLDOWN | MUX_MODE3)  /* etk_d7.hsusb1_data3 */
                >;
        };
+
+       tfp410_pins: tfp410_dvi_pins {
+               pinctrl-single,pins = <
+                       0x196 (PIN_OUTPUT | MUX_MODE4)   /* hdq_sio.gpio_170 */
+               >;
+       };
+
+       dss_pins: pinmux_dss_dvi_pins {
+               pinctrl-single,pins = <
+                       0x0a4 (PIN_OUTPUT | MUX_MODE0)   /* dss_pclk.dss_pclk */
+                       0x0a6 (PIN_OUTPUT | MUX_MODE0)   /* dss_hsync.dss_hsync */
+                       0x0a8 (PIN_OUTPUT | MUX_MODE0)   /* dss_vsync.dss_vsync */
+                       0x0aa (PIN_OUTPUT | MUX_MODE0)   /* dss_acbias.dss_acbias */
+                       0x0ac (PIN_OUTPUT | MUX_MODE0)   /* dss_data0.dss_data0 */
+                       0x0ae (PIN_OUTPUT | MUX_MODE0)   /* dss_data1.dss_data1 */
+                       0x0b0 (PIN_OUTPUT | MUX_MODE0)   /* dss_data2.dss_data2 */
+                       0x0b2 (PIN_OUTPUT | MUX_MODE0)   /* dss_data3.dss_data3 */
+                       0x0b4 (PIN_OUTPUT | MUX_MODE0)   /* dss_data4.dss_data4 */
+                       0x0b6 (PIN_OUTPUT | MUX_MODE0)   /* dss_data5.dss_data5 */
+                       0x0b8 (PIN_OUTPUT | MUX_MODE0)   /* dss_data6.dss_data6 */
+                       0x0ba (PIN_OUTPUT | MUX_MODE0)   /* dss_data7.dss_data7 */
+                       0x0bc (PIN_OUTPUT | MUX_MODE0)   /* dss_data8.dss_data8 */
+                       0x0be (PIN_OUTPUT | MUX_MODE0)   /* dss_data9.dss_data9 */
+                       0x0c0 (PIN_OUTPUT | MUX_MODE0)   /* dss_data10.dss_data10 */
+                       0x0c2 (PIN_OUTPUT | MUX_MODE0)   /* dss_data11.dss_data11 */
+                       0x0c4 (PIN_OUTPUT | MUX_MODE0)   /* dss_data12.dss_data12 */
+                       0x0c6 (PIN_OUTPUT | MUX_MODE0)   /* dss_data13.dss_data13 */
+                       0x0c8 (PIN_OUTPUT | MUX_MODE0)   /* dss_data14.dss_data14 */
+                       0x0ca (PIN_OUTPUT | MUX_MODE0)   /* dss_data15.dss_data15 */
+                       0x0cc (PIN_OUTPUT | MUX_MODE0)   /* dss_data16.dss_data16 */
+                       0x0ce (PIN_OUTPUT | MUX_MODE0)   /* dss_data17.dss_data17 */
+                       0x0d0 (PIN_OUTPUT | MUX_MODE0)   /* dss_data18.dss_data18 */
+                       0x0d2 (PIN_OUTPUT | MUX_MODE0)   /* dss_data19.dss_data19 */
+                       0x0d4 (PIN_OUTPUT | MUX_MODE0)   /* dss_data20.dss_data20 */
+                       0x0d6 (PIN_OUTPUT | MUX_MODE0)   /* dss_data21.dss_data21 */
+                       0x0d8 (PIN_OUTPUT | MUX_MODE0)   /* dss_data22.dss_data22 */
+                       0x0da (PIN_OUTPUT | MUX_MODE0)   /* dss_data23.dss_data23 */
+               >;
+       };
 };
 
 &leds_pins {
 &usbhsehci {
        phys = <&hsusb1_phy>;
 };
+
+&vpll2 {
+        /* Needed for DSS */
+        regulator-name = "vdds_dsi";
+};
index 525e6d9b09784c721b4660554a17abdda14273e9..02a23f8a3384255abca5d54ecf53417226a8347f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Device Tree Source for IGEP COM Module
+ * Device Tree Source for IGEP COM MODULE (TI OMAP AM/DM37x)
  *
  * Copyright (C) 2012 Javier Martinez Canillas <javier@collabora.co.uk>
  * Copyright (C) 2012 Enric Balletbo i Serra <eballetbo@gmail.com>
@@ -12,7 +12,7 @@
 #include "omap3-igep.dtsi"
 
 / {
-       model = "IGEP COM Module";
+       model = "IGEP COM MODULE (TI OMAP AM/DM37x)";
        compatible = "isee,omap3-igep0030", "ti,omap3";
 
        leds {
index c4f20bfe4cce15e641af5ef08c92ca939973b9c3..6fc85f96353024ad61d04d74d7ca51f8afb1c7ce 100644 (file)
@@ -9,7 +9,7 @@
 
 /dts-v1/;
 
-#include "omap34xx.dtsi"
+#include "omap34xx-hs.dtsi"
 
 / {
        model = "Nokia N900";
                >;
        };
 
+       mmc2_pins: pinmux_mmc2_pins {
+               pinctrl-single,pins = <
+                       0x128 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_clk */
+                       0x12a (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_cmd */
+                       0x12c (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_dat0 */
+                       0x12e (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_dat1 */
+                       0x130 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_dat2 */
+                       0x132 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_dat3 */
+                       0x134 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_dat4 */
+                       0x136 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_dat5 */
+                       0x138 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_dat6 */
+                       0x13a (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc2_dat7 */
+               >;
+       };
+
        display_pins: pinmux_display_pins {
                pinctrl-single,pins = <
                        0x0d4 (PIN_OUTPUT | MUX_MODE4)          /* RX51_LCD_RESET_GPIO */
        cd-gpios = <&gpio6 0 GPIO_ACTIVE_HIGH>; /* 160 */
 };
 
+/* most boards use vaux3, only some old versions use vmmc2 instead */
 &mmc2 {
-       status = "disabled";
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc2_pins>;
+       vmmc-supply = <&vaux3>;
+       vmmc_aux-supply = <&vsim>;
+       bus-width = <8>;
+       non-removable;
 };
 
 &mmc3 {
index 94eb77d3b9ddc5a2c506f271834103cb06b4881e..5c26c184f2c18b50a18cdd51bd53b20f9b3f359b 100644 (file)
@@ -8,7 +8,7 @@
  * published by the Free Software Foundation.
  */
 
-#include "omap36xx.dtsi"
+#include "omap36xx-hs.dtsi"
 
 / {
        cpus {
index f3a0c26ed0c2bcd6d6df65dcecc3f18329abec18..daabf99d402a8e4ff645824dcad9d56fc693b17d 100644 (file)
                ranges;
                ti,hwmods = "l3_main";
 
+               aes: aes@480c5000 {
+                       compatible = "ti,omap3-aes";
+                       ti,hwmods = "aes";
+                       reg = <0x480c5000 0x50>;
+                       interrupts = <0>;
+               };
+
                counter32k: counter@48320000 {
                        compatible = "ti,omap-counter32k";
                        reg = <0x48320000 0x20>;
                        ti,hwmods = "i2c3";
                };
 
+               mailbox: mailbox@48094000 {
+                       compatible = "ti,omap3-mailbox";
+                       ti,hwmods = "mailbox";
+                       reg = <0x48094000 0x200>;
+                       interrupts = <26>;
+               };
+
                mcspi1: spi@48098000 {
                        compatible = "ti,omap2-mcspi";
                        reg = <0x48098000 0x100>;
                        dma-names = "tx", "rx";
                };
 
+               mmu_isp: mmu@480bd400 {
+                       compatible = "ti,omap3-mmu-isp";
+                       ti,hwmods = "mmu_isp";
+                       reg = <0x480bd400 0x80>;
+                       interrupts = <8>;
+               };
+
                wdt2: wdt@48314000 {
                        compatible = "ti,omap3-wdt";
                        reg = <0x48314000 0x80>;
                        dma-names = "tx", "rx";
                };
 
+               sham: sham@480c3000 {
+                       compatible = "ti,omap3-sham";
+                       ti,hwmods = "sham";
+                       reg = <0x480c3000 0x64>;
+                       interrupts = <49>;
+               };
+
+               smartreflex_core: smartreflex@480cb000 {
+                       compatible = "ti,omap3-smartreflex-core";
+                       ti,hwmods = "smartreflex_core";
+                       reg = <0x480cb000 0x400>;
+                       interrupts = <19>;
+               };
+
+               smartreflex_mpu_iva: smartreflex@480c9000 {
+                       compatible = "ti,omap3-smartreflex-iva";
+                       ti,hwmods = "smartreflex_mpu_iva";
+                       reg = <0x480c9000 0x400>;
+                       interrupts = <18>;
+               };
+
                timer1: timer@48318000 {
                        compatible = "ti,omap3430-timer";
                        reg = <0x48318000 0x400>;
diff --git a/arch/arm/boot/dts/omap34xx-hs.dtsi b/arch/arm/boot/dts/omap34xx-hs.dtsi
new file mode 100644 (file)
index 0000000..1ff6264
--- /dev/null
@@ -0,0 +1,16 @@
+/* Disabled modules for secure omaps */
+
+#include "omap34xx.dtsi"
+
+/* Secure omaps have some devices inaccessible depending on the firmware */
+&aes {
+       status = "disabled";
+};
+
+&sham {
+       status = "disabled";
+};
+
+&timer12 {
+       status = "disabled";
+};
diff --git a/arch/arm/boot/dts/omap36xx-hs.dtsi b/arch/arm/boot/dts/omap36xx-hs.dtsi
new file mode 100644 (file)
index 0000000..2c7febb
--- /dev/null
@@ -0,0 +1,16 @@
+/* Disabled modules for secure omaps */
+
+#include "omap36xx.dtsi"
+
+/* Secure omaps have some devices inaccessible depending on the firmware */
+&aes {
+       status = "disabled";
+};
+
+&sham {
+       status = "disabled";
+};
+
+&timer12 {
+       status = "disabled";
+};
index 298e85020e1b20bec89b8ecc52b38886e4656467..88c6a05cab415f3cb04cdec0fb2bc3c504ec8d7f 100644 (file)
                        0xf0 (PIN_INPUT_PULLUP | MUX_MODE0)     /* i2c4_sda */
                >;
        };
-};
-
-&omap4_pmx_wkup {
-       led_wkgpio_pins: pinmux_leds_wkpins {
-               pinctrl-single,pins = <
-                       0x1a (PIN_OUTPUT | MUX_MODE3)   /* gpio_wk7 */
-                       0x1c (PIN_OUTPUT | MUX_MODE3)   /* gpio_wk8 */
-               >;
-       };
 
        /*
         * wl12xx GPIO outputs for WLAN_EN, BT_EN, FM_EN, BT_WAKEUP
                pinctrl-single,pins = <
                        0x38 (PIN_INPUT | MUX_MODE3)            /* gpmc_ncs2.gpio_52 */
                        0x3a (PIN_INPUT | MUX_MODE3)            /* gpmc_ncs3.gpio_53 */
-                       0x108 (PIN_OUTPUT | MUX_MODE0)          /* sdmmc5_clk.sdmmc5_clk */
+                       0x108 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc5_clk.sdmmc5_clk */
                        0x10a (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc5_cmd.sdmmc5_cmd */
                        0x10c (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc5_dat0.sdmmc5_dat0 */
                        0x10e (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc5_dat1.sdmmc5_dat1 */
        };
 };
 
+&omap4_pmx_wkup {
+       led_wkgpio_pins: pinmux_leds_wkpins {
+               pinctrl-single,pins = <
+                       0x1a (PIN_OUTPUT | MUX_MODE3)   /* gpio_wk7 */
+                       0x1c (PIN_OUTPUT | MUX_MODE3)   /* gpio_wk8 */
+               >;
+       };
+};
+
 &i2c1 {
        pinctrl-names = "default";
        pinctrl-0 = <&i2c1_pins>;
index 5fc3f43c5a81d4c9256b063f31bb32fc544dde38..dbc81fb6ef033428ce6b02d7287b7efa46ebfa1e 100644 (file)
        wl12xx_pins: pinmux_wl12xx_pins {
                pinctrl-single,pins = <
                        0x3a (PIN_INPUT | MUX_MODE3)            /* gpmc_ncs3.gpio_53 */
-                       0x108 (PIN_OUTPUT | MUX_MODE3)          /* sdmmc5_clk.sdmmc5_clk */
-                       0x10a (PIN_INPUT_PULLUP | MUX_MODE3)    /* sdmmc5_cmd.sdmmc5_cmd */
-                       0x10c (PIN_INPUT_PULLUP | MUX_MODE3)    /* sdmmc5_dat0.sdmmc5_dat0 */
-                       0x10e (PIN_INPUT_PULLUP | MUX_MODE3)    /* sdmmc5_dat1.sdmmc5_dat1 */
-                       0x110 (PIN_INPUT_PULLUP | MUX_MODE3)    /* sdmmc5_dat2.sdmmc5_dat2 */
-                       0x112 (PIN_INPUT_PULLUP | MUX_MODE3)    /* sdmmc5_dat3.sdmmc5_dat3 */
+                       0x108 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc5_clk.sdmmc5_clk */
+                       0x10a (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc5_cmd.sdmmc5_cmd */
+                       0x10c (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc5_dat0.sdmmc5_dat0 */
+                       0x10e (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc5_dat1.sdmmc5_dat1 */
+                       0x110 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc5_dat2.sdmmc5_dat2 */
+                       0x112 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc5_dat3.sdmmc5_dat3 */
                >;
        };
 };
index aed83deaa991c9b8856218ef0792f1c3f51cc2b4..fcc5bb63f03a949cd80ed090a66f8a901614899f 100644 (file)
@@ -58,7 +58,7 @@
        status = "okay";
 
        ethphy: ethernet-phy {
-               device-type = "ethernet-phy";
+               device_type = "ethernet-phy";
                reg = <8>;
        };
 };
diff --git a/arch/arm/boot/dts/r7s72100-genmai-reference.dts b/arch/arm/boot/dts/r7s72100-genmai-reference.dts
new file mode 100644 (file)
index 0000000..da19c70
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Device Tree Source for the Genmai board
+ *
+ * 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/ "r7s72100.dtsi"
+
+/ {
+       model = "Genmai";
+       compatible = "renesas,genmai-reference", "renesas,r7s72100";
+
+       chosen {
+               bootargs = "console=ttySC2,115200 ignore_loglevel rw root=/dev/nfs ip=dhcp";
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x08000000 0x08000000>;
+       };
+
+       lbsc {
+               #address-cells = <1>;
+               #size-cells = <1>;
+       };
+};
index 1fb20f2333cc80a8a89ae1c15485c6f60fc64572..b1deaf7e2e06826b1893925e19812420aa46eeec 100644 (file)
@@ -9,7 +9,7 @@
  */
 
 /dts-v1/;
-/include/ "r7s72100.dtsi"
+#include "r7s72100.dtsi"
 
 / {
        model = "Genmai";
index 9443e93d3cac7f07cfdca4fa24b825424ab310a2..70b1fff8f4a3592a69bf889455504fa1d553adde 100644 (file)
@@ -9,7 +9,7 @@
  */
 
 /dts-v1/;
-/include/ "r8a73a4.dtsi"
+#include "r8a73a4.dtsi"
 #include <dt-bindings/gpio/gpio.h>
 
 / {
                reg = <0 0x40000000 0 0x40000000>;
        };
 
+       memory@200000000 {
+               device_type = "memory";
+               reg = <2 0x00000000 0 0x40000000>;
+       };
+
        vcc_mmc0: regulator@0 {
                compatible = "regulator-fixed";
                regulator-name = "MMC0 Vcc";
        pinctrl-0 = <&scifa0_pins>;
        pinctrl-names = "default";
 
-       scifa0_pins: scifa0 {
+       scifa0_pins: serial0 {
                renesas,groups = "scifa0_data";
                renesas,function = "scifa0";
        };
 
-       mmc0_pins: mmcif {
+       mmc0_pins: mmc {
                renesas,groups = "mmc0_data8", "mmc0_ctrl";
                renesas,function = "mmc0";
        };
 
-       sdhi0_pins: sdhi0 {
+       sdhi0_pins: sd0 {
                renesas,groups = "sdhi0_data4", "sdhi0_ctrl", "sdhi0_cd";
                renesas,function = "sdhi0";
        };
 
-       sdhi1_pins: sdhi1 {
+       sdhi1_pins: sd1 {
                renesas,groups = "sdhi1_data4", "sdhi1_ctrl";
                renesas,function = "sdhi1";
        };
index 91436b58016f1d48fa5cd12c3946377500b9d70a..ce085fa444a12ae24230ac87ff1e55a8efd43e9f 100644 (file)
@@ -9,7 +9,8 @@
  */
 
 /dts-v1/;
-/include/ "r8a73a4.dtsi"
+#include "r8a73a4.dtsi"
+#include <dt-bindings/interrupt-controller/irq.h>
 
 / {
        model = "APE6EVM";
                reg = <0 0x40000000 0 0x40000000>;
        };
 
+       memory@200000000 {
+               device_type = "memory";
+               reg = <2 0x00000000 0 0x40000000>;
+       };
+
        ape6evm_fixed_3v3: fixedregulator@0 {
                compatible = "regulator-fixed";
                regulator-name = "3V3";
@@ -40,7 +46,7 @@
                        compatible = "smsc,lan9118", "smsc,lan9115";
                        reg = <0x08000000 0x1000>;
                        interrupt-parent = <&irqc1>;
-                       interrupts = <8 0x4>;
+                       interrupts = <8 IRQ_TYPE_LEVEL_HIGH>;
                        phy-mode = "mii";
                        reg-io-width = <4>;
                        smsc,irq-active-high;
index 287e047592a03d28e009cc0500c27ab6a18e6de1..6b7ce89a68f79cf1c2eaaaa2629e4a2e2389741a 100644 (file)
@@ -9,6 +9,9 @@
  * kind, whether express or implied.
  */
 
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
 / {
        compatible = "renesas,r8a73a4";
        interrupt-parent = <&gic>;
                        <0 0xf1002000 0 0x1000>,
                        <0 0xf1004000 0 0x2000>,
                        <0 0xf1006000 0 0x2000>;
-               interrupts = <1 9 0xf04>;
+               interrupts = <1 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
        };
 
        timer {
                compatible = "arm,armv7-timer";
-               interrupts = <1 13 0xf08>,
-                               <1 14 0xf08>,
-                               <1 11 0xf08>,
-                               <1 10 0xf08>;
+               interrupts = <1 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+                            <1 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+                            <1 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+                            <1 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
        };
 
        irqc0: interrupt-controller@e61c0000 {
                interrupt-controller;
                reg = <0 0xe61c0000 0 0x200>;
                interrupt-parent = <&gic>;
-               interrupts = <0 0 4>, <0 1 4>, <0 2 4>, <0 3 4>,
-                               <0 4 4>, <0 5 4>, <0 6 4>, <0 7 4>,
-                               <0 8 4>, <0 9 4>, <0 10 4>, <0 11 4>,
-                               <0 12 4>, <0 13 4>, <0 14 4>, <0 15 4>,
-                               <0 16 4>, <0 17 4>, <0 18 4>, <0 19 4>,
-                               <0 20 4>, <0 21 4>, <0 22 4>, <0 23 4>,
-                               <0 24 4>, <0 25 4>, <0 26 4>, <0 27 4>,
-                               <0 28 4>, <0 29 4>, <0 30 4>, <0 31 4>;
+               interrupts = <0 0 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 1 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 2 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 3 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 4 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 5 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 6 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 7 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 8 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 9 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 10 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 11 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 12 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 13 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 14 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 15 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 16 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 17 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 18 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 19 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 20 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 21 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 22 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 23 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 24 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 25 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 26 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 27 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 28 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 29 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 30 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 31 IRQ_TYPE_LEVEL_HIGH>;
        };
 
        irqc1: interrupt-controller@e61c0200 {
                interrupt-controller;
                reg = <0 0xe61c0200 0 0x200>;
                interrupt-parent = <&gic>;
-               interrupts = <0 32 4>, <0 33 4>, <0 34 4>, <0 35 4>,
-                               <0 36 4>, <0 37 4>, <0 38 4>, <0 39 4>,
-                               <0 40 4>, <0 41 4>, <0 42 4>, <0 43 4>,
-                               <0 44 4>, <0 45 4>, <0 46 4>, <0 47 4>,
-                               <0 48 4>, <0 49 4>, <0 50 4>, <0 51 4>,
-                               <0 52 4>, <0 53 4>, <0 54 4>, <0 55 4>,
-                               <0 56 4>, <0 57 4>;
+               interrupts = <0 32 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 33 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 34 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 35 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 36 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 37 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 38 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 39 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 40 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 41 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 42 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 43 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 44 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 45 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 46 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 47 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 48 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 49 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 50 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 51 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 52 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 53 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 54 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 55 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 56 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 57 IRQ_TYPE_LEVEL_HIGH>;
        };
 
        dmac: dma-multiplexer@0 {
                        compatible = "renesas,shdma-r8a73a4";
                        reg = <0 0xe6700020 0 0x89e0>;
                        interrupt-parent = <&gic>;
-                       interrupts = <0 220 4
-                                       0 200 4
-                                       0 201 4
-                                       0 202 4
-                                       0 203 4
-                                       0 204 4
-                                       0 205 4
-                                       0 206 4
-                                       0 207 4
-                                       0 208 4
-                                       0 209 4
-                                       0 210 4
-                                       0 211 4
-                                       0 212 4
-                                       0 213 4
-                                       0 214 4
-                                       0 215 4
-                                       0 216 4
-                                       0 217 4
-                                       0 218 4
-                                       0 219 4>;
+                       interrupts = <0 220 IRQ_TYPE_LEVEL_HIGH
+                                       0 200 IRQ_TYPE_LEVEL_HIGH
+                                       0 201 IRQ_TYPE_LEVEL_HIGH
+                                       0 202 IRQ_TYPE_LEVEL_HIGH
+                                       0 203 IRQ_TYPE_LEVEL_HIGH
+                                       0 204 IRQ_TYPE_LEVEL_HIGH
+                                       0 205 IRQ_TYPE_LEVEL_HIGH
+                                       0 206 IRQ_TYPE_LEVEL_HIGH
+                                       0 207 IRQ_TYPE_LEVEL_HIGH
+                                       0 208 IRQ_TYPE_LEVEL_HIGH
+                                       0 209 IRQ_TYPE_LEVEL_HIGH
+                                       0 210 IRQ_TYPE_LEVEL_HIGH
+                                       0 211 IRQ_TYPE_LEVEL_HIGH
+                                       0 212 IRQ_TYPE_LEVEL_HIGH
+                                       0 213 IRQ_TYPE_LEVEL_HIGH
+                                       0 214 IRQ_TYPE_LEVEL_HIGH
+                                       0 215 IRQ_TYPE_LEVEL_HIGH
+                                       0 216 IRQ_TYPE_LEVEL_HIGH
+                                       0 217 IRQ_TYPE_LEVEL_HIGH
+                                       0 218 IRQ_TYPE_LEVEL_HIGH
+                                       0 219 IRQ_TYPE_LEVEL_HIGH>;
                        interrupt-names = "error",
                                        "ch0", "ch1", "ch2", "ch3",
                                        "ch4", "ch5", "ch6", "ch7",
                reg = <0 0xe61f0000 0 0x14>, <0 0xe61f0100 0 0x38>,
                         <0 0xe61f0200 0 0x38>, <0 0xe61f0300 0 0x38>;
                interrupt-parent = <&gic>;
-               interrupts = <0 69 4>;
+               interrupts = <0 69 IRQ_TYPE_LEVEL_HIGH>;
        };
 
        i2c0: i2c@e6500000 {
                compatible = "renesas,rmobile-iic";
                reg = <0 0xe6500000 0 0x428>;
                interrupt-parent = <&gic>;
-               interrupts = <0 174 0x4>;
+               interrupts = <0 174 IRQ_TYPE_LEVEL_HIGH>;
                status = "disabled";
        };
 
                compatible = "renesas,rmobile-iic";
                reg = <0 0xe6510000 0 0x428>;
                interrupt-parent = <&gic>;
-               interrupts = <0 175 0x4>;
+               interrupts = <0 175 IRQ_TYPE_LEVEL_HIGH>;
                status = "disabled";
        };
 
                compatible = "renesas,rmobile-iic";
                reg = <0 0xe6520000 0 0x428>;
                interrupt-parent = <&gic>;
-               interrupts = <0 176 0x4>;
+               interrupts = <0 176 IRQ_TYPE_LEVEL_HIGH>;
                status = "disabled";
        };
 
                compatible = "renesas,rmobile-iic";
                reg = <0 0xe6530000 0 0x428>;
                interrupt-parent = <&gic>;
-               interrupts = <0 177 0x4>;
+               interrupts = <0 177 IRQ_TYPE_LEVEL_HIGH>;
                status = "disabled";
        };
 
                compatible = "renesas,rmobile-iic";
                reg = <0 0xe6540000 0 0x428>;
                interrupt-parent = <&gic>;
-               interrupts = <0 178 0x4>;
+               interrupts = <0 178 IRQ_TYPE_LEVEL_HIGH>;
                status = "disabled";
        };
 
                compatible = "renesas,rmobile-iic";
                reg = <0 0xe60b0000 0 0x428>;
                interrupt-parent = <&gic>;
-               interrupts = <0 179 0x4>;
+               interrupts = <0 179 IRQ_TYPE_LEVEL_HIGH>;
                status = "disabled";
        };
 
                compatible = "renesas,rmobile-iic";
                reg = <0 0xe6550000 0 0x428>;
                interrupt-parent = <&gic>;
-               interrupts = <0 184 0x4>;
+               interrupts = <0 184 IRQ_TYPE_LEVEL_HIGH>;
                status = "disabled";
        };
 
                compatible = "renesas,rmobile-iic";
                reg = <0 0xe6560000 0 0x428>;
                interrupt-parent = <&gic>;
-               interrupts = <0 185 0x4>;
+               interrupts = <0 185 IRQ_TYPE_LEVEL_HIGH>;
                status = "disabled";
        };
 
                compatible = "renesas,rmobile-iic";
                reg = <0 0xe6570000 0 0x428>;
                interrupt-parent = <&gic>;
-               interrupts = <0 173 0x4>;
+               interrupts = <0 173 IRQ_TYPE_LEVEL_HIGH>;
                status = "disabled";
        };
 
-       mmcif0: mmcif@ee200000 {
+       mmcif0: mmc@ee200000 {
                compatible = "renesas,sh-mmcif";
                reg = <0 0xee200000 0 0x80>;
                interrupt-parent = <&gic>;
-               interrupts = <0 169 0x4>;
+               interrupts = <0 169 IRQ_TYPE_LEVEL_HIGH>;
                reg-io-width = <4>;
                status = "disabled";
        };
 
-       mmcif1: mmcif@ee220000 {
+       mmcif1: mmc@ee220000 {
                compatible = "renesas,sh-mmcif";
                reg = <0 0xee220000 0 0x80>;
                interrupt-parent = <&gic>;
-               interrupts = <0 170 0x4>;
+               interrupts = <0 170 IRQ_TYPE_LEVEL_HIGH>;
                reg-io-width = <4>;
                status = "disabled";
        };
                #gpio-cells = <2>;
        };
 
-       sdhi0: sdhi@ee100000 {
+       sdhi0: sd@ee100000 {
                compatible = "renesas,sdhi-r8a73a4";
                reg = <0 0xee100000 0 0x100>;
                interrupt-parent = <&gic>;
-               interrupts = <0 165 4>;
+               interrupts = <0 165 IRQ_TYPE_LEVEL_HIGH>;
                cap-sd-highspeed;
                status = "disabled";
        };
 
-       sdhi1: sdhi@ee120000 {
+       sdhi1: sd@ee120000 {
                compatible = "renesas,sdhi-r8a73a4";
                reg = <0 0xee120000 0 0x100>;
                interrupt-parent = <&gic>;
-               interrupts = <0 166 4>;
+               interrupts = <0 166 IRQ_TYPE_LEVEL_HIGH>;
                cap-sd-highspeed;
                status = "disabled";
        };
 
-       sdhi2: sdhi@ee140000 {
+       sdhi2: sd@ee140000 {
                compatible = "renesas,sdhi-r8a73a4";
                reg = <0 0xee140000 0 0x100>;
                interrupt-parent = <&gic>;
-               interrupts = <0 167 4>;
+               interrupts = <0 167 IRQ_TYPE_LEVEL_HIGH>;
                cap-sd-highspeed;
                status = "disabled";
        };
index 1c56c5e56950846217471ae98ee00c5bed4922ac..6d6fd3dff2d3f68b3db92e7ba98fb4048bb50214 100644 (file)
@@ -9,8 +9,9 @@
  */
 
 /dts-v1/;
-/include/ "r8a7740.dtsi"
+#include "r8a7740.dtsi"
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/pwm/pwm.h>
 
 / {
                pinctrl-0 = <&backlight_pins>;
                pinctrl-names = "default";
        };
+
+       sound {
+               compatible = "simple-audio-card";
+
+               simple-audio-card,format = "i2s";
+
+               simple-audio-card,cpu {
+                       sound-dai = <&sh_fsi2 0>;
+                       bitclock-inversion;
+               };
+
+               simple-audio-card,codec {
+                       sound-dai = <&wm8978>;
+                       bitclock-master;
+                       frame-master;
+                       system-clock-frequency = <12288000>;
+               };
+       };
 };
 
 &i2c0 {
        status = "okay";
-       touchscreen: st1232@55 {
+       touchscreen@55 {
                compatible = "sitronix,st1232";
                reg = <0x55>;
                interrupt-parent = <&irqpin1>;
-               interrupts = <2 0>; /* IRQ10: hwirq 2 on irqpin1 */
+               interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
                pinctrl-0 = <&st1232_pins>;
                pinctrl-names = "default";
                gpios = <&pfc 166 GPIO_ACTIVE_LOW>;
        };
+
+       wm8978: wm8978@1a {
+               #sound-dai-cells = <0>;
+               compatible = "wlf,wm8978";
+               reg = <0x1a>;
+       };
 };
 
 &pfc {
        pinctrl-0 = <&scifa1_pins>;
        pinctrl-names = "default";
 
-       scifa1_pins: scifa1 {
+       scifa1_pins: serial1 {
                renesas,groups = "scifa1_data";
                renesas,function = "scifa1";
        };
 
-       st1232_pins: st1232 {
+       st1232_pins: touchscreen {
                renesas,groups = "intc_irq10";
                renesas,function = "intc";
        };
                renesas,function = "mmc0";
        };
 
-       sdhi0_pins: sdhi0 {
+       sdhi0_pins: sd0 {
                renesas,groups = "sdhi0_data4", "sdhi0_ctrl", "sdhi0_wp";
                renesas,function = "sdhi0";
        };
+
+       fsia_pins: sounda {
+               renesas,groups = "fsia_sclk_in", "fsia_mclk_out",
+                                "fsia_data_in_1", "fsia_data_out_0";
+               renesas,function = "fsia";
+       };
 };
 
 &tpu {
        cd-gpios = <&pfc 167 GPIO_ACTIVE_LOW>;
        status = "okay";
 };
+
+&sh_fsi2 {
+       pinctrl-0 = <&fsia_pins>;
+       pinctrl-names = "default";
+
+       status = "okay";
+};
index 426cd9c3e1c430fc214651809be12c489b2765b9..a06a11e1a84026efaf0cc39914e7629c1fde72a1 100644 (file)
@@ -9,7 +9,7 @@
  */
 
 /dts-v1/;
-/include/ "r8a7740.dtsi"
+#include "r8a7740.dtsi"
 
 / {
        model = "armadillo 800 eva";
index ae1e230f711ddf243168abc55cfc6cd3e3095cf8..2782f642acfcc413007ab5720c04fe188f1372bd 100644 (file)
@@ -10,6 +10,8 @@
 
 /include/ "skeleton.dtsi"
 
+#include <dt-bindings/interrupt-controller/irq.h>
+
 / {
        compatible = "renesas,r8a7740";
 
 
        pmu {
                compatible = "arm,cortex-a9-pmu";
-               interrupts = <0 83 4>;
+               interrupts = <0 83 IRQ_TYPE_LEVEL_HIGH>;
        };
 
        /* irqpin0: IRQ0 - IRQ7 */
        irqpin0: irqpin@e6900000 {
-               compatible = "renesas,intc-irqpin";
+               compatible = "renesas,intc-irqpin-r8a7740", "renesas,intc-irqpin";
                #interrupt-cells = <2>;
                interrupt-controller;
                reg = <0xe6900000 4>,
                        <0xe6900040 1>,
                        <0xe6900060 1>;
                interrupt-parent = <&gic>;
-               interrupts = <0 149 0x4
-                             0 149 0x4
-                             0 149 0x4
-                             0 149 0x4
-                             0 149 0x4
-                             0 149 0x4
-                             0 149 0x4
-                             0 149 0x4>;
+               interrupts = <0 149 IRQ_TYPE_LEVEL_HIGH
+                             0 149 IRQ_TYPE_LEVEL_HIGH
+                             0 149 IRQ_TYPE_LEVEL_HIGH
+                             0 149 IRQ_TYPE_LEVEL_HIGH
+                             0 149 IRQ_TYPE_LEVEL_HIGH
+                             0 149 IRQ_TYPE_LEVEL_HIGH
+                             0 149 IRQ_TYPE_LEVEL_HIGH
+                             0 149 IRQ_TYPE_LEVEL_HIGH>;
        };
 
        /* irqpin1: IRQ8 - IRQ15 */
        irqpin1: irqpin@e6900004 {
-               compatible = "renesas,intc-irqpin";
+               compatible = "renesas,intc-irqpin-r8a7740", "renesas,intc-irqpin";
                #interrupt-cells = <2>;
                interrupt-controller;
                reg = <0xe6900004 4>,
                        <0xe6900044 1>,
                        <0xe6900064 1>;
                interrupt-parent = <&gic>;
-               interrupts = <0 149 0x4
-                             0 149 0x4
-                             0 149 0x4
-                             0 149 0x4
-                             0 149 0x4
-                             0 149 0x4
-                             0 149 0x4
-                             0 149 0x4>;
+               interrupts = <0 149 IRQ_TYPE_LEVEL_HIGH
+                             0 149 IRQ_TYPE_LEVEL_HIGH
+                             0 149 IRQ_TYPE_LEVEL_HIGH
+                             0 149 IRQ_TYPE_LEVEL_HIGH
+                             0 149 IRQ_TYPE_LEVEL_HIGH
+                             0 149 IRQ_TYPE_LEVEL_HIGH
+                             0 149 IRQ_TYPE_LEVEL_HIGH
+                             0 149 IRQ_TYPE_LEVEL_HIGH>;
        };
 
        /* irqpin2: IRQ16 - IRQ23 */
        irqpin2: irqpin@e6900008 {
-               compatible = "renesas,intc-irqpin";
+               compatible = "renesas,intc-irqpin-r8a7740", "renesas,intc-irqpin";
                #interrupt-cells = <2>;
                interrupt-controller;
                reg = <0xe6900008 4>,
                        <0xe6900048 1>,
                        <0xe6900068 1>;
                interrupt-parent = <&gic>;
-               interrupts = <0 149 0x4
-                             0 149 0x4
-                             0 149 0x4
-                             0 149 0x4
-                             0 149 0x4
-                             0 149 0x4
-                             0 149 0x4
-                             0 149 0x4>;
+               interrupts = <0 149 IRQ_TYPE_LEVEL_HIGH
+                             0 149 IRQ_TYPE_LEVEL_HIGH
+                             0 149 IRQ_TYPE_LEVEL_HIGH
+                             0 149 IRQ_TYPE_LEVEL_HIGH
+                             0 149 IRQ_TYPE_LEVEL_HIGH
+                             0 149 IRQ_TYPE_LEVEL_HIGH
+                             0 149 IRQ_TYPE_LEVEL_HIGH
+                             0 149 IRQ_TYPE_LEVEL_HIGH>;
        };
 
        /* irqpin3: IRQ24 - IRQ31 */
        irqpin3: irqpin@e690000c {
-               compatible = "renesas,intc-irqpin";
+               compatible = "renesas,intc-irqpin-r8a7740", "renesas,intc-irqpin";
                #interrupt-cells = <2>;
                interrupt-controller;
                reg = <0xe690000c 4>,
                        <0xe690004c 1>,
                        <0xe690006c 1>;
                interrupt-parent = <&gic>;
-               interrupts = <0 149 0x4
-                             0 149 0x4
-                             0 149 0x4
-                             0 149 0x4
-                             0 149 0x4
-                             0 149 0x4
-                             0 149 0x4
-                             0 149 0x4>;
+               interrupts = <0 149 IRQ_TYPE_LEVEL_HIGH
+                             0 149 IRQ_TYPE_LEVEL_HIGH
+                             0 149 IRQ_TYPE_LEVEL_HIGH
+                             0 149 IRQ_TYPE_LEVEL_HIGH
+                             0 149 IRQ_TYPE_LEVEL_HIGH
+                             0 149 IRQ_TYPE_LEVEL_HIGH
+                             0 149 IRQ_TYPE_LEVEL_HIGH
+                             0 149 IRQ_TYPE_LEVEL_HIGH>;
        };
 
        i2c0: i2c@fff20000 {
                compatible = "renesas,rmobile-iic";
                reg = <0xfff20000 0x425>;
                interrupt-parent = <&gic>;
-               interrupts = <0 201 0x4
-                             0 202 0x4
-                             0 203 0x4
-                             0 204 0x4>;
+               interrupts = <0 201 IRQ_TYPE_LEVEL_HIGH
+                             0 202 IRQ_TYPE_LEVEL_HIGH
+                             0 203 IRQ_TYPE_LEVEL_HIGH
+                             0 204 IRQ_TYPE_LEVEL_HIGH>;
                status = "disabled";
        };
 
                compatible = "renesas,rmobile-iic";
                reg = <0xe6c20000 0x425>;
                interrupt-parent = <&gic>;
-               interrupts = <0 70 0x4
-                             0 71 0x4
-                             0 72 0x4
-                             0 73 0x4>;
+               interrupts = <0 70 IRQ_TYPE_LEVEL_HIGH
+                             0 71 IRQ_TYPE_LEVEL_HIGH
+                             0 72 IRQ_TYPE_LEVEL_HIGH
+                             0 73 IRQ_TYPE_LEVEL_HIGH>;
                status = "disabled";
        };
 
                #pwm-cells = <3>;
        };
 
-       mmcif0: mmcif@e6bd0000 {
+       mmcif0: mmc@e6bd0000 {
                compatible = "renesas,sh-mmcif";
                reg = <0xe6bd0000 0x100>;
                interrupt-parent = <&gic>;
-               interrupts = <0 56 4
-                               0 57 4>;
+               interrupts = <0 56 IRQ_TYPE_LEVEL_HIGH
+                             0 57 IRQ_TYPE_LEVEL_HIGH>;
                status = "disabled";
        };
 
-       sdhi0: sdhi@e6850000 {
+       sdhi0: sd@e6850000 {
                compatible = "renesas,sdhi-r8a7740";
                reg = <0xe6850000 0x100>;
                interrupt-parent = <&gic>;
-               interrupts = <0 117 4
-                               0 118 4
-                               0 119 4>;
+               interrupts = <0 117 IRQ_TYPE_LEVEL_HIGH
+                             0 118 IRQ_TYPE_LEVEL_HIGH
+                             0 119 IRQ_TYPE_LEVEL_HIGH>;
                cap-sd-highspeed;
                cap-sdio-irq;
                status = "disabled";
        };
 
-       sdhi1: sdhi@e6860000 {
+       sdhi1: sd@e6860000 {
                compatible = "renesas,sdhi-r8a7740";
                reg = <0xe6860000 0x100>;
                interrupt-parent = <&gic>;
-               interrupts = <0 121 4
-                               0 122 4
-                               0 123 4>;
+               interrupts = <0 121 IRQ_TYPE_LEVEL_HIGH
+                             0 122 IRQ_TYPE_LEVEL_HIGH
+                             0 123 IRQ_TYPE_LEVEL_HIGH>;
+               cap-sd-highspeed;
+               cap-sdio-irq;
+               status = "disabled";
+       };
+
+       sdhi2: sd@e6870000 {
+               compatible = "renesas,sdhi-r8a7740";
+               reg = <0xe6870000 0x100>;
+               interrupt-parent = <&gic>;
+               interrupts = <0 125 IRQ_TYPE_LEVEL_HIGH
+                             0 126 IRQ_TYPE_LEVEL_HIGH
+                             0 127 IRQ_TYPE_LEVEL_HIGH>;
                cap-sd-highspeed;
                cap-sdio-irq;
                status = "disabled";
        };
+
+       sh_fsi2: sound@fe1f0000 {
+               #sound-dai-cells = <1>;
+               compatible = "renesas,sh_fsi2";
+               reg = <0xfe1f0000 0x400>;
+               interrupt-parent = <&gic>;
+               interrupts = <0 9 0x4>;
+               status = "disabled";
+       };
 };
index 969e386e852c443f0b5bb95440a0e595d491c04e..bb62c7a906f47c7b52b8563aedcaf6ae56e46197 100644 (file)
@@ -15,7 +15,8 @@
  */
 
 /dts-v1/;
-/include/ "r8a7778.dtsi"
+#include "r8a7778.dtsi"
+#include <dt-bindings/interrupt-controller/irq.h>
 
 / {
        model = "bockw";
 
                phy-mode = "mii";
                interrupt-parent = <&irqpin>;
-               interrupts = <0 0>; /* IRQ0: hwirq 0 on irqpin */
+               interrupts = <0 IRQ_TYPE_EDGE_FALLING>;
                reg-io-width = <4>;
                vddvario-supply = <&fixedregulator3v3>;
                vdd33a-supply = <&fixedregulator3v3>;
        };
+
+};
+
+&mmcif {
+       pinctrl-0 = <&mmc_pins>;
+       pinctrl-names = "default";
+
+       vmmc-supply = <&fixedregulator3v3>;
+       bus-width = <8>;
+       broken-cd;
+       status = "okay";
 };
 
 &irqpin {
        status = "okay";
 };
+
+&pfc {
+       pinctrl-0 = <&scif0_pins>;
+       pinctrl-names = "default";
+
+       scif0_pins: serial0 {
+               renesas,groups = "scif0_data_a", "scif0_ctrl";
+               renesas,function = "scif0";
+       };
+
+       mmc_pins: mmc {
+               renesas,groups = "mmc_data8", "mmc_ctrl";
+               renesas,function = "mmc";
+       };
+
+       sdhi0_pins: sd0 {
+               renesas,groups = "sdhi0_data4", "sdhi0_ctrl",
+                                 "sdhi0_cd", "sdhi0_wp";
+               renesas,function = "sdhi0";
+       };
+
+       hspi0_pins: hspi0 {
+               renesas,groups = "hspi0_a";
+               renesas,function = "hspi0";
+       };
+};
+
+&sdhi0 {
+       pinctrl-0 = <&sdhi0_pins>;
+       pinctrl-names = "default";
+
+       vmmc-supply = <&fixedregulator3v3>;
+       bus-width = <4>;
+       status = "okay";
+};
+
+&hspi0 {
+       pinctrl-0 = <&hspi0_pins>;
+       pinctrl-names = "default";
+       status = "okay";
+};
index 12bbebc9c95594bcbcc7093c472c42a4b0a492ca..46a884d4517566959992b98901d6a13b94064798 100644 (file)
@@ -15,7 +15,7 @@
  */
 
 /dts-v1/;
-/include/ "r8a7778.dtsi"
+#include "r8a7778.dtsi"
 
 / {
        model = "bockw";
index a6308a399e2d2dbbf4fed33ee943b37f98ed0991..ddb3bd7a8838f63f8a1f369c9778d7a8c2519392 100644 (file)
@@ -16,6 +16,8 @@
 
 /include/ "skeleton.dtsi"
 
+#include <dt-bindings/interrupt-controller/irq.h>
+
 / {
        compatible = "renesas,r8a7778";
 
                };
        };
 
+       aliases {
+               spi0 = &hspi0;
+               spi1 = &hspi1;
+               spi2 = &hspi2;
+       };
+
        gic: interrupt-controller@fe438000 {
                compatible = "arm,cortex-a9-gic";
                #interrupt-cells = <3>;
@@ -35,7 +43,7 @@
 
        /* irqpin: IRQ0 - IRQ3 */
        irqpin: irqpin@fe78001c {
-               compatible = "renesas,intc-irqpin";
+               compatible = "renesas,intc-irqpin-r8a7778", "renesas,intc-irqpin";
                #interrupt-cells = <2>;
                interrupt-controller;
                status = "disabled"; /* default off */
                        <0xfe780044 4>,
                        <0xfe780064 4>;
                interrupt-parent = <&gic>;
-               interrupts =   <0 27 0x4
-                               0 28 0x4
-                               0 29 0x4
-                               0 30 0x4>;
+               interrupts =   <0 27 IRQ_TYPE_LEVEL_HIGH
+                               0 28 IRQ_TYPE_LEVEL_HIGH
+                               0 29 IRQ_TYPE_LEVEL_HIGH
+                               0 30 IRQ_TYPE_LEVEL_HIGH>;
                sense-bitfield-width = <2>;
        };
 
@@ -56,7 +64,7 @@
                compatible = "renesas,gpio-r8a7778", "renesas,gpio-rcar";
                reg = <0xffc40000 0x2c>;
                interrupt-parent = <&gic>;
-               interrupts = <0 103 0x4>;
+               interrupts = <0 103 IRQ_TYPE_LEVEL_HIGH>;
                #gpio-cells = <2>;
                gpio-controller;
                gpio-ranges = <&pfc 0 0 32>;
@@ -68,7 +76,7 @@
                compatible = "renesas,gpio-r8a7778", "renesas,gpio-rcar";
                reg = <0xffc41000 0x2c>;
                interrupt-parent = <&gic>;
-               interrupts = <0 103 0x4>;
+               interrupts = <0 103 IRQ_TYPE_LEVEL_HIGH>;
                #gpio-cells = <2>;
                gpio-controller;
                gpio-ranges = <&pfc 0 32 32>;
@@ -80,7 +88,7 @@
                compatible = "renesas,gpio-r8a7778", "renesas,gpio-rcar";
                reg = <0xffc42000 0x2c>;
                interrupt-parent = <&gic>;
-               interrupts = <0 103 0x4>;
+               interrupts = <0 103 IRQ_TYPE_LEVEL_HIGH>;
                #gpio-cells = <2>;
                gpio-controller;
                gpio-ranges = <&pfc 0 64 32>;
                compatible = "renesas,gpio-r8a7778", "renesas,gpio-rcar";
                reg = <0xffc43000 0x2c>;
                interrupt-parent = <&gic>;
-               interrupts = <0 103 0x4>;
+               interrupts = <0 103 IRQ_TYPE_LEVEL_HIGH>;
                #gpio-cells = <2>;
                gpio-controller;
                gpio-ranges = <&pfc 0 96 32>;
                compatible = "renesas,gpio-r8a7778", "renesas,gpio-rcar";
                reg = <0xffc44000 0x2c>;
                interrupt-parent = <&gic>;
-               interrupts = <0 103 0x4>;
+               interrupts = <0 103 IRQ_TYPE_LEVEL_HIGH>;
                #gpio-cells = <2>;
                gpio-controller;
                gpio-ranges = <&pfc 0 128 27>;
 
        pfc: pfc@fffc0000 {
                compatible = "renesas,pfc-r8a7778";
-               reg = <0xfffc000 0x118>;
+               reg = <0xfffc0000 0x118>;
+       };
+
+       i2c0: i2c@ffc70000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "renesas,i2c-r8a7778";
+               reg = <0xffc70000 0x1000>;
+               interrupt-parent = <&gic>;
+               interrupts = <0 67 IRQ_TYPE_LEVEL_HIGH>;
+               status = "disabled";
+       };
+
+       i2c1: i2c@ffc71000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "renesas,i2c-r8a7778";
+               reg = <0xffc71000 0x1000>;
+               interrupt-parent = <&gic>;
+               interrupts = <0 78 IRQ_TYPE_LEVEL_HIGH>;
+               status = "disabled";
+       };
+
+       i2c2: i2c@ffc72000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "renesas,i2c-r8a7778";
+               reg = <0xffc72000 0x1000>;
+               interrupt-parent = <&gic>;
+               interrupts = <0 76 IRQ_TYPE_LEVEL_HIGH>;
+               status = "disabled";
+       };
+
+       i2c3: i2c@ffc73000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "renesas,i2c-r8a7778";
+               reg = <0xffc73000 0x1000>;
+               interrupt-parent = <&gic>;
+               interrupts = <0 77 IRQ_TYPE_LEVEL_HIGH>;
+               status = "disabled";
+       };
+
+       mmcif: mmc@ffe4e000 {
+               compatible = "renesas,sh-mmcif";
+               reg = <0xffe4e000 0x100>;
+               interrupt-parent = <&gic>;
+               interrupts = <0 61 IRQ_TYPE_LEVEL_HIGH>;
+               status = "disabled";
+       };
+
+       sdhi0: sd@ffe4c000 {
+               compatible = "renesas,sdhi-r8a7778";
+               reg = <0xffe4c000 0x100>;
+               interrupt-parent = <&gic>;
+               interrupts = <0 87 IRQ_TYPE_LEVEL_HIGH>;
+               cap-sd-highspeed;
+               cap-sdio-irq;
+               status = "disabled";
+       };
+
+       sdhi1: sd@ffe4d000 {
+               compatible = "renesas,sdhi-r8a7778";
+               reg = <0xffe4d000 0x100>;
+               interrupt-parent = <&gic>;
+               interrupts = <0 88 IRQ_TYPE_LEVEL_HIGH>;
+               cap-sd-highspeed;
+               cap-sdio-irq;
+               status = "disabled";
+       };
+
+       sdhi2: sd@ffe4f000 {
+               compatible = "renesas,sdhi-r8a7778";
+               reg = <0xffe4f000 0x100>;
+               interrupt-parent = <&gic>;
+               interrupts = <0 86 IRQ_TYPE_LEVEL_HIGH>;
+               cap-sd-highspeed;
+               cap-sdio-irq;
+               status = "disabled";
+       };
+
+       i2c0: i2c@ffc70000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "renesas,i2c-r8a7778";
+               reg = <0xffc70000 0x1000>;
+               interrupt-parent = <&gic>;
+               interrupts = <0 67 IRQ_TYPE_LEVEL_HIGH>;
+               status = "disabled";
+       };
+
+       i2c1: i2c@ffc71000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "renesas,i2c-r8a7778";
+               reg = <0xffc71000 0x1000>;
+               interrupt-parent = <&gic>;
+               interrupts = <0 78 IRQ_TYPE_LEVEL_HIGH>;
+               status = "disabled";
+       };
+
+       i2c2: i2c@ffc72000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "renesas,i2c-r8a7778";
+               reg = <0xffc72000 0x1000>;
+               interrupt-parent = <&gic>;
+               interrupts = <0 76 IRQ_TYPE_LEVEL_HIGH>;
+               status = "disabled";
+       };
+
+       i2c3: i2c@ffc73000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "renesas,i2c-r8a7778";
+               reg = <0xffc73000 0x1000>;
+               interrupt-parent = <&gic>;
+               interrupts = <0 77 IRQ_TYPE_LEVEL_HIGH>;
+               status = "disabled";
+       };
+
+       hspi0: spi@fffc7000 {
+               compatible = "renesas,hspi";
+               reg = <0xfffc7000 0x18>;
+               interrupt-controller = <&gic>;
+               interrupts = <0 63 IRQ_TYPE_LEVEL_HIGH>;
+               status = "disabled";
+       };
+
+       hspi1: spi@fffc8000 {
+               compatible = "renesas,hspi";
+               reg = <0xfffc8000 0x18>;
+               interrupt-controller = <&gic>;
+               interrupts = <0 84 IRQ_TYPE_LEVEL_HIGH>;
+               status = "disabled";
+       };
+
+       hspi2: spi@fffc6000 {
+               compatible = "renesas,hspi";
+               reg = <0xfffc6000 0x18>;
+               interrupt-controller = <&gic>;
+               interrupts = <0 85 IRQ_TYPE_LEVEL_HIGH>;
+               status = "disabled";
        };
 };
index ab4110aa3c3b5a4ad31f1600959195099f8ace9c..76f5eef7d1cce9055587164f5a157a48ec66956a 100644 (file)
@@ -10,8 +10,9 @@
  */
 
 /dts-v1/;
-/include/ "r8a7779.dtsi"
+#include "r8a7779.dtsi"
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
 
 / {
        model = "marzen";
@@ -43,7 +44,7 @@
 
                phy-mode = "mii";
                interrupt-parent = <&irqpin0>;
-               interrupts = <1 0>; /* IRQ1: hwirq 1 on irqpin0 */
+               interrupts = <1 IRQ_TYPE_EDGE_FALLING>;
                reg-io-width = <4>;
                vddvario-supply = <&fixedregulator3v3>;
                vdd33a-supply = <&fixedregulator3v3>;
@@ -68,7 +69,7 @@
 };
 
 &pfc {
-       pinctrl-0 = <&scif2_pins &scif4_pins &sdhi0_pins>;
+       pinctrl-0 = <&scif2_pins &scif4_pins>;
        pinctrl-names = "default";
 
        lan0_pins: lan0 {
                };
        };
 
-       scif2_pins: scif2 {
+       scif2_pins: serial2 {
                renesas,groups = "scif2_data_c";
                renesas,function = "scif2";
        };
 
-       scif4_pins: scif4 {
+       scif4_pins: serial4 {
                renesas,groups = "scif4_data";
                renesas,function = "scif4";
        };
 
-       sdhi0_pins: sdhi0 {
-               renesas,groups = "sdhi0_data4", "sdhi0_ctrl", "sdhi0_cd",
-                                "sdhi0_wp";
+       sdhi0_pins: sd0 {
+               renesas,groups = "sdhi0_data4", "sdhi0_ctrl", "sdhi0_cd";
                renesas,function = "sdhi0";
        };
+
+       hspi0_pins: hspi0 {
+               renesas,groups = "hspi0";
+               renesas,function = "hspi0";
+       };
+};
+
+&sdhi0 {
+       pinctrl-0 = <&sdhi0_pins>;
+       pinctrl-names = "default";
+
+       vmmc-supply = <&fixedregulator3v3>;
+       bus-width = <4>;
+       status = "okay";
+};
+
+&hspi0 {
+       pinctrl-0 = <&hspi0_pins>;
+       pinctrl-names = "default";
+       status = "okay";
 };
index f3f7f79997360d65c7a8d5bfeeba9d23e76168d3..a7af2c2371f2581b6e9f8e1e43a064eef46bc60e 100644 (file)
@@ -10,7 +10,7 @@
  */
 
 /dts-v1/;
-/include/ "r8a7779.dtsi"
+#include "r8a7779.dtsi"
 
 / {
        model = "marzen";
index 19faeac3fd2e1b74f5d289948dd486f473f931de..d0561d4c7c466056096969331d467f6196b9ff63 100644 (file)
@@ -11,6 +11,8 @@
 
 /include/ "skeleton.dtsi"
 
+#include <dt-bindings/interrupt-controller/irq.h>
+
 / {
        compatible = "renesas,r8a7779";
 
                };
        };
 
+       aliases {
+               spi0 = &hspi0;
+               spi1 = &hspi1;
+               spi2 = &hspi2;
+       };
+
         gic: interrupt-controller@f0001000 {
                 compatible = "arm,cortex-a9-gic";
                 #interrupt-cells = <3>;
@@ -52,7 +60,7 @@
                compatible = "renesas,gpio-r8a7779", "renesas,gpio-rcar";
                reg = <0xffc40000 0x2c>;
                interrupt-parent = <&gic>;
-               interrupts = <0 141 0x4>;
+               interrupts = <0 141 IRQ_TYPE_LEVEL_HIGH>;
                #gpio-cells = <2>;
                gpio-controller;
                gpio-ranges = <&pfc 0 0 32>;
@@ -64,7 +72,7 @@
                compatible = "renesas,gpio-r8a7779", "renesas,gpio-rcar";
                reg = <0xffc41000 0x2c>;
                interrupt-parent = <&gic>;
-               interrupts = <0 142 0x4>;
+               interrupts = <0 142 IRQ_TYPE_LEVEL_HIGH>;
                #gpio-cells = <2>;
                gpio-controller;
                gpio-ranges = <&pfc 0 32 32>;
@@ -76,7 +84,7 @@
                compatible = "renesas,gpio-r8a7779", "renesas,gpio-rcar";
                reg = <0xffc42000 0x2c>;
                interrupt-parent = <&gic>;
-               interrupts = <0 143 0x4>;
+               interrupts = <0 143 IRQ_TYPE_LEVEL_HIGH>;
                #gpio-cells = <2>;
                gpio-controller;
                gpio-ranges = <&pfc 0 64 32>;
@@ -88,7 +96,7 @@
                compatible = "renesas,gpio-r8a7779", "renesas,gpio-rcar";
                reg = <0xffc43000 0x2c>;
                interrupt-parent = <&gic>;
-               interrupts = <0 144 0x4>;
+               interrupts = <0 144 IRQ_TYPE_LEVEL_HIGH>;
                #gpio-cells = <2>;
                gpio-controller;
                gpio-ranges = <&pfc 0 96 32>;
                compatible = "renesas,gpio-r8a7779", "renesas,gpio-rcar";
                reg = <0xffc44000 0x2c>;
                interrupt-parent = <&gic>;
-               interrupts = <0 145 0x4>;
+               interrupts = <0 145 IRQ_TYPE_LEVEL_HIGH>;
                #gpio-cells = <2>;
                gpio-controller;
                gpio-ranges = <&pfc 0 128 32>;
                compatible = "renesas,gpio-r8a7779", "renesas,gpio-rcar";
                reg = <0xffc45000 0x2c>;
                interrupt-parent = <&gic>;
-               interrupts = <0 146 0x4>;
+               interrupts = <0 146 IRQ_TYPE_LEVEL_HIGH>;
                #gpio-cells = <2>;
                gpio-controller;
                gpio-ranges = <&pfc 0 160 32>;
                compatible = "renesas,gpio-r8a7779", "renesas,gpio-rcar";
                reg = <0xffc46000 0x2c>;
                interrupt-parent = <&gic>;
-               interrupts = <0 147 0x4>;
+               interrupts = <0 147 IRQ_TYPE_LEVEL_HIGH>;
                #gpio-cells = <2>;
                gpio-controller;
                gpio-ranges = <&pfc 0 192 9>;
        };
 
        irqpin0: irqpin@fe780010 {
-               compatible = "renesas,intc-irqpin";
+               compatible = "renesas,intc-irqpin-r8a7779", "renesas,intc-irqpin";
                #interrupt-cells = <2>;
                status = "disabled";
                interrupt-controller;
                        <0xfe780044 4>,
                        <0xfe780064 4>;
                interrupt-parent = <&gic>;
-               interrupts = <0 27 0x4
-                               0 28 0x4
-                               0 29 0x4
-                               0 30 0x4>;
+               interrupts = <0 27 IRQ_TYPE_LEVEL_HIGH
+                             0 28 IRQ_TYPE_LEVEL_HIGH
+                             0 29 IRQ_TYPE_LEVEL_HIGH
+                             0 30 IRQ_TYPE_LEVEL_HIGH>;
                sense-bitfield-width = <2>;
        };
 
        i2c0: i2c@ffc70000 {
                #address-cells = <1>;
                #size-cells = <0>;
-               compatible = "renesas,rmobile-iic";
+               compatible = "renesas,i2c-r8a7779";
                reg = <0xffc70000 0x1000>;
                interrupt-parent = <&gic>;
-               interrupts = <0 79 0x4>;
+               interrupts = <0 79 IRQ_TYPE_LEVEL_HIGH>;
                status = "disabled";
        };
 
        i2c1: i2c@ffc71000 {
                #address-cells = <1>;
                #size-cells = <0>;
-               compatible = "renesas,rmobile-iic";
+               compatible = "renesas,i2c-r8a7779";
                reg = <0xffc71000 0x1000>;
                interrupt-parent = <&gic>;
-               interrupts = <0 82 0x4>;
+               interrupts = <0 82 IRQ_TYPE_LEVEL_HIGH>;
                status = "disabled";
        };
 
        i2c2: i2c@ffc72000 {
                #address-cells = <1>;
                #size-cells = <0>;
-               compatible = "renesas,rmobile-iic";
+               compatible = "renesas,i2c-r8a7779";
                reg = <0xffc72000 0x1000>;
                interrupt-parent = <&gic>;
-               interrupts = <0 80 0x4>;
+               interrupts = <0 80 IRQ_TYPE_LEVEL_HIGH>;
                status = "disabled";
        };
 
        i2c3: i2c@ffc73000 {
                #address-cells = <1>;
                #size-cells = <0>;
-               compatible = "renesas,rmobile-iic";
+               compatible = "renesas,i2c-r8a7779";
                reg = <0xffc73000 0x1000>;
                interrupt-parent = <&gic>;
-               interrupts = <0 81 0x4>;
+               interrupts = <0 81 IRQ_TYPE_LEVEL_HIGH>;
                status = "disabled";
        };
 
                compatible = "renesas,rcar-sata";
                reg = <0xfc600000 0x2000>;
                interrupt-parent = <&gic>;
-               interrupts = <0 100 0x4>;
+               interrupts = <0 100 IRQ_TYPE_LEVEL_HIGH>;
+       };
+
+       sdhi0: sd@ffe4c000 {
+               compatible = "renesas,sdhi-r8a7779";
+               reg = <0xffe4c000 0x100>;
+               interrupt-parent = <&gic>;
+               interrupts = <0 104 IRQ_TYPE_LEVEL_HIGH>;
+               cap-sd-highspeed;
+               cap-sdio-irq;
+               status = "disabled";
+       };
+
+       sdhi1: sd@ffe4d000 {
+               compatible = "renesas,sdhi-r8a7779";
+               reg = <0xffe4d000 0x100>;
+               interrupt-parent = <&gic>;
+               interrupts = <0 105 IRQ_TYPE_LEVEL_HIGH>;
+               cap-sd-highspeed;
+               cap-sdio-irq;
+               status = "disabled";
+       };
+
+       sdhi2: sd@ffe4e000 {
+               compatible = "renesas,sdhi-r8a7779";
+               reg = <0xffe4e000 0x100>;
+               interrupt-parent = <&gic>;
+               interrupts = <0 107 IRQ_TYPE_LEVEL_HIGH>;
+               cap-sd-highspeed;
+               cap-sdio-irq;
+               status = "disabled";
+       };
+
+       sdhi3: sd@ffe4f000 {
+               compatible = "renesas,sdhi-r8a7779";
+               reg = <0xffe4f000 0x100>;
+               interrupt-parent = <&gic>;
+               interrupts = <0 106 IRQ_TYPE_LEVEL_HIGH>;
+               cap-sd-highspeed;
+               cap-sdio-irq;
+               status = "disabled";
+       };
+
+       hspi0: spi@fffc7000 {
+               compatible = "renesas,hspi";
+               reg = <0xfffc7000 0x18>;
+               interrupt-controller = <&gic>;
+               interrupts = <0 73 IRQ_TYPE_LEVEL_HIGH>;
+               status = "disabled";
+       };
+
+       hspi1: spi@fffc8000 {
+               compatible = "renesas,hspi";
+               reg = <0xfffc8000 0x18>;
+               interrupt-controller = <&gic>;
+               interrupts = <0 74 IRQ_TYPE_LEVEL_HIGH>;
+               status = "disabled";
+       };
+
+       hspi2: spi@fffc6000 {
+               compatible = "renesas,hspi";
+               reg = <0xfffc6000 0x18>;
+               interrupt-controller = <&gic>;
+               interrupts = <0 75 IRQ_TYPE_LEVEL_HIGH>;
+               status = "disabled";
        };
 };
index c462ef138922b260666434bc65a9f1d9f1fb31fe..dfedc0ea82e1c89e6ea6b1fea5a7c8d5a45a8ea0 100644 (file)
@@ -9,7 +9,7 @@
  */
 
 /dts-v1/;
-/include/ "r8a7790.dtsi"
+#include "r8a7790.dtsi"
 #include <dt-bindings/gpio/gpio.h>
 
 / {
                reg = <0 0x40000000 0 0x80000000>;
        };
 
+       memory@180000000 {
+               device_type = "memory";
+               reg = <1 0x80000000 0 0x80000000>;
+       };
+
        lbsc {
                #address-cells = <1>;
                #size-cells = <1>;
                        gpios = <&gpio5 17 GPIO_ACTIVE_HIGH>;
                };
        };
+
+       fixedregulator3v3: fixedregulator@0 {
+               compatible = "regulator-fixed";
+               regulator-name = "fixed-3.3V";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-boot-on;
+               regulator-always-on;
+       };
+};
+
+&pfc {
+       pinctrl-0 = <&scif0_pins &scif1_pins>;
+       pinctrl-names = "default";
+
+       scif0_pins: serial0 {
+               renesas,groups = "scif0_data";
+               renesas,function = "scif0";
+       };
+
+       scif1_pins: serial1 {
+               renesas,groups = "scif1_data";
+               renesas,function = "scif1";
+       };
+
+       mmc1_pins: mmc1 {
+               renesas,groups = "mmc1_data8", "mmc1_ctrl";
+               renesas,function = "mmc1";
+       };
+};
+
+&mmcif1 {
+       pinctrl-0 = <&mmc1_pins>;
+       pinctrl-names = "default";
+
+       vmmc-supply = <&fixedregulator3v3>;
+       bus-width = <8>;
+       non-removable;
+       status = "okay";
 };
index 203bd089af29d83355ed9b2ebdc029045012320f..10e6a08164e58998602da8d62f4487c75ee39673 100644 (file)
@@ -9,7 +9,7 @@
  */
 
 /dts-v1/;
-/include/ "r8a7790.dtsi"
+#include "r8a7790.dtsi"
 
 / {
        model = "Lager";
                reg = <0 0x40000000 0 0x80000000>;
        };
 
+       memory@180000000 {
+               device_type = "memory";
+               reg = <1 0x80000000 0 0x80000000>;
+       };
+
        lbsc {
                #address-cells = <1>;
                #size-cells = <1>;
index ee845fad939b895a1bfb907c6597f9f916d926f8..68b7b87e535f6343bd20ff6d1156ed60877f9cf5 100644 (file)
@@ -8,6 +8,9 @@
  * kind, whether express or implied.
  */
 
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
 / {
        compatible = "renesas,r8a7790";
        interrupt-parent = <&gic>;
                        <0 0xf1002000 0 0x1000>,
                        <0 0xf1004000 0 0x2000>,
                        <0 0xf1006000 0 0x2000>;
-               interrupts = <1 9 0xf04>;
+               interrupts = <1 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
        };
 
-       gpio0: gpio@ffc40000 {
+       gpio0: gpio@e6050000 {
                compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
-               reg = <0 0xffc40000 0 0x2c>;
+               reg = <0 0xe6050000 0 0x50>;
                interrupt-parent = <&gic>;
-               interrupts = <0 4 0x4>;
+               interrupts = <0 4 IRQ_TYPE_LEVEL_HIGH>;
                #gpio-cells = <2>;
                gpio-controller;
                gpio-ranges = <&pfc 0 0 32>;
                interrupt-controller;
        };
 
-       gpio1: gpio@ffc41000 {
+       gpio1: gpio@e6051000 {
                compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
-               reg = <0 0xffc41000 0 0x2c>;
+               reg = <0 0xe6051000 0 0x50>;
                interrupt-parent = <&gic>;
-               interrupts = <0 5 0x4>;
+               interrupts = <0 5 IRQ_TYPE_LEVEL_HIGH>;
                #gpio-cells = <2>;
                gpio-controller;
                gpio-ranges = <&pfc 0 32 32>;
                interrupt-controller;
        };
 
-       gpio2: gpio@ffc42000 {
+       gpio2: gpio@e6052000 {
                compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
-               reg = <0 0xffc42000 0 0x2c>;
+               reg = <0 0xe6052000 0 0x50>;
                interrupt-parent = <&gic>;
-               interrupts = <0 6 0x4>;
+               interrupts = <0 6 IRQ_TYPE_LEVEL_HIGH>;
                #gpio-cells = <2>;
                gpio-controller;
                gpio-ranges = <&pfc 0 64 32>;
                interrupt-controller;
        };
 
-       gpio3: gpio@ffc43000 {
+       gpio3: gpio@e6053000 {
                compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
-               reg = <0 0xffc43000 0 0x2c>;
+               reg = <0 0xe6053000 0 0x50>;
                interrupt-parent = <&gic>;
-               interrupts = <0 7 0x4>;
+               interrupts = <0 7 IRQ_TYPE_LEVEL_HIGH>;
                #gpio-cells = <2>;
                gpio-controller;
                gpio-ranges = <&pfc 0 96 32>;
                interrupt-controller;
        };
 
-       gpio4: gpio@ffc44000 {
+       gpio4: gpio@e6054000 {
                compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
-               reg = <0 0xffc44000 0 0x2c>;
+               reg = <0 0xe6054000 0 0x50>;
                interrupt-parent = <&gic>;
-               interrupts = <0 8 0x4>;
+               interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>;
                #gpio-cells = <2>;
                gpio-controller;
                gpio-ranges = <&pfc 0 128 32>;
                interrupt-controller;
        };
 
-       gpio5: gpio@ffc45000 {
+       gpio5: gpio@e6055000 {
                compatible = "renesas,gpio-r8a7790", "renesas,gpio-rcar";
-               reg = <0 0xffc45000 0 0x2c>;
+               reg = <0 0xe6055000 0 0x50>;
                interrupt-parent = <&gic>;
-               interrupts = <0 9 0x4>;
+               interrupts = <0 9 IRQ_TYPE_LEVEL_HIGH>;
                #gpio-cells = <2>;
                gpio-controller;
                gpio-ranges = <&pfc 0 160 32>;
                interrupt-controller;
        };
 
+       thermal@e61f0000 {
+               compatible = "renesas,thermal-r8a7790", "renesas,rcar-thermal";
+               reg = <0 0xe61f0000 0 0x14>, <0 0xe61f0100 0 0x38>;
+               interrupt-parent = <&gic>;
+               interrupts = <0 69 IRQ_TYPE_LEVEL_HIGH>;
+       };
+
        timer {
                compatible = "arm,armv7-timer";
-               interrupts = <1 13 0xf08>,
-                               <1 14 0xf08>,
-                               <1 11 0xf08>,
-                               <1 10 0xf08>;
+               interrupts = <1 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+                            <1 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+                            <1 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+                            <1 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
        };
 
        irqc0: interrupt-controller@e61c0000 {
-               compatible = "renesas,irqc";
+               compatible = "renesas,irqc-r8a7790", "renesas,irqc";
                #interrupt-cells = <2>;
                interrupt-controller;
                reg = <0 0xe61c0000 0 0x200>;
                interrupt-parent = <&gic>;
-               interrupts = <0 0 4>, <0 1 4>, <0 2 4>, <0 3 4>;
+               interrupts = <0 0 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 1 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 2 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 3 IRQ_TYPE_LEVEL_HIGH>;
        };
 
        i2c0: i2c@e6508000 {
                compatible = "renesas,i2c-r8a7790";
                reg = <0 0xe6508000 0 0x40>;
                interrupt-parent = <&gic>;
-               interrupts = <0 287 0x4>;
+               interrupts = <0 287 IRQ_TYPE_LEVEL_HIGH>;
                status = "disabled";
        };
 
                compatible = "renesas,i2c-r8a7790";
                reg = <0 0xe6518000 0 0x40>;
                interrupt-parent = <&gic>;
-               interrupts = <0 288 0x4>;
+               interrupts = <0 288 IRQ_TYPE_LEVEL_HIGH>;
                status = "disabled";
        };
 
                compatible = "renesas,i2c-r8a7790";
                reg = <0 0xe6530000 0 0x40>;
                interrupt-parent = <&gic>;
-               interrupts = <0 286 0x4>;
+               interrupts = <0 286 IRQ_TYPE_LEVEL_HIGH>;
                status = "disabled";
        };
 
                compatible = "renesas,i2c-r8a7790";
                reg = <0 0xe6540000 0 0x40>;
                interrupt-parent = <&gic>;
-               interrupts = <0 290 0x4>;
+               interrupts = <0 290 IRQ_TYPE_LEVEL_HIGH>;
                status = "disabled";
        };
 
        mmcif0: mmcif@ee200000 {
-               compatible = "renesas,sh-mmcif";
+               compatible = "renesas,mmcif-r8a7790", "renesas,sh-mmcif";
                reg = <0 0xee200000 0 0x80>;
                interrupt-parent = <&gic>;
-               interrupts = <0 169 0x4>;
+               interrupts = <0 169 IRQ_TYPE_LEVEL_HIGH>;
                reg-io-width = <4>;
                status = "disabled";
        };
 
-       mmcif1: mmcif@ee220000 {
-               compatible = "renesas,sh-mmcif";
+       mmcif1: mmc@ee220000 {
+               compatible = "renesas,mmcif-r8a7790", "renesas,sh-mmcif";
                reg = <0 0xee220000 0 0x80>;
                interrupt-parent = <&gic>;
-               interrupts = <0 170 0x4>;
+               interrupts = <0 170 IRQ_TYPE_LEVEL_HIGH>;
                reg-io-width = <4>;
                status = "disabled";
        };
                reg = <0 0xe6060000 0 0x250>;
        };
 
-       sdhi0: sdhi@ee100000 {
+       sdhi0: sd@ee100000 {
                compatible = "renesas,sdhi-r8a7790";
                reg = <0 0xee100000 0 0x100>;
                interrupt-parent = <&gic>;
-               interrupts = <0 165 4>;
+               interrupts = <0 165 IRQ_TYPE_LEVEL_HIGH>;
                cap-sd-highspeed;
                status = "disabled";
        };
 
-       sdhi1: sdhi@ee120000 {
+       sdhi1: sd@ee120000 {
                compatible = "renesas,sdhi-r8a7790";
                reg = <0 0xee120000 0 0x100>;
                interrupt-parent = <&gic>;
-               interrupts = <0 166 4>;
+               interrupts = <0 166 IRQ_TYPE_LEVEL_HIGH>;
                cap-sd-highspeed;
                status = "disabled";
        };
 
-       sdhi2: sdhi@ee140000 {
+       sdhi2: sd@ee140000 {
                compatible = "renesas,sdhi-r8a7790";
                reg = <0 0xee140000 0 0x100>;
                interrupt-parent = <&gic>;
-               interrupts = <0 167 4>;
+               interrupts = <0 167 IRQ_TYPE_LEVEL_HIGH>;
                cap-sd-highspeed;
                status = "disabled";
        };
 
-       sdhi3: sdhi@ee160000 {
+       sdhi3: sd@ee160000 {
                compatible = "renesas,sdhi-r8a7790";
                reg = <0 0xee160000 0 0x100>;
                interrupt-parent = <&gic>;
-               interrupts = <0 168 4>;
+               interrupts = <0 168 IRQ_TYPE_LEVEL_HIGH>;
                cap-sd-highspeed;
                status = "disabled";
        };
diff --git a/arch/arm/boot/dts/r8a7791-koelsch-reference.dts b/arch/arm/boot/dts/r8a7791-koelsch-reference.dts
new file mode 100644 (file)
index 0000000..1919273
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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"
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+       model = "Koelsch";
+       compatible = "renesas,koelsch-reference", "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>;
+       };
+
+       leds {
+               compatible = "gpio-leds";
+               led6 {
+                       gpios = <&gpio2 19 GPIO_ACTIVE_HIGH>;
+               };
+               led7 {
+                       gpios = <&gpio2 20 GPIO_ACTIVE_HIGH>;
+               };
+               led8 {
+                       gpios = <&gpio2 21 GPIO_ACTIVE_HIGH>;
+               };
+       };
+};
+
+&pfc {
+       pinctrl-0 = <&scif0_pins &scif1_pins>;
+       pinctrl-names = "default";
+
+       scif0_pins: serial0 {
+               renesas,groups = "scif0_data_d";
+               renesas,function = "scif0";
+       };
+
+       scif1_pins: serial1 {
+               renesas,groups = "scif1_data_d";
+               renesas,function = "scif1";
+       };
+};
index 1ce5250ec278fef727fa46c2a09c9cc09007b259..c4e8b3a0cd13af0ff201f3df89a8d9821c2452dc 100644 (file)
@@ -10,7 +10,7 @@
  */
 
 /dts-v1/;
-/include/ "r8a7791.dtsi"
+#include "r8a7791.dtsi"
 
 / {
        model = "Koelsch";
index fea5cfef4691c3656b7b34560eedccaee38ef0b1..a349aff54c76c333139962d16c4ba6bbc566b8ef 100644 (file)
@@ -9,6 +9,9 @@
  * kind, whether express or implied.
  */
 
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
 / {
        compatible = "renesas,r8a7791";
        interrupt-parent = <&gic>;
                        <0 0xf1002000 0 0x1000>,
                        <0 0xf1004000 0 0x2000>,
                        <0 0xf1006000 0 0x2000>;
-               interrupts = <1 9 0xf04>;
+               interrupts = <1 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+       };
+
+       gpio0: gpio@e6050000 {
+               compatible = "renesas,gpio-r8a7791", "renesas,gpio-rcar";
+               reg = <0 0xe6050000 0 0x50>;
+               interrupt-parent = <&gic>;
+               interrupts = <0 4 IRQ_TYPE_LEVEL_HIGH>;
+               #gpio-cells = <2>;
+               gpio-controller;
+               gpio-ranges = <&pfc 0 0 32>;
+               #interrupt-cells = <2>;
+               interrupt-controller;
+       };
+
+       gpio1: gpio@e6051000 {
+               compatible = "renesas,gpio-r8a7791", "renesas,gpio-rcar";
+               reg = <0 0xe6051000 0 0x50>;
+               interrupt-parent = <&gic>;
+               interrupts = <0 5 IRQ_TYPE_LEVEL_HIGH>;
+               #gpio-cells = <2>;
+               gpio-controller;
+               gpio-ranges = <&pfc 0 32 32>;
+               #interrupt-cells = <2>;
+               interrupt-controller;
+       };
+
+       gpio2: gpio@e6052000 {
+               compatible = "renesas,gpio-r8a7791", "renesas,gpio-rcar";
+               reg = <0 0xe6052000 0 0x50>;
+               interrupt-parent = <&gic>;
+               interrupts = <0 6 IRQ_TYPE_LEVEL_HIGH>;
+               #gpio-cells = <2>;
+               gpio-controller;
+               gpio-ranges = <&pfc 0 64 32>;
+               #interrupt-cells = <2>;
+               interrupt-controller;
+       };
+
+       gpio3: gpio@e6053000 {
+               compatible = "renesas,gpio-r8a7791", "renesas,gpio-rcar";
+               reg = <0 0xe6053000 0 0x50>;
+               interrupt-parent = <&gic>;
+               interrupts = <0 7 IRQ_TYPE_LEVEL_HIGH>;
+               #gpio-cells = <2>;
+               gpio-controller;
+               gpio-ranges = <&pfc 0 96 32>;
+               #interrupt-cells = <2>;
+               interrupt-controller;
+       };
+
+       gpio4: gpio@e6054000 {
+               compatible = "renesas,gpio-r8a7791", "renesas,gpio-rcar";
+               reg = <0 0xe6054000 0 0x50>;
+               interrupt-parent = <&gic>;
+               interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>;
+               #gpio-cells = <2>;
+               gpio-controller;
+               gpio-ranges = <&pfc 0 128 32>;
+               #interrupt-cells = <2>;
+               interrupt-controller;
+       };
+
+       gpio5: gpio@e6055000 {
+               compatible = "renesas,gpio-r8a7791", "renesas,gpio-rcar";
+               reg = <0 0xe6055000 0 0x50>;
+               interrupt-parent = <&gic>;
+               interrupts = <0 9 IRQ_TYPE_LEVEL_HIGH>;
+               #gpio-cells = <2>;
+               gpio-controller;
+               gpio-ranges = <&pfc 0 160 32>;
+               #interrupt-cells = <2>;
+               interrupt-controller;
+       };
+
+       gpio6: gpio@e6055400 {
+               compatible = "renesas,gpio-r8a7791", "renesas,gpio-rcar";
+               reg = <0 0xe6055400 0 0x50>;
+               interrupt-parent = <&gic>;
+               interrupts = <0 10 IRQ_TYPE_LEVEL_HIGH>;
+               #gpio-cells = <2>;
+               gpio-controller;
+               gpio-ranges = <&pfc 0 192 32>;
+               #interrupt-cells = <2>;
+               interrupt-controller;
+       };
+
+       gpio7: gpio@e6055800 {
+               compatible = "renesas,gpio-r8a7791", "renesas,gpio-rcar";
+               reg = <0 0xe6055800 0 0x50>;
+               interrupt-parent = <&gic>;
+               interrupts = <0 11 IRQ_TYPE_LEVEL_HIGH>;
+               #gpio-cells = <2>;
+               gpio-controller;
+               gpio-ranges = <&pfc 0 224 26>;
+               #interrupt-cells = <2>;
+               interrupt-controller;
+       };
+
+       thermal@e61f0000 {
+               compatible = "renesas,thermal-r8a7791", "renesas,rcar-thermal";
+               reg = <0 0xe61f0000 0 0x14>, <0 0xe61f0100 0 0x38>;
+               interrupt-parent = <&gic>;
+               interrupts = <0 69 IRQ_TYPE_LEVEL_HIGH>;
        };
 
        timer {
                compatible = "arm,armv7-timer";
-               interrupts = <1 13 0xf08>,
-                               <1 14 0xf08>,
-                               <1 11 0xf08>,
-                               <1 10 0xf08>;
+               interrupts = <1 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+                            <1 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+                            <1 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+                            <1 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
        };
 
        irqc0: interrupt-controller@e61c0000 {
-               compatible = "renesas,irqc";
+               compatible = "renesas,irqc-r8a7791", "renesas,irqc";
                #interrupt-cells = <2>;
                interrupt-controller;
                reg = <0 0xe61c0000 0 0x200>;
                interrupt-parent = <&gic>;
-               interrupts = <0 0 4>,
-                             <0 1 4>,
-                             <0 2 4>,
-                             <0 3 4>,
-                             <0 12 4>,
-                             <0 13 4>,
-                             <0 14 4>,
-                             <0 15 4>,
-                             <0 16 4>,
-                             <0 17 4>;
+               interrupts = <0 0 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 1 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 2 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 3 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 12 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 13 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 14 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 15 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 16 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 17 IRQ_TYPE_LEVEL_HIGH>;
+       };
+
+       pfc: pfc@e6060000 {
+               compatible = "renesas,pfc-r8a7791";
+               reg = <0 0xe6060000 0 0x250>;
+               #gpio-range-cells = <3>;
        };
 };
index 5cdaba4cea8653d8db51616f443a4d8ee2d79ef4..fad42f5fd8c48c5f69b595d30ebbe987c427f1d5 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * sama5d3.dtsi - Device Tree Include file for SAMA5D3 family SoC
- *                applies to SAMA5D31, SAMA5D33, SAMA5D34, SAMA5D35 SoC
+ *                applies to SAMA5D31, SAMA5D33, SAMA5D34, SAMA5D35, SAMA5D36 SoC
  *
  *  Copyright (C) 2013 Atmel,
  *                2013 Ludovic Desroches <ludovic.desroches@atmel.com>
@@ -13,6 +13,7 @@
 #include <dt-bindings/pinctrl/at91.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/clk/at91.h>
 
 / {
        model = "Atmel SAMA5D3 family SoC";
                reg = <0x20000000 0x8000000>;
        };
 
+       clocks {
+               adc_op_clk: adc_op_clk{
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <20000000>;
+               };
+       };
+
        ahb {
                compatible = "simple-bus";
                #address-cells = <1>;
@@ -79,6 +88,8 @@
                                status = "disabled";
                                #address-cells = <1>;
                                #size-cells = <0>;
+                               clocks = <&mci0_clk>;
+                               clock-names = "mci_clk";
                        };
 
                        spi0: spi@f0004000 {
                                dma-names = "tx", "rx";
                                pinctrl-names = "default";
                                pinctrl-0 = <&pinctrl_spi0>;
+                               clocks = <&spi0_clk>;
+                               clock-names = "spi_clk";
                                status = "disabled";
                        };
 
                                interrupts = <38 IRQ_TYPE_LEVEL_HIGH 4>;
                                pinctrl-names = "default";
                                pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>;
+                               clocks = <&ssc0_clk>;
+                               clock-names = "pclk";
                                status = "disabled";
                        };
 
                                compatible = "atmel,at91sam9x5-tcb";
                                reg = <0xf0010000 0x100>;
                                interrupts = <26 IRQ_TYPE_LEVEL_HIGH 0>;
+                               clocks = <&tcb0_clk>;
+                               clock-names = "t0_clk";
                        };
 
                        i2c0: i2c@f0014000 {
                                pinctrl-0 = <&pinctrl_i2c0>;
                                #address-cells = <1>;
                                #size-cells = <0>;
+                               clocks = <&twi0_clk>;
                                status = "disabled";
                        };
 
                                pinctrl-0 = <&pinctrl_i2c1>;
                                #address-cells = <1>;
                                #size-cells = <0>;
+                               clocks = <&twi1_clk>;
                                status = "disabled";
                        };
 
                                interrupts = <12 IRQ_TYPE_LEVEL_HIGH 5>;
                                pinctrl-names = "default";
                                pinctrl-0 = <&pinctrl_usart0>;
+                               clocks = <&usart0_clk>;
+                               clock-names = "usart";
                                status = "disabled";
                        };
 
                                interrupts = <13 IRQ_TYPE_LEVEL_HIGH 5>;
                                pinctrl-names = "default";
                                pinctrl-0 = <&pinctrl_usart1>;
+                               clocks = <&usart1_clk>;
+                               clock-names = "usart";
                                status = "disabled";
                        };
 
                                status = "disabled";
                                #address-cells = <1>;
                                #size-cells = <0>;
+                               clocks = <&mci1_clk>;
+                               clock-names = "mci_clk";
                        };
 
                        spi1: spi@f8008000 {
                                dma-names = "tx", "rx";
                                pinctrl-names = "default";
                                pinctrl-0 = <&pinctrl_spi1>;
+                               clocks = <&spi1_clk>;
+                               clock-names = "spi_clk";
                                status = "disabled";
                        };
 
                                interrupts = <39 IRQ_TYPE_LEVEL_HIGH 4>;
                                pinctrl-names = "default";
                                pinctrl-0 = <&pinctrl_ssc1_tx &pinctrl_ssc1_rx>;
+                               clocks = <&ssc1_clk>;
+                               clock-names = "pclk";
                                status = "disabled";
                        };
 
                                        &pinctrl_adc0_ad10
                                        &pinctrl_adc0_ad11
                                        >;
+                               clocks = <&adc_clk>,
+                                        <&adc_op_clk>;
+                               clock-names = "adc_clk", "adc_op_clk";
                                atmel,adc-channel-base = <0x50>;
                                atmel,adc-channels-used = <0xfff>;
                                atmel,adc-drdy-mask = <0x1000000>;
                                dmas = <&dma1 2 AT91_DMA_CFG_PER_ID(11)>,
                                       <&dma1 2 AT91_DMA_CFG_PER_ID(12)>;
                                dma-names = "tx", "rx";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_i2c2>;
                                #address-cells = <1>;
                                #size-cells = <0>;
+                               clocks = <&twi2_clk>;
                                status = "disabled";
                        };
 
                                interrupts = <14 IRQ_TYPE_LEVEL_HIGH 5>;
                                pinctrl-names = "default";
                                pinctrl-0 = <&pinctrl_usart2>;
+                               clocks = <&usart2_clk>;
+                               clock-names = "usart";
                                status = "disabled";
                        };
 
                                interrupts = <15 IRQ_TYPE_LEVEL_HIGH 5>;
                                pinctrl-names = "default";
                                pinctrl-0 = <&pinctrl_usart3>;
+                               clocks = <&usart3_clk>;
+                               clock-names = "usart";
                                status = "disabled";
                        };
 
                        sha@f8034000 {
-                               compatible = "atmel,sam9g46-sha";
+                               compatible = "atmel,at91sam9g46-sha";
                                reg = <0xf8034000 0x100>;
                                interrupts = <42 IRQ_TYPE_LEVEL_HIGH 0>;
+                               dmas = <&dma1 2 AT91_DMA_CFG_PER_ID(17)>;
+                               dma-names = "tx";
                        };
 
                        aes@f8038000 {
-                               compatible = "atmel,sam9g46-aes";
+                               compatible = "atmel,at91sam9g46-aes";
                                reg = <0xf8038000 0x100>;
-                               interrupts = <43 4 0>;
+                               interrupts = <43 IRQ_TYPE_LEVEL_HIGH 0>;
+                               dmas = <&dma1 2 AT91_DMA_CFG_PER_ID(18)>,
+                                      <&dma1 2 AT91_DMA_CFG_PER_ID(19)>;
+                               dma-names = "tx", "rx";
                        };
 
                        tdes@f803c000 {
-                               compatible = "atmel,sam9g46-tdes";
+                               compatible = "atmel,at91sam9g46-tdes";
                                reg = <0xf803c000 0x100>;
                                interrupts = <44 IRQ_TYPE_LEVEL_HIGH 0>;
+                               dmas = <&dma1 2 AT91_DMA_CFG_PER_ID(20)>,
+                                      <&dma1 2 AT91_DMA_CFG_PER_ID(21)>;
+                               dma-names = "tx", "rx";
                        };
 
                        dma0: dma-controller@ffffe600 {
                                reg = <0xffffe600 0x200>;
                                interrupts = <30 IRQ_TYPE_LEVEL_HIGH 0>;
                                #dma-cells = <2>;
+                               clocks = <&dma0_clk>;
+                               clock-names = "dma_clk";
                        };
 
                        dma1: dma-controller@ffffe800 {
                                reg = <0xffffe800 0x200>;
                                interrupts = <31 IRQ_TYPE_LEVEL_HIGH 0>;
                                #dma-cells = <2>;
+                               clocks = <&dma1_clk>;
+                               clock-names = "dma_clk";
                        };
 
                        ramc0: ramc@ffffea00 {
                                interrupts = <2 IRQ_TYPE_LEVEL_HIGH 7>;
                                pinctrl-names = "default";
                                pinctrl-0 = <&pinctrl_dbgu>;
+                               clocks = <&dbgu_clk>;
+                               clock-names = "usart";
                                status = "disabled";
                        };
 
                                        };
                                };
 
+                               i2c2 {
+                                       pinctrl_i2c2: i2c2-0 {
+                                               atmel,pins =
+                                                       <AT91_PIOA 18 AT91_PERIPH_B AT91_PINCTRL_NONE   /* TWD2 pin, conflicts with LCDDAT18, ISI_D2 */
+                                                        AT91_PIOA 19 AT91_PERIPH_B AT91_PINCTRL_NONE>; /* TWCK2 pin, conflicts with LCDDAT19, ISI_D3 */
+                                       };
+                               };
+
                                isi {
                                        pinctrl_isi: isi-0 {
                                                atmel,pins =
                                        gpio-controller;
                                        interrupt-controller;
                                        #interrupt-cells = <2>;
+                                       clocks = <&pioA_clk>;
                                };
 
                                pioB: gpio@fffff400 {
                                        gpio-controller;
                                        interrupt-controller;
                                        #interrupt-cells = <2>;
+                                       clocks = <&pioB_clk>;
                                };
 
                                pioC: gpio@fffff600 {
                                        gpio-controller;
                                        interrupt-controller;
                                        #interrupt-cells = <2>;
+                                       clocks = <&pioC_clk>;
                                };
 
                                pioD: gpio@fffff800 {
                                        gpio-controller;
                                        interrupt-controller;
                                        #interrupt-cells = <2>;
+                                       clocks = <&pioD_clk>;
                                };
 
                                pioE: gpio@fffffa00 {
                                        gpio-controller;
                                        interrupt-controller;
                                        #interrupt-cells = <2>;
+                                       clocks = <&pioE_clk>;
                                };
                        };
 
                        pmc: pmc@fffffc00 {
-                               compatible = "atmel,at91rm9200-pmc";
+                               compatible = "atmel,sama5d3-pmc";
                                reg = <0xfffffc00 0x120>;
+                               interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
+                               interrupt-controller;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               #interrupt-cells = <1>;
+
+                               clk32k: slck {
+                                       compatible = "fixed-clock";
+                                       #clock-cells = <0>;
+                                       clock-frequency = <32768>;
+                               };
+
+                               main: mainck {
+                                       compatible = "atmel,at91rm9200-clk-main";
+                                       #clock-cells = <0>;
+                                       interrupt-parent = <&pmc>;
+                                       interrupts = <AT91_PMC_MOSCS>;
+                                       clocks = <&clk32k>;
+                               };
+
+                               plla: pllack {
+                                       compatible = "atmel,sama5d3-clk-pll";
+                                       #clock-cells = <0>;
+                                       interrupt-parent = <&pmc>;
+                                       interrupts = <AT91_PMC_LOCKA>;
+                                       clocks = <&main>;
+                                       reg = <0>;
+                                       atmel,clk-input-range = <8000000 50000000>;
+                                       #atmel,pll-clk-output-range-cells = <4>;
+                                       atmel,pll-clk-output-ranges = <400000000 1000000000 0 0>;
+                               };
+
+                               plladiv: plladivck {
+                                       compatible = "atmel,at91sam9x5-clk-plldiv";
+                                       #clock-cells = <0>;
+                                       clocks = <&plla>;
+                               };
+
+                               utmi: utmick {
+                                       compatible = "atmel,at91sam9x5-clk-utmi";
+                                       #clock-cells = <0>;
+                                       interrupt-parent = <&pmc>;
+                                       interrupts = <AT91_PMC_LOCKU>;
+                                       clocks = <&main>;
+                               };
+
+                               mck: masterck {
+                                       compatible = "atmel,at91sam9x5-clk-master";
+                                       #clock-cells = <0>;
+                                       interrupt-parent = <&pmc>;
+                                       interrupts = <AT91_PMC_MCKRDY>;
+                                       clocks = <&clk32k>, <&main>, <&plladiv>, <&utmi>;
+                                       atmel,clk-output-range = <0 166000000>;
+                                       atmel,clk-divisors = <1 2 4 3>;
+                               };
+
+                               usb: usbck {
+                                       compatible = "atmel,at91sam9x5-clk-usb";
+                                       #clock-cells = <0>;
+                                       clocks = <&plladiv>, <&utmi>;
+                               };
+
+                               prog: progck {
+                                       compatible = "atmel,at91sam9x5-clk-programmable";
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       interrupt-parent = <&pmc>;
+                                       clocks = <&clk32k>, <&main>, <&plladiv>, <&utmi>, <&mck>;
+
+                                       prog0: prog0 {
+                                               #clock-cells = <0>;
+                                               reg = <0>;
+                                               interrupts = <AT91_PMC_PCKRDY(0)>;
+                                       };
+
+                                       prog1: prog1 {
+                                               #clock-cells = <0>;
+                                               reg = <1>;
+                                               interrupts = <AT91_PMC_PCKRDY(1)>;
+                                       };
+
+                                       prog2: prog2 {
+                                               #clock-cells = <0>;
+                                               reg = <2>;
+                                               interrupts = <AT91_PMC_PCKRDY(2)>;
+                                       };
+                               };
+
+                               smd: smdclk {
+                                       compatible = "atmel,at91sam9x5-clk-smd";
+                                       #clock-cells = <0>;
+                                       clocks = <&plladiv>, <&utmi>;
+                               };
+
+                               systemck {
+                                       compatible = "atmel,at91rm9200-clk-system";
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+
+                                       ddrck: ddrck {
+                                               #clock-cells = <0>;
+                                               reg = <2>;
+                                               clocks = <&mck>;
+                                       };
+
+                                       smdck: smdck {
+                                               #clock-cells = <0>;
+                                               reg = <4>;
+                                               clocks = <&smd>;
+                                       };
+
+                                       uhpck: uhpck {
+                                               #clock-cells = <0>;
+                                               reg = <6>;
+                                               clocks = <&usb>;
+                                       };
+
+                                       udpck: udpck {
+                                               #clock-cells = <0>;
+                                               reg = <7>;
+                                               clocks = <&usb>;
+                                       };
+
+                                       pck0: pck0 {
+                                               #clock-cells = <0>;
+                                               reg = <8>;
+                                               clocks = <&prog0>;
+                                       };
+
+                                       pck1: pck1 {
+                                               #clock-cells = <0>;
+                                               reg = <9>;
+                                               clocks = <&prog1>;
+                                       };
+
+                                       pck2: pck2 {
+                                               #clock-cells = <0>;
+                                               reg = <10>;
+                                               clocks = <&prog2>;
+                                       };
+                               };
+
+                               periphck {
+                                       compatible = "atmel,at91sam9x5-clk-peripheral";
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       clocks = <&mck>;
+
+                                       dbgu_clk: dbgu_clk {
+                                               #clock-cells = <0>;
+                                               reg = <2>;
+                                       };
+
+                                       pioA_clk: pioA_clk {
+                                               #clock-cells = <0>;
+                                               reg = <6>;
+                                       };
+
+                                       pioB_clk: pioB_clk {
+                                               #clock-cells = <0>;
+                                               reg = <7>;
+                                       };
+
+                                       pioC_clk: pioC_clk {
+                                               #clock-cells = <0>;
+                                               reg = <8>;
+                                       };
+
+                                       pioD_clk: pioD_clk {
+                                               #clock-cells = <0>;
+                                               reg = <9>;
+                                       };
+
+                                       pioE_clk: pioE_clk {
+                                               #clock-cells = <0>;
+                                               reg = <10>;
+                                       };
+
+                                       usart0_clk: usart0_clk {
+                                               #clock-cells = <0>;
+                                               reg = <12>;
+                                               atmel,clk-output-range = <0 66000000>;
+                                       };
+
+                                       usart1_clk: usart1_clk {
+                                               #clock-cells = <0>;
+                                               reg = <13>;
+                                               atmel,clk-output-range = <0 66000000>;
+                                       };
+
+                                       usart2_clk: usart2_clk {
+                                               #clock-cells = <0>;
+                                               reg = <14>;
+                                               atmel,clk-output-range = <0 66000000>;
+                                       };
+
+                                       usart3_clk: usart3_clk {
+                                               #clock-cells = <0>;
+                                               reg = <15>;
+                                               atmel,clk-output-range = <0 66000000>;
+                                       };
+
+                                       twi0_clk: twi0_clk {
+                                               reg = <18>;
+                                               #clock-cells = <0>;
+                                               atmel,clk-output-range = <0 16625000>;
+                                       };
+
+                                       twi1_clk: twi1_clk {
+                                               #clock-cells = <0>;
+                                               reg = <19>;
+                                               atmel,clk-output-range = <0 16625000>;
+                                       };
+
+                                       twi2_clk: twi2_clk {
+                                               #clock-cells = <0>;
+                                               reg = <20>;
+                                               atmel,clk-output-range = <0 16625000>;
+                                       };
+
+                                       mci0_clk: mci0_clk {
+                                               #clock-cells = <0>;
+                                               reg = <21>;
+                                       };
+
+                                       mci1_clk: mci1_clk {
+                                               #clock-cells = <0>;
+                                               reg = <22>;
+                                       };
+
+                                       spi0_clk: spi0_clk {
+                                               #clock-cells = <0>;
+                                               reg = <24>;
+                                               atmel,clk-output-range = <0 133000000>;
+                                       };
+
+                                       spi1_clk: spi1_clk {
+                                               #clock-cells = <0>;
+                                               reg = <25>;
+                                               atmel,clk-output-range = <0 133000000>;
+                                       };
+
+                                       tcb0_clk: tcb0_clk {
+                                               #clock-cells = <0>;
+                                               reg = <26>;
+                                               atmel,clk-output-range = <0 133000000>;
+                                       };
+
+                                       pwm_clk: pwm_clk {
+                                               #clock-cells = <0>;
+                                               reg = <28>;
+                                       };
+
+                                       adc_clk: adc_clk {
+                                               #clock-cells = <0>;
+                                               reg = <29>;
+                                               atmel,clk-output-range = <0 66000000>;
+                                       };
+
+                                       dma0_clk: dma0_clk {
+                                               #clock-cells = <0>;
+                                               reg = <30>;
+                                       };
+
+                                       dma1_clk: dma1_clk {
+                                               #clock-cells = <0>;
+                                               reg = <31>;
+                                       };
+
+                                       uhphs_clk: uhphs_clk {
+                                               #clock-cells = <0>;
+                                               reg = <32>;
+                                       };
+
+                                       udphs_clk: udphs_clk {
+                                               #clock-cells = <0>;
+                                               reg = <33>;
+                                       };
+
+                                       isi_clk: isi_clk {
+                                               #clock-cells = <0>;
+                                               reg = <37>;
+                                       };
+
+                                       ssc0_clk: ssc0_clk {
+                                               #clock-cells = <0>;
+                                               reg = <38>;
+                                               atmel,clk-output-range = <0 66000000>;
+                                       };
+
+                                       ssc1_clk: ssc1_clk {
+                                               #clock-cells = <0>;
+                                               reg = <39>;
+                                               atmel,clk-output-range = <0 66000000>;
+                                       };
+
+                                       sha_clk: sha_clk {
+                                               #clock-cells = <0>;
+                                               reg = <42>;
+                                       };
+
+                                       aes_clk: aes_clk {
+                                               #clock-cells = <0>;
+                                               reg = <43>;
+                                       };
+
+                                       tdes_clk: tdes_clk {
+                                               #clock-cells = <0>;
+                                               reg = <44>;
+                                       };
+
+                                       trng_clk: trng_clk {
+                                               #clock-cells = <0>;
+                                               reg = <45>;
+                                       };
+
+                                       fuse_clk: fuse_clk {
+                                               #clock-cells = <0>;
+                                               reg = <48>;
+                                       };
+                               };
                        };
 
                        rstc@fffffe00 {
                                compatible = "atmel,at91sam9260-pit";
                                reg = <0xfffffe30 0xf>;
                                interrupts = <3 IRQ_TYPE_LEVEL_HIGH 5>;
+                               clocks = <&mck>;
                        };
 
                        watchdog@fffffe40 {
                        reg = <0x00500000 0x100000
                               0xf8030000 0x4000>;
                        interrupts = <33 IRQ_TYPE_LEVEL_HIGH 2>;
+                       clocks = <&udphs_clk>, <&utmi>;
+                       clock-names = "pclk", "hclk";
                        status = "disabled";
 
                        ep0 {
                        compatible = "atmel,at91rm9200-ohci", "usb-ohci";
                        reg = <0x00600000 0x100000>;
                        interrupts = <32 IRQ_TYPE_LEVEL_HIGH 2>;
+                       clocks = <&usb>, <&uhphs_clk>, <&udphs_clk>,
+                                <&uhpck>;
+                       clock-names = "usb_clk", "ohci_clk", "hclk", "uhpck";
                        status = "disabled";
                };
 
                        compatible = "atmel,at91sam9g45-ehci", "usb-ehci";
                        reg = <0x00700000 0x100000>;
                        interrupts = <32 IRQ_TYPE_LEVEL_HIGH 2>;
+                       clocks = <&usb>, <&uhphs_clk>, <&uhpck>;
+                       clock-names = "usb_clk", "ehci_clk", "uhpck";
                        status = "disabled";
                };
 
diff --git a/arch/arm/boot/dts/sama5d36.dtsi b/arch/arm/boot/dts/sama5d36.dtsi
new file mode 100644 (file)
index 0000000..6c31c26
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * sama5d36.dtsi - Device Tree Include file for SAMA5D36 SoC
+ *
+ *  Copyright (C) 2013 Atmel,
+ *                2013 Josh Wu <josh.wu@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+#include "sama5d3.dtsi"
+#include "sama5d3_can.dtsi"
+#include "sama5d3_emac.dtsi"
+#include "sama5d3_gmac.dtsi"
+#include "sama5d3_lcd.dtsi"
+#include "sama5d3_mci2.dtsi"
+#include "sama5d3_tcb1.dtsi"
+#include "sama5d3_uart.dtsi"
+
+/ {
+       compatible = "atmel,samad36", "atmel,sama5d3", "atmel,sama5";
+};
diff --git a/arch/arm/boot/dts/sama5d36ek.dts b/arch/arm/boot/dts/sama5d36ek.dts
new file mode 100644 (file)
index 0000000..59576c6
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * sama5d36ek.dts - Device Tree file for SAMA5D36-EK board
+ *
+ *  Copyright (C) 2013 Atmel,
+ *                2013 Josh Wu <josh.wu@atmel.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+/dts-v1/;
+#include "sama5d36.dtsi"
+#include "sama5d3xmb.dtsi"
+#include "sama5d3xdm.dtsi"
+
+/ {
+       model = "Atmel SAMA5D36-EK";
+       compatible = "atmel,sama5d36ek", "atmel,sama5d3xmb", "atmel,sama5d3xcm", "atmel,sama5d36", "atmel,sama5d3", "atmel,sama5";
+
+       ahb {
+               apb {
+                       spi0: spi@f0004000 {
+                               status = "okay";
+                       };
+
+                       ssc0: ssc@f0008000 {
+                               status = "okay";
+                       };
+
+                       can0: can@f000c000 {
+                               status = "okay";
+                       };
+
+                       i2c0: i2c@f0014000 {
+                               status = "okay";
+                       };
+
+                       i2c1: i2c@f0018000 {
+                               status = "okay";
+                       };
+
+                       macb0: ethernet@f0028000 {
+                               status = "okay";
+                       };
+
+                       macb1: ethernet@f802c000 {
+                               status = "okay";
+                       };
+               };
+       };
+
+       sound {
+               status = "okay";
+       };
+};
index 8ed3260cef6687b59e084c07366633ef3c9acc0e..a0775851cce56d01c696adb65a4cbf2f8dc9d514 100644 (file)
 
                        };
 
+                       pmc: pmc@fffffc00 {
+                               periphck {
+                                       can0_clk: can0_clk {
+                                               #clock-cells = <0>;
+                                               reg = <40>;
+                                               atmel,clk-output-range = <0 66000000>;
+                                       };
+
+                                       can1_clk: can0_clk {
+                                               #clock-cells = <0>;
+                                               reg = <41>;
+                                               atmel,clk-output-range = <0 66000000>;
+                                       };
+                               };
+                       };
+
                        can0: can@f000c000 {
                                compatible = "atmel,at91sam9x5-can";
                                reg = <0xf000c000 0x300>;
                                interrupts = <40 IRQ_TYPE_LEVEL_HIGH 3>;
                                pinctrl-names = "default";
                                pinctrl-0 = <&pinctrl_can0_rx_tx>;
+                               clocks = <&can0_clk>;
+                               clock-names = "can_clk";
                                status = "disabled";
                        };
 
@@ -47,6 +65,8 @@
                                interrupts = <41 IRQ_TYPE_LEVEL_HIGH 3>;
                                pinctrl-names = "default";
                                pinctrl-0 = <&pinctrl_can1_rx_tx>;
+                               clocks = <&can1_clk>;
+                               clock-names = "can_clk";
                                status = "disabled";
                        };
                };
index 4d4f351f1f9facbc30cc249dffa34d94bfcf4113..fe2af92763129beb8b4b493adbfb847684b4a264 100644 (file)
                                };
                        };
 
+                       pmc: pmc@fffffc00 {
+                               periphck {
+                                       macb1_clk: macb1_clk {
+                                               #clock-cells = <0>;
+                                               reg = <35>;
+                                       };
+                               };
+                       };
+
                        macb1: ethernet@f802c000 {
                                compatible = "cdns,at32ap7000-macb", "cdns,macb";
                                reg = <0xf802c000 0x100>;
                                interrupts = <35 IRQ_TYPE_LEVEL_HIGH 3>;
                                pinctrl-names = "default";
                                pinctrl-0 = <&pinctrl_macb1_rmii>;
+                               clocks = <&macb1_clk>, <&macb1_clk>;
+                               clock-names = "hclk", "pclk";
                                status = "disabled";
                        };
                };
index 0ba8be30ccd8900bfc77b803aeac537fb89ce619..a6cb0508762f159579d719032e2dbb2d28ccb879 100644 (file)
                                };
                        };
 
+                       pmc: pmc@fffffc00 {
+                               periphck {
+                                       macb0_clk: macb0_clk {
+                                               #clock-cells = <0>;
+                                               reg = <34>;
+                                       };
+                               };
+                       };
+
                        macb0: ethernet@f0028000 {
                                compatible = "cdns,pc302-gem", "cdns,gem";
                                reg = <0xf0028000 0x100>;
                                interrupts = <34 IRQ_TYPE_LEVEL_HIGH 3>;
                                pinctrl-names = "default";
                                pinctrl-0 = <&pinctrl_macb0_data_rgmii &pinctrl_macb0_signal_rgmii>;
+                               clocks = <&macb0_clk>, <&macb0_clk>;
+                               clock-names = "hclk", "pclk";
                                status = "disabled";
                        };
                };
index 01f52a79f8baeb458532b60bfac20a20f6283db2..85d30270156561c3e8b44cc189482ec469c6e1af 100644 (file)
                                        };
                                };
                        };
+
+                       pmc: pmc@fffffc00 {
+                               periphck {
+                                       lcdc_clk: lcdc_clk {
+                                               #clock-cells = <0>;
+                                               reg = <36>;
+                                       };
+                               };
+
+                               systemck {
+                                       lcdck: lcdck {
+                                               #clock-cells = <0>;
+                                               reg = <3>;
+                                               clocks = <&mck>;
+                                       };
+                               };
+                       };
                };
        };
 };
index 38e88e39e551c2c68b75720b1133b5b4591e5d8f..b029fe7ef17a657946de4d2fe71168b4b03210d8 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <dt-bindings/pinctrl/at91.h>
 #include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/clk/at91.h>
 
 / {
        ahb {
                                };
                        };
 
+                       pmc: pmc@fffffc00 {
+                               periphck {
+                                       mci2_clk: mci2_clk {
+                                               #clock-cells = <0>;
+                                               reg = <23>;
+                                       };
+                               };
+                       };
+
                        mmc2: mmc@f8004000 {
                                compatible = "atmel,hsmci";
                                reg = <0xf8004000 0x600>;
@@ -38,6 +48,8 @@
                                dma-names = "rxtx";
                                pinctrl-names = "default";
                                pinctrl-0 = <&pinctrl_mmc2_clk_cmd_dat0 &pinctrl_mmc2_dat1_3>;
+                               clocks = <&mci2_clk>;
+                               clock-names = "mci_clk";
                                status = "disabled";
                                #address-cells = <1>;
                                #size-cells = <0>;
index 5264bb4a69988606c0c5e8dd19c61fc0a8c9c0db..382b04431f66b621e01a9f2fe7a9e488ac4c171b 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <dt-bindings/pinctrl/at91.h>
 #include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/clk/at91.h>
 
 / {
        aliases {
 
        ahb {
                apb {
+                       pmc: pmc@fffffc00 {
+                               periphck {
+                                       tcb1_clk: tcb1_clk {
+                                               #clock-cells = <0>;
+                                               reg = <27>;
+                                       };
+                               };
+                       };
+
                        tcb1: timer@f8014000 {
                                compatible = "atmel,at91sam9x5-tcb";
                                reg = <0xf8014000 0x100>;
                                interrupts = <27 IRQ_TYPE_LEVEL_HIGH 0>;
+                               clocks = <&tcb1_clk>;
+                               clock-names = "t0_clk";
                        };
                };
        };
index 98fcb2d57446708e42cc22892d0def31273cd543..a9fa75e4165205f9a1259f9a0821519faee54070 100644 (file)
@@ -9,8 +9,14 @@
 
 #include <dt-bindings/pinctrl/at91.h>
 #include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/clk/at91.h>
 
 / {
+       aliases {
+               serial5 = &uart0;
+               serial6 = &uart1;
+       };
+
        ahb {
                apb {
                        pinctrl@fffff200 {
                                };
                        };
 
+                       pmc: pmc@fffffc00 {
+                               periphck {
+                                       uart0_clk: uart0_clk {
+                                               #clock-cells = <0>;
+                                               reg = <16>;
+                                               atmel,clk-output-range = <0 66000000>;
+                                       };
+
+                                       uart1_clk: uart1_clk {
+                                               #clock-cells = <0>;
+                                               reg = <17>;
+                                               atmel,clk-output-range = <0 66000000>;
+                                       };
+                               };
+                       };
+
                        uart0: serial@f0024000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xf0024000 0x200>;
                                interrupts = <16 IRQ_TYPE_LEVEL_HIGH 5>;
                                pinctrl-names = "default";
                                pinctrl-0 = <&pinctrl_uart0>;
+                               clocks = <&uart0_clk>;
+                               clock-names = "usart";
                                status = "disabled";
                        };
 
@@ -46,6 +70,8 @@
                                interrupts = <17 IRQ_TYPE_LEVEL_HIGH 5>;
                                pinctrl-names = "default";
                                pinctrl-0 = <&pinctrl_uart1>;
+                               clocks = <&uart1_clk>;
+                               clock-names = "usart";
                                status = "disabled";
                        };
                };
index 726a0f35100c5218fb0b467bef7fa611f953b6de..f55ed072c8e6b1c0290a5aa3eb4ab4b7680e121b 100644 (file)
                reg = <0x20000000 0x20000000>;
        };
 
-       clocks {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               ranges;
-
-               main_clock: clock@0 {
-                       compatible = "atmel,osc", "fixed-clock";
-                       clock-frequency = <12000000>;
-               };
-       };
-
        ahb {
                apb {
                        spi0: spi@f0004000 {
                        macb0: ethernet@f0028000 {
                                phy-mode = "rgmii";
                        };
+
+                       pmc: pmc@fffffc00 {
+                               main: mainck {
+                                       clock-frequency = <12000000>;
+                               };
+                       };
                };
 
                nand0: nand@60000000 {
index 1c296d6b2f2a7925cd3af7d9b6e73e439d17d25d..f9bdde542ced2f9e0a76aa6ae73a5a7478215ae6 100644 (file)
@@ -18,6 +18,7 @@
                                        interrupts = <31 0x0>;
                                        pinctrl-names = "default";
                                        pinctrl-0 = <&pinctrl_qt1070_irq>;
+                                       wakeup-source;
                                };
                        };
 
index 8acf51e0cdae8b10bdda5d875a61f4c9e543e19c..a759a276c9a972d4174e519240e4f9ed7d720fd0 100644 (file)
@@ -9,7 +9,7 @@
  */
 
 /dts-v1/;
-/include/ "sh7372.dtsi"
+#include "sh7372.dtsi"
 
 / {
        model = "Mackerel (AP4 EVM 2nd)";
index 8ee06dd81799da98cbe14ed6c43973e4d4bd513f..5bb593daab529301cf64d1ef9b0c9c9ffc2fbec4 100644 (file)
@@ -12,8 +12,9 @@
  */
 
 /dts-v1/;
-/include/ "sh73a0.dtsi"
+#include "sh73a0.dtsi"
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
 
 / {
        model = "KZM-A9-GT";
@@ -82,7 +83,7 @@
                reg = <0x10000000 0x100>;
                phy-mode = "mii";
                interrupt-parent = <&irqpin0>;
-               interrupts = <3 0>;     /* active low */
+               interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
                reg-io-width = <4>;
                smsc,irq-push-pull;
                smsc,save-mac-address;
                        gpios = <&pfc 23 GPIO_ACTIVE_LOW>;
                };
        };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+
+               back-key {
+                       gpios = <&pcf8575 8 GPIO_ACTIVE_LOW>;
+                       linux,code = <158>;
+                       label = "SW3";
+               };
+
+               right-key {
+                       gpios = <&pcf8575 9 GPIO_ACTIVE_LOW>;
+                       linux,code = <106>;
+                       label = "SW2-R";
+               };
+
+               left-key {
+                       gpios = <&pcf8575 10 GPIO_ACTIVE_LOW>;
+                       linux,code = <105>;
+                       label = "SW2-L";
+               };
+
+               enter-key {
+                       gpios = <&pcf8575 11 GPIO_ACTIVE_LOW>;
+                       linux,code = <28>;
+                       label = "SW2-P";
+               };
+
+               up-key {
+                       gpios = <&pcf8575 12 GPIO_ACTIVE_LOW>;
+                       linux,code = <103>;
+                       label = "SW2-U";
+               };
+
+               down-key {
+                       gpios = <&pcf8575 13 GPIO_ACTIVE_LOW>;
+                       linux,code = <108>;
+                       label = "SW2-D";
+               };
+
+               home-key {
+                       gpios = <&pcf8575 14 GPIO_ACTIVE_LOW>;
+                       linux,code = <102>;
+                       label = "SW1";
+               };
+       };
 };
 
 &i2c0 {
        pinctrl-0 = <&i2c3_pins>;
        pinctrl-names = "default";
        status = "okay";
+
+       pcf8575: gpio@20 {
+               compatible = "nxp,pcf8575";
+               reg = <0x20>;
+               interrupt-parent = <&irqpin2>;
+               interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+               gpio-controller;
+               #gpio-cells = <2>;
+               interrupt-controller;
+               #interrupt-cells = <2>;
+       };
 };
 
 &mmcif {
                renesas,function = "i2c3";
        };
 
-       mmcif_pins: mmcif {
+       mmcif_pins: mmc {
                mux {
                        renesas,groups = "mmc0_data8_0", "mmc0_ctrl_0";
                        renesas,function = "mmc0";
                };
        };
 
-       scifa4_pins: scifa4 {
+       scifa4_pins: serial4 {
                renesas,groups = "scifa4_data", "scifa4_ctrl";
                renesas,function = "scifa4";
        };
 
-       sdhi0_pins: sdhi0 {
+       sdhi0_pins: sd0 {
                renesas,groups = "sdhi0_data4", "sdhi0_ctrl", "sdhi0_cd", "sdhi0_wp";
                renesas,function = "sdhi0";
        };
 
-       sdhi2_pins: sdhi2 {
+       sdhi2_pins: sd2 {
                renesas,groups = "sdhi2_data4", "sdhi2_ctrl";
                renesas,function = "sdhi2";
        };
index 0f1ca7792c46acebbbce831371e04200aa89846d..27c5f426d172f03d53801875ec5a5293c4f45b88 100644 (file)
@@ -9,7 +9,7 @@
  */
 
 /dts-v1/;
-/include/ "sh73a0.dtsi"
+#include "sh73a0.dtsi"
 
 / {
        model = "KZM-A9-GT";
index fcf26889a8a0aacb380d980fb6cccdd36ee36dff..241c8cdaeaa1e3434818dc32317cad5bea7b646c 100644 (file)
@@ -10,6 +10,8 @@
 
 /include/ "skeleton.dtsi"
 
+#include <dt-bindings/interrupt-controller/irq.h>
+
 / {
        compatible = "renesas,sh73a0";
 
 
        pmu {
                compatible = "arm,cortex-a9-pmu";
-               interrupts = <0 55 4>,
-                            <0 56 4>;
+               interrupts = <0 55 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 56 IRQ_TYPE_LEVEL_HIGH>;
        };
 
        irqpin0: irqpin@e6900000 {
-               compatible = "renesas,intc-irqpin";
+               compatible = "renesas,intc-irqpin-sh73a0", "renesas,intc-irqpin";
                #interrupt-cells = <2>;
                interrupt-controller;
                reg = <0xe6900000 4>,
                        <0xe6900040 1>,
                        <0xe6900060 1>;
                interrupt-parent = <&gic>;
-               interrupts = <0 1 0x4
-                             0 2 0x4
-                             0 3 0x4
-                             0 4 0x4
-                             0 5 0x4
-                             0 6 0x4
-                             0 7 0x4
-                             0 8 0x4>;
+               interrupts = <0 1 IRQ_TYPE_LEVEL_HIGH
+                             0 2 IRQ_TYPE_LEVEL_HIGH
+                             0 3 IRQ_TYPE_LEVEL_HIGH
+                             0 4 IRQ_TYPE_LEVEL_HIGH
+                             0 5 IRQ_TYPE_LEVEL_HIGH
+                             0 6 IRQ_TYPE_LEVEL_HIGH
+                             0 7 IRQ_TYPE_LEVEL_HIGH
+                             0 8 IRQ_TYPE_LEVEL_HIGH>;
        };
 
        irqpin1: irqpin@e6900004 {
-               compatible = "renesas,intc-irqpin";
+               compatible = "renesas,intc-irqpin-sh73a0", "renesas,intc-irqpin";
                #interrupt-cells = <2>;
                interrupt-controller;
                reg = <0xe6900004 4>,
                        <0xe6900044 1>,
                        <0xe6900064 1>;
                interrupt-parent = <&gic>;
-               interrupts = <0 9 0x4
-                             0 10 0x4
-                             0 11 0x4
-                             0 12 0x4
-                             0 13 0x4
-                             0 14 0x4
-                             0 15 0x4
-                             0 16 0x4>;
+               interrupts = <0 9 IRQ_TYPE_LEVEL_HIGH
+                             0 10 IRQ_TYPE_LEVEL_HIGH
+                             0 11 IRQ_TYPE_LEVEL_HIGH
+                             0 12 IRQ_TYPE_LEVEL_HIGH
+                             0 13 IRQ_TYPE_LEVEL_HIGH
+                             0 14 IRQ_TYPE_LEVEL_HIGH
+                             0 15 IRQ_TYPE_LEVEL_HIGH
+                             0 16 IRQ_TYPE_LEVEL_HIGH>;
                control-parent;
        };
 
        irqpin2: irqpin@e6900008 {
-               compatible = "renesas,intc-irqpin";
+               compatible = "renesas,intc-irqpin-sh73a0", "renesas,intc-irqpin";
                #interrupt-cells = <2>;
                interrupt-controller;
                reg = <0xe6900008 4>,
                        <0xe6900048 1>,
                        <0xe6900068 1>;
                interrupt-parent = <&gic>;
-               interrupts = <0 17 0x4
-                             0 18 0x4
-                             0 19 0x4
-                             0 20 0x4
-                             0 21 0x4
-                             0 22 0x4
-                             0 23 0x4
-                             0 24 0x4>;
+               interrupts = <0 17 IRQ_TYPE_LEVEL_HIGH
+                             0 18 IRQ_TYPE_LEVEL_HIGH
+                             0 19 IRQ_TYPE_LEVEL_HIGH
+                             0 20 IRQ_TYPE_LEVEL_HIGH
+                             0 21 IRQ_TYPE_LEVEL_HIGH
+                             0 22 IRQ_TYPE_LEVEL_HIGH
+                             0 23 IRQ_TYPE_LEVEL_HIGH
+                             0 24 IRQ_TYPE_LEVEL_HIGH>;
        };
 
        irqpin3: irqpin@e690000c {
-               compatible = "renesas,intc-irqpin";
+               compatible = "renesas,intc-irqpin-sh73a0", "renesas,intc-irqpin";
                #interrupt-cells = <2>;
                interrupt-controller;
                reg = <0xe690000c 4>,
                        <0xe690004c 1>,
                        <0xe690006c 1>;
                interrupt-parent = <&gic>;
-               interrupts = <0 25 0x4
-                             0 26 0x4
-                             0 27 0x4
-                             0 28 0x4
-                             0 29 0x4
-                             0 30 0x4
-                             0 31 0x4
-                             0 32 0x4>;
+               interrupts = <0 25 IRQ_TYPE_LEVEL_HIGH
+                             0 26 IRQ_TYPE_LEVEL_HIGH
+                             0 27 IRQ_TYPE_LEVEL_HIGH
+                             0 28 IRQ_TYPE_LEVEL_HIGH
+                             0 29 IRQ_TYPE_LEVEL_HIGH
+                             0 30 IRQ_TYPE_LEVEL_HIGH
+                             0 31 IRQ_TYPE_LEVEL_HIGH
+                             0 32 IRQ_TYPE_LEVEL_HIGH>;
        };
 
        i2c0: i2c@e6820000 {
                compatible = "renesas,rmobile-iic";
                reg = <0xe6820000 0x425>;
                interrupt-parent = <&gic>;
-               interrupts = <0 167 0x4
-                             0 168 0x4
-                             0 169 0x4
-                             0 170 0x4>;
+               interrupts = <0 167 IRQ_TYPE_LEVEL_HIGH
+                             0 168 IRQ_TYPE_LEVEL_HIGH
+                             0 169 IRQ_TYPE_LEVEL_HIGH
+                             0 170 IRQ_TYPE_LEVEL_HIGH>;
                status = "disabled";
        };
 
                compatible = "renesas,rmobile-iic";
                reg = <0xe6822000 0x425>;
                interrupt-parent = <&gic>;
-               interrupts = <0 51 0x4
-                             0 52 0x4
-                             0 53 0x4
-                             0 54 0x4>;
+               interrupts = <0 51 IRQ_TYPE_LEVEL_HIGH
+                             0 52 IRQ_TYPE_LEVEL_HIGH
+                             0 53 IRQ_TYPE_LEVEL_HIGH
+                             0 54 IRQ_TYPE_LEVEL_HIGH>;
                status = "disabled";
        };
 
                compatible = "renesas,rmobile-iic";
                reg = <0xe6824000 0x425>;
                interrupt-parent = <&gic>;
-               interrupts = <0 171 0x4
-                             0 172 0x4
-                             0 173 0x4
-                             0 174 0x4>;
+               interrupts = <0 171 IRQ_TYPE_LEVEL_HIGH
+                             0 172 IRQ_TYPE_LEVEL_HIGH
+                             0 173 IRQ_TYPE_LEVEL_HIGH
+                             0 174 IRQ_TYPE_LEVEL_HIGH>;
                status = "disabled";
        };
 
                compatible = "renesas,rmobile-iic";
                reg = <0xe6826000 0x425>;
                interrupt-parent = <&gic>;
-               interrupts = <0 183 0x4
-                             0 184 0x4
-                             0 185 0x4
-                             0 186 0x4>;
+               interrupts = <0 183 IRQ_TYPE_LEVEL_HIGH
+                             0 184 IRQ_TYPE_LEVEL_HIGH
+                             0 185 IRQ_TYPE_LEVEL_HIGH
+                             0 186 IRQ_TYPE_LEVEL_HIGH>;
                status = "disabled";
        };
 
                compatible = "renesas,rmobile-iic";
                reg = <0xe6828000 0x425>;
                interrupt-parent = <&gic>;
-               interrupts = <0 187 0x4
-                             0 188 0x4
-                             0 189 0x4
-                             0 190 0x4>;
+               interrupts = <0 187 IRQ_TYPE_LEVEL_HIGH
+                             0 188 IRQ_TYPE_LEVEL_HIGH
+                             0 189 IRQ_TYPE_LEVEL_HIGH
+                             0 190 IRQ_TYPE_LEVEL_HIGH>;
                status = "disabled";
        };
 
-       mmcif: mmcif@e6bd0000 {
+       mmcif: mmc@e6bd0000 {
                compatible = "renesas,sh-mmcif";
                reg = <0xe6bd0000 0x100>;
                interrupt-parent = <&gic>;
-               interrupts = <0 140 0x4
-                             0 141 0x4>;
+               interrupts = <0 140 IRQ_TYPE_LEVEL_HIGH
+                             0 141 IRQ_TYPE_LEVEL_HIGH>;
                reg-io-width = <4>;
                status = "disabled";
        };
 
-       sdhi0: sdhi@ee100000 {
-               compatible = "renesas,sdhi-r8a7740";
+       sdhi0: sd@ee100000 {
+               compatible = "renesas,sdhi-sh73a0";
                reg = <0xee100000 0x100>;
                interrupt-parent = <&gic>;
-               interrupts = <0 83 4
-                               0 84 4
-                               0 85 4>;
+               interrupts = <0 83 IRQ_TYPE_LEVEL_HIGH
+                             0 84 IRQ_TYPE_LEVEL_HIGH
+                             0 85 IRQ_TYPE_LEVEL_HIGH>;
                cap-sd-highspeed;
                status = "disabled";
        };
 
        /* SDHI1 and SDHI2 have no CD pins, no need for CD IRQ */
-       sdhi1: sdhi@ee120000 {
-               compatible = "renesas,sdhi-r8a7740";
+       sdhi1: sd@ee120000 {
+               compatible = "renesas,sdhi-sh73a0";
                reg = <0xee120000 0x100>;
                interrupt-parent = <&gic>;
-               interrupts = <0 88 4
-                               0 89 4>;
+               interrupts = <0 88 IRQ_TYPE_LEVEL_HIGH
+                             0 89 IRQ_TYPE_LEVEL_HIGH>;
                toshiba,mmc-wrprotect-disable;
                cap-sd-highspeed;
                status = "disabled";
        };
 
-       sdhi2: sdhi@ee140000 {
-               compatible = "renesas,sdhi-r8a7740";
+       sdhi2: sd@ee140000 {
+               compatible = "renesas,sdhi-sh73a0";
                reg = <0xee140000 0x100>;
                interrupt-parent = <&gic>;
-               interrupts = <0 104 4
-                               0 105 4>;
+               interrupts = <0 104 IRQ_TYPE_LEVEL_HIGH
+                             0 105 IRQ_TYPE_LEVEL_HIGH>;
                toshiba,mmc-wrprotect-disable;
                cap-sd-highspeed;
                status = "disabled";
index 6d09b8d42fdd123da5e3b5e4b315983c42f9c6eb..f936476c2753ff380ab7cfe04064fba2598d87c4 100644 (file)
 
                                        mpu_periph_clk: mpu_periph_clk {
                                                #clock-cells = <0>;
-                                               compatible = "altr,socfpga-gate-clk";
+                                               compatible = "altr,socfpga-perip-clk";
                                                clocks = <&mpuclk>;
                                                fixed-divider = <4>;
                                        };
 
                                        mpu_l2_ram_clk: mpu_l2_ram_clk {
                                                #clock-cells = <0>;
-                                               compatible = "altr,socfpga-gate-clk";
+                                               compatible = "altr,socfpga-perip-clk";
                                                clocks = <&mpuclk>;
                                                fixed-divider = <2>;
                                        };
 
                                        l3_main_clk: l3_main_clk {
                                                #clock-cells = <0>;
-                                               compatible = "altr,socfpga-gate-clk";
+                                               compatible = "altr,socfpga-perip-clk";
                                                clocks = <&mainclk>;
+                                               fixed-divider = <1>;
                                        };
 
                                        l3_mp_clk: l3_mp_clk {
index 8c45d85ac13edd437c082c8f63966052b67bdab8..4851c387d52dfa843ed9eff81e5e098146854d27 100644 (file)
@@ -15,7 +15,7 @@
 /* Pull Up */
 #define PU                     (1 << 26)
 /* Open Drain */
-#define OD                     (1 << 26)
+#define OD                     (1 << 25)
 #define RT                     (1 << 23)
 #define INVERTCLK              (1 << 22)
 #define CLKNOTDATA             (1 << 21)
index 7da99fe497e13d59215b2bdd1b16a41fcd120c70..e0853ea02df2296dc78c997123f3173754df48a8 100644 (file)
                        interrupts = <0 31 IRQ_TYPE_LEVEL_HIGH>;
                        v-ape-supply = <&db8500_vape_reg>;
 
+                       dmas = <&dma 31 0 0x12>, /* Logical - DevToMem - HighPrio */
+                              <&dma 31 0 0x10>; /* Logical - MemToDev - HighPrio */
+                       dma-names = "rx", "tx";
+
                        clocks = <&prcc_kclk 1 3>, <&prcc_pclk 1 3>;
                        clock-names = "msp", "apb_pclk";
 
                        interrupts = <0 62 IRQ_TYPE_LEVEL_HIGH>;
                        v-ape-supply = <&db8500_vape_reg>;
 
+                       dmas = <&dma 30 0 0x10>; /* Logical - MemToDev - HighPrio */
+                       dma-names = "tx";
+
                        clocks = <&prcc_kclk 1 4>, <&prcc_pclk 1 4>;
                        clock-names = "msp", "apb_pclk";
 
                        interrupts = <0 98 IRQ_TYPE_LEVEL_HIGH>;
                        v-ape-supply = <&db8500_vape_reg>;
 
+                       dmas = <&dma 14 0 0x12>, /* Logical  - DevToMem - HighPrio */
+                              <&dma 14 1 0x19>; /* Physical Chan 1 - MemToDev
+                                                    HighPrio - Fixed */
+                       dma-names = "rx", "tx";
+
                        clocks = <&prcc_kclk 2 3>, <&prcc_pclk 2 5>;
                        clock-names = "msp", "apb_pclk";
 
                        interrupts = <0 62 IRQ_TYPE_LEVEL_HIGH>;
                        v-ape-supply = <&db8500_vape_reg>;
 
+                       dmas = <&dma 30 0 0x12>; /* Logical - DevToMem - HighPrio */
+                       dma-names = "rx";
+
                        clocks = <&prcc_kclk 1 10>, <&prcc_pclk 1 11>;
                        clock-names = "msp", "apb_pclk";
 
                        status = "disabled";
                };
 
+               mcde@a0350000 {
+                       compatible = "stericsson,mcde";
+                       reg = <0xa0350000 0x1000>, /* MCDE */
+                             <0xa0351000 0x1000>, /* DSI link 1 */
+                             <0xa0352000 0x1000>, /* DSI link 2 */
+                             <0xa0353000 0x1000>; /* DSI link 3 */
+                       interrupts = <0 48 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&prcmu_clk PRCMU_MCDECLK>, /* Main MCDE clock */
+                                <&prcmu_clk PRCMU_LCDCLK>, /* LCD clock */
+                                <&prcmu_clk PRCMU_PLLDSI>, /* HDMI clock */
+                                <&prcmu_clk PRCMU_DSI0CLK>, /* DSI 0 */
+                                <&prcmu_clk PRCMU_DSI1CLK>, /* DSI 1 */
+                                <&prcmu_clk PRCMU_DSI0ESCCLK>, /* TVout clock 0 */
+                                <&prcmu_clk PRCMU_DSI1ESCCLK>, /* TVout clock 1 */
+                                <&prcmu_clk PRCMU_DSI2ESCCLK>; /* TVout clock 2 */
+               };
+
                cryp@a03cb000 {
                        compatible = "stericsson,ux500-cryp";
                        reg = <0xa03cb000 0x1000>;
diff --git a/arch/arm/boot/dts/ste-href-family-pinctrl.dtsi b/arch/arm/boot/dts/ste-href-family-pinctrl.dtsi
new file mode 100644 (file)
index 0000000..addfcc7
--- /dev/null
@@ -0,0 +1,745 @@
+/*
+ * Copyright 2013 Linaro Ltd.
+ *
+ * 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 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include "ste-nomadik-pinctrl.dtsi"
+
+/ {
+       soc {
+               pinctrl {
+                       /* Settings for all UART default and sleep states */
+                       uart0 {
+                               uart0_default_mode: uart0_default {
+                                       default_mux {
+                                               ste,function = "u0";
+                                               ste,pins = "u0_a_1";
+                                       };
+                                       default_cfg1 {
+                                               ste,pins = "GPIO0_AJ5", "GPIO2_AH4"; /* CTS+RXD */
+                                               ste,config = <&in_pu>;
+                                       };
+
+                                       default_cfg2 {
+                                               ste,pins = "GPIO1_AJ3", "GPIO3_AH3"; /* RTS+TXD */
+                                               ste,config = <&out_hi>;
+                                       };
+                               };
+
+                               uart0_sleep_mode: uart0_sleep {
+                                       sleep_cfg1 {
+                                               ste,pins = "GPIO0_AJ5", "GPIO2_AH4"; /* CTS+RXD */
+                                               ste,config = <&slpm_in_wkup_pdis>;
+                                       };
+
+                                       sleep_cfg2 {
+                                               ste,pins = "GPIO1_AJ3"; /* RTS */
+                                               ste,config = <&slpm_out_hi_wkup_pdis>;
+                                       };
+
+                                       sleep_cfg3 {
+                                               ste,pins = "GPIO3_AH3"; /* TXD */
+                                               ste,config = <&slpm_out_wkup_pdis>;
+                                       };
+                               };
+                       };
+
+                       uart1 {
+                               uart1_default_mode: uart1_default {
+                                       default_mux {
+                                               ste,function = "u1";
+                                               ste,pins = "u1rxtx_a_1";
+                                       };
+                                       default_cfg1 {
+                                               ste,pins = "GPIO4_AH6"; /* RXD */
+                                               ste,config = <&in_pu>;
+                                       };
+
+                                       default_cfg2 {
+                                               ste,pins = "GPIO5_AG6"; /* TXD */
+                                               ste,config = <&out_hi>;
+                                       };
+                               };
+
+                               uart1_sleep_mode: uart1_sleep {
+                                       sleep_cfg1 {
+                                               ste,pins = "GPIO4_AH6"; /* RXD */
+                                               ste,config = <&slpm_in_wkup_pdis>;
+                                       };
+
+                                       sleep_cfg2 {
+                                               ste,pins = "GPIO5_AG6"; /* TXD */
+                                               ste,config = <&slpm_out_wkup_pdis>;
+                                       };
+                               };
+                       };
+
+                       uart2 {
+                               uart2_default_mode: uart2_default {
+                                       default_mux {
+                                               ste,function = "u2";
+                                               ste,pins = "u2rxtx_c_1";
+                                       };
+                                       default_cfg1 {
+                                               ste,pins = "GPIO29_W2"; /* RXD */
+                                               ste,config = <&in_pu>;
+                                       };
+
+                                       default_cfg2 {
+                                               ste,pins = "GPIO30_W3"; /* TXD */
+                                               ste,config = <&out_hi>;
+                                       };
+                               };
+
+                               uart2_sleep_mode: uart2_sleep {
+                                       sleep_cfg1 {
+                                               ste,pins = "GPIO29_W2"; /* RXD */
+                                               ste,config = <&in_wkup_pdis>;
+                                       };
+
+                                       sleep_cfg2 {
+                                               ste,pins = "GPIO30_W3"; /* TXD */
+                                               ste,config = <&out_wkup_pdis>;
+                                       };
+                               };
+                       };
+
+                       /* Settings for all I2C default and sleep states */
+                       i2c0 {
+                               i2c0_default_mode: i2c_default {
+                                       default_mux {
+                                               ste,function = "i2c0";
+                                               ste,pins = "i2c0_a_1";
+                                       };
+                                       default_cfg1 {
+                                               ste,pins = "GPIO147_C15", "GPIO148_B16"; /* SDA/SCL */
+                                               ste,config = <&in_pu>;
+                                       };
+                               };
+
+                               i2c0_sleep_mode: i2c_sleep {
+                                       sleep_cfg1 {
+                                               ste,pins = "GPIO147_C15", "GPIO148_B16"; /* SDA/SCL */
+                                               ste,config = <&slpm_in_wkup_pdis>;
+                                       };
+                               };
+                       };
+
+                       i2c1 {
+                               i2c1_default_mode: i2c_default {
+                                       default_mux {
+                                               ste,function = "i2c1";
+                                               ste,pins = "i2c1_b_2";
+                                       };
+                                       default_cfg1 {
+                                               ste,pins = "GPIO16_AD3", "GPIO17_AD4"; /* SDA/SCL */
+                                               ste,config = <&in_pu>;
+                                       };
+                               };
+
+                               i2c1_sleep_mode: i2c_sleep {
+                                       sleep_cfg1 {
+                                               ste,pins = "GPIO16_AD3", "GPIO17_AD4"; /* SDA/SCL */
+                                               ste,config = <&slpm_in_wkup_pdis>;
+                                       };
+                               };
+                       };
+
+                       i2c2 {
+                               i2c2_default_mode: i2c_default {
+                                       default_mux {
+                                               ste,function = "i2c2";
+                                               ste,pins = "i2c2_b_2";
+                                       };
+                                       default_cfg1 {
+                                               ste,pins = "GPIO10_AF5", "GPIO11_AG4"; /* SDA/SCL */
+                                               ste,config = <&in_pu>;
+                                       };
+                               };
+
+                               i2c2_sleep_mode: i2c_sleep {
+                                       sleep_cfg1 {
+                                               ste,pins = "GPIO10_AF5", "GPIO11_AG4"; /* SDA/SCL */
+                                               ste,config = <&slpm_in_wkup_pdis>;
+                                       };
+                               };
+                       };
+
+                       i2c3 {
+                               i2c3_default_mode: i2c_default {
+                                       default_mux {
+                                               ste,function = "i2c3";
+                                               ste,pins = "i2c3_c_2";
+                                       };
+                                       default_cfg1 {
+                                               ste,pins = "GPIO229_AG7", "GPIO230_AF7"; /* SDA/SCL */
+                                               ste,config = <&in_pu>;
+                                       };
+                               };
+
+                               i2c3_sleep_mode: i2c_sleep {
+                                       sleep_cfg1 {
+                                               ste,pins = "GPIO229_AG7", "GPIO230_AF7"; /* SDA/SCL */
+                                               ste,config = <&slpm_in_wkup_pdis>;
+                                       };
+                               };
+                       };
+
+                       /*
+                        * Activating I2C4 will conflict with UART1 about the same pins so do not
+                        * enable I2C4 and UART1 at the same time.
+                        */
+                       i2c4 {
+                               i2c4_default_mode: i2c_default {
+                                       default_mux {
+                                               ste,function = "i2c4";
+                                               ste,pins = "i2c4_b_1";
+                                       };
+                                       default_cfg1 {
+                                               ste,pins = "GPIO4_AH6", "GPIO5_AG6"; /* SDA/SCL */
+                                               ste,config = <&in_pu>;
+                                       };
+                               };
+
+                               i2c4_sleep_mode: i2c_sleep {
+                                       sleep_cfg1 {
+                                               ste,pins = "GPIO4_AH6", "GPIO5_AG6"; /* SDA/SCL */
+                                               ste,config = <&slpm_in_wkup_pdis>;
+                                       };
+                               };
+                       };
+
+                       /* Settings for all SPI default and sleep states */
+                       spi2 {
+                               spi2_default_mode: spi_default {
+                                       default_mux {
+                                               ste,function = "spi2";
+                                               ste,pins = "spi2_oc1_2";
+                                       };
+                                       default_cfg1 {
+                                               ste,pins = "GPIO216_AG12"; /* FRM */
+                                               ste,config = <&gpio_out_hi>;
+                                       };
+                                       default_cfg2 {
+                                               ste,pins = "GPIO218_AH11"; /* RXD */
+                                               ste,config = <&in_pd>;
+                                       };
+                                       default_cfg3 {
+                                               ste,pins =
+                                               "GPIO215_AH13", /* TXD */
+                                               "GPIO217_AH12"; /* CLK */
+                                               ste,config = <&out_lo>;
+                                       };
+                               };
+
+                               spi2_idle_mode: spi_idle {
+                                       /*
+                                        * The idle mode is basically sleep mode sans wakeups. Also
+                                        * note that we have muxes the pins off the function here
+                                        * as we do not state any muxing.
+                                        */
+                                       idle_cfg1 {
+                                               ste,pins = "GPIO218_AH11"; /* RXD */
+                                               ste,config = <&slpm_in_pdis>;
+                                       };
+                                       idle_cfg2 {
+                                               ste,pins = "GPIO215_AH13"; /* TXD */
+                                               ste,config = <&slpm_out_lo_pdis>;
+                                       };
+                                       idle_cfg3 {
+                                               ste,pins = "GPIO217_AH12"; /* CLK */
+                                               ste,config = <&slpm_pdis>;
+                                       };
+                               };
+
+                               spi2_sleep_mode: spi_sleep {
+                                       sleep_cfg1 {
+                                               ste,pins =
+                                               "GPIO216_AG12", /* FRM */
+                                               "GPIO218_AH11"; /* RXD */
+                                               ste,config = <&slpm_in_wkup_pdis>;
+                                       };
+                                       sleep_cfg2 {
+                                               ste,pins = "GPIO215_AH13"; /* TXD */
+                                               ste,config = <&slpm_out_lo_wkup_pdis>;
+                                       };
+                                       sleep_cfg3 {
+                                               ste,pins = "GPIO217_AH12"; /* CLK */
+                                               ste,config = <&slpm_wkup_pdis>;
+                                       };
+                               };
+                       };
+
+                       /* Settings for all MMC/SD/SDIO default and sleep states */
+                       sdi0 {
+                               /* This is the external SD card slot, 4 bits wide */
+                               sdi0_default_mode: sdi0_default {
+                                       default_mux {
+                                               ste,function = "mc0";
+                                               ste,pins = "mc0_a_1";
+                                       };
+                                       default_cfg1 {
+                                               ste,pins =
+                                               "GPIO18_AC2", /* CMDDIR */
+                                               "GPIO19_AC1", /* DAT0DIR */
+                                               "GPIO20_AB4"; /* DAT2DIR */
+                                               ste,config = <&out_hi>;
+                                       };
+                                       default_cfg2 {
+                                               ste,pins = "GPIO22_AA3"; /* FBCLK */
+                                               ste,config = <&in_nopull>;
+                                       };
+                                       default_cfg3 {
+                                               ste,pins = "GPIO23_AA4"; /* CLK */
+                                               ste,config = <&out_lo>;
+                                       };
+                                       default_cfg4 {
+                                               ste,pins =
+                                               "GPIO24_AB2", /* CMD */
+                                               "GPIO25_Y4", /* DAT0 */
+                                               "GPIO26_Y2", /* DAT1 */
+                                               "GPIO27_AA2", /* DAT2 */
+                                               "GPIO28_AA1"; /* DAT3 */
+                                               ste,config = <&in_pu>;
+                                       };
+                               };
+
+                               sdi0_sleep_mode: sdi0_sleep {
+                                       sleep_cfg1 {
+                                               ste,pins =
+                                               "GPIO18_AC2", /* CMDDIR */
+                                               "GPIO19_AC1", /* DAT0DIR */
+                                               "GPIO20_AB4"; /* DAT2DIR */
+                                               ste,config = <&slpm_out_hi_wkup_pdis>;
+                                       };
+                                       sleep_cfg2 {
+                                               ste,pins =
+                                               "GPIO22_AA3", /* FBCLK */
+                                               "GPIO24_AB2", /* CMD */
+                                               "GPIO25_Y4", /* DAT0 */
+                                               "GPIO26_Y2", /* DAT1 */
+                                               "GPIO27_AA2", /* DAT2 */
+                                               "GPIO28_AA1"; /* DAT3 */
+                                               ste,config = <&slpm_in_wkup_pdis>;
+                                       };
+                                       sleep_cfg3 {
+                                               ste,pins = "GPIO23_AA4"; /* CLK */
+                                               ste,config = <&slpm_out_lo_wkup_pdis>;
+                                       };
+                               };
+                       };
+
+                       sdi1 {
+                               /* This is the WLAN SDIO 4 bits wide */
+                               sdi1_default_mode: sdi1_default {
+                                       default_mux {
+                                               ste,function = "mc1";
+                                               ste,pins = "mc1_a_1";
+                                       };
+                                       default_cfg1 {
+                                               ste,pins = "GPIO208_AH16"; /* CLK */
+                                               ste,config = <&out_lo>;
+                                       };
+                                       default_cfg2 {
+                                               ste,pins = "GPIO209_AG15"; /* FBCLK */
+                                               ste,config = <&in_nopull>;
+                                       };
+                                       default_cfg3 {
+                                               ste,pins =
+                                               "GPIO210_AJ15", /* CMD */
+                                               "GPIO211_AG14", /* DAT0 */
+                                               "GPIO212_AF13", /* DAT1 */
+                                               "GPIO213_AG13", /* DAT2 */
+                                               "GPIO214_AH15"; /* DAT3 */
+                                               ste,config = <&in_pu>;
+                                       };
+                               };
+
+                               sdi1_sleep_mode: sdi1_sleep {
+                                       sleep_cfg1 {
+                                               ste,pins = "GPIO208_AH16"; /* CLK */
+                                               ste,config = <&slpm_out_lo_wkup_pdis>;
+                                       };
+                                       sleep_cfg2 {
+                                               ste,pins =
+                                               "GPIO209_AG15", /* FBCLK */
+                                               "GPIO210_AJ15", /* CMD */
+                                               "GPIO211_AG14", /* DAT0 */
+                                               "GPIO212_AF13", /* DAT1 */
+                                               "GPIO213_AG13", /* DAT2 */
+                                               "GPIO214_AH15"; /* DAT3 */
+                                               ste,config = <&slpm_in_wkup_pdis>;
+                                       };
+                               };
+                       };
+
+                       sdi2 {
+                               /* This is the eMMC 8 bits wide, usually PoP eMMC */
+                               sdi2_default_mode: sdi2_default {
+                                       default_mux {
+                                               ste,function = "mc2";
+                                               ste,pins = "mc2_a_1";
+                                       };
+                                       default_cfg1 {
+                                               ste,pins = "GPIO128_A5"; /* CLK */
+                                               ste,config = <&out_lo>;
+                                       };
+                                       default_cfg2 {
+                                               ste,pins = "GPIO130_C8"; /* FBCLK */
+                                               ste,config = <&in_nopull>;
+                                       };
+                                       default_cfg3 {
+                                               ste,pins =
+                                               "GPIO129_B4", /* CMD */
+                                               "GPIO131_A12", /* DAT0 */
+                                               "GPIO132_C10", /* DAT1 */
+                                               "GPIO133_B10", /* DAT2 */
+                                               "GPIO134_B9", /* DAT3 */
+                                               "GPIO135_A9", /* DAT4 */
+                                               "GPIO136_C7", /* DAT5 */
+                                               "GPIO137_A7", /* DAT6 */
+                                               "GPIO138_C5"; /* DAT7 */
+                                               ste,config = <&in_pu>;
+                                       };
+                               };
+
+                               sdi2_sleep_mode: sdi2_sleep {
+                                       sleep_cfg1 {
+                                               ste,pins = "GPIO128_A5"; /* CLK */
+                                               ste,config = <&out_lo_wkup_pdis>;
+                                       };
+                                       sleep_cfg2 {
+                                               ste,pins =
+                                               "GPIO130_C8", /* FBCLK */
+                                               "GPIO129_B4"; /* CMD */
+                                               ste,config = <&in_wkup_pdis_en>;
+                                       };
+                                       sleep_cfg3 {
+                                               ste,pins =
+                                               "GPIO131_A12", /* DAT0 */
+                                               "GPIO132_C10", /* DAT1 */
+                                               "GPIO133_B10", /* DAT2 */
+                                               "GPIO134_B9", /* DAT3 */
+                                               "GPIO135_A9", /* DAT4 */
+                                               "GPIO136_C7", /* DAT5 */
+                                               "GPIO137_A7", /* DAT6 */
+                                               "GPIO138_C5"; /* DAT7 */
+                                               ste,config = <&in_wkup_pdis>;
+                                       };
+                               };
+                       };
+
+                       sdi4 {
+                               /* This is the eMMC 8 bits wide, usually PCB-mounted eMMC */
+                               sdi4_default_mode: sdi4_default {
+                                       default_mux {
+                                               ste,function = "mc4";
+                                               ste,pins = "mc4_a_1";
+                                       };
+                                       default_cfg1 {
+                                               ste,pins = "GPIO203_AE23"; /* CLK */
+                                               ste,config = <&out_lo>;
+                                       };
+                                       default_cfg2 {
+                                               ste,pins = "GPIO202_AF25"; /* FBCLK */
+                                               ste,config = <&in_nopull>;
+                                       };
+                                       default_cfg3 {
+                                               ste,pins =
+                                               "GPIO201_AF24", /* CMD */
+                                               "GPIO200_AH26", /* DAT0 */
+                                               "GPIO199_AH23", /* DAT1 */
+                                               "GPIO198_AG25", /* DAT2 */
+                                               "GPIO197_AH24", /* DAT3 */
+                                               "GPIO207_AJ23", /* DAT4 */
+                                               "GPIO206_AG24", /* DAT5 */
+                                               "GPIO205_AG23", /* DAT6 */
+                                               "GPIO204_AF23"; /* DAT7 */
+                                               ste,config = <&in_pu>;
+                                       };
+                               };
+
+                               sdi4_sleep_mode: sdi4_sleep {
+                                       sleep_cfg1 {
+                                               ste,pins = "GPIO203_AE23"; /* CLK */
+                                               ste,config = <&out_lo_wkup_pdis>;
+                                       };
+                                       sleep_cfg2 {
+                                               ste,pins =
+                                               "GPIO202_AF25", /* FBCLK */
+                                               "GPIO201_AF24", /* CMD */
+                                               "GPIO200_AH26", /* DAT0 */
+                                               "GPIO199_AH23", /* DAT1 */
+                                               "GPIO198_AG25", /* DAT2 */
+                                               "GPIO197_AH24", /* DAT3 */
+                                               "GPIO207_AJ23", /* DAT4 */
+                                               "GPIO206_AG24", /* DAT5 */
+                                               "GPIO205_AG23", /* DAT6 */
+                                               "GPIO204_AF23"; /* DAT7 */
+                                               ste,config = <&slpm_in_wkup_pdis>;
+                                       };
+                               };
+                       };
+
+                       /*
+                        * Multi-rate serial ports (MSPs) - MSP3 output is internal and
+                        * cannot be muxed onto any pins.
+                        */
+                       msp0 {
+                               msp0_default_mode: msp0_default {
+                                       default_msp0_mux {
+                                               ste,function = "msp0";
+                                               ste,pins = "msp0txrx_a_1", "msp0tfstck_a_1";
+                                       };
+                                       default_msp0_cfg {
+                                               ste,pins =
+                                               "GPIO12_AC4", /* TXD */
+                                               "GPIO15_AC3", /* RXD */
+                                               "GPIO13_AF3", /* TFS */
+                                               "GPIO14_AE3"; /* TCK */
+                                               ste,config = <&in_nopull>;
+                                       };
+                               };
+                       };
+
+                       msp1 {
+                               msp1_default_mode: msp1_default {
+                                       default_mux {
+                                               ste,function = "msp1";
+                                               ste,pins = "msp1txrx_a_1", "msp1_a_1";
+                                       };
+                                       default_cfg1 {
+                                               ste,pins = "GPIO33_AF2";
+                                               ste,config = <&out_lo>;
+                                       };
+                                       default_cfg2 {
+                                               ste,pins =
+                                               "GPIO34_AE1",
+                                               "GPIO35_AE2",
+                                               "GPIO36_AG2";
+                                               ste,config = <&in_nopull>;
+                                       };
+
+                               };
+                       };
+
+                       msp2 {
+                               msp2_default_mode: msp2_default {
+                                       /* MSP2 usually used for HDMI audio */
+                                       default_mux {
+                                               ste,function = "msp2";
+                                               ste,pins = "msp2_a_1";
+                                       };
+                                       default_cfg1 {
+                                               ste,pins =
+                                               "GPIO193_AH27", /* TXD */
+                                               "GPIO194_AF27", /* TCK */
+                                               "GPIO195_AG28"; /* TFS */
+                                               ste,config = <&in_pd>;
+                                       };
+                                       default_cfg2 {
+                                               ste,pins = "GPIO196_AG26"; /* RXD */
+                                               ste,config = <&out_lo>;
+                                       };
+                               };
+                       };
+
+
+                       musb {
+                               musb_default_mode: musb_default {
+                                       default_mux {
+                                               ste,function = "usb";
+                                               ste,pins = "usb_a_1";
+                                       };
+                                       default_cfg1 {
+                                               ste,pins =
+                                               "GPIO256_AF28", /* NXT */
+                                               "GPIO258_AD29", /* XCLK */
+                                               "GPIO259_AC29", /* DIR */
+                                               "GPIO260_AD28", /* DAT7 */
+                                               "GPIO261_AD26", /* DAT6 */
+                                               "GPIO262_AE26", /* DAT5 */
+                                               "GPIO263_AG29", /* DAT4 */
+                                               "GPIO264_AE27", /* DAT3 */
+                                               "GPIO265_AD27", /* DAT2 */
+                                               "GPIO266_AC28", /* DAT1 */
+                                               "GPIO267_AC27"; /* DAT0 */
+                                               ste,config = <&in_nopull>;
+                                       };
+                                       default_cfg2 {
+                                               ste,pins = "GPIO257_AE29"; /* STP */
+                                               ste,config = <&out_hi>;
+                                       };
+                               };
+
+                               musb_sleep_mode: musb_sleep {
+                                       sleep_cfg1 {
+                                               ste,pins =
+                                               "GPIO256_AF28", /* NXT */
+                                               "GPIO258_AD29", /* XCLK */
+                                               "GPIO259_AC29"; /* DIR */
+                                               ste,config = <&slpm_wkup_pdis_en>;
+                                       };
+                                       sleep_cfg2 {
+                                               ste,pins = "GPIO257_AE29"; /* STP */
+                                               ste,config = <&slpm_out_hi_wkup_pdis>;
+                                       };
+                                       sleep_cfg3 {
+                                               ste,pins =
+                                               "GPIO260_AD28", /* DAT7 */
+                                               "GPIO261_AD26", /* DAT6 */
+                                               "GPIO262_AE26", /* DAT5 */
+                                               "GPIO263_AG29", /* DAT4 */
+                                               "GPIO264_AE27", /* DAT3 */
+                                               "GPIO265_AD27", /* DAT2 */
+                                               "GPIO266_AC28", /* DAT1 */
+                                               "GPIO267_AC27"; /* DAT0 */
+                                               ste,config = <&slpm_in_wkup_pdis_en>;
+                                       };
+                               };
+                       };
+
+                       mcde {
+                               lcd_default_mode: lcd_default {
+                                       default_mux {
+                                               /* Mux in VSI0 and all the data lines */
+                                               ste,function = "lcd";
+                                               ste,pins =
+                                               "lcdvsi0_a_1", /* VSI0 for LCD */
+                                               "lcd_d0_d7_a_1", /* Data lines */
+                                               "lcd_d8_d11_a_1", /* TV-out */
+                                               "lcdaclk_b_1", /* Clock line for TV-out */
+                                               "lcdvsi1_a_1"; /* VSI1 for HDMI */
+                                       };
+                                       default_cfg1 {
+                                               ste,pins =
+                                               "GPIO68_E1", /* VSI0 */
+                                               "GPIO69_E2"; /* VSI1 */
+                                               ste,config = <&in_pu>;
+                                       };
+                               };
+                               lcd_sleep_mode: lcd_sleep {
+                                       sleep_cfg1 {
+                                               ste,pins = "GPIO69_E2"; /* VSI1 */
+                                               ste,config = <&slpm_in_wkup_pdis>;
+                                       };
+                               };
+                       };
+
+                       ske {
+                               /* SKE keys on position 2 in an 8x8 matrix */
+                               ske_kpa2_default_mode: ske_kpa2_default {
+                                       default_mux {
+                                               ste,function = "kp";
+                                               ste,pins = "kp_a_2";
+                                       };
+                                       default_cfg1 {
+                                               ste,pins =
+                                               "GPIO153_B17", /* I7 */
+                                               "GPIO154_C16", /* I6 */
+                                               "GPIO155_C19", /* I5 */
+                                               "GPIO156_C17", /* I4 */
+                                               "GPIO161_D21", /* I3 */
+                                               "GPIO162_D20", /* I2 */
+                                               "GPIO163_C20", /* I1 */
+                                               "GPIO164_B21"; /* I0 */
+                                               ste,config = <&in_pd>;
+                                       };
+                                       default_cfg2 {
+                                               ste,pins =
+                                               "GPIO157_A18", /* O7 */
+                                               "GPIO158_C18", /* O6 */
+                                               "GPIO159_B19", /* O5 */
+                                               "GPIO160_B20", /* O4 */
+                                               "GPIO165_C21", /* O3 */
+                                               "GPIO166_A22", /* O2 */
+                                               "GPIO167_B24", /* O1 */
+                                               "GPIO168_C22"; /* O0 */
+                                               ste,config = <&out_lo>;
+                                       };
+                               };
+                               ske_kpa2_sleep_mode: ske_kpa2_sleep {
+                                       sleep_cfg1 {
+                                               ste,pins =
+                                               "GPIO153_B17", /* I7 */
+                                               "GPIO154_C16", /* I6 */
+                                               "GPIO155_C19", /* I5 */
+                                               "GPIO156_C17", /* I4 */
+                                               "GPIO161_D21", /* I3 */
+                                               "GPIO162_D20", /* I2 */
+                                               "GPIO163_C20", /* I1 */
+                                               "GPIO164_B21"; /* I0 */
+                                               ste,config = <&slpm_in_pu_wkup_pdis_en>;
+                                       };
+                                       sleep_cfg2 {
+                                               ste,pins =
+                                               "GPIO157_A18", /* O7 */
+                                               "GPIO158_C18", /* O6 */
+                                               "GPIO159_B19", /* O5 */
+                                               "GPIO160_B20", /* O4 */
+                                               "GPIO165_C21", /* O3 */
+                                               "GPIO166_A22", /* O2 */
+                                               "GPIO167_B24", /* O1 */
+                                               "GPIO168_C22"; /* O0 */
+                                               ste,config = <&slpm_out_lo_pdis>;
+                                       };
+                               };
+                               /*
+                                * SKE keys on position 1 and "other C1" combi giving
+                                * six rows of six keys.
+                                */
+                               ske_kpaoc1_default_mode: ske_kpaoc1_default {
+                                       default_mux {
+                                               ste,function = "kp";
+                                               ste,pins = "kp_a_1", "kp_oc1_1";
+                                       };
+                                       default_cfg1 {
+                                               ste,pins =
+                                               "GPIO91_B6", /* KP_O0 */
+                                               "GPIO90_A3", /* KP_O1 */
+                                               "GPIO87_B3", /* KP_O2 */
+                                               "GPIO86_C6", /* KP_O3 */
+                                               "GPIO96_D8", /* KP_O6 */
+                                               "GPIO94_D7"; /* KP_O7 */
+                                               ste,config = <&out_lo>;
+                                       };
+                                       default_cfg2 {
+                                               ste,pins =
+                                               "GPIO93_B7", /* KP_I0 */
+                                               "GPIO92_D6", /* KP_I1 */
+                                               "GPIO89_E6", /* KP_I2 */
+                                               "GPIO88_C4", /* KP_I3 */
+                                               "GPIO97_D9", /* KP_I6 */
+                                               "GPIO95_E8"; /* KP_I7 */
+                                               ste,config = <&in_pu>;
+                                       };
+                               };
+                       };
+
+                       wlan {
+                               wlan_default_mode: wlan_default {
+                                       /*
+                                        * Activate this mode with the WLAN chip.
+                                        * These are plain GPIO pins used by WLAN
+                                        */
+                                       default_cfg1 {
+                                               ste,pins =
+                                               "GPIO226_AF8", /* WLAN_PMU_EN */
+                                               "GPIO85_D5"; /* WLAN_ENA */
+                                               ste,config = <&gpio_out_lo>;
+                                       };
+                                       default_cfg2 {
+                                               ste,pins = "GPIO4_AH6"; /* WLAN_IRQ on UART1 */
+                                               ste,config = <&gpio_in_pu>;
+                                       };
+                               };
+                       };
+               };
+       };
+};
index 76704ec0ffcc89bf3fd0d7e90726c6cc1502807b..1c3574435ea81fe6f275aff7244c6fd828cd99d0 100644 (file)
 #include <dt-bindings/interrupt-controller/irq.h>
 
 / {
+       gpio_keys {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               vdd-supply = <&ab8500_ldo_aux1_reg>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&prox_stuib_mode>, <&hall_stuib_mode>;
+
+               button@139 {
+                       /* Proximity sensor */
+                       gpios = <&gpio6 25 0x4>;
+                       linux,code = <11>; /* SW_FRONT_PROXIMITY */
+                       label = "SFH7741 Proximity Sensor";
+               };
+               button@145 {
+                       /* Hall sensor */
+                       gpios = <&gpio4 17 0x4>;
+                       linux,code = <0>; /* SW_LID */
+                       label = "HED54XXU11 Hall Effect Sensor";
+               };
+       };
+
        soc {
                i2c@80004000 {
                        stmpe1601: stmpe1601@40 {
                                rohm,flip-y;
                        };
                };
+
+               pinctrl {
+                       prox {
+                               prox_stuib_mode: prox_stuib {
+                                       stuib_cfg {
+                                               ste,pins = "GPIO217_AH12";
+                                               ste,config = <&gpio_in_pu>;
+                                       };
+                               };
+                       };
+                       hall {
+                               hall_stuib_mode: stuib_tvk {
+                                       stuib_cfg {
+                                               ste,pins = "GPIO145_C13";
+                                               ste,config = <&gpio_in_pu>;
+                                       };
+                               };
+                       };
+               };
        };
 };
index 76d3ef13175f4d40ff9fb4ef3cbe0e8a287504ce..c40565320978e78f71c7d798476ba2b9b4a62689 100644 (file)
 #include <dt-bindings/interrupt-controller/irq.h>
 
 / {
+       gpio_keys {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               vdd-supply = <&ab8500_ldo_aux1_reg>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&prox_tvk_mode>, <&hall_tvk_mode>;
+
+               button@139 {
+                       /* Proximity sensor */
+                       gpios = <&gpio6 25 0x4>;
+                       linux,code = <11>; /* SW_FRONT_PROXIMITY */
+                       label = "SFH7741 Proximity Sensor";
+               };
+               button@145 {
+                       /* Hall sensor */
+                       gpios = <&gpio4 17 0x4>;
+                       linux,code = <0>; /* SW_LID */
+                       label = "HED54XXU11 Hall Effect Sensor";
+               };
+       };
+
        soc {
-               /* Add Synaptics touch screen, TC35892 keypad etc here */
+               /* Add Synaptics touch screen, TC35893 keypad etc here */
                i2c@80004000 {
-                       tc3589x@44 {
-                               compatible = "tc3589x";
+                       tc35893@44 {
+                               compatible = "toshiba,tc35893";
                                reg = <0x44>;
                                interrupt-parent = <&gpio6>;
                                interrupts = <26 IRQ_TYPE_EDGE_RISING>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&tc35893_tvk_mode>;
 
                                interrupt-controller;
-                               #interrupt-cells = <2>;
+                               #interrupt-cells = <1>;
 
                                tc3589x_gpio {
-                                       compatible = "tc3589x-gpio";
-                                       interrupts = <0 IRQ_TYPE_EDGE_RISING>;
+                                       compatible = "toshiba,tc3589x-gpio";
+                                       interrupts = <0>;
 
                                        interrupt-controller;
                                        #interrupt-cells = <2>;
                                        gpio-controller;
                                        #gpio-cells = <2>;
                                };
+                               tc3589x_keypad {
+                                       compatible = "toshiba,tc3589x-keypad";
+                                       interrupts = <6>;
+                                       debounce-delay-ms = <4>;
+                                       keypad,num-columns = <8>;
+                                       keypad,num-rows = <8>;
+                                       linux,no-autorepeat;
+                                       linux,wakeup;
+                                       linux,keymap = <0x0301006b
+                                                       0x04010066
+                                                       0x06040072
+                                                       0x040200d7
+                                                       0x0303006a
+                                                       0x0205000e
+                                                       0x0607008b
+                                                       0x0500001c
+                                                       0x0403000b
+                                                       0x03040034
+                                                       0x05020067
+                                                       0x0305006c
+                                                       0x040500e7
+                                                       0x0005009e
+                                                       0x06020073
+                                                       0x01030039
+                                                       0x07060069
+                                                       0x050500d9>;
+                               };
+                       };
+               };
+               pinctrl {
+                       /* Pull up this GPIO pin */
+                       tc35893 {
+                               tc35893_tvk_mode: tc35893_tvk {
+                                       tvk_cfg {
+                                               ste,pins = "GPIO218_AH11";
+                                               ste,config = <&gpio_in_pu>;
+                                       };
+                               };
+                       };
+                       prox {
+                               prox_tvk_mode: prox_tvk {
+                                       tvk_cfg {
+                                               ste,pins = "GPIO217_AH12";
+                                               ste,config = <&gpio_in_pu>;
+                                       };
+                               };
+                       };
+                       hall {
+                               hall_tvk_mode: hall_tvk {
+                                       tvk_cfg {
+                                               ste,pins = "GPIO145_C13";
+                                               ste,config = <&gpio_in_pu>;
+                                       };
+                               };
                        };
                };
        };
index aa3f02060fdd43114570eceedbf1ef54dc49a01f..e28242173d18fae01ace4ddad502306d540a405b 100644 (file)
 
 #include <dt-bindings/interrupt-controller/irq.h>
 #include "ste-dbx5x0.dtsi"
+#include "ste-href-family-pinctrl.dtsi"
 
 / {
        memory {
                reg = <0x00000000 0x20000000>;
        };
 
-       gpio_keys {
-               compatible = "gpio-keys";
-               #address-cells = <1>;
-               #size-cells = <0>;
-
-               button@1 {
-                       linux,code = <11>;
-                       label = "SFH7741 Proximity Sensor";
+       soc {
+               usb_per5@a03e0000 {
+                       pinctrl-names = "default", "sleep";
+                       pinctrl-0 = <&musb_default_mode>;
+                       pinctrl-1 = <&musb_sleep_mode>;
                };
-       };
 
-       soc {
                uart@80120000 {
+                       pinctrl-names = "default", "sleep";
+                       pinctrl-0 = <&uart0_default_mode>;
+                       pinctrl-1 = <&uart0_sleep_mode>;
                        status = "okay";
                };
 
                uart@80121000 {
+                       pinctrl-names = "default", "sleep";
+                       pinctrl-0 = <&uart1_default_mode>;
+                       pinctrl-1 = <&uart1_sleep_mode>;
                        status = "okay";
                };
 
                uart@80007000 {
+                       pinctrl-names = "default", "sleep";
+                       pinctrl-0 = <&uart2_default_mode>;
+                       pinctrl-1 = <&uart2_sleep_mode>;
                        status = "okay";
                };
 
+               i2c@80004000 {
+                       pinctrl-names = "default","sleep";
+                       pinctrl-0 = <&i2c0_default_mode>;
+                       pinctrl-1 = <&i2c0_sleep_mode>;
+               };
+
+               i2c@80122000 {
+                       pinctrl-names = "default","sleep";
+                       pinctrl-0 = <&i2c1_default_mode>;
+                       pinctrl-1 = <&i2c1_sleep_mode>;
+               };
+
                i2c@80128000 {
+                       pinctrl-names = "default","sleep";
+                       pinctrl-0 = <&i2c2_default_mode>;
+                       pinctrl-1 = <&i2c2_sleep_mode>;
                        lp5521@33 {
                                compatible = "national,lp5521";
                                reg = <0x33>;
                        };
                };
 
+               i2c@80110000 {
+                       pinctrl-names = "default","sleep";
+                       pinctrl-0 = <&i2c3_default_mode>;
+                       pinctrl-1 = <&i2c3_sleep_mode>;
+               };
+
                // External Micro SD slot
                sdi0_per1@80126000 {
                        arm,primecell-periphid = <0x10480180>;
                        mmc-cap-mmc-highspeed;
                        vmmc-supply = <&ab8500_ldo_aux3_reg>;
                        vqmmc-supply = <&vmmci>;
+                       pinctrl-names = "default", "sleep";
+                       pinctrl-0 = <&sdi0_default_mode>;
+                       pinctrl-1 = <&sdi0_sleep_mode>;
 
                        cd-gpios  = <&tc3589x_gpio 3 0x4>;
 
                        arm,primecell-periphid = <0x10480180>;
                        max-frequency = <100000000>;
                        bus-width = <4>;
+                       pinctrl-names = "default", "sleep";
+                       pinctrl-0 = <&sdi1_default_mode>;
+                       pinctrl-1 = <&sdi1_sleep_mode>;
 
                        status = "okay";
                };
                        max-frequency = <100000000>;
                        bus-width = <8>;
                        mmc-cap-mmc-highspeed;
+                       pinctrl-names = "default", "sleep";
+                       pinctrl-0 = <&sdi2_default_mode>;
+                       pinctrl-1 = <&sdi2_sleep_mode>;
 
                        status = "okay";
                };
                        bus-width = <8>;
                        mmc-cap-mmc-highspeed;
                        vmmc-supply = <&ab8500_ldo_aux2_reg>;
+                       pinctrl-names = "default", "sleep";
+                       pinctrl-0 = <&sdi4_default_mode>;
+                       pinctrl-1 = <&sdi4_sleep_mode>;
 
                        status = "okay";
                };
                        stericsson,audio-codec = <&codec>;
                };
 
+               msp0: msp@80123000 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&msp0_default_mode>;
+                       status = "okay";
+               };
+
                msp1: msp@80124000 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&msp1_default_mode>;
+                       status = "okay";
+               };
+
+               msp2: msp@80117000 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&msp2_default_mode>;
                        status = "okay";
                };
 
                                };
                        };
                };
+
+               mcde@a0350000 {
+                       pinctrl-names = "default", "sleep";
+                       pinctrl-0 = <&lcd_default_mode>;
+                       pinctrl-1 = <&lcd_sleep_mode>;
+               };
        };
 };
index b2cd7bc2752f2a6ea67e0849593410cc61dd176a..b0f5def8e2a8fcb843805368ad94352f9e3d2854 100644 (file)
                                reg = <0x33>;
                        };
 
-                       tc3589x@42 {
-                               compatible = "tc3589x";
+                       tc35892@42 {
+                               compatible = "toshiba,tc35892";
                                reg = <0x42>;
                                interrupt-parent = <&gpio6>;
                                interrupts = <25 IRQ_TYPE_EDGE_RISING>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&tc35892_hrefprev60_mode>;
 
                                interrupt-controller;
-                               #interrupt-cells = <2>;
+                               #interrupt-cells = <1>;
 
                                tc3589x_gpio: tc3589x_gpio {
                                        compatible = "tc3589x-gpio";
-                                       interrupts = <0 IRQ_TYPE_EDGE_RISING>;
+                                       interrupts = <0>;
 
                                        interrupt-controller;
                                        #interrupt-cells = <2>;
                        };
                };
 
+               ssp@80002000 {
+                       /*
+                        * On the first generation boards, this SSP/SPI port was connected
+                        * to the AB8500.
+                        */
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&ssp0_hrefprev60_mode>;
+               };
+
                vmmci: regulator-gpio {
                        gpios = <&tc3589x_gpio 18 0x4>;
                        enable-gpio = <&tc3589x_gpio 17 0x4>;
 
                        status = "okay";
                };
+
+               pinctrl {
+                       /* Set this up using hogs */
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&ipgpio_hrefprev60_mode>;
+
+                       ssp0 {
+                               ssp0_hrefprev60_mode: ssp0_hrefprev60_default {
+                                       hrefprev60_mux {
+                                               ste,function = "ssp0";
+                                               ste,pins = "ssp0_a_1";
+                                       };
+                                       hrefprev60_cfg1 {
+                                               ste,pins = "GPIO145_C13"; /* RXD */
+                                               ste,config = <&in_pd>;
+                                       };
+
+                               };
+                       };
+                       sdi0 {
+                               /* This additional pin needed on early MOP500 and HREFs previous to v60 */
+                               sdi0_default_mode: sdi0_default {
+                                       hrefprev60_mux {
+                                               ste,function = "mc0";
+                                               ste,pins = "mc0dat31dir_a_1";
+                                       };
+                                       hrefprev60_cfg1 {
+                                               ste,pins = "GPIO21_AB3"; /* DAT31DIR */
+                                               ste,config = <&out_hi>;
+                                       };
+
+                               };
+                       };
+                       tc35892 {
+                               tc35892_hrefprev60_mode: tc35892_hrefprev60 {
+                                       hrefprev60_cfg {
+                                               ste,pins = "GPIO217_AH12";
+                                               ste,config = <&gpio_in_pu>;
+                                       };
+                               };
+                       };
+                       ipgpio {
+                                ipgpio_hrefprev60_mode: ipgpio_hrefprev60 {
+                                       hrefprev60_mux {
+                                               ste,function = "ipgpio";
+                                               ste,pins = "ipgpio0_c_1", "ipgpio1_c_1";
+                                       };
+                                       hrefprev60_cfg1 {
+                                               ste,pins = "GPIO6_AF6", "GPIO7_AG5";
+                                               ste,config = <&in_pu>;
+                                       };
+                                };
+                       };
+               };
        };
 };
index aed511b47a9e6fe015050920bb8ed3a0e19eb918..941bf9ad6f013971ae6843ec283429d18f499149 100644 (file)
        model = "ST-Ericsson HREF (v60+) platform with Device Tree";
        compatible = "st-ericsson,hrefv60+", "st-ericsson,u8500";
 
-       gpio_keys {
-               button@1 {
-                       gpios = <&gpio5 25 0x4>;
-               };
-       };
-
        soc {
                // External Micro SD slot
                sdi0_per1@80126000 {
 
                        status = "okay";
                };
+
+               pinctrl {
+                       /*
+                        * Set this up using hogs, as time goes by and as seems fit, these
+                        * can be moved over to being controlled by respective device.
+                        */
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&ipgpio_hrefv60_mode>,
+                                 <&accel_hrefv60_mode>,
+                                 <&magneto_hrefv60_mode>,
+                                 <&etm_hrefv60_mode>,
+                                 <&nahj_hrefv60_mode>,
+                                 <&nfc_hrefv60_mode>,
+                                 <&force_hrefv60_mode>,
+                                 <&dipro_hrefv60_mode>,
+                                 <&vaudio_hf_hrefv60_mode>,
+                                 <&gbf_hrefv60_mode>,
+                                 <&hdtv_hrefv60_mode>,
+                                 <&touch_hrefv60_mode>;
+
+                       sdi0 {
+                               /* SD card detect GPIO pin, extend default state */
+                               sdi0_default_mode: sdi0_default {
+                                       default_hrefv60_cfg1 {
+                                               ste,pins = "GPIO95_E8";
+                                               ste,config = <&gpio_in_pu>;
+                                       };
+                               };
+                       };
+                       ipgpio {
+                               /*
+                                * XENON Flashgun on image processor GPIO (controlled from image
+                                * processor firmware), mux in these image processor GPIO lines 0
+                                * (XENON_FLASH_ID), 1 (XENON_READY) and there is an assistant
+                                * LED on IP GPIO 4 (XENON_EN2) on altfunction C, that need bias
+                                * from GPIO21 so pull up 0, 1 and drive 4 and GPIO21 low as output.
+                                */
+                               ipgpio_hrefv60_mode: ipgpio_hrefv60 {
+                                       hrefv60_mux {
+                                               ste,function = "ipgpio";
+                                               ste,pins = "ipgpio0_c_1", "ipgpio1_c_1", "ipgpio4_c_1";
+                                       };
+                                       hrefv60_cfg1 {
+                                               ste,pins = "GPIO6_AF6", "GPIO7_AG5";
+                                               ste,config = <&in_pu>;
+                                       };
+                                       hrefv60_cfg2 {
+                                               ste,pins = "GPIO21_AB3";
+                                               ste,config = <&gpio_out_lo>;
+                                       };
+                                       hrefv60_cfg3 {
+                                               ste,pins = "GPIO64_F3";
+                                               ste,config = <&out_lo>;
+                                       };
+                               };
+                       };
+                       accelerometer {
+                               accel_hrefv60_mode: accel_hrefv60 {
+                                       /* Accelerometer interrupt lines 1 & 2 */
+                                       hrefv60_cfg1 {
+                                               ste,pins = "GPIO82_C1", "GPIO83_D3";
+                                               ste,config = <&gpio_in_pu>;
+                                       };
+                               };
+                       };
+                       magnetometer {
+                               magneto_hrefv60_mode: magneto_hrefv60 {
+                                       /* Magnetometer uses GPIO 31 and 32, pull these up/down respectively */
+                                       hrefv60_cfg1 {
+                                               ste,pins = "GPIO31_V3";
+                                               ste,config = <&gpio_in_pu>;
+                                       };
+                                       hrefv60_cfg2 {
+                                               ste,pins = "GPIO32_V2";
+                                               ste,config = <&gpio_in_pd>;
+                                       };
+                               };
+                       };
+                       etm {
+                               /*
+                                * Drive D19-D23 for the ETM PTM trace interface low,
+                                * (presumably pins are unconnected therefore grounded here,
+                                * the "other alt C1" setting enables these pins)
+                                */
+                               etm_hrefv60_mode: etm_hrefv60 {
+                                       hrefv60_cfg1 {
+                                               ste,pins =
+                                               "GPIO70_G5",
+                                               "GPIO71_G4",
+                                               "GPIO72_H4",
+                                               "GPIO73_H3",
+                                               "GPIO74_J3";
+                                               ste,config = <&gpio_out_lo>;
+                                       };
+                                };
+                       };
+                       nahj {
+                               nahj_hrefv60_mode: nahj_hrefv60 {
+                                       /* NAHJ CTRL on GPIO76 to low, CTRL_INV on GPIO216 to high */
+                                       hrefv60_cfg1 {
+                                               ste,pins = "GPIO76_J2";
+                                               ste,config = <&gpio_out_lo>;
+                                       };
+                                       hrefv60_cfg2 {
+                                               ste,pins = "GPIO216_AG12";
+                                               ste,config = <&gpio_out_hi>;
+                                       };
+                                };
+                       };
+                       nfc {
+                               nfc_hrefv60_mode: nfc_hrefv60 {
+                                       /* NFC ENA and RESET to low, pulldown IRQ line */
+                                       hrefv60_cfg1 {
+                                               ste,pins =
+                                               "GPIO77_H1", /* NFC_ENA */
+                                               "GPIO142_C11"; /* NFC_RESET */
+                                               ste,config = <&gpio_out_lo>;
+                                       };
+                                       hrefv60_cfg2 {
+                                               ste,pins = "GPIO144_B13"; /* NFC_IRQ */
+                                               ste,config = <&gpio_in_pd>;
+                                       };
+                                };
+                       };
+                       force {
+                               force_hrefv60_mode: force_hrefv60 {
+                                       hrefv60_cfg1 {
+                                               ste,pins = "GPIO91_B6"; /* FORCE_SENSING_INT */
+                                               ste,config = <&gpio_in_pu>;
+                                       };
+                                       hrefv60_cfg2 {
+                                               ste,pins =
+                                               "GPIO92_D6", /* FORCE_SENSING_RST */
+                                               "GPIO97_D9"; /* FORCE_SENSING_WU */
+                                               ste,config = <&gpio_out_lo>;
+                                       };
+                                };
+                       };
+                       dipro {
+                               dipro_hrefv60_mode: dipro_hrefv60 {
+                                       hrefv60_cfg1 {
+                                               ste,pins = "GPIO139_C9"; /* DIPRO_INT */
+                                               ste,config = <&gpio_in_pu>;
+                                       };
+                                };
+                       };
+                       vaudio_hf {
+                               vaudio_hf_hrefv60_mode: vaudio_hf_hrefv60 {
+                                       /* Audio Amplifier HF enable GPIO */
+                                       hrefv60_cfg1 {
+                                               ste,pins = "GPIO149_B14"; /* VAUDIO_HF_EN, enable MAX8968 */
+                                               ste,config = <&gpio_out_hi>;
+                                       };
+                                };
+                       };
+                       gbf {
+                               gbf_hrefv60_mode: gbf_hrefv60 {
+                                       /*
+                                        * GBF (GPS, Bluetooth, FM-radio) interface,
+                                        * pull low to reset state
+                                        */
+                                       hrefv60_cfg1 {
+                                               ste,pins = "GPIO171_D23"; /* GBF_ENA_RESET */
+                                               ste,config = <&gpio_out_lo>;
+                                       };
+                                };
+                       };
+                       hdtv {
+                               hdtv_hrefv60_mode: hdtv_hrefv60 {
+                                       /* MSP : HDTV INTERFACE GPIO line */
+                                       hrefv60_cfg1 {
+                                               ste,pins = "GPIO192_AJ27";
+                                               ste,config = <&gpio_in_pd>;
+                                       };
+                                };
+                       };
+                       touch {
+                               touch_hrefv60_mode: touch_hrefv60 {
+                                       /*
+                                        * Touch screen uses GPIO 143 for RST1, GPIO 146 for RST2 and
+                                        * GPIO 67 for interrupts. Pull-up the IRQ line and drive both
+                                        * reset signals low.
+                                        */
+                                       hrefv60_cfg1 {
+                                               ste,pins = "GPIO143_D12", "GPIO146_D13";
+                                               ste,config = <&gpio_out_lo>;
+                                       };
+                                       hrefv60_cfg2 {
+                                               ste,pins = "GPIO67_G2";
+                                               ste,config = <&gpio_in_pu>;
+                                       };
+                               };
+                       };
+                       mcde {
+                               lcd_hrefv60_mode: lcd_hrefv60 {
+                                       /*
+                                        * Display Interface 1 uses GPIO 65 for RST (reset).
+                                        * Display Interface 2 uses GPIO 66 for RST (reset).
+                                        * Drive DISP1 reset high (not reset), driver DISP2 reset low (reset)
+                                        */
+                                       hrefv60_cfg1 {
+                                               ste,pins ="GPIO65_F1";
+                                               ste,config = <&gpio_out_hi>;
+                                       };
+                                       hrefv60_cfg2 {
+                                               ste,pins ="GPIO66_G3";
+                                               ste,config = <&gpio_out_lo>;
+                                       };
+                               };
+                       };
+               };
        };
 };
index efddee9403c424b1bb2c0e21d027fae10fc13808..e6f22b266420d0be0ead75fe81e500ac427b8d11 100644 (file)
                ste,output = <OUTPUT_LOW>;
        };
 
+       gpio_in_pu: gpio_input_pull_up {
+               ste,gpio = <GPIOMODE_ENABLED>;
+               ste,input = <INPUT_PULLUP>;
+       };
+
+       gpio_in_pd: gpio_input_pull_down {
+               ste,gpio = <GPIOMODE_ENABLED>;
+               ste,input = <INPUT_PULLDOWN>;
+       };
+
        gpio_out_lo: gpio_output_low {
                ste,gpio = <GPIOMODE_ENABLED>;
                ste,output = <OUTPUT_LOW>;
        };
 
+       gpio_out_hi: gpio_output_high {
+               ste,gpio = <GPIOMODE_ENABLED>;
+               ste,output = <OUTPUT_HIGH>;
+       };
+
+       slpm_pdis: slpm_pdis {
+               ste,sleep = <SLPM_ENABLED>;
+               ste,sleep-wakeup = <SLPM_WAKEUP_DISABLE>;
+               ste,sleep-pull-disable = <SLPM_PDIS_DISABLED>;
+       };
+
+       slpm_wkup_pdis: slpm_wkup_pdis {
+               ste,sleep = <SLPM_ENABLED>;
+               ste,sleep-wakeup = <SLPM_WAKEUP_ENABLE>;
+               ste,sleep-pull-disable = <SLPM_PDIS_DISABLED>;
+       };
+
+       slpm_wkup_pdis_en: slpm_wkup_pdis_en {
+               ste,sleep = <SLPM_ENABLED>;
+               ste,sleep-wakeup = <SLPM_WAKEUP_ENABLE>;
+               ste,sleep-pull-disable = <SLPM_PDIS_ENABLED>;
+       };
+
        slpm_in_pu: slpm_in_pu {
                ste,sleep = <SLPM_ENABLED>;
                ste,sleep-input = <SLPM_INPUT_PULLUP>;
                ste,sleep-wakeup = <SLPM_WAKEUP_ENABLE>;
        };
 
+       slpm_in_pdis: slpm_in_pdis {
+               ste,sleep = <SLPM_ENABLED>;
+               ste,sleep-input = <SLPM_DIR_INPUT>;
+               ste,sleep-wakeup = <SLPM_WAKEUP_DISABLE>;
+               ste,sleep-pull-disable = <SLPM_PDIS_DISABLED>;
+       };
+
        slpm_in_wkup_pdis: slpm_in_wkup_pdis {
                ste,sleep = <SLPM_ENABLED>;
                ste,sleep-input = <SLPM_DIR_INPUT>;
                ste,sleep-pull-disable = <SLPM_PDIS_DISABLED>;
        };
 
+       slpm_in_wkup_pdis_en: slpm_in_wkup_pdis_en {
+               ste,sleep = <SLPM_ENABLED>;
+               ste,sleep-input = <SLPM_DIR_INPUT>;
+               ste,sleep-wakeup = <SLPM_WAKEUP_ENABLE>;
+               ste,sleep-pull-disable = <SLPM_PDIS_ENABLED>;
+       };
+
+       slpm_in_pu_wkup_pdis_en: slpm_in_wkup_pdis_en {
+               ste,sleep = <SLPM_ENABLED>;
+               ste,sleep-input = <SLPM_INPUT_PULLUP>;
+               ste,sleep-wakeup = <SLPM_WAKEUP_ENABLE>;
+               ste,sleep-pull-disable = <SLPM_PDIS_ENABLED>;
+       };
+
        slpm_out_lo: slpm_out_lo {
                ste,sleep = <SLPM_ENABLED>;
                ste,sleep-output = <SLPM_OUTPUT_LOW>;
                ste,sleep-pull-disable = <SLPM_PDIS_DISABLED>;
        };
 
+       slpm_out_lo_pdis: slpm_out_lo_pdis {
+               ste,sleep = <SLPM_ENABLED>;
+               ste,sleep-output = <SLPM_OUTPUT_LOW>;
+               ste,sleep-wakeup = <SLPM_WAKEUP_DISABLE>;
+               ste,sleep-pull-disable = <SLPM_PDIS_DISABLED>;
+       };
+
+       slpm_out_lo_wkup_pdis: slpm_out_lo_wkup_pdis {
+               ste,sleep = <SLPM_ENABLED>;
+               ste,sleep-output = <SLPM_OUTPUT_LOW>;
+               ste,sleep-wakeup = <SLPM_WAKEUP_ENABLE>;
+               ste,sleep-pull-disable = <SLPM_PDIS_DISABLED>;
+       };
+
        slpm_out_wkup_pdis: slpm_out_wkup_pdis {
                ste,sleep = <SLPM_ENABLED>;
                ste,sleep-output = <SLPM_DIR_OUTPUT>;
                ste,sleep-pull-disable = <SLPM_PDIS_DISABLED>;
        };
 
+       in_wkup_pdis_en: in_wkup_pdis_en {
+               ste,sleep-input = <SLPM_DIR_INPUT>;
+               ste,sleep-wakeup = <SLPM_WAKEUP_ENABLE>;
+               ste,sleep-pull-disable = <SLPM_PDIS_ENABLED>;
+       };
+
+       out_lo_wkup_pdis: out_lo_wkup_pdis {
+               ste,sleep-output = <SLPM_OUTPUT_LOW>;
+               ste,sleep-wakeup = <SLPM_WAKEUP_ENABLE>;
+               ste,sleep-pull-disable = <SLPM_PDIS_DISABLED>;
+       };
+
        out_hi_wkup_pdis: out_hi_wkup_pdis {
                ste,sleep-output = <SLPM_OUTPUT_HIGH>;
                ste,sleep-wakeup = <SLPM_WAKEUP_ENABLE>;
index f0b39f835914beda02952a3cd9eb8860e38599ba..9070c3701c89172f28fb71740473c0345fa48e70 100644 (file)
@@ -11,6 +11,7 @@
 
 /dts-v1/;
 #include "ste-dbx5x0.dtsi"
+#include "ste-href-family-pinctrl.dtsi"
 
 / {
        model = "Calao Systems Snowball platform with device tree";
@@ -75,6 +76,8 @@
 
        leds {
                compatible = "gpio-leds";
+               pinctrl-names = "default";
+               pinctrl-0 = <&gpioled_snowball_mode>;
                used-led {
                        label = "user_led";
                        gpios = <&gpio4 14 0x4>;
        };
 
        soc {
+               usb_per5@a03e0000 {
+                       pinctrl-names = "default", "sleep";
+                       pinctrl-0 = <&musb_default_mode>;
+                       pinctrl-1 = <&musb_sleep_mode>;
+               };
 
                sound {
                        compatible = "stericsson,snd-soc-mop500";
                        stericsson,audio-codec = <&codec>;
                };
 
+               msp0: msp@80123000 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&msp0_default_mode>;
+                       status = "okay";
+               };
+
                msp1: msp@80124000 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&msp1_default_mode>;
+                       status = "okay";
+               };
+
+               msp2: msp@80117000 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&msp2_default_mode>;
                        status = "okay";
                };
 
                                interrupt-parent = <&gpio4>;
                                vdd33a-supply = <&en_3v3_reg>;
                                vddvario-supply = <&db8500_vape_reg>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&eth_snowball_mode>;
 
                                reg-shift = <1>;
                                reg-io-width = <2>;
                        mmc-cap-mmc-highspeed;
                        vmmc-supply = <&ab8500_ldo_aux3_reg>;
                        vqmmc-supply = <&vmmci>;
+                       pinctrl-names = "default", "sleep";
+                       pinctrl-0 = <&sdi0_default_mode>;
+                       pinctrl-1 = <&sdi0_sleep_mode>;
 
                        cd-gpios  = <&gpio6 26 0x4>; // 218
                        cd-inverted;
                        status = "okay";
                };
 
+               // WLAN SDIO channel
+               sdi1_per2@80118000 {
+                       arm,primecell-periphid = <0x10480180>;
+                       max-frequency = <100000000>;
+                       bus-width = <4>;
+                       pinctrl-names = "default", "sleep";
+                       pinctrl-0 = <&sdi1_default_mode>;
+                       pinctrl-1 = <&sdi1_sleep_mode>;
+
+                       status = "okay";
+               };
+
+               // Unused PoP eMMC - register and put it to sleep by default */
+               sdi2_per3@80005000 {
+                       arm,primecell-periphid = <0x10480180>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&sdi2_sleep_mode>;
+
+                       status = "okay";
+               };
+
                // On-board eMMC
                sdi4_per2@80114000 {
                        arm,primecell-periphid = <0x10480180>;
                        bus-width = <8>;
                        mmc-cap-mmc-highspeed;
                        vmmc-supply = <&ab8500_ldo_aux2_reg>;
+                       pinctrl-names = "default", "sleep";
+                       pinctrl-0 = <&sdi4_default_mode>;
+                       pinctrl-1 = <&sdi4_sleep_mode>;
 
                        status = "okay";
                };
 
                uart@80120000 {
+                       pinctrl-names = "default", "sleep";
+                       pinctrl-0 = <&uart0_default_mode>;
+                       pinctrl-1 = <&uart0_sleep_mode>;
                        status = "okay";
                };
 
                uart@80121000 {
+                       pinctrl-names = "default", "sleep";
+                       pinctrl-0 = <&uart1_default_mode>;
+                       pinctrl-1 = <&uart1_sleep_mode>;
                        status = "okay";
                };
 
                uart@80007000 {
+                       pinctrl-names = "default", "sleep";
+                       pinctrl-0 = <&uart2_default_mode>;
+                       pinctrl-1 = <&uart2_sleep_mode>;
                        status = "okay";
                };
 
+               i2c@80004000 {
+                       pinctrl-names = "default","sleep";
+                       pinctrl-0 = <&i2c0_default_mode>;
+                       pinctrl-1 = <&i2c0_sleep_mode>;
+               };
+
+               i2c@80122000 {
+                       pinctrl-names = "default","sleep";
+                       pinctrl-0 = <&i2c1_default_mode>;
+                       pinctrl-1 = <&i2c1_sleep_mode>;
+               };
+
+               i2c@80128000 {
+                       pinctrl-names = "default","sleep";
+                       pinctrl-0 = <&i2c2_default_mode>;
+                       pinctrl-1 = <&i2c2_sleep_mode>;
+               };
+
+               i2c@80110000 {
+                       pinctrl-names = "default","sleep";
+                       pinctrl-0 = <&i2c3_default_mode>;
+                       pinctrl-1 = <&i2c3_sleep_mode>;
+               };
+
+               ssp@80002000 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&ssp0_snowball_mode>;
+               };
+
                cpufreq-cooling {
                        status = "okay";
                };
                                };
                        };
                };
+
+               pinctrl {
+                       /*
+                        * Set this up using hogs, as time goes by and as seems fit, these
+                        * can be moved over to being controlled by respective device.
+                        */
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&accel_snowball_mode>,
+                                 <&magneto_snowball_mode>,
+                                 <&gbf_snowball_mode>,
+                                 <&wlan_snowball_mode>;
+
+                       ethernet {
+                               /*
+                                * Mux in "SM" which is used for the
+                                * SMSC911x Ethernet adapter
+                                */
+                               eth_snowball_mode: eth_snowball {
+                                       snowball_mux {
+                                               ste,function = "sm";
+                                               ste,pins = "sm_b_1";
+                                       };
+                                       /* LAN IRQ pin */
+                                       snowball_cfg1 {
+                                               ste,pins = "GPIO140_B11";
+                                               ste,config = <&in_nopull>;
+                                       };
+                                       /* LAN reset pin */
+                                       snowball_cfg2 {
+                                               ste,pins = "GPIO141_C12";
+                                               ste,config = <&gpio_out_hi>;
+                                       };
+
+                               };
+                       };
+                       sdi0 {
+                               sdi0_default_mode: sdi0_default {
+                                       snowball_mux {
+                                               ste,function = "mc0";
+                                               ste,pins = "mc0dat31dir_a_1";
+                                       };
+                                       snowball_cfg1 {
+                                               ste,pins = "GPIO21_AB3"; /* DAT31DIR */
+                                               ste,config = <&out_hi>;
+                                       };
+
+                               };
+                       };
+                       ssp0 {
+                               ssp0_snowball_mode: ssp0_snowball_default {
+                                       snowball_mux {
+                                               ste,function = "ssp0";
+                                               ste,pins = "ssp0_a_1";
+                                       };
+                                       snowball_cfg1 {
+                                               ste,pins = "GPIO144_B13"; /* FRM */
+                                               ste,config = <&gpio_out_hi>;
+                                       };
+                                       snowball_cfg2 {
+                                               ste,pins = "GPIO145_C13"; /* RXD */
+                                               ste,config = <&in_pd>;
+                                       };
+                                       snowball_cfg3 {
+                                               ste,pins =
+                                               "GPIO146_D13", /* TXD */
+                                               "GPIO143_D12"; /* CLK */
+                                               ste,config = <&out_lo>;
+                                       };
+
+                               };
+                       };
+                       gpio_led {
+                               gpioled_snowball_mode: gpioled_default {
+                                       snowball_cfg1 {
+                                               ste,pins = "GPIO142_C11";
+                                               ste,config = <&gpio_out_hi>;
+                                       };
+
+                               };
+                       };
+                       accelerometer {
+                               accel_snowball_mode: accel_snowball {
+                                       /* Accelerometer lines */
+                                       snowball_cfg1 {
+                                               ste,pins =
+                                               "GPIO163_C20", /* ACCEL_IRQ1 */
+                                               "GPIO164_B21"; /* ACCEL_IRQ2 */
+                                               ste,config = <&gpio_in_pu>;
+                                       };
+                               };
+                       };
+                       magnetometer {
+                               magneto_snowball_mode: magneto_snowball {
+                                       snowball_cfg1 {
+                                               ste,pins = "GPIO165_C21"; /* MAG_DRDY */
+                                               ste,config = <&gpio_in_pu>;
+                                       };
+                               };
+                       };
+                       gbf {
+                               gbf_snowball_mode: gbf_snowball {
+                                       /*
+                                        * GBF (GPS, Bluetooth, FM-radio) interface,
+                                        * pull low to reset state
+                                        */
+                                       snowball_cfg1 {
+                                               ste,pins = "GPIO171_D23"; /* GBF_ENA_RESET */
+                                               ste,config = <&gpio_out_lo>;
+                                       };
+                                };
+                       };
+                       wlan {
+                               wlan_snowball_mode: wlan_snowball {
+                                       /*
+                                        * Activate this mode with the WLAN chip.
+                                        * These are plain GPIO pins used by WLAN
+                                        */
+                                       snowball_cfg1 {
+                                               ste,pins =
+                                               "GPIO161_D21", /* WLAN_PMU_EN */
+                                               "GPIO215_AH13"; /* WLAN_ENA */
+                                               ste,config = <&gpio_out_lo>;
+                                       };
+                                       snowball_cfg2 {
+                                               ste,pins = "GPIO216_AG12"; /* WLAN_IRQ */
+                                               ste,config = <&gpio_in_pu>;
+                                       };
+                               };
+                       };
+               };
+
+               mcde@a0350000 {
+                       pinctrl-names = "default", "sleep";
+                       pinctrl-0 = <&lcd_default_mode>;
+                       pinctrl-1 = <&lcd_sleep_mode>;
+               };
        };
 };
index 1d322b24d1e441bebabfd55d93ec9738b067f1ee..e56449d41481fc3badf5fdd83ce3930c77f628f8 100644 (file)
                                        };
                                };
                        };
+
+                       sbc_i2c0 {
+                               pinctrl_sbc_i2c0_default: sbc_i2c0-default {
+                                       st,pins {
+                                               sda = <&PIO4 6 ALT1 BIDIR>;
+                                               scl = <&PIO4 5 ALT1 BIDIR>;
+                                       };
+                               };
+                       };
+
+                       sbc_i2c1 {
+                               pinctrl_sbc_i2c1_default: sbc_i2c1-default {
+                                       st,pins {
+                                               sda = <&PIO3 2 ALT2 BIDIR>;
+                                               scl = <&PIO3 1 ALT2 BIDIR>;
+                                       };
+                               };
+                       };
                };
 
                pin-controller-front {
                                reg             = <0x7000 0x100>;
                                st,bank-name    = "PIO12";
                        };
+
+                       i2c0 {
+                               pinctrl_i2c0_default: i2c0-default {
+                                       st,pins {
+                                               sda = <&PIO9 3 ALT1 BIDIR>;
+                                               scl = <&PIO9 2 ALT1 BIDIR>;
+                                       };
+                               };
+                       };
+
+                       i2c1 {
+                               pinctrl_i2c1_default: i2c1-default {
+                                       st,pins {
+                                               sda = <&PIO12 1 ALT1 BIDIR>;
+                                               scl = <&PIO12 0 ALT1 BIDIR>;
+                                       };
+                               };
+                       };
                };
 
                pin-controller-rear {
index 74ab8ded4b49b0faf3ecdf4729b22d16fd8b27b8..d9c7dd1d95a4545a083874f8d0a4193f96063198 100644 (file)
@@ -9,6 +9,7 @@
 #include "stih41x.dtsi"
 #include "stih415-clock.dtsi"
 #include "stih415-pinctrl.dtsi"
+#include <dt-bindings/interrupt-controller/arm-gic.h>
 / {
 
        L2: cache-controller {
                        pinctrl-names   = "default";
                        pinctrl-0       = <&pinctrl_sbc_serial1>;
                };
+
+               i2c@fed40000 {
+                       compatible      = "st,comms-ssc4-i2c";
+                       reg             = <0xfed40000 0x110>;
+                       interrupts      = <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks          = <&CLKS_ICN_REG_0>;
+                       clock-names     = "ssc";
+                       clock-frequency = <400000>;
+                       pinctrl-names   = "default";
+                       pinctrl-0       = <&pinctrl_i2c0_default>;
+
+                       status          = "disabled";
+               };
+
+               i2c@fed41000 {
+                       compatible      = "st,comms-ssc4-i2c";
+                       reg             = <0xfed41000 0x110>;
+                       interrupts      = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks          = <&CLKS_ICN_REG_0>;
+                       clock-names     = "ssc";
+                       clock-frequency = <400000>;
+                       pinctrl-names   = "default";
+                       pinctrl-0       = <&pinctrl_i2c1_default>;
+
+                       status          = "disabled";
+               };
+
+               i2c@fe540000 {
+                       compatible      = "st,comms-ssc4-i2c";
+                       reg             = <0xfe540000 0x110>;
+                       interrupts      = <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks          = <&CLK_SYSIN>;
+                       clock-names     = "ssc";
+                       clock-frequency = <400000>;
+                       pinctrl-names   = "default";
+                       pinctrl-0       = <&pinctrl_sbc_i2c0_default>;
+
+                       status          = "disabled";
+               };
+
+               i2c@fe541000 {
+                       compatible      = "st,comms-ssc4-i2c";
+                       reg             = <0xfe541000 0x110>;
+                       interrupts      = <GIC_SPI 207 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks          = <&CLK_SYSIN>;
+                       clock-names     = "ssc";
+                       clock-frequency = <400000>;
+                       pinctrl-names   = "default";
+                       pinctrl-0       = <&pinctrl_sbc_i2c1_default>;
+
+                       status          = "disabled";
+               };
        };
 };
index 0f246c979262d3c39676576fdde4c2797cb0d118..b29ff4ba542c51300d566f9649a78ed614e0f3b0 100644 (file)
                                        };
                                };
                        };
+
+                       sbc_i2c0 {
+                               pinctrl_sbc_i2c0_default: sbc_i2c0-default {
+                                       st,pins {
+                                               sda = <&PIO4 6 ALT1 BIDIR>;
+                                               scl = <&PIO4 5 ALT1 BIDIR>;
+                                       };
+                               };
+                       };
+
+                       sbc_i2c1 {
+                               pinctrl_sbc_i2c1_default: sbc_i2c1-default {
+                                       st,pins {
+                                               sda = <&PIO3 2 ALT2 BIDIR>;
+                                               scl = <&PIO3 1 ALT2 BIDIR>;
+                                       };
+                               };
+                       };
                };
 
                pin-controller-front {
                                };
                        };
 
+                       i2c0 {
+                               pinctrl_i2c0_default: i2c0-default {
+                                       st,pins {
+                                               sda = <&PIO9 3 ALT1 BIDIR>;
+                                               scl = <&PIO9 2 ALT1 BIDIR>;
+                                       };
+                               };
+                       };
+
+                       i2c1 {
+                               pinctrl_i2c1_default: i2c1-default {
+                                       st,pins {
+                                               sda = <&PIO12 1 ALT1 BIDIR>;
+                                               scl = <&PIO12 0 ALT1 BIDIR>;
+                                       };
+                               };
+                       };
                };
 
                pin-controller-rear {
index 1a0326ea7d070ad762d6f83719aa0fcc29a98dd2..b7ab47b95816de67897c567fcbab4ffb61e90219 100644 (file)
@@ -9,6 +9,7 @@
 #include "stih41x.dtsi"
 #include "stih416-clock.dtsi"
 #include "stih416-pinctrl.dtsi"
+#include <dt-bindings/interrupt-controller/arm-gic.h>
 / {
        L2: cache-controller {
                compatible = "arm,pl310-cache";
                        pinctrl-0       = <&pinctrl_sbc_serial1>;
                        clocks          = <&CLK_SYSIN>;
                };
+
+               i2c@fed40000 {
+                       compatible      = "st,comms-ssc4-i2c";
+                       reg             = <0xfed40000 0x110>;
+                       interrupts      = <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks          = <&CLK_S_ICN_REG_0>;
+                       clock-names     = "ssc";
+                       clock-frequency = <400000>;
+                       pinctrl-names   = "default";
+                       pinctrl-0       = <&pinctrl_i2c0_default>;
+
+                       status          = "disabled";
+               };
+
+               i2c@fed41000 {
+                       compatible      = "st,comms-ssc4-i2c";
+                       reg             = <0xfed41000 0x110>;
+                       interrupts      = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks          = <&CLK_S_ICN_REG_0>;
+                       clock-names     = "ssc";
+                       clock-frequency = <400000>;
+                       pinctrl-names   = "default";
+                       pinctrl-0       = <&pinctrl_i2c1_default>;
+
+                       status          = "disabled";
+               };
+
+               i2c@fe540000 {
+                       compatible      = "st,comms-ssc4-i2c";
+                       reg             = <0xfe540000 0x110>;
+                       interrupts      = <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks          = <&CLK_SYSIN>;
+                       clock-names     = "ssc";
+                       clock-frequency = <400000>;
+                       pinctrl-names   = "default";
+                       pinctrl-0       = <&pinctrl_sbc_i2c0_default>;
+
+                       status          = "disabled";
+               };
+
+               i2c@fe541000 {
+                       compatible      = "st,comms-ssc4-i2c";
+                       reg             = <0xfe541000 0x110>;
+                       interrupts      = <GIC_SPI 207 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks          = <&CLK_SYSIN>;
+                       clock-names     = "ssc";
+                       clock-frequency = <400000>;
+                       pinctrl-names   = "default";
+                       pinctrl-0       = <&pinctrl_sbc_i2c1_default>;
+
+                       status          = "disabled";
+               };
        };
 };
index 8e694d2b8f5b9910879404a8e6e64b00c81c11b8..1e6aa92772f55588d5b8c32b87490f781dc4dfa6 100644 (file)
                        };
                };
 
+               /* HDMI Tx I2C */
+               i2c@fed41000 {
+                       /* HDMI V1.3a supports Standard mode only */
+                       clock-frequency = <100000>;
+                       i2c-min-scl-pulse-width-us = <0>;
+                       i2c-min-sda-pulse-width-us = <5>;
+
+                       status = "okay";
+               };
        };
 };
index 133e18143b1ba0d2c278d98c45d247a963d08491..0ef0a69df8ea36909f38e40d6552a8be27fb5d6c 100644 (file)
                                default-state = "off";
                        };
                };
+
+               i2c@fed40000 {
+                       status = "okay";
+               };
+
+               /* HDMI Tx I2C */
+               i2c@fed41000 {
+                       /* HDMI V1.3a supports Standard mode only */
+                       clock-frequency = <100000>;
+                       i2c-min-scl-pulse-width-us = <0>;
+                       i2c-min-sda-pulse-width-us = <5>;
+
+                       status = "okay";
+               };
+
+               i2c@fe540000 {
+                       status = "okay";
+               };
+
+               i2c@fe541000 {
+                       status = "okay";
+               };
        };
 };
index d5c9bca01232fe40516b2dcd67a2561ebbfa7d50..cbe89ff10686b15e008cb4bfc42ac385038b6a4a 100644 (file)
                                        reg = <3>;
                                        regulator-compatible = "sm2";
                                        regulator-name = "vdd_sm2,vin_ldo*";
-                                       regulator-min-microvolt = <3700000>;
-                                       regulator-max-microvolt = <3700000>;
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <1800000>;
                                        regulator-always-on;
                                };
 
index c42e4f938dcde153355f58d0ed995eda8db08af1..432960ae952a36d16725483f30d59c3c27fbe910 100644 (file)
 &fec1 {
        phy-mode = "rmii";
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_fec1_1>;
+       pinctrl-0 = <&pinctrl_fec1>;
        status = "okay";
 };
 
+&iomuxc {
+       vf610-cosmic {
+               pinctrl_fec1: fec1grp {
+                       fsl,pins = <VF610_FEC1_PINGRP1>;
+               };
+
+               pinctrl_uart1: uart1grp {
+                       fsl,pins = <VF610_UART1_PINGRP1>;
+               };
+       };
+};
+
 &uart1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_uart1_1>;
+       pinctrl-0 = <&pinctrl_uart1>;
        status = "okay";
 };
diff --git a/arch/arm/boot/dts/vf610-pingrp.h b/arch/arm/boot/dts/vf610-pingrp.h
new file mode 100644 (file)
index 0000000..0858f4f
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 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.
+ *
+ */
+
+#ifndef __DTS_VF610_PINGRP_H
+#define __DTS_VF610_PINGRP_H
+
+#include "vf610-pinfunc.h"
+
+#define VF610_DCU0_PINGRP1 \
+       VF610_PAD_PTB8__GPIO_30                 0x42 \
+       VF610_PAD_PTE0__DCU0_HSYNC              0x42 \
+       VF610_PAD_PTE1__DCU0_VSYNC              0x42 \
+       VF610_PAD_PTE2__DCU0_PCLK               0x42 \
+       VF610_PAD_PTE4__DCU0_DE                 0x42 \
+       VF610_PAD_PTE5__DCU0_R0                 0x42 \
+       VF610_PAD_PTE6__DCU0_R1                 0x42 \
+       VF610_PAD_PTE7__DCU0_R2                 0x42 \
+       VF610_PAD_PTE8__DCU0_R3                 0x42 \
+       VF610_PAD_PTE9__DCU0_R4                 0x42 \
+       VF610_PAD_PTE10__DCU0_R5                0x42 \
+       VF610_PAD_PTE11__DCU0_R6                0x42 \
+       VF610_PAD_PTE12__DCU0_R7                0x42 \
+       VF610_PAD_PTE13__DCU0_G0                0x42 \
+       VF610_PAD_PTE14__DCU0_G1                0x42 \
+       VF610_PAD_PTE15__DCU0_G2                0x42 \
+       VF610_PAD_PTE16__DCU0_G3                0x42 \
+       VF610_PAD_PTE17__DCU0_G4                0x42 \
+       VF610_PAD_PTE18__DCU0_G5                0x42 \
+       VF610_PAD_PTE19__DCU0_G6                0x42 \
+       VF610_PAD_PTE20__DCU0_G7                0x42 \
+       VF610_PAD_PTE21__DCU0_B0                0x42 \
+       VF610_PAD_PTE22__DCU0_B1                0x42 \
+       VF610_PAD_PTE23__DCU0_B2                0x42 \
+       VF610_PAD_PTE24__DCU0_B3                0x42 \
+       VF610_PAD_PTE25__DCU0_B4                0x42 \
+       VF610_PAD_PTE26__DCU0_B5                0x42 \
+       VF610_PAD_PTE27__DCU0_B6                0x42 \
+       VF610_PAD_PTE28__DCU0_B7                0x42
+
+#define VF610_DSPI0_PINGRP1 \
+       VF610_PAD_PTB19__DSPI0_CS0              0x1182 \
+       VF610_PAD_PTB20__DSPI0_SIN              0x1181 \
+       VF610_PAD_PTB21__DSPI0_SOUT             0x1182 \
+       VF610_PAD_PTB22__DSPI0_SCK              0x1182
+
+#define VF610_ESDHC1_PINGRP1 \
+       VF610_PAD_PTA24__ESDHC1_CLK             0x31ef \
+       VF610_PAD_PTA25__ESDHC1_CMD             0x31ef \
+       VF610_PAD_PTA26__ESDHC1_DAT0            0x31ef \
+       VF610_PAD_PTA27__ESDHC1_DAT1            0x31ef \
+       VF610_PAD_PTA28__ESDHC1_DATA2           0x31ef \
+       VF610_PAD_PTA29__ESDHC1_DAT3            0x31ef \
+       VF610_PAD_PTA7__GPIO_134                0x219d
+
+#define VF610_FEC0_PINGRP1 \
+       VF610_PAD_PTA6__RMII_CLKIN              0x30d1 \
+       VF610_PAD_PTC0__ENET_RMII0_MDC          0x30d3 \
+       VF610_PAD_PTC1__ENET_RMII0_MDIO         0x30d1 \
+       VF610_PAD_PTC2__ENET_RMII0_CRS          0x30d1 \
+       VF610_PAD_PTC3__ENET_RMII0_RXD1         0x30d1 \
+       VF610_PAD_PTC4__ENET_RMII0_RXD0         0x30d1 \
+       VF610_PAD_PTC5__ENET_RMII0_RXER         0x30d1 \
+       VF610_PAD_PTC6__ENET_RMII0_TXD1         0x30d2 \
+       VF610_PAD_PTC7__ENET_RMII0_TXD0         0x30d2 \
+       VF610_PAD_PTC8__ENET_RMII0_TXEN         0x30d2
+
+#define VF610_FEC1_PINGRP1 \
+       VF610_PAD_PTC9__ENET_RMII1_MDC          0x30d2 \
+       VF610_PAD_PTC10__ENET_RMII1_MDIO        0x30d3 \
+       VF610_PAD_PTC11__ENET_RMII1_CRS         0x30d1 \
+       VF610_PAD_PTC12__ENET_RMII_RXD1         0x30d1 \
+       VF610_PAD_PTC13__ENET_RMII1_RXD0        0x30d1 \
+       VF610_PAD_PTC14__ENET_RMII1_RXER        0x30d1 \
+       VF610_PAD_PTC15__ENET_RMII1_TXD1        0x30d2 \
+       VF610_PAD_PTC16__ENET_RMII1_TXD0        0x30d2 \
+       VF610_PAD_PTC17__ENET_RMII1_TXEN        0x30d2 \
+
+#define VF610_I2C0_PINGRP1 \
+       VF610_PAD_PTB14__I2C0_SCL               0x30d3 \
+       VF610_PAD_PTB15__I2C0_SDA               0x30d3 \
+
+#define VF610_PWM0_PINGRP1 \
+       VF610_PAD_PTB0__FTM0_CH0                0x1582 \
+       VF610_PAD_PTB1__FTM0_CH1                0x1582 \
+       VF610_PAD_PTB2__FTM0_CH2                0x1582 \
+       VF610_PAD_PTB3__FTM0_CH3                0x1582 \
+       VF610_PAD_PTB6__FTM0_CH6                0x1582 \
+       VF610_PAD_PTB7__FTM0_CH7                0x1582
+
+#define VF610_QSPI0_PINGRP1 \
+       VF610_PAD_PTD0__QSPI0_A_QSCK            0x307b \
+       VF610_PAD_PTD1__QSPI0_A_CS0             0x307f \
+       VF610_PAD_PTD2__QSPI0_A_DATA3           0x3073 \
+       VF610_PAD_PTD3__QSPI0_A_DATA2           0x3073 \
+       VF610_PAD_PTD4__QSPI0_A_DATA1           0x3073 \
+       VF610_PAD_PTD5__QSPI0_A_DATA0           0x307b \
+       VF610_PAD_PTD7__QSPI0_B_QSCK            0x307b \
+       VF610_PAD_PTD8__QSPI0_B_CS0             0x307f \
+       VF610_PAD_PTD9__QSPI0_B_DATA3           0x3073 \
+       VF610_PAD_PTD10__QSPI0_B_DATA2          0x3073 \
+       VF610_PAD_PTD11__QSPI0_B_DATA1          0x3073 \
+       VF610_PAD_PTD12__QSPI0_B_DATA0          0x307b
+
+#define VF610_SAI2_PINGRP1 \
+       VF610_PAD_PTA16__SAI2_TX_BCLK           0x02ed \
+       VF610_PAD_PTA18__SAI2_TX_DATA           0x02ee \
+       VF610_PAD_PTA19__SAI2_TX_SYNC           0x02ed \
+       VF610_PAD_PTA21__SAI2_RX_BCLK           0x02ed \
+       VF610_PAD_PTA22__SAI2_RX_DATA           0x02ed \
+       VF610_PAD_PTA23__SAI2_RX_SYNC           0x02ed \
+       VF610_PAD_PTB18__EXT_AUDIO_MCLK         0x02ed
+
+#define VF610_UART1_PINGRP1 \
+       VF610_PAD_PTB4__UART1_TX                0x21a2 \
+       VF610_PAD_PTB5__UART1_RX                0x21a1
+
+#define VF610_USBVBUS_PINGRP1 \
+       VF610_PAD_PTA24__USB1_VBUS_EN           0x219c \
+       VF610_PAD_PTA16__USB0_VBUS_EN           0x219c
+
+#endif /* __DTS_VF610_PINGRP_H */
index c8047ca16501324aaed37981ab133c0207d682f7..80db14eabb7d7f5fc6dba40fbe282ace9901ef70 100644 (file)
@@ -39,7 +39,7 @@
 &dspi0 {
        bus-num = <0>;
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_dspi0_1>;
+       pinctrl-0 = <&pinctrl_dspi0>;
        status = "okay";
 
        sflash: at26df081a@0 {
 &fec0 {
        phy-mode = "rmii";
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_fec0_1>;
+       pinctrl-0 = <&pinctrl_fec0>;
        status = "okay";
 };
 
 &fec1 {
        phy-mode = "rmii";
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_fec1_1>;
+       pinctrl-0 = <&pinctrl_fec1>;
        status = "okay";
 };
 
 &i2c0 {
        clock-frequency = <100000>;
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_i2c0_1>;
+       pinctrl-0 = <&pinctrl_i2c0>;
        status = "okay";
 };
 
+&iomuxc {
+       vf610-twr {
+               pinctrl_dspi0: dspi0grp {
+                       fsl,pins = <VF610_DSPI0_PINGRP1>;
+               };
+
+               pinctrl_fec0: fec0grp {
+                       fsl,pins = <VF610_FEC0_PINGRP1>;
+               };
+
+               pinctrl_fec1: fec1grp {
+                       fsl,pins = <VF610_FEC1_PINGRP1>;
+               };
+
+               pinctrl_i2c0: i2c0grp {
+                       fsl,pins = <VF610_I2C0_PINGRP1>;
+               };
+
+               pinctrl_uart1: uart1grp {
+                       fsl,pins = <VF610_UART1_PINGRP1>;
+               };
+       };
+};
+
 &uart1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_uart1_1>;
+       pinctrl-0 = <&pinctrl_uart1>;
        status = "okay";
 };
index d31ce1b4a7b08df9dab864e633afe665a2400a59..ef8a0eecbe6d48e3925f9dd8249403f5538356f7 100644 (file)
@@ -8,7 +8,7 @@
  */
 
 #include "skeleton.dtsi"
-#include "vf610-pinfunc.h"
+#include "vf610-pingrp.h"
 #include <dt-bindings/clock/vf610-clock.h>
 
 / {
                                compatible = "fsl,vf610-iomuxc";
                                reg = <0x40048000 0x1000>;
                                #gpio-range-cells = <3>;
-
-                               /* functions and groups pins */
-
-                               dcu0 {
-                                       pinctrl_dcu0_1: dcu0grp_1 {
-                                               fsl,pins = <
-                                               VF610_PAD_PTB8__GPIO_30         0x42
-                                               VF610_PAD_PTE0__DCU0_HSYNC      0x42
-                                               VF610_PAD_PTE1__DCU0_VSYNC      0x42
-                                               VF610_PAD_PTE2__DCU0_PCLK       0x42
-                                               VF610_PAD_PTE4__DCU0_DE         0x42
-                                               VF610_PAD_PTE5__DCU0_R0         0x42
-                                               VF610_PAD_PTE6__DCU0_R1         0x42
-                                               VF610_PAD_PTE7__DCU0_R2         0x42
-                                               VF610_PAD_PTE8__DCU0_R3         0x42
-                                               VF610_PAD_PTE9__DCU0_R4         0x42
-                                               VF610_PAD_PTE10__DCU0_R5        0x42
-                                               VF610_PAD_PTE11__DCU0_R6        0x42
-                                               VF610_PAD_PTE12__DCU0_R7        0x42
-                                               VF610_PAD_PTE13__DCU0_G0        0x42
-                                               VF610_PAD_PTE14__DCU0_G1        0x42
-                                               VF610_PAD_PTE15__DCU0_G2        0x42
-                                               VF610_PAD_PTE16__DCU0_G3        0x42
-                                               VF610_PAD_PTE17__DCU0_G4        0x42
-                                               VF610_PAD_PTE18__DCU0_G5        0x42
-                                               VF610_PAD_PTE19__DCU0_G6        0x42
-                                               VF610_PAD_PTE20__DCU0_G7        0x42
-                                               VF610_PAD_PTE21__DCU0_B0        0x42
-                                               VF610_PAD_PTE22__DCU0_B1        0x42
-                                               VF610_PAD_PTE23__DCU0_B2        0x42
-                                               VF610_PAD_PTE24__DCU0_B3        0x42
-                                               VF610_PAD_PTE25__DCU0_B4        0x42
-                                               VF610_PAD_PTE26__DCU0_B5        0x42
-                                               VF610_PAD_PTE27__DCU0_B6        0x42
-                                               VF610_PAD_PTE28__DCU0_B7        0x42
-                                               >;
-                                       };
-                               };
-
-                               dspi0 {
-                                       pinctrl_dspi0_1: dspi0grp_1 {
-                                               fsl,pins = <
-                                               VF610_PAD_PTB19__DSPI0_CS0      0x1182
-                                               VF610_PAD_PTB20__DSPI0_SIN      0x1181
-                                               VF610_PAD_PTB21__DSPI0_SOUT     0x1182
-                                               VF610_PAD_PTB22__DSPI0_SCK      0x1182
-                                               >;
-                                       };
-                               };
-
-                               esdhc1 {
-                                       pinctrl_esdhc1_1: esdhc1grp_1 {
-                                               fsl,pins = <
-                                               VF610_PAD_PTA24__ESDHC1_CLK     0x31ef
-                                               VF610_PAD_PTA25__ESDHC1_CMD     0x31ef
-                                               VF610_PAD_PTA26__ESDHC1_DAT0    0x31ef
-                                               VF610_PAD_PTA27__ESDHC1_DAT1    0x31ef
-                                               VF610_PAD_PTA28__ESDHC1_DATA2   0x31ef
-                                               VF610_PAD_PTA29__ESDHC1_DAT3    0x31ef
-                                               VF610_PAD_PTA7__GPIO_134        0x219d
-                                               >;
-                                       };
-                               };
-
-                               fec0 {
-                                       pinctrl_fec0_1: fec0grp_1 {
-                                               fsl,pins = <
-                                               VF610_PAD_PTA6__RMII_CLKIN      0x30d1
-                                               VF610_PAD_PTC0__ENET_RMII0_MDC  0x30d3
-                                               VF610_PAD_PTC1__ENET_RMII0_MDIO 0x30d1
-                                               VF610_PAD_PTC2__ENET_RMII0_CRS  0x30d1
-                                               VF610_PAD_PTC3__ENET_RMII0_RXD1 0x30d1
-                                               VF610_PAD_PTC4__ENET_RMII0_RXD0 0x30d1
-                                               VF610_PAD_PTC5__ENET_RMII0_RXER 0x30d1
-                                               VF610_PAD_PTC6__ENET_RMII0_TXD1 0x30d2
-                                               VF610_PAD_PTC7__ENET_RMII0_TXD0 0x30d2
-                                               VF610_PAD_PTC8__ENET_RMII0_TXEN 0x30d2
-                                               >;
-                                       };
-                               };
-
-                               fec1 {
-                                       pinctrl_fec1_1: fec1grp_1 {
-                                               fsl,pins = <
-                                               VF610_PAD_PTC9__ENET_RMII1_MDC          0x30d2
-                                               VF610_PAD_PTC10__ENET_RMII1_MDIO        0x30d3
-                                               VF610_PAD_PTC11__ENET_RMII1_CRS         0x30d1
-                                               VF610_PAD_PTC12__ENET_RMII_RXD1         0x30d1
-                                               VF610_PAD_PTC13__ENET_RMII1_RXD0        0x30d1
-                                               VF610_PAD_PTC14__ENET_RMII1_RXER        0x30d1
-                                               VF610_PAD_PTC15__ENET_RMII1_TXD1        0x30d2
-                                               VF610_PAD_PTC16__ENET_RMII1_TXD0        0x30d2
-                                               VF610_PAD_PTC17__ENET_RMII1_TXEN        0x30d2
-                                               >;
-                                       };
-                               };
-
-                               i2c0 {
-                                       pinctrl_i2c0_1: i2c0grp_1 {
-                                               fsl,pins = <
-                                               VF610_PAD_PTB14__I2C0_SCL       0x30d3
-                                               VF610_PAD_PTB15__I2C0_SDA       0x30d3
-                                               >;
-                                       };
-                               };
-
-                               pwm0 {
-                                       pinctrl_pwm0_1: pwm0grp_1 {
-                                               fsl,pins = <
-                                               VF610_PAD_PTB0__FTM0_CH0        0x1582
-                                               VF610_PAD_PTB1__FTM0_CH1        0x1582
-                                               VF610_PAD_PTB2__FTM0_CH2        0x1582
-                                               VF610_PAD_PTB3__FTM0_CH3        0x1582
-                                               VF610_PAD_PTB6__FTM0_CH6        0x1582
-                                               VF610_PAD_PTB7__FTM0_CH7        0x1582
-                                               >;
-                                       };
-                               };
-
-                               qspi0 {
-                                       pinctrl_qspi0_1: qspi0grp_1 {
-                                               fsl,pins = <
-                                               VF610_PAD_PTD0__QSPI0_A_QSCK    0x307b
-                                               VF610_PAD_PTD1__QSPI0_A_CS0     0x307f
-                                               VF610_PAD_PTD2__QSPI0_A_DATA3   0x3073
-                                               VF610_PAD_PTD3__QSPI0_A_DATA2   0x3073
-                                               VF610_PAD_PTD4__QSPI0_A_DATA1   0x3073
-                                               VF610_PAD_PTD5__QSPI0_A_DATA0   0x307b
-                                               VF610_PAD_PTD7__QSPI0_B_QSCK    0x307b
-                                               VF610_PAD_PTD8__QSPI0_B_CS0     0x307f
-                                               VF610_PAD_PTD9__QSPI0_B_DATA3   0x3073
-                                               VF610_PAD_PTD10__QSPI0_B_DATA2  0x3073
-                                               VF610_PAD_PTD11__QSPI0_B_DATA1  0x3073
-                                               VF610_PAD_PTD12__QSPI0_B_DATA0  0x307b
-                                               >;
-                                       };
-                               };
-
-                               sai2 {
-                                       pinctrl_sai2_1: sai2grp_1 {
-                                               fsl,pins = <
-                                               VF610_PAD_PTA16__SAI2_TX_BCLK   0x02ed
-                                               VF610_PAD_PTA18__SAI2_TX_DATA   0x02ee
-                                               VF610_PAD_PTA19__SAI2_TX_SYNC   0x02ed
-                                               VF610_PAD_PTA21__SAI2_RX_BCLK   0x02ed
-                                               VF610_PAD_PTA22__SAI2_RX_DATA   0x02ed
-                                               VF610_PAD_PTA23__SAI2_RX_SYNC   0x02ed
-                                               VF610_PAD_PTB18__EXT_AUDIO_MCLK 0x02ed
-                                               >;
-                                       };
-                               };
-
-                               uart1 {
-                                       pinctrl_uart1_1: uart1grp_1 {
-                                               fsl,pins = <
-                                               VF610_PAD_PTB4__UART1_TX        0x21a2
-                                               VF610_PAD_PTB5__UART1_RX        0x21a1
-                                               >;
-                                       };
-                               };
-
-                               usbvbus {
-                                       pinctrl_usbvbus_1: usbvbusgrp_1 {
-                                               fsl,pins = <
-                                               VF610_PAD_PTA24__USB1_VBUS_EN   0x219c
-                                               VF610_PAD_PTA16__USB0_VBUS_EN   0x219c
-                                               >;
-                                       };
-                               };
-
                        };
 
                        gpio1: gpio@40049000 {
index 26020a03f659f2d78fe37f2dca7f3e0a0eb573ca..87c5f1b595bb83fee159b247be762d19c27a3055 100644 (file)
@@ -35,8 +35,7 @@ void mcpm_set_early_poke(unsigned cpu, unsigned cluster,
        unsigned long *poke = &mcpm_entry_early_pokes[cluster][cpu][0];
        poke[0] = poke_phys_addr;
        poke[1] = poke_val;
-       __cpuc_flush_dcache_area((void *)poke, 8);
-       outer_clean_range(__pa(poke), __pa(poke + 2));
+       __sync_cache_range_w(poke, 2 * sizeof(*poke));
 }
 
 static const struct mcpm_platform_ops *platform_ops;
index ce922d0ea7aa85daa59c408ac5cd79beab5459a6..53c6a26b633d678f6d63f530931157aaefc68f84 100644 (file)
@@ -66,7 +66,7 @@ static long __init sp804_get_clock_rate(struct clk *clk)
 
 static void __iomem *sched_clock_base;
 
-static u32 sp804_read(void)
+static u64 notrace sp804_read(void)
 {
        return ~readl_relaxed(sched_clock_base + TIMER_VALUE);
 }
@@ -104,7 +104,7 @@ void __init __sp804_clocksource_and_sched_clock_init(void __iomem *base,
 
        if (use_sched_clock) {
                sched_clock_base = base;
-               setup_sched_clock(sp804_read, 32, rate);
+               sched_clock_register(sp804_read, 32, rate);
        }
 }
 
index 1ce39940795d9ebddb81509e84577b6be88e23ed..cb26c62dc7228a47335f79e50f32029721cc8bf5 100644 (file)
@@ -13,7 +13,7 @@ CONFIG_EMBEDDED=y
 CONFIG_PERF_EVENTS=y
 CONFIG_SLAB=y
 # CONFIG_BLOCK is not set
-CONFIG_ARCH_SHMOBILE=y
+CONFIG_ARCH_SHMOBILE_LEGACY=y
 CONFIG_ARCH_R8A73A4=y
 CONFIG_MACH_APE6EVM=y
 # CONFIG_ARM_THUMB is not set
index fae939d3d7f0a863b5284e95778fbc2f6c67f9c4..5abf1a2e31603e9570207d43fa1a4bbdaf7a0f2a 100644 (file)
@@ -15,7 +15,7 @@ CONFIG_MODULE_FORCE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_SHMOBILE=y
+CONFIG_ARCH_SHMOBILE_LEGACY=y
 CONFIG_ARCH_R8A7740=y
 CONFIG_MACH_ARMADILLO800EVA=y
 # CONFIG_SH_TIMER_TMU is not set
index 34e9780e63baa9f4f77467a0c9884cca3a9ddaf8..f43392dc2dcf659c1b1ac4d8a6b524e21f106cd6 100644 (file)
@@ -44,17 +44,26 @@ CONFIG_VFP=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 # CONFIG_SUSPEND is not set
 CONFIG_NET=y
+CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
 CONFIG_NETWORK_SECMARK=y
-# CONFIG_WIRELESS is not set
+CONFIG_NETFILTER=y
+CONFIG_CFG80211=y
+CONFIG_MAC80211=y
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_STANDALONE is not set
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_NETDEVICES=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_SMSC95XX=y
+CONFIG_ZD1211RW=y
+CONFIG_INPUT_EVDEV=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
 CONFIG_SERIAL_AMBA_PL011=y
@@ -71,15 +80,13 @@ CONFIG_FB=y
 CONFIG_FB_SIMPLE=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
-# CONFIG_USB_SUPPORT is not set
+CONFIG_USB=y
+CONFIG_USB_STORAGE=y
 CONFIG_MMC=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_SDHCI_BCM2835=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_GPIO=y
-CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=y
 CONFIG_LEDS_TRIGGER_ONESHOT=y
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
@@ -88,6 +95,8 @@ CONFIG_LEDS_TRIGGER_GPIO=y
 CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
 CONFIG_LEDS_TRIGGER_TRANSIENT=y
 CONFIG_LEDS_TRIGGER_CAMERA=y
+CONFIG_STAGING=y
+CONFIG_USB_DWC2=y
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
@@ -109,20 +118,20 @@ CONFIG_NLS_ASCII=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_NLS_UTF8=y
 CONFIG_PRINTK_TIME=y
+CONFIG_BOOT_PRINTK_DELAY=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DEBUG_INFO=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
 # CONFIG_ENABLE_MUST_CHECK is not set
 CONFIG_UNUSED_SYMBOLS=y
-CONFIG_LOCKUP_DETECTOR=y
-CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_MEMORY_INIT=y
-CONFIG_BOOT_PRINTK_DELAY=y
+CONFIG_LOCKUP_DETECTOR=y
 CONFIG_SCHED_TRACER=y
 CONFIG_STACK_TRACER=y
 CONFIG_FUNCTION_PROFILER=y
-CONFIG_DYNAMIC_DEBUG=y
+CONFIG_TEST_KSTRTOX=y
 CONFIG_KGDB=y
 CONFIG_KGDB_KDB=y
-CONFIG_TEST_KSTRTOX=y
 CONFIG_STRICT_DEVMEM=y
 CONFIG_DEBUG_LL=y
 CONFIG_EARLY_PRINTK=y
index b38cd107f82dfe5b1efffb4075e04fc39f9f41c5..80cff50beb34ab930709077d03d9a69d72481f5b 100644 (file)
@@ -8,7 +8,7 @@ CONFIG_SYSCTL_SYSCALL=y
 CONFIG_EMBEDDED=y
 CONFIG_SLAB=y
 # CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_SHMOBILE=y
+CONFIG_ARCH_SHMOBILE_LEGACY=y
 CONFIG_ARCH_R8A7778=y
 CONFIG_MACH_BOCKW=y
 CONFIG_MEMORY_START=0x60000000
@@ -27,12 +27,12 @@ CONFIG_HIGHMEM=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_ARM_APPENDED_DTB=y
-CONFIG_CMDLINE="console=ttySC0,115200 ignore_loglevel root=/dev/nfs ip=dhcp"
-CONFIG_CMDLINE_FORCE=y
+CONFIG_VFP=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 # CONFIG_SUSPEND is not set
 CONFIG_PM_RUNTIME=y
 CONFIG_NET=y
+CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
 CONFIG_IP_PNP=y
@@ -44,8 +44,6 @@ CONFIG_IP_PNP_DHCP=y
 # CONFIG_INET_DIAG is not set
 # CONFIG_IPV6 is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_DEVTMPFS=y
-CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
@@ -82,6 +80,7 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y
 # CONFIG_HWMON is not set
 CONFIG_I2C=y
 CONFIG_I2C_RCAR=y
+CONFIG_REGULATOR=y
 CONFIG_MEDIA_SUPPORT=y
 CONFIG_MEDIA_CAMERA_SUPPORT=y
 CONFIG_V4L_PLATFORM_DRIVERS=y
@@ -108,11 +107,12 @@ CONFIG_MMC_SDHI=y
 CONFIG_MMC_SH_MMCIF=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_RX8581=y
+CONFIG_DMADEVICES=y
+CONFIG_RCAR_HPB_DMAE=y
 CONFIG_UIO=y
 CONFIG_UIO_PDRV_GENIRQ=y
 # CONFIG_IOMMU_SUPPORT is not set
 # CONFIG_DNOTIFY is not set
-# CONFIG_INOTIFY_USER is not set
 CONFIG_TMPFS=y
 # CONFIG_MISC_FILESYSTEMS is not set
 CONFIG_NFS_FS=y
index ad7dfbbafa453422fc5c986e2f749d3eaf609a0c..aec8a3ea14365d1ead3c9d189426c616fc07ab7d 100644 (file)
@@ -13,7 +13,7 @@ CONFIG_S3C24XX_PWM=y
 CONFIG_ARCH_EXYNOS5=y
 CONFIG_MACH_EXYNOS4_DT=y
 CONFIG_SMP=y
-CONFIG_NR_CPUS=2
+CONFIG_NR_CPUS=8
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
diff --git a/arch/arm/configs/genmai_defconfig b/arch/arm/configs/genmai_defconfig
new file mode 100644 (file)
index 0000000..aa0b704
--- /dev/null
@@ -0,0 +1,116 @@
+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_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_SHMOBILE_LEGACY=y
+CONFIG_ARCH_R7S72100=y
+CONFIG_MACH_GENMAI=y
+# CONFIG_SH_TIMER_CMT is not set
+# CONFIG_SH_TIMER_MTU2 is not set
+# CONFIG_SH_TIMER_TMU is not set
+# CONFIG_EM_TIMER_STI is not set
+CONFIG_ARM_ERRATA_430973=y
+CONFIG_ARM_ERRATA_458693=y
+CONFIG_ARM_ERRATA_460075=y
+CONFIG_ARM_ERRATA_743622=y
+CONFIG_ARM_ERRATA_754322=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_FORCE_MAX_ZONEORDER=13
+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_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=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_WIRELESS is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_NETDEVICES=y
+# CONFIG_NET_CORE is not set
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+CONFIG_SH_ETH=y
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+# CONFIG_WLAN is not set
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=10
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C_SH_MOBILE=y
+# CONFIG_HWMON is not set
+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
+CONFIG_MMC_SH_MMCIF=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_RTC_CLASS=y
+CONFIG_DMADEVICES=y
+CONFIG_SH_DMAE=y
+# CONFIG_IOMMU_SUPPORT is not set
+# CONFIG_DNOTIFY is not set
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_CONFIGFS_FS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_V4_1=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+# CONFIG_ARM_UNWIND is not set
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
index e958ebe7977984be0a2a30746b2acefcfadfecca..6309ee52ccfcb3d74563f8ea6d5bfe396daf546c 100644 (file)
@@ -91,6 +91,7 @@ CONFIG_SMSC911X=y
 CONFIG_SMSC_PHY=y
 # CONFIG_INPUT_MOUSEDEV is not set
 CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
 CONFIG_KEYBOARD_IMX=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_TOUCHSCREEN=y
@@ -118,6 +119,7 @@ CONFIG_IMX2_WDT=y
 CONFIG_MFD_MC13XXX_SPI=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_GPIO=y
 CONFIG_REGULATOR_MC13783=y
 CONFIG_REGULATOR_MC13892=y
 CONFIG_MEDIA_SUPPORT=y
index 8d0c5a018ed72b720f0b235be8dff2ee9bf1e77a..f338fd6370ad0f045fb74baf63de3cad783249cb 100644 (file)
@@ -42,6 +42,7 @@ CONFIG_VMSPLIT_2G=y
 CONFIG_PREEMPT_VOLUNTARY=y
 CONFIG_AEABI=y
 # CONFIG_OABI_COMPAT is not set
+CONFIG_HIGHMEM=y
 CONFIG_CMDLINE="noinitrd console=ttymxc0,115200"
 CONFIG_VFP=y
 CONFIG_NEON=y
@@ -129,6 +130,8 @@ CONFIG_MOUSE_PS2_ELANTECH=y
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_EGALAX=y
 CONFIG_TOUCHSCREEN_MC13783=y
+CONFIG_TOUCHSCREEN_TSC2007=y
+CONFIG_TOUCHSCREEN_STMPE=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_MMA8450=y
 CONFIG_SERIO_SERPORT=m
@@ -156,6 +159,7 @@ CONFIG_IMX2_WDT=y
 CONFIG_MFD_DA9052_I2C=y
 CONFIG_MFD_MC13XXX_SPI=y
 CONFIG_MFD_MC13XXX_I2C=y
+CONFIG_MFD_STMPE=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_ANATOP=y
index 0ae0eaebf6b22ea7c71ed5746ee448029346af9f..2e762d94e94b31501c1e7e3ea16965c72d3d9b9c 100644 (file)
@@ -27,6 +27,7 @@ CONFIG_PCI_MVEBU=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 # CONFIG_OABI_COMPAT is not set
+CONFIG_HIGHMEM=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_CPU_FREQ=y
index 825c16dee8a002689b6498ad94c0421ea19aef13..7fd65a01ec7ee2636a179d955cebd5ab90bd30c4 100644 (file)
@@ -9,7 +9,7 @@ CONFIG_EMBEDDED=y
 CONFIG_PERF_EVENTS=y
 CONFIG_SLAB=y
 # CONFIG_BLOCK is not set
-CONFIG_ARCH_SHMOBILE=y
+CONFIG_ARCH_SHMOBILE_LEGACY=y
 CONFIG_ARCH_R8A7791=y
 CONFIG_MACH_KOELSCH=y
 # CONFIG_SWP_EMULATE is not set
index 6c37f4a98eb82b3dbabdecf9a2f60dceb5737aa4..e42ce3756af3e9cac163fca222fcbcb3c30fb440 100644 (file)
@@ -13,7 +13,7 @@ CONFIG_SLAB=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_SHMOBILE=y
+CONFIG_ARCH_SHMOBILE_LEGACY=y
 CONFIG_ARCH_EMEV2=y
 CONFIG_MACH_KZM9D=y
 CONFIG_MEMORY_START=0x40000000
@@ -32,6 +32,7 @@ CONFIG_FORCE_MAX_ZONEORDER=13
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_ARM_APPENDED_DTB=y
+CONFIG_AUTO_ZRELADDR=y
 CONFIG_VFP=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_PM_RUNTIME=y
index 1ad028023a6460e3b665b4044c6994232b9b3ca1..9934dbc23d64f7892d09e213720cbf0ff6b581c8 100644 (file)
@@ -22,7 +22,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_SHMOBILE=y
+CONFIG_ARCH_SHMOBILE_LEGACY=y
 CONFIG_ARCH_SH73A0=y
 CONFIG_MACH_KZM9G=y
 CONFIG_MEMORY_START=0x41000000
index 35bff5e0d57a26b799e4554497859dcf1f029e9b..883443f8f4f30ec5af446e5683e08cfad512b3e8 100644 (file)
@@ -12,7 +12,7 @@ CONFIG_SLAB=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_SHMOBILE=y
+CONFIG_ARCH_SHMOBILE_LEGACY=y
 CONFIG_ARCH_R8A7790=y
 CONFIG_MACH_LAGER=y
 # CONFIG_SH_TIMER_TMU is not set
@@ -80,7 +80,7 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 CONFIG_I2C_GPIO=y
-CONFIG_I2C_SH_MOBILE=y
+CONFIG_I2C_RCAR=y
 CONFIG_GPIO_SH_PFC=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIO_RCAR=y
@@ -89,6 +89,7 @@ CONFIG_THERMAL=y
 CONFIG_RCAR_THERMAL=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_GPIO=y
 CONFIG_DRM=y
 CONFIG_DRM_RCAR_DU=y
 # CONFIG_USB_SUPPORT is not set
index 9fb11895b2e27f73663b547a7abb4719adeece34..a61e1653fc5e07c728b5cc17048968818ed53117 100644 (file)
@@ -14,7 +14,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_SHMOBILE=y
+CONFIG_ARCH_SHMOBILE_LEGACY=y
 CONFIG_ARCH_SH7372=y
 CONFIG_MACH_MACKEREL=y
 CONFIG_MEMORY_SIZE=0x10000000
index 5cc6360340b1c683dfe5b31c15a54c61e457963a..f21bd405cc2a4f3d756bc11cae91f8f332f41732 100644 (file)
@@ -9,7 +9,7 @@ CONFIG_SYSCTL_SYSCALL=y
 CONFIG_EMBEDDED=y
 CONFIG_SLAB=y
 # CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_SHMOBILE=y
+CONFIG_ARCH_SHMOBILE_LEGACY=y
 CONFIG_ARCH_R8A7779=y
 CONFIG_MACH_MARZEN=y
 CONFIG_MEMORY_START=0x60000000
@@ -30,12 +30,12 @@ CONFIG_HIGHMEM=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_ARM_APPENDED_DTB=y
-CONFIG_CMDLINE="console=ttySC2,115200 earlyprintk=sh-sci.2,115200 ignore_loglevel root=/dev/nfs ip=on"
-CONFIG_CMDLINE_FORCE=y
+CONFIG_VFP=y
 CONFIG_KEXEC=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_PM_RUNTIME=y
 CONFIG_NET=y
+CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
 CONFIG_IP_PNP=y
@@ -43,8 +43,6 @@ CONFIG_IP_PNP_DHCP=y
 # CONFIG_IPV6 is not set
 # CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_DEVTMPFS=y
-CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
@@ -61,7 +59,6 @@ CONFIG_NETDEVICES=y
 # CONFIG_NET_VENDOR_MICREL is not set
 # CONFIG_NET_VENDOR_NATSEMI is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
-CONFIG_SMC911X=y
 CONFIG_SMSC911X=y
 # CONFIG_NET_VENDOR_STMICRO is not set
 # CONFIG_WLAN is not set
@@ -106,11 +103,12 @@ CONFIG_USB_STORAGE=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_GPIO=y
+CONFIG_DMADEVICES=y
+CONFIG_RCAR_HPB_DMAE=y
 CONFIG_UIO=y
 CONFIG_UIO_PDRV_GENIRQ=y
 # CONFIG_IOMMU_SUPPORT is not set
 # CONFIG_DNOTIFY is not set
-# CONFIG_INOTIFY_USER is not set
 CONFIG_TMPFS=y
 # CONFIG_MISC_FILESYSTEMS is not set
 CONFIG_NFS_FS=y
index 4a5903e048272429bf58d753419bddda18d2f586..cdb85cb6b3b0e2813fa93a1dae00b105ce2c6e79 100644 (file)
@@ -68,7 +68,9 @@ CONFIG_NET_CALXEDA_XGMAC=y
 CONFIG_KS8851=y
 CONFIG_SMSC911X=y
 CONFIG_STMMAC_ETH=y
+CONFIG_ICPLUS_PHY=y
 CONFIG_MDIO_SUN4I=y
+CONFIG_TI_CPSW=y
 CONFIG_KEYBOARD_SPEAR=y
 CONFIG_SERIO_AMBAKMI=y
 CONFIG_SERIAL_8250=y
@@ -90,6 +92,8 @@ CONFIG_SERIAL_XILINX_PS_UART=y
 CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y
 CONFIG_SERIAL_FSL_LPUART=y
 CONFIG_SERIAL_FSL_LPUART_CONSOLE=y
+CONFIG_SERIAL_ST_ASC=y
+CONFIG_SERIAL_ST_ASC_CONSOLE=y
 CONFIG_I2C_DESIGNWARE_PLATFORM=y
 CONFIG_I2C_SIRF=y
 CONFIG_I2C_TEGRA=y
@@ -133,12 +137,14 @@ CONFIG_USB_GPIO_VBUS=y
 CONFIG_USB_ISP1301=y
 CONFIG_USB_MXS_PHY=y
 CONFIG_MMC=y
+CONFIG_MMC_BLOCK_MINORS=16
 CONFIG_MMC_ARMMMCI=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_SDHCI_ESDHC_IMX=y
 CONFIG_MMC_SDHCI_TEGRA=y
 CONFIG_MMC_SDHCI_SPEAR=y
+CONFIG_MMC_SDHCI_BCM_KONA=y
 CONFIG_MMC_OMAP=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_EDAC=y
index 594d706b641f8df1de256c875d638795acaa054f..6fcb5c88a6435f2ccb57174db713fbe5382f0a62 100644 (file)
@@ -69,6 +69,7 @@ CONFIG_USB_XHCI_HCD=y
 CONFIG_MMC=y
 CONFIG_MMC_MVSDIO=y
 CONFIG_NEW_LEDS=y
+CONFIG_LEDS_GPIO=y
 CONFIG_LEDS_CLASS=m
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=y
index 98a50c309b90ad72b710fdeddc4117208fa6c29c..bfa80a11e8c76304c800f2df62090f1f50d089c1 100644 (file)
@@ -173,6 +173,7 @@ CONFIG_MFD_PALMAS=y
 CONFIG_MFD_TPS65217=y
 CONFIG_MFD_TPS65910=y
 CONFIG_TWL6040_CORE=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_PALMAS=y
 CONFIG_REGULATOR_TPS65023=y
 CONFIG_REGULATOR_TPS6507X=y
index d57a85badb5ef49959ad5bc8049768330367a920..3e2259b60236d76af041a1a6eb3ef99cab7975a6 100644 (file)
@@ -12,6 +12,9 @@ CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=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
@@ -58,4 +61,8 @@ CONFIG_LEDS_TRIGGER_HEARTBEAT=y
 CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
 CONFIG_COMMON_CLK_DEBUG=y
 # CONFIG_IOMMU_SUPPORT is not set
+CONFIG_TMPFS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
 CONFIG_NLS=y
+CONFIG_PRINTK_TIME=y
index ac632cc38f249767bcedfc1232a4e4b8e6bc70d9..c6ebc184bf68201c69a0791ed83f0bbfc64b4348 100644 (file)
@@ -22,6 +22,7 @@ CONFIG_CMDLINE="root=/dev/ram0 console=ttyAMA2,115200n8"
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
 CONFIG_CPU_IDLE=y
+CONFIG_ARM_U8500_CPUIDLE=y
 CONFIG_VFP=y
 CONFIG_NEON=y
 CONFIG_PM_RUNTIME=y
@@ -109,6 +110,8 @@ CONFIG_EXT2_FS_SECURITY=y
 CONFIG_EXT3_FS=y
 CONFIG_EXT4_FS=y
 CONFIG_VFAT_FS=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_MISC_FILESYSTEMS is not set
index ee753f1749cd795b03557273afdb3d0832d6fc8e..e9a49fe0284e41c2f6d6d9448fb73e9a2ad99ead 100644 (file)
@@ -481,4 +481,9 @@ static inline void __sync_cache_range_r(volatile void *p, size_t size)
        : : : "r0","r1","r2","r3","r4","r5","r6","r7", \
              "r9","r10","lr","memory" )
 
+int set_memory_ro(unsigned long addr, int numpages);
+int set_memory_rw(unsigned long addr, int numpages);
+int set_memory_x(unsigned long addr, int numpages);
+int set_memory_nx(unsigned long addr, int numpages);
+
 #endif
index 3c597c222ef278a8eb170a4169b5e54dcc158ac0..fbeb39c869e9fdcedace1d61688247c14141cab3 100644 (file)
@@ -329,7 +329,7 @@ extern void _memset_io(volatile void __iomem *, int, size_t);
  */
 #define ioremap(cookie,size)           __arm_ioremap((cookie), (size), MT_DEVICE)
 #define ioremap_nocache(cookie,size)   __arm_ioremap((cookie), (size), MT_DEVICE)
-#define ioremap_cached(cookie,size)    __arm_ioremap((cookie), (size), MT_DEVICE_CACHED)
+#define ioremap_cache(cookie,size)     __arm_ioremap((cookie), (size), MT_DEVICE_CACHED)
 #define ioremap_wc(cookie,size)                __arm_ioremap((cookie), (size), MT_DEVICE_WC)
 #define iounmap                                __arm_iounmap
 
index 2fe141fcc8d63311b63a2be06a0289a31b0174a3..f98c7f32c9c8aefb256c7c7a287c6c2d69602011 100644 (file)
@@ -22,18 +22,21 @@ struct map_desc {
 };
 
 /* types 0-3 are defined in asm/io.h */
-#define MT_UNCACHED            4
-#define MT_CACHECLEAN          5
-#define MT_MINICLEAN           6
-#define MT_LOW_VECTORS         7
-#define MT_HIGH_VECTORS                8
-#define MT_MEMORY              9
-#define MT_ROM                 10
-#define MT_MEMORY_NONCACHED    11
-#define MT_MEMORY_DTCM         12
-#define MT_MEMORY_ITCM         13
-#define MT_MEMORY_SO           14
-#define MT_MEMORY_DMA_READY    15
+enum {
+       MT_UNCACHED = 4,
+       MT_CACHECLEAN,
+       MT_MINICLEAN,
+       MT_LOW_VECTORS,
+       MT_HIGH_VECTORS,
+       MT_MEMORY_RWX,
+       MT_MEMORY_RW,
+       MT_ROM,
+       MT_MEMORY_RWX_NONCACHED,
+       MT_MEMORY_RW_DTCM,
+       MT_MEMORY_RWX_ITCM,
+       MT_MEMORY_RW_SO,
+       MT_MEMORY_DMA_READY,
+};
 
 #ifdef CONFIG_MMU
 extern void iotable_init(struct map_desc *, int);
index 86a659a19526c75a2ba3b91ce839925cc52d26de..dfff709fda3ccdddbc0d67f3ff1a04c702c85ad6 100644 (file)
@@ -160,6 +160,7 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
        return (pmd_t *)pud;
 }
 
+#define pmd_large(pmd)         (pmd_val(pmd) & 2)
 #define pmd_bad(pmd)           (pmd_val(pmd) & 2)
 
 #define copy_pmd(pmdpd,pmdps)          \
index 4f9503908dca4a7dc536324514801bcbd03d32fd..03243f7eeddfc57beebb8100132dae059f96af77 100644 (file)
                                                 PMD_TYPE_TABLE)
 #define pmd_sect(pmd)          ((pmd_val(pmd) & PMD_TYPE_MASK) == \
                                                 PMD_TYPE_SECT)
+#define pmd_large(pmd)         pmd_sect(pmd)
 
 #define pud_clear(pudp)                        \
        do {                            \
index be956dbf6baea3a7481baa11c58233d0741702d1..7d59b524f2af3c48480762a9b41f36fefb04e546 100644 (file)
@@ -61,7 +61,7 @@ extern void __pgd_error(const char *file, int line, pgd_t);
  * mapping to be mapped at.  This is particularly important for
  * non-high vector CPUs.
  */
-#define FIRST_USER_ADDRESS     PAGE_SIZE
+#define FIRST_USER_ADDRESS     (PAGE_SIZE * 2)
 
 /*
  * Use TASK_SIZE as the ceiling argument for free_pgtables() and
@@ -254,6 +254,8 @@ PTE_BIT_FUNC(mkclean,   &= ~L_PTE_DIRTY);
 PTE_BIT_FUNC(mkdirty,   |= L_PTE_DIRTY);
 PTE_BIT_FUNC(mkold,     &= ~L_PTE_YOUNG);
 PTE_BIT_FUNC(mkyoung,   |= L_PTE_YOUNG);
+PTE_BIT_FUNC(mkexec,   &= ~L_PTE_XN);
+PTE_BIT_FUNC(mknexec,   |= L_PTE_XN);
 
 static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
 
index 75579a9d6f76cba3cc84ad61d01ed103269378bd..3759cacdd7f8601322b98ffed6598d97ee8bd016 100644 (file)
@@ -117,6 +117,6 @@ static inline bool set_phys_to_machine(unsigned long pfn, unsigned long mfn)
        return __set_phys_to_machine(pfn, mfn);
 }
 
-#define xen_remap(cookie, size) ioremap_cached((cookie), (size));
+#define xen_remap(cookie, size) ioremap_cache((cookie), (size));
 
 #endif /* _ASM_ARM_XEN_PAGE_H */
index 29da84e183f4a7939ff9e9bb69c96f1b93f68538..42b823cd2d22ffd119b303610ea865880253eb4d 100644 (file)
 #define IMX35_UART_BASE_ADDR(n)        IMX35_UART##n##_BASE_ADDR
 #define IMX35_UART_BASE(n)     IMX35_UART_BASE_ADDR(n)
 
+#define IMX50_UART1_BASE_ADDR  0x53fbc000
+#define IMX50_UART2_BASE_ADDR  0x53fc0000
+#define IMX50_UART3_BASE_ADDR  0x5000c000
+#define IMX50_UART4_BASE_ADDR  0x53ff0000
+#define IMX50_UART5_BASE_ADDR  0x63f90000
+#define IMX50_UART_BASE_ADDR(n)        IMX50_UART##n##_BASE_ADDR
+#define IMX50_UART_BASE(n)     IMX50_UART_BASE_ADDR(n)
+
 #define IMX51_UART1_BASE_ADDR  0x73fbc000
 #define IMX51_UART2_BASE_ADDR  0x73fc0000
 #define IMX51_UART3_BASE_ADDR  0x7000c000
@@ -85,6 +93,8 @@
 #define UART_PADDR     IMX_DEBUG_UART_BASE(IMX31)
 #elif defined(CONFIG_DEBUG_IMX35_UART)
 #define UART_PADDR     IMX_DEBUG_UART_BASE(IMX35)
+#elif defined(CONFIG_DEBUG_IMX50_UART)
+#define UART_PADDR     IMX_DEBUG_UART_BASE(IMX50)
 #elif defined(CONFIG_DEBUG_IMX51_UART)
 #define UART_PADDR     IMX_DEBUG_UART_BASE(IMX51)
 #elif defined(CONFIG_DEBUG_IMX53_UART)
index be6a720dd1834a8f697fc9db98170c15a39f484f..f98763f0bc179f30edf4a6e1b0b1f0f58bed27c6 100644 (file)
 #define TEGRA_APB_MISC_GP_HIDREV       (TEGRA_APB_MISC_BASE + 0x804)
 
 /*
- * Must be 1MB-aligned since a 1MB mapping is used early on.
+ * Must be section-aligned since a section mapping is used early on.
  * Must not overlap with regions in mach-tegra/io.c:tegra_io_desc[].
  */
-#define UART_VIRTUAL_BASE              0xfe100000
+#define UART_VIRTUAL_BASE              0xfe800000
 
 #define checkuart(rp, rv, lhu, bit, uart) \
                /* Load address of CLK_RST register */ \
 92:            and     \rv, \rp, #0xffffff     @ offset within 1MB section
                add     \rv, \rv, #UART_VIRTUAL_BASE
                str     \rv, [\tmp, #8]         @ Store in tegra_uart_virt
-               movw    \rv, #TEGRA_APB_MISC_GP_HIDREV & 0xffff
-               movt    \rv, #TEGRA_APB_MISC_GP_HIDREV >> 16
-               ldr     \rv, [\rv, #0]          @ Load HIDREV
-               ubfx    \rv, \rv, #8, #8        @ 15:8 are SoC version
-               cmp     \rv, #0x20              @ Tegra20?
-               moveq   \rv, #0x75              @ Tegra20 divisor
-               movne   \rv, #0xdd              @ Tegra30 divisor
-               str     \rv, [\tmp, #12]        @ Save divisor to scratch
-               /* uart[UART_LCR] = UART_LCR_WLEN8 | UART_LCR_DLAB; */
-               mov     \rv, #UART_LCR_WLEN8 | UART_LCR_DLAB
-               str     \rv, [\rp, #UART_LCR << UART_SHIFT]
-               /* uart[UART_DLL] = div & 0xff; */
-               ldr     \rv, [\tmp, #12]
-               and     \rv, \rv, #0xff
-               str     \rv, [\rp, #UART_DLL << UART_SHIFT]
-               /* uart[UART_DLM] = div >> 8; */
-               ldr     \rv, [\tmp, #12]
-               lsr     \rv, \rv, #8
-               str     \rv, [\rp, #UART_DLM << UART_SHIFT]
-               /* uart[UART_LCR] = UART_LCR_WLEN8; */
-               mov     \rv, #UART_LCR_WLEN8
-               str     \rv, [\rp, #UART_LCR << UART_SHIFT]
                b       100f
 
                .align
                cmp     \rx, #0
                beq     1002f
 1001:          ldrb    \rd, [\rx, #UART_LSR << UART_SHIFT]
-               and     \rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE
-               teq     \rd, #UART_LSR_TEMT | UART_LSR_THRE
+               and     \rd, \rd, #UART_LSR_THRE
+               teq     \rd, #UART_LSR_THRE
                bne     1001b
 1002:
                .endm
 /*
  * Storage for the state maintained by the macros above.
  *
- * In the kernel proper, this data is located in arch/arm/mach-tegra/common.c.
+ * In the kernel proper, this data is located in arch/arm/mach-tegra/tegra.c.
  * That's because this header is included from multiple files, and we only
  * want a single copy of the data. In particular, the UART probing code above
  * assumes it's running using physical addresses. This is true when this file
@@ -247,6 +225,4 @@ tegra_uart_config:
        .word 0
        /* Debug UART virtual address */
        .word 0
-       /* Scratch space for debug macro */
-       .word 0
 #endif
index 52b26432c9a9941e8281a4483dd7aed148a99995..2260f1855820fa2d2961025b2683c2e30982a8e0 100644 (file)
@@ -14,8 +14,6 @@
 #include <asm/thread_notify.h>
 #include <asm/v7m.h>
 
-#include <mach/entry-macro.S>
-
 #include "entry-header.S"
 
 #ifdef CONFIG_TRACE_IRQFLAGS
index 8ff0ecdc637fd3bd2b41c0d129715acad13152e2..131a6ab5f35504dfc70c6f9e1421632c25d5feae 100644 (file)
@@ -385,7 +385,6 @@ out:
        return ret;
 
 out_unmap:
-       amba_set_drvdata(dev, NULL);
        iounmap(t->etb_regs);
 
 out_release:
@@ -398,8 +397,6 @@ static int etb_remove(struct amba_device *dev)
 {
        struct tracectx *t = amba_get_drvdata(dev);
 
-       amba_set_drvdata(dev, NULL);
-
        iounmap(t->etb_regs);
        t->etb_regs = NULL;
 
@@ -588,7 +585,6 @@ out:
        return ret;
 
 out_unmap:
-       amba_set_drvdata(dev, NULL);
        iounmap(t->etm_regs);
 
 out_release:
@@ -601,8 +597,6 @@ static int etm_remove(struct amba_device *dev)
 {
        struct tracectx *t = amba_get_drvdata(dev);
 
-       amba_set_drvdata(dev, NULL);
-
        iounmap(t->etm_regs);
        t->etm_regs = NULL;
 
index 57221e349a7ce0eec03445cd56de2845e5d23358..f0d180d8b29f4e22558a98fdf9366ebaf1c0c0cb 100644 (file)
 #include <asm/pgalloc.h>
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
+#include <asm/fncpy.h>
 #include <asm/mach-types.h>
 #include <asm/smp_plat.h>
 #include <asm/system_misc.h>
 
-extern const unsigned char relocate_new_kernel[];
+extern void relocate_new_kernel(void);
 extern const unsigned int relocate_new_kernel_size;
 
 extern unsigned long kexec_start_address;
@@ -142,6 +143,8 @@ void machine_kexec(struct kimage *image)
 {
        unsigned long page_list;
        unsigned long reboot_code_buffer_phys;
+       unsigned long reboot_entry = (unsigned long)relocate_new_kernel;
+       unsigned long reboot_entry_phys;
        void *reboot_code_buffer;
 
        /*
@@ -168,16 +171,16 @@ void machine_kexec(struct kimage *image)
 
 
        /* copy our kernel relocation code to the control code page */
-       memcpy(reboot_code_buffer,
-              relocate_new_kernel, relocate_new_kernel_size);
+       reboot_entry = fncpy(reboot_code_buffer,
+                            reboot_entry,
+                            relocate_new_kernel_size);
+       reboot_entry_phys = (unsigned long)reboot_entry +
+               (reboot_code_buffer_phys - (unsigned long)reboot_code_buffer);
 
-
-       flush_icache_range((unsigned long) reboot_code_buffer,
-                          (unsigned long) reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE);
        printk(KERN_INFO "Bye!\n");
 
        if (kexec_reinit)
                kexec_reinit();
 
-       soft_restart(reboot_code_buffer_phys);
+       soft_restart(reboot_entry_phys);
 }
index 94f6b05f9e24e8cd1d79063f03a9b2dd16791c67..92f7b15dd22121d4aa674fd78cd95cac8924c07f 100644 (file)
@@ -404,6 +404,7 @@ EXPORT_SYMBOL(dump_fpu);
 unsigned long get_wchan(struct task_struct *p)
 {
        struct stackframe frame;
+       unsigned long stack_page;
        int count = 0;
        if (!p || p == current || p->state == TASK_RUNNING)
                return 0;
@@ -412,9 +413,11 @@ unsigned long get_wchan(struct task_struct *p)
        frame.sp = thread_saved_sp(p);
        frame.lr = 0;                   /* recovered from the stack */
        frame.pc = thread_saved_pc(p);
+       stack_page = (unsigned long)task_stack_page(p);
        do {
-               int ret = unwind_frame(&frame);
-               if (ret < 0)
+               if (frame.sp < stack_page ||
+                   frame.sp >= stack_page + THREAD_SIZE ||
+                   unwind_frame(&frame) < 0)
                        return 0;
                if (!in_sched_functions(frame.pc))
                        return frame.pc;
index d0cdedf4864dc52092355e105f3ba04bba5c5704..95858966d84ec0f10d392a3356cb0367fcee0b85 100644 (file)
@@ -2,10 +2,12 @@
  * relocate_kernel.S - put the kernel image in place to boot
  */
 
+#include <linux/linkage.h>
 #include <asm/kexec.h>
 
-       .globl relocate_new_kernel
-relocate_new_kernel:
+       .align  3       /* not needed for this code, but keeps fncpy() happy */
+
+ENTRY(relocate_new_kernel)
 
        ldr     r0,kexec_indirection_page
        ldr     r1,kexec_start_address
@@ -79,6 +81,8 @@ kexec_mach_type:
 kexec_boot_atags:
        .long   0x0
 
+ENDPROC(relocate_new_kernel)
+
 relocate_new_kernel_end:
 
        .globl relocate_new_kernel_size
index 6a1b8a81b1ae448168572a9558aaf026f9e7e47e..7a2dd4689a75c9b112d577eccfca1a44d9a3faf6 100644 (file)
@@ -334,7 +334,7 @@ static void __init cacheid_init(void)
                cacheid = CACHEID_VIVT;
        }
 
-       printk("CPU: %s data cache, %s instruction cache\n",
+       pr_info("CPU: %s data cache, %s instruction cache\n",
                cache_is_vivt() ? "VIVT" :
                cache_is_vipt_aliasing() ? "VIPT aliasing" :
                cache_is_vipt_nonaliasing() ? "PIPT / VIPT nonaliasing" : "unknown",
@@ -416,7 +416,7 @@ void notrace cpu_init(void)
        struct stack *stk = &stacks[cpu];
 
        if (cpu >= NR_CPUS) {
-               printk(KERN_CRIT "CPU%u: bad primary CPU number\n", cpu);
+               pr_crit("CPU%u: bad primary CPU number\n", cpu);
                BUG();
        }
 
@@ -484,7 +484,7 @@ void __init smp_setup_processor_id(void)
         */
        set_my_cpu_offset(0);
 
-       printk(KERN_INFO "Booting Linux on physical CPU 0x%x\n", mpidr);
+       pr_info("Booting Linux on physical CPU 0x%x\n", mpidr);
 }
 
 struct mpidr_hash mpidr_hash;
@@ -564,8 +564,8 @@ static void __init setup_processor(void)
         */
        list = lookup_processor_type(read_cpuid_id());
        if (!list) {
-               printk("CPU configuration botched (ID %08x), unable "
-                      "to continue.\n", read_cpuid_id());
+               pr_err("CPU configuration botched (ID %08x), unable to continue.\n",
+                      read_cpuid_id());
                while (1);
        }
 
@@ -585,9 +585,9 @@ static void __init setup_processor(void)
        cpu_cache = *list->cache;
 #endif
 
-       printk("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n",
-              cpu_name, read_cpuid_id(), read_cpuid_id() & 15,
-              proc_arch[cpu_architecture()], cr_alignment);
+       pr_info("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n",
+               cpu_name, read_cpuid_id(), read_cpuid_id() & 15,
+               proc_arch[cpu_architecture()], cr_alignment);
 
        snprintf(init_utsname()->machine, __NEW_UTS_LEN + 1, "%s%c",
                 list->arch_name, ENDIANNESS);
@@ -629,8 +629,8 @@ int __init arm_add_memory(u64 start, u64 size)
        u64 aligned_start;
 
        if (meminfo.nr_banks >= NR_BANKS) {
-               printk(KERN_CRIT "NR_BANKS too low, "
-                       "ignoring memory at 0x%08llx\n", (long long)start);
+               pr_crit("NR_BANKS too low, ignoring memory at 0x%08llx\n",
+                       (long long)start);
                return -EINVAL;
        }
 
@@ -643,14 +643,14 @@ int __init arm_add_memory(u64 start, u64 size)
 
 #ifndef CONFIG_ARCH_PHYS_ADDR_T_64BIT
        if (aligned_start > ULONG_MAX) {
-               printk(KERN_CRIT "Ignoring memory at 0x%08llx outside "
-                      "32-bit physical address space\n", (long long)start);
+               pr_crit("Ignoring memory at 0x%08llx outside 32-bit physical address space\n",
+                       (long long)start);
                return -EINVAL;
        }
 
        if (aligned_start + size > ULONG_MAX) {
-               printk(KERN_CRIT "Truncating memory at 0x%08llx to fit in "
-                       "32-bit physical address space\n", (long long)start);
+               pr_crit("Truncating memory at 0x%08llx to fit in 32-bit physical address space\n",
+                       (long long)start);
                /*
                 * To ensure bank->start + bank->size is representable in
                 * 32 bits, we use ULONG_MAX as the upper limit rather than 4GB.
@@ -819,16 +819,15 @@ static void __init reserve_crashkernel(void)
 
        ret = reserve_bootmem(crash_base, crash_size, BOOTMEM_EXCLUSIVE);
        if (ret < 0) {
-               printk(KERN_WARNING "crashkernel reservation failed - "
-                      "memory is in use (0x%lx)\n", (unsigned long)crash_base);
+               pr_warn("crashkernel reservation failed - memory is in use (0x%lx)\n",
+                       (unsigned long)crash_base);
                return;
        }
 
-       printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
-              "for crashkernel (System RAM: %ldMB)\n",
-              (unsigned long)(crash_size >> 20),
-              (unsigned long)(crash_base >> 20),
-              (unsigned long)(total_mem >> 20));
+       pr_info("Reserving %ldMB of memory at %ldMB for crashkernel (System RAM: %ldMB)\n",
+               (unsigned long)(crash_size >> 20),
+               (unsigned long)(crash_base >> 20),
+               (unsigned long)(total_mem >> 20));
 
        crashk_res.start = crash_base;
        crashk_res.end = crash_base + crash_size - 1;
@@ -873,8 +872,6 @@ void __init setup_arch(char **cmdline_p)
        machine_desc = mdesc;
        machine_name = mdesc->name;
 
-       setup_dma_zone(mdesc);
-
        if (mdesc->reboot_mode != REBOOT_HARD)
                reboot_mode = mdesc->reboot_mode;
 
@@ -892,6 +889,7 @@ void __init setup_arch(char **cmdline_p)
        sort(&meminfo.bank, meminfo.nr_banks, sizeof(meminfo.bank[0]), meminfo_cmp, NULL);
 
        early_paging_init(mdesc, lookup_processor_type(read_cpuid_id()));
+       setup_dma_zone(mdesc);
        sanity_check_meminfo();
        arm_memblock_init(&meminfo, mdesc);
 
index 3c5d0f2170fd7ee309260c2d2c0a6108a24e54f8..b84d0cb13682ccd42e41a22894cb8d2c1821496d 100644 (file)
  * snippets.
  */
 
+/*
+ * In CPU_THUMBONLY case kernel arm opcodes are not allowed.
+ * Note in this case codes skips those instructions but it uses .org
+ * directive to keep correct layout of sigreturn_codes array.
+ */
+#ifndef CONFIG_CPU_THUMBONLY
+#define ARM_OK(code...)        code
+#else
+#define ARM_OK(code...)
+#endif
+
+       .macro arm_slot n
+       .org    sigreturn_codes + 12 * (\n)
+ARM_OK(        .arm    )
+       .endm
+
+       .macro thumb_slot n
+       .org    sigreturn_codes + 12 * (\n) + 8
+       .thumb
+       .endm
+
 #if __LINUX_ARM_ARCH__ <= 4
        /*
         * Note we manually set minimally required arch that supports
        .global sigreturn_codes
        .type   sigreturn_codes, #object
 
-       .arm
+       .align
 
 sigreturn_codes:
 
        /* ARM sigreturn syscall code snippet */
-       mov     r7, #(__NR_sigreturn - __NR_SYSCALL_BASE)
-       swi     #(__NR_sigreturn)|(__NR_OABI_SYSCALL_BASE)
+       arm_slot 0
+ARM_OK(        mov     r7, #(__NR_sigreturn - __NR_SYSCALL_BASE)       )
+ARM_OK(        swi     #(__NR_sigreturn)|(__NR_OABI_SYSCALL_BASE)      )
 
        /* Thumb sigreturn syscall code snippet */
-       .thumb
+       thumb_slot 0
        movs    r7, #(__NR_sigreturn - __NR_SYSCALL_BASE)
        swi     #0
 
        /* ARM sigreturn_rt syscall code snippet */
-       .arm
-       mov     r7, #(__NR_rt_sigreturn - __NR_SYSCALL_BASE)
-       swi     #(__NR_rt_sigreturn)|(__NR_OABI_SYSCALL_BASE)
+       arm_slot 1
+ARM_OK(        mov     r7, #(__NR_rt_sigreturn - __NR_SYSCALL_BASE)    )
+ARM_OK(        swi     #(__NR_rt_sigreturn)|(__NR_OABI_SYSCALL_BASE)   )
 
        /* Thumb sigreturn_rt syscall code snippet */
-       .thumb
+       thumb_slot 1
        movs    r7, #(__NR_rt_sigreturn - __NR_SYSCALL_BASE)
        swi     #0
 
@@ -74,7 +96,7 @@ sigreturn_codes:
         * it is thumb case or not, so we need additional
         * word after real last entry.
         */
-       .arm
+       arm_slot 2
        .space  4
 
        .size   sigreturn_codes, . - sigreturn_codes
index dc894ab3622b1effac1b885bd919bf629f66dc5d..8c61325b8bfce744fc8b7702317ecb1d365cb915 100644 (file)
@@ -105,8 +105,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
        secondary_data.pgdir = get_arch_pgd(idmap_pgd);
        secondary_data.swapper_pg_dir = get_arch_pgd(swapper_pg_dir);
 #endif
-       __cpuc_flush_dcache_area(&secondary_data, sizeof(secondary_data));
-       outer_clean_range(__pa(&secondary_data), __pa(&secondary_data + 1));
+       sync_cache_w(&secondary_data);
 
        /*
         * Now bring the CPU into our world.
index 00f79e59985bccaf54bd3b1c8f2e292f49014a47..af4e8c8a5422c4383396f7f4b3a836a67426b7de 100644 (file)
@@ -31,7 +31,7 @@ int notrace unwind_frame(struct stackframe *frame)
        high = ALIGN(low, THREAD_SIZE);
 
        /* check current frame pointer is within bounds */
-       if (fp < (low + 12) || fp + 4 >= high)
+       if (fp < low + 12 || fp > high - 4)
                return -EINVAL;
 
        /* restore the registers from the stack frame */
index f50f19e5c138839bede270baf3531a41aa5af7c4..7a3be1d4d0b13b7ca984721403aafda47ecb574c 100644 (file)
@@ -52,7 +52,7 @@ static struct map_desc dtcm_iomap[] __initdata = {
                .virtual        = DTCM_OFFSET,
                .pfn            = __phys_to_pfn(DTCM_OFFSET),
                .length         = 0,
-               .type           = MT_MEMORY_DTCM
+               .type           = MT_MEMORY_RW_DTCM
        }
 };
 
@@ -61,7 +61,7 @@ static struct map_desc itcm_iomap[] __initdata = {
                .virtual        = ITCM_OFFSET,
                .pfn            = __phys_to_pfn(ITCM_OFFSET),
                .length         = 0,
-               .type           = MT_MEMORY_ITCM
+               .type           = MT_MEMORY_RWX_ITCM,
        }
 };
 
index dbf0923e8d76bda9392b902e0c8e500025d70402..a55a142678706e4954df5338bfb613ae8fc177f3 100644 (file)
@@ -56,7 +56,7 @@ static void dump_mem(const char *, const char *, unsigned long, unsigned long);
 void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame)
 {
 #ifdef CONFIG_KALLSYMS
-       printk("[<%08lx>] (%pS) from [<%08lx>] (%pS)\n", where, (void *)where, from, (void *)from);
+       printk("[<%08lx>] (%ps) from [<%08lx>] (%pS)\n", where, (void *)where, from, (void *)from);
 #else
        printk("Function entered at [<%08lx>] from [<%08lx>]\n", where, from);
 #endif
@@ -509,9 +509,10 @@ static inline int
 __do_cache_op(unsigned long start, unsigned long end)
 {
        int ret;
-       unsigned long chunk = PAGE_SIZE;
 
        do {
+               unsigned long chunk = min(PAGE_SIZE, end - start);
+
                if (signal_pending(current)) {
                        struct thread_info *ti = current_thread_info();
 
index cd07b5814c2304f0908342b04291af09388790b7..4102be617fce0644434e3aa7f7fec65c09fcb5e7 100644 (file)
@@ -80,14 +80,14 @@ for_each_frame:     tst     frame, mask             @ Check for address exceptions
 
                ldr     r1, [sv_pc, #-4]        @ if stmfd sp!, {args} exists,
                ldr     r3, .Ldsi+4
-               teq     r3, r1, lsr #10
+               teq     r3, r1, lsr #11
                ldreq   r0, [frame, #-8]        @ get sp
                subeq   r0, r0, #4              @ point at the last arg
                bleq    .Ldumpstm               @ dump saved registers
 
 1004:          ldr     r1, [sv_pc, #0]         @ if stmfd sp!, {..., fp, ip, lr, pc}
                ldr     r3, .Ldsi               @ instruction exists,
-               teq     r3, r1, lsr #10
+               teq     r3, r1, lsr #11
                subeq   r0, frame, #16
                bleq    .Ldumpstm               @ dump saved registers
 
@@ -128,11 +128,11 @@ ENDPROC(c_backtrace)
                beq     2f
                add     r7, r7, #1
                teq     r7, #6
-               moveq   r7, #1
-               moveq   r1, #'\n'
-               movne   r1, #' '
-               ldr     r3, [stack], #-4
-               mov     r2, reg
+               moveq   r7, #0
+               adr     r3, .Lcr
+               addne   r3, r3, #1              @ skip newline
+               ldr     r2, [stack], #-4
+               mov     r1, reg
                adr     r0, .Lfp
                bl      printk
 2:             subs    reg, reg, #1
@@ -142,11 +142,11 @@ ENDPROC(c_backtrace)
                blne    printk
                ldmfd   sp!, {instr, reg, stack, r7, pc}
 
-.Lfp:          .asciz  "%cr%d:%08x"
+.Lfp:          .asciz  " r%d:%08x%s"
 .Lcr:          .asciz  "\n"
 .Lbad:         .asciz  "Backtrace aborted due to bad frame pointer <%p>\n"
                .align
-.Ldsi:         .word   0xe92dd800 >> 10        @ stmfd sp!, {... fp, ip, lr, pc}
-               .word   0xe92d0000 >> 10        @ stmfd sp!, {}
+.Ldsi:         .word   0xe92dd800 >> 11        @ stmfd sp!, {... fp, ip, lr, pc}
+               .word   0xe92d0000 >> 11        @ stmfd sp!, {}
 
 #endif
index 36b668d8e121ee7450c8beffb5e9661923102038..bc1033b897b44510b16a8ab202f0c1b989cc15e5 100644 (file)
@@ -40,6 +40,7 @@ ENTRY(__loop_const_udelay)                    @ 0 <= r0 <= 0x7fffff06
 /*
  * loops = r0 * HZ * loops_per_jiffy / 1000000
  */
+               .align 3
 
 @ Delay routine
 ENTRY(__loop_delay)
index 699b71e7f7ecffb0e978a8387af33699c19233ca..44a4c9dfa4e51132150250ec5b98d9a34da0c401 100644 (file)
@@ -1,15 +1,33 @@
 if ARCH_AT91
 
+config HAVE_AT91_UTMI
+       bool
+
+config HAVE_AT91_USB_CLK
+       bool
+
 config HAVE_AT91_DBGU0
        bool
 
 config HAVE_AT91_DBGU1
        bool
 
+config AT91_USE_OLD_CLK
+       bool
+
 config AT91_PMC_UNIT
        bool
        default !ARCH_AT91X40
 
+config COMMON_CLK_AT91
+       bool
+       default AT91_PMC_UNIT && USE_OF && !AT91_USE_OLD_CLK
+       select COMMON_CLK
+
+config OLD_CLK_AT91
+       bool
+       default AT91_PMC_UNIT && AT91_USE_OLD_CLK
+
 config AT91_SAM9_ALT_RESET
        bool
        default !ARCH_AT91X40
@@ -21,6 +39,9 @@ config AT91_SAM9G45_RESET
 config AT91_SAM9_TIME
        bool
 
+config HAVE_AT91_SMD
+       bool
+
 config SOC_AT91SAM9
        bool
        select AT91_SAM9_TIME
@@ -65,9 +86,12 @@ config SOC_SAMA5D3
        select SOC_SAMA5
        select HAVE_FB_ATMEL
        select HAVE_AT91_DBGU1
+       select HAVE_AT91_UTMI
+       select HAVE_AT91_SMD
+       select HAVE_AT91_USB_CLK
        help
          Select this if you are using one of Atmel's SAMA5D3 family SoC.
-         This support covers SAMA5D31, SAMA5D33, SAMA5D34, SAMA5D35.
+         This support covers SAMA5D31, SAMA5D33, SAMA5D34, SAMA5D35, SAMA5D36.
 endif
 
 if SOC_SAM_V4_V5
@@ -78,11 +102,15 @@ config SOC_AT91RM9200
        select HAVE_AT91_DBGU0
        select MULTI_IRQ_HANDLER
        select SPARSE_IRQ
+       select AT91_USE_OLD_CLK
+       select HAVE_AT91_USB_CLK
 
 config SOC_AT91SAM9260
        bool "AT91SAM9260, AT91SAM9XE or AT91SAM9G20"
        select HAVE_AT91_DBGU0
        select SOC_AT91SAM9
+       select AT91_USE_OLD_CLK
+       select HAVE_AT91_USB_CLK
        help
          Select this if you are using one of Atmel's AT91SAM9260, AT91SAM9XE
          or AT91SAM9G20 SoC.
@@ -92,6 +120,8 @@ config SOC_AT91SAM9261
        select HAVE_AT91_DBGU0
        select HAVE_FB_ATMEL
        select SOC_AT91SAM9
+       select AT91_USE_OLD_CLK
+       select HAVE_AT91_USB_CLK
        help
          Select this if you are using one of Atmel's AT91SAM9261 or AT91SAM9G10 SoC.
 
@@ -100,18 +130,25 @@ config SOC_AT91SAM9263
        select HAVE_AT91_DBGU1
        select HAVE_FB_ATMEL
        select SOC_AT91SAM9
+       select AT91_USE_OLD_CLK
+       select HAVE_AT91_USB_CLK
 
 config SOC_AT91SAM9RL
        bool "AT91SAM9RL"
        select HAVE_AT91_DBGU0
        select HAVE_FB_ATMEL
        select SOC_AT91SAM9
+       select AT91_USE_OLD_CLK
+       select HAVE_AT91_UTMI
 
 config SOC_AT91SAM9G45
        bool "AT91SAM9G45 or AT91SAM9M10 families"
        select HAVE_AT91_DBGU1
        select HAVE_FB_ATMEL
        select SOC_AT91SAM9
+       select AT91_USE_OLD_CLK
+       select HAVE_AT91_UTMI
+       select HAVE_AT91_USB_CLK
        help
          Select this if you are using one of Atmel's AT91SAM9G45 family SoC.
          This support covers AT91SAM9G45, AT91SAM9G46, AT91SAM9M10 and AT91SAM9M11.
@@ -121,6 +158,10 @@ config SOC_AT91SAM9X5
        select HAVE_AT91_DBGU0
        select HAVE_FB_ATMEL
        select SOC_AT91SAM9
+       select AT91_USE_OLD_CLK
+       select HAVE_AT91_UTMI
+       select HAVE_AT91_SMD
+       select HAVE_AT91_USB_CLK
        help
          Select this if you are using one of Atmel's AT91SAM9x5 family SoC.
          This means that your SAM9 name finishes with a '5' (except if it is
@@ -133,6 +174,8 @@ config SOC_AT91SAM9N12
        select HAVE_AT91_DBGU0
        select HAVE_FB_ATMEL
        select SOC_AT91SAM9
+       select AT91_USE_OLD_CLK
+       select HAVE_AT91_USB_CLK
        help
          Select this if you are using Atmel's AT91SAM9N12 SoC.
 
index ca900be144ce9466db4a1cfb6fb577eef669e81e..075efb62f551a31cef9aa776fe5c21a4a3a4ebff 100644 (file)
@@ -12,26 +12,32 @@ config ARCH_AT91_NONE
 config ARCH_AT91RM9200
        bool "AT91RM9200"
        select SOC_AT91RM9200
+       select AT91_USE_OLD_CLK
 
 config ARCH_AT91SAM9260
        bool "AT91SAM9260 or AT91SAM9XE or AT91SAM9G20"
        select SOC_AT91SAM9260
+       select AT91_USE_OLD_CLK
 
 config ARCH_AT91SAM9261
        bool "AT91SAM9261 or AT91SAM9G10"
        select SOC_AT91SAM9261
+       select AT91_USE_OLD_CLK
 
 config ARCH_AT91SAM9263
        bool "AT91SAM9263"
        select SOC_AT91SAM9263
+       select AT91_USE_OLD_CLK
 
 config ARCH_AT91SAM9RL
        bool "AT91SAM9RL"
        select SOC_AT91SAM9RL
+       select AT91_USE_OLD_CLK
 
 config ARCH_AT91SAM9G45
        bool "AT91SAM9G45"
        select SOC_AT91SAM9G45
+       select AT91_USE_OLD_CLK
 
 config ARCH_AT91X40
        bool "AT91x40"
@@ -241,7 +247,7 @@ config MACH_PCONTROL_G20
        bool "PControl G20 CPU module"
        help
          Select this if you are using taskit's Stamp9G20 CPU module on this
-         carrier board, beeing the decentralized unit of a building automation
+         carrier board, being the decentralized unit of a building automation
          system; featuring nvram, eth-switch, iso-rs485, display, io
 
 config MACH_GSIA18S
index 90aab2d5a07f3aed6acc2ed8788105b877756fe6..705b38a179ec5b6a06d51d69bcd2b9280d288cf2 100644 (file)
@@ -7,7 +7,7 @@ obj-m           :=
 obj-n          :=
 obj-           :=
 
-obj-$(CONFIG_AT91_PMC_UNIT)    += clock.o
+obj-$(CONFIG_OLD_CLK_AT91)     += clock.o
 obj-$(CONFIG_AT91_SAM9_ALT_RESET) += at91sam9_alt_reset.o
 obj-$(CONFIG_AT91_SAM9G45_RESET) += at91sam9g45_reset.o
 obj-$(CONFIG_AT91_SAM9_TIME)   += at91sam926x_time.o
index 25805f2f6010f3d7b98035f9c8e3b1e09524a4e3..e47f5fd232f5f91e9a42b83beb8a21faddc6ac65 100644 (file)
 
 #include <linux/module.h>
 #include <linux/reboot.h>
+#include <linux/clk/at91_pmc.h>
 
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/system_misc.h>
 #include <mach/at91rm9200.h>
-#include <mach/at91_pmc.h>
 #include <mach/at91_st.h>
 #include <mach/cpu.h>
 
index f607deb40f4da6a88a0778b203cdcfbbc8518ecc..bc7b363a3083bfdab31591786fe38991c199e2dc 100644 (file)
@@ -174,7 +174,6 @@ clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev)
 static struct clock_event_device clkevt = {
        .name           = "at91_tick",
        .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-       .shift          = 32,
        .rating         = 150,
        .set_next_event = clkevt32k_next_event,
        .set_mode       = clkevt32k_mode,
@@ -265,11 +264,9 @@ void __init at91rm9200_timer_init(void)
        at91_st_write(AT91_ST_RTMR, 1);
 
        /* Setup timer clockevent, with minimum of two ticks (important!!) */
-       clkevt.mult = div_sc(AT91_SLOW_CLOCK, NSEC_PER_SEC, clkevt.shift);
-       clkevt.max_delta_ns = clockevent_delta2ns(AT91_ST_ALMV, &clkevt);
-       clkevt.min_delta_ns = clockevent_delta2ns(2, &clkevt) + 1;
        clkevt.cpumask = cpumask_of(0);
-       clockevents_register_device(&clkevt);
+       clockevents_config_and_register(&clkevt, AT91_SLOW_CLOCK,
+                                       2, AT91_ST_ALMV);
 
        /* register clocksource */
        clocksource_register_hz(&clk32k, AT91_SLOW_CLOCK);
index d6a1fa85371d3ee732f4048298532dab817478fc..6c821e5621590b5e920d330a2d895b196b7530b9 100644 (file)
@@ -11,6 +11,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/clk/at91_pmc.h>
 
 #include <asm/proc-fns.h>
 #include <asm/irq.h>
@@ -20,7 +21,6 @@
 #include <mach/cpu.h>
 #include <mach/at91_dbgu.h>
 #include <mach/at91sam9260.h>
-#include <mach/at91_pmc.h>
 
 #include "at91_aic.h"
 #include "at91_rstc.h"
index 23ba1d8a1531ca5f123f94591290450a0a403be6..6276b4c1acfed2943354809b8b5f6ddd37bba9f9 100644 (file)
@@ -11,6 +11,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/clk/at91_pmc.h>
 
 #include <asm/proc-fns.h>
 #include <asm/irq.h>
@@ -19,7 +20,6 @@
 #include <asm/system_misc.h>
 #include <mach/cpu.h>
 #include <mach/at91sam9261.h>
-#include <mach/at91_pmc.h>
 
 #include "at91_aic.h"
 #include "at91_rstc.h"
index 7eccb0fc57bc080c3eaee8c8f830a2a7fb127cad..37b90f4b990c3ce4e5360c526ca979810277121c 100644 (file)
@@ -11,6 +11,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/clk/at91_pmc.h>
 
 #include <asm/proc-fns.h>
 #include <asm/irq.h>
@@ -18,7 +19,6 @@
 #include <asm/mach/map.h>
 #include <asm/system_misc.h>
 #include <mach/at91sam9263.h>
-#include <mach/at91_pmc.h>
 
 #include "at91_aic.h"
 #include "at91_rstc.h"
index bb392320a0dd39d978bd5f1d3e861d2fce14b14c..0f04ffe9c5a87c2afb4f90b02d75b86b70fd722b 100644 (file)
@@ -39,6 +39,7 @@
 static u32 pit_cycle;          /* write-once */
 static u32 pit_cnt;            /* access only w/system irq blocked */
 static void __iomem *pit_base_addr __read_mostly;
+static struct clk *mck;
 
 static inline unsigned int pit_read(unsigned int reg_offset)
 {
@@ -195,10 +196,14 @@ static int __init of_at91sam926x_pit_init(void)
        if (!pit_base_addr)
                goto node_err;
 
+       mck = of_clk_get(np, 0);
+
        /* Get the interrupts property */
        ret = irq_of_parse_and_map(np, 0);
        if (!ret) {
                pr_crit("AT91: PIT: Unable to get IRQ from DT\n");
+               if (!IS_ERR(mck))
+                       clk_put(mck);
                goto ioremap_err;
        }
        at91sam926x_pit_irq.irq = ret;
@@ -230,6 +235,8 @@ void __init at91sam926x_pit_init(void)
        unsigned        bits;
        int             ret;
 
+       mck = ERR_PTR(-ENOENT);
+
        /* For device tree enabled device: initialize here */
        of_at91sam926x_pit_init();
 
@@ -237,7 +244,12 @@ void __init at91sam926x_pit_init(void)
         * Use our actual MCK to figure out how many MCK/16 ticks per
         * 1/HZ period (instead of a compile-time constant LATCH).
         */
-       pit_rate = clk_get_rate(clk_get(NULL, "mck")) / 16;
+       if (IS_ERR(mck))
+               mck = clk_get(NULL, "mck");
+
+       if (IS_ERR(mck))
+               panic("AT91: PIT: Unable to get mck clk\n");
+       pit_rate = clk_get_rate(mck) / 16;
        pit_cycle = (pit_rate + HZ/2) / HZ;
        WARN_ON(((pit_cycle - 1) & ~AT91_PIT_PIV) != 0);
 
index 9405aa08b10498430b097594865c95976297c6ba..2f455ce35268513d5abaafc954a54be76ef48a26 100644 (file)
 
 #include <linux/module.h>
 #include <linux/dma-mapping.h>
+#include <linux/clk/at91_pmc.h>
 
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/system_misc.h>
 #include <mach/at91sam9g45.h>
-#include <mach/at91_pmc.h>
 #include <mach/cpu.h>
 
 #include "at91_aic.h"
index 388ec3aec4b95edc8e63f8907a09fd66b2889a15..4ef088c62eabdf6661a801f495e795912f250cd5 100644 (file)
@@ -8,12 +8,12 @@
 
 #include <linux/module.h>
 #include <linux/dma-mapping.h>
+#include <linux/clk/at91_pmc.h>
 
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <mach/at91sam9n12.h>
-#include <mach/at91_pmc.h>
 #include <mach/cpu.h>
 
 #include "board.h"
index 0750ffb7e6b16d7a52dd636475226b9b9035b301..3651517abedfb1214386cabd93d7ab82844d16aa 100644 (file)
@@ -10,6 +10,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/clk/at91_pmc.h>
 
 #include <asm/proc-fns.h>
 #include <asm/irq.h>
@@ -19,7 +20,6 @@
 #include <mach/cpu.h>
 #include <mach/at91_dbgu.h>
 #include <mach/at91sam9rl.h>
-#include <mach/at91_pmc.h>
 
 #include "at91_aic.h"
 #include "at91_rstc.h"
index e8a2e075a1b888262077e46457774679d51776e9..3e8ec26e39dcc7404120fab8cbbfb0e168d9fa44 100644 (file)
@@ -8,12 +8,12 @@
 
 #include <linux/module.h>
 #include <linux/dma-mapping.h>
+#include <linux/clk/at91_pmc.h>
 
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <mach/at91sam9x5.h>
-#include <mach/at91_pmc.h>
 #include <mach/cpu.h>
 
 #include "board.h"
index bf00d15d954d3d3f1b6ce1d55ec5840890518fa4..075ec0576adaf8b3d5b234a1aad729cb9aaeced7 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/phy.h>
+#include <linux/clk-provider.h>
 
 #include <asm/setup.h>
 #include <asm/irq.h>
 #include "at91_aic.h"
 #include "generic.h"
 
+static void __init sama5_dt_timer_init(void)
+{
+#if defined(CONFIG_COMMON_CLK)
+       of_clk_init(NULL);
+#endif
+       at91sam926x_pit_init();
+}
 
 static const struct of_device_id irq_of_match[] __initconst = {
 
@@ -72,7 +80,7 @@ static const char *sama5_dt_board_compat[] __initdata = {
 
 DT_MACHINE_START(sama5_dt, "Atmel SAMA5 (Device Tree)")
        /* Maintainer: Atmel */
-       .init_time      = at91sam926x_pit_init,
+       .init_time      = sama5_dt_timer_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic5_handle_irq,
        .init_early     = at91_dt_initialize,
index 6b2630a92f71723644ff7c7242cf6579aa7f4802..72b2579447337a8c650d998ea35eee6205d02721 100644 (file)
@@ -24,9 +24,9 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/of_address.h>
+#include <linux/clk/at91_pmc.h>
 
 #include <mach/hardware.h>
-#include <mach/at91_pmc.h>
 #include <mach/cpu.h>
 
 #include <asm/proc-fns.h>
@@ -884,6 +884,11 @@ static int __init at91_pmc_init(unsigned long main_clock)
 #if defined(CONFIG_OF)
 static struct of_device_id pmc_ids[] = {
        { .compatible = "atmel,at91rm9200-pmc" },
+       { .compatible = "atmel,at91sam9260-pmc" },
+       { .compatible = "atmel,at91sam9g45-pmc" },
+       { .compatible = "atmel,at91sam9n12-pmc" },
+       { .compatible = "atmel,at91sam9x5-pmc" },
+       { .compatible = "atmel,sama5d3-pmc" },
        { /*sentinel*/ }
 };
 
index 26dee3ce9397a0cf41705d0fbafe6ee87b0a9fbc..631fa3b8c16d77be9832f7aa89345e9e7259e94d 100644 (file)
@@ -46,11 +46,12 @@ extern void at91sam926x_pit_init(void);
 extern void at91x40_timer_init(void);
 
  /* Clocks */
-#ifdef CONFIG_AT91_PMC_UNIT
+#ifdef CONFIG_OLD_CLK_AT91
 extern int __init at91_clock_init(unsigned long main_clock);
 extern int __init at91_dt_clock_init(void);
 #else
 static int inline at91_clock_init(unsigned long main_clock) { return 0; }
+static int inline at91_dt_clock_init(void) { return 0; }
 #endif
 struct device;
 
index d3d7b993846bb14103134289643c0fd004ae21ef..86c71debab5b617f11e50f701f7c1d768a232913 100644 (file)
@@ -53,6 +53,7 @@
 #define ARCH_EXID_SAMA5D33     0x00414300
 #define ARCH_EXID_SAMA5D34     0x00414301
 #define ARCH_EXID_SAMA5D35     0x00584300
+#define ARCH_EXID_SAMA5D36     0x00004301
 
 #define ARCH_FAMILY_AT91X92    0x09200000
 #define ARCH_FAMILY_AT91SAM9   0x01900000
@@ -105,7 +106,7 @@ enum at91_soc_subtype {
 
        /* SAMA5D3 */
        AT91_SOC_SAMA5D31, AT91_SOC_SAMA5D33, AT91_SOC_SAMA5D34,
-       AT91_SOC_SAMA5D35,
+       AT91_SOC_SAMA5D35, AT91_SOC_SAMA5D36,
 
        /* No subtype for this SoC */
        AT91_SOC_SUBTYPE_NONE,
index 9986542e8060119fcad4eee37564fdf3d8d164a6..d43b79f56e942e554d65d0d723f28315f3cf5bd1 100644 (file)
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/clk/at91_pmc.h>
 
 #include <asm/irq.h>
 #include <linux/atomic.h>
 #include <asm/mach/time.h>
 #include <asm/mach/irq.h>
 
-#include <mach/at91_pmc.h>
 #include <mach/cpu.h>
 
 #include "at91_aic.h"
index 3ed190ce062bd5add5a426e07b1cf6c5d1e5b89a..c5101dcb4fb04d8d9af68bea524043feb3c289a9 100644 (file)
 #include <mach/at91_ramc.h>
 #include <mach/at91rm9200_sdramc.h>
 
+#ifdef CONFIG_PM
 extern void at91_pm_set_standby(void (*at91_standby)(void));
+#else
+static inline void at91_pm_set_standby(void (*at91_standby)(void)) { }
+#endif
 
 /*
  * The AT91RM9200 goes into self-refresh mode with this command, and will
index 098c28ddf025fb95dfae6530ee547a7aaf76358b..20018779bae7a50db61b75ca8a1e9ebf1858d02d 100644 (file)
@@ -13,8 +13,8 @@
  */
 
 #include <linux/linkage.h>
+#include <linux/clk/at91_pmc.h>
 #include <mach/hardware.h>
-#include <mach/at91_pmc.h>
 #include <mach/at91_ramc.h>
 
 
index 3ea86428ee0964f11d0955a90d0348626e68da58..3d775d08de08def15011e449bca421fe19dc0f95 100644 (file)
 
 #include <linux/module.h>
 #include <linux/dma-mapping.h>
+#include <linux/clk/at91_pmc.h>
 
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <mach/sama5d3.h>
-#include <mach/at91_pmc.h>
 #include <mach/cpu.h>
 
 #include "soc.h"
 #include "generic.h"
-#include "clock.h"
 #include "sam9_smc.h"
 
-/* --------------------------------------------------------------------
- *  Clocks
- * -------------------------------------------------------------------- */
-
-/*
- * The peripheral clocks.
- */
-
-static struct clk pioA_clk = {
-       .name           = "pioA_clk",
-       .pid            = SAMA5D3_ID_PIOA,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk pioB_clk = {
-       .name           = "pioB_clk",
-       .pid            = SAMA5D3_ID_PIOB,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk pioC_clk = {
-       .name           = "pioC_clk",
-       .pid            = SAMA5D3_ID_PIOC,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk pioD_clk = {
-       .name           = "pioD_clk",
-       .pid            = SAMA5D3_ID_PIOD,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk pioE_clk = {
-       .name           = "pioE_clk",
-       .pid            = SAMA5D3_ID_PIOE,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart0_clk = {
-       .name           = "usart0_clk",
-       .pid            = SAMA5D3_ID_USART0,
-       .type           = CLK_TYPE_PERIPHERAL,
-       .div            = AT91_PMC_PCR_DIV2,
-};
-static struct clk usart1_clk = {
-       .name           = "usart1_clk",
-       .pid            = SAMA5D3_ID_USART1,
-       .type           = CLK_TYPE_PERIPHERAL,
-       .div            = AT91_PMC_PCR_DIV2,
-};
-static struct clk usart2_clk = {
-       .name           = "usart2_clk",
-       .pid            = SAMA5D3_ID_USART2,
-       .type           = CLK_TYPE_PERIPHERAL,
-       .div            = AT91_PMC_PCR_DIV2,
-};
-static struct clk usart3_clk = {
-       .name           = "usart3_clk",
-       .pid            = SAMA5D3_ID_USART3,
-       .type           = CLK_TYPE_PERIPHERAL,
-       .div            = AT91_PMC_PCR_DIV2,
-};
-static struct clk uart0_clk = {
-       .name           = "uart0_clk",
-       .pid            = SAMA5D3_ID_UART0,
-       .type           = CLK_TYPE_PERIPHERAL,
-       .div            = AT91_PMC_PCR_DIV2,
-};
-static struct clk uart1_clk = {
-       .name           = "uart1_clk",
-       .pid            = SAMA5D3_ID_UART1,
-       .type           = CLK_TYPE_PERIPHERAL,
-       .div            = AT91_PMC_PCR_DIV2,
-};
-static struct clk twi0_clk = {
-       .name           = "twi0_clk",
-       .pid            = SAMA5D3_ID_TWI0,
-       .type           = CLK_TYPE_PERIPHERAL,
-       .div            = AT91_PMC_PCR_DIV2,
-};
-static struct clk twi1_clk = {
-       .name           = "twi1_clk",
-       .pid            = SAMA5D3_ID_TWI1,
-       .type           = CLK_TYPE_PERIPHERAL,
-       .div            = AT91_PMC_PCR_DIV2,
-};
-static struct clk twi2_clk = {
-       .name           = "twi2_clk",
-       .pid            = SAMA5D3_ID_TWI2,
-       .type           = CLK_TYPE_PERIPHERAL,
-       .div            = AT91_PMC_PCR_DIV2,
-};
-static struct clk mmc0_clk = {
-       .name           = "mci0_clk",
-       .pid            = SAMA5D3_ID_HSMCI0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk mmc1_clk = {
-       .name           = "mci1_clk",
-       .pid            = SAMA5D3_ID_HSMCI1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk mmc2_clk = {
-       .name           = "mci2_clk",
-       .pid            = SAMA5D3_ID_HSMCI2,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk spi0_clk = {
-       .name           = "spi0_clk",
-       .pid            = SAMA5D3_ID_SPI0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk spi1_clk = {
-       .name           = "spi1_clk",
-       .pid            = SAMA5D3_ID_SPI1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk tcb0_clk = {
-       .name           = "tcb0_clk",
-       .pid            = SAMA5D3_ID_TC0,
-       .type           = CLK_TYPE_PERIPHERAL,
-       .div            = AT91_PMC_PCR_DIV2,
-};
-static struct clk tcb1_clk = {
-       .name           = "tcb1_clk",
-       .pid            = SAMA5D3_ID_TC1,
-       .type           = CLK_TYPE_PERIPHERAL,
-       .div            = AT91_PMC_PCR_DIV2,
-};
-static struct clk adc_clk = {
-       .name           = "adc_clk",
-       .pid            = SAMA5D3_ID_ADC,
-       .type           = CLK_TYPE_PERIPHERAL,
-       .div            = AT91_PMC_PCR_DIV2,
-};
-static struct clk adc_op_clk = {
-       .name           = "adc_op_clk",
-       .type           = CLK_TYPE_PERIPHERAL,
-       .rate_hz        = 5000000,
-};
-static struct clk dma0_clk = {
-       .name           = "dma0_clk",
-       .pid            = SAMA5D3_ID_DMA0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk dma1_clk = {
-       .name           = "dma1_clk",
-       .pid            = SAMA5D3_ID_DMA1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk uhphs_clk = {
-       .name           = "uhphs",
-       .pid            = SAMA5D3_ID_UHPHS,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk udphs_clk = {
-       .name           = "udphs_clk",
-       .pid            = SAMA5D3_ID_UDPHS,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-/* gmac only for sama5d33, sama5d34, sama5d35 */
-static struct clk macb0_clk = {
-       .name           = "macb0_clk",
-       .pid            = SAMA5D3_ID_GMAC,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-/* emac only for sama5d31, sama5d35 */
-static struct clk macb1_clk = {
-       .name           = "macb1_clk",
-       .pid            = SAMA5D3_ID_EMAC,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-/* lcd only for sama5d31, sama5d33, sama5d34 */
-static struct clk lcdc_clk = {
-       .name           = "lcdc_clk",
-       .pid            = SAMA5D3_ID_LCDC,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-/* isi only for sama5d33, sama5d35 */
-static struct clk isi_clk = {
-       .name           = "isi_clk",
-       .pid            = SAMA5D3_ID_ISI,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk can0_clk = {
-       .name           = "can0_clk",
-       .pid            = SAMA5D3_ID_CAN0,
-       .type           = CLK_TYPE_PERIPHERAL,
-       .div            = AT91_PMC_PCR_DIV2,
-};
-static struct clk can1_clk = {
-       .name           = "can1_clk",
-       .pid            = SAMA5D3_ID_CAN1,
-       .type           = CLK_TYPE_PERIPHERAL,
-       .div            = AT91_PMC_PCR_DIV2,
-};
-static struct clk ssc0_clk = {
-       .name           = "ssc0_clk",
-       .pid            = SAMA5D3_ID_SSC0,
-       .type           = CLK_TYPE_PERIPHERAL,
-       .div            = AT91_PMC_PCR_DIV2,
-};
-static struct clk ssc1_clk = {
-       .name           = "ssc1_clk",
-       .pid            = SAMA5D3_ID_SSC1,
-       .type           = CLK_TYPE_PERIPHERAL,
-       .div            = AT91_PMC_PCR_DIV2,
-};
-static struct clk sha_clk = {
-       .name           = "sha_clk",
-       .pid            = SAMA5D3_ID_SHA,
-       .type           = CLK_TYPE_PERIPHERAL,
-       .div            = AT91_PMC_PCR_DIV8,
-};
-static struct clk aes_clk = {
-       .name           = "aes_clk",
-       .pid            = SAMA5D3_ID_AES,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk tdes_clk = {
-       .name           = "tdes_clk",
-       .pid            = SAMA5D3_ID_TDES,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-
-static struct clk *periph_clocks[] __initdata = {
-       &pioA_clk,
-       &pioB_clk,
-       &pioC_clk,
-       &pioD_clk,
-       &pioE_clk,
-       &usart0_clk,
-       &usart1_clk,
-       &usart2_clk,
-       &usart3_clk,
-       &uart0_clk,
-       &uart1_clk,
-       &twi0_clk,
-       &twi1_clk,
-       &twi2_clk,
-       &mmc0_clk,
-       &mmc1_clk,
-       &mmc2_clk,
-       &spi0_clk,
-       &spi1_clk,
-       &tcb0_clk,
-       &tcb1_clk,
-       &adc_clk,
-       &adc_op_clk,
-       &dma0_clk,
-       &dma1_clk,
-       &uhphs_clk,
-       &udphs_clk,
-       &macb0_clk,
-       &macb1_clk,
-       &lcdc_clk,
-       &isi_clk,
-       &can0_clk,
-       &can1_clk,
-       &ssc0_clk,
-       &ssc1_clk,
-       &sha_clk,
-       &aes_clk,
-       &tdes_clk,
-};
-
-static struct clk pck0 = {
-       .name           = "pck0",
-       .pmc_mask       = AT91_PMC_PCK0,
-       .type           = CLK_TYPE_PROGRAMMABLE,
-       .id             = 0,
-};
-
-static struct clk pck1 = {
-       .name           = "pck1",
-       .pmc_mask       = AT91_PMC_PCK1,
-       .type           = CLK_TYPE_PROGRAMMABLE,
-       .id             = 1,
-};
-
-static struct clk pck2 = {
-       .name           = "pck2",
-       .pmc_mask       = AT91_PMC_PCK2,
-       .type           = CLK_TYPE_PROGRAMMABLE,
-       .id             = 2,
-};
-
-static struct clk_lookup periph_clocks_lookups[] = {
-       /* lookup table for DT entries */
-       CLKDEV_CON_DEV_ID("usart", "ffffee00.serial", &mck),
-       CLKDEV_CON_DEV_ID(NULL, "fffff200.gpio", &pioA_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioB_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioC_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioD_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffffa00.gpio", &pioE_clk),
-       CLKDEV_CON_DEV_ID("usart", "f001c000.serial", &usart0_clk),
-       CLKDEV_CON_DEV_ID("usart", "f0020000.serial", &usart1_clk),
-       CLKDEV_CON_DEV_ID("usart", "f8020000.serial", &usart2_clk),
-       CLKDEV_CON_DEV_ID("usart", "f8024000.serial", &usart3_clk),
-       CLKDEV_CON_DEV_ID(NULL, "f0014000.i2c", &twi0_clk),
-       CLKDEV_CON_DEV_ID(NULL, "f0018000.i2c", &twi1_clk),
-       CLKDEV_CON_DEV_ID(NULL, "f801c000.i2c", &twi2_clk),
-       CLKDEV_CON_DEV_ID("mci_clk", "f0000000.mmc", &mmc0_clk),
-       CLKDEV_CON_DEV_ID("mci_clk", "f8000000.mmc", &mmc1_clk),
-       CLKDEV_CON_DEV_ID("mci_clk", "f8004000.mmc", &mmc2_clk),
-       CLKDEV_CON_DEV_ID("spi_clk", "f0004000.spi", &spi0_clk),
-       CLKDEV_CON_DEV_ID("spi_clk", "f8008000.spi", &spi1_clk),
-       CLKDEV_CON_DEV_ID("t0_clk", "f0010000.timer", &tcb0_clk),
-       CLKDEV_CON_DEV_ID("t0_clk", "f8014000.timer", &tcb1_clk),
-       CLKDEV_CON_DEV_ID("tsc_clk", "f8018000.tsadcc", &adc_clk),
-       CLKDEV_CON_DEV_ID("dma_clk", "ffffe600.dma-controller", &dma0_clk),
-       CLKDEV_CON_DEV_ID("dma_clk", "ffffe800.dma-controller", &dma1_clk),
-       CLKDEV_CON_DEV_ID("hclk", "600000.ohci", &uhphs_clk),
-       CLKDEV_CON_DEV_ID("ohci_clk", "600000.ohci", &uhphs_clk),
-       CLKDEV_CON_DEV_ID("ehci_clk", "700000.ehci", &uhphs_clk),
-       CLKDEV_CON_DEV_ID("pclk", "500000.gadget", &udphs_clk),
-       CLKDEV_CON_DEV_ID("hclk", "500000.gadget", &utmi_clk),
-       CLKDEV_CON_DEV_ID("hclk", "f0028000.ethernet", &macb0_clk),
-       CLKDEV_CON_DEV_ID("pclk", "f0028000.ethernet", &macb0_clk),
-       CLKDEV_CON_DEV_ID("hclk", "f802c000.ethernet", &macb1_clk),
-       CLKDEV_CON_DEV_ID("pclk", "f802c000.ethernet", &macb1_clk),
-       CLKDEV_CON_DEV_ID("pclk", "f0008000.ssc", &ssc0_clk),
-       CLKDEV_CON_DEV_ID("pclk", "f000c000.ssc", &ssc1_clk),
-       CLKDEV_CON_DEV_ID("can_clk", "f000c000.can", &can0_clk),
-       CLKDEV_CON_DEV_ID("can_clk", "f8010000.can", &can1_clk),
-       CLKDEV_CON_DEV_ID("sha_clk", "f8034000.sha", &sha_clk),
-       CLKDEV_CON_DEV_ID("aes_clk", "f8038000.aes", &aes_clk),
-       CLKDEV_CON_DEV_ID("tdes_clk", "f803c000.tdes", &tdes_clk),
-};
-
-static void __init sama5d3_register_clocks(void)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
-               clk_register(periph_clocks[i]);
-
-       clkdev_add_table(periph_clocks_lookups,
-                        ARRAY_SIZE(periph_clocks_lookups));
-
-       clk_register(&pck0);
-       clk_register(&pck1);
-       clk_register(&pck2);
-}
-
 /* --------------------------------------------------------------------
  *  AT91SAM9x5 processor initialization
  * -------------------------------------------------------------------- */
@@ -378,6 +37,5 @@ static void __init sama5d3_initialize(void)
 
 AT91_SOC_START(sama5d3)
        .map_io = sama5d3_map_io,
-       .register_clocks = sama5d3_register_clocks,
        .init = sama5d3_initialize,
 AT91_SOC_END
index 094b3459c288e37700c42ea85a57ced905323eda..f7ca97b7291e2f9b48a2968f47bc92e788ff79cf 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/pm.h>
 #include <linux/of_address.h>
 #include <linux/pinctrl/machine.h>
+#include <linux/clk/at91_pmc.h>
 
 #include <asm/system_misc.h>
 #include <asm/mach/map.h>
@@ -18,7 +19,6 @@
 #include <mach/hardware.h>
 #include <mach/cpu.h>
 #include <mach/at91_dbgu.h>
-#include <mach/at91_pmc.h>
 
 #include "at91_shdwc.h"
 #include "soc.h"
@@ -81,7 +81,7 @@ void __init at91_init_sram(int bank, unsigned long base, unsigned int length)
 
        desc->pfn = __phys_to_pfn(base);
        desc->length = length;
-       desc->type = MT_MEMORY_NONCACHED;
+       desc->type = MT_MEMORY_RWX_NONCACHED;
 
        pr_info("AT91: sram at 0x%lx of 0x%x mapped at 0x%lx\n",
                base, length, desc->virtual);
@@ -233,6 +233,9 @@ static void __init soc_detect(u32 dbgu_base)
                case ARCH_EXID_SAMA5D35:
                        at91_soc_initdata.subtype = AT91_SOC_SAMA5D35;
                        break;
+               case ARCH_EXID_SAMA5D36:
+                       at91_soc_initdata.subtype = AT91_SOC_SAMA5D36;
+                       break;
                }
        }
 }
@@ -275,6 +278,7 @@ static const char *soc_subtype_name[] = {
        [AT91_SOC_SAMA5D33]     = "sama5d33",
        [AT91_SOC_SAMA5D34]     = "sama5d34",
        [AT91_SOC_SAMA5D35]     = "sama5d35",
+       [AT91_SOC_SAMA5D36]     = "sama5d36",
        [AT91_SOC_SUBTYPE_NONE] = "None",
        [AT91_SOC_SUBTYPE_UNKNOWN] = "Unknown",
 };
@@ -491,7 +495,8 @@ void __init at91rm9200_dt_initialize(void)
        at91_dt_clock_init();
 
        /* Register the processor-specific clocks */
-       at91_boot_soc.register_clocks();
+       if (at91_boot_soc.register_clocks)
+               at91_boot_soc.register_clocks();
 
        at91_boot_soc.init();
 }
@@ -506,7 +511,8 @@ void __init at91_dt_initialize(void)
        at91_dt_clock_init();
 
        /* Register the processor-specific clocks */
-       at91_boot_soc.register_clocks();
+       if (at91_boot_soc.register_clocks)
+               at91_boot_soc.register_clocks();
 
        if (at91_boot_soc.init)
                at91_boot_soc.init();
index 560045cafc3417c4fe8aba877ff7d233a4fbf949..d1f9612f8c1544bebd7ffc9a19001e73cbcfdd05 100644 (file)
@@ -12,4 +12,4 @@ config ARCH_BCM2835
        select PINCTRL_BCM2835
        help
          This enables support for the Broadcom BCM2835 SoC. This SoC is
-         use in the Raspberry Pi, and Roku 2 devices.
+         used in the Raspberry Pi and Roku 2 devices.
index 134641d688bb12f201dd2d0cedcd166890a8ce71..a1935911e4f19ffd1a62080241470a6651cc2c10 100644 (file)
@@ -259,7 +259,7 @@ asmlinkage void __exception_irq_entry clps711x_handle_irq(struct pt_regs *regs)
        } while (1);
 }
 
-static u32 notrace clps711x_sched_clock_read(void)
+static u64 notrace clps711x_sched_clock_read(void)
 {
        return ~readw_relaxed(CLPS711X_VIRT_BASE + TC1D);
 }
@@ -366,7 +366,7 @@ void __init clps711x_timer_init(void)
        tmp = clps_readl(SYSCON1) & ~(SYSCON1_TC1S | SYSCON1_TC1M);
        clps_writel(tmp, SYSCON1);
 
-       setup_sched_clock(clps711x_sched_clock_read, 16, timl);
+       sched_clock_register(clps711x_sched_clock_read, 16, timl);
 
        clocksource_mmio_init(CLPS711X_VIRT_BASE + TC1D,
                              "clps711x_clocksource", timl, 300, 16,
index c46eccbbd51226f5ae6ab5a16e1c89668c35fa1d..78829c513fdc354bce631d67f45922efff84368d 100644 (file)
@@ -487,7 +487,7 @@ int __init da8xx_register_emac(void)
 
 static struct resource da830_mcasp1_resources[] = {
        {
-               .name   = "mcasp1",
+               .name   = "mpu",
                .start  = DAVINCI_DA830_MCASP1_REG_BASE,
                .end    = DAVINCI_DA830_MCASP1_REG_BASE + (SZ_1K * 12) - 1,
                .flags  = IORESOURCE_MEM,
@@ -515,7 +515,7 @@ static struct platform_device da830_mcasp1_device = {
 
 static struct resource da850_mcasp_resources[] = {
        {
-               .name   = "mcasp",
+               .name   = "mpu",
                .start  = DAVINCI_DA8XX_MCASP0_REG_BASE,
                .end    = DAVINCI_DA8XX_MCASP0_REG_BASE + (SZ_1K * 12) - 1,
                .flags  = IORESOURCE_MEM,
index ef9ff1fb6f52a2533378ba37563c06e877b32ea3..6117fc644188d9aa81c2397dbb60538db190beea 100644 (file)
@@ -641,6 +641,7 @@ static struct platform_device dm355_edma_device = {
 
 static struct resource dm355_asp1_resources[] = {
        {
+               .name   = "mpu",
                .start  = DAVINCI_ASP1_BASE,
                .end    = DAVINCI_ASP1_BASE + SZ_8K - 1,
                .flags  = IORESOURCE_MEM,
@@ -906,7 +907,7 @@ static struct davinci_gpio_platform_data dm355_gpio_platform_data = {
 int __init dm355_gpio_register(void)
 {
        return davinci_gpio_register(dm355_gpio_resources,
-                                    sizeof(dm355_gpio_resources),
+                                    ARRAY_SIZE(dm355_gpio_resources),
                                     &dm355_gpio_platform_data);
 }
 /*----------------------------------------------------------------------*/
index 1511a0680f9a1d399cf3094b538c3c52caa06547..d7c6f85d3fc9d5c4347ec214ae8e71a310f89b62 100644 (file)
@@ -720,7 +720,7 @@ static struct davinci_gpio_platform_data dm365_gpio_platform_data = {
 int __init dm365_gpio_register(void)
 {
        return davinci_gpio_register(dm365_gpio_resources,
-                                    sizeof(dm365_gpio_resources),
+                                    ARRAY_SIZE(dm365_gpio_resources),
                                     &dm365_gpio_platform_data);
 }
 
@@ -942,6 +942,7 @@ static struct platform_device dm365_edma_device = {
 
 static struct resource dm365_asp_resources[] = {
        {
+               .name   = "mpu",
                .start  = DAVINCI_DM365_ASP0_BASE,
                .end    = DAVINCI_DM365_ASP0_BASE + SZ_8K - 1,
                .flags  = IORESOURCE_MEM,
index 143a3217e8efb8fde1aa417700c45840d242aac0..3ce47997bb46150e82f40e718474feeae52b6d5e 100644 (file)
@@ -572,6 +572,7 @@ static struct platform_device dm644x_edma_device = {
 /* DM6446 EVM uses ASP0; line-out is a pair of RCA jacks */
 static struct resource dm644x_asp_resources[] = {
        {
+               .name   = "mpu",
                .start  = DAVINCI_ASP0_BASE,
                .end    = DAVINCI_ASP0_BASE + SZ_8K - 1,
                .flags  = IORESOURCE_MEM,
@@ -792,7 +793,7 @@ static struct davinci_gpio_platform_data dm644_gpio_platform_data = {
 int __init dm644x_gpio_register(void)
 {
        return davinci_gpio_register(dm644_gpio_resources,
-                                    sizeof(dm644_gpio_resources),
+                                    ARRAY_SIZE(dm644_gpio_resources),
                                     &dm644_gpio_platform_data);
 }
 /*----------------------------------------------------------------------*/
index 2a73f299c1d094615236359d6ac27959cdd16295..0e81fea65e7fb484cda893f0a4cd91d0b74fc0ad 100644 (file)
@@ -621,7 +621,7 @@ static struct platform_device dm646x_edma_device = {
 
 static struct resource dm646x_mcasp0_resources[] = {
        {
-               .name   = "mcasp0",
+               .name   = "mpu",
                .start  = DAVINCI_DM646X_MCASP0_REG_BASE,
                .end    = DAVINCI_DM646X_MCASP0_REG_BASE + (SZ_1K << 1) - 1,
                .flags  = IORESOURCE_MEM,
@@ -641,7 +641,7 @@ static struct resource dm646x_mcasp0_resources[] = {
 
 static struct resource dm646x_mcasp1_resources[] = {
        {
-               .name   = "mcasp1",
+               .name   = "mpu",
                .start  = DAVINCI_DM646X_MCASP1_REG_BASE,
                .end    = DAVINCI_DM646X_MCASP1_REG_BASE + (SZ_1K << 1) - 1,
                .flags  = IORESOURCE_MEM,
@@ -769,7 +769,7 @@ static struct davinci_gpio_platform_data dm646x_gpio_platform_data = {
 int __init dm646x_gpio_register(void)
 {
        return davinci_gpio_register(dm646x_gpio_resources,
-                                    sizeof(dm646x_gpio_resources),
+                                    ARRAY_SIZE(dm646x_gpio_resources),
                                     &dm646x_gpio_platform_data);
 }
 /*----------------------------------------------------------------------*/
index 56c6eb5266adf8f5c18629db9cfb65018f5bad50..24ad30f32ae327d8e8bd0bb3056232ab78e66da0 100644 (file)
@@ -285,7 +285,7 @@ static struct clocksource clocksource_davinci = {
 /*
  * Overwrite weak default sched_clock with something more precise
  */
-static u32 notrace davinci_read_sched_clock(void)
+static u64 notrace davinci_read_sched_clock(void)
 {
        return timer32_read(&timers[TID_CLOCKSOURCE]);
 }
@@ -391,7 +391,7 @@ void __init davinci_timer_init(void)
                                    davinci_clock_tick_rate))
                printk(err, clocksource_davinci.name);
 
-       setup_sched_clock(davinci_read_sched_clock, 32,
+       sched_clock_register(davinci_read_sched_clock, 32,
                          davinci_clock_tick_rate);
 
        /* setup clockevent */
index c122bcff9f7c91647a3251266348bef2c531a12b..0d1a89298ece95518c43e07c2c32aa0b15147c69 100644 (file)
@@ -162,7 +162,7 @@ void __init dove_ge00_init(struct mv643xx_eth_platform_data *eth_data)
 /*****************************************************************************
  * SoC RTC
  ****************************************************************************/
-void __init dove_rtc_init(void)
+static void __init dove_rtc_init(void)
 {
        orion_rtc_init(DOVE_RTC_PHYS_BASE, IRQ_DOVE_RTC);
 }
@@ -256,19 +256,10 @@ void __init dove_timer_init(void)
                        IRQ_DOVE_BRIDGE, dove_tclk);
 }
 
-/*****************************************************************************
- * Cryptographic Engines and Security Accelerator (CESA)
- ****************************************************************************/
-void __init dove_crypto_init(void)
-{
-       orion_crypto_init(DOVE_CRYPT_PHYS_BASE, DOVE_CESA_PHYS_BASE,
-                         DOVE_CESA_SIZE, IRQ_DOVE_CRYPTO);
-}
-
 /*****************************************************************************
  * XOR 0
  ****************************************************************************/
-void __init dove_xor0_init(void)
+static void __init dove_xor0_init(void)
 {
        orion_xor0_init(DOVE_XOR0_PHYS_BASE, DOVE_XOR0_HIGH_PHYS_BASE,
                        IRQ_DOVE_XOR_00, IRQ_DOVE_XOR_01);
@@ -277,7 +268,7 @@ void __init dove_xor0_init(void)
 /*****************************************************************************
  * XOR 1
  ****************************************************************************/
-void __init dove_xor1_init(void)
+static void __init dove_xor1_init(void)
 {
        orion_xor1_init(DOVE_XOR1_PHYS_BASE, DOVE_XOR1_HIGH_PHYS_BASE,
                        IRQ_DOVE_XOR_10, IRQ_DOVE_XOR_11);
index 93e54fd4e3d55900192f62e573d6d97a2919aa4b..bec570ae6494d0bfacd8b479ee9876fbc61dbfeb 100644 (file)
@@ -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
index d95ee28a616a3ed53c776dda2df2fa5da6f229f1..157ba88433c949c1db4595400cfbea3cc29a5c47 100644 (file)
@@ -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>
@@ -44,6 +45,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>
 
@@ -137,7 +139,7 @@ static irqreturn_t ep93xx_timer_interrupt(int irq, void *dev_id)
 
 static struct irqaction ep93xx_timer_irq = {
        .name           = "ep93xx timer",
-       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+       .flags          = IRQF_TIMER | IRQF_IRQPOLL,
        .handler        = ep93xx_timer_interrupt,
 };
 
@@ -925,8 +927,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);
 
@@ -937,6 +1039,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);
 
@@ -949,6 +1053,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)
index e256e0baec2ec729344333d198004a637f20123f..4c0bbd97f741c7a6ab90de0260a77e9c4877fb82 100644 (file)
@@ -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 *);
index 2739ca2c13346f1ed4bdce26916ae4e2270900ad..e0091685fd4861c8eb6f41b00c5f316865c1668b 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/spinlock.h>
+#include <video/vga.h>
 
 #include <asm/pgtable.h>
 #include <asm/page.h>
@@ -196,6 +197,8 @@ void __init footbridge_map_io(void)
                iotable_init(ebsa285_host_io_desc, ARRAY_SIZE(ebsa285_host_io_desc));
                pci_map_io_early(__phys_to_pfn(DC21285_PCI_IO));
        }
+
+       vga_base = PCIMEM_BASE;
 }
 
 void footbridge_restart(enum reboot_mode mode, const char *cmd)
index 3490a24f969e4a0b450ef146cee72f37e1cb6c9f..7c2fdae9a38b63454523277a005dcf6c5c1c65ab 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/spinlock.h>
-#include <video/vga.h>
 
 #include <asm/irq.h>
 #include <asm/mach/pci.h>
@@ -291,7 +290,6 @@ void __init dc21285_preinit(void)
        int cfn_mode;
 
        pcibios_min_mem = 0x81000000;
-       vga_base = PCIMEM_BASE;
 
        mem_size = (unsigned int)high_memory - PAGE_OFFSET;
        for (mem_mask = 0x00100000; mem_mask < 0x10000000; mem_mask <<= 1)
index b08243500e2e9bc8f7196d6e6c5484b3ba7dadb4..1a7235fb52acb3cb8ae784dbeeda4fb3c940594a 100644 (file)
@@ -30,21 +30,24 @@ static const struct {
        const char *name;
        const char *trigger;
 } ebsa285_leds[] = {
-       { "ebsa285:amber", "heartbeat", },
-       { "ebsa285:green", "cpu0", },
+       { "ebsa285:amber", "cpu0", },
+       { "ebsa285:green", "heartbeat", },
        { "ebsa285:red",},
 };
 
+static unsigned char hw_led_state;
+
 static void ebsa285_led_set(struct led_classdev *cdev,
                enum led_brightness b)
 {
        struct ebsa285_led *led = container_of(cdev,
                        struct ebsa285_led, cdev);
 
-       if (b != LED_OFF)
-               *XBUS_LEDS |= led->mask;
+       if (b == LED_OFF)
+               hw_led_state |= led->mask;
        else
-               *XBUS_LEDS &= ~led->mask;
+               hw_led_state &= ~led->mask;
+       *XBUS_LEDS = hw_led_state;
 }
 
 static enum led_brightness ebsa285_led_get(struct led_classdev *cdev)
@@ -52,18 +55,19 @@ static enum led_brightness ebsa285_led_get(struct led_classdev *cdev)
        struct ebsa285_led *led = container_of(cdev,
                        struct ebsa285_led, cdev);
 
-       return (*XBUS_LEDS & led->mask) ? LED_FULL : LED_OFF;
+       return hw_led_state & led->mask ? LED_OFF : LED_FULL;
 }
 
 static int __init ebsa285_leds_init(void)
 {
        int i;
 
-       if (machine_is_ebsa285())
+       if (!machine_is_ebsa285())
                return -ENODEV;
 
-       /* 3 LEDS All ON */
-       *XBUS_LEDS |= XBUS_LED_AMBER | XBUS_LED_GREEN | XBUS_LED_RED;
+       /* 3 LEDS all off */
+       hw_led_state = XBUS_LED_AMBER | XBUS_LED_GREEN | XBUS_LED_RED;
+       *XBUS_LEDS = hw_led_state;
 
        for (i = 0; i < ARRAY_SIZE(ebsa285_leds); i++) {
                struct ebsa285_led *led;
index b3d7e5634b83cb02ce568040099027007820a45b..bd3bf66ce3449a31c9c7c9f56be6b4225ee9cbf9 100644 (file)
 #include <linux/clkdev.h>
 #include <linux/clocksource.h>
 #include <linux/dma-mapping.h>
+#include <linux/input.h>
 #include <linux/io.h>
 #include <linux/irqchip.h>
+#include <linux/mailbox.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/of_address.h>
+#include <linux/reboot.h>
 #include <linux/amba/bus.h>
 #include <linux/platform_device.h>
 
@@ -130,6 +133,24 @@ static struct platform_device highbank_cpuidle_device = {
        .name = "cpuidle-calxeda",
 };
 
+static int hb_keys_notifier(struct notifier_block *nb, unsigned long event, void *data)
+{
+       u32 key = *(u32 *)data;
+
+       if (event != 0x1000)
+               return 0;
+
+       if (key == KEY_POWER)
+               orderly_poweroff(false);
+       else if (key == 0xffff)
+               ctrl_alt_del();
+
+       return 0;
+}
+static struct notifier_block hb_keys_nb = {
+       .notifier_call = hb_keys_notifier,
+};
+
 static void __init highbank_init(void)
 {
        struct device_node *np;
@@ -145,6 +166,8 @@ static void __init highbank_init(void)
        bus_register_notifier(&platform_bus_type, &highbank_platform_nb);
        bus_register_notifier(&amba_bustype, &highbank_amba_nb);
 
+       pl320_ipc_register_notifier(&hb_keys_nb);
+
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 
        if (psci_ops.cpu_suspend)
index 7a6e6f71006893a9c2a54d4a17166762c4647977..d511e05465466b3d11dff8f21f4b2175b36cf3fd 100644 (file)
@@ -11,6 +11,7 @@ config ARCH_MXC
        select GENERIC_IRQ_CHIP
        select MIGHT_HAVE_CACHE_L2X0 if ARCH_MULTI_V6_V7
        select MULTI_IRQ_HANDLER
+       select PINCTRL
        select SOC_BUS
        select SPARSE_IRQ
        select USE_OF
@@ -20,16 +21,6 @@ config ARCH_MXC
 menu "Freescale i.MX support"
        depends on ARCH_MXC
 
-config MXC_IRQ_PRIOR
-       bool "Use IRQ priority"
-       help
-         Select this if you want to use prioritized IRQ handling.
-         This feature prevents higher priority ISR to be interrupted
-         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.
-
 config MXC_TZIC
        bool
 
@@ -109,6 +100,7 @@ config SOC_IMX25
        select ARCH_MXC_IOMUX_V3
        select CPU_ARM926T
        select MXC_AVIC
+       select PINCTRL_IMX25
 
 config SOC_IMX27
        bool
@@ -118,6 +110,7 @@ config SOC_IMX27
        select IMX_HAVE_IOMUX_V1
        select MACH_MX27
        select MXC_AVIC
+       select PINCTRL_IMX27
 
 config SOC_IMX31
        bool
@@ -145,7 +138,6 @@ config SOC_IMX5
 config SOC_IMX51
        bool
        select HAVE_IMX_SRC
-       select PINCTRL
        select PINCTRL_IMX51
        select SOC_IMX5
 
@@ -766,11 +758,19 @@ endchoice
 
 comment "Device tree only"
 
+config SOC_IMX50
+       bool "i.MX50 support"
+       select HAVE_IMX_SRC
+       select PINCTRL_IMX50
+       select SOC_IMX5
+
+       help
+         This enables support for Freescale i.MX50 processor.
+
 config SOC_IMX53
        bool "i.MX53 support"
        select HAVE_IMX_SRC
        select IMX_HAVE_PLATFORM_IMX2_WDT
-       select PINCTRL
        select PINCTRL_IMX53
        select SOC_IMX5
 
@@ -796,7 +796,6 @@ config SOC_IMX6Q
        select MFD_SYSCON
        select MIGHT_HAVE_PCI
        select PCI_DOMAINS if PCI
-       select PINCTRL
        select PINCTRL_IMX6Q
        select PL310_ERRATA_588369 if CACHE_PL310
        select PL310_ERRATA_727915 if CACHE_PL310
@@ -817,7 +816,6 @@ config SOC_IMX6SL
        select HAVE_IMX_MMDC
        select HAVE_IMX_SRC
        select MFD_SYSCON
-       select PINCTRL
        select PINCTRL_IMX6SL
        select PL310_ERRATA_588369 if CACHE_PL310
        select PL310_ERRATA_727915 if CACHE_PL310
@@ -831,7 +829,6 @@ config SOC_VF610
        select CPU_V7
        select ARM_GIC
        select CLKSRC_OF
-       select PINCTRL
        select PINCTRL_VF610
        select VF_PIT_TIMER
        select PL310_ERRATA_588369 if CACHE_PL310
index 1789e2b3190389f287a4ce79a747b17c1072a48d..0db16972839630f8c47fa7987f547bc66f1a9091 100644 (file)
@@ -112,6 +112,7 @@ obj-$(CONFIG_MACH_EUKREA_CPUIMX51SD) += mach-cpuimx51sd.o
 obj-$(CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD) += eukrea_mbimxsd51-baseboard.o
 
 obj-$(CONFIG_MACH_IMX51_DT) += imx51-dt.o
+obj-$(CONFIG_SOC_IMX50) += mach-imx50.o
 obj-$(CONFIG_SOC_IMX53) += mach-imx53.o
 
 obj-$(CONFIG_SOC_VF610) += clk-vf610.o mach-vf610.o
index e163ec7a8441170151493adc38146dadf4115b39..8d1df2e4b7ac23a5bea5a101342bd8fa313686b7 100644 (file)
 static void __iomem *avic_base;
 static struct irq_domain *domain;
 
-#ifdef CONFIG_MXC_IRQ_PRIOR
-static int avic_irq_set_priority(unsigned char irq, unsigned char prio)
-{
-       struct irq_data *d = irq_get_irq_data(irq);
-       unsigned int temp;
-       unsigned int mask = 0x0F << irq % 8 * 4;
-
-       irq = d->hwirq;
-
-       if (irq >= AVIC_NUM_IRQS)
-               return -EINVAL;
-
-       temp = __raw_readl(avic_base + AVIC_NIPRIORITY(irq / 8));
-       temp &= ~mask;
-       temp |= prio & mask;
-
-       __raw_writel(temp, avic_base + AVIC_NIPRIORITY(irq / 8));
-
-       return 0;
-}
-#endif
-
 #ifdef CONFIG_FIQ
 static int avic_set_irq_fiq(unsigned int irq, unsigned int type)
 {
@@ -102,9 +80,6 @@ static int avic_set_irq_fiq(unsigned int irq, unsigned int type)
 
 
 static struct mxc_extra_irq avic_extra_irq = {
-#ifdef CONFIG_MXC_IRQ_PRIOR
-       .set_priority = avic_irq_set_priority,
-#endif
 #ifdef CONFIG_FIQ
        .set_irq_fiq = avic_set_irq_fiq,
 #endif
index ce37af26ff8c6931b62e9459d7ffb7df1daf81ab..19fca1fdc6feb76f0e86805ec7d5c980b716c515 100644 (file)
 #include <linux/io.h>
 #include <linux/clkdev.h>
 #include <linux/clk-provider.h>
-#include <linux/of.h>
 #include <linux/err.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
+#include <dt-bindings/clock/imx5-clock.h>
 
 #include "crm-regs-imx5.h"
 #include "clk.h"
@@ -83,50 +83,7 @@ static const char *spdif_sel[] = { "pll1_sw", "pll2_sw", "pll3_sw", "spdif_xtal_
 static const char *spdif0_com_sel[] = { "spdif0_podf", "ssi1_root_gate", };
 static const char *mx51_spdif1_com_sel[] = { "spdif1_podf", "ssi2_root_gate", };
 
-
-enum imx5_clks {
-       dummy, ckil, osc, ckih1, ckih2, ahb, ipg, axi_a, axi_b, uart_pred,
-       uart_root, esdhc_a_pred, esdhc_b_pred, esdhc_c_s, esdhc_d_s,
-       emi_sel, emi_slow_podf, nfc_podf, ecspi_pred, ecspi_podf, usboh3_pred,
-       usboh3_podf, usb_phy_pred, usb_phy_podf, cpu_podf, di_pred, tve_di_unused,
-       tve_s, uart1_ipg_gate, uart1_per_gate, uart2_ipg_gate,
-       uart2_per_gate, uart3_ipg_gate, uart3_per_gate, i2c1_gate, i2c2_gate,
-       gpt_ipg_gate, pwm1_ipg_gate, pwm1_hf_gate, pwm2_ipg_gate, pwm2_hf_gate,
-       gpt_hf_gate, fec_gate, usboh3_per_gate, esdhc1_ipg_gate, esdhc2_ipg_gate,
-       esdhc3_ipg_gate, esdhc4_ipg_gate, ssi1_ipg_gate, ssi2_ipg_gate,
-       ssi3_ipg_gate, ecspi1_ipg_gate, ecspi1_per_gate, ecspi2_ipg_gate,
-       ecspi2_per_gate, cspi_ipg_gate, sdma_gate, emi_slow_gate, ipu_s,
-       ipu_gate, nfc_gate, ipu_di1_gate, vpu_s, vpu_gate,
-       vpu_reference_gate, uart4_ipg_gate, uart4_per_gate, uart5_ipg_gate,
-       uart5_per_gate, tve_gate, tve_pred, esdhc1_per_gate, esdhc2_per_gate,
-       esdhc3_per_gate, esdhc4_per_gate, usb_phy_gate, hsi2c_gate,
-       mipi_hsc1_gate, mipi_hsc2_gate, mipi_esc_gate, mipi_hsp_gate,
-       ldb_di1_div_3_5, ldb_di1_div, ldb_di0_div_3_5, ldb_di0_div,
-       ldb_di1_gate, can2_serial_gate, can2_ipg_gate, i2c3_gate, lp_apm,
-       periph_apm, main_bus, ahb_max, aips_tz1, aips_tz2, tmax1, tmax2,
-       tmax3, spba, uart_sel, esdhc_a_sel, esdhc_b_sel, esdhc_a_podf,
-       esdhc_b_podf, ecspi_sel, usboh3_sel, usb_phy_sel, iim_gate,
-       usboh3_gate, emi_fast_gate, ipu_di0_gate,gpc_dvfs, pll1_sw, pll2_sw,
-       pll3_sw, ipu_di0_sel, ipu_di1_sel, tve_ext_sel, mx51_mipi, pll4_sw,
-       ldb_di1_sel, di_pll4_podf, ldb_di0_sel, ldb_di0_gate, usb_phy1_gate,
-       usb_phy2_gate, per_lp_apm, per_pred1, per_pred2, per_podf, per_root,
-       ssi_apm, ssi1_root_sel, ssi2_root_sel, ssi3_root_sel, ssi_ext1_sel,
-       ssi_ext2_sel, ssi_ext1_com_sel, ssi_ext2_com_sel, ssi1_root_pred,
-       ssi1_root_podf, ssi2_root_pred, ssi2_root_podf, ssi_ext1_pred,
-       ssi_ext1_podf, ssi_ext2_pred, ssi_ext2_podf, ssi1_root_gate,
-       ssi2_root_gate, ssi3_root_gate, ssi_ext1_gate, ssi_ext2_gate,
-       epit1_ipg_gate, epit1_hf_gate, epit2_ipg_gate, epit2_hf_gate,
-       can_sel, can1_serial_gate, can1_ipg_gate,
-       owire_gate, gpu3d_s, gpu2d_s, gpu3d_gate, gpu2d_gate, garb_gate,
-       cko1_sel, cko1_podf, cko1,
-       cko2_sel, cko2_podf, cko2,
-       srtc_gate, pata_gate, sata_gate, spdif_xtal_sel, spdif0_sel,
-       spdif1_sel, spdif0_pred, spdif0_podf, spdif1_pred, spdif1_podf,
-       spdif0_com_s, spdif1_com_sel, spdif0_gate, spdif1_gate, spdif_ipg_gate,
-       ocram, clk_max
-};
-
-static struct clk *clk[clk_max];
+static struct clk *clk[IMX5_CLK_END];
 static struct clk_onecell_data clk_data;
 
 static void __init mx5_clocks_common_init(unsigned long rate_ckil,
@@ -135,236 +92,296 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil,
 {
        int i;
 
-       clk[dummy] = imx_clk_fixed("dummy", 0);
-       clk[ckil] = imx_obtain_fixed_clock("ckil", rate_ckil);
-       clk[osc] = imx_obtain_fixed_clock("osc", rate_osc);
-       clk[ckih1] = imx_obtain_fixed_clock("ckih1", rate_ckih1);
-       clk[ckih2] = imx_obtain_fixed_clock("ckih2", rate_ckih2);
-
-       clk[lp_apm] = imx_clk_mux("lp_apm", MXC_CCM_CCSR, 9, 1,
-                               lp_apm_sel, ARRAY_SIZE(lp_apm_sel));
-       clk[periph_apm] = imx_clk_mux("periph_apm", MXC_CCM_CBCMR, 12, 2,
-                               periph_apm_sel, ARRAY_SIZE(periph_apm_sel));
-       clk[main_bus] = imx_clk_mux("main_bus", MXC_CCM_CBCDR, 25, 1,
-                               main_bus_sel, ARRAY_SIZE(main_bus_sel));
-       clk[per_lp_apm] = imx_clk_mux("per_lp_apm", MXC_CCM_CBCMR, 1, 1,
-                               per_lp_apm_sel, ARRAY_SIZE(per_lp_apm_sel));
-       clk[per_pred1] = imx_clk_divider("per_pred1", "per_lp_apm", MXC_CCM_CBCDR, 6, 2);
-       clk[per_pred2] = imx_clk_divider("per_pred2", "per_pred1", MXC_CCM_CBCDR, 3, 3);
-       clk[per_podf] = imx_clk_divider("per_podf", "per_pred2", MXC_CCM_CBCDR, 0, 3);
-       clk[per_root] = imx_clk_mux("per_root", MXC_CCM_CBCMR, 0, 1,
-                               per_root_sel, ARRAY_SIZE(per_root_sel));
-       clk[ahb] = imx_clk_divider("ahb", "main_bus", MXC_CCM_CBCDR, 10, 3);
-       clk[ahb_max] = imx_clk_gate2("ahb_max", "ahb", MXC_CCM_CCGR0, 28);
-       clk[aips_tz1] = imx_clk_gate2("aips_tz1", "ahb", MXC_CCM_CCGR0, 24);
-       clk[aips_tz2] = imx_clk_gate2("aips_tz2", "ahb", MXC_CCM_CCGR0, 26);
-       clk[tmax1] = imx_clk_gate2("tmax1", "ahb", MXC_CCM_CCGR1, 0);
-       clk[tmax2] = imx_clk_gate2("tmax2", "ahb", MXC_CCM_CCGR1, 2);
-       clk[tmax3] = imx_clk_gate2("tmax3", "ahb", MXC_CCM_CCGR1, 4);
-       clk[spba] = imx_clk_gate2("spba", "ipg", MXC_CCM_CCGR5, 0);
-       clk[ipg] = imx_clk_divider("ipg", "ahb", MXC_CCM_CBCDR, 8, 2);
-       clk[axi_a] = imx_clk_divider("axi_a", "main_bus", MXC_CCM_CBCDR, 16, 3);
-       clk[axi_b] = imx_clk_divider("axi_b", "main_bus", MXC_CCM_CBCDR, 19, 3);
-       clk[uart_sel] = imx_clk_mux("uart_sel", MXC_CCM_CSCMR1, 24, 2,
-                               standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
-       clk[uart_pred] = imx_clk_divider("uart_pred", "uart_sel", MXC_CCM_CSCDR1, 3, 3);
-       clk[uart_root] = imx_clk_divider("uart_root", "uart_pred", MXC_CCM_CSCDR1, 0, 3);
-
-       clk[esdhc_a_sel] = imx_clk_mux("esdhc_a_sel", MXC_CCM_CSCMR1, 20, 2,
-                               standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
-       clk[esdhc_b_sel] = imx_clk_mux("esdhc_b_sel", MXC_CCM_CSCMR1, 16, 2,
-                               standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
-       clk[esdhc_a_pred] = imx_clk_divider("esdhc_a_pred", "esdhc_a_sel", MXC_CCM_CSCDR1, 16, 3);
-       clk[esdhc_a_podf] = imx_clk_divider("esdhc_a_podf", "esdhc_a_pred", MXC_CCM_CSCDR1, 11, 3);
-       clk[esdhc_b_pred] = imx_clk_divider("esdhc_b_pred", "esdhc_b_sel", MXC_CCM_CSCDR1, 22, 3);
-       clk[esdhc_b_podf] = imx_clk_divider("esdhc_b_podf", "esdhc_b_pred", MXC_CCM_CSCDR1, 19, 3);
-       clk[esdhc_c_s] = imx_clk_mux("esdhc_c_sel", MXC_CCM_CSCMR1, 19, 1, esdhc_c_sel, ARRAY_SIZE(esdhc_c_sel));
-       clk[esdhc_d_s] = imx_clk_mux("esdhc_d_sel", MXC_CCM_CSCMR1, 18, 1, esdhc_d_sel, ARRAY_SIZE(esdhc_d_sel));
-
-       clk[emi_sel] = imx_clk_mux("emi_sel", MXC_CCM_CBCDR, 26, 1,
-                               emi_slow_sel, ARRAY_SIZE(emi_slow_sel));
-       clk[emi_slow_podf] = imx_clk_divider("emi_slow_podf", "emi_sel", MXC_CCM_CBCDR, 22, 3);
-       clk[nfc_podf] = imx_clk_divider("nfc_podf", "emi_slow_podf", MXC_CCM_CBCDR, 13, 3);
-       clk[ecspi_sel] = imx_clk_mux("ecspi_sel", MXC_CCM_CSCMR1, 4, 2,
-                               standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
-       clk[ecspi_pred] = imx_clk_divider("ecspi_pred", "ecspi_sel", MXC_CCM_CSCDR2, 25, 3);
-       clk[ecspi_podf] = imx_clk_divider("ecspi_podf", "ecspi_pred", MXC_CCM_CSCDR2, 19, 6);
-       clk[usboh3_sel] = imx_clk_mux("usboh3_sel", MXC_CCM_CSCMR1, 22, 2,
-                               standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
-       clk[usboh3_pred] = imx_clk_divider("usboh3_pred", "usboh3_sel", MXC_CCM_CSCDR1, 8, 3);
-       clk[usboh3_podf] = imx_clk_divider("usboh3_podf", "usboh3_pred", MXC_CCM_CSCDR1, 6, 2);
-       clk[usb_phy_pred] = imx_clk_divider("usb_phy_pred", "pll3_sw", MXC_CCM_CDCDR, 3, 3);
-       clk[usb_phy_podf] = imx_clk_divider("usb_phy_podf", "usb_phy_pred", MXC_CCM_CDCDR, 0, 3);
-       clk[usb_phy_sel] = imx_clk_mux("usb_phy_sel", MXC_CCM_CSCMR1, 26, 1,
-                               usb_phy_sel_str, ARRAY_SIZE(usb_phy_sel_str));
-       clk[cpu_podf] = imx_clk_divider("cpu_podf", "pll1_sw", MXC_CCM_CACRR, 0, 3);
-       clk[di_pred] = imx_clk_divider("di_pred", "pll3_sw", MXC_CCM_CDCDR, 6, 3);
-       clk[iim_gate] = imx_clk_gate2("iim_gate", "ipg", MXC_CCM_CCGR0, 30);
-       clk[uart1_ipg_gate] = imx_clk_gate2("uart1_ipg_gate", "ipg", MXC_CCM_CCGR1, 6);
-       clk[uart1_per_gate] = imx_clk_gate2("uart1_per_gate", "uart_root", MXC_CCM_CCGR1, 8);
-       clk[uart2_ipg_gate] = imx_clk_gate2("uart2_ipg_gate", "ipg", MXC_CCM_CCGR1, 10);
-       clk[uart2_per_gate] = imx_clk_gate2("uart2_per_gate", "uart_root", MXC_CCM_CCGR1, 12);
-       clk[uart3_ipg_gate] = imx_clk_gate2("uart3_ipg_gate", "ipg", MXC_CCM_CCGR1, 14);
-       clk[uart3_per_gate] = imx_clk_gate2("uart3_per_gate", "uart_root", MXC_CCM_CCGR1, 16);
-       clk[i2c1_gate] = imx_clk_gate2("i2c1_gate", "per_root", MXC_CCM_CCGR1, 18);
-       clk[i2c2_gate] = imx_clk_gate2("i2c2_gate", "per_root", MXC_CCM_CCGR1, 20);
-       clk[pwm1_ipg_gate] = imx_clk_gate2("pwm1_ipg_gate", "ipg", MXC_CCM_CCGR2, 10);
-       clk[pwm1_hf_gate] = imx_clk_gate2("pwm1_hf_gate", "per_root", MXC_CCM_CCGR2, 12);
-       clk[pwm2_ipg_gate] = imx_clk_gate2("pwm2_ipg_gate", "ipg", MXC_CCM_CCGR2, 14);
-       clk[pwm2_hf_gate] = imx_clk_gate2("pwm2_hf_gate", "per_root", MXC_CCM_CCGR2, 16);
-       clk[gpt_ipg_gate] = imx_clk_gate2("gpt_ipg_gate", "ipg", MXC_CCM_CCGR2, 18);
-       clk[gpt_hf_gate] = imx_clk_gate2("gpt_hf_gate", "per_root", MXC_CCM_CCGR2, 20);
-       clk[fec_gate] = imx_clk_gate2("fec_gate", "ipg", MXC_CCM_CCGR2, 24);
-       clk[usboh3_gate] = imx_clk_gate2("usboh3_gate", "ipg", MXC_CCM_CCGR2, 26);
-       clk[usboh3_per_gate] = imx_clk_gate2("usboh3_per_gate", "usboh3_podf", MXC_CCM_CCGR2, 28);
-       clk[esdhc1_ipg_gate] = imx_clk_gate2("esdhc1_ipg_gate", "ipg", MXC_CCM_CCGR3, 0);
-       clk[esdhc2_ipg_gate] = imx_clk_gate2("esdhc2_ipg_gate", "ipg", MXC_CCM_CCGR3, 4);
-       clk[esdhc3_ipg_gate] = imx_clk_gate2("esdhc3_ipg_gate", "ipg", MXC_CCM_CCGR3, 8);
-       clk[esdhc4_ipg_gate] = imx_clk_gate2("esdhc4_ipg_gate", "ipg", MXC_CCM_CCGR3, 12);
-       clk[ssi1_ipg_gate] = imx_clk_gate2("ssi1_ipg_gate", "ipg", MXC_CCM_CCGR3, 16);
-       clk[ssi2_ipg_gate] = imx_clk_gate2("ssi2_ipg_gate", "ipg", MXC_CCM_CCGR3, 20);
-       clk[ssi3_ipg_gate] = imx_clk_gate2("ssi3_ipg_gate", "ipg", MXC_CCM_CCGR3, 24);
-       clk[ecspi1_ipg_gate] = imx_clk_gate2("ecspi1_ipg_gate", "ipg", MXC_CCM_CCGR4, 18);
-       clk[ecspi1_per_gate] = imx_clk_gate2("ecspi1_per_gate", "ecspi_podf", MXC_CCM_CCGR4, 20);
-       clk[ecspi2_ipg_gate] = imx_clk_gate2("ecspi2_ipg_gate", "ipg", MXC_CCM_CCGR4, 22);
-       clk[ecspi2_per_gate] = imx_clk_gate2("ecspi2_per_gate", "ecspi_podf", MXC_CCM_CCGR4, 24);
-       clk[cspi_ipg_gate] = imx_clk_gate2("cspi_ipg_gate", "ipg", MXC_CCM_CCGR4, 26);
-       clk[sdma_gate] = imx_clk_gate2("sdma_gate", "ipg", MXC_CCM_CCGR4, 30);
-       clk[emi_fast_gate] = imx_clk_gate2("emi_fast_gate", "dummy", MXC_CCM_CCGR5, 14);
-       clk[emi_slow_gate] = imx_clk_gate2("emi_slow_gate", "emi_slow_podf", MXC_CCM_CCGR5, 16);
-       clk[ipu_s] = imx_clk_mux("ipu_sel", MXC_CCM_CBCMR, 6, 2, ipu_sel, ARRAY_SIZE(ipu_sel));
-       clk[ipu_gate] = imx_clk_gate2("ipu_gate", "ipu_sel", MXC_CCM_CCGR5, 10);
-       clk[nfc_gate] = imx_clk_gate2("nfc_gate", "nfc_podf", MXC_CCM_CCGR5, 20);
-       clk[ipu_di0_gate] = imx_clk_gate2("ipu_di0_gate", "ipu_di0_sel", MXC_CCM_CCGR6, 10);
-       clk[ipu_di1_gate] = imx_clk_gate2("ipu_di1_gate", "ipu_di1_sel", MXC_CCM_CCGR6, 12);
-       clk[gpu3d_s] = imx_clk_mux("gpu3d_sel", MXC_CCM_CBCMR, 4, 2, gpu3d_sel, ARRAY_SIZE(gpu3d_sel));
-       clk[gpu2d_s] = imx_clk_mux("gpu2d_sel", MXC_CCM_CBCMR, 16, 2, gpu2d_sel, ARRAY_SIZE(gpu2d_sel));
-       clk[gpu3d_gate] = imx_clk_gate2("gpu3d_gate", "gpu3d_sel", MXC_CCM_CCGR5, 2);
-       clk[garb_gate] = imx_clk_gate2("garb_gate", "axi_a", MXC_CCM_CCGR5, 4);
-       clk[gpu2d_gate] = imx_clk_gate2("gpu2d_gate", "gpu2d_sel", MXC_CCM_CCGR6, 14);
-       clk[vpu_s] = imx_clk_mux("vpu_sel", MXC_CCM_CBCMR, 14, 2, vpu_sel, ARRAY_SIZE(vpu_sel));
-       clk[vpu_gate] = imx_clk_gate2("vpu_gate", "vpu_sel", MXC_CCM_CCGR5, 6);
-       clk[vpu_reference_gate] = imx_clk_gate2("vpu_reference_gate", "osc", MXC_CCM_CCGR5, 8);
-       clk[uart4_ipg_gate] = imx_clk_gate2("uart4_ipg_gate", "ipg", MXC_CCM_CCGR7, 8);
-       clk[uart4_per_gate] = imx_clk_gate2("uart4_per_gate", "uart_root", MXC_CCM_CCGR7, 10);
-       clk[uart5_ipg_gate] = imx_clk_gate2("uart5_ipg_gate", "ipg", MXC_CCM_CCGR7, 12);
-       clk[uart5_per_gate] = imx_clk_gate2("uart5_per_gate", "uart_root", MXC_CCM_CCGR7, 14);
-       clk[gpc_dvfs] = imx_clk_gate2("gpc_dvfs", "dummy", MXC_CCM_CCGR5, 24);
-
-       clk[ssi_apm] = imx_clk_mux("ssi_apm", MXC_CCM_CSCMR1, 8, 2, ssi_apm_sels, ARRAY_SIZE(ssi_apm_sels));
-       clk[ssi1_root_sel] = imx_clk_mux("ssi1_root_sel", MXC_CCM_CSCMR1, 14, 2, ssi_clk_sels, ARRAY_SIZE(ssi_clk_sels));
-       clk[ssi2_root_sel] = imx_clk_mux("ssi2_root_sel", MXC_CCM_CSCMR1, 12, 2, ssi_clk_sels, ARRAY_SIZE(ssi_clk_sels));
-       clk[ssi3_root_sel] = imx_clk_mux("ssi3_root_sel", MXC_CCM_CSCMR1, 11, 1, ssi3_clk_sels, ARRAY_SIZE(ssi3_clk_sels));
-       clk[ssi_ext1_sel] = imx_clk_mux("ssi_ext1_sel", MXC_CCM_CSCMR1, 28, 2, ssi_clk_sels, ARRAY_SIZE(ssi_clk_sels));
-       clk[ssi_ext2_sel] = imx_clk_mux("ssi_ext2_sel", MXC_CCM_CSCMR1, 30, 2, ssi_clk_sels, ARRAY_SIZE(ssi_clk_sels));
-       clk[ssi_ext1_com_sel] = imx_clk_mux("ssi_ext1_com_sel", MXC_CCM_CSCMR1, 0, 1, ssi_ext1_com_sels, ARRAY_SIZE(ssi_ext1_com_sels));
-       clk[ssi_ext2_com_sel] = imx_clk_mux("ssi_ext2_com_sel", MXC_CCM_CSCMR1, 1, 1, ssi_ext2_com_sels, ARRAY_SIZE(ssi_ext2_com_sels));
-       clk[ssi1_root_pred] = imx_clk_divider("ssi1_root_pred", "ssi1_root_sel", MXC_CCM_CS1CDR, 6, 3);
-       clk[ssi1_root_podf] = imx_clk_divider("ssi1_root_podf", "ssi1_root_pred", MXC_CCM_CS1CDR, 0, 6);
-       clk[ssi2_root_pred] = imx_clk_divider("ssi2_root_pred", "ssi2_root_sel", MXC_CCM_CS2CDR, 6, 3);
-       clk[ssi2_root_podf] = imx_clk_divider("ssi2_root_podf", "ssi2_root_pred", MXC_CCM_CS2CDR, 0, 6);
-       clk[ssi_ext1_pred] = imx_clk_divider("ssi_ext1_pred", "ssi_ext1_sel", MXC_CCM_CS1CDR, 22, 3);
-       clk[ssi_ext1_podf] = imx_clk_divider("ssi_ext1_podf", "ssi_ext1_pred", MXC_CCM_CS1CDR, 16, 6);
-       clk[ssi_ext2_pred] = imx_clk_divider("ssi_ext2_pred", "ssi_ext2_sel", MXC_CCM_CS2CDR, 22, 3);
-       clk[ssi_ext2_podf] = imx_clk_divider("ssi_ext2_podf", "ssi_ext2_pred", MXC_CCM_CS2CDR, 16, 6);
-       clk[ssi1_root_gate] = imx_clk_gate2("ssi1_root_gate", "ssi1_root_podf", MXC_CCM_CCGR3, 18);
-       clk[ssi2_root_gate] = imx_clk_gate2("ssi2_root_gate", "ssi2_root_podf", MXC_CCM_CCGR3, 22);
-       clk[ssi3_root_gate] = imx_clk_gate2("ssi3_root_gate", "ssi3_root_sel", MXC_CCM_CCGR3, 26);
-       clk[ssi_ext1_gate] = imx_clk_gate2("ssi_ext1_gate", "ssi_ext1_com_sel", MXC_CCM_CCGR3, 28);
-       clk[ssi_ext2_gate] = imx_clk_gate2("ssi_ext2_gate", "ssi_ext2_com_sel", MXC_CCM_CCGR3, 30);
-       clk[epit1_ipg_gate] = imx_clk_gate2("epit1_ipg_gate", "ipg", MXC_CCM_CCGR2, 2);
-       clk[epit1_hf_gate] = imx_clk_gate2("epit1_hf_gate", "per_root", MXC_CCM_CCGR2, 4);
-       clk[epit2_ipg_gate] = imx_clk_gate2("epit2_ipg_gate", "ipg", MXC_CCM_CCGR2, 6);
-       clk[epit2_hf_gate] = imx_clk_gate2("epit2_hf_gate", "per_root", MXC_CCM_CCGR2, 8);
-       clk[owire_gate] = imx_clk_gate2("owire_gate", "per_root", MXC_CCM_CCGR2, 22);
-       clk[srtc_gate] = imx_clk_gate2("srtc_gate", "per_root", MXC_CCM_CCGR4, 28);
-       clk[pata_gate] = imx_clk_gate2("pata_gate", "ipg", MXC_CCM_CCGR4, 0);
-       clk[spdif0_sel] = imx_clk_mux("spdif0_sel", MXC_CCM_CSCMR2, 0, 2, spdif_sel, ARRAY_SIZE(spdif_sel));
-       clk[spdif0_pred] = imx_clk_divider("spdif0_pred", "spdif0_sel", MXC_CCM_CDCDR, 25, 3);
-       clk[spdif0_podf] = imx_clk_divider("spdif0_podf", "spdif0_pred", MXC_CCM_CDCDR, 19, 6);
-       clk[spdif0_com_s] = imx_clk_mux_flags("spdif0_com_sel", MXC_CCM_CSCMR2, 4, 1,
-                               spdif0_com_sel, ARRAY_SIZE(spdif0_com_sel), CLK_SET_RATE_PARENT);
-       clk[spdif0_gate] = imx_clk_gate2("spdif0_gate", "spdif0_com_sel", MXC_CCM_CCGR5, 26);
-       clk[spdif_ipg_gate] = imx_clk_gate2("spdif_ipg_gate", "ipg", MXC_CCM_CCGR5, 30);
+       clk[IMX5_CLK_DUMMY]             = imx_clk_fixed("dummy", 0);
+       clk[IMX5_CLK_CKIL]              = imx_obtain_fixed_clock("ckil", rate_ckil);
+       clk[IMX5_CLK_OSC]               = imx_obtain_fixed_clock("osc", rate_osc);
+       clk[IMX5_CLK_CKIH1]             = imx_obtain_fixed_clock("ckih1", rate_ckih1);
+       clk[IMX5_CLK_CKIH2]             = imx_obtain_fixed_clock("ckih2", rate_ckih2);
+
+       clk[IMX5_CLK_PERIPH_APM]        = imx_clk_mux("periph_apm", MXC_CCM_CBCMR, 12, 2,
+                                               periph_apm_sel, ARRAY_SIZE(periph_apm_sel));
+       clk[IMX5_CLK_MAIN_BUS]          = imx_clk_mux("main_bus", MXC_CCM_CBCDR, 25, 1,
+                                               main_bus_sel, ARRAY_SIZE(main_bus_sel));
+       clk[IMX5_CLK_PER_LP_APM]        = imx_clk_mux("per_lp_apm", MXC_CCM_CBCMR, 1, 1,
+                                               per_lp_apm_sel, ARRAY_SIZE(per_lp_apm_sel));
+       clk[IMX5_CLK_PER_PRED1]         = imx_clk_divider("per_pred1", "per_lp_apm", MXC_CCM_CBCDR, 6, 2);
+       clk[IMX5_CLK_PER_PRED2]         = imx_clk_divider("per_pred2", "per_pred1", MXC_CCM_CBCDR, 3, 3);
+       clk[IMX5_CLK_PER_PODF]          = imx_clk_divider("per_podf", "per_pred2", MXC_CCM_CBCDR, 0, 3);
+       clk[IMX5_CLK_PER_ROOT]          = imx_clk_mux("per_root", MXC_CCM_CBCMR, 0, 1,
+                                               per_root_sel, ARRAY_SIZE(per_root_sel));
+       clk[IMX5_CLK_AHB]               = imx_clk_divider("ahb", "main_bus", MXC_CCM_CBCDR, 10, 3);
+       clk[IMX5_CLK_AHB_MAX]           = imx_clk_gate2("ahb_max", "ahb", MXC_CCM_CCGR0, 28);
+       clk[IMX5_CLK_AIPS_TZ1]          = imx_clk_gate2("aips_tz1", "ahb", MXC_CCM_CCGR0, 24);
+       clk[IMX5_CLK_AIPS_TZ2]          = imx_clk_gate2("aips_tz2", "ahb", MXC_CCM_CCGR0, 26);
+       clk[IMX5_CLK_TMAX1]             = imx_clk_gate2("tmax1", "ahb", MXC_CCM_CCGR1, 0);
+       clk[IMX5_CLK_TMAX2]             = imx_clk_gate2("tmax2", "ahb", MXC_CCM_CCGR1, 2);
+       clk[IMX5_CLK_TMAX3]             = imx_clk_gate2("tmax3", "ahb", MXC_CCM_CCGR1, 4);
+       clk[IMX5_CLK_SPBA]              = imx_clk_gate2("spba", "ipg", MXC_CCM_CCGR5, 0);
+       clk[IMX5_CLK_IPG]               = imx_clk_divider("ipg", "ahb", MXC_CCM_CBCDR, 8, 2);
+       clk[IMX5_CLK_AXI_A]             = imx_clk_divider("axi_a", "main_bus", MXC_CCM_CBCDR, 16, 3);
+       clk[IMX5_CLK_AXI_B]             = imx_clk_divider("axi_b", "main_bus", MXC_CCM_CBCDR, 19, 3);
+       clk[IMX5_CLK_UART_SEL]          = imx_clk_mux("uart_sel", MXC_CCM_CSCMR1, 24, 2,
+                                               standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
+       clk[IMX5_CLK_UART_PRED]         = imx_clk_divider("uart_pred", "uart_sel", MXC_CCM_CSCDR1, 3, 3);
+       clk[IMX5_CLK_UART_ROOT]         = imx_clk_divider("uart_root", "uart_pred", MXC_CCM_CSCDR1, 0, 3);
+
+       clk[IMX5_CLK_ESDHC_A_SEL]       = imx_clk_mux("esdhc_a_sel", MXC_CCM_CSCMR1, 20, 2,
+                                               standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
+       clk[IMX5_CLK_ESDHC_B_SEL]       = imx_clk_mux("esdhc_b_sel", MXC_CCM_CSCMR1, 16, 2,
+                                               standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
+       clk[IMX5_CLK_ESDHC_A_PRED]      = imx_clk_divider("esdhc_a_pred", "esdhc_a_sel", MXC_CCM_CSCDR1, 16, 3);
+       clk[IMX5_CLK_ESDHC_A_PODF]      = imx_clk_divider("esdhc_a_podf", "esdhc_a_pred", MXC_CCM_CSCDR1, 11, 3);
+       clk[IMX5_CLK_ESDHC_B_PRED]      = imx_clk_divider("esdhc_b_pred", "esdhc_b_sel", MXC_CCM_CSCDR1, 22, 3);
+       clk[IMX5_CLK_ESDHC_B_PODF]      = imx_clk_divider("esdhc_b_podf", "esdhc_b_pred", MXC_CCM_CSCDR1, 19, 3);
+       clk[IMX5_CLK_ESDHC_C_SEL]       = imx_clk_mux("esdhc_c_sel", MXC_CCM_CSCMR1, 19, 1, esdhc_c_sel, ARRAY_SIZE(esdhc_c_sel));
+       clk[IMX5_CLK_ESDHC_D_SEL]       = imx_clk_mux("esdhc_d_sel", MXC_CCM_CSCMR1, 18, 1, esdhc_d_sel, ARRAY_SIZE(esdhc_d_sel));
+
+       clk[IMX5_CLK_EMI_SEL]           = imx_clk_mux("emi_sel", MXC_CCM_CBCDR, 26, 1,
+                                               emi_slow_sel, ARRAY_SIZE(emi_slow_sel));
+       clk[IMX5_CLK_EMI_SLOW_PODF]     = imx_clk_divider("emi_slow_podf", "emi_sel", MXC_CCM_CBCDR, 22, 3);
+       clk[IMX5_CLK_NFC_PODF]          = imx_clk_divider("nfc_podf", "emi_slow_podf", MXC_CCM_CBCDR, 13, 3);
+       clk[IMX5_CLK_ECSPI_SEL]         = imx_clk_mux("ecspi_sel", MXC_CCM_CSCMR1, 4, 2,
+                                               standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
+       clk[IMX5_CLK_ECSPI_PRED]        = imx_clk_divider("ecspi_pred", "ecspi_sel", MXC_CCM_CSCDR2, 25, 3);
+       clk[IMX5_CLK_ECSPI_PODF]        = imx_clk_divider("ecspi_podf", "ecspi_pred", MXC_CCM_CSCDR2, 19, 6);
+       clk[IMX5_CLK_USBOH3_SEL]        = imx_clk_mux("usboh3_sel", MXC_CCM_CSCMR1, 22, 2,
+                                               standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
+       clk[IMX5_CLK_USBOH3_PRED]       = imx_clk_divider("usboh3_pred", "usboh3_sel", MXC_CCM_CSCDR1, 8, 3);
+       clk[IMX5_CLK_USBOH3_PODF]       = imx_clk_divider("usboh3_podf", "usboh3_pred", MXC_CCM_CSCDR1, 6, 2);
+       clk[IMX5_CLK_USB_PHY_PRED]      = imx_clk_divider("usb_phy_pred", "pll3_sw", MXC_CCM_CDCDR, 3, 3);
+       clk[IMX5_CLK_USB_PHY_PODF]      = imx_clk_divider("usb_phy_podf", "usb_phy_pred", MXC_CCM_CDCDR, 0, 3);
+       clk[IMX5_CLK_USB_PHY_SEL]       = imx_clk_mux("usb_phy_sel", MXC_CCM_CSCMR1, 26, 1,
+                                               usb_phy_sel_str, ARRAY_SIZE(usb_phy_sel_str));
+       clk[IMX5_CLK_CPU_PODF]          = imx_clk_divider("cpu_podf", "pll1_sw", MXC_CCM_CACRR, 0, 3);
+       clk[IMX5_CLK_DI_PRED]           = imx_clk_divider("di_pred", "pll3_sw", MXC_CCM_CDCDR, 6, 3);
+       clk[IMX5_CLK_IIM_GATE]          = imx_clk_gate2("iim_gate", "ipg", MXC_CCM_CCGR0, 30);
+       clk[IMX5_CLK_UART1_IPG_GATE]    = imx_clk_gate2("uart1_ipg_gate", "ipg", MXC_CCM_CCGR1, 6);
+       clk[IMX5_CLK_UART1_PER_GATE]    = imx_clk_gate2("uart1_per_gate", "uart_root", MXC_CCM_CCGR1, 8);
+       clk[IMX5_CLK_UART2_IPG_GATE]    = imx_clk_gate2("uart2_ipg_gate", "ipg", MXC_CCM_CCGR1, 10);
+       clk[IMX5_CLK_UART2_PER_GATE]    = imx_clk_gate2("uart2_per_gate", "uart_root", MXC_CCM_CCGR1, 12);
+       clk[IMX5_CLK_UART3_IPG_GATE]    = imx_clk_gate2("uart3_ipg_gate", "ipg", MXC_CCM_CCGR1, 14);
+       clk[IMX5_CLK_UART3_PER_GATE]    = imx_clk_gate2("uart3_per_gate", "uart_root", MXC_CCM_CCGR1, 16);
+       clk[IMX5_CLK_I2C1_GATE]         = imx_clk_gate2("i2c1_gate", "per_root", MXC_CCM_CCGR1, 18);
+       clk[IMX5_CLK_I2C2_GATE]         = imx_clk_gate2("i2c2_gate", "per_root", MXC_CCM_CCGR1, 20);
+       clk[IMX5_CLK_PWM1_IPG_GATE]     = imx_clk_gate2("pwm1_ipg_gate", "ipg", MXC_CCM_CCGR2, 10);
+       clk[IMX5_CLK_PWM1_HF_GATE]      = imx_clk_gate2("pwm1_hf_gate", "per_root", MXC_CCM_CCGR2, 12);
+       clk[IMX5_CLK_PWM2_IPG_GATE]     = imx_clk_gate2("pwm2_ipg_gate", "ipg", MXC_CCM_CCGR2, 14);
+       clk[IMX5_CLK_PWM2_HF_GATE]      = imx_clk_gate2("pwm2_hf_gate", "per_root", MXC_CCM_CCGR2, 16);
+       clk[IMX5_CLK_GPT_IPG_GATE]      = imx_clk_gate2("gpt_ipg_gate", "ipg", MXC_CCM_CCGR2, 18);
+       clk[IMX5_CLK_GPT_HF_GATE]       = imx_clk_gate2("gpt_hf_gate", "per_root", MXC_CCM_CCGR2, 20);
+       clk[IMX5_CLK_FEC_GATE]          = imx_clk_gate2("fec_gate", "ipg", MXC_CCM_CCGR2, 24);
+       clk[IMX5_CLK_USBOH3_GATE]       = imx_clk_gate2("usboh3_gate", "ipg", MXC_CCM_CCGR2, 26);
+       clk[IMX5_CLK_USBOH3_PER_GATE]   = imx_clk_gate2("usboh3_per_gate", "usboh3_podf", MXC_CCM_CCGR2, 28);
+       clk[IMX5_CLK_ESDHC1_IPG_GATE]   = imx_clk_gate2("esdhc1_ipg_gate", "ipg", MXC_CCM_CCGR3, 0);
+       clk[IMX5_CLK_ESDHC2_IPG_GATE]   = imx_clk_gate2("esdhc2_ipg_gate", "ipg", MXC_CCM_CCGR3, 4);
+       clk[IMX5_CLK_ESDHC3_IPG_GATE]   = imx_clk_gate2("esdhc3_ipg_gate", "ipg", MXC_CCM_CCGR3, 8);
+       clk[IMX5_CLK_ESDHC4_IPG_GATE]   = imx_clk_gate2("esdhc4_ipg_gate", "ipg", MXC_CCM_CCGR3, 12);
+       clk[IMX5_CLK_SSI1_IPG_GATE]     = imx_clk_gate2("ssi1_ipg_gate", "ipg", MXC_CCM_CCGR3, 16);
+       clk[IMX5_CLK_SSI2_IPG_GATE]     = imx_clk_gate2("ssi2_ipg_gate", "ipg", MXC_CCM_CCGR3, 20);
+       clk[IMX5_CLK_SSI3_IPG_GATE]     = imx_clk_gate2("ssi3_ipg_gate", "ipg", MXC_CCM_CCGR3, 24);
+       clk[IMX5_CLK_ECSPI1_IPG_GATE]   = imx_clk_gate2("ecspi1_ipg_gate", "ipg", MXC_CCM_CCGR4, 18);
+       clk[IMX5_CLK_ECSPI1_PER_GATE]   = imx_clk_gate2("ecspi1_per_gate", "ecspi_podf", MXC_CCM_CCGR4, 20);
+       clk[IMX5_CLK_ECSPI2_IPG_GATE]   = imx_clk_gate2("ecspi2_ipg_gate", "ipg", MXC_CCM_CCGR4, 22);
+       clk[IMX5_CLK_ECSPI2_PER_GATE]   = imx_clk_gate2("ecspi2_per_gate", "ecspi_podf", MXC_CCM_CCGR4, 24);
+       clk[IMX5_CLK_CSPI_IPG_GATE]     = imx_clk_gate2("cspi_ipg_gate", "ipg", MXC_CCM_CCGR4, 26);
+       clk[IMX5_CLK_SDMA_GATE]         = imx_clk_gate2("sdma_gate", "ipg", MXC_CCM_CCGR4, 30);
+       clk[IMX5_CLK_EMI_FAST_GATE]     = imx_clk_gate2("emi_fast_gate", "dummy", MXC_CCM_CCGR5, 14);
+       clk[IMX5_CLK_EMI_SLOW_GATE]     = imx_clk_gate2("emi_slow_gate", "emi_slow_podf", MXC_CCM_CCGR5, 16);
+       clk[IMX5_CLK_IPU_SEL]           = imx_clk_mux("ipu_sel", MXC_CCM_CBCMR, 6, 2, ipu_sel, ARRAY_SIZE(ipu_sel));
+       clk[IMX5_CLK_IPU_GATE]          = imx_clk_gate2("ipu_gate", "ipu_sel", MXC_CCM_CCGR5, 10);
+       clk[IMX5_CLK_NFC_GATE]          = imx_clk_gate2("nfc_gate", "nfc_podf", MXC_CCM_CCGR5, 20);
+       clk[IMX5_CLK_IPU_DI0_GATE]      = imx_clk_gate2("ipu_di0_gate", "ipu_di0_sel", MXC_CCM_CCGR6, 10);
+       clk[IMX5_CLK_IPU_DI1_GATE]      = imx_clk_gate2("ipu_di1_gate", "ipu_di1_sel", MXC_CCM_CCGR6, 12);
+       clk[IMX5_CLK_GPU3D_SEL]         = imx_clk_mux("gpu3d_sel", MXC_CCM_CBCMR, 4, 2, gpu3d_sel, ARRAY_SIZE(gpu3d_sel));
+       clk[IMX5_CLK_GPU2D_SEL]         = imx_clk_mux("gpu2d_sel", MXC_CCM_CBCMR, 16, 2, gpu2d_sel, ARRAY_SIZE(gpu2d_sel));
+       clk[IMX5_CLK_GPU3D_GATE]        = imx_clk_gate2("gpu3d_gate", "gpu3d_sel", MXC_CCM_CCGR5, 2);
+       clk[IMX5_CLK_GARB_GATE]         = imx_clk_gate2("garb_gate", "axi_a", MXC_CCM_CCGR5, 4);
+       clk[IMX5_CLK_GPU2D_GATE]        = imx_clk_gate2("gpu2d_gate", "gpu2d_sel", MXC_CCM_CCGR6, 14);
+       clk[IMX5_CLK_VPU_SEL]           = imx_clk_mux("vpu_sel", MXC_CCM_CBCMR, 14, 2, vpu_sel, ARRAY_SIZE(vpu_sel));
+       clk[IMX5_CLK_VPU_GATE]          = imx_clk_gate2("vpu_gate", "vpu_sel", MXC_CCM_CCGR5, 6);
+       clk[IMX5_CLK_VPU_REFERENCE_GATE] = imx_clk_gate2("vpu_reference_gate", "osc", MXC_CCM_CCGR5, 8);
+       clk[IMX5_CLK_UART4_IPG_GATE]    = imx_clk_gate2("uart4_ipg_gate", "ipg", MXC_CCM_CCGR7, 8);
+       clk[IMX5_CLK_UART4_PER_GATE]    = imx_clk_gate2("uart4_per_gate", "uart_root", MXC_CCM_CCGR7, 10);
+       clk[IMX5_CLK_UART5_IPG_GATE]    = imx_clk_gate2("uart5_ipg_gate", "ipg", MXC_CCM_CCGR7, 12);
+       clk[IMX5_CLK_UART5_PER_GATE]    = imx_clk_gate2("uart5_per_gate", "uart_root", MXC_CCM_CCGR7, 14);
+       clk[IMX5_CLK_GPC_DVFS]          = imx_clk_gate2("gpc_dvfs", "dummy", MXC_CCM_CCGR5, 24);
+
+       clk[IMX5_CLK_SSI_APM]           = imx_clk_mux("ssi_apm", MXC_CCM_CSCMR1, 8, 2, ssi_apm_sels, ARRAY_SIZE(ssi_apm_sels));
+       clk[IMX5_CLK_SSI1_ROOT_SEL]     = imx_clk_mux("ssi1_root_sel", MXC_CCM_CSCMR1, 14, 2, ssi_clk_sels, ARRAY_SIZE(ssi_clk_sels));
+       clk[IMX5_CLK_SSI2_ROOT_SEL]     = imx_clk_mux("ssi2_root_sel", MXC_CCM_CSCMR1, 12, 2, ssi_clk_sels, ARRAY_SIZE(ssi_clk_sels));
+       clk[IMX5_CLK_SSI3_ROOT_SEL]     = imx_clk_mux("ssi3_root_sel", MXC_CCM_CSCMR1, 11, 1, ssi3_clk_sels, ARRAY_SIZE(ssi3_clk_sels));
+       clk[IMX5_CLK_SSI_EXT1_SEL]      = imx_clk_mux("ssi_ext1_sel", MXC_CCM_CSCMR1, 28, 2, ssi_clk_sels, ARRAY_SIZE(ssi_clk_sels));
+       clk[IMX5_CLK_SSI_EXT2_SEL]      = imx_clk_mux("ssi_ext2_sel", MXC_CCM_CSCMR1, 30, 2, ssi_clk_sels, ARRAY_SIZE(ssi_clk_sels));
+       clk[IMX5_CLK_SSI_EXT1_COM_SEL]  = imx_clk_mux("ssi_ext1_com_sel", MXC_CCM_CSCMR1, 0, 1, ssi_ext1_com_sels, ARRAY_SIZE(ssi_ext1_com_sels));
+       clk[IMX5_CLK_SSI_EXT2_COM_SEL]  = imx_clk_mux("ssi_ext2_com_sel", MXC_CCM_CSCMR1, 1, 1, ssi_ext2_com_sels, ARRAY_SIZE(ssi_ext2_com_sels));
+       clk[IMX5_CLK_SSI1_ROOT_PRED]    = imx_clk_divider("ssi1_root_pred", "ssi1_root_sel", MXC_CCM_CS1CDR, 6, 3);
+       clk[IMX5_CLK_SSI1_ROOT_PODF]    = imx_clk_divider("ssi1_root_podf", "ssi1_root_pred", MXC_CCM_CS1CDR, 0, 6);
+       clk[IMX5_CLK_SSI2_ROOT_PRED]    = imx_clk_divider("ssi2_root_pred", "ssi2_root_sel", MXC_CCM_CS2CDR, 6, 3);
+       clk[IMX5_CLK_SSI2_ROOT_PODF]    = imx_clk_divider("ssi2_root_podf", "ssi2_root_pred", MXC_CCM_CS2CDR, 0, 6);
+       clk[IMX5_CLK_SSI_EXT1_PRED]     = imx_clk_divider("ssi_ext1_pred", "ssi_ext1_sel", MXC_CCM_CS1CDR, 22, 3);
+       clk[IMX5_CLK_SSI_EXT1_PODF]     = imx_clk_divider("ssi_ext1_podf", "ssi_ext1_pred", MXC_CCM_CS1CDR, 16, 6);
+       clk[IMX5_CLK_SSI_EXT2_PRED]     = imx_clk_divider("ssi_ext2_pred", "ssi_ext2_sel", MXC_CCM_CS2CDR, 22, 3);
+       clk[IMX5_CLK_SSI_EXT2_PODF]     = imx_clk_divider("ssi_ext2_podf", "ssi_ext2_pred", MXC_CCM_CS2CDR, 16, 6);
+       clk[IMX5_CLK_SSI1_ROOT_GATE]    = imx_clk_gate2("ssi1_root_gate", "ssi1_root_podf", MXC_CCM_CCGR3, 18);
+       clk[IMX5_CLK_SSI2_ROOT_GATE]    = imx_clk_gate2("ssi2_root_gate", "ssi2_root_podf", MXC_CCM_CCGR3, 22);
+       clk[IMX5_CLK_SSI3_ROOT_GATE]    = imx_clk_gate2("ssi3_root_gate", "ssi3_root_sel", MXC_CCM_CCGR3, 26);
+       clk[IMX5_CLK_SSI_EXT1_GATE]     = imx_clk_gate2("ssi_ext1_gate", "ssi_ext1_com_sel", MXC_CCM_CCGR3, 28);
+       clk[IMX5_CLK_SSI_EXT2_GATE]     = imx_clk_gate2("ssi_ext2_gate", "ssi_ext2_com_sel", MXC_CCM_CCGR3, 30);
+       clk[IMX5_CLK_EPIT1_IPG_GATE]    = imx_clk_gate2("epit1_ipg_gate", "ipg", MXC_CCM_CCGR2, 2);
+       clk[IMX5_CLK_EPIT1_HF_GATE]     = imx_clk_gate2("epit1_hf_gate", "per_root", MXC_CCM_CCGR2, 4);
+       clk[IMX5_CLK_EPIT2_IPG_GATE]    = imx_clk_gate2("epit2_ipg_gate", "ipg", MXC_CCM_CCGR2, 6);
+       clk[IMX5_CLK_EPIT2_HF_GATE]     = imx_clk_gate2("epit2_hf_gate", "per_root", MXC_CCM_CCGR2, 8);
+       clk[IMX5_CLK_OWIRE_GATE]        = imx_clk_gate2("owire_gate", "per_root", MXC_CCM_CCGR2, 22);
+       clk[IMX5_CLK_SRTC_GATE]         = imx_clk_gate2("srtc_gate", "per_root", MXC_CCM_CCGR4, 28);
+       clk[IMX5_CLK_PATA_GATE]         = imx_clk_gate2("pata_gate", "ipg", MXC_CCM_CCGR4, 0);
+       clk[IMX5_CLK_SPDIF0_SEL]        = imx_clk_mux("spdif0_sel", MXC_CCM_CSCMR2, 0, 2, spdif_sel, ARRAY_SIZE(spdif_sel));
+       clk[IMX5_CLK_SPDIF0_PRED]       = imx_clk_divider("spdif0_pred", "spdif0_sel", MXC_CCM_CDCDR, 25, 3);
+       clk[IMX5_CLK_SPDIF0_PODF]       = imx_clk_divider("spdif0_podf", "spdif0_pred", MXC_CCM_CDCDR, 19, 6);
+       clk[IMX5_CLK_SPDIF0_COM_SEL]    = imx_clk_mux_flags("spdif0_com_sel", MXC_CCM_CSCMR2, 4, 1,
+                                               spdif0_com_sel, ARRAY_SIZE(spdif0_com_sel), CLK_SET_RATE_PARENT);
+       clk[IMX5_CLK_SPDIF0_GATE]       = imx_clk_gate2("spdif0_gate", "spdif0_com_sel", MXC_CCM_CCGR5, 26);
+       clk[IMX5_CLK_SPDIF_IPG_GATE]    = imx_clk_gate2("spdif_ipg_gate", "ipg", MXC_CCM_CCGR5, 30);
+       clk[IMX5_CLK_SAHARA_IPG_GATE]   = imx_clk_gate2("sahara_ipg_gate", "ipg", MXC_CCM_CCGR4, 14);
+       clk[IMX5_CLK_SATA_REF]          = imx_clk_fixed_factor("sata_ref", "usb_phy1_gate", 1, 1);
 
        for (i = 0; i < ARRAY_SIZE(clk); i++)
                if (IS_ERR(clk[i]))
                        pr_err("i.MX5 clk %d: register failed with %ld\n",
                                i, PTR_ERR(clk[i]));
 
-       clk_register_clkdev(clk[gpt_hf_gate], "per", "imx-gpt.0");
-       clk_register_clkdev(clk[gpt_ipg_gate], "ipg", "imx-gpt.0");
-       clk_register_clkdev(clk[uart1_per_gate], "per", "imx21-uart.0");
-       clk_register_clkdev(clk[uart1_ipg_gate], "ipg", "imx21-uart.0");
-       clk_register_clkdev(clk[uart2_per_gate], "per", "imx21-uart.1");
-       clk_register_clkdev(clk[uart2_ipg_gate], "ipg", "imx21-uart.1");
-       clk_register_clkdev(clk[uart3_per_gate], "per", "imx21-uart.2");
-       clk_register_clkdev(clk[uart3_ipg_gate], "ipg", "imx21-uart.2");
-       clk_register_clkdev(clk[uart4_per_gate], "per", "imx21-uart.3");
-       clk_register_clkdev(clk[uart4_ipg_gate], "ipg", "imx21-uart.3");
-       clk_register_clkdev(clk[uart5_per_gate], "per", "imx21-uart.4");
-       clk_register_clkdev(clk[uart5_ipg_gate], "ipg", "imx21-uart.4");
-       clk_register_clkdev(clk[ecspi1_per_gate], "per", "imx51-ecspi.0");
-       clk_register_clkdev(clk[ecspi1_ipg_gate], "ipg", "imx51-ecspi.0");
-       clk_register_clkdev(clk[ecspi2_per_gate], "per", "imx51-ecspi.1");
-       clk_register_clkdev(clk[ecspi2_ipg_gate], "ipg", "imx51-ecspi.1");
-       clk_register_clkdev(clk[cspi_ipg_gate], NULL, "imx35-cspi.2");
-       clk_register_clkdev(clk[pwm1_ipg_gate], "pwm", "mxc_pwm.0");
-       clk_register_clkdev(clk[pwm2_ipg_gate], "pwm", "mxc_pwm.1");
-       clk_register_clkdev(clk[i2c1_gate], NULL, "imx21-i2c.0");
-       clk_register_clkdev(clk[i2c2_gate], NULL, "imx21-i2c.1");
-       clk_register_clkdev(clk[usboh3_per_gate], "per", "mxc-ehci.0");
-       clk_register_clkdev(clk[usboh3_gate], "ipg", "mxc-ehci.0");
-       clk_register_clkdev(clk[usboh3_gate], "ahb", "mxc-ehci.0");
-       clk_register_clkdev(clk[usboh3_per_gate], "per", "mxc-ehci.1");
-       clk_register_clkdev(clk[usboh3_gate], "ipg", "mxc-ehci.1");
-       clk_register_clkdev(clk[usboh3_gate], "ahb", "mxc-ehci.1");
-       clk_register_clkdev(clk[usboh3_per_gate], "per", "mxc-ehci.2");
-       clk_register_clkdev(clk[usboh3_gate], "ipg", "mxc-ehci.2");
-       clk_register_clkdev(clk[usboh3_gate], "ahb", "mxc-ehci.2");
-       clk_register_clkdev(clk[usboh3_per_gate], "per", "imx-udc-mx51");
-       clk_register_clkdev(clk[usboh3_gate], "ipg", "imx-udc-mx51");
-       clk_register_clkdev(clk[usboh3_gate], "ahb", "imx-udc-mx51");
-       clk_register_clkdev(clk[nfc_gate], NULL, "imx51-nand");
-       clk_register_clkdev(clk[ssi1_ipg_gate], NULL, "imx-ssi.0");
-       clk_register_clkdev(clk[ssi2_ipg_gate], NULL, "imx-ssi.1");
-       clk_register_clkdev(clk[ssi3_ipg_gate], NULL, "imx-ssi.2");
-       clk_register_clkdev(clk[sdma_gate], NULL, "imx35-sdma");
-       clk_register_clkdev(clk[cpu_podf], NULL, "cpu0");
-       clk_register_clkdev(clk[iim_gate], "iim", NULL);
-       clk_register_clkdev(clk[dummy], NULL, "imx2-wdt.0");
-       clk_register_clkdev(clk[dummy], NULL, "imx2-wdt.1");
-       clk_register_clkdev(clk[dummy], NULL, "imx-keypad");
-       clk_register_clkdev(clk[ipu_di1_gate], "di1", "imx-tve.0");
-       clk_register_clkdev(clk[gpc_dvfs], "gpc_dvfs", NULL);
-       clk_register_clkdev(clk[epit1_ipg_gate], "ipg", "imx-epit.0");
-       clk_register_clkdev(clk[epit1_hf_gate], "per", "imx-epit.0");
-       clk_register_clkdev(clk[epit2_ipg_gate], "ipg", "imx-epit.1");
-       clk_register_clkdev(clk[epit2_hf_gate], "per", "imx-epit.1");
+       clk_register_clkdev(clk[IMX5_CLK_GPT_HF_GATE], "per", "imx-gpt.0");
+       clk_register_clkdev(clk[IMX5_CLK_GPT_IPG_GATE], "ipg", "imx-gpt.0");
+       clk_register_clkdev(clk[IMX5_CLK_UART1_PER_GATE], "per", "imx21-uart.0");
+       clk_register_clkdev(clk[IMX5_CLK_UART1_IPG_GATE], "ipg", "imx21-uart.0");
+       clk_register_clkdev(clk[IMX5_CLK_UART2_PER_GATE], "per", "imx21-uart.1");
+       clk_register_clkdev(clk[IMX5_CLK_UART2_IPG_GATE], "ipg", "imx21-uart.1");
+       clk_register_clkdev(clk[IMX5_CLK_UART3_PER_GATE], "per", "imx21-uart.2");
+       clk_register_clkdev(clk[IMX5_CLK_UART3_IPG_GATE], "ipg", "imx21-uart.2");
+       clk_register_clkdev(clk[IMX5_CLK_UART4_PER_GATE], "per", "imx21-uart.3");
+       clk_register_clkdev(clk[IMX5_CLK_UART4_IPG_GATE], "ipg", "imx21-uart.3");
+       clk_register_clkdev(clk[IMX5_CLK_UART5_PER_GATE], "per", "imx21-uart.4");
+       clk_register_clkdev(clk[IMX5_CLK_UART5_IPG_GATE], "ipg", "imx21-uart.4");
+       clk_register_clkdev(clk[IMX5_CLK_ECSPI1_PER_GATE], "per", "imx51-ecspi.0");
+       clk_register_clkdev(clk[IMX5_CLK_ECSPI1_IPG_GATE], "ipg", "imx51-ecspi.0");
+       clk_register_clkdev(clk[IMX5_CLK_ECSPI2_PER_GATE], "per", "imx51-ecspi.1");
+       clk_register_clkdev(clk[IMX5_CLK_ECSPI2_IPG_GATE], "ipg", "imx51-ecspi.1");
+       clk_register_clkdev(clk[IMX5_CLK_CSPI_IPG_GATE], NULL, "imx35-cspi.2");
+       clk_register_clkdev(clk[IMX5_CLK_PWM1_IPG_GATE], "pwm", "mxc_pwm.0");
+       clk_register_clkdev(clk[IMX5_CLK_PWM2_IPG_GATE], "pwm", "mxc_pwm.1");
+       clk_register_clkdev(clk[IMX5_CLK_I2C1_GATE], NULL, "imx21-i2c.0");
+       clk_register_clkdev(clk[IMX5_CLK_I2C2_GATE], NULL, "imx21-i2c.1");
+       clk_register_clkdev(clk[IMX5_CLK_USBOH3_PER_GATE], "per", "mxc-ehci.0");
+       clk_register_clkdev(clk[IMX5_CLK_USBOH3_GATE], "ipg", "mxc-ehci.0");
+       clk_register_clkdev(clk[IMX5_CLK_USBOH3_GATE], "ahb", "mxc-ehci.0");
+       clk_register_clkdev(clk[IMX5_CLK_USBOH3_PER_GATE], "per", "mxc-ehci.1");
+       clk_register_clkdev(clk[IMX5_CLK_USBOH3_GATE], "ipg", "mxc-ehci.1");
+       clk_register_clkdev(clk[IMX5_CLK_USBOH3_GATE], "ahb", "mxc-ehci.1");
+       clk_register_clkdev(clk[IMX5_CLK_USBOH3_PER_GATE], "per", "mxc-ehci.2");
+       clk_register_clkdev(clk[IMX5_CLK_USBOH3_GATE], "ipg", "mxc-ehci.2");
+       clk_register_clkdev(clk[IMX5_CLK_USBOH3_GATE], "ahb", "mxc-ehci.2");
+       clk_register_clkdev(clk[IMX5_CLK_USBOH3_PER_GATE], "per", "imx-udc-mx51");
+       clk_register_clkdev(clk[IMX5_CLK_USBOH3_GATE], "ipg", "imx-udc-mx51");
+       clk_register_clkdev(clk[IMX5_CLK_USBOH3_GATE], "ahb", "imx-udc-mx51");
+       clk_register_clkdev(clk[IMX5_CLK_NFC_GATE], NULL, "imx51-nand");
+       clk_register_clkdev(clk[IMX5_CLK_SSI1_IPG_GATE], NULL, "imx-ssi.0");
+       clk_register_clkdev(clk[IMX5_CLK_SSI2_IPG_GATE], NULL, "imx-ssi.1");
+       clk_register_clkdev(clk[IMX5_CLK_SSI3_IPG_GATE], NULL, "imx-ssi.2");
+       clk_register_clkdev(clk[IMX5_CLK_SDMA_GATE], NULL, "imx35-sdma");
+       clk_register_clkdev(clk[IMX5_CLK_CPU_PODF], NULL, "cpu0");
+       clk_register_clkdev(clk[IMX5_CLK_IIM_GATE], "iim", NULL);
+       clk_register_clkdev(clk[IMX5_CLK_DUMMY], NULL, "imx2-wdt.0");
+       clk_register_clkdev(clk[IMX5_CLK_DUMMY], NULL, "imx2-wdt.1");
+       clk_register_clkdev(clk[IMX5_CLK_DUMMY], NULL, "imx-keypad");
+       clk_register_clkdev(clk[IMX5_CLK_IPU_DI1_GATE], "di1", "imx-tve.0");
+       clk_register_clkdev(clk[IMX5_CLK_GPC_DVFS], "gpc_dvfs", NULL);
+       clk_register_clkdev(clk[IMX5_CLK_EPIT1_IPG_GATE], "ipg", "imx-epit.0");
+       clk_register_clkdev(clk[IMX5_CLK_EPIT1_HF_GATE], "per", "imx-epit.0");
+       clk_register_clkdev(clk[IMX5_CLK_EPIT2_IPG_GATE], "ipg", "imx-epit.1");
+       clk_register_clkdev(clk[IMX5_CLK_EPIT2_HF_GATE], "per", "imx-epit.1");
 
        /* Set SDHC parents to be PLL2 */
-       clk_set_parent(clk[esdhc_a_sel], clk[pll2_sw]);
-       clk_set_parent(clk[esdhc_b_sel], clk[pll2_sw]);
+       clk_set_parent(clk[IMX5_CLK_ESDHC_A_SEL], clk[IMX5_CLK_PLL2_SW]);
+       clk_set_parent(clk[IMX5_CLK_ESDHC_B_SEL], clk[IMX5_CLK_PLL2_SW]);
 
        /* move usb phy clk to 24MHz */
-       clk_set_parent(clk[usb_phy_sel], clk[osc]);
-
-       clk_prepare_enable(clk[gpc_dvfs]);
-       clk_prepare_enable(clk[ahb_max]); /* esdhc3 */
-       clk_prepare_enable(clk[aips_tz1]);
-       clk_prepare_enable(clk[aips_tz2]); /* fec */
-       clk_prepare_enable(clk[spba]);
-       clk_prepare_enable(clk[emi_fast_gate]); /* fec */
-       clk_prepare_enable(clk[emi_slow_gate]); /* eim */
-       clk_prepare_enable(clk[mipi_hsc1_gate]);
-       clk_prepare_enable(clk[mipi_hsc2_gate]);
-       clk_prepare_enable(clk[mipi_esc_gate]);
-       clk_prepare_enable(clk[mipi_hsp_gate]);
-       clk_prepare_enable(clk[tmax1]);
-       clk_prepare_enable(clk[tmax2]); /* esdhc2, fec */
-       clk_prepare_enable(clk[tmax3]); /* esdhc1, esdhc4 */
+       clk_set_parent(clk[IMX5_CLK_USB_PHY_SEL], clk[IMX5_CLK_OSC]);
+
+       clk_prepare_enable(clk[IMX5_CLK_GPC_DVFS]);
+       clk_prepare_enable(clk[IMX5_CLK_AHB_MAX]); /* esdhc3 */
+       clk_prepare_enable(clk[IMX5_CLK_AIPS_TZ1]);
+       clk_prepare_enable(clk[IMX5_CLK_AIPS_TZ2]); /* fec */
+       clk_prepare_enable(clk[IMX5_CLK_SPBA]);
+       clk_prepare_enable(clk[IMX5_CLK_EMI_FAST_GATE]); /* fec */
+       clk_prepare_enable(clk[IMX5_CLK_EMI_SLOW_GATE]); /* eim */
+       clk_prepare_enable(clk[IMX5_CLK_MIPI_HSC1_GATE]);
+       clk_prepare_enable(clk[IMX5_CLK_MIPI_HSC2_GATE]);
+       clk_prepare_enable(clk[IMX5_CLK_MIPI_ESC_GATE]);
+       clk_prepare_enable(clk[IMX5_CLK_MIPI_HSP_GATE]);
+       clk_prepare_enable(clk[IMX5_CLK_TMAX1]);
+       clk_prepare_enable(clk[IMX5_CLK_TMAX2]); /* esdhc2, fec */
+       clk_prepare_enable(clk[IMX5_CLK_TMAX3]); /* esdhc1, esdhc4 */
 }
 
+static void __init mx50_clocks_init(struct device_node *np)
+{
+       void __iomem *base;
+       unsigned long r;
+       int i, irq;
+
+       clk[IMX5_CLK_PLL1_SW]           = imx_clk_pllv2("pll1_sw", "osc", MX53_DPLL1_BASE);
+       clk[IMX5_CLK_PLL2_SW]           = imx_clk_pllv2("pll2_sw", "osc", MX53_DPLL2_BASE);
+       clk[IMX5_CLK_PLL3_SW]           = imx_clk_pllv2("pll3_sw", "osc", MX53_DPLL3_BASE);
+
+       clk[IMX5_CLK_LP_APM]            = imx_clk_mux("lp_apm", MXC_CCM_CCSR, 10, 1,
+                                               lp_apm_sel, ARRAY_SIZE(lp_apm_sel));
+       clk[IMX5_CLK_ESDHC1_PER_GATE]   = imx_clk_gate2("esdhc1_per_gate", "esdhc_a_podf", MXC_CCM_CCGR3, 2);
+       clk[IMX5_CLK_ESDHC2_PER_GATE]   = imx_clk_gate2("esdhc2_per_gate", "esdhc_c_sel", MXC_CCM_CCGR3, 6);
+       clk[IMX5_CLK_ESDHC3_PER_GATE]   = imx_clk_gate2("esdhc3_per_gate", "esdhc_b_podf", MXC_CCM_CCGR3, 10);
+       clk[IMX5_CLK_ESDHC4_PER_GATE]   = imx_clk_gate2("esdhc4_per_gate", "esdhc_d_sel", MXC_CCM_CCGR3, 14);
+       clk[IMX5_CLK_USB_PHY1_GATE]     = imx_clk_gate2("usb_phy1_gate", "usb_phy_sel", MXC_CCM_CCGR4, 10);
+       clk[IMX5_CLK_USB_PHY2_GATE]     = imx_clk_gate2("usb_phy2_gate", "usb_phy_sel", MXC_CCM_CCGR4, 12);
+       clk[IMX5_CLK_I2C3_GATE]         = imx_clk_gate2("i2c3_gate", "per_root", MXC_CCM_CCGR1, 22);
+
+       clk[IMX5_CLK_CKO1_SEL]          = imx_clk_mux("cko1_sel", MXC_CCM_CCOSR, 0, 4,
+                                               mx53_cko1_sel, ARRAY_SIZE(mx53_cko1_sel));
+       clk[IMX5_CLK_CKO1_PODF]         = imx_clk_divider("cko1_podf", "cko1_sel", MXC_CCM_CCOSR, 4, 3);
+       clk[IMX5_CLK_CKO1]              = imx_clk_gate2("cko1", "cko1_podf", MXC_CCM_CCOSR, 7);
+
+       clk[IMX5_CLK_CKO2_SEL]          = imx_clk_mux("cko2_sel", MXC_CCM_CCOSR, 16, 5,
+                                               mx53_cko2_sel, ARRAY_SIZE(mx53_cko2_sel));
+       clk[IMX5_CLK_CKO2_PODF]         = imx_clk_divider("cko2_podf", "cko2_sel", MXC_CCM_CCOSR, 21, 3);
+       clk[IMX5_CLK_CKO2]              = imx_clk_gate2("cko2", "cko2_podf", MXC_CCM_CCOSR, 24);
+
+       for (i = 0; i < ARRAY_SIZE(clk); i++)
+               if (IS_ERR(clk[i]))
+                       pr_err("i.MX50 clk %d: register failed with %ld\n",
+                               i, PTR_ERR(clk[i]));
+
+       clk_data.clks = clk;
+       clk_data.clk_num = ARRAY_SIZE(clk);
+       of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+
+       mx5_clocks_common_init(0, 0, 0, 0);
+
+       /* set SDHC root clock to 200MHZ*/
+       clk_set_rate(clk[IMX5_CLK_ESDHC_A_PODF], 200000000);
+       clk_set_rate(clk[IMX5_CLK_ESDHC_B_PODF], 200000000);
+
+       clk_prepare_enable(clk[IMX5_CLK_IIM_GATE]);
+       imx_print_silicon_rev("i.MX50", IMX_CHIP_REVISION_1_1);
+       clk_disable_unprepare(clk[IMX5_CLK_IIM_GATE]);
+
+       r = clk_round_rate(clk[IMX5_CLK_USBOH3_PER_GATE], 54000000);
+       clk_set_rate(clk[IMX5_CLK_USBOH3_PER_GATE], r);
+
+       np = of_find_compatible_node(NULL, NULL, "fsl,imx50-gpt");
+       base = of_iomap(np, 0);
+       WARN_ON(!base);
+       irq = irq_of_parse_and_map(np, 0);
+       mxc_timer_init(base, irq);
+}
+CLK_OF_DECLARE(imx50_ccm, "fsl,imx50-ccm", mx50_clocks_init);
+
 int __init mx51_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
                        unsigned long rate_ckih1, unsigned long rate_ckih2)
 {
@@ -372,38 +389,40 @@ int __init mx51_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
        u32 val;
        struct device_node *np;
 
-       clk[pll1_sw] = imx_clk_pllv2("pll1_sw", "osc", MX51_DPLL1_BASE);
-       clk[pll2_sw] = imx_clk_pllv2("pll2_sw", "osc", MX51_DPLL2_BASE);
-       clk[pll3_sw] = imx_clk_pllv2("pll3_sw", "osc", MX51_DPLL3_BASE);
-       clk[ipu_di0_sel] = imx_clk_mux("ipu_di0_sel", MXC_CCM_CSCMR2, 26, 3,
-                               mx51_ipu_di0_sel, ARRAY_SIZE(mx51_ipu_di0_sel));
-       clk[ipu_di1_sel] = imx_clk_mux("ipu_di1_sel", MXC_CCM_CSCMR2, 29, 3,
-                               mx51_ipu_di1_sel, ARRAY_SIZE(mx51_ipu_di1_sel));
-       clk[tve_ext_sel] = imx_clk_mux_flags("tve_ext_sel", MXC_CCM_CSCMR1, 6, 1,
-                               mx51_tve_ext_sel, ARRAY_SIZE(mx51_tve_ext_sel), CLK_SET_RATE_PARENT);
-       clk[tve_s] = imx_clk_mux("tve_sel", MXC_CCM_CSCMR1, 7, 1,
-                               mx51_tve_sel, ARRAY_SIZE(mx51_tve_sel));
-       clk[tve_gate] = imx_clk_gate2("tve_gate", "tve_sel", MXC_CCM_CCGR2, 30);
-       clk[tve_pred] = imx_clk_divider("tve_pred", "pll3_sw", MXC_CCM_CDCDR, 28, 3);
-       clk[esdhc1_per_gate] = imx_clk_gate2("esdhc1_per_gate", "esdhc_a_podf", MXC_CCM_CCGR3, 2);
-       clk[esdhc2_per_gate] = imx_clk_gate2("esdhc2_per_gate", "esdhc_b_podf", MXC_CCM_CCGR3, 6);
-       clk[esdhc3_per_gate] = imx_clk_gate2("esdhc3_per_gate", "esdhc_c_sel", MXC_CCM_CCGR3, 10);
-       clk[esdhc4_per_gate] = imx_clk_gate2("esdhc4_per_gate", "esdhc_d_sel", MXC_CCM_CCGR3, 14);
-       clk[usb_phy_gate] = imx_clk_gate2("usb_phy_gate", "usb_phy_sel", MXC_CCM_CCGR2, 0);
-       clk[hsi2c_gate] = imx_clk_gate2("hsi2c_gate", "ipg", MXC_CCM_CCGR1, 22);
-       clk[mipi_hsc1_gate] = imx_clk_gate2("mipi_hsc1_gate", "ipg", MXC_CCM_CCGR4, 6);
-       clk[mipi_hsc2_gate] = imx_clk_gate2("mipi_hsc2_gate", "ipg", MXC_CCM_CCGR4, 8);
-       clk[mipi_esc_gate] = imx_clk_gate2("mipi_esc_gate", "ipg", MXC_CCM_CCGR4, 10);
-       clk[mipi_hsp_gate] = imx_clk_gate2("mipi_hsp_gate", "ipg", MXC_CCM_CCGR4, 12);
-       clk[spdif_xtal_sel] = imx_clk_mux("spdif_xtal_sel", MXC_CCM_CSCMR1, 2, 2,
-                               mx51_spdif_xtal_sel, ARRAY_SIZE(mx51_spdif_xtal_sel));
-       clk[spdif1_sel] = imx_clk_mux("spdif1_sel", MXC_CCM_CSCMR2, 2, 2,
-                               spdif_sel, ARRAY_SIZE(spdif_sel));
-       clk[spdif1_pred] = imx_clk_divider("spdif1_pred", "spdif1_sel", MXC_CCM_CDCDR, 16, 3);
-       clk[spdif1_podf] = imx_clk_divider("spdif1_podf", "spdif1_pred", MXC_CCM_CDCDR, 9, 6);
-       clk[spdif1_com_sel] = imx_clk_mux("spdif1_com_sel", MXC_CCM_CSCMR2, 5, 1,
-                               mx51_spdif1_com_sel, ARRAY_SIZE(mx51_spdif1_com_sel));
-       clk[spdif1_gate] = imx_clk_gate2("spdif1_gate", "spdif1_com_sel", MXC_CCM_CCGR5, 28);
+       clk[IMX5_CLK_PLL1_SW]           = imx_clk_pllv2("pll1_sw", "osc", MX51_DPLL1_BASE);
+       clk[IMX5_CLK_PLL2_SW]           = imx_clk_pllv2("pll2_sw", "osc", MX51_DPLL2_BASE);
+       clk[IMX5_CLK_PLL3_SW]           = imx_clk_pllv2("pll3_sw", "osc", MX51_DPLL3_BASE);
+       clk[IMX5_CLK_LP_APM]            = imx_clk_mux("lp_apm", MXC_CCM_CCSR, 9, 1,
+                                               lp_apm_sel, ARRAY_SIZE(lp_apm_sel));
+       clk[IMX5_CLK_IPU_DI0_SEL]       = imx_clk_mux("ipu_di0_sel", MXC_CCM_CSCMR2, 26, 3,
+                                               mx51_ipu_di0_sel, ARRAY_SIZE(mx51_ipu_di0_sel));
+       clk[IMX5_CLK_IPU_DI1_SEL]       = imx_clk_mux("ipu_di1_sel", MXC_CCM_CSCMR2, 29, 3,
+                                               mx51_ipu_di1_sel, ARRAY_SIZE(mx51_ipu_di1_sel));
+       clk[IMX5_CLK_TVE_EXT_SEL]       = imx_clk_mux_flags("tve_ext_sel", MXC_CCM_CSCMR1, 6, 1,
+                                               mx51_tve_ext_sel, ARRAY_SIZE(mx51_tve_ext_sel), CLK_SET_RATE_PARENT);
+       clk[IMX5_CLK_TVE_SEL]           = imx_clk_mux("tve_sel", MXC_CCM_CSCMR1, 7, 1,
+                                               mx51_tve_sel, ARRAY_SIZE(mx51_tve_sel));
+       clk[IMX5_CLK_TVE_GATE]          = imx_clk_gate2("tve_gate", "tve_sel", MXC_CCM_CCGR2, 30);
+       clk[IMX5_CLK_TVE_PRED]          = imx_clk_divider("tve_pred", "pll3_sw", MXC_CCM_CDCDR, 28, 3);
+       clk[IMX5_CLK_ESDHC1_PER_GATE]   = imx_clk_gate2("esdhc1_per_gate", "esdhc_a_podf", MXC_CCM_CCGR3, 2);
+       clk[IMX5_CLK_ESDHC2_PER_GATE]   = imx_clk_gate2("esdhc2_per_gate", "esdhc_b_podf", MXC_CCM_CCGR3, 6);
+       clk[IMX5_CLK_ESDHC3_PER_GATE]   = imx_clk_gate2("esdhc3_per_gate", "esdhc_c_sel", MXC_CCM_CCGR3, 10);
+       clk[IMX5_CLK_ESDHC4_PER_GATE]   = imx_clk_gate2("esdhc4_per_gate", "esdhc_d_sel", MXC_CCM_CCGR3, 14);
+       clk[IMX5_CLK_USB_PHY_GATE]      = imx_clk_gate2("usb_phy_gate", "usb_phy_sel", MXC_CCM_CCGR2, 0);
+       clk[IMX5_CLK_HSI2C_GATE]        = imx_clk_gate2("hsi2c_gate", "ipg", MXC_CCM_CCGR1, 22);
+       clk[IMX5_CLK_MIPI_HSC1_GATE]    = imx_clk_gate2("mipi_hsc1_gate", "ipg", MXC_CCM_CCGR4, 6);
+       clk[IMX5_CLK_MIPI_HSC2_GATE]    = imx_clk_gate2("mipi_hsc2_gate", "ipg", MXC_CCM_CCGR4, 8);
+       clk[IMX5_CLK_MIPI_ESC_GATE]     = imx_clk_gate2("mipi_esc_gate", "ipg", MXC_CCM_CCGR4, 10);
+       clk[IMX5_CLK_MIPI_HSP_GATE]     = imx_clk_gate2("mipi_hsp_gate", "ipg", MXC_CCM_CCGR4, 12);
+       clk[IMX5_CLK_SPDIF_XTAL_SEL]    = imx_clk_mux("spdif_xtal_sel", MXC_CCM_CSCMR1, 2, 2,
+                                               mx51_spdif_xtal_sel, ARRAY_SIZE(mx51_spdif_xtal_sel));
+       clk[IMX5_CLK_SPDIF1_SEL]        = imx_clk_mux("spdif1_sel", MXC_CCM_CSCMR2, 2, 2,
+                                               spdif_sel, ARRAY_SIZE(spdif_sel));
+       clk[IMX5_CLK_SPDIF1_PRED]       = imx_clk_divider("spdif1_pred", "spdif1_sel", MXC_CCM_CDCDR, 16, 3);
+       clk[IMX5_CLK_SPDIF1_PODF]       = imx_clk_divider("spdif1_podf", "spdif1_pred", MXC_CCM_CDCDR, 9, 6);
+       clk[IMX5_CLK_SPDIF1_COM_SEL]    = imx_clk_mux("spdif1_com_sel", MXC_CCM_CSCMR2, 5, 1,
+                                               mx51_spdif1_com_sel, ARRAY_SIZE(mx51_spdif1_com_sel));
+       clk[IMX5_CLK_SPDIF1_GATE]       = imx_clk_gate2("spdif1_gate", "spdif1_com_sel", MXC_CCM_CCGR5, 28);
 
        for (i = 0; i < ARRAY_SIZE(clk); i++)
                if (IS_ERR(clk[i]))
@@ -417,37 +436,37 @@ int __init mx51_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
 
        mx5_clocks_common_init(rate_ckil, rate_osc, rate_ckih1, rate_ckih2);
 
-       clk_register_clkdev(clk[hsi2c_gate], NULL, "imx21-i2c.2");
-       clk_register_clkdev(clk[mx51_mipi], "mipi_hsp", NULL);
-       clk_register_clkdev(clk[vpu_gate], NULL, "imx51-vpu.0");
-       clk_register_clkdev(clk[fec_gate], NULL, "imx27-fec.0");
-       clk_register_clkdev(clk[usb_phy_gate], "phy", "mxc-ehci.0");
-       clk_register_clkdev(clk[esdhc1_ipg_gate], "ipg", "sdhci-esdhc-imx51.0");
-       clk_register_clkdev(clk[dummy], "ahb", "sdhci-esdhc-imx51.0");
-       clk_register_clkdev(clk[esdhc1_per_gate], "per", "sdhci-esdhc-imx51.0");
-       clk_register_clkdev(clk[esdhc2_ipg_gate], "ipg", "sdhci-esdhc-imx51.1");
-       clk_register_clkdev(clk[dummy], "ahb", "sdhci-esdhc-imx51.1");
-       clk_register_clkdev(clk[esdhc2_per_gate], "per", "sdhci-esdhc-imx51.1");
-       clk_register_clkdev(clk[esdhc3_ipg_gate], "ipg", "sdhci-esdhc-imx51.2");
-       clk_register_clkdev(clk[dummy], "ahb", "sdhci-esdhc-imx51.2");
-       clk_register_clkdev(clk[esdhc3_per_gate], "per", "sdhci-esdhc-imx51.2");
-       clk_register_clkdev(clk[esdhc4_ipg_gate], "ipg", "sdhci-esdhc-imx51.3");
-       clk_register_clkdev(clk[dummy], "ahb", "sdhci-esdhc-imx51.3");
-       clk_register_clkdev(clk[esdhc4_per_gate], "per", "sdhci-esdhc-imx51.3");
+       clk_register_clkdev(clk[IMX5_CLK_HSI2C_GATE], NULL, "imx21-i2c.2");
+       clk_register_clkdev(clk[IMX5_CLK_MX51_MIPI], "mipi_hsp", NULL);
+       clk_register_clkdev(clk[IMX5_CLK_VPU_GATE], NULL, "imx51-vpu.0");
+       clk_register_clkdev(clk[IMX5_CLK_FEC_GATE], NULL, "imx27-fec.0");
+       clk_register_clkdev(clk[IMX5_CLK_USB_PHY_GATE], "phy", "mxc-ehci.0");
+       clk_register_clkdev(clk[IMX5_CLK_ESDHC1_IPG_GATE], "ipg", "sdhci-esdhc-imx51.0");
+       clk_register_clkdev(clk[IMX5_CLK_DUMMY], "ahb", "sdhci-esdhc-imx51.0");
+       clk_register_clkdev(clk[IMX5_CLK_ESDHC1_PER_GATE], "per", "sdhci-esdhc-imx51.0");
+       clk_register_clkdev(clk[IMX5_CLK_ESDHC2_IPG_GATE], "ipg", "sdhci-esdhc-imx51.1");
+       clk_register_clkdev(clk[IMX5_CLK_DUMMY], "ahb", "sdhci-esdhc-imx51.1");
+       clk_register_clkdev(clk[IMX5_CLK_ESDHC2_PER_GATE], "per", "sdhci-esdhc-imx51.1");
+       clk_register_clkdev(clk[IMX5_CLK_ESDHC3_IPG_GATE], "ipg", "sdhci-esdhc-imx51.2");
+       clk_register_clkdev(clk[IMX5_CLK_DUMMY], "ahb", "sdhci-esdhc-imx51.2");
+       clk_register_clkdev(clk[IMX5_CLK_ESDHC3_PER_GATE], "per", "sdhci-esdhc-imx51.2");
+       clk_register_clkdev(clk[IMX5_CLK_ESDHC4_IPG_GATE], "ipg", "sdhci-esdhc-imx51.3");
+       clk_register_clkdev(clk[IMX5_CLK_DUMMY], "ahb", "sdhci-esdhc-imx51.3");
+       clk_register_clkdev(clk[IMX5_CLK_ESDHC4_PER_GATE], "per", "sdhci-esdhc-imx51.3");
 
        /* set the usboh3 parent to pll2_sw */
-       clk_set_parent(clk[usboh3_sel], clk[pll2_sw]);
+       clk_set_parent(clk[IMX5_CLK_USBOH3_SEL], clk[IMX5_CLK_PLL2_SW]);
 
        /* set SDHC root clock to 166.25MHZ*/
-       clk_set_rate(clk[esdhc_a_podf], 166250000);
-       clk_set_rate(clk[esdhc_b_podf], 166250000);
+       clk_set_rate(clk[IMX5_CLK_ESDHC_A_PODF], 166250000);
+       clk_set_rate(clk[IMX5_CLK_ESDHC_B_PODF], 166250000);
 
        /* System timer */
        mxc_timer_init(MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR), MX51_INT_GPT);
 
-       clk_prepare_enable(clk[iim_gate]);
+       clk_prepare_enable(clk[IMX5_CLK_IIM_GATE]);
        imx_print_silicon_rev("i.MX51", mx51_revision());
-       clk_disable_unprepare(clk[iim_gate]);
+       clk_disable_unprepare(clk[IMX5_CLK_IIM_GATE]);
 
        /*
         * Reference Manual says: Functionality of CCDR[18] and CLPCR[23] is no
@@ -479,57 +498,59 @@ static void __init mx53_clocks_init(struct device_node *np)
        unsigned long r;
        void __iomem *base;
 
-       clk[pll1_sw] = imx_clk_pllv2("pll1_sw", "osc", MX53_DPLL1_BASE);
-       clk[pll2_sw] = imx_clk_pllv2("pll2_sw", "osc", MX53_DPLL2_BASE);
-       clk[pll3_sw] = imx_clk_pllv2("pll3_sw", "osc", MX53_DPLL3_BASE);
-       clk[pll4_sw] = imx_clk_pllv2("pll4_sw", "osc", MX53_DPLL4_BASE);
-
-       clk[ldb_di1_div_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7);
-       clk[ldb_di1_div] = imx_clk_divider_flags("ldb_di1_div", "ldb_di1_div_3_5", MXC_CCM_CSCMR2, 11, 1, 0);
-       clk[ldb_di1_sel] = imx_clk_mux_flags("ldb_di1_sel", MXC_CCM_CSCMR2, 9, 1,
-                               mx53_ldb_di1_sel, ARRAY_SIZE(mx53_ldb_di1_sel), CLK_SET_RATE_PARENT);
-       clk[di_pll4_podf] = imx_clk_divider("di_pll4_podf", "pll4_sw", MXC_CCM_CDCDR, 16, 3);
-       clk[ldb_di0_div_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7);
-       clk[ldb_di0_div] = imx_clk_divider_flags("ldb_di0_div", "ldb_di0_div_3_5", MXC_CCM_CSCMR2, 10, 1, 0);
-       clk[ldb_di0_sel] = imx_clk_mux_flags("ldb_di0_sel", MXC_CCM_CSCMR2, 8, 1,
-                               mx53_ldb_di0_sel, ARRAY_SIZE(mx53_ldb_di0_sel), CLK_SET_RATE_PARENT);
-       clk[ldb_di0_gate] = imx_clk_gate2("ldb_di0_gate", "ldb_di0_div", MXC_CCM_CCGR6, 28);
-       clk[ldb_di1_gate] = imx_clk_gate2("ldb_di1_gate", "ldb_di1_div", MXC_CCM_CCGR6, 30);
-       clk[ipu_di0_sel] = imx_clk_mux("ipu_di0_sel", MXC_CCM_CSCMR2, 26, 3,
-                               mx53_ipu_di0_sel, ARRAY_SIZE(mx53_ipu_di0_sel));
-       clk[ipu_di1_sel] = imx_clk_mux("ipu_di1_sel", MXC_CCM_CSCMR2, 29, 3,
-                               mx53_ipu_di1_sel, ARRAY_SIZE(mx53_ipu_di1_sel));
-       clk[tve_ext_sel] = imx_clk_mux_flags("tve_ext_sel", MXC_CCM_CSCMR1, 6, 1,
-                               mx53_tve_ext_sel, ARRAY_SIZE(mx53_tve_ext_sel), CLK_SET_RATE_PARENT);
-       clk[tve_gate] = imx_clk_gate2("tve_gate", "tve_pred", MXC_CCM_CCGR2, 30);
-       clk[tve_pred] = imx_clk_divider("tve_pred", "tve_ext_sel", MXC_CCM_CDCDR, 28, 3);
-       clk[esdhc1_per_gate] = imx_clk_gate2("esdhc1_per_gate", "esdhc_a_podf", MXC_CCM_CCGR3, 2);
-       clk[esdhc2_per_gate] = imx_clk_gate2("esdhc2_per_gate", "esdhc_c_sel", MXC_CCM_CCGR3, 6);
-       clk[esdhc3_per_gate] = imx_clk_gate2("esdhc3_per_gate", "esdhc_b_podf", MXC_CCM_CCGR3, 10);
-       clk[esdhc4_per_gate] = imx_clk_gate2("esdhc4_per_gate", "esdhc_d_sel", MXC_CCM_CCGR3, 14);
-       clk[usb_phy1_gate] = imx_clk_gate2("usb_phy1_gate", "usb_phy_sel", MXC_CCM_CCGR4, 10);
-       clk[usb_phy2_gate] = imx_clk_gate2("usb_phy2_gate", "usb_phy_sel", MXC_CCM_CCGR4, 12);
-       clk[can_sel] = imx_clk_mux("can_sel", MXC_CCM_CSCMR2, 6, 2,
-                               mx53_can_sel, ARRAY_SIZE(mx53_can_sel));
-       clk[can1_serial_gate] = imx_clk_gate2("can1_serial_gate", "can_sel", MXC_CCM_CCGR6, 22);
-       clk[can1_ipg_gate] = imx_clk_gate2("can1_ipg_gate", "ipg", MXC_CCM_CCGR6, 20);
-       clk[ocram] = imx_clk_gate2("ocram", "ahb", MXC_CCM_CCGR6, 2);
-       clk[can2_serial_gate] = imx_clk_gate2("can2_serial_gate", "can_sel", MXC_CCM_CCGR4, 8);
-       clk[can2_ipg_gate] = imx_clk_gate2("can2_ipg_gate", "ipg", MXC_CCM_CCGR4, 6);
-       clk[i2c3_gate] = imx_clk_gate2("i2c3_gate", "per_root", MXC_CCM_CCGR1, 22);
-       clk[sata_gate] = imx_clk_gate2("sata_gate", "ipg", MXC_CCM_CCGR4, 2);
-
-       clk[cko1_sel] = imx_clk_mux("cko1_sel", MXC_CCM_CCOSR, 0, 4,
-                               mx53_cko1_sel, ARRAY_SIZE(mx53_cko1_sel));
-       clk[cko1_podf] = imx_clk_divider("cko1_podf", "cko1_sel", MXC_CCM_CCOSR, 4, 3);
-       clk[cko1] = imx_clk_gate2("cko1", "cko1_podf", MXC_CCM_CCOSR, 7);
-
-       clk[cko2_sel] = imx_clk_mux("cko2_sel", MXC_CCM_CCOSR, 16, 5,
-                               mx53_cko2_sel, ARRAY_SIZE(mx53_cko2_sel));
-       clk[cko2_podf] = imx_clk_divider("cko2_podf", "cko2_sel", MXC_CCM_CCOSR, 21, 3);
-       clk[cko2] = imx_clk_gate2("cko2", "cko2_podf", MXC_CCM_CCOSR, 24);
-       clk[spdif_xtal_sel] = imx_clk_mux("spdif_xtal_sel", MXC_CCM_CSCMR1, 2, 2,
-                               mx53_spdif_xtal_sel, ARRAY_SIZE(mx53_spdif_xtal_sel));
+       clk[IMX5_CLK_PLL1_SW]           = imx_clk_pllv2("pll1_sw", "osc", MX53_DPLL1_BASE);
+       clk[IMX5_CLK_PLL2_SW]           = imx_clk_pllv2("pll2_sw", "osc", MX53_DPLL2_BASE);
+       clk[IMX5_CLK_PLL3_SW]           = imx_clk_pllv2("pll3_sw", "osc", MX53_DPLL3_BASE);
+       clk[IMX5_CLK_PLL4_SW]           = imx_clk_pllv2("pll4_sw", "osc", MX53_DPLL4_BASE);
+
+       clk[IMX5_CLK_LP_APM]            = imx_clk_mux("lp_apm", MXC_CCM_CCSR, 10, 1,
+                                               lp_apm_sel, ARRAY_SIZE(lp_apm_sel));
+       clk[IMX5_CLK_LDB_DI1_DIV_3_5]   = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7);
+       clk[IMX5_CLK_LDB_DI1_DIV]       = imx_clk_divider_flags("ldb_di1_div", "ldb_di1_div_3_5", MXC_CCM_CSCMR2, 11, 1, 0);
+       clk[IMX5_CLK_LDB_DI1_SEL]       = imx_clk_mux_flags("ldb_di1_sel", MXC_CCM_CSCMR2, 9, 1,
+                                               mx53_ldb_di1_sel, ARRAY_SIZE(mx53_ldb_di1_sel), CLK_SET_RATE_PARENT);
+       clk[IMX5_CLK_DI_PLL4_PODF]      = imx_clk_divider("di_pll4_podf", "pll4_sw", MXC_CCM_CDCDR, 16, 3);
+       clk[IMX5_CLK_LDB_DI0_DIV_3_5]   = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7);
+       clk[IMX5_CLK_LDB_DI0_DIV]       = imx_clk_divider_flags("ldb_di0_div", "ldb_di0_div_3_5", MXC_CCM_CSCMR2, 10, 1, 0);
+       clk[IMX5_CLK_LDB_DI0_SEL]       = imx_clk_mux_flags("ldb_di0_sel", MXC_CCM_CSCMR2, 8, 1,
+                                               mx53_ldb_di0_sel, ARRAY_SIZE(mx53_ldb_di0_sel), CLK_SET_RATE_PARENT);
+       clk[IMX5_CLK_LDB_DI0_GATE]      = imx_clk_gate2("ldb_di0_gate", "ldb_di0_div", MXC_CCM_CCGR6, 28);
+       clk[IMX5_CLK_LDB_DI1_GATE]      = imx_clk_gate2("ldb_di1_gate", "ldb_di1_div", MXC_CCM_CCGR6, 30);
+       clk[IMX5_CLK_IPU_DI0_SEL]       = imx_clk_mux("ipu_di0_sel", MXC_CCM_CSCMR2, 26, 3,
+                                               mx53_ipu_di0_sel, ARRAY_SIZE(mx53_ipu_di0_sel));
+       clk[IMX5_CLK_IPU_DI1_SEL]       = imx_clk_mux("ipu_di1_sel", MXC_CCM_CSCMR2, 29, 3,
+                                               mx53_ipu_di1_sel, ARRAY_SIZE(mx53_ipu_di1_sel));
+       clk[IMX5_CLK_TVE_EXT_SEL]       = imx_clk_mux_flags("tve_ext_sel", MXC_CCM_CSCMR1, 6, 1,
+                                               mx53_tve_ext_sel, ARRAY_SIZE(mx53_tve_ext_sel), CLK_SET_RATE_PARENT);
+       clk[IMX5_CLK_TVE_GATE]          = imx_clk_gate2("tve_gate", "tve_pred", MXC_CCM_CCGR2, 30);
+       clk[IMX5_CLK_TVE_PRED]          = imx_clk_divider("tve_pred", "tve_ext_sel", MXC_CCM_CDCDR, 28, 3);
+       clk[IMX5_CLK_ESDHC1_PER_GATE]   = imx_clk_gate2("esdhc1_per_gate", "esdhc_a_podf", MXC_CCM_CCGR3, 2);
+       clk[IMX5_CLK_ESDHC2_PER_GATE]   = imx_clk_gate2("esdhc2_per_gate", "esdhc_c_sel", MXC_CCM_CCGR3, 6);
+       clk[IMX5_CLK_ESDHC3_PER_GATE]   = imx_clk_gate2("esdhc3_per_gate", "esdhc_b_podf", MXC_CCM_CCGR3, 10);
+       clk[IMX5_CLK_ESDHC4_PER_GATE]   = imx_clk_gate2("esdhc4_per_gate", "esdhc_d_sel", MXC_CCM_CCGR3, 14);
+       clk[IMX5_CLK_USB_PHY1_GATE]     = imx_clk_gate2("usb_phy1_gate", "usb_phy_sel", MXC_CCM_CCGR4, 10);
+       clk[IMX5_CLK_USB_PHY2_GATE]     = imx_clk_gate2("usb_phy2_gate", "usb_phy_sel", MXC_CCM_CCGR4, 12);
+       clk[IMX5_CLK_CAN_SEL]           = imx_clk_mux("can_sel", MXC_CCM_CSCMR2, 6, 2,
+                                               mx53_can_sel, ARRAY_SIZE(mx53_can_sel));
+       clk[IMX5_CLK_CAN1_SERIAL_GATE]  = imx_clk_gate2("can1_serial_gate", "can_sel", MXC_CCM_CCGR6, 22);
+       clk[IMX5_CLK_CAN1_IPG_GATE]     = imx_clk_gate2("can1_ipg_gate", "ipg", MXC_CCM_CCGR6, 20);
+       clk[IMX5_CLK_OCRAM]             = imx_clk_gate2("ocram", "ahb", MXC_CCM_CCGR6, 2);
+       clk[IMX5_CLK_CAN2_SERIAL_GATE]  = imx_clk_gate2("can2_serial_gate", "can_sel", MXC_CCM_CCGR4, 8);
+       clk[IMX5_CLK_CAN2_IPG_GATE]     = imx_clk_gate2("can2_ipg_gate", "ipg", MXC_CCM_CCGR4, 6);
+       clk[IMX5_CLK_I2C3_GATE]         = imx_clk_gate2("i2c3_gate", "per_root", MXC_CCM_CCGR1, 22);
+       clk[IMX5_CLK_SATA_GATE]         = imx_clk_gate2("sata_gate", "ipg", MXC_CCM_CCGR4, 2);
+
+       clk[IMX5_CLK_CKO1_SEL]          = imx_clk_mux("cko1_sel", MXC_CCM_CCOSR, 0, 4,
+                                               mx53_cko1_sel, ARRAY_SIZE(mx53_cko1_sel));
+       clk[IMX5_CLK_CKO1_PODF]         = imx_clk_divider("cko1_podf", "cko1_sel", MXC_CCM_CCOSR, 4, 3);
+       clk[IMX5_CLK_CKO1]              = imx_clk_gate2("cko1", "cko1_podf", MXC_CCM_CCOSR, 7);
+
+       clk[IMX5_CLK_CKO2_SEL]          = imx_clk_mux("cko2_sel", MXC_CCM_CCOSR, 16, 5,
+                                               mx53_cko2_sel, ARRAY_SIZE(mx53_cko2_sel));
+       clk[IMX5_CLK_CKO2_PODF]         = imx_clk_divider("cko2_podf", "cko2_sel", MXC_CCM_CCOSR, 21, 3);
+       clk[IMX5_CLK_CKO2]              = imx_clk_gate2("cko2", "cko2_podf", MXC_CCM_CCOSR, 24);
+       clk[IMX5_CLK_SPDIF_XTAL_SEL]    = imx_clk_mux("spdif_xtal_sel", MXC_CCM_CSCMR1, 2, 2,
+                                               mx53_spdif_xtal_sel, ARRAY_SIZE(mx53_spdif_xtal_sel));
 
        for (i = 0; i < ARRAY_SIZE(clk); i++)
                if (IS_ERR(clk[i]))
@@ -542,33 +563,36 @@ static void __init mx53_clocks_init(struct device_node *np)
 
        mx5_clocks_common_init(0, 0, 0, 0);
 
-       clk_register_clkdev(clk[vpu_gate], NULL, "imx53-vpu.0");
-       clk_register_clkdev(clk[i2c3_gate], NULL, "imx21-i2c.2");
-       clk_register_clkdev(clk[fec_gate], NULL, "imx25-fec.0");
-       clk_register_clkdev(clk[usb_phy1_gate], "usb_phy1", "mxc-ehci.0");
-       clk_register_clkdev(clk[esdhc1_ipg_gate], "ipg", "sdhci-esdhc-imx53.0");
-       clk_register_clkdev(clk[dummy], "ahb", "sdhci-esdhc-imx53.0");
-       clk_register_clkdev(clk[esdhc1_per_gate], "per", "sdhci-esdhc-imx53.0");
-       clk_register_clkdev(clk[esdhc2_ipg_gate], "ipg", "sdhci-esdhc-imx53.1");
-       clk_register_clkdev(clk[dummy], "ahb", "sdhci-esdhc-imx53.1");
-       clk_register_clkdev(clk[esdhc2_per_gate], "per", "sdhci-esdhc-imx53.1");
-       clk_register_clkdev(clk[esdhc3_ipg_gate], "ipg", "sdhci-esdhc-imx53.2");
-       clk_register_clkdev(clk[dummy], "ahb", "sdhci-esdhc-imx53.2");
-       clk_register_clkdev(clk[esdhc3_per_gate], "per", "sdhci-esdhc-imx53.2");
-       clk_register_clkdev(clk[esdhc4_ipg_gate], "ipg", "sdhci-esdhc-imx53.3");
-       clk_register_clkdev(clk[dummy], "ahb", "sdhci-esdhc-imx53.3");
-       clk_register_clkdev(clk[esdhc4_per_gate], "per", "sdhci-esdhc-imx53.3");
+       clk_register_clkdev(clk[IMX5_CLK_VPU_GATE], NULL, "imx53-vpu.0");
+       clk_register_clkdev(clk[IMX5_CLK_I2C3_GATE], NULL, "imx21-i2c.2");
+       clk_register_clkdev(clk[IMX5_CLK_FEC_GATE], NULL, "imx25-fec.0");
+       clk_register_clkdev(clk[IMX5_CLK_USB_PHY1_GATE], "usb_phy1", "mxc-ehci.0");
+       clk_register_clkdev(clk[IMX5_CLK_ESDHC1_IPG_GATE], "ipg", "sdhci-esdhc-imx53.0");
+       clk_register_clkdev(clk[IMX5_CLK_DUMMY], "ahb", "sdhci-esdhc-imx53.0");
+       clk_register_clkdev(clk[IMX5_CLK_ESDHC1_PER_GATE], "per", "sdhci-esdhc-imx53.0");
+       clk_register_clkdev(clk[IMX5_CLK_ESDHC2_IPG_GATE], "ipg", "sdhci-esdhc-imx53.1");
+       clk_register_clkdev(clk[IMX5_CLK_DUMMY], "ahb", "sdhci-esdhc-imx53.1");
+       clk_register_clkdev(clk[IMX5_CLK_ESDHC2_PER_GATE], "per", "sdhci-esdhc-imx53.1");
+       clk_register_clkdev(clk[IMX5_CLK_ESDHC3_IPG_GATE], "ipg", "sdhci-esdhc-imx53.2");
+       clk_register_clkdev(clk[IMX5_CLK_DUMMY], "ahb", "sdhci-esdhc-imx53.2");
+       clk_register_clkdev(clk[IMX5_CLK_ESDHC3_PER_GATE], "per", "sdhci-esdhc-imx53.2");
+       clk_register_clkdev(clk[IMX5_CLK_ESDHC4_IPG_GATE], "ipg", "sdhci-esdhc-imx53.3");
+       clk_register_clkdev(clk[IMX5_CLK_DUMMY], "ahb", "sdhci-esdhc-imx53.3");
+       clk_register_clkdev(clk[IMX5_CLK_ESDHC4_PER_GATE], "per", "sdhci-esdhc-imx53.3");
 
        /* set SDHC root clock to 200MHZ*/
-       clk_set_rate(clk[esdhc_a_podf], 200000000);
-       clk_set_rate(clk[esdhc_b_podf], 200000000);
+       clk_set_rate(clk[IMX5_CLK_ESDHC_A_PODF], 200000000);
+       clk_set_rate(clk[IMX5_CLK_ESDHC_B_PODF], 200000000);
+
+       /* move can bus clk to 24MHz */
+       clk_set_parent(clk[IMX5_CLK_CAN_SEL], clk[IMX5_CLK_LP_APM]);
 
-       clk_prepare_enable(clk[iim_gate]);
+       clk_prepare_enable(clk[IMX5_CLK_IIM_GATE]);
        imx_print_silicon_rev("i.MX53", mx53_revision());
-       clk_disable_unprepare(clk[iim_gate]);
+       clk_disable_unprepare(clk[IMX5_CLK_IIM_GATE]);
 
-       r = clk_round_rate(clk[usboh3_per_gate], 54000000);
-       clk_set_rate(clk[usboh3_per_gate], r);
+       r = clk_round_rate(clk[IMX5_CLK_USBOH3_PER_GATE], 54000000);
+       clk_set_rate(clk[IMX5_CLK_USBOH3_PER_GATE], r);
 
        np = of_find_compatible_node(NULL, NULL, "fsl,imx53-gpt");
        base = of_iomap(np, 0);
index 04cfd0fcb0e56db864d28f4240b2341ae20927b0..74ecceb4b5f46ba83d8a01972f985fff2b5c7581 100644 (file)
@@ -114,7 +114,7 @@ static struct clk *clk[clk_max];
 static struct clk_onecell_data clk_data;
 
 static enum mx6q_clks const clks_init_on[] __initconst = {
-       mmdc_ch0_axi, rom, pll1_sys,
+       mmdc_ch0_axi, rom, arm,
 };
 
 static struct clk_div_table clk_enet_ref_table[] = {
index c0c4ef55e35bd7e522b4f83d038d50f752265db4..a747a7df175f08d3884c72d2138743befb4f3160 100644 (file)
@@ -63,7 +63,7 @@ static struct clk_div_table video_div_table[] = {
        { }
 };
 
-static struct clk *clks[IMX6SL_CLK_CLK_END];
+static struct clk *clks[IMX6SL_CLK_END];
 static struct clk_onecell_data clk_data;
 
 static void __init imx6sl_clocks_init(struct device_node *ccm_node)
index c1eaee3469542d08660d0a4aecc81a1f468f5041..d21d14ca46c1786b4cc42f47976cbdc6cc384d5d 100644 (file)
  *
  * PLL clock version 1, found on i.MX1/21/25/27/31/35
  */
+
+#define MFN_BITS       (10)
+#define MFN_SIGN       (BIT(MFN_BITS - 1))
+#define MFN_MASK       (MFN_SIGN - 1)
+
 struct clk_pllv1 {
        struct clk_hw   hw;
        void __iomem    *base;
@@ -25,6 +30,11 @@ struct clk_pllv1 {
 
 #define to_clk_pllv1(clk) (container_of(clk, struct clk_pllv1, clk))
 
+static inline bool mfn_is_negative(unsigned int mfn)
+{
+       return !cpu_is_mx1() && !cpu_is_mx21() && (mfn & MFN_SIGN);
+}
+
 static unsigned long clk_pllv1_recalc_rate(struct clk_hw *hw,
                unsigned long parent_rate)
 {
@@ -58,10 +68,15 @@ static unsigned long clk_pllv1_recalc_rate(struct clk_hw *hw,
 
        /*
         * On all i.MXs except i.MX1 and i.MX21 mfn is a 10bit
-        * 2's complements number
+        * 2's complements number.
+        * On i.MX27 the bit 9 is the sign bit.
         */
-       if (!cpu_is_mx1() && !cpu_is_mx21() && mfn >= 0x200)
-               mfn_abs = 0x400 - mfn;
+       if (mfn_is_negative(mfn)) {
+               if (cpu_is_mx27())
+                       mfn_abs = mfn & MFN_MASK;
+               else
+                       mfn_abs = BIT(MFN_BITS) - mfn;
+       }
 
        rate = parent_rate * 2;
        rate /= pd + 1;
@@ -70,7 +85,7 @@ static unsigned long clk_pllv1_recalc_rate(struct clk_hw *hw,
 
        do_div(ll, mfd + 1);
 
-       if (!cpu_is_mx1() && !cpu_is_mx21() && mfn >= 0x200)
+       if (mfn_is_negative(mfn))
                ll = -ll;
 
        ll = (rate * mfi) + ll;
index b169a396d93bfcf193c83d7329a6fdc290101425..ecd66d8e20b62b84419f0c0bcc4a54d0c5ef8a02 100644 (file)
@@ -298,6 +298,11 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
        clk[VF610_CLK_FLEXCAN0] = imx_clk_gate2("flexcan0", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(0));
        clk[VF610_CLK_FLEXCAN1] = imx_clk_gate2("flexcan1", "ipg_bus", CCM_CCGR9, CCM_CCGRx_CGn(4));
 
+       clk[VF610_CLK_DMAMUX0] = imx_clk_gate2("dmamux0", "platform_bus", CCM_CCGR0, CCM_CCGRx_CGn(4));
+       clk[VF610_CLK_DMAMUX1] = imx_clk_gate2("dmamux1", "platform_bus", CCM_CCGR0, CCM_CCGRx_CGn(5));
+       clk[VF610_CLK_DMAMUX2] = imx_clk_gate2("dmamux2", "platform_bus", CCM_CCGR6, CCM_CCGRx_CGn(1));
+       clk[VF610_CLK_DMAMUX3] = imx_clk_gate2("dmamux3", "platform_bus", CCM_CCGR6, CCM_CCGRx_CGn(2));
+
        clk_set_parent(clk[VF610_CLK_QSPI0_SEL], clk[VF610_CLK_PLL1_PFD4]);
        clk_set_rate(clk[VF610_CLK_QSPI0_X4_DIV], clk_get_rate(clk[VF610_CLK_QSPI0_SEL]) / 2);
        clk_set_rate(clk[VF610_CLK_QSPI0_X2_DIV], clk_get_rate(clk[VF610_CLK_QSPI0_X4_DIV]) / 2);
index 24a7899e36a8abed143d2bfdadcf854e0970a14c..59c3b9b26bb40bbabe40f471d6a420efee43a1c2 100644 (file)
@@ -108,6 +108,7 @@ void tzic_handle_irq(struct pt_regs *);
 #define imx27_handle_irq avic_handle_irq
 #define imx31_handle_irq avic_handle_irq
 #define imx35_handle_irq avic_handle_irq
+#define imx50_handle_irq tzic_handle_irq
 #define imx51_handle_irq tzic_handle_irq
 #define imx53_handle_irq tzic_handle_irq
 
index 818a1cc2fe45e4ead8c2f4cd367ba24148d2aa30..e1e70ef7bc2d2f62916d9da5c84c87f18881e569 100644 (file)
@@ -25,7 +25,7 @@ static void __init imx31_dt_init(void)
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
-static const char *imx31_dt_board_compat[] __initdata = {
+static const char *imx31_dt_board_compat[] __initconst = {
        "fsl,imx31",
        NULL
 };
index bece8a65e6f01893e9e58df0799b580b8c356365..0230d78d141322f3288a5728f294ea4be9376ec9 100644 (file)
@@ -29,7 +29,7 @@ static void __init imx51_dt_init(void)
        platform_device_register_full(&devinfo);
 }
 
-static const char *imx51_dt_board_compat[] __initdata = {
+static const char *imx51_dt_board_compat[] __initconst = {
        "fsl,imx51",
        NULL
 };
index 5b2dabba330fd7ad69c534aa3714bc821d77342a..6e3175dc0c0aaed7dccca96b9767f4c0d4baf3ae 100644 (file)
@@ -24,7 +24,6 @@
 
 struct mxc_extra_irq
 {
-       int (*set_priority)(unsigned char irq, unsigned char prio);
        int (*set_irq_fiq)(unsigned int irq, unsigned int type);
 };
 
index 771362d1fbee712247242c3d7c5d9956b7f58e70..65e4c53e1554b134ff458ba3960f060bec130a1b 100644 (file)
@@ -53,7 +53,7 @@ static const struct imxi2c_platform_data
 };
 
 #define TSC2007_IRQGPIO                IMX_GPIO_NR(3, 2)
-static int tsc2007_get_pendown_state(void)
+static int tsc2007_get_pendown_state(struct device *dev)
 {
        return !gpio_get_value(TSC2007_IRQGPIO);
 }
index 9b5ddf5bbd339e4aff4012256762144c77332557..1fba2b8e983f7e9104ac506a8fccc951f361611b 100644 (file)
@@ -121,7 +121,7 @@ static const struct imxuart_platform_data uart_pdata __initconst = {
        .flags = IMXUART_HAVE_RTSCTS,
 };
 
-static int tsc2007_get_pendown_state(void)
+static int tsc2007_get_pendown_state(struct device *dev)
 {
        if (mx51_revision() < IMX_CHIP_REVISION_3_0)
                return !gpio_get_value(TSC2007_IRQGPIO_REV2);
diff --git a/arch/arm/mach-imx/mach-imx50.c b/arch/arm/mach-imx/mach-imx50.c
new file mode 100644 (file)
index 0000000..77b77a9
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2013 Greg Ungerer <gerg@uclinux.org>
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/of_platform.h>
+#include <asm/mach/arch.h>
+
+#include "common.h"
+
+static void __init imx50_dt_init(void)
+{
+       mxc_arch_reset_init_dt();
+
+       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char *imx50_dt_board_compat[] __initconst = {
+       "fsl,imx50",
+       NULL
+};
+
+DT_MACHINE_START(IMX50_DT, "Freescale i.MX50 (Device Tree Support)")
+       .map_io         = mx53_map_io,
+       .init_irq       = mx53_init_irq,
+       .handle_irq     = imx50_handle_irq,
+       .init_machine   = imx50_dt_init,
+       .dt_compat      = imx50_dt_board_compat,
+       .restart        = mxc_restart,
+MACHINE_END
index c9c4d8d96931daf05794c4bab73facedb9fb943c..65850908a4b4d88b31e32f3a750df7b13c45fcec 100644 (file)
@@ -31,7 +31,7 @@ static void __init imx53_dt_init(void)
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
-static const char *imx53_dt_board_compat[] __initdata = {
+static const char *imx53_dt_board_compat[] __initconst = {
        "fsl,imx53",
        NULL
 };
index d0cfb225ec9aa5e9e9599b6e3ee5c6c32870e0f7..d2ea6e60ea7b2042f6ff8d73503db73f95fd9770 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/cpu.h>
+#include <linux/delay.h>
 #include <linux/export.h>
 #include <linux/init.h>
 #include <linux/io.h>
@@ -23,6 +24,7 @@
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/pm_opp.h>
+#include <linux/pci.h>
 #include <linux/phy.h>
 #include <linux/reboot.h>
 #include <linux/regmap.h>
@@ -78,6 +80,34 @@ static int ksz9031rn_phy_fixup(struct phy_device *dev)
        return 0;
 }
 
+/*
+ * fixup for PLX PEX8909 bridge to configure GPIO1-7 as output High
+ * as they are used for slots1-7 PERST#
+ */
+static void ventana_pciesw_early_fixup(struct pci_dev *dev)
+{
+       u32 dw;
+
+       if (!of_machine_is_compatible("gw,ventana"))
+               return;
+
+       if (dev->devfn != 0)
+               return;
+
+       pci_read_config_dword(dev, 0x62c, &dw);
+       dw |= 0xaaa8; // GPIO1-7 outputs
+       pci_write_config_dword(dev, 0x62c, dw);
+
+       pci_read_config_dword(dev, 0x644, &dw);
+       dw |= 0xfe;   // GPIO1-7 output high
+       pci_write_config_dword(dev, 0x644, dw);
+
+       msleep(100);
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8609, ventana_pciesw_early_fixup);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8606, ventana_pciesw_early_fixup);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8604, ventana_pciesw_early_fixup);
+
 static int ar8031_phy_fixup(struct phy_device *dev)
 {
        u16 val;
@@ -243,7 +273,7 @@ static void __init imx6q_init_irq(void)
        irqchip_init();
 }
 
-static const char *imx6q_dt_compat[] __initdata = {
+static const char *imx6q_dt_compat[] __initconst = {
        "fsl,imx6dl",
        "fsl,imx6q",
        NULL,
index 2f952e3fcf899172b40ffc7e1cfff7aa94718bc2..cca183a1129193afdd2002da7c09a2fcfc50bb6f 100644 (file)
@@ -61,7 +61,7 @@ static void __init imx6sl_init_irq(void)
        irqchip_init();
 }
 
-static const char *imx6sl_dt_compat[] __initdata = {
+static const char *imx6sl_dt_compat[] __initconst = {
        "fsl,imx6sl",
        NULL,
 };
index af0cb8a9dc4898827b1c569506b761fb4b476787..2d8aef5a6efab86ff0a9bbecae52f64f02f301f8 100644 (file)
@@ -26,7 +26,7 @@ static void __init vf610_init_irq(void)
        irqchip_init();
 }
 
-static const char *vf610_dt_compat[] __initdata = {
+static const char *vf610_dt_compat[] __initconst = {
        "fsl,vf610",
        NULL,
 };
index d1d52600f458c3604eb77c4bcfae51432b2a932c..4c112021aa4ef8511121a0237179a5b7a6ebcf4f 100644 (file)
@@ -89,15 +89,7 @@ void __init imx51_init_early(void)
 
 void __init imx53_init_early(void)
 {
-       struct device_node *np;
-       void __iomem *base;
-
        mxc_set_cpu_type(MXC_CPU_MX53);
-
-       np = of_find_compatible_node(NULL, NULL, "fsl,imx53-iomuxc");
-       base = of_iomap(np, 0);
-       WARN_ON(!base);
-       mxc_iomux_v3_init(base);
        imx_src_init();
 }
 
index 9b6638aadeaa8958069f018c734c077593410044..1a3a5f6157706c7f9400d3bfd61ffffcce1b9424 100644 (file)
@@ -111,7 +111,7 @@ static void gpt_irq_acknowledge(void)
 
 static void __iomem *sched_clock_reg;
 
-static u32 notrace mxc_read_sched_clock(void)
+static u64 notrace mxc_read_sched_clock(void)
 {
        return sched_clock_reg ? __raw_readl(sched_clock_reg) : 0;
 }
@@ -123,7 +123,7 @@ static int __init mxc_clocksource_init(struct clk *timer_clk)
 
        sched_clock_reg = reg;
 
-       setup_sched_clock(mxc_read_sched_clock, 32, c);
+       sched_clock_register(mxc_read_sched_clock, 32, c);
        return clocksource_mmio_init(reg, "mxc_timer1", c, 200, 32,
                        clocksource_mmio_readl_up);
 }
index d50dc2dbfd89e53571a716b80e01bd567400ea36..17c0fe6274357842d2769efc2f0bf2ac5241b982 100644 (file)
@@ -63,6 +63,9 @@
 
 /* Base address to the AP system controller */
 void __iomem *ap_syscon_base;
+/* Base address to the external bus interface */
+static void __iomem *ebi_base;
+
 
 /*
  * All IO addresses are mapped onto VA 0xFFFx.xxxx, where x.xxxx
@@ -72,15 +75,11 @@ void __iomem *ap_syscon_base;
  * just for now).
  */
 #define VA_IC_BASE     __io_address(INTEGRATOR_IC_BASE)
-#define VA_EBI_BASE    __io_address(INTEGRATOR_EBI_BASE)
-#define VA_CMIC_BASE   __io_address(INTEGRATOR_HDR_IC)
 
 /*
  * Logical      Physical
  * ef000000                    Cache flush
- * f1000000    10000000        Core module registers
  * f1100000    11000000        System controller registers
- * f1200000    12000000        EBI registers
  * f1300000    13000000        Counter/Timer
  * f1400000    14000000        Interrupt controller
  * f1600000    16000000        UART 0
@@ -91,16 +90,6 @@ void __iomem *ap_syscon_base;
 
 static struct map_desc ap_io_desc[] __initdata __maybe_unused = {
        {
-               .virtual        = IO_ADDRESS(INTEGRATOR_HDR_BASE),
-               .pfn            = __phys_to_pfn(INTEGRATOR_HDR_BASE),
-               .length         = SZ_4K,
-               .type           = MT_DEVICE
-       }, {
-               .virtual        = IO_ADDRESS(INTEGRATOR_EBI_BASE),
-               .pfn            = __phys_to_pfn(INTEGRATOR_EBI_BASE),
-               .length         = SZ_4K,
-               .type           = MT_DEVICE
-       }, {
                .virtual        = IO_ADDRESS(INTEGRATOR_CT_BASE),
                .pfn            = __phys_to_pfn(INTEGRATOR_CT_BASE),
                .length         = SZ_4K,
@@ -174,9 +163,6 @@ device_initcall(irq_syscore_init);
 /*
  * Flash handling.
  */
-#define EBI_CSR1 (VA_EBI_BASE + INTEGRATOR_EBI_CSR1_OFFSET)
-#define EBI_LOCK (VA_EBI_BASE + INTEGRATOR_EBI_LOCK_OFFSET)
-
 static int ap_flash_init(struct platform_device *dev)
 {
        u32 tmp;
@@ -184,13 +170,15 @@ static int ap_flash_init(struct platform_device *dev)
        writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP,
               ap_syscon_base + INTEGRATOR_SC_CTRLC_OFFSET);
 
-       tmp = readl(EBI_CSR1) | INTEGRATOR_EBI_WRITE_ENABLE;
-       writel(tmp, EBI_CSR1);
+       tmp = readl(ebi_base + INTEGRATOR_EBI_CSR1_OFFSET) |
+               INTEGRATOR_EBI_WRITE_ENABLE;
+       writel(tmp, ebi_base + INTEGRATOR_EBI_CSR1_OFFSET);
 
-       if (!(readl(EBI_CSR1) & INTEGRATOR_EBI_WRITE_ENABLE)) {
-               writel(0xa05f, EBI_LOCK);
-               writel(tmp, EBI_CSR1);
-               writel(0, EBI_LOCK);
+       if (!(readl(ebi_base + INTEGRATOR_EBI_CSR1_OFFSET)
+             & INTEGRATOR_EBI_WRITE_ENABLE)) {
+               writel(0xa05f, ebi_base + INTEGRATOR_EBI_LOCK_OFFSET);
+               writel(tmp, ebi_base + INTEGRATOR_EBI_CSR1_OFFSET);
+               writel(0, ebi_base + INTEGRATOR_EBI_LOCK_OFFSET);
        }
        return 0;
 }
@@ -202,13 +190,15 @@ static void ap_flash_exit(struct platform_device *dev)
        writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP,
               ap_syscon_base + INTEGRATOR_SC_CTRLC_OFFSET);
 
-       tmp = readl(EBI_CSR1) & ~INTEGRATOR_EBI_WRITE_ENABLE;
-       writel(tmp, EBI_CSR1);
+       tmp = readl(ebi_base + INTEGRATOR_EBI_CSR1_OFFSET) &
+               ~INTEGRATOR_EBI_WRITE_ENABLE;
+       writel(tmp, ebi_base + INTEGRATOR_EBI_CSR1_OFFSET);
 
-       if (readl(EBI_CSR1) & INTEGRATOR_EBI_WRITE_ENABLE) {
-               writel(0xa05f, EBI_LOCK);
-               writel(tmp, EBI_CSR1);
-               writel(0, EBI_LOCK);
+       if (readl(ebi_base + INTEGRATOR_EBI_CSR1_OFFSET) &
+           INTEGRATOR_EBI_WRITE_ENABLE) {
+               writel(0xa05f, ebi_base + INTEGRATOR_EBI_LOCK_OFFSET);
+               writel(tmp, ebi_base + INTEGRATOR_EBI_CSR1_OFFSET);
+               writel(0, ebi_base + INTEGRATOR_EBI_LOCK_OFFSET);
        }
 }
 
@@ -277,7 +267,7 @@ struct amba_pl010_data ap_uart_data = {
 
 static unsigned long timer_reload;
 
-static u32 notrace integrator_read_sched_clock(void)
+static u64 notrace integrator_read_sched_clock(void)
 {
        return -readl((void __iomem *) TIMER2_VA_BASE + TIMER_VALUE);
 }
@@ -298,7 +288,7 @@ static void integrator_clocksource_init(unsigned long inrate,
 
        clocksource_mmio_init(base + TIMER_VALUE, "timer2",
                        rate, 200, 16, clocksource_mmio_readl_down);
-       setup_sched_clock(integrator_read_sched_clock, 16, rate);
+       sched_clock_register(integrator_read_sched_clock, 16, rate);
 }
 
 static void __iomem * clkevt_base;
@@ -475,11 +465,17 @@ static const struct of_device_id ap_syscon_match[] = {
        { },
 };
 
+static const struct of_device_id ebi_match[] = {
+       { .compatible = "arm,external-bus-interface"},
+       { },
+};
+
 static void __init ap_init_of(void)
 {
        unsigned long sc_dec;
        struct device_node *root;
        struct device_node *syscon;
+       struct device_node *ebi;
        struct device *parent;
        struct soc_device *soc_dev;
        struct soc_device_attribute *soc_dev_attr;
@@ -495,10 +491,16 @@ static void __init ap_init_of(void)
        syscon = of_find_matching_node(root, ap_syscon_match);
        if (!syscon)
                return;
+       ebi = of_find_matching_node(root, ebi_match);
+       if (!ebi)
+               return;
 
        ap_syscon_base = of_iomap(syscon, 0);
        if (!ap_syscon_base)
                return;
+       ebi_base = of_iomap(ebi, 0);
+       if (!ebi_base)
+               return;
 
        ap_sc_id = readl(ap_syscon_base);
 
index 4fc0a195de0103e865b4827af89dd101f6336241..5e84149d1790dccf090a4c0b7373d07b7435b91b 100644 (file)
@@ -64,9 +64,6 @@ static void __iomem *intcp_con_base;
 
 /*
  * Logical      Physical
- * f1000000    10000000        Core module registers
- * f1100000    11000000        System controller registers
- * f1200000    12000000        EBI registers
  * f1300000    13000000        Counter/Timer
  * f1400000    14000000        Interrupt controller
  * f1600000    16000000        UART 0
@@ -74,21 +71,10 @@ static void __iomem *intcp_con_base;
  * f1a00000    1a000000        Debug LEDs
  * fc900000    c9000000        GPIO
  * fca00000    ca000000        SIC
- * fcb00000    cb000000        CP system control
  */
 
 static struct map_desc intcp_io_desc[] __initdata __maybe_unused = {
        {
-               .virtual        = IO_ADDRESS(INTEGRATOR_HDR_BASE),
-               .pfn            = __phys_to_pfn(INTEGRATOR_HDR_BASE),
-               .length         = SZ_4K,
-               .type           = MT_DEVICE
-       }, {
-               .virtual        = IO_ADDRESS(INTEGRATOR_EBI_BASE),
-               .pfn            = __phys_to_pfn(INTEGRATOR_EBI_BASE),
-               .length         = SZ_4K,
-               .type           = MT_DEVICE
-       }, {
                .virtual        = IO_ADDRESS(INTEGRATOR_CT_BASE),
                .pfn            = __phys_to_pfn(INTEGRATOR_CT_BASE),
                .length         = SZ_4K,
index 9edaf4734fa84956d27539b2411e581aa1ef76a5..bc9d8ec2918efded94977dfeda9993c644421486 100644 (file)
@@ -475,7 +475,7 @@ void __init ixp4xx_sys_init(void)
 /*
  * sched_clock()
  */
-static u32 notrace ixp4xx_read_sched_clock(void)
+static u64 notrace ixp4xx_read_sched_clock(void)
 {
        return *IXP4XX_OSTS;
 }
@@ -493,7 +493,7 @@ unsigned long ixp4xx_timer_freq = IXP4XX_TIMER_FREQ;
 EXPORT_SYMBOL(ixp4xx_timer_freq);
 static void __init ixp4xx_clocksource_init(void)
 {
-       setup_sched_clock(ixp4xx_read_sched_clock, 32, ixp4xx_timer_freq);
+       sched_clock_register(ixp4xx_read_sched_clock, 32, ixp4xx_timer_freq);
 
        clocksource_mmio_init(NULL, "OSTS", ixp4xx_timer_freq, 200, 32,
                        ixp4xx_clocksource_read);
index 9caa4fe95913c672a6b874c5b8b8d573294ae857..78188159484d79e760d8ec22a6303a81d100aeae 100644 (file)
  * warranty of any kind, whether express or implied.
  */
 
+#include <linux/clk.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_net.h>
 #include <linux/of_platform.h>
-#include <linux/clk-provider.h>
 #include <linux/dma-mapping.h>
 #include <linux/irqchip.h>
 #include <linux/kexec.h>
 #include <asm/mach/arch.h>
-#include <asm/mach/map.h>
 #include <mach/bridge-regs.h>
-#include <linux/platform_data/usb-ehci-orion.h>
-#include <plat/irq.h>
 #include <plat/common.h>
 #include "common.h"
 
-/*
- * There are still devices that doesn't know about DT yet.  Get clock
- * gates here and add a clock lookup alias, so that old platform
- * devices still work.
-*/
-
-static void __init kirkwood_legacy_clk_init(void)
-{
-
-       struct device_node *np = of_find_compatible_node(
-               NULL, NULL, "marvell,kirkwood-gating-clock");
-       struct of_phandle_args clkspec;
-       struct clk *clk;
-
-       clkspec.np = np;
-       clkspec.args_count = 1;
-
-       /*
-        * The ethernet interfaces forget the MAC address assigned by
-        * u-boot if the clocks are turned off. Until proper DT support
-        * is available we always enable them for now.
-        */
-       clkspec.args[0] = CGC_BIT_GE0;
-       clk = of_clk_get_from_provider(&clkspec);
-       clk_prepare_enable(clk);
-
-       clkspec.args[0] = CGC_BIT_GE1;
-       clk = of_clk_get_from_provider(&clkspec);
-       clk_prepare_enable(clk);
-}
-
 #define MV643XX_ETH_MAC_ADDR_LOW       0x0414
 #define MV643XX_ETH_MAC_ADDR_HIGH      0x0418
 
@@ -140,7 +106,7 @@ eth_fixup_skip:
 
 static void __init kirkwood_dt_init(void)
 {
-       pr_info("Kirkwood: %s, TCLK=%d.\n", kirkwood_id(), kirkwood_tclk);
+       pr_info("Kirkwood: %s.\n", kirkwood_id());
 
        /*
         * Disable propagation of mbus errors to the CPU local bus,
@@ -156,8 +122,6 @@ static void __init kirkwood_dt_init(void)
 
        kirkwood_cpufreq_init();
        kirkwood_cpuidle_init();
-       /* Setup clocks for legacy devices */
-       kirkwood_legacy_clk_init();
 
        kirkwood_pm_init();
        kirkwood_dt_eth_fixup();
index 7ac41e83cfefd42b0e219a2f6cfc173f0624ab2f..024022d91fe3e453dc4462fae847d12cb87dcdfa 100644 (file)
@@ -61,7 +61,7 @@ static inline uint32_t timer_read(void)
        return __raw_readl(mmp_timer_base + TMR_CVWR(1));
 }
 
-static u32 notrace mmp_read_sched_clock(void)
+static u64 notrace mmp_read_sched_clock(void)
 {
        return timer_read();
 }
@@ -195,7 +195,7 @@ void __init timer_init(int irq)
 {
        timer_config();
 
-       setup_sched_clock(mmp_read_sched_clock, 32, CLOCK_TICK_RATE);
+       sched_clock_register(mmp_read_sched_clock, 32, CLOCK_TICK_RATE);
 
        ckevt.cpumask = cpumask_of(0);
 
index 1e9c3383daba7e6995f301527eb480b5ebdb8662..fd1644987534e6a54db4a7b157f9df817eff222e 100644 (file)
@@ -187,7 +187,7 @@ static struct notifier_block msm_timer_cpu_nb = {
        .notifier_call = msm_timer_cpu_notify,
 };
 
-static notrace u32 msm_sched_clock_read(void)
+static u64 notrace msm_sched_clock_read(void)
 {
        return msm_clocksource.read(&msm_clocksource);
 }
@@ -229,7 +229,7 @@ err:
        res = clocksource_register_hz(cs, dgt_hz);
        if (res)
                pr_err("clocksource_register failed\n");
-       setup_sched_clock(msm_sched_clock_read, sched_bits, dgt_hz);
+       sched_clock_register(msm_sched_clock_read, sched_bits, dgt_hz);
 }
 
 #ifdef CONFIG_OF
index 58adf2fd9cfc98ea03f6b1f8cfe037ceb01bd78b..4e9d58148ca7e3031cbbdaa5dba2bb5aa0607619 100644 (file)
@@ -27,6 +27,7 @@
 #include <asm/smp_plat.h>
 #include <asm/cacheflush.h>
 #include "armada-370-xp.h"
+#include "coherency.h"
 
 unsigned long coherency_phys_base;
 static void __iomem *coherency_base;
index df33ad8a6c08935b9fea023c570c8881b22ecb8b..760226c4135309b4ec79ddda47ba9fb18c31a3f4 100644 (file)
@@ -14,7 +14,9 @@
 #ifndef __MACH_370_XP_COHERENCY_H
 #define __MACH_370_XP_COHERENCY_H
 
-int set_cpu_coherent(int cpu_id, int smp_group_id);
+extern unsigned long coherency_phys_base;
+
+int set_cpu_coherent(unsigned int cpu_id, int smp_group_id);
 int coherency_init(void);
 
 #endif /* __MACH_370_XP_COHERENCY_H */
index e366010e1d91097432383f7c9c6cca7e220a6bc7..0e6016fadcc58a3ae249eba501d31c11b7e1062e 100644 (file)
@@ -26,7 +26,6 @@ void armada_370_xp_handle_irq(struct pt_regs *regs);
 
 void armada_xp_cpu_die(unsigned int cpu);
 int armada_370_xp_coherency_init(void);
-int armada_370_xp_pmsu_init(void);
 void armada_xp_secondary_startup(void);
 extern struct smp_operations armada_xp_smp_ops;
 #endif
index b228b6a80c85cc9693b3246de4272bd115c0e561..d95e910471684544d63e853308419d68036ec01c 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/errno.h>
 #include <linux/smp.h>
 #include <asm/proc-fns.h>
+#include "common.h"
 
 /*
  * platform-specific code to shutdown a CPU
index ff69c2df298b6b2ce69f742c7f5b6dbcf179f821..a6da03f5b24ec921090af5508a2b6d87a66c7197 100644 (file)
@@ -46,7 +46,7 @@ static struct clk *__init get_cpu_clk(int cpu)
        return cpu_clk;
 }
 
-void __init set_secondary_cpus_clock(void)
+static void __init set_secondary_cpus_clock(void)
 {
        int thiscpu, cpu;
        unsigned long rate;
@@ -94,7 +94,7 @@ static void __init armada_xp_smp_init_cpus(void)
        set_smp_cross_call(armada_mpic_send_doorbell);
 }
 
-void __init armada_xp_smp_prepare_cpus(unsigned int max_cpus)
+static void __init armada_xp_smp_prepare_cpus(unsigned int max_cpus)
 {
        struct device_node *node;
        struct resource res;
index 27fc4f049474ed94b07cef00dfe3304b1165369c..d71ef53107c4e9a530a558458d31eecf92039bd2 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/io.h>
 #include <linux/smp.h>
 #include <asm/smp_plat.h>
+#include "pmsu.h"
 
 static void __iomem *pmsu_mp_base;
 static void __iomem *pmsu_reset_base;
@@ -58,7 +59,7 @@ int armada_xp_boot_cpu(unsigned int cpu_id, void *boot_addr)
 }
 #endif
 
-int __init armada_370_xp_pmsu_init(void)
+static int __init armada_370_xp_pmsu_init(void)
 {
        struct device_node *np;
 
index 5175083cdb34650802288789c55a82aee8c20d08..a7fb89a5b5d9818db3174916d0e7e0589ed53456 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/of_address.h>
 #include <linux/io.h>
 #include <linux/reboot.h>
+#include "common.h"
 
 static void __iomem *system_controller_base;
 
@@ -39,14 +40,14 @@ struct mvebu_system_controller {
 };
 static struct mvebu_system_controller *mvebu_sc;
 
-const struct mvebu_system_controller armada_370_xp_system_controller = {
+static const struct mvebu_system_controller armada_370_xp_system_controller = {
        .rstoutn_mask_offset = 0x60,
        .system_soft_reset_offset = 0x64,
        .rstoutn_mask_reset_out_en = 0x1,
        .system_soft_reset = 0x1,
 };
 
-const struct mvebu_system_controller orion_system_controller = {
+static const struct mvebu_system_controller orion_system_controller = {
        .rstoutn_mask_offset = 0x108,
        .system_soft_reset_offset = 0x10c,
        .rstoutn_mask_reset_out_en = 0x4,
index 1dc5acd4fc99bb7f0001217214d53199dd89174d..2e7cec86e50e94bdb95b2905216614525fe39ff0 100644 (file)
@@ -157,6 +157,8 @@ enum mac_oui {
        OUI_FSL,
        OUI_DENX,
        OUI_CRYSTALFONTZ,
+       OUI_I2SE,
+       OUI_ARMADEUS,
 };
 
 static void __init update_fec_mac_prop(enum mac_oui oui)
@@ -211,6 +213,16 @@ static void __init update_fec_mac_prop(enum mac_oui oui)
                        macaddr[1] = 0xb9;
                        macaddr[2] = 0xe1;
                        break;
+               case OUI_I2SE:
+                       macaddr[0] = 0x00;
+                       macaddr[1] = 0x01;
+                       macaddr[2] = 0x87;
+                       break;
+               case OUI_ARMADEUS:
+                       macaddr[0] = 0x00;
+                       macaddr[1] = 0x1e;
+                       macaddr[2] = 0xac;
+                       break;
                }
                val = ocotp[i];
                macaddr[3] = (val >> 16) & 0xff;
@@ -236,6 +248,11 @@ static void __init imx28_evk_init(void)
        mxs_saif_clkmux_select(MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0);
 }
 
+static void __init imx28_apf28_init(void)
+{
+       update_fec_mac_prop(OUI_ARMADEUS);
+}
+
 static int apx4devkit_phy_fixup(struct phy_device *phy)
 {
        phy->dev_flags |= MICREL_PHY_50MHZ_CLK;
@@ -330,6 +347,11 @@ static void __init crystalfontz_init(void)
        update_fec_mac_prop(OUI_CRYSTALFONTZ);
 }
 
+static void __init duckbill_init(void)
+{
+       update_fec_mac_prop(OUI_I2SE);
+}
+
 static void __init m28cu3_init(void)
 {
        update_fec_mac_prop(OUI_DENX);
@@ -426,6 +448,11 @@ static int __init mxs_restart_init(void)
        return 0;
 }
 
+static void __init eukrea_mbmx283lc_init(void)
+{
+       mxs_saif_clkmux_select(MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0);
+}
+
 static void __init mxs_machine_init(void)
 {
        struct device_node *root;
@@ -458,10 +485,16 @@ static void __init mxs_machine_init(void)
 
        if (of_machine_is_compatible("fsl,imx28-evk"))
                imx28_evk_init();
+       if (of_machine_is_compatible("armadeus,imx28-apf28"))
+               imx28_apf28_init();
        else if (of_machine_is_compatible("bluegiga,apx4devkit"))
                apx4devkit_init();
        else if (of_machine_is_compatible("crystalfontz,cfa10036"))
                crystalfontz_init();
+       else if (of_machine_is_compatible("eukrea,mbmx283lc"))
+               eukrea_mbmx283lc_init();
+       else if (of_machine_is_compatible("i2se,duckbill"))
+               duckbill_init();
        else if (of_machine_is_compatible("msr,m28cu3"))
                m28cu3_init();
 
index 6b5f298d66382abe2f380952c32fda20bcfdfa56..a7588cfd0286d9293c73ea76723cc9e17b612ac5 100644 (file)
@@ -181,7 +181,7 @@ static __init void omap_init_mpu_timer(unsigned long rate)
  * ---------------------------------------------------------------------------
  */
 
-static u32 notrace omap_mpu_read_sched_clock(void)
+static u64 notrace omap_mpu_read_sched_clock(void)
 {
        return ~omap_mpu_timer_read(1);
 }
@@ -193,7 +193,7 @@ static void __init omap_init_clocksource(unsigned long rate)
                        "%s: can't register clocksource!\n";
 
        omap_mpu_timer_start(1, ~0, 1);
-       setup_sched_clock(omap_mpu_read_sched_clock, 32, rate);
+       sched_clock_register(omap_mpu_read_sched_clock, 32, rate);
 
        if (clocksource_mmio_init(&timer->read_tim, "mpu_timer2", rate,
                        300, 32, clocksource_mmio_readl_down))
index 19f1652e94cfbf5e1f09d2d4cc27e44087cc68d7..8d972ff18c561111317aa96d61c0b9fda2d8cade 100644 (file)
@@ -131,6 +131,24 @@ DT_MACHINE_START(OMAP3_GP_DT, "Generic OMAP3-GP (Flattened Device Tree)")
        .dt_compat      = omap3_gp_boards_compat,
        .restart        = omap3xxx_restart,
 MACHINE_END
+
+static const char *am3517_boards_compat[] __initdata = {
+       "ti,am3517",
+       NULL,
+};
+
+DT_MACHINE_START(AM3517_DT, "Generic AM3517 (Flattened Device Tree)")
+       .reserve        = omap_reserve,
+       .map_io         = omap3_map_io,
+       .init_early     = am35xx_init_early,
+       .init_irq       = omap_intc_of_init,
+       .handle_irq     = omap3_intc_handle_irq,
+       .init_machine   = omap_generic_init,
+       .init_late      = omap3_init_late,
+       .init_time      = omap3_gptimer_timer_init,
+       .dt_compat      = am3517_boards_compat,
+       .restart        = omap3xxx_restart,
+MACHINE_END
 #endif
 
 #ifdef CONFIG_SOC_AM33XX
index 365bfd3d9c68b8486f23049a71889484c60eb793..dadccc91488c64e94c06e9bf93b54bc5c294e26e 100644 (file)
@@ -223,7 +223,7 @@ void __init omap_4430sdp_display_init_of(void)
 static struct connector_dvi_platform_data omap3_igep2_dvi_connector_pdata = {
        .name                   = "dvi",
        .source                 = "tfp410.0",
-       .i2c_bus_num            = 3,
+       .i2c_bus_num            = 2,
 };
 
 static struct platform_device omap3_igep2_dvi_connector_device = {
index cd22262a2cc09a1ad5b951254500a11afdfc8e30..07b68d5a7940e402705568114b7e0523cdda44f8 100644 (file)
@@ -244,7 +244,7 @@ static struct map_desc omap44xx_io_desc[] __initdata = {
                .virtual        = OMAP4_SRAM_VA,
                .pfn            = __phys_to_pfn(OMAP4_SRAM_PA),
                .length         = PAGE_SIZE,
-               .type           = MT_MEMORY_SO,
+               .type           = MT_MEMORY_RW_SO,
        },
 #endif
 
@@ -282,7 +282,7 @@ static struct map_desc omap54xx_io_desc[] __initdata = {
                .virtual        = OMAP4_SRAM_VA,
                .pfn            = __phys_to_pfn(OMAP4_SRAM_PA),
                .length         = PAGE_SIZE,
-               .type           = MT_MEMORY_SO,
+               .type           = MT_MEMORY_RW_SO,
        },
 #endif
 };
index b39efd46abf991827169a6c17a6aa91f3dfeb39f..b5110f19abc7b256484289336c7f28cb4bec913d 100644 (file)
@@ -87,7 +87,7 @@ void __init omap_barriers_init(void)
        dram_io_desc[0].virtual = OMAP4_DRAM_BARRIER_VA;
        dram_io_desc[0].pfn = __phys_to_pfn(paddr);
        dram_io_desc[0].length = size;
-       dram_io_desc[0].type = MT_MEMORY_SO;
+       dram_io_desc[0].type = MT_MEMORY_RW_SO;
        iotable_init(dram_io_desc, ARRAY_SIZE(dram_io_desc));
        dram_sync = (void __iomem *) dram_io_desc[0].virtual;
        sram_sync = (void __iomem *) OMAP4_SRAM_VA;
index 53f0735817bb7cf984f3fada24c7e8960941860c..e0a398cf28d80a409e25055c19ad44baef25d7fc 100644 (file)
@@ -183,6 +183,10 @@ static int omap_device_build_from_dt(struct platform_device *pdev)
 odbfd_exit1:
        kfree(hwmods);
 odbfd_exit:
+       /* if data/we are at fault.. load up a fail handler */
+       if (ret)
+               pdev->dev.pm_domain = &omap_device_fail_pm_domain;
+
        return ret;
 }
 
@@ -604,6 +608,19 @@ static int _od_runtime_resume(struct device *dev)
 
        return pm_generic_runtime_resume(dev);
 }
+
+static int _od_fail_runtime_suspend(struct device *dev)
+{
+       dev_warn(dev, "%s: FIXME: missing hwmod/omap_dev info\n", __func__);
+       return -ENODEV;
+}
+
+static int _od_fail_runtime_resume(struct device *dev)
+{
+       dev_warn(dev, "%s: FIXME: missing hwmod/omap_dev info\n", __func__);
+       return -ENODEV;
+}
+
 #endif
 
 #ifdef CONFIG_SUSPEND
@@ -657,6 +674,13 @@ static int _od_resume_noirq(struct device *dev)
 #define _od_resume_noirq NULL
 #endif
 
+struct dev_pm_domain omap_device_fail_pm_domain = {
+       .ops = {
+               SET_RUNTIME_PM_OPS(_od_fail_runtime_suspend,
+                                  _od_fail_runtime_resume, NULL)
+       }
+};
+
 struct dev_pm_domain omap_device_pm_domain = {
        .ops = {
                SET_RUNTIME_PM_OPS(_od_runtime_suspend, _od_runtime_resume,
index 17ca1aec271033d7551c2ffd4cf22fd0c4724fb2..78c02b355179894126f5e2e75f835fc1d753060a 100644 (file)
@@ -29,6 +29,7 @@
 #include "omap_hwmod.h"
 
 extern struct dev_pm_domain omap_device_pm_domain;
+extern struct dev_pm_domain omap_device_fail_pm_domain;
 
 /* omap_device._state values */
 #define OMAP_DEVICE_STATE_UNKNOWN      0
index e3f0ecaf87dd76c3b075c389173ac89faff04a6a..8a1b5e0bad40df2adbab8b202e0dd87602fe7921 100644 (file)
@@ -399,7 +399,7 @@ static int _set_clockactivity(struct omap_hwmod *oh, u8 clockact, u32 *v)
 }
 
 /**
- * _set_softreset: set OCP_SYSCONFIG.CLOCKACTIVITY bits in @v
+ * _set_softreset: set OCP_SYSCONFIG.SOFTRESET bit in @v
  * @oh: struct omap_hwmod *
  * @v: pointer to register contents to modify
  *
@@ -426,6 +426,36 @@ static int _set_softreset(struct omap_hwmod *oh, u32 *v)
        return 0;
 }
 
+/**
+ * _clear_softreset: clear OCP_SYSCONFIG.SOFTRESET bit in @v
+ * @oh: struct omap_hwmod *
+ * @v: pointer to register contents to modify
+ *
+ * Clear the SOFTRESET bit in @v for hwmod @oh.  Returns -EINVAL upon
+ * error or 0 upon success.
+ */
+static int _clear_softreset(struct omap_hwmod *oh, u32 *v)
+{
+       u32 softrst_mask;
+
+       if (!oh->class->sysc ||
+           !(oh->class->sysc->sysc_flags & SYSC_HAS_SOFTRESET))
+               return -EINVAL;
+
+       if (!oh->class->sysc->sysc_fields) {
+               WARN(1,
+                    "omap_hwmod: %s: sysc_fields absent for sysconfig class\n",
+                    oh->name);
+               return -EINVAL;
+       }
+
+       softrst_mask = (0x1 << oh->class->sysc->sysc_fields->srst_shift);
+
+       *v &= ~softrst_mask;
+
+       return 0;
+}
+
 /**
  * _wait_softreset_complete - wait for an OCP softreset to complete
  * @oh: struct omap_hwmod * to wait on
@@ -785,6 +815,7 @@ static int _init_interface_clks(struct omap_hwmod *oh)
                        pr_warning("omap_hwmod: %s: cannot clk_get interface_clk %s\n",
                                   oh->name, os->clk);
                        ret = -EINVAL;
+                       continue;
                }
                os->_clk = c;
                /*
@@ -821,6 +852,7 @@ static int _init_opt_clks(struct omap_hwmod *oh)
                        pr_warning("omap_hwmod: %s: cannot clk_get opt_clk %s\n",
                                   oh->name, oc->clk);
                        ret = -EINVAL;
+                       continue;
                }
                oc->_clk = c;
                /*
@@ -1911,6 +1943,12 @@ static int _ocp_softreset(struct omap_hwmod *oh)
        ret = _set_softreset(oh, &v);
        if (ret)
                goto dis_opt_clks;
+
+       _write_sysconfig(v, oh);
+       ret = _clear_softreset(oh, &v);
+       if (ret)
+               goto dis_opt_clks;
+
        _write_sysconfig(v, oh);
 
        if (oh->class->sysc->srst_udelay)
@@ -2326,38 +2364,80 @@ static int _shutdown(struct omap_hwmod *oh)
        return 0;
 }
 
+static int of_dev_find_hwmod(struct device_node *np,
+                            struct omap_hwmod *oh)
+{
+       int count, i, res;
+       const char *p;
+
+       count = of_property_count_strings(np, "ti,hwmods");
+       if (count < 1)
+               return -ENODEV;
+
+       for (i = 0; i < count; i++) {
+               res = of_property_read_string_index(np, "ti,hwmods",
+                                                   i, &p);
+               if (res)
+                       continue;
+               if (!strcmp(p, oh->name)) {
+                       pr_debug("omap_hwmod: dt %s[%i] uses hwmod %s\n",
+                                np->name, i, oh->name);
+                       return i;
+               }
+       }
+
+       return -ENODEV;
+}
+
 /**
  * of_dev_hwmod_lookup - look up needed hwmod from dt blob
  * @np: struct device_node *
  * @oh: struct omap_hwmod *
+ * @index: index of the entry found
+ * @found: struct device_node * found or NULL
  *
  * Parse the dt blob and find out needed hwmod. Recursive function is
  * implemented to take care hierarchical dt blob parsing.
- * Return: The device node on success or NULL on failure.
+ * Return: Returns 0 on success, -ENODEV when not found.
  */
-static struct device_node *of_dev_hwmod_lookup(struct device_node *np,
-                                               struct omap_hwmod *oh)
+static int of_dev_hwmod_lookup(struct device_node *np,
+                              struct omap_hwmod *oh,
+                              int *index,
+                              struct device_node **found)
 {
-       struct device_node *np0 = NULL, *np1 = NULL;
-       const char *p;
+       struct device_node *np0 = NULL;
+       int res;
+
+       res = of_dev_find_hwmod(np, oh);
+       if (res >= 0) {
+               *found = np;
+               *index = res;
+               return 0;
+       }
 
        for_each_child_of_node(np, np0) {
-               if (of_find_property(np0, "ti,hwmods", NULL)) {
-                       p = of_get_property(np0, "ti,hwmods", NULL);
-                       if (!strcmp(p, oh->name))
-                               return np0;
-                       np1 = of_dev_hwmod_lookup(np0, oh);
-                       if (np1)
-                               return np1;
+               struct device_node *fc;
+               int i;
+
+               res = of_dev_hwmod_lookup(np0, oh, &i, &fc);
+               if (res == 0) {
+                       *found = fc;
+                       *index = i;
+                       return 0;
                }
        }
-       return NULL;
+
+       *found = NULL;
+       *index = 0;
+
+       return -ENODEV;
 }
 
 /**
  * _init_mpu_rt_base - populate the virtual address for a hwmod
  * @oh: struct omap_hwmod * to locate the virtual address
  * @data: (unused, caller should pass NULL)
+ * @index: index of the reg entry iospace in device tree
  * @np: struct device_node * of the IP block's device node in the DT data
  *
  * Cache the virtual address used by the MPU to access this IP block's
@@ -2368,7 +2448,7 @@ static struct device_node *of_dev_hwmod_lookup(struct device_node *np,
  * -ENXIO on absent or invalid register target address space.
  */
 static int __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data,
-                                   struct device_node *np)
+                                   int index, struct device_node *np)
 {
        struct omap_hwmod_addr_space *mem;
        void __iomem *va_start = NULL;
@@ -2390,13 +2470,17 @@ static int __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data,
                if (!np)
                        return -ENXIO;
 
-               va_start = of_iomap(np, oh->mpu_rt_idx);
+               va_start = of_iomap(np, index + oh->mpu_rt_idx);
        } else {
                va_start = ioremap(mem->pa_start, mem->pa_end - mem->pa_start);
        }
 
        if (!va_start) {
-               pr_err("omap_hwmod: %s: Could not ioremap\n", oh->name);
+               if (mem)
+                       pr_err("omap_hwmod: %s: Could not ioremap\n", oh->name);
+               else
+                       pr_err("omap_hwmod: %s: Missing dt reg%i for %s\n",
+                              oh->name, index, np->full_name);
                return -ENXIO;
        }
 
@@ -2422,17 +2506,29 @@ static int __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data,
  */
 static int __init _init(struct omap_hwmod *oh, void *data)
 {
-       int r;
+       int r, index;
        struct device_node *np = NULL;
 
        if (oh->_state != _HWMOD_STATE_REGISTERED)
                return 0;
 
-       if (of_have_populated_dt())
-               np = of_dev_hwmod_lookup(of_find_node_by_name(NULL, "ocp"), oh);
+       if (of_have_populated_dt()) {
+               struct device_node *bus;
+
+               bus = of_find_node_by_name(NULL, "ocp");
+               if (!bus)
+                       return -ENODEV;
+
+               r = of_dev_hwmod_lookup(bus, oh, &index, &np);
+               if (r)
+                       pr_debug("omap_hwmod: %s missing dt data\n", oh->name);
+               else if (np && index)
+                       pr_warn("omap_hwmod: %s using broken dt data from %s\n",
+                               oh->name, np->name);
+       }
 
        if (oh->class->sysc) {
-               r = _init_mpu_rt_base(oh, NULL, np);
+               r = _init_mpu_rt_base(oh, NULL, index, np);
                if (r < 0) {
                        WARN(1, "omap_hwmod: %s: doesn't have mpu register target base\n",
                             oh->name);
@@ -3169,6 +3265,11 @@ int omap_hwmod_softreset(struct omap_hwmod *oh)
                goto error;
        _write_sysconfig(v, oh);
 
+       ret = _clear_softreset(oh, &v);
+       if (ret)
+               goto error;
+       _write_sysconfig(v, oh);
+
 error:
        return ret;
 }
index 9e56fabd7fa3b834fbe09a463facd521592107a7..d33742908f970a21b24c2cefeef03799d3d84532 100644 (file)
@@ -1943,7 +1943,8 @@ static struct omap_hwmod_class_sysconfig omap3xxx_usb_host_hs_sysc = {
        .syss_offs      = 0x0014,
        .sysc_flags     = (SYSC_HAS_MIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
                           SYSC_HAS_SIDLEMODE | SYSC_HAS_ENAWAKEUP |
-                          SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+                          SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
+                          SYSS_HAS_RESET_STATUS),
        .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
                           MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
        .sysc_fields    = &omap_hwmod_sysc_type1,
@@ -2021,15 +2022,7 @@ static struct omap_hwmod omap3xxx_usb_host_hs_hwmod = {
         * hence HWMOD_SWSUP_MSTANDBY
         */
 
-       /*
-        * During system boot; If the hwmod framework resets the module
-        * the module will have smart idle settings; which can lead to deadlock
-        * (above Errata Id:i660); so, dont reset the module during boot;
-        * Use HWMOD_INIT_NO_RESET.
-        */
-
-       .flags          = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY |
-                         HWMOD_INIT_NO_RESET,
+       .flags          = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY,
 };
 
 /*
index 1e5b12cb8246290cc8e2865036e0f4a291513f9c..3318cae96e7d1e94a8699192d1c00512c8f34f38 100644 (file)
@@ -2937,7 +2937,7 @@ static struct omap_hwmod_class_sysconfig omap44xx_usb_host_hs_sysc = {
        .sysc_offs      = 0x0010,
        .syss_offs      = 0x0014,
        .sysc_flags     = (SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE |
-                          SYSC_HAS_SOFTRESET),
+                          SYSC_HAS_SOFTRESET | SYSC_HAS_RESET_STATUS),
        .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
                           SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO |
                           MSTANDBY_SMART | MSTANDBY_SMART_WKUP),
@@ -3001,15 +3001,7 @@ static struct omap_hwmod omap44xx_usb_host_hs_hwmod = {
         * hence HWMOD_SWSUP_MSTANDBY
         */
 
-       /*
-        * During system boot; If the hwmod framework resets the module
-        * the module will have smart idle settings; which can lead to deadlock
-        * (above Errata Id:i660); so, dont reset the module during boot;
-        * Use HWMOD_INIT_NO_RESET.
-        */
-
-       .flags          = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY |
-                         HWMOD_INIT_NO_RESET,
+       .flags          = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY,
 };
 
 /*
index 9e08d6994a0b09c44760e03323c9543f720ad026..e297d6231c3aa3c35910d25f3115466be2d453ab 100644 (file)
@@ -1544,7 +1544,8 @@ static struct omap_hwmod_class_sysconfig omap54xx_usb_host_hs_sysc = {
        .rev_offs       = 0x0000,
        .sysc_offs      = 0x0010,
        .sysc_flags     = (SYSC_HAS_MIDLEMODE | SYSC_HAS_RESET_STATUS |
-                          SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
+                          SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+                          SYSC_HAS_RESET_STATUS),
        .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
                           SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO |
                           MSTANDBY_SMART | MSTANDBY_SMART_WKUP),
@@ -1598,15 +1599,7 @@ static struct omap_hwmod omap54xx_usb_host_hs_hwmod = {
         * hence HWMOD_SWSUP_MSTANDBY
         */
 
-       /*
-        * During system boot; If the hwmod framework resets the module
-        * the module will have smart idle settings; which can lead to deadlock
-        * (above Errata Id:i660); so, dont reset the module during boot;
-        * Use HWMOD_INIT_NO_RESET.
-        */
-
-       .flags          = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY |
-                         HWMOD_INIT_NO_RESET,
+       .flags          = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY,
        .main_clk       = "l3init_60m_fclk",
        .prcm = {
                .omap4 = {
index 10c71450cf632c2816c40ab22207ad65ef09dd0b..39f020c982e8b3a41d547d9d45b60c46cb08877b 100644 (file)
@@ -139,6 +139,7 @@ struct of_dev_auxdata omap_auxdata_lookup[] __initdata = {
 
 static struct pdata_init pdata_quirks[] __initdata = {
 #ifdef CONFIG_ARCH_OMAP3
+       { "nokia,omap3-n900", hsmmc2_internal_input_clk, },
        { "nokia,omap3-n9", hsmmc2_internal_input_clk, },
        { "nokia,omap3-n950", hsmmc2_internal_input_clk, },
        { "isee,omap3-igep0020", omap3_igep0020_legacy_init, },
index e233dfcbc18670ff6f0e507df07b6f9c09289534..93a2a6e4260f46c6b1580d7dbf50188dbc7154a3 100644 (file)
@@ -128,7 +128,8 @@ skip_voltdm:
        for (i = 0; i < pwrdm->banks; i++)
                pwrdm->ret_mem_off_counter[i] = 0;
 
-       arch_pwrdm->pwrdm_wait_transition(pwrdm);
+       if (arch_pwrdm && arch_pwrdm->pwrdm_wait_transition)
+               arch_pwrdm->pwrdm_wait_transition(pwrdm);
        pwrdm->state = pwrdm_read_pwrst(pwrdm);
        pwrdm->state_counter[pwrdm->state] = 1;
 
index 3ca81e0ada5e228e083ed591f0976174e2e6b972..ec084d158f642b3cf919adbbb0c6fd97e64f6317 100644 (file)
@@ -379,7 +379,7 @@ static struct clocksource clocksource_gpt = {
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
-static u32 notrace dmtimer_read_sched_clock(void)
+static u64 notrace dmtimer_read_sched_clock(void)
 {
        if (clksrc.reserved)
                return __omap_dm_timer_read_counter(&clksrc,
@@ -471,7 +471,7 @@ static void __init omap2_gptimer_clocksource_init(int gptimer_id,
        __omap_dm_timer_load_start(&clksrc,
                                   OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0,
                                   OMAP_TIMER_NONPOSTED);
-       setup_sched_clock(dmtimer_read_sched_clock, 32, clksrc.rate);
+       sched_clock_register(dmtimer_read_sched_clock, 32, clksrc.rate);
 
        if (clocksource_register_hz(&clocksource_gpt, clksrc.rate))
                pr_err("Could not register clocksource %s\n",
index b91002ca92f3b42b6a04f54683daa4f2504e5c2a..c134a826070a14ccadda4293181f27cf81278804 100644 (file)
@@ -21,7 +21,7 @@
 #include <plat/irq.h>
 #include "common.h"
 
-struct of_dev_auxdata orion5x_auxdata_lookup[] __initdata = {
+static struct of_dev_auxdata orion5x_auxdata_lookup[] __initdata = {
        OF_DEV_AUXDATA("marvell,orion-spi", 0xf1010600, "orion_spi.0", NULL),
        OF_DEV_AUXDATA("marvell,mv64xxx-i2c", 0xf1011000, "mv64xxx_i2c.0",
                       NULL),
index 91a5852b44f3a8fe09d0815009ff54329b23c582..3f1de1111e0f207e4a0dbd5d66208d2054f1a810 100644 (file)
@@ -24,7 +24,6 @@
 #include <asm/page.h>
 #include <asm/setup.h>
 #include <asm/system_misc.h>
-#include <asm/timex.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
@@ -135,7 +134,7 @@ void __init orion5x_sata_init(struct mv_sata_platform_data *sata_data)
 /*****************************************************************************
  * SPI
  ****************************************************************************/
-void __init orion5x_spi_init()
+void __init orion5x_spi_init(void)
 {
        orion_spi_init(SPI_PHYS_BASE);
 }
@@ -185,7 +184,7 @@ static void __init orion5x_crypto_init(void)
 /*****************************************************************************
  * Watchdog
  ****************************************************************************/
-void __init orion5x_wdt_init(void)
+static void __init orion5x_wdt_init(void)
 {
        orion_wdt_init();
 }
@@ -246,7 +245,7 @@ void orion5x_setup_wins(void)
 
 int orion5x_tclk;
 
-int __init orion5x_find_tclk(void)
+static int __init orion5x_find_tclk(void)
 {
        u32 dev, rev;
 
index 4b2aefd1d96180e7a3e5962a72c907734a136539..dc01c4ffc9a8d090ad8d7691ffedf9588cdd2414 100644 (file)
@@ -202,7 +202,7 @@ __initcall(db88f5281_7seg_init);
  * PCI
  ****************************************************************************/
 
-void __init db88f5281_pci_preinit(void)
+static void __init db88f5281_pci_preinit(void)
 {
        int pin;
 
index 30a192b9c51730da9dfb94ccdf93128ceb8143de..9654b0cc58928741c13281eaf7c6b737411dd7ec 100644 (file)
@@ -16,6 +16,7 @@
 #include <mach/bridge-regs.h>
 #include <plat/orion-gpio.h>
 #include <plat/irq.h>
+#include "common.h"
 
 static int __initdata gpio0_irqs[4] = {
        IRQ_ORION5X_GPIO_0_7,
index 7fab6705303073ab9b6cdb1dbf6cae17a0840390..87a12d6930ffc4525a1a1335789162711968e4fe 100644 (file)
@@ -240,11 +240,11 @@ static int __init pcie_setup(struct pci_sys_data *sys)
 #define PCI_BAR_SIZE_DDR_CS(n) (((n) == 0) ? ORION5X_PCI_REG(0xc08) : \
                                 ((n) == 1) ? ORION5X_PCI_REG(0xd08) : \
                                 ((n) == 2) ? ORION5X_PCI_REG(0xc0c) : \
-                                ((n) == 3) ? ORION5X_PCI_REG(0xd0c) : 0)
+                                ((n) == 3) ? ORION5X_PCI_REG(0xd0c) : NULL)
 #define PCI_BAR_REMAP_DDR_CS(n)        (((n) == 0) ? ORION5X_PCI_REG(0xc48) : \
                                 ((n) == 1) ? ORION5X_PCI_REG(0xd48) : \
                                 ((n) == 2) ? ORION5X_PCI_REG(0xc4c) : \
-                                ((n) == 3) ? ORION5X_PCI_REG(0xd4c) : 0)
+                                ((n) == 3) ? ORION5X_PCI_REG(0xd4c) : NULL)
 #define PCI_BAR_ENABLE         ORION5X_PCI_REG(0xc3c)
 #define PCI_ADDR_DECODE_CTRL   ORION5X_PCI_REG(0xd3c)
 
index b1cf68493ffc35666b357d61242fafd01097b97d..b576ef5f18a16a777fd7948995d10d047a82eafe 100644 (file)
@@ -108,7 +108,7 @@ static struct platform_device rd88f5182_gpio_leds = {
  * PCI
  ****************************************************************************/
 
-void __init rd88f5182_pci_preinit(void)
+static void __init rd88f5182_pci_preinit(void)
 {
        int pin;
 
index 7e90648446980995bf00778342d1d2e57d546850..6208d125c1b946602ce12977ca45607a264685f6 100644 (file)
@@ -77,7 +77,7 @@ static struct platform_device tsp2_nor_flash = {
 #define TSP2_PCI_SLOT0_OFFS            7
 #define TSP2_PCI_SLOT0_IRQ_PIN         11
 
-void __init tsp2_pci_preinit(void)
+static void __init tsp2_pci_preinit(void)
 {
        int pin;
 
index e90c0618fdad5cb7cefe722639310811703b186d..9136797addb271816579c78505bd06630397d4d4 100644 (file)
@@ -106,7 +106,7 @@ static struct platform_device qnap_ts209_nor_flash = {
 #define QNAP_TS209_PCI_SLOT0_IRQ_PIN   6
 #define QNAP_TS209_PCI_SLOT1_IRQ_PIN   7
 
-void __init qnap_ts209_pci_preinit(void)
+static void __init qnap_ts209_pci_preinit(void)
 {
        int pin;
 
index e960855d32ac30b75e6a328181be3cbe8fed9535..db16dae441e252607bcb2d13f6e172b7410cc19d 100644 (file)
@@ -57,7 +57,7 @@ static struct map_desc ts78xx_io_desc[] __initdata = {
        },
 };
 
-void __init ts78xx_map_io(void)
+static void __init ts78xx_map_io(void)
 {
        orion5x_map_io();
        iotable_init(ts78xx_io_desc, ARRAY_SIZE(ts78xx_io_desc));
index 9aa852a8fab9f2c7784003764086cd9d1af8dc2e..d1bfaa73b1c9bb53adbfb359c7a149aacd8cda24 100644 (file)
@@ -33,7 +33,7 @@
  * calls to sched_clock() which should always be the case in practice.
  */
 
-static u32 notrace pxa_read_sched_clock(void)
+static u64 notrace pxa_read_sched_clock(void)
 {
        return readl_relaxed(OSCR);
 }
@@ -149,7 +149,7 @@ void __init pxa_timer_init(void)
        writel_relaxed(0, OIER);
        writel_relaxed(OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3, OSSR);
 
-       setup_sched_clock(pxa_read_sched_clock, 32, clock_tick_rate);
+       sched_clock_register(pxa_read_sched_clock, 32, clock_tick_rate);
 
        ckevt_pxa_osmr0.cpumask = cpumask_of(0);
 
index 2cb8dc55b50ecbc4aa612ab805b52f03efec3eb9..7094bccbae913ae953594a51e900ce13f8e4137d 100644 (file)
@@ -17,9 +17,10 @@ config CPU_S3C6410
        help
          Enable S3C6410 CPU support
 
-config S3C64XX_DMA
-       bool "S3C64XX DMA"
-       select S3C_DMA
+config S3C64XX_PL080
+       bool "S3C64XX DMA using generic PL08x driver"
+       select AMBA_PL08X
+       select SAMSUNG_DMADEV
 
 config S3C64XX_SETUP_SDHCI
        bool
index 6faedcffce040d0cfc041c9d3b559ff1be94a207..58069a702a435046ae627bff9ab4e8c689b1aa3c 100644 (file)
@@ -26,7 +26,7 @@ obj-$(CONFIG_CPU_IDLE)                += cpuidle.o
 
 # DMA support
 
-obj-$(CONFIG_S3C64XX_DMA)      += dma.o
+obj-$(CONFIG_S3C64XX_PL080)    += pl080.o
 
 # Device support
 
index bd3bd562011e1515198e924627fd7165f57cb3dd..7043e7a3a67ed868f9e4465d7afae197619dcdc9 100644 (file)
@@ -58,4 +58,9 @@ int __init s3c64xx_pm_late_initcall(void);
 static inline int s3c64xx_pm_late_initcall(void) { return 0; }
 #endif
 
+#ifdef CONFIG_S3C64XX_PL080
+extern struct pl08x_platform_data s3c64xx_dma0_plat_data;
+extern struct pl08x_platform_data s3c64xx_dma1_plat_data;
+#endif
+
 #endif /* __ARCH_ARM_MACH_S3C64XX_COMMON_H */
diff --git a/arch/arm/mach-s3c64xx/dma.c b/arch/arm/mach-s3c64xx/dma.c
deleted file mode 100644 (file)
index 7e22c21..0000000
+++ /dev/null
@@ -1,762 +0,0 @@
-/* linux/arch/arm/plat-s3c64xx/dma.c
- *
- * Copyright 2009 Openmoko, Inc.
- * Copyright 2009 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *     http://armlinux.simtec.co.uk/
- *
- * S3C64XX DMA core
- *
- * 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.
-*/
-
-/*
- * 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>
-#include <linux/dmapool.h>
-#include <linux/device.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#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>
-#include <mach/irqs.h>
-
-#include "regs-sys.h"
-
-/* dma channel state information */
-
-struct s3c64xx_dmac {
-       struct device           dev;
-       struct clk              *clk;
-       void __iomem            *regs;
-       struct s3c2410_dma_chan *channels;
-       enum dma_ch              chanbase;
-};
-
-/* pool to provide LLI buffers */
-static struct dma_pool *dma_pool;
-
-/* Debug configuration and code */
-
-static unsigned char debug_show_buffs = 0;
-
-static void dbg_showchan(struct s3c2410_dma_chan *chan)
-{
-       pr_debug("DMA%d: %08x->%08x L %08x C %08x,%08x S %08x\n",
-                chan->number,
-                readl(chan->regs + PL080_CH_SRC_ADDR),
-                readl(chan->regs + PL080_CH_DST_ADDR),
-                readl(chan->regs + PL080_CH_LLI),
-                readl(chan->regs + PL080_CH_CONTROL),
-                readl(chan->regs + PL080S_CH_CONTROL2),
-                readl(chan->regs + PL080S_CH_CONFIG));
-}
-
-static void show_lli(struct pl080s_lli *lli)
-{
-       pr_debug("LLI[%p] %08x->%08x, NL %08x C %08x,%08x\n",
-                lli, lli->src_addr, lli->dst_addr, lli->next_lli,
-                lli->control0, lli->control1);
-}
-
-static void dbg_showbuffs(struct s3c2410_dma_chan *chan)
-{
-       struct s3c64xx_dma_buff *ptr;
-       struct s3c64xx_dma_buff *end;
-
-       pr_debug("DMA%d: buffs next %p, curr %p, end %p\n",
-                chan->number, chan->next, chan->curr, chan->end);
-
-       ptr = chan->next;
-       end = chan->end;
-
-       if (debug_show_buffs) {
-               for (; ptr != NULL; ptr = ptr->next) {
-                       pr_debug("DMA%d: %08x ",
-                                chan->number, ptr->lli_dma);
-                       show_lli(ptr->lli);
-               }
-       }
-}
-
-/* End of Debug */
-
-static struct s3c2410_dma_chan *s3c64xx_dma_map_channel(unsigned int channel)
-{
-       struct s3c2410_dma_chan *chan;
-       unsigned int start, offs;
-
-       start = 0;
-
-       if (channel >= DMACH_PCM1_TX)
-               start = 8;
-
-       for (offs = 0; offs < 8; offs++) {
-               chan = &s3c2410_chans[start + offs];
-               if (!chan->in_use)
-                       goto found;
-       }
-
-       return NULL;
-
-found:
-       s3c_dma_chan_map[channel] = chan;
-       return chan;
-}
-
-int s3c2410_dma_config(enum dma_ch channel, int xferunit)
-{
-       struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
-
-       if (chan == NULL)
-               return -EINVAL;
-
-       switch (xferunit) {
-       case 1:
-               chan->hw_width = 0;
-               break;
-       case 2:
-               chan->hw_width = 1;
-               break;
-       case 4:
-               chan->hw_width = 2;
-               break;
-       default:
-               printk(KERN_ERR "%s: illegal width %d\n", __func__, xferunit);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL(s3c2410_dma_config);
-
-static void s3c64xx_dma_fill_lli(struct s3c2410_dma_chan *chan,
-                                struct pl080s_lli *lli,
-                                dma_addr_t data, int size)
-{
-       dma_addr_t src, dst;
-       u32 control0, control1;
-
-       switch (chan->source) {
-       case DMA_FROM_DEVICE:
-               src = chan->dev_addr;
-               dst = data;
-               control0 = PL080_CONTROL_SRC_AHB2;
-               control0 |= PL080_CONTROL_DST_INCR;
-               break;
-
-       case DMA_TO_DEVICE:
-               src = data;
-               dst = chan->dev_addr;
-               control0 = PL080_CONTROL_DST_AHB2;
-               control0 |= PL080_CONTROL_SRC_INCR;
-               break;
-       default:
-               BUG();
-       }
-
-       /* note, we do not currently setup any of the burst controls */
-
-       control1 = size >> chan->hw_width;      /* size in no of xfers */
-       control0 |= PL080_CONTROL_PROT_SYS;     /* always in priv. mode */
-       control0 |= PL080_CONTROL_TC_IRQ_EN;    /* always fire IRQ */
-       control0 |= (u32)chan->hw_width << PL080_CONTROL_DWIDTH_SHIFT;
-       control0 |= (u32)chan->hw_width << PL080_CONTROL_SWIDTH_SHIFT;
-
-       lli->src_addr = src;
-       lli->dst_addr = dst;
-       lli->next_lli = 0;
-       lli->control0 = control0;
-       lli->control1 = control1;
-}
-
-static void s3c64xx_lli_to_regs(struct s3c2410_dma_chan *chan,
-                               struct pl080s_lli *lli)
-{
-       void __iomem *regs = chan->regs;
-
-       pr_debug("%s: LLI %p => regs\n", __func__, lli);
-       show_lli(lli);
-
-       writel(lli->src_addr, regs + PL080_CH_SRC_ADDR);
-       writel(lli->dst_addr, regs + PL080_CH_DST_ADDR);
-       writel(lli->next_lli, regs + PL080_CH_LLI);
-       writel(lli->control0, regs + PL080_CH_CONTROL);
-       writel(lli->control1, regs + PL080S_CH_CONTROL2);
-}
-
-static int s3c64xx_dma_start(struct s3c2410_dma_chan *chan)
-{
-       struct s3c64xx_dmac *dmac = chan->dmac;
-       u32 config;
-       u32 bit = chan->bit;
-
-       dbg_showchan(chan);
-
-       pr_debug("%s: clearing interrupts\n", __func__);
-
-       /* clear interrupts */
-       writel(bit, dmac->regs + PL080_TC_CLEAR);
-       writel(bit, dmac->regs + PL080_ERR_CLEAR);
-
-       pr_debug("%s: starting channel\n", __func__);
-
-       config = readl(chan->regs + PL080S_CH_CONFIG);
-       config |= PL080_CONFIG_ENABLE;
-       config &= ~PL080_CONFIG_HALT;
-
-       pr_debug("%s: writing config %08x\n", __func__, config);
-       writel(config, chan->regs + PL080S_CH_CONFIG);
-
-       return 0;
-}
-
-static int s3c64xx_dma_stop(struct s3c2410_dma_chan *chan)
-{
-       u32 config;
-       int timeout;
-
-       pr_debug("%s: stopping channel\n", __func__);
-
-       dbg_showchan(chan);
-
-       config = readl(chan->regs + PL080S_CH_CONFIG);
-       config |= PL080_CONFIG_HALT;
-       writel(config, chan->regs + PL080S_CH_CONFIG);
-
-       timeout = 1000;
-       do {
-               config = readl(chan->regs + PL080S_CH_CONFIG);
-               pr_debug("%s: %d - config %08x\n", __func__, timeout, config);
-               if (config & PL080_CONFIG_ACTIVE)
-                       udelay(10);
-               else
-                       break;
-               } while (--timeout > 0);
-
-       if (config & PL080_CONFIG_ACTIVE) {
-               printk(KERN_ERR "%s: channel still active\n", __func__);
-               return -EFAULT;
-       }
-
-       config = readl(chan->regs + PL080S_CH_CONFIG);
-       config &= ~PL080_CONFIG_ENABLE;
-       writel(config, chan->regs + PL080S_CH_CONFIG);
-
-       return 0;
-}
-
-static inline void s3c64xx_dma_bufffdone(struct s3c2410_dma_chan *chan,
-                                        struct s3c64xx_dma_buff *buf,
-                                        enum s3c2410_dma_buffresult result)
-{
-       if (chan->callback_fn != NULL)
-               (chan->callback_fn)(chan, buf->pw, 0, result);
-}
-
-static void s3c64xx_dma_freebuff(struct s3c64xx_dma_buff *buff)
-{
-       dma_pool_free(dma_pool, buff->lli, buff->lli_dma);
-       kfree(buff);
-}
-
-static int s3c64xx_dma_flush(struct s3c2410_dma_chan *chan)
-{
-       struct s3c64xx_dma_buff *buff, *next;
-       u32 config;
-
-       dbg_showchan(chan);
-
-       pr_debug("%s: flushing channel\n", __func__);
-
-       config = readl(chan->regs + PL080S_CH_CONFIG);
-       config &= ~PL080_CONFIG_ENABLE;
-       writel(config, chan->regs + PL080S_CH_CONFIG);
-
-       /* dump all the buffers associated with this channel */
-
-       for (buff = chan->curr; buff != NULL; buff = next) {
-               next = buff->next;
-               pr_debug("%s: buff %p (next %p)\n", __func__, buff, buff->next);
-
-               s3c64xx_dma_bufffdone(chan, buff, S3C2410_RES_ABORT);
-               s3c64xx_dma_freebuff(buff);
-       }
-
-       chan->curr = chan->next = chan->end = NULL;
-
-       return 0;
-}
-
-int s3c2410_dma_ctrl(enum dma_ch channel, enum s3c2410_chan_op op)
-{
-       struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
-
-       WARN_ON(!chan);
-       if (!chan)
-               return -EINVAL;
-
-       switch (op) {
-       case S3C2410_DMAOP_START:
-               return s3c64xx_dma_start(chan);
-
-       case S3C2410_DMAOP_STOP:
-               return s3c64xx_dma_stop(chan);
-
-       case S3C2410_DMAOP_FLUSH:
-               return s3c64xx_dma_flush(chan);
-
-       /* believe PAUSE/RESUME are no-ops */
-       case S3C2410_DMAOP_PAUSE:
-       case S3C2410_DMAOP_RESUME:
-       case S3C2410_DMAOP_STARTED:
-       case S3C2410_DMAOP_TIMEOUT:
-               return 0;
-       }
-
-       return -ENOENT;
-}
-EXPORT_SYMBOL(s3c2410_dma_ctrl);
-
-/* s3c2410_dma_enque
- *
- */
-
-int s3c2410_dma_enqueue(enum dma_ch channel, void *id,
-                       dma_addr_t data, int size)
-{
-       struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
-       struct s3c64xx_dma_buff *next;
-       struct s3c64xx_dma_buff *buff;
-       struct pl080s_lli *lli;
-       unsigned long flags;
-       int ret;
-
-       WARN_ON(!chan);
-       if (!chan)
-               return -EINVAL;
-
-       buff = kzalloc(sizeof(struct s3c64xx_dma_buff), GFP_ATOMIC);
-       if (!buff) {
-               printk(KERN_ERR "%s: no memory for buffer\n", __func__);
-               return -ENOMEM;
-       }
-
-       lli = dma_pool_alloc(dma_pool, GFP_ATOMIC, &buff->lli_dma);
-       if (!lli) {
-               printk(KERN_ERR "%s: no memory for lli\n", __func__);
-               ret = -ENOMEM;
-               goto err_buff;
-       }
-
-       pr_debug("%s: buff %p, dp %08x lli (%p, %08x) %d\n",
-                __func__, buff, data, lli, (u32)buff->lli_dma, size);
-
-       buff->lli = lli;
-       buff->pw = id;
-
-       s3c64xx_dma_fill_lli(chan, lli, data, size);
-
-       local_irq_save(flags);
-
-       if ((next = chan->next) != NULL) {
-               struct s3c64xx_dma_buff *end = chan->end;
-               struct pl080s_lli *endlli = end->lli;
-
-               pr_debug("enquing onto channel\n");
-
-               end->next = buff;
-               endlli->next_lli = buff->lli_dma;
-
-               if (chan->flags & S3C2410_DMAF_CIRCULAR) {
-                       struct s3c64xx_dma_buff *curr = chan->curr;
-                       lli->next_lli = curr->lli_dma;
-               }
-
-               if (next == chan->curr) {
-                       writel(buff->lli_dma, chan->regs + PL080_CH_LLI);
-                       chan->next = buff;
-               }
-
-               show_lli(endlli);
-               chan->end = buff;
-       } else {
-               pr_debug("enquing onto empty channel\n");
-
-               chan->curr = buff;
-               chan->next = buff;
-               chan->end = buff;
-
-               s3c64xx_lli_to_regs(chan, lli);
-       }
-
-       local_irq_restore(flags);
-
-       show_lli(lli);
-
-       dbg_showchan(chan);
-       dbg_showbuffs(chan);
-       return 0;
-
-err_buff:
-       kfree(buff);
-       return ret;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_enqueue);
-
-
-int s3c2410_dma_devconfig(enum dma_ch channel,
-                         enum dma_data_direction source,
-                         unsigned long devaddr)
-{
-       struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
-       u32 peripheral;
-       u32 config = 0;
-
-       pr_debug("%s: channel %d, source %d, dev %08lx, chan %p\n",
-                __func__, channel, source, devaddr, chan);
-
-       WARN_ON(!chan);
-       if (!chan)
-               return -EINVAL;
-
-       peripheral = (chan->peripheral & 0xf);
-       chan->source = source;
-       chan->dev_addr = devaddr;
-
-       pr_debug("%s: peripheral %d\n", __func__, peripheral);
-
-       switch (source) {
-       case DMA_FROM_DEVICE:
-               config = 2 << PL080_CONFIG_FLOW_CONTROL_SHIFT;
-               config |= peripheral << PL080_CONFIG_SRC_SEL_SHIFT;
-               break;
-       case DMA_TO_DEVICE:
-               config = 1 << PL080_CONFIG_FLOW_CONTROL_SHIFT;
-               config |= peripheral << PL080_CONFIG_DST_SEL_SHIFT;
-               break;
-       default:
-               printk(KERN_ERR "%s: bad source\n", __func__);
-               return -EINVAL;
-       }
-
-       /* allow TC and ERR interrupts */
-       config |= PL080_CONFIG_TC_IRQ_MASK;
-       config |= PL080_CONFIG_ERR_IRQ_MASK;
-
-       pr_debug("%s: config %08x\n", __func__, config);
-
-       writel(config, chan->regs + PL080S_CH_CONFIG);
-
-       return 0;
-}
-EXPORT_SYMBOL(s3c2410_dma_devconfig);
-
-
-int s3c2410_dma_getposition(enum dma_ch channel,
-                           dma_addr_t *src, dma_addr_t *dst)
-{
-       struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
-
-       WARN_ON(!chan);
-       if (!chan)
-               return -EINVAL;
-
-       if (src != NULL)
-               *src = readl(chan->regs + PL080_CH_SRC_ADDR);
-
-       if (dst != NULL)
-               *dst = readl(chan->regs + PL080_CH_DST_ADDR);
-
-       return 0;
-}
-EXPORT_SYMBOL(s3c2410_dma_getposition);
-
-/* s3c2410_request_dma
- *
- * get control of an dma channel
-*/
-
-int s3c2410_dma_request(enum dma_ch channel,
-                       struct s3c2410_dma_client *client,
-                       void *dev)
-{
-       struct s3c2410_dma_chan *chan;
-       unsigned long flags;
-
-       pr_debug("dma%d: s3c2410_request_dma: client=%s, dev=%p\n",
-                channel, client->name, dev);
-
-       local_irq_save(flags);
-
-       chan = s3c64xx_dma_map_channel(channel);
-       if (chan == NULL) {
-               local_irq_restore(flags);
-               return -EBUSY;
-       }
-
-       dbg_showchan(chan);
-
-       chan->client = client;
-       chan->in_use = 1;
-       chan->peripheral = channel;
-       chan->flags = 0;
-
-       local_irq_restore(flags);
-
-       /* need to setup */
-
-       pr_debug("%s: channel initialised, %p\n", __func__, chan);
-
-       return chan->number | DMACH_LOW_LEVEL;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_request);
-
-/* s3c2410_dma_free
- *
- * release the given channel back to the system, will stop and flush
- * any outstanding transfers, and ensure the channel is ready for the
- * next claimant.
- *
- * Note, although a warning is currently printed if the freeing client
- * info is not the same as the registrant's client info, the free is still
- * allowed to go through.
-*/
-
-int s3c2410_dma_free(enum dma_ch channel, struct s3c2410_dma_client *client)
-{
-       struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
-       unsigned long flags;
-
-       if (chan == NULL)
-               return -EINVAL;
-
-       local_irq_save(flags);
-
-       if (chan->client != client) {
-               printk(KERN_WARNING "dma%d: possible free from different client (channel %p, passed %p)\n",
-                      channel, chan->client, client);
-       }
-
-       /* sort out stopping and freeing the channel */
-
-
-       chan->client = NULL;
-       chan->in_use = 0;
-
-       if (!(channel & DMACH_LOW_LEVEL))
-               s3c_dma_chan_map[channel] = NULL;
-
-       local_irq_restore(flags);
-
-       return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_free);
-
-static irqreturn_t s3c64xx_dma_irq(int irq, void *pw)
-{
-       struct s3c64xx_dmac *dmac = pw;
-       struct s3c2410_dma_chan *chan;
-       enum s3c2410_dma_buffresult res;
-       u32 tcstat, errstat;
-       u32 bit;
-       int offs;
-
-       tcstat = readl(dmac->regs + PL080_TC_STATUS);
-       errstat = readl(dmac->regs + PL080_ERR_STATUS);
-
-       for (offs = 0, bit = 1; offs < 8; offs++, bit <<= 1) {
-               struct s3c64xx_dma_buff *buff;
-
-               if (!(errstat & bit) && !(tcstat & bit))
-                       continue;
-
-               chan = dmac->channels + offs;
-               res = S3C2410_RES_ERR;
-
-               if (tcstat & bit) {
-                       writel(bit, dmac->regs + PL080_TC_CLEAR);
-                       res = S3C2410_RES_OK;
-               }
-
-               if (errstat & bit)
-                       writel(bit, dmac->regs + PL080_ERR_CLEAR);
-
-               /* 'next' points to the buffer that is next to the
-                * currently active buffer.
-                * For CIRCULAR queues, 'next' will be same as 'curr'
-                * when 'end' is the active buffer.
-                */
-               buff = chan->curr;
-               while (buff && buff != chan->next
-                               && buff->next != chan->next)
-                       buff = buff->next;
-
-               if (!buff)
-                       BUG();
-
-               if (buff == chan->next)
-                       buff = chan->end;
-
-               s3c64xx_dma_bufffdone(chan, buff, res);
-
-               /* Free the node and update curr, if non-circular queue */
-               if (!(chan->flags & S3C2410_DMAF_CIRCULAR)) {
-                       chan->curr = buff->next;
-                       s3c64xx_dma_freebuff(buff);
-               }
-
-               /* Update 'next' */
-               buff = chan->next;
-               if (chan->next == chan->end) {
-                       chan->next = chan->curr;
-                       if (!(chan->flags & S3C2410_DMAF_CIRCULAR))
-                               chan->end = NULL;
-               } else {
-                       chan->next = buff->next;
-               }
-       }
-
-       return IRQ_HANDLED;
-}
-
-static struct bus_type dma_subsys = {
-       .name           = "s3c64xx-dma",
-       .dev_name       = "s3c64xx-dma",
-};
-
-static int s3c64xx_dma_init1(int chno, enum dma_ch chbase,
-                            int irq, unsigned int base)
-{
-       struct s3c2410_dma_chan *chptr = &s3c2410_chans[chno];
-       struct s3c64xx_dmac *dmac;
-       char clkname[16];
-       void __iomem *regs;
-       void __iomem *regptr;
-       int err, ch;
-
-       dmac = kzalloc(sizeof(struct s3c64xx_dmac), GFP_KERNEL);
-       if (!dmac) {
-               printk(KERN_ERR "%s: failed to alloc mem\n", __func__);
-               return -ENOMEM;
-       }
-
-       dmac->dev.id = chno / 8;
-       dmac->dev.bus = &dma_subsys;
-
-       err = device_register(&dmac->dev);
-       if (err) {
-               printk(KERN_ERR "%s: failed to register device\n", __func__);
-               goto err_alloc;
-       }
-
-       regs = ioremap(base, 0x200);
-       if (!regs) {
-               printk(KERN_ERR "%s: failed to ioremap()\n", __func__);
-               err = -ENXIO;
-               goto err_dev;
-       }
-
-       snprintf(clkname, sizeof(clkname), "dma%d", dmac->dev.id);
-
-       dmac->clk = clk_get(NULL, clkname);
-       if (IS_ERR(dmac->clk)) {
-               printk(KERN_ERR "%s: failed to get clock %s\n", __func__, clkname);
-               err = PTR_ERR(dmac->clk);
-               goto err_map;
-       }
-
-       clk_prepare_enable(dmac->clk);
-
-       dmac->regs = regs;
-       dmac->chanbase = chbase;
-       dmac->channels = chptr;
-
-       err = request_irq(irq, s3c64xx_dma_irq, 0, "DMA", dmac);
-       if (err < 0) {
-               printk(KERN_ERR "%s: failed to get irq\n", __func__);
-               goto err_clk;
-       }
-
-       regptr = regs + PL080_Cx_BASE(0);
-
-       for (ch = 0; ch < 8; ch++, chptr++) {
-               pr_debug("%s: registering DMA %d (%p)\n",
-                        __func__, chno + ch, regptr);
-
-               chptr->bit = 1 << ch;
-               chptr->number = chno + ch;
-               chptr->dmac = dmac;
-               chptr->regs = regptr;
-               regptr += PL080_Cx_STRIDE;
-       }
-
-       /* for the moment, permanently enable the controller */
-       writel(PL080_CONFIG_ENABLE, regs + PL080_CONFIG);
-
-       printk(KERN_INFO "PL080: IRQ %d, at %p, channels %d..%d\n",
-              irq, regs, chno, chno+8);
-
-       return 0;
-
-err_clk:
-       clk_disable_unprepare(dmac->clk);
-       clk_put(dmac->clk);
-err_map:
-       iounmap(regs);
-err_dev:
-       device_unregister(&dmac->dev);
-err_alloc:
-       kfree(dmac);
-       return err;
-}
-
-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);
-       if (!dma_pool) {
-               printk(KERN_ERR "%s: failed to create pool\n", __func__);
-               return -ENOMEM;
-       }
-
-       ret = subsys_system_register(&dma_subsys, NULL);
-       if (ret) {
-               printk(KERN_ERR "%s: failed to create subsys\n", __func__);
-               return -ENOMEM;
-       }
-
-       /* Set all DMA configuration to be DMA, not SDMA */
-       writel(0xffffff, S3C64XX_SDMA_SEL);
-
-       /* Register standard DMA controllers */
-       s3c64xx_dma_init1(0, DMACH_UART0, IRQ_DMA0, 0x75000000);
-       s3c64xx_dma_init1(8, DMACH_PCM1_TX, IRQ_DMA1, 0x75100000);
-
-       return 0;
-}
-
-arch_initcall(s3c64xx_dma_init);
index fe1a98cf0e4c7cb3a63311efec61f507e9ebf8e2..059b1fc8503727d7c84139ce7c2311cbc1a7ab8a 100644 (file)
 #ifndef __ASM_ARCH_DMA_H
 #define __ASM_ARCH_DMA_H __FILE__
 
-#define S3C_DMA_CHANNELS       (16)
+#define S3C64XX_DMA_CHAN(name)         ((unsigned long)(name))
+
+/* DMA0/SDMA0 */
+#define DMACH_UART0            S3C64XX_DMA_CHAN("uart0_tx")
+#define DMACH_UART0_SRC2       S3C64XX_DMA_CHAN("uart0_rx")
+#define DMACH_UART1            S3C64XX_DMA_CHAN("uart1_tx")
+#define DMACH_UART1_SRC2       S3C64XX_DMA_CHAN("uart1_rx")
+#define DMACH_UART2            S3C64XX_DMA_CHAN("uart2_tx")
+#define DMACH_UART2_SRC2       S3C64XX_DMA_CHAN("uart2_rx")
+#define DMACH_UART3            S3C64XX_DMA_CHAN("uart3_tx")
+#define DMACH_UART3_SRC2       S3C64XX_DMA_CHAN("uart3_rx")
+#define DMACH_PCM0_TX          S3C64XX_DMA_CHAN("pcm0_tx")
+#define DMACH_PCM0_RX          S3C64XX_DMA_CHAN("pcm0_rx")
+#define DMACH_I2S0_OUT         S3C64XX_DMA_CHAN("i2s0_tx")
+#define DMACH_I2S0_IN          S3C64XX_DMA_CHAN("i2s0_rx")
+#define DMACH_SPI0_TX          S3C64XX_DMA_CHAN("spi0_tx")
+#define DMACH_SPI0_RX          S3C64XX_DMA_CHAN("spi0_rx")
+#define DMACH_HSI_I2SV40_TX    S3C64XX_DMA_CHAN("i2s2_tx")
+#define DMACH_HSI_I2SV40_RX    S3C64XX_DMA_CHAN("i2s2_rx")
+
+/* DMA1/SDMA1 */
+#define DMACH_PCM1_TX          S3C64XX_DMA_CHAN("pcm1_tx")
+#define DMACH_PCM1_RX          S3C64XX_DMA_CHAN("pcm1_rx")
+#define DMACH_I2S1_OUT         S3C64XX_DMA_CHAN("i2s1_tx")
+#define DMACH_I2S1_IN          S3C64XX_DMA_CHAN("i2s1_rx")
+#define DMACH_SPI1_TX          S3C64XX_DMA_CHAN("spi1_tx")
+#define DMACH_SPI1_RX          S3C64XX_DMA_CHAN("spi1_rx")
+#define DMACH_AC97_PCMOUT      S3C64XX_DMA_CHAN("ac97_out")
+#define DMACH_AC97_PCMIN       S3C64XX_DMA_CHAN("ac97_in")
+#define DMACH_AC97_MICIN       S3C64XX_DMA_CHAN("ac97_mic")
+#define DMACH_PWM              S3C64XX_DMA_CHAN("pwm")
+#define DMACH_IRDA             S3C64XX_DMA_CHAN("irda")
+#define DMACH_EXTERNAL         S3C64XX_DMA_CHAN("external")
+#define DMACH_SECURITY_RX      S3C64XX_DMA_CHAN("sec_rx")
+#define DMACH_SECURITY_TX      S3C64XX_DMA_CHAN("sec_tx")
 
-/* see mach-s3c2410/dma.h for notes on dma channel numbers */
-
-/* Note, for the S3C64XX architecture we keep the DMACH_
- * defines in the order they are allocated to [S]DMA0/[S]DMA1
- * so that is easy to do DHACH_ -> DMA controller conversion
- */
 enum dma_ch {
-       /* DMA0/SDMA0 */
-       DMACH_UART0 = 0,
-       DMACH_UART0_SRC2,
-       DMACH_UART1,
-       DMACH_UART1_SRC2,
-       DMACH_UART2,
-       DMACH_UART2_SRC2,
-       DMACH_UART3,
-       DMACH_UART3_SRC2,
-       DMACH_PCM0_TX,
-       DMACH_PCM0_RX,
-       DMACH_I2S0_OUT,
-       DMACH_I2S0_IN,
-       DMACH_SPI0_TX,
-       DMACH_SPI0_RX,
-       DMACH_HSI_I2SV40_TX,
-       DMACH_HSI_I2SV40_RX,
+       DMACH_MAX = 32
+};
 
-       /* DMA1/SDMA1 */
-       DMACH_PCM1_TX = 16,
-       DMACH_PCM1_RX,
-       DMACH_I2S1_OUT,
-       DMACH_I2S1_IN,
-       DMACH_SPI1_TX,
-       DMACH_SPI1_RX,
-       DMACH_AC97_PCMOUT,
-       DMACH_AC97_PCMIN,
-       DMACH_AC97_MICIN,
-       DMACH_PWM,
-       DMACH_IRDA,
-       DMACH_EXTERNAL,
-       DMACH_RES1,
-       DMACH_RES2,
-       DMACH_SECURITY_RX,      /* SDMA1 only */
-       DMACH_SECURITY_TX,      /* SDMA1 only */
-       DMACH_MAX               /* the end */
+struct s3c2410_dma_client {
+       char    *name;
 };
 
 static inline bool samsung_dma_has_circular(void)
@@ -65,67 +62,10 @@ static inline bool samsung_dma_has_circular(void)
 
 static inline bool samsung_dma_is_dmadev(void)
 {
-       return false;
+       return true;
 }
-#define S3C2410_DMAF_CIRCULAR          (1 << 0)
-
-#include <plat/dma.h>
-
-#define DMACH_LOW_LEVEL (1<<28) /* use this to specifiy hardware ch no */
-
-struct s3c64xx_dma_buff;
-
-/** s3c64xx_dma_buff - S3C64XX DMA buffer descriptor
- * @next: Pointer to next buffer in queue or ring.
- * @pw: Client provided identifier
- * @lli: Pointer to hardware descriptor this buffer is associated with.
- * @lli_dma: Hardare address of the descriptor.
- */
-struct s3c64xx_dma_buff {
-       struct s3c64xx_dma_buff *next;
-
-       void                    *pw;
-       struct pl080s_lli       *lli;
-       dma_addr_t               lli_dma;
-};
-
-struct s3c64xx_dmac;
-
-struct s3c2410_dma_chan {
-       unsigned char            number;      /* number of this dma channel */
-       unsigned char            in_use;      /* channel allocated */
-       unsigned char            bit;         /* bit for enable/disable/etc */
-       unsigned char            hw_width;
-       unsigned char            peripheral;
-
-       unsigned int             flags;
-       enum dma_data_direction  source;
-
-
-       dma_addr_t              dev_addr;
-
-       struct s3c2410_dma_client *client;
-       struct s3c64xx_dmac     *dmac;          /* pointer to controller */
-
-       void __iomem            *regs;
-
-       /* cdriver callbacks */
-       s3c2410_dma_cbfn_t       callback_fn;   /* buffer done callback */
-       s3c2410_dma_opfn_t       op_fn;         /* channel op callback */
-
-       /* buffer list and information */
-       struct s3c64xx_dma_buff *curr;          /* current dma buffer */
-       struct s3c64xx_dma_buff *next;          /* next buffer to load */
-       struct s3c64xx_dma_buff *end;           /* end of queue */
-
-       /* note, when channel is running in circular mode, curr is the
-        * first buffer enqueued, end is the last and curr is where the
-        * last buffer-done event is set-at. The buffers are not freed
-        * and the last buffer hardware descriptor points back to the
-        * first.
-        */
-};
 
-#include <plat/dma-core.h>
+#include <linux/amba/pl08x.h>
+#include <plat/dma-ops.h>
 
 #endif /* __ASM_ARCH_IRQ_H */
diff --git a/arch/arm/mach-s3c64xx/pl080.c b/arch/arm/mach-s3c64xx/pl080.c
new file mode 100644 (file)
index 0000000..901a984
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * Samsung's S3C64XX generic DMA support using amba-pl08x driver.
+ *
+ * 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/kernel.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/pl080.h>
+#include <linux/amba/pl08x.h>
+#include <linux/of.h>
+
+#include <mach/irqs.h>
+#include <mach/map.h>
+
+#include "regs-sys.h"
+
+static int pl08x_get_xfer_signal(const struct pl08x_channel_data *cd)
+{
+       return cd->min_signal;
+}
+
+static void pl08x_put_xfer_signal(const struct pl08x_channel_data *cd, int ch)
+{
+}
+
+/*
+ * DMA0
+ */
+
+static struct pl08x_channel_data s3c64xx_dma0_info[] = {
+       {
+               .bus_id = "uart0_tx",
+               .min_signal = 0,
+               .max_signal = 0,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "uart0_rx",
+               .min_signal = 1,
+               .max_signal = 1,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "uart1_tx",
+               .min_signal = 2,
+               .max_signal = 2,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "uart1_rx",
+               .min_signal = 3,
+               .max_signal = 3,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "uart2_tx",
+               .min_signal = 4,
+               .max_signal = 4,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "uart2_rx",
+               .min_signal = 5,
+               .max_signal = 5,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "uart3_tx",
+               .min_signal = 6,
+               .max_signal = 6,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "uart3_rx",
+               .min_signal = 7,
+               .max_signal = 7,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "pcm0_tx",
+               .min_signal = 8,
+               .max_signal = 8,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "pcm0_rx",
+               .min_signal = 9,
+               .max_signal = 9,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "i2s0_tx",
+               .min_signal = 10,
+               .max_signal = 10,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "i2s0_rx",
+               .min_signal = 11,
+               .max_signal = 11,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "spi0_tx",
+               .min_signal = 12,
+               .max_signal = 12,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "spi0_rx",
+               .min_signal = 13,
+               .max_signal = 13,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "i2s2_tx",
+               .min_signal = 14,
+               .max_signal = 14,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "i2s2_rx",
+               .min_signal = 15,
+               .max_signal = 15,
+               .periph_buses = PL08X_AHB2,
+       }
+};
+
+struct pl08x_platform_data s3c64xx_dma0_plat_data = {
+       .memcpy_channel = {
+               .bus_id = "memcpy",
+               .cctl_memcpy =
+                       (PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT |
+                       PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT |
+                       PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT |
+                       PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT |
+                       PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE |
+                       PL080_CONTROL_PROT_SYS),
+       },
+       .lli_buses = PL08X_AHB1,
+       .mem_buses = PL08X_AHB1,
+       .get_xfer_signal = pl08x_get_xfer_signal,
+       .put_xfer_signal = pl08x_put_xfer_signal,
+       .slave_channels = s3c64xx_dma0_info,
+       .num_slave_channels = ARRAY_SIZE(s3c64xx_dma0_info),
+};
+
+static AMBA_AHB_DEVICE(s3c64xx_dma0, "dma-pl080s.0", 0,
+                       0x75000000, {IRQ_DMA0}, &s3c64xx_dma0_plat_data);
+
+/*
+ * DMA1
+ */
+
+static struct pl08x_channel_data s3c64xx_dma1_info[] = {
+       {
+               .bus_id = "pcm1_tx",
+               .min_signal = 0,
+               .max_signal = 0,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "pcm1_rx",
+               .min_signal = 1,
+               .max_signal = 1,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "i2s1_tx",
+               .min_signal = 2,
+               .max_signal = 2,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "i2s1_rx",
+               .min_signal = 3,
+               .max_signal = 3,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "spi1_tx",
+               .min_signal = 4,
+               .max_signal = 4,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "spi1_rx",
+               .min_signal = 5,
+               .max_signal = 5,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "ac97_out",
+               .min_signal = 6,
+               .max_signal = 6,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "ac97_in",
+               .min_signal = 7,
+               .max_signal = 7,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "ac97_mic",
+               .min_signal = 8,
+               .max_signal = 8,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "pwm",
+               .min_signal = 9,
+               .max_signal = 9,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "irda",
+               .min_signal = 10,
+               .max_signal = 10,
+               .periph_buses = PL08X_AHB2,
+       }, {
+               .bus_id = "external",
+               .min_signal = 11,
+               .max_signal = 11,
+               .periph_buses = PL08X_AHB2,
+       },
+};
+
+struct pl08x_platform_data s3c64xx_dma1_plat_data = {
+       .memcpy_channel = {
+               .bus_id = "memcpy",
+               .cctl_memcpy =
+                       (PL080_BSIZE_4 << PL080_CONTROL_SB_SIZE_SHIFT |
+                       PL080_BSIZE_4 << PL080_CONTROL_DB_SIZE_SHIFT |
+                       PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT |
+                       PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT |
+                       PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE |
+                       PL080_CONTROL_PROT_SYS),
+       },
+       .lli_buses = PL08X_AHB1,
+       .mem_buses = PL08X_AHB1,
+       .get_xfer_signal = pl08x_get_xfer_signal,
+       .put_xfer_signal = pl08x_put_xfer_signal,
+       .slave_channels = s3c64xx_dma1_info,
+       .num_slave_channels = ARRAY_SIZE(s3c64xx_dma1_info),
+};
+
+static AMBA_AHB_DEVICE(s3c64xx_dma1, "dma-pl080s.1", 0,
+                       0x75100000, {IRQ_DMA1}, &s3c64xx_dma1_plat_data);
+
+static int __init s3c64xx_pl080_init(void)
+{
+       /* Set all DMA configuration to be DMA, not SDMA */
+       writel(0xffffff, S3C64XX_SDMA_SEL);
+
+       if (of_have_populated_dt())
+               return 0;
+
+       amba_device_register(&s3c64xx_dma0_device, &iomem_resource);
+       amba_device_register(&s3c64xx_dma1_device, &iomem_resource);
+
+       return 0;
+}
+arch_initcall(s3c64xx_pl080_init);
index 713c86cd3d640ab758b723da8e4abd4ee6bf85c6..6fd4acb8f18713b204e45d2c8a32f8854b061ae9 100644 (file)
@@ -20,7 +20,7 @@
 #include <mach/hardware.h>
 #include <mach/irqs.h>
 
-static u32 notrace sa1100_read_sched_clock(void)
+static u64 notrace sa1100_read_sched_clock(void)
 {
        return readl_relaxed(OSCR);
 }
@@ -122,7 +122,7 @@ void __init sa1100_timer_init(void)
        writel_relaxed(0, OIER);
        writel_relaxed(OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3, OSSR);
 
-       setup_sched_clock(sa1100_read_sched_clock, 32, 3686400);
+       sched_clock_register(sa1100_read_sched_clock, 32, 3686400);
 
        ckevt_sa1100_osmr0.cpumask = cpumask_of(0);
 
index a4a4b75109b218c53fc2cb8357f2465fb90b18d7..3e57d457308a4c16d0e4970e7093ffb3faab6dbe 100644 (file)
@@ -1,6 +1,10 @@
+config ARCH_SHMOBILE
+       bool
+
 config ARCH_SHMOBILE_MULTI
-       bool "SH-Mobile Series" if ARCH_MULTI_V7
+       bool "Renesas ARM SoCs" if ARCH_MULTI_V7
        depends on MMU
+       select ARCH_SHMOBILE
        select CPU_V7
        select GENERIC_CLOCKEVENTS
        select HAVE_ARM_SCU if SMP
@@ -15,24 +19,39 @@ config ARCH_SHMOBILE_MULTI
 
 if ARCH_SHMOBILE_MULTI
 
-comment "SH-Mobile System Type"
+comment "Renesas ARM SoCs System Type"
 
 config ARCH_EMEV2
        bool "Emma Mobile EV2"
 
-comment "SH-Mobile Board Type"
+config ARCH_R7S72100
+       bool "RZ/A1H (R7S72100)"
+
+config ARCH_R8A7791
+       bool "R-Car M2 (R8A77910)"
+       select RENESAS_IRQC
+
+comment "Renesas ARM SoCs Board Type"
+
+config MACH_GENMAI
+       bool "Genmai board"
+       depends on ARCH_R7S72100
+
+config MACH_KOELSCH
+       bool "Koelsch board"
+       depends on ARCH_R8A7791
 
 config MACH_KZM9D
        bool "KZM9D board"
        depends on ARCH_EMEV2
        select REGULATOR_FIXED_VOLTAGE if REGULATOR
 
-comment "SH-Mobile System Configuration"
+comment "Renesas ARM SoCs System Configuration"
 endif
 
-if ARCH_SHMOBILE
+if ARCH_SHMOBILE_LEGACY
 
-comment "SH-Mobile System Type"
+comment "Renesas ARM SoCs System Type"
 
 config ARCH_SH7372
        bool "SH-Mobile AP4 (SH7372)"
@@ -97,23 +116,28 @@ config ARCH_R8A7790
 
 config ARCH_R8A7791
        bool "R-Car M2 (R8A77910)"
+       select ARCH_WANT_OPTIONAL_GPIOLIB
        select ARM_GIC
        select CPU_V7
        select SH_CLK_CPG
+       select RENESAS_IRQC
 
 config ARCH_EMEV2
        bool "Emma Mobile EV2"
        select ARCH_WANT_OPTIONAL_GPIOLIB
        select ARM_GIC
        select CPU_V7
+       select USE_OF
+       select AUTO_ZRELADDR
 
 config ARCH_R7S72100
        bool "RZ/A1H (R7S72100)"
+       select ARCH_WANT_OPTIONAL_GPIOLIB
        select ARM_GIC
        select CPU_V7
        select SH_CLK_CPG
 
-comment "SH-Mobile Board Type"
+comment "Renesas ARM SoCs Board Type"
 
 config MACH_APE6EVM
        bool "APE6EVM board"
@@ -190,6 +214,17 @@ config MACH_GENMAI
        depends on ARCH_R7S72100
        select USE_OF
 
+config MACH_GENMAI_REFERENCE
+       bool "Genmai board - Reference Device Tree Implementation"
+       depends on ARCH_R7S72100
+       select USE_OF
+       ---help---
+          Use reference implementation of Genmai board support
+          which makes use of device tree at the expense
+          of not supporting a number of devices.
+
+          This is intended to aid developers
+
 config MACH_MARZEN
        bool "MARZEN board"
        depends on ARCH_R8A7779
@@ -231,11 +266,16 @@ config MACH_KOELSCH
        depends on ARCH_R8A7791
        select USE_OF
 
-config MACH_KZM9D
-       bool "KZM9D board"
-       depends on ARCH_EMEV2
-       select REGULATOR_FIXED_VOLTAGE if REGULATOR
+config MACH_KOELSCH_REFERENCE
+       bool "Koelsch board - Reference Device Tree Implementation"
+       depends on ARCH_R8A7791
        select USE_OF
+       ---help---
+          Use reference implementation of Koelsch board support
+          which makes use of device tree at the expense
+          of not supporting a number of devices.
+
+          This is intended to aid developers
 
 config MACH_KZM9G
        bool "KZM-A9-GT board"
@@ -261,7 +301,7 @@ config MACH_KZM9G_REFERENCE
 
           This is intended to aid developers
 
-comment "SH-Mobile System Configuration"
+comment "Renesas ARM SoCs System Configuration"
 
 config CPU_HAS_INTEVT
         bool
@@ -274,7 +314,7 @@ source "drivers/sh/Kconfig"
 
 endif
 
-if ARCH_SHMOBILE || ARCH_SHMOBILE_MULTI
+if ARCH_SHMOBILE
 
 menu "Timer and clock configuration"
 
@@ -286,8 +326,8 @@ config SHMOBILE_TIMER_HZ
          Allows the configuration of the timer frequency. It is customary
          to have the timer interrupt run at 1000 Hz or 100 Hz, but in the
          case of low timer frequencies other values may be more suitable.
-         SH-Mobile systems using a 32768 Hz RCLK for clock events may want
-         to select a HZ value such as 128 that can evenly divide RCLK.
+         Renesas ARM SoC systems using a 32768 Hz RCLK for clock events may
+         want to select a HZ value such as 128 that can evenly divide RCLK.
          A HZ value that does not divide evenly may cause timer drift.
 
 config SH_TIMER_CMT
index 51db2bcafabf028f97cb4ffc5e32def8ef1aad77..1c131046dec634ca92b0f61a99def17cdc7362ca 100644 (file)
@@ -56,6 +56,8 @@ obj-$(CONFIG_ARCH_R8A7779)    += pm-r8a7779.o
 
 # Board objects
 ifdef CONFIG_ARCH_SHMOBILE_MULTI
+obj-$(CONFIG_MACH_GENMAI)      += board-genmai-reference.o
+obj-$(CONFIG_MACH_KOELSCH)     += board-koelsch-reference.o
 obj-$(CONFIG_MACH_KZM9D)       += board-kzm9d-reference.o
 else
 obj-$(CONFIG_MACH_APE6EVM)     += board-ape6evm.o
@@ -64,6 +66,7 @@ obj-$(CONFIG_MACH_MACKEREL)   += board-mackerel.o
 obj-$(CONFIG_MACH_BOCKW)       += board-bockw.o
 obj-$(CONFIG_MACH_BOCKW_REFERENCE)     += board-bockw-reference.o
 obj-$(CONFIG_MACH_GENMAI)      += board-genmai.o
+obj-$(CONFIG_MACH_GENMAI_REFERENCE)    += board-genmai-reference.o
 obj-$(CONFIG_MACH_MARZEN)      += board-marzen.o
 obj-$(CONFIG_MACH_MARZEN_REFERENCE)    += board-marzen-reference.o
 obj-$(CONFIG_MACH_LAGER)       += board-lager.o
@@ -71,7 +74,7 @@ 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_KOELSCH_REFERENCE)   += board-koelsch-reference.o
 obj-$(CONFIG_MACH_KZM9G)       += board-kzm9g.o
 obj-$(CONFIG_MACH_KZM9G_REFERENCE)     += board-kzm9g-reference.o
 endif
index 391d72a5536ceb473acee7eaf2f0312ef268b6ce..759e4f8fcd37b9b793fb4d8024223ce76d0d77a8 100644 (file)
@@ -6,9 +6,10 @@ 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_GENMAI) += 0x8008000
+loadaddr-$(CONFIG_MACH_GENMAI) += 0x08008000
+loadaddr-$(CONFIG_MACH_GENMAI_REFERENCE) += 0x08008000
 loadaddr-$(CONFIG_MACH_KOELSCH) += 0x40008000
-loadaddr-$(CONFIG_MACH_KZM9D) += 0x40008000
+loadaddr-$(CONFIG_MACH_KOELSCH_REFERENCE) += 0x40008000
 loadaddr-$(CONFIG_MACH_KZM9G) += 0x41008000
 loadaddr-$(CONFIG_MACH_KZM9G_REFERENCE) += 0x41008000
 loadaddr-$(CONFIG_MACH_LAGER) += 0x40008000
index 0fa068e30a3001992952a41230cf9ca609793c72..fe071a9130b78d2986faecabfa7fb2f208166d4e 100644 (file)
@@ -168,7 +168,7 @@ static const struct sh_mmcif_plat_data mmcif0_pdata __initconst = {
 };
 
 static const struct resource mmcif0_resources[] __initconst = {
-       DEFINE_RES_MEM_NAMED(0xee200000, 0x100, "MMCIF0"),
+       DEFINE_RES_MEM(0xee200000, 0x100),
        DEFINE_RES_IRQ(gic_spi(169)),
 };
 
@@ -179,7 +179,7 @@ static const struct sh_mobile_sdhi_info sdhi0_pdata __initconst = {
 };
 
 static const struct resource sdhi0_resources[] __initconst = {
-       DEFINE_RES_MEM_NAMED(0xee100000, 0x100, "SDHI0"),
+       DEFINE_RES_MEM(0xee100000, 0x100),
        DEFINE_RES_IRQ(gic_spi(165)),
 };
 
@@ -191,7 +191,7 @@ static const struct sh_mobile_sdhi_info sdhi1_pdata __initconst = {
 };
 
 static const struct resource sdhi1_resources[] __initconst = {
-       DEFINE_RES_MEM_NAMED(0xee120000, 0x100, "SDHI1"),
+       DEFINE_RES_MEM(0xee120000, 0x100),
        DEFINE_RES_IRQ(gic_spi(166)),
 };
 
index 958e3cbf0ac2f2110e7f4fc9ca41dc19e66e4ca8..d9e28c7aca491a1bc6d76f49be8be5db42f18f1e 100644 (file)
@@ -958,7 +958,7 @@ static struct resource fsi_resources[] = {
        [0] = {
                .name   = "FSI",
                .start  = 0xfe1f0000,
-               .end    = 0xfe1f8400 - 1,
+               .end    = 0xfe1f0400 - 1,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
index ae88fdad4b3a9921ea02f9c1db001348753bb98a..027373f8de8215a74dc2b757e25d6e638416e7c8 100644 (file)
@@ -19,7 +19,6 @@
  */
 
 #include <linux/of_platform.h>
-#include <linux/pinctrl/machine.h>
 #include <mach/common.h>
 #include <mach/r8a7778.h>
 #include <asm/mach/arch.h>
  *     see board-bock.c for checking detail of dip-switch
  */
 
-static const struct pinctrl_map bockw_pinctrl_map[] = {
-       /* SCIF0 */
-       PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.0", "pfc-r8a7778",
-                                 "scif0_data_a", "scif0"),
-       PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.0", "pfc-r8a7778",
-                                 "scif0_ctrl", "scif0"),
-};
-
 #define FPGA   0x18200000
 #define IRQ0MR 0x30
 #define COMCTLR        0x101c
+
+#define PFC    0xfffc0000
+#define PUPR4  0x110
 static void __init bockw_init(void)
 {
-       static void __iomem *fpga;
+       void __iomem *fpga;
+       void __iomem *pfc;
 
        r8a7778_clock_init();
        r8a7778_init_irq_extpin_dt(1);
-
-       pinctrl_register_mappings(bockw_pinctrl_map,
-                                 ARRAY_SIZE(bockw_pinctrl_map));
-       r8a7778_pinmux_init();
        r8a7778_add_dt_devices();
 
        fpga = ioremap_nocache(FPGA, SZ_1M);
@@ -63,6 +54,19 @@ static void __init bockw_init(void)
                u16 val = ioread16(fpga + IRQ0MR);
                val &= ~(1 << 4); /* enable SMSC911x */
                iowrite16(val, fpga + IRQ0MR);
+
+               iounmap(fpga);
+       }
+
+       pfc = ioremap_nocache(PFC, 0x200);
+       if (pfc) {
+               /*
+                * FIXME
+                *
+                * SDHI CD/WP pin needs pull-up
+                */
+               iowrite32(ioread32(pfc + PUPR4) | (3 << 26), pfc + PUPR4);
+               iounmap(pfc);
        }
 
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
index 38611526fe9a55953372afcd2662aa668b34e080..eb5b54fc5cc994dc0f9fbe9b7cbfc0f5cd063bd1 100644 (file)
@@ -116,6 +116,11 @@ static struct regulator_consumer_supply dummy_supplies[] = {
        REGULATOR_SUPPLY("vdd33a", "smsc911x"),
 };
 
+static struct regulator_consumer_supply fixed3v3_power_consumers[] = {
+       REGULATOR_SUPPLY("vmmc", "sh_mmcif"),
+       REGULATOR_SUPPLY("vqmmc", "sh_mmcif"),
+};
+
 static struct smsc911x_platform_config smsc911x_data __initdata = {
        .irq_polarity   = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
        .irq_type       = SMSC911X_IRQ_TYPE_PUSH_PULL,
@@ -271,7 +276,6 @@ static struct resource mmc_resources[] __initdata = {
 
 static struct sh_mmcif_plat_data sh_mmcif_plat __initdata = {
        .sup_pclk       = 0,
-       .ocr            = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34,
        .caps           = MMC_CAP_4_BIT_DATA |
                          MMC_CAP_8_BIT_DATA |
                          MMC_CAP_NEEDS_POLL,
@@ -328,11 +332,11 @@ static struct rsnd_ssi_platform_info rsnd_ssi[] = {
        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(2, 0, gic_iid(0x85), RSND_SSI_CLK_PIN_SHARE),
        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),
+       RSND_SSI_SET(4, 0, gic_iid(0x86), RSND_SSI_CLK_PIN_SHARE),
 };
 
 static struct rsnd_scu_platform_info rsnd_scu[9] = {
@@ -614,6 +618,10 @@ static void __init bockw_init(void)
                &usb_phy_platform_data,
                sizeof(struct rcar_phy_platform_data));
 
+       regulator_register_fixed(0, dummy_supplies,
+                                ARRAY_SIZE(dummy_supplies));
+       regulator_register_always_on(1, "fixed-3.3V", fixed3v3_power_consumers,
+                                    ARRAY_SIZE(fixed3v3_power_consumers), 3300000);
 
        /* for SMSC */
        fpga = ioremap_nocache(FPGA, SZ_1M);
@@ -629,9 +637,6 @@ static void __init bockw_init(void)
                val &= ~(1 << 4); /* enable SMSC911x */
                iowrite16(val, fpga + IRQ0MR);
 
-               regulator_register_fixed(0, dummy_supplies,
-                                        ARRAY_SIZE(dummy_supplies));
-
                platform_device_register_resndata(
                        &platform_bus, "smsc911x", -1,
                        smsc911x_resources, ARRAY_SIZE(smsc911x_resources),
diff --git a/arch/arm/mach-shmobile/board-genmai-reference.c b/arch/arm/mach-shmobile/board-genmai-reference.c
new file mode 100644 (file)
index 0000000..7630c10
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Genmai board support
+ *
+ * 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/clk-provider.h>
+#include <linux/kernel.h>
+#include <linux/of_platform.h>
+#include <mach/common.h>
+#include <mach/r7s72100.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+static void __init genmai_add_standard_devices(void)
+{
+#ifdef CONFIG_COMMON_CLK
+       of_clk_init(NULL);
+#else
+       r7s72100_clock_init();
+#endif
+       r7s72100_add_dt_devices();
+       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char * const genmai_boards_compat_dt[] __initconst = {
+       "renesas,genmai-reference",
+       NULL,
+};
+
+DT_MACHINE_START(GENMAI_DT, "genmai")
+       .init_early     = r7s72100_init_early,
+       .init_machine   = genmai_add_standard_devices,
+       .dt_compat      = genmai_boards_compat_dt,
+MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-koelsch-reference.c b/arch/arm/mach-shmobile/board-koelsch-reference.c
new file mode 100644 (file)
index 0000000..a804a17
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Koelsch board support - Reference DT implementation
+ *
+ * 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/clk-provider.h>
+#include <linux/kernel.h>
+#include <linux/of_platform.h>
+#include <mach/common.h>
+#include <mach/rcar-gen2.h>
+#include <mach/r8a7791.h>
+#include <asm/mach/arch.h>
+
+static void __init koelsch_add_standard_devices(void)
+{
+#ifdef CONFIG_COMMON_CLK
+       of_clk_init(NULL);
+#else
+       r8a7791_clock_init();
+#endif
+       r8a7791_add_dt_devices();
+       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char * const koelsch_boards_compat_dt[] __initconst = {
+       "renesas,koelsch-reference",
+       NULL,
+};
+
+DT_MACHINE_START(KOELSCH_DT, "koelsch")
+       .smp            = smp_ops(r8a7791_smp_ops),
+       .init_early     = r8a7791_init_early,
+       .init_time      = rcar_gen2_timer_init,
+       .init_machine   = koelsch_add_standard_devices,
+       .init_late      = shmobile_init_late,
+       .dt_compat      = koelsch_boards_compat_dt,
+MACHINE_END
index ace1711a6cd83b1b8dcde8aead16a97156d72c8d..6e12914d6d587ade5543e90bdfb7c05459684f77 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
 #include <linux/kernel.h>
+#include <linux/leds.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/platform_data/gpio-rcar.h>
 #include <linux/platform_device.h>
 #include <mach/common.h>
 #include <mach/r8a7791.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
+/* LEDS */
+static struct gpio_led koelsch_leds[] = {
+       {
+               .name           = "led8",
+               .gpio           = RCAR_GP_PIN(2, 21),
+               .default_state  = LEDS_GPIO_DEFSTATE_ON,
+       }, {
+               .name           = "led7",
+               .gpio           = RCAR_GP_PIN(2, 20),
+               .default_state  = LEDS_GPIO_DEFSTATE_ON,
+       }, {
+               .name           = "led6",
+               .gpio           = RCAR_GP_PIN(2, 19),
+               .default_state  = LEDS_GPIO_DEFSTATE_ON,
+       },
+};
+
+static const struct gpio_led_platform_data koelsch_leds_pdata __initconst = {
+       .leds           = koelsch_leds,
+       .num_leds       = ARRAY_SIZE(koelsch_leds),
+};
+
+/* GPIO KEY */
+#define GPIO_KEY(c, g, d, ...) \
+       { .code = c, .gpio = g, .desc = d, .active_low = 1, \
+         .wakeup = 1, .debounce_interval = 20 }
+
+static struct gpio_keys_button gpio_buttons[] = {
+       GPIO_KEY(KEY_4,         RCAR_GP_PIN(5, 3),      "SW2-pin4"),
+       GPIO_KEY(KEY_3,         RCAR_GP_PIN(5, 2),      "SW2-pin3"),
+       GPIO_KEY(KEY_2,         RCAR_GP_PIN(5, 1),      "SW2-pin2"),
+       GPIO_KEY(KEY_1,         RCAR_GP_PIN(5, 0),      "SW2-pin1"),
+       GPIO_KEY(KEY_G,         RCAR_GP_PIN(7, 6),      "SW36"),
+       GPIO_KEY(KEY_F,         RCAR_GP_PIN(7, 5),      "SW35"),
+       GPIO_KEY(KEY_E,         RCAR_GP_PIN(7, 4),      "SW34"),
+       GPIO_KEY(KEY_D,         RCAR_GP_PIN(7, 3),      "SW33"),
+       GPIO_KEY(KEY_C,         RCAR_GP_PIN(7, 2),      "SW32"),
+       GPIO_KEY(KEY_B,         RCAR_GP_PIN(7, 1),      "SW31"),
+       GPIO_KEY(KEY_A,         RCAR_GP_PIN(7, 0),      "SW30"),
+};
+
+static const struct gpio_keys_platform_data koelsch_keys_pdata __initconst = {
+       .buttons        = gpio_buttons,
+       .nbuttons       = ARRAY_SIZE(gpio_buttons),
+};
+
+static const struct pinctrl_map koelsch_pinctrl_map[] = {
+       /* SCIF0 (CN19: DEBUG SERIAL0) */
+       PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.6", "pfc-r8a7791",
+                                 "scif0_data_d", "scif0"),
+       /* SCIF1 (CN20: DEBUG SERIAL1) */
+       PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.7", "pfc-r8a7791",
+                                 "scif1_data_d", "scif1"),
+};
+
 static void __init koelsch_add_standard_devices(void)
 {
        r8a7791_clock_init();
+       pinctrl_register_mappings(koelsch_pinctrl_map,
+                                 ARRAY_SIZE(koelsch_pinctrl_map));
+       r8a7791_pinmux_init();
        r8a7791_add_standard_devices();
+       platform_device_register_data(&platform_bus, "leds-gpio", -1,
+                                     &koelsch_leds_pdata,
+                                     sizeof(koelsch_leds_pdata));
+       platform_device_register_data(&platform_bus, "gpio-keys", -1,
+                                     &koelsch_keys_pdata,
+                                     sizeof(koelsch_keys_pdata));
 }
 
 static const char * const koelsch_boards_compat_dt[] __initconst = {
@@ -41,7 +111,8 @@ static const char * const koelsch_boards_compat_dt[] __initconst = {
 DT_MACHINE_START(KOELSCH_DT, "koelsch")
        .smp            = smp_ops(r8a7791_smp_ops),
        .init_early     = r8a7791_init_early,
-       .init_machine   = koelsch_add_standard_devices,
        .init_time      = rcar_gen2_timer_init,
+       .init_machine   = koelsch_add_standard_devices,
+       .init_late      = shmobile_init_late,
        .dt_compat      = koelsch_boards_compat_dt,
 MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-kzm9d.c b/arch/arm/mach-shmobile/board-kzm9d.c
deleted file mode 100644 (file)
index 30c2cc6..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * kzm9d board support
- *
- * Copyright (C) 2012  Renesas Solutions Corp.
- * Copyright (C) 2012  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/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/regulator/fixed.h>
-#include <linux/regulator/machine.h>
-#include <linux/smsc911x.h>
-#include <mach/common.h>
-#include <mach/emev2.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-/* Dummy supplies, where voltage doesn't matter */
-static struct regulator_consumer_supply dummy_supplies[] = {
-       REGULATOR_SUPPLY("vddvario", "smsc911x"),
-       REGULATOR_SUPPLY("vdd33a", "smsc911x"),
-};
-
-/* Ether */
-static struct resource smsc911x_resources[] = {
-       [0] = {
-               .start  = 0x20000000,
-               .end    = 0x2000ffff,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = EMEV2_GPIO_IRQ(1),
-               .flags  = IORESOURCE_IRQ | IRQF_TRIGGER_HIGH,
-       },
-};
-
-static struct smsc911x_platform_config smsc911x_platdata = {
-       .flags          = SMSC911X_USE_32BIT,
-       .irq_type       = SMSC911X_IRQ_TYPE_PUSH_PULL,
-       .irq_polarity   = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
-};
-
-static struct platform_device smsc91x_device = {
-       .name   = "smsc911x",
-       .id     = -1,
-       .dev    = {
-                 .platform_data = &smsc911x_platdata,
-               },
-       .num_resources  = ARRAY_SIZE(smsc911x_resources),
-       .resource       = smsc911x_resources,
-};
-
-static struct platform_device *kzm9d_devices[] __initdata = {
-       &smsc91x_device,
-};
-
-void __init kzm9d_add_standard_devices(void)
-{
-       regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
-
-       emev2_add_standard_devices();
-
-       platform_add_devices(kzm9d_devices, ARRAY_SIZE(kzm9d_devices));
-}
-
-static const char *kzm9d_boards_compat_dt[] __initdata = {
-       "renesas,kzm9d",
-       NULL,
-};
-
-DT_MACHINE_START(KZM9D_DT, "kzm9d")
-       .smp            = smp_ops(emev2_smp_ops),
-       .map_io         = emev2_map_io,
-       .init_early     = emev2_init_delay,
-       .init_machine   = kzm9d_add_standard_devices,
-       .init_late      = shmobile_init_late,
-       .dt_compat      = kzm9d_boards_compat_dt,
-MACHINE_END
index 1a1a4a888632afb67fa47a532d3c251d3818fd65..51a3bcc704e5257db674b39aa8de845d8d9fd853 100644 (file)
 
 #include <linux/init.h>
 #include <linux/of_platform.h>
+#include <mach/common.h>
+#include <mach/rcar-gen2.h>
 #include <mach/r8a7790.h>
 #include <asm/mach/arch.h>
 
 static void __init lager_add_standard_devices(void)
 {
-       /* clocks are setup late during boot in the case of DT */
        r8a7790_clock_init();
-
        r8a7790_add_dt_devices();
-        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 static const char *lager_boards_compat_dt[] __initdata = {
@@ -42,5 +42,6 @@ DT_MACHINE_START(LAGER_DT, "lager")
        .init_early     = r8a7790_init_early,
        .init_time      = rcar_gen2_timer_init,
        .init_machine   = lager_add_standard_devices,
+       .init_late      = shmobile_init_late,
        .dt_compat      = lager_boards_compat_dt,
 MACHINE_END
index a8d3ce646fb900514fa983964bf8d70d0e88c278..f20c10a18543973c3d5797d83e8ac4bae26c8708 100644 (file)
@@ -31,7 +31,9 @@
 #include <linux/platform_data/rcar-du.h>
 #include <linux/platform_device.h>
 #include <linux/phy.h>
+#include <linux/regulator/driver.h>
 #include <linux/regulator/fixed.h>
+#include <linux/regulator/gpio-regulator.h>
 #include <linux/regulator/machine.h>
 #include <linux/sh_eth.h>
 #include <mach/common.h>
 #include <mach/r8a7790.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/mtd.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/rspi.h>
+#include <linux/spi/spi.h>
 
 /* DU */
 static struct rcar_du_encoder_data lager_du_encoders[] = {
@@ -120,7 +127,8 @@ static const struct gpio_led_platform_data lager_leds_pdata __initconst = {
 
 /* GPIO KEY */
 #define GPIO_KEY(c, g, d, ...) \
-       { .code = c, .gpio = g, .desc = d, .active_low = 1 }
+       { .code = c, .gpio = g, .desc = d, .active_low = 1, \
+         .wakeup = 1, .debounce_interval = 20 }
 
 static struct gpio_keys_button gpio_buttons[] = {
        GPIO_KEY(KEY_4,         RCAR_GP_PIN(1, 28),     "SW2-pin4"),
@@ -140,6 +148,71 @@ static struct regulator_consumer_supply fixed3v3_power_consumers[] =
        REGULATOR_SUPPLY("vmmc", "sh_mmcif.1"),
 };
 
+/*
+ * SDHI regulator macro
+ *
+ ** FIXME**
+ * Lager board vqmmc is provided via DA9063 PMIC chip,
+ * and we should use ${LINK}/drivers/mfd/da9063-* driver for it.
+ * but, it doesn't have regulator support at this point.
+ * It uses gpio-regulator for vqmmc as quick-hack.
+ */
+#define SDHI_REGULATOR(idx, vdd_pin, vccq_pin)                         \
+static struct regulator_consumer_supply vcc_sdhi##idx##_consumer =     \
+       REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi." #idx);               \
+                                                                       \
+static struct regulator_init_data vcc_sdhi##idx##_init_data = {                \
+       .constraints = {                                                \
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,              \
+       },                                                              \
+       .consumer_supplies      = &vcc_sdhi##idx##_consumer,            \
+       .num_consumer_supplies  = 1,                                    \
+};                                                                     \
+                                                                       \
+static const struct fixed_voltage_config vcc_sdhi##idx##_info __initconst = {\
+       .supply_name    = "SDHI" #idx "Vcc",                            \
+       .microvolts     = 3300000,                                      \
+       .gpio           = vdd_pin,                                      \
+       .enable_high    = 1,                                            \
+       .init_data      = &vcc_sdhi##idx##_init_data,                   \
+};                                                                     \
+                                                                       \
+static struct regulator_consumer_supply vccq_sdhi##idx##_consumer =    \
+       REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi." #idx);              \
+                                                                       \
+static struct regulator_init_data vccq_sdhi##idx##_init_data = {       \
+       .constraints = {                                                \
+               .input_uV       = 3300000,                              \
+               .min_uV         = 1800000,                              \
+               .max_uV         = 3300000,                              \
+               .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |            \
+                                 REGULATOR_CHANGE_STATUS,              \
+       },                                                              \
+       .consumer_supplies      = &vccq_sdhi##idx##_consumer,           \
+       .num_consumer_supplies  = 1,                                    \
+};                                                                     \
+                                                                       \
+static struct gpio vccq_sdhi##idx##_gpio =                             \
+       { vccq_pin, GPIOF_OUT_INIT_HIGH, "vccq-sdhi" #idx };            \
+                                                                       \
+static struct gpio_regulator_state vccq_sdhi##idx##_states[] = {       \
+       { .value = 1800000, .gpios = 0 },                               \
+       { .value = 3300000, .gpios = 1 },                               \
+};                                                                     \
+                                                                       \
+static const struct gpio_regulator_config vccq_sdhi##idx##_info __initconst = {\
+       .supply_name    = "vqmmc",                                      \
+       .gpios          = &vccq_sdhi##idx##_gpio,                       \
+       .nr_gpios       = 1,                                            \
+       .states         = vccq_sdhi##idx##_states,                      \
+       .nr_states      = ARRAY_SIZE(vccq_sdhi##idx##_states),          \
+       .type           = REGULATOR_VOLTAGE,                            \
+       .init_data      = &vccq_sdhi##idx##_init_data,                  \
+};
+
+SDHI_REGULATOR(0, RCAR_GP_PIN(5, 24), RCAR_GP_PIN(5, 29));
+SDHI_REGULATOR(2, RCAR_GP_PIN(5, 25), RCAR_GP_PIN(5, 30));
+
 /* MMCIF */
 static const struct sh_mmcif_plat_data mmcif1_pdata __initconst = {
        .caps           = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE,
@@ -148,7 +221,7 @@ static const struct sh_mmcif_plat_data mmcif1_pdata __initconst = {
 };
 
 static const struct resource mmcif1_resources[] __initconst = {
-       DEFINE_RES_MEM_NAMED(0xee220000, 0x80, "MMCIF1"),
+       DEFINE_RES_MEM(0xee220000, 0x80),
        DEFINE_RES_IRQ(gic_spi(170)),
 };
 
@@ -165,6 +238,59 @@ static const struct resource ether_resources[] __initconst = {
        DEFINE_RES_IRQ(gic_spi(162)),
 };
 
+/* SPI Flash memory (Spansion S25FL512SAGMFIG11 64Mb) */
+static struct mtd_partition spi_flash_part[] = {
+       /* Reserved for user loader program, read-only */
+       {
+               .name = "loader",
+               .offset = 0,
+               .size = SZ_256K,
+               .mask_flags = MTD_WRITEABLE,
+       },
+       /* Reserved for user program, read-only */
+       {
+               .name = "user",
+               .offset = MTDPART_OFS_APPEND,
+               .size = SZ_4M,
+               .mask_flags = MTD_WRITEABLE,
+       },
+       /* All else is writable (e.g. JFFS2) */
+       {
+               .name = "flash",
+               .offset = MTDPART_OFS_APPEND,
+               .size = MTDPART_SIZ_FULL,
+               .mask_flags = 0,
+       },
+};
+
+static struct flash_platform_data spi_flash_data = {
+       .name           = "m25p80",
+       .parts          = spi_flash_part,
+       .nr_parts       = ARRAY_SIZE(spi_flash_part),
+       .type           = "s25fl512s",
+};
+
+static const struct rspi_plat_data qspi_pdata __initconst = {
+       .num_chipselect = 1,
+};
+
+static const struct spi_board_info spi_info[] __initconst = {
+       {
+               .modalias               = "m25p80",
+               .platform_data          = &spi_flash_data,
+               .mode                   = SPI_MODE_0,
+               .max_speed_hz           = 30000000,
+               .bus_num                = 0,
+               .chip_select            = 0,
+       },
+};
+
+/* QSPI resource */
+static const struct resource qspi_resources[] __initconst = {
+       DEFINE_RES_MEM(0xe6b10000, 0x1000),
+       DEFINE_RES_IRQ(gic_spi(184)),
+};
+
 static const struct pinctrl_map lager_pinctrl_map[] = {
        /* DU (CN10: ARGB0, CN13: LVDS) */
        PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7790", "pfc-r8a7790",
@@ -197,6 +323,9 @@ static const struct pinctrl_map lager_pinctrl_map[] = {
 
 static void __init lager_add_standard_devices(void)
 {
+       int fixed_regulator_idx = 0;
+       int gpio_regulator_idx = 0;
+
        r8a7790_clock_init();
 
        pinctrl_register_mappings(lager_pinctrl_map,
@@ -210,7 +339,8 @@ static void __init lager_add_standard_devices(void)
        platform_device_register_data(&platform_bus, "gpio-keys", -1,
                                      &lager_keys_pdata,
                                      sizeof(lager_keys_pdata));
-       regulator_register_always_on(0, "fixed-3.3V", fixed3v3_power_consumers,
+       regulator_register_always_on(fixed_regulator_idx++,
+                                    "fixed-3.3V", fixed3v3_power_consumers,
                                     ARRAY_SIZE(fixed3v3_power_consumers), 3300000);
        platform_device_register_resndata(&platform_bus, "sh_mmcif", 1,
                                          mmcif1_resources, ARRAY_SIZE(mmcif1_resources),
@@ -222,6 +352,22 @@ static void __init lager_add_standard_devices(void)
                                          &ether_pdata, sizeof(ether_pdata));
 
        lager_add_du_device();
+
+       platform_device_register_resndata(&platform_bus, "qspi", 0,
+                                         qspi_resources,
+                                         ARRAY_SIZE(qspi_resources),
+                                         &qspi_pdata, sizeof(qspi_pdata));
+       spi_register_board_info(spi_info, ARRAY_SIZE(spi_info));
+
+       platform_device_register_data(&platform_bus, "reg-fixed-voltage", fixed_regulator_idx++,
+                                     &vcc_sdhi0_info, sizeof(struct fixed_voltage_config));
+       platform_device_register_data(&platform_bus, "reg-fixed-voltage", fixed_regulator_idx++,
+                                     &vcc_sdhi2_info, sizeof(struct fixed_voltage_config));
+
+       platform_device_register_data(&platform_bus, "gpio-regulator", gpio_regulator_idx++,
+                                     &vccq_sdhi0_info, sizeof(struct gpio_regulator_config));
+       platform_device_register_data(&platform_bus, "gpio-regulator", gpio_regulator_idx++,
+                                     &vccq_sdhi2_info, sizeof(struct gpio_regulator_config));
 }
 
 /*
@@ -245,7 +391,9 @@ static void __init lager_init(void)
 {
        lager_add_standard_devices();
 
-       phy_register_fixup_for_id("r8a7790-ether-ff:01", lager_ksz8041_fixup);
+       if (IS_ENABLED(CONFIG_PHYLIB))
+               phy_register_fixup_for_id("r8a7790-ether-ff:01",
+                                         lager_ksz8041_fixup);
 }
 
 static const char * const lager_boards_compat_dt[] __initconst = {
@@ -258,5 +406,6 @@ DT_MACHINE_START(LAGER_DT, "lager")
        .init_early     = r8a7790_init_early,
        .init_time      = rcar_gen2_timer_init,
        .init_machine   = lager_init,
+       .init_late      = shmobile_init_late,
        .dt_compat      = lager_boards_compat_dt,
 MACHINE_END
index af06753eb8092500de41707ac68216bd3ed244a0..207acf0e07dac2476ca85f32ec0def8eb04aaad4 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/sh_flctl.h>
 #include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf-generic.h>
 #include <linux/platform_data/gpio_backlight.h>
 #include <linux/pm_clock.h>
 #include <linux/regulator/fixed.h>
@@ -548,9 +549,9 @@ static void __init hdmi_init_pm_clock(void)
                 clk_get_rate(&sh7372_pllc2_clk));
 
        rate = clk_round_rate(&sh7372_pllc2_clk, 594000000);
-       if (rate < 0) {
+       if (rate <= 0) {
                pr_err("Cannot get suitable rate: %ld\n", rate);
-               ret = rate;
+               ret = -EINVAL;
                goto out;
        }
 
@@ -1311,6 +1312,10 @@ static struct i2c_board_info i2c1_devices[] = {
        },
 };
 
+static unsigned long pin_pulldown_conf[] = {
+       PIN_CONF_PACKED(PIN_CONFIG_BIAS_PULL_DOWN, 0),
+};
+
 static const struct pinctrl_map mackerel_pinctrl_map[] = {
        /* ADXL34X */
        PIN_MAP_MUX_GROUP_DEFAULT("1-0053", "pfc-sh7372",
@@ -1396,17 +1401,19 @@ static const struct pinctrl_map mackerel_pinctrl_map[] = {
        /* USBHS0 */
        PIN_MAP_MUX_GROUP_DEFAULT("renesas_usbhs.0", "pfc-sh7372",
                                  "usb0_vbus", "usb0"),
+       PIN_MAP_CONFIGS_GROUP_DEFAULT("renesas_usbhs.0", "pfc-sh7372",
+                                     "usb0_vbus", pin_pulldown_conf),
        /* USBHS1 */
        PIN_MAP_MUX_GROUP_DEFAULT("renesas_usbhs.1", "pfc-sh7372",
                                  "usb1_vbus", "usb1"),
+       PIN_MAP_CONFIGS_GROUP_DEFAULT("renesas_usbhs.&", "pfc-sh7372",
+                                     "usb1_vbus", pin_pulldown_conf),
        PIN_MAP_MUX_GROUP_DEFAULT("renesas_usbhs.1", "pfc-sh7372",
                                  "usb1_otg_id_0", "usb1"),
 };
 
 #define GPIO_PORT9CR   IOMEM(0xE6051009)
 #define GPIO_PORT10CR  IOMEM(0xE605100A)
-#define GPIO_PORT167CR IOMEM(0xE60520A7)
-#define GPIO_PORT168CR IOMEM(0xE60520A8)
 #define SRCR4          IOMEM(0xe61580bc)
 #define USCCR1         IOMEM(0xE6058144)
 static void __init mackerel_init(void)
@@ -1446,12 +1453,6 @@ static void __init mackerel_init(void)
 
        gpio_request_one(151, GPIOF_OUT_INIT_HIGH, NULL); /* LCDDON */
 
-       /* USBHS0 */
-       gpio_request_pulldown(GPIO_PORT168CR); /* VBUS0_0 pull down */
-
-       /* USBHS1 */
-       gpio_request_pulldown(GPIO_PORT167CR); /* VBUS0_1 pull down */
-
        /* FSI2 port A (ak4643) */
        gpio_request_one(161, GPIOF_OUT_INIT_LOW, NULL); /* slave */
 
index da1352f5f71b6195969d17ef0de30ba9d4c8e7fe..d832a4477b4bdb8e46970c49ed1b45843405cf45 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/leds.h>
 #include <linux/dma-mapping.h>
 #include <linux/pinctrl/machine.h>
+#include <linux/platform_data/camera-rcar.h>
 #include <linux/platform_data/gpio-rcar.h>
 #include <linux/platform_data/rcar-du.h>
 #include <linux/platform_data/usb-rcar-phy.h>
@@ -259,10 +260,30 @@ static struct platform_device leds_device = {
        },
 };
 
+/* VIN */
 static struct rcar_vin_platform_data vin_platform_data __initdata = {
        .flags  = RCAR_VIN_BT656,
 };
 
+#define MARZEN_VIN(idx)                                                \
+static struct resource vin##idx##_resources[] __initdata = {   \
+       DEFINE_RES_MEM(0xffc50000 + 0x1000 * (idx), 0x1000),    \
+       DEFINE_RES_IRQ(gic_iid(0x5f + (idx))),                  \
+};                                                             \
+                                                               \
+static struct platform_device_info vin##idx##_info __initdata = { \
+       .parent         = &platform_bus,                        \
+       .name           = "r8a7779-vin",                        \
+       .id             = idx,                                  \
+       .res            = vin##idx##_resources,                 \
+       .num_res        = ARRAY_SIZE(vin##idx##_resources),     \
+       .dma_mask       = DMA_BIT_MASK(32),                     \
+       .data           = &vin_platform_data,                   \
+       .size_data      = sizeof(vin_platform_data),            \
+}
+MARZEN_VIN(1);
+MARZEN_VIN(3);
+
 #define MARZEN_CAMERA(idx)                                     \
 static struct i2c_board_info camera##idx##_info = {            \
        I2C_BOARD_INFO("adv7180", 0x20 + (idx)),                \
@@ -326,8 +347,6 @@ static const struct pinctrl_map marzen_pinctrl_map[] = {
                                  "sdhi0_ctrl", "sdhi0"),
        PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7779",
                                  "sdhi0_cd", "sdhi0"),
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7779",
-                                 "sdhi0_wp", "sdhi0"),
        /* SMSC */
        PIN_MAP_MUX_GROUP_DEFAULT("smsc911x", "pfc-r8a7779",
                                  "intc_irq1_b", "intc"),
@@ -367,8 +386,8 @@ static void __init marzen_init(void)
        r8a7779_init_irq_extpin(1); /* IRQ1 as individual interrupt */
 
        r8a7779_add_standard_devices();
-       r8a7779_add_vin_device(1, &vin_platform_data);
-       r8a7779_add_vin_device(3, &vin_platform_data);
+       platform_device_register_full(&vin1_info);
+       platform_device_register_full(&vin3_info);
        platform_add_devices(marzen_devices, ARRAY_SIZE(marzen_devices));
        marzen_add_du_device();
 }
index 4aba20ca127e1ef5f2cc214bfa946a28f216a6bf..7b457aed8253c96ce208de8d6575bca12af3012a 100644 (file)
@@ -170,6 +170,9 @@ static struct clk_lookup lookups[] = {
        CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
 
        /* MSTP clocks */
+       CLKDEV_CON_ID("mtu2_fck", &mstp_clks[MSTP33]),
+
+       /* ICK */
        CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP47]),
        CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP46]),
        CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP45]),
@@ -178,6 +181,7 @@ static struct clk_lookup lookups[] = {
        CLKDEV_ICK_ID("sci_fck", "sh-sci.5", &mstp_clks[MSTP42]),
        CLKDEV_ICK_ID("sci_fck", "sh-sci.6", &mstp_clks[MSTP41]),
        CLKDEV_ICK_ID("sci_fck", "sh-sci.7", &mstp_clks[MSTP40]),
+       CLKDEV_CON_ID("mtu2_fck", &mstp_clks[MSTP33]),
 };
 
 void __init r7s72100_clock_init(void)
index 571409b611d386b5067236248d129d2f0ca154a1..7348d58f500e9089bd46ef7a97cf4be79a8ec46b 100644 (file)
@@ -584,15 +584,15 @@ static struct clk_lookup lookups[] = {
        CLKDEV_DEV_ID("rcar_thermal", &mstp_clks[MSTP522]),
        CLKDEV_DEV_ID("e6520000.i2c", &mstp_clks[MSTP300]),
        CLKDEV_DEV_ID("sh_mmcif.1", &mstp_clks[MSTP305]),
-       CLKDEV_DEV_ID("ee220000.mmcif", &mstp_clks[MSTP305]),
+       CLKDEV_DEV_ID("ee220000.mmc", &mstp_clks[MSTP305]),
        CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP312]),
-       CLKDEV_DEV_ID("ee140000.sdhi", &mstp_clks[MSTP312]),
+       CLKDEV_DEV_ID("ee140000.sd", &mstp_clks[MSTP312]),
        CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]),
-       CLKDEV_DEV_ID("ee120000.sdhi", &mstp_clks[MSTP313]),
+       CLKDEV_DEV_ID("ee120000.sd", &mstp_clks[MSTP313]),
        CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]),
-       CLKDEV_DEV_ID("ee100000.sdhi", &mstp_clks[MSTP314]),
+       CLKDEV_DEV_ID("ee100000.sd", &mstp_clks[MSTP314]),
        CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP315]),
-       CLKDEV_DEV_ID("ee200000.mmcif", &mstp_clks[MSTP315]),
+       CLKDEV_DEV_ID("ee200000.mmc", &mstp_clks[MSTP315]),
        CLKDEV_DEV_ID("e6550000.i2c", &mstp_clks[MSTP316]),
        CLKDEV_DEV_ID("e6560000.i2c", &mstp_clks[MSTP317]),
        CLKDEV_DEV_ID("e6500000.i2c", &mstp_clks[MSTP318]),
index c826bca4024e30bfc45a2cd07338f55cb5d97bac..dd989f93498f66bca2534f4a9daac35fe14ab7ef 100644 (file)
@@ -585,22 +585,23 @@ static struct clk_lookup lookups[] = {
 
        CLKDEV_DEV_ID("sh_cmt.10",              &mstp_clks[MSTP329]),
        CLKDEV_DEV_ID("sh_fsi2",                &mstp_clks[MSTP328]),
+       CLKDEV_DEV_ID("fe1f0000.sound",         &mstp_clks[MSTP328]),
        CLKDEV_DEV_ID("i2c-sh_mobile.1",        &mstp_clks[MSTP323]),
        CLKDEV_DEV_ID("e6c20000.i2c",           &mstp_clks[MSTP323]),
        CLKDEV_DEV_ID("renesas_usbhs",          &mstp_clks[MSTP320]),
        CLKDEV_DEV_ID("sh_mobile_sdhi.0",       &mstp_clks[MSTP314]),
-       CLKDEV_DEV_ID("e6850000.sdhi",          &mstp_clks[MSTP314]),
+       CLKDEV_DEV_ID("e6850000.sd",            &mstp_clks[MSTP314]),
        CLKDEV_DEV_ID("sh_mobile_sdhi.1",       &mstp_clks[MSTP313]),
-       CLKDEV_DEV_ID("e6860000.sdhi",          &mstp_clks[MSTP313]),
+       CLKDEV_DEV_ID("e6860000.sd",            &mstp_clks[MSTP313]),
        CLKDEV_DEV_ID("sh_mmcif",               &mstp_clks[MSTP312]),
-       CLKDEV_DEV_ID("e6bd0000.mmcif",         &mstp_clks[MSTP312]),
+       CLKDEV_DEV_ID("e6bd0000.mmc",           &mstp_clks[MSTP312]),
        CLKDEV_DEV_ID("r8a7740-gether",         &mstp_clks[MSTP309]),
        CLKDEV_DEV_ID("e9a00000.sh-eth",        &mstp_clks[MSTP309]),
        CLKDEV_DEV_ID("renesas-tpu-pwm",        &mstp_clks[MSTP304]),
        CLKDEV_DEV_ID("e6600000.pwm",           &mstp_clks[MSTP304]),
 
        CLKDEV_DEV_ID("sh_mobile_sdhi.2",       &mstp_clks[MSTP415]),
-       CLKDEV_DEV_ID("e6870000.sdhi",          &mstp_clks[MSTP415]),
+       CLKDEV_DEV_ID("e6870000.sd",            &mstp_clks[MSTP415]),
 
        /* ICK */
        CLKDEV_ICK_ID("host",   "renesas_usbhs",        &mstp_clks[MSTP416]),
index fb6af83858e3f0210f9eeaae2c2794a5a618ca48..4b601bf4ede4de3d8395bc1515321f0e733c23fb 100644 (file)
@@ -173,9 +173,13 @@ static struct clk_lookup lookups[] = {
 
        /* MSTP32 clocks */
        CLKDEV_DEV_ID("sh_mmcif", &mstp_clks[MSTP331]), /* MMC */
+       CLKDEV_DEV_ID("ffe4e000.mmc", &mstp_clks[MSTP331]), /* MMC */
        CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP323]), /* SDHI0 */
+       CLKDEV_DEV_ID("ffe4c000.sd", &mstp_clks[MSTP323]), /* SDHI0 */
        CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP322]), /* SDHI1 */
+       CLKDEV_DEV_ID("ffe4d000.sd", &mstp_clks[MSTP322]), /* SDHI1 */
        CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP321]), /* SDHI2 */
+       CLKDEV_DEV_ID("ffe4f000.sd", &mstp_clks[MSTP321]), /* SDHI2 */
        CLKDEV_DEV_ID("r8a777x-ether", &mstp_clks[MSTP114]), /* Ether */
        CLKDEV_DEV_ID("r8a7778-vin.0", &mstp_clks[MSTP110]), /* VIN0 */
        CLKDEV_DEV_ID("r8a7778-vin.1", &mstp_clks[MSTP109]), /* VIN1 */
@@ -183,9 +187,13 @@ static struct clk_lookup lookups[] = {
        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("ffc70000.i2c", &mstp_clks[MSTP030]), /* I2C0 */
        CLKDEV_DEV_ID("i2c-rcar.1", &mstp_clks[MSTP029]), /* I2C1 */
+       CLKDEV_DEV_ID("ffc71000.i2c", &mstp_clks[MSTP029]), /* I2C1 */
        CLKDEV_DEV_ID("i2c-rcar.2", &mstp_clks[MSTP028]), /* I2C2 */
+       CLKDEV_DEV_ID("ffc72000.i2c", &mstp_clks[MSTP028]), /* I2C2 */
        CLKDEV_DEV_ID("i2c-rcar.3", &mstp_clks[MSTP027]), /* I2C3 */
+       CLKDEV_DEV_ID("ffc73000.i2c", &mstp_clks[MSTP027]), /* I2C3 */
        CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP026]), /* SCIF0 */
        CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP025]), /* SCIF1 */
        CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP024]), /* SCIF2 */
@@ -195,8 +203,11 @@ static struct clk_lookup lookups[] = {
        CLKDEV_DEV_ID("sh_tmu.0", &mstp_clks[MSTP016]), /* TMU00 */
        CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP015]), /* TMU01 */
        CLKDEV_DEV_ID("sh-hspi.0", &mstp_clks[MSTP007]), /* HSPI0 */
+       CLKDEV_DEV_ID("fffc7000.spi", &mstp_clks[MSTP007]), /* HSPI0 */
        CLKDEV_DEV_ID("sh-hspi.1", &mstp_clks[MSTP007]), /* HSPI1 */
+       CLKDEV_DEV_ID("fffc8000.spi", &mstp_clks[MSTP007]), /* HSPI1 */
        CLKDEV_DEV_ID("sh-hspi.2", &mstp_clks[MSTP007]), /* HSPI2 */
+       CLKDEV_DEV_ID("fffc6000.spi", &mstp_clks[MSTP007]), /* HSPI2 */
        CLKDEV_DEV_ID("rcar_sound", &mstp_clks[MSTP008]), /* SRU */
 
        CLKDEV_ICK_ID("ssi.0", "rcar_sound", &mstp_clks[MSTP012]),
index 1f7080fab0a53556a4ce5efb3cbf3368dce71465..f1fb89b76786a690037b154d907c9668707f192b 100644 (file)
@@ -184,9 +184,13 @@ static struct clk_lookup lookups[] = {
        CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP016]), /* TMU01 */
        CLKDEV_DEV_ID("sh_tmu.2", &mstp_clks[MSTP016]), /* TMU02 */
        CLKDEV_DEV_ID("i2c-rcar.0", &mstp_clks[MSTP030]), /* I2C0 */
+       CLKDEV_DEV_ID("ffc70000.i2c", &mstp_clks[MSTP030]), /* I2C0 */
        CLKDEV_DEV_ID("i2c-rcar.1", &mstp_clks[MSTP029]), /* I2C1 */
+       CLKDEV_DEV_ID("ffc71000.i2c", &mstp_clks[MSTP029]), /* I2C1 */
        CLKDEV_DEV_ID("i2c-rcar.2", &mstp_clks[MSTP028]), /* I2C2 */
+       CLKDEV_DEV_ID("ffc72000.i2c", &mstp_clks[MSTP028]), /* I2C2 */
        CLKDEV_DEV_ID("i2c-rcar.3", &mstp_clks[MSTP027]), /* I2C3 */
+       CLKDEV_DEV_ID("ffc73000.i2c", &mstp_clks[MSTP027]), /* I2C3 */
        CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP026]), /* SCIF0 */
        CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP025]), /* SCIF1 */
        CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP024]), /* SCIF2 */
@@ -194,12 +198,19 @@ static struct clk_lookup lookups[] = {
        CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP022]), /* SCIF4 */
        CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP021]), /* SCIF6 */
        CLKDEV_DEV_ID("sh-hspi.0", &mstp_clks[MSTP007]), /* HSPI0 */
+       CLKDEV_DEV_ID("fffc7000.spi", &mstp_clks[MSTP007]), /* HSPI0 */
        CLKDEV_DEV_ID("sh-hspi.1", &mstp_clks[MSTP007]), /* HSPI1 */
+       CLKDEV_DEV_ID("fffc8000.spi", &mstp_clks[MSTP007]), /* HSPI1 */
        CLKDEV_DEV_ID("sh-hspi.2", &mstp_clks[MSTP007]), /* HSPI2 */
+       CLKDEV_DEV_ID("fffc6000.spi", &mstp_clks[MSTP007]), /* HSPI2 */
        CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP323]), /* SDHI0 */
+       CLKDEV_DEV_ID("ffe4c000.sd", &mstp_clks[MSTP323]), /* SDHI0 */
        CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP322]), /* SDHI1 */
+       CLKDEV_DEV_ID("ffe4d000.sd", &mstp_clks[MSTP322]), /* SDHI1 */
        CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP321]), /* SDHI2 */
+       CLKDEV_DEV_ID("ffe4e000.sd", &mstp_clks[MSTP321]), /* SDHI2 */
        CLKDEV_DEV_ID("sh_mobile_sdhi.3", &mstp_clks[MSTP320]), /* SDHI3 */
+       CLKDEV_DEV_ID("ffe4f000.sd", &mstp_clks[MSTP320]), /* SDHI3 */
        CLKDEV_DEV_ID("rcar-du-r8a7779", &mstp_clks[MSTP103]), /* DU */
 };
 
index a64f965c7da142b118ab42a52afadeb5038dff81..312376d2cfd14572d60753118d3c375797423ed0 100644 (file)
@@ -53,6 +53,7 @@
 #define SMSTPCR7 0xe615014c
 #define SMSTPCR8 0xe6150990
 #define SMSTPCR9 0xe6150994
+#define SMSTPCR10 0xe6150998
 
 #define SDCKCR         0xE6150074
 #define SD2CKCR                0xE6150078
@@ -77,7 +78,7 @@ static struct sh_clk_ops followparent_clk_ops = {
 };
 
 static struct clk main_clk = {
-       /* .parent will be set r8a73a4_clock_init */
+       /* .parent will be set r8a7790_clock_init */
        .ops    = &followparent_clk_ops,
 };
 
@@ -182,10 +183,14 @@ static struct clk div6_clks[DIV6_NR] = {
 
 /* MSTP */
 enum {
+       MSTP1015, MSTP1014, MSTP1013, MSTP1012, MSTP1011, MSTP1010,
+       MSTP1009, MSTP1008, MSTP1007, MSTP1006, MSTP1005,
        MSTP931, MSTP930, MSTP929, MSTP928,
+       MSTP917,
        MSTP813,
        MSTP726, MSTP725, MSTP724, MSTP723, MSTP722, MSTP721, MSTP720,
        MSTP717, MSTP716,
+       MSTP704,
        MSTP522,
        MSTP315, MSTP314, MSTP313, MSTP312, MSTP311, MSTP305, MSTP304,
        MSTP216, MSTP207, MSTP206, MSTP204, MSTP203, MSTP202,
@@ -194,10 +199,22 @@ enum {
 };
 
 static struct clk mstp_clks[MSTP_NR] = {
-       [MSTP931] = SH_CLK_MSTP32(&hp_clk, SMSTPCR9, 31, 0), /* I2C0 */
-       [MSTP930] = SH_CLK_MSTP32(&hp_clk, SMSTPCR9, 30, 0), /* I2C1 */
-       [MSTP929] = SH_CLK_MSTP32(&hp_clk, SMSTPCR9, 29, 0), /* I2C2 */
-       [MSTP928] = SH_CLK_MSTP32(&hp_clk, SMSTPCR9, 28, 0), /* I2C3 */
+       [MSTP1015] = SH_CLK_MSTP32(&p_clk, SMSTPCR10, 15, 0), /* SSI0 */
+       [MSTP1014] = SH_CLK_MSTP32(&p_clk, SMSTPCR10, 14, 0), /* SSI1 */
+       [MSTP1013] = SH_CLK_MSTP32(&p_clk, SMSTPCR10, 13, 0), /* SSI2 */
+       [MSTP1012] = SH_CLK_MSTP32(&p_clk, SMSTPCR10, 12, 0), /* SSI3 */
+       [MSTP1011] = SH_CLK_MSTP32(&p_clk, SMSTPCR10, 11, 0), /* SSI4 */
+       [MSTP1010] = SH_CLK_MSTP32(&p_clk, SMSTPCR10, 10, 0), /* SSI5 */
+       [MSTP1009] = SH_CLK_MSTP32(&p_clk, SMSTPCR10,  9, 0), /* SSI6 */
+       [MSTP1008] = SH_CLK_MSTP32(&p_clk, SMSTPCR10,  8, 0), /* SSI7 */
+       [MSTP1007] = SH_CLK_MSTP32(&p_clk, SMSTPCR10,  7, 0), /* SSI8 */
+       [MSTP1006] = SH_CLK_MSTP32(&p_clk, SMSTPCR10,  6, 0), /* SSI9 */
+       [MSTP1005] = SH_CLK_MSTP32(&p_clk, SMSTPCR10,  5, 0), /* SSI ALL */
+       [MSTP931] = SH_CLK_MSTP32(&p_clk, SMSTPCR9, 31, 0), /* I2C0 */
+       [MSTP930] = SH_CLK_MSTP32(&p_clk, SMSTPCR9, 30, 0), /* I2C1 */
+       [MSTP929] = SH_CLK_MSTP32(&p_clk, SMSTPCR9, 29, 0), /* I2C2 */
+       [MSTP928] = SH_CLK_MSTP32(&p_clk, SMSTPCR9, 28, 0), /* I2C3 */
+       [MSTP917] = SH_CLK_MSTP32(&qspi_clk, SMSTPCR9, 17, 0), /* QSPI */
        [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 */
@@ -208,6 +225,7 @@ static struct clk mstp_clks[MSTP_NR] = {
        [MSTP720] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 20, 0), /* SCIF1 */
        [MSTP717] = SH_CLK_MSTP32(&zs_clk, SMSTPCR7, 17, 0), /* HSCIF0 */
        [MSTP716] = SH_CLK_MSTP32(&zs_clk, SMSTPCR7, 16, 0), /* HSCIF1 */
+       [MSTP704] = SH_CLK_MSTP32(&mp_clk, SMSTPCR7, 4, 0), /* HSUSB */
        [MSTP522] = SH_CLK_MSTP32(&extal_clk, SMSTPCR5, 22, 0), /* Thermal */
        [MSTP315] = SH_CLK_MSTP32(&div6_clks[DIV6_MMC0], SMSTPCR3, 15, 0), /* MMC0 */
        [MSTP314] = SH_CLK_MSTP32(&div4_clks[DIV4_SD0], SMSTPCR3, 14, 0), /* SDHI0 */
@@ -262,11 +280,7 @@ 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("rcar_sound", &mstp_clks[MSTP1005]),
        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]),
@@ -282,20 +296,42 @@ static struct clk_lookup lookups[] = {
        CLKDEV_DEV_ID("e6530000.i2c", &mstp_clks[MSTP929]),
        CLKDEV_DEV_ID("e6540000.i2c", &mstp_clks[MSTP928]),
        CLKDEV_DEV_ID("r8a7790-ether", &mstp_clks[MSTP813]),
+       CLKDEV_DEV_ID("e61f0000.thermal", &mstp_clks[MSTP522]),
        CLKDEV_DEV_ID("rcar_thermal", &mstp_clks[MSTP522]),
-       CLKDEV_DEV_ID("ee200000.mmcif", &mstp_clks[MSTP315]),
+       CLKDEV_DEV_ID("ee200000.mmc", &mstp_clks[MSTP315]),
        CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP315]),
-       CLKDEV_DEV_ID("ee100000.sdhi", &mstp_clks[MSTP314]),
+       CLKDEV_DEV_ID("ee100000.sd", &mstp_clks[MSTP314]),
        CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]),
-       CLKDEV_DEV_ID("ee120000.sdhi", &mstp_clks[MSTP313]),
+       CLKDEV_DEV_ID("ee120000.sd", &mstp_clks[MSTP313]),
        CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]),
-       CLKDEV_DEV_ID("ee140000.sdhi", &mstp_clks[MSTP312]),
+       CLKDEV_DEV_ID("ee140000.sd", &mstp_clks[MSTP312]),
        CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP312]),
-       CLKDEV_DEV_ID("ee160000.sdhi", &mstp_clks[MSTP311]),
+       CLKDEV_DEV_ID("ee160000.sd", &mstp_clks[MSTP311]),
        CLKDEV_DEV_ID("sh_mobile_sdhi.3", &mstp_clks[MSTP311]),
-       CLKDEV_DEV_ID("ee220000.mmcif", &mstp_clks[MSTP305]),
+       CLKDEV_DEV_ID("ee220000.mmc", &mstp_clks[MSTP305]),
        CLKDEV_DEV_ID("sh_mmcif.1", &mstp_clks[MSTP305]),
        CLKDEV_DEV_ID("sh_cmt.0", &mstp_clks[MSTP124]),
+       CLKDEV_DEV_ID("qspi.0", &mstp_clks[MSTP917]),
+       CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP704]),
+
+       /* ICK */
+       CLKDEV_ICK_ID("usbhs", "usb_phy_rcar_gen2", &mstp_clks[MSTP704]),
+       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_ICK_ID("ssi.0", "rcar_sound", &mstp_clks[MSTP1015]),
+       CLKDEV_ICK_ID("ssi.1", "rcar_sound", &mstp_clks[MSTP1014]),
+       CLKDEV_ICK_ID("ssi.2", "rcar_sound", &mstp_clks[MSTP1013]),
+       CLKDEV_ICK_ID("ssi.3", "rcar_sound", &mstp_clks[MSTP1012]),
+       CLKDEV_ICK_ID("ssi.4", "rcar_sound", &mstp_clks[MSTP1011]),
+       CLKDEV_ICK_ID("ssi.5", "rcar_sound", &mstp_clks[MSTP1010]),
+       CLKDEV_ICK_ID("ssi.6", "rcar_sound", &mstp_clks[MSTP1009]),
+       CLKDEV_ICK_ID("ssi.7", "rcar_sound", &mstp_clks[MSTP1008]),
+       CLKDEV_ICK_ID("ssi.8", "rcar_sound", &mstp_clks[MSTP1007]),
+       CLKDEV_ICK_ID("ssi.9", "rcar_sound", &mstp_clks[MSTP1006]),
+
 };
 
 #define R8A7790_CLOCK_ROOT(e, m, p0, p1, p30, p31)             \
@@ -321,10 +357,10 @@ void __init r8a7790_clock_init(void)
                R8A7790_CLOCK_ROOT(20, &extal_clk, 130, 156, 80, 66);
                break;
        case MD(14):
-               R8A7790_CLOCK_ROOT(26, &extal_div2_clk, 200, 240, 122, 102);
+               R8A7790_CLOCK_ROOT(26 / 2, &extal_div2_clk, 200, 240, 122, 102);
                break;
        case MD(13) | MD(14):
-               R8A7790_CLOCK_ROOT(30, &extal_div2_clk, 172, 208, 106, 88);
+               R8A7790_CLOCK_ROOT(30 / 2, &extal_div2_clk, 172, 208, 106, 88);
                break;
        }
 
index c9a26f16ce5b68bb1fc01a9c036a8299262df0e7..ff2d60d55bd5310ed6e6e286a396392d176058f0 100644 (file)
@@ -103,6 +103,7 @@ 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);
+SH_FIXED_RATIO_CLK_SET(zx_clk,                 pll1_clk,       1, 3);
 
 static struct clk *main_clks[] = {
        &extal_clk,
@@ -116,12 +117,14 @@ static struct clk *main_clks[] = {
        &rclk_clk,
        &mp_clk,
        &cp_clk,
+       &zx_clk,
 };
 
 /* MSTP */
 enum {
-       MSTP721, MSTP720,
+       MSTP726, MSTP724, MSTP723, MSTP721, MSTP720,
        MSTP719, MSTP718, MSTP715, MSTP714,
+       MSTP522,
        MSTP216, MSTP207, MSTP206,
        MSTP204, MSTP203, MSTP202, MSTP1105, MSTP1106, MSTP1107,
        MSTP124,
@@ -129,12 +132,16 @@ enum {
 };
 
 static struct clk mstp_clks[MSTP_NR] = {
+       [MSTP726] = SH_CLK_MSTP32(&zx_clk, SMSTPCR7, 26, 0), /* LVDS0 */
+       [MSTP724] = SH_CLK_MSTP32(&zx_clk, SMSTPCR7, 24, 0), /* DU0 */
+       [MSTP723] = SH_CLK_MSTP32(&zx_clk, SMSTPCR7, 23, 0), /* DU1 */
        [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 */
+       [MSTP522] = SH_CLK_MSTP32(&extal_clk, SMSTPCR5, 22, 0), /* Thermal */
        [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 */
@@ -164,6 +171,9 @@ static struct clk_lookup lookups[] = {
        CLKDEV_CON_ID("peripheral_clk", &hp_clk),
 
        /* MSTP */
+       CLKDEV_ICK_ID("lvds.0", "rcar-du-r8a7791", &mstp_clks[MSTP726]),
+       CLKDEV_ICK_ID("du.0", "rcar-du-r8a7791", &mstp_clks[MSTP724]),
+       CLKDEV_ICK_ID("du.1", "rcar-du-r8a7791", &mstp_clks[MSTP723]),
        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 */
@@ -180,6 +190,8 @@ static struct clk_lookup lookups[] = {
        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]),
+       CLKDEV_DEV_ID("e61f0000.thermal", &mstp_clks[MSTP522]),
+       CLKDEV_DEV_ID("rcar_thermal", &mstp_clks[MSTP522]),
 };
 
 #define R8A7791_CLOCK_ROOT(e, m, p0, p1, p30, p31)             \
index 5390c6bbbc02dd389852ba519118ddaab2222a37..28489978b09ca949e7f6b1209a7f200c2373ae16 100644 (file)
@@ -504,10 +504,6 @@ static struct clk_lookup lookups[] = {
        CLKDEV_CON_ID("spu_clk", &div6_clks[DIV6_SPU]),
        CLKDEV_CON_ID("vou_clk", &div6_clks[DIV6_VOU]),
        CLKDEV_CON_ID("hdmi_clk", &div6_reparent_clks[DIV6_HDMI]),
-       CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSIT]),
-       CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSIT]),
-       CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSI0P]),
-       CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSI1P]),
 
        /* MSTP32 clocks */
        CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* IIC2 */
@@ -574,6 +570,11 @@ static struct clk_lookup lookups[] = {
        CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */
        CLKDEV_DEV_ID("sh_cmt.2", &mstp_clks[MSTP400]), /* CMT2 */
 
+       /* ICK */
+       CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSIT]),
+       CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSIT]),
+       CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSI0P]),
+       CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSI1P]),
        CLKDEV_ICK_ID("hdmi", "sh_mobile_lcdc_fb.1",
                      &div6_reparent_clks[DIV6_HDMI]),
        CLKDEV_ICK_ID("ick", "sh-mobile-hdmi", &div6_reparent_clks[DIV6_HDMI]),
index c92c023f0d27c1de8778665e372d1abfba82db42..30d88689a9601af8eed53add75583db590c7342f 100644 (file)
@@ -625,12 +625,6 @@ static struct clk_lookup lookups[] = {
        CLKDEV_CON_ID("sdhi0_clk", &div6_clks[DIV6_SDHI0]),
        CLKDEV_CON_ID("sdhi1_clk", &div6_clks[DIV6_SDHI1]),
        CLKDEV_CON_ID("sdhi2_clk", &div6_clks[DIV6_SDHI2]),
-       CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSIT]),
-       CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSIT]),
-       CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSI0P]),
-       CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSI1P]),
-       CLKDEV_ICK_ID("dsiphy_clk", "sh-mipi-dsi.0", &dsi0phy_clk),
-       CLKDEV_ICK_ID("dsiphy_clk", "sh-mipi-dsi.1", &dsi1phy_clk),
 
        /* MSTP32 clocks */
        CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* I2C2 */
@@ -663,13 +657,13 @@ static struct clk_lookup lookups[] = {
        CLKDEV_DEV_ID("e6822000.i2c", &mstp_clks[MSTP323]), /* I2C1 */
        CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP322]), /* USB */
        CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), /* SDHI0 */
-       CLKDEV_DEV_ID("ee100000.sdhi", &mstp_clks[MSTP314]), /* SDHI0 */
+       CLKDEV_DEV_ID("ee100000.sd", &mstp_clks[MSTP314]), /* SDHI0 */
        CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */
-       CLKDEV_DEV_ID("ee120000.sdhi", &mstp_clks[MSTP313]), /* SDHI1 */
+       CLKDEV_DEV_ID("ee120000.sd", &mstp_clks[MSTP313]), /* SDHI1 */
        CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMCIF0 */
-       CLKDEV_DEV_ID("e6bd0000.mmcif", &mstp_clks[MSTP312]), /* MMCIF0 */
+       CLKDEV_DEV_ID("e6bd0000.mmc", &mstp_clks[MSTP312]), /* MMCIF0 */
        CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP311]), /* SDHI2 */
-       CLKDEV_DEV_ID("ee140000.sdhi", &mstp_clks[MSTP311]), /* SDHI2 */
+       CLKDEV_DEV_ID("ee140000.sd", &mstp_clks[MSTP311]), /* SDHI2 */
        CLKDEV_DEV_ID("renesas-tpu-pwm.0", &mstp_clks[MSTP304]), /* TPU0 */
        CLKDEV_DEV_ID("renesas-tpu-pwm.1", &mstp_clks[MSTP303]), /* TPU1 */
        CLKDEV_DEV_ID("renesas-tpu-pwm.2", &mstp_clks[MSTP302]), /* TPU2 */
@@ -680,6 +674,14 @@ static struct clk_lookup lookups[] = {
        CLKDEV_DEV_ID("i2c-sh_mobile.4", &mstp_clks[MSTP410]), /* I2C4 */
        CLKDEV_DEV_ID("e6828000.i2c", &mstp_clks[MSTP410]), /* I2C4 */
        CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */
+
+       /* ICK */
+       CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSIT]),
+       CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSIT]),
+       CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSI0P]),
+       CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSI1P]),
+       CLKDEV_ICK_ID("dsiphy_clk", "sh-mipi-dsi.0", &dsi0phy_clk),
+       CLKDEV_ICK_ID("dsiphy_clk", "sh-mipi-dsi.1", &dsi1phy_clk),
 };
 
 void __init sh73a0_clock_init(void)
index c2eb7568d9bed4080b468efa9aba4a26e7d6d043..fcb142a14e0756b55eedec81a63fb0c78e51f302 100644 (file)
@@ -3,12 +3,7 @@
 
 extern void emev2_map_io(void);
 extern void emev2_init_delay(void);
-extern void emev2_add_standard_devices(void);
 extern void emev2_clock_init(void);
-
-#define EMEV2_GPIO_BASE 200
-#define EMEV2_GPIO_IRQ(n) (EMEV2_GPIO_BASE + (n))
-
 extern struct smp_operations emev2_smp_ops;
 
 #endif /* __ASM_EMEV2_H__ */
index 441886c9714baddffb609247b872fca7054c514a..b497f932d04f03c16d795d6f33b09619ea15f74c 100644 (file)
@@ -27,6 +27,24 @@ enum {
        HPBDMA_SLAVE_DUMMY,
        HPBDMA_SLAVE_SDHI0_TX,
        HPBDMA_SLAVE_SDHI0_RX,
+       HPBDMA_SLAVE_HPBIF0_TX,
+       HPBDMA_SLAVE_HPBIF0_RX,
+       HPBDMA_SLAVE_HPBIF1_TX,
+       HPBDMA_SLAVE_HPBIF1_RX,
+       HPBDMA_SLAVE_HPBIF2_TX,
+       HPBDMA_SLAVE_HPBIF2_RX,
+       HPBDMA_SLAVE_HPBIF3_TX,
+       HPBDMA_SLAVE_HPBIF3_RX,
+       HPBDMA_SLAVE_HPBIF4_TX,
+       HPBDMA_SLAVE_HPBIF4_RX,
+       HPBDMA_SLAVE_HPBIF5_TX,
+       HPBDMA_SLAVE_HPBIF5_RX,
+       HPBDMA_SLAVE_HPBIF6_TX,
+       HPBDMA_SLAVE_HPBIF6_RX,
+       HPBDMA_SLAVE_HPBIF7_TX,
+       HPBDMA_SLAVE_HPBIF7_RX,
+       HPBDMA_SLAVE_HPBIF8_TX,
+       HPBDMA_SLAVE_HPBIF8_RX,
 };
 
 extern void r8a7778_add_standard_devices(void);
index 17af34ed89c801553b248f12f0d3c39336553854..5014145f272e22a1247c34f54b1039369ee4bc50 100644 (file)
@@ -3,8 +3,6 @@
 
 #include <linux/sh_clk.h>
 #include <linux/pm_domain.h>
-#include <linux/sh_eth.h>
-#include <linux/platform_data/camera-rcar.h>
 
 /* HPB-DMA slave IDs */
 enum {
@@ -40,9 +38,6 @@ extern void r8a7779_earlytimer_init(void);
 extern void r8a7779_add_early_devices(void);
 extern void r8a7779_add_standard_devices(void);
 extern void r8a7779_add_standard_devices_dt(void);
-extern void r8a7779_add_ether_device(struct sh_eth_plat_data *pdata);
-extern void r8a7779_add_vin_device(int idx,
-                                  struct rcar_vin_platform_data *pdata);
 extern void r8a7779_init_late(void);
 extern void r8a7779_clock_init(void);
 extern void r8a7779_pinmux_init(void);
index 051ead3c286e7f4a7bc2015bb8e384e74972cc5c..200fa699f730e81fe8e02336ee69e07cc20e6898 100644 (file)
@@ -4,6 +4,7 @@
 void r8a7791_add_standard_devices(void);
 void r8a7791_add_dt_devices(void);
 void r8a7791_clock_init(void);
+void r8a7791_pinmux_init(void);
 void r8a7791_init_early(void);
 extern struct smp_operations r8a7791_smp_ops;
 
index 3ad531caf4f098a172d01824263546c5e2cc2c08..c8f2a1a69a5274bec8eab99f44549fb3bbbae955 100644 (file)
  * 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/clk-provider.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/platform_device.h>
-#include <linux/platform_data/gpio-em.h>
 #include <linux/of_platform.h>
-#include <linux/delay.h>
-#include <linux/input.h>
-#include <linux/io.h>
-#include <linux/irqchip/arm-gic.h>
 #include <mach/common.h>
 #include <mach/emev2.h>
-#include <mach/irqs.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
-#include <asm/mach/time.h>
 
 static struct map_desc emev2_io_desc[] __initdata = {
 #ifdef CONFIG_SMP
@@ -52,150 +43,20 @@ void __init emev2_map_io(void)
        iotable_init(emev2_io_desc, ARRAY_SIZE(emev2_io_desc));
 }
 
-/* UART */
-static struct resource uart0_resources[] = {
-       DEFINE_RES_MEM(0xe1020000, 0x38),
-       DEFINE_RES_IRQ(40),
-};
-
-static struct resource uart1_resources[] = {
-       DEFINE_RES_MEM(0xe1030000, 0x38),
-       DEFINE_RES_IRQ(41),
-};
-
-static struct resource uart2_resources[] = {
-       DEFINE_RES_MEM(0xe1040000, 0x38),
-       DEFINE_RES_IRQ(42),
-};
-
-static struct resource uart3_resources[] = {
-       DEFINE_RES_MEM(0xe1050000, 0x38),
-       DEFINE_RES_IRQ(43),
-};
-
-#define emev2_register_uart(idx)                                       \
-       platform_device_register_simple("serial8250-em", idx,           \
-                                       uart##idx##_resources,          \
-                                       ARRAY_SIZE(uart##idx##_resources))
-
-/* STI */
-static struct resource sti_resources[] = {
-       DEFINE_RES_MEM(0xe0180000, 0x54),
-       DEFINE_RES_IRQ(157),
-};
-
-#define emev2_register_sti()                                   \
-       platform_device_register_simple("em_sti", 0,            \
-                                       sti_resources,          \
-                                       ARRAY_SIZE(sti_resources))
-
-/* GIO */
-static struct gpio_em_config gio0_config = {
-       .gpio_base = 0,
-       .irq_base = EMEV2_GPIO_IRQ(0),
-       .number_of_pins = 32,
-};
-
-static struct resource gio0_resources[] = {
-       DEFINE_RES_MEM(0xe0050000, 0x2c),
-       DEFINE_RES_MEM(0xe0050040, 0x20),
-       DEFINE_RES_IRQ(99),
-       DEFINE_RES_IRQ(100),
-};
-
-static struct gpio_em_config gio1_config = {
-       .gpio_base = 32,
-       .irq_base = EMEV2_GPIO_IRQ(32),
-       .number_of_pins = 32,
-};
-
-static struct resource gio1_resources[] = {
-       DEFINE_RES_MEM(0xe0050080, 0x2c),
-       DEFINE_RES_MEM(0xe00500c0, 0x20),
-       DEFINE_RES_IRQ(101),
-       DEFINE_RES_IRQ(102),
-};
-
-static struct gpio_em_config gio2_config = {
-       .gpio_base = 64,
-       .irq_base = EMEV2_GPIO_IRQ(64),
-       .number_of_pins = 32,
-};
-
-static struct resource gio2_resources[] = {
-       DEFINE_RES_MEM(0xe0050100, 0x2c),
-       DEFINE_RES_MEM(0xe0050140, 0x20),
-       DEFINE_RES_IRQ(103),
-       DEFINE_RES_IRQ(104),
-};
-
-static struct gpio_em_config gio3_config = {
-       .gpio_base = 96,
-       .irq_base = EMEV2_GPIO_IRQ(96),
-       .number_of_pins = 32,
-};
-
-static struct resource gio3_resources[] = {
-       DEFINE_RES_MEM(0xe0050180, 0x2c),
-       DEFINE_RES_MEM(0xe00501c0, 0x20),
-       DEFINE_RES_IRQ(105),
-       DEFINE_RES_IRQ(106),
-};
-
-static struct gpio_em_config gio4_config = {
-       .gpio_base = 128,
-       .irq_base = EMEV2_GPIO_IRQ(128),
-       .number_of_pins = 31,
-};
-
-static struct resource gio4_resources[] = {
-       DEFINE_RES_MEM(0xe0050200, 0x2c),
-       DEFINE_RES_MEM(0xe0050240, 0x20),
-       DEFINE_RES_IRQ(107),
-       DEFINE_RES_IRQ(108),
-};
-
-#define emev2_register_gio(idx)                                                \
-       platform_device_register_resndata(&platform_bus, "em_gio",      \
-                                         idx, gio##idx##_resources,    \
-                                         ARRAY_SIZE(gio##idx##_resources), \
-                                         &gio##idx##_config,           \
-                                         sizeof(struct gpio_em_config))
-
-static struct resource pmu_resources[] = {
-       DEFINE_RES_IRQ(152),
-       DEFINE_RES_IRQ(153),
-};
-
-#define emev2_register_pmu()                                   \
-       platform_device_register_simple("arm-pmu", -1,          \
-                                       pmu_resources,          \
-                                       ARRAY_SIZE(pmu_resources))
-
-void __init emev2_add_standard_devices(void)
-{
-       if (!IS_ENABLED(CONFIG_COMMON_CLK))
-               emev2_clock_init();
-
-       emev2_register_uart(0);
-       emev2_register_uart(1);
-       emev2_register_uart(2);
-       emev2_register_uart(3);
-       emev2_register_sti();
-       emev2_register_gio(0);
-       emev2_register_gio(1);
-       emev2_register_gio(2);
-       emev2_register_gio(3);
-       emev2_register_gio(4);
-       emev2_register_pmu();
-}
-
 void __init emev2_init_delay(void)
 {
        shmobile_setup_delay(533, 1, 3); /* Cortex-A9 @ 533MHz */
 }
 
-#ifdef CONFIG_USE_OF
+static void __init emev2_add_standard_devices_dt(void)
+{
+#ifdef CONFIG_COMMON_CLK
+       of_clk_init(NULL);
+#else
+       emev2_clock_init();
+#endif
+       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
 
 static const char *emev2_boards_compat_dt[] __initdata = {
        "renesas,emev2",
@@ -206,7 +67,7 @@ DT_MACHINE_START(EMEV2_DT, "Generic Emma Mobile EV2 (Flattened Device Tree)")
        .smp            = smp_ops(emev2_smp_ops),
        .map_io         = emev2_map_io,
        .init_early     = emev2_init_delay,
+       .init_machine   = emev2_add_standard_devices_dt,
+       .init_late      = shmobile_init_late,
        .dt_compat      = emev2_boards_compat_dt,
 MACHINE_END
-
-#endif /* CONFIG_USE_OF */
index d4eb509a1c878b2add188c4760b30684773535ac..55f0b9c7c482c04c7b1631b6b3c482e0ffcb957d 100644 (file)
@@ -22,6 +22,7 @@
 #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/r7s72100.h>
@@ -58,6 +59,26 @@ static inline void r7s72100_register_scif(int idx)
                                      sizeof(struct plat_sci_port));
 }
 
+
+static struct sh_timer_config mtu2_0_platform_data __initdata = {
+       .name = "MTU2_0",
+       .timer_bit = 0,
+       .channel_offset = -0x80,
+       .clockevent_rating = 200,
+};
+
+static struct resource mtu2_0_resources[] __initdata = {
+       DEFINE_RES_MEM(0xfcff0300, 0x27),
+       DEFINE_RES_IRQ(gic_iid(139)), /* MTU2 TGI0A */
+};
+
+#define r7s72100_register_mtu2(idx)                                    \
+       platform_device_register_resndata(&platform_bus, "sh_mtu2",     \
+                                         idx, mtu2_##idx##_resources,  \
+                                         ARRAY_SIZE(mtu2_##idx##_resources), \
+                                         &mtu2_##idx##_platform_data,  \
+                                         sizeof(struct sh_timer_config))
+
 void __init r7s72100_add_dt_devices(void)
 {
        r7s72100_register_scif(SCIF0);
@@ -68,6 +89,7 @@ void __init r7s72100_add_dt_devices(void)
        r7s72100_register_scif(SCIF5);
        r7s72100_register_scif(SCIF6);
        r7s72100_register_scif(SCIF7);
+       r7s72100_register_mtu2(0);
 }
 
 void __init r7s72100_init_early(void)
index b0f2749071bec3feee42e44a82c52449a8494e81..cc94b64c2ef50a0795ab7bb2a6435599d4320ea7 100644 (file)
@@ -275,7 +275,7 @@ static const struct sh_dmae_pdata dma_pdata = {
 
 static struct resource dma_resources[] = {
        DEFINE_RES_MEM(0xe6700020, 0x89e0),
-       DEFINE_RES_IRQ_NAMED(gic_spi(220), "error_irq"),
+       DEFINE_RES_IRQ(gic_spi(220)),
        {
                /* IRQ for channels 0-19 */
                .start  = gic_spi(200),
index 03fcc5974ef92170c5002bf857ddb35e95a49d57..81701cfb6cc6a96715c4935baf8e21fc1242aa95 100644 (file)
@@ -319,6 +319,29 @@ void __init r8a7778_add_dt_devices(void)
 #define HPB_DMAE_ASYNCMDR_ASMD21_SINGLE        BIT(1)  /* SDHI0 */
 #define HPB_DMAE_ASYNCMDR_ASMD21_MULTI 0       /* SDHI0 */
 
+#define HPBDMA_HPBIF(_id)                              \
+{                                                      \
+       .id     = HPBDMA_SLAVE_HPBIF## _id ##_TX,       \
+       .addr   = 0xffda0000 + (_id * 0x1000),          \
+       .dcr    = HPB_DMAE_DCR_CT |                     \
+                 HPB_DMAE_DCR_DIP |                    \
+                 HPB_DMAE_DCR_SPDS_32BIT |             \
+                 HPB_DMAE_DCR_DMDL |                   \
+                 HPB_DMAE_DCR_DPDS_32BIT,              \
+       .port   = 0x1111,                               \
+       .dma_ch = (28 + _id),                           \
+}, {                                                   \
+       .id     = HPBDMA_SLAVE_HPBIF## _id ##_RX,       \
+       .addr   = 0xffda0000 + (_id * 0x1000),          \
+       .dcr    = HPB_DMAE_DCR_CT |                     \
+                 HPB_DMAE_DCR_DIP |                    \
+                 HPB_DMAE_DCR_SMDL |                   \
+                 HPB_DMAE_DCR_SPDS_32BIT |             \
+                 HPB_DMAE_DCR_DPDS_32BIT,              \
+       .port   = 0x1111,                               \
+       .dma_ch = (28 + _id),                           \
+}
+
 static const struct hpb_dmae_slave_config hpb_dmae_slaves[] = {
        {
                .id     = HPBDMA_SLAVE_SDHI0_TX,
@@ -349,11 +372,39 @@ static const struct hpb_dmae_slave_config hpb_dmae_slaves[] = {
                .flags  = HPB_DMAE_SET_ASYNC_RESET | HPB_DMAE_SET_ASYNC_MODE,
                .dma_ch = 22,
        },
+
+       HPBDMA_HPBIF(0),
+       HPBDMA_HPBIF(1),
+       HPBDMA_HPBIF(2),
+       HPBDMA_HPBIF(3),
+       HPBDMA_HPBIF(4),
+       HPBDMA_HPBIF(5),
+       HPBDMA_HPBIF(6),
+       HPBDMA_HPBIF(7),
+       HPBDMA_HPBIF(8),
 };
 
 static const struct hpb_dmae_channel hpb_dmae_channels[] = {
        HPB_DMAE_CHANNEL(0x7e, HPBDMA_SLAVE_SDHI0_TX), /* ch. 21 */
        HPB_DMAE_CHANNEL(0x7e, HPBDMA_SLAVE_SDHI0_RX), /* ch. 22 */
+       HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF0_TX), /* ch. 28 */
+       HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF0_RX), /* ch. 28 */
+       HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF1_TX), /* ch. 29 */
+       HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF1_RX), /* ch. 29 */
+       HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF2_TX), /* ch. 30 */
+       HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF2_RX), /* ch. 30 */
+       HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF3_TX), /* ch. 31 */
+       HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF3_RX), /* ch. 31 */
+       HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF4_TX), /* ch. 32 */
+       HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF4_RX), /* ch. 32 */
+       HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF5_TX), /* ch. 33 */
+       HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF5_RX), /* ch. 33 */
+       HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF6_TX), /* ch. 34 */
+       HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF6_RX), /* ch. 34 */
+       HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF7_TX), /* ch. 35 */
+       HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF7_RX), /* ch. 35 */
+       HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF8_TX), /* ch. 36 */
+       HPB_DMAE_CHANNEL(0x7f, HPBDMA_SLAVE_HPBIF8_RX), /* ch. 36 */
 };
 
 static struct hpb_dmae_pdata dma_platform_data __initdata = {
index 13049e9d691ca17d7be5d5d3dc9b8b565b42a3e3..8f9453152fb91f9760185466cf666c23c8eb1052 100644 (file)
@@ -598,45 +598,6 @@ static struct platform_device ohci1_device = {
        .resource       = ohci1_resources,
 };
 
-/* Ether */
-static struct resource ether_resources[] __initdata = {
-       {
-               .start  = 0xfde00000,
-               .end    = 0xfde003ff,
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .start  = gic_iid(0xb4),
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-#define R8A7779_VIN(idx) \
-static struct resource vin##idx##_resources[] __initdata = {           \
-       DEFINE_RES_MEM(0xffc50000 + 0x1000 * (idx), 0x1000),            \
-       DEFINE_RES_IRQ(gic_iid(0x5f + (idx))),                          \
-};                                                                     \
-                                                                       \
-static struct platform_device_info vin##idx##_info __initdata = {      \
-       .parent         = &platform_bus,                                \
-       .name           = "r8a7779-vin",                                \
-       .id             = idx,                                          \
-       .res            = vin##idx##_resources,                         \
-       .num_res        = ARRAY_SIZE(vin##idx##_resources),             \
-       .dma_mask       = DMA_BIT_MASK(32),                             \
-}
-
-R8A7779_VIN(0);
-R8A7779_VIN(1);
-R8A7779_VIN(2);
-R8A7779_VIN(3);
-
-static struct platform_device_info *vin_info_table[] __initdata = {
-       &vin0_info,
-       &vin1_info,
-       &vin2_info,
-       &vin3_info,
-};
-
 /* HPB-DMA */
 
 /* Asynchronous mode register bits */
@@ -825,24 +786,6 @@ void __init r8a7779_add_standard_devices(void)
        r8a7779_register_hpb_dmae();
 }
 
-void __init r8a7779_add_ether_device(struct sh_eth_plat_data *pdata)
-{
-       platform_device_register_resndata(&platform_bus, "r8a777x-ether", -1,
-                                         ether_resources,
-                                         ARRAY_SIZE(ether_resources),
-                                         pdata, sizeof(*pdata));
-}
-
-void __init r8a7779_add_vin_device(int id, struct rcar_vin_platform_data *pdata)
-{
-       BUG_ON(id < 0 || id > 3);
-
-       vin_info_table[id]->data = pdata;
-       vin_info_table[id]->size_data = sizeof(*pdata);
-
-       platform_device_register_full(vin_info_table[id]);
-}
-
 /* do nothing for !CONFIG_SMP or !CONFIG_HAVE_TWD */
 void __init __weak r8a7779_register_twd(void) { }
 
index c47bcebbcb00bbfa229d16c9d2fcad2430ef631e..3543c3bacb75d828cd9681f9e5b93740822a9467 100644 (file)
@@ -34,6 +34,10 @@ static const struct resource pfc_resources[] __initconst = {
        DEFINE_RES_MEM(0xe6060000, 0x250),
 };
 
+#define r8a7790_register_pfc()                                         \
+       platform_device_register_simple("pfc-r8a7790", -1, pfc_resources, \
+                                       ARRAY_SIZE(pfc_resources))
+
 #define R8A7790_GPIO(idx)                                              \
 static const struct resource r8a7790_gpio##idx##_resources[] __initconst = { \
        DEFINE_RES_MEM(0xe6050000 + 0x1000 * (idx), 0x50),              \
@@ -65,8 +69,7 @@ R8A7790_GPIO(5);
 
 void __init r8a7790_pinmux_init(void)
 {
-       platform_device_register_simple("pfc-r8a7790", -1, pfc_resources,
-                                       ARRAY_SIZE(pfc_resources));
+       r8a7790_register_pfc();
        r8a7790_register_gpio(0);
        r8a7790_register_gpio(1);
        r8a7790_register_gpio(2);
index d9393d61ee27028fb59efe284cc7d9d69db132d6..cddca99b434f051ebdbf9e2ffe27d9a6482a2cc1 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/irq.h>
 #include <linux/kernel.h>
 #include <linux/of_platform.h>
+#include <linux/platform_data/gpio-rcar.h>
 #include <linux/platform_data/irq-renesas-irqc.h>
 #include <linux/serial_sci.h>
 #include <linux/sh_timer.h>
 #include <mach/rcar-gen2.h>
 #include <asm/mach/arch.h>
 
+static const struct resource pfc_resources[] __initconst = {
+       DEFINE_RES_MEM(0xe6060000, 0x250),
+};
+
+#define r8a7791_register_pfc()                                         \
+       platform_device_register_simple("pfc-r8a7791", -1, pfc_resources, \
+                                       ARRAY_SIZE(pfc_resources))
+
+#define R8A7791_GPIO(idx, base, nr)                                    \
+static const struct resource r8a7791_gpio##idx##_resources[] __initconst = { \
+       DEFINE_RES_MEM((base), 0x50),                                   \
+       DEFINE_RES_IRQ(gic_spi(4 + (idx))),                             \
+};                                                                     \
+                                                                       \
+static const struct gpio_rcar_config                                   \
+r8a7791_gpio##idx##_platform_data __initconst = {                      \
+       .gpio_base      = 32 * (idx),                                   \
+       .irq_base       = 0,                                            \
+       .number_of_pins = (nr),                                         \
+       .pctl_name      = "pfc-r8a7791",                                \
+       .has_both_edge_trigger = 1,                                     \
+};                                                                     \
+
+R8A7791_GPIO(0, 0xe6050000, 32);
+R8A7791_GPIO(1, 0xe6051000, 32);
+R8A7791_GPIO(2, 0xe6052000, 32);
+R8A7791_GPIO(3, 0xe6053000, 32);
+R8A7791_GPIO(4, 0xe6054000, 32);
+R8A7791_GPIO(5, 0xe6055000, 32);
+R8A7791_GPIO(6, 0xe6055400, 32);
+R8A7791_GPIO(7, 0xe6055800, 26);
+
+#define r8a7791_register_gpio(idx)                                     \
+       platform_device_register_resndata(&platform_bus, "gpio_rcar", idx, \
+               r8a7791_gpio##idx##_resources,                          \
+               ARRAY_SIZE(r8a7791_gpio##idx##_resources),              \
+               &r8a7791_gpio##idx##_platform_data,                     \
+               sizeof(r8a7791_gpio##idx##_platform_data))
+
+void __init r8a7791_pinmux_init(void)
+{
+       r8a7791_register_pfc();
+       r8a7791_register_gpio(0);
+       r8a7791_register_gpio(1);
+       r8a7791_register_gpio(2);
+       r8a7791_register_gpio(3);
+       r8a7791_register_gpio(4);
+       r8a7791_register_gpio(5);
+       r8a7791_register_gpio(6);
+       r8a7791_register_gpio(7);
+}
+
 #define SCIF_COMMON(scif_type, baseaddr, irq)                  \
        .type           = scif_type,                            \
        .mapbase        = baseaddr,                             \
@@ -136,6 +189,17 @@ static struct resource irqc0_resources[] = {
                                          &irqc##idx##_data,            \
                                          sizeof(struct renesas_irqc_config))
 
+static const struct resource thermal_resources[] __initconst = {
+       DEFINE_RES_MEM(0xe61f0000, 0x14),
+       DEFINE_RES_MEM(0xe61f0100, 0x38),
+       DEFINE_RES_IRQ(gic_spi(69)),
+};
+
+#define r8a7791_register_thermal()                                     \
+       platform_device_register_simple("rcar_thermal", -1,             \
+                                       thermal_resources,              \
+                                       ARRAY_SIZE(thermal_resources))
+
 void __init r8a7791_add_dt_devices(void)
 {
        r8a7791_register_scif(SCIFA0);
@@ -160,6 +224,7 @@ void __init r8a7791_add_standard_devices(void)
 {
        r8a7791_add_dt_devices();
        r8a7791_register_irqc(0);
+       r8a7791_register_thermal();
 }
 
 void __init r8a7791_init_early(void)
index 22de17417fd7c83a4ae4c9b66162cd3c16f1cb04..65151c48cbd4fdc1ee431abf4ce264358d4ad69b 100644 (file)
@@ -273,7 +273,7 @@ static struct sh_timer_config tmu00_platform_data = {
 };
 
 static struct resource tmu00_resources[] = {
-       [0] = DEFINE_RES_MEM_NAMED(0xfff60008, 0xc, "TMU00"),
+       [0] = DEFINE_RES_MEM(0xfff60008, 0xc),
        [1] = {
                .start  = intcs_evt2irq(0x0e80), /* TMU0_TUNI00 */
                .flags  = IORESOURCE_IRQ,
@@ -298,7 +298,7 @@ static struct sh_timer_config tmu01_platform_data = {
 };
 
 static struct resource tmu01_resources[] = {
-       [0] = DEFINE_RES_MEM_NAMED(0xfff60014, 0xc, "TMU00"),
+       [0] = DEFINE_RES_MEM(0xfff60014, 0xc),
        [1] = {
                .start  = intcs_evt2irq(0x0ea0), /* TMU0_TUNI01 */
                .flags  = IORESOURCE_IRQ,
@@ -316,7 +316,7 @@ static struct platform_device tmu01_device = {
 };
 
 static struct resource i2c0_resources[] = {
-       [0] = DEFINE_RES_MEM_NAMED(0xe6820000, 0x426, "IIC0"),
+       [0] = DEFINE_RES_MEM(0xe6820000, 0x426),
        [1] = {
                .start  = gic_spi(167),
                .end    = gic_spi(170),
@@ -325,7 +325,7 @@ static struct resource i2c0_resources[] = {
 };
 
 static struct resource i2c1_resources[] = {
-       [0] = DEFINE_RES_MEM_NAMED(0xe6822000, 0x426, "IIC1"),
+       [0] = DEFINE_RES_MEM(0xe6822000, 0x426),
        [1] = {
                .start  = gic_spi(51),
                .end    = gic_spi(54),
@@ -334,7 +334,7 @@ static struct resource i2c1_resources[] = {
 };
 
 static struct resource i2c2_resources[] = {
-       [0] = DEFINE_RES_MEM_NAMED(0xe6824000, 0x426, "IIC2"),
+       [0] = DEFINE_RES_MEM(0xe6824000, 0x426),
        [1] = {
                .start  = gic_spi(171),
                .end    = gic_spi(174),
@@ -343,7 +343,7 @@ static struct resource i2c2_resources[] = {
 };
 
 static struct resource i2c3_resources[] = {
-       [0] = DEFINE_RES_MEM_NAMED(0xe6826000, 0x426, "IIC3"),
+       [0] = DEFINE_RES_MEM(0xe6826000, 0x426),
        [1] = {
                .start  = gic_spi(183),
                .end    = gic_spi(186),
@@ -352,7 +352,7 @@ static struct resource i2c3_resources[] = {
 };
 
 static struct resource i2c4_resources[] = {
-       [0] = DEFINE_RES_MEM_NAMED(0xe6828000, 0x426, "IIC4"),
+       [0] = DEFINE_RES_MEM(0xe6828000, 0x426),
        [1] = {
                .start  = gic_spi(187),
                .end    = gic_spi(190),
@@ -722,7 +722,7 @@ static struct platform_device pmu_device = {
 
 /* an IPMMU module for ICB */
 static struct resource ipmmu_resources[] = {
-       DEFINE_RES_MEM_NAMED(0xfe951000, 0x100, "IPMMU"),
+       DEFINE_RES_MEM(0xfe951000, 0x100),
 };
 
 static const char * const ipmmu_dev_names[] = {
index e834763ac2a521bd02ff6a7704d30576657cd10c..2c4141413db92ebbd0e39f43fef95a53ca6a034f 100644 (file)
@@ -26,23 +26,4 @@ static inline void __init gpio_direction_none(void __iomem * addr)
        __raw_writeb(0x00, addr);
 }
 
-static inline void __init gpio_request_pullup(void __iomem * addr)
-{
-       u8 data = __raw_readb(addr);
-
-       data &= 0x0F;
-       data |= 0xC0;
-       __raw_writeb(data, addr);
-}
-
-static inline void __init gpio_request_pulldown(void __iomem * addr)
-{
-       u8 data = __raw_readb(addr);
-
-       data &= 0x0F;
-       data |= 0xA0;
-
-       __raw_writeb(data, addr);
-}
-
 #endif /* __ASM_ARCH_GPIO_H */
index 037100a1563aca5f52dd2e68f42c711dc71484c2..aee77f06f887da5d8f73e2112333a015640e93ab 100644 (file)
@@ -10,6 +10,7 @@ config ARCH_SOCFPGA
        select GENERIC_CLOCKEVENTS
        select GPIO_PL061 if GPIOLIB
        select HAVE_ARM_SCU
+       select HAVE_ARM_TWD if SMP
        select HAVE_SMP
        select MFD_SYSCON
        select SPARSE_IRQ
index 9a4e910c3796154c8fa6c167851a8f6b112265f3..2adc2ab081e2436b06a5c5d4389b0daf42ec4fc9 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/io.h>
 #include <linux/export.h>
 #include <linux/random.h>
+#include <linux/clk.h>
 #include <linux/tegra-soc.h>
 
 #include "fuse.h"
@@ -54,6 +55,7 @@ int tegra_cpu_speedo_id;              /* only exist in Tegra30 and later */
 int tegra_soc_speedo_id;
 enum tegra_revision tegra_revision;
 
+static struct clk *fuse_clk;
 static int tegra_fuse_spare_bit;
 static void (*tegra_init_speedo_data)(void);
 
@@ -77,6 +79,22 @@ static const char *tegra_revision_name[TEGRA_REVISION_MAX] = {
        [TEGRA_REVISION_A04]     = "A04",
 };
 
+static void tegra_fuse_enable_clk(void)
+{
+       if (IS_ERR(fuse_clk))
+               fuse_clk = clk_get_sys(NULL, "fuse");
+       if (IS_ERR(fuse_clk))
+               return;
+       clk_prepare_enable(fuse_clk);
+}
+
+static void tegra_fuse_disable_clk(void)
+{
+       if (IS_ERR(fuse_clk))
+               return;
+       clk_disable_unprepare(fuse_clk);
+}
+
 u32 tegra_fuse_readl(unsigned long offset)
 {
        return tegra_apb_readl(TEGRA_FUSE_BASE + offset);
@@ -84,7 +102,15 @@ u32 tegra_fuse_readl(unsigned long offset)
 
 bool tegra_spare_fuse(int bit)
 {
-       return tegra_fuse_readl(tegra_fuse_spare_bit + bit * 4);
+       bool ret;
+
+       tegra_fuse_enable_clk();
+
+       ret = tegra_fuse_readl(tegra_fuse_spare_bit + bit * 4);
+
+       tegra_fuse_disable_clk();
+
+       return ret;
 }
 
 static enum tegra_revision tegra_get_revision(u32 id)
@@ -113,10 +139,14 @@ static void tegra_get_process_id(void)
 {
        u32 reg;
 
+       tegra_fuse_enable_clk();
+
        reg = tegra_fuse_readl(tegra_fuse_spare_bit);
        tegra_cpu_process_id = (reg >> 6) & 3;
        reg = tegra_fuse_readl(tegra_fuse_spare_bit);
        tegra_core_process_id = (reg >> 12) & 3;
+
+       tegra_fuse_disable_clk();
 }
 
 u32 tegra_read_chipid(void)
@@ -159,6 +189,15 @@ void __init tegra_init_fuse(void)
        reg |= 1 << 28;
        writel(reg, IO_ADDRESS(TEGRA_CLK_RESET_BASE + 0x48));
 
+       /*
+        * Enable FUSE clock. This needs to be hardcoded because the clock
+        * subsystem is not active during early boot.
+        */
+       reg = readl(IO_ADDRESS(TEGRA_CLK_RESET_BASE + 0x14));
+       reg |= 1 << 7;
+       writel(reg, IO_ADDRESS(TEGRA_CLK_RESET_BASE + 0x14));
+       fuse_clk = ERR_PTR(-EINVAL);
+
        reg = tegra_fuse_readl(FUSE_SKU_INFO);
        randomness[0] = reg;
        tegra_sku_id = reg & 0xFF;
index 26b1c2ad0cebfd30a50573138808b7df17cd34cf..ee79808e93a3f2edf91e43f2f6c069917cf1f4dd 100644 (file)
@@ -19,6 +19,7 @@
 #ifndef __MACH_TEGRA_IOMAP_H
 #define __MACH_TEGRA_IOMAP_H
 
+#include <asm/pgtable.h>
 #include <asm/sizes.h>
 
 #define TEGRA_IRAM_BASE                        0x40000000
  * two 256MB io windows (that actually only use about 64KB
  * at the start of each).
  *
- * We will just map the first 1MB of each window (to minimize
+ * We will just map the first MMU section of each window (to minimize
  * pt entries needed) and provide a macro to transform physical
  * io addresses to an appropriate void __iomem *.
- *
  */
 
 #define IO_IRAM_PHYS   0x40000000
 #define IO_IRAM_VIRT   IOMEM(0xFE400000)
 #define IO_IRAM_SIZE   SZ_256K
 
-#define IO_CPU_PHYS     0x50040000
-#define IO_CPU_VIRT     IOMEM(0xFE000000)
+#define IO_CPU_PHYS    0x50040000
+#define IO_CPU_VIRT    IOMEM(0xFE440000)
 #define IO_CPU_SIZE    SZ_16K
 
 #define IO_PPSB_PHYS   0x60000000
 #define IO_PPSB_VIRT   IOMEM(0xFE200000)
-#define IO_PPSB_SIZE   SZ_1M
+#define IO_PPSB_SIZE   SECTION_SIZE
 
 #define IO_APB_PHYS    0x70000000
-#define IO_APB_VIRT    IOMEM(0xFE300000)
-#define IO_APB_SIZE    SZ_1M
+#define IO_APB_VIRT    IOMEM(0xFE000000)
+#define IO_APB_SIZE    SECTION_SIZE
 
 #define IO_TO_VIRT_BETWEEN(p, st, sz)  ((p) >= (st) && (p) < ((st) + (sz)))
 #define IO_TO_VIRT_XLATE(p, pst, vst)  (((p) - (pst) + (vst)))
index 73368176c6e8592ecc5f2f0155d5598885692fd3..ea14d380fc0cd51beb66d8ef049999d7bb563420 100644 (file)
  * 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] = {
+u32 tegra_uart_config[3] = {
        /* 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)
index 9a5f9fb352ce1c7ca97baa3e4269ef54770e2faa..9724e4e7cc93ffa6232833bbb0c1f6ebdc1fbdf2 100644 (file)
@@ -341,7 +341,7 @@ static struct irqaction u300_timer_irq = {
  * stamp. (Inspired by OMAP implementation.)
  */
 
-static u32 notrace u300_read_sched_clock(void)
+static u64 notrace u300_read_sched_clock(void)
 {
        return readl(u300_timer_base + U300_TIMER_APP_GPT2CC);
 }
@@ -379,7 +379,7 @@ static void __init u300_timer_init_of(struct device_node *np)
        clk_prepare_enable(clk);
        rate = clk_get_rate(clk);
 
-       setup_sched_clock(u300_read_sched_clock, 32, rate);
+       sched_clock_register(u300_read_sched_clock, 32, rate);
 
        u300_delay_timer.read_current_timer = &u300_read_current_timer;
        u300_delay_timer.freq = rate;
index 616b96e86ad4fb067395ad4d2411cb8befcb92b8..d05ba759da3015a1aa54bafc7dceaef190c2a212 100644 (file)
@@ -2,10 +2,10 @@
 # Makefile for the linux kernel, U8500 machine.
 #
 
-obj-y                          := cpu.o devices.o id.o timer.o pm.o
+obj-y                          := cpu.o id.o timer.o pm.o
 obj-$(CONFIG_CACHE_L2X0)       += cache-l2x0.o
-obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o
-obj-$(CONFIG_MACH_MOP500)      += board-mop500.o board-mop500-sdi.o \
+obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o
+obj-$(CONFIG_MACH_MOP500)      += board-mop500-sdi.o \
                                board-mop500-regulators.o \
                                board-mop500-pins.o \
                                board-mop500-audio.o
index 154e15f59702c1010af74cce8fed51077c78e111..dc7f9015776641abde6e91adc8c9c93fe0c042a2 100644 (file)
@@ -7,16 +7,13 @@
 #include <linux/platform_device.h>
 #include <linux/init.h>
 #include <linux/gpio.h>
-#include <linux/platform_data/pinctrl-nomadik.h>
 #include <linux/platform_data/dma-ste-dma40.h>
 
-#include "devices.h"
 #include "irqs.h"
 #include <linux/platform_data/asoc-ux500-msp.h>
 
 #include "ste-dma40-db8500.h"
 #include "board-mop500.h"
-#include "devices-db8500.h"
 
 static struct stedma40_chan_cfg msp0_dma_rx = {
        .high_priority = true,
index 0efb1560fc355dc4f1f7887bfcba4cca260fda27..f63619b69113f16e274c3addb6843949f8f94cd4 100644 (file)
 #include <linux/string.h>
 #include <linux/pinctrl/machine.h>
 #include <linux/pinctrl/pinconf-generic.h>
-#include <linux/platform_data/pinctrl-nomadik.h>
 
 #include <asm/mach-types.h>
 
 #include "board-mop500.h"
 
-enum custom_pin_cfg_t {
-       PINS_FOR_DEFAULT,
-       PINS_FOR_U9500,
-};
-
-static enum custom_pin_cfg_t pinsfor;
-
 /* These simply sets bias for pins */
 #define BIAS(a,b) static unsigned long a[] = { b }
 
-BIAS(pd, PIN_PULL_DOWN);
-BIAS(in_nopull, PIN_INPUT_NOPULL);
-BIAS(in_nopull_slpm_nowkup, PIN_INPUT_NOPULL|PIN_SLPM_WAKEUP_DISABLE);
-BIAS(in_pu, PIN_INPUT_PULLUP);
-BIAS(in_pd, PIN_INPUT_PULLDOWN);
-BIAS(out_hi, PIN_OUTPUT_HIGH);
-BIAS(out_lo, PIN_OUTPUT_LOW);
-BIAS(out_lo_slpm_nowkup, PIN_OUTPUT_LOW|PIN_SLPM_WAKEUP_DISABLE);
-
 BIAS(abx500_out_lo, PIN_CONF_PACKED(PIN_CONFIG_OUTPUT, 0));
 BIAS(abx500_in_pd, PIN_CONF_PACKED(PIN_CONFIG_BIAS_PULL_DOWN, 1));
 BIAS(abx500_in_nopull, PIN_CONF_PACKED(PIN_CONFIG_BIAS_PULL_DOWN, 0));
 
-/* These also force them into GPIO mode */
-BIAS(gpio_in_pu, PIN_INPUT_PULLUP|PIN_GPIOMODE_ENABLED);
-BIAS(gpio_in_pd, PIN_INPUT_PULLDOWN|PIN_GPIOMODE_ENABLED);
-BIAS(gpio_in_pu_slpm_gpio_nopull, PIN_INPUT_PULLUP|PIN_GPIOMODE_ENABLED|PIN_SLPM_GPIO|PIN_SLPM_INPUT_NOPULL);
-BIAS(gpio_in_pd_slpm_gpio_nopull, PIN_INPUT_PULLDOWN|PIN_GPIOMODE_ENABLED|PIN_SLPM_GPIO|PIN_SLPM_INPUT_NOPULL);
-BIAS(gpio_out_hi, PIN_OUTPUT_HIGH|PIN_GPIOMODE_ENABLED);
-BIAS(gpio_out_lo, PIN_OUTPUT_LOW|PIN_GPIOMODE_ENABLED);
-/* Sleep modes */
-BIAS(slpm_in_wkup_pdis, PIN_SLEEPMODE_ENABLED|
-       PIN_SLPM_DIR_INPUT|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
-BIAS(slpm_in_wkup_pdis_en, PIN_SLEEPMODE_ENABLED|
-       PIN_SLPM_DIR_INPUT|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_ENABLED);
-BIAS(slpm_wkup_pdis, PIN_SLEEPMODE_ENABLED|
-       PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
-BIAS(slpm_wkup_pdis_en, PIN_SLEEPMODE_ENABLED|
-       PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_ENABLED);
-BIAS(slpm_out_lo_pdis, PIN_SLEEPMODE_ENABLED|
-       PIN_SLPM_OUTPUT_LOW|PIN_SLPM_WAKEUP_DISABLE|PIN_SLPM_PDIS_DISABLED);
-BIAS(slpm_out_lo_wkup_pdis, PIN_SLEEPMODE_ENABLED|
-       PIN_SLPM_OUTPUT_LOW|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
-BIAS(slpm_out_hi_wkup_pdis, PIN_SLEEPMODE_ENABLED|PIN_SLPM_OUTPUT_HIGH|
-       PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
-BIAS(slpm_in_nopull_wkup_pdis, PIN_SLEEPMODE_ENABLED|
-       PIN_SLPM_INPUT_NOPULL|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
-BIAS(slpm_in_pu_wkup_pdis_en, PIN_SLEEPMODE_ENABLED|PIN_SLPM_INPUT_PULLUP|
-       PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_ENABLED);
-BIAS(slpm_out_wkup_pdis, PIN_SLEEPMODE_ENABLED|
-       PIN_SLPM_DIR_OUTPUT|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
-BIAS(out_lo_wkup_pdis, PIN_SLPM_OUTPUT_LOW|
-       PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
-BIAS(in_wkup_pdis_en, PIN_SLPM_DIR_INPUT|PIN_SLPM_WAKEUP_ENABLE|
-       PIN_SLPM_PDIS_ENABLED);
-BIAS(in_wkup_pdis, PIN_SLPM_DIR_INPUT|PIN_SLPM_WAKEUP_ENABLE|
-       PIN_SLPM_PDIS_DISABLED);
-BIAS(out_wkup_pdis, PIN_SLPM_DIR_OUTPUT|PIN_SLPM_WAKEUP_ENABLE|
-       PIN_SLPM_PDIS_DISABLED);
-
-/* We use these to define hog settings that are always done on boot */
-#define DB8500_MUX_HOG(group,func) \
-       PIN_MAP_MUX_GROUP_HOG_DEFAULT("pinctrl-db8500", group, func)
-#define DB8500_PIN_HOG(pin,conf) \
-       PIN_MAP_CONFIGS_PIN_HOG_DEFAULT("pinctrl-db8500", pin, conf)
-
-/* These are default states associated with device and changed runtime */
-#define DB8500_MUX(group,func,dev) \
-       PIN_MAP_MUX_GROUP_DEFAULT(dev, "pinctrl-db8500", group, func)
-#define DB8500_PIN(pin,conf,dev) \
-       PIN_MAP_CONFIGS_PIN_DEFAULT(dev, "pinctrl-db8500", pin, conf)
-#define DB8500_PIN_IDLE(pin, conf, dev) \
-       PIN_MAP_CONFIGS_PIN(dev, PINCTRL_STATE_IDLE, "pinctrl-db8500",  \
-                           pin, conf)
-#define DB8500_PIN_SLEEP(pin, conf, dev) \
-       PIN_MAP_CONFIGS_PIN(dev, PINCTRL_STATE_SLEEP, "pinctrl-db8500", \
-                           pin, conf)
-#define DB8500_MUX_STATE(group, func, dev, state) \
-       PIN_MAP_MUX_GROUP(dev, state, "pinctrl-db8500", group, func)
-#define DB8500_PIN_STATE(pin, conf, dev, state) \
-       PIN_MAP_CONFIGS_PIN(dev, state, "pinctrl-db8500", pin, conf)
-
 #define AB8500_MUX_HOG(group, func) \
        PIN_MAP_MUX_GROUP_HOG_DEFAULT("pinctrl-ab8500.0", group, func)
 #define AB8500_PIN_HOG(pin, conf) \
@@ -344,725 +268,8 @@ static struct pinctrl_map __initdata ab8505_pinmap[] = {
        AB8505_PIN_HOG("GPIO53_D15", in_pd),
 };
 
-/* Pin control settings */
-static struct pinctrl_map __initdata mop500_family_pinmap[] = {
-       /*
-        * uMSP0, mux in 4 pins, regular placement of RX/TX
-        * explicitly set the pins to no pull
-        */
-       DB8500_MUX_HOG("msp0txrx_a_1", "msp0"),
-       DB8500_MUX_HOG("msp0tfstck_a_1", "msp0"),
-       DB8500_PIN_HOG("GPIO12_AC4", in_nopull), /* TXD */
-       DB8500_PIN_HOG("GPIO15_AC3", in_nopull), /* RXD */
-       DB8500_PIN_HOG("GPIO13_AF3", in_nopull), /* TFS */
-       DB8500_PIN_HOG("GPIO14_AE3", in_nopull), /* TCK */
-       /* MSP2 for HDMI, pull down TXD, TCK, TFS  */
-       DB8500_MUX_HOG("msp2_a_1", "msp2"),
-       DB8500_PIN_HOG("GPIO193_AH27", in_pd), /* TXD */
-       DB8500_PIN_HOG("GPIO194_AF27", in_pd), /* TCK */
-       DB8500_PIN_HOG("GPIO195_AG28", in_pd), /* TFS */
-       DB8500_PIN_HOG("GPIO196_AG26", out_lo), /* RXD */
-       /*
-        * LCD, set TE0 (using LCD VSI0) and D14 (touch screen interrupt) to
-        * pull-up
-        * TODO: is this really correct? Snowball doesn't have a LCD.
-        */
-       DB8500_MUX_HOG("lcdvsi0_a_1", "lcd"),
-       DB8500_PIN_HOG("GPIO68_E1", in_pu),
-       DB8500_PIN_HOG("GPIO84_C2", gpio_in_pu),
-       /*
-        * STMPE1601/tc35893 keypad IRQ GPIO 218
-        * TODO: set for snowball and HREF really??
-        */
-       DB8500_PIN_HOG("GPIO218_AH11", gpio_in_pu),
-       /*
-        * UART0, we do not mux in u0 here.
-        * uart-0 pins gpio configuration should be kept intact to prevent
-        * a glitch in tx line when the tty dev is opened. Later these pins
-        * are configured by uart driver
-        */
-       DB8500_PIN_HOG("GPIO0_AJ5", in_pu), /* CTS */
-       DB8500_PIN_HOG("GPIO1_AJ3", out_hi), /* RTS */
-       DB8500_PIN_HOG("GPIO2_AH4", in_pu), /* RXD */
-       DB8500_PIN_HOG("GPIO3_AH3", out_hi), /* TXD */
-       /*
-        * Mux in UART2 on altfunction C and set pull-ups.
-        * TODO: is this used on U8500 variants and Snowball really?
-        * The setting on GPIO31 conflicts with magnetometer use on hrefv60
-        */
-       /* default state for UART2 */
-       DB8500_MUX("u2rxtx_c_1", "u2", "uart2"),
-       DB8500_PIN("GPIO29_W2", in_pu, "uart2"), /* RXD */
-       DB8500_PIN("GPIO30_W3", out_hi, "uart2"), /* TXD */
-       /* Sleep state for UART2 */
-       DB8500_PIN_SLEEP("GPIO29_W2", in_wkup_pdis, "uart2"),
-       DB8500_PIN_SLEEP("GPIO30_W3", out_wkup_pdis, "uart2"),
-       /*
-        * The following pin sets were known as "runtime pins" before being
-        * converted to the pinctrl model. Here we model them as "default"
-        * states.
-        */
-       /* Mux in UART0 after initialization */
-       DB8500_MUX("u0_a_1", "u0", "uart0"),
-       DB8500_PIN("GPIO0_AJ5", in_pu, "uart0"), /* CTS */
-       DB8500_PIN("GPIO1_AJ3", out_hi, "uart0"), /* RTS */
-       DB8500_PIN("GPIO2_AH4", in_pu, "uart0"), /* RXD */
-       DB8500_PIN("GPIO3_AH3", out_hi, "uart0"), /* TXD */
-       /* Sleep state for UART0 */
-       DB8500_PIN_SLEEP("GPIO0_AJ5", slpm_in_wkup_pdis, "uart0"),
-       DB8500_PIN_SLEEP("GPIO1_AJ3", slpm_out_hi_wkup_pdis, "uart0"),
-       DB8500_PIN_SLEEP("GPIO2_AH4", slpm_in_wkup_pdis, "uart0"),
-       DB8500_PIN_SLEEP("GPIO3_AH3", slpm_out_wkup_pdis, "uart0"),
-       /* Mux in UART1 after initialization */
-       DB8500_MUX("u1rxtx_a_1", "u1", "uart1"),
-       DB8500_PIN("GPIO4_AH6", in_pu, "uart1"), /* RXD */
-       DB8500_PIN("GPIO5_AG6", out_hi, "uart1"), /* TXD */
-       /* Sleep state for UART1 */
-       DB8500_PIN_SLEEP("GPIO4_AH6", slpm_in_wkup_pdis, "uart1"),
-       DB8500_PIN_SLEEP("GPIO5_AG6", slpm_out_wkup_pdis, "uart1"),
-       /* MSP1 for ALSA codec */
-       DB8500_MUX_HOG("msp1txrx_a_1", "msp1"),
-       DB8500_MUX_HOG("msp1_a_1", "msp1"),
-       DB8500_PIN_HOG("GPIO33_AF2", out_lo_slpm_nowkup),
-       DB8500_PIN_HOG("GPIO34_AE1", in_nopull_slpm_nowkup),
-       DB8500_PIN_HOG("GPIO35_AE2", in_nopull_slpm_nowkup),
-       DB8500_PIN_HOG("GPIO36_AG2", in_nopull_slpm_nowkup),
-       /* Mux in LCD data lines 8 thru 11 and LCDA CLK for MCDE TVOUT */
-       DB8500_MUX("lcd_d8_d11_a_1", "lcd", "mcde-tvout"),
-       DB8500_MUX("lcdaclk_b_1", "lcda", "mcde-tvout"),
-       /* Mux in LCD VSI1 and pull it up for MCDE HDMI output */
-       DB8500_MUX("lcdvsi1_a_1", "lcd", "0-0070"),
-       DB8500_PIN("GPIO69_E2", in_pu, "0-0070"),
-       /* LCD VSI1 sleep state */
-       DB8500_PIN_SLEEP("GPIO69_E2", slpm_in_wkup_pdis, "0-0070"),
-       /* Mux in i2c0 block, default state */
-       DB8500_MUX("i2c0_a_1", "i2c0", "nmk-i2c.0"),
-       /* i2c0 sleep state */
-       DB8500_PIN_SLEEP("GPIO147_C15", slpm_in_nopull_wkup_pdis, "nmk-i2c.0"), /* SDA */
-       DB8500_PIN_SLEEP("GPIO148_B16", slpm_in_nopull_wkup_pdis, "nmk-i2c.0"), /* SCL */
-       /* Mux in i2c1 block, default state  */
-       DB8500_MUX("i2c1_b_2", "i2c1", "nmk-i2c.1"),
-       /* i2c1 sleep state */
-       DB8500_PIN_SLEEP("GPIO16_AD3", slpm_in_nopull_wkup_pdis, "nmk-i2c.1"), /* SDA */
-       DB8500_PIN_SLEEP("GPIO17_AD4", slpm_in_nopull_wkup_pdis, "nmk-i2c.1"), /* SCL */
-       /* Mux in i2c2 block, default state  */
-       DB8500_MUX("i2c2_b_2", "i2c2", "nmk-i2c.2"),
-       /* i2c2 sleep state */
-       DB8500_PIN_SLEEP("GPIO10_AF5", slpm_in_nopull_wkup_pdis, "nmk-i2c.2"), /* SDA */
-       DB8500_PIN_SLEEP("GPIO11_AG4", slpm_in_nopull_wkup_pdis, "nmk-i2c.2"), /* SCL */
-       /* Mux in i2c3 block, default state  */
-       DB8500_MUX("i2c3_c_2", "i2c3", "nmk-i2c.3"),
-       /* i2c3 sleep state */
-       DB8500_PIN_SLEEP("GPIO229_AG7", slpm_in_nopull_wkup_pdis, "nmk-i2c.3"), /* SDA */
-       DB8500_PIN_SLEEP("GPIO230_AF7", slpm_in_nopull_wkup_pdis, "nmk-i2c.3"), /* SCL */
-       /* Mux in SDI0 (here called MC0) used for removable MMC/SD/SDIO cards */
-       DB8500_MUX("mc0_a_1", "mc0", "sdi0"),
-       DB8500_PIN("GPIO18_AC2", out_hi, "sdi0"), /* CMDDIR */
-       DB8500_PIN("GPIO19_AC1", out_hi, "sdi0"), /* DAT0DIR */
-       DB8500_PIN("GPIO20_AB4", out_hi, "sdi0"), /* DAT2DIR */
-       DB8500_PIN("GPIO22_AA3", in_nopull, "sdi0"), /* FBCLK */
-       DB8500_PIN("GPIO23_AA4", out_lo, "sdi0"), /* CLK */
-       DB8500_PIN("GPIO24_AB2", in_pu, "sdi0"), /* CMD */
-       DB8500_PIN("GPIO25_Y4", in_pu, "sdi0"), /* DAT0 */
-       DB8500_PIN("GPIO26_Y2", in_pu, "sdi0"), /* DAT1 */
-       DB8500_PIN("GPIO27_AA2", in_pu, "sdi0"), /* DAT2 */
-       DB8500_PIN("GPIO28_AA1", in_pu, "sdi0"), /* DAT3 */
-       /* SDI0 sleep state */
-       DB8500_PIN_SLEEP("GPIO18_AC2", slpm_out_hi_wkup_pdis, "sdi0"),
-       DB8500_PIN_SLEEP("GPIO19_AC1", slpm_out_hi_wkup_pdis, "sdi0"),
-       DB8500_PIN_SLEEP("GPIO20_AB4", slpm_out_hi_wkup_pdis, "sdi0"),
-       DB8500_PIN_SLEEP("GPIO22_AA3", slpm_in_wkup_pdis, "sdi0"),
-       DB8500_PIN_SLEEP("GPIO23_AA4", slpm_out_lo_wkup_pdis, "sdi0"),
-       DB8500_PIN_SLEEP("GPIO24_AB2", slpm_in_wkup_pdis, "sdi0"),
-       DB8500_PIN_SLEEP("GPIO25_Y4", slpm_in_wkup_pdis, "sdi0"),
-       DB8500_PIN_SLEEP("GPIO26_Y2", slpm_in_wkup_pdis, "sdi0"),
-       DB8500_PIN_SLEEP("GPIO27_AA2", slpm_in_wkup_pdis, "sdi0"),
-       DB8500_PIN_SLEEP("GPIO28_AA1", slpm_in_wkup_pdis, "sdi0"),
-
-       /* Mux in SDI1 (here called MC1) used for SDIO for CW1200 WLAN */
-       DB8500_MUX("mc1_a_1", "mc1", "sdi1"),
-       DB8500_PIN("GPIO208_AH16", out_lo, "sdi1"), /* CLK */
-       DB8500_PIN("GPIO209_AG15", in_nopull, "sdi1"), /* FBCLK */
-       DB8500_PIN("GPIO210_AJ15", in_pu, "sdi1"), /* CMD */
-       DB8500_PIN("GPIO211_AG14", in_pu, "sdi1"), /* DAT0 */
-       DB8500_PIN("GPIO212_AF13", in_pu, "sdi1"), /* DAT1 */
-       DB8500_PIN("GPIO213_AG13", in_pu, "sdi1"), /* DAT2 */
-       DB8500_PIN("GPIO214_AH15", in_pu, "sdi1"), /* DAT3 */
-       /* SDI1 sleep state */
-       DB8500_PIN_SLEEP("GPIO208_AH16", slpm_out_lo_wkup_pdis, "sdi1"), /* CLK */
-       DB8500_PIN_SLEEP("GPIO209_AG15", slpm_in_wkup_pdis, "sdi1"), /* FBCLK */
-       DB8500_PIN_SLEEP("GPIO210_AJ15", slpm_in_wkup_pdis, "sdi1"), /* CMD */
-       DB8500_PIN_SLEEP("GPIO211_AG14", slpm_in_wkup_pdis, "sdi1"), /* DAT0 */
-       DB8500_PIN_SLEEP("GPIO212_AF13", slpm_in_wkup_pdis, "sdi1"), /* DAT1 */
-       DB8500_PIN_SLEEP("GPIO213_AG13", slpm_in_wkup_pdis, "sdi1"), /* DAT2 */
-       DB8500_PIN_SLEEP("GPIO214_AH15", slpm_in_wkup_pdis, "sdi1"), /* DAT3 */
-
-       /* Mux in SDI2 (here called MC2) used for for PoP eMMC */
-       DB8500_MUX("mc2_a_1", "mc2", "sdi2"),
-       DB8500_PIN("GPIO128_A5", out_lo, "sdi2"), /* CLK */
-       DB8500_PIN("GPIO129_B4", in_pu, "sdi2"), /* CMD */
-       DB8500_PIN("GPIO130_C8", in_nopull, "sdi2"), /* FBCLK */
-       DB8500_PIN("GPIO131_A12", in_pu, "sdi2"), /* DAT0 */
-       DB8500_PIN("GPIO132_C10", in_pu, "sdi2"), /* DAT1 */
-       DB8500_PIN("GPIO133_B10", in_pu, "sdi2"), /* DAT2 */
-       DB8500_PIN("GPIO134_B9", in_pu, "sdi2"), /* DAT3 */
-       DB8500_PIN("GPIO135_A9", in_pu, "sdi2"), /* DAT4 */
-       DB8500_PIN("GPIO136_C7", in_pu, "sdi2"), /* DAT5 */
-       DB8500_PIN("GPIO137_A7", in_pu, "sdi2"), /* DAT6 */
-       DB8500_PIN("GPIO138_C5", in_pu, "sdi2"), /* DAT7 */
-       /* SDI2 sleep state */
-       DB8500_PIN_SLEEP("GPIO128_A5", out_lo_wkup_pdis, "sdi2"), /* CLK */
-       DB8500_PIN_SLEEP("GPIO129_B4", in_wkup_pdis_en, "sdi2"), /* CMD */
-       DB8500_PIN_SLEEP("GPIO130_C8", in_wkup_pdis_en, "sdi2"), /* FBCLK */
-       DB8500_PIN_SLEEP("GPIO131_A12", in_wkup_pdis, "sdi2"), /* DAT0 */
-       DB8500_PIN_SLEEP("GPIO132_C10", in_wkup_pdis, "sdi2"), /* DAT1 */
-       DB8500_PIN_SLEEP("GPIO133_B10", in_wkup_pdis, "sdi2"), /* DAT2 */
-       DB8500_PIN_SLEEP("GPIO134_B9", in_wkup_pdis, "sdi2"), /* DAT3 */
-       DB8500_PIN_SLEEP("GPIO135_A9", in_wkup_pdis, "sdi2"), /* DAT4 */
-       DB8500_PIN_SLEEP("GPIO136_C7", in_wkup_pdis, "sdi2"), /* DAT5 */
-       DB8500_PIN_SLEEP("GPIO137_A7", in_wkup_pdis, "sdi2"), /* DAT6 */
-       DB8500_PIN_SLEEP("GPIO138_C5", in_wkup_pdis, "sdi2"), /* DAT7 */
-
-       /* Mux in SDI4 (here called MC4) used for for PCB-mounted eMMC */
-       DB8500_MUX("mc4_a_1", "mc4", "sdi4"),
-       DB8500_PIN("GPIO197_AH24", in_pu, "sdi4"), /* DAT3 */
-       DB8500_PIN("GPIO198_AG25", in_pu, "sdi4"), /* DAT2 */
-       DB8500_PIN("GPIO199_AH23", in_pu, "sdi4"), /* DAT1 */
-       DB8500_PIN("GPIO200_AH26", in_pu, "sdi4"), /* DAT0 */
-       DB8500_PIN("GPIO201_AF24", in_pu, "sdi4"), /* CMD */
-       DB8500_PIN("GPIO202_AF25", in_nopull, "sdi4"), /* FBCLK */
-       DB8500_PIN("GPIO203_AE23", out_lo, "sdi4"), /* CLK */
-       DB8500_PIN("GPIO204_AF23", in_pu, "sdi4"), /* DAT7 */
-       DB8500_PIN("GPIO205_AG23", in_pu, "sdi4"), /* DAT6 */
-       DB8500_PIN("GPIO206_AG24", in_pu, "sdi4"), /* DAT5 */
-       DB8500_PIN("GPIO207_AJ23", in_pu, "sdi4"), /* DAT4 */
-       /*SDI4 sleep state */
-       DB8500_PIN_SLEEP("GPIO197_AH24", slpm_in_wkup_pdis, "sdi4"), /* DAT3 */
-       DB8500_PIN_SLEEP("GPIO198_AG25", slpm_in_wkup_pdis, "sdi4"), /* DAT2 */
-       DB8500_PIN_SLEEP("GPIO199_AH23", slpm_in_wkup_pdis, "sdi4"), /* DAT1 */
-       DB8500_PIN_SLEEP("GPIO200_AH26", slpm_in_wkup_pdis, "sdi4"), /* DAT0 */
-       DB8500_PIN_SLEEP("GPIO201_AF24", slpm_in_wkup_pdis, "sdi4"), /* CMD */
-       DB8500_PIN_SLEEP("GPIO202_AF25", slpm_in_wkup_pdis, "sdi4"), /* FBCLK */
-       DB8500_PIN_SLEEP("GPIO203_AE23", slpm_out_lo_wkup_pdis, "sdi4"), /* CLK */
-       DB8500_PIN_SLEEP("GPIO204_AF23", slpm_in_wkup_pdis, "sdi4"), /* DAT7 */
-       DB8500_PIN_SLEEP("GPIO205_AG23", slpm_in_wkup_pdis, "sdi4"), /* DAT6 */
-       DB8500_PIN_SLEEP("GPIO206_AG24", slpm_in_wkup_pdis, "sdi4"), /* DAT5 */
-       DB8500_PIN_SLEEP("GPIO207_AJ23", slpm_in_wkup_pdis, "sdi4"), /* DAT4 */
-
-       /* Mux in USB pins, drive STP high */
-       /* USB default state */
-       DB8500_MUX("usb_a_1", "usb", "ab8500-usb.0"),
-       DB8500_PIN("GPIO257_AE29", out_hi, "ab8500-usb.0"), /* STP */
-       /* USB sleep state */
-       DB8500_PIN_SLEEP("GPIO256_AF28", slpm_wkup_pdis_en, "ab8500-usb.0"), /* NXT */
-       DB8500_PIN_SLEEP("GPIO257_AE29", slpm_out_hi_wkup_pdis, "ab8500-usb.0"), /* STP */
-       DB8500_PIN_SLEEP("GPIO258_AD29", slpm_wkup_pdis_en, "ab8500-usb.0"), /* XCLK */
-       DB8500_PIN_SLEEP("GPIO259_AC29", slpm_wkup_pdis_en, "ab8500-usb.0"), /* DIR */
-       DB8500_PIN_SLEEP("GPIO260_AD28", slpm_in_wkup_pdis_en, "ab8500-usb.0"), /* DAT7 */
-       DB8500_PIN_SLEEP("GPIO261_AD26", slpm_in_wkup_pdis_en, "ab8500-usb.0"), /* DAT6 */
-       DB8500_PIN_SLEEP("GPIO262_AE26", slpm_in_wkup_pdis_en, "ab8500-usb.0"), /* DAT5 */
-       DB8500_PIN_SLEEP("GPIO263_AG29", slpm_in_wkup_pdis_en, "ab8500-usb.0"), /* DAT4 */
-       DB8500_PIN_SLEEP("GPIO264_AE27", slpm_in_wkup_pdis_en, "ab8500-usb.0"), /* DAT3 */
-       DB8500_PIN_SLEEP("GPIO265_AD27", slpm_in_wkup_pdis_en, "ab8500-usb.0"), /* DAT2 */
-       DB8500_PIN_SLEEP("GPIO266_AC28", slpm_in_wkup_pdis_en, "ab8500-usb.0"), /* DAT1 */
-       DB8500_PIN_SLEEP("GPIO267_AC27", slpm_in_wkup_pdis_en, "ab8500-usb.0"), /* DAT0 */
-
-       /* Mux in SPI2 pins on the "other C1" altfunction */
-       DB8500_MUX("spi2_oc1_2", "spi2", "spi2"),
-       DB8500_PIN("GPIO216_AG12", gpio_out_hi, "spi2"), /* FRM */
-       DB8500_PIN("GPIO218_AH11", in_pd, "spi2"), /* RXD */
-       DB8500_PIN("GPIO215_AH13", out_lo, "spi2"), /* TXD */
-       DB8500_PIN("GPIO217_AH12", out_lo, "spi2"), /* CLK */
-       /* SPI2 idle state */
-       DB8500_PIN_IDLE("GPIO218_AH11", slpm_in_wkup_pdis, "spi2"), /* RXD */
-       DB8500_PIN_IDLE("GPIO215_AH13", slpm_out_lo_wkup_pdis, "spi2"), /* TXD */
-       DB8500_PIN_IDLE("GPIO217_AH12", slpm_wkup_pdis, "spi2"), /* CLK */
-       /* SPI2 sleep state */
-       DB8500_PIN_SLEEP("GPIO216_AG12", slpm_in_wkup_pdis, "spi2"), /* FRM */
-       DB8500_PIN_SLEEP("GPIO218_AH11", slpm_in_wkup_pdis, "spi2"), /* RXD */
-       DB8500_PIN_SLEEP("GPIO215_AH13", slpm_out_lo_wkup_pdis, "spi2"), /* TXD */
-       DB8500_PIN_SLEEP("GPIO217_AH12", slpm_wkup_pdis, "spi2"), /* CLK */
-
-       /* ske default state */
-       DB8500_MUX("kp_a_2", "kp", "nmk-ske-keypad"),
-       DB8500_PIN("GPIO153_B17", in_pd, "nmk-ske-keypad"), /* I7 */
-       DB8500_PIN("GPIO154_C16", in_pd, "nmk-ske-keypad"), /* I6 */
-       DB8500_PIN("GPIO155_C19", in_pd, "nmk-ske-keypad"), /* I5 */
-       DB8500_PIN("GPIO156_C17", in_pd, "nmk-ske-keypad"), /* I4 */
-       DB8500_PIN("GPIO161_D21", in_pd, "nmk-ske-keypad"), /* I3 */
-       DB8500_PIN("GPIO162_D20", in_pd, "nmk-ske-keypad"), /* I2 */
-       DB8500_PIN("GPIO163_C20", in_pd, "nmk-ske-keypad"), /* I1 */
-       DB8500_PIN("GPIO164_B21", in_pd, "nmk-ske-keypad"), /* I0 */
-       DB8500_PIN("GPIO157_A18", out_lo, "nmk-ske-keypad"), /* O7 */
-       DB8500_PIN("GPIO158_C18", out_lo, "nmk-ske-keypad"), /* O6 */
-       DB8500_PIN("GPIO159_B19", out_lo, "nmk-ske-keypad"), /* O5 */
-       DB8500_PIN("GPIO160_B20", out_lo, "nmk-ske-keypad"), /* O4 */
-       DB8500_PIN("GPIO165_C21", out_lo, "nmk-ske-keypad"), /* O3 */
-       DB8500_PIN("GPIO166_A22", out_lo, "nmk-ske-keypad"), /* O2 */
-       DB8500_PIN("GPIO167_B24", out_lo, "nmk-ske-keypad"), /* O1 */
-       DB8500_PIN("GPIO168_C22", out_lo, "nmk-ske-keypad"), /* O0 */
-       /* ske sleep state */
-       DB8500_PIN_SLEEP("GPIO153_B17", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I7 */
-       DB8500_PIN_SLEEP("GPIO154_C16", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I6 */
-       DB8500_PIN_SLEEP("GPIO155_C19", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I5 */
-       DB8500_PIN_SLEEP("GPIO156_C17", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I4 */
-       DB8500_PIN_SLEEP("GPIO161_D21", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I3 */
-       DB8500_PIN_SLEEP("GPIO162_D20", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I2 */
-       DB8500_PIN_SLEEP("GPIO163_C20", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I1 */
-       DB8500_PIN_SLEEP("GPIO164_B21", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I0 */
-       DB8500_PIN_SLEEP("GPIO157_A18", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O7 */
-       DB8500_PIN_SLEEP("GPIO158_C18", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O6 */
-       DB8500_PIN_SLEEP("GPIO159_B19", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O5 */
-       DB8500_PIN_SLEEP("GPIO160_B20", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O4 */
-       DB8500_PIN_SLEEP("GPIO165_C21", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O3 */
-       DB8500_PIN_SLEEP("GPIO166_A22", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O2 */
-       DB8500_PIN_SLEEP("GPIO167_B24", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O1 */
-       DB8500_PIN_SLEEP("GPIO168_C22", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O0 */
-
-       /* STM APE pins states */
-       DB8500_MUX_STATE("stmape_c_1", "stmape",
-               "stm", "ape_mipi34"),
-       DB8500_PIN_STATE("GPIO70_G5", in_nopull,
-               "stm", "ape_mipi34"), /* clk */
-       DB8500_PIN_STATE("GPIO71_G4", in_nopull,
-               "stm", "ape_mipi34"), /* dat3 */
-       DB8500_PIN_STATE("GPIO72_H4", in_nopull,
-               "stm", "ape_mipi34"), /* dat2 */
-       DB8500_PIN_STATE("GPIO73_H3", in_nopull,
-               "stm", "ape_mipi34"), /* dat1 */
-       DB8500_PIN_STATE("GPIO74_J3", in_nopull,
-               "stm", "ape_mipi34"), /* dat0 */
-
-       DB8500_PIN_STATE("GPIO70_G5", slpm_out_lo_pdis,
-               "stm", "ape_mipi34_sleep"), /* clk */
-       DB8500_PIN_STATE("GPIO71_G4", slpm_out_lo_pdis,
-               "stm", "ape_mipi34_sleep"), /* dat3 */
-       DB8500_PIN_STATE("GPIO72_H4", slpm_out_lo_pdis,
-               "stm", "ape_mipi34_sleep"), /* dat2 */
-       DB8500_PIN_STATE("GPIO73_H3", slpm_out_lo_pdis,
-               "stm", "ape_mipi34_sleep"), /* dat1 */
-       DB8500_PIN_STATE("GPIO74_J3", slpm_out_lo_pdis,
-               "stm", "ape_mipi34_sleep"), /* dat0 */
-
-       DB8500_MUX_STATE("stmape_oc1_1", "stmape",
-               "stm", "ape_microsd"),
-       DB8500_PIN_STATE("GPIO23_AA4", in_nopull,
-               "stm", "ape_microsd"), /* clk */
-       DB8500_PIN_STATE("GPIO25_Y4", in_nopull,
-               "stm", "ape_microsd"), /* dat0 */
-       DB8500_PIN_STATE("GPIO26_Y2", in_nopull,
-               "stm", "ape_microsd"), /* dat1 */
-       DB8500_PIN_STATE("GPIO27_AA2", in_nopull,
-               "stm", "ape_microsd"), /* dat2 */
-       DB8500_PIN_STATE("GPIO28_AA1", in_nopull,
-               "stm", "ape_microsd"), /* dat3 */
-
-       DB8500_PIN_STATE("GPIO23_AA4", slpm_out_lo_wkup_pdis,
-               "stm", "ape_microsd_sleep"), /* clk */
-       DB8500_PIN_STATE("GPIO25_Y4", slpm_in_wkup_pdis,
-               "stm", "ape_microsd_sleep"), /* dat0 */
-       DB8500_PIN_STATE("GPIO26_Y2", slpm_in_wkup_pdis,
-               "stm", "ape_microsd_sleep"), /* dat1 */
-       DB8500_PIN_STATE("GPIO27_AA2", slpm_in_wkup_pdis,
-               "stm", "ape_microsd_sleep"), /* dat2 */
-       DB8500_PIN_STATE("GPIO28_AA1", slpm_in_wkup_pdis,
-               "stm", "ape_microsd_sleep"), /* dat3 */
-
-       /*  STM Modem pins states */
-       DB8500_MUX_STATE("stmmod_oc3_2", "stmmod",
-               "stm", "mod_mipi34"),
-       DB8500_MUX_STATE("uartmodrx_oc3_1", "uartmod",
-               "stm", "mod_mipi34"),
-       DB8500_MUX_STATE("uartmodtx_oc3_1", "uartmod",
-               "stm", "mod_mipi34"),
-       DB8500_PIN_STATE("GPIO70_G5", in_nopull,
-               "stm", "mod_mipi34"), /* clk */
-       DB8500_PIN_STATE("GPIO71_G4", in_nopull,
-               "stm", "mod_mipi34"), /* dat3 */
-       DB8500_PIN_STATE("GPIO72_H4", in_nopull,
-               "stm", "mod_mipi34"), /* dat2 */
-       DB8500_PIN_STATE("GPIO73_H3", in_nopull,
-               "stm", "mod_mipi34"), /* dat1 */
-       DB8500_PIN_STATE("GPIO74_J3", in_nopull,
-               "stm", "mod_mipi34"), /* dat0 */
-       DB8500_PIN_STATE("GPIO75_H2", in_pu,
-               "stm", "mod_mipi34"), /* uartmod rx */
-       DB8500_PIN_STATE("GPIO76_J2", out_lo,
-               "stm", "mod_mipi34"), /* uartmod tx */
-
-       DB8500_PIN_STATE("GPIO70_G5", slpm_out_lo_pdis,
-               "stm", "mod_mipi34_sleep"), /* clk */
-       DB8500_PIN_STATE("GPIO71_G4", slpm_out_lo_pdis,
-               "stm", "mod_mipi34_sleep"), /* dat3 */
-       DB8500_PIN_STATE("GPIO72_H4", slpm_out_lo_pdis,
-               "stm", "mod_mipi34_sleep"), /* dat2 */
-       DB8500_PIN_STATE("GPIO73_H3", slpm_out_lo_pdis,
-               "stm", "mod_mipi34_sleep"), /* dat1 */
-       DB8500_PIN_STATE("GPIO74_J3", slpm_out_lo_pdis,
-               "stm", "mod_mipi34_sleep"), /* dat0 */
-       DB8500_PIN_STATE("GPIO75_H2", slpm_in_wkup_pdis,
-               "stm", "mod_mipi34_sleep"), /* uartmod rx */
-       DB8500_PIN_STATE("GPIO76_J2", slpm_out_lo_wkup_pdis,
-               "stm", "mod_mipi34_sleep"), /* uartmod tx */
-
-       DB8500_MUX_STATE("stmmod_b_1", "stmmod",
-               "stm", "mod_microsd"),
-       DB8500_MUX_STATE("uartmodrx_oc3_1", "uartmod",
-               "stm", "mod_microsd"),
-       DB8500_MUX_STATE("uartmodtx_oc3_1", "uartmod",
-               "stm", "mod_microsd"),
-       DB8500_PIN_STATE("GPIO23_AA4", in_nopull,
-               "stm", "mod_microsd"), /* clk */
-       DB8500_PIN_STATE("GPIO25_Y4", in_nopull,
-               "stm", "mod_microsd"), /* dat0 */
-       DB8500_PIN_STATE("GPIO26_Y2", in_nopull,
-               "stm", "mod_microsd"), /* dat1 */
-       DB8500_PIN_STATE("GPIO27_AA2", in_nopull,
-               "stm", "mod_microsd"), /* dat2 */
-       DB8500_PIN_STATE("GPIO28_AA1", in_nopull,
-               "stm", "mod_microsd"), /* dat3 */
-       DB8500_PIN_STATE("GPIO75_H2", in_pu,
-               "stm", "mod_microsd"), /* uartmod rx */
-       DB8500_PIN_STATE("GPIO76_J2", out_lo,
-               "stm", "mod_microsd"), /* uartmod tx */
-
-       DB8500_PIN_STATE("GPIO23_AA4", slpm_out_lo_wkup_pdis,
-               "stm", "mod_microsd_sleep"), /* clk */
-       DB8500_PIN_STATE("GPIO25_Y4", slpm_in_wkup_pdis,
-               "stm", "mod_microsd_sleep"), /* dat0 */
-       DB8500_PIN_STATE("GPIO26_Y2", slpm_in_wkup_pdis,
-               "stm", "mod_microsd_sleep"), /* dat1 */
-       DB8500_PIN_STATE("GPIO27_AA2", slpm_in_wkup_pdis,
-               "stm", "mod_microsd_sleep"), /* dat2 */
-       DB8500_PIN_STATE("GPIO28_AA1", slpm_in_wkup_pdis,
-               "stm", "mod_microsd_sleep"), /* dat3 */
-       DB8500_PIN_STATE("GPIO75_H2", slpm_in_wkup_pdis,
-               "stm", "mod_microsd_sleep"), /* uartmod rx */
-       DB8500_PIN_STATE("GPIO76_J2", slpm_out_lo_wkup_pdis,
-               "stm", "mod_microsd_sleep"), /* uartmod tx */
-
-       /*  STM dual Modem/APE pins state */
-       DB8500_MUX_STATE("stmmod_oc3_2", "stmmod",
-               "stm", "mod_mipi34_ape_mipi60"),
-       DB8500_MUX_STATE("stmape_c_2", "stmape",
-               "stm", "mod_mipi34_ape_mipi60"),
-       DB8500_MUX_STATE("uartmodrx_oc3_1", "uartmod",
-               "stm", "mod_mipi34_ape_mipi60"),
-       DB8500_MUX_STATE("uartmodtx_oc3_1", "uartmod",
-               "stm", "mod_mipi34_ape_mipi60"),
-       DB8500_PIN_STATE("GPIO70_G5", in_nopull,
-               "stm", "mod_mipi34_ape_mipi60"), /* clk */
-       DB8500_PIN_STATE("GPIO71_G4", in_nopull,
-               "stm", "mod_mipi34_ape_mipi60"), /* dat3 */
-       DB8500_PIN_STATE("GPIO72_H4", in_nopull,
-               "stm", "mod_mipi34_ape_mipi60"), /* dat2 */
-       DB8500_PIN_STATE("GPIO73_H3", in_nopull,
-               "stm", "mod_mipi34_ape_mipi60"), /* dat1 */
-       DB8500_PIN_STATE("GPIO74_J3", in_nopull,
-               "stm", "mod_mipi34_ape_mipi60"), /* dat0 */
-       DB8500_PIN_STATE("GPIO75_H2", in_pu,
-               "stm", "mod_mipi34_ape_mipi60"), /* uartmod rx */
-       DB8500_PIN_STATE("GPIO76_J2", out_lo,
-               "stm", "mod_mipi34_ape_mipi60"), /* uartmod tx */
-       DB8500_PIN_STATE("GPIO155_C19", in_nopull,
-               "stm", "mod_mipi34_ape_mipi60"), /* clk */
-       DB8500_PIN_STATE("GPIO156_C17", in_nopull,
-               "stm", "mod_mipi34_ape_mipi60"), /* dat3 */
-       DB8500_PIN_STATE("GPIO157_A18", in_nopull,
-               "stm", "mod_mipi34_ape_mipi60"), /* dat2 */
-       DB8500_PIN_STATE("GPIO158_C18", in_nopull,
-               "stm", "mod_mipi34_ape_mipi60"), /* dat1 */
-       DB8500_PIN_STATE("GPIO159_B19", in_nopull,
-               "stm", "mod_mipi34_ape_mipi60"), /* dat0 */
-
-       DB8500_PIN_STATE("GPIO70_G5", slpm_out_lo_pdis,
-               "stm", "mod_mipi34_ape_mipi60_sleep"), /* clk */
-       DB8500_PIN_STATE("GPIO71_G4", slpm_out_lo_pdis,
-               "stm", "mod_mipi34_ape_mipi60_sleep"), /* dat3 */
-       DB8500_PIN_STATE("GPIO72_H4", slpm_out_lo_pdis,
-               "stm", "mod_mipi34_ape_mipi60_sleep"), /* dat2 */
-       DB8500_PIN_STATE("GPIO73_H3", slpm_out_lo_pdis,
-               "stm", "mod_mipi34_ape_mipi60_sleep"), /* dat1 */
-       DB8500_PIN_STATE("GPIO74_J3", slpm_out_lo_pdis,
-               "stm", "mod_mipi34_ape_mipi60_sleep"), /* dat0 */
-       DB8500_PIN_STATE("GPIO75_H2", slpm_in_wkup_pdis,
-               "stm", "mod_mipi34_ape_mipi60_sleep"), /* uartmod rx */
-       DB8500_PIN_STATE("GPIO76_J2", slpm_out_lo_wkup_pdis,
-               "stm", "mod_mipi34_ape_mipi60_sleep"), /* uartmod tx */
-       DB8500_PIN_STATE("GPIO155_C19", slpm_in_wkup_pdis,
-               "stm", "mod_mipi34_ape_mipi60_sleep"), /* clk */
-       DB8500_PIN_STATE("GPIO156_C17", slpm_in_wkup_pdis,
-               "stm", "mod_mipi34_ape_mipi60_sleep"), /* dat3 */
-       DB8500_PIN_STATE("GPIO157_A18", slpm_in_wkup_pdis,
-               "stm", "mod_mipi34_ape_mipi60_sleep"), /* dat2 */
-       DB8500_PIN_STATE("GPIO158_C18", slpm_in_wkup_pdis,
-               "stm", "mod_mipi34_ape_mipi60_sleep"), /* dat1 */
-       DB8500_PIN_STATE("GPIO159_B19", slpm_in_wkup_pdis,
-               "stm", "mod_mipi34_ape_mipi60_sleep"), /* dat0 */
-};
-
-/*
- * These are specifically for the MOP500 and HREFP (pre-v60) version of the
- * board, which utilized a TC35892 GPIO expander instead of using a lot of
- * on-chip pins as the HREFv60 and later does.
- */
-static struct pinctrl_map __initdata mop500_pinmap[] = {
-       /* Mux in SSP0, pull down RXD pin */
-       DB8500_MUX_HOG("ssp0_a_1", "ssp0"),
-       DB8500_PIN_HOG("GPIO145_C13", pd),
-       /*
-        * XENON Flashgun on image processor GPIO (controlled from image
-        * processor firmware), mux in these image processor GPIO lines 0
-        * (XENON_FLASH_ID) and 1 (XENON_READY) on altfunction C and pull up
-        * the pins.
-        */
-       DB8500_MUX_HOG("ipgpio0_c_1", "ipgpio"),
-       DB8500_MUX_HOG("ipgpio1_c_1", "ipgpio"),
-       DB8500_PIN_HOG("GPIO6_AF6", in_pu),
-       DB8500_PIN_HOG("GPIO7_AG5", in_pu),
-       /* TC35892 IRQ, pull up the line, let the driver mux in the pin */
-       DB8500_PIN_HOG("GPIO217_AH12", gpio_in_pu),
-       /* Mux in UART1 and set the pull-ups */
-       DB8500_MUX_HOG("u1rxtx_a_1", "u1"),
-       DB8500_PIN_HOG("GPIO4_AH6", in_pu), /* RXD */
-       DB8500_PIN_HOG("GPIO5_AG6", out_hi), /* TXD */
-       /*
-        * Runtime stuff: make it possible to mux in the SKE keypad
-        * and bias the pins
-        */
-       /* ske default state */
-       DB8500_MUX("kp_a_2", "kp", "nmk-ske-keypad"),
-       DB8500_PIN("GPIO153_B17", in_pu, "nmk-ske-keypad"), /* I7 */
-       DB8500_PIN("GPIO154_C16", in_pu, "nmk-ske-keypad"), /* I6 */
-       DB8500_PIN("GPIO155_C19", in_pu, "nmk-ske-keypad"), /* I5 */
-       DB8500_PIN("GPIO156_C17", in_pu, "nmk-ske-keypad"), /* I4 */
-       DB8500_PIN("GPIO161_D21", in_pu, "nmk-ske-keypad"), /* I3 */
-       DB8500_PIN("GPIO162_D20", in_pu, "nmk-ske-keypad"), /* I2 */
-       DB8500_PIN("GPIO163_C20", in_pu, "nmk-ske-keypad"), /* I1 */
-       DB8500_PIN("GPIO164_B21", in_pu, "nmk-ske-keypad"), /* I0 */
-       DB8500_PIN("GPIO157_A18", out_lo, "nmk-ske-keypad"), /* O7 */
-       DB8500_PIN("GPIO158_C18", out_lo, "nmk-ske-keypad"), /* O6 */
-       DB8500_PIN("GPIO159_B19", out_lo, "nmk-ske-keypad"), /* O5 */
-       DB8500_PIN("GPIO160_B20", out_lo, "nmk-ske-keypad"), /* O4 */
-       DB8500_PIN("GPIO165_C21", out_lo, "nmk-ske-keypad"), /* O3 */
-       DB8500_PIN("GPIO166_A22", out_lo, "nmk-ske-keypad"), /* O2 */
-       DB8500_PIN("GPIO167_B24", out_lo, "nmk-ske-keypad"), /* O1 */
-       DB8500_PIN("GPIO168_C22", out_lo, "nmk-ske-keypad"), /* O0 */
-       /* ske sleep state */
-       DB8500_PIN_SLEEP("GPIO153_B17", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I7 */
-       DB8500_PIN_SLEEP("GPIO154_C16", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I6 */
-       DB8500_PIN_SLEEP("GPIO155_C19", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I5 */
-       DB8500_PIN_SLEEP("GPIO156_C17", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I4 */
-       DB8500_PIN_SLEEP("GPIO161_D21", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I3 */
-       DB8500_PIN_SLEEP("GPIO162_D20", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I2 */
-       DB8500_PIN_SLEEP("GPIO163_C20", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I1 */
-       DB8500_PIN_SLEEP("GPIO164_B21", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I0 */
-       DB8500_PIN_SLEEP("GPIO157_A18", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O7 */
-       DB8500_PIN_SLEEP("GPIO158_C18", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O6 */
-       DB8500_PIN_SLEEP("GPIO159_B19", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O5 */
-       DB8500_PIN_SLEEP("GPIO160_B20", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O4 */
-       DB8500_PIN_SLEEP("GPIO165_C21", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O3 */
-       DB8500_PIN_SLEEP("GPIO166_A22", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O2 */
-       DB8500_PIN_SLEEP("GPIO167_B24", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O1 */
-       DB8500_PIN_SLEEP("GPIO168_C22", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O0 */
-
-       /* Mux in and drive the SDI0 DAT31DIR line high at runtime */
-       DB8500_MUX("mc0dat31dir_a_1", "mc0", "sdi0"),
-       DB8500_PIN("GPIO21_AB3", out_hi, "sdi0"),
-};
-
-/*
- * The HREFv60 series of platforms is using available pins on the DB8500
- * insteaf of the Toshiba I2C GPIO expander, reusing some pins like the SSP0
- * and SSP1 ports (previously connected to the AB8500) as generic GPIO lines.
- */
-static struct pinctrl_map __initdata hrefv60_pinmap[] = {
-       /* Drive WLAN_ENA low */
-       DB8500_PIN_HOG("GPIO85_D5", gpio_out_lo), /* WLAN_ENA */
-       /*
-        * XENON Flashgun on image processor GPIO (controlled from image
-        * processor firmware), mux in these image processor GPIO lines 0
-        * (XENON_FLASH_ID), 1 (XENON_READY) and there is an assistant
-        * LED on IP GPIO 4 (XENON_EN2) on altfunction C, that need bias
-        * from GPIO21 so pull up 0, 1 and drive 4 and GPIO21 low as output.
-        */
-       DB8500_MUX_HOG("ipgpio0_c_1", "ipgpio"),
-       DB8500_MUX_HOG("ipgpio1_c_1", "ipgpio"),
-       DB8500_MUX_HOG("ipgpio4_c_1", "ipgpio"),
-       DB8500_PIN_HOG("GPIO6_AF6", in_pu), /* XENON_FLASH_ID */
-       DB8500_PIN_HOG("GPIO7_AG5", in_pu), /* XENON_READY */
-       DB8500_PIN_HOG("GPIO21_AB3", gpio_out_lo), /* XENON_EN1 */
-       DB8500_PIN_HOG("GPIO64_F3", out_lo), /* XENON_EN2 */
-       /* Magnetometer uses GPIO 31 and 32, pull these up/down respectively */
-       DB8500_PIN_HOG("GPIO31_V3", gpio_in_pu), /* EN1 */
-       DB8500_PIN_HOG("GPIO32_V2", gpio_in_pd), /* DRDY */
-       /*
-        * Display Interface 1 uses GPIO 65 for RST (reset).
-        * Display Interface 2 uses GPIO 66 for RST (reset).
-        * Drive DISP1 reset high (not reset), driver DISP2 reset low (reset)
-        */
-       DB8500_PIN_HOG("GPIO65_F1", gpio_out_hi), /* DISP1 NO RST */
-       DB8500_PIN_HOG("GPIO66_G3", gpio_out_lo), /* DISP2 RST */
-       /*
-        * Touch screen uses GPIO 143 for RST1, GPIO 146 for RST2 and
-        * GPIO 67 for interrupts. Pull-up the IRQ line and drive both
-        * reset signals low.
-        */
-       DB8500_PIN_HOG("GPIO143_D12", gpio_out_lo), /* TOUCH_RST1 */
-       DB8500_PIN_HOG("GPIO67_G2", gpio_in_pu), /* TOUCH_INT2 */
-       DB8500_PIN_HOG("GPIO146_D13", gpio_out_lo), /* TOUCH_RST2 */
-       /*
-        * Drive D19-D23 for the ETM PTM trace interface low,
-        * (presumably pins are unconnected therefore grounded here,
-        * the "other alt C1" setting enables these pins)
-        */
-       DB8500_PIN_HOG("GPIO70_G5", gpio_out_lo),
-       DB8500_PIN_HOG("GPIO71_G4", gpio_out_lo),
-       DB8500_PIN_HOG("GPIO72_H4", gpio_out_lo),
-       DB8500_PIN_HOG("GPIO73_H3", gpio_out_lo),
-       DB8500_PIN_HOG("GPIO74_J3", gpio_out_lo),
-       /* NAHJ CTRL on GPIO 76 to low, CTRL_INV on GPIO216 to high */
-       DB8500_PIN_HOG("GPIO76_J2", gpio_out_lo), /* CTRL */
-       DB8500_PIN_HOG("GPIO216_AG12", gpio_out_hi), /* CTRL_INV */
-       /* NFC ENA and RESET to low, pulldown IRQ line */
-       DB8500_PIN_HOG("GPIO77_H1", gpio_out_lo), /* NFC_ENA */
-       DB8500_PIN_HOG("GPIO144_B13", gpio_in_pd), /* NFC_IRQ */
-       DB8500_PIN_HOG("GPIO142_C11", gpio_out_lo), /* NFC_RESET */
-       /*
-        * SKE keyboard partly on alt A and partly on "Other alt C1"
-        * Driver KP_O1,2,3,6,7 low and pull up KP_I 0,2,3 for three
-        * rows of 6 keys, then pull up force sensing interrup and
-        * drive reset and force sensing WU low.
-        */
-       DB8500_MUX_HOG("kp_a_1", "kp"),
-       DB8500_MUX_HOG("kp_oc1_1", "kp"),
-       DB8500_PIN_HOG("GPIO90_A3", out_lo), /* KP_O1 */
-       DB8500_PIN_HOG("GPIO87_B3", out_lo), /* KP_O2 */
-       DB8500_PIN_HOG("GPIO86_C6", out_lo), /* KP_O3 */
-       DB8500_PIN_HOG("GPIO96_D8", out_lo), /* KP_O6 */
-       DB8500_PIN_HOG("GPIO94_D7", out_lo), /* KP_O7 */
-       DB8500_PIN_HOG("GPIO93_B7", in_pu), /* KP_I0 */
-       DB8500_PIN_HOG("GPIO89_E6", in_pu), /* KP_I2 */
-       DB8500_PIN_HOG("GPIO88_C4", in_pu), /* KP_I3 */
-       DB8500_PIN_HOG("GPIO91_B6", gpio_in_pu), /* FORCE_SENSING_INT */
-       DB8500_PIN_HOG("GPIO92_D6", gpio_out_lo), /* FORCE_SENSING_RST */
-       DB8500_PIN_HOG("GPIO97_D9", gpio_out_lo), /* FORCE_SENSING_WU */
-       /* DiPro Sensor interrupt */
-       DB8500_PIN_HOG("GPIO139_C9", gpio_in_pu), /* DIPRO_INT */
-       /* Audio Amplifier HF enable */
-       DB8500_PIN_HOG("GPIO149_B14", gpio_out_hi), /* VAUDIO_HF_EN, enable MAX8968 */
-       /* GBF interface, pull low to reset state */
-       DB8500_PIN_HOG("GPIO171_D23", gpio_out_lo), /* GBF_ENA_RESET */
-       /* MSP : HDTV INTERFACE GPIO line */
-       DB8500_PIN_HOG("GPIO192_AJ27", gpio_in_pd),
-       /* Accelerometer interrupt lines */
-       DB8500_PIN_HOG("GPIO82_C1", gpio_in_pu), /* ACC_INT1 */
-       DB8500_PIN_HOG("GPIO83_D3", gpio_in_pu), /* ACC_INT2 */
-       /* SD card detect GPIO pin */
-       DB8500_PIN_HOG("GPIO95_E8", gpio_in_pu),
-       /*
-        * Runtime stuff
-        * Pull up/down of some sensor GPIO pins, for proximity, HAL sensor
-        * etc.
-        */
-       DB8500_PIN("GPIO217_AH12", gpio_in_pu_slpm_gpio_nopull, "gpio-keys.0"),
-       DB8500_PIN("GPIO145_C13", gpio_in_pd_slpm_gpio_nopull, "gpio-keys.0"),
-       DB8500_PIN("GPIO139_C9", gpio_in_pu_slpm_gpio_nopull, "gpio-keys.0"),
-};
-
-static struct pinctrl_map __initdata u9500_pinmap[] = {
-       /* Mux in UART1 (just RX/TX) and set the pull-ups */
-       DB8500_MUX_HOG("u1rxtx_a_1", "u1"),
-       DB8500_PIN_HOG("GPIO4_AH6", in_pu),
-       DB8500_PIN_HOG("GPIO5_AG6", out_hi),
-       /* WLAN_IRQ line */
-       DB8500_PIN_HOG("GPIO144_B13", gpio_in_pu),
-       /* HSI */
-       DB8500_MUX_HOG("hsir_a_1", "hsi"),
-       DB8500_MUX_HOG("hsit_a_2", "hsi"),
-       DB8500_PIN_HOG("GPIO219_AG10", in_pd), /* RX FLA0 */
-       DB8500_PIN_HOG("GPIO220_AH10", in_pd), /* RX DAT0 */
-       DB8500_PIN_HOG("GPIO221_AJ11", out_lo), /* RX RDY0 */
-       DB8500_PIN_HOG("GPIO222_AJ9", out_lo), /* TX FLA0 */
-       DB8500_PIN_HOG("GPIO223_AH9", out_lo), /* TX DAT0 */
-       DB8500_PIN_HOG("GPIO224_AG9", in_pd), /* TX RDY0 */
-       DB8500_PIN_HOG("GPIO225_AG8", in_pd), /* CAWAKE0 */
-       DB8500_PIN_HOG("GPIO226_AF8", gpio_out_hi), /* ACWAKE0 */
-};
-
-static struct pinctrl_map __initdata u8500_pinmap[] = {
-       DB8500_PIN_HOG("GPIO226_AF8", gpio_out_lo), /* WLAN_PMU_EN */
-       DB8500_PIN_HOG("GPIO4_AH6", gpio_in_pu), /* WLAN_IRQ */
-};
-
-static struct pinctrl_map __initdata snowball_pinmap[] = {
-       /* Mux in SSP0 connected to AB8500, pull down RXD pin */
-       DB8500_MUX_HOG("ssp0_a_1", "ssp0"),
-       DB8500_PIN_HOG("GPIO145_C13", pd),
-       /* Always drive the MC0 DAT31DIR line high on these boards */
-       DB8500_PIN_HOG("GPIO21_AB3", out_hi),
-       /* Mux in "SM" which is used for the SMSC911x Ethernet adapter */
-       DB8500_MUX_HOG("sm_b_1", "sm"),
-       /* User LED */
-       DB8500_PIN_HOG("GPIO142_C11", gpio_out_hi),
-       /* Drive RSTn_LAN high */
-       DB8500_PIN_HOG("GPIO141_C12", gpio_out_hi),
-       /*  Accelerometer/Magnetometer */
-       DB8500_PIN_HOG("GPIO163_C20", gpio_in_pu), /* ACCEL_IRQ1 */
-       DB8500_PIN_HOG("GPIO164_B21", gpio_in_pu), /* ACCEL_IRQ2 */
-       DB8500_PIN_HOG("GPIO165_C21", gpio_in_pu), /* MAG_DRDY */
-       /* WLAN/GBF */
-       DB8500_PIN_HOG("GPIO161_D21", gpio_out_lo), /* WLAN_PMU_EN */
-       DB8500_PIN_HOG("GPIO171_D23", gpio_out_hi), /* GBF_ENA */
-       DB8500_PIN_HOG("GPIO215_AH13", gpio_out_lo), /* WLAN_ENA */
-       DB8500_PIN_HOG("GPIO216_AG12", gpio_in_pu), /* WLAN_IRQ */
-};
-
-/*
- * passing "pinsfor=" in kernel cmdline allows for custom
- * configuration of GPIOs on u8500 derived boards.
- */
-static int __init early_pinsfor(char *p)
-{
-       pinsfor = PINS_FOR_DEFAULT;
-
-       if (strcmp(p, "u9500-21") == 0)
-               pinsfor = PINS_FOR_U9500;
-
-       return 0;
-}
-early_param("pinsfor", early_pinsfor);
-
-int pins_for_u9500(void)
-{
-       if (pinsfor == PINS_FOR_U9500)
-               return 1;
-
-       return 0;
-}
-
-static void __init mop500_href_family_pinmaps_init(void)
-{
-       switch (pinsfor) {
-       case PINS_FOR_U9500:
-               pinctrl_register_mappings(u9500_pinmap,
-                                         ARRAY_SIZE(u9500_pinmap));
-               break;
-       case PINS_FOR_DEFAULT:
-               pinctrl_register_mappings(u8500_pinmap,
-                                         ARRAY_SIZE(u8500_pinmap));
-       default:
-               break;
-       }
-}
-
 void __init mop500_pinmaps_init(void)
 {
-       pinctrl_register_mappings(mop500_family_pinmap,
-                                 ARRAY_SIZE(mop500_family_pinmap));
-       pinctrl_register_mappings(mop500_pinmap,
-                                 ARRAY_SIZE(mop500_pinmap));
-       mop500_href_family_pinmaps_init();
        if (machine_is_u8520())
                pinctrl_register_mappings(ab8505_pinmap,
                                          ARRAY_SIZE(ab8505_pinmap));
@@ -1073,23 +280,12 @@ void __init mop500_pinmaps_init(void)
 
 void __init snowball_pinmaps_init(void)
 {
-       pinctrl_register_mappings(mop500_family_pinmap,
-                                 ARRAY_SIZE(mop500_family_pinmap));
-       pinctrl_register_mappings(snowball_pinmap,
-                                 ARRAY_SIZE(snowball_pinmap));
-       pinctrl_register_mappings(u8500_pinmap,
-                                 ARRAY_SIZE(u8500_pinmap));
        pinctrl_register_mappings(ab8500_pinmap,
                                  ARRAY_SIZE(ab8500_pinmap));
 }
 
 void __init hrefv60_pinmaps_init(void)
 {
-       pinctrl_register_mappings(mop500_family_pinmap,
-                                 ARRAY_SIZE(mop500_family_pinmap));
-       pinctrl_register_mappings(hrefv60_pinmap,
-                                 ARRAY_SIZE(hrefv60_pinmap));
-       mop500_href_family_pinmaps_init();
        pinctrl_register_mappings(ab8500_pinmap,
                                  ARRAY_SIZE(ab8500_pinmap));
 }
index 26600a1c53190ad3ae3724456a17dd7b8a35009d..fcbf3a13a5392235a9343fb44b66f2891bdb38c4 100644 (file)
 #include <linux/platform_data/dma-ste-dma40.h>
 
 #include <asm/mach-types.h>
-#include "devices.h"
 
 #include "db8500-regs.h"
-#include "devices-db8500.h"
 #include "board-mop500.h"
 #include "ste-dma40-db8500.h"
 
diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c
deleted file mode 100644 (file)
index 514d40b..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2008-2012 ST-Ericsson
- *
- * Author: Srinidhi KASAGAR <srinidhi.kasagar@stericsson.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/kernel.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/platform_data/db8500_thermal.h>
-#include <linux/amba/bus.h>
-#include <linux/amba/pl022.h>
-#include <linux/mfd/abx500/ab8500.h>
-#include <linux/regulator/ab8500.h>
-#include <linux/regulator/fixed.h>
-#include <linux/regulator/driver.h>
-#include <linux/mfd/tps6105x.h>
-#include <linux/platform_data/leds-lp55xx.h>
-#include <linux/input.h>
-#include <linux/delay.h>
-#include <linux/leds.h>
-#include <linux/pinctrl/consumer.h>
-#include <linux/platform_data/pinctrl-nomadik.h>
-#include <linux/platform_data/dma-ste-dma40.h>
-
-#include <asm/mach-types.h>
-
-#include "setup.h"
-#include "devices.h"
-#include "irqs.h"
-
-#include "ste-dma40-db8500.h"
-#include "db8500-regs.h"
-#include "devices-db8500.h"
-#include "board-mop500.h"
-#include "board-mop500-regulators.h"
-
-struct ab8500_platform_data ab8500_platdata = {
-       .irq_base       = MOP500_AB8500_IRQ_BASE,
-       .regulator      = &ab8500_regulator_plat_data,
-};
-
-#ifdef CONFIG_STE_DMA40
-static struct stedma40_chan_cfg ssp0_dma_cfg_rx = {
-       .mode = STEDMA40_MODE_LOGICAL,
-       .dir = DMA_DEV_TO_MEM,
-       .dev_type = DB8500_DMA_DEV8_SSP0,
-};
-
-static struct stedma40_chan_cfg ssp0_dma_cfg_tx = {
-       .mode = STEDMA40_MODE_LOGICAL,
-       .dir = DMA_MEM_TO_DEV,
-       .dev_type = DB8500_DMA_DEV8_SSP0,
-};
-#endif
-
-struct pl022_ssp_controller ssp0_plat = {
-       .bus_id = 0,
-#ifdef CONFIG_STE_DMA40
-       .enable_dma = 1,
-       .dma_filter = stedma40_filter,
-       .dma_rx_param = &ssp0_dma_cfg_rx,
-       .dma_tx_param = &ssp0_dma_cfg_tx,
-#else
-       .enable_dma = 0,
-#endif
-       /* on this platform, gpio 31,142,144,214 &
-        * 224 are connected as chip selects
-        */
-       .num_chipselect = 5,
-};
index 511d6febbe9996ac7f4831ba6d878435765c2869..d48e8662c6763eb8a45bfd72752ab7509e0e9a5a 100644 (file)
@@ -87,7 +87,6 @@ extern struct msp_i2s_platform_data msp0_platform_data;
 extern struct msp_i2s_platform_data msp1_platform_data;
 extern struct msp_i2s_platform_data msp2_platform_data;
 extern struct msp_i2s_platform_data msp3_platform_data;
-extern struct pl022_ssp_controller ssp0_plat;
 
 void __init mop500_pinmaps_init(void);
 void __init snowball_pinmaps_init(void);
index 2e85c1e72535138a1b90c543ec3e95e2b36a6fa6..d8f5ce430fa723db4b528274dc0010fb20c903ce 100644 (file)
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/regulator/machine.h>
-#include <linux/platform_data/pinctrl-nomadik.h>
 #include <linux/random.h>
 
 #include <asm/pmu.h>
 #include <asm/mach/map.h>
 
 #include "setup.h"
-#include "devices.h"
 #include "irqs.h"
 
-#include "devices-db8500.h"
-#include "db8500-regs.h"
+#include "board-mop500-regulators.h"
 #include "board-mop500.h"
+#include "db8500-regs.h"
 #include "id.h"
 
+struct ab8500_platform_data ab8500_platdata = {
+       .irq_base       = MOP500_AB8500_IRQ_BASE,
+       .regulator      = &ab8500_regulator_plat_data,
+};
+
+struct prcmu_pdata db8500_prcmu_pdata = {
+       .ab_platdata    = &ab8500_platdata,
+       .ab_irq         = IRQ_DB8500_AB8500,
+       .irq_base       = IRQ_PRCMU_BASE,
+       .version_offset = DB8500_PRCMU_FW_VERSION_OFFSET,
+       .legacy_offset  = DB8500_PRCMU_LEGACY_OFFSET,
+};
+
 /* minimum static i/o mapping required to boot U8500 platforms */
 static struct map_desc u8500_uart_io_desc[] __initdata = {
        __IO_DEV_DESC(U8500_UART0_BASE, SZ_4K),
@@ -140,6 +151,10 @@ static struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = {
        /* Requires call-back bindings. */
        OF_DEV_AUXDATA("arm,cortex-a9-pmu", 0, "arm-pmu", &db8500_pmu_platdata),
        /* Requires DMA bindings. */
+       OF_DEV_AUXDATA("arm,pl18x", 0x80126000, "sdi0",  &mop500_sdi0_data),
+       OF_DEV_AUXDATA("arm,pl18x", 0x80118000, "sdi1",  &mop500_sdi1_data),
+       OF_DEV_AUXDATA("arm,pl18x", 0x80005000, "sdi2",  &mop500_sdi2_data),
+       OF_DEV_AUXDATA("arm,pl18x", 0x80114000, "sdi4",  &mop500_sdi4_data),
        OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80123000,
                       "ux500-msp-i2s.0", &msp0_platform_data),
        OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80124000,
@@ -155,9 +170,6 @@ static struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = {
        OF_DEV_AUXDATA("stericsson,ux500-hash", 0xa03c2000, "hash1", NULL),
        OF_DEV_AUXDATA("stericsson,snd-soc-mop500", 0, "snd-soc-mop500.0",
                        NULL),
-       /* Requires device name bindings. */
-       OF_DEV_AUXDATA("stericsson,db8500-pinctrl", U8500_PRCMU_BASE,
-               "pinctrl-db8500", NULL),
        {},
 };
 
index f84d4397896b39705e0227dac27555542c1d9cc0..d11ac4bf336cb7352ac34ee079fc560a800e036e 100644 (file)
@@ -25,7 +25,6 @@
 #include <asm/mach/map.h>
 
 #include "setup.h"
-#include "devices.h"
 
 #include "board-mop500.h"
 #include "db8500-regs.h"
@@ -64,12 +63,7 @@ void __init ux500_init_irq(void)
        } else
                ux500_unknown_soc();
 
-#ifdef CONFIG_OF
-       if (of_have_populated_dt())
-               irqchip_init();
-       else
-#endif
-               gic_init(0, 29, dist_base, cpu_base);
+       irqchip_init();
 
        /*
         * Init clocks here so that they are available for system timer
@@ -79,16 +73,11 @@ void __init ux500_init_irq(void)
                prcmu_early_init(U8500_PRCMU_BASE, SZ_8K - 1);
                ux500_pm_init(U8500_PRCMU_BASE, SZ_8K - 1);
 
-               if (of_have_populated_dt())
-                       u8500_of_clk_init(U8500_CLKRST1_BASE,
-                                         U8500_CLKRST2_BASE,
-                                         U8500_CLKRST3_BASE,
-                                         U8500_CLKRST5_BASE,
-                                         U8500_CLKRST6_BASE);
-               else
-                       u8500_clk_init(U8500_CLKRST1_BASE, U8500_CLKRST2_BASE,
-                                      U8500_CLKRST3_BASE, U8500_CLKRST5_BASE,
-                                      U8500_CLKRST6_BASE);
+               u8500_of_clk_init(U8500_CLKRST1_BASE,
+                                 U8500_CLKRST2_BASE,
+                                 U8500_CLKRST3_BASE,
+                                 U8500_CLKRST5_BASE,
+                                 U8500_CLKRST6_BASE);
        } else if (cpu_is_u9540()) {
                prcmu_early_init(U8500_PRCMU_BASE, SZ_8K - 1);
                ux500_pm_init(U8500_PRCMU_BASE, SZ_8K - 1);
diff --git a/arch/arm/mach-ux500/devices-db8500.c b/arch/arm/mach-ux500/devices-db8500.c
deleted file mode 100644 (file)
index c59f89d..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
- * License terms: GNU General Public License (GPL) version 2
- */
-
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/amba/bus.h>
-#include <linux/amba/pl022.h>
-#include <linux/mfd/dbx500-prcmu.h>
-
-#include "setup.h"
-#include "irqs.h"
-
-#include "db8500-regs.h"
-#include "devices-db8500.h"
-
-struct prcmu_pdata db8500_prcmu_pdata = {
-       .ab_platdata    = &ab8500_platdata,
-       .ab_irq         = IRQ_DB8500_AB8500,
-       .irq_base       = IRQ_PRCMU_BASE,
-       .version_offset = DB8500_PRCMU_FW_VERSION_OFFSET,
-       .legacy_offset  = DB8500_PRCMU_LEGACY_OFFSET,
-};
diff --git a/arch/arm/mach-ux500/devices-db8500.h b/arch/arm/mach-ux500/devices-db8500.h
deleted file mode 100644 (file)
index b8ffc99..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
- * License terms: GNU General Public License (GPL), version 2.
- */
-
-#ifndef __DEVICES_DB8500_H
-#define __DEVICES_DB8500_H
-
-#include "irqs.h"
-#include "db8500-regs.h"
-
-struct platform_device;
-
-extern struct ab8500_platform_data ab8500_platdata;
-extern struct prcmu_pdata db8500_prcmu_pdata;
-
-#endif
diff --git a/arch/arm/mach-ux500/devices.c b/arch/arm/mach-ux500/devices.c
deleted file mode 100644 (file)
index 0f9e52b..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
- * License terms: GNU General Public License (GPL) version 2
- */
-
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/amba/bus.h>
-
-#include "setup.h"
-
-#include "db8500-regs.h"
-
-void __init amba_add_devices(struct amba_device *devs[], int num)
-{
-       int i;
-
-       for (i = 0; i < num; i++) {
-               struct amba_device *d = devs[i];
-               amba_device_register(d, &iomem_resource);
-       }
-}
diff --git a/arch/arm/mach-ux500/devices.h b/arch/arm/mach-ux500/devices.h
deleted file mode 100644 (file)
index 5bca7c6..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * License terms: GNU General Public License (GPL) version 2
- */
-
-#ifndef __ASM_ARCH_DEVICES_H__
-#define __ASM_ARCH_DEVICES_H__
-
-struct platform_device;
-struct amba_device;
-
-extern struct amba_device ux500_pl031_device;
-
-#endif
index bdb356498a748563091d7563525db015500dbfc1..2dea8b59d2220e1bacf274bdf7c75c010bbf8728 100644 (file)
 void ux500_restart(enum reboot_mode mode, const char *cmd);
 
 void __init ux500_map_io(void);
-extern void __init u8500_map_io(void);
-
-extern struct device * __init u8500_init_devices(void);
 
 extern void __init ux500_init_irq(void);
 
 extern struct device *ux500_soc_device_init(const char *soc_id);
 
-struct amba_device;
-extern void __init amba_add_devices(struct amba_device *devs[], int num);
-
 extern void ux500_timer_init(void);
 
 #define __IO_DEV_DESC(x, sz)   {               \
@@ -43,7 +37,7 @@ extern void ux500_timer_init(void);
        .virtual        = IO_ADDRESS(x),        \
        .pfn            = __phys_to_pfn(x),     \
        .length         = sz,                   \
-       .type           = MT_MEMORY,            \
+       .type           = MT_MEMORY_RWX,                \
 }
 
 extern struct smp_operations ux500_smp_ops;
index 05a4ff78b3bd9e73deaf4c0e814f79cdae8e971e..87efda0aa348fc5c9165047cde0163195818d76a 100644 (file)
 #include <linux/clocksource.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
-#include <linux/platform_data/clocksource-nomadik-mtu.h>
-
-#include <asm/smp_twd.h>
 
 #include "setup.h"
-#include "irqs.h"
 
 #include "db8500-regs.h"
 #include "id.h"
 
-#ifdef CONFIG_HAVE_ARM_TWD
-static DEFINE_TWD_LOCAL_TIMER(u8500_twd_local_timer,
-                             U8500_TWD_BASE, IRQ_LOCALTIMER);
-
-static void __init ux500_twd_init(void)
-{
-       struct twd_local_timer *twd_local_timer;
-       int err;
-
-       /* Use this to switch local timer base if changed in new ASICs */
-       twd_local_timer = &u8500_twd_local_timer;
-
-       if (of_have_populated_dt())
-               clocksource_of_init();
-       else {
-               err = twd_local_timer_register(twd_local_timer);
-               if (err)
-                       pr_err("twd_local_timer_register failed %d\n", err);
-       }
-}
-#else
-#define ux500_twd_init()       do { } while(0)
-#endif
-
 const static struct of_device_id prcmu_timer_of_match[] __initconst = {
        { .compatible = "stericsson,db8500-prcmu-timer-4", },
        { },
@@ -51,54 +23,26 @@ const static struct of_device_id prcmu_timer_of_match[] __initconst = {
 
 void __init ux500_timer_init(void)
 {
-       void __iomem *mtu_timer_base;
        void __iomem *prcmu_timer_base;
        void __iomem *tmp_base;
        struct device_node *np;
 
-       if (cpu_is_u8500_family() || cpu_is_ux540_family()) {
-               mtu_timer_base = __io_address(U8500_MTU0_BASE);
+       if (cpu_is_u8500_family() || cpu_is_ux540_family())
                prcmu_timer_base = __io_address(U8500_PRCMU_TIMER_4_BASE);
-       } else {
+       else
                ux500_unknown_soc();
-       }
 
-       /* TODO: Once MTU has been DT:ed place code above into else. */
-       if (of_have_populated_dt()) {
-#ifdef CONFIG_OF
-               np = of_find_matching_node(NULL, prcmu_timer_of_match);
-               if (!np)
-#endif
-                       goto dt_fail;
+       np = of_find_matching_node(NULL, prcmu_timer_of_match);
+       if (!np)
+               goto dt_fail;
 
-               tmp_base = of_iomap(np, 0);
-               if (!tmp_base)
-                       goto dt_fail;
+       tmp_base = of_iomap(np, 0);
+       if (!tmp_base)
+               goto dt_fail;
 
-               prcmu_timer_base = tmp_base;
-       }
+       prcmu_timer_base = tmp_base;
 
 dt_fail:
-       /* Doing it the old fashioned way. */
-
-       /*
-        * Here we register the timerblocks active in the system.
-        * Localtimers (twd) is started when both cpu is up and running.
-        * MTU register a clocksource, clockevent and sched_clock.
-        * Since the MTU is located in the VAPE power domain
-        * it will be cleared in sleep which makes it unsuitable.
-        * We however need it as a timer tick (clockevent)
-        * during boot to calibrate delay until twd is started.
-        * RTC-RTT have problems as timer tick during boot since it is
-        * depending on delay which is not yet calibrated. RTC-RTT is in the
-        * always-on powerdomain and is used as clockevent instead of twd when
-        * sleeping.
-        * The PRCMU timer 4 register a clocksource and
-        * sched_clock with higher rating then MTU since is always-on.
-        *
-        */
-       if (!of_have_populated_dt())
-               nmdk_timer_init(mtu_timer_base, IRQ_MTU0);
        clksrc_dbx500_prcmu_init(prcmu_timer_base);
-       ux500_twd_init();
+       clocksource_of_init();
 }
index ecfe6e53f6e03ffe7a12bf0776b784106f7efe19..7f39ce2f841fb1f9056269c1a8ce415b89a21191 100644 (file)
@@ -12,6 +12,7 @@ ifneq ($(CONFIG_MMU),y)
 obj-y                          += nommu.o
 endif
 
+obj-$(CONFIG_ARM_PTDUMP)       += dump.o
 obj-$(CONFIG_MODULES)          += proc-syms.o
 
 obj-$(CONFIG_ALIGNMENT_TRAP)   += alignment.o
index b5c467a65c271a8c8538defc2880b0689067d046..778bcf88ee798b4104f35fef3ed1d6fc933f3392 100644 (file)
@@ -146,18 +146,18 @@ flush_levels:
        ldr     r7, =0x7fff
        ands    r7, r7, r1, lsr #13             @ extract max number of the index size
 loop1:
-       mov     r9, r4                          @ create working copy of max way size
+       mov     r9, r7                          @ create working copy of max index
 loop2:
- ARM(  orr     r11, r10, r9, lsl r5    )       @ factor way and cache number into r11
- THUMB(        lsl     r6, r9, r5              )
+ ARM(  orr     r11, r10, r4, lsl r5    )       @ factor way and cache number into r11
+ THUMB(        lsl     r6, r4, r5              )
  THUMB(        orr     r11, r10, r6            )       @ factor way and cache number into r11
- ARM(  orr     r11, r11, r7, lsl r2    )       @ factor index number into r11
- THUMB(        lsl     r6, r7, r2              )
+ ARM(  orr     r11, r11, r9, lsl r2    )       @ factor index number into r11
+ THUMB(        lsl     r6, r9, r2              )
  THUMB(        orr     r11, r11, r6            )       @ factor index number into r11
        mcr     p15, 0, r11, c7, c14, 2         @ clean & invalidate by set/way
-       subs    r9, r9, #1                      @ decrement the way
+       subs    r9, r9, #1                      @ decrement the index
        bge     loop2
-       subs    r7, r7, #1                      @ decrement the index
+       subs    r4, r4, #1                      @ decrement the way
        bge     loop1
 skip:
        add     r10, r10, #2                    @ increment cache number
index 79f8b39801a8e570bd86ea80e566ee939bbb600b..1a77450e728ad17cf6b8fec2beb3111a2a8bfb94 100644 (file)
@@ -9,6 +9,7 @@
  *
  *  DMA uncached mapping support.
  */
+#include <linux/bootmem.h>
 #include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/gfp.h>
@@ -157,6 +158,44 @@ struct dma_map_ops arm_coherent_dma_ops = {
 };
 EXPORT_SYMBOL(arm_coherent_dma_ops);
 
+static int __dma_supported(struct device *dev, u64 mask, bool warn)
+{
+       unsigned long max_dma_pfn;
+
+       /*
+        * If the mask allows for more memory than we can address,
+        * and we actually have that much memory, then we must
+        * indicate that DMA to this device is not supported.
+        */
+       if (sizeof(mask) != sizeof(dma_addr_t) &&
+           mask > (dma_addr_t)~0 &&
+           dma_to_pfn(dev, ~0) < max_pfn) {
+               if (warn) {
+                       dev_warn(dev, "Coherent DMA mask %#llx is larger than dma_addr_t allows\n",
+                                mask);
+                       dev_warn(dev, "Driver did not use or check the return value from dma_set_coherent_mask()?\n");
+               }
+               return 0;
+       }
+
+       max_dma_pfn = min(max_pfn, arm_dma_pfn_limit);
+
+       /*
+        * Translate the device's DMA mask to a PFN limit.  This
+        * PFN number includes the page which we can DMA to.
+        */
+       if (dma_to_pfn(dev, mask) < max_dma_pfn) {
+               if (warn)
+                       dev_warn(dev, "Coherent DMA mask %#llx (pfn %#lx-%#lx) covers a smaller range of system memory than the DMA zone pfn 0x0-%#lx\n",
+                                mask,
+                                dma_to_pfn(dev, 0), dma_to_pfn(dev, mask) + 1,
+                                max_dma_pfn + 1);
+               return 0;
+       }
+
+       return 1;
+}
+
 static u64 get_coherent_dma_mask(struct device *dev)
 {
        u64 mask = (u64)DMA_BIT_MASK(32);
@@ -173,32 +212,8 @@ static u64 get_coherent_dma_mask(struct device *dev)
                        return 0;
                }
 
-               /*
-                * If the mask allows for more memory than we can address,
-                * and we actually have that much memory, then fail the
-                * allocation.
-                */
-               if (sizeof(mask) != sizeof(dma_addr_t) &&
-                   mask > (dma_addr_t)~0 &&
-                   dma_to_pfn(dev, ~0) > arm_dma_pfn_limit) {
-                       dev_warn(dev, "Coherent DMA mask %#llx is larger than dma_addr_t allows\n",
-                                mask);
-                       dev_warn(dev, "Driver did not use or check the return value from dma_set_coherent_mask()?\n");
-                       return 0;
-               }
-
-               /*
-                * Now check that the mask, when translated to a PFN,
-                * fits within the allowable addresses which we can
-                * allocate.
-                */
-               if (dma_to_pfn(dev, mask) < arm_dma_pfn_limit) {
-                       dev_warn(dev, "Coherent DMA mask %#llx (pfn %#lx-%#lx) covers a smaller range of system memory than the DMA zone pfn 0x0-%#lx\n",
-                                mask,
-                                dma_to_pfn(dev, 0), dma_to_pfn(dev, mask) + 1,
-                                arm_dma_pfn_limit + 1);
+               if (!__dma_supported(dev, mask, true))
                        return 0;
-               }
        }
 
        return mask;
@@ -361,7 +376,7 @@ void __init init_dma_coherent_pool_size(unsigned long size)
 static int __init atomic_pool_init(void)
 {
        struct dma_pool *pool = &atomic_pool;
-       pgprot_t prot = pgprot_dmacoherent(pgprot_kernel);
+       pgprot_t prot = pgprot_dmacoherent(PAGE_KERNEL);
        gfp_t gfp = GFP_KERNEL | GFP_DMA;
        unsigned long nr_pages = pool->size >> PAGE_SHIFT;
        unsigned long *bitmap;
@@ -609,7 +624,7 @@ static void __free_from_contiguous(struct device *dev, struct page *page,
        if (PageHighMem(page))
                __dma_free_remap(cpu_addr, size);
        else
-               __dma_remap(page, size, pgprot_kernel);
+               __dma_remap(page, size, PAGE_KERNEL);
        dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT);
 }
 
@@ -1027,28 +1042,7 @@ void arm_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
  */
 int dma_supported(struct device *dev, u64 mask)
 {
-       unsigned long limit;
-
-       /*
-        * If the mask allows for more memory than we can address,
-        * and we actually have that much memory, then we must
-        * indicate that DMA to this device is not supported.
-        */
-       if (sizeof(mask) != sizeof(dma_addr_t) &&
-           mask > (dma_addr_t)~0 &&
-           dma_to_pfn(dev, ~0) > arm_dma_pfn_limit)
-               return 0;
-
-       /*
-        * Translate the device's DMA mask to a PFN limit.  This
-        * PFN number includes the page which we can DMA to.
-        */
-       limit = dma_to_pfn(dev, mask);
-
-       if (limit < arm_dma_pfn_limit)
-               return 0;
-
-       return 1;
+       return __dma_supported(dev, mask, false);
 }
 EXPORT_SYMBOL(dma_supported);
 
@@ -1357,7 +1351,7 @@ static void __iommu_free_atomic(struct device *dev, void *cpu_addr,
 static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
            dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs)
 {
-       pgprot_t prot = __get_dma_pgprot(attrs, pgprot_kernel);
+       pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL);
        struct page **pages;
        void *addr = NULL;
 
diff --git a/arch/arm/mm/dump.c b/arch/arm/mm/dump.c
new file mode 100644 (file)
index 0000000..4e76d9b
--- /dev/null
@@ -0,0 +1,345 @@
+/*
+ * Debug helper to dump the current kernel pagetables of the system
+ * so that we can see what the various memory ranges are set to.
+ *
+ * Derived from x86 implementation:
+ * (C) Copyright 2008 Intel Corporation
+ *
+ * Author: Arjan van de Ven <arjan@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+#include <linux/debugfs.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/seq_file.h>
+
+#include <asm/fixmap.h>
+#include <asm/pgtable.h>
+
+struct addr_marker {
+       unsigned long start_address;
+       const char *name;
+};
+
+static struct addr_marker address_markers[] = {
+       { MODULES_VADDR,        "Modules" },
+       { PAGE_OFFSET,          "Kernel Mapping" },
+       { 0,                    "vmalloc() Area" },
+       { VMALLOC_END,          "vmalloc() End" },
+       { FIXADDR_START,        "Fixmap Area" },
+       { CONFIG_VECTORS_BASE,  "Vectors" },
+       { CONFIG_VECTORS_BASE + PAGE_SIZE * 2, "Vectors End" },
+       { -1,                   NULL },
+};
+
+struct pg_state {
+       struct seq_file *seq;
+       const struct addr_marker *marker;
+       unsigned long start_address;
+       unsigned level;
+       u64 current_prot;
+};
+
+struct prot_bits {
+       u64             mask;
+       u64             val;
+       const char      *set;
+       const char      *clear;
+};
+
+static const struct prot_bits pte_bits[] = {
+       {
+               .mask   = L_PTE_USER,
+               .val    = L_PTE_USER,
+               .set    = "USR",
+               .clear  = "   ",
+       }, {
+               .mask   = L_PTE_RDONLY,
+               .val    = L_PTE_RDONLY,
+               .set    = "ro",
+               .clear  = "RW",
+       }, {
+               .mask   = L_PTE_XN,
+               .val    = L_PTE_XN,
+               .set    = "NX",
+               .clear  = "x ",
+       }, {
+               .mask   = L_PTE_SHARED,
+               .val    = L_PTE_SHARED,
+               .set    = "SHD",
+               .clear  = "   ",
+       }, {
+               .mask   = L_PTE_MT_MASK,
+               .val    = L_PTE_MT_UNCACHED,
+               .set    = "SO/UNCACHED",
+       }, {
+               .mask   = L_PTE_MT_MASK,
+               .val    = L_PTE_MT_BUFFERABLE,
+               .set    = "MEM/BUFFERABLE/WC",
+       }, {
+               .mask   = L_PTE_MT_MASK,
+               .val    = L_PTE_MT_WRITETHROUGH,
+               .set    = "MEM/CACHED/WT",
+       }, {
+               .mask   = L_PTE_MT_MASK,
+               .val    = L_PTE_MT_WRITEBACK,
+               .set    = "MEM/CACHED/WBRA",
+#ifndef CONFIG_LPAE
+       }, {
+               .mask   = L_PTE_MT_MASK,
+               .val    = L_PTE_MT_MINICACHE,
+               .set    = "MEM/MINICACHE",
+#endif
+       }, {
+               .mask   = L_PTE_MT_MASK,
+               .val    = L_PTE_MT_WRITEALLOC,
+               .set    = "MEM/CACHED/WBWA",
+       }, {
+               .mask   = L_PTE_MT_MASK,
+               .val    = L_PTE_MT_DEV_SHARED,
+               .set    = "DEV/SHARED",
+#ifndef CONFIG_LPAE
+       }, {
+               .mask   = L_PTE_MT_MASK,
+               .val    = L_PTE_MT_DEV_NONSHARED,
+               .set    = "DEV/NONSHARED",
+#endif
+       }, {
+               .mask   = L_PTE_MT_MASK,
+               .val    = L_PTE_MT_DEV_WC,
+               .set    = "DEV/WC",
+       }, {
+               .mask   = L_PTE_MT_MASK,
+               .val    = L_PTE_MT_DEV_CACHED,
+               .set    = "DEV/CACHED",
+       },
+};
+
+static const struct prot_bits section_bits[] = {
+#ifndef CONFIG_LPAE
+       /* These are approximate */
+       {
+               .mask   = PMD_SECT_AP_READ | PMD_SECT_AP_WRITE,
+               .val    = 0,
+               .set    = "    ro",
+       }, {
+               .mask   = PMD_SECT_AP_READ | PMD_SECT_AP_WRITE,
+               .val    = PMD_SECT_AP_WRITE,
+               .set    = "    RW",
+       }, {
+               .mask   = PMD_SECT_AP_READ | PMD_SECT_AP_WRITE,
+               .val    = PMD_SECT_AP_READ,
+               .set    = "USR ro",
+       }, {
+               .mask   = PMD_SECT_AP_READ | PMD_SECT_AP_WRITE,
+               .val    = PMD_SECT_AP_READ | PMD_SECT_AP_WRITE,
+               .set    = "USR RW",
+#else
+       {
+               .mask   = PMD_SECT_USER,
+               .val    = PMD_SECT_USER,
+               .set    = "USR",
+       }, {
+               .mask   = PMD_SECT_RDONLY,
+               .val    = PMD_SECT_RDONLY,
+               .set    = "ro",
+               .clear  = "RW",
+#endif
+       }, {
+               .mask   = PMD_SECT_XN,
+               .val    = PMD_SECT_XN,
+               .set    = "NX",
+               .clear  = "x ",
+       }, {
+               .mask   = PMD_SECT_S,
+               .val    = PMD_SECT_S,
+               .set    = "SHD",
+               .clear  = "   ",
+       },
+};
+
+struct pg_level {
+       const struct prot_bits *bits;
+       size_t num;
+       u64 mask;
+};
+
+static struct pg_level pg_level[] = {
+       {
+       }, { /* pgd */
+       }, { /* pud */
+       }, { /* pmd */
+               .bits   = section_bits,
+               .num    = ARRAY_SIZE(section_bits),
+       }, { /* pte */
+               .bits   = pte_bits,
+               .num    = ARRAY_SIZE(pte_bits),
+       },
+};
+
+static void dump_prot(struct pg_state *st, const struct prot_bits *bits, size_t num)
+{
+       unsigned i;
+
+       for (i = 0; i < num; i++, bits++) {
+               const char *s;
+
+               if ((st->current_prot & bits->mask) == bits->val)
+                       s = bits->set;
+               else
+                       s = bits->clear;
+
+               if (s)
+                       seq_printf(st->seq, " %s", s);
+       }
+}
+
+static void note_page(struct pg_state *st, unsigned long addr, unsigned level, u64 val)
+{
+       static const char units[] = "KMGTPE";
+       u64 prot = val & pg_level[level].mask;
+
+       if (addr < USER_PGTABLES_CEILING)
+               return;
+
+       if (!st->level) {
+               st->level = level;
+               st->current_prot = prot;
+               seq_printf(st->seq, "---[ %s ]---\n", st->marker->name);
+       } else if (prot != st->current_prot || level != st->level ||
+                  addr >= st->marker[1].start_address) {
+               const char *unit = units;
+               unsigned long delta;
+
+               if (st->current_prot) {
+                       seq_printf(st->seq, "0x%08lx-0x%08lx   ",
+                                  st->start_address, addr);
+
+                       delta = (addr - st->start_address) >> 10;
+                       while (!(delta & 1023) && unit[1]) {
+                               delta >>= 10;
+                               unit++;
+                       }
+                       seq_printf(st->seq, "%9lu%c", delta, *unit);
+                       if (pg_level[st->level].bits)
+                               dump_prot(st, pg_level[st->level].bits, pg_level[st->level].num);
+                       seq_printf(st->seq, "\n");
+               }
+
+               if (addr >= st->marker[1].start_address) {
+                       st->marker++;
+                       seq_printf(st->seq, "---[ %s ]---\n", st->marker->name);
+               }
+               st->start_address = addr;
+               st->current_prot = prot;
+               st->level = level;
+       }
+}
+
+static void walk_pte(struct pg_state *st, pmd_t *pmd, unsigned long start)
+{
+       pte_t *pte = pte_offset_kernel(pmd, 0);
+       unsigned long addr;
+       unsigned i;
+
+       for (i = 0; i < PTRS_PER_PTE; i++, pte++) {
+               addr = start + i * PAGE_SIZE;
+               note_page(st, addr, 4, pte_val(*pte));
+       }
+}
+
+static void walk_pmd(struct pg_state *st, pud_t *pud, unsigned long start)
+{
+       pmd_t *pmd = pmd_offset(pud, 0);
+       unsigned long addr;
+       unsigned i;
+
+       for (i = 0; i < PTRS_PER_PMD; i++, pmd++) {
+               addr = start + i * PMD_SIZE;
+               if (pmd_none(*pmd) || pmd_large(*pmd) || !pmd_present(*pmd))
+                       note_page(st, addr, 3, pmd_val(*pmd));
+               else
+                       walk_pte(st, pmd, addr);
+       }
+}
+
+static void walk_pud(struct pg_state *st, pgd_t *pgd, unsigned long start)
+{
+       pud_t *pud = pud_offset(pgd, 0);
+       unsigned long addr;
+       unsigned i;
+
+       for (i = 0; i < PTRS_PER_PUD; i++, pud++) {
+               addr = start + i * PUD_SIZE;
+               if (!pud_none(*pud)) {
+                       walk_pmd(st, pud, addr);
+               } else {
+                       note_page(st, addr, 2, pud_val(*pud));
+               }
+       }
+}
+
+static void walk_pgd(struct seq_file *m)
+{
+       pgd_t *pgd = swapper_pg_dir;
+       struct pg_state st;
+       unsigned long addr;
+       unsigned i, pgdoff = USER_PGTABLES_CEILING / PGDIR_SIZE;
+
+       memset(&st, 0, sizeof(st));
+       st.seq = m;
+       st.marker = address_markers;
+
+       pgd += pgdoff;
+
+       for (i = pgdoff; i < PTRS_PER_PGD; i++, pgd++) {
+               addr = i * PGDIR_SIZE;
+               if (!pgd_none(*pgd)) {
+                       walk_pud(&st, pgd, addr);
+               } else {
+                       note_page(&st, addr, 1, pgd_val(*pgd));
+               }
+       }
+
+       note_page(&st, 0, 0, 0);
+}
+
+static int ptdump_show(struct seq_file *m, void *v)
+{
+       walk_pgd(m);
+       return 0;
+}
+
+static int ptdump_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, ptdump_show, NULL);
+}
+
+static const struct file_operations ptdump_fops = {
+       .open           = ptdump_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static int ptdump_init(void)
+{
+       struct dentry *pe;
+       unsigned i, j;
+
+       for (i = 0; i < ARRAY_SIZE(pg_level); i++)
+               if (pg_level[i].bits)
+                       for (j = 0; j < pg_level[i].num; j++)
+                               pg_level[i].mask |= pg_level[i].bits[j].mask;
+
+       address_markers[2].start_address = VMALLOC_START;
+
+       pe = debugfs_create_file("kernel_page_tables", 0400, NULL, NULL,
+                                &ptdump_fops);
+       return pe ? 0 : -ENOMEM;
+}
+__initcall(ptdump_init);
index 3e8f106ee5fe01855fe12f66b0c581822c0521da..1f7b19a470606726595ebc692f3b05aae94729c6 100644 (file)
@@ -229,7 +229,7 @@ void __init setup_dma_zone(const struct machine_desc *mdesc)
 #ifdef CONFIG_ZONE_DMA
        if (mdesc->dma_zone_size) {
                arm_dma_zone_size = mdesc->dma_zone_size;
-               arm_dma_limit = PHYS_OFFSET + arm_dma_zone_size - 1;
+               arm_dma_limit = __pv_phys_offset + arm_dma_zone_size - 1;
        } else
                arm_dma_limit = 0xffffffff;
        arm_dma_pfn_limit = arm_dma_limit >> PAGE_SHIFT;
index f123d6eb074b056586dd840ba2465d3fba2b36a2..f9c32ba73544d64551e8ff2d4f890b74432eec15 100644 (file)
@@ -392,9 +392,9 @@ __arm_ioremap_exec(phys_addr_t phys_addr, size_t size, bool cached)
        unsigned int mtype;
 
        if (cached)
-               mtype = MT_MEMORY;
+               mtype = MT_MEMORY_RWX;
        else
-               mtype = MT_MEMORY_NONCACHED;
+               mtype = MT_MEMORY_RWX_NONCACHED;
 
        return __arm_ioremap_caller(phys_addr, size, mtype,
                        __builtin_return_address(0));
index d27158c38eb0b190b869e028b93d8265fb90969e..5e85ed371364c17657be7d7155139a5e3f536437 100644 (file)
@@ -146,7 +146,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 
        info.flags = VM_UNMAPPED_AREA_TOPDOWN;
        info.length = len;
-       info.low_limit = PAGE_SIZE;
+       info.low_limit = FIRST_USER_ADDRESS;
        info.high_limit = mm->mmap_base;
        info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
        info.align_offset = pgoff << PAGE_SHIFT;
index 580ef2de82d728f8ecfde5f5f3b208a2e5525b06..4f08c133cc255e2e2c2b93a0f28b79caaf3fc795 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/cputype.h>
 #include <asm/sections.h>
 #include <asm/cachetype.h>
+#include <asm/sections.h>
 #include <asm/setup.h>
 #include <asm/smp_plat.h>
 #include <asm/tlb.h>
@@ -287,36 +288,43 @@ static struct mem_type mem_types[] = {
                .prot_l1   = PMD_TYPE_TABLE,
                .domain    = DOMAIN_USER,
        },
-       [MT_MEMORY] = {
+       [MT_MEMORY_RWX] = {
                .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY,
                .prot_l1   = PMD_TYPE_TABLE,
                .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE,
                .domain    = DOMAIN_KERNEL,
        },
+       [MT_MEMORY_RW] = {
+               .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
+                            L_PTE_XN,
+               .prot_l1   = PMD_TYPE_TABLE,
+               .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE,
+               .domain    = DOMAIN_KERNEL,
+       },
        [MT_ROM] = {
                .prot_sect = PMD_TYPE_SECT,
                .domain    = DOMAIN_KERNEL,
        },
-       [MT_MEMORY_NONCACHED] = {
+       [MT_MEMORY_RWX_NONCACHED] = {
                .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
                                L_PTE_MT_BUFFERABLE,
                .prot_l1   = PMD_TYPE_TABLE,
                .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE,
                .domain    = DOMAIN_KERNEL,
        },
-       [MT_MEMORY_DTCM] = {
+       [MT_MEMORY_RW_DTCM] = {
                .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
                                L_PTE_XN,
                .prot_l1   = PMD_TYPE_TABLE,
                .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN,
                .domain    = DOMAIN_KERNEL,
        },
-       [MT_MEMORY_ITCM] = {
+       [MT_MEMORY_RWX_ITCM] = {
                .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY,
                .prot_l1   = PMD_TYPE_TABLE,
                .domain    = DOMAIN_KERNEL,
        },
-       [MT_MEMORY_SO] = {
+       [MT_MEMORY_RW_SO] = {
                .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
                                L_PTE_MT_UNCACHED | L_PTE_XN,
                .prot_l1   = PMD_TYPE_TABLE,
@@ -325,7 +333,8 @@ static struct mem_type mem_types[] = {
                .domain    = DOMAIN_KERNEL,
        },
        [MT_MEMORY_DMA_READY] = {
-               .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY,
+               .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
+                               L_PTE_XN,
                .prot_l1   = PMD_TYPE_TABLE,
                .domain    = DOMAIN_KERNEL,
        },
@@ -337,6 +346,44 @@ const struct mem_type *get_mem_type(unsigned int type)
 }
 EXPORT_SYMBOL(get_mem_type);
 
+#define PTE_SET_FN(_name, pteop) \
+static int pte_set_##_name(pte_t *ptep, pgtable_t token, unsigned long addr, \
+                       void *data) \
+{ \
+       pte_t pte = pteop(*ptep); \
+\
+       set_pte_ext(ptep, pte, 0); \
+       return 0; \
+} \
+
+#define SET_MEMORY_FN(_name, callback) \
+int set_memory_##_name(unsigned long addr, int numpages) \
+{ \
+       unsigned long start = addr; \
+       unsigned long size = PAGE_SIZE*numpages; \
+       unsigned end = start + size; \
+\
+       if (start < MODULES_VADDR || start >= MODULES_END) \
+               return -EINVAL;\
+\
+       if (end < MODULES_VADDR || end >= MODULES_END) \
+               return -EINVAL; \
+\
+       apply_to_page_range(&init_mm, start, size, callback, NULL); \
+       flush_tlb_kernel_range(start, end); \
+       return 0;\
+}
+
+PTE_SET_FN(ro, pte_wrprotect)
+PTE_SET_FN(rw, pte_mkwrite)
+PTE_SET_FN(x, pte_mkexec)
+PTE_SET_FN(nx, pte_mknexec)
+
+SET_MEMORY_FN(ro, pte_set_ro)
+SET_MEMORY_FN(rw, pte_set_rw)
+SET_MEMORY_FN(x, pte_set_x)
+SET_MEMORY_FN(nx, pte_set_nx)
+
 /*
  * Adjust the PMD section entries according to the CPU in use.
  */
@@ -410,6 +457,9 @@ static void __init build_mem_type_table(void)
                        mem_types[MT_DEVICE_NONSHARED].prot_sect |= PMD_SECT_XN;
                        mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_XN;
                        mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_XN;
+
+                       /* Also setup NX memory mapping */
+                       mem_types[MT_MEMORY_RW].prot_sect |= PMD_SECT_XN;
                }
                if (cpu_arch >= CPU_ARCH_ARMv7 && (cr & CR_TRE)) {
                        /*
@@ -487,11 +537,13 @@ static void __init build_mem_type_table(void)
                        mem_types[MT_DEVICE_WC].prot_pte |= L_PTE_SHARED;
                        mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_S;
                        mem_types[MT_DEVICE_CACHED].prot_pte |= L_PTE_SHARED;
-                       mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
-                       mem_types[MT_MEMORY].prot_pte |= L_PTE_SHARED;
+                       mem_types[MT_MEMORY_RWX].prot_sect |= PMD_SECT_S;
+                       mem_types[MT_MEMORY_RWX].prot_pte |= L_PTE_SHARED;
+                       mem_types[MT_MEMORY_RW].prot_sect |= PMD_SECT_S;
+                       mem_types[MT_MEMORY_RW].prot_pte |= L_PTE_SHARED;
                        mem_types[MT_MEMORY_DMA_READY].prot_pte |= L_PTE_SHARED;
-                       mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_S;
-                       mem_types[MT_MEMORY_NONCACHED].prot_pte |= L_PTE_SHARED;
+                       mem_types[MT_MEMORY_RWX_NONCACHED].prot_sect |= PMD_SECT_S;
+                       mem_types[MT_MEMORY_RWX_NONCACHED].prot_pte |= L_PTE_SHARED;
                }
        }
 
@@ -502,15 +554,15 @@ static void __init build_mem_type_table(void)
        if (cpu_arch >= CPU_ARCH_ARMv6) {
                if (cpu_arch >= CPU_ARCH_ARMv7 && (cr & CR_TRE)) {
                        /* Non-cacheable Normal is XCB = 001 */
-                       mem_types[MT_MEMORY_NONCACHED].prot_sect |=
+                       mem_types[MT_MEMORY_RWX_NONCACHED].prot_sect |=
                                PMD_SECT_BUFFERED;
                } else {
                        /* For both ARMv6 and non-TEX-remapping ARMv7 */
-                       mem_types[MT_MEMORY_NONCACHED].prot_sect |=
+                       mem_types[MT_MEMORY_RWX_NONCACHED].prot_sect |=
                                PMD_SECT_TEX(1);
                }
        } else {
-               mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_BUFFERABLE;
+               mem_types[MT_MEMORY_RWX_NONCACHED].prot_sect |= PMD_SECT_BUFFERABLE;
        }
 
 #ifdef CONFIG_ARM_LPAE
@@ -543,10 +595,12 @@ static void __init build_mem_type_table(void)
 
        mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask;
        mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask;
-       mem_types[MT_MEMORY].prot_sect |= ecc_mask | cp->pmd;
-       mem_types[MT_MEMORY].prot_pte |= kern_pgprot;
+       mem_types[MT_MEMORY_RWX].prot_sect |= ecc_mask | cp->pmd;
+       mem_types[MT_MEMORY_RWX].prot_pte |= kern_pgprot;
+       mem_types[MT_MEMORY_RW].prot_sect |= ecc_mask | cp->pmd;
+       mem_types[MT_MEMORY_RW].prot_pte |= kern_pgprot;
        mem_types[MT_MEMORY_DMA_READY].prot_pte |= kern_pgprot;
-       mem_types[MT_MEMORY_NONCACHED].prot_sect |= ecc_mask;
+       mem_types[MT_MEMORY_RWX_NONCACHED].prot_sect |= ecc_mask;
        mem_types[MT_ROM].prot_sect |= cp->pmd;
 
        switch (cp->pmd) {
@@ -1296,6 +1350,8 @@ static void __init kmap_init(void)
 static void __init map_lowmem(void)
 {
        struct memblock_region *reg;
+       unsigned long kernel_x_start = round_down(__pa(_stext), SECTION_SIZE);
+       unsigned long kernel_x_end = round_up(__pa(__init_end), SECTION_SIZE);
 
        /* Map all the lowmem memory banks. */
        for_each_memblock(memory, reg) {
@@ -1308,12 +1364,40 @@ static void __init map_lowmem(void)
                if (start >= end)
                        break;
 
-               map.pfn = __phys_to_pfn(start);
-               map.virtual = __phys_to_virt(start);
-               map.length = end - start;
-               map.type = MT_MEMORY;
+               if (end < kernel_x_start || start >= kernel_x_end) {
+                       map.pfn = __phys_to_pfn(start);
+                       map.virtual = __phys_to_virt(start);
+                       map.length = end - start;
+                       map.type = MT_MEMORY_RWX;
 
-               create_mapping(&map);
+                       create_mapping(&map);
+               } else {
+                       /* This better cover the entire kernel */
+                       if (start < kernel_x_start) {
+                               map.pfn = __phys_to_pfn(start);
+                               map.virtual = __phys_to_virt(start);
+                               map.length = kernel_x_start - start;
+                               map.type = MT_MEMORY_RW;
+
+                               create_mapping(&map);
+                       }
+
+                       map.pfn = __phys_to_pfn(kernel_x_start);
+                       map.virtual = __phys_to_virt(kernel_x_start);
+                       map.length = kernel_x_end - kernel_x_start;
+                       map.type = MT_MEMORY_RWX;
+
+                       create_mapping(&map);
+
+                       if (kernel_x_end < end) {
+                               map.pfn = __phys_to_pfn(kernel_x_end);
+                               map.virtual = __phys_to_virt(kernel_x_end);
+                               map.length = end - kernel_x_end;
+                               map.type = MT_MEMORY_RW;
+
+                               create_mapping(&map);
+                       }
+               }
        }
 }
 
index 0acb089d0f70db818ce487fa67b0fb90b1b0b69d..1046b373d1aedb2823e3bb62f106681f9b63fc2a 100644 (file)
@@ -87,7 +87,8 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
                init_pud = pud_offset(init_pgd, 0);
                init_pmd = pmd_offset(init_pud, 0);
                init_pte = pte_offset_map(init_pmd, 0);
-               set_pte_ext(new_pte, *init_pte, 0);
+               set_pte_ext(new_pte + 0, init_pte[0], 0);
+               set_pte_ext(new_pte + 1, init_pte[1], 0);
                pte_unmap(init_pte);
                pte_unmap(new_pte);
        }
index 29606bd75f3f19b265e7bfaf2cb11c0156afbcb7..d70b73364a3fe8a549407f51c0f8f35e786360d7 100644 (file)
@@ -54,7 +54,7 @@ static struct clocksource iop_clocksource = {
 /*
  * IOP sched_clock() implementation via its clocksource.
  */
-static u32 notrace iop_read_sched_clock(void)
+static u64 notrace iop_read_sched_clock(void)
 {
        return 0xffffffffu - read_tcr1();
 }
@@ -142,7 +142,7 @@ void __init iop_init_time(unsigned long tick_rate)
 {
        u32 timer_ctl;
 
-       setup_sched_clock(iop_read_sched_clock, 32, tick_rate);
+       sched_clock_register(iop_read_sched_clock, 32, tick_rate);
 
        ticks_per_jiffy = DIV_ROUND_CLOSEST(tick_rate, HZ);
        iop_tick_rate = tick_rate;
index d9bc98eb2a6b6b80559faa096f47cda066060e00..384a776d8eb2c8e3133642d7e118ced04e9eb951 100644 (file)
@@ -38,7 +38,7 @@
  */
 static void __iomem *sync32k_cnt_reg;
 
-static u32 notrace omap_32k_read_sched_clock(void)
+static u64 notrace omap_32k_read_sched_clock(void)
 {
        return sync32k_cnt_reg ? __raw_readl(sync32k_cnt_reg) : 0;
 }
@@ -115,7 +115,7 @@ int __init omap_init_clocksource_32k(void __iomem *vbase)
                return ret;
        }
 
-       setup_sched_clock(omap_32k_read_sched_clock, 32, 32768);
+       sched_clock_register(omap_32k_read_sched_clock, 32, 32768);
        register_persistent_clock(NULL, omap_read_persistent_clock);
        pr_info("OMAP clocksource: 32k_counter at 32768 Hz\n");
 
index fb92abb91628a2e06f6aebc54f03a724a79c23ee..2861b155485aefa0adeb1029d6657b4081179af6 100644 (file)
@@ -336,8 +336,11 @@ static inline void __omap_dm_timer_enable_posted(struct omap_dm_timer *timer)
        if (timer->posted)
                return;
 
-       if (timer->errata & OMAP_TIMER_ERRATA_I103_I767)
+       if (timer->errata & OMAP_TIMER_ERRATA_I103_I767) {
+               timer->posted = OMAP_TIMER_NONPOSTED;
+               __omap_dm_timer_write(timer, OMAP_TIMER_IF_CTRL_REG, 0, 0);
                return;
+       }
 
        __omap_dm_timer_write(timer, OMAP_TIMER_IF_CTRL_REG,
                              OMAP_TIMER_CTRL_POSTED, 0);
index c66d163d7a2a25084179e71e6a2d57f8e04263ff..830ff07f33856dfa886a3224fe352dab2bd336f5 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/platform_data/dma-mv_xor.h>
 #include <linux/platform_data/usb-ehci-orion.h>
 #include <mach/bridge-regs.h>
+#include <plat/common.h>
 
 /* Create a clkdev entry for a given device/clk */
 void __init orion_clkdev_add(const char *con_id, const char *dev_id,
@@ -256,7 +257,7 @@ static __init void ge_complete(
 /*****************************************************************************
  * GE00
  ****************************************************************************/
-struct mv643xx_eth_shared_platform_data orion_ge00_shared_data;
+static struct mv643xx_eth_shared_platform_data orion_ge00_shared_data;
 
 static struct resource orion_ge00_shared_resources[] = {
        {
@@ -322,7 +323,7 @@ void __init orion_ge00_init(struct mv643xx_eth_platform_data *eth_data,
 /*****************************************************************************
  * GE01
  ****************************************************************************/
-struct mv643xx_eth_shared_platform_data orion_ge01_shared_data;
+static struct mv643xx_eth_shared_platform_data orion_ge01_shared_data;
 
 static struct resource orion_ge01_shared_resources[] = {
        {
@@ -373,7 +374,7 @@ void __init orion_ge01_init(struct mv643xx_eth_platform_data *eth_data,
 /*****************************************************************************
  * GE10
  ****************************************************************************/
-struct mv643xx_eth_shared_platform_data orion_ge10_shared_data;
+static struct mv643xx_eth_shared_platform_data orion_ge10_shared_data;
 
 static struct resource orion_ge10_shared_resources[] = {
        {
@@ -422,7 +423,7 @@ void __init orion_ge10_init(struct mv643xx_eth_platform_data *eth_data,
 /*****************************************************************************
  * GE11
  ****************************************************************************/
-struct mv643xx_eth_shared_platform_data orion_ge11_shared_data;
+static struct mv643xx_eth_shared_platform_data orion_ge11_shared_data;
 
 static struct resource orion_ge11_shared_resources[] = {
        {
index 9d2b2ac74938da9b52f2ee1f629fdb6ca3b602b7..261258f717fc200f99d6768d3fe7353ccaf18b90 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/sched_clock.h>
+#include <plat/time.h>
 
 /*
  * MBus bridge block registers.
@@ -60,7 +61,7 @@ static u32 ticks_per_jiffy;
  * at least 7.5ns (133MHz TCLK).
  */
 
-static u32 notrace orion_read_sched_clock(void)
+static u64 notrace orion_read_sched_clock(void)
 {
        return ~readl(timer_base + TIMER0_VAL_OFF);
 }
@@ -174,7 +175,7 @@ static irqreturn_t orion_timer_interrupt(int irq, void *dev_id)
 
 static struct irqaction orion_timer_irq = {
        .name           = "orion_tick",
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_TIMER,
        .handler        = orion_timer_interrupt
 };
 
@@ -201,7 +202,7 @@ orion_time_init(void __iomem *_bridge_base, u32 _bridge_timer1_clr_mask,
        /*
         * Set scale and timer for sched_clock.
         */
-       setup_sched_clock(orion_read_sched_clock, 32, tclk);
+       sched_clock_register(orion_read_sched_clock, 32, tclk);
 
        /*
         * Setup free-running clocksource timer (interrupts
index 99a3590f034949cc45bc99df724857e096888e51..ac07e871f6a781594ffae471516527e7ea090941 100644 (file)
@@ -1468,6 +1468,8 @@ void __init s3c64xx_spi0_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
        pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi0_cfg_gpio;
 #if defined(CONFIG_PL330_DMA)
        pd.filter = pl330_filter;
+#elif defined(CONFIG_S3C64XX_PL080)
+       pd.filter = pl08x_filter_id;
 #elif defined(CONFIG_S3C24XX_DMAC)
        pd.filter = s3c24xx_dma_filter;
 #endif
@@ -1509,8 +1511,10 @@ void __init s3c64xx_spi1_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
        pd.num_cs = num_cs;
        pd.src_clk_nr = src_clk_nr;
        pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi1_cfg_gpio;
-#ifdef CONFIG_PL330_DMA
+#if defined(CONFIG_PL330_DMA)
        pd.filter = pl330_filter;
+#elif defined(CONFIG_S3C64XX_PL080)
+       pd.filter = pl08x_filter_id;
 #endif
 
        s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi1);
@@ -1550,8 +1554,10 @@ void __init s3c64xx_spi2_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
        pd.num_cs = num_cs;
        pd.src_clk_nr = src_clk_nr;
        pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi2_cfg_gpio;
-#ifdef CONFIG_PL330_DMA
+#if defined(CONFIG_PL330_DMA)
        pd.filter = pl330_filter;
+#elif defined(CONFIG_S3C64XX_PL080)
+       pd.filter = pl08x_filter_id;
 #endif
 
        s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi2);
index ec0d731b0e7b88ed8bc7b2937528545c15f60f6e..886326ee6f6c373c36d16fddef48b9ce58d5f7c9 100644 (file)
 
 #include <mach/dma.h>
 
+#if defined(CONFIG_PL330_DMA)
+#define dma_filter pl330_filter
+#elif defined(CONFIG_S3C64XX_PL080)
+#define dma_filter pl08x_filter_id
+#endif
+
 static unsigned samsung_dmadev_request(enum dma_ch dma_ch,
                                struct samsung_dma_req *param,
                                struct device *dev, char *ch_name)
@@ -30,7 +36,7 @@ static unsigned samsung_dmadev_request(enum dma_ch dma_ch,
        if (dev->of_node)
                return (unsigned)dma_request_slave_channel(dev, ch_name);
        else
-               return (unsigned)dma_request_channel(mask, pl330_filter,
+               return (unsigned)dma_request_channel(mask, dma_filter,
                                                        (void *)dma_ch);
 }
 
index 4afc32f90b6d51f553e7d987cf972730466adb57..f48dc0a4736c8d2d1703a29dc0ece5bb9662f3ca 100644 (file)
@@ -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
index faa651602780b6570b1af0d079d08a9b409e651e..ebee4dc11a946686a1c558c82f3f027b7c0f173b 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/device.h>
 #include <linux/gpio.h>
 #include <linux/irqchip/arm-vic.h>
+#include <linux/of.h>
 
 #include <plat/regs-irqtype.h>
 
@@ -202,6 +203,9 @@ static int __init s5p_init_irq_eint(void)
 {
        int irq;
 
+       if (of_have_populated_dt())
+               return -ENODEV;
+
        for (irq = IRQ_EINT(0); irq <= IRQ_EINT(15); irq++)
                irq_set_chip(irq, &s5p_irq_vic_eint);
 
index 51b109e3b6c38d4d265dc53f581203ecef34ab34..c966ae90f4a0cda8796ddfeed9c0caef970e81a1 100644 (file)
@@ -26,7 +26,7 @@
 
 static void __iomem *ctr;
 
-static u32 notrace versatile_read_sched_clock(void)
+static u64 notrace versatile_read_sched_clock(void)
 {
        if (ctr)
                return readl(ctr);
@@ -37,5 +37,5 @@ static u32 notrace versatile_read_sched_clock(void)
 void __init versatile_sched_clock_init(void __iomem *reg, unsigned long rate)
 {
        ctr = reg;
-       setup_sched_clock(versatile_read_sched_clock, 32, rate);
+       sched_clock_register(versatile_read_sched_clock, 32, rate);
 }
index 23732cdff5511ff3c20bf1cbd403034797faf296..b31ee1b275b011d7010dbcac1eea3ab206290908 100644 (file)
@@ -25,8 +25,9 @@ struct xen_p2m_entry {
        struct rb_node rbnode_phys;
 };
 
-rwlock_t p2m_lock;
+static rwlock_t p2m_lock;
 struct rb_root phys_to_mach = RB_ROOT;
+EXPORT_SYMBOL_GPL(phys_to_mach);
 static struct rb_root mach_to_phys = RB_ROOT;
 
 static int xen_add_phys_to_mach_entry(struct xen_p2m_entry *new)
@@ -200,7 +201,7 @@ bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn)
 }
 EXPORT_SYMBOL_GPL(__set_phys_to_machine);
 
-int p2m_init(void)
+static int p2m_init(void)
 {
        rwlock_init(&p2m_lock);
        return 0;
index 88c8b6c1341a445bdc425955383a8563033edd90..6d4dd22ee4b7bc70622f3fe95538bcba0ff6b99e 100644 (file)
@@ -159,8 +159,7 @@ config NR_CPUS
        range 2 32
        depends on SMP
        # These have to remain sorted largest to smallest
-       default "8" if ARCH_XGENE
-       default "4"
+       default "8"
 
 config HOTPLUG_CPU
        bool "Support for hot-pluggable CPUs"
index 4cc813eddacbebee4c84f864f103bb6492d7c193..57276972722768b86f5c21d0cdd50481e1a48683 100644 (file)
@@ -229,7 +229,7 @@ extern void __iomem *__ioremap(phys_addr_t phys_addr, size_t size, pgprot_t prot
 extern void __iounmap(volatile void __iomem *addr);
 extern void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size);
 
-#define PROT_DEFAULT           (PTE_TYPE_PAGE | PTE_AF | PTE_DIRTY)
+#define PROT_DEFAULT           (pgprot_default | PTE_DIRTY)
 #define PROT_DEVICE_nGnRE      (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_DEVICE_nGnRE))
 #define PROT_NORMAL_NC         (PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL_NC))
 #define PROT_NORMAL            (PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL))
index 755f86143320167038e24e9be093e61b8b307e65..b1d2e26c3c883e7259f0ab679efe33ffe2935429 100644 (file)
@@ -43,7 +43,7 @@
  * Section
  */
 #define PMD_SECT_VALID         (_AT(pmdval_t, 1) << 0)
-#define PMD_SECT_PROT_NONE     (_AT(pmdval_t, 1) << 2)
+#define PMD_SECT_PROT_NONE     (_AT(pmdval_t, 1) << 58)
 #define PMD_SECT_USER          (_AT(pmdval_t, 1) << 6)         /* AP[1] */
 #define PMD_SECT_RDONLY                (_AT(pmdval_t, 1) << 7)         /* AP[2] */
 #define PMD_SECT_S             (_AT(pmdval_t, 3) << 8)
index 7009387348b7c416f9dc8732a18c7563eac4af4e..c68cca5c3523221421e93460805a3c4d9cbac5a4 100644 (file)
@@ -282,8 +282,9 @@ ENDPROC(secondary_holding_pen)
         * be used where CPUs are brought online dynamically by the kernel.
         */
 ENTRY(secondary_entry)
-       bl      __calc_phys_offset              // x2=phys offset
        bl      el2_setup                       // Drop to EL1
+       bl      __calc_phys_offset              // x24=PHYS_OFFSET, x28=PHYS_OFFSET-PAGE_OFFSET
+       bl      set_cpu_boot_mode_flag
        b       secondary_startup
 ENDPROC(secondary_entry)
 
index 421b99fd635dfae60c36d4c45837d73ca71a7187..0f7fec52c7f84030afb9958cdd4627bb2ceb9546 100644 (file)
@@ -111,12 +111,12 @@ ENTRY(__cpu_setup)
        bl      __flush_dcache_all
        mov     lr, x28
        ic      iallu                           // I+BTB cache invalidate
+       tlbi    vmalle1is                       // invalidate I + D TLBs
        dsb     sy
 
        mov     x0, #3 << 20
        msr     cpacr_el1, x0                   // Enable FP/ASIMD
        msr     mdscr_el1, xzr                  // Reset mdscr_el1
-       tlbi    vmalle1is                       // invalidate I + D TLBs
        /*
         * Memory region attributes for LPAE:
         *
index 7b1f2cd854008c16117cf5c39c06f4bd2115a9fa..1f121497b5177c4a3ac30d715dd98a1f623686cd 100644 (file)
@@ -298,8 +298,10 @@ static int __init set_abdac_rate(struct platform_device *pdev)
         */
        retval = clk_round_rate(pll1,
                        CONFIG_BOARD_FAVR32_ABDAC_RATE * 256 * 16);
-       if (retval < 0)
+       if (retval <= 0) {
+               retval = -EINVAL;
                goto out_abdac;
+       }
 
        retval = clk_set_rate(pll1, retval);
        if (retval != 0)
index d5aff36ade922f07ca18c34552b140919d598dfc..4733e38e7ae62cb111324ef17877bbd90b97a712 100644 (file)
@@ -59,7 +59,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index 4abcf435d599a4a88b26ae1049b401dfcfa8a2e8..1be0ee31bd91c277753a5be27510ced4554712bf 100644 (file)
@@ -61,7 +61,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index 18f3fa0470ff294a9755cd263d30c4a4080198e7..796e536f7bc43576d7079a41237356eb5977dbfe 100644 (file)
@@ -60,7 +60,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index 06e389cfcd126e4c75111398758a5813d7fe2275..9a57da44eb6fd3390a5df2ce4d905bec1ec88c79 100644 (file)
@@ -48,7 +48,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index 2518a1368d7caea758cfba9b152abe07b59870d0..97fe1b399b069d2965552ef78a7c3e29da1dd084 100644 (file)
@@ -59,7 +59,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index 245ef6bd0fa61f56de23c1b4ce57abb51771489c..a176d24467e9d28f25e31364aa8e92b0fd3d8de0 100644 (file)
@@ -62,7 +62,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index fa6cbac6e4189c2e5a39eed8b6cb49ec44a3dd96..d1bf6dcfc47d4c289fca01896377d67cfbc62a94 100644 (file)
@@ -61,7 +61,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index bbd5131021a57d840bed7dede2db9d61b074e8f4..2813dd2b913876b0604c31751204b16ac6eb12fe 100644 (file)
@@ -53,7 +53,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index c1cd726f901233b1dd552cb3d28f3375682f3ad9..f8ff3a3baad4cc702ed4b374b95c21c943b0a84f 100644 (file)
@@ -42,7 +42,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index 754ae56b276739a58113bc89b87395d0b35b6ab2..992228e54e38cf56dc0cc1567c129d5ec907543b 100644 (file)
@@ -42,7 +42,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index 58589d8cc0acd829af7612b782368a907f6c3e64..b8e698b0d1fa30e2563fff8e9a0792a36b8ec3a1 100644 (file)
@@ -54,7 +54,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index c90fbf6d35bc16d60f12d1e5be4cf836f2fc9391..07bed3f7eb5e6022372ed35b6a8e303356cbbc8a 100644 (file)
@@ -58,7 +58,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index ba7c31e269cb0aed7b0ba9a72c1ce641cf0e346a..18db853386c81e73087c2c106d7271a415c3dce2 100644 (file)
@@ -58,7 +58,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index 65de4431108c837334dc07facfc578fb815d55cd..91df6b2986be2a1691449bfe47953715e387060d 100644 (file)
@@ -46,7 +46,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
 CONFIG_MTD_CONCAT=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
index 0a8bfdc420e0e6730c4ba1464de3ee92fafd8a2f..d630e089dd322c6ab735831a4ebd5424308a9a75 100644 (file)
@@ -49,7 +49,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
index 12f828ad5058d09158f8d3e2007b76a7a42cbb4a..d0f771be9e96eda02c1045bbb5702cc9b9f74b8d 100644 (file)
@@ -59,7 +59,7 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id)
 static struct irqaction timer_irqaction = {
        .handler        = timer_interrupt,
        /* Oprofile uses the same irq as the timer, so allow it to be shared */
-       .flags          = IRQF_TIMER | IRQF_DISABLED | IRQF_SHARED,
+       .flags          = IRQF_TIMER | IRQF_SHARED,
        .name           = "avr32_comparator",
 };
 
index 32d680eb6f4842be56d17f40197c2a6fd4f77f37..db190842b80c74e026784037516df9b27471f4b8 100644 (file)
@@ -181,7 +181,7 @@ static const struct platform_suspend_ops avr32_pm_ops = {
        .enter  = avr32_pm_enter,
 };
 
-static unsigned long avr32_pm_offset(void *symbol)
+static unsigned long __init avr32_pm_offset(void *symbol)
 {
        extern u8 pm_exception[];
 
index 09c5a0f5f4d1778156a5ee83715e6a2aec7f0441..86648c083bb4b1297275dc2bc4ceb3ecd949aa5b 100644 (file)
@@ -12,6 +12,7 @@
 #define _ASM_C6X_CACHE_H
 
 #include <linux/irqflags.h>
+#include <linux/init.h>
 
 /*
  * Cache line size
index 916ffe770bcf5691c0e2b6744a40f0d45c81d487..84715fcbba0875ed7e689ec761c2e4a2184477bd 100644 (file)
@@ -23,8 +23,7 @@
  */
 
 #include <linux/module.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
 #include <asm/sal.h>
 
 MODULE_AUTHOR("Bjorn Helgaas <bjorn.helgaas@hp.com>");
index 75f25a8e300170ce85130da8fd2f739faa983059..dbdd2231c75ddc9fab61fd1b2dca7c1cc60a3e3e 100644 (file)
@@ -87,6 +87,30 @@ config MMU_SUN3
        bool
        depends on MMU && !MMU_MOTOROLA && !MMU_COLDFIRE
 
+config KEXEC
+       bool "kexec system call"
+       depends on M68KCLASSIC
+       help
+         kexec is a system call that implements the ability to shutdown your
+         current kernel, and to start another kernel.  It is like a reboot
+         but it is independent of the system firmware.   And like a reboot
+         you can start any kernel with it, not just Linux.
+
+         The name comes from the similarity to the exec system call.
+
+         It is an ongoing process to be certain the hardware in a machine
+         is properly shutdown, so do not be surprised if this code does not
+         initially work for you.  As of this writing the exact hardware
+         interface is strongly in flux, so no good recommendation can be
+         made.
+
+config BOOTINFO_PROC
+       bool "Export bootinfo in procfs"
+       depends on KEXEC && M68KCLASSIC
+       help
+         Say Y to export the bootinfo used to boot the kernel in a
+         "bootinfo" file in procfs.  This is useful with kexec.
+
 menu "Platform setup"
 
 source arch/m68k/Kconfig.cpu
index 99449fbf9a726834ec2b2c268956a13f0ab0b99d..ba03cec3f711e024422fe916a407b4cf56556f76 100644 (file)
@@ -87,7 +87,7 @@ void *amiga_chip_alloc_res(unsigned long size, struct resource *res)
 
        atomic_sub(size, &chipavail);
        pr_debug("amiga_chip_alloc_res: returning %pR\n", res);
-       return (void *)ZTWO_VADDR(res->start);
+       return ZTWO_VADDR(res->start);
 }
 
 void amiga_chip_free(void *ptr)
index b819390e29cdb7e901e926a9190b30ebadb8916c..9625b71322275ea942da3bc1b3a6616e205bdc7a 100644 (file)
@@ -28,6 +28,8 @@
 #include <linux/keyboard.h>
 
 #include <asm/bootinfo.h>
+#include <asm/bootinfo-amiga.h>
+#include <asm/byteorder.h>
 #include <asm/setup.h>
 #include <asm/pgtable.h>
 #include <asm/amigahw.h>
@@ -140,46 +142,46 @@ static struct resource ram_resource[NUM_MEMINFO];
      *  Parse an Amiga-specific record in the bootinfo
      */
 
-int amiga_parse_bootinfo(const struct bi_record *record)
+int __init amiga_parse_bootinfo(const struct bi_record *record)
 {
        int unknown = 0;
-       const unsigned long *data = record->data;
+       const void *data = record->data;
 
-       switch (record->tag) {
+       switch (be16_to_cpu(record->tag)) {
        case BI_AMIGA_MODEL:
-               amiga_model = *data;
+               amiga_model = be32_to_cpup(data);
                break;
 
        case BI_AMIGA_ECLOCK:
-               amiga_eclock = *data;
+               amiga_eclock = be32_to_cpup(data);
                break;
 
        case BI_AMIGA_CHIPSET:
-               amiga_chipset = *data;
+               amiga_chipset = be32_to_cpup(data);
                break;
 
        case BI_AMIGA_CHIP_SIZE:
-               amiga_chip_size = *(const int *)data;
+               amiga_chip_size = be32_to_cpup(data);
                break;
 
        case BI_AMIGA_VBLANK:
-               amiga_vblank = *(const unsigned char *)data;
+               amiga_vblank = *(const __u8 *)data;
                break;
 
        case BI_AMIGA_PSFREQ:
-               amiga_psfreq = *(const unsigned char *)data;
+               amiga_psfreq = *(const __u8 *)data;
                break;
 
        case BI_AMIGA_AUTOCON:
 #ifdef CONFIG_ZORRO
                if (zorro_num_autocon < ZORRO_NUM_AUTO) {
-                       const struct ConfigDev *cd = (struct ConfigDev *)data;
-                       struct zorro_dev *dev = &zorro_autocon[zorro_num_autocon++];
+                       const struct ConfigDev *cd = data;
+                       struct zorro_dev_init *dev = &zorro_autocon_init[zorro_num_autocon++];
                        dev->rom = cd->cd_Rom;
-                       dev->slotaddr = cd->cd_SlotAddr;
-                       dev->slotsize = cd->cd_SlotSize;
-                       dev->resource.start = (unsigned long)cd->cd_BoardAddr;
-                       dev->resource.end = dev->resource.start + cd->cd_BoardSize - 1;
+                       dev->slotaddr = be16_to_cpu(cd->cd_SlotAddr);
+                       dev->slotsize = be16_to_cpu(cd->cd_SlotSize);
+                       dev->boardaddr = be32_to_cpu(cd->cd_BoardAddr);
+                       dev->boardsize = be32_to_cpu(cd->cd_BoardSize);
                } else
                        printk("amiga_parse_bootinfo: too many AutoConfig devices\n");
 #endif /* CONFIG_ZORRO */
@@ -358,6 +360,14 @@ static void __init amiga_identify(void)
 #undef AMIGAHW_ANNOUNCE
 }
 
+
+static unsigned long amiga_random_get_entropy(void)
+{
+       /* VPOSR/VHPOSR provide at least 17 bits of data changing at 1.79 MHz */
+       return *(unsigned long *)&amiga_custom.vposr;
+}
+
+
     /*
      *  Setup the Amiga configuration info
      */
@@ -395,6 +405,8 @@ void __init config_amiga(void)
        mach_heartbeat = amiga_heartbeat;
 #endif
 
+       mach_random_get_entropy = amiga_random_get_entropy;
+
        /* Fill in the clock value (based on the 700 kHz E-Clock) */
        amiga_colorclock = 5*amiga_eclock;      /* 3.5 MHz */
 
@@ -608,6 +620,8 @@ static void amiga_mem_console_write(struct console *co, const char *s,
 
 static int __init amiga_savekmsg_setup(char *arg)
 {
+       bool registered;
+
        if (!MACH_IS_AMIGA || strcmp(arg, "mem"))
                return 0;
 
@@ -618,14 +632,16 @@ static int __init amiga_savekmsg_setup(char *arg)
 
        /* Just steal the block, the chipram allocator isn't functional yet */
        amiga_chip_size -= SAVEKMSG_MAXMEM;
-       savekmsg = (void *)ZTWO_VADDR(CHIP_PHYSADDR + amiga_chip_size);
+       savekmsg = ZTWO_VADDR(CHIP_PHYSADDR + amiga_chip_size);
        savekmsg->magic1 = SAVEKMSG_MAGIC1;
        savekmsg->magic2 = SAVEKMSG_MAGIC2;
        savekmsg->magicptr = ZTWO_PADDR(savekmsg);
        savekmsg->size = 0;
 
+       registered = !!amiga_console_driver.write;
        amiga_console_driver.write = amiga_mem_console_write;
-       register_console(&amiga_console_driver);
+       if (!registered)
+               register_console(&amiga_console_driver);
        return 0;
 }
 
@@ -707,11 +723,16 @@ void amiga_serial_gets(struct console *co, char *s, int len)
 
 static int __init amiga_debug_setup(char *arg)
 {
-       if (MACH_IS_AMIGA && !strcmp(arg, "ser")) {
-               /* no initialization required (?) */
-               amiga_console_driver.write = amiga_serial_console_write;
+       bool registered;
+
+       if (!MACH_IS_AMIGA || strcmp(arg, "ser"))
+               return 0;
+
+       /* no initialization required (?) */
+       registered = !!amiga_console_driver.write;
+       amiga_console_driver.write = amiga_serial_console_write;
+       if (!registered)
                register_console(&amiga_console_driver);
-       }
        return 0;
 }
 
index dacd9f911f7171f847fc0087faf20a34092f0e1c..d34029d7b05892a5c0d2e646129a89407402b368 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <asm/amigahw.h>
 #include <asm/amigayle.h>
+#include <asm/byteorder.h>
 
 
 #ifdef CONFIG_ZORRO
@@ -66,10 +67,12 @@ static int __init z_dev_present(zorro_id id)
 {
        unsigned int i;
 
-       for (i = 0; i < zorro_num_autocon; i++)
-               if (zorro_autocon[i].rom.er_Manufacturer == ZORRO_MANUF(id) &&
-                   zorro_autocon[i].rom.er_Product == ZORRO_PROD(id))
+       for (i = 0; i < zorro_num_autocon; i++) {
+               const struct ExpansionRom *rom = &zorro_autocon_init[i].rom;
+               if (be16_to_cpu(rom->er_Manufacturer) == ZORRO_MANUF(id) &&
+                   rom->er_Product == ZORRO_PROD(id))
                        return 1;
+       }
 
        return 0;
 }
index 3ea56b90e7188df2c758bce798fc46c2d96df461..9268c0f96376b30eee39caba6d023d3fd0488cab 100644 (file)
@@ -1,3 +1,4 @@
+#include <linux/init.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
@@ -9,6 +10,8 @@
 
 #include <asm/setup.h>
 #include <asm/bootinfo.h>
+#include <asm/bootinfo-apollo.h>
+#include <asm/byteorder.h>
 #include <asm/pgtable.h>
 #include <asm/apollohw.h>
 #include <asm/irq.h>
@@ -43,26 +46,25 @@ static const char *apollo_models[] = {
        [APOLLO_DN4500-APOLLO_DN3000] = "DN4500 (Roadrunner)"
 };
 
-int apollo_parse_bootinfo(const struct bi_record *record) {
-
+int __init apollo_parse_bootinfo(const struct bi_record *record)
+{
        int unknown = 0;
-       const unsigned long *data = record->data;
+       const void *data = record->data;
 
-       switch(record->tag) {
-               case BI_APOLLO_MODEL:
-                       apollo_model=*data;
-                       break;
+       switch (be16_to_cpu(record->tag)) {
+       case BI_APOLLO_MODEL:
+               apollo_model = be32_to_cpup(data);
+               break;
 
-               default:
-                        unknown=1;
+       default:
+                unknown=1;
        }
 
        return unknown;
 }
 
-void dn_setup_model(void) {
-
-
+static void __init dn_setup_model(void)
+{
        printk("Apollo hardware found: ");
        printk("[%s]\n", apollo_models[apollo_model - APOLLO_DN3000]);
 
index fb2d0bd9b3adab5304dc160a3bcf192aa0568a53..01a62161b08a1a69a74635de7004e4e65c73bf20 100644 (file)
@@ -37,6 +37,8 @@
 #include <linux/module.h>
 
 #include <asm/bootinfo.h>
+#include <asm/bootinfo-atari.h>
+#include <asm/byteorder.h>
 #include <asm/setup.h>
 #include <asm/atarihw.h>
 #include <asm/atariints.h>
@@ -129,14 +131,14 @@ static int __init scc_test(volatile char *ctla)
 int __init atari_parse_bootinfo(const struct bi_record *record)
 {
        int unknown = 0;
-       const u_long *data = record->data;
+       const void *data = record->data;
 
-       switch (record->tag) {
+       switch (be16_to_cpu(record->tag)) {
        case BI_ATARI_MCH_COOKIE:
-               atari_mch_cookie = *data;
+               atari_mch_cookie = be32_to_cpup(data);
                break;
        case BI_ATARI_MCH_TYPE:
-               atari_mch_type = *data;
+               atari_mch_type = be32_to_cpup(data);
                break;
        default:
                unknown = 1;
index a547ba9683d14a551c9d4a18632d3c3a5d7a1bed..03cb5e08d7cf9f4995a8e24c613e48c03c11b6f1 100644 (file)
@@ -287,6 +287,8 @@ static void __init atari_init_midi_port(int cflag)
 
 static int __init atari_debug_setup(char *arg)
 {
+       bool registered;
+
        if (!MACH_IS_ATARI)
                return 0;
 
@@ -294,6 +296,7 @@ static int __init atari_debug_setup(char *arg)
                /* defaults to ser2 for a Falcon and ser1 otherwise */
                arg = MACH_IS_FALCON ? "ser2" : "ser1";
 
+       registered = !!atari_console_driver.write;
        if (!strcmp(arg, "ser1")) {
                /* ST-MFP Modem1 serial port */
                atari_init_mfp_port(B9600|CS8);
@@ -317,7 +320,7 @@ static int __init atari_debug_setup(char *arg)
                sound_ym.wd_data = sound_ym.rd_data_reg_sel | 0x20; /* strobe H */
                atari_console_driver.write = atari_par_console_write;
        }
-       if (atari_console_driver.write)
+       if (atari_console_driver.write && !registered)
                register_console(&atari_console_driver);
 
        return 0;
index 8943aa4c18e63cd3b0719b3a8d9f50e6bec40671..478623dbb2092b357a1f355d382ad3cc272f8e95 100644 (file)
@@ -28,6 +28,8 @@
 #include <linux/bcd.h>
 
 #include <asm/bootinfo.h>
+#include <asm/bootinfo-vme.h>
+#include <asm/byteorder.h>
 #include <asm/pgtable.h>
 #include <asm/setup.h>
 #include <asm/irq.h>
@@ -50,9 +52,9 @@ void bvme6000_set_vectors (void);
 static irq_handler_t tick_handler;
 
 
-int bvme6000_parse_bootinfo(const struct bi_record *bi)
+int __init bvme6000_parse_bootinfo(const struct bi_record *bi)
 {
-       if (bi->tag == BI_VME_TYPE)
+       if (be16_to_cpu(bi->tag) == BI_VME_TYPE)
                return 0;
        else
                return 1;
index 19325e117eeaaec7b844e1e50d328719077e3261..1f87c0789b12c23fed962c6b0b69bf903884f229 100644 (file)
@@ -345,10 +345,6 @@ CONFIG_HEARTBEAT=y
 CONFIG_PROC_HARDWARE=y
 CONFIG_AMIGA_BUILTIN_SERIAL=y
 CONFIG_SERIAL_CONSOLE=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_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_JFS_FS=m
@@ -385,7 +381,7 @@ CONFIG_QNX6FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V4=y
+CONFIG_NFS_V4=m
 CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
index 14dc6ccda7f45349c82c0dd1f0d113831b3ac07b..ea5b647943641c8ae80094888c4af5b925596cec 100644 (file)
@@ -302,10 +302,6 @@ CONFIG_RTC_DRV_GENERIC=m
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_HEARTBEAT=y
 CONFIG_PROC_HARDWARE=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_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_JFS_FS=m
@@ -342,7 +338,7 @@ CONFIG_QNX6FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V4=y
+CONFIG_NFS_V4=m
 CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
index 6d5370c914b265123b6963df409ca3b82d17f8cf..0c3d280187f2ce5fd5ef3e7a8c95ec723a2fb32b 100644 (file)
@@ -320,10 +320,6 @@ CONFIG_NFBLOCK=y
 CONFIG_NFCON=y
 CONFIG_NFETH=y
 CONFIG_ATARI_DSP56K=m
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-# CONFIG_EXT3_FS_XATTR is not set
 CONFIG_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_JFS_FS=m
@@ -360,7 +356,7 @@ CONFIG_QNX6FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V4=y
+CONFIG_NFS_V4=m
 CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
index c015ddb6fd80635c81affec06369ced3f62185f8..9b6b515c5a23312e5344ffe2277616324db12725 100644 (file)
@@ -294,10 +294,6 @@ CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_GENERIC=m
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_PROC_HARDWARE=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_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_JFS_FS=m
@@ -334,7 +330,7 @@ CONFIG_QNX6FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V4=y
+CONFIG_NFS_V4=m
 CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
index ec7382d8afff5390a4210a45ba348637605c4f59..efffa687135f47341fcb795166c2eb1050a605f9 100644 (file)
@@ -304,10 +304,6 @@ CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_GENERIC=m
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_PROC_HARDWARE=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_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_JFS_FS=m
@@ -344,7 +340,7 @@ CONFIG_QNX6FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V4=y
+CONFIG_NFS_V4=m
 CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
index c1616824e201f0e8e53605226dae70cf4feb692a..e7292f460af45665ac7cdbef46c02a56f4b07921 100644 (file)
@@ -40,7 +40,6 @@ CONFIG_INET=y
 # CONFIG_IPV6 is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_RAM=y
index a6599e42facfb8cefb1062f7be679366a4ef5210..0cd4b39f325b6c609a385f31de4cf4c76db2a957 100644 (file)
@@ -38,7 +38,6 @@ CONFIG_INET=y
 # CONFIG_IPV6 is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_RAM=y
index 3fa60a57a0f9a19eab0872db442251c87f65f606..a60cb35091352d20399c39fbfe1cd863b072a5b8 100644 (file)
@@ -36,7 +36,6 @@ CONFIG_INET=y
 # CONFIG_IPV6 is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_RAM=y
index a1230e82bb1e5226c3d61968b1c625bbf40c6a17..e6502ab7cb2fee0ac7b2bd7a1089e41450f05780 100644 (file)
@@ -39,7 +39,6 @@ CONFIG_INET=y
 # CONFIG_IPV6 is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_RAM=y
index 43795f41f7c7b1da1267c8c5bef183cde4e97257..023812abd2e6c6d701015dd99f70693dd1eb7251 100644 (file)
@@ -38,7 +38,6 @@ CONFIG_INET=y
 # CONFIG_IPV6 is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_RAM=y
index 72746c57a571312b47b4b2989bd05d08ffa9180c..557b39f3be9094e223fb8715cae927c0c5ba1cd3 100644 (file)
@@ -38,7 +38,6 @@ CONFIG_INET=y
 # CONFIG_IPV6 is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_RAM=y
index 7d46fbec70424dc84fbe07a9ab1e77c7d1f2bec2..73a8565746dcd490abe13619ea87d66b28661b99 100644 (file)
@@ -327,10 +327,6 @@ CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_GENERIC=m
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_PROC_HARDWARE=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_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_JFS_FS=m
@@ -367,7 +363,7 @@ CONFIG_QNX6FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V4=y
+CONFIG_NFS_V4=m
 CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
index b17a8837f0e1016b273e5f74c6f75803a1e372b8..19c7939f700fa7b7cccc8e2547dbacefa7dbb315 100644 (file)
@@ -405,10 +405,6 @@ CONFIG_NFETH=y
 CONFIG_ATARI_DSP56K=m
 CONFIG_AMIGA_BUILTIN_SERIAL=y
 CONFIG_SERIAL_CONSOLE=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_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_JFS_FS=m
@@ -445,7 +441,7 @@ CONFIG_QNX6FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V4=y
+CONFIG_NFS_V4=m
 CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
index 5586c6529fce367fb22061b87c708b9ba10a1f61..81fab00de63a6c4912f24fabcff1eb49ba0e6903 100644 (file)
@@ -294,10 +294,6 @@ CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_GENERIC=m
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_PROC_HARDWARE=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_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_JFS_FS=m
@@ -334,7 +330,7 @@ CONFIG_QNX6FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V4=y
+CONFIG_NFS_V4=m
 CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
index e5e8262bbacdd0a94c4f0b1e0e89c06166ddd8ec..df0783770611d83e85022775a25bb84c62881143 100644 (file)
@@ -294,10 +294,6 @@ CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_GENERIC=m
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_PROC_HARDWARE=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_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_JFS_FS=m
@@ -334,7 +330,7 @@ CONFIG_QNX6FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V4=y
+CONFIG_NFS_V4=m
 CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
index be1496ed9b66028655205c48a36b69a365ed203b..f64c8963fa5dd0d8e939b3fa58467b5fba6116e6 100644 (file)
@@ -318,10 +318,6 @@ CONFIG_RTC_DRV_GENERIC=m
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_HEARTBEAT=y
 CONFIG_PROC_HARDWARE=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_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_JFS_FS=m
@@ -358,7 +354,7 @@ CONFIG_QNX6FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V4=y
+CONFIG_NFS_V4=m
 CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
index 54674d61e00141069e1fb5113e22e19784fc5c01..99bcc60f82a30c30a7431aeed7fb536318006cca 100644 (file)
@@ -296,10 +296,6 @@ CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_GENERIC=m
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_PROC_HARDWARE=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_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_JFS_FS=m
@@ -336,7 +332,7 @@ CONFIG_QNX6FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V4=y
+CONFIG_NFS_V4=m
 CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
index 832d9539f44194faff9d4e6940223f1d938850fc..2023a91500f380e45a63d1cc00d303330381dce3 100644 (file)
@@ -296,10 +296,6 @@ CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_GENERIC=m
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_PROC_HARDWARE=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_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_JFS_FS=m
@@ -336,7 +332,7 @@ CONFIG_QNX6FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V4=y
+CONFIG_NFS_V4=m
 CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
index 121a6660ad4e5c40db157c25385507f4f51a674f..71b78ecee75c64773921bb9aed81aefbf24dae73 100644 (file)
@@ -9,6 +9,7 @@
  * the GNU General Public License (GPL), incorporated herein by reference.
  */
 
+#include <linux/init.h>
 #include <linux/types.h>
 #include <linux/console.h>
 #include <linux/string.h>
@@ -70,7 +71,7 @@ static void nf_poweroff(void)
                nf_call(id);
 }
 
-void nf_init(void)
+void __init nf_init(void)
 {
        unsigned long id, version;
        char buf[256];
index 0721858fbd1ef6618b288bcbea33369995e35653..2d75ae246167a37f07d71a9bb743702fff686092 100644 (file)
@@ -62,17 +62,18 @@ struct nfhd_device {
 static void nfhd_make_request(struct request_queue *queue, struct bio *bio)
 {
        struct nfhd_device *dev = queue->queuedata;
-       struct bio_vec *bvec;
-       int i, dir, len, shift;
-       sector_t sec = bio->bi_sector;
+       struct bio_vec bvec;
+       struct bvec_iter iter;
+       int dir, len, shift;
+       sector_t sec = bio->bi_iter.bi_sector;
 
        dir = bio_data_dir(bio);
        shift = dev->bshift;
-       bio_for_each_segment(bvec, bio, i) {
-               len = bvec->bv_len;
+       bio_for_each_segment(bvec, bio, iter) {
+               len = bvec.bv_len;
                len >>= 9;
                nfhd_read_write(dev->id, 0, dir, sec >> shift, len >> shift,
-                               bvec_to_phys(bvec));
+                               bvec_to_phys(&bvec));
                sec += len;
        }
        bio_endio(bio, 0);
index b7609f791522a45f12170799cdae4f89bc8ab80f..2e5a787ea11b8f987ef3994292c7d57832bfc266 100644 (file)
@@ -14,6 +14,8 @@
 #include <linux/console.h>
 
 #include <asm/bootinfo.h>
+#include <asm/bootinfo-hp300.h>
+#include <asm/byteorder.h>
 #include <asm/machdep.h>
 #include <asm/blinken.h>
 #include <asm/io.h>                               /* readb() and writeb() */
@@ -70,15 +72,15 @@ extern int hp300_setup_serial_console(void) __init;
 int __init hp300_parse_bootinfo(const struct bi_record *record)
 {
        int unknown = 0;
-       const unsigned long *data = record->data;
+       const void *data = record->data;
 
-       switch (record->tag) {
+       switch (be16_to_cpu(record->tag)) {
        case BI_HP300_MODEL:
-               hp300_model = *data;
+               hp300_model = be32_to_cpup(data);
                break;
 
        case BI_HP300_UART_SCODE:
-               hp300_uart_scode = *data;
+               hp300_uart_scode = be32_to_cpup(data);
                break;
 
        case BI_HP300_UART_ADDR:
index 7a19b5686a4a69255f94c96aab86c382d461e482..5ad568110f1728701bab85c80c783910740cb069 100644 (file)
 
 #include <linux/ioport.h>
 
-    /*
-     *  Different Amiga models
-     */
-
-#define AMI_UNKNOWN    (0)
-#define AMI_500                (1)
-#define AMI_500PLUS    (2)
-#define AMI_600                (3)
-#define AMI_1000       (4)
-#define AMI_1200       (5)
-#define AMI_2000       (6)
-#define AMI_2500       (7)
-#define AMI_3000       (8)
-#define AMI_3000T      (9)
-#define AMI_3000PLUS   (10)
-#define AMI_4000       (11)
-#define AMI_4000T      (12)
-#define AMI_CDTV       (13)
-#define AMI_CD32       (14)
-#define AMI_DRACO      (15)
+#include <asm/bootinfo-amiga.h>
 
 
     /*
 
 extern unsigned long amiga_chipset;
 
-#define CS_STONEAGE    (0)
-#define CS_OCS         (1)
-#define CS_ECS         (2)
-#define CS_AGA         (3)
-
 
     /*
      *  Miscellaneous
@@ -266,7 +242,7 @@ struct CIA {
 
 #define zTwoBase (0x80000000)
 #define ZTWO_PADDR(x) (((unsigned long)(x))-zTwoBase)
-#define ZTWO_VADDR(x) (((unsigned long)(x))+zTwoBase)
+#define ZTWO_VADDR(x) ((void __iomem *)(((unsigned long)(x))+zTwoBase))
 
 #define CUSTOM_PHYSADDR     (0xdff000)
 #define amiga_custom ((*(volatile struct CUSTOM *)(zTwoBase+CUSTOM_PHYSADDR)))
index 6c19e0c22411a2bd4f7b76c2daf228e462f1eb27..87fc899d32eeba4fa057d52ce172e25fa8bb0664 100644 (file)
@@ -5,18 +5,11 @@
 
 #include <linux/types.h>
 
-/*
-   apollo models
-*/
+#include <asm/bootinfo-apollo.h>
+
 
 extern u_long apollo_model;
 
-#define APOLLO_UNKNOWN (0)
-#define APOLLO_DN3000 (1)
-#define APOLLO_DN3010 (2)
-#define APOLLO_DN3500 (3)
-#define APOLLO_DN4000 (4)
-#define APOLLO_DN4500 (5)
 
 /*
    see scn2681 data sheet for more info.
index d887050e6da6438516f0884c78ed9eb9889e2eda..972c8f33f05532c5bb6576471ca0ff4466f8b81d 100644 (file)
@@ -21,7 +21,7 @@
 #define _LINUX_ATARIHW_H_
 
 #include <linux/types.h>
-#include <asm/bootinfo.h>
+#include <asm/bootinfo-atari.h>
 #include <asm/raw_io.h>
 
 extern u_long atari_mch_cookie;
index 67e7a78ad96be0c0a6c069fc2dbb399729f20eba..8e213267f8e7165054c35f9d81dab22481467fa4 100644 (file)
 ** 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.
-**
-** Created 09/29/92 by Greg Harp
-**
-** 5/2/94 Roman Hodek:
-**   Added bi_atari part of the machine dependent union bi_un; for now it
-**   contains just a model field to distinguish between TT and Falcon.
-** 26/7/96 Roman Zippel:
-**   Renamed to setup.h; added some useful macros to allow gcc some
-**   optimizations if possible.
-** 5/10/96 Geert Uytterhoeven:
-**   Redesign of the boot information structure; renamed to bootinfo.h again
-** 27/11/96 Geert Uytterhoeven:
-**   Backwards compatibility with bootinfo interface version 1.0
 */
 
 #ifndef _M68K_BOOTINFO_H
 #define _M68K_BOOTINFO_H
 
+#include <uapi/asm/bootinfo.h>
 
-    /*
-     *  Bootinfo definitions
-     *
-     *  This is an easily parsable and extendable structure containing all
-     *  information to be passed from the bootstrap to the kernel.
-     *
-     *  This way I hope to keep all future changes back/forewards compatible.
-     *  Thus, keep your fingers crossed...
-     *
-     *  This structure is copied right after the kernel bss by the bootstrap
-     *  routine.
-     */
 
 #ifndef __ASSEMBLY__
 
-struct bi_record {
-    unsigned short tag;                        /* tag ID */
-    unsigned short size;               /* size of record (in bytes) */
-    unsigned long data[0];             /* data */
-};
-
-#endif /* __ASSEMBLY__ */
-
-
-    /*
-     *  Tag Definitions
-     *
-     *  Machine independent tags start counting from 0x0000
-     *  Machine dependent tags start counting from 0x8000
-     */
-
-#define BI_LAST                        0x0000  /* last record (sentinel) */
-#define BI_MACHTYPE            0x0001  /* machine type (u_long) */
-#define BI_CPUTYPE             0x0002  /* cpu type (u_long) */
-#define BI_FPUTYPE             0x0003  /* fpu type (u_long) */
-#define BI_MMUTYPE             0x0004  /* mmu type (u_long) */
-#define BI_MEMCHUNK            0x0005  /* memory chunk address and size */
-                                       /* (struct mem_info) */
-#define BI_RAMDISK             0x0006  /* ramdisk address and size */
-                                       /* (struct mem_info) */
-#define BI_COMMAND_LINE                0x0007  /* kernel command line parameters */
-                                       /* (string) */
-
-    /*
-     *  Amiga-specific tags
-     */
-
-#define BI_AMIGA_MODEL         0x8000  /* model (u_long) */
-#define BI_AMIGA_AUTOCON       0x8001  /* AutoConfig device */
-                                       /* (struct ConfigDev) */
-#define BI_AMIGA_CHIP_SIZE     0x8002  /* size of Chip RAM (u_long) */
-#define BI_AMIGA_VBLANK                0x8003  /* VBLANK frequency (u_char) */
-#define BI_AMIGA_PSFREQ                0x8004  /* power supply frequency (u_char) */
-#define BI_AMIGA_ECLOCK                0x8005  /* EClock frequency (u_long) */
-#define BI_AMIGA_CHIPSET       0x8006  /* native chipset present (u_long) */
-#define BI_AMIGA_SERPER                0x8007  /* serial port period (u_short) */
-
-    /*
-     *  Atari-specific tags
-     */
-
-#define BI_ATARI_MCH_COOKIE    0x8000  /* _MCH cookie from TOS (u_long) */
-#define BI_ATARI_MCH_TYPE      0x8001  /* special machine type (u_long) */
-                                       /* (values are ATARI_MACH_* defines */
-
-/* mch_cookie values (upper word) */
-#define ATARI_MCH_ST           0
-#define ATARI_MCH_STE          1
-#define ATARI_MCH_TT           2
-#define ATARI_MCH_FALCON       3
-
-/* mch_type values */
-#define ATARI_MACH_NORMAL      0       /* no special machine type */
-#define ATARI_MACH_MEDUSA      1       /* Medusa 040 */
-#define ATARI_MACH_HADES       2       /* Hades 040 or 060 */
-#define ATARI_MACH_AB40                3       /* Afterburner040 on Falcon */
-
-    /*
-     *  VME-specific tags
-     */
-
-#define BI_VME_TYPE            0x8000  /* VME sub-architecture (u_long) */
-#define BI_VME_BRDINFO         0x8001  /* VME board information (struct) */
-
-/* BI_VME_TYPE codes */
-#define        VME_TYPE_TP34V          0x0034  /* Tadpole TP34V */
-#define VME_TYPE_MVME147       0x0147  /* Motorola MVME147 */
-#define VME_TYPE_MVME162       0x0162  /* Motorola MVME162 */
-#define VME_TYPE_MVME166       0x0166  /* Motorola MVME166 */
-#define VME_TYPE_MVME167       0x0167  /* Motorola MVME167 */
-#define VME_TYPE_MVME172       0x0172  /* Motorola MVME172 */
-#define VME_TYPE_MVME177       0x0177  /* Motorola MVME177 */
-#define VME_TYPE_BVME4000      0x4000  /* BVM Ltd. BVME4000 */
-#define VME_TYPE_BVME6000      0x6000  /* BVM Ltd. BVME6000 */
-
-/* BI_VME_BRDINFO is a 32 byte struct as returned by the Bug code on
- * Motorola VME boards.  Contains board number, Bug version, board
- * configuration options, etc.  See include/asm/mvme16xhw.h for details.
- */
-
-
-    /*
-     *  Macintosh-specific tags (all u_long)
-     */
-
-#define BI_MAC_MODEL           0x8000  /* Mac Gestalt ID (model type) */
-#define BI_MAC_VADDR           0x8001  /* Mac video base address */
-#define BI_MAC_VDEPTH          0x8002  /* Mac video depth */
-#define BI_MAC_VROW            0x8003  /* Mac video rowbytes */
-#define BI_MAC_VDIM            0x8004  /* Mac video dimensions */
-#define BI_MAC_VLOGICAL                0x8005  /* Mac video logical base */
-#define BI_MAC_SCCBASE         0x8006  /* Mac SCC base address */
-#define BI_MAC_BTIME           0x8007  /* Mac boot time */
-#define BI_MAC_GMTBIAS         0x8008  /* Mac GMT timezone offset */
-#define BI_MAC_MEMSIZE         0x8009  /* Mac RAM size (sanity check) */
-#define BI_MAC_CPUID           0x800a  /* Mac CPU type (sanity check) */
-#define BI_MAC_ROMBASE         0x800b  /* Mac system ROM base address */
-
-    /*
-     *  Macintosh hardware profile data - unused, see macintosh.h for
-     *  reasonable type values
-     */
-
-#define BI_MAC_VIA1BASE                0x8010  /* Mac VIA1 base address (always present) */
-#define BI_MAC_VIA2BASE                0x8011  /* Mac VIA2 base address (type varies) */
-#define BI_MAC_VIA2TYPE                0x8012  /* Mac VIA2 type (VIA, RBV, OSS) */
-#define BI_MAC_ADBTYPE         0x8013  /* Mac ADB interface type */
-#define BI_MAC_ASCBASE         0x8014  /* Mac Apple Sound Chip base address */
-#define BI_MAC_SCSI5380                0x8015  /* Mac NCR 5380 SCSI (base address, multi) */
-#define BI_MAC_SCSIDMA         0x8016  /* Mac SCSI DMA (base address) */
-#define BI_MAC_SCSI5396                0x8017  /* Mac NCR 53C96 SCSI (base address, multi) */
-#define BI_MAC_IDETYPE         0x8018  /* Mac IDE interface type */
-#define BI_MAC_IDEBASE         0x8019  /* Mac IDE interface base address */
-#define BI_MAC_NUBUS           0x801a  /* Mac Nubus type (none, regular, pseudo) */
-#define BI_MAC_SLOTMASK                0x801b  /* Mac Nubus slots present */
-#define BI_MAC_SCCTYPE         0x801c  /* Mac SCC serial type (normal, IOP) */
-#define BI_MAC_ETHTYPE         0x801d  /* Mac builtin ethernet type (Sonic, MACE */
-#define BI_MAC_ETHBASE         0x801e  /* Mac builtin ethernet base address */
-#define BI_MAC_PMU             0x801f  /* Mac power management / poweroff hardware */
-#define BI_MAC_IOP_SWIM                0x8020  /* Mac SWIM floppy IOP */
-#define BI_MAC_IOP_ADB         0x8021  /* Mac ADB IOP */
-
-    /*
-     * Mac: compatibility with old booter data format (temporarily)
-     * Fields unused with the new bootinfo can be deleted now; instead of
-     * adding new fields the struct might be splitted into a hardware address
-     * part and a hardware type part
-     */
-
-#ifndef __ASSEMBLY__
-
-struct mac_booter_data
-{
-       unsigned long videoaddr;
-       unsigned long videorow;
-       unsigned long videodepth;
-       unsigned long dimensions;
-       unsigned long args;
-       unsigned long boottime;
-       unsigned long gmtbias;
-       unsigned long bootver;
-       unsigned long videological;
-       unsigned long sccbase;
-       unsigned long id;
-       unsigned long memsize;
-       unsigned long serialmf;
-       unsigned long serialhsk;
-       unsigned long serialgpi;
-       unsigned long printmf;
-       unsigned long printhsk;
-       unsigned long printgpi;
-       unsigned long cpuid;
-       unsigned long rombase;
-       unsigned long adbdelay;
-       unsigned long timedbra;
-};
-
-extern struct mac_booter_data
-       mac_bi_data;
-
+#ifdef CONFIG_BOOTINFO_PROC
+extern void save_bootinfo(const struct bi_record *bi);
+#else
+static inline void save_bootinfo(const struct bi_record *bi) {}
 #endif
 
-    /*
-     *  Apollo-specific tags
-     */
-
-#define BI_APOLLO_MODEL         0x8000  /* model (u_long) */
-
-    /*
-     *  HP300-specific tags
-     */
-
-#define BI_HP300_MODEL         0x8000  /* model (u_long) */
-#define BI_HP300_UART_SCODE    0x8001  /* UART select code (u_long) */
-#define BI_HP300_UART_ADDR     0x8002  /* phys. addr of UART (u_long) */
-
-    /*
-     * Stuff for bootinfo interface versioning
-     *
-     * At the start of kernel code, a 'struct bootversion' is located.
-     * bootstrap checks for a matching version of the interface before booting
-     * a kernel, to avoid user confusion if kernel and bootstrap don't work
-     * together :-)
-     *
-     * If incompatible changes are made to the bootinfo interface, the major
-     * number below should be stepped (and the minor reset to 0) for the
-     * appropriate machine. If a change is backward-compatible, the minor
-     * should be stepped. "Backwards-compatible" means that booting will work,
-     * but certain features may not.
-     */
-
-#define BOOTINFOV_MAGIC                        0x4249561A      /* 'BIV^Z' */
-#define MK_BI_VERSION(major,minor)     (((major)<<16)+(minor))
-#define BI_VERSION_MAJOR(v)            (((v) >> 16) & 0xffff)
-#define BI_VERSION_MINOR(v)            ((v) & 0xffff)
-
-#ifndef __ASSEMBLY__
-
-struct bootversion {
-    unsigned short branch;
-    unsigned long magic;
-    struct {
-       unsigned long machtype;
-       unsigned long version;
-    } machversions[0];
-};
-
 #endif /* __ASSEMBLY__ */
 
-#define AMIGA_BOOTI_VERSION    MK_BI_VERSION( 2, 0 )
-#define ATARI_BOOTI_VERSION    MK_BI_VERSION( 2, 1 )
-#define MAC_BOOTI_VERSION      MK_BI_VERSION( 2, 0 )
-#define MVME147_BOOTI_VERSION  MK_BI_VERSION( 2, 0 )
-#define MVME16x_BOOTI_VERSION  MK_BI_VERSION( 2, 0 )
-#define BVME6000_BOOTI_VERSION MK_BI_VERSION( 2, 0 )
-#define Q40_BOOTI_VERSION      MK_BI_VERSION( 2, 0 )
-#define HP300_BOOTI_VERSION    MK_BI_VERSION( 2, 0 )
-
-#ifdef BOOTINFO_COMPAT_1_0
-
-    /*
-     *  Backwards compatibility with bootinfo interface version 1.0
-     */
-
-#define COMPAT_AMIGA_BOOTI_VERSION    MK_BI_VERSION( 1, 0 )
-#define COMPAT_ATARI_BOOTI_VERSION    MK_BI_VERSION( 1, 0 )
-#define COMPAT_MAC_BOOTI_VERSION      MK_BI_VERSION( 1, 0 )
-
-#include <linux/zorro.h>
-
-#define COMPAT_NUM_AUTO    16
-
-struct compat_bi_Amiga {
-    int model;
-    int num_autocon;
-    struct ConfigDev autocon[COMPAT_NUM_AUTO];
-    unsigned long chip_size;
-    unsigned char vblank;
-    unsigned char psfreq;
-    unsigned long eclock;
-    unsigned long chipset;
-    unsigned long hw_present;
-};
-
-struct compat_bi_Atari {
-    unsigned long hw_present;
-    unsigned long mch_cookie;
-};
-
-#ifndef __ASSEMBLY__
-
-struct compat_bi_Macintosh
-{
-       unsigned long videoaddr;
-       unsigned long videorow;
-       unsigned long videodepth;
-       unsigned long dimensions;
-       unsigned long args;
-       unsigned long boottime;
-       unsigned long gmtbias;
-       unsigned long bootver;
-       unsigned long videological;
-       unsigned long sccbase;
-       unsigned long id;
-       unsigned long memsize;
-       unsigned long serialmf;
-       unsigned long serialhsk;
-       unsigned long serialgpi;
-       unsigned long printmf;
-       unsigned long printhsk;
-       unsigned long printgpi;
-       unsigned long cpuid;
-       unsigned long rombase;
-       unsigned long adbdelay;
-       unsigned long timedbra;
-};
-
-#endif
-
-struct compat_mem_info {
-    unsigned long addr;
-    unsigned long size;
-};
-
-#define COMPAT_NUM_MEMINFO  4
-
-#define COMPAT_CPUB_68020 0
-#define COMPAT_CPUB_68030 1
-#define COMPAT_CPUB_68040 2
-#define COMPAT_CPUB_68060 3
-#define COMPAT_FPUB_68881 5
-#define COMPAT_FPUB_68882 6
-#define COMPAT_FPUB_68040 7
-#define COMPAT_FPUB_68060 8
-
-#define COMPAT_CPU_68020    (1<<COMPAT_CPUB_68020)
-#define COMPAT_CPU_68030    (1<<COMPAT_CPUB_68030)
-#define COMPAT_CPU_68040    (1<<COMPAT_CPUB_68040)
-#define COMPAT_CPU_68060    (1<<COMPAT_CPUB_68060)
-#define COMPAT_CPU_MASK     (31)
-#define COMPAT_FPU_68881    (1<<COMPAT_FPUB_68881)
-#define COMPAT_FPU_68882    (1<<COMPAT_FPUB_68882)
-#define COMPAT_FPU_68040    (1<<COMPAT_FPUB_68040)
-#define COMPAT_FPU_68060    (1<<COMPAT_FPUB_68060)
-#define COMPAT_FPU_MASK     (0xfe0)
-
-#define COMPAT_CL_SIZE      (256)
-
-struct compat_bootinfo {
-    unsigned long machtype;
-    unsigned long cputype;
-    struct compat_mem_info memory[COMPAT_NUM_MEMINFO];
-    int num_memory;
-    unsigned long ramdisk_size;
-    unsigned long ramdisk_addr;
-    char command_line[COMPAT_CL_SIZE];
-    union {
-       struct compat_bi_Amiga     bi_ami;
-       struct compat_bi_Atari     bi_ata;
-       struct compat_bi_Macintosh bi_mac;
-    } bi_un;
-};
-
-#define bi_amiga       bi_un.bi_ami
-#define bi_atari       bi_un.bi_ata
-#define bi_mac         bi_un.bi_mac
-
-#endif /* BOOTINFO_COMPAT_1_0 */
-
 
 #endif /* _M68K_BOOTINFO_H */
index d998ea67c19c34d8fd1c005629bffecb9771d7cb..64f5271dd7be2ec70f4503af410a7af48362dfad 100644 (file)
@@ -1,25 +1,9 @@
 #ifndef _M68K_HP300HW_H
 #define _M68K_HP300HW_H
 
-extern unsigned long hp300_model;
+#include <asm/bootinfo-hp300.h>
 
-/* This information was taken from NetBSD */
-#define        HP_320          (0)     /* 16MHz 68020+HP MMU+16K external cache */
-#define        HP_330          (1)     /* 16MHz 68020+68851 MMU */
-#define        HP_340          (2)     /* 16MHz 68030 */
-#define        HP_345          (3)     /* 50MHz 68030+32K external cache */
-#define        HP_350          (4)     /* 25MHz 68020+HP MMU+32K external cache */
-#define        HP_360          (5)     /* 25MHz 68030 */
-#define        HP_370          (6)     /* 33MHz 68030+64K external cache */
-#define        HP_375          (7)     /* 50MHz 68030+32K external cache */
-#define        HP_380          (8)     /* 25MHz 68040 */
-#define        HP_385          (9)     /* 33MHz 68040 */
 
-#define        HP_400          (10)    /* 50MHz 68030+32K external cache */
-#define        HP_425T         (11)    /* 25MHz 68040 - model 425t */
-#define        HP_425S         (12)    /* 25MHz 68040 - model 425s */
-#define HP_425E                (13)    /* 25MHz 68040 - model 425e */
-#define HP_433T                (14)    /* 33MHz 68040 - model 433t */
-#define HP_433S                (15)    /* 33MHz 68040 - model 433s */
+extern unsigned long hp300_model;
 
 #endif /* _M68K_HP300HW_H */
diff --git a/arch/m68k/include/asm/kexec.h b/arch/m68k/include/asm/kexec.h
new file mode 100644 (file)
index 0000000..3df97ab
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef _ASM_M68K_KEXEC_H
+#define _ASM_M68K_KEXEC_H
+
+#ifdef CONFIG_KEXEC
+
+/* Maximum physical address we can use pages from */
+#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
+/* Maximum address we can reach in physical address mode */
+#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL)
+/* Maximum address we can use for the control code buffer */
+#define KEXEC_CONTROL_MEMORY_LIMIT (-1UL)
+
+#define KEXEC_CONTROL_PAGE_SIZE        4096
+
+#define KEXEC_ARCH KEXEC_ARCH_68K
+
+#ifndef __ASSEMBLY__
+
+static inline void crash_setup_regs(struct pt_regs *newregs,
+                                   struct pt_regs *oldregs)
+{
+       /* Dummy implementation for now */
+}
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* CONFIG_KEXEC */
+
+#endif /* _ASM_M68K_KEXEC_H */
index 682a1a2ff55f931ceeeac2f812d5254a75d1810b..d323b2c2d07d4e9a574da7e7f97d7a21bca08b6f 100644 (file)
@@ -4,6 +4,9 @@
 #include <linux/seq_file.h>
 #include <linux/interrupt.h>
 
+#include <asm/bootinfo-mac.h>
+
+
 /*
  *     Apple Macintoshisms
  */
@@ -74,65 +77,29 @@ struct mac_model
 #define MAC_FLOPPY_SWIM_IOP    3
 #define MAC_FLOPPY_AV          4
 
-/*
- *     Gestalt numbers
- */
+extern struct mac_model *macintosh_config;
 
-#define MAC_MODEL_II           6
-#define MAC_MODEL_IIX          7
-#define MAC_MODEL_IICX         8
-#define MAC_MODEL_SE30         9
-#define MAC_MODEL_IICI         11
-#define MAC_MODEL_IIFX         13      /* And well numbered it is too */
-#define MAC_MODEL_IISI         18
-#define MAC_MODEL_LC           19
-#define MAC_MODEL_Q900         20
-#define MAC_MODEL_PB170                21
-#define MAC_MODEL_Q700         22
-#define MAC_MODEL_CLII         23      /* aka: P200 */
-#define MAC_MODEL_PB140                25
-#define MAC_MODEL_Q950         26      /* aka: WGS95 */
-#define MAC_MODEL_LCIII                27      /* aka: P450 */
-#define MAC_MODEL_PB210                29
-#define MAC_MODEL_C650         30
-#define MAC_MODEL_PB230                32
-#define MAC_MODEL_PB180                33
-#define MAC_MODEL_PB160                34
-#define MAC_MODEL_Q800         35      /* aka: WGS80 */
-#define MAC_MODEL_Q650         36
-#define MAC_MODEL_LCII         37      /* aka: P400/405/410/430 */
-#define MAC_MODEL_PB250                38
-#define MAC_MODEL_IIVI         44
-#define MAC_MODEL_P600         45      /* aka: P600CD */
-#define MAC_MODEL_IIVX         48
-#define MAC_MODEL_CCL          49      /* aka: P250 */
-#define MAC_MODEL_PB165C       50
-#define MAC_MODEL_C610         52      /* aka: WGS60 */
-#define MAC_MODEL_Q610         53
-#define MAC_MODEL_PB145                54      /* aka: PB145B */
-#define MAC_MODEL_P520         56      /* aka: LC520 */
-#define MAC_MODEL_C660         60
-#define MAC_MODEL_P460         62      /* aka: LCIII+, P466/P467 */
-#define MAC_MODEL_PB180C       71
-#define MAC_MODEL_PB520                72      /* aka: PB520C, PB540, PB540C, PB550C */
-#define MAC_MODEL_PB270C       77
-#define MAC_MODEL_Q840         78
-#define MAC_MODEL_P550         80      /* aka: LC550, P560 */
-#define MAC_MODEL_CCLII                83      /* aka: P275 */
-#define MAC_MODEL_PB165                84
-#define MAC_MODEL_PB190                85      /* aka: PB190CS */
-#define MAC_MODEL_TV           88
-#define MAC_MODEL_P475         89      /* aka: LC475, P476 */
-#define MAC_MODEL_P475F                90      /* aka: P475 w/ FPU (no LC040) */
-#define MAC_MODEL_P575         92      /* aka: LC575, P577/P578 */
-#define MAC_MODEL_Q605         94
-#define MAC_MODEL_Q605_ACC     95      /* Q605 accelerated to 33 MHz */
-#define MAC_MODEL_Q630         98      /* aka: LC630, P630/631/635/636/637/638/640 */
-#define MAC_MODEL_P588         99      /* aka: LC580, P580 */
-#define MAC_MODEL_PB280                102
-#define MAC_MODEL_PB280C       103
-#define MAC_MODEL_PB150                115
 
-extern struct mac_model *macintosh_config;
+    /*
+     * Internal representation of the Mac hardware, filled in from bootinfo
+     */
+
+struct mac_booter_data
+{
+       unsigned long videoaddr;
+       unsigned long videorow;
+       unsigned long videodepth;
+       unsigned long dimensions;
+       unsigned long boottime;
+       unsigned long gmtbias;
+       unsigned long videological;
+       unsigned long sccbase;
+       unsigned long id;
+       unsigned long memsize;
+       unsigned long cpuid;
+       unsigned long rombase;
+};
+
+extern struct mac_booter_data mac_bi_data;
 
 #endif
index 9f70a01f73dc9960e00817963aceb75b5e89db24..05b43bf5cdf3909f7ea23b2da4ed4dbb6d9dd9bb 100644 (file)
 
 #include <asm/atarihw.h>
 
-#define RTC_PORT(x)    (TT_RTC_BAS + 2*(x))
+#define ATARI_RTC_PORT(x)      (TT_RTC_BAS + 2*(x))
 #define RTC_ALWAYS_BCD 0
 
 #define CMOS_READ(addr) ({ \
-atari_outb_p((addr),RTC_PORT(0)); \
-atari_inb_p(RTC_PORT(1)); \
+atari_outb_p((addr), ATARI_RTC_PORT(0)); \
+atari_inb_p(ATARI_RTC_PORT(1)); \
 })
 #define CMOS_WRITE(val, addr) ({ \
-atari_outb_p((addr),RTC_PORT(0)); \
-atari_outb_p((val),RTC_PORT(1)); \
+atari_outb_p((addr), ATARI_RTC_PORT(0)); \
+atari_outb_p((val), ATARI_RTC_PORT(1)); \
 })
 #endif /* CONFIG_ATARI */
 
index 6117f56653d28d3c14bcbee597a552b18cf6cecd..1eb89de631e5c09d1be76d0c043d2e467906b9a6 100644 (file)
@@ -3,23 +3,6 @@
 
 #include <asm/irq.h>
 
-/* Board ID data structure - pointer to this retrieved from Bug by head.S */
-
-/* Note, bytes 12 and 13 are board no in BCD (0162,0166,0167,0177,etc) */
-
-extern long mvme_bdid_ptr;
-
-typedef struct {
-       char    bdid[4];
-       u_char  rev, mth, day, yr;
-       u_short size, reserved;
-       u_short brdno;
-       char brdsuffix[2];
-       u_long  options;
-       u_short clun, dlun, ctype, dnum;
-       u_long  option2;
-} t_bdid, *p_bdid;
-
 
 typedef struct {
        u_char  ack_icr,
index 65e78a2dad64a9840fdb96bdc898e8b848f52331..8f2023f8c1c45727a6904d0567fb070e9f8b7364 100644 (file)
@@ -22,6 +22,7 @@
 #ifndef _M68K_SETUP_H
 #define _M68K_SETUP_H
 
+#include <uapi/asm/bootinfo.h>
 #include <uapi/asm/setup.h>
 
 
@@ -297,14 +298,14 @@ extern int m68k_is040or060;
 #define NUM_MEMINFO    4
 
 #ifndef __ASSEMBLY__
-struct mem_info {
+struct m68k_mem_info {
        unsigned long addr;             /* physical address of memory chunk */
        unsigned long size;             /* length of memory chunk (in bytes) */
 };
 
 extern int m68k_num_memory;            /* # of memory blocks found (and used) */
 extern int m68k_realnum_memory;                /* real # of memory blocks found */
-extern struct mem_info m68k_memory[NUM_MEMINFO];/* memory description */
+extern struct m68k_mem_info m68k_memory[NUM_MEMINFO];/* memory description */
 #endif
 
 #endif /* _M68K_SETUP_H */
index 6759dad954f61d9a3d40800f63cf95179c8129aa..efc1f48923573d4731806326b1e72395775fde3d 100644 (file)
@@ -28,4 +28,14 @@ static inline cycles_t get_cycles(void)
        return 0;
 }
 
+extern unsigned long (*mach_random_get_entropy)(void);
+
+static inline unsigned long random_get_entropy(void)
+{
+       if (mach_random_get_entropy)
+               return mach_random_get_entropy();
+       return 0;
+}
+#define random_get_entropy     random_get_entropy
+
 #endif
index 1fef45ada0973c7d83494f42c0c780ebc18f5ca3..6a2d257bdfb2224492f8f901575d17cc9b4f82d7 100644 (file)
@@ -11,6 +11,14 @@ generic-y += termbits.h
 generic-y += termios.h
 
 header-y += a.out.h
+header-y += bootinfo.h
+header-y += bootinfo-amiga.h
+header-y += bootinfo-apollo.h
+header-y += bootinfo-atari.h
+header-y += bootinfo-hp300.h
+header-y += bootinfo-mac.h
+header-y += bootinfo-q40.h
+header-y += bootinfo-vme.h
 header-y += byteorder.h
 header-y += cachectl.h
 header-y += fcntl.h
diff --git a/arch/m68k/include/uapi/asm/bootinfo-amiga.h b/arch/m68k/include/uapi/asm/bootinfo-amiga.h
new file mode 100644 (file)
index 0000000..daad3c5
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+** asm/bootinfo-amiga.h -- Amiga-specific boot information definitions
+*/
+
+#ifndef _UAPI_ASM_M68K_BOOTINFO_AMIGA_H
+#define _UAPI_ASM_M68K_BOOTINFO_AMIGA_H
+
+
+    /*
+     *  Amiga-specific tags
+     */
+
+#define BI_AMIGA_MODEL         0x8000  /* model (__be32) */
+#define BI_AMIGA_AUTOCON       0x8001  /* AutoConfig device */
+                                       /* (AmigaOS struct ConfigDev) */
+#define BI_AMIGA_CHIP_SIZE     0x8002  /* size of Chip RAM (__be32) */
+#define BI_AMIGA_VBLANK                0x8003  /* VBLANK frequency (__u8) */
+#define BI_AMIGA_PSFREQ                0x8004  /* power supply frequency (__u8) */
+#define BI_AMIGA_ECLOCK                0x8005  /* EClock frequency (__be32) */
+#define BI_AMIGA_CHIPSET       0x8006  /* native chipset present (__be32) */
+#define BI_AMIGA_SERPER                0x8007  /* serial port period (__be16) */
+
+
+    /*
+     *  Amiga models (BI_AMIGA_MODEL)
+     */
+
+#define AMI_UNKNOWN            0
+#define AMI_500                        1
+#define AMI_500PLUS            2
+#define AMI_600                        3
+#define AMI_1000               4
+#define AMI_1200               5
+#define AMI_2000               6
+#define AMI_2500               7
+#define AMI_3000               8
+#define AMI_3000T              9
+#define AMI_3000PLUS           10
+#define AMI_4000               11
+#define AMI_4000T              12
+#define AMI_CDTV               13
+#define AMI_CD32               14
+#define AMI_DRACO              15
+
+
+    /*
+     *  Amiga chipsets (BI_AMIGA_CHIPSET)
+     */
+
+#define CS_STONEAGE            0
+#define CS_OCS                 1
+#define CS_ECS                 2
+#define CS_AGA                 3
+
+
+    /*
+     *  Latest Amiga bootinfo version
+     */
+
+#define AMIGA_BOOTI_VERSION    MK_BI_VERSION(2, 0)
+
+
+#endif /* _UAPI_ASM_M68K_BOOTINFO_AMIGA_H */
diff --git a/arch/m68k/include/uapi/asm/bootinfo-apollo.h b/arch/m68k/include/uapi/asm/bootinfo-apollo.h
new file mode 100644 (file)
index 0000000..a93e0af
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+** asm/bootinfo-apollo.h -- Apollo-specific boot information definitions
+*/
+
+#ifndef _UAPI_ASM_M68K_BOOTINFO_APOLLO_H
+#define _UAPI_ASM_M68K_BOOTINFO_APOLLO_H
+
+
+    /*
+     *  Apollo-specific tags
+     */
+
+#define BI_APOLLO_MODEL                0x8000  /* model (__be32) */
+
+
+    /*
+     *  Apollo models (BI_APOLLO_MODEL)
+     */
+
+#define APOLLO_UNKNOWN         0
+#define APOLLO_DN3000          1
+#define APOLLO_DN3010          2
+#define APOLLO_DN3500          3
+#define APOLLO_DN4000          4
+#define APOLLO_DN4500          5
+
+
+#endif /* _UAPI_ASM_M68K_BOOTINFO_APOLLO_H */
diff --git a/arch/m68k/include/uapi/asm/bootinfo-atari.h b/arch/m68k/include/uapi/asm/bootinfo-atari.h
new file mode 100644 (file)
index 0000000..a817854
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+** asm/bootinfo-atari.h -- Atari-specific boot information definitions
+*/
+
+#ifndef _UAPI_ASM_M68K_BOOTINFO_ATARI_H
+#define _UAPI_ASM_M68K_BOOTINFO_ATARI_H
+
+
+    /*
+     *  Atari-specific tags
+     */
+
+#define BI_ATARI_MCH_COOKIE    0x8000  /* _MCH cookie from TOS (__be32) */
+#define BI_ATARI_MCH_TYPE      0x8001  /* special machine type (__be32) */
+
+
+    /*
+     *  mch_cookie values (upper word of BI_ATARI_MCH_COOKIE)
+     */
+
+#define ATARI_MCH_ST           0
+#define ATARI_MCH_STE          1
+#define ATARI_MCH_TT           2
+#define ATARI_MCH_FALCON       3
+
+
+    /*
+     *  Atari machine types (BI_ATARI_MCH_TYPE)
+     */
+
+#define ATARI_MACH_NORMAL      0       /* no special machine type */
+#define ATARI_MACH_MEDUSA      1       /* Medusa 040 */
+#define ATARI_MACH_HADES       2       /* Hades 040 or 060 */
+#define ATARI_MACH_AB40                3       /* Afterburner040 on Falcon */
+
+
+    /*
+     *  Latest Atari bootinfo version
+     */
+
+#define ATARI_BOOTI_VERSION    MK_BI_VERSION(2, 1)
+
+
+#endif /* _UAPI_ASM_M68K_BOOTINFO_ATARI_H */
diff --git a/arch/m68k/include/uapi/asm/bootinfo-hp300.h b/arch/m68k/include/uapi/asm/bootinfo-hp300.h
new file mode 100644 (file)
index 0000000..c90cb71
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+** asm/bootinfo-hp300.h -- HP9000/300-specific boot information definitions
+*/
+
+#ifndef _UAPI_ASM_M68K_BOOTINFO_HP300_H
+#define _UAPI_ASM_M68K_BOOTINFO_HP300_H
+
+
+    /*
+     *  HP9000/300-specific tags
+     */
+
+#define BI_HP300_MODEL         0x8000  /* model (__be32) */
+#define BI_HP300_UART_SCODE    0x8001  /* UART select code (__be32) */
+#define BI_HP300_UART_ADDR     0x8002  /* phys. addr of UART (__be32) */
+
+
+    /*
+     *  HP9000/300 and /400 models (BI_HP300_MODEL)
+     *
+     * This information was taken from NetBSD
+     */
+
+#define HP_320         0       /* 16MHz 68020+HP MMU+16K external cache */
+#define HP_330         1       /* 16MHz 68020+68851 MMU */
+#define HP_340         2       /* 16MHz 68030 */
+#define HP_345         3       /* 50MHz 68030+32K external cache */
+#define HP_350         4       /* 25MHz 68020+HP MMU+32K external cache */
+#define HP_360         5       /* 25MHz 68030 */
+#define HP_370         6       /* 33MHz 68030+64K external cache */
+#define HP_375         7       /* 50MHz 68030+32K external cache */
+#define HP_380         8       /* 25MHz 68040 */
+#define HP_385         9       /* 33MHz 68040 */
+
+#define HP_400         10      /* 50MHz 68030+32K external cache */
+#define HP_425T                11      /* 25MHz 68040 - model 425t */
+#define HP_425S                12      /* 25MHz 68040 - model 425s */
+#define HP_425E                13      /* 25MHz 68040 - model 425e */
+#define HP_433T                14      /* 33MHz 68040 - model 433t */
+#define HP_433S                15      /* 33MHz 68040 - model 433s */
+
+
+    /*
+     *  Latest HP9000/300 bootinfo version
+     */
+
+#define HP300_BOOTI_VERSION    MK_BI_VERSION(2, 0)
+
+
+#endif /* _UAPI_ASM_M68K_BOOTINFO_HP300_H */
diff --git a/arch/m68k/include/uapi/asm/bootinfo-mac.h b/arch/m68k/include/uapi/asm/bootinfo-mac.h
new file mode 100644 (file)
index 0000000..b44ff73
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+** asm/bootinfo-mac.h -- Macintosh-specific boot information definitions
+*/
+
+#ifndef _UAPI_ASM_M68K_BOOTINFO_MAC_H
+#define _UAPI_ASM_M68K_BOOTINFO_MAC_H
+
+
+    /*
+     *  Macintosh-specific tags (all __be32)
+     */
+
+#define BI_MAC_MODEL           0x8000  /* Mac Gestalt ID (model type) */
+#define BI_MAC_VADDR           0x8001  /* Mac video base address */
+#define BI_MAC_VDEPTH          0x8002  /* Mac video depth */
+#define BI_MAC_VROW            0x8003  /* Mac video rowbytes */
+#define BI_MAC_VDIM            0x8004  /* Mac video dimensions */
+#define BI_MAC_VLOGICAL                0x8005  /* Mac video logical base */
+#define BI_MAC_SCCBASE         0x8006  /* Mac SCC base address */
+#define BI_MAC_BTIME           0x8007  /* Mac boot time */
+#define BI_MAC_GMTBIAS         0x8008  /* Mac GMT timezone offset */
+#define BI_MAC_MEMSIZE         0x8009  /* Mac RAM size (sanity check) */
+#define BI_MAC_CPUID           0x800a  /* Mac CPU type (sanity check) */
+#define BI_MAC_ROMBASE         0x800b  /* Mac system ROM base address */
+
+
+    /*
+     *  Macintosh hardware profile data - unused, see macintosh.h for
+     *  reasonable type values
+     */
+
+#define BI_MAC_VIA1BASE                0x8010  /* Mac VIA1 base address (always present) */
+#define BI_MAC_VIA2BASE                0x8011  /* Mac VIA2 base address (type varies) */
+#define BI_MAC_VIA2TYPE                0x8012  /* Mac VIA2 type (VIA, RBV, OSS) */
+#define BI_MAC_ADBTYPE         0x8013  /* Mac ADB interface type */
+#define BI_MAC_ASCBASE         0x8014  /* Mac Apple Sound Chip base address */
+#define BI_MAC_SCSI5380                0x8015  /* Mac NCR 5380 SCSI (base address, multi) */
+#define BI_MAC_SCSIDMA         0x8016  /* Mac SCSI DMA (base address) */
+#define BI_MAC_SCSI5396                0x8017  /* Mac NCR 53C96 SCSI (base address, multi) */
+#define BI_MAC_IDETYPE         0x8018  /* Mac IDE interface type */
+#define BI_MAC_IDEBASE         0x8019  /* Mac IDE interface base address */
+#define BI_MAC_NUBUS           0x801a  /* Mac Nubus type (none, regular, pseudo) */
+#define BI_MAC_SLOTMASK                0x801b  /* Mac Nubus slots present */
+#define BI_MAC_SCCTYPE         0x801c  /* Mac SCC serial type (normal, IOP) */
+#define BI_MAC_ETHTYPE         0x801d  /* Mac builtin ethernet type (Sonic, MACE */
+#define BI_MAC_ETHBASE         0x801e  /* Mac builtin ethernet base address */
+#define BI_MAC_PMU             0x801f  /* Mac power management / poweroff hardware */
+#define BI_MAC_IOP_SWIM                0x8020  /* Mac SWIM floppy IOP */
+#define BI_MAC_IOP_ADB         0x8021  /* Mac ADB IOP */
+
+
+    /*
+     * Macintosh Gestalt numbers (BI_MAC_MODEL)
+     */
+
+#define MAC_MODEL_II           6
+#define MAC_MODEL_IIX          7
+#define MAC_MODEL_IICX         8
+#define MAC_MODEL_SE30         9
+#define MAC_MODEL_IICI         11
+#define MAC_MODEL_IIFX         13      /* And well numbered it is too */
+#define MAC_MODEL_IISI         18
+#define MAC_MODEL_LC           19
+#define MAC_MODEL_Q900         20
+#define MAC_MODEL_PB170                21
+#define MAC_MODEL_Q700         22
+#define MAC_MODEL_CLII         23      /* aka: P200 */
+#define MAC_MODEL_PB140                25
+#define MAC_MODEL_Q950         26      /* aka: WGS95 */
+#define MAC_MODEL_LCIII                27      /* aka: P450 */
+#define MAC_MODEL_PB210                29
+#define MAC_MODEL_C650         30
+#define MAC_MODEL_PB230                32
+#define MAC_MODEL_PB180                33
+#define MAC_MODEL_PB160                34
+#define MAC_MODEL_Q800         35      /* aka: WGS80 */
+#define MAC_MODEL_Q650         36
+#define MAC_MODEL_LCII         37      /* aka: P400/405/410/430 */
+#define MAC_MODEL_PB250                38
+#define MAC_MODEL_IIVI         44
+#define MAC_MODEL_P600         45      /* aka: P600CD */
+#define MAC_MODEL_IIVX         48
+#define MAC_MODEL_CCL          49      /* aka: P250 */
+#define MAC_MODEL_PB165C       50
+#define MAC_MODEL_C610         52      /* aka: WGS60 */
+#define MAC_MODEL_Q610         53
+#define MAC_MODEL_PB145                54      /* aka: PB145B */
+#define MAC_MODEL_P520         56      /* aka: LC520 */
+#define MAC_MODEL_C660         60
+#define MAC_MODEL_P460         62      /* aka: LCIII+, P466/P467 */
+#define MAC_MODEL_PB180C       71
+#define MAC_MODEL_PB520                72      /* aka: PB520C, PB540, PB540C, PB550C */
+#define MAC_MODEL_PB270C       77
+#define MAC_MODEL_Q840         78
+#define MAC_MODEL_P550         80      /* aka: LC550, P560 */
+#define MAC_MODEL_CCLII                83      /* aka: P275 */
+#define MAC_MODEL_PB165                84
+#define MAC_MODEL_PB190                85      /* aka: PB190CS */
+#define MAC_MODEL_TV           88
+#define MAC_MODEL_P475         89      /* aka: LC475, P476 */
+#define MAC_MODEL_P475F                90      /* aka: P475 w/ FPU (no LC040) */
+#define MAC_MODEL_P575         92      /* aka: LC575, P577/P578 */
+#define MAC_MODEL_Q605         94
+#define MAC_MODEL_Q605_ACC     95      /* Q605 accelerated to 33 MHz */
+#define MAC_MODEL_Q630         98      /* aka: LC630, P630/631/635/636/637/638/640 */
+#define MAC_MODEL_P588         99      /* aka: LC580, P580 */
+#define MAC_MODEL_PB280                102
+#define MAC_MODEL_PB280C       103
+#define MAC_MODEL_PB150                115
+
+
+    /*
+     *  Latest Macintosh bootinfo version
+     */
+
+#define MAC_BOOTI_VERSION      MK_BI_VERSION(2, 0)
+
+
+#endif /* _UAPI_ASM_M68K_BOOTINFO_MAC_H */
diff --git a/arch/m68k/include/uapi/asm/bootinfo-q40.h b/arch/m68k/include/uapi/asm/bootinfo-q40.h
new file mode 100644 (file)
index 0000000..c79fea7
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+** asm/bootinfo-q40.h -- Q40-specific boot information definitions
+*/
+
+#ifndef _UAPI_ASM_M68K_BOOTINFO_Q40_H
+#define _UAPI_ASM_M68K_BOOTINFO_Q40_H
+
+
+    /*
+     *  Latest Q40 bootinfo version
+     */
+
+#define Q40_BOOTI_VERSION      MK_BI_VERSION(2, 0)
+
+
+#endif /* _UAPI_ASM_M68K_BOOTINFO_Q40_H */
diff --git a/arch/m68k/include/uapi/asm/bootinfo-vme.h b/arch/m68k/include/uapi/asm/bootinfo-vme.h
new file mode 100644 (file)
index 0000000..a135eb4
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+** asm/bootinfo-vme.h -- VME-specific boot information definitions
+*/
+
+#ifndef _UAPI_ASM_M68K_BOOTINFO_VME_H
+#define _UAPI_ASM_M68K_BOOTINFO_VME_H
+
+
+#include <linux/types.h>
+
+
+    /*
+     *  VME-specific tags
+     */
+
+#define BI_VME_TYPE            0x8000  /* VME sub-architecture (__be32) */
+#define BI_VME_BRDINFO         0x8001  /* VME board information (struct) */
+
+
+    /*
+     *  VME models (BI_VME_TYPE)
+     */
+
+#define VME_TYPE_TP34V         0x0034  /* Tadpole TP34V */
+#define VME_TYPE_MVME147       0x0147  /* Motorola MVME147 */
+#define VME_TYPE_MVME162       0x0162  /* Motorola MVME162 */
+#define VME_TYPE_MVME166       0x0166  /* Motorola MVME166 */
+#define VME_TYPE_MVME167       0x0167  /* Motorola MVME167 */
+#define VME_TYPE_MVME172       0x0172  /* Motorola MVME172 */
+#define VME_TYPE_MVME177       0x0177  /* Motorola MVME177 */
+#define VME_TYPE_BVME4000      0x4000  /* BVM Ltd. BVME4000 */
+#define VME_TYPE_BVME6000      0x6000  /* BVM Ltd. BVME6000 */
+
+
+#ifndef __ASSEMBLY__
+
+/*
+ * Board ID data structure - pointer to this retrieved from Bug by head.S
+ *
+ * BI_VME_BRDINFO is a 32 byte struct as returned by the Bug code on
+ * Motorola VME boards.  Contains board number, Bug version, board
+ * configuration options, etc.
+ *
+ * Note, bytes 12 and 13 are board no in BCD (0162,0166,0167,0177,etc)
+ */
+
+typedef struct {
+       char    bdid[4];
+       __u8    rev, mth, day, yr;
+       __be16  size, reserved;
+       __be16  brdno;
+       char    brdsuffix[2];
+       __be32  options;
+       __be16  clun, dlun, ctype, dnum;
+       __be32  option2;
+} t_bdid, *p_bdid;
+
+#endif /* __ASSEMBLY__ */
+
+
+    /*
+     *  Latest VME bootinfo versions
+     */
+
+#define MVME147_BOOTI_VERSION  MK_BI_VERSION(2, 0)
+#define MVME16x_BOOTI_VERSION  MK_BI_VERSION(2, 0)
+#define BVME6000_BOOTI_VERSION MK_BI_VERSION(2, 0)
+
+
+#endif /* _UAPI_ASM_M68K_BOOTINFO_VME_H */
diff --git a/arch/m68k/include/uapi/asm/bootinfo.h b/arch/m68k/include/uapi/asm/bootinfo.h
new file mode 100644 (file)
index 0000000..cdeb26a
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * asm/bootinfo.h -- Definition of the Linux/m68k boot information structure
+ *
+ * Copyright 1992 by Greg Harp
+ *
+ * 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 _UAPI_ASM_M68K_BOOTINFO_H
+#define _UAPI_ASM_M68K_BOOTINFO_H
+
+
+#include <linux/types.h>
+
+
+#ifndef __ASSEMBLY__
+
+    /*
+     *  Bootinfo definitions
+     *
+     *  This is an easily parsable and extendable structure containing all
+     *  information to be passed from the bootstrap to the kernel.
+     *
+     *  This way I hope to keep all future changes back/forewards compatible.
+     *  Thus, keep your fingers crossed...
+     *
+     *  This structure is copied right after the kernel by the bootstrap
+     *  routine.
+     */
+
+struct bi_record {
+       __be16 tag;                     /* tag ID */
+       __be16 size;                    /* size of record (in bytes) */
+       __be32 data[0];                 /* data */
+};
+
+
+struct mem_info {
+       __be32 addr;                    /* physical address of memory chunk */
+       __be32 size;                    /* length of memory chunk (in bytes) */
+};
+
+#endif /* __ASSEMBLY__ */
+
+
+    /*
+     *  Tag Definitions
+     *
+     *  Machine independent tags start counting from 0x0000
+     *  Machine dependent tags start counting from 0x8000
+     */
+
+#define BI_LAST                        0x0000  /* last record (sentinel) */
+#define BI_MACHTYPE            0x0001  /* machine type (__be32) */
+#define BI_CPUTYPE             0x0002  /* cpu type (__be32) */
+#define BI_FPUTYPE             0x0003  /* fpu type (__be32) */
+#define BI_MMUTYPE             0x0004  /* mmu type (__be32) */
+#define BI_MEMCHUNK            0x0005  /* memory chunk address and size */
+                                       /* (struct mem_info) */
+#define BI_RAMDISK             0x0006  /* ramdisk address and size */
+                                       /* (struct mem_info) */
+#define BI_COMMAND_LINE                0x0007  /* kernel command line parameters */
+                                       /* (string) */
+
+
+    /*
+     *  Linux/m68k Architectures (BI_MACHTYPE)
+     */
+
+#define MACH_AMIGA             1
+#define MACH_ATARI             2
+#define MACH_MAC               3
+#define MACH_APOLLO            4
+#define MACH_SUN3              5
+#define MACH_MVME147           6
+#define MACH_MVME16x           7
+#define MACH_BVME6000          8
+#define MACH_HP300             9
+#define MACH_Q40               10
+#define MACH_SUN3X             11
+#define MACH_M54XX             12
+
+
+    /*
+     *  CPU, FPU and MMU types (BI_CPUTYPE, BI_FPUTYPE, BI_MMUTYPE)
+     *
+     *  Note: we may rely on the following equalities:
+     *
+     *      CPU_68020 == MMU_68851
+     *      CPU_68030 == MMU_68030
+     *      CPU_68040 == FPU_68040 == MMU_68040
+     *      CPU_68060 == FPU_68060 == MMU_68060
+     */
+
+#define CPUB_68020             0
+#define CPUB_68030             1
+#define CPUB_68040             2
+#define CPUB_68060             3
+#define CPUB_COLDFIRE          4
+
+#define CPU_68020              (1 << CPUB_68020)
+#define CPU_68030              (1 << CPUB_68030)
+#define CPU_68040              (1 << CPUB_68040)
+#define CPU_68060              (1 << CPUB_68060)
+#define CPU_COLDFIRE           (1 << CPUB_COLDFIRE)
+
+#define FPUB_68881             0
+#define FPUB_68882             1
+#define FPUB_68040             2       /* Internal FPU */
+#define FPUB_68060             3       /* Internal FPU */
+#define FPUB_SUNFPA            4       /* Sun-3 FPA */
+#define FPUB_COLDFIRE          5       /* ColdFire FPU */
+
+#define FPU_68881              (1 << FPUB_68881)
+#define FPU_68882              (1 << FPUB_68882)
+#define FPU_68040              (1 << FPUB_68040)
+#define FPU_68060              (1 << FPUB_68060)
+#define FPU_SUNFPA             (1 << FPUB_SUNFPA)
+#define FPU_COLDFIRE           (1 << FPUB_COLDFIRE)
+
+#define MMUB_68851             0
+#define MMUB_68030             1       /* Internal MMU */
+#define MMUB_68040             2       /* Internal MMU */
+#define MMUB_68060             3       /* Internal MMU */
+#define MMUB_APOLLO            4       /* Custom Apollo */
+#define MMUB_SUN3              5       /* Custom Sun-3 */
+#define MMUB_COLDFIRE          6       /* Internal MMU */
+
+#define MMU_68851              (1 << MMUB_68851)
+#define MMU_68030              (1 << MMUB_68030)
+#define MMU_68040              (1 << MMUB_68040)
+#define MMU_68060              (1 << MMUB_68060)
+#define MMU_SUN3               (1 << MMUB_SUN3)
+#define MMU_APOLLO             (1 << MMUB_APOLLO)
+#define MMU_COLDFIRE           (1 << MMUB_COLDFIRE)
+
+
+    /*
+     * Stuff for bootinfo interface versioning
+     *
+     * At the start of kernel code, a 'struct bootversion' is located.
+     * bootstrap checks for a matching version of the interface before booting
+     * a kernel, to avoid user confusion if kernel and bootstrap don't work
+     * together :-)
+     *
+     * If incompatible changes are made to the bootinfo interface, the major
+     * number below should be stepped (and the minor reset to 0) for the
+     * appropriate machine. If a change is backward-compatible, the minor
+     * should be stepped. "Backwards-compatible" means that booting will work,
+     * but certain features may not.
+     */
+
+#define BOOTINFOV_MAGIC                        0x4249561A      /* 'BIV^Z' */
+#define MK_BI_VERSION(major, minor)    (((major) << 16) + (minor))
+#define BI_VERSION_MAJOR(v)            (((v) >> 16) & 0xffff)
+#define BI_VERSION_MINOR(v)            ((v) & 0xffff)
+
+#ifndef __ASSEMBLY__
+
+struct bootversion {
+       __be16 branch;
+       __be32 magic;
+       struct {
+               __be32 machtype;
+               __be32 version;
+       } machversions[0];
+} __packed;
+
+#endif /* __ASSEMBLY__ */
+
+
+#endif /* _UAPI_ASM_M68K_BOOTINFO_H */
index 85579bff455ccb32fc7f9e805d0f78383c053245..6a6dc636761eaa210844f10614ad1633cff41bc3 100644 (file)
@@ -6,98 +6,11 @@
 ** 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.
-**
-** Created 09/29/92 by Greg Harp
-**
-** 5/2/94 Roman Hodek:
-**   Added bi_atari part of the machine dependent union bi_un; for now it
-**   contains just a model field to distinguish between TT and Falcon.
-** 26/7/96 Roman Zippel:
-**   Renamed to setup.h; added some useful macros to allow gcc some
-**   optimizations if possible.
-** 5/10/96 Geert Uytterhoeven:
-**   Redesign of the boot information structure; moved boot information
-**   structure to bootinfo.h
 */
 
 #ifndef _UAPI_M68K_SETUP_H
 #define _UAPI_M68K_SETUP_H
 
-
-
-    /*
-     *  Linux/m68k Architectures
-     */
-
-#define MACH_AMIGA    1
-#define MACH_ATARI    2
-#define MACH_MAC      3
-#define MACH_APOLLO   4
-#define MACH_SUN3     5
-#define MACH_MVME147  6
-#define MACH_MVME16x  7
-#define MACH_BVME6000 8
-#define MACH_HP300    9
-#define MACH_Q40     10
-#define MACH_SUN3X   11
-#define MACH_M54XX   12
-
 #define COMMAND_LINE_SIZE 256
 
-
-
-    /*
-     *  CPU, FPU and MMU types
-     *
-     *  Note: we may rely on the following equalities:
-     *
-     *      CPU_68020 == MMU_68851
-     *      CPU_68030 == MMU_68030
-     *      CPU_68040 == FPU_68040 == MMU_68040
-     *      CPU_68060 == FPU_68060 == MMU_68060
-     */
-
-#define CPUB_68020     0
-#define CPUB_68030     1
-#define CPUB_68040     2
-#define CPUB_68060     3
-#define CPUB_COLDFIRE  4
-
-#define CPU_68020      (1<<CPUB_68020)
-#define CPU_68030      (1<<CPUB_68030)
-#define CPU_68040      (1<<CPUB_68040)
-#define CPU_68060      (1<<CPUB_68060)
-#define CPU_COLDFIRE   (1<<CPUB_COLDFIRE)
-
-#define FPUB_68881     0
-#define FPUB_68882     1
-#define FPUB_68040     2                       /* Internal FPU */
-#define FPUB_68060     3                       /* Internal FPU */
-#define FPUB_SUNFPA    4                       /* Sun-3 FPA */
-#define FPUB_COLDFIRE  5                       /* ColdFire FPU */
-
-#define FPU_68881      (1<<FPUB_68881)
-#define FPU_68882      (1<<FPUB_68882)
-#define FPU_68040      (1<<FPUB_68040)
-#define FPU_68060      (1<<FPUB_68060)
-#define FPU_SUNFPA     (1<<FPUB_SUNFPA)
-#define FPU_COLDFIRE   (1<<FPUB_COLDFIRE)
-
-#define MMUB_68851     0
-#define MMUB_68030     1                       /* Internal MMU */
-#define MMUB_68040     2                       /* Internal MMU */
-#define MMUB_68060     3                       /* Internal MMU */
-#define MMUB_APOLLO    4                       /* Custom Apollo */
-#define MMUB_SUN3      5                       /* Custom Sun-3 */
-#define MMUB_COLDFIRE  6                       /* Internal MMU */
-
-#define MMU_68851      (1<<MMUB_68851)
-#define MMU_68030      (1<<MMUB_68030)
-#define MMU_68040      (1<<MMUB_68040)
-#define MMU_68060      (1<<MMUB_68060)
-#define MMU_SUN3       (1<<MMUB_SUN3)
-#define MMU_APOLLO     (1<<MMUB_APOLLO)
-#define MMU_COLDFIRE   (1<<MMUB_COLDFIRE)
-
-
 #endif /* _UAPI_M68K_SETUP_H */
index 655347d807801e3543412c5aaedc550f3ebdef80..2d5d9be162732dae6ae603622e3572e1d0349523 100644 (file)
@@ -22,3 +22,6 @@ obj-$(CONFIG_PCI) += pcibios.o
 
 obj-$(CONFIG_HAS_DMA)  += dma.o
 
+obj-$(CONFIG_KEXEC)            += machine_kexec.o relocate_kernel.o
+obj-$(CONFIG_BOOTINFO_PROC)    += bootinfo_proc.o
+
index 8b7b228463667da0145f9d7e821172553822d20d..3a386341aa6e282336a5ceea41b248fc45943191 100644 (file)
@@ -98,6 +98,9 @@ int main(void)
        DEFINE(CIABBASE, &ciab);
        DEFINE(C_PRA, offsetof(struct CIA, pra));
        DEFINE(ZTWOBASE, zTwoBase);
+
+       /* enum m68k_fixup_type */
+       DEFINE(M68K_FIXUP_MEMOFFSET, m68k_fixup_memoffset);
 #endif
 
        return 0;
diff --git a/arch/m68k/kernel/bootinfo_proc.c b/arch/m68k/kernel/bootinfo_proc.c
new file mode 100644 (file)
index 0000000..7ee853e
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Based on arch/arm/kernel/atags_proc.c
+ */
+
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/printk.h>
+#include <linux/proc_fs.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+#include <asm/byteorder.h>
+
+
+static char bootinfo_tmp[1536] __initdata;
+
+static void *bootinfo_copy;
+static size_t bootinfo_size;
+
+static ssize_t bootinfo_read(struct file *file, char __user *buf,
+                         size_t count, loff_t *ppos)
+{
+       return simple_read_from_buffer(buf, count, ppos, bootinfo_copy,
+                                      bootinfo_size);
+}
+
+static const struct file_operations bootinfo_fops = {
+       .read = bootinfo_read,
+       .llseek = default_llseek,
+};
+
+void __init save_bootinfo(const struct bi_record *bi)
+{
+       const void *start = bi;
+       size_t size = sizeof(bi->tag);
+
+       while (be16_to_cpu(bi->tag) != BI_LAST) {
+               uint16_t n = be16_to_cpu(bi->size);
+               size += n;
+               bi = (struct bi_record *)((unsigned long)bi + n);
+       }
+
+       if (size > sizeof(bootinfo_tmp)) {
+               pr_err("Cannot save %zu bytes of bootinfo\n", size);
+               return;
+       }
+
+       pr_info("Saving %zu bytes of bootinfo\n", size);
+       memcpy(bootinfo_tmp, start, size);
+       bootinfo_size = size;
+}
+
+static int __init init_bootinfo_procfs(void)
+{
+       /*
+        * This cannot go into save_bootinfo() because kmalloc and proc don't
+        * work yet when it is called.
+        */
+       struct proc_dir_entry *pde;
+
+       if (!bootinfo_size)
+               return -EINVAL;
+
+       bootinfo_copy = kmalloc(bootinfo_size, GFP_KERNEL);
+       if (!bootinfo_copy)
+               return -ENOMEM;
+
+       memcpy(bootinfo_copy, bootinfo_tmp, bootinfo_size);
+
+       pde = proc_create_data("bootinfo", 0400, NULL, &bootinfo_fops, NULL);
+       if (!pde) {
+               kfree(bootinfo_copy);
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+arch_initcall(init_bootinfo_procfs);
index ac85f16534af929c33d0f1daf1f3a565488b6af4..7d7913f5dce3beabd14ecac0afdc66109ee30e55 100644 (file)
@@ -23,7 +23,7 @@
 ** 98/04/25 Phil Blundell: added HP300 support
 ** 1998/08/30 David Kilzer: Added support for font_desc structures
 **            for linux-2.1.115
-** 9/02/11  Richard Zidlicky: added Q40 support (initial vesion 99/01/01)
+** 1999/02/11  Richard Zidlicky: added Q40 support (initial version 99/01/01)
 ** 2004/05/13 Kars de Jong: Finalised HP300 support
 **
 ** This file is subject to the terms and conditions of the GNU General Public
 #include <linux/linkage.h>
 #include <linux/init.h>
 #include <asm/bootinfo.h>
+#include <asm/bootinfo-amiga.h>
+#include <asm/bootinfo-atari.h>
+#include <asm/bootinfo-hp300.h>
+#include <asm/bootinfo-mac.h>
+#include <asm/bootinfo-q40.h>
+#include <asm/bootinfo-vme.h>
 #include <asm/setup.h>
 #include <asm/entry.h>
 #include <asm/pgtable.h>
@@ -1532,7 +1538,7 @@ L(cache_done):
 
 /*
  * Find a tag record in the bootinfo structure
- * The bootinfo structure is located right after the kernel bss
+ * The bootinfo structure is located right after the kernel
  * Returns: d0: size (-1 if not found)
  *          a0: data pointer (end-of-records if not found)
  */
@@ -3896,8 +3902,6 @@ BVME_SCC_DATA_A   = 0xffb0000f
 #endif
 
 #if defined(CONFIG_MAC)
-L(mac_booter_data):
-       .long   0
 L(mac_videobase):
        .long   0
 L(mac_videodepth):
diff --git a/arch/m68k/kernel/machine_kexec.c b/arch/m68k/kernel/machine_kexec.c
new file mode 100644 (file)
index 0000000..d4affc9
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * machine_kexec.c - handle transition of Linux booting another kernel
+ */
+#include <linux/compiler.h>
+#include <linux/kexec.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+
+#include <asm/cacheflush.h>
+#include <asm/page.h>
+#include <asm/setup.h>
+
+extern const unsigned char relocate_new_kernel[];
+extern const size_t relocate_new_kernel_size;
+
+int machine_kexec_prepare(struct kimage *kimage)
+{
+       return 0;
+}
+
+void machine_kexec_cleanup(struct kimage *kimage)
+{
+}
+
+void machine_shutdown(void)
+{
+}
+
+void machine_crash_shutdown(struct pt_regs *regs)
+{
+}
+
+typedef void (*relocate_kernel_t)(unsigned long ptr,
+                                 unsigned long start,
+                                 unsigned long cpu_mmu_flags) __noreturn;
+
+void machine_kexec(struct kimage *image)
+{
+       void *reboot_code_buffer;
+       unsigned long cpu_mmu_flags;
+
+       reboot_code_buffer = page_address(image->control_code_page);
+
+       memcpy(reboot_code_buffer, relocate_new_kernel,
+              relocate_new_kernel_size);
+
+       /*
+        * we do not want to be bothered.
+        */
+       local_irq_disable();
+
+       pr_info("Will call new kernel at 0x%08lx. Bye...\n", image->start);
+       __flush_cache_all();
+       cpu_mmu_flags = m68k_cputype | m68k_mmutype << 8;
+       ((relocate_kernel_t) reboot_code_buffer)(image->head & PAGE_MASK,
+                                                image->start,
+                                                cpu_mmu_flags);
+}
diff --git a/arch/m68k/kernel/relocate_kernel.S b/arch/m68k/kernel/relocate_kernel.S
new file mode 100644 (file)
index 0000000..3e09a89
--- /dev/null
@@ -0,0 +1,159 @@
+#include <linux/linkage.h>
+
+#include <asm/asm-offsets.h>
+#include <asm/page.h>
+#include <asm/setup.h>
+
+
+#define MMU_BASE       8               /* MMU flags base in cpu_mmu_flags */
+
+.text
+
+ENTRY(relocate_new_kernel)
+       movel %sp@(4),%a0               /* a0 = ptr */
+       movel %sp@(8),%a1               /* a1 = start */
+       movel %sp@(12),%d1              /* d1 = cpu_mmu_flags */
+       movew #PAGE_MASK,%d2            /* d2 = PAGE_MASK */
+
+       /* Disable MMU */
+
+       btst #MMU_BASE + MMUB_68851,%d1
+       jeq 3f
+
+1:     /* 68851 or 68030 */
+
+       lea %pc@(.Lcopy),%a4
+2:     addl #0x00000000,%a4            /* virt_to_phys() */
+
+       .section ".m68k_fixup","aw"
+       .long M68K_FIXUP_MEMOFFSET, 2b+2
+       .previous
+
+       .chip 68030
+       pmove %tc,%d0                   /* Disable MMU */
+       bclr #7,%d0
+       pmove %d0,%tc
+       jmp %a4@                        /* Jump to physical .Lcopy */
+       .chip 68k
+
+3:
+       btst #MMU_BASE + MMUB_68030,%d1
+       jne 1b
+
+       btst #MMU_BASE + MMUB_68040,%d1
+       jeq 6f
+
+4:     /* 68040 or 68060 */
+
+       lea %pc@(.Lcont040),%a4
+5:     addl #0x00000000,%a4            /* virt_to_phys() */
+
+       .section ".m68k_fixup","aw"
+       .long M68K_FIXUP_MEMOFFSET, 5b+2
+       .previous
+
+       movel %a4,%d0
+       andl #0xff000000,%d0
+       orw #0xe020,%d0                 /* Map 16 MiB, enable, cacheable */
+       .chip 68040
+       movec %d0,%itt0
+       movec %d0,%dtt0
+       .chip 68k
+       jmp %a4@                        /* Jump to physical .Lcont040 */
+
+.Lcont040:
+       moveq #0,%d0
+       .chip 68040
+       movec %d0,%tc                   /* Disable MMU */
+       movec %d0,%itt0
+       movec %d0,%itt1
+       movec %d0,%dtt0
+       movec %d0,%dtt1
+       .chip 68k
+       jra .Lcopy
+
+6:
+       btst #MMU_BASE + MMUB_68060,%d1
+       jne 4b
+
+.Lcopy:
+       movel %a0@+,%d0                 /* d0 = entry = *ptr */
+       jeq .Lflush
+
+       btst #2,%d0                     /* entry & IND_DONE? */
+       jne .Lflush
+
+       btst #1,%d0                     /* entry & IND_INDIRECTION? */
+       jeq 1f
+       andw %d2,%d0
+       movel %d0,%a0                   /* ptr = entry & PAGE_MASK */
+       jra .Lcopy
+
+1:
+       btst #0,%d0                     /* entry & IND_DESTINATION? */
+       jeq 2f
+       andw %d2,%d0
+       movel %d0,%a2                   /* a2 = dst = entry & PAGE_MASK */
+       jra .Lcopy
+
+2:
+       btst #3,%d0                     /* entry & IND_SOURCE? */
+       jeq .Lcopy
+
+       andw %d2,%d0
+       movel %d0,%a3                   /* a3 = src = entry & PAGE_MASK */
+       movew #PAGE_SIZE/32 - 1,%d0     /* d0 = PAGE_SIZE/32 - 1 */
+3:
+       movel %a3@+,%a2@+               /* *dst++ = *src++ */
+       movel %a3@+,%a2@+               /* *dst++ = *src++ */
+       movel %a3@+,%a2@+               /* *dst++ = *src++ */
+       movel %a3@+,%a2@+               /* *dst++ = *src++ */
+       movel %a3@+,%a2@+               /* *dst++ = *src++ */
+       movel %a3@+,%a2@+               /* *dst++ = *src++ */
+       movel %a3@+,%a2@+               /* *dst++ = *src++ */
+       movel %a3@+,%a2@+               /* *dst++ = *src++ */
+       dbf %d0, 3b
+       jra .Lcopy
+
+.Lflush:
+       /* Flush all caches */
+
+       btst #CPUB_68020,%d1
+       jeq 2f
+
+1:     /* 68020 or 68030 */
+       .chip 68030
+       movec %cacr,%d0
+       orw #0x808,%d0
+       movec %d0,%cacr
+       .chip 68k
+       jra .Lreincarnate
+
+2:
+       btst #CPUB_68030,%d1
+       jne 1b
+
+       btst #CPUB_68040,%d1
+       jeq 4f
+
+3:     /* 68040 or 68060 */
+       .chip 68040
+       nop
+       cpusha %bc
+       nop
+       cinva %bc
+       nop
+       .chip 68k
+       jra .Lreincarnate
+
+4:
+       btst #CPUB_68060,%d1
+       jne 3b
+
+.Lreincarnate:
+       jmp %a1@
+
+relocate_new_kernel_end:
+
+ENTRY(relocate_new_kernel_size)
+       .long relocate_new_kernel_end - relocate_new_kernel
index e67e53159573a81d0db7da0d93464766e47ab264..5b8ec4d5f8e8d79d1becaa48d489d0117374daa8 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/initrd.h>
 
 #include <asm/bootinfo.h>
+#include <asm/byteorder.h>
 #include <asm/sections.h>
 #include <asm/setup.h>
 #include <asm/fpu.h>
@@ -71,12 +72,12 @@ EXPORT_SYMBOL(m68k_num_memory);
 int m68k_realnum_memory;
 EXPORT_SYMBOL(m68k_realnum_memory);
 unsigned long m68k_memoffset;
-struct mem_info m68k_memory[NUM_MEMINFO];
+struct m68k_mem_info m68k_memory[NUM_MEMINFO];
 EXPORT_SYMBOL(m68k_memory);
 
-struct mem_info m68k_ramdisk;
+static struct m68k_mem_info m68k_ramdisk __initdata;
 
-static char m68k_command_line[CL_SIZE];
+static char m68k_command_line[CL_SIZE] __initdata;
 
 void (*mach_sched_init) (irq_handler_t handler) __initdata = NULL;
 /* machine dependent irq functions */
@@ -143,11 +144,16 @@ extern void paging_init(void);
 
 static void __init m68k_parse_bootinfo(const struct bi_record *record)
 {
-       while (record->tag != BI_LAST) {
+       uint16_t tag;
+
+       save_bootinfo(record);
+
+       while ((tag = be16_to_cpu(record->tag)) != BI_LAST) {
                int unknown = 0;
-               const unsigned long *data = record->data;
+               const void *data = record->data;
+               uint16_t size = be16_to_cpu(record->size);
 
-               switch (record->tag) {
+               switch (tag) {
                case BI_MACHTYPE:
                case BI_CPUTYPE:
                case BI_FPUTYPE:
@@ -157,20 +163,27 @@ static void __init m68k_parse_bootinfo(const struct bi_record *record)
 
                case BI_MEMCHUNK:
                        if (m68k_num_memory < NUM_MEMINFO) {
-                               m68k_memory[m68k_num_memory].addr = data[0];
-                               m68k_memory[m68k_num_memory].size = data[1];
+                               const struct mem_info *m = data;
+                               m68k_memory[m68k_num_memory].addr =
+                                       be32_to_cpu(m->addr);
+                               m68k_memory[m68k_num_memory].size =
+                                       be32_to_cpu(m->size);
                                m68k_num_memory++;
                        } else
-                               printk("m68k_parse_bootinfo: too many memory chunks\n");
+                               pr_warn("%s: too many memory chunks\n",
+                                       __func__);
                        break;
 
                case BI_RAMDISK:
-                       m68k_ramdisk.addr = data[0];
-                       m68k_ramdisk.size = data[1];
+                       {
+                               const struct mem_info *m = data;
+                               m68k_ramdisk.addr = be32_to_cpu(m->addr);
+                               m68k_ramdisk.size = be32_to_cpu(m->size);
+                       }
                        break;
 
                case BI_COMMAND_LINE:
-                       strlcpy(m68k_command_line, (const char *)data,
+                       strlcpy(m68k_command_line, data,
                                sizeof(m68k_command_line));
                        break;
 
@@ -197,17 +210,16 @@ static void __init m68k_parse_bootinfo(const struct bi_record *record)
                                unknown = 1;
                }
                if (unknown)
-                       printk("m68k_parse_bootinfo: unknown tag 0x%04x ignored\n",
-                              record->tag);
-               record = (struct bi_record *)((unsigned long)record +
-                                             record->size);
+                       pr_warn("%s: unknown tag 0x%04x ignored\n", __func__,
+                               tag);
+               record = (struct bi_record *)((unsigned long)record + size);
        }
 
        m68k_realnum_memory = m68k_num_memory;
 #ifdef CONFIG_SINGLE_MEMORY_CHUNK
        if (m68k_num_memory > 1) {
-               printk("Ignoring last %i chunks of physical memory\n",
-                      (m68k_num_memory - 1));
+               pr_warn("%s: ignoring last %i chunks of physical memory\n",
+                       __func__, (m68k_num_memory - 1));
                m68k_num_memory = 1;
        }
 #endif
@@ -219,7 +231,7 @@ void __init setup_arch(char **cmdline_p)
        int i;
 #endif
 
-       /* The bootinfo is located right after the kernel bss */
+       /* The bootinfo is located right after the kernel */
        if (!CPU_IS_COLDFIRE)
                m68k_parse_bootinfo((const struct bi_record *)_end);
 
@@ -247,7 +259,7 @@ void __init setup_arch(char **cmdline_p)
                asm (".chip 68060; movec %%pcr,%0; .chip 68k"
                     : "=d" (pcr));
                if (((pcr >> 8) & 0xff) <= 5) {
-                       printk("Enabling workaround for errata I14\n");
+                       pr_warn("Enabling workaround for errata I14\n");
                        asm (".chip 68060; movec %0,%%pcr; .chip 68k"
                             : : "d" (pcr | 0x20));
                }
@@ -336,12 +348,12 @@ void __init setup_arch(char **cmdline_p)
                panic("No configuration setup");
        }
 
+       paging_init();
+
 #ifdef CONFIG_NATFEAT
        nf_init();
 #endif
 
-       paging_init();
-
 #ifndef CONFIG_SUN3
        for (i = 1; i < m68k_num_memory; i++)
                free_bootmem_node(NODE_DATA(i), m68k_memory[i].addr,
@@ -353,7 +365,7 @@ void __init setup_arch(char **cmdline_p)
                                     BOOTMEM_DEFAULT);
                initrd_start = (unsigned long)phys_to_virt(m68k_ramdisk.addr);
                initrd_end = initrd_start + m68k_ramdisk.size;
-               printk("initrd: %08lx - %08lx\n", initrd_start, initrd_end);
+               pr_info("initrd: %08lx - %08lx\n", initrd_start, initrd_end);
        }
 #endif
 
@@ -538,9 +550,9 @@ void check_bugs(void)
 {
 #ifndef CONFIG_M68KFPU_EMU
        if (m68k_fputype == 0) {
-               printk(KERN_EMERG "*** YOU DO NOT HAVE A FLOATING POINT UNIT, "
+               pr_emerg("*** YOU DO NOT HAVE A FLOATING POINT UNIT, "
                        "WHICH IS REQUIRED BY LINUX/M68K ***\n");
-               printk(KERN_EMERG "Upgrade your hardware or join the FPU "
+               pr_emerg("Upgrade your hardware or join the FPU "
                        "emulation project\n");
                panic("no FPU");
        }
index 7eb9792009f8994d4bddd0566b6da18649318cb1..958f1adb9d0c421eeec89d1cdbdf62361a866326 100644 (file)
 #include <linux/timex.h>
 #include <linux/profile.h>
 
+
+unsigned long (*mach_random_get_entropy)(void);
+
+
 /*
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "xtime_update()" routine every clocktick
index afb95d5fb26b3b29b172d730d8b5bacc4c3c664a..982c3fe73c4a45b45eeeff08e8d8446a47151c16 100644 (file)
 #include <linux/adb.h>
 #include <linux/cuda.h>
 
-#define BOOTINFO_COMPAT_1_0
 #include <asm/setup.h>
 #include <asm/bootinfo.h>
+#include <asm/bootinfo-mac.h>
+#include <asm/byteorder.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -107,45 +108,46 @@ static void __init mac_sched_init(irq_handler_t vector)
 int __init mac_parse_bootinfo(const struct bi_record *record)
 {
        int unknown = 0;
-       const u_long *data = record->data;
+       const void *data = record->data;
 
-       switch (record->tag) {
+       switch (be16_to_cpu(record->tag)) {
        case BI_MAC_MODEL:
-               mac_bi_data.id = *data;
+               mac_bi_data.id = be32_to_cpup(data);
                break;
        case BI_MAC_VADDR:
-               mac_bi_data.videoaddr = *data;
+               mac_bi_data.videoaddr = be32_to_cpup(data);
                break;
        case BI_MAC_VDEPTH:
-               mac_bi_data.videodepth = *data;
+               mac_bi_data.videodepth = be32_to_cpup(data);
                break;
        case BI_MAC_VROW:
-               mac_bi_data.videorow = *data;
+               mac_bi_data.videorow = be32_to_cpup(data);
                break;
        case BI_MAC_VDIM:
-               mac_bi_data.dimensions = *data;
+               mac_bi_data.dimensions = be32_to_cpup(data);
                break;
        case BI_MAC_VLOGICAL:
-               mac_bi_data.videological = VIDEOMEMBASE + (*data & ~VIDEOMEMMASK);
-               mac_orig_videoaddr = *data;
+               mac_orig_videoaddr = be32_to_cpup(data);
+               mac_bi_data.videological =
+                       VIDEOMEMBASE + (mac_orig_videoaddr & ~VIDEOMEMMASK);
                break;
        case BI_MAC_SCCBASE:
-               mac_bi_data.sccbase = *data;
+               mac_bi_data.sccbase = be32_to_cpup(data);
                break;
        case BI_MAC_BTIME:
-               mac_bi_data.boottime = *data;
+               mac_bi_data.boottime = be32_to_cpup(data);
                break;
        case BI_MAC_GMTBIAS:
-               mac_bi_data.gmtbias = *data;
+               mac_bi_data.gmtbias = be32_to_cpup(data);
                break;
        case BI_MAC_MEMSIZE:
-               mac_bi_data.memsize = *data;
+               mac_bi_data.memsize = be32_to_cpup(data);
                break;
        case BI_MAC_CPUID:
-               mac_bi_data.cpuid = *data;
+               mac_bi_data.cpuid = be32_to_cpup(data);
                break;
        case BI_MAC_ROMBASE:
-               mac_bi_data.rombase = *data;
+               mac_bi_data.rombase = be32_to_cpup(data);
                break;
        default:
                unknown = 1;
index 7d8d46127ad9fc91717dcb660ac9647d0b9708e4..4d2adfb32a2ab4f61951357114a8d053bf74de82 100644 (file)
 #include <linux/init.h>
 #include <linux/interrupt.h>
 
-#include <asm/bootinfo.h>
 #include <asm/macintosh.h>
 #include <asm/macints.h>
 #include <asm/mac_iop.h>
 
 /*#define DEBUG_IOP*/
 
-/* Set to non-zero if the IOPs are present. Set by iop_init() */
+/* Non-zero if the IOPs are present */
 
-int iop_scc_present,iop_ism_present;
+int iop_scc_present, iop_ism_present;
 
 /* structure for tracking channel listeners */
 
index 5e085554ac7f2bb9f0c3a964a30f001049804f8a..707b61aea2030c8f7de9058a2546a8eb85ce1639 100644 (file)
@@ -25,8 +25,6 @@
 #include <asm/mac_via.h>
 #include <asm/mac_oss.h>
 
-#define BOOTINFO_COMPAT_1_0
-#include <asm/bootinfo.h>
 #include <asm/machdep.h>
 
 /* Offset between Unix time (1970-based) and Mac time (1904-based) */
index 6c4c882c126e826e2d1b114f39acaf3e8b9ddc15..54037125ebf8c0e05c82cb937cb2560a7575244d 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 
-#include <asm/bootinfo.h>
 #include <asm/macintosh.h>
 #include <asm/macints.h>
 #include <asm/mac_via.h>
index 6f026fc302fab3ca70f6e05386a732ac52e1d985..835fa04511c85ad0d6e71ba8ee1f3a2dc26fcc1b 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/irq.h>
 
 #include <asm/traps.h>
-#include <asm/bootinfo.h>
 #include <asm/macintosh.h>
 #include <asm/macints.h>
 #include <asm/mac_psc.h>
@@ -54,7 +53,7 @@ static void psc_debug_dump(void)
  * expanded to cover what I think are the other 7 channels.
  */
 
-static void psc_dma_die_die_die(void)
+static __init void psc_dma_die_die_die(void)
 {
        int i;
 
index 5d1458bb871b8bd5e55eb25c5501067adef4810b..e198dec868e472e802768c5a9459e498e7623b00 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/module.h>
 #include <linux/irq.h>
 
-#include <asm/bootinfo.h>
 #include <asm/macintosh.h>
 #include <asm/macints.h>
 #include <asm/mac_via.h>
index 6b4baa6e4d31d8f24e09950d581f6ae9ab1cc6dd..acaff6a49e357e89154651f6ec57db9ab53f0459 100644 (file)
@@ -59,7 +59,7 @@ EXPORT_SYMBOL(pg_data_table);
 void __init m68k_setup_node(int node)
 {
 #ifndef CONFIG_SINGLE_MEMORY_CHUNK
-       struct mem_info *info = m68k_memory + node;
+       struct m68k_mem_info *info = m68k_memory + node;
        int i, end;
 
        i = (unsigned long)phys_to_virt(info->addr) >> __virt_to_node_shift();
index 251c5437787be6054086b4d5586adfc0887e0472..7d4024432163ffa534665582fcf522ed4e9ea51f 100644 (file)
@@ -233,7 +233,7 @@ void __init paging_init(void)
                        printk("Fix your bootloader or use a memfile to make use of this area!\n");
                        m68k_num_memory--;
                        memmove(m68k_memory + i, m68k_memory + i + 1,
-                               (m68k_num_memory - i) * sizeof(struct mem_info));
+                               (m68k_num_memory - i) * sizeof(struct m68k_mem_info));
                        continue;
                }
                addr = m68k_memory[i].addr + m68k_memory[i].size;
index 1c6262803b9455d46fbde9b05587fc910b1687f5..1bb3ce6634d36630d4ad82e34e91cc45de83da97 100644 (file)
@@ -26,6 +26,8 @@
 #include <linux/interrupt.h>
 
 #include <asm/bootinfo.h>
+#include <asm/bootinfo-vme.h>
+#include <asm/byteorder.h>
 #include <asm/pgtable.h>
 #include <asm/setup.h>
 #include <asm/irq.h>
@@ -51,9 +53,10 @@ static int bcd2int (unsigned char b);
 irq_handler_t tick_handler;
 
 
-int mvme147_parse_bootinfo(const struct bi_record *bi)
+int __init mvme147_parse_bootinfo(const struct bi_record *bi)
 {
-       if (bi->tag == BI_VME_TYPE || bi->tag == BI_VME_BRDINFO)
+       uint16_t tag = be16_to_cpu(bi->tag);
+       if (tag == BI_VME_TYPE || tag == BI_VME_BRDINFO)
                return 0;
        else
                return 1;
index 080a342458a1934162aa61f44d72d59dfc1afbd9..eab7d342757ef6abdf01e13ff1a199209381c81d 100644 (file)
@@ -29,6 +29,8 @@
 #include <linux/module.h>
 
 #include <asm/bootinfo.h>
+#include <asm/bootinfo-vme.h>
+#include <asm/byteorder.h>
 #include <asm/pgtable.h>
 #include <asm/setup.h>
 #include <asm/irq.h>
@@ -60,9 +62,10 @@ unsigned short mvme16x_config;
 EXPORT_SYMBOL(mvme16x_config);
 
 
-int mvme16x_parse_bootinfo(const struct bi_record *bi)
+int __init mvme16x_parse_bootinfo(const struct bi_record *bi)
 {
-       if (bi->tag == BI_VME_TYPE || bi->tag == BI_VME_BRDINFO)
+       uint16_t tag = be16_to_cpu(bi->tag);
+       if (tag == BI_VME_TYPE || tag == BI_VME_BRDINFO)
                return 0;
        else
                return 1;
@@ -87,15 +90,15 @@ static void mvme16x_get_model(char *model)
     suf[3] = '\0';
     suf[0] = suf[1] ? '-' : '\0';
 
-    sprintf(model, "Motorola MVME%x%s", p->brdno, suf);
+    sprintf(model, "Motorola MVME%x%s", be16_to_cpu(p->brdno), suf);
 }
 
 
 static void mvme16x_get_hardware_list(struct seq_file *m)
 {
-    p_bdid p = &mvme_bdid;
+    uint16_t brdno = be16_to_cpu(mvme_bdid.brdno);
 
-    if (p->brdno == 0x0162 || p->brdno == 0x0172)
+    if (brdno == 0x0162 || brdno == 0x0172)
     {
        unsigned char rev = *(unsigned char *)MVME162_VERSION_REG;
 
@@ -285,6 +288,7 @@ void __init config_mvme16x(void)
 {
     p_bdid p = &mvme_bdid;
     char id[40];
+    uint16_t brdno = be16_to_cpu(p->brdno);
 
     mach_max_dma_address = 0xffffffff;
     mach_sched_init      = mvme16x_sched_init;
@@ -306,18 +310,18 @@ void __init config_mvme16x(void)
     }
     /* Board type is only set by newer versions of vmelilo/tftplilo */
     if (vme_brdtype == 0)
-       vme_brdtype = p->brdno;
+       vme_brdtype = brdno;
 
     mvme16x_get_model(id);
     printk ("\nBRD_ID: %s   BUG %x.%x %02x/%02x/%02x\n", id, p->rev>>4,
                                        p->rev&0xf, p->yr, p->mth, p->day);
-    if (p->brdno == 0x0162 || p->brdno == 0x172)
+    if (brdno == 0x0162 || brdno == 0x172)
     {
        unsigned char rev = *(unsigned char *)MVME162_VERSION_REG;
 
        mvme16x_config = rev | MVME16x_CONFIG_GOT_SCCA;
 
-       printk ("MVME%x Hardware status:\n", p->brdno);
+       printk ("MVME%x Hardware status:\n", brdno);
        printk ("    CPU Type           68%s040\n",
                        rev & MVME16x_CONFIG_GOT_FPU ? "" : "LC");
        printk ("    CPU clock          %dMHz\n",
@@ -347,12 +351,12 @@ void __init config_mvme16x(void)
 
 static irqreturn_t mvme16x_abort_int (int irq, void *dev_id)
 {
-       p_bdid p = &mvme_bdid;
        unsigned long *new = (unsigned long *)vectors;
        unsigned long *old = (unsigned long *)0xffe00000;
        volatile unsigned char uc, *ucp;
+       uint16_t brdno = be16_to_cpu(mvme_bdid.brdno);
 
-       if (p->brdno == 0x0162 || p->brdno == 0x172)
+       if (brdno == 0x0162 || brdno == 0x172)
        {
                ucp = (volatile unsigned char *)0xfff42043;
                uc = *ucp | 8;
@@ -366,7 +370,7 @@ static irqreturn_t mvme16x_abort_int (int irq, void *dev_id)
        *(new+9) = *(old+9);            /* Trace */
        *(new+47) = *(old+47);          /* Trap #15 */
 
-       if (p->brdno == 0x0162 || p->brdno == 0x172)
+       if (brdno == 0x0162 || brdno == 0x172)
                *(new+0x5e) = *(old+0x5e);      /* ABORT switch */
        else
                *(new+0x6e) = *(old+0x6e);      /* ABORT switch */
@@ -381,7 +385,7 @@ static irqreturn_t mvme16x_timer_int (int irq, void *dev_id)
 
 void mvme16x_sched_init (irq_handler_t timer_routine)
 {
-    p_bdid p = &mvme_bdid;
+    uint16_t brdno = be16_to_cpu(mvme_bdid.brdno);
     int irq;
 
     tick_handler = timer_routine;
@@ -394,7 +398,7 @@ void mvme16x_sched_init (irq_handler_t timer_routine)
                                "timer", mvme16x_timer_int))
        panic ("Couldn't register timer int");
 
-    if (p->brdno == 0x0162 || p->brdno == 0x172)
+    if (brdno == 0x0162 || brdno == 0x172)
        irq = MVME162_IRQ_ABORT;
     else
         irq = MVME167_IRQ_ABORT;
index 078bb744b5fe1193232a96999eb85c92b798c04a..e90fe903613ead8ad480797d138f7d566f738f48 100644 (file)
@@ -154,7 +154,7 @@ static unsigned int serports[] =
        0x3f8,0x2f8,0x3e8,0x2e8,0
 };
 
-static void q40_disable_irqs(void)
+static void __init q40_disable_irqs(void)
 {
        unsigned i, j;
 
@@ -198,7 +198,7 @@ void __init config_q40(void)
 }
 
 
-int q40_parse_bootinfo(const struct bi_record *rec)
+int __init q40_parse_bootinfo(const struct bi_record *rec)
 {
        return 1;
 }
index d522eaab45510aacd13b7cdf6e11ff14f88659a0..d95506e06c2ac42b67f9ce634413da8efc50082f 100644 (file)
@@ -7,6 +7,7 @@
  *
  */
 
+#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/bootmem.h>
@@ -62,10 +63,7 @@ int dvma_map_iommu(unsigned long kaddr, unsigned long baddr,
 
 }
 
-void sun3_dvma_init(void)
+void __init sun3_dvma_init(void)
 {
-
        memset(ptelist, 0, sizeof(ptelist));
-
-
 }
index 8edc510a21be663122fc285df8f624cf818d6b7b..3f258e230ba5d0c95806848ef96c64ce1160d479 100644 (file)
@@ -6,6 +6,7 @@
 ** Started 1/16/98 @ 2:22 am
 */
 
+#include <linux/init.h>
 #include <linux/mman.h>
 #include <linux/mm.h>
 #include <linux/kernel.h>
@@ -122,7 +123,7 @@ void print_pte_vaddr (unsigned long vaddr)
 /*
  * Initialise the MMU emulator.
  */
-void mmu_emu_init(unsigned long bootmem_end)
+void __init mmu_emu_init(unsigned long bootmem_end)
 {
        unsigned long seg, num;
        int i,j;
index cab54482ca34b97fa4412eaaaa4a0ee31d173833..b37521a5259ddb7a040d6606fdd24f324f657e8f 100644 (file)
@@ -6,6 +6,8 @@
  * Contains common routines for sun3/sun3x DVMA management.
  */
 
+#include <linux/bootmem.h>
+#include <linux/init.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/gfp.h>
@@ -30,7 +32,7 @@ static inline void dvma_unmap_iommu(unsigned long a, int b)
 extern void sun3_dvma_init(void);
 #endif
 
-static unsigned long iommu_use[IOMMU_TOTAL_ENTRIES];
+static unsigned long *iommu_use;
 
 #define dvma_index(baddr) ((baddr - DVMA_START) >> DVMA_PAGE_SHIFT)
 
@@ -245,7 +247,7 @@ static inline int free_baddr(unsigned long baddr)
 
 }
 
-void dvma_init(void)
+void __init dvma_init(void)
 {
 
        struct hole *hole;
@@ -265,7 +267,7 @@ void dvma_init(void)
 
        list_add(&(hole->list), &hole_list);
 
-       memset(iommu_use, 0, sizeof(iommu_use));
+       iommu_use = alloc_bootmem(IOMMU_TOTAL_ENTRIES * sizeof(unsigned long));
 
        dvma_unmap_iommu(DVMA_START, DVMA_SIZE);
 
index a7b7e818d6279450119f4a8da5e76cf1c6746466..0898c3f8150851a34e8c4f54fe8c3d7760497cd4 100644 (file)
@@ -10,7 +10,6 @@
 
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/bootinfo.h>
 #include <asm/setup.h>
 #include <asm/traps.h>
 #include <asm/sun3xprom.h>
index e0373f81a1172fdabc23afc174302a89b2f8814a..1d7e770f7a54bfca3c9382b5fe5b657885037612 100644 (file)
@@ -7,13 +7,11 @@
 
 enum ipi_msg_type {
        IPI_CALL_FUNC,
-       IPI_CALL_FUNC_SINGLE,
        IPI_RESCHEDULE,
 };
 
 extern void arch_send_call_function_single_ipi(int cpu);
 extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
-#define arch_send_call_function_ipi_mask arch_send_call_function_ipi_mask
 
 asmlinkage void secondary_start_kernel(void);
 
index db589ad5dbc41e5bb1cb0bc52dfc4faefc9c1820..c700d625067a96cb725064e0c19ceadad078cd6a 100644 (file)
@@ -399,11 +399,6 @@ static int __init dma_alloc_init(void)
                pgd = pgd_offset(&init_mm, CONSISTENT_START);
                pud = pud_alloc(&init_mm, pgd, CONSISTENT_START);
                pmd = pmd_alloc(&init_mm, pud, CONSISTENT_START);
-               if (!pmd) {
-                       pr_err("%s: no pmd tables\n", __func__);
-                       ret = -ENOMEM;
-                       break;
-               }
                WARN_ON(!pmd_none(*pmd));
 
                pte = pte_alloc_kernel(pmd, CONSISTENT_START);
index 7c01131429817ab58ce63490cc97e5dba4f4b4c9..f74008b6da070827893f656857f20e6b8104f045 100644 (file)
@@ -491,7 +491,7 @@ void arch_send_call_function_ipi_mask(const struct cpumask *mask)
 
 void arch_send_call_function_single_ipi(int cpu)
 {
-       send_ipi_message(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
+       send_ipi_message(cpumask_of(cpu), IPI_CALL_FUNC);
 }
 
 void show_ipi_list(struct seq_file *p)
@@ -517,11 +517,10 @@ static DEFINE_SPINLOCK(stop_lock);
  *
  *  Bit 0 - Inter-processor function call
  */
-static int do_IPI(struct pt_regs *regs)
+static int do_IPI(void)
 {
        unsigned int cpu = smp_processor_id();
        struct ipi_data *ipi = &per_cpu(ipi_data, cpu);
-       struct pt_regs *old_regs = set_irq_regs(regs);
        unsigned long msgs, nextmsg;
        int handled = 0;
 
@@ -546,10 +545,6 @@ static int do_IPI(struct pt_regs *regs)
                        generic_smp_call_function_interrupt();
                        break;
 
-               case IPI_CALL_FUNC_SINGLE:
-                       generic_smp_call_function_single_interrupt();
-                       break;
-
                default:
                        pr_crit("CPU%u: Unknown IPI message 0x%lx\n",
                                cpu, nextmsg);
@@ -557,8 +552,6 @@ static int do_IPI(struct pt_regs *regs)
                }
        }
 
-       set_irq_regs(old_regs);
-
        return handled;
 }
 
@@ -624,7 +617,7 @@ static void kick_raise_softirq(cpumask_t callmap, unsigned int irq)
 static TBIRES ipi_handler(TBIRES State, int SigNum, int Triggers,
                   int Inst, PTBI pTBI, int *handled)
 {
-       *handled = do_IPI((struct pt_regs *)State.Sig.pCtx);
+       *handled = do_IPI();
 
        return State;
 }
index 40350a3c24e907f01f3c193018abb6a34ee35541..a69eaf2ab1301466c662e27f37837c86d8193d61 100644 (file)
@@ -1,3 +1,5 @@
+KBUILD_DEFCONFIG := mmu_defconfig
+
 ifeq ($(CONFIG_MMU),y)
 UTS_SYSNAME = -DUTS_SYSNAME=\"Linux\"
 else
index c07ed5d2a82034f11cbadc6e836d4e31761d380f..1b281d3ea734418a0f39d12625e8ac1a749a6b1c 100644 (file)
@@ -16,7 +16,6 @@
 # ifndef __ASSEMBLY__
 extern char _ssbss[], _esbss[];
 extern unsigned long __ivt_start[], __ivt_end[];
-extern char _etext[], _stext[];
 
 extern u32 _fdt_start[], _fdt_end[];
 
index 8de8ebc309f15b0ca080cdf6f7c93e54fd168d74..603e22fec6d5b888d3f164cd08afa0d17ed3b037 100644 (file)
@@ -136,7 +136,7 @@ void __init machine_early_init(const char *cmdline, unsigned int ram,
        lockdep_init();
 
 /* initialize device tree for usage in early_printk */
-       early_init_devtree((void *)_fdt_start);
+       early_init_devtree(_fdt_start);
 
 #ifdef CONFIG_EARLY_PRINTK
        setup_early_printk(NULL);
@@ -152,8 +152,7 @@ void __init machine_early_init(const char *cmdline, unsigned int ram,
        if (fdt)
                pr_info("FDT at 0x%08x\n", fdt);
        else
-               pr_info("Compiled-in FDT at 0x%08x\n",
-                                       (unsigned int)_fdt_start);
+               pr_info("Compiled-in FDT at %p\n", _fdt_start);
 
 #ifdef CONFIG_MTD_UCLINUX
        pr_info("Found romfs @ 0x%08x (0x%08x)\n",
index 9a357fffcfbe0a0c6767e5b12d70d22f23e5b1b7..820b7a313d9bfd593cdaa63e6374f0cf4bd15d6a 100644 (file)
@@ -92,7 +92,6 @@ void __init plat_mem_setup(void)
        _machine_restart = ar7_machine_restart;
        _machine_halt = ar7_machine_halt;
        pm_power_off = ar7_machine_power_off;
-       panic_timeout = 3;
 
        io_base = (unsigned long)ioremap(AR7_REGS_BASE, 0x10000);
        if (!io_base)
index d71005835c007aeb8df0f8b288fbfb1f3045457d..9100122e5cef891c18767fee89c98858df661f11 100644 (file)
@@ -111,9 +111,6 @@ void __init plat_mem_setup(void)
        iomem_resource.start = EMMA2RH_IO_BASE;
        iomem_resource.end = EMMA2RH_ROM_BASE - 1;
 
-       /* Reboot on panic */
-       panic_timeout = 180;
-
        markeins_sio_setup();
 }
 
index 638c5db122c924dca997725d58ee0fd34b36fe1b..8c55de42693d2bcd73420654f45bb050c3e2c696 100644 (file)
@@ -44,7 +44,7 @@ static int pvc_line_proc_show(struct seq_file *m, void *v)
 {
        int lineno = *(int *)m->private;
 
-       if (lineno < 0 || lineno > PVC_NLINES) {
+       if (lineno < 0 || lineno >= PVC_NLINES) {
                printk(KERN_WARNING "proc_read_line: invalid lineno %d\n", lineno);
                return 0;
        }
@@ -68,7 +68,7 @@ static ssize_t pvc_line_proc_write(struct file *file, const char __user *buf,
        char kbuf[PVC_LINELEN];
        size_t len;
 
-       BUG_ON(lineno < 0 || lineno > PVC_NLINES);
+       BUG_ON(lineno < 0 || lineno >= PVC_NLINES);
 
        len = min(count, sizeof(kbuf) - 1);
        if (copy_from_user(kbuf, buf, len))
index 6d981bb337ecd8abf96324d1e0f2a006caa942de..54e75c77184b883fdbec601e1b2e97e49b1aa8c9 100644 (file)
@@ -92,7 +92,6 @@ static void __init xlp_init_mem_from_bars(void)
 
 void __init plat_mem_setup(void)
 {
-       panic_timeout   = 5;
        _machine_restart = (void (*)(char *))nlm_linux_exit;
        _machine_halt   = nlm_linux_exit;
        pm_power_off    = nlm_linux_exit;
index 214d123b79faf7f6659ae4127ffe938257fb26ae..921be5f77797706279d61c1c79f897a206546d07 100644 (file)
@@ -92,7 +92,6 @@ static void nlm_linux_exit(void)
 
 void __init plat_mem_setup(void)
 {
-       panic_timeout   = 5;
        _machine_restart = (void (*)(char *))nlm_linux_exit;
        _machine_halt   = nlm_linux_exit;
        pm_power_off    = nlm_linux_exit;
index 41707a245dea61c1cabd467f2bc3d2ec2ca28cd8..3462c831d0ea5f1b307fcd002645d7b328bc816f 100644 (file)
@@ -134,8 +134,6 @@ void __init plat_mem_setup(void)
 #error invalid SiByte board configuration
 #endif
 
-       panic_timeout = 5;  /* For debug.  */
-
        board_be_handler = swarm_be_handler;
 
        if (xicor_probe())
index d8a455ede5a751c8dc31604526e425fb50167ee0..fec8bf97d806422ce76a578c83576733633a9bf6 100644 (file)
@@ -853,37 +853,44 @@ UNHANDLED_EXCEPTION(_vector_0x1f00,0x1f00)
 
 /* ========================================================[ return ] === */
 
+_resume_userspace:
+       DISABLE_INTERRUPTS(r3,r4)
+       l.lwz   r4,TI_FLAGS(r10)
+       l.andi  r13,r4,_TIF_WORK_MASK
+       l.sfeqi r13,0
+       l.bf    _restore_all
+        l.nop
+
 _work_pending:
-       /*
-        * if (current_thread_info->flags & _TIF_NEED_RESCHED)
-        *     schedule();
-        */
-       l.lwz   r5,TI_FLAGS(r10)
-       l.andi  r3,r5,_TIF_NEED_RESCHED
-       l.sfnei r3,0
-       l.bnf   _work_notifysig
+       l.lwz   r5,PT_ORIG_GPR11(r1)
+       l.sfltsi r5,0
+       l.bnf   1f
         l.nop
-       l.jal   schedule
+       l.andi  r5,r5,0
+1:
+       l.jal   do_work_pending
+        l.ori  r3,r1,0                 /* pt_regs */
+
+       l.sfeqi r11,0
+       l.bf    _restore_all
         l.nop
-       l.j     _resume_userspace
+       l.sfltsi r11,0
+       l.bnf   1f
         l.nop
-
-/* Handle pending signals and notify-resume requests.
- * do_notify_resume must be passed the latest pushed pt_regs, not
- * necessarily the "userspace" ones.  Also, pt_regs->syscallno
- * must be set so that the syscall restart functionality works.
- */
-_work_notifysig:
-       l.jal   do_notify_resume
-        l.ori  r3,r1,0           /* pt_regs */
-
-_resume_userspace:
-       DISABLE_INTERRUPTS(r3,r4)
-       l.lwz   r3,TI_FLAGS(r10)
-       l.andi  r3,r3,_TIF_WORK_MASK
-       l.sfnei r3,0
-       l.bf    _work_pending
+       l.and   r11,r11,r0
+       l.ori   r11,r11,__NR_restart_syscall
+       l.j     _syscall_check_trace_enter
         l.nop
+1:
+       l.lwz   r11,PT_ORIG_GPR11(r1)
+       /* Restore arg registers */
+       l.lwz   r3,PT_GPR3(r1)
+       l.lwz   r4,PT_GPR4(r1)
+       l.lwz   r5,PT_GPR5(r1)
+       l.lwz   r6,PT_GPR6(r1)
+       l.lwz   r7,PT_GPR7(r1)
+       l.j     _syscall_check_trace_enter
+        l.lwz  r8,PT_GPR8(r1)
 
 _restore_all:
        RESTORE_ALL
index ae167f7e081aa0368cb571093df8f16a9dcf71d9..66775bc07a8eeb780e65a290247b3156f0a44ccd 100644 (file)
 #include <linux/tracehook.h>
 
 #include <asm/processor.h>
+#include <asm/syscall.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
 
 #define DEBUG_SIG 0
 
 struct rt_sigframe {
-       struct siginfo *pinfo;
-       void *puc;
        struct siginfo info;
        struct ucontext uc;
        unsigned char retcode[16];      /* trampoline code */
 };
 
-static int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
+static int restore_sigcontext(struct pt_regs *regs,
+                             struct sigcontext __user *sc)
 {
-       unsigned int err = 0;
+       int err = 0;
 
-       /* Alwys make any pending restarted system call return -EINTR */
+       /* Always make any pending restarted system calls return -EINTR */
        current_thread_info()->restart_block.fn = do_no_restart_syscall;
 
        /*
@@ -53,25 +53,21 @@ static int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
         * (sc is already checked for VERIFY_READ since the sigframe was
         *  checked in sys_sigreturn previously)
         */
-       if (__copy_from_user(regs, sc->regs.gpr, 32 * sizeof(unsigned long)))
-               goto badframe;
-       if (__copy_from_user(&regs->pc, &sc->regs.pc, sizeof(unsigned long)))
-               goto badframe;
-       if (__copy_from_user(&regs->sr, &sc->regs.sr, sizeof(unsigned long)))
-               goto badframe;
+       err |= __copy_from_user(regs, sc->regs.gpr, 32 * sizeof(unsigned long));
+       err |= __copy_from_user(&regs->pc, &sc->regs.pc, sizeof(unsigned long));
+       err |= __copy_from_user(&regs->sr, &sc->regs.sr, sizeof(unsigned long));
 
        /* make sure the SM-bit is cleared so user-mode cannot fool us */
        regs->sr &= ~SPR_SR_SM;
 
+       regs->orig_gpr11 = -1;  /* Avoid syscall restart checks */
+
        /* TODO: the other ports use regs->orig_XX to disable syscall checks
         * after this completes, but we don't use that mechanism. maybe we can
         * use it now ?
         */
 
        return err;
-
-badframe:
-       return 1;
 }
 
 asmlinkage long _sys_rt_sigreturn(struct pt_regs *regs)
@@ -111,21 +107,18 @@ badframe:
  * Set up a signal frame.
  */
 
-static int setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
-                           unsigned long mask)
+static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
 {
        int err = 0;
 
        /* copy the regs */
-
+       /* There should be no need to save callee-saved registers here...
+        * ...but we save them anyway.  Revisit this
+        */
        err |= __copy_to_user(sc->regs.gpr, regs, 32 * sizeof(unsigned long));
        err |= __copy_to_user(&sc->regs.pc, &regs->pc, sizeof(unsigned long));
        err |= __copy_to_user(&sc->regs.sr, &regs->sr, sizeof(unsigned long));
 
-       /* then some other stuff */
-
-       err |= __put_user(mask, &sc->oldmask);
-
        return err;
 }
 
@@ -173,55 +166,53 @@ static inline void __user *get_sigframe(struct k_sigaction *ka,
  * trampoline which performs the syscall sigreturn, or a provided
  * user-mode trampoline.
  */
-static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
-                         sigset_t *set, struct pt_regs *regs)
+static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
+                         struct pt_regs *regs)
 {
        struct rt_sigframe *frame;
        unsigned long return_ip;
        int err = 0;
 
-       frame = get_sigframe(ka, regs, sizeof(*frame));
+       frame = get_sigframe(&ksig->ka, regs, sizeof(*frame));
 
        if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-               goto give_sigsegv;
+               return -EFAULT;
 
-       err |= __put_user(&frame->info, &frame->pinfo);
-       err |= __put_user(&frame->uc, &frame->puc);
+       /* Create siginfo.  */
+       if (ksig->ka.sa.sa_flags & SA_SIGINFO)
+               err |= copy_siginfo_to_user(&frame->info, &ksig->info);
 
-       if (ka->sa.sa_flags & SA_SIGINFO)
-               err |= copy_siginfo_to_user(&frame->info, info);
-       if (err)
-               goto give_sigsegv;
-
-       /* Clear all the bits of the ucontext we don't use.  */
-       err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));
+       /* Create the ucontext.  */
        err |= __put_user(0, &frame->uc.uc_flags);
        err |= __put_user(NULL, &frame->uc.uc_link);
        err |= __save_altstack(&frame->uc.uc_stack, regs->sp);
-       err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]);
+       err |= setup_sigcontext(regs, &frame->uc.uc_mcontext);
 
        err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
 
        if (err)
-               goto give_sigsegv;
+               return -EFAULT;
 
        /* trampoline - the desired return ip is the retcode itself */
        return_ip = (unsigned long)&frame->retcode;
-       /* This is l.ori r11,r0,__NR_sigreturn, l.sys 1 */
-       err |= __put_user(0xa960, (short *)(frame->retcode + 0));
-       err |= __put_user(__NR_rt_sigreturn, (short *)(frame->retcode + 2));
+       /* This is:
+               l.ori r11,r0,__NR_sigreturn
+               l.sys 1
+        */
+       err |= __put_user(0xa960,             (short *)(frame->retcode + 0));
+       err |= __put_user(__NR_rt_sigreturn,  (short *)(frame->retcode + 2));
        err |= __put_user(0x20000001, (unsigned long *)(frame->retcode + 4));
        err |= __put_user(0x15000000, (unsigned long *)(frame->retcode + 8));
 
        if (err)
-               goto give_sigsegv;
+               return -EFAULT;
 
        /* TODO what is the current->exec_domain stuff and invmap ? */
 
        /* Set up registers for signal handler */
-       regs->pc = (unsigned long)ka->sa.sa_handler; /* what we enter NOW */
+       regs->pc = (unsigned long)ksig->ka.sa.sa_handler; /* what we enter NOW */
        regs->gpr[9] = (unsigned long)return_ip;     /* what we enter LATER */
-       regs->gpr[3] = (unsigned long)sig;           /* arg 1: signo */
+       regs->gpr[3] = (unsigned long)ksig->sig;           /* arg 1: signo */
        regs->gpr[4] = (unsigned long)&frame->info;  /* arg 2: (siginfo_t*) */
        regs->gpr[5] = (unsigned long)&frame->uc;    /* arg 3: ucontext */
 
@@ -229,25 +220,16 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        regs->sp = (unsigned long)frame;
 
        return 0;
-
-give_sigsegv:
-       force_sigsegv(sig, current);
-       return -EFAULT;
 }
 
 static inline void
-handle_signal(unsigned long sig,
-             siginfo_t *info, struct k_sigaction *ka,
-             struct pt_regs *regs)
+handle_signal(struct ksignal *ksig, struct pt_regs *regs)
 {
        int ret;
 
-       ret = setup_rt_frame(sig, ka, info, sigmask_to_save(), regs);
-       if (ret)
-               return;
+       ret = setup_rt_frame(ksig, sigmask_to_save(), regs);
 
-       signal_delivered(sig, info, ka, regs,
-                                test_thread_flag(TIF_SINGLESTEP));
+       signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
 }
 
 /*
@@ -262,82 +244,99 @@ handle_signal(unsigned long sig,
  * mode below.
  */
 
-void do_signal(struct pt_regs *regs)
+int do_signal(struct pt_regs *regs, int syscall)
 {
-       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 (!user_mode(regs))
-               return;
-
-       signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-
-       /* If we are coming out of a syscall then we need
-        * to check if the syscall was interrupted and wants to be
-        * restarted after handling the signal.  If so, the original
-        * syscall number is put back into r11 and the PC rewound to
-        * point at the l.sys instruction that resulted in the
-        * original syscall.  Syscall results other than the four
-        * below mean that the syscall executed to completion and no
-        * restart is necessary.
-        */
-       if (regs->orig_gpr11) {
-               int restart = 0;
-
-               switch (regs->gpr[11]) {
+       struct ksignal ksig;
+       unsigned long continue_addr = 0;
+       unsigned long restart_addr = 0;
+       unsigned long retval = 0;
+       int restart = 0;
+
+       if (syscall) {
+               continue_addr = regs->pc;
+               restart_addr = continue_addr - 4;
+               retval = regs->gpr[11];
+
+               /*
+                * Setup syscall restart here so that a debugger will
+                * see the already changed PC.
+                */
+               switch (retval) {
                case -ERESTART_RESTARTBLOCK:
+                       restart = -2;
+                       /* Fall through */
                case -ERESTARTNOHAND:
-                       /* Restart if there is no signal handler */
-                       restart = (signr <= 0);
-                       break;
                case -ERESTARTSYS:
-                       /* Restart if there no signal handler or
-                        * SA_RESTART flag is set */
-                       restart = (signr <= 0 || (ka.sa.sa_flags & SA_RESTART));
-                       break;
                case -ERESTARTNOINTR:
-                       /* Always restart */
-                       restart = 1;
+                       restart++;
+                       regs->gpr[11] = regs->orig_gpr11;
+                       regs->pc = restart_addr;
                        break;
                }
-
-               if (restart) {
-                       if (regs->gpr[11] == -ERESTART_RESTARTBLOCK)
-                               regs->gpr[11] = __NR_restart_syscall;
-                       else
-                               regs->gpr[11] = regs->orig_gpr11;
-                       regs->pc -= 4;
-               } else {
-                       regs->gpr[11] = -EINTR;
-               }
        }
 
-       if (signr <= 0) {
-               /* no signal to deliver so we just put the saved sigmask
-                * back */
+       /*
+        * Get the signal to deliver.  During the call to get_signal the
+        * debugger may change all our registers so we may need to revert
+        * the decision to restart the syscall; specifically, if the PC is
+        * changed, don't restart the syscall.
+        */
+       if (get_signal(&ksig)) {
+               if (unlikely(restart) && regs->pc == restart_addr) {
+                       if (retval == -ERESTARTNOHAND ||
+                           retval == -ERESTART_RESTARTBLOCK
+                           || (retval == -ERESTARTSYS
+                               && !(ksig.ka.sa.sa_flags & SA_RESTART))) {
+                               /* No automatic restart */
+                               regs->gpr[11] = -EINTR;
+                               regs->pc = continue_addr;
+                       }
+               }
+               handle_signal(&ksig, regs);
+       } else {
+               /* no handler */
                restore_saved_sigmask();
-       } else {                /* signr > 0 */
-               /* Whee!  Actually deliver the signal.  */
-               handle_signal(signr, &info, &ka, regs);
+               /*
+                * Restore pt_regs PC as syscall restart will be handled by
+                * kernel without return to userspace
+                */
+               if (unlikely(restart) && regs->pc == restart_addr) {
+                       regs->pc = continue_addr;
+                       return restart;
+               }
        }
 
-       return;
+       return 0;
 }
 
-asmlinkage void do_notify_resume(struct pt_regs *regs)
+asmlinkage int
+do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall)
 {
-       if (current_thread_info()->flags & _TIF_SIGPENDING)
-               do_signal(regs);
-
-       if (current_thread_info()->flags & _TIF_NOTIFY_RESUME) {
-               clear_thread_flag(TIF_NOTIFY_RESUME);
-               tracehook_notify_resume(regs);
-       }
+       do {
+               if (likely(thread_flags & _TIF_NEED_RESCHED)) {
+                       schedule();
+               } else {
+                       if (unlikely(!user_mode(regs)))
+                               return 0;
+                       local_irq_enable();
+                       if (thread_flags & _TIF_SIGPENDING) {
+                               int restart = do_signal(regs, syscall);
+                               if (unlikely(restart)) {
+                                       /*
+                                        * Restart without handlers.
+                                        * Deal with it without leaving
+                                        * the kernel space.
+                                        */
+                                       return restart;
+                               }
+                               syscall = 0;
+                       } else {
+                               clear_thread_flag(TIF_NOTIFY_RESUME);
+                               tracehook_notify_resume(regs);
+                       }
+               }
+               local_irq_disable();
+               thread_flags = current_thread_info()->flags;
+       } while (thread_flags & _TIF_WORK_MASK);
+       return 0;
 }
index ec1b014952b6601458f4c3b2901d8e86670b96fc..acacd348df89bb2f817855e5247e82f731539c6f 100644 (file)
@@ -50,7 +50,7 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_IDE=y
 CONFIG_BLK_DEV_IDECD=y
 CONFIG_BLK_DEV_NS87415=y
-CONFIG_BLK_DEV_SIIMAGE=m
+CONFIG_PATA_SIL680=m
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
index e1c8d2015c8938ac0a3440d38af427b4ac8eec7a..8249ac9d9cfcc2a2e74d1111ac4b16ac54e67493 100644 (file)
@@ -20,7 +20,6 @@ CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 CONFIG_BLK_DEV_INTEGRITY=y
 CONFIG_PA8X00=y
-CONFIG_MLONGCALLS=y
 CONFIG_64BIT=y
 CONFIG_SMP=y
 CONFIG_PREEMPT=y
@@ -81,8 +80,6 @@ CONFIG_IDE=y
 CONFIG_BLK_DEV_IDECD=y
 CONFIG_BLK_DEV_PLATFORM=y
 CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_SIIMAGE=y
-CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_BLK_DEV_SR=m
@@ -94,6 +91,8 @@ CONFIG_SCSI_FC_ATTRS=y
 CONFIG_SCSI_SAS_LIBSAS=m
 CONFIG_ISCSI_TCP=m
 CONFIG_ISCSI_BOOT_SYSFS=m
+CONFIG_ATA=y
+CONFIG_PATA_SIL680=y
 CONFIG_FUSION=y
 CONFIG_FUSION_SPI=y
 CONFIG_FUSION_SAS=y
@@ -114,9 +113,8 @@ CONFIG_INPUT_FF_MEMLESS=m
 # CONFIG_KEYBOARD_ATKBD is not set
 # CONFIG_KEYBOARD_HIL_OLD is not set
 # CONFIG_KEYBOARD_HIL is not set
-CONFIG_MOUSE_PS2=m
+# CONFIG_MOUSE_PS2 is not set
 CONFIG_INPUT_MISC=y
-CONFIG_INPUT_CM109=m
 CONFIG_SERIO_SERPORT=m
 CONFIG_SERIO_PARKBD=m
 CONFIG_SERIO_GSCPS2=m
@@ -167,34 +165,6 @@ CONFIG_SND_VERBOSE_PRINTK=y
 CONFIG_SND_AD1889=m
 # CONFIG_SND_USB is not set
 # CONFIG_SND_GSC is not set
-CONFIG_HID_A4TECH=m
-CONFIG_HID_APPLE=m
-CONFIG_HID_BELKIN=m
-CONFIG_HID_CHERRY=m
-CONFIG_HID_CHICONY=m
-CONFIG_HID_CYPRESS=m
-CONFIG_HID_DRAGONRISE=m
-CONFIG_HID_EZKEY=m
-CONFIG_HID_KYE=m
-CONFIG_HID_GYRATION=m
-CONFIG_HID_TWINHAN=m
-CONFIG_HID_KENSINGTON=m
-CONFIG_HID_LOGITECH=m
-CONFIG_HID_LOGITECH_DJ=m
-CONFIG_HID_MICROSOFT=m
-CONFIG_HID_MONTEREY=m
-CONFIG_HID_NTRIG=m
-CONFIG_HID_ORTEK=m
-CONFIG_HID_PANTHERLORD=m
-CONFIG_HID_PETALYNX=m
-CONFIG_HID_SAMSUNG=m
-CONFIG_HID_SUNPLUS=m
-CONFIG_HID_GREENASIA=m
-CONFIG_HID_SMARTJOYPLUS=m
-CONFIG_HID_TOPSEED=m
-CONFIG_HID_THRUSTMASTER=m
-CONFIG_HID_ZEROPLUS=m
-CONFIG_USB_HID=m
 CONFIG_USB=y
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_STORAGE=y
index 5874cebee07701725f3ab9939acb6cd11f1e46f2..28c1b5de044e827d128f3165ea15d807f39ff0b6 100644 (file)
@@ -24,7 +24,6 @@ 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
@@ -68,7 +67,6 @@ 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
@@ -82,6 +80,7 @@ CONFIG_SCSI_ZALON=y
 CONFIG_SCSI_QLA_ISCSI=m
 CONFIG_SCSI_DH=y
 CONFIG_ATA=y
+CONFIG_PATA_SIL680=y
 CONFIG_ATA_GENERIC=y
 CONFIG_MD=y
 CONFIG_MD_LINEAR=m
@@ -162,7 +161,7 @@ CONFIG_SLIP_MODE_SLIP6=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_KEYBOARD_HIL_OLD is not set
 # CONFIG_KEYBOARD_HIL is not set
-# CONFIG_INPUT_MOUSE is not set
+# CONFIG_MOUSE_PS2 is not set
 CONFIG_INPUT_MISC=y
 CONFIG_SERIO_SERPORT=m
 # CONFIG_HP_SDC is not set
@@ -216,32 +215,7 @@ CONFIG_BACKLIGHT_LCD_SUPPORT=y
 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
@@ -251,13 +225,8 @@ 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_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_TRIGGERS=y
index d7e3cc60dbc3693a3b8ce475fbd128bb9563a284..77e9b67c87ee1ed382670ec604b067f5b3a99b25 100644 (file)
@@ -6,5 +6,3 @@
  * This is used for 16550-compatible UARTs
  */
 #define BASE_BAUD ( 1843200 / 16 )
-
-#define SERIAL_PORT_DFNS
index 06cb3992907e67e9847b84259e5a61f3e42c2b71..608716f8496bf8dfe0acc08a71a15807ce20c557 100644 (file)
@@ -36,6 +36,9 @@
  *     HP PARISC Hardware Database
  *     Access to this database is only possible during bootup
  *     so don't reference this table after starting the init process
+ *
+ *     NOTE: Product names which are listed here and ends with a '?'
+ *     are guessed. If you know the correct name, please let us know.
  */
  
 static struct hp_hardware hp_hardware_list[] = {
@@ -222,7 +225,7 @@ static struct hp_hardware hp_hardware_list[] = {
        {HPHW_NPROC,0x5DD,0x4,0x81,"Duet W2"},
        {HPHW_NPROC,0x5DE,0x4,0x81,"Piccolo W+"},
        {HPHW_NPROC,0x5DF,0x4,0x81,"Cantata W2"},
-       {HPHW_NPROC,0x5DF,0x0,0x00,"Marcato W+? (rp5470)"},
+       {HPHW_NPROC,0x5DF,0x0,0x00,"Marcato W+ (rp5470)?"},
        {HPHW_NPROC,0x5E0,0x4,0x91,"Cantata DC- W2"},
        {HPHW_NPROC,0x5E1,0x4,0x91,"Crescendo DC- W2"},
        {HPHW_NPROC,0x5E2,0x4,0x91,"Crescendo 650 W2"},
@@ -276,9 +279,11 @@ static struct hp_hardware hp_hardware_list[] = {
        {HPHW_NPROC,0x888,0x4,0x91,"Storm Peak Fast DC-"},
        {HPHW_NPROC,0x889,0x4,0x91,"Storm Peak Fast"},
        {HPHW_NPROC,0x88A,0x4,0x91,"Crestone Peak Slow"},
+       {HPHW_NPROC,0x88B,0x4,0x91,"Crestone Peak Fast?"},
        {HPHW_NPROC,0x88C,0x4,0x91,"Orca Mako+"},
        {HPHW_NPROC,0x88D,0x4,0x91,"Rainier/Medel Mako+ Slow"},
        {HPHW_NPROC,0x88E,0x4,0x91,"Rainier/Medel Mako+ Fast"},
+       {HPHW_NPROC,0x892,0x4,0x91,"Mt. Hamilton Slow Mako+?"},
        {HPHW_NPROC,0x894,0x4,0x91,"Mt. Hamilton Fast Mako+"},
        {HPHW_NPROC,0x895,0x4,0x91,"Storm Peak Slow Mako+"},
        {HPHW_NPROC,0x896,0x4,0x91,"Storm Peak Fast Mako+"},
index d2d58258aea68084c4f09cc6012a741b838b22d5..d4dc588c0dc1f6963f99e6545de14031192d4543 100644 (file)
@@ -41,9 +41,7 @@ END(boot_args)
         .import fault_vector_11,code    /* IVA parisc 1.1 32 bit */
        .import $global$                /* forward declaration */
 #endif /*!CONFIG_64BIT*/
-       .export _stext,data             /* Kernel want it this way! */
-_stext:
-ENTRY(stext)
+ENTRY(parisc_kernel_start)
        .proc
        .callinfo
 
@@ -347,7 +345,7 @@ smp_slave_stext:
        .procend
 #endif /* CONFIG_SMP */
 
-ENDPROC(stext)
+ENDPROC(parisc_kernel_start)
 
 #ifndef CONFIG_64BIT
        .section .data..read_mostly
index 5dfd248e3f1a84fd6dbd961bf278002338cba4b0..0d3a9d4927b58009bfe0c4dc4114585409ddd2f5 100644 (file)
@@ -61,8 +61,15 @@ static int get_offset(struct address_space *mapping)
        return (unsigned long) mapping >> 8;
 }
 
-static unsigned long get_shared_area(struct address_space *mapping,
-               unsigned long addr, unsigned long len, unsigned long pgoff)
+static unsigned long shared_align_offset(struct file *filp, unsigned long pgoff)
+{
+       struct address_space *mapping = filp ? filp->f_mapping : NULL;
+
+       return (get_offset(mapping) + pgoff) << PAGE_SHIFT;
+}
+
+static unsigned long get_shared_area(struct file *filp, unsigned long addr,
+               unsigned long len, unsigned long pgoff)
 {
        struct vm_unmapped_area_info info;
 
@@ -71,7 +78,7 @@ static unsigned long get_shared_area(struct address_space *mapping,
        info.low_limit = PAGE_ALIGN(addr);
        info.high_limit = TASK_SIZE;
        info.align_mask = PAGE_MASK & (SHMLBA - 1);
-       info.align_offset = (get_offset(mapping) + pgoff) << PAGE_SHIFT;
+       info.align_offset = shared_align_offset(filp, pgoff);
        return vm_unmapped_area(&info);
 }
 
@@ -82,20 +89,18 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
                return -ENOMEM;
        if (flags & MAP_FIXED) {
                if ((flags & MAP_SHARED) &&
-                   (addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1))
+                   (addr - shared_align_offset(filp, pgoff)) & (SHMLBA - 1))
                        return -EINVAL;
                return addr;
        }
        if (!addr)
                addr = TASK_UNMAPPED_BASE;
 
-       if (filp) {
-               addr = get_shared_area(filp->f_mapping, addr, len, pgoff);
-       } else if(flags & MAP_SHARED) {
-               addr = get_shared_area(NULL, addr, len, pgoff);
-       } else {
+       if (filp || (flags & MAP_SHARED))
+               addr = get_shared_area(filp, addr, len, pgoff);
+       else
                addr = get_unshared_area(addr, len);
-       }
+
        return addr;
 }
 
index 76ed62ed785b6f4be9c1a6e663101ff3daeb6aa7..ddd988b267a9ddde0e9d2433f87e036f41e9d2a1 100644 (file)
@@ -168,7 +168,7 @@ void unwind_table_remove(struct unwind_table *table)
 }
 
 /* Called from setup_arch to import the kernel unwind info */
-int unwind_init(void)
+int __init unwind_init(void)
 {
        long start, stop;
        register unsigned long gp __asm__ ("r27");
@@ -233,7 +233,6 @@ static void unwind_frame_regs(struct unwind_frame_info *info)
        e = find_unwind_entry(info->ip);
        if (e == NULL) {
                unsigned long sp;
-               extern char _stext[], _etext[];
 
                dbg("Cannot find unwind entry for 0x%lx; forced unwinding\n", info->ip);
 
@@ -281,8 +280,7 @@ static void unwind_frame_regs(struct unwind_frame_info *info)
                                break;
                        info->prev_ip = tmp;
                        sp = info->prev_sp;
-               } while (info->prev_ip < (unsigned long)_stext ||
-                        info->prev_ip > (unsigned long)_etext);
+               } while (!kernel_text_address(info->prev_ip));
 
                info->rp = 0;
 
@@ -435,9 +433,8 @@ unsigned long return_address(unsigned int level)
        do {
                if (unwind_once(&info) < 0 || info.ip == 0)
                        return 0;
-               if (!__kernel_text_address(info.ip)) {
+               if (!kernel_text_address(info.ip))
                        return 0;
-               }
        } while (info.ip && level--);
 
        return info.ip;
index 4bb095a2f6fc2266388723cbb2634518a9570e44..0dacc5ca555afe7643da970bf9f3ae75ebc88790 100644 (file)
@@ -6,24 +6,19 @@
  *    Copyright (C) 2000 Michael Ang <mang with subcarrier.org>
  *    Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org>
  *    Copyright (C) 2003 James Bottomley <jejb with parisc-linux.org>
- *    Copyright (C) 2006 Helge Deller <deller@gmx.de>
- *
- *
- *    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) 2006-2013 Helge Deller <deller@gmx.de>
+ */
+
+/*
+ * Put page table entries (swapper_pg_dir) as the first thing in .bss. This
+ * will ensure that it has .bss alignment (PAGE_SIZE).
  */
+#define BSS_FIRST_SECTIONS     *(.data..vm0.pmd) \
+                               *(.data..vm0.pgd) \
+                               *(.data..vm0.pte)
+
 #include <asm-generic/vmlinux.lds.h>
+
 /* needed for the processor specific cache alignment size */   
 #include <asm/cache.h>
 #include <asm/page.h>
@@ -39,7 +34,7 @@ OUTPUT_FORMAT("elf64-hppa-linux")
 OUTPUT_ARCH(hppa:hppa2.0w)
 #endif
 
-ENTRY(_stext)
+ENTRY(parisc_kernel_start)
 #ifndef CONFIG_64BIT
 jiffies = jiffies_64 + 4;
 #else
@@ -49,11 +44,29 @@ SECTIONS
 {
        . = KERNEL_BINARY_TEXT_START;
 
+       __init_begin = .;
+       HEAD_TEXT_SECTION
+       INIT_TEXT_SECTION(8)
+
+       . = ALIGN(PAGE_SIZE);
+       INIT_DATA_SECTION(PAGE_SIZE)
+       /* we have to discard exit text and such at runtime, not link time */
+       .exit.text :
+       {
+               EXIT_TEXT
+       }
+       .exit.data :
+       {
+               EXIT_DATA
+       }
+       PERCPU_SECTION(8)
+       . = ALIGN(PAGE_SIZE);
+       __init_end = .;
+       /* freed after init ends here */
+
        _text = .;              /* Text and read-only data */
-       .head ALIGN(16) : {
-               HEAD_TEXT
-       } = 0
-       .text ALIGN(16) : {
+       _stext = .;
+       .text ALIGN(PAGE_SIZE) : {
                TEXT_TEXT
                SCHED_TEXT
                LOCK_TEXT
@@ -68,21 +81,28 @@ SECTIONS
                *(.lock.text)           /* out-of-line lock text */
                *(.gnu.warning)
        }
-       /* End of text section */
+       . = ALIGN(PAGE_SIZE);
        _etext = .;
+       /* End of text section */
 
        /* Start of data section */
        _sdata = .;
 
-       RODATA
+       RO_DATA_SECTION(8)
 
-       /* writeable */
-       /* Make sure this is page aligned so
-        * that we can properly leave these
-        * as writable
-        */
-       . = ALIGN(PAGE_SIZE);
-       data_start = .;
+#ifdef CONFIG_64BIT
+       . = ALIGN(16);
+       /* Linkage tables */
+       .opd : {
+               *(.opd)
+       } PROVIDE (__gp = .);
+       .plt : {
+               *(.plt)
+       }
+       .dlt : {
+               *(.dlt)
+       }
+#endif
 
        /* unwind info */
        .PARISC.unwind : {
@@ -91,7 +111,15 @@ SECTIONS
                __stop___unwind = .;
        }
 
-       EXCEPTION_TABLE(16)
+       /* writeable */
+       /* Make sure this is page aligned so
+        * that we can properly leave these
+        * as writable
+        */
+       . = ALIGN(PAGE_SIZE);
+       data_start = .;
+
+       EXCEPTION_TABLE(8)
        NOTES
 
        /* Data */
@@ -107,54 +135,8 @@ SECTIONS
        _edata = .;
 
        /* BSS */
-       __bss_start = .;
-       /* page table entries need to be PAGE_SIZE aligned */
-       . = ALIGN(PAGE_SIZE);
-       .data..vmpages : {
-               *(.data..vm0.pmd)
-               *(.data..vm0.pgd)
-               *(.data..vm0.pte)
-       }
-       .bss : {
-               *(.bss)
-               *(COMMON)
-       }
-       __bss_stop = .;
-
-#ifdef CONFIG_64BIT
-       . = ALIGN(16);
-       /* Linkage tables */
-       .opd : {
-               *(.opd)
-       } PROVIDE (__gp = .); 
-       .plt : {
-               *(.plt)
-       } 
-       .dlt : {
-               *(.dlt)
-       }
-#endif
+       BSS_SECTION(PAGE_SIZE, PAGE_SIZE, 8)
 
-       /* reserve space for interrupt stack by aligning __init* to 16k */
-       . = ALIGN(16384);
-       __init_begin = .;
-       INIT_TEXT_SECTION(16384)
-       . = ALIGN(PAGE_SIZE);
-       INIT_DATA_SECTION(16)
-       /* we have to discard exit text and such at runtime, not link time */
-       .exit.text :
-       {
-               EXIT_TEXT
-       }
-       .exit.data :
-       {
-               EXIT_DATA
-       }
-
-       PERCPU_SECTION(L1_CACHE_BYTES)
-       . = ALIGN(PAGE_SIZE);
-       __init_end = .;
-       /* freed after init ends here */
        _end = . ;
 
        STABS_DEBUG
index b0f96c0e6316f15531afb2a5a2a0e4684d1892a8..96f8168cf4ec1d9d50aad70ae17f54110a2c1527 100644 (file)
@@ -32,6 +32,7 @@
 #include <asm/sections.h>
 
 extern int  data_start;
+extern void parisc_kernel_start(void); /* Kernel entry point in head.S */
 
 #if PT_NLEVELS == 3
 /* NOTE: This layout exactly conforms to the hybrid L2/L3 page table layout
@@ -324,8 +325,9 @@ static void __init setup_bootmem(void)
        reserve_bootmem_node(NODE_DATA(0), 0UL,
                        (unsigned long)(PAGE0->mem_free +
                                PDC_CONSOLE_IO_IODC_SIZE), BOOTMEM_DEFAULT);
-       reserve_bootmem_node(NODE_DATA(0), __pa((unsigned long)_text),
-                       (unsigned long)(_end - _text), BOOTMEM_DEFAULT);
+       reserve_bootmem_node(NODE_DATA(0), __pa(KERNEL_BINARY_TEXT_START),
+                       (unsigned long)(_end - KERNEL_BINARY_TEXT_START),
+                       BOOTMEM_DEFAULT);
        reserve_bootmem_node(NODE_DATA(0), (bootmap_start_pfn << PAGE_SHIFT),
                        ((bootmap_pfn - bootmap_start_pfn) << PAGE_SHIFT),
                        BOOTMEM_DEFAULT);
@@ -378,6 +380,17 @@ static void __init setup_bootmem(void)
        request_resource(&sysram_resources[0], &pdcdata_resource);
 }
 
+static int __init parisc_text_address(unsigned long vaddr)
+{
+       static unsigned long head_ptr __initdata;
+
+       if (!head_ptr)
+               head_ptr = PAGE_MASK & (unsigned long)
+                       dereference_function_descriptor(&parisc_kernel_start);
+
+       return core_kernel_text(vaddr) || vaddr == head_ptr;
+}
+
 static void __init map_pages(unsigned long start_vaddr,
                             unsigned long start_paddr, unsigned long size,
                             pgprot_t pgprot, int force)
@@ -466,7 +479,7 @@ static void __init map_pages(unsigned long start_vaddr,
                                 */
                                if (force)
                                        pte =  __mk_pte(address, pgprot);
-                               else if (core_kernel_text(vaddr) &&
+                               else if (parisc_text_address(vaddr) &&
                                         address != fv_addr)
                                        pte = __mk_pte(address, PAGE_KERNEL_EXEC);
                                else
index b44b52c0a8f07d2854d5a21ca6fb2ecf409409c1..0e46756713bf39378361a8852b94cba368a0c49f 100644 (file)
@@ -147,6 +147,10 @@ config EARLY_PRINTK
        bool
        default y
 
+config PANIC_TIMEOUT
+       int
+       default 180
+
 config COMPAT
        bool
        default y if PPC64
@@ -379,6 +383,12 @@ config ARCH_HAS_WALK_MEMORY
 config ARCH_ENABLE_MEMORY_HOTREMOVE
        def_bool y
 
+config PPC64_SUPPORTS_MEMORY_FAILURE
+       bool "Add support for memory hwpoison"
+       depends on PPC_BOOK3S_64
+       default "y" if PPC_POWERNV
+       select ARCH_SUPPORTS_MEMORY_FAILURE
+
 config KEXEC
        bool "kexec system call"
        depends on (PPC_BOOK3S || FSL_BOOKE || (44x && !SMP))
@@ -1037,11 +1047,6 @@ config KEYS_COMPAT
 
 source "crypto/Kconfig"
 
-config PPC_CLOCK
-       bool
-       default n
-       select HAVE_CLK
-
 config PPC_LIB_RHEAP
        bool
 
index 554734ff302e89234c0d3ae51d1f11a840119c57..d61c03525777ce3cdaeab8a294fb6083e64cfe81 100644 (file)
@@ -16,6 +16,7 @@ mktree
 uImage
 cuImage.*
 dtbImage.*
+*.dtb
 treeImage.*
 zImage
 zImage.initrd
index a543c4088cba1ea026062a45df2c4ca0c95648ab..a1b883730b3169d8171c06c4fdc2d50cfe874b41 100644 (file)
                };
        };
 
+       clocks {
+               osc {
+                       clock-frequency = <25000000>;
+               };
+       };
+
        soc@80000000 {
+               bus-frequency = <80000000>;     /* 80 MHz ips bus */
 
                clock@f00 {
                        compatible = "fsl,mpc5121rev2-clock", "fsl,mpc5121-clock";
index 1613d6e4049eb2ba22aeceef97e8e57110620713..5ba7f01e2a297878251001d427bf498bdd94397c 100644 (file)
 
                MSI: ppc4xx-msi@C10000000 {
                        compatible = "amcc,ppc4xx-msi", "ppc4xx-msi";
-                       reg = < 0x0 0xEF620000 0x100>;
+                       reg = <0xEF620000 0x100>;
                        sdr-base = <0x4B0>;
                        msi-data = <0x00000000>;
                        msi-mask = <0x44440000>;
index bd14c00e5146b31a90c8913e2b605c06d40184f1..2c0e1552d20bb9a410ab6c27762d676e6e7f5b9e 100644 (file)
@@ -9,6 +9,8 @@
  * option) any later version.
  */
 
+#include <dt-bindings/clock/mpc512x-clock.h>
+
 /dts-v1/;
 
 / {
                compatible = "fsl,mpc5121-mbx";
                reg = <0x20000000 0x4000>;
                interrupts = <66 0x8>;
+               clocks = <&clks MPC512x_CLK_MBX_BUS>,
+                        <&clks MPC512x_CLK_MBX_3D>,
+                        <&clks MPC512x_CLK_MBX>;
+               clock-names = "mbx-bus", "mbx-3d", "mbx";
        };
 
        sram@30000000 {
@@ -62,6 +68,8 @@
                interrupts = <6 8>;
                #address-cells = <1>;
                #size-cells = <1>;
+               clocks = <&clks MPC512x_CLK_NFC>;
+               clock-names = "ipg";
        };
 
        localbus@80000020 {
                ranges = <0x0 0x0 0xfc000000 0x04000000>;
        };
 
+       clocks {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               osc: osc {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <33000000>;
+               };
+       };
+
        soc@80000000 {
                compatible = "fsl,mpc5121-immr";
                #address-cells = <1>;
                #size-cells = <1>;
-               #interrupt-cells = <2>;
                ranges = <0x0 0x80000000 0x400000>;
                reg = <0x80000000 0x400000>;
                bus-frequency = <66000000>;     /* 66 MHz ips bus */
                };
 
                /* Clock control */
-               clock@f00 {
+               clks: clock@f00 {
                        compatible = "fsl,mpc5121-clock";
                        reg = <0xf00 0x100>;
+                       #clock-cells = <1>;
+                       clocks = <&osc>;
+                       clock-names = "osc";
                };
 
                /* Power Management Controller */
                        compatible = "fsl,mpc5121-mscan";
                        reg = <0x1300 0x80>;
                        interrupts = <12 0x8>;
+                       clocks = <&clks MPC512x_CLK_BDLC>,
+                                <&clks MPC512x_CLK_IPS>,
+                                <&clks MPC512x_CLK_SYS>,
+                                <&clks MPC512x_CLK_REF>,
+                                <&clks MPC512x_CLK_MSCAN0_MCLK>;
+                       clock-names = "ipg", "ips", "sys", "ref", "mclk";
                };
 
                can@1380 {
                        compatible = "fsl,mpc5121-mscan";
                        reg = <0x1380 0x80>;
                        interrupts = <13 0x8>;
+                       clocks = <&clks MPC512x_CLK_BDLC>,
+                                <&clks MPC512x_CLK_IPS>,
+                                <&clks MPC512x_CLK_SYS>,
+                                <&clks MPC512x_CLK_REF>,
+                                <&clks MPC512x_CLK_MSCAN1_MCLK>;
+                       clock-names = "ipg", "ips", "sys", "ref", "mclk";
                };
 
                sdhc@1500 {
                        interrupts = <8 0x8>;
                        dmas = <&dma0 30>;
                        dma-names = "rx-tx";
+                       clocks = <&clks MPC512x_CLK_IPS>,
+                                <&clks MPC512x_CLK_SDHC>;
+                       clock-names = "ipg", "per";
                };
 
                i2c@1700 {
                        compatible = "fsl,mpc5121-i2c", "fsl-i2c";
                        reg = <0x1700 0x20>;
                        interrupts = <9 0x8>;
+                       clocks = <&clks MPC512x_CLK_I2C>;
+                       clock-names = "ipg";
                };
 
                i2c@1720 {
                        compatible = "fsl,mpc5121-i2c", "fsl-i2c";
                        reg = <0x1720 0x20>;
                        interrupts = <10 0x8>;
+                       clocks = <&clks MPC512x_CLK_I2C>;
+                       clock-names = "ipg";
                };
 
                i2c@1740 {
                        compatible = "fsl,mpc5121-i2c", "fsl-i2c";
                        reg = <0x1740 0x20>;
                        interrupts = <11 0x8>;
+                       clocks = <&clks MPC512x_CLK_I2C>;
+                       clock-names = "ipg";
                };
 
                i2ccontrol@1760 {
                        compatible = "fsl,mpc5121-axe";
                        reg = <0x2000 0x100>;
                        interrupts = <42 0x8>;
+                       clocks = <&clks MPC512x_CLK_AXE>;
+                       clock-names = "ipg";
                };
 
                display@2100 {
                        compatible = "fsl,mpc5121-diu";
                        reg = <0x2100 0x100>;
                        interrupts = <64 0x8>;
+                       clocks = <&clks MPC512x_CLK_DIU>;
+                       clock-names = "ipg";
                };
 
                can@2300 {
                        compatible = "fsl,mpc5121-mscan";
                        reg = <0x2300 0x80>;
                        interrupts = <90 0x8>;
+                       clocks = <&clks MPC512x_CLK_BDLC>,
+                                <&clks MPC512x_CLK_IPS>,
+                                <&clks MPC512x_CLK_SYS>,
+                                <&clks MPC512x_CLK_REF>,
+                                <&clks MPC512x_CLK_MSCAN2_MCLK>;
+                       clock-names = "ipg", "ips", "sys", "ref", "mclk";
                };
 
                can@2380 {
                        compatible = "fsl,mpc5121-mscan";
                        reg = <0x2380 0x80>;
                        interrupts = <91 0x8>;
+                       clocks = <&clks MPC512x_CLK_BDLC>,
+                                <&clks MPC512x_CLK_IPS>,
+                                <&clks MPC512x_CLK_SYS>,
+                                <&clks MPC512x_CLK_REF>,
+                                <&clks MPC512x_CLK_MSCAN3_MCLK>;
+                       clock-names = "ipg", "ips", "sys", "ref", "mclk";
                };
 
                viu@2400 {
                        compatible = "fsl,mpc5121-viu";
                        reg = <0x2400 0x400>;
                        interrupts = <67 0x8>;
+                       clocks = <&clks MPC512x_CLK_VIU>;
+                       clock-names = "ipg";
                };
 
                mdio@2800 {
                        reg = <0x2800 0x800>;
                        #address-cells = <1>;
                        #size-cells = <0>;
+                       clocks = <&clks MPC512x_CLK_FEC>;
+                       clock-names = "per";
                };
 
                eth0: ethernet@2800 {
                        reg = <0x2800 0x800>;
                        local-mac-address = [ 00 00 00 00 00 00 ];
                        interrupts = <4 0x8>;
+                       clocks = <&clks MPC512x_CLK_FEC>;
+                       clock-names = "per";
                };
 
                /* USB1 using external ULPI PHY */
                        interrupts = <43 0x8>;
                        dr_mode = "otg";
                        phy_type = "ulpi";
+                       clocks = <&clks MPC512x_CLK_USB1>;
+                       clock-names = "ipg";
                };
 
                /* USB0 using internal UTMI PHY */
                        interrupts = <44 0x8>;
                        dr_mode = "otg";
                        phy_type = "utmi_wide";
+                       clocks = <&clks MPC512x_CLK_USB2>;
+                       clock-names = "ipg";
                };
 
                /* IO control */
                        compatible = "fsl,mpc5121-pata";
                        reg = <0x10200 0x100>;
                        interrupts = <5 0x8>;
+                       clocks = <&clks MPC512x_CLK_PATA>;
+                       clock-names = "ipg";
                };
 
                /* 512x PSCs are not 52xx PSC compatible */
                        interrupts = <40 0x8>;
                        fsl,rx-fifo-size = <16>;
                        fsl,tx-fifo-size = <16>;
+                       clocks = <&clks MPC512x_CLK_PSC0>,
+                                <&clks MPC512x_CLK_PSC0_MCLK>;
+                       clock-names = "ipg", "mclk";
                };
 
                /* PSC1 */
                        interrupts = <40 0x8>;
                        fsl,rx-fifo-size = <16>;
                        fsl,tx-fifo-size = <16>;
+                       clocks = <&clks MPC512x_CLK_PSC1>,
+                                <&clks MPC512x_CLK_PSC1_MCLK>;
+                       clock-names = "ipg", "mclk";
                };
 
                /* PSC2 */
                        interrupts = <40 0x8>;
                        fsl,rx-fifo-size = <16>;
                        fsl,tx-fifo-size = <16>;
+                       clocks = <&clks MPC512x_CLK_PSC2>,
+                                <&clks MPC512x_CLK_PSC2_MCLK>;
+                       clock-names = "ipg", "mclk";
                };
 
                /* PSC3 */
                        interrupts = <40 0x8>;
                        fsl,rx-fifo-size = <16>;
                        fsl,tx-fifo-size = <16>;
+                       clocks = <&clks MPC512x_CLK_PSC3>,
+                                <&clks MPC512x_CLK_PSC3_MCLK>;
+                       clock-names = "ipg", "mclk";
                };
 
                /* PSC4 */
                        interrupts = <40 0x8>;
                        fsl,rx-fifo-size = <16>;
                        fsl,tx-fifo-size = <16>;
+                       clocks = <&clks MPC512x_CLK_PSC4>,
+                                <&clks MPC512x_CLK_PSC4_MCLK>;
+                       clock-names = "ipg", "mclk";
                };
 
                /* PSC5 */
                        interrupts = <40 0x8>;
                        fsl,rx-fifo-size = <16>;
                        fsl,tx-fifo-size = <16>;
+                       clocks = <&clks MPC512x_CLK_PSC5>,
+                                <&clks MPC512x_CLK_PSC5_MCLK>;
+                       clock-names = "ipg", "mclk";
                };
 
                /* PSC6 */
                        interrupts = <40 0x8>;
                        fsl,rx-fifo-size = <16>;
                        fsl,tx-fifo-size = <16>;
+                       clocks = <&clks MPC512x_CLK_PSC6>,
+                                <&clks MPC512x_CLK_PSC6_MCLK>;
+                       clock-names = "ipg", "mclk";
                };
 
                /* PSC7 */
                        interrupts = <40 0x8>;
                        fsl,rx-fifo-size = <16>;
                        fsl,tx-fifo-size = <16>;
+                       clocks = <&clks MPC512x_CLK_PSC7>,
+                                <&clks MPC512x_CLK_PSC7_MCLK>;
+                       clock-names = "ipg", "mclk";
                };
 
                /* PSC8 */
                        interrupts = <40 0x8>;
                        fsl,rx-fifo-size = <16>;
                        fsl,tx-fifo-size = <16>;
+                       clocks = <&clks MPC512x_CLK_PSC8>,
+                                <&clks MPC512x_CLK_PSC8_MCLK>;
+                       clock-names = "ipg", "mclk";
                };
 
                /* PSC9 */
                        interrupts = <40 0x8>;
                        fsl,rx-fifo-size = <16>;
                        fsl,tx-fifo-size = <16>;
+                       clocks = <&clks MPC512x_CLK_PSC9>,
+                                <&clks MPC512x_CLK_PSC9_MCLK>;
+                       clock-names = "ipg", "mclk";
                };
 
                /* PSC10 */
                        interrupts = <40 0x8>;
                        fsl,rx-fifo-size = <16>;
                        fsl,tx-fifo-size = <16>;
+                       clocks = <&clks MPC512x_CLK_PSC10>,
+                                <&clks MPC512x_CLK_PSC10_MCLK>;
+                       clock-names = "ipg", "mclk";
                };
 
                /* PSC11 */
                        interrupts = <40 0x8>;
                        fsl,rx-fifo-size = <16>;
                        fsl,tx-fifo-size = <16>;
+                       clocks = <&clks MPC512x_CLK_PSC11>,
+                                <&clks MPC512x_CLK_PSC11_MCLK>;
+                       clock-names = "ipg", "mclk";
                };
 
                pscfifo@11f00 {
                        compatible = "fsl,mpc5121-psc-fifo";
                        reg = <0x11f00 0x100>;
                        interrupts = <40 0x8>;
+                       clocks = <&clks MPC512x_CLK_PSC_FIFO>;
+                       clock-names = "ipg";
                };
 
                dma0: dma@14000 {
                #address-cells = <3>;
                #size-cells = <2>;
                #interrupt-cells = <1>;
+               clocks = <&clks MPC512x_CLK_PCI>;
+               clock-names = "ipg";
 
                reg = <0x80008500 0x100 /* internal registers */
                       0x80008300 0x8>; /* config space access registers */
index fc7073bc547efaa4e196a80d08be24155fea9695..391a4e299783d84830002c95535bd9a5c6d9c848 100644 (file)
                        #size-cells = <1>;
                        compatible = "xlnx,compound";
                        ethernet@81c00000 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
                                compatible = "xlnx,xps-ll-temac-1.01.b";
                                device_type = "network";
                                interrupt-parent = <&xps_intc_0>;
index 69b57daf402e056d0739e4ec50303f8349b78c0d..0b88c7b30bb9a4a5697cc87fe8fd6486bfca6bf4 100644 (file)
@@ -12,7 +12,6 @@ CONFIG_EXPERT=y
 CONFIG_PPC_MPC52xx=y
 CONFIG_PPC_MPC5200_SIMPLE=y
 # CONFIG_PPC_PMAC is not set
-CONFIG_PPC_BESTCOMM=y
 CONFIG_SPARSE_IRQ=y
 CONFIG_PM=y
 # CONFIG_PCI is not set
@@ -71,6 +70,8 @@ CONFIG_USB_DEVICEFS=y
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 CONFIG_USB_STORAGE=y
+CONFIG_DMADEVICES=y
+CONFIG_PPC_BESTCOMM=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
index f3638ae0a627ceb6c481dae4bbc588616864548c..104a332e79ab961f2881776ea0ca80539b4444b7 100644 (file)
@@ -15,7 +15,6 @@ CONFIG_PPC_MPC52xx=y
 CONFIG_PPC_MPC5200_SIMPLE=y
 CONFIG_PPC_LITE5200=y
 # CONFIG_PPC_PMAC is not set
-CONFIG_PPC_BESTCOMM=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SPARSE_IRQ=y
@@ -59,6 +58,8 @@ CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_MPC=y
 # CONFIG_HWMON is not set
 CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_DMADEVICES=y
+CONFIG_PPC_BESTCOMM=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
index 0c7de9620ea64a1715a836866c244dc1317e38d4..0d13ad7e44782fdf9adafa6f3a82231920048c98 100644 (file)
@@ -12,7 +12,6 @@ CONFIG_EXPERT=y
 CONFIG_PPC_MPC52xx=y
 CONFIG_PPC_MPC5200_SIMPLE=y
 # CONFIG_PPC_PMAC is not set
-CONFIG_PPC_BESTCOMM=y
 CONFIG_SPARSE_IRQ=y
 CONFIG_PM=y
 # CONFIG_PCI is not set
@@ -84,6 +83,8 @@ CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_DS1307=y
+CONFIG_DMADEVICES=y
+CONFIG_PPC_BESTCOMM=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
index 22e719575c60b33cb64cee5fcb840c2507f942c8..430aa182fa1ceab8f53ca6af410ca39772095f3b 100644 (file)
@@ -21,7 +21,6 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_PPC_MPC52xx=y
 CONFIG_PPC_MPC5200_SIMPLE=y
 # CONFIG_PPC_PMAC is not set
-CONFIG_PPC_BESTCOMM=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_HZ_100=y
@@ -87,6 +86,8 @@ CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 CONFIG_USB_STORAGE=m
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_PCF8563=m
+CONFIG_DMADEVICES=y
+CONFIG_PPC_BESTCOMM=y
 CONFIG_EXT2_FS=m
 CONFIG_EXT3_FS=m
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
index 716a37be16e33b5d071416592ca8eb39fc7cca2f..7af4c5bb7c63b30d23a058d885a26cbe40b179ee 100644 (file)
@@ -17,7 +17,6 @@ CONFIG_PPC_MPC52xx=y
 CONFIG_PPC_MPC5200_SIMPLE=y
 CONFIG_PPC_MPC5200_BUGFIX=y
 # CONFIG_PPC_PMAC is not set
-CONFIG_PPC_BESTCOMM=y
 CONFIG_PM=y
 # CONFIG_PCI is not set
 CONFIG_NET=y
@@ -86,6 +85,8 @@ CONFIG_USB_STORAGE=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_DS1307=y
 CONFIG_RTC_DRV_DS1374=y
+CONFIG_DMADEVICES=y
+CONFIG_PPC_BESTCOMM=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
index 6640a35bebb7ac74d88d63f5c4420510088e088a..8b682d1cf4d6c49e90f83182db293fc6f1db6264 100644 (file)
@@ -15,7 +15,6 @@ CONFIG_PPC_MEDIA5200=y
 CONFIG_PPC_MPC5200_BUGFIX=y
 CONFIG_PPC_MPC5200_LPBFIFO=m
 # CONFIG_PPC_PMAC is not set
-CONFIG_PPC_BESTCOMM=y
 CONFIG_SIMPLE_GPIO=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -125,6 +124,8 @@ CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_DS1307=y
 CONFIG_RTC_DRV_DS1374=y
 CONFIG_RTC_DRV_PCF8563=m
+CONFIG_DMADEVICES=y
+CONFIG_PPC_BESTCOMM=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
index bd8a6f71944f153367df2312fa121ed97977ce27..cec044a3ff69dd6c05dcfec122fcb53653b412f8 100644 (file)
@@ -2,7 +2,6 @@ CONFIG_PPC64=y
 CONFIG_ALTIVEC=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
-CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -45,8 +44,9 @@ CONFIG_INET_AH=y
 CONFIG_INET_ESP=y
 # CONFIG_IPV6 is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_MTD=y
-CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_SLRAM=y
 CONFIG_MTD_PHRAM=y
@@ -88,7 +88,6 @@ CONFIG_BLK_DEV_DM=y
 CONFIG_DM_CRYPT=y
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
-CONFIG_MII=y
 CONFIG_TIGON3=y
 CONFIG_E1000=y
 CONFIG_PASEMI_MAC=y
@@ -174,8 +173,8 @@ CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_CRC_CCITT=y
 CONFIG_PRINTK_TIME=y
-CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
+CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 # CONFIG_SCHED_DEBUG is not set
index 910194e9a1e2a2eab5f64d05be6cf9a522cb33a0..a5e9a7d494d8bd685104397bff26d0265dc15e54 100644 (file)
 #include <asm/asm-compat.h>
 #include <asm/synch.h>
 
+/* PPC bit number conversion */
+#define PPC_BITLSHIFT(be)      (BITS_PER_LONG - 1 - (be))
+#define PPC_BIT(bit)           (1UL << PPC_BITLSHIFT(bit))
+#define PPC_BITMASK(bs, be)    ((PPC_BIT(bs) - PPC_BIT(be)) | PPC_BIT(bs))
+
 /*
  * clear_bit doesn't imply a memory barrier
  */
index 9e495c9a6a889d68bca11e1575ee82c3422b7348..ed0afc1e44a43324a31fb59994b42a768ecb8e33 100644 (file)
@@ -41,8 +41,20 @@ struct ppc64_caches {
 extern struct ppc64_caches ppc64_caches;
 #endif /* __powerpc64__ && ! __ASSEMBLY__ */
 
-#if !defined(__ASSEMBLY__)
+#if defined(__ASSEMBLY__)
+/*
+ * For a snooping icache, we still need a dummy icbi to purge all the
+ * prefetched instructions from the ifetch buffers. We also need a sync
+ * before the icbi to order the the actual stores to memory that might
+ * have modified instructions with the icbi.
+ */
+#define PURGE_PREFETCHED_INS   \
+       sync;                   \
+       icbi    0,r3;           \
+       sync;                   \
+       isync
 
+#else
 #define __read_mostly __attribute__((__section__(".data..read_mostly")))
 
 #ifdef CONFIG_6xx
diff --git a/arch/powerpc/include/asm/clk_interface.h b/arch/powerpc/include/asm/clk_interface.h
deleted file mode 100644 (file)
index ab1882c..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef __ASM_POWERPC_CLK_INTERFACE_H
-#define __ASM_POWERPC_CLK_INTERFACE_H
-
-#include <linux/clk.h>
-
-struct clk_interface {
-       struct clk*     (*clk_get)      (struct device *dev, const char *id);
-       int             (*clk_enable)   (struct clk *clk);
-       void            (*clk_disable)  (struct clk *clk);
-       unsigned long   (*clk_get_rate) (struct clk *clk);
-       void            (*clk_put)      (struct clk *clk);
-       long            (*clk_round_rate) (struct clk *clk, unsigned long rate);
-       int             (*clk_set_rate) (struct clk *clk, unsigned long rate);
-       int             (*clk_set_parent) (struct clk *clk, struct clk *parent);
-       struct clk*     (*clk_get_parent) (struct clk *clk);
-};
-
-extern struct clk_interface clk_functions;
-
-#endif /* __ASM_POWERPC_CLK_INTERFACE_H */
index a6f8c7a5cbb74f61925243a1ca42bc183d80361a..97e02f985df8e47946438ecc1b0ba2f040ee7bf5 100644 (file)
@@ -34,6 +34,13 @@ int instr_is_branch_to_addr(const unsigned int *instr, unsigned long addr);
 unsigned long branch_target(const unsigned int *instr);
 unsigned int translate_branch(const unsigned int *dest,
                              const unsigned int *src);
+#ifdef CONFIG_PPC_BOOK3E_64
+void __patch_exception(int exc, unsigned long addr);
+#define patch_exception(exc, name) do { \
+       extern unsigned int name; \
+       __patch_exception((exc), (unsigned long)&name); \
+} while (0)
+#endif
 
 static inline unsigned long ppc_function_entry(void *func)
 {
index 0d4939ba48e72167a9a496f4f10a805d0badd3eb..617cc767c07681b109c5acd54f667cc3274956b5 100644 (file)
@@ -90,6 +90,18 @@ struct cpu_spec {
         * if the error is fatal, 1 if it was fully recovered and 0 to
         * pass up (not CPU originated) */
        int             (*machine_check)(struct pt_regs *regs);
+
+       /*
+        * Processor specific early machine check handler which is
+        * called in real mode to handle SLB and TLB errors.
+        */
+       long            (*machine_check_early)(struct pt_regs *regs);
+
+       /*
+        * Processor specific routine to flush tlbs.
+        */
+       void            (*flush_tlb)(unsigned long inval_selector);
+
 };
 
 extern struct cpu_spec         *cur_cpu_spec;
index 894662a5d4d5c5aa25f43e30653609d80d901774..ff4e2e80856debaaeda9e72ca35a6a4595dc405e 100644 (file)
@@ -301,9 +301,12 @@ do_kvm_##n:                                                                \
        beq     4f;                     /* if from kernel mode          */ \
        ACCOUNT_CPU_USER_ENTRY(r9, r10);                                   \
        SAVE_PPR(area, r9, r10);                                           \
-4:     std     r2,GPR2(r1);            /* save r2 in stackframe        */ \
-       SAVE_4GPRS(3, r1);              /* save r3 - r6 in stackframe   */ \
-       SAVE_2GPRS(7, r1);              /* save r7, r8 in stackframe    */ \
+4:     EXCEPTION_PROLOG_COMMON_2(area)                                    \
+       EXCEPTION_PROLOG_COMMON_3(n)                                       \
+       ACCOUNT_STOLEN_TIME
+
+/* Save original regs values from save area to stack frame. */
+#define EXCEPTION_PROLOG_COMMON_2(area)                                           \
        ld      r9,area+EX_R9(r13);     /* move r9, r10 to stackframe   */ \
        ld      r10,area+EX_R10(r13);                                      \
        std     r9,GPR9(r1);                                               \
@@ -318,11 +321,16 @@ do_kvm_##n:                                                               \
        ld      r10,area+EX_CFAR(r13);                                     \
        std     r10,ORIG_GPR3(r1);                                         \
        END_FTR_SECTION_NESTED(CPU_FTR_CFAR, CPU_FTR_CFAR, 66);            \
+       GET_CTR(r10, area);                                                \
+       std     r10,_CTR(r1);
+
+#define EXCEPTION_PROLOG_COMMON_3(n)                                      \
+       std     r2,GPR2(r1);            /* save r2 in stackframe        */ \
+       SAVE_4GPRS(3, r1);              /* save r3 - r6 in stackframe   */ \
+       SAVE_2GPRS(7, r1);              /* save r7, r8 in stackframe    */ \
        mflr    r9;                     /* Get LR, later save to stack  */ \
        ld      r2,PACATOC(r13);        /* get kernel TOC into r2       */ \
        std     r9,_LINK(r1);                                              \
-       GET_CTR(r10, area);                                                \
-       std     r10,_CTR(r1);                                              \
        lbz     r10,PACASOFTIRQEN(r13);                            \
        mfspr   r11,SPRN_XER;           /* save XER in stackframe       */ \
        std     r10,SOFTE(r1);                                             \
@@ -332,8 +340,7 @@ do_kvm_##n:                                                         \
        li      r10,0;                                                     \
        ld      r11,exception_marker@toc(r2);                              \
        std     r10,RESULT(r1);         /* clear regs->result           */ \
-       std     r11,STACK_FRAME_OVERHEAD-16(r1); /* mark the frame      */ \
-       ACCOUNT_STOLEN_TIME
+       std     r11,STACK_FRAME_OVERHEAD-16(r1); /* mark the frame      */
 
 /*
  * Exception vectors.
index 3bdcfce2c42a926bebc7c2f580ee720f96350818..418fb654370d09c70837943fe399dba75a10cfd2 100644 (file)
@@ -6,7 +6,8 @@
 
 typedef struct {
        unsigned int __softirq_pending;
-       unsigned int timer_irqs;
+       unsigned int timer_irqs_event;
+       unsigned int timer_irqs_others;
        unsigned int pmu_irqs;
        unsigned int mce_exceptions;
        unsigned int spurious_irqs;
index 575fbf81fad02dcd8e946cecfa9c5d5c35e11810..97d3869991ca691ebf0342b496ebe767aee7492a 100644 (file)
@@ -191,8 +191,24 @@ DEF_MMIO_OUT_D(out_le32, 32, stw);
 
 #endif /* __BIG_ENDIAN */
 
+/*
+ * Cache inhibitied accessors for use in real mode, you don't want to use these
+ * unless you know what you're doing.
+ *
+ * NB. These use the cpu byte ordering.
+ */
+DEF_MMIO_OUT_X(out_rm8,   8, stbcix);
+DEF_MMIO_OUT_X(out_rm16, 16, sthcix);
+DEF_MMIO_OUT_X(out_rm32, 32, stwcix);
+DEF_MMIO_IN_X(in_rm8,   8, lbzcix);
+DEF_MMIO_IN_X(in_rm16, 16, lhzcix);
+DEF_MMIO_IN_X(in_rm32, 32, lwzcix);
+
 #ifdef __powerpc64__
 
+DEF_MMIO_OUT_X(out_rm64, 64, stdcix);
+DEF_MMIO_IN_X(in_rm64, 64, ldcix);
+
 #ifdef __BIG_ENDIAN__
 DEF_MMIO_OUT_D(out_be64, 64, std);
 DEF_MMIO_IN_D(in_be64, 64, ld);
index c34656a8925e2f8c3d64d42f7f4efd79dbe36872..774fa2776907ffc570777dc1207fb24c65aa1270 100644 (file)
@@ -101,8 +101,34 @@ extern void iommu_free_table(struct iommu_table *tbl, const char *node_name);
  */
 extern struct iommu_table *iommu_init_table(struct iommu_table * tbl,
                                            int nid);
+#ifdef CONFIG_IOMMU_API
 extern void iommu_register_group(struct iommu_table *tbl,
                                 int pci_domain_number, unsigned long pe_num);
+extern int iommu_add_device(struct device *dev);
+extern void iommu_del_device(struct device *dev);
+#else
+static inline void iommu_register_group(struct iommu_table *tbl,
+                                       int pci_domain_number,
+                                       unsigned long pe_num)
+{
+}
+
+static inline int iommu_add_device(struct device *dev)
+{
+       return 0;
+}
+
+static inline void iommu_del_device(struct device *dev)
+{
+}
+#endif /* !CONFIG_IOMMU_API */
+
+static inline void set_iommu_table_base_and_group(struct device *dev,
+                                                 void *base)
+{
+       set_iommu_table_base(dev, base);
+       iommu_add_device(dev);
+}
 
 extern int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
                        struct scatterlist *sglist, int nelems,
index 844c28de7ec05e96f4578701a9d46c6dda6d2ecb..d0a2a2f9956471362e13093272955f42c0e4121b 100644 (file)
@@ -132,8 +132,6 @@ struct slb_shadow {
        } save_area[SLB_NUM_BOLTED];
 } ____cacheline_aligned;
 
-extern struct slb_shadow slb_shadow[];
-
 /*
  * Layout of entries in the hypervisor's dispatch trace log buffer.
  */
diff --git a/arch/powerpc/include/asm/mce.h b/arch/powerpc/include/asm/mce.h
new file mode 100644 (file)
index 0000000..a2b8c7b
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * Machine check exception header 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.
+ *
+ * Copyright 2013 IBM Corporation
+ * Author: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
+ */
+
+#ifndef __ASM_PPC64_MCE_H__
+#define __ASM_PPC64_MCE_H__
+
+#include <linux/bitops.h>
+
+/*
+ * Machine Check bits on power7 and power8
+ */
+#define P7_SRR1_MC_LOADSTORE(srr1)     ((srr1) & PPC_BIT(42)) /* P8 too */
+
+/* SRR1 bits for machine check (On Power7 and Power8) */
+#define P7_SRR1_MC_IFETCH(srr1)        ((srr1) & PPC_BITMASK(43, 45)) /* P8 too */
+
+#define P7_SRR1_MC_IFETCH_UE           (0x1 << PPC_BITLSHIFT(45)) /* P8 too */
+#define P7_SRR1_MC_IFETCH_SLB_PARITY   (0x2 << PPC_BITLSHIFT(45)) /* P8 too */
+#define P7_SRR1_MC_IFETCH_SLB_MULTIHIT (0x3 << PPC_BITLSHIFT(45)) /* P8 too */
+#define P7_SRR1_MC_IFETCH_SLB_BOTH     (0x4 << PPC_BITLSHIFT(45))
+#define P7_SRR1_MC_IFETCH_TLB_MULTIHIT (0x5 << PPC_BITLSHIFT(45)) /* P8 too */
+#define P7_SRR1_MC_IFETCH_UE_TLB_RELOAD        (0x6 << PPC_BITLSHIFT(45)) /* P8 too */
+#define P7_SRR1_MC_IFETCH_UE_IFU_INTERNAL      (0x7 << PPC_BITLSHIFT(45))
+
+/* SRR1 bits for machine check (On Power8) */
+#define P8_SRR1_MC_IFETCH_ERAT_MULTIHIT        (0x4 << PPC_BITLSHIFT(45))
+
+/* DSISR bits for machine check (On Power7 and Power8) */
+#define P7_DSISR_MC_UE                 (PPC_BIT(48))   /* P8 too */
+#define P7_DSISR_MC_UE_TABLEWALK       (PPC_BIT(49))   /* P8 too */
+#define P7_DSISR_MC_ERAT_MULTIHIT      (PPC_BIT(52))   /* P8 too */
+#define P7_DSISR_MC_TLB_MULTIHIT_MFTLB (PPC_BIT(53))   /* P8 too */
+#define P7_DSISR_MC_SLB_PARITY_MFSLB   (PPC_BIT(55))   /* P8 too */
+#define P7_DSISR_MC_SLB_MULTIHIT       (PPC_BIT(56))   /* P8 too */
+#define P7_DSISR_MC_SLB_MULTIHIT_PARITY        (PPC_BIT(57))   /* P8 too */
+
+/*
+ * DSISR bits for machine check (Power8) in addition to above.
+ * Secondary DERAT Multihit
+ */
+#define P8_DSISR_MC_ERAT_MULTIHIT_SEC  (PPC_BIT(54))
+
+/* SLB error bits */
+#define P7_DSISR_MC_SLB_ERRORS         (P7_DSISR_MC_ERAT_MULTIHIT | \
+                                        P7_DSISR_MC_SLB_PARITY_MFSLB | \
+                                        P7_DSISR_MC_SLB_MULTIHIT | \
+                                        P7_DSISR_MC_SLB_MULTIHIT_PARITY)
+
+#define P8_DSISR_MC_SLB_ERRORS         (P7_DSISR_MC_SLB_ERRORS | \
+                                        P8_DSISR_MC_ERAT_MULTIHIT_SEC)
+enum MCE_Version {
+       MCE_V1 = 1,
+};
+
+enum MCE_Severity {
+       MCE_SEV_NO_ERROR = 0,
+       MCE_SEV_WARNING = 1,
+       MCE_SEV_ERROR_SYNC = 2,
+       MCE_SEV_FATAL = 3,
+};
+
+enum MCE_Disposition {
+       MCE_DISPOSITION_RECOVERED = 0,
+       MCE_DISPOSITION_NOT_RECOVERED = 1,
+};
+
+enum MCE_Initiator {
+       MCE_INITIATOR_UNKNOWN = 0,
+       MCE_INITIATOR_CPU = 1,
+};
+
+enum MCE_ErrorType {
+       MCE_ERROR_TYPE_UNKNOWN = 0,
+       MCE_ERROR_TYPE_UE = 1,
+       MCE_ERROR_TYPE_SLB = 2,
+       MCE_ERROR_TYPE_ERAT = 3,
+       MCE_ERROR_TYPE_TLB = 4,
+};
+
+enum MCE_UeErrorType {
+       MCE_UE_ERROR_INDETERMINATE = 0,
+       MCE_UE_ERROR_IFETCH = 1,
+       MCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH = 2,
+       MCE_UE_ERROR_LOAD_STORE = 3,
+       MCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE = 4,
+};
+
+enum MCE_SlbErrorType {
+       MCE_SLB_ERROR_INDETERMINATE = 0,
+       MCE_SLB_ERROR_PARITY = 1,
+       MCE_SLB_ERROR_MULTIHIT = 2,
+};
+
+enum MCE_EratErrorType {
+       MCE_ERAT_ERROR_INDETERMINATE = 0,
+       MCE_ERAT_ERROR_PARITY = 1,
+       MCE_ERAT_ERROR_MULTIHIT = 2,
+};
+
+enum MCE_TlbErrorType {
+       MCE_TLB_ERROR_INDETERMINATE = 0,
+       MCE_TLB_ERROR_PARITY = 1,
+       MCE_TLB_ERROR_MULTIHIT = 2,
+};
+
+struct machine_check_event {
+       enum MCE_Version        version:8;      /* 0x00 */
+       uint8_t                 in_use;         /* 0x01 */
+       enum MCE_Severity       severity:8;     /* 0x02 */
+       enum MCE_Initiator      initiator:8;    /* 0x03 */
+       enum MCE_ErrorType      error_type:8;   /* 0x04 */
+       enum MCE_Disposition    disposition:8;  /* 0x05 */
+       uint8_t                 reserved_1[2];  /* 0x06 */
+       uint64_t                gpr3;           /* 0x08 */
+       uint64_t                srr0;           /* 0x10 */
+       uint64_t                srr1;           /* 0x18 */
+       union {                                 /* 0x20 */
+               struct {
+                       enum MCE_UeErrorType ue_error_type:8;
+                       uint8_t         effective_address_provided;
+                       uint8_t         physical_address_provided;
+                       uint8_t         reserved_1[5];
+                       uint64_t        effective_address;
+                       uint64_t        physical_address;
+                       uint8_t         reserved_2[8];
+               } ue_error;
+
+               struct {
+                       enum MCE_SlbErrorType slb_error_type:8;
+                       uint8_t         effective_address_provided;
+                       uint8_t         reserved_1[6];
+                       uint64_t        effective_address;
+                       uint8_t         reserved_2[16];
+               } slb_error;
+
+               struct {
+                       enum MCE_EratErrorType erat_error_type:8;
+                       uint8_t         effective_address_provided;
+                       uint8_t         reserved_1[6];
+                       uint64_t        effective_address;
+                       uint8_t         reserved_2[16];
+               } erat_error;
+
+               struct {
+                       enum MCE_TlbErrorType tlb_error_type:8;
+                       uint8_t         effective_address_provided;
+                       uint8_t         reserved_1[6];
+                       uint64_t        effective_address;
+                       uint8_t         reserved_2[16];
+               } tlb_error;
+       } u;
+};
+
+struct mce_error_info {
+       enum MCE_ErrorType error_type:8;
+       union {
+               enum MCE_UeErrorType ue_error_type:8;
+               enum MCE_SlbErrorType slb_error_type:8;
+               enum MCE_EratErrorType erat_error_type:8;
+               enum MCE_TlbErrorType tlb_error_type:8;
+       } u;
+       uint8_t         reserved[2];
+};
+
+#define MAX_MC_EVT     100
+
+/* Release flags for get_mce_event() */
+#define MCE_EVENT_RELEASE      true
+#define MCE_EVENT_DONTRELEASE  false
+
+extern void save_mce_event(struct pt_regs *regs, long handled,
+                          struct mce_error_info *mce_err, uint64_t addr);
+extern int get_mce_event(struct machine_check_event *mce, bool release);
+extern void release_mce_event(void);
+extern void machine_check_queue_event(void);
+extern void machine_check_process_queued_event(void);
+extern void machine_check_print_event_info(struct machine_check_event *evt);
+extern uint64_t get_mce_fault_addr(struct machine_check_event *evt);
+
+#endif /* __ASM_PPC64_MCE_H__ */
index 033c06be1d840da02423d596121940d0aa11adb5..aded1b81bfd6c989506c96edf8b61441009732a0 100644 (file)
@@ -33,6 +33,28 @@ struct opal_takeover_args {
        u64     rd_loc;                 /* r11 */
 };
 
+/*
+ * SG entry
+ *
+ * WARNING: The current implementation requires each entry
+ * to represent a block that is 4k aligned *and* each block
+ * size except the last one in the list to be as well.
+ */
+struct opal_sg_entry {
+       void    *data;
+       long    length;
+};
+
+/* sg list */
+struct opal_sg_list {
+       unsigned long num_entries;
+       struct opal_sg_list *next;
+       struct opal_sg_entry entry[];
+};
+
+/* We calculate number of sg entries based on PAGE_SIZE */
+#define SG_ENTRIES_PER_NODE ((PAGE_SIZE - 16) / sizeof(struct opal_sg_entry))
+
 extern long opal_query_takeover(u64 *hal_size, u64 *hal_align);
 
 extern long opal_do_takeover(struct opal_takeover_args *args);
@@ -132,6 +154,8 @@ extern int opal_enter_rtas(struct rtas_args *args,
 #define OPAL_FLASH_VALIDATE                    76
 #define OPAL_FLASH_MANAGE                      77
 #define OPAL_FLASH_UPDATE                      78
+#define OPAL_GET_MSG                           85
+#define OPAL_CHECK_ASYNC_COMPLETION            86
 
 #ifndef __ASSEMBLY__
 
@@ -211,7 +235,16 @@ enum OpalPendingState {
        OPAL_EVENT_ERROR_LOG            = 0x40,
        OPAL_EVENT_EPOW                 = 0x80,
        OPAL_EVENT_LED_STATUS           = 0x100,
-       OPAL_EVENT_PCI_ERROR            = 0x200
+       OPAL_EVENT_PCI_ERROR            = 0x200,
+       OPAL_EVENT_MSG_PENDING          = 0x800,
+};
+
+enum OpalMessageType {
+       OPAL_MSG_ASYNC_COMP             = 0,
+       OPAL_MSG_MEM_ERR,
+       OPAL_MSG_EPOW,
+       OPAL_MSG_SHUTDOWN,
+       OPAL_MSG_TYPE_MAX,
 };
 
 /* Machine check related definitions */
@@ -356,6 +389,12 @@ enum OpalLPCAddressType {
        OPAL_LPC_FW     = 2,
 };
 
+struct opal_msg {
+       uint32_t msg_type;
+       uint32_t reserved;
+       uint64_t params[8];
+};
+
 struct opal_machine_check_event {
        enum OpalMCE_Version    version:8;      /* 0x00 */
        uint8_t                 in_use;         /* 0x01 */
@@ -404,6 +443,58 @@ struct opal_machine_check_event {
        } u;
 };
 
+/* FSP memory errors handling */
+enum OpalMemErr_Version {
+       OpalMemErr_V1 = 1,
+};
+
+enum OpalMemErrType {
+       OPAL_MEM_ERR_TYPE_RESILIENCE    = 0,
+       OPAL_MEM_ERR_TYPE_DYN_DALLOC,
+       OPAL_MEM_ERR_TYPE_SCRUB,
+};
+
+/* Memory Reilience error type */
+enum OpalMemErr_ResilErrType {
+       OPAL_MEM_RESILIENCE_CE          = 0,
+       OPAL_MEM_RESILIENCE_UE,
+       OPAL_MEM_RESILIENCE_UE_SCRUB,
+};
+
+/* Dynamic Memory Deallocation type */
+enum OpalMemErr_DynErrType {
+       OPAL_MEM_DYNAMIC_DEALLOC        = 0,
+};
+
+/* OpalMemoryErrorData->flags */
+#define OPAL_MEM_CORRECTED_ERROR       0x0001
+#define OPAL_MEM_THRESHOLD_EXCEEDED    0x0002
+#define OPAL_MEM_ACK_REQUIRED          0x8000
+
+struct OpalMemoryErrorData {
+       enum OpalMemErr_Version version:8;      /* 0x00 */
+       enum OpalMemErrType     type:8;         /* 0x01 */
+       uint16_t                flags;          /* 0x02 */
+       uint8_t                 reserved_1[4];  /* 0x04 */
+
+       union {
+               /* Memory Resilience corrected/uncorrected error info */
+               struct {
+                       enum OpalMemErr_ResilErrType resil_err_type:8;
+                       uint8_t         reserved_1[7];
+                       uint64_t        physical_address_start;
+                       uint64_t        physical_address_end;
+               } resilience;
+               /* Dynamic memory deallocation error info */
+               struct {
+                       enum OpalMemErr_DynErrType dyn_err_type:8;
+                       uint8_t         reserved_1[7];
+                       uint64_t        physical_address_start;
+                       uint64_t        physical_address_end;
+               } dyn_dealloc;
+       } u;
+};
+
 enum {
        OPAL_P7IOC_DIAG_TYPE_NONE       = 0,
        OPAL_P7IOC_DIAG_TYPE_RGC        = 1,
@@ -731,6 +822,9 @@ int64_t opal_validate_flash(uint64_t buffer, uint32_t *size, uint32_t *result);
 int64_t opal_manage_flash(uint8_t op);
 int64_t opal_update_flash(uint64_t blk_list);
 
+int64_t opal_get_msg(uint64_t buffer, size_t size);
+int64_t opal_check_completion(uint64_t buffer, size_t size, uint64_t token);
+
 /* Internal functions */
 extern int early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data);
 
@@ -744,6 +838,8 @@ extern int early_init_dt_scan_opal(unsigned long node, const char *uname,
                                   int depth, void *data);
 
 extern int opal_notifier_register(struct notifier_block *nb);
+extern int opal_message_notifier_register(enum OpalMessageType msg_type,
+                                               struct notifier_block *nb);
 extern void opal_notifier_enable(void);
 extern void opal_notifier_disable(void);
 extern void opal_notifier_update_evt(uint64_t evt_mask, uint64_t evt_val);
index b6ea9e068c13dd483033a9f8aea2251d45084cac..c3523d1dda585a6a6678bed340d4c28dc2c5a798 100644 (file)
@@ -152,6 +152,15 @@ struct paca_struct {
         */
        struct opal_machine_check_event *opal_mc_evt;
 #endif
+#ifdef CONFIG_PPC_BOOK3S_64
+       /* Exclusive emergency stack pointer for machine check exception. */
+       void *mc_emergency_sp;
+       /*
+        * Flag to check whether we are in machine check early handler
+        * and already using emergency stack.
+        */
+       u16 in_mce;
+#endif
 
        /* Stuff for accurate time accounting */
        u64 user_time;                  /* accumulated usermode TB ticks */
index 27b2386f738a681fbea5a305b958e3681374df35..842846c1b71185b1a5e086e8521ed65342ae9cb0 100644 (file)
@@ -84,10 +84,8 @@ static inline void pgtable_free_tlb(struct mmu_gather *tlb,
 static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table,
                                  unsigned long address)
 {
-       struct page *page = page_address(table);
-
        tlb_flush_pgtable(tlb, address);
-       pgtable_page_dtor(page);
-       pgtable_free_tlb(tlb, page, 0);
+       pgtable_page_dtor(table);
+       pgtable_free_tlb(tlb, page_address(table), 0);
 }
 #endif /* _ASM_POWERPC_PGALLOC_32_H */
index 694012877bf7f1cfd1e1ea067b448f7e7c449e87..4b0be20fcbfdeee22498ea67f7a6b2adb3b55213 100644 (file)
@@ -148,11 +148,9 @@ static inline void pgtable_free_tlb(struct mmu_gather *tlb,
 static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table,
                                  unsigned long address)
 {
-       struct page *page = page_address(table);
-
        tlb_flush_pgtable(tlb, address);
-       pgtable_page_dtor(page);
-       pgtable_free_tlb(tlb, page, 0);
+       pgtable_page_dtor(table);
+       pgtable_free_tlb(tlb, page_address(table), 0);
 }
 
 #else /* if CONFIG_PPC_64K_PAGES */
index 7d6eacf249cf420a3e6d0a6f5ef108c76e663e80..b999ca3189858e05b75c855de000003f3cafcbe6 100644 (file)
@@ -3,6 +3,7 @@
 #ifdef __KERNEL__
 
 #ifndef __ASSEMBLY__
+#include <linux/mmdebug.h>
 #include <asm/processor.h>             /* For TASK_SIZE */
 #include <asm/mmu.h>
 #include <asm/page.h>
@@ -33,10 +34,73 @@ static inline int pte_dirty(pte_t pte)              { return pte_val(pte) & _PAGE_DIRTY; }
 static inline int pte_young(pte_t pte)         { return pte_val(pte) & _PAGE_ACCESSED; }
 static inline int pte_file(pte_t pte)          { return pte_val(pte) & _PAGE_FILE; }
 static inline int pte_special(pte_t pte)       { return pte_val(pte) & _PAGE_SPECIAL; }
-static inline int pte_present(pte_t pte)       { return pte_val(pte) & _PAGE_PRESENT; }
 static inline int pte_none(pte_t pte)          { return (pte_val(pte) & ~_PTE_NONE_MASK) == 0; }
 static inline pgprot_t pte_pgprot(pte_t pte)   { return __pgprot(pte_val(pte) & PAGE_PROT_BITS); }
 
+#ifdef CONFIG_NUMA_BALANCING
+
+static inline int pte_present(pte_t pte)
+{
+       return pte_val(pte) & (_PAGE_PRESENT | _PAGE_NUMA);
+}
+
+#define pte_numa pte_numa
+static inline int pte_numa(pte_t pte)
+{
+       return (pte_val(pte) &
+               (_PAGE_NUMA|_PAGE_PRESENT)) == _PAGE_NUMA;
+}
+
+#define pte_mknonnuma pte_mknonnuma
+static inline pte_t pte_mknonnuma(pte_t pte)
+{
+       pte_val(pte) &= ~_PAGE_NUMA;
+       pte_val(pte) |=  _PAGE_PRESENT | _PAGE_ACCESSED;
+       return pte;
+}
+
+#define pte_mknuma pte_mknuma
+static inline pte_t pte_mknuma(pte_t pte)
+{
+       /*
+        * We should not set _PAGE_NUMA on non present ptes. Also clear the
+        * present bit so that hash_page will return 1 and we collect this
+        * as numa fault.
+        */
+       if (pte_present(pte)) {
+               pte_val(pte) |= _PAGE_NUMA;
+               pte_val(pte) &= ~_PAGE_PRESENT;
+       } else
+               VM_BUG_ON(1);
+       return pte;
+}
+
+#define pmd_numa pmd_numa
+static inline int pmd_numa(pmd_t pmd)
+{
+       return pte_numa(pmd_pte(pmd));
+}
+
+#define pmd_mknonnuma pmd_mknonnuma
+static inline pmd_t pmd_mknonnuma(pmd_t pmd)
+{
+       return pte_pmd(pte_mknonnuma(pmd_pte(pmd)));
+}
+
+#define pmd_mknuma pmd_mknuma
+static inline pmd_t pmd_mknuma(pmd_t pmd)
+{
+       return pte_pmd(pte_mknuma(pmd_pte(pmd)));
+}
+
+# else
+
+static inline int pte_present(pte_t pte)
+{
+       return pte_val(pte) & _PAGE_PRESENT;
+}
+#endif /* CONFIG_NUMA_BALANCING */
+
 /* Conversion functions: convert a page and protection to a page entry,
  * and a page entry and page directory to the page they refer to.
  *
index 0419eeb53274c64891c87f1c573e712e6167d62b..2505d8eab15cb94da40aea90b9986aa853c0aecb 100644 (file)
@@ -19,7 +19,7 @@
 #define _PAGE_FILE             0x0002 /* (!present only) software: pte holds file offset */
 #define _PAGE_EXEC             0x0004 /* No execute on POWER4 and newer (we invert) */
 #define _PAGE_GUARDED          0x0008
-#define _PAGE_COHERENT         0x0010 /* M: enforce memory coherence (SMP systems) */
+/* We can derive Memory coherence from _PAGE_NO_CACHE */
 #define _PAGE_NO_CACHE         0x0020 /* I: cache inhibit */
 #define _PAGE_WRITETHRU                0x0040 /* W: cache write-through */
 #define _PAGE_DIRTY            0x0080 /* C: page changed */
 #define _PAGE_RW               0x0200 /* software: user write access allowed */
 #define _PAGE_BUSY             0x0800 /* software: PTE & hash are busy */
 
+/*
+ * Used for tracking numa faults
+ */
+#define _PAGE_NUMA     0x00000010 /* Gather numa placement stats */
+
+
 /* No separate kernel read-only */
 #define _PAGE_KERNEL_RW                (_PAGE_RW | _PAGE_DIRTY) /* user access blocked by key */
 #define _PAGE_KERNEL_RO                 _PAGE_KERNEL_RW
index 703a8412dac28e2a567b4d1b4da5586ae890c34a..11ba86e176315e4ef260c8eb740ba52ca347c192 100644 (file)
@@ -26,6 +26,7 @@ extern void reloc_got2(unsigned long);
 void check_for_initrd(void);
 void do_init_bootmem(void);
 void setup_panic(void);
+#define ARCH_PANIC_TIMEOUT 180
 
 #endif /* !__ASSEMBLY__ */
 
index 75c6ecdb8f3728a175bd61808cad34a9689fd47e..7422a999a39a5bfd8edbd674905417951a792a25 100644 (file)
@@ -36,9 +36,8 @@ typedef ppc_opcode_t uprobe_opcode_t;
 
 struct arch_uprobe {
        union {
-               u8      insn[MAX_UINSN_BYTES];
-               u8      ixol[MAX_UINSN_BYTES];
-               u32     ainsn;
+               u32     insn;
+               u32     ixol;
        };
 };
 
index 445cb6e39d5b0bb3058caaefe6af61f3f5ba2618..fcc9a89a46950867c81aaec671f9ac6d782c0a77 100644 (file)
@@ -39,6 +39,7 @@ obj-$(CONFIG_PPC64)           += setup_64.o sys_ppc32.o \
 obj-$(CONFIG_HAVE_HW_BREAKPOINT)       += hw_breakpoint.o
 obj-$(CONFIG_PPC_BOOK3S_64)    += cpu_setup_ppc970.o cpu_setup_pa6t.o
 obj-$(CONFIG_PPC_BOOK3S_64)    += cpu_setup_power.o
+obj-$(CONFIG_PPC_BOOK3S_64)    += mce.o mce_power.o
 obj64-$(CONFIG_RELOCATABLE)    += reloc_64.o
 obj-$(CONFIG_PPC_BOOK3E_64)    += exceptions-64e.o idle_book3e.o
 obj-$(CONFIG_PPC_A2)           += cpu_setup_a2.o
@@ -47,7 +48,6 @@ obj-$(CONFIG_ALTIVEC)         += vecemu.o
 obj-$(CONFIG_PPC_970_NAP)      += idle_power4.o
 obj-$(CONFIG_PPC_P7_NAP)       += idle_power7.o
 obj-$(CONFIG_PPC_OF)           += of_platform.o prom_parse.o
-obj-$(CONFIG_PPC_CLOCK)                += clock.o
 procfs-y                       := proc_powerpc.o
 obj-$(CONFIG_PROC_FS)          += $(procfs-y)
 rtaspci-$(CONFIG_PPC64)-$(CONFIG_PCI)  := rtas_pci.o
index 2ea5cc033ec8b633febb50071c43cfd31958f4f3..41a283956a29453779056af0cd0c2f436841cc25 100644 (file)
@@ -232,6 +232,10 @@ int main(void)
        DEFINE(PACA_DTL_RIDX, offsetof(struct paca_struct, dtl_ridx));
 #endif /* CONFIG_PPC_STD_MMU_64 */
        DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp));
+#ifdef CONFIG_PPC_BOOK3S_64
+       DEFINE(PACAMCEMERGSP, offsetof(struct paca_struct, mc_emergency_sp));
+       DEFINE(PACA_IN_MCE, offsetof(struct paca_struct, in_mce));
+#endif
        DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id));
        DEFINE(PACAKEXECSTATE, offsetof(struct paca_struct, kexec_state));
        DEFINE(PACA_STARTTIME, offsetof(struct paca_struct, starttime));
diff --git a/arch/powerpc/kernel/clock.c b/arch/powerpc/kernel/clock.c
deleted file mode 100644 (file)
index a764b47..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Dummy clk implementations for powerpc.
- * These need to be overridden in platform code.
- */
-
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/errno.h>
-#include <linux/export.h>
-#include <asm/clk_interface.h>
-
-struct clk_interface clk_functions;
-
-struct clk *clk_get(struct device *dev, const char *id)
-{
-       if (clk_functions.clk_get)
-               return clk_functions.clk_get(dev, id);
-       return ERR_PTR(-ENOSYS);
-}
-EXPORT_SYMBOL(clk_get);
-
-void clk_put(struct clk *clk)
-{
-       if (clk_functions.clk_put)
-               clk_functions.clk_put(clk);
-}
-EXPORT_SYMBOL(clk_put);
-
-int clk_enable(struct clk *clk)
-{
-       if (clk_functions.clk_enable)
-               return clk_functions.clk_enable(clk);
-       return -ENOSYS;
-}
-EXPORT_SYMBOL(clk_enable);
-
-void clk_disable(struct clk *clk)
-{
-       if (clk_functions.clk_disable)
-               clk_functions.clk_disable(clk);
-}
-EXPORT_SYMBOL(clk_disable);
-
-unsigned long clk_get_rate(struct clk *clk)
-{
-       if (clk_functions.clk_get_rate)
-               return clk_functions.clk_get_rate(clk);
-       return 0;
-}
-EXPORT_SYMBOL(clk_get_rate);
-
-long clk_round_rate(struct clk *clk, unsigned long rate)
-{
-       if (clk_functions.clk_round_rate)
-               return clk_functions.clk_round_rate(clk, rate);
-       return -ENOSYS;
-}
-EXPORT_SYMBOL(clk_round_rate);
-
-int clk_set_rate(struct clk *clk, unsigned long rate)
-{
-       if (clk_functions.clk_set_rate)
-               return clk_functions.clk_set_rate(clk, rate);
-       return -ENOSYS;
-}
-EXPORT_SYMBOL(clk_set_rate);
-
-struct clk *clk_get_parent(struct clk *clk)
-{
-       if (clk_functions.clk_get_parent)
-               return clk_functions.clk_get_parent(clk);
-       return ERR_PTR(-ENOSYS);
-}
-EXPORT_SYMBOL(clk_get_parent);
-
-int clk_set_parent(struct clk *clk, struct clk *parent)
-{
-       if (clk_functions.clk_set_parent)
-               return clk_functions.clk_set_parent(clk, parent);
-       return -ENOSYS;
-}
-EXPORT_SYMBOL(clk_set_parent);
index 18b5b9cf8e3730f4608ca6ff997810d5cc47df9a..37d1bb002aa97bbd3ea52b19304f746521e30bff 100644 (file)
@@ -29,7 +29,7 @@ _GLOBAL(__setup_cpu_power7)
        mtspr   SPRN_LPID,r0
        mfspr   r3,SPRN_LPCR
        bl      __init_LPCR
-       bl      __init_TLB
+       bl      __init_tlb_power7
        mtlr    r11
        blr
 
@@ -42,7 +42,7 @@ _GLOBAL(__restore_cpu_power7)
        mtspr   SPRN_LPID,r0
        mfspr   r3,SPRN_LPCR
        bl      __init_LPCR
-       bl      __init_TLB
+       bl      __init_tlb_power7
        mtlr    r11
        blr
 
@@ -59,7 +59,7 @@ _GLOBAL(__setup_cpu_power8)
        oris    r3, r3, LPCR_AIL_3@h
        bl      __init_LPCR
        bl      __init_HFSCR
-       bl      __init_TLB
+       bl      __init_tlb_power8
        bl      __init_PMU_HV
        mtlr    r11
        blr
@@ -78,7 +78,7 @@ _GLOBAL(__restore_cpu_power8)
        oris    r3, r3, LPCR_AIL_3@h
        bl      __init_LPCR
        bl      __init_HFSCR
-       bl      __init_TLB
+       bl      __init_tlb_power8
        bl      __init_PMU_HV
        mtlr    r11
        blr
@@ -134,15 +134,31 @@ __init_HFSCR:
        mtspr   SPRN_HFSCR,r3
        blr
 
-__init_TLB:
-       /*
-        * Clear the TLB using the "IS 3" form of tlbiel instruction
-        * (invalidate by congruence class). P7 has 128 CCs, P8 has 512
-        * so we just always do 512
-        */
+/*
+ * Clear the TLB using the specified IS form of tlbiel instruction
+ * (invalidate by congruence class). P7 has 128 CCs., P8 has 512.
+ *
+ * r3 = IS field
+ */
+__init_tlb_power7:
+       li      r3,0xc00        /* IS field = 0b11 */
+_GLOBAL(__flush_tlb_power7)
+       li      r6,128
+       mtctr   r6
+       mr      r7,r3           /* IS field */
+       ptesync
+2:     tlbiel  r7
+       addi    r7,r7,0x1000
+       bdnz    2b
+       ptesync
+1:     blr
+
+__init_tlb_power8:
+       li      r3,0xc00        /* IS field = 0b11 */
+_GLOBAL(__flush_tlb_power8)
        li      r6,512
        mtctr   r6
-       li      r7,0xc00        /* IS field = 0b11 */
+       mr      r7,r3           /* IS field */
        ptesync
 2:     tlbiel  r7
        addi    r7,r7,0x1000
index 597d954e58601b36f376953898faf9178b818239..6c8dd5da4de5ea0b8b88196b773d2e39fca1c732 100644 (file)
@@ -71,6 +71,10 @@ extern void __restore_cpu_power7(void);
 extern void __setup_cpu_power8(unsigned long offset, struct cpu_spec* spec);
 extern void __restore_cpu_power8(void);
 extern void __restore_cpu_a2(void);
+extern void __flush_tlb_power7(unsigned long inval_selector);
+extern void __flush_tlb_power8(unsigned long inval_selector);
+extern long __machine_check_early_realmode_p7(struct pt_regs *regs);
+extern long __machine_check_early_realmode_p8(struct pt_regs *regs);
 #endif /* CONFIG_PPC64 */
 #if defined(CONFIG_E500)
 extern void __setup_cpu_e5500(unsigned long offset, struct cpu_spec* spec);
@@ -440,6 +444,8 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .oprofile_cpu_type      = "ppc64/ibm-compat-v1",
                .cpu_setup              = __setup_cpu_power7,
                .cpu_restore            = __restore_cpu_power7,
+               .flush_tlb              = __flush_tlb_power7,
+               .machine_check_early    = __machine_check_early_realmode_p7,
                .platform               = "power7",
        },
        {       /* 2.07-compliant processor, i.e. Power8 "architected" mode */
@@ -456,6 +462,8 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .oprofile_cpu_type      = "ppc64/ibm-compat-v1",
                .cpu_setup              = __setup_cpu_power8,
                .cpu_restore            = __restore_cpu_power8,
+               .flush_tlb              = __flush_tlb_power8,
+               .machine_check_early    = __machine_check_early_realmode_p8,
                .platform               = "power8",
        },
        {       /* Power7 */
@@ -474,6 +482,8 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .oprofile_type          = PPC_OPROFILE_POWER4,
                .cpu_setup              = __setup_cpu_power7,
                .cpu_restore            = __restore_cpu_power7,
+               .flush_tlb              = __flush_tlb_power7,
+               .machine_check_early    = __machine_check_early_realmode_p7,
                .platform               = "power7",
        },
        {       /* Power7+ */
@@ -492,6 +502,8 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .oprofile_type          = PPC_OPROFILE_POWER4,
                .cpu_setup              = __setup_cpu_power7,
                .cpu_restore            = __restore_cpu_power7,
+               .flush_tlb              = __flush_tlb_power7,
+               .machine_check_early    = __machine_check_early_realmode_p7,
                .platform               = "power7+",
        },
        {       /* Power8E */
@@ -510,6 +522,8 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .oprofile_type          = PPC_OPROFILE_INVALID,
                .cpu_setup              = __setup_cpu_power8,
                .cpu_restore            = __restore_cpu_power8,
+               .flush_tlb              = __flush_tlb_power8,
+               .machine_check_early    = __machine_check_early_realmode_p8,
                .platform               = "power8",
        },
        {       /* Power8 */
@@ -528,6 +542,8 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .oprofile_type          = PPC_OPROFILE_INVALID,
                .cpu_setup              = __setup_cpu_power8,
                .cpu_restore            = __restore_cpu_power8,
+               .flush_tlb              = __flush_tlb_power8,
+               .machine_check_early    = __machine_check_early_realmode_p8,
                .platform               = "power8",
        },
        {       /* Cell Broadband Engine */
index 4bd687d5e7aa3f80e1b33912b5451bd34a3187b1..f4b7a227f18350f3f46c078e8101019e388dbfb6 100644 (file)
@@ -84,7 +84,7 @@
 #define EEH_MAX_FAILS  2100000
 
 /* Time to wait for a PCI slot to report status, in milliseconds */
-#define PCI_BUS_RESET_WAIT_MSEC (60*1000)
+#define PCI_BUS_RESET_WAIT_MSEC (5*60*1000)
 
 /* Platform dependent EEH operations */
 struct eeh_ops *eeh_ops = NULL;
index 36bed5a12750b639e2c305153585869be536ddef..4ef59c33777f0a4bd6bc0115e102db031b8f5094 100644 (file)
@@ -468,7 +468,7 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus)
 /* The longest amount of time to wait for a pci device
  * to come back on line, in seconds.
  */
-#define MAX_WAIT_FOR_RECOVERY 150
+#define MAX_WAIT_FOR_RECOVERY 300
 
 static void eeh_handle_normal_event(struct eeh_pe *pe)
 {
index bbfb0294b3544072ac22b2fcfee486620ae1479e..770d6d65c47b62b1d101021ec0e4b063226606dc 100644 (file)
@@ -183,6 +183,11 @@ syscall_exit:
 #ifdef SHOW_SYSCALLS
        bl      .do_show_syscall_exit
        ld      r3,RESULT(r1)
+#endif
+#ifdef CONFIG_PPC_BOOK3S_64
+BEGIN_FTR_SECTION
+       bl      .machine_check_process_queued_event
+END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
 #endif
        CURRENT_THREAD_INFO(r12, r1)
 
index 9f905e40922e41de4eb6f43421290944c5d08567..b5c3313567da8e5e606c94f7a1cf4a2c04a47e95 100644 (file)
@@ -155,8 +155,30 @@ machine_check_pSeries_1:
         */
        HMT_MEDIUM_PPR_DISCARD
        SET_SCRATCH0(r13)               /* save r13 */
+#ifdef CONFIG_PPC_P7_NAP
+BEGIN_FTR_SECTION
+       /* Running native on arch 2.06 or later, check if we are
+        * waking up from nap. We only handle no state loss and
+        * supervisor state loss. We do -not- handle hypervisor
+        * state loss at this time.
+        */
+       mfspr   r13,SPRN_SRR1
+       rlwinm. r13,r13,47-31,30,31
+       beq     9f
+
+       /* waking up from powersave (nap) state */
+       cmpwi   cr1,r13,2
+       /* Total loss of HV state is fatal. let's just stay stuck here */
+       bgt     cr1,.
+9:
+END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
+#endif /* CONFIG_PPC_P7_NAP */
        EXCEPTION_PROLOG_0(PACA_EXMC)
+BEGIN_FTR_SECTION
+       b       machine_check_pSeries_early
+FTR_SECTION_ELSE
        b       machine_check_pSeries_0
+ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE)
 
        . = 0x300
        .globl data_access_pSeries
@@ -405,6 +427,64 @@ denorm_exception_hv:
 
        .align  7
        /* moved from 0x200 */
+machine_check_pSeries_early:
+BEGIN_FTR_SECTION
+       EXCEPTION_PROLOG_1(PACA_EXMC, NOTEST, 0x200)
+       /*
+        * Register contents:
+        * R13          = PACA
+        * R9           = CR
+        * Original R9 to R13 is saved on PACA_EXMC
+        *
+        * Switch to mc_emergency stack and handle re-entrancy (though we
+        * currently don't test for overflow). Save MCE registers srr1,
+        * srr0, dar and dsisr and then set ME=1
+        *
+        * We use paca->in_mce to check whether this is the first entry or
+        * nested machine check. We increment paca->in_mce to track nested
+        * machine checks.
+        *
+        * If this is the first entry then set stack pointer to
+        * paca->mc_emergency_sp, otherwise r1 is already pointing to
+        * stack frame on mc_emergency stack.
+        *
+        * NOTE: We are here with MSR_ME=0 (off), which means we risk a
+        * checkstop if we get another machine check exception before we do
+        * rfid with MSR_ME=1.
+        */
+       mr      r11,r1                  /* Save r1 */
+       lhz     r10,PACA_IN_MCE(r13)
+       cmpwi   r10,0                   /* Are we in nested machine check */
+       bne     0f                      /* Yes, we are. */
+       /* First machine check entry */
+       ld      r1,PACAMCEMERGSP(r13)   /* Use MC emergency stack */
+0:     subi    r1,r1,INT_FRAME_SIZE    /* alloc stack frame */
+       addi    r10,r10,1               /* increment paca->in_mce */
+       sth     r10,PACA_IN_MCE(r13)
+       std     r11,GPR1(r1)            /* Save r1 on the stack. */
+       std     r11,0(r1)               /* make stack chain pointer */
+       mfspr   r11,SPRN_SRR0           /* Save SRR0 */
+       std     r11,_NIP(r1)
+       mfspr   r11,SPRN_SRR1           /* Save SRR1 */
+       std     r11,_MSR(r1)
+       mfspr   r11,SPRN_DAR            /* Save DAR */
+       std     r11,_DAR(r1)
+       mfspr   r11,SPRN_DSISR          /* Save DSISR */
+       std     r11,_DSISR(r1)
+       std     r9,_CCR(r1)             /* Save CR in stackframe */
+       /* Save r9 through r13 from EXMC save area to stack frame. */
+       EXCEPTION_PROLOG_COMMON_2(PACA_EXMC)
+       mfmsr   r11                     /* get MSR value */
+       ori     r11,r11,MSR_ME          /* turn on ME bit */
+       ori     r11,r11,MSR_RI          /* turn on RI bit */
+       ld      r12,PACAKBASE(r13)      /* get high part of &label */
+       LOAD_HANDLER(r12, machine_check_handle_early)
+       mtspr   SPRN_SRR0,r12
+       mtspr   SPRN_SRR1,r11
+       rfid
+       b       .       /* prevent speculative execution */
+END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
+
 machine_check_pSeries:
        .globl machine_check_fwnmi
 machine_check_fwnmi:
@@ -688,30 +768,6 @@ kvmppc_skip_Hinterrupt:
 
        STD_EXCEPTION_COMMON(0x100, system_reset, .system_reset_exception)
 
-       /*
-        * Machine check is different because we use a different
-        * save area: PACA_EXMC instead of PACA_EXGEN.
-        */
-       .align  7
-       .globl machine_check_common
-machine_check_common:
-
-       mfspr   r10,SPRN_DAR
-       std     r10,PACA_EXGEN+EX_DAR(r13)
-       mfspr   r10,SPRN_DSISR
-       stw     r10,PACA_EXGEN+EX_DSISR(r13)
-       EXCEPTION_PROLOG_COMMON(0x200, PACA_EXMC)
-       FINISH_NAP
-       DISABLE_INTS
-       ld      r3,PACA_EXGEN+EX_DAR(r13)
-       lwz     r4,PACA_EXGEN+EX_DSISR(r13)
-       std     r3,_DAR(r1)
-       std     r4,_DSISR(r1)
-       bl      .save_nvgprs
-       addi    r3,r1,STACK_FRAME_OVERHEAD
-       bl      .machine_check_exception
-       b       .ret_from_except
-
        STD_EXCEPTION_COMMON_ASYNC(0x500, hardware_interrupt, do_IRQ)
        STD_EXCEPTION_COMMON_ASYNC(0x900, decrementer, .timer_interrupt)
        STD_EXCEPTION_COMMON(0x980, hdecrementer, .hdec_interrupt)
@@ -1262,6 +1318,146 @@ _GLOBAL(opal_mc_secondary_handler)
        b       machine_check_pSeries
 #endif /* CONFIG_PPC_POWERNV */
 
+       /*
+        * Machine check is different because we use a different
+        * save area: PACA_EXMC instead of PACA_EXGEN.
+        */
+       .align  7
+       .globl machine_check_common
+machine_check_common:
+
+       mfspr   r10,SPRN_DAR
+       std     r10,PACA_EXGEN+EX_DAR(r13)
+       mfspr   r10,SPRN_DSISR
+       stw     r10,PACA_EXGEN+EX_DSISR(r13)
+       EXCEPTION_PROLOG_COMMON(0x200, PACA_EXMC)
+       FINISH_NAP
+       DISABLE_INTS
+       ld      r3,PACA_EXGEN+EX_DAR(r13)
+       lwz     r4,PACA_EXGEN+EX_DSISR(r13)
+       std     r3,_DAR(r1)
+       std     r4,_DSISR(r1)
+       bl      .save_nvgprs
+       addi    r3,r1,STACK_FRAME_OVERHEAD
+       bl      .machine_check_exception
+       b       .ret_from_except
+
+#define MACHINE_CHECK_HANDLER_WINDUP                   \
+       /* Clear MSR_RI before setting SRR0 and SRR1. */\
+       li      r0,MSR_RI;                              \
+       mfmsr   r9;             /* get MSR value */     \
+       andc    r9,r9,r0;                               \
+       mtmsrd  r9,1;           /* Clear MSR_RI */      \
+       /* Move original SRR0 and SRR1 into the respective regs */      \
+       ld      r9,_MSR(r1);                            \
+       mtspr   SPRN_SRR1,r9;                           \
+       ld      r3,_NIP(r1);                            \
+       mtspr   SPRN_SRR0,r3;                           \
+       ld      r9,_CTR(r1);                            \
+       mtctr   r9;                                     \
+       ld      r9,_XER(r1);                            \
+       mtxer   r9;                                     \
+       ld      r9,_LINK(r1);                           \
+       mtlr    r9;                                     \
+       REST_GPR(0, r1);                                \
+       REST_8GPRS(2, r1);                              \
+       REST_GPR(10, r1);                               \
+       ld      r11,_CCR(r1);                           \
+       mtcr    r11;                                    \
+       /* Decrement paca->in_mce. */                   \
+       lhz     r12,PACA_IN_MCE(r13);                   \
+       subi    r12,r12,1;                              \
+       sth     r12,PACA_IN_MCE(r13);                   \
+       REST_GPR(11, r1);                               \
+       REST_2GPRS(12, r1);                             \
+       /* restore original r1. */                      \
+       ld      r1,GPR1(r1)
+
+       /*
+        * Handle machine check early in real mode. We come here with
+        * ME=1, MMU (IR=0 and DR=0) off and using MC emergency stack.
+        */
+       .align  7
+       .globl machine_check_handle_early
+machine_check_handle_early:
+BEGIN_FTR_SECTION
+       std     r0,GPR0(r1)     /* Save r0 */
+       EXCEPTION_PROLOG_COMMON_3(0x200)
+       bl      .save_nvgprs
+       addi    r3,r1,STACK_FRAME_OVERHEAD
+       bl      .machine_check_early
+       ld      r12,_MSR(r1)
+#ifdef CONFIG_PPC_P7_NAP
+       /*
+        * Check if thread was in power saving mode. We come here when any
+        * of the following is true:
+        * a. thread wasn't in power saving mode
+        * b. thread was in power saving mode with no state loss or
+        *    supervisor state loss
+        *
+        * Go back to nap again if (b) is true.
+        */
+       rlwinm. r11,r12,47-31,30,31     /* Was it in power saving mode? */
+       beq     4f                      /* No, it wasn;t */
+       /* Thread was in power saving mode. Go back to nap again. */
+       cmpwi   r11,2
+       bne     3f
+       /* Supervisor state loss */
+       li      r0,1
+       stb     r0,PACA_NAPSTATELOST(r13)
+3:     bl      .machine_check_queue_event
+       MACHINE_CHECK_HANDLER_WINDUP
+       GET_PACA(r13)
+       ld      r1,PACAR1(r13)
+       b       .power7_enter_nap_mode
+4:
+#endif
+       /*
+        * Check if we are coming from hypervisor userspace. If yes then we
+        * continue in host kernel in V mode to deliver the MC event.
+        */
+       rldicl. r11,r12,4,63            /* See if MC hit while in HV mode. */
+       beq     5f
+       andi.   r11,r12,MSR_PR          /* See if coming from user. */
+       bne     9f                      /* continue in V mode if we are. */
+
+5:
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+       /*
+        * We are coming from kernel context. Check if we are coming from
+        * guest. if yes, then we can continue. We will fall through
+        * do_kvm_200->kvmppc_interrupt to deliver the MC event to guest.
+        */
+       lbz     r11,HSTATE_IN_GUEST(r13)
+       cmpwi   r11,0                   /* Check if coming from guest */
+       bne     9f                      /* continue if we are. */
+#endif
+       /*
+        * At this point we are not sure about what context we come from.
+        * Queue up the MCE event and return from the interrupt.
+        * But before that, check if this is an un-recoverable exception.
+        * If yes, then stay on emergency stack and panic.
+        */
+       andi.   r11,r12,MSR_RI
+       bne     2f
+1:     addi    r3,r1,STACK_FRAME_OVERHEAD
+       bl      .unrecoverable_exception
+       b       1b
+2:
+       /*
+        * Return from MC interrupt.
+        * Queue up the MCE event so that we can log it later, while
+        * returning from kernel or opal call.
+        */
+       bl      .machine_check_queue_event
+       MACHINE_CHECK_HANDLER_WINDUP
+       rfid
+9:
+       /* Deliver the machine check to host kernel in V mode. */
+       MACHINE_CHECK_HANDLER_WINDUP
+       b       machine_check_pSeries
+END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
+
 
 /*
  * r13 points to the PACA, r9 contains the saved CR,
index 847e40e62fcee8420046e153e5da9354bc80a40e..3fdef0f0c67fa959e631a4ccee2d3a330001fa44 100644 (file)
@@ -84,6 +84,7 @@ _GLOBAL(power7_nap)
        std     r9,_MSR(r1)
        std     r1,PACAR1(r13)
 
+_GLOBAL(power7_enter_nap_mode)
 #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
        /* Tell KVM we're napping */
        li      r4,KVM_HWTHREAD_IN_NAP
index 572bb5b95f35d815f6f24fe7b59a67bf420fbe2b..d22abe0b08e3c221a709210181db09647ec1687e 100644 (file)
@@ -1105,7 +1105,7 @@ void iommu_release_ownership(struct iommu_table *tbl)
 }
 EXPORT_SYMBOL_GPL(iommu_release_ownership);
 
-static int iommu_add_device(struct device *dev)
+int iommu_add_device(struct device *dev)
 {
        struct iommu_table *tbl;
        int ret = 0;
@@ -1134,52 +1134,12 @@ static int iommu_add_device(struct device *dev)
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(iommu_add_device);
 
-static void iommu_del_device(struct device *dev)
+void iommu_del_device(struct device *dev)
 {
        iommu_group_remove_device(dev);
 }
-
-static int iommu_bus_notifier(struct notifier_block *nb,
-                             unsigned long action, void *data)
-{
-       struct device *dev = data;
-
-       switch (action) {
-       case BUS_NOTIFY_ADD_DEVICE:
-               return iommu_add_device(dev);
-       case BUS_NOTIFY_DEL_DEVICE:
-               iommu_del_device(dev);
-               return 0;
-       default:
-               return 0;
-       }
-}
-
-static struct notifier_block tce_iommu_bus_nb = {
-       .notifier_call = iommu_bus_notifier,
-};
-
-static int __init tce_iommu_init(void)
-{
-       struct pci_dev *pdev = NULL;
-
-       BUILD_BUG_ON(PAGE_SIZE < IOMMU_PAGE_SIZE);
-
-       for_each_pci_dev(pdev)
-               iommu_add_device(&pdev->dev);
-
-       bus_register_notifier(&pci_bus_type, &tce_iommu_bus_nb);
-       return 0;
-}
-
-subsys_initcall_sync(tce_iommu_init);
-
-#else
-
-void iommu_register_group(struct iommu_table *tbl,
-               int pci_domain_number, unsigned long pe_num)
-{
-}
+EXPORT_SYMBOL_GPL(iommu_del_device);
 
 #endif /* CONFIG_IOMMU_API */
index ba0165615215577be84a8a576283a5fd6df12e51..9729b23bfb0a2deebf0e5157accb2d68541b6bf0 100644 (file)
@@ -354,8 +354,13 @@ int arch_show_interrupts(struct seq_file *p, int prec)
 
        seq_printf(p, "%*s: ", prec, "LOC");
        for_each_online_cpu(j)
-               seq_printf(p, "%10u ", per_cpu(irq_stat, j).timer_irqs);
-        seq_printf(p, "  Local timer interrupts\n");
+               seq_printf(p, "%10u ", per_cpu(irq_stat, j).timer_irqs_event);
+        seq_printf(p, "  Local timer interrupts for timer event device\n");
+
+       seq_printf(p, "%*s: ", prec, "LOC");
+       for_each_online_cpu(j)
+               seq_printf(p, "%10u ", per_cpu(irq_stat, j).timer_irqs_others);
+        seq_printf(p, "  Local timer interrupts for others\n");
 
        seq_printf(p, "%*s: ", prec, "SPU");
        for_each_online_cpu(j)
@@ -389,11 +394,12 @@ int arch_show_interrupts(struct seq_file *p, int prec)
  */
 u64 arch_irq_stat_cpu(unsigned int cpu)
 {
-       u64 sum = per_cpu(irq_stat, cpu).timer_irqs;
+       u64 sum = per_cpu(irq_stat, cpu).timer_irqs_event;
 
        sum += per_cpu(irq_stat, cpu).pmu_irqs;
        sum += per_cpu(irq_stat, cpu).mce_exceptions;
        sum += per_cpu(irq_stat, cpu).spurious_irqs;
+       sum += per_cpu(irq_stat, cpu).timer_irqs_others;
 #ifdef CONFIG_PPC_DOORBELL
        sum += per_cpu(irq_stat, cpu).doorbell_irqs;
 #endif
index 88a7fb458dfd50f0201d269d8177007cc382c62d..75d4f7340da893bc2825f97dda750409d8963323 100644 (file)
@@ -148,7 +148,7 @@ void __init reserve_crashkernel(void)
                 * a small SLB (128MB) since the crash kernel needs to place
                 * itself and some stacks to be in the first segment.
                 */
-               crashk_res.start = min(0x80000000ULL, (ppc64_rma_size / 2));
+               crashk_res.start = min(0x8000000ULL, (ppc64_rma_size / 2));
 #else
                crashk_res.start = KDUMP_KERNELBASE;
 #endif
diff --git a/arch/powerpc/kernel/mce.c b/arch/powerpc/kernel/mce.c
new file mode 100644 (file)
index 0000000..c0c52ec
--- /dev/null
@@ -0,0 +1,345 @@
+/*
+ * Machine check exception handling.
+ *
+ * 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 2013 IBM Corporation
+ * Author: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
+ */
+
+#undef DEBUG
+#define pr_fmt(fmt) "mce: " fmt
+
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/percpu.h>
+#include <linux/export.h>
+#include <asm/mce.h>
+
+static DEFINE_PER_CPU(int, mce_nest_count);
+static DEFINE_PER_CPU(struct machine_check_event[MAX_MC_EVT], mce_event);
+
+/* Queue for delayed MCE events. */
+static DEFINE_PER_CPU(int, mce_queue_count);
+static DEFINE_PER_CPU(struct machine_check_event[MAX_MC_EVT], mce_event_queue);
+
+static void mce_set_error_info(struct machine_check_event *mce,
+                              struct mce_error_info *mce_err)
+{
+       mce->error_type = mce_err->error_type;
+       switch (mce_err->error_type) {
+       case MCE_ERROR_TYPE_UE:
+               mce->u.ue_error.ue_error_type = mce_err->u.ue_error_type;
+               break;
+       case MCE_ERROR_TYPE_SLB:
+               mce->u.slb_error.slb_error_type = mce_err->u.slb_error_type;
+               break;
+       case MCE_ERROR_TYPE_ERAT:
+               mce->u.erat_error.erat_error_type = mce_err->u.erat_error_type;
+               break;
+       case MCE_ERROR_TYPE_TLB:
+               mce->u.tlb_error.tlb_error_type = mce_err->u.tlb_error_type;
+               break;
+       case MCE_ERROR_TYPE_UNKNOWN:
+       default:
+               break;
+       }
+}
+
+/*
+ * Decode and save high level MCE information into per cpu buffer which
+ * is an array of machine_check_event structure.
+ */
+void save_mce_event(struct pt_regs *regs, long handled,
+                   struct mce_error_info *mce_err,
+                   uint64_t addr)
+{
+       uint64_t srr1;
+       int index = __get_cpu_var(mce_nest_count)++;
+       struct machine_check_event *mce = &__get_cpu_var(mce_event[index]);
+
+       /*
+        * Return if we don't have enough space to log mce event.
+        * mce_nest_count may go beyond MAX_MC_EVT but that's ok,
+        * the check below will stop buffer overrun.
+        */
+       if (index >= MAX_MC_EVT)
+               return;
+
+       /* Populate generic machine check info */
+       mce->version = MCE_V1;
+       mce->srr0 = regs->nip;
+       mce->srr1 = regs->msr;
+       mce->gpr3 = regs->gpr[3];
+       mce->in_use = 1;
+
+       mce->initiator = MCE_INITIATOR_CPU;
+       if (handled)
+               mce->disposition = MCE_DISPOSITION_RECOVERED;
+       else
+               mce->disposition = MCE_DISPOSITION_NOT_RECOVERED;
+       mce->severity = MCE_SEV_ERROR_SYNC;
+
+       srr1 = regs->msr;
+
+       /*
+        * Populate the mce error_type and type-specific error_type.
+        */
+       mce_set_error_info(mce, mce_err);
+
+       if (!addr)
+               return;
+
+       if (mce->error_type == MCE_ERROR_TYPE_TLB) {
+               mce->u.tlb_error.effective_address_provided = true;
+               mce->u.tlb_error.effective_address = addr;
+       } else if (mce->error_type == MCE_ERROR_TYPE_SLB) {
+               mce->u.slb_error.effective_address_provided = true;
+               mce->u.slb_error.effective_address = addr;
+       } else if (mce->error_type == MCE_ERROR_TYPE_ERAT) {
+               mce->u.erat_error.effective_address_provided = true;
+               mce->u.erat_error.effective_address = addr;
+       } else if (mce->error_type == MCE_ERROR_TYPE_UE) {
+               mce->u.ue_error.effective_address_provided = true;
+               mce->u.ue_error.effective_address = addr;
+       }
+       return;
+}
+
+/*
+ * get_mce_event:
+ *     mce     Pointer to machine_check_event structure to be filled.
+ *     release Flag to indicate whether to free the event slot or not.
+ *             0 <= do not release the mce event. Caller will invoke
+ *                  release_mce_event() once event has been consumed.
+ *             1 <= release the slot.
+ *
+ *     return  1 = success
+ *             0 = failure
+ *
+ * get_mce_event() will be called by platform specific machine check
+ * handle routine and in KVM.
+ * When we call get_mce_event(), we are still in interrupt context and
+ * preemption will not be scheduled until ret_from_expect() routine
+ * is called.
+ */
+int get_mce_event(struct machine_check_event *mce, bool release)
+{
+       int index = __get_cpu_var(mce_nest_count) - 1;
+       struct machine_check_event *mc_evt;
+       int ret = 0;
+
+       /* Sanity check */
+       if (index < 0)
+               return ret;
+
+       /* Check if we have MCE info to process. */
+       if (index < MAX_MC_EVT) {
+               mc_evt = &__get_cpu_var(mce_event[index]);
+               /* Copy the event structure and release the original */
+               if (mce)
+                       *mce = *mc_evt;
+               if (release)
+                       mc_evt->in_use = 0;
+               ret = 1;
+       }
+       /* Decrement the count to free the slot. */
+       if (release)
+               __get_cpu_var(mce_nest_count)--;
+
+       return ret;
+}
+
+void release_mce_event(void)
+{
+       get_mce_event(NULL, true);
+}
+
+/*
+ * Queue up the MCE event which then can be handled later.
+ */
+void machine_check_queue_event(void)
+{
+       int index;
+       struct machine_check_event evt;
+
+       if (!get_mce_event(&evt, MCE_EVENT_RELEASE))
+               return;
+
+       index = __get_cpu_var(mce_queue_count)++;
+       /* If queue is full, just return for now. */
+       if (index >= MAX_MC_EVT) {
+               __get_cpu_var(mce_queue_count)--;
+               return;
+       }
+       __get_cpu_var(mce_event_queue[index]) = evt;
+}
+
+/*
+ * process pending MCE event from the mce event queue. This function will be
+ * called during syscall exit.
+ */
+void machine_check_process_queued_event(void)
+{
+       int index;
+
+       preempt_disable();
+       /*
+        * For now just print it to console.
+        * TODO: log this error event to FSP or nvram.
+        */
+       while (__get_cpu_var(mce_queue_count) > 0) {
+               index = __get_cpu_var(mce_queue_count) - 1;
+               machine_check_print_event_info(
+                               &__get_cpu_var(mce_event_queue[index]));
+               __get_cpu_var(mce_queue_count)--;
+       }
+       preempt_enable();
+}
+
+void machine_check_print_event_info(struct machine_check_event *evt)
+{
+       const char *level, *sevstr, *subtype;
+       static const char *mc_ue_types[] = {
+               "Indeterminate",
+               "Instruction fetch",
+               "Page table walk ifetch",
+               "Load/Store",
+               "Page table walk Load/Store",
+       };
+       static const char *mc_slb_types[] = {
+               "Indeterminate",
+               "Parity",
+               "Multihit",
+       };
+       static const char *mc_erat_types[] = {
+               "Indeterminate",
+               "Parity",
+               "Multihit",
+       };
+       static const char *mc_tlb_types[] = {
+               "Indeterminate",
+               "Parity",
+               "Multihit",
+       };
+
+       /* Print things out */
+       if (evt->version != MCE_V1) {
+               pr_err("Machine Check Exception, Unknown event version %d !\n",
+                      evt->version);
+               return;
+       }
+       switch (evt->severity) {
+       case MCE_SEV_NO_ERROR:
+               level = KERN_INFO;
+               sevstr = "Harmless";
+               break;
+       case MCE_SEV_WARNING:
+               level = KERN_WARNING;
+               sevstr = "";
+               break;
+       case MCE_SEV_ERROR_SYNC:
+               level = KERN_ERR;
+               sevstr = "Severe";
+               break;
+       case MCE_SEV_FATAL:
+       default:
+               level = KERN_ERR;
+               sevstr = "Fatal";
+               break;
+       }
+
+       printk("%s%s Machine check interrupt [%s]\n", level, sevstr,
+              evt->disposition == MCE_DISPOSITION_RECOVERED ?
+              "Recovered" : "[Not recovered");
+       printk("%s  Initiator: %s\n", level,
+              evt->initiator == MCE_INITIATOR_CPU ? "CPU" : "Unknown");
+       switch (evt->error_type) {
+       case MCE_ERROR_TYPE_UE:
+               subtype = evt->u.ue_error.ue_error_type <
+                       ARRAY_SIZE(mc_ue_types) ?
+                       mc_ue_types[evt->u.ue_error.ue_error_type]
+                       : "Unknown";
+               printk("%s  Error type: UE [%s]\n", level, subtype);
+               if (evt->u.ue_error.effective_address_provided)
+                       printk("%s    Effective address: %016llx\n",
+                              level, evt->u.ue_error.effective_address);
+               if (evt->u.ue_error.physical_address_provided)
+                       printk("%s      Physial address: %016llx\n",
+                              level, evt->u.ue_error.physical_address);
+               break;
+       case MCE_ERROR_TYPE_SLB:
+               subtype = evt->u.slb_error.slb_error_type <
+                       ARRAY_SIZE(mc_slb_types) ?
+                       mc_slb_types[evt->u.slb_error.slb_error_type]
+                       : "Unknown";
+               printk("%s  Error type: SLB [%s]\n", level, subtype);
+               if (evt->u.slb_error.effective_address_provided)
+                       printk("%s    Effective address: %016llx\n",
+                              level, evt->u.slb_error.effective_address);
+               break;
+       case MCE_ERROR_TYPE_ERAT:
+               subtype = evt->u.erat_error.erat_error_type <
+                       ARRAY_SIZE(mc_erat_types) ?
+                       mc_erat_types[evt->u.erat_error.erat_error_type]
+                       : "Unknown";
+               printk("%s  Error type: ERAT [%s]\n", level, subtype);
+               if (evt->u.erat_error.effective_address_provided)
+                       printk("%s    Effective address: %016llx\n",
+                              level, evt->u.erat_error.effective_address);
+               break;
+       case MCE_ERROR_TYPE_TLB:
+               subtype = evt->u.tlb_error.tlb_error_type <
+                       ARRAY_SIZE(mc_tlb_types) ?
+                       mc_tlb_types[evt->u.tlb_error.tlb_error_type]
+                       : "Unknown";
+               printk("%s  Error type: TLB [%s]\n", level, subtype);
+               if (evt->u.tlb_error.effective_address_provided)
+                       printk("%s    Effective address: %016llx\n",
+                              level, evt->u.tlb_error.effective_address);
+               break;
+       default:
+       case MCE_ERROR_TYPE_UNKNOWN:
+               printk("%s  Error type: Unknown\n", level);
+               break;
+       }
+}
+
+uint64_t get_mce_fault_addr(struct machine_check_event *evt)
+{
+       switch (evt->error_type) {
+       case MCE_ERROR_TYPE_UE:
+               if (evt->u.ue_error.effective_address_provided)
+                       return evt->u.ue_error.effective_address;
+               break;
+       case MCE_ERROR_TYPE_SLB:
+               if (evt->u.slb_error.effective_address_provided)
+                       return evt->u.slb_error.effective_address;
+               break;
+       case MCE_ERROR_TYPE_ERAT:
+               if (evt->u.erat_error.effective_address_provided)
+                       return evt->u.erat_error.effective_address;
+               break;
+       case MCE_ERROR_TYPE_TLB:
+               if (evt->u.tlb_error.effective_address_provided)
+                       return evt->u.tlb_error.effective_address;
+               break;
+       default:
+       case MCE_ERROR_TYPE_UNKNOWN:
+               break;
+       }
+       return 0;
+}
+EXPORT_SYMBOL(get_mce_fault_addr);
diff --git a/arch/powerpc/kernel/mce_power.c b/arch/powerpc/kernel/mce_power.c
new file mode 100644 (file)
index 0000000..b36e777
--- /dev/null
@@ -0,0 +1,284 @@
+/*
+ * Machine check exception handling CPU-side for power7 and power8
+ *
+ * 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 2013 IBM Corporation
+ * Author: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
+ */
+
+#undef DEBUG
+#define pr_fmt(fmt) "mce_power: " fmt
+
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <asm/mmu.h>
+#include <asm/mce.h>
+
+/* flush SLBs and reload */
+static void flush_and_reload_slb(void)
+{
+       struct slb_shadow *slb;
+       unsigned long i, n;
+
+       /* Invalidate all SLBs */
+       asm volatile("slbmte %0,%0; slbia" : : "r" (0));
+
+#ifdef CONFIG_KVM_BOOK3S_HANDLER
+       /*
+        * If machine check is hit when in guest or in transition, we will
+        * only flush the SLBs and continue.
+        */
+       if (get_paca()->kvm_hstate.in_guest)
+               return;
+#endif
+
+       /* For host kernel, reload the SLBs from shadow SLB buffer. */
+       slb = get_slb_shadow();
+       if (!slb)
+               return;
+
+       n = min_t(u32, slb->persistent, SLB_MIN_SIZE);
+
+       /* Load up the SLB entries from shadow SLB */
+       for (i = 0; i < n; i++) {
+               unsigned long rb = slb->save_area[i].esid;
+               unsigned long rs = slb->save_area[i].vsid;
+
+               rb = (rb & ~0xFFFul) | i;
+               asm volatile("slbmte %0,%1" : : "r" (rs), "r" (rb));
+       }
+}
+
+static long mce_handle_derror(uint64_t dsisr, uint64_t slb_error_bits)
+{
+       long handled = 1;
+
+       /*
+        * flush and reload SLBs for SLB errors and flush TLBs for TLB errors.
+        * reset the error bits whenever we handle them so that at the end
+        * we can check whether we handled all of them or not.
+        * */
+       if (dsisr & slb_error_bits) {
+               flush_and_reload_slb();
+               /* reset error bits */
+               dsisr &= ~(slb_error_bits);
+       }
+       if (dsisr & P7_DSISR_MC_TLB_MULTIHIT_MFTLB) {
+               if (cur_cpu_spec && cur_cpu_spec->flush_tlb)
+                       cur_cpu_spec->flush_tlb(TLBIEL_INVAL_PAGE);
+               /* reset error bits */
+               dsisr &= ~P7_DSISR_MC_TLB_MULTIHIT_MFTLB;
+       }
+       /* Any other errors we don't understand? */
+       if (dsisr & 0xffffffffUL)
+               handled = 0;
+
+       return handled;
+}
+
+static long mce_handle_derror_p7(uint64_t dsisr)
+{
+       return mce_handle_derror(dsisr, P7_DSISR_MC_SLB_ERRORS);
+}
+
+static long mce_handle_common_ierror(uint64_t srr1)
+{
+       long handled = 0;
+
+       switch (P7_SRR1_MC_IFETCH(srr1)) {
+       case 0:
+               break;
+       case P7_SRR1_MC_IFETCH_SLB_PARITY:
+       case P7_SRR1_MC_IFETCH_SLB_MULTIHIT:
+               /* flush and reload SLBs for SLB errors. */
+               flush_and_reload_slb();
+               handled = 1;
+               break;
+       case P7_SRR1_MC_IFETCH_TLB_MULTIHIT:
+               if (cur_cpu_spec && cur_cpu_spec->flush_tlb) {
+                       cur_cpu_spec->flush_tlb(TLBIEL_INVAL_PAGE);
+                       handled = 1;
+               }
+               break;
+       default:
+               break;
+       }
+
+       return handled;
+}
+
+static long mce_handle_ierror_p7(uint64_t srr1)
+{
+       long handled = 0;
+
+       handled = mce_handle_common_ierror(srr1);
+
+       if (P7_SRR1_MC_IFETCH(srr1) == P7_SRR1_MC_IFETCH_SLB_BOTH) {
+               flush_and_reload_slb();
+               handled = 1;
+       }
+       return handled;
+}
+
+static void mce_get_common_ierror(struct mce_error_info *mce_err, uint64_t srr1)
+{
+       switch (P7_SRR1_MC_IFETCH(srr1)) {
+       case P7_SRR1_MC_IFETCH_SLB_PARITY:
+               mce_err->error_type = MCE_ERROR_TYPE_SLB;
+               mce_err->u.slb_error_type = MCE_SLB_ERROR_PARITY;
+               break;
+       case P7_SRR1_MC_IFETCH_SLB_MULTIHIT:
+               mce_err->error_type = MCE_ERROR_TYPE_SLB;
+               mce_err->u.slb_error_type = MCE_SLB_ERROR_MULTIHIT;
+               break;
+       case P7_SRR1_MC_IFETCH_TLB_MULTIHIT:
+               mce_err->error_type = MCE_ERROR_TYPE_TLB;
+               mce_err->u.tlb_error_type = MCE_TLB_ERROR_MULTIHIT;
+               break;
+       case P7_SRR1_MC_IFETCH_UE:
+       case P7_SRR1_MC_IFETCH_UE_IFU_INTERNAL:
+               mce_err->error_type = MCE_ERROR_TYPE_UE;
+               mce_err->u.ue_error_type = MCE_UE_ERROR_IFETCH;
+               break;
+       case P7_SRR1_MC_IFETCH_UE_TLB_RELOAD:
+               mce_err->error_type = MCE_ERROR_TYPE_UE;
+               mce_err->u.ue_error_type =
+                               MCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH;
+               break;
+       }
+}
+
+static void mce_get_ierror_p7(struct mce_error_info *mce_err, uint64_t srr1)
+{
+       mce_get_common_ierror(mce_err, srr1);
+       if (P7_SRR1_MC_IFETCH(srr1) == P7_SRR1_MC_IFETCH_SLB_BOTH) {
+               mce_err->error_type = MCE_ERROR_TYPE_SLB;
+               mce_err->u.slb_error_type = MCE_SLB_ERROR_INDETERMINATE;
+       }
+}
+
+static void mce_get_derror_p7(struct mce_error_info *mce_err, uint64_t dsisr)
+{
+       if (dsisr & P7_DSISR_MC_UE) {
+               mce_err->error_type = MCE_ERROR_TYPE_UE;
+               mce_err->u.ue_error_type = MCE_UE_ERROR_LOAD_STORE;
+       } else if (dsisr & P7_DSISR_MC_UE_TABLEWALK) {
+               mce_err->error_type = MCE_ERROR_TYPE_UE;
+               mce_err->u.ue_error_type =
+                               MCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE;
+       } else if (dsisr & P7_DSISR_MC_ERAT_MULTIHIT) {
+               mce_err->error_type = MCE_ERROR_TYPE_ERAT;
+               mce_err->u.erat_error_type = MCE_ERAT_ERROR_MULTIHIT;
+       } else if (dsisr & P7_DSISR_MC_SLB_MULTIHIT) {
+               mce_err->error_type = MCE_ERROR_TYPE_SLB;
+               mce_err->u.slb_error_type = MCE_SLB_ERROR_MULTIHIT;
+       } else if (dsisr & P7_DSISR_MC_SLB_PARITY_MFSLB) {
+               mce_err->error_type = MCE_ERROR_TYPE_SLB;
+               mce_err->u.slb_error_type = MCE_SLB_ERROR_PARITY;
+       } else if (dsisr & P7_DSISR_MC_TLB_MULTIHIT_MFTLB) {
+               mce_err->error_type = MCE_ERROR_TYPE_TLB;
+               mce_err->u.tlb_error_type = MCE_TLB_ERROR_MULTIHIT;
+       } else if (dsisr & P7_DSISR_MC_SLB_MULTIHIT_PARITY) {
+               mce_err->error_type = MCE_ERROR_TYPE_SLB;
+               mce_err->u.slb_error_type = MCE_SLB_ERROR_INDETERMINATE;
+       }
+}
+
+long __machine_check_early_realmode_p7(struct pt_regs *regs)
+{
+       uint64_t srr1, addr;
+       long handled = 1;
+       struct mce_error_info mce_error_info = { 0 };
+
+       srr1 = regs->msr;
+
+       /*
+        * Handle memory errors depending whether this was a load/store or
+        * ifetch exception. Also, populate the mce error_type and
+        * type-specific error_type from either SRR1 or DSISR, depending
+        * whether this was a load/store or ifetch exception
+        */
+       if (P7_SRR1_MC_LOADSTORE(srr1)) {
+               handled = mce_handle_derror_p7(regs->dsisr);
+               mce_get_derror_p7(&mce_error_info, regs->dsisr);
+               addr = regs->dar;
+       } else {
+               handled = mce_handle_ierror_p7(srr1);
+               mce_get_ierror_p7(&mce_error_info, srr1);
+               addr = regs->nip;
+       }
+
+       save_mce_event(regs, handled, &mce_error_info, addr);
+       return handled;
+}
+
+static void mce_get_ierror_p8(struct mce_error_info *mce_err, uint64_t srr1)
+{
+       mce_get_common_ierror(mce_err, srr1);
+       if (P7_SRR1_MC_IFETCH(srr1) == P8_SRR1_MC_IFETCH_ERAT_MULTIHIT) {
+               mce_err->error_type = MCE_ERROR_TYPE_ERAT;
+               mce_err->u.erat_error_type = MCE_ERAT_ERROR_MULTIHIT;
+       }
+}
+
+static void mce_get_derror_p8(struct mce_error_info *mce_err, uint64_t dsisr)
+{
+       mce_get_derror_p7(mce_err, dsisr);
+       if (dsisr & P8_DSISR_MC_ERAT_MULTIHIT_SEC) {
+               mce_err->error_type = MCE_ERROR_TYPE_ERAT;
+               mce_err->u.erat_error_type = MCE_ERAT_ERROR_MULTIHIT;
+       }
+}
+
+static long mce_handle_ierror_p8(uint64_t srr1)
+{
+       long handled = 0;
+
+       handled = mce_handle_common_ierror(srr1);
+
+       if (P7_SRR1_MC_IFETCH(srr1) == P8_SRR1_MC_IFETCH_ERAT_MULTIHIT) {
+               flush_and_reload_slb();
+               handled = 1;
+       }
+       return handled;
+}
+
+static long mce_handle_derror_p8(uint64_t dsisr)
+{
+       return mce_handle_derror(dsisr, P8_DSISR_MC_SLB_ERRORS);
+}
+
+long __machine_check_early_realmode_p8(struct pt_regs *regs)
+{
+       uint64_t srr1, addr;
+       long handled = 1;
+       struct mce_error_info mce_error_info = { 0 };
+
+       srr1 = regs->msr;
+
+       if (P7_SRR1_MC_LOADSTORE(srr1)) {
+               handled = mce_handle_derror_p8(regs->dsisr);
+               mce_get_derror_p8(&mce_error_info, regs->dsisr);
+               addr = regs->dar;
+       } else {
+               handled = mce_handle_ierror_p8(srr1);
+               mce_get_ierror_p8(&mce_error_info, srr1);
+               addr = regs->nip;
+       }
+
+       save_mce_event(regs, handled, &mce_error_info, addr);
+       return handled;
+}
index e47d268727a4a8ed87948a4d3ab5f87ad00793b1..879f09620f8341e27dbfd1ed6be47fe242eab812 100644 (file)
@@ -344,7 +344,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_UNIFIED_ID_CACHE)
  */
 _KPROBE(flush_icache_range)
 BEGIN_FTR_SECTION
-       isync
+       PURGE_PREFETCHED_INS
        blr                             /* for 601, do nothing */
 END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
        li      r5,L1_CACHE_BYTES-1
@@ -448,6 +448,7 @@ _GLOBAL(invalidate_dcache_range)
  */
 _GLOBAL(__flush_dcache_icache)
 BEGIN_FTR_SECTION
+       PURGE_PREFETCHED_INS
        blr
 END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
        rlwinm  r3,r3,0,0,31-PAGE_SHIFT         /* Get page base address */
@@ -489,6 +490,7 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_TYPE_44x)
  */
 _GLOBAL(__flush_dcache_icache_phys)
 BEGIN_FTR_SECTION
+       PURGE_PREFETCHED_INS
        blr                                     /* for 601, do nothing */
 END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
        mfmsr   r10
index e59caf874d05ed60e500579b06bfcdf38bd85125..3d0249599d524af2a8883cacc4df5d44716273b8 100644 (file)
@@ -67,6 +67,7 @@ PPC64_CACHES:
 
 _KPROBE(flush_icache_range)
 BEGIN_FTR_SECTION
+       PURGE_PREFETCHED_INS
        blr
 END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
 /*
@@ -211,6 +212,11 @@ _GLOBAL(__flush_dcache_icache)
  * Different systems have different cache line sizes
  */
 
+BEGIN_FTR_SECTION
+       PURGE_PREFETCHED_INS
+       blr
+END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
+
 /* Flush the dcache */
        ld      r7,PPC64_CACHES@toc(r2)
        clrrdi  r3,r3,PAGE_SHIFT                    /* Page align */
@@ -246,8 +252,8 @@ _GLOBAL(__bswapdi2)
        or      r3,r7,r9
        blr
 
-#if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE)
 
+#ifdef CONFIG_PPC_EARLY_DEBUG_BOOTX
 _GLOBAL(rmci_on)
        sync
        isync
@@ -277,6 +283,9 @@ _GLOBAL(rmci_off)
        isync
        sync
        blr
+#endif /* CONFIG_PPC_EARLY_DEBUG_BOOTX */
+
+#if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE)
 
 /*
  * Do an IO access in real mode
index 0620eaaaad45b419c70475485a9d052c0ddbe246..623c356fe34f794f9fdeabb4d7a8edeccda081a3 100644 (file)
@@ -99,12 +99,28 @@ static inline void free_lppacas(void) { }
  * 3 persistent SLBs are registered here.  The buffer will be zero
  * initially, hence will all be invaild until we actually write them.
  */
-struct slb_shadow slb_shadow[] __cacheline_aligned = {
-       [0 ... (NR_CPUS-1)] = {
-               .persistent = cpu_to_be32(SLB_NUM_BOLTED),
-               .buffer_length = cpu_to_be32(sizeof(struct slb_shadow)),
-       },
-};
+static struct slb_shadow *slb_shadow;
+
+static void __init allocate_slb_shadows(int nr_cpus, int limit)
+{
+       int size = PAGE_ALIGN(sizeof(struct slb_shadow) * nr_cpus);
+       slb_shadow = __va(memblock_alloc_base(size, PAGE_SIZE, limit));
+       memset(slb_shadow, 0, size);
+}
+
+static struct slb_shadow * __init init_slb_shadow(int cpu)
+{
+       struct slb_shadow *s = &slb_shadow[cpu];
+
+       s->persistent = cpu_to_be32(SLB_NUM_BOLTED);
+       s->buffer_length = cpu_to_be32(sizeof(*s));
+
+       return s;
+}
+
+#else /* CONFIG_PPC_STD_MMU_64 */
+
+static void __init allocate_slb_shadows(int nr_cpus, int limit) { }
 
 #endif /* CONFIG_PPC_STD_MMU_64 */
 
@@ -142,7 +158,7 @@ void __init initialise_paca(struct paca_struct *new_paca, int cpu)
        new_paca->__current = &init_task;
        new_paca->data_offset = 0xfeeeeeeeeeeeeeeeULL;
 #ifdef CONFIG_PPC_STD_MMU_64
-       new_paca->slb_shadow_ptr = &slb_shadow[cpu];
+       new_paca->slb_shadow_ptr = init_slb_shadow(cpu);
 #endif /* CONFIG_PPC_STD_MMU_64 */
 }
 
@@ -190,6 +206,8 @@ void __init allocate_pacas(void)
 
        allocate_lppacas(nr_cpu_ids, limit);
 
+       allocate_slb_shadows(nr_cpu_ids, limit);
+
        /* Can't use for_each_*_cpu, as they aren't functional yet */
        for (cpu = 0; cpu < nr_cpu_ids; cpu++)
                initialise_paca(&paca[cpu], cpu);
index b903dc5cf944aee99fc36629fdb974f3e26b6888..2b0da27eaee4242f156d37bfbb4efa06bad334df 100644 (file)
@@ -296,9 +296,6 @@ void __init setup_arch(char **cmdline_p)
        if (cpu_has_feature(CPU_FTR_UNIFIED_ID_CACHE))
                ucache_bsize = icache_bsize = dcache_bsize;
 
-       /* reboot on panic */
-       panic_timeout = 180;
-
        if (ppc_md.panic)
                setup_panic();
 
index 4085aaa9478fd90eff1f1ce149d661bc7488284f..02929896bb66395c2ff9ddeffcf6bbdcdc012a15 100644 (file)
@@ -520,9 +520,6 @@ static void __init irqstack_early_init(void)
 #ifdef CONFIG_PPC_BOOK3E
 static void __init exc_lvl_early_init(void)
 {
-       extern unsigned int interrupt_base_book3e;
-       extern unsigned int exc_debug_debug_book3e;
-
        unsigned int i;
 
        for_each_possible_cpu(i) {
@@ -535,8 +532,7 @@ static void __init exc_lvl_early_init(void)
        }
 
        if (cpu_has_feature(CPU_FTR_DEBUG_LVL_EXC))
-               patch_branch(&interrupt_base_book3e + (0x040 / 4) + 1,
-                            (unsigned long)&exc_debug_debug_book3e, 0);
+               patch_exception(0x040, exc_debug_debug_book3e);
 }
 #else
 #define exc_lvl_early_init()
@@ -544,7 +540,8 @@ static void __init exc_lvl_early_init(void)
 
 /*
  * Stack space used when we detect a bad kernel stack pointer, and
- * early in SMP boots before relocation is enabled.
+ * early in SMP boots before relocation is enabled. Exclusive emergency
+ * stack for machine checks.
  */
 static void __init emergency_stack_init(void)
 {
@@ -567,6 +564,13 @@ static void __init emergency_stack_init(void)
                sp  = memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit);
                sp += THREAD_SIZE;
                paca[i].emergency_sp = __va(sp);
+
+#ifdef CONFIG_PPC_BOOK3S_64
+               /* emergency stack for machine check exception handling. */
+               sp  = memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit);
+               sp += THREAD_SIZE;
+               paca[i].mc_emergency_sp = __va(sp);
+#endif
        }
 }
 
@@ -588,9 +592,6 @@ void __init setup_arch(char **cmdline_p)
        dcache_bsize = ppc64_caches.dline_size;
        icache_bsize = ppc64_caches.iline_size;
 
-       /* reboot on panic */
-       panic_timeout = 180;
-
        if (ppc_md.panic)
                setup_panic();
 
index a3b64f3bf9a298b057cfdc57b008ea01eebecf63..19d654b0150a487f8cbd2168f1d3b0136065db7d 100644 (file)
@@ -369,13 +369,8 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
        cpumask_set_cpu(boot_cpuid, cpu_sibling_mask(boot_cpuid));
        cpumask_set_cpu(boot_cpuid, cpu_core_mask(boot_cpuid));
 
-       if (smp_ops)
-               if (smp_ops->probe)
-                       max_cpus = smp_ops->probe();
-               else
-                       max_cpus = NR_CPUS;
-       else
-               max_cpus = 1;
+       if (smp_ops && smp_ops->probe)
+               smp_ops->probe();
 }
 
 void smp_prepare_boot_cpu(void)
index b4e667663d9bfc2e9954435790b0ebc5b6fc94ca..cad777eb613af11ef6f1b736610a326605c9b12d 100644 (file)
@@ -108,14 +108,14 @@ void ppc_enable_pmcs(void)
 }
 EXPORT_SYMBOL(ppc_enable_pmcs);
 
-#define SYSFS_PMCSETUP(NAME, ADDRESS) \
+#define __SYSFS_SPRSETUP(NAME, ADDRESS, EXTRA) \
 static void read_##NAME(void *val) \
 { \
        *(unsigned long *)val = mfspr(ADDRESS); \
 } \
 static void write_##NAME(void *val) \
 { \
-       ppc_enable_pmcs(); \
+       EXTRA; \
        mtspr(ADDRESS, *(unsigned long *)val);  \
 } \
 static ssize_t show_##NAME(struct device *dev, \
@@ -140,6 +140,10 @@ static ssize_t __used \
        return count; \
 }
 
+#define SYSFS_PMCSETUP(NAME, ADDRESS)  \
+       __SYSFS_SPRSETUP(NAME, ADDRESS, ppc_enable_pmcs())
+#define SYSFS_SPRSETUP(NAME, ADDRESS)  \
+       __SYSFS_SPRSETUP(NAME, ADDRESS, )
 
 /* Let's define all possible registers, we'll only hook up the ones
  * that are implemented on the current processor
@@ -175,10 +179,10 @@ SYSFS_PMCSETUP(pmc7, SPRN_PMC7);
 SYSFS_PMCSETUP(pmc8, SPRN_PMC8);
 
 SYSFS_PMCSETUP(mmcra, SPRN_MMCRA);
-SYSFS_PMCSETUP(purr, SPRN_PURR);
-SYSFS_PMCSETUP(spurr, SPRN_SPURR);
-SYSFS_PMCSETUP(dscr, SPRN_DSCR);
-SYSFS_PMCSETUP(pir, SPRN_PIR);
+SYSFS_SPRSETUP(purr, SPRN_PURR);
+SYSFS_SPRSETUP(spurr, SPRN_SPURR);
+SYSFS_SPRSETUP(dscr, SPRN_DSCR);
+SYSFS_SPRSETUP(pir, SPRN_PIR);
 
 /*
   Lets only enable read for phyp resources and
@@ -249,34 +253,34 @@ SYSFS_PMCSETUP(pa6t_pmc3, SPRN_PA6T_PMC3);
 SYSFS_PMCSETUP(pa6t_pmc4, SPRN_PA6T_PMC4);
 SYSFS_PMCSETUP(pa6t_pmc5, SPRN_PA6T_PMC5);
 #ifdef CONFIG_DEBUG_KERNEL
-SYSFS_PMCSETUP(hid0, SPRN_HID0);
-SYSFS_PMCSETUP(hid1, SPRN_HID1);
-SYSFS_PMCSETUP(hid4, SPRN_HID4);
-SYSFS_PMCSETUP(hid5, SPRN_HID5);
-SYSFS_PMCSETUP(ima0, SPRN_PA6T_IMA0);
-SYSFS_PMCSETUP(ima1, SPRN_PA6T_IMA1);
-SYSFS_PMCSETUP(ima2, SPRN_PA6T_IMA2);
-SYSFS_PMCSETUP(ima3, SPRN_PA6T_IMA3);
-SYSFS_PMCSETUP(ima4, SPRN_PA6T_IMA4);
-SYSFS_PMCSETUP(ima5, SPRN_PA6T_IMA5);
-SYSFS_PMCSETUP(ima6, SPRN_PA6T_IMA6);
-SYSFS_PMCSETUP(ima7, SPRN_PA6T_IMA7);
-SYSFS_PMCSETUP(ima8, SPRN_PA6T_IMA8);
-SYSFS_PMCSETUP(ima9, SPRN_PA6T_IMA9);
-SYSFS_PMCSETUP(imaat, SPRN_PA6T_IMAAT);
-SYSFS_PMCSETUP(btcr, SPRN_PA6T_BTCR);
-SYSFS_PMCSETUP(pccr, SPRN_PA6T_PCCR);
-SYSFS_PMCSETUP(rpccr, SPRN_PA6T_RPCCR);
-SYSFS_PMCSETUP(der, SPRN_PA6T_DER);
-SYSFS_PMCSETUP(mer, SPRN_PA6T_MER);
-SYSFS_PMCSETUP(ber, SPRN_PA6T_BER);
-SYSFS_PMCSETUP(ier, SPRN_PA6T_IER);
-SYSFS_PMCSETUP(sier, SPRN_PA6T_SIER);
-SYSFS_PMCSETUP(siar, SPRN_PA6T_SIAR);
-SYSFS_PMCSETUP(tsr0, SPRN_PA6T_TSR0);
-SYSFS_PMCSETUP(tsr1, SPRN_PA6T_TSR1);
-SYSFS_PMCSETUP(tsr2, SPRN_PA6T_TSR2);
-SYSFS_PMCSETUP(tsr3, SPRN_PA6T_TSR3);
+SYSFS_SPRSETUP(hid0, SPRN_HID0);
+SYSFS_SPRSETUP(hid1, SPRN_HID1);
+SYSFS_SPRSETUP(hid4, SPRN_HID4);
+SYSFS_SPRSETUP(hid5, SPRN_HID5);
+SYSFS_SPRSETUP(ima0, SPRN_PA6T_IMA0);
+SYSFS_SPRSETUP(ima1, SPRN_PA6T_IMA1);
+SYSFS_SPRSETUP(ima2, SPRN_PA6T_IMA2);
+SYSFS_SPRSETUP(ima3, SPRN_PA6T_IMA3);
+SYSFS_SPRSETUP(ima4, SPRN_PA6T_IMA4);
+SYSFS_SPRSETUP(ima5, SPRN_PA6T_IMA5);
+SYSFS_SPRSETUP(ima6, SPRN_PA6T_IMA6);
+SYSFS_SPRSETUP(ima7, SPRN_PA6T_IMA7);
+SYSFS_SPRSETUP(ima8, SPRN_PA6T_IMA8);
+SYSFS_SPRSETUP(ima9, SPRN_PA6T_IMA9);
+SYSFS_SPRSETUP(imaat, SPRN_PA6T_IMAAT);
+SYSFS_SPRSETUP(btcr, SPRN_PA6T_BTCR);
+SYSFS_SPRSETUP(pccr, SPRN_PA6T_PCCR);
+SYSFS_SPRSETUP(rpccr, SPRN_PA6T_RPCCR);
+SYSFS_SPRSETUP(der, SPRN_PA6T_DER);
+SYSFS_SPRSETUP(mer, SPRN_PA6T_MER);
+SYSFS_SPRSETUP(ber, SPRN_PA6T_BER);
+SYSFS_SPRSETUP(ier, SPRN_PA6T_IER);
+SYSFS_SPRSETUP(sier, SPRN_PA6T_SIER);
+SYSFS_SPRSETUP(siar, SPRN_PA6T_SIAR);
+SYSFS_SPRSETUP(tsr0, SPRN_PA6T_TSR0);
+SYSFS_SPRSETUP(tsr1, SPRN_PA6T_TSR1);
+SYSFS_SPRSETUP(tsr2, SPRN_PA6T_TSR2);
+SYSFS_SPRSETUP(tsr3, SPRN_PA6T_TSR3);
 #endif /* CONFIG_DEBUG_KERNEL */
 #endif /* HAS_PPC_PMC_PA6T */
 
index b3b144121cc99d64df0c409b0773259770ddf0af..afb1b56ef4fa6481f940e85130e17b4efc585023 100644 (file)
@@ -510,7 +510,6 @@ void timer_interrupt(struct pt_regs * regs)
         */
        may_hard_irq_enable();
 
-       __get_cpu_var(irq_stat).timer_irqs++;
 
 #if defined(CONFIG_PPC32) && defined(CONFIG_PMAC)
        if (atomic_read(&ppc_n_lost_interrupts) != 0)
@@ -532,10 +531,12 @@ void timer_interrupt(struct pt_regs * regs)
                *next_tb = ~(u64)0;
                if (evt->event_handler)
                        evt->event_handler(evt);
+               __get_cpu_var(irq_stat).timer_irqs_event++;
        } else {
                now = *next_tb - now;
                if (now <= DECREMENTER_MAX)
                        set_dec((int)now);
+               __get_cpu_var(irq_stat).timer_irqs_others++;
        }
 
 #ifdef CONFIG_PPC64
index 907a472f9a9e4c1db3747a8d4ff22cc1bb133ee8..330841766b09ef852fa96b5874b8619d8a7d950c 100644 (file)
@@ -285,6 +285,21 @@ void system_reset_exception(struct pt_regs *regs)
 
        /* What should we do here? We could issue a shutdown or hard reset. */
 }
+
+/*
+ * This function is called in real mode. Strictly no printk's please.
+ *
+ * regs->nip and regs->msr contains srr0 and ssr1.
+ */
+long machine_check_early(struct pt_regs *regs)
+{
+       long handled = 0;
+
+       if (cur_cpu_spec && cur_cpu_spec->machine_check_early)
+               handled = cur_cpu_spec->machine_check_early(regs);
+       return handled;
+}
+
 #endif
 
 /*
index 59f419b935f2501653379fd099b2b1b731a4e7d9..003b20964ea0dfa435af8e1aac8fadde534f1fc2 100644 (file)
@@ -186,7 +186,7 @@ bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
         * emulate_step() returns 1 if the insn was successfully emulated.
         * For all other cases, we need to single-step in hardware.
         */
-       ret = emulate_step(regs, auprobe->ainsn);
+       ret = emulate_step(regs, auprobe->insn);
        if (ret > 0)
                return true;
 
index a353c485808c6ea203eac428106b5fdf41943b36..768a9f977c001ee73e6d5aa2f0b8ee44ea3b35f5 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/kvm_host.h>
 #include <linux/kernel.h>
 #include <asm/opal.h>
+#include <asm/mce.h>
 
 /* SRR1 bits for machine check on POWER7 */
 #define SRR1_MC_LDSTERR                (1ul << (63-42))
@@ -58,18 +59,6 @@ static void reload_slb(struct kvm_vcpu *vcpu)
        }
 }
 
-/* POWER7 TLB flush */
-static void flush_tlb_power7(struct kvm_vcpu *vcpu)
-{
-       unsigned long i, rb;
-
-       rb = TLBIEL_INVAL_SET_LPID;
-       for (i = 0; i < POWER7_TLB_SETS; ++i) {
-               asm volatile("tlbiel %0" : : "r" (rb));
-               rb += 1 << TLBIEL_INVAL_SET_SHIFT;
-       }
-}
-
 /*
  * On POWER7, see if we can handle a machine check that occurred inside
  * the guest in real mode, without switching to the host partition.
@@ -79,9 +68,7 @@ static void flush_tlb_power7(struct kvm_vcpu *vcpu)
 static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu)
 {
        unsigned long srr1 = vcpu->arch.shregs.msr;
-#ifdef CONFIG_PPC_POWERNV
-       struct opal_machine_check_event *opal_evt;
-#endif
+       struct machine_check_event mce_evt;
        long handled = 1;
 
        if (srr1 & SRR1_MC_LDSTERR) {
@@ -96,7 +83,8 @@ static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu)
                                   DSISR_MC_SLB_PARITY | DSISR_MC_DERAT_MULTI);
                }
                if (dsisr & DSISR_MC_TLB_MULTI) {
-                       flush_tlb_power7(vcpu);
+                       if (cur_cpu_spec && cur_cpu_spec->flush_tlb)
+                               cur_cpu_spec->flush_tlb(TLBIEL_INVAL_SET_LPID);
                        dsisr &= ~DSISR_MC_TLB_MULTI;
                }
                /* Any other errors we don't understand? */
@@ -113,28 +101,38 @@ static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu)
                reload_slb(vcpu);
                break;
        case SRR1_MC_IFETCH_TLBMULTI:
-               flush_tlb_power7(vcpu);
+               if (cur_cpu_spec && cur_cpu_spec->flush_tlb)
+                       cur_cpu_spec->flush_tlb(TLBIEL_INVAL_SET_LPID);
                break;
        default:
                handled = 0;
        }
 
-#ifdef CONFIG_PPC_POWERNV
        /*
-        * See if OPAL has already handled the condition.
-        * We assume that if the condition is recovered then OPAL
+        * See if we have already handled the condition in the linux host.
+        * We assume that if the condition is recovered then linux host
         * will have generated an error log event that we will pick
         * up and log later.
+        * Don't release mce event now. In case if condition is not
+        * recovered we do guest exit and go back to linux host machine
+        * check handler. Hence we need make sure that current mce event
+        * is available for linux host to consume.
         */
-       opal_evt = local_paca->opal_mc_evt;
-       if (opal_evt->version == OpalMCE_V1 &&
-           (opal_evt->severity == OpalMCE_SEV_NO_ERROR ||
-            opal_evt->disposition == OpalMCE_DISPOSITION_RECOVERED))
+       if (!get_mce_event(&mce_evt, MCE_EVENT_DONTRELEASE))
+               goto out;
+
+       if (mce_evt.version == MCE_V1 &&
+           (mce_evt.severity == MCE_SEV_NO_ERROR ||
+            mce_evt.disposition == MCE_DISPOSITION_RECOVERED))
                handled = 1;
 
+out:
+       /*
+        * If we have handled the error, then release the mce event because
+        * we will be delivering machine check to guest.
+        */
        if (handled)
-               opal_evt->in_use = 0;
-#endif
+               release_mce_event();
 
        return handled;
 }
index 17e5b23643124347febe56a05f5deb7e1a2e361e..d5edbeb8eb8209e61a9d6524acfa565e3f30782f 100644 (file)
@@ -159,6 +159,21 @@ unsigned int translate_branch(const unsigned int *dest, const unsigned int *src)
        return 0;
 }
 
+#ifdef CONFIG_PPC_BOOK3E_64
+void __patch_exception(int exc, unsigned long addr)
+{
+       extern unsigned int interrupt_base_book3e;
+       unsigned int *ibase = &interrupt_base_book3e;
+
+       /* Our exceptions vectors start with a NOP and -then- a branch
+        * to deal with single stepping from userspace which stops on
+        * the second instruction. Thus we need to patch the second
+        * instruction of the exception, not the first one
+        */
+
+       patch_branch(ibase + (exc / 4) + 1, addr, 0);
+}
+#endif
 
 #ifdef CONFIG_CODE_PATCHING_SELFTEST
 
index d3cbda62857b92ffb0867c4fe0ab1deeb0979313..1136d26a95ae02ac075914e13f54720864b71fea 100644 (file)
@@ -148,7 +148,10 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
        and     r0,r0,r4                /* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/
        andc    r0,r30,r0               /* r0 = pte & ~r0 */
        rlwimi  r3,r0,32-1,31,31        /* Insert result into PP lsb */
-       ori     r3,r3,HPTE_R_C          /* Always add "C" bit for perf. */
+       /*
+        * Always add "C" bit for perf. Memory coherence is always enabled
+        */
+       ori     r3,r3,HPTE_R_C | HPTE_R_M
 
        /* We eventually do the icache sync here (maybe inline that
         * code rather than call a C function...) 
@@ -457,7 +460,10 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
        and     r0,r0,r4                /* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/
        andc    r0,r3,r0                /* r0 = pte & ~r0 */
        rlwimi  r3,r0,32-1,31,31        /* Insert result into PP lsb */
-       ori     r3,r3,HPTE_R_C          /* Always add "C" bit for perf. */
+       /*
+        * Always add "C" bit for perf. Memory coherence is always enabled
+        */
+       ori     r3,r3,HPTE_R_C | HPTE_R_M
 
        /* We eventually do the icache sync here (maybe inline that
         * code rather than call a C function...)
@@ -795,7 +801,10 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
        and     r0,r0,r4                /* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/
        andc    r0,r30,r0               /* r0 = pte & ~r0 */
        rlwimi  r3,r0,32-1,31,31        /* Insert result into PP lsb */
-       ori     r3,r3,HPTE_R_C          /* Always add "C" bit for perf. */
+       /*
+        * Always add "C" bit for perf. Memory coherence is always enabled
+        */
+       ori     r3,r3,HPTE_R_C | HPTE_R_M
 
        /* We eventually do the icache sync here (maybe inline that
         * code rather than call a C function...)
index 6176b3cdf57991590df2b26f42f27eed593096bb..de6881259aef3bd552c53ea77751093336e2e5be 100644 (file)
@@ -169,9 +169,10 @@ static unsigned long htab_convert_pte_flags(unsigned long pteflags)
        if ((pteflags & _PAGE_USER) && !((pteflags & _PAGE_RW) &&
                                         (pteflags & _PAGE_DIRTY)))
                rflags |= 1;
-
-       /* Always add C */
-       return rflags | HPTE_R_C;
+       /*
+        * Always add "C" bit for perf. Memory coherence is always enabled
+        */
+       return rflags | HPTE_R_C | HPTE_R_M;
 }
 
 int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
index 34de9e0cdc3466313eea62bbdd7079df409547c8..826893fcb3a78b0198d5fa4b0b047428d8852802 100644 (file)
@@ -127,7 +127,11 @@ repeat:
 
                /* Add in WIMG bits */
                rflags |= (new_pmd & (_PAGE_WRITETHRU | _PAGE_NO_CACHE |
-                                     _PAGE_COHERENT | _PAGE_GUARDED));
+                                     _PAGE_GUARDED));
+               /*
+                * enable the memory coherence always
+                */
+               rflags |= HPTE_R_M;
 
                /* Insert into the hash table, primary slot */
                slot = ppc_md.hpte_insert(hpte_group, vpn, pa, rflags, 0,
index 0b7fb6761015526a38be8dac7ee51d0ca4d9f161..a5bcf930119691ad01c4116faaece823292669aa 100644 (file)
@@ -99,6 +99,10 @@ int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid,
                /* Add in WIMG bits */
                rflags |= (new_pte & (_PAGE_WRITETHRU | _PAGE_NO_CACHE |
                                      _PAGE_COHERENT | _PAGE_GUARDED));
+               /*
+                * enable the memory coherence always
+                */
+               rflags |= HPTE_R_M;
 
                slot = hpte_insert_repeating(hash, vpn, pa, rflags, 0,
                                             mmu_psize, ssize);
index 841e0d00863c94d99cac5c139b887dc97c21cfe1..ad90429bbd8b4b25883738bd867719588ac32b92 100644 (file)
@@ -174,7 +174,7 @@ void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep,
                pte_t pte)
 {
 #ifdef CONFIG_DEBUG_VM
-       WARN_ON(pte_present(*ptep));
+       WARN_ON(pte_val(*ptep) & _PAGE_PRESENT);
 #endif
        /* Note: mm->context.id might not yet have been assigned as
         * this context might not have been activated yet when this
index 9d95786aa80ffbdcb8601379d774fc1f158006d0..02e8681fb8655a724b6e75746301d8a0cbb6befb 100644 (file)
@@ -687,7 +687,7 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr,
                pmd_t *pmdp, pmd_t pmd)
 {
 #ifdef CONFIG_DEBUG_VM
-       WARN_ON(!pmd_none(*pmdp));
+       WARN_ON(pmd_val(*pmdp) & _PAGE_PRESENT);
        assert_spin_locked(&mm->page_table_lock);
        WARN_ON(!pmd_trans_huge(pmd));
 #endif
index 358d743031385ae7a269ba65200483227126d372..8805b7b87dc60e1f47e511116301d8865a86241f 100644 (file)
@@ -518,25 +518,6 @@ static void setup_page_sizes(void)
        }
 }
 
-static void __patch_exception(int exc, unsigned long addr)
-{
-       extern unsigned int interrupt_base_book3e;
-       unsigned int *ibase = &interrupt_base_book3e;
-       /* Our exceptions vectors start with a NOP and -then- a branch
-        * to deal with single stepping from userspace which stops on
-        * the second instruction. Thus we need to patch the second
-        * instruction of the exception, not the first one
-        */
-
-       patch_branch(ibase + (exc / 4) + 1, addr, 0);
-}
-
-#define patch_exception(exc, name) do { \
-       extern unsigned int name; \
-       __patch_exception((exc), (unsigned long)&name); \
-} while (0)
-
 static void setup_mmu_htw(void)
 {
        /* Check if HW tablewalk is present, and if yes, enable it by:
index fc9c1cbfcb1d5ff7719d75f7db46d36a8e93d1b9..5aa3f4b5332c575b6de4963e5d0ade67f6f63855 100644 (file)
@@ -1,9 +1,9 @@
 config PPC_MPC512x
        bool "512x-based boards"
        depends on 6xx
+       select COMMON_CLK
        select FSL_SOC
        select IPIC
-       select PPC_CLOCK
        select PPC_PCI_CHOICE
        select FSL_PCI if PCI
        select ARCH_WANT_OPTIONAL_GPIOLIB
index 72fb9340e09fa7bd2c8e4921a4e57bfdda3d760b..01693121a2b1a54feedcaac3489a4ea96f0ad64b 100644 (file)
@@ -1,7 +1,8 @@
 #
 # Makefile for the Freescale PowerPC 512x linux kernel.
 #
-obj-y                          += clock.o mpc512x_shared.o
+obj-$(CONFIG_COMMON_CLK)       += clock-commonclk.o
+obj-y                          += mpc512x_shared.o
 obj-$(CONFIG_MPC5121_ADS)      += mpc5121_ads.o mpc5121_ads_cpld.o
 obj-$(CONFIG_MPC512x_GENERIC)  += mpc512x_generic.o
 obj-$(CONFIG_PDM360NG)         += pdm360ng.o
diff --git a/arch/powerpc/platforms/512x/clock-commonclk.c b/arch/powerpc/platforms/512x/clock-commonclk.c
new file mode 100644 (file)
index 0000000..29b5fa6
--- /dev/null
@@ -0,0 +1,950 @@
+/*
+ * Copyright (C) 2013 DENX Software Engineering
+ *
+ * Gerhard Sittig, <gsi@denx.de>
+ *
+ * common clock driver support for the MPC512x platform
+ *
+ * This 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/bitops.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <asm/mpc5121.h>
+#include <dt-bindings/clock/mpc512x-clock.h>
+
+#include "mpc512x.h"           /* our public mpc5121_clk_init() API */
+
+/* helpers to keep the MCLK intermediates "somewhere" in our table */
+enum {
+       MCLK_IDX_MUX0,
+       MCLK_IDX_EN0,
+       MCLK_IDX_DIV0,
+       MCLK_MAX_IDX,
+};
+
+#define NR_PSCS                        12
+#define NR_MSCANS              4
+#define NR_SPDIFS              1
+#define NR_MCLKS               (NR_PSCS + NR_MSCANS + NR_SPDIFS)
+
+/* extend the public set of clocks by adding internal slots for management */
+enum {
+       /* arrange for adjacent numbers after the public set */
+       MPC512x_CLK_START_PRIVATE = MPC512x_CLK_LAST_PUBLIC,
+       /* clocks which aren't announced to the public */
+       MPC512x_CLK_DDR,
+       MPC512x_CLK_MEM,
+       MPC512x_CLK_IIM,
+       MPC512x_CLK_SDHC_2,
+       /* intermediates in div+gate combos or fractional dividers */
+       MPC512x_CLK_DDR_UG,
+       MPC512x_CLK_SDHC_x4,
+       MPC512x_CLK_SDHC_UG,
+       MPC512x_CLK_DIU_x4,
+       MPC512x_CLK_DIU_UG,
+       MPC512x_CLK_MBX_BUS_UG,
+       MPC512x_CLK_MBX_UG,
+       MPC512x_CLK_MBX_3D_UG,
+       MPC512x_CLK_PCI_UG,
+       MPC512x_CLK_NFC_UG,
+       MPC512x_CLK_LPC_UG,
+       MPC512x_CLK_SPDIF_TX_IN,
+       /* intermediates for the mux+gate+div+mux MCLK generation */
+       MPC512x_CLK_MCLKS_FIRST,
+       MPC512x_CLK_MCLKS_LAST = MPC512x_CLK_MCLKS_FIRST
+                               + NR_MCLKS * MCLK_MAX_IDX,
+       /* internal, symbolic spec for the number of slots */
+       MPC512x_CLK_LAST_PRIVATE,
+};
+
+/* data required for the OF clock provider registration */
+static struct clk *clks[MPC512x_CLK_LAST_PRIVATE];
+static struct clk_onecell_data clk_data;
+
+/* CCM register access */
+static struct mpc512x_ccm __iomem *clkregs;
+static DEFINE_SPINLOCK(clklock);
+
+/* convenience wrappers around the common clk API */
+static inline struct clk *mpc512x_clk_fixed(const char *name, int rate)
+{
+       return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate);
+}
+
+static inline struct clk *mpc512x_clk_factor(
+       const char *name, const char *parent_name,
+       int mul, int div)
+{
+       int clkflags;
+
+       clkflags = CLK_SET_RATE_PARENT;
+       return clk_register_fixed_factor(NULL, name, parent_name, clkflags,
+                                        mul, div);
+}
+
+static inline struct clk *mpc512x_clk_divider(
+       const char *name, const char *parent_name, u8 clkflags,
+       u32 __iomem *reg, u8 pos, u8 len, int divflags)
+{
+       return clk_register_divider(NULL, name, parent_name, clkflags,
+                                   reg, pos, len, divflags, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_divtable(
+       const char *name, const char *parent_name,
+       u32 __iomem *reg, u8 pos, u8 len,
+       const struct clk_div_table *divtab)
+{
+       u8 divflags;
+
+       divflags = 0;
+       return clk_register_divider_table(NULL, name, parent_name, 0,
+                                         reg, pos, len, divflags,
+                                         divtab, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_gated(
+       const char *name, const char *parent_name,
+       u32 __iomem *reg, u8 pos)
+{
+       int clkflags;
+
+       clkflags = CLK_SET_RATE_PARENT;
+       return clk_register_gate(NULL, name, parent_name, clkflags,
+                                reg, pos, 0, &clklock);
+}
+
+static inline struct clk *mpc512x_clk_muxed(const char *name,
+       const char **parent_names, int parent_count,
+       u32 __iomem *reg, u8 pos, u8 len)
+{
+       int clkflags;
+       u8 muxflags;
+
+       clkflags = CLK_SET_RATE_PARENT;
+       muxflags = 0;
+       return clk_register_mux(NULL, name,
+                               parent_names, parent_count, clkflags,
+                               reg, pos, len, muxflags, &clklock);
+}
+
+/* helper to isolate a bit field from a register */
+static inline int get_bit_field(uint32_t __iomem *reg, uint8_t pos, uint8_t len)
+{
+       uint32_t val;
+
+       val = in_be32(reg);
+       val >>= pos;
+       val &= (1 << len) - 1;
+       return val;
+}
+
+/* get the SPMF and translate it into the "sys pll" multiplier */
+static int get_spmf_mult(void)
+{
+       static int spmf_to_mult[] = {
+               68, 1, 12, 16, 20, 24, 28, 32,
+               36, 40, 44, 48, 52, 56, 60, 64,
+       };
+       int spmf;
+
+       spmf = get_bit_field(&clkregs->spmr, 24, 4);
+       return spmf_to_mult[spmf];
+}
+
+/*
+ * get the SYS_DIV value and translate it into a divide factor
+ *
+ * values returned from here are a multiple of the real factor since the
+ * divide ratio is fractional
+ */
+static int get_sys_div_x2(void)
+{
+       static int sysdiv_code_to_x2[] = {
+               4, 5, 6, 7, 8, 9, 10, 14,
+               12, 16, 18, 22, 20, 24, 26, 30,
+               28, 32, 34, 38, 36, 40, 42, 46,
+               44, 48, 50, 54, 52, 56, 58, 62,
+               60, 64, 66,
+       };
+       int divcode;
+
+       divcode = get_bit_field(&clkregs->scfr2, 26, 6);
+       return sysdiv_code_to_x2[divcode];
+}
+
+/*
+ * get the CPMF value and translate it into a multiplier factor
+ *
+ * values returned from here are a multiple of the real factor since the
+ * multiplier ratio is fractional
+ */
+static int get_cpmf_mult_x2(void)
+{
+       static int cpmf_to_mult[] = {
+               72, 2, 2, 3, 4, 5, 6, 7,
+       };
+       int cpmf;
+
+       cpmf = get_bit_field(&clkregs->spmr, 16, 4);
+       return cpmf_to_mult[cpmf];
+}
+
+/*
+ * some of the clock dividers do scale in a linear way, yet not all of
+ * their bit combinations are legal; use a divider table to get a
+ * resulting set of applicable divider values
+ */
+
+/* applies to the IPS_DIV, and PCI_DIV values */
+static struct clk_div_table divtab_2346[] = {
+       { .val = 2, .div = 2, },
+       { .val = 3, .div = 3, },
+       { .val = 4, .div = 4, },
+       { .val = 6, .div = 6, },
+       { .div = 0, },
+};
+
+/* applies to the MBX_DIV, LPC_DIV, and NFC_DIV values */
+static struct clk_div_table divtab_1234[] = {
+       { .val = 1, .div = 1, },
+       { .val = 2, .div = 2, },
+       { .val = 3, .div = 3, },
+       { .val = 4, .div = 4, },
+       { .div = 0, },
+};
+
+static int get_freq_from_dt(char *propname)
+{
+       struct device_node *np;
+       const unsigned int *prop;
+       int val;
+
+       val = 0;
+       np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
+       if (np) {
+               prop = of_get_property(np, propname, NULL);
+               if (prop)
+                       val = *prop;
+           of_node_put(np);
+       }
+       return val;
+}
+
+static void mpc512x_clk_preset_data(void)
+{
+       size_t i;
+
+       for (i = 0; i < ARRAY_SIZE(clks); i++)
+               clks[i] = ERR_PTR(-ENODEV);
+}
+
+/*
+ * - receives the "bus frequency" from the caller (that's the IPS clock
+ *   rate, the historical source of clock information)
+ * - fetches the system PLL multiplier and divider values as well as the
+ *   IPS divider value from hardware
+ * - determines the REF clock rate either from the XTAL/OSC spec (if
+ *   there is a device tree node describing the oscillator) or from the
+ *   IPS bus clock (supported for backwards compatibility, such that
+ *   setups without XTAL/OSC specs keep working)
+ * - creates the "ref" clock item in the clock tree, such that
+ *   subsequent code can create the remainder of the hierarchy (REF ->
+ *   SYS -> CSB -> IPS) from the REF clock rate and the returned mul/div
+ *   values
+ */
+static void mpc512x_clk_setup_ref_clock(struct device_node *np, int bus_freq,
+                                       int *sys_mul, int *sys_div,
+                                       int *ips_div)
+{
+       struct clk *osc_clk;
+       int calc_freq;
+
+       /* fetch mul/div factors from the hardware */
+       *sys_mul = get_spmf_mult();
+       *sys_mul *= 2;          /* compensate for the fractional divider */
+       *sys_div = get_sys_div_x2();
+       *ips_div = get_bit_field(&clkregs->scfr1, 23, 3);
+
+       /* lookup the oscillator clock for its rate */
+       osc_clk = of_clk_get_by_name(np, "osc");
+
+       /*
+        * either descend from OSC to REF (and in bypassing verify the
+        * IPS rate), or backtrack from IPS and multiplier values that
+        * were fetched from hardware to REF and thus to the OSC value
+        *
+        * in either case the REF clock gets created here and the
+        * remainder of the clock tree can get spanned from there
+        */
+       if (!IS_ERR(osc_clk)) {
+               clks[MPC512x_CLK_REF] = mpc512x_clk_factor("ref", "osc", 1, 1);
+               calc_freq = clk_get_rate(clks[MPC512x_CLK_REF]);
+               calc_freq *= *sys_mul;
+               calc_freq /= *sys_div;
+               calc_freq /= 2;
+               calc_freq /= *ips_div;
+               if (bus_freq && calc_freq != bus_freq)
+                       pr_warn("calc rate %d != OF spec %d\n",
+                               calc_freq, bus_freq);
+       } else {
+               calc_freq = bus_freq;   /* start with IPS */
+               calc_freq *= *ips_div;  /* IPS -> CSB */
+               calc_freq *= 2;         /* CSB -> SYS */
+               calc_freq *= *sys_div;  /* SYS -> PLL out */
+               calc_freq /= *sys_mul;  /* PLL out -> REF == OSC */
+               clks[MPC512x_CLK_REF] = mpc512x_clk_fixed("ref", calc_freq);
+       }
+}
+
+/*
+ * helper code for the MCLK subtree setup
+ *
+ * the overview in section 5.2.4 of the MPC5121e Reference Manual rev4
+ * suggests that all instances of the "PSC clock generation" are equal,
+ * and that one might re-use the PSC setup for MSCAN clock generation
+ * (section 5.2.5) as well, at least the logic if not the data for
+ * description
+ *
+ * the details (starting at page 5-20) show differences in the specific
+ * inputs of the first mux stage ("can clk in", "spdif tx"), and the
+ * factual non-availability of the second mux stage (it's present yet
+ * only one input is valid)
+ *
+ * the MSCAN clock related registers (starting at page 5-35) all
+ * reference "spdif clk" at the first mux stage and don't mention any
+ * "can clk" at all, which somehow is unexpected
+ *
+ * TODO re-check the document, and clarify whether the RM is correct in
+ * the overview or in the details, and whether the difference is a
+ * clipboard induced error or results from chip revisions
+ *
+ * it turns out that the RM rev4 as of 2012-06 talks about "can" for the
+ * PSCs while RM rev3 as of 2008-10 talks about "spdif", so I guess that
+ * first a doc update is required which better reflects reality in the
+ * SoC before the implementation should follow while no questions remain
+ */
+
+/*
+ * note that this declaration raises a checkpatch warning, but
+ * it's the very data type which <linux/clk-provider.h> expects,
+ * making this declaration pass checkpatch will break compilation
+ */
+static const char *parent_names_mux0[] = {
+       "sys", "ref", "psc-mclk-in", "spdif-tx",
+};
+
+enum mclk_type {
+       MCLK_TYPE_PSC,
+       MCLK_TYPE_MSCAN,
+       MCLK_TYPE_SPDIF,
+};
+
+struct mclk_setup_data {
+       enum mclk_type type;
+       bool has_mclk1;
+       const char *name_mux0;
+       const char *name_en0;
+       const char *name_div0;
+       const char *parent_names_mux1[2];
+       const char *name_mclk;
+};
+
+#define MCLK_SETUP_DATA_PSC(id) { \
+       MCLK_TYPE_PSC, 0, \
+       "psc" #id "-mux0", \
+       "psc" #id "-en0", \
+       "psc" #id "_mclk_div", \
+       { "psc" #id "_mclk_div", "dummy", }, \
+       "psc" #id "_mclk", \
+}
+
+#define MCLK_SETUP_DATA_MSCAN(id) { \
+       MCLK_TYPE_MSCAN, 0, \
+       "mscan" #id "-mux0", \
+       "mscan" #id "-en0", \
+       "mscan" #id "_mclk_div", \
+       { "mscan" #id "_mclk_div", "dummy", }, \
+       "mscan" #id "_mclk", \
+}
+
+#define MCLK_SETUP_DATA_SPDIF { \
+       MCLK_TYPE_SPDIF, 1, \
+       "spdif-mux0", \
+       "spdif-en0", \
+       "spdif_mclk_div", \
+       { "spdif_mclk_div", "spdif-rx", }, \
+       "spdif_mclk", \
+}
+
+static struct mclk_setup_data mclk_psc_data[] = {
+       MCLK_SETUP_DATA_PSC(0),
+       MCLK_SETUP_DATA_PSC(1),
+       MCLK_SETUP_DATA_PSC(2),
+       MCLK_SETUP_DATA_PSC(3),
+       MCLK_SETUP_DATA_PSC(4),
+       MCLK_SETUP_DATA_PSC(5),
+       MCLK_SETUP_DATA_PSC(6),
+       MCLK_SETUP_DATA_PSC(7),
+       MCLK_SETUP_DATA_PSC(8),
+       MCLK_SETUP_DATA_PSC(9),
+       MCLK_SETUP_DATA_PSC(10),
+       MCLK_SETUP_DATA_PSC(11),
+};
+
+static struct mclk_setup_data mclk_mscan_data[] = {
+       MCLK_SETUP_DATA_MSCAN(0),
+       MCLK_SETUP_DATA_MSCAN(1),
+       MCLK_SETUP_DATA_MSCAN(2),
+       MCLK_SETUP_DATA_MSCAN(3),
+};
+
+static struct mclk_setup_data mclk_spdif_data[] = {
+       MCLK_SETUP_DATA_SPDIF,
+};
+
+/* setup the MCLK clock subtree of an individual PSC/MSCAN/SPDIF */
+static void mpc512x_clk_setup_mclk(struct mclk_setup_data *entry, size_t idx)
+{
+       size_t clks_idx_pub, clks_idx_int;
+       u32 __iomem *mccr_reg;  /* MCLK control register (mux, en, div) */
+       int div;
+
+       /* derive a few parameters from the component type and index */
+       switch (entry->type) {
+       case MCLK_TYPE_PSC:
+               clks_idx_pub = MPC512x_CLK_PSC0_MCLK + idx;
+               clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+                            + (idx) * MCLK_MAX_IDX;
+               mccr_reg = &clkregs->psc_ccr[idx];
+               break;
+       case MCLK_TYPE_MSCAN:
+               clks_idx_pub = MPC512x_CLK_MSCAN0_MCLK + idx;
+               clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+                            + (NR_PSCS + idx) * MCLK_MAX_IDX;
+               mccr_reg = &clkregs->mscan_ccr[idx];
+               break;
+       case MCLK_TYPE_SPDIF:
+               clks_idx_pub = MPC512x_CLK_SPDIF_MCLK;
+               clks_idx_int = MPC512x_CLK_MCLKS_FIRST
+                            + (NR_PSCS + NR_MSCANS) * MCLK_MAX_IDX;
+               mccr_reg = &clkregs->spccr;
+               break;
+       default:
+               return;
+       }
+
+       /*
+        * this was grabbed from the PPC_CLOCK implementation, which
+        * enforced a specific MCLK divider while the clock was gated
+        * during setup (that's a documented hardware requirement)
+        *
+        * the PPC_CLOCK implementation might even have violated the
+        * "MCLK <= IPS" constraint, the fixed divider value of 1
+        * results in a divider of 2 and thus MCLK = SYS/2 which equals
+        * CSB which is greater than IPS; the serial port setup may have
+        * adjusted the divider which the clock setup might have left in
+        * an undesirable state
+        *
+        * initial setup is:
+        * - MCLK 0 from SYS
+        * - MCLK DIV such to not exceed the IPS clock
+        * - MCLK 0 enabled
+        * - MCLK 1 from MCLK DIV
+        */
+       div = clk_get_rate(clks[MPC512x_CLK_SYS]);
+       div /= clk_get_rate(clks[MPC512x_CLK_IPS]);
+       out_be32(mccr_reg, (0 << 16));
+       out_be32(mccr_reg, (0 << 16) | ((div - 1) << 17));
+       out_be32(mccr_reg, (1 << 16) | ((div - 1) << 17));
+
+       /*
+        * create the 'struct clk' items of the MCLK's clock subtree
+        *
+        * note that by design we always create all nodes and won't take
+        * shortcuts here, because
+        * - the "internal" MCLK_DIV and MCLK_OUT signal in turn are
+        *   selectable inputs to the CFM while those who "actually use"
+        *   the PSC/MSCAN/SPDIF (serial drivers et al) need the MCLK
+        *   for their bitrate
+        * - in the absence of "aliases" for clocks we need to create
+        *   individial 'struct clk' items for whatever might get
+        *   referenced or looked up, even if several of those items are
+        *   identical from the logical POV (their rate value)
+        * - for easier future maintenance and for better reflection of
+        *   the SoC's documentation, it appears appropriate to generate
+        *   clock items even for those muxers which actually are NOPs
+        *   (those with two inputs of which one is reserved)
+        */
+       clks[clks_idx_int + MCLK_IDX_MUX0] = mpc512x_clk_muxed(
+                       entry->name_mux0,
+                       &parent_names_mux0[0], ARRAY_SIZE(parent_names_mux0),
+                       mccr_reg, 14, 2);
+       clks[clks_idx_int + MCLK_IDX_EN0] = mpc512x_clk_gated(
+                       entry->name_en0, entry->name_mux0,
+                       mccr_reg, 16);
+       clks[clks_idx_int + MCLK_IDX_DIV0] = mpc512x_clk_divider(
+                       entry->name_div0,
+                       entry->name_en0, CLK_SET_RATE_GATE,
+                       mccr_reg, 17, 15, 0);
+       if (entry->has_mclk1) {
+               clks[clks_idx_pub] = mpc512x_clk_muxed(
+                               entry->name_mclk,
+                               &entry->parent_names_mux1[0],
+                               ARRAY_SIZE(entry->parent_names_mux1),
+                               mccr_reg, 7, 1);
+       } else {
+               clks[clks_idx_pub] = mpc512x_clk_factor(
+                               entry->name_mclk,
+                               entry->parent_names_mux1[0],
+                               1, 1);
+       }
+}
+
+static void mpc512x_clk_setup_clock_tree(struct device_node *np, int busfreq)
+{
+       int sys_mul, sys_div, ips_div;
+       int mul, div;
+       size_t mclk_idx;
+       int freq;
+
+       /*
+        * developer's notes:
+        * - consider whether to handle clocks which have both gates and
+        *   dividers via intermediates or by means of composites
+        * - fractional dividers appear to not map well to composites
+        *   since they can be seen as a fixed multiplier and an
+        *   adjustable divider, while composites can only combine at
+        *   most one of a mux, div, and gate each into one 'struct clk'
+        *   item
+        * - PSC/MSCAN/SPDIF clock generation OTOH already is very
+        *   specific and cannot get mapped to componsites (at least not
+        *   a single one, maybe two of them, but then some of these
+        *   intermediate clock signals get referenced elsewhere (e.g.
+        *   in the clock frequency measurement, CFM) and thus need
+        *   publicly available names
+        * - the current source layout appropriately reflects the
+        *   hardware setup, and it works, so it's questionable whether
+        *   further changes will result in big enough a benefit
+        */
+
+       /* regardless of whether XTAL/OSC exists, have REF created */
+       mpc512x_clk_setup_ref_clock(np, busfreq, &sys_mul, &sys_div, &ips_div);
+
+       /* now setup the REF -> SYS -> CSB -> IPS hierarchy */
+       clks[MPC512x_CLK_SYS] = mpc512x_clk_factor("sys", "ref",
+                                                  sys_mul, sys_div);
+       clks[MPC512x_CLK_CSB] = mpc512x_clk_factor("csb", "sys", 1, 2);
+       clks[MPC512x_CLK_IPS] = mpc512x_clk_divtable("ips", "csb",
+                                                    &clkregs->scfr1, 23, 3,
+                                                    divtab_2346);
+
+       /* now setup anything below SYS and CSB and IPS */
+       clks[MPC512x_CLK_DDR_UG] = mpc512x_clk_factor("ddr-ug", "sys", 1, 2);
+       clks[MPC512x_CLK_SDHC_x4] = mpc512x_clk_factor("sdhc-x4", "csb", 4, 1);
+       clks[MPC512x_CLK_SDHC_UG] = mpc512x_clk_divider("sdhc-ug", "sdhc-x4", 0,
+                                                       &clkregs->scfr2, 0, 8,
+                                                       CLK_DIVIDER_ONE_BASED);
+       clks[MPC512x_CLK_DIU_x4] = mpc512x_clk_factor("diu-x4", "csb", 4, 1);
+       clks[MPC512x_CLK_DIU_UG] = mpc512x_clk_divider("diu-ug", "diu-x4", 0,
+                                                      &clkregs->scfr1, 0, 8,
+                                                      CLK_DIVIDER_ONE_BASED);
+
+       /*
+        * the "power architecture PLL" was setup from data which was
+        * sampled from the reset config word, at this point in time the
+        * configuration can be considered fixed and read only (i.e. no
+        * longer adjustable, or no longer in need of adjustment), which
+        * is why we don't register a PLL here but assume fixed factors
+        */
+       mul = get_cpmf_mult_x2();
+       div = 2;        /* compensate for the fractional factor */
+       clks[MPC512x_CLK_E300] = mpc512x_clk_factor("e300", "csb", mul, div);
+
+       clks[MPC512x_CLK_MBX_BUS_UG] = mpc512x_clk_factor("mbx-bus-ug", "csb",
+                                                         1, 2);
+       clks[MPC512x_CLK_MBX_UG] = mpc512x_clk_divtable("mbx-ug", "mbx-bus-ug",
+                                                       &clkregs->scfr1, 14, 3,
+                                                       divtab_1234);
+       clks[MPC512x_CLK_MBX_3D_UG] = mpc512x_clk_factor("mbx-3d-ug", "mbx-ug",
+                                                        1, 1);
+       clks[MPC512x_CLK_PCI_UG] = mpc512x_clk_divtable("pci-ug", "csb",
+                                                       &clkregs->scfr1, 20, 3,
+                                                       divtab_2346);
+       clks[MPC512x_CLK_NFC_UG] = mpc512x_clk_divtable("nfc-ug", "ips",
+                                                       &clkregs->scfr1, 8, 3,
+                                                       divtab_1234);
+       clks[MPC512x_CLK_LPC_UG] = mpc512x_clk_divtable("lpc-ug", "ips",
+                                                       &clkregs->scfr1, 11, 3,
+                                                       divtab_1234);
+
+       clks[MPC512x_CLK_LPC] = mpc512x_clk_gated("lpc", "lpc-ug",
+                                                 &clkregs->sccr1, 30);
+       clks[MPC512x_CLK_NFC] = mpc512x_clk_gated("nfc", "nfc-ug",
+                                                 &clkregs->sccr1, 29);
+       clks[MPC512x_CLK_PATA] = mpc512x_clk_gated("pata", "ips",
+                                                  &clkregs->sccr1, 28);
+       /* for PSCs there is a "registers" gate and a bitrate MCLK subtree */
+       for (mclk_idx = 0; mclk_idx < ARRAY_SIZE(mclk_psc_data); mclk_idx++) {
+               char name[12];
+               snprintf(name, sizeof(name), "psc%d", mclk_idx);
+               clks[MPC512x_CLK_PSC0 + mclk_idx] = mpc512x_clk_gated(
+                               name, "ips", &clkregs->sccr1, 27 - mclk_idx);
+               mpc512x_clk_setup_mclk(&mclk_psc_data[mclk_idx], mclk_idx);
+       }
+       clks[MPC512x_CLK_PSC_FIFO] = mpc512x_clk_gated("psc-fifo", "ips",
+                                                      &clkregs->sccr1, 15);
+       clks[MPC512x_CLK_SATA] = mpc512x_clk_gated("sata", "ips",
+                                                  &clkregs->sccr1, 14);
+       clks[MPC512x_CLK_FEC] = mpc512x_clk_gated("fec", "ips",
+                                                 &clkregs->sccr1, 13);
+       clks[MPC512x_CLK_PCI] = mpc512x_clk_gated("pci", "pci-ug",
+                                                 &clkregs->sccr1, 11);
+       clks[MPC512x_CLK_DDR] = mpc512x_clk_gated("ddr", "ddr-ug",
+                                                 &clkregs->sccr1, 10);
+
+       clks[MPC512x_CLK_DIU] = mpc512x_clk_gated("diu", "diu-ug",
+                                                 &clkregs->sccr2, 31);
+       clks[MPC512x_CLK_AXE] = mpc512x_clk_gated("axe", "csb",
+                                                 &clkregs->sccr2, 30);
+       clks[MPC512x_CLK_MEM] = mpc512x_clk_gated("mem", "ips",
+                                                 &clkregs->sccr2, 29);
+       clks[MPC512x_CLK_USB1] = mpc512x_clk_gated("usb1", "csb",
+                                                  &clkregs->sccr2, 28);
+       clks[MPC512x_CLK_USB2] = mpc512x_clk_gated("usb2", "csb",
+                                                  &clkregs->sccr2, 27);
+       clks[MPC512x_CLK_I2C] = mpc512x_clk_gated("i2c", "ips",
+                                                 &clkregs->sccr2, 26);
+       /* MSCAN differs from PSC with just one gate for multiple components */
+       clks[MPC512x_CLK_BDLC] = mpc512x_clk_gated("bdlc", "ips",
+                                                  &clkregs->sccr2, 25);
+       for (mclk_idx = 0; mclk_idx < ARRAY_SIZE(mclk_mscan_data); mclk_idx++)
+               mpc512x_clk_setup_mclk(&mclk_mscan_data[mclk_idx], mclk_idx);
+       clks[MPC512x_CLK_SDHC] = mpc512x_clk_gated("sdhc", "sdhc-ug",
+                                                  &clkregs->sccr2, 24);
+       /* there is only one SPDIF component, which shares MCLK support code */
+       clks[MPC512x_CLK_SPDIF] = mpc512x_clk_gated("spdif", "ips",
+                                                   &clkregs->sccr2, 23);
+       mpc512x_clk_setup_mclk(&mclk_spdif_data[0], 0);
+       clks[MPC512x_CLK_MBX_BUS] = mpc512x_clk_gated("mbx-bus", "mbx-bus-ug",
+                                                     &clkregs->sccr2, 22);
+       clks[MPC512x_CLK_MBX] = mpc512x_clk_gated("mbx", "mbx-ug",
+                                                 &clkregs->sccr2, 21);
+       clks[MPC512x_CLK_MBX_3D] = mpc512x_clk_gated("mbx-3d", "mbx-3d-ug",
+                                                    &clkregs->sccr2, 20);
+       clks[MPC512x_CLK_IIM] = mpc512x_clk_gated("iim", "csb",
+                                                 &clkregs->sccr2, 19);
+       clks[MPC512x_CLK_VIU] = mpc512x_clk_gated("viu", "csb",
+                                                 &clkregs->sccr2, 18);
+       clks[MPC512x_CLK_SDHC_2] = mpc512x_clk_gated("sdhc-2", "sdhc-ug",
+                                                    &clkregs->sccr2, 17);
+
+       /*
+        * externally provided clocks (when implemented in hardware,
+        * device tree may specify values which otherwise were unknown)
+        */
+       freq = get_freq_from_dt("psc_mclk_in");
+       if (!freq)
+               freq = 25000000;
+       clks[MPC512x_CLK_PSC_MCLK_IN] = mpc512x_clk_fixed("psc_mclk_in", freq);
+       freq = get_freq_from_dt("spdif_tx_in");
+       clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_tx_in", freq);
+       freq = get_freq_from_dt("spdif_rx_in");
+       clks[MPC512x_CLK_SPDIF_TX_IN] = mpc512x_clk_fixed("spdif_rx_in", freq);
+
+       /* fixed frequency for AC97, always 24.567MHz */
+       clks[MPC512x_CLK_AC97] = mpc512x_clk_fixed("ac97", 24567000);
+
+       /*
+        * pre-enable those "internal" clock items which never get
+        * claimed by any peripheral driver, to not have the clock
+        * subsystem disable them late at startup
+        */
+       clk_prepare_enable(clks[MPC512x_CLK_DUMMY]);
+       clk_prepare_enable(clks[MPC512x_CLK_E300]);     /* PowerPC CPU */
+       clk_prepare_enable(clks[MPC512x_CLK_DDR]);      /* DRAM */
+       clk_prepare_enable(clks[MPC512x_CLK_MEM]);      /* SRAM */
+       clk_prepare_enable(clks[MPC512x_CLK_IPS]);      /* SoC periph */
+       clk_prepare_enable(clks[MPC512x_CLK_LPC]);      /* boot media */
+}
+
+/*
+ * registers the set of public clocks (those listed in the dt-bindings/
+ * header file) for OF lookups, keeps the intermediates private to us
+ */
+static void mpc5121_clk_register_of_provider(struct device_node *np)
+{
+       clk_data.clks = clks;
+       clk_data.clk_num = MPC512x_CLK_LAST_PUBLIC + 1; /* _not_ ARRAY_SIZE() */
+       of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+}
+
+/*
+ * temporary support for the period of time between introduction of CCF
+ * support and the adjustment of peripheral drivers to OF based lookups
+ */
+static void mpc5121_clk_provide_migration_support(void)
+{
+
+       /*
+        * pre-enable those clock items which are not yet appropriately
+        * acquired by their peripheral driver
+        *
+        * the PCI clock cannot get acquired by its peripheral driver,
+        * because for this platform the driver won't probe(), instead
+        * initialization is done from within the .setup_arch() routine
+        * at a point in time where the clock provider has not been
+        * setup yet and thus isn't available yet
+        *
+        * so we "pre-enable" the clock here, to not have the clock
+        * subsystem automatically disable this item in a late init call
+        *
+        * this PCI clock pre-enable workaround only applies when there
+        * are device tree nodes for PCI and thus the peripheral driver
+        * has attached to bridges, otherwise the PCI clock remains
+        * unused and so it gets disabled
+        */
+       clk_prepare_enable(clks[MPC512x_CLK_PSC3_MCLK]);/* serial console */
+       if (of_find_compatible_node(NULL, "pci", "fsl,mpc5121-pci"))
+               clk_prepare_enable(clks[MPC512x_CLK_PCI]);
+}
+
+/*
+ * those macros are not exactly pretty, but they encapsulate a lot
+ * of copy'n'paste heavy code which is even more ugly, and reduce
+ * the potential for inconsistencies in those many code copies
+ */
+#define FOR_NODES(compatname) \
+       for_each_compatible_node(np, NULL, compatname)
+
+#define NODE_PREP do { \
+       of_address_to_resource(np, 0, &res); \
+       snprintf(devname, sizeof(devname), "%08x.%s", res.start, np->name); \
+} while (0)
+
+#define NODE_CHK(clkname, clkitem, regnode, regflag) do { \
+       struct clk *clk; \
+       clk = of_clk_get_by_name(np, clkname); \
+       if (IS_ERR(clk)) { \
+               clk = clkitem; \
+               clk_register_clkdev(clk, clkname, devname); \
+               if (regnode) \
+                       clk_register_clkdev(clk, clkname, np->name); \
+               did_register |= DID_REG_ ## regflag; \
+               pr_debug("clock alias name '%s' for dev '%s' pointer %p\n", \
+                        clkname, devname, clk); \
+       } else { \
+               clk_put(clk); \
+       } \
+} while (0)
+
+/*
+ * register source code provided fallback results for clock lookups,
+ * these get consulted when OF based clock lookup fails (that is in the
+ * case of not yet adjusted device tree data, where clock related specs
+ * are missing)
+ */
+static void mpc5121_clk_provide_backwards_compat(void)
+{
+       enum did_reg_flags {
+               DID_REG_PSC     = BIT(0),
+               DID_REG_PSCFIFO = BIT(1),
+               DID_REG_NFC     = BIT(2),
+               DID_REG_CAN     = BIT(3),
+               DID_REG_I2C     = BIT(4),
+               DID_REG_DIU     = BIT(5),
+               DID_REG_VIU     = BIT(6),
+               DID_REG_FEC     = BIT(7),
+               DID_REG_USB     = BIT(8),
+               DID_REG_PATA    = BIT(9),
+       };
+
+       int did_register;
+       struct device_node *np;
+       struct resource res;
+       int idx;
+       char devname[32];
+
+       did_register = 0;
+
+       FOR_NODES(mpc512x_select_psc_compat()) {
+               NODE_PREP;
+               idx = (res.start >> 8) & 0xf;
+               NODE_CHK("ipg", clks[MPC512x_CLK_PSC0 + idx], 0, PSC);
+               NODE_CHK("mclk", clks[MPC512x_CLK_PSC0_MCLK + idx], 0, PSC);
+       }
+
+       FOR_NODES("fsl,mpc5121-psc-fifo") {
+               NODE_PREP;
+               NODE_CHK("ipg", clks[MPC512x_CLK_PSC_FIFO], 1, PSCFIFO);
+       }
+
+       FOR_NODES("fsl,mpc5121-nfc") {
+               NODE_PREP;
+               NODE_CHK("ipg", clks[MPC512x_CLK_NFC], 0, NFC);
+       }
+
+       FOR_NODES("fsl,mpc5121-mscan") {
+               NODE_PREP;
+               idx = 0;
+               idx += (res.start & 0x2000) ? 2 : 0;
+               idx += (res.start & 0x0080) ? 1 : 0;
+               NODE_CHK("ipg", clks[MPC512x_CLK_BDLC], 0, CAN);
+               NODE_CHK("mclk", clks[MPC512x_CLK_MSCAN0_MCLK + idx], 0, CAN);
+       }
+
+       /*
+        * do register the 'ips', 'sys', and 'ref' names globally
+        * instead of inside each individual CAN node, as there is no
+        * potential for a name conflict (in contrast to 'ipg' and 'mclk')
+        */
+       if (did_register & DID_REG_CAN) {
+               clk_register_clkdev(clks[MPC512x_CLK_IPS], "ips", NULL);
+               clk_register_clkdev(clks[MPC512x_CLK_SYS], "sys", NULL);
+               clk_register_clkdev(clks[MPC512x_CLK_REF], "ref", NULL);
+       }
+
+       FOR_NODES("fsl,mpc5121-i2c") {
+               NODE_PREP;
+               NODE_CHK("ipg", clks[MPC512x_CLK_I2C], 0, I2C);
+       }
+
+       /*
+        * workaround for the fact that the I2C driver does an "anonymous"
+        * lookup (NULL name spec, which yields the first clock spec) for
+        * which we cannot register an alias -- a _global_ 'ipg' alias that
+        * is not bound to any device name and returns the I2C clock item
+        * is not a good idea
+        *
+        * so we have the lookup in the peripheral driver fail, which is
+        * silent and non-fatal, and pre-enable the clock item here such
+        * that register access is possible
+        *
+        * see commit b3bfce2b "i2c: mpc: cleanup clock API use" for
+        * details, adjusting s/NULL/"ipg"/ in i2c-mpc.c would make this
+        * workaround obsolete
+        */
+       if (did_register & DID_REG_I2C)
+               clk_prepare_enable(clks[MPC512x_CLK_I2C]);
+
+       FOR_NODES("fsl,mpc5121-diu") {
+               NODE_PREP;
+               NODE_CHK("ipg", clks[MPC512x_CLK_DIU], 1, DIU);
+       }
+
+       FOR_NODES("fsl,mpc5121-viu") {
+               NODE_PREP;
+               NODE_CHK("ipg", clks[MPC512x_CLK_VIU], 0, VIU);
+       }
+
+       /*
+        * note that 2771399a "fs_enet: cleanup clock API use" did use the
+        * "per" string for the clock lookup in contrast to the "ipg" name
+        * which most other nodes are using -- this is not a fatal thing
+        * but just something to keep in mind when doing compatibility
+        * registration, it's a non-issue with up-to-date device tree data
+        */
+       FOR_NODES("fsl,mpc5121-fec") {
+               NODE_PREP;
+               NODE_CHK("per", clks[MPC512x_CLK_FEC], 0, FEC);
+       }
+       FOR_NODES("fsl,mpc5121-fec-mdio") {
+               NODE_PREP;
+               NODE_CHK("per", clks[MPC512x_CLK_FEC], 0, FEC);
+       }
+
+       FOR_NODES("fsl,mpc5121-usb2-dr") {
+               NODE_PREP;
+               idx = (res.start & 0x4000) ? 1 : 0;
+               NODE_CHK("ipg", clks[MPC512x_CLK_USB1 + idx], 0, USB);
+       }
+
+       FOR_NODES("fsl,mpc5121-pata") {
+               NODE_PREP;
+               NODE_CHK("ipg", clks[MPC512x_CLK_PATA], 0, PATA);
+       }
+
+       /*
+        * try to collapse diagnostics into a single line of output yet
+        * provide a full list of what is missing, to avoid noise in the
+        * absence of up-to-date device tree data -- backwards
+        * compatibility to old DTBs is a requirement, updates may be
+        * desirable or preferrable but are not at all mandatory
+        */
+       if (did_register) {
+               pr_notice("device tree lacks clock specs, adding fallbacks (0x%x,%s%s%s%s%s%s%s%s%s%s)\n",
+                         did_register,
+                         (did_register & DID_REG_PSC) ? " PSC" : "",
+                         (did_register & DID_REG_PSCFIFO) ? " PSCFIFO" : "",
+                         (did_register & DID_REG_NFC) ? " NFC" : "",
+                         (did_register & DID_REG_CAN) ? " CAN" : "",
+                         (did_register & DID_REG_I2C) ? " I2C" : "",
+                         (did_register & DID_REG_DIU) ? " DIU" : "",
+                         (did_register & DID_REG_VIU) ? " VIU" : "",
+                         (did_register & DID_REG_FEC) ? " FEC" : "",
+                         (did_register & DID_REG_USB) ? " USB" : "",
+                         (did_register & DID_REG_PATA) ? " PATA" : "");
+       } else {
+               pr_debug("device tree has clock specs, no fallbacks added\n");
+       }
+}
+
+int __init mpc5121_clk_init(void)
+{
+       struct device_node *clk_np;
+       int busfreq;
+
+       /* map the clock control registers */
+       clk_np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
+       if (!clk_np)
+               return -ENODEV;
+       clkregs = of_iomap(clk_np, 0);
+       WARN_ON(!clkregs);
+
+       /* invalidate all not yet registered clock slots */
+       mpc512x_clk_preset_data();
+
+       /*
+        * have the device tree scanned for "fixed-clock" nodes (which
+        * includes the oscillator node if the board's DT provides one)
+        */
+       of_clk_init(NULL);
+
+       /*
+        * add a dummy clock for those situations where a clock spec is
+        * required yet no real clock is involved
+        */
+       clks[MPC512x_CLK_DUMMY] = mpc512x_clk_fixed("dummy", 0);
+
+       /*
+        * have all the real nodes in the clock tree populated from REF
+        * down to all leaves, either starting from the OSC node or from
+        * a REF root that was created from the IPS bus clock input
+        */
+       busfreq = get_freq_from_dt("bus-frequency");
+       mpc512x_clk_setup_clock_tree(clk_np, busfreq);
+
+       /* register as an OF clock provider */
+       mpc5121_clk_register_of_provider(clk_np);
+
+       /*
+        * unbreak not yet adjusted peripheral drivers during migration
+        * towards fully operational common clock support, and allow
+        * operation in the absence of clock related device tree specs
+        */
+       mpc5121_clk_provide_migration_support();
+       mpc5121_clk_provide_backwards_compat();
+
+       return 0;
+}
diff --git a/arch/powerpc/platforms/512x/clock.c b/arch/powerpc/platforms/512x/clock.c
deleted file mode 100644 (file)
index fd8a376..0000000
+++ /dev/null
@@ -1,754 +0,0 @@
-/*
- * Copyright (C) 2007,2008 Freescale Semiconductor, Inc. All rights reserved.
- *
- * Author: John Rigby <jrigby@freescale.com>
- *
- * Implements the clk api defined in include/linux/clk.h
- *
- *    Original based on linux/arch/arm/mach-integrator/clock.c
- *
- *    Copyright (C) 2004 ARM Limited.
- *    Written by Deep Blue Solutions 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/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/clk.h>
-#include <linux/mutex.h>
-#include <linux/io.h>
-
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
-#include <asm/mpc5xxx.h>
-#include <asm/mpc5121.h>
-#include <asm/clk_interface.h>
-
-#include "mpc512x.h"
-
-#undef CLK_DEBUG
-
-static int clocks_initialized;
-
-#define CLK_HAS_RATE   0x1     /* has rate in MHz */
-#define CLK_HAS_CTRL   0x2     /* has control reg and bit */
-
-struct clk {
-       struct list_head node;
-       char name[32];
-       int flags;
-       struct device *dev;
-       unsigned long rate;
-       struct module *owner;
-       void (*calc) (struct clk *);
-       struct clk *parent;
-       int reg, bit;           /* CLK_HAS_CTRL */
-       int div_shift;          /* only used by generic_div_clk_calc */
-};
-
-static LIST_HEAD(clocks);
-static DEFINE_MUTEX(clocks_mutex);
-
-static struct clk *mpc5121_clk_get(struct device *dev, const char *id)
-{
-       struct clk *p, *clk = ERR_PTR(-ENOENT);
-       int dev_match;
-       int id_match;
-
-       if (dev == NULL || id == NULL)
-               return clk;
-
-       mutex_lock(&clocks_mutex);
-       list_for_each_entry(p, &clocks, node) {
-               dev_match = id_match = 0;
-
-               if (dev == p->dev)
-                       dev_match++;
-               if (strcmp(id, p->name) == 0)
-                       id_match++;
-               if ((dev_match || id_match) && try_module_get(p->owner)) {
-                       clk = p;
-                       break;
-               }
-       }
-       mutex_unlock(&clocks_mutex);
-
-       return clk;
-}
-
-#ifdef CLK_DEBUG
-static void dump_clocks(void)
-{
-       struct clk *p;
-
-       mutex_lock(&clocks_mutex);
-       printk(KERN_INFO "CLOCKS:\n");
-       list_for_each_entry(p, &clocks, node) {
-               pr_info("  %s=%ld", p->name, p->rate);
-               if (p->parent)
-                       pr_cont(" %s=%ld", p->parent->name,
-                              p->parent->rate);
-               if (p->flags & CLK_HAS_CTRL)
-                       pr_cont(" reg/bit=%d/%d", p->reg, p->bit);
-               pr_cont("\n");
-       }
-       mutex_unlock(&clocks_mutex);
-}
-#define        DEBUG_CLK_DUMP() dump_clocks()
-#else
-#define        DEBUG_CLK_DUMP()
-#endif
-
-
-static void mpc5121_clk_put(struct clk *clk)
-{
-       module_put(clk->owner);
-}
-
-#define NRPSC 12
-
-struct mpc512x_clockctl {
-       u32 spmr;               /* System PLL Mode Reg */
-       u32 sccr[2];            /* System Clk Ctrl Reg 1 & 2 */
-       u32 scfr1;              /* System Clk Freq Reg 1 */
-       u32 scfr2;              /* System Clk Freq Reg 2 */
-       u32 reserved;
-       u32 bcr;                /* Bread Crumb Reg */
-       u32 pccr[NRPSC];        /* PSC Clk Ctrl Reg 0-11 */
-       u32 spccr;              /* SPDIF Clk Ctrl Reg */
-       u32 cccr;               /* CFM Clk Ctrl Reg */
-       u32 dccr;               /* DIU Clk Cnfg Reg */
-};
-
-static struct mpc512x_clockctl __iomem *clockctl;
-
-static int mpc5121_clk_enable(struct clk *clk)
-{
-       unsigned int mask;
-
-       if (clk->flags & CLK_HAS_CTRL) {
-               mask = in_be32(&clockctl->sccr[clk->reg]);
-               mask |= 1 << clk->bit;
-               out_be32(&clockctl->sccr[clk->reg], mask);
-       }
-       return 0;
-}
-
-static void mpc5121_clk_disable(struct clk *clk)
-{
-       unsigned int mask;
-
-       if (clk->flags & CLK_HAS_CTRL) {
-               mask = in_be32(&clockctl->sccr[clk->reg]);
-               mask &= ~(1 << clk->bit);
-               out_be32(&clockctl->sccr[clk->reg], mask);
-       }
-}
-
-static unsigned long mpc5121_clk_get_rate(struct clk *clk)
-{
-       if (clk->flags & CLK_HAS_RATE)
-               return clk->rate;
-       else
-               return 0;
-}
-
-static long mpc5121_clk_round_rate(struct clk *clk, unsigned long rate)
-{
-       return rate;
-}
-
-static int mpc5121_clk_set_rate(struct clk *clk, unsigned long rate)
-{
-       return 0;
-}
-
-static int clk_register(struct clk *clk)
-{
-       mutex_lock(&clocks_mutex);
-       list_add(&clk->node, &clocks);
-       mutex_unlock(&clocks_mutex);
-       return 0;
-}
-
-static unsigned long spmf_mult(void)
-{
-       /*
-        * Convert spmf to multiplier
-        */
-       static int spmf_to_mult[] = {
-               68, 1, 12, 16,
-               20, 24, 28, 32,
-               36, 40, 44, 48,
-               52, 56, 60, 64
-       };
-       int spmf = (in_be32(&clockctl->spmr) >> 24) & 0xf;
-       return spmf_to_mult[spmf];
-}
-
-static unsigned long sysdiv_div_x_2(void)
-{
-       /*
-        * Convert sysdiv to divisor x 2
-        * Some divisors have fractional parts so
-        * multiply by 2 then divide by this value
-        */
-       static int sysdiv_to_div_x_2[] = {
-               4, 5, 6, 7,
-               8, 9, 10, 14,
-               12, 16, 18, 22,
-               20, 24, 26, 30,
-               28, 32, 34, 38,
-               36, 40, 42, 46,
-               44, 48, 50, 54,
-               52, 56, 58, 62,
-               60, 64, 66,
-       };
-       int sysdiv = (in_be32(&clockctl->scfr2) >> 26) & 0x3f;
-       return sysdiv_to_div_x_2[sysdiv];
-}
-
-static unsigned long ref_to_sys(unsigned long rate)
-{
-       rate *= spmf_mult();
-       rate *= 2;
-       rate /= sysdiv_div_x_2();
-
-       return rate;
-}
-
-static unsigned long sys_to_ref(unsigned long rate)
-{
-       rate *= sysdiv_div_x_2();
-       rate /= 2;
-       rate /= spmf_mult();
-
-       return rate;
-}
-
-static long ips_to_ref(unsigned long rate)
-{
-       int ips_div = (in_be32(&clockctl->scfr1) >> 23) & 0x7;
-
-       rate *= ips_div;        /* csb_clk = ips_clk * ips_div */
-       rate *= 2;              /* sys_clk = csb_clk * 2 */
-       return sys_to_ref(rate);
-}
-
-static unsigned long devtree_getfreq(char *clockname)
-{
-       struct device_node *np;
-       const unsigned int *prop;
-       unsigned int val = 0;
-
-       np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-immr");
-       if (np) {
-               prop = of_get_property(np, clockname, NULL);
-               if (prop)
-                       val = *prop;
-           of_node_put(np);
-       }
-       return val;
-}
-
-static void ref_clk_calc(struct clk *clk)
-{
-       unsigned long rate;
-
-       rate = devtree_getfreq("bus-frequency");
-       if (rate == 0) {
-               printk(KERN_ERR "No bus-frequency in dev tree\n");
-               clk->rate = 0;
-               return;
-       }
-       clk->rate = ips_to_ref(rate);
-}
-
-static struct clk ref_clk = {
-       .name = "ref_clk",
-       .calc = ref_clk_calc,
-};
-
-
-static void sys_clk_calc(struct clk *clk)
-{
-       clk->rate = ref_to_sys(ref_clk.rate);
-}
-
-static struct clk sys_clk = {
-       .name = "sys_clk",
-       .calc = sys_clk_calc,
-};
-
-static void diu_clk_calc(struct clk *clk)
-{
-       int diudiv_x_2 = in_be32(&clockctl->scfr1) & 0xff;
-       unsigned long rate;
-
-       rate = sys_clk.rate;
-
-       rate *= 2;
-       rate /= diudiv_x_2;
-
-       clk->rate = rate;
-}
-
-static void viu_clk_calc(struct clk *clk)
-{
-       unsigned long rate;
-
-       rate = sys_clk.rate;
-       rate /= 2;
-       clk->rate = rate;
-}
-
-static void half_clk_calc(struct clk *clk)
-{
-       clk->rate = clk->parent->rate / 2;
-}
-
-static void generic_div_clk_calc(struct clk *clk)
-{
-       int div = (in_be32(&clockctl->scfr1) >> clk->div_shift) & 0x7;
-
-       clk->rate = clk->parent->rate / div;
-}
-
-static void unity_clk_calc(struct clk *clk)
-{
-       clk->rate = clk->parent->rate;
-}
-
-static struct clk csb_clk = {
-       .name = "csb_clk",
-       .calc = half_clk_calc,
-       .parent = &sys_clk,
-};
-
-static void e300_clk_calc(struct clk *clk)
-{
-       int spmf = (in_be32(&clockctl->spmr) >> 16) & 0xf;
-       int ratex2 = clk->parent->rate * spmf;
-
-       clk->rate = ratex2 / 2;
-}
-
-static struct clk e300_clk = {
-       .name = "e300_clk",
-       .calc = e300_clk_calc,
-       .parent = &csb_clk,
-};
-
-static struct clk ips_clk = {
-       .name = "ips_clk",
-       .calc = generic_div_clk_calc,
-       .parent = &csb_clk,
-       .div_shift = 23,
-};
-
-/*
- * Clocks controlled by SCCR1 (.reg = 0)
- */
-static struct clk lpc_clk = {
-       .name = "lpc_clk",
-       .flags = CLK_HAS_CTRL,
-       .reg = 0,
-       .bit = 30,
-       .calc = generic_div_clk_calc,
-       .parent = &ips_clk,
-       .div_shift = 11,
-};
-
-static struct clk nfc_clk = {
-       .name = "nfc_clk",
-       .flags = CLK_HAS_CTRL,
-       .reg = 0,
-       .bit = 29,
-       .calc = generic_div_clk_calc,
-       .parent = &ips_clk,
-       .div_shift = 8,
-};
-
-static struct clk pata_clk = {
-       .name = "pata_clk",
-       .flags = CLK_HAS_CTRL,
-       .reg = 0,
-       .bit = 28,
-       .calc = unity_clk_calc,
-       .parent = &ips_clk,
-};
-
-/*
- * PSC clocks (bits 27 - 16)
- * are setup elsewhere
- */
-
-static struct clk sata_clk = {
-       .name = "sata_clk",
-       .flags = CLK_HAS_CTRL,
-       .reg = 0,
-       .bit = 14,
-       .calc = unity_clk_calc,
-       .parent = &ips_clk,
-};
-
-static struct clk fec_clk = {
-       .name = "fec_clk",
-       .flags = CLK_HAS_CTRL,
-       .reg = 0,
-       .bit = 13,
-       .calc = unity_clk_calc,
-       .parent = &ips_clk,
-};
-
-static struct clk pci_clk = {
-       .name = "pci_clk",
-       .flags = CLK_HAS_CTRL,
-       .reg = 0,
-       .bit = 11,
-       .calc = generic_div_clk_calc,
-       .parent = &csb_clk,
-       .div_shift = 20,
-};
-
-/*
- * Clocks controlled by SCCR2 (.reg = 1)
- */
-static struct clk diu_clk = {
-       .name = "diu_clk",
-       .flags = CLK_HAS_CTRL,
-       .reg = 1,
-       .bit = 31,
-       .calc = diu_clk_calc,
-};
-
-static struct clk viu_clk = {
-       .name = "viu_clk",
-       .flags = CLK_HAS_CTRL,
-       .reg = 1,
-       .bit = 18,
-       .calc = viu_clk_calc,
-};
-
-static struct clk axe_clk = {
-       .name = "axe_clk",
-       .flags = CLK_HAS_CTRL,
-       .reg = 1,
-       .bit = 30,
-       .calc = unity_clk_calc,
-       .parent = &csb_clk,
-};
-
-static struct clk usb1_clk = {
-       .name = "usb1_clk",
-       .flags = CLK_HAS_CTRL,
-       .reg = 1,
-       .bit = 28,
-       .calc = unity_clk_calc,
-       .parent = &csb_clk,
-};
-
-static struct clk usb2_clk = {
-       .name = "usb2_clk",
-       .flags = CLK_HAS_CTRL,
-       .reg = 1,
-       .bit = 27,
-       .calc = unity_clk_calc,
-       .parent = &csb_clk,
-};
-
-static struct clk i2c_clk = {
-       .name = "i2c_clk",
-       .flags = CLK_HAS_CTRL,
-       .reg = 1,
-       .bit = 26,
-       .calc = unity_clk_calc,
-       .parent = &ips_clk,
-};
-
-static struct clk mscan_clk = {
-       .name = "mscan_clk",
-       .flags = CLK_HAS_CTRL,
-       .reg = 1,
-       .bit = 25,
-       .calc = unity_clk_calc,
-       .parent = &ips_clk,
-};
-
-static struct clk sdhc_clk = {
-       .name = "sdhc_clk",
-       .flags = CLK_HAS_CTRL,
-       .reg = 1,
-       .bit = 24,
-       .calc = unity_clk_calc,
-       .parent = &ips_clk,
-};
-
-static struct clk mbx_bus_clk = {
-       .name = "mbx_bus_clk",
-       .flags = CLK_HAS_CTRL,
-       .reg = 1,
-       .bit = 22,
-       .calc = half_clk_calc,
-       .parent = &csb_clk,
-};
-
-static struct clk mbx_clk = {
-       .name = "mbx_clk",
-       .flags = CLK_HAS_CTRL,
-       .reg = 1,
-       .bit = 21,
-       .calc = unity_clk_calc,
-       .parent = &csb_clk,
-};
-
-static struct clk mbx_3d_clk = {
-       .name = "mbx_3d_clk",
-       .flags = CLK_HAS_CTRL,
-       .reg = 1,
-       .bit = 20,
-       .calc = generic_div_clk_calc,
-       .parent = &mbx_bus_clk,
-       .div_shift = 14,
-};
-
-static void psc_mclk_in_calc(struct clk *clk)
-{
-       clk->rate = devtree_getfreq("psc_mclk_in");
-       if (!clk->rate)
-               clk->rate = 25000000;
-}
-
-static struct clk psc_mclk_in = {
-       .name = "psc_mclk_in",
-       .calc = psc_mclk_in_calc,
-};
-
-static struct clk spdif_txclk = {
-       .name = "spdif_txclk",
-       .flags = CLK_HAS_CTRL,
-       .reg = 1,
-       .bit = 23,
-};
-
-static struct clk spdif_rxclk = {
-       .name = "spdif_rxclk",
-       .flags = CLK_HAS_CTRL,
-       .reg = 1,
-       .bit = 23,
-};
-
-static void ac97_clk_calc(struct clk *clk)
-{
-       /* ac97 bit clock is always 24.567 MHz */
-       clk->rate = 24567000;
-}
-
-static struct clk ac97_clk = {
-       .name = "ac97_clk_in",
-       .calc = ac97_clk_calc,
-};
-
-static struct clk *rate_clks[] = {
-       &ref_clk,
-       &sys_clk,
-       &diu_clk,
-       &viu_clk,
-       &csb_clk,
-       &e300_clk,
-       &ips_clk,
-       &fec_clk,
-       &sata_clk,
-       &pata_clk,
-       &nfc_clk,
-       &lpc_clk,
-       &mbx_bus_clk,
-       &mbx_clk,
-       &mbx_3d_clk,
-       &axe_clk,
-       &usb1_clk,
-       &usb2_clk,
-       &i2c_clk,
-       &mscan_clk,
-       &sdhc_clk,
-       &pci_clk,
-       &psc_mclk_in,
-       &spdif_txclk,
-       &spdif_rxclk,
-       &ac97_clk,
-       NULL
-};
-
-static void rate_clk_init(struct clk *clk)
-{
-       if (clk->calc) {
-               clk->calc(clk);
-               clk->flags |= CLK_HAS_RATE;
-               clk_register(clk);
-       } else {
-               printk(KERN_WARNING
-                      "Could not initialize clk %s without a calc routine\n",
-                      clk->name);
-       }
-}
-
-static void rate_clks_init(void)
-{
-       struct clk **cpp, *clk;
-
-       cpp = rate_clks;
-       while ((clk = *cpp++))
-               rate_clk_init(clk);
-}
-
-/*
- * There are two clk enable registers with 32 enable bits each
- * psc clocks and device clocks are all stored in dev_clks
- */
-static struct clk dev_clks[2][32];
-
-/*
- * Given a psc number return the dev_clk
- * associated with it
- */
-static struct clk *psc_dev_clk(int pscnum)
-{
-       int reg, bit;
-       struct clk *clk;
-
-       reg = 0;
-       bit = 27 - pscnum;
-
-       clk = &dev_clks[reg][bit];
-       clk->reg = 0;
-       clk->bit = bit;
-       return clk;
-}
-
-/*
- * PSC clock rate calculation
- */
-static void psc_calc_rate(struct clk *clk, int pscnum, struct device_node *np)
-{
-       unsigned long mclk_src = sys_clk.rate;
-       unsigned long mclk_div;
-
-       /*
-        * Can only change value of mclk divider
-        * when the divider is disabled.
-        *
-        * Zero is not a valid divider so minimum
-        * divider is 1
-        *
-        * disable/set divider/enable
-        */
-       out_be32(&clockctl->pccr[pscnum], 0);
-       out_be32(&clockctl->pccr[pscnum], 0x00020000);
-       out_be32(&clockctl->pccr[pscnum], 0x00030000);
-
-       if (in_be32(&clockctl->pccr[pscnum]) & 0x80) {
-               clk->rate = spdif_rxclk.rate;
-               return;
-       }
-
-       switch ((in_be32(&clockctl->pccr[pscnum]) >> 14) & 0x3) {
-       case 0:
-               mclk_src = sys_clk.rate;
-               break;
-       case 1:
-               mclk_src = ref_clk.rate;
-               break;
-       case 2:
-               mclk_src = psc_mclk_in.rate;
-               break;
-       case 3:
-               mclk_src = spdif_txclk.rate;
-               break;
-       }
-
-       mclk_div = ((in_be32(&clockctl->pccr[pscnum]) >> 17) & 0x7fff) + 1;
-       clk->rate = mclk_src / mclk_div;
-}
-
-/*
- * Find all psc nodes in device tree and assign a clock
- * with name "psc%d_mclk" and dev pointing at the device
- * returned from of_find_device_by_node
- */
-static void psc_clks_init(void)
-{
-       struct device_node *np;
-       struct platform_device *ofdev;
-       u32 reg;
-       const char *psc_compat;
-
-       psc_compat = mpc512x_select_psc_compat();
-       if (!psc_compat)
-               return;
-
-       for_each_compatible_node(np, NULL, psc_compat) {
-               if (!of_property_read_u32(np, "reg", &reg)) {
-                       int pscnum = (reg & 0xf00) >> 8;
-                       struct clk *clk = psc_dev_clk(pscnum);
-
-                       clk->flags = CLK_HAS_RATE | CLK_HAS_CTRL;
-                       ofdev = of_find_device_by_node(np);
-                       clk->dev = &ofdev->dev;
-                       /*
-                        * AC97 is special rate clock does
-                        * not go through normal path
-                        */
-                       if (of_device_is_compatible(np, "fsl,mpc5121-psc-ac97"))
-                               clk->rate = ac97_clk.rate;
-                       else
-                               psc_calc_rate(clk, pscnum, np);
-                       sprintf(clk->name, "psc%d_mclk", pscnum);
-                       clk_register(clk);
-                       clk_enable(clk);
-               }
-       }
-}
-
-static struct clk_interface mpc5121_clk_functions = {
-       .clk_get                = mpc5121_clk_get,
-       .clk_enable             = mpc5121_clk_enable,
-       .clk_disable            = mpc5121_clk_disable,
-       .clk_get_rate           = mpc5121_clk_get_rate,
-       .clk_put                = mpc5121_clk_put,
-       .clk_round_rate         = mpc5121_clk_round_rate,
-       .clk_set_rate           = mpc5121_clk_set_rate,
-       .clk_set_parent         = NULL,
-       .clk_get_parent         = NULL,
-};
-
-int __init mpc5121_clk_init(void)
-{
-       struct device_node *np;
-
-       np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
-       if (np) {
-               clockctl = of_iomap(np, 0);
-               of_node_put(np);
-       }
-
-       if (!clockctl) {
-               printk(KERN_ERR "Could not map clock control registers\n");
-               return 0;
-       }
-
-       rate_clks_init();
-       psc_clks_init();
-
-       /* leave clockctl mapped forever */
-       /*iounmap(clockctl); */
-       DEBUG_CLK_DUMP();
-       clocks_initialized++;
-       clk_functions = mpc5121_clk_functions;
-       return 0;
-}
index 36b5652aada200cc05fe7e12a99e84b989a9d434..adb95f03d4d4b20002992977120bd8a27073dc88 100644 (file)
@@ -12,6 +12,7 @@
  * (at your option) any later version.
  */
 
+#include <linux/clk.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/irq.h>
@@ -68,98 +69,112 @@ struct fsl_diu_shared_fb {
        bool            in_use;
 };
 
-#define DIU_DIV_MASK   0x000000ff
+/* receives a pixel clock spec in pico seconds, adjusts the DIU clock rate */
 static void mpc512x_set_pixel_clock(unsigned int pixclock)
 {
-       unsigned long bestval, bestfreq, speed, busfreq;
-       unsigned long minpixclock, maxpixclock, pixval;
-       struct mpc512x_ccm __iomem *ccm;
        struct device_node *np;
-       u32 temp;
-       long err;
-       int i;
+       struct clk *clk_diu;
+       unsigned long epsilon, minpixclock, maxpixclock;
+       unsigned long offset, want, got, delta;
 
-       np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock");
+       /* lookup and enable the DIU clock */
+       np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-diu");
        if (!np) {
-               pr_err("Can't find clock control module.\n");
+               pr_err("Could not find DIU device tree node.\n");
                return;
        }
-
-       ccm = of_iomap(np, 0);
+       clk_diu = of_clk_get(np, 0);
+       if (IS_ERR(clk_diu)) {
+               /* backwards compat with device trees that lack clock specs */
+               clk_diu = clk_get_sys(np->name, "ipg");
+       }
        of_node_put(np);
-       if (!ccm) {
-               pr_err("Can't map clock control module reg.\n");
+       if (IS_ERR(clk_diu)) {
+               pr_err("Could not lookup DIU clock.\n");
                return;
        }
-
-       np = of_find_node_by_type(NULL, "cpu");
-       if (np) {
-               const unsigned int *prop =
-                       of_get_property(np, "bus-frequency", NULL);
-
-               of_node_put(np);
-               if (prop) {
-                       busfreq = *prop;
-               } else {
-                       pr_err("Can't get bus-frequency property\n");
-                       return;
-               }
-       } else {
-               pr_err("Can't find 'cpu' node.\n");
+       if (clk_prepare_enable(clk_diu)) {
+               pr_err("Could not enable DIU clock.\n");
                return;
        }
 
-       /* Pixel Clock configuration */
-       pr_debug("DIU: Bus Frequency = %lu\n", busfreq);
-       speed = busfreq * 4; /* DIU_DIV ratio is 4 * CSB_CLK / DIU_CLK */
-
-       /* Calculate the pixel clock with the smallest error */
-       /* calculate the following in steps to avoid overflow */
-       pr_debug("DIU pixclock in ps - %d\n", pixclock);
-       temp = (1000000000 / pixclock) * 1000;
-       pixclock = temp;
-       pr_debug("DIU pixclock freq - %u\n", pixclock);
-
-       temp = temp / 20; /* pixclock * 0.05 */
-       pr_debug("deviation = %d\n", temp);
-       minpixclock = pixclock - temp;
-       maxpixclock = pixclock + temp;
-       pr_debug("DIU minpixclock - %lu\n", minpixclock);
-       pr_debug("DIU maxpixclock - %lu\n", maxpixclock);
-       pixval = speed/pixclock;
-       pr_debug("DIU pixval = %lu\n", pixval);
-
-       err = LONG_MAX;
-       bestval = pixval;
-       pr_debug("DIU bestval = %lu\n", bestval);
-
-       bestfreq = 0;
-       for (i = -1; i <= 1; i++) {
-               temp = speed / (pixval+i);
-               pr_debug("DIU test pixval i=%d, pixval=%lu, temp freq. = %u\n",
-                       i, pixval, temp);
-               if ((temp < minpixclock) || (temp > maxpixclock))
-                       pr_debug("DIU exceeds monitor range (%lu to %lu)\n",
-                               minpixclock, maxpixclock);
-               else if (abs(temp - pixclock) < err) {
-                       pr_debug("Entered the else if block %d\n", i);
-                       err = abs(temp - pixclock);
-                       bestval = pixval + i;
-                       bestfreq = temp;
-               }
+       /*
+        * convert the picoseconds spec into the desired clock rate,
+        * determine the acceptable clock range for the monitor (+/- 5%),
+        * do the calculation in steps to avoid integer overflow
+        */
+       pr_debug("DIU pixclock in ps - %u\n", pixclock);
+       pixclock = (1000000000 / pixclock) * 1000;
+       pr_debug("DIU pixclock freq  - %u\n", pixclock);
+       epsilon = pixclock / 20; /* pixclock * 0.05 */
+       pr_debug("DIU deviation      - %lu\n", epsilon);
+       minpixclock = pixclock - epsilon;
+       maxpixclock = pixclock + epsilon;
+       pr_debug("DIU minpixclock    - %lu\n", minpixclock);
+       pr_debug("DIU maxpixclock    - %lu\n", maxpixclock);
+
+       /*
+        * check whether the DIU supports the desired pixel clock
+        *
+        * - simply request the desired clock and see what the
+        *   platform's clock driver will make of it, assuming that it
+        *   will setup the best approximation of the requested value
+        * - try other candidate frequencies in the order of decreasing
+        *   preference (i.e. with increasing distance from the desired
+        *   pixel clock, and checking the lower frequency before the
+        *   higher frequency to not overload the hardware) until the
+        *   first match is found -- any potential subsequent match
+        *   would only be as good as the former match or typically
+        *   would be less preferrable
+        *
+        * the offset increment of pixelclock divided by 64 is an
+        * arbitrary choice -- it's simple to calculate, in the typical
+        * case we expect the first check to succeed already, in the
+        * worst case seven frequencies get tested (the exact center and
+        * three more values each to the left and to the right) before
+        * the 5% tolerance window is exceeded, resulting in fast enough
+        * execution yet high enough probability of finding a suitable
+        * value, while the error rate will be in the order of single
+        * percents
+        */
+       for (offset = 0; offset <= epsilon; offset += pixclock / 64) {
+               want = pixclock - offset;
+               pr_debug("DIU checking clock - %lu\n", want);
+               clk_set_rate(clk_diu, want);
+               got = clk_get_rate(clk_diu);
+               delta = abs(pixclock - got);
+               if (delta < epsilon)
+                       break;
+               if (!offset)
+                       continue;
+               want = pixclock + offset;
+               pr_debug("DIU checking clock - %lu\n", want);
+               clk_set_rate(clk_diu, want);
+               got = clk_get_rate(clk_diu);
+               delta = abs(pixclock - got);
+               if (delta < epsilon)
+                       break;
        }
+       if (offset <= epsilon) {
+               pr_debug("DIU clock accepted - %lu\n", want);
+               pr_debug("DIU pixclock want %u, got %lu, delta %lu, eps %lu\n",
+                        pixclock, got, delta, epsilon);
+               return;
+       }
+       pr_warn("DIU pixclock auto search unsuccessful\n");
 
-       pr_debug("DIU chose = %lx\n", bestval);
-       pr_debug("DIU error = %ld\n NomPixClk ", err);
-       pr_debug("DIU: Best Freq = %lx\n", bestfreq);
-       /* Modify DIU_DIV in CCM SCFR1 */
-       temp = in_be32(&ccm->scfr1);
-       pr_debug("DIU: Current value of SCFR1: 0x%08x\n", temp);
-       temp &= ~DIU_DIV_MASK;
-       temp |= (bestval & DIU_DIV_MASK);
-       out_be32(&ccm->scfr1, temp);
-       pr_debug("DIU: Modified value of SCFR1: 0x%08x\n", temp);
-       iounmap(ccm);
+       /*
+        * what is the most appropriate action to take when the search
+        * for an available pixel clock which is acceptable to the
+        * monitor has failed?  disable the DIU (clock) or just provide
+        * a "best effort"?  we go with the latter
+        */
+       pr_warn("DIU pixclock best effort fallback (backend's choice)\n");
+       clk_set_rate(clk_diu, pixclock);
+       got = clk_get_rate(clk_diu);
+       delta = abs(pixclock - got);
+       pr_debug("DIU pixclock want %u, got %lu, delta %lu, eps %lu\n",
+                pixclock, got, delta, epsilon);
 }
 
 static enum fsl_diu_monitor_port
index af54174801f7aa9042f12487e5fe94530f8d089a..b625a2c6f4f27b5ba77dfd9e9c8ccf1a9cf66c23 100644 (file)
@@ -1,7 +1,7 @@
 config PPC_MPC52xx
        bool "52xx-based boards"
        depends on 6xx
-       select PPC_CLOCK
+       select COMMON_CLK
        select PPC_PCI_CHOICE
 
 config PPC_MPC5200_SIMPLE
index bca2465a9c347ad65f3617a7a51f2e4f2a73034a..434fda39bf8b51f219098f207ce9cf35760fd484 100644 (file)
@@ -72,6 +72,7 @@ config PPC_BOOK3S_64
        select PPC_HAVE_PMU_SUPPORT
        select SYS_SUPPORTS_HUGETLBFS
        select HAVE_ARCH_TRANSPARENT_HUGEPAGE if PPC_64K_PAGES
+       select ARCH_SUPPORTS_NUMA_BALANCING
 
 config PPC_BOOK3E_64
        bool "Embedded processors"
index c34ee4e608734f387a0e43ed87abc1ba27e6dd27..d4d245c0d78799a6f48e65aae52560b75daac6e7 100644 (file)
@@ -111,7 +111,7 @@ static long beat_lpar_hpte_insert(unsigned long hpte_group,
                DBG_LOW(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r);
 
        if (rflags & _PAGE_NO_CACHE)
-               hpte_r &= ~_PAGE_COHERENT;
+               hpte_r &= ~HPTE_R_M;
 
        raw_spin_lock(&beat_htab_lock);
        lpar_rc = beat_read_mask(hpte_group);
@@ -337,7 +337,7 @@ static long beat_lpar_hpte_insert_v3(unsigned long hpte_group,
                DBG_LOW(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r);
 
        if (rflags & _PAGE_NO_CACHE)
-               hpte_r &= ~_PAGE_COHERENT;
+               hpte_r &= ~HPTE_R_M;
 
        /* insert into not-volted entry */
        lpar_rc = beat_insert_htab_entry3(0, hpte_group, hpte_v, hpte_r,
index 9fced3f6d2dcfadbf0f26c71d57693d79b1c78ba..895e8a20a3fc064069d49d4b4cc1280b05df4e87 100644 (file)
@@ -13,11 +13,6 @@ config PPC_POWERNV
        select ARCH_RANDOM
        default y
 
-config POWERNV_MSI
-       bool "Support PCI MSI on PowerNV platform"
-       depends on PCI_MSI
-       default y
-
 config PPC_POWERNV_RTAS
        depends on PPC_POWERNV
        bool "Support for RTAS based PowerNV platforms such as BML"
index 873fa1370dc44c1b0b3994e7555c4fac450adcbd..8d767fde5a6ac32484bf106698d8c43e1292cd73 100644 (file)
@@ -6,3 +6,4 @@ obj-$(CONFIG_SMP)       += smp.o
 obj-$(CONFIG_PCI)      += pci.o pci-p5ioc2.o pci-ioda.o
 obj-$(CONFIG_EEH)      += eeh-ioda.o eeh-powernv.o
 obj-$(CONFIG_PPC_SCOM) += opal-xscom.o
+obj-$(CONFIG_MEMORY_FAILURE)   += opal-memory-errors.o
index 02245cee78183852d52f3a907023dcd9a63529bf..31320c641c92ca139c33815cd99e3c8b48bd54e1 100644 (file)
@@ -588,11 +588,8 @@ static int ioda_eeh_get_log(struct eeh_pe *pe, int severity,
                return -EIO;
        }
 
-       /*
-        * FIXME: We probably need log the error in somewhere.
-        * Lets make it up in future.
-        */
-       /* pr_info("%s", phb->diag.blob); */
+       /* The PHB diag-data is always indicative */
+       pnv_pci_dump_phb_diag_data(hose, phb->diag.blob);
 
        spin_unlock_irqrestore(&phb->lock, flags);
 
@@ -681,164 +678,20 @@ static void ioda_eeh_hub_diag(struct pci_controller *hose)
        }
 }
 
-static void ioda_eeh_p7ioc_phb_diag(struct pci_controller *hose,
-                                   struct OpalIoPhbErrorCommon *common)
-{
-       struct OpalIoP7IOCPhbErrorData *data;
-       int i;
-
-       data = (struct OpalIoP7IOCPhbErrorData *)common;
-
-       pr_info("P7IOC PHB#%x Diag-data (Version: %d)\n\n",
-               hose->global_number, common->version);
-
-       pr_info("  brdgCtl:              %08x\n", data->brdgCtl);
-
-       pr_info("  portStatusReg:        %08x\n", data->portStatusReg);
-       pr_info("  rootCmplxStatus:      %08x\n", data->rootCmplxStatus);
-       pr_info("  busAgentStatus:       %08x\n", data->busAgentStatus);
-
-       pr_info("  deviceStatus:         %08x\n", data->deviceStatus);
-       pr_info("  slotStatus:           %08x\n", data->slotStatus);
-       pr_info("  linkStatus:           %08x\n", data->linkStatus);
-       pr_info("  devCmdStatus:         %08x\n", data->devCmdStatus);
-       pr_info("  devSecStatus:         %08x\n", data->devSecStatus);
-
-       pr_info("  rootErrorStatus:      %08x\n", data->rootErrorStatus);
-       pr_info("  uncorrErrorStatus:    %08x\n", data->uncorrErrorStatus);
-       pr_info("  corrErrorStatus:      %08x\n", data->corrErrorStatus);
-       pr_info("  tlpHdr1:              %08x\n", data->tlpHdr1);
-       pr_info("  tlpHdr2:              %08x\n", data->tlpHdr2);
-       pr_info("  tlpHdr3:              %08x\n", data->tlpHdr3);
-       pr_info("  tlpHdr4:              %08x\n", data->tlpHdr4);
-       pr_info("  sourceId:             %08x\n", data->sourceId);
-
-       pr_info("  errorClass:           %016llx\n", data->errorClass);
-       pr_info("  correlator:           %016llx\n", data->correlator);
-       pr_info("  p7iocPlssr:           %016llx\n", data->p7iocPlssr);
-       pr_info("  p7iocCsr:             %016llx\n", data->p7iocCsr);
-       pr_info("  lemFir:               %016llx\n", data->lemFir);
-       pr_info("  lemErrorMask:         %016llx\n", data->lemErrorMask);
-       pr_info("  lemWOF:               %016llx\n", data->lemWOF);
-       pr_info("  phbErrorStatus:       %016llx\n", data->phbErrorStatus);
-       pr_info("  phbFirstErrorStatus:  %016llx\n", data->phbFirstErrorStatus);
-       pr_info("  phbErrorLog0:         %016llx\n", data->phbErrorLog0);
-       pr_info("  phbErrorLog1:         %016llx\n", data->phbErrorLog1);
-       pr_info("  mmioErrorStatus:      %016llx\n", data->mmioErrorStatus);
-       pr_info("  mmioFirstErrorStatus: %016llx\n", data->mmioFirstErrorStatus);
-       pr_info("  mmioErrorLog0:        %016llx\n", data->mmioErrorLog0);
-       pr_info("  mmioErrorLog1:        %016llx\n", data->mmioErrorLog1);
-       pr_info("  dma0ErrorStatus:      %016llx\n", data->dma0ErrorStatus);
-       pr_info("  dma0FirstErrorStatus: %016llx\n", data->dma0FirstErrorStatus);
-       pr_info("  dma0ErrorLog0:        %016llx\n", data->dma0ErrorLog0);
-       pr_info("  dma0ErrorLog1:        %016llx\n", data->dma0ErrorLog1);
-       pr_info("  dma1ErrorStatus:      %016llx\n", data->dma1ErrorStatus);
-       pr_info("  dma1FirstErrorStatus: %016llx\n", data->dma1FirstErrorStatus);
-       pr_info("  dma1ErrorLog0:        %016llx\n", data->dma1ErrorLog0);
-       pr_info("  dma1ErrorLog1:        %016llx\n", data->dma1ErrorLog1);
-
-       for (i = 0; i < OPAL_P7IOC_NUM_PEST_REGS; i++) {
-               if ((data->pestA[i] >> 63) == 0 &&
-                   (data->pestB[i] >> 63) == 0)
-                       continue;
-
-               pr_info("  PE[%3d] PESTA:        %016llx\n", i, data->pestA[i]);
-               pr_info("          PESTB:        %016llx\n", data->pestB[i]);
-       }
-}
-
-static void ioda_eeh_phb3_phb_diag(struct pci_controller *hose,
-                                   struct OpalIoPhbErrorCommon *common)
-{
-       struct OpalIoPhb3ErrorData *data;
-       int i;
-
-       data = (struct OpalIoPhb3ErrorData*)common;
-       pr_info("PHB3 PHB#%x Diag-data (Version: %d)\n\n",
-               hose->global_number, common->version);
-
-       pr_info("  brdgCtl:              %08x\n", data->brdgCtl);
-
-       pr_info("  portStatusReg:        %08x\n", data->portStatusReg);
-       pr_info("  rootCmplxStatus:      %08x\n", data->rootCmplxStatus);
-       pr_info("  busAgentStatus:       %08x\n", data->busAgentStatus);
-
-       pr_info("  deviceStatus:         %08x\n", data->deviceStatus);
-       pr_info("  slotStatus:           %08x\n", data->slotStatus);
-       pr_info("  linkStatus:           %08x\n", data->linkStatus);
-       pr_info("  devCmdStatus:         %08x\n", data->devCmdStatus);
-       pr_info("  devSecStatus:         %08x\n", data->devSecStatus);
-
-       pr_info("  rootErrorStatus:      %08x\n", data->rootErrorStatus);
-       pr_info("  uncorrErrorStatus:    %08x\n", data->uncorrErrorStatus);
-       pr_info("  corrErrorStatus:      %08x\n", data->corrErrorStatus);
-       pr_info("  tlpHdr1:              %08x\n", data->tlpHdr1);
-       pr_info("  tlpHdr2:              %08x\n", data->tlpHdr2);
-       pr_info("  tlpHdr3:              %08x\n", data->tlpHdr3);
-       pr_info("  tlpHdr4:              %08x\n", data->tlpHdr4);
-       pr_info("  sourceId:             %08x\n", data->sourceId);
-       pr_info("  errorClass:           %016llx\n", data->errorClass);
-       pr_info("  correlator:           %016llx\n", data->correlator);
-       pr_info("  nFir:                 %016llx\n", data->nFir);
-       pr_info("  nFirMask:             %016llx\n", data->nFirMask);
-       pr_info("  nFirWOF:              %016llx\n", data->nFirWOF);
-       pr_info("  PhbPlssr:             %016llx\n", data->phbPlssr);
-       pr_info("  PhbCsr:               %016llx\n", data->phbCsr);
-       pr_info("  lemFir:               %016llx\n", data->lemFir);
-       pr_info("  lemErrorMask:         %016llx\n", data->lemErrorMask);
-       pr_info("  lemWOF:               %016llx\n", data->lemWOF);
-       pr_info("  phbErrorStatus:       %016llx\n", data->phbErrorStatus);
-       pr_info("  phbFirstErrorStatus:  %016llx\n", data->phbFirstErrorStatus);
-       pr_info("  phbErrorLog0:         %016llx\n", data->phbErrorLog0);
-       pr_info("  phbErrorLog1:         %016llx\n", data->phbErrorLog1);
-       pr_info("  mmioErrorStatus:      %016llx\n", data->mmioErrorStatus);
-       pr_info("  mmioFirstErrorStatus: %016llx\n", data->mmioFirstErrorStatus);
-       pr_info("  mmioErrorLog0:        %016llx\n", data->mmioErrorLog0);
-       pr_info("  mmioErrorLog1:        %016llx\n", data->mmioErrorLog1);
-       pr_info("  dma0ErrorStatus:      %016llx\n", data->dma0ErrorStatus);
-       pr_info("  dma0FirstErrorStatus: %016llx\n", data->dma0FirstErrorStatus);
-       pr_info("  dma0ErrorLog0:        %016llx\n", data->dma0ErrorLog0);
-       pr_info("  dma0ErrorLog1:        %016llx\n", data->dma0ErrorLog1);
-       pr_info("  dma1ErrorStatus:      %016llx\n", data->dma1ErrorStatus);
-       pr_info("  dma1FirstErrorStatus: %016llx\n", data->dma1FirstErrorStatus);
-       pr_info("  dma1ErrorLog0:        %016llx\n", data->dma1ErrorLog0);
-       pr_info("  dma1ErrorLog1:        %016llx\n", data->dma1ErrorLog1);
-
-       for (i = 0; i < OPAL_PHB3_NUM_PEST_REGS; i++) {
-               if ((data->pestA[i] >> 63) == 0 &&
-                   (data->pestB[i] >> 63) == 0)
-                       continue;
-
-               pr_info("  PE[%3d] PESTA:        %016llx\n", i, data->pestA[i]);
-               pr_info("          PESTB:        %016llx\n", data->pestB[i]);
-       }
-}
-
 static void ioda_eeh_phb_diag(struct pci_controller *hose)
 {
        struct pnv_phb *phb = hose->private_data;
-       struct OpalIoPhbErrorCommon *common;
        long rc;
 
-       common = (struct OpalIoPhbErrorCommon *)phb->diag.blob;
-       rc = opal_pci_get_phb_diag_data2(phb->opal_id, common, PAGE_SIZE);
+       rc = opal_pci_get_phb_diag_data2(phb->opal_id, phb->diag.blob,
+                                        PNV_PCI_DIAG_BUF_SIZE);
        if (rc != OPAL_SUCCESS) {
                pr_warning("%s: Failed to get diag-data for PHB#%x (%ld)\n",
                            __func__, hose->global_number, rc);
                return;
        }
 
-       switch (common->ioType) {
-       case OPAL_PHB_ERROR_DATA_TYPE_P7IOC:
-               ioda_eeh_p7ioc_phb_diag(hose, common);
-               break;
-       case OPAL_PHB_ERROR_DATA_TYPE_PHB3:
-               ioda_eeh_phb3_phb_diag(hose, common);
-               break;
-       default:
-               pr_warning("%s: Unrecognized I/O chip %d\n",
-                          __func__, common->ioType);
-       }
+       pnv_pci_dump_phb_diag_data(hose, phb->diag.blob);
 }
 
 static int ioda_eeh_get_phb_pe(struct pci_controller *hose,
index 6ffa6b1ec5b784e2dcfbb3ee555acbd22b5c8526..4aeae4f36e1d718f865a0722194fc7991acec778 100644 (file)
@@ -103,27 +103,6 @@ struct image_header_t {
        uint32_t        size;
 };
 
-/* Scatter/gather entry */
-struct opal_sg_entry {
-       void    *data;
-       long    length;
-};
-
-/* We calculate number of entries based on PAGE_SIZE */
-#define SG_ENTRIES_PER_NODE ((PAGE_SIZE - 16) / sizeof(struct opal_sg_entry))
-
-/*
- * This struct is very similar but not identical to that
- * needed by the opal flash update. All we need to do for
- * opal is rewrite num_entries into a version/length and
- * translate the pointers to absolute.
- */
-struct opal_sg_list {
-       unsigned long num_entries;
-       struct opal_sg_list *next;
-       struct opal_sg_entry entry[SG_ENTRIES_PER_NODE];
-};
-
 struct validate_flash_t {
        int             status;         /* Return status */
        void            *buf;           /* Candiate image buffer */
@@ -333,7 +312,7 @@ static struct opal_sg_list *image_data_to_sglist(void)
        addr = image_data.data;
        size = image_data.size;
 
-       sg1 = kzalloc((sizeof(struct opal_sg_list)), GFP_KERNEL);
+       sg1 = kzalloc(PAGE_SIZE, GFP_KERNEL);
        if (!sg1)
                return NULL;
 
@@ -351,8 +330,7 @@ static struct opal_sg_list *image_data_to_sglist(void)
 
                sg1->num_entries++;
                if (sg1->num_entries >= SG_ENTRIES_PER_NODE) {
-                       sg1->next = kzalloc((sizeof(struct opal_sg_list)),
-                                           GFP_KERNEL);
+                       sg1->next = kzalloc(PAGE_SIZE, GFP_KERNEL);
                        if (!sg1->next) {
                                pr_err("%s : Failed to allocate memory\n",
                                       __func__);
@@ -402,7 +380,10 @@ static int opal_flash_update(int op)
                else
                        sg->next = NULL;
 
-               /* Make num_entries into the version/length field */
+               /*
+                * Convert num_entries to version/length format
+                * to satisfy OPAL.
+                */
                sg->num_entries = (SG_LIST_VERSION << 56) |
                        (sg->num_entries * sizeof(struct opal_sg_entry) + 16);
        }
diff --git a/arch/powerpc/platforms/powernv/opal-memory-errors.c b/arch/powerpc/platforms/powernv/opal-memory-errors.c
new file mode 100644 (file)
index 0000000..ec41322
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * OPAL asynchronus Memory error handling support in PowreNV.
+ *
+ * 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 2013 IBM Corporation
+ * Author: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
+ */
+
+#undef DEBUG
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+
+#include <asm/opal.h>
+#include <asm/cputable.h>
+
+static int opal_mem_err_nb_init;
+static LIST_HEAD(opal_memory_err_list);
+static DEFINE_SPINLOCK(opal_mem_err_lock);
+
+struct OpalMsgNode {
+       struct list_head list;
+       struct opal_msg msg;
+};
+
+static void handle_memory_error_event(struct OpalMemoryErrorData *merr_evt)
+{
+       uint64_t paddr_start, paddr_end;
+
+       pr_debug("%s: Retrived memory error event, type: 0x%x\n",
+                 __func__, merr_evt->type);
+       switch (merr_evt->type) {
+       case OPAL_MEM_ERR_TYPE_RESILIENCE:
+               paddr_start = merr_evt->u.resilience.physical_address_start;
+               paddr_end = merr_evt->u.resilience.physical_address_end;
+               break;
+       case OPAL_MEM_ERR_TYPE_DYN_DALLOC:
+               paddr_start = merr_evt->u.dyn_dealloc.physical_address_start;
+               paddr_end = merr_evt->u.dyn_dealloc.physical_address_end;
+               break;
+       default:
+               return;
+       }
+
+       for (; paddr_start < paddr_end; paddr_start += PAGE_SIZE) {
+               memory_failure(paddr_start >> PAGE_SHIFT, 0, 0);
+       }
+}
+
+static void handle_memory_error(void)
+{
+       unsigned long flags;
+       struct OpalMemoryErrorData *merr_evt;
+       struct OpalMsgNode *msg_node;
+
+       spin_lock_irqsave(&opal_mem_err_lock, flags);
+       while (!list_empty(&opal_memory_err_list)) {
+                msg_node = list_entry(opal_memory_err_list.next,
+                                          struct OpalMsgNode, list);
+               list_del(&msg_node->list);
+               spin_unlock_irqrestore(&opal_mem_err_lock, flags);
+
+               merr_evt = (struct OpalMemoryErrorData *)
+                                       &msg_node->msg.params[0];
+               handle_memory_error_event(merr_evt);
+               kfree(msg_node);
+               spin_lock_irqsave(&opal_mem_err_lock, flags);
+       }
+       spin_unlock_irqrestore(&opal_mem_err_lock, flags);
+}
+
+static void mem_error_handler(struct work_struct *work)
+{
+       handle_memory_error();
+}
+
+static DECLARE_WORK(mem_error_work, mem_error_handler);
+
+/*
+ * opal_memory_err_event - notifier handler that queues up the opal message
+ * to be preocessed later.
+ */
+static int opal_memory_err_event(struct notifier_block *nb,
+                         unsigned long msg_type, void *msg)
+{
+       unsigned long flags;
+       struct OpalMsgNode *msg_node;
+
+       if (msg_type != OPAL_MSG_MEM_ERR)
+               return 0;
+
+       msg_node = kzalloc(sizeof(*msg_node), GFP_ATOMIC);
+       if (!msg_node) {
+               pr_err("MEMORY_ERROR: out of memory, Opal message event not"
+                      "handled\n");
+               return -ENOMEM;
+       }
+       memcpy(&msg_node->msg, msg, sizeof(struct opal_msg));
+
+       spin_lock_irqsave(&opal_mem_err_lock, flags);
+       list_add(&msg_node->list, &opal_memory_err_list);
+       spin_unlock_irqrestore(&opal_mem_err_lock, flags);
+
+       schedule_work(&mem_error_work);
+       return 0;
+}
+
+static struct notifier_block opal_mem_err_nb = {
+       .notifier_call  = opal_memory_err_event,
+       .next           = NULL,
+       .priority       = 0,
+};
+
+static int __init opal_mem_err_init(void)
+{
+       int ret;
+
+       if (!opal_mem_err_nb_init) {
+               ret = opal_message_notifier_register(
+                                       OPAL_MSG_MEM_ERR, &opal_mem_err_nb);
+               if (ret) {
+                       pr_err("%s: Can't register OPAL event notifier (%d)\n",
+                              __func__, ret);
+                       return ret;
+               }
+               opal_mem_err_nb_init = 1;
+       }
+       return 0;
+}
+subsys_initcall(opal_mem_err_init);
index 7d07c7e80ec09e9232b3cafd9c41a104992b5331..b1885db8fdf34bfe068f1712d486f6884dc50d0e 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <asm/opal.h>
 #include <asm/firmware.h>
+#include <asm/machdep.h>
 
 static void opal_to_tm(u32 y_m_d, u64 h_m_s_ms, struct rtc_time *tm)
 {
@@ -48,8 +49,11 @@ unsigned long __init opal_get_boot_time(void)
                else
                        mdelay(10);
        }
-       if (rc != OPAL_SUCCESS)
+       if (rc != OPAL_SUCCESS) {
+               ppc_md.get_rtc_time = NULL;
+               ppc_md.set_rtc_time = NULL;
                return 0;
+       }
        y_m_d = be32_to_cpu(__y_m_d);
        h_m_s_ms = be64_to_cpu(__h_m_s_ms);
        opal_to_tm(y_m_d, h_m_s_ms, &tm);
index e7806504e9769162f921e704cf55d0b3e210cf6c..719aa5c325c65121c9a826a3cefc3e59ec014f47 100644 (file)
@@ -126,3 +126,5 @@ OPAL_CALL(opal_return_cpu,                  OPAL_RETURN_CPU);
 OPAL_CALL(opal_validate_flash,                 OPAL_FLASH_VALIDATE);
 OPAL_CALL(opal_manage_flash,                   OPAL_FLASH_MANAGE);
 OPAL_CALL(opal_update_flash,                   OPAL_FLASH_UPDATE);
+OPAL_CALL(opal_get_msg,                                OPAL_GET_MSG);
+OPAL_CALL(opal_check_completion,               OPAL_CHECK_ASYNC_COMPLETION);
index 1c798cd553722f6f043a066c299100be89c10f96..7a184a0ff18371c717ed705d2a2f021b65eec8f3 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/notifier.h>
 #include <linux/slab.h>
+#include <linux/sched.h>
 #include <linux/kobject.h>
 #include <asm/opal.h>
 #include <asm/firmware.h>
+#include <asm/mce.h>
 
 #include "powernv.h"
 
@@ -38,6 +40,7 @@ extern u64 opal_mc_secondary_handler[];
 static unsigned int *opal_irqs;
 static unsigned int opal_irq_count;
 static ATOMIC_NOTIFIER_HEAD(opal_notifier_head);
+static struct atomic_notifier_head opal_msg_notifier_head[OPAL_MSG_TYPE_MAX];
 static DEFINE_SPINLOCK(opal_notifier_lock);
 static uint64_t last_notified_mask = 0x0ul;
 static atomic_t opal_notifier_hold = ATOMIC_INIT(0);
@@ -88,14 +91,10 @@ static int __init opal_register_exception_handlers(void)
        if (!(powerpc_firmware_features & FW_FEATURE_OPAL))
                return -ENODEV;
 
-       /* Hookup some exception handlers. We use the fwnmi area at 0x7000
-        * to provide the glue space to OPAL
+       /* Hookup some exception handlers except machine check. We use the
+        * fwnmi area at 0x7000 to provide the glue space to OPAL
         */
        glue = 0x7000;
-       opal_register_exception_handler(OPAL_MACHINE_CHECK_HANDLER,
-                                       __pa(opal_mc_secondary_handler[0]),
-                                       glue);
-       glue += 128;
        opal_register_exception_handler(OPAL_HYPERVISOR_MAINTENANCE_HANDLER,
                                        0, glue);
        glue += 128;
@@ -169,6 +168,95 @@ void opal_notifier_disable(void)
        atomic_set(&opal_notifier_hold, 1);
 }
 
+/*
+ * Opal message notifier based on message type. Allow subscribers to get
+ * notified for specific messgae type.
+ */
+int opal_message_notifier_register(enum OpalMessageType msg_type,
+                                       struct notifier_block *nb)
+{
+       if (!nb) {
+               pr_warning("%s: Invalid argument (%p)\n",
+                          __func__, nb);
+               return -EINVAL;
+       }
+       if (msg_type > OPAL_MSG_TYPE_MAX) {
+               pr_warning("%s: Invalid message type argument (%d)\n",
+                          __func__, msg_type);
+               return -EINVAL;
+       }
+       return atomic_notifier_chain_register(
+                               &opal_msg_notifier_head[msg_type], nb);
+}
+
+static void opal_message_do_notify(uint32_t msg_type, void *msg)
+{
+       /* notify subscribers */
+       atomic_notifier_call_chain(&opal_msg_notifier_head[msg_type],
+                                       msg_type, msg);
+}
+
+static void opal_handle_message(void)
+{
+       s64 ret;
+       /*
+        * TODO: pre-allocate a message buffer depending on opal-msg-size
+        * value in /proc/device-tree.
+        */
+       static struct opal_msg msg;
+
+       ret = opal_get_msg(__pa(&msg), sizeof(msg));
+       /* No opal message pending. */
+       if (ret == OPAL_RESOURCE)
+               return;
+
+       /* check for errors. */
+       if (ret) {
+               pr_warning("%s: Failed to retrive opal message, err=%lld\n",
+                               __func__, ret);
+               return;
+       }
+
+       /* Sanity check */
+       if (msg.msg_type > OPAL_MSG_TYPE_MAX) {
+               pr_warning("%s: Unknown message type: %u\n",
+                               __func__, msg.msg_type);
+               return;
+       }
+       opal_message_do_notify(msg.msg_type, (void *)&msg);
+}
+
+static int opal_message_notify(struct notifier_block *nb,
+                         unsigned long events, void *change)
+{
+       if (events & OPAL_EVENT_MSG_PENDING)
+               opal_handle_message();
+       return 0;
+}
+
+static struct notifier_block opal_message_nb = {
+       .notifier_call  = opal_message_notify,
+       .next           = NULL,
+       .priority       = 0,
+};
+
+static int __init opal_message_init(void)
+{
+       int ret, i;
+
+       for (i = 0; i < OPAL_MSG_TYPE_MAX; i++)
+               ATOMIC_INIT_NOTIFIER_HEAD(&opal_msg_notifier_head[i]);
+
+       ret = opal_notifier_register(&opal_message_nb);
+       if (ret) {
+               pr_err("%s: Can't register OPAL event notifier (%d)\n",
+                      __func__, ret);
+               return ret;
+       }
+       return 0;
+}
+early_initcall(opal_message_init);
+
 int opal_get_chars(uint32_t vtermno, char *buf, int count)
 {
        s64 rc;
@@ -254,119 +342,62 @@ int opal_put_chars(uint32_t vtermno, const char *data, int total_len)
        return written;
 }
 
+static int opal_recover_mce(struct pt_regs *regs,
+                                       struct machine_check_event *evt)
+{
+       int recovered = 0;
+       uint64_t ea = get_mce_fault_addr(evt);
+
+       if (!(regs->msr & MSR_RI)) {
+               /* If MSR_RI isn't set, we cannot recover */
+               recovered = 0;
+       } else if (evt->disposition == MCE_DISPOSITION_RECOVERED) {
+               /* Platform corrected itself */
+               recovered = 1;
+       } else if (ea && !is_kernel_addr(ea)) {
+               /*
+                * Faulting address is not in kernel text. We should be fine.
+                * We need to find which process uses this address.
+                * For now, kill the task if we have received exception when
+                * in userspace.
+                *
+                * TODO: Queue up this address for hwpoisioning later.
+                */
+               if (user_mode(regs) && !is_global_init(current)) {
+                       _exception(SIGBUS, regs, BUS_MCEERR_AR, regs->nip);
+                       recovered = 1;
+               } else
+                       recovered = 0;
+       } else if (user_mode(regs) && !is_global_init(current) &&
+               evt->severity == MCE_SEV_ERROR_SYNC) {
+               /*
+                * If we have received a synchronous error when in userspace
+                * kill the task.
+                */
+               _exception(SIGBUS, regs, BUS_MCEERR_AR, regs->nip);
+               recovered = 1;
+       }
+       return recovered;
+}
+
 int opal_machine_check(struct pt_regs *regs)
 {
-       struct opal_machine_check_event *opal_evt = get_paca()->opal_mc_evt;
-       struct opal_machine_check_event evt;
-       const char *level, *sevstr, *subtype;
-       static const char *opal_mc_ue_types[] = {
-               "Indeterminate",
-               "Instruction fetch",
-               "Page table walk ifetch",
-               "Load/Store",
-               "Page table walk Load/Store",
-       };
-       static const char *opal_mc_slb_types[] = {
-               "Indeterminate",
-               "Parity",
-               "Multihit",
-       };
-       static const char *opal_mc_erat_types[] = {
-               "Indeterminate",
-               "Parity",
-               "Multihit",
-       };
-       static const char *opal_mc_tlb_types[] = {
-               "Indeterminate",
-               "Parity",
-               "Multihit",
-       };
-
-       /* Copy the event structure and release the original */
-       evt = *opal_evt;
-       opal_evt->in_use = 0;
+       struct machine_check_event evt;
+
+       if (!get_mce_event(&evt, MCE_EVENT_RELEASE))
+               return 0;
 
        /* Print things out */
-       if (evt.version != OpalMCE_V1) {
+       if (evt.version != MCE_V1) {
                pr_err("Machine Check Exception, Unknown event version %d !\n",
                       evt.version);
                return 0;
        }
-       switch(evt.severity) {
-       case OpalMCE_SEV_NO_ERROR:
-               level = KERN_INFO;
-               sevstr = "Harmless";
-               break;
-       case OpalMCE_SEV_WARNING:
-               level = KERN_WARNING;
-               sevstr = "";
-               break;
-       case OpalMCE_SEV_ERROR_SYNC:
-               level = KERN_ERR;
-               sevstr = "Severe";
-               break;
-       case OpalMCE_SEV_FATAL:
-       default:
-               level = KERN_ERR;
-               sevstr = "Fatal";
-               break;
-       }
+       machine_check_print_event_info(&evt);
 
-       printk("%s%s Machine check interrupt [%s]\n", level, sevstr,
-              evt.disposition == OpalMCE_DISPOSITION_RECOVERED ?
-              "Recovered" : "[Not recovered");
-       printk("%s  Initiator: %s\n", level,
-              evt.initiator == OpalMCE_INITIATOR_CPU ? "CPU" : "Unknown");
-       switch(evt.error_type) {
-       case OpalMCE_ERROR_TYPE_UE:
-               subtype = evt.u.ue_error.ue_error_type <
-                       ARRAY_SIZE(opal_mc_ue_types) ?
-                       opal_mc_ue_types[evt.u.ue_error.ue_error_type]
-                       : "Unknown";
-               printk("%s  Error type: UE [%s]\n", level, subtype);
-               if (evt.u.ue_error.effective_address_provided)
-                       printk("%s    Effective address: %016llx\n",
-                              level, evt.u.ue_error.effective_address);
-               if (evt.u.ue_error.physical_address_provided)
-                       printk("%s      Physial address: %016llx\n",
-                              level, evt.u.ue_error.physical_address);
-               break;
-       case OpalMCE_ERROR_TYPE_SLB:
-               subtype = evt.u.slb_error.slb_error_type <
-                       ARRAY_SIZE(opal_mc_slb_types) ?
-                       opal_mc_slb_types[evt.u.slb_error.slb_error_type]
-                       : "Unknown";
-               printk("%s  Error type: SLB [%s]\n", level, subtype);
-               if (evt.u.slb_error.effective_address_provided)
-                       printk("%s    Effective address: %016llx\n",
-                              level, evt.u.slb_error.effective_address);
-               break;
-       case OpalMCE_ERROR_TYPE_ERAT:
-               subtype = evt.u.erat_error.erat_error_type <
-                       ARRAY_SIZE(opal_mc_erat_types) ?
-                       opal_mc_erat_types[evt.u.erat_error.erat_error_type]
-                       : "Unknown";
-               printk("%s  Error type: ERAT [%s]\n", level, subtype);
-               if (evt.u.erat_error.effective_address_provided)
-                       printk("%s    Effective address: %016llx\n",
-                              level, evt.u.erat_error.effective_address);
-               break;
-       case OpalMCE_ERROR_TYPE_TLB:
-               subtype = evt.u.tlb_error.tlb_error_type <
-                       ARRAY_SIZE(opal_mc_tlb_types) ?
-                       opal_mc_tlb_types[evt.u.tlb_error.tlb_error_type]
-                       : "Unknown";
-               printk("%s  Error type: TLB [%s]\n", level, subtype);
-               if (evt.u.tlb_error.effective_address_provided)
-                       printk("%s    Effective address: %016llx\n",
-                              level, evt.u.tlb_error.effective_address);
-               break;
-       default:
-       case OpalMCE_ERROR_TYPE_UNKNOWN:
-               printk("%s  Error type: Unknown\n", level);
-               break;
-       }
-       return evt.severity == OpalMCE_SEV_FATAL ? 0 : 1;
+       if (opal_recover_mce(regs, &evt))
+               return 1;
+       return 0;
 }
 
 static irqreturn_t opal_interrupt(int irq, void *data)
index 084cdfa40682b2be9f35fde51eb2e4e201accfe9..f0e68714696e5acb4140cc09fc2829cc23f0217f 100644 (file)
@@ -460,7 +460,7 @@ static void pnv_pci_ioda_dma_dev_setup(struct pnv_phb *phb, struct pci_dev *pdev
                return;
 
        pe = &phb->ioda.pe_array[pdn->pe_number];
-       set_iommu_table_base(&pdev->dev, &pe->tce32_table);
+       set_iommu_table_base_and_group(&pdev->dev, &pe->tce32_table);
 }
 
 static void pnv_ioda_setup_bus_dma(struct pnv_ioda_pe *pe, struct pci_bus *bus)
@@ -468,7 +468,7 @@ static void pnv_ioda_setup_bus_dma(struct pnv_ioda_pe *pe, struct pci_bus *bus)
        struct pci_dev *dev;
 
        list_for_each_entry(dev, &bus->devices, bus_list) {
-               set_iommu_table_base(&dev->dev, &pe->tce32_table);
+               set_iommu_table_base_and_group(&dev->dev, &pe->tce32_table);
                if (dev->subordinate)
                        pnv_ioda_setup_bus_dma(pe, dev->subordinate);
        }
@@ -644,7 +644,7 @@ static void pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb,
        iommu_register_group(tbl, pci_domain_nr(pe->pbus), pe->pe_number);
 
        if (pe->pdev)
-               set_iommu_table_base(&pe->pdev->dev, tbl);
+               set_iommu_table_base_and_group(&pe->pdev->dev, tbl);
        else
                pnv_ioda_setup_bus_dma(pe, pe->pbus);
 
@@ -720,9 +720,10 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb,
                tbl->it_type = TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE;
        }
        iommu_init_table(tbl, phb->hose->node);
+       iommu_register_group(tbl, pci_domain_nr(pe->pbus), pe->pe_number);
 
        if (pe->pdev)
-               set_iommu_table_base(&pe->pdev->dev, tbl);
+               set_iommu_table_base_and_group(&pe->pdev->dev, tbl);
        else
                pnv_ioda_setup_bus_dma(pe, pe->pbus);
 
index f8b4bd8afb2e5da39cd8632c7a6a8eae54448aeb..e3807d69393e02c753e1777cffb03c5d6ae0db74 100644 (file)
@@ -92,7 +92,7 @@ static void pnv_pci_p5ioc2_dma_dev_setup(struct pnv_phb *phb,
                                pci_domain_nr(phb->hose->bus), phb->opal_id);
        }
 
-       set_iommu_table_base(&pdev->dev, &phb->p5ioc2.iommu_table);
+       set_iommu_table_base_and_group(&pdev->dev, &phb->p5ioc2.iommu_table);
 }
 
 static void __init pnv_pci_init_p5ioc2_phb(struct device_node *np, u64 hub_id,
index 4eb33a9ed5325a3e84b2a7f1d4d58d5dc7fa7b22..bac289aac7ccb36da9be53aba4904ba2f0b91d13 100644 (file)
@@ -124,77 +124,157 @@ static void pnv_teardown_msi_irqs(struct pci_dev *pdev)
 }
 #endif /* CONFIG_PCI_MSI */
 
-static void pnv_pci_dump_p7ioc_diag_data(struct pnv_phb *phb)
+static void pnv_pci_dump_p7ioc_diag_data(struct pci_controller *hose,
+                                        struct OpalIoPhbErrorCommon *common)
 {
-       struct OpalIoP7IOCPhbErrorData *data = &phb->diag.p7ioc;
+       struct OpalIoP7IOCPhbErrorData *data;
        int i;
 
-       pr_info("PHB %d diagnostic data:\n", phb->hose->global_number);
-
-       pr_info("  brdgCtl              = 0x%08x\n", data->brdgCtl);
-
-       pr_info("  portStatusReg        = 0x%08x\n", data->portStatusReg);
-       pr_info("  rootCmplxStatus      = 0x%08x\n", data->rootCmplxStatus);
-       pr_info("  busAgentStatus       = 0x%08x\n", data->busAgentStatus);
-
-       pr_info("  deviceStatus         = 0x%08x\n", data->deviceStatus);
-       pr_info("  slotStatus           = 0x%08x\n", data->slotStatus);
-       pr_info("  linkStatus           = 0x%08x\n", data->linkStatus);
-       pr_info("  devCmdStatus         = 0x%08x\n", data->devCmdStatus);
-       pr_info("  devSecStatus         = 0x%08x\n", data->devSecStatus);
-
-       pr_info("  rootErrorStatus      = 0x%08x\n", data->rootErrorStatus);
-       pr_info("  uncorrErrorStatus    = 0x%08x\n", data->uncorrErrorStatus);
-       pr_info("  corrErrorStatus      = 0x%08x\n", data->corrErrorStatus);
-       pr_info("  tlpHdr1              = 0x%08x\n", data->tlpHdr1);
-       pr_info("  tlpHdr2              = 0x%08x\n", data->tlpHdr2);
-       pr_info("  tlpHdr3              = 0x%08x\n", data->tlpHdr3);
-       pr_info("  tlpHdr4              = 0x%08x\n", data->tlpHdr4);
-       pr_info("  sourceId             = 0x%08x\n", data->sourceId);
-
-       pr_info("  errorClass           = 0x%016llx\n", data->errorClass);
-       pr_info("  correlator           = 0x%016llx\n", data->correlator);
-
-       pr_info("  p7iocPlssr           = 0x%016llx\n", data->p7iocPlssr);
-       pr_info("  p7iocCsr             = 0x%016llx\n", data->p7iocCsr);
-       pr_info("  lemFir               = 0x%016llx\n", data->lemFir);
-       pr_info("  lemErrorMask         = 0x%016llx\n", data->lemErrorMask);
-       pr_info("  lemWOF               = 0x%016llx\n", data->lemWOF);
-       pr_info("  phbErrorStatus       = 0x%016llx\n", data->phbErrorStatus);
-       pr_info("  phbFirstErrorStatus  = 0x%016llx\n", data->phbFirstErrorStatus);
-       pr_info("  phbErrorLog0         = 0x%016llx\n", data->phbErrorLog0);
-       pr_info("  phbErrorLog1         = 0x%016llx\n", data->phbErrorLog1);
-       pr_info("  mmioErrorStatus      = 0x%016llx\n", data->mmioErrorStatus);
-       pr_info("  mmioFirstErrorStatus = 0x%016llx\n", data->mmioFirstErrorStatus);
-       pr_info("  mmioErrorLog0        = 0x%016llx\n", data->mmioErrorLog0);
-       pr_info("  mmioErrorLog1        = 0x%016llx\n", data->mmioErrorLog1);
-       pr_info("  dma0ErrorStatus      = 0x%016llx\n", data->dma0ErrorStatus);
-       pr_info("  dma0FirstErrorStatus = 0x%016llx\n", data->dma0FirstErrorStatus);
-       pr_info("  dma0ErrorLog0        = 0x%016llx\n", data->dma0ErrorLog0);
-       pr_info("  dma0ErrorLog1        = 0x%016llx\n", data->dma0ErrorLog1);
-       pr_info("  dma1ErrorStatus      = 0x%016llx\n", data->dma1ErrorStatus);
-       pr_info("  dma1FirstErrorStatus = 0x%016llx\n", data->dma1FirstErrorStatus);
-       pr_info("  dma1ErrorLog0        = 0x%016llx\n", data->dma1ErrorLog0);
-       pr_info("  dma1ErrorLog1        = 0x%016llx\n", data->dma1ErrorLog1);
+       data = (struct OpalIoP7IOCPhbErrorData *)common;
+       pr_info("P7IOC PHB#%d Diag-data (Version: %d)\n\n",
+               hose->global_number, common->version);
+
+       pr_info("  brdgCtl:              %08x\n", data->brdgCtl);
+
+       pr_info("  portStatusReg:        %08x\n", data->portStatusReg);
+       pr_info("  rootCmplxStatus:      %08x\n", data->rootCmplxStatus);
+       pr_info("  busAgentStatus:       %08x\n", data->busAgentStatus);
+
+       pr_info("  deviceStatus:         %08x\n", data->deviceStatus);
+       pr_info("  slotStatus:           %08x\n", data->slotStatus);
+       pr_info("  linkStatus:           %08x\n", data->linkStatus);
+       pr_info("  devCmdStatus:         %08x\n", data->devCmdStatus);
+       pr_info("  devSecStatus:         %08x\n", data->devSecStatus);
+
+       pr_info("  rootErrorStatus:      %08x\n", data->rootErrorStatus);
+       pr_info("  uncorrErrorStatus:    %08x\n", data->uncorrErrorStatus);
+       pr_info("  corrErrorStatus:      %08x\n", data->corrErrorStatus);
+       pr_info("  tlpHdr1:              %08x\n", data->tlpHdr1);
+       pr_info("  tlpHdr2:              %08x\n", data->tlpHdr2);
+       pr_info("  tlpHdr3:              %08x\n", data->tlpHdr3);
+       pr_info("  tlpHdr4:              %08x\n", data->tlpHdr4);
+       pr_info("  sourceId:             %08x\n", data->sourceId);
+       pr_info("  errorClass:           %016llx\n", data->errorClass);
+       pr_info("  correlator:           %016llx\n", data->correlator);
+       pr_info("  p7iocPlssr:           %016llx\n", data->p7iocPlssr);
+       pr_info("  p7iocCsr:             %016llx\n", data->p7iocCsr);
+       pr_info("  lemFir:               %016llx\n", data->lemFir);
+       pr_info("  lemErrorMask:         %016llx\n", data->lemErrorMask);
+       pr_info("  lemWOF:               %016llx\n", data->lemWOF);
+       pr_info("  phbErrorStatus:       %016llx\n", data->phbErrorStatus);
+       pr_info("  phbFirstErrorStatus:  %016llx\n", data->phbFirstErrorStatus);
+       pr_info("  phbErrorLog0:         %016llx\n", data->phbErrorLog0);
+       pr_info("  phbErrorLog1:         %016llx\n", data->phbErrorLog1);
+       pr_info("  mmioErrorStatus:      %016llx\n", data->mmioErrorStatus);
+       pr_info("  mmioFirstErrorStatus%016llx\n", data->mmioFirstErrorStatus);
+       pr_info("  mmioErrorLog0:        %016llx\n", data->mmioErrorLog0);
+       pr_info("  mmioErrorLog1:        %016llx\n", data->mmioErrorLog1);
+       pr_info("  dma0ErrorStatus:      %016llx\n", data->dma0ErrorStatus);
+       pr_info("  dma0FirstErrorStatus%016llx\n", data->dma0FirstErrorStatus);
+       pr_info("  dma0ErrorLog0:        %016llx\n", data->dma0ErrorLog0);
+       pr_info("  dma0ErrorLog1:        %016llx\n", data->dma0ErrorLog1);
+       pr_info("  dma1ErrorStatus:      %016llx\n", data->dma1ErrorStatus);
+       pr_info("  dma1FirstErrorStatus%016llx\n", data->dma1FirstErrorStatus);
+       pr_info("  dma1ErrorLog0:        %016llx\n", data->dma1ErrorLog0);
+       pr_info("  dma1ErrorLog1:        %016llx\n", data->dma1ErrorLog1);
 
        for (i = 0; i < OPAL_P7IOC_NUM_PEST_REGS; i++) {
                if ((data->pestA[i] >> 63) == 0 &&
                    (data->pestB[i] >> 63) == 0)
                        continue;
-               pr_info("  PE[%3d] PESTA        = 0x%016llx\n", i, data->pestA[i]);
-               pr_info("          PESTB        = 0x%016llx\n", data->pestB[i]);
+
+               pr_info("  PE[%3d] PESTA:        %016llx\n", i, data->pestA[i]);
+               pr_info("          PESTB:        %016llx\n", data->pestB[i]);
+       }
+}
+
+static void pnv_pci_dump_phb3_diag_data(struct pci_controller *hose,
+                                       struct OpalIoPhbErrorCommon *common)
+{
+       struct OpalIoPhb3ErrorData *data;
+       int i;
+
+       data = (struct OpalIoPhb3ErrorData*)common;
+       pr_info("PHB3 PHB#%d Diag-data (Version: %d)\n\n",
+               hose->global_number, common->version);
+
+       pr_info("  brdgCtl:              %08x\n", data->brdgCtl);
+
+       pr_info("  portStatusReg:        %08x\n", data->portStatusReg);
+       pr_info("  rootCmplxStatus:      %08x\n", data->rootCmplxStatus);
+       pr_info("  busAgentStatus:       %08x\n", data->busAgentStatus);
+
+       pr_info("  deviceStatus:         %08x\n", data->deviceStatus);
+       pr_info("  slotStatus:           %08x\n", data->slotStatus);
+       pr_info("  linkStatus:           %08x\n", data->linkStatus);
+       pr_info("  devCmdStatus:         %08x\n", data->devCmdStatus);
+       pr_info("  devSecStatus:         %08x\n", data->devSecStatus);
+
+       pr_info("  rootErrorStatus:      %08x\n", data->rootErrorStatus);
+       pr_info("  uncorrErrorStatus:    %08x\n", data->uncorrErrorStatus);
+       pr_info("  corrErrorStatus:      %08x\n", data->corrErrorStatus);
+       pr_info("  tlpHdr1:              %08x\n", data->tlpHdr1);
+       pr_info("  tlpHdr2:              %08x\n", data->tlpHdr2);
+       pr_info("  tlpHdr3:              %08x\n", data->tlpHdr3);
+       pr_info("  tlpHdr4:              %08x\n", data->tlpHdr4);
+       pr_info("  sourceId:             %08x\n", data->sourceId);
+       pr_info("  errorClass:           %016llx\n", data->errorClass);
+       pr_info("  correlator:           %016llx\n", data->correlator);
+
+       pr_info("  nFir:                 %016llx\n", data->nFir);
+       pr_info("  nFirMask:             %016llx\n", data->nFirMask);
+       pr_info("  nFirWOF:              %016llx\n", data->nFirWOF);
+       pr_info("  PhbPlssr:             %016llx\n", data->phbPlssr);
+       pr_info("  PhbCsr:               %016llx\n", data->phbCsr);
+       pr_info("  lemFir:               %016llx\n", data->lemFir);
+       pr_info("  lemErrorMask:         %016llx\n", data->lemErrorMask);
+       pr_info("  lemWOF:               %016llx\n", data->lemWOF);
+       pr_info("  phbErrorStatus:       %016llx\n", data->phbErrorStatus);
+       pr_info("  phbFirstErrorStatus:  %016llx\n", data->phbFirstErrorStatus);
+       pr_info("  phbErrorLog0:         %016llx\n", data->phbErrorLog0);
+       pr_info("  phbErrorLog1:         %016llx\n", data->phbErrorLog1);
+       pr_info("  mmioErrorStatus:      %016llx\n", data->mmioErrorStatus);
+       pr_info("  mmioFirstErrorStatus: %016llx\n", data->mmioFirstErrorStatus);
+       pr_info("  mmioErrorLog0:        %016llx\n", data->mmioErrorLog0);
+       pr_info("  mmioErrorLog1:        %016llx\n", data->mmioErrorLog1);
+       pr_info("  dma0ErrorStatus:      %016llx\n", data->dma0ErrorStatus);
+       pr_info("  dma0FirstErrorStatus: %016llx\n", data->dma0FirstErrorStatus);
+       pr_info("  dma0ErrorLog0:        %016llx\n", data->dma0ErrorLog0);
+       pr_info("  dma0ErrorLog1:        %016llx\n", data->dma0ErrorLog1);
+       pr_info("  dma1ErrorStatus:      %016llx\n", data->dma1ErrorStatus);
+       pr_info("  dma1FirstErrorStatus: %016llx\n", data->dma1FirstErrorStatus);
+       pr_info("  dma1ErrorLog0:        %016llx\n", data->dma1ErrorLog0);
+       pr_info("  dma1ErrorLog1:        %016llx\n", data->dma1ErrorLog1);
+
+       for (i = 0; i < OPAL_PHB3_NUM_PEST_REGS; i++) {
+               if ((data->pestA[i] >> 63) == 0 &&
+                   (data->pestB[i] >> 63) == 0)
+                       continue;
+
+               pr_info("  PE[%3d] PESTA:        %016llx\n", i, data->pestA[i]);
+               pr_info("          PESTB:        %016llx\n", data->pestB[i]);
        }
 }
 
-static void pnv_pci_dump_phb_diag_data(struct pnv_phb *phb)
+void pnv_pci_dump_phb_diag_data(struct pci_controller *hose,
+                               unsigned char *log_buff)
 {
-       switch(phb->model) {
-       case PNV_PHB_MODEL_P7IOC:
-               pnv_pci_dump_p7ioc_diag_data(phb);
+       struct OpalIoPhbErrorCommon *common;
+
+       if (!hose || !log_buff)
+               return;
+
+       common = (struct OpalIoPhbErrorCommon *)log_buff;
+       switch (common->ioType) {
+       case OPAL_PHB_ERROR_DATA_TYPE_P7IOC:
+               pnv_pci_dump_p7ioc_diag_data(hose, common);
+               break;
+       case OPAL_PHB_ERROR_DATA_TYPE_PHB3:
+               pnv_pci_dump_phb3_diag_data(hose, common);
                break;
        default:
-               pr_warning("PCI %d: Can't decode this PHB diag data\n",
-                          phb->hose->global_number);
+               pr_warn("%s: Unrecognized ioType %d\n",
+                       __func__, common->ioType);
        }
 }
 
@@ -222,7 +302,7 @@ static void pnv_pci_handle_eeh_config(struct pnv_phb *phb, u32 pe_no)
                 * with the normal errors generated when probing empty slots
                 */
                if (has_diag)
-                       pnv_pci_dump_phb_diag_data(phb);
+                       pnv_pci_dump_phb_diag_data(phb->hose, phb->diag.blob);
                else
                        pr_warning("PCI %d: No diag data available\n",
                                   phb->hose->global_number);
@@ -536,7 +616,7 @@ static void pnv_pci_dma_fallback_setup(struct pci_controller *hose,
                pdn->iommu_table = pnv_pci_setup_bml_iommu(hose);
        if (!pdn->iommu_table)
                return;
-       set_iommu_table_base(&pdev->dev, pdn->iommu_table);
+       set_iommu_table_base_and_group(&pdev->dev, pdn->iommu_table);
 }
 
 static void pnv_pci_dma_dev_setup(struct pci_dev *pdev)
@@ -657,3 +737,34 @@ void __init pnv_pci_init(void)
        ppc_md.teardown_msi_irqs = pnv_teardown_msi_irqs;
 #endif
 }
+
+static int tce_iommu_bus_notifier(struct notifier_block *nb,
+               unsigned long action, void *data)
+{
+       struct device *dev = data;
+
+       switch (action) {
+       case BUS_NOTIFY_ADD_DEVICE:
+               return iommu_add_device(dev);
+       case BUS_NOTIFY_DEL_DEVICE:
+               if (dev->iommu_group)
+                       iommu_del_device(dev);
+               return 0;
+       default:
+               return 0;
+       }
+}
+
+static struct notifier_block tce_iommu_bus_nb = {
+       .notifier_call = tce_iommu_bus_notifier,
+};
+
+static int __init tce_iommu_bus_notifier_init(void)
+{
+       BUILD_BUG_ON(PAGE_SIZE < IOMMU_PAGE_SIZE);
+
+       bus_register_notifier(&pci_bus_type, &tce_iommu_bus_nb);
+       return 0;
+}
+
+subsys_initcall_sync(tce_iommu_bus_notifier_init);
index 911c24ef033e0ae207036e5d5cab8bceaf07e14a..9a11ff0c5c0b4b65d461f0120cc88f6cf7a75589 100644 (file)
@@ -176,6 +176,7 @@ struct pnv_phb {
        union {
                unsigned char                   blob[PNV_PCI_DIAG_BUF_SIZE];
                struct OpalIoP7IOCPhbErrorData  p7ioc;
+               struct OpalIoPhb3ErrorData      phb3;
        } diag;
 };
 
@@ -184,6 +185,8 @@ extern struct pci_ops pnv_pci_ops;
 extern struct pnv_eeh_ops ioda_eeh_ops;
 #endif
 
+void pnv_pci_dump_phb_diag_data(struct pci_controller *hose,
+                               unsigned char *log_buff);
 int pnv_pci_cfg_read(struct device_node *dn,
                     int where, int size, u32 *val);
 int pnv_pci_cfg_write(struct device_node *dn,
index e17fa1432d80706ad9b5fa2682ea88751027c38a..a0bca05e26b0c7478c7483c43b2437fa0f6a61d7 100644 (file)
@@ -143,7 +143,7 @@ static void _dump_areas(unsigned int spe_id, unsigned long priv2,
        pr_debug("%s:%d: shadow:  %lxh\n", func, line, shadow);
 }
 
-inline u64 ps3_get_spe_id(void *arg)
+u64 ps3_get_spe_id(void *arg)
 {
        return spu_pdata(arg)->spe_id;
 }
index 62b4f8025de005ad77bdbfcd42024d25614eb79c..e66643250fee3eea1c2de2d832f9b3cbb0fc7632 100644 (file)
@@ -34,7 +34,7 @@ config PPC_SPLPAR
 
 config PSERIES_MSI
        bool
-       depends on PCI_MSI && EEH
+       depends on PCI_MSI && PPC_PSERIES && EEH
        default y
 
 config PSERIES_ENERGY
index f253361552aee3fbc3c98f077790f89551b4ea74..a80af6c20cba0899bcbdf5ff98587d3dfc724dc0 100644 (file)
@@ -687,7 +687,8 @@ static void pci_dma_dev_setup_pSeries(struct pci_dev *dev)
                iommu_table_setparms(phb, dn, tbl);
                PCI_DN(dn)->iommu_table = iommu_init_table(tbl, phb->node);
                iommu_register_group(tbl, pci_domain_nr(phb->bus), 0);
-               set_iommu_table_base(&dev->dev, PCI_DN(dn)->iommu_table);
+               set_iommu_table_base_and_group(&dev->dev,
+                                              PCI_DN(dn)->iommu_table);
                return;
        }
 
@@ -699,7 +700,8 @@ static void pci_dma_dev_setup_pSeries(struct pci_dev *dev)
                dn = dn->parent;
 
        if (dn && PCI_DN(dn))
-               set_iommu_table_base(&dev->dev, PCI_DN(dn)->iommu_table);
+               set_iommu_table_base_and_group(&dev->dev,
+                                              PCI_DN(dn)->iommu_table);
        else
                printk(KERN_WARNING "iommu: Device %s has no iommu table\n",
                       pci_name(dev));
@@ -1193,7 +1195,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
                pr_debug("  found DMA window, table: %p\n", pci->iommu_table);
        }
 
-       set_iommu_table_base(&dev->dev, pci->iommu_table);
+       set_iommu_table_base_and_group(&dev->dev, pci->iommu_table);
 }
 
 static int dma_set_mask_pSeriesLP(struct device *dev, u64 dma_mask)
index 4fca3def9db951896864d0b716d7dea8a2364ba2..b02af9ef3ff61ab45fb2ae86f2b49cdc6b5cc7ff 100644 (file)
@@ -92,7 +92,7 @@ void vpa_init(int cpu)
         * PAPR says this feature is SLB-Buffer but firmware never
         * reports that.  All SPLPAR support SLB shadow buffer.
         */
-       addr = __pa(&slb_shadow[cpu]);
+       addr = __pa(paca[cpu].slb_shadow_ptr);
        if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
                ret = register_slb_shadow(hwcpu, addr);
                if (ret)
@@ -153,7 +153,8 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
 
        /* Make pHyp happy */
        if ((rflags & _PAGE_NO_CACHE) && !(rflags & _PAGE_WRITETHRU))
-               hpte_r &= ~_PAGE_COHERENT;
+               hpte_r &= ~HPTE_R_M;
+
        if (firmware_has_feature(FW_FEATURE_XCMO) && !(hpte_r & HPTE_R_N))
                flags |= H_COALESCE_CAND;
 
index c1f1908587011d6d131dd56bdf2e1cb283c41128..6f76ae417f47e561bbf7e8b01c588a8e73f6374d 100644 (file)
@@ -470,7 +470,7 @@ static long pseries_little_endian_exceptions(void)
 
 static void __init pSeries_setup_arch(void)
 {
-       panic_timeout = 10;
+       set_arch_panic_timeout(10, ARCH_PANIC_TIMEOUT);
 
        /* Discover PIC type and setup ppc_md accordingly */
        pseries_discover_pic();
index 13ec968be4c7a25ca79fc480a7aab26e514b3bb8..7baa70d6dc016c85b8e4874f7618dbf9145d30ac 100644 (file)
@@ -19,7 +19,7 @@ config PPC_MSI_BITMAP
        default y if MPIC
        default y if FSL_PCI
        default y if PPC4xx_MSI
-       default y if POWERNV_MSI
+       default y if PPC_POWERNV
 
 source "arch/powerpc/sysdev/xics/Kconfig"
 
index 1c16141c031c9e2d2512b0d308a8456c15fd1ae1..47b6b9f81d4305537b7d0e6290e178efb4253f4c 100644 (file)
@@ -109,27 +109,28 @@ axon_ram_make_request(struct request_queue *queue, struct bio *bio)
        struct axon_ram_bank *bank = bio->bi_bdev->bd_disk->private_data;
        unsigned long phys_mem, phys_end;
        void *user_mem;
-       struct bio_vec *vec;
+       struct bio_vec vec;
        unsigned int transfered;
-       unsigned short idx;
+       struct bvec_iter iter;
 
-       phys_mem = bank->io_addr + (bio->bi_sector << AXON_RAM_SECTOR_SHIFT);
+       phys_mem = bank->io_addr + (bio->bi_iter.bi_sector <<
+                                   AXON_RAM_SECTOR_SHIFT);
        phys_end = bank->io_addr + bank->size;
        transfered = 0;
-       bio_for_each_segment(vec, bio, idx) {
-               if (unlikely(phys_mem + vec->bv_len > phys_end)) {
+       bio_for_each_segment(vec, bio, iter) {
+               if (unlikely(phys_mem + vec.bv_len > phys_end)) {
                        bio_io_error(bio);
                        return;
                }
 
-               user_mem = page_address(vec->bv_page) + vec->bv_offset;
+               user_mem = page_address(vec.bv_page) + vec.bv_offset;
                if (bio_data_dir(bio) == READ)
-                       memcpy(user_mem, (void *) phys_mem, vec->bv_len);
+                       memcpy(user_mem, (void *) phys_mem, vec.bv_len);
                else
-                       memcpy((void *) phys_mem, user_mem, vec->bv_len);
+                       memcpy((void *) phys_mem, user_mem, vec.bv_len);
 
-               phys_mem += vec->bv_len;
-               transfered += vec->bv_len;
+               phys_mem += vec.bv_len;
+               transfered += vec.bv_len;
        }
        bio_endio(bio, 0);
 }
index 4dfd61df8aba99a01fb0d3d141d1544aeea3b341..7066e52624686a2b1d472eaebefcc8fd3da55b16 100644 (file)
@@ -122,7 +122,7 @@ static int fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask)
         * address width of the SoC such that we can address any internal
         * SoC address from across PCI if needed
         */
-       if ((dev->bus == &pci_bus_type) &&
+       if ((dev_is_pci(dev)) &&
            dma_mask >= DMA_BIT_MASK(MAX_PHYS_ADDR_BITS)) {
                set_dma_ops(dev, &dma_direct_ops);
                set_dma_offset(dev, pci64_dma_offset);
index b7c43453236dfac7d001b583e554d8938b0ba426..85d9e37f5ccbf76c93c2cf71c1d70677d7a14366 100644 (file)
@@ -339,7 +339,7 @@ void *ppc4xx_ocm_alloc(phys_addr_t *phys, int size, int align,
                if (IS_ERR_VALUE(offset))
                        continue;
 
-               ocm_blk = kzalloc(sizeof(struct ocm_block *), GFP_KERNEL);
+               ocm_blk = kzalloc(sizeof(struct ocm_block), GFP_KERNEL);
                if (!ocm_blk) {
                        printk(KERN_ERR "PPC4XX OCM: could not allocate ocm block");
                        rh_free(ocm_reg->rh, offset);
index af9d3469fb9933e4f3d424f01e3230ddeb580c67..a90731b3d44a3ea41052690975aefcd8b3ce2db7 100644 (file)
@@ -2051,6 +2051,10 @@ static void dump_one_paca(int cpu)
        DUMP(p, stab_addr, "lx");
 #endif
        DUMP(p, emergency_sp, "p");
+#ifdef CONFIG_PPC_BOOK3S_64
+       DUMP(p, mc_emergency_sp, "p");
+       DUMP(p, in_mce, "x");
+#endif
        DUMP(p, data_offset, "lx");
        DUMP(p, hw_cpu_id, "x");
        DUMP(p, cpu_start, "x");
index 5877e71901b345ef191a911f9ad0ba537abd9c8c..1e1a03d2d19fbbb35804d4fc28d8d9eac355a9c4 100644 (file)
@@ -347,14 +347,14 @@ config SMP
          Even if you don't know what to do here, say Y.
 
 config NR_CPUS
-       int "Maximum number of CPUs (2-64)"
-       range 2 64
+       int "Maximum number of CPUs (2-256)"
+       range 2 256
        depends on SMP
        default "32" if !64BIT
        default "64" if 64BIT
        help
          This allows you to specify the maximum number of CPUs which this
-         kernel will support.  The maximum supported value is 64 and the
+         kernel will support. The maximum supported value is 256 and the
          minimum value which makes sense is 2.
 
          This is purely to save memory - each supported CPU adds
index 4363528dc8fd013492b2165f6978b5e5226657b1..b3feabd39f31f8eead0a69f4340a8abc0ea17da6 100644 (file)
@@ -55,8 +55,7 @@ struct pcc_param {
 
 struct s390_xts_ctx {
        u8 key[32];
-       u8 xts_param[16];
-       struct pcc_param pcc;
+       u8 pcc_key[32];
        long enc;
        long dec;
        int key_len;
@@ -591,7 +590,7 @@ static int xts_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
                xts_ctx->enc = KM_XTS_128_ENCRYPT;
                xts_ctx->dec = KM_XTS_128_DECRYPT;
                memcpy(xts_ctx->key + 16, in_key, 16);
-               memcpy(xts_ctx->pcc.key + 16, in_key + 16, 16);
+               memcpy(xts_ctx->pcc_key + 16, in_key + 16, 16);
                break;
        case 48:
                xts_ctx->enc = 0;
@@ -602,7 +601,7 @@ static int xts_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
                xts_ctx->enc = KM_XTS_256_ENCRYPT;
                xts_ctx->dec = KM_XTS_256_DECRYPT;
                memcpy(xts_ctx->key, in_key, 32);
-               memcpy(xts_ctx->pcc.key, in_key + 32, 32);
+               memcpy(xts_ctx->pcc_key, in_key + 32, 32);
                break;
        default:
                *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
@@ -621,29 +620,33 @@ static int xts_aes_crypt(struct blkcipher_desc *desc, long func,
        unsigned int nbytes = walk->nbytes;
        unsigned int n;
        u8 *in, *out;
-       void *param;
+       struct pcc_param pcc_param;
+       struct {
+               u8 key[32];
+               u8 init[16];
+       } xts_param;
 
        if (!nbytes)
                goto out;
 
-       memset(xts_ctx->pcc.block, 0, sizeof(xts_ctx->pcc.block));
-       memset(xts_ctx->pcc.bit, 0, sizeof(xts_ctx->pcc.bit));
-       memset(xts_ctx->pcc.xts, 0, sizeof(xts_ctx->pcc.xts));
-       memcpy(xts_ctx->pcc.tweak, walk->iv, sizeof(xts_ctx->pcc.tweak));
-       param = xts_ctx->pcc.key + offset;
-       ret = crypt_s390_pcc(func, param);
+       memset(pcc_param.block, 0, sizeof(pcc_param.block));
+       memset(pcc_param.bit, 0, sizeof(pcc_param.bit));
+       memset(pcc_param.xts, 0, sizeof(pcc_param.xts));
+       memcpy(pcc_param.tweak, walk->iv, sizeof(pcc_param.tweak));
+       memcpy(pcc_param.key, xts_ctx->pcc_key, 32);
+       ret = crypt_s390_pcc(func, &pcc_param.key[offset]);
        if (ret < 0)
                return -EIO;
 
-       memcpy(xts_ctx->xts_param, xts_ctx->pcc.xts, 16);
-       param = xts_ctx->key + offset;
+       memcpy(xts_param.key, xts_ctx->key, 32);
+       memcpy(xts_param.init, pcc_param.xts, 16);
        do {
                /* only use complete blocks */
                n = nbytes & ~(AES_BLOCK_SIZE - 1);
                out = walk->dst.virt.addr;
                in = walk->src.virt.addr;
 
-               ret = crypt_s390_km(func, param, out, in, n);
+               ret = crypt_s390_km(func, &xts_param.key[offset], out, in, n);
                if (ret < 0 || ret != n)
                        return -EIO;
 
index 30ef748bc161eb3a7f52084ea763d54fe6ed09fc..2f390956c7c1c930722320956a54d1e65ada5673 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <linux/types.h>
 #include <asm/chpid.h>
+#include <asm/cpu.h>
 
 #define SCLP_CHP_INFO_MASK_SIZE                32
 
@@ -37,7 +38,7 @@ struct sclp_cpu_info {
        unsigned int standby;
        unsigned int combined;
        int has_cpu_type;
-       struct sclp_cpu_entry cpu[255];
+       struct sclp_cpu_entry cpu[MAX_CPU_ADDRESS + 1];
 };
 
 int sclp_get_cpu_info(struct sclp_cpu_info *info);
index e83fc116f5bf2c24ceb4f4b9aa663d7d1c291b8f..fe94ea7c9fa0b554ac757fed5272de835ec158b1 100644 (file)
@@ -154,6 +154,46 @@ struct ica_xcRB {
        unsigned short  priority_window;
        unsigned int    status;
 } __attribute__((packed));
+
+/**
+ * EP11 CPRB
+ */
+struct ep11_cprb {
+       unsigned short  cprb_len;       /* CPRB header length     0x0020    */
+       unsigned char   cprb_ver_id;    /* CPRB version id.       0x04      */
+       unsigned char   pad_000[2];     /* Alignment pad bytes              */
+       unsigned char   flags;          /* Admin cmd 0x80 / func. cmd 0x00  */
+       unsigned char   func_id[2];     /* Function id / subtype  0x5434    */
+       unsigned int    source_id;      /* Source id [originator id]        */
+       unsigned int    target_id;      /* Target id [usage/ctrl domain id] */
+       unsigned int    ret_code;       /* Return code                      */
+       unsigned int    reserved1;      /* Reserved                         */
+       unsigned int    reserved2;      /* Reserved                         */
+       unsigned int    payload_len;    /* Payload length                   */
+} __attribute__((packed));
+
+/**
+ * EP11 target device
+ */
+struct ep11_target_dev {
+       short ap_id;    /* AP device id    */
+       short dom_id;   /* Usage domain id */
+};
+
+/**
+ * EP11 user request block
+ */
+struct ep11_urb {
+       short                   targets_num;    /* Number of target adapters */
+       struct target_list      *targets;       /* Target adapter list       */
+       unsigned long           weight;         /* Level of request priority */
+       unsigned long           req_no;         /* Request id/number         */
+       unsigned long           req_len;        /* Request length            */
+       char __user             *req;           /* Pointer to request block  */
+       unsigned long           resp_len;       /* Response length           */
+       char  __user            *resp;          /* Pointer to response block */
+} __attribute__((packed));
+
 #define AUTOSELECT ((unsigned int)0xFFFFFFFF)
 
 #define ZCRYPT_IOCTL_MAGIC 'z'
@@ -183,6 +223,9 @@ struct ica_xcRB {
  *   ZSECSENDCPRB
  *     Send an arbitrary CPRB to a crypto card.
  *
+ *   ZSENDEP11CPRB
+ *     Send an arbitrary EP11 CPRB to an EP11 coprocessor crypto card.
+ *
  *   Z90STAT_STATUS_MASK
  *     Return an 64 element array of unsigned chars for the status of
  *     all devices.
@@ -256,6 +299,7 @@ struct ica_xcRB {
 #define ICARSAMODEXPO  _IOC(_IOC_READ|_IOC_WRITE, ZCRYPT_IOCTL_MAGIC, 0x05, 0)
 #define ICARSACRT      _IOC(_IOC_READ|_IOC_WRITE, ZCRYPT_IOCTL_MAGIC, 0x06, 0)
 #define ZSECSENDCPRB   _IOC(_IOC_READ|_IOC_WRITE, ZCRYPT_IOCTL_MAGIC, 0x81, 0)
+#define ZSENDEP11CPRB  _IOC(_IOC_READ|_IOC_WRITE, ZCRYPT_IOCTL_MAGIC, 0x04, 0)
 
 /* New status calls */
 #define Z90STAT_TOTALCOUNT     _IOR(ZCRYPT_IOCTL_MAGIC, 0x40, int)
index 496116cd65ec8ef3a1b566ac8c1c0641dfcad5f4..e4c99a1836511b16b90de5b4591bea5dc9fc8e69 100644 (file)
@@ -72,6 +72,7 @@ int main(void)
        /* constants used by the vdso */
        DEFINE(__CLOCK_REALTIME, CLOCK_REALTIME);
        DEFINE(__CLOCK_MONOTONIC, CLOCK_MONOTONIC);
+       DEFINE(__CLOCK_THREAD_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID);
        DEFINE(__CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC);
        BLANK();
        /* idle data offsets */
index a84476f2a9bb3ae488eb7a936021a744a822dd31..613649096783401e0cf9acf73069dff48a35e438 100644 (file)
@@ -125,7 +125,7 @@ int vdso_alloc_per_cpu(struct _lowcore *lowcore)
                psal[i] = 0x80000000;
 
        lowcore->paste[4] = (u32)(addr_t) psal;
-       psal[0] = 0x20000000;
+       psal[0] = 0x02000000;
        psal[2] = (u32)(addr_t) aste;
        *(unsigned long *) (aste + 2) = segment_table +
                _ASCE_TABLE_LENGTH + _ASCE_USER_BITS + _ASCE_TYPE_SEGMENT;
index 5be8e472f57d1d0debe31c849b4177492380d957..65fc3979c2f11bb037fd7f646c18a1188b4c4553 100644 (file)
@@ -46,18 +46,13 @@ __kernel_clock_gettime:
        jnm     3f
        a       %r0,__VDSO_TK_MULT(%r5)
 3:     alr     %r0,%r2
-       al      %r0,__VDSO_XTIME_NSEC(%r5)      /*  + tk->xtime_nsec */
-       al      %r1,__VDSO_XTIME_NSEC+4(%r5)
-       brc     12,4f
-       ahi     %r0,1
-4:     al      %r0,__VDSO_WTOM_NSEC(%r5)       /*  + wall_to_monotonic.nsec */
+       al      %r0,__VDSO_WTOM_NSEC(%r5)
        al      %r1,__VDSO_WTOM_NSEC+4(%r5)
        brc     12,5f
        ahi     %r0,1
 5:     l       %r2,__VDSO_TK_SHIFT(%r5)        /* Timekeeper shift */
        srdl    %r0,0(%r2)                      /*  >> tk->shift */
-       l       %r2,__VDSO_XTIME_SEC+4(%r5)
-       al      %r2,__VDSO_WTOM_SEC+4(%r5)
+       l       %r2,__VDSO_WTOM_SEC+4(%r5)
        cl      %r4,__VDSO_UPD_COUNT+4(%r5)     /* check update counter */
        jne     1b
        basr    %r5,0
index 176e1f75f9aa6c1554dbf0818b7d4cd6661c0846..34deba7c7ed1d8b18036b0b07f9b7cd9d41e9259 100644 (file)
@@ -23,7 +23,9 @@ __kernel_clock_getres:
        je      0f
        cghi    %r2,__CLOCK_MONOTONIC
        je      0f
-       cghi    %r2,-2          /* CLOCK_THREAD_CPUTIME_ID for this thread */
+       cghi    %r2,__CLOCK_THREAD_CPUTIME_ID
+       je      0f
+       cghi    %r2,-2          /* Per-thread CPUCLOCK with PID=0, VIRT=1 */
        jne     2f
        larl    %r5,_vdso_data
        icm     %r0,15,__LC_ECTG_OK(%r5)
index 0add1072ba306623665148816155f951f0baeeda..91940ed33a4ab21686f890481545cbfdd9404468 100644 (file)
@@ -22,7 +22,9 @@ __kernel_clock_gettime:
        larl    %r5,_vdso_data
        cghi    %r2,__CLOCK_REALTIME
        je      4f
-       cghi    %r2,-2          /* CLOCK_THREAD_CPUTIME_ID for this thread */
+       cghi    %r2,__CLOCK_THREAD_CPUTIME_ID
+       je      9f
+       cghi    %r2,-2          /* Per-thread CPUCLOCK with PID=0, VIRT=1 */
        je      9f
        cghi    %r2,__CLOCK_MONOTONIC
        jne     12f
@@ -35,13 +37,11 @@ __kernel_clock_gettime:
        jnz     0b
        stck    48(%r15)                        /* Store TOD clock */
        lgf     %r2,__VDSO_TK_SHIFT(%r5)        /* Timekeeper shift */
-       lg      %r0,__VDSO_XTIME_SEC(%r5)       /* tk->xtime_sec */
-       alg     %r0,__VDSO_WTOM_SEC(%r5)        /*  + wall_to_monotonic.sec */
+       lg      %r0,__VDSO_WTOM_SEC(%r5)
        lg      %r1,48(%r15)
        sg      %r1,__VDSO_XTIME_STAMP(%r5)     /* TOD - cycle_last */
        msgf    %r1,__VDSO_TK_MULT(%r5)         /*  * tk->mult */
-       alg     %r1,__VDSO_XTIME_NSEC(%r5)      /*  + tk->xtime_nsec */
-       alg     %r1,__VDSO_WTOM_NSEC(%r5)       /*  + wall_to_monotonic.nsec */
+       alg     %r1,__VDSO_WTOM_NSEC(%r5)
        srlg    %r1,%r1,0(%r2)                  /*  >> tk->shift */
        clg     %r4,__VDSO_UPD_COUNT(%r5)       /* check update counter */
        jne     0b
index 122f737a901fbad4e22de06652e6eb9b04abdfc8..5bc3a15465c71a53906ed0f99a848298c30b2831 100644 (file)
@@ -502,7 +502,7 @@ static struct platform_device keysc_device = {
 /* TouchScreen */
 #define IRQ0 evt2irq(0x600)
 
-static int ts_get_pendown_state(void)
+static int ts_get_pendown_state(struct device *dev)
 {
        int val = 0;
        gpio_free(GPIO_FN_INTC_IRQ0);
index ec9ad593c3da743bacbd5875a577709a94e3333b..01a38696137e9952c9e07f91669685b3b349b50d 100644 (file)
@@ -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 (file)
index 0000000..b604619
--- /dev/null
@@ -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 (file)
index 0000000..3371f90
--- /dev/null
@@ -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__ */
index 990195d9845607bfcca4a8b3cfcd05c41df582bc..92f0da4c86a7533e18269e6f5d439130e1a71815 100644 (file)
@@ -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 (file)
index 0000000..ef95a9b
--- /dev/null
@@ -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);
index f9173766ec4be2393e4207efe7092741f35fc271..ac4922ad3c148d3fc0883afe9ccb8a50d078fc76 100644 (file)
@@ -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;
        }
index 60b19f50c80a8f9d7f31b4b4105ed4fcded6a5ca..b45fe3fb4d2cfbc7999d34a1b25baf9bc0278c2e 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/kgdb.h>
 #include <linux/kdebug.h>
 #include <linux/ftrace.h>
+#include <linux/context_tracking.h>
 
 #include <asm/cacheflush.h>
 #include <asm/kdebug.h>
index 48d92bbe62e9eae2460df5fb99bdd83974b9aecb..36e658a4291c685e12d554dfd74ac153179591dc 100644 (file)
@@ -33,12 +33,11 @@ MODE_INCLUDE        += -I$(srctree)/$(ARCH_DIR)/include/shared/skas
 
 HEADER_ARCH    := $(SUBARCH)
 
-# Additional ARCH settings for x86
-ifeq ($(SUBARCH),i386)
-        HEADER_ARCH := x86
+ifneq ($(filter $(SUBARCH),x86 x86_64 i386),)
+       HEADER_ARCH := x86
 endif
-ifeq ($(SUBARCH),x86_64)
-        HEADER_ARCH := x86
+
+ifdef CONFIG_64BIT
        KBUILD_CFLAGS += -mcmodel=large
 endif
 
index 4d6fdf68edf31cf31b993081a6d9432dff6e3c5b..799d7e413bf57247f258b25ad6306a91b363e67c 100644 (file)
@@ -19,7 +19,7 @@ struct stack_frame {
        unsigned long return_address;
 };
 
-static void print_stack_trace(unsigned long *sp, unsigned long bp)
+static void do_stack_trace(unsigned long *sp, unsigned long bp)
 {
        int reliable;
        unsigned long addr;
@@ -94,5 +94,5 @@ void show_stack(struct task_struct *task, unsigned long *stack)
        }
        printk(KERN_CONT "\n");
 
-       print_stack_trace(sp, bp);
+       do_stack_trace(sp, bp);
 }
index e903c71f7e69822d2ce5240b957399dbab783037..6bdaa0f193a65f99bb29f245dd8b99c364b094a4 100644 (file)
@@ -952,7 +952,7 @@ config X86_ANCIENT_MCE
        depends on X86_32 && X86_MCE
        ---help---
          Include support for machine check handling on old Pentium 5 or WinChip
-         systems. These typically need to be enabled explicitely on the command
+         systems. These typically need to be enabled explicitly on the command
          line.
 
 config X86_MCE_THRESHOLD
@@ -1727,16 +1727,60 @@ config RELOCATABLE
 
          Note: If CONFIG_RELOCATABLE=y, then the kernel runs from the address
          it has been loaded at and the compile time physical address
-         (CONFIG_PHYSICAL_START) is ignored.
+         (CONFIG_PHYSICAL_START) is used as the minimum location.
 
-# Relocation on x86-32 needs some additional build support
+config RANDOMIZE_BASE
+       bool "Randomize the address of the kernel image"
+       depends on RELOCATABLE
+       depends on !HIBERNATION
+       default n
+       ---help---
+          Randomizes the physical and virtual address at which the
+          kernel image is decompressed, as a security feature that
+          deters exploit attempts relying on knowledge of the location
+          of kernel internals.
+
+          Entropy is generated using the RDRAND instruction if it is
+          supported. If RDTSC is supported, it is used as well. If
+          neither RDRAND nor RDTSC are supported, then randomness is
+          read from the i8254 timer.
+
+          The kernel will be offset by up to RANDOMIZE_BASE_MAX_OFFSET,
+          and aligned according to PHYSICAL_ALIGN. Since the kernel is
+          built using 2GiB addressing, and PHYSICAL_ALGIN must be at a
+          minimum of 2MiB, only 10 bits of entropy is theoretically
+          possible. At best, due to page table layouts, 64-bit can use
+          9 bits of entropy and 32-bit uses 8 bits.
+
+config RANDOMIZE_BASE_MAX_OFFSET
+       hex "Maximum ASLR offset allowed"
+       depends on RANDOMIZE_BASE
+       range 0x0 0x20000000 if X86_32
+       default "0x20000000" if X86_32
+       range 0x0 0x40000000 if X86_64
+       default "0x40000000" if X86_64
+       ---help---
+        Determines the maximal offset in bytes that will be applied to the
+        kernel when Address Space Layout Randomization (ASLR) is active.
+        Must be less than or equal to the actual physical memory on the
+        system. This must be a multiple of CONFIG_PHYSICAL_ALIGN.
+
+        On 32-bit this is limited to 512MiB.
+
+        On 64-bit this is limited by how the kernel fixmap page table is
+        positioned, so this cannot be larger that 1GiB currently. Normally
+        there is a 512MiB to 1.5GiB split between kernel and modules. When
+        this is raised above the 512MiB default, the modules area will
+        shrink to compensate, up to the current maximum 1GiB to 1GiB split.
+
+# Relocation on x86 needs some additional build support
 config X86_NEED_RELOCS
        def_bool y
-       depends on X86_32 && RELOCATABLE
+       depends on RANDOMIZE_BASE || (X86_32 && RELOCATABLE)
 
 config PHYSICAL_ALIGN
        hex "Alignment value to which kernel should be aligned"
-       default "0x1000000"
+       default "0x200000"
        range 0x2000 0x1000000 if X86_32
        range 0x200000 0x1000000 if X86_64
        ---help---
index 41250fb33985e179f63b399cfb6a2d10c93a4e29..eda00f9be0cf100caee9ec195f838c6e31885b70 100644 (file)
@@ -31,6 +31,9 @@ ifeq ($(CONFIG_X86_32),y)
 
         KBUILD_CFLAGS += -msoft-float -mregparm=3 -freg-struct-return
 
+        # Don't autogenerate SSE instructions
+       KBUILD_CFLAGS += -mno-sse
+
         # Never want PIC in a 32-bit kernel, prevent breakage with GCC built
         # with nonstandard options
         KBUILD_CFLAGS += -fno-pic
@@ -57,8 +60,11 @@ else
         KBUILD_AFLAGS += -m64
         KBUILD_CFLAGS += -m64
 
+        # Don't autogenerate SSE instructions
+       KBUILD_CFLAGS += -mno-sse
+
        # Use -mpreferred-stack-boundary=3 if supported.
-       KBUILD_CFLAGS += $(call cc-option,-mno-sse -mpreferred-stack-boundary=3)
+       KBUILD_CFLAGS += $(call cc-option,-mpreferred-stack-boundary=3)
 
         # FIXME - should be integrated in Makefile.cpu (Makefile_32.cpu)
         cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8)
index dce69a2568963bf97efa8a3598be4645cc93834b..28f7db7993f5015f27b724bbad43c89c2ec0bb73 100644 (file)
@@ -20,7 +20,7 @@ targets               := vmlinux.bin setup.bin setup.elf bzImage
 targets                += fdimage fdimage144 fdimage288 image.iso mtools.conf
 subdir-                := compressed
 
-setup-y                += a20.o bioscall.o cmdline.o copy.o cpu.o cpucheck.o
+setup-y                += a20.o bioscall.o cmdline.o copy.o cpu.o cpuflags.o cpucheck.o
 setup-y                += early_serial_console.o edd.o header.o main.o mca.o memory.o
 setup-y                += pm.o pmjump.o printf.o regs.o string.o tty.o video.o
 setup-y                += video-mode.o version.o
index ef72baeff48475cd1ce9583880c33b9970b1b556..50f8c5e0f37e1d2dd7030da9d72c5be21e2ee282 100644 (file)
@@ -26,9 +26,8 @@
 #include <asm/boot.h>
 #include <asm/setup.h>
 #include "bitops.h"
-#include <asm/cpufeature.h>
-#include <asm/processor-flags.h>
 #include "ctype.h"
+#include "cpuflags.h"
 
 /* Useful macros */
 #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
@@ -307,14 +306,7 @@ static inline int cmdline_find_option_bool(const char *option)
        return __cmdline_find_option_bool(cmd_line_ptr, option);
 }
 
-
 /* cpu.c, cpucheck.c */
-struct cpu_features {
-       int level;              /* Family, or 64 for x86-64 */
-       int model;
-       u32 flags[NCAPINTS];
-};
-extern struct cpu_features cpu;
 int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr);
 int validate_cpu(void);
 
index dcd90df10ab4e271dd6ee0e3ed737015326efa18..ae8b5dbbd8c5c401ff63e6a188aac29e0b197ca1 100644 (file)
@@ -27,7 +27,7 @@ HOST_EXTRACFLAGS += -I$(srctree)/tools/include
 
 VMLINUX_OBJS = $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o \
        $(obj)/string.o $(obj)/cmdline.o $(obj)/early_serial_console.o \
-       $(obj)/piggy.o
+       $(obj)/piggy.o $(obj)/cpuflags.o $(obj)/aslr.o
 
 $(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone
 
diff --git a/arch/x86/boot/compressed/aslr.c b/arch/x86/boot/compressed/aslr.c
new file mode 100644 (file)
index 0000000..84be175
--- /dev/null
@@ -0,0 +1,317 @@
+#include "misc.h"
+
+#ifdef CONFIG_RANDOMIZE_BASE
+#include <asm/msr.h>
+#include <asm/archrandom.h>
+#include <asm/e820.h>
+
+#include <generated/compile.h>
+#include <linux/module.h>
+#include <linux/uts.h>
+#include <linux/utsname.h>
+#include <generated/utsrelease.h>
+#include <linux/version.h>
+
+/* Simplified build-specific string for starting entropy. */
+static const char build_str[] = UTS_RELEASE " (" LINUX_COMPILE_BY "@"
+               LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION;
+
+#define I8254_PORT_CONTROL     0x43
+#define I8254_PORT_COUNTER0    0x40
+#define I8254_CMD_READBACK     0xC0
+#define I8254_SELECT_COUNTER0  0x02
+#define I8254_STATUS_NOTREADY  0x40
+static inline u16 i8254(void)
+{
+       u16 status, timer;
+
+       do {
+               outb(I8254_PORT_CONTROL,
+                    I8254_CMD_READBACK | I8254_SELECT_COUNTER0);
+               status = inb(I8254_PORT_COUNTER0);
+               timer  = inb(I8254_PORT_COUNTER0);
+               timer |= inb(I8254_PORT_COUNTER0) << 8;
+       } while (status & I8254_STATUS_NOTREADY);
+
+       return timer;
+}
+
+static unsigned long rotate_xor(unsigned long hash, const void *area,
+                               size_t size)
+{
+       size_t i;
+       unsigned long *ptr = (unsigned long *)area;
+
+       for (i = 0; i < size / sizeof(hash); i++) {
+               /* Rotate by odd number of bits and XOR. */
+               hash = (hash << ((sizeof(hash) * 8) - 7)) | (hash >> 7);
+               hash ^= ptr[i];
+       }
+
+       return hash;
+}
+
+/* Attempt to create a simple but unpredictable starting entropy. */
+static unsigned long get_random_boot(void)
+{
+       unsigned long hash = 0;
+
+       hash = rotate_xor(hash, build_str, sizeof(build_str));
+       hash = rotate_xor(hash, real_mode, sizeof(*real_mode));
+
+       return hash;
+}
+
+static unsigned long get_random_long(void)
+{
+#ifdef CONFIG_X86_64
+       const unsigned long mix_const = 0x5d6008cbf3848dd3UL;
+#else
+       const unsigned long mix_const = 0x3f39e593UL;
+#endif
+       unsigned long raw, random = get_random_boot();
+       bool use_i8254 = true;
+
+       debug_putstr("KASLR using");
+
+       if (has_cpuflag(X86_FEATURE_RDRAND)) {
+               debug_putstr(" RDRAND");
+               if (rdrand_long(&raw)) {
+                       random ^= raw;
+                       use_i8254 = false;
+               }
+       }
+
+       if (has_cpuflag(X86_FEATURE_TSC)) {
+               debug_putstr(" RDTSC");
+               rdtscll(raw);
+
+               random ^= raw;
+               use_i8254 = false;
+       }
+
+       if (use_i8254) {
+               debug_putstr(" i8254");
+               random ^= i8254();
+       }
+
+       /* Circular multiply for better bit diffusion */
+       asm("mul %3"
+           : "=a" (random), "=d" (raw)
+           : "a" (random), "rm" (mix_const));
+       random += raw;
+
+       debug_putstr("...\n");
+
+       return random;
+}
+
+struct mem_vector {
+       unsigned long start;
+       unsigned long size;
+};
+
+#define MEM_AVOID_MAX 5
+struct mem_vector mem_avoid[MEM_AVOID_MAX];
+
+static bool mem_contains(struct mem_vector *region, struct mem_vector *item)
+{
+       /* Item at least partially before region. */
+       if (item->start < region->start)
+               return false;
+       /* Item at least partially after region. */
+       if (item->start + item->size > region->start + region->size)
+               return false;
+       return true;
+}
+
+static bool mem_overlaps(struct mem_vector *one, struct mem_vector *two)
+{
+       /* Item one is entirely before item two. */
+       if (one->start + one->size <= two->start)
+               return false;
+       /* Item one is entirely after item two. */
+       if (one->start >= two->start + two->size)
+               return false;
+       return true;
+}
+
+static void mem_avoid_init(unsigned long input, unsigned long input_size,
+                          unsigned long output, unsigned long output_size)
+{
+       u64 initrd_start, initrd_size;
+       u64 cmd_line, cmd_line_size;
+       unsigned long unsafe, unsafe_len;
+       char *ptr;
+
+       /*
+        * Avoid the region that is unsafe to overlap during
+        * decompression (see calculations at top of misc.c).
+        */
+       unsafe_len = (output_size >> 12) + 32768 + 18;
+       unsafe = (unsigned long)input + input_size - unsafe_len;
+       mem_avoid[0].start = unsafe;
+       mem_avoid[0].size = unsafe_len;
+
+       /* Avoid initrd. */
+       initrd_start  = (u64)real_mode->ext_ramdisk_image << 32;
+       initrd_start |= real_mode->hdr.ramdisk_image;
+       initrd_size  = (u64)real_mode->ext_ramdisk_size << 32;
+       initrd_size |= real_mode->hdr.ramdisk_size;
+       mem_avoid[1].start = initrd_start;
+       mem_avoid[1].size = initrd_size;
+
+       /* Avoid kernel command line. */
+       cmd_line  = (u64)real_mode->ext_cmd_line_ptr << 32;
+       cmd_line |= real_mode->hdr.cmd_line_ptr;
+       /* Calculate size of cmd_line. */
+       ptr = (char *)(unsigned long)cmd_line;
+       for (cmd_line_size = 0; ptr[cmd_line_size++]; )
+               ;
+       mem_avoid[2].start = cmd_line;
+       mem_avoid[2].size = cmd_line_size;
+
+       /* Avoid heap memory. */
+       mem_avoid[3].start = (unsigned long)free_mem_ptr;
+       mem_avoid[3].size = BOOT_HEAP_SIZE;
+
+       /* Avoid stack memory. */
+       mem_avoid[4].start = (unsigned long)free_mem_end_ptr;
+       mem_avoid[4].size = BOOT_STACK_SIZE;
+}
+
+/* Does this memory vector overlap a known avoided area? */
+bool mem_avoid_overlap(struct mem_vector *img)
+{
+       int i;
+
+       for (i = 0; i < MEM_AVOID_MAX; i++) {
+               if (mem_overlaps(img, &mem_avoid[i]))
+                       return true;
+       }
+
+       return false;
+}
+
+unsigned long slots[CONFIG_RANDOMIZE_BASE_MAX_OFFSET / CONFIG_PHYSICAL_ALIGN];
+unsigned long slot_max = 0;
+
+static void slots_append(unsigned long addr)
+{
+       /* Overflowing the slots list should be impossible. */
+       if (slot_max >= CONFIG_RANDOMIZE_BASE_MAX_OFFSET /
+                       CONFIG_PHYSICAL_ALIGN)
+               return;
+
+       slots[slot_max++] = addr;
+}
+
+static unsigned long slots_fetch_random(void)
+{
+       /* Handle case of no slots stored. */
+       if (slot_max == 0)
+               return 0;
+
+       return slots[get_random_long() % slot_max];
+}
+
+static void process_e820_entry(struct e820entry *entry,
+                              unsigned long minimum,
+                              unsigned long image_size)
+{
+       struct mem_vector region, img;
+
+       /* Skip non-RAM entries. */
+       if (entry->type != E820_RAM)
+               return;
+
+       /* Ignore entries entirely above our maximum. */
+       if (entry->addr >= CONFIG_RANDOMIZE_BASE_MAX_OFFSET)
+               return;
+
+       /* Ignore entries entirely below our minimum. */
+       if (entry->addr + entry->size < minimum)
+               return;
+
+       region.start = entry->addr;
+       region.size = entry->size;
+
+       /* Potentially raise address to minimum location. */
+       if (region.start < minimum)
+               region.start = minimum;
+
+       /* Potentially raise address to meet alignment requirements. */
+       region.start = ALIGN(region.start, CONFIG_PHYSICAL_ALIGN);
+
+       /* Did we raise the address above the bounds of this e820 region? */
+       if (region.start > entry->addr + entry->size)
+               return;
+
+       /* Reduce size by any delta from the original address. */
+       region.size -= region.start - entry->addr;
+
+       /* Reduce maximum size to fit end of image within maximum limit. */
+       if (region.start + region.size > CONFIG_RANDOMIZE_BASE_MAX_OFFSET)
+               region.size = CONFIG_RANDOMIZE_BASE_MAX_OFFSET - region.start;
+
+       /* Walk each aligned slot and check for avoided areas. */
+       for (img.start = region.start, img.size = image_size ;
+            mem_contains(&region, &img) ;
+            img.start += CONFIG_PHYSICAL_ALIGN) {
+               if (mem_avoid_overlap(&img))
+                       continue;
+               slots_append(img.start);
+       }
+}
+
+static unsigned long find_random_addr(unsigned long minimum,
+                                     unsigned long size)
+{
+       int i;
+       unsigned long addr;
+
+       /* Make sure minimum is aligned. */
+       minimum = ALIGN(minimum, CONFIG_PHYSICAL_ALIGN);
+
+       /* Verify potential e820 positions, appending to slots list. */
+       for (i = 0; i < real_mode->e820_entries; i++) {
+               process_e820_entry(&real_mode->e820_map[i], minimum, size);
+       }
+
+       return slots_fetch_random();
+}
+
+unsigned char *choose_kernel_location(unsigned char *input,
+                                     unsigned long input_size,
+                                     unsigned char *output,
+                                     unsigned long output_size)
+{
+       unsigned long choice = (unsigned long)output;
+       unsigned long random;
+
+       if (cmdline_find_option_bool("nokaslr")) {
+               debug_putstr("KASLR disabled...\n");
+               goto out;
+       }
+
+       /* Record the various known unsafe memory ranges. */
+       mem_avoid_init((unsigned long)input, input_size,
+                      (unsigned long)output, output_size);
+
+       /* Walk e820 and find a random address. */
+       random = find_random_addr(choice, output_size);
+       if (!random) {
+               debug_putstr("KASLR could not find suitable E820 region...\n");
+               goto out;
+       }
+
+       /* Always enforce the minimum. */
+       if (random < choice)
+               goto out;
+
+       choice = random;
+out:
+       return (unsigned char *)choice;
+}
+
+#endif /* CONFIG_RANDOMIZE_BASE */
index bffd73b45b1f27a4dc6cdd2ab6ee5451cd1bbd0d..b68e3033e6b9bd6fa76f89e3fbaa034823790ad7 100644 (file)
@@ -1,6 +1,6 @@
 #include "misc.h"
 
-#ifdef CONFIG_EARLY_PRINTK
+#if CONFIG_EARLY_PRINTK || CONFIG_RANDOMIZE_BASE
 
 static unsigned long fs;
 static inline void set_fs(unsigned long seg)
diff --git a/arch/x86/boot/compressed/cpuflags.c b/arch/x86/boot/compressed/cpuflags.c
new file mode 100644 (file)
index 0000000..aa31346
--- /dev/null
@@ -0,0 +1,12 @@
+#ifdef CONFIG_RANDOMIZE_BASE
+
+#include "../cpuflags.c"
+
+bool has_cpuflag(int flag)
+{
+       get_cpuflags();
+
+       return test_bit(flag, cpu.flags);
+}
+
+#endif
index 5d6f6891b1881ee812c060bc730915d73d4d7f65..9116aac232c746ae4f5262508fba437db9fbb431 100644 (file)
@@ -117,9 +117,11 @@ preferred_addr:
        addl    %eax, %ebx
        notl    %eax
        andl    %eax, %ebx
-#else
-       movl    $LOAD_PHYSICAL_ADDR, %ebx
+       cmpl    $LOAD_PHYSICAL_ADDR, %ebx
+       jge     1f
 #endif
+       movl    $LOAD_PHYSICAL_ADDR, %ebx
+1:
 
        /* Target address to relocate to for decompression */
        addl    $z_extract_offset, %ebx
@@ -191,14 +193,14 @@ relocated:
        leal    boot_heap(%ebx), %eax
        pushl   %eax            /* heap area */
        pushl   %esi            /* real mode pointer */
-       call    decompress_kernel
+       call    decompress_kernel /* returns kernel location in %eax */
        addl    $24, %esp
 
 /*
  * Jump to the decompressed kernel.
  */
        xorl    %ebx, %ebx
-       jmp     *%ebp
+       jmp     *%eax
 
 /*
  * Stack and heap for uncompression
index c337422b575de190280334ef5cd61214441644f9..c5c1ae0997e7b223128b009a220b899e22ffeb25 100644 (file)
@@ -94,9 +94,11 @@ ENTRY(startup_32)
        addl    %eax, %ebx
        notl    %eax
        andl    %eax, %ebx
-#else
-       movl    $LOAD_PHYSICAL_ADDR, %ebx
+       cmpl    $LOAD_PHYSICAL_ADDR, %ebx
+       jge     1f
 #endif
+       movl    $LOAD_PHYSICAL_ADDR, %ebx
+1:
 
        /* Target address to relocate to for decompression */
        addl    $z_extract_offset, %ebx
@@ -269,9 +271,11 @@ preferred_addr:
        addq    %rax, %rbp
        notq    %rax
        andq    %rax, %rbp
-#else
-       movq    $LOAD_PHYSICAL_ADDR, %rbp
+       cmpq    $LOAD_PHYSICAL_ADDR, %rbp
+       jge     1f
 #endif
+       movq    $LOAD_PHYSICAL_ADDR, %rbp
+1:
 
        /* Target address to relocate to for decompression */
        leaq    z_extract_offset(%rbp), %rbx
@@ -339,13 +343,13 @@ relocated:
        movl    $z_input_len, %ecx      /* input_len */
        movq    %rbp, %r8               /* output target address */
        movq    $z_output_len, %r9      /* decompressed length */
-       call    decompress_kernel
+       call    decompress_kernel       /* returns kernel location in %rax */
        popq    %rsi
 
 /*
  * Jump to the decompressed kernel.
  */
-       jmp     *%rbp
+       jmp     *%rax
 
        .code32
 no_longmode:
index 434f077d2c4d7b664216e6adaa22ac44ea51786a..196eaf373a06ad89c11bc9133a5c97b0e5ebc6d9 100644 (file)
@@ -112,14 +112,8 @@ struct boot_params *real_mode;             /* Pointer to real-mode data */
 void *memset(void *s, int c, size_t n);
 void *memcpy(void *dest, const void *src, size_t n);
 
-#ifdef CONFIG_X86_64
-#define memptr long
-#else
-#define memptr unsigned
-#endif
-
-static memptr free_mem_ptr;
-static memptr free_mem_end_ptr;
+memptr free_mem_ptr;
+memptr free_mem_end_ptr;
 
 static char *vidmem;
 static int vidport;
@@ -395,7 +389,7 @@ static void parse_elf(void *output)
        free(phdrs);
 }
 
-asmlinkage void decompress_kernel(void *rmode, memptr heap,
+asmlinkage void *decompress_kernel(void *rmode, memptr heap,
                                  unsigned char *input_data,
                                  unsigned long input_len,
                                  unsigned char *output,
@@ -422,6 +416,10 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap,
        free_mem_ptr     = heap;        /* Heap */
        free_mem_end_ptr = heap + BOOT_HEAP_SIZE;
 
+       output = choose_kernel_location(input_data, input_len,
+                                       output, output_len);
+
+       /* Validate memory location choices. */
        if ((unsigned long)output & (MIN_KERNEL_ALIGN - 1))
                error("Destination address inappropriately aligned");
 #ifdef CONFIG_X86_64
@@ -441,5 +439,5 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap,
        parse_elf(output);
        handle_relocations(output, output_len);
        debug_putstr("done.\nBooting the kernel.\n");
-       return;
+       return output;
 }
index 674019d8e2355901b69de5c55cfb92669c5628be..24e3e569a13ce9bf1ba620811ff4b09d6fa6e32d 100644 (file)
 #define BOOT_BOOT_H
 #include "../ctype.h"
 
+#ifdef CONFIG_X86_64
+#define memptr long
+#else
+#define memptr unsigned
+#endif
+
 /* misc.c */
+extern memptr free_mem_ptr;
+extern memptr free_mem_end_ptr;
 extern struct boot_params *real_mode;          /* Pointer to real-mode data */
 void __putstr(const char *s);
 #define error_putstr(__x)  __putstr(__x)
@@ -39,23 +47,40 @@ static inline void debug_putstr(const char *s)
 
 #endif
 
-#ifdef CONFIG_EARLY_PRINTK
-
+#if CONFIG_EARLY_PRINTK || CONFIG_RANDOMIZE_BASE
 /* cmdline.c */
 int cmdline_find_option(const char *option, char *buffer, int bufsize);
 int cmdline_find_option_bool(const char *option);
+#endif
 
-/* early_serial_console.c */
-extern int early_serial_base;
-void console_init(void);
 
+#if CONFIG_RANDOMIZE_BASE
+/* aslr.c */
+unsigned char *choose_kernel_location(unsigned char *input,
+                                     unsigned long input_size,
+                                     unsigned char *output,
+                                     unsigned long output_size);
+/* cpuflags.c */
+bool has_cpuflag(int flag);
 #else
+static inline
+unsigned char *choose_kernel_location(unsigned char *input,
+                                     unsigned long input_size,
+                                     unsigned char *output,
+                                     unsigned long output_size)
+{
+       return output;
+}
+#endif
 
+#ifdef CONFIG_EARLY_PRINTK
 /* early_serial_console.c */
+extern int early_serial_base;
+void console_init(void);
+#else
 static const int early_serial_base;
 static inline void console_init(void)
 { }
-
 #endif
 
 #endif
index 4d3ff037201ffbee0bb468e04d069b02909d094d..100a9a10076a649e7e7008a3579867391ca16fa4 100644 (file)
@@ -28,8 +28,6 @@
 #include <asm/required-features.h>
 #include <asm/msr-index.h>
 
-struct cpu_features cpu;
-static u32 cpu_vendor[3];
 static u32 err_flags[NCAPINTS];
 
 static const int req_level = CONFIG_X86_MINIMUM_CPU_FAMILY;
@@ -69,92 +67,8 @@ static int is_transmeta(void)
               cpu_vendor[2] == A32('M', 'x', '8', '6');
 }
 
-static int has_fpu(void)
-{
-       u16 fcw = -1, fsw = -1;
-       u32 cr0;
-
-       asm("movl %%cr0,%0" : "=r" (cr0));
-       if (cr0 & (X86_CR0_EM|X86_CR0_TS)) {
-               cr0 &= ~(X86_CR0_EM|X86_CR0_TS);
-               asm volatile("movl %0,%%cr0" : : "r" (cr0));
-       }
-
-       asm volatile("fninit ; fnstsw %0 ; fnstcw %1"
-                    : "+m" (fsw), "+m" (fcw));
-
-       return fsw == 0 && (fcw & 0x103f) == 0x003f;
-}
-
-static int has_eflag(u32 mask)
-{
-       u32 f0, f1;
-
-       asm("pushfl ; "
-           "pushfl ; "
-           "popl %0 ; "
-           "movl %0,%1 ; "
-           "xorl %2,%1 ; "
-           "pushl %1 ; "
-           "popfl ; "
-           "pushfl ; "
-           "popl %1 ; "
-           "popfl"
-           : "=&r" (f0), "=&r" (f1)
-           : "ri" (mask));
-
-       return !!((f0^f1) & mask);
-}
-
-static void get_flags(void)
-{
-       u32 max_intel_level, max_amd_level;
-       u32 tfms;
-
-       if (has_fpu())
-               set_bit(X86_FEATURE_FPU, cpu.flags);
-
-       if (has_eflag(X86_EFLAGS_ID)) {
-               asm("cpuid"
-                   : "=a" (max_intel_level),
-                     "=b" (cpu_vendor[0]),
-                     "=d" (cpu_vendor[1]),
-                     "=c" (cpu_vendor[2])
-                   : "a" (0));
-
-               if (max_intel_level >= 0x00000001 &&
-                   max_intel_level <= 0x0000ffff) {
-                       asm("cpuid"
-                           : "=a" (tfms),
-                             "=c" (cpu.flags[4]),
-                             "=d" (cpu.flags[0])
-                           : "a" (0x00000001)
-                           : "ebx");
-                       cpu.level = (tfms >> 8) & 15;
-                       cpu.model = (tfms >> 4) & 15;
-                       if (cpu.level >= 6)
-                               cpu.model += ((tfms >> 16) & 0xf) << 4;
-               }
-
-               asm("cpuid"
-                   : "=a" (max_amd_level)
-                   : "a" (0x80000000)
-                   : "ebx", "ecx", "edx");
-
-               if (max_amd_level >= 0x80000001 &&
-                   max_amd_level <= 0x8000ffff) {
-                       u32 eax = 0x80000001;
-                       asm("cpuid"
-                           : "+a" (eax),
-                             "=c" (cpu.flags[6]),
-                             "=d" (cpu.flags[1])
-                           : : "ebx");
-               }
-       }
-}
-
 /* Returns a bitmask of which words we have error bits in */
-static int check_flags(void)
+static int check_cpuflags(void)
 {
        u32 err;
        int i;
@@ -187,8 +101,8 @@ int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr)
        if (has_eflag(X86_EFLAGS_AC))
                cpu.level = 4;
 
-       get_flags();
-       err = check_flags();
+       get_cpuflags();
+       err = check_cpuflags();
 
        if (test_bit(X86_FEATURE_LM, cpu.flags))
                cpu.level = 64;
@@ -207,8 +121,8 @@ int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr)
                eax &= ~(1 << 15);
                asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx));
 
-               get_flags();    /* Make sure it really did something */
-               err = check_flags();
+               get_cpuflags(); /* Make sure it really did something */
+               err = check_cpuflags();
        } else if (err == 0x01 &&
                   !(err_flags[0] & ~(1 << X86_FEATURE_CX8)) &&
                   is_centaur() && cpu.model >= 6) {
@@ -223,7 +137,7 @@ int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr)
                asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx));
 
                set_bit(X86_FEATURE_CX8, cpu.flags);
-               err = check_flags();
+               err = check_cpuflags();
        } else if (err == 0x01 && is_transmeta()) {
                /* Transmeta might have masked feature bits in word 0 */
 
@@ -238,7 +152,7 @@ int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr)
                    : : "ecx", "ebx");
                asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx));
 
-               err = check_flags();
+               err = check_cpuflags();
        }
 
        if (err_flags_ptr)
diff --git a/arch/x86/boot/cpuflags.c b/arch/x86/boot/cpuflags.c
new file mode 100644 (file)
index 0000000..a9fcb7c
--- /dev/null
@@ -0,0 +1,104 @@
+#include <linux/types.h>
+#include "bitops.h"
+
+#include <asm/processor-flags.h>
+#include <asm/required-features.h>
+#include <asm/msr-index.h>
+#include "cpuflags.h"
+
+struct cpu_features cpu;
+u32 cpu_vendor[3];
+
+static bool loaded_flags;
+
+static int has_fpu(void)
+{
+       u16 fcw = -1, fsw = -1;
+       unsigned long cr0;
+
+       asm volatile("mov %%cr0,%0" : "=r" (cr0));
+       if (cr0 & (X86_CR0_EM|X86_CR0_TS)) {
+               cr0 &= ~(X86_CR0_EM|X86_CR0_TS);
+               asm volatile("mov %0,%%cr0" : : "r" (cr0));
+       }
+
+       asm volatile("fninit ; fnstsw %0 ; fnstcw %1"
+                    : "+m" (fsw), "+m" (fcw));
+
+       return fsw == 0 && (fcw & 0x103f) == 0x003f;
+}
+
+int has_eflag(unsigned long mask)
+{
+       unsigned long f0, f1;
+
+       asm volatile("pushf     \n\t"
+                    "pushf     \n\t"
+                    "pop %0    \n\t"
+                    "mov %0,%1 \n\t"
+                    "xor %2,%1 \n\t"
+                    "push %1   \n\t"
+                    "popf      \n\t"
+                    "pushf     \n\t"
+                    "pop %1    \n\t"
+                    "popf"
+                    : "=&r" (f0), "=&r" (f1)
+                    : "ri" (mask));
+
+       return !!((f0^f1) & mask);
+}
+
+/* Handle x86_32 PIC using ebx. */
+#if defined(__i386__) && defined(__PIC__)
+# define EBX_REG "=r"
+#else
+# define EBX_REG "=b"
+#endif
+
+static inline void cpuid(u32 id, u32 *a, u32 *b, u32 *c, u32 *d)
+{
+       asm volatile(".ifnc %%ebx,%3 ; movl  %%ebx,%3 ; .endif  \n\t"
+                    "cpuid                                     \n\t"
+                    ".ifnc %%ebx,%3 ; xchgl %%ebx,%3 ; .endif  \n\t"
+                   : "=a" (*a), "=c" (*c), "=d" (*d), EBX_REG (*b)
+                   : "a" (id)
+       );
+}
+
+void get_cpuflags(void)
+{
+       u32 max_intel_level, max_amd_level;
+       u32 tfms;
+       u32 ignored;
+
+       if (loaded_flags)
+               return;
+       loaded_flags = true;
+
+       if (has_fpu())
+               set_bit(X86_FEATURE_FPU, cpu.flags);
+
+       if (has_eflag(X86_EFLAGS_ID)) {
+               cpuid(0x0, &max_intel_level, &cpu_vendor[0], &cpu_vendor[2],
+                     &cpu_vendor[1]);
+
+               if (max_intel_level >= 0x00000001 &&
+                   max_intel_level <= 0x0000ffff) {
+                       cpuid(0x1, &tfms, &ignored, &cpu.flags[4],
+                             &cpu.flags[0]);
+                       cpu.level = (tfms >> 8) & 15;
+                       cpu.model = (tfms >> 4) & 15;
+                       if (cpu.level >= 6)
+                               cpu.model += ((tfms >> 16) & 0xf) << 4;
+               }
+
+               cpuid(0x80000000, &max_amd_level, &ignored, &ignored,
+                     &ignored);
+
+               if (max_amd_level >= 0x80000001 &&
+                   max_amd_level <= 0x8000ffff) {
+                       cpuid(0x80000001, &ignored, &ignored, &cpu.flags[6],
+                             &cpu.flags[1]);
+               }
+       }
+}
diff --git a/arch/x86/boot/cpuflags.h b/arch/x86/boot/cpuflags.h
new file mode 100644 (file)
index 0000000..ea97697
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef BOOT_CPUFLAGS_H
+#define BOOT_CPUFLAGS_H
+
+#include <asm/cpufeature.h>
+#include <asm/processor-flags.h>
+
+struct cpu_features {
+       int level;              /* Family, or 64 for x86-64 */
+       int model;
+       u32 flags[NCAPINTS];
+};
+
+extern struct cpu_features cpu;
+extern u32 cpu_vendor[3];
+
+int has_eflag(unsigned long mask);
+void get_cpuflags(void);
+
+#endif
index 0d9ec770f2f8770f8e5a320300ea47f3bf39b9bb..e6a92455740e6a5dfc64c5b1a1193a693594feab 100644 (file)
 
 #ifdef CONFIG_ARCH_RANDOM
 
+/* Instead of arch_get_random_long() when alternatives haven't run. */
+static inline int rdrand_long(unsigned long *v)
+{
+       int ok;
+       asm volatile("1: " RDRAND_LONG "\n\t"
+                    "jc 2f\n\t"
+                    "decl %0\n\t"
+                    "jnz 1b\n\t"
+                    "2:"
+                    : "=r" (ok), "=a" (*v)
+                    : "0" (RDRAND_RETRY_LOOPS));
+       return ok;
+}
+
 #define GET_RANDOM(name, type, rdrand, nop)                    \
 static inline int name(type *v)                                        \
 {                                                              \
@@ -68,6 +82,13 @@ GET_RANDOM(arch_get_random_int, unsigned int, RDRAND_INT, ASM_NOP3);
 
 #endif /* CONFIG_X86_64 */
 
+#else
+
+static inline int rdrand_long(unsigned long *v)
+{
+       return 0;
+}
+
 #endif  /* CONFIG_ARCH_RANDOM */
 
 extern void x86_init_rdrand(struct cpuinfo_x86 *c);
index da31c8b8a92ddd0459bc1b6a0a7058f4d1f93766..b17f4f48ecd7d9a48646a295c7ffaaa544399fa8 100644 (file)
@@ -77,7 +77,7 @@ static inline void atomic_sub(int i, atomic_t *v)
  */
 static inline int atomic_sub_and_test(int i, atomic_t *v)
 {
-       GEN_BINARY_RMWcc(LOCK_PREFIX "subl", v->counter, i, "%0", "e");
+       GEN_BINARY_RMWcc(LOCK_PREFIX "subl", v->counter, "er", i, "%0", "e");
 }
 
 /**
@@ -141,7 +141,7 @@ static inline int atomic_inc_and_test(atomic_t *v)
  */
 static inline int atomic_add_negative(int i, atomic_t *v)
 {
-       GEN_BINARY_RMWcc(LOCK_PREFIX "addl", v->counter, i, "%0", "s");
+       GEN_BINARY_RMWcc(LOCK_PREFIX "addl", v->counter, "er", i, "%0", "s");
 }
 
 /**
index 3f065c985aeed272d120e3cec19f04b9ee9f5254..46e9052bbd28cdea457130607cd5a50ddc5c6204 100644 (file)
@@ -72,7 +72,7 @@ static inline void atomic64_sub(long i, atomic64_t *v)
  */
 static inline int atomic64_sub_and_test(long i, atomic64_t *v)
 {
-       GEN_BINARY_RMWcc(LOCK_PREFIX "subq", v->counter, i, "%0", "e");
+       GEN_BINARY_RMWcc(LOCK_PREFIX "subq", v->counter, "er", i, "%0", "e");
 }
 
 /**
@@ -138,7 +138,7 @@ static inline int atomic64_inc_and_test(atomic64_t *v)
  */
 static inline int atomic64_add_negative(long i, atomic64_t *v)
 {
-       GEN_BINARY_RMWcc(LOCK_PREFIX "addq", v->counter, i, "%0", "s");
+       GEN_BINARY_RMWcc(LOCK_PREFIX "addq", v->counter, "er", i, "%0", "s");
 }
 
 /**
index 6d76d093598930ce24476118fd68d690bb78035c..9fc1af74dc8393a5107742f12f82dd47be1db0ea 100644 (file)
@@ -205,7 +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)
 {
-       GEN_BINARY_RMWcc(LOCK_PREFIX "bts", *addr, nr, "%0", "c");
+       GEN_BINARY_RMWcc(LOCK_PREFIX "bts", *addr, "Ir", nr, "%0", "c");
 }
 
 /**
@@ -251,7 +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)
 {
-       GEN_BINARY_RMWcc(LOCK_PREFIX "btr", *addr, nr, "%0", "c");
+       GEN_BINARY_RMWcc(LOCK_PREFIX "btr", *addr, "Ir", nr, "%0", "c");
 }
 
 /**
@@ -304,7 +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)
 {
-       GEN_BINARY_RMWcc(LOCK_PREFIX "btc", *addr, nr, "%0", "c");
+       GEN_BINARY_RMWcc(LOCK_PREFIX "btc", *addr, "Ir", nr, "%0", "c");
 }
 
 static __always_inline int constant_test_bit(long nr, const volatile unsigned long *addr)
index 65c6e6e3a5521bc73e843a5459b63ec99e02d689..89a05b0507b98dbbb2ed83169c59058f044704a7 100644 (file)
@@ -1,6 +1,24 @@
 #ifndef _ASM_X86_EFI_H
 #define _ASM_X86_EFI_H
 
+/*
+ * We map the EFI regions needed for runtime services non-contiguously,
+ * with preserved alignment on virtual addresses starting from -4G down
+ * for a total max space of 64G. This way, we provide for stable runtime
+ * services addresses across kernels so that a kexec'd kernel can still
+ * use them.
+ *
+ * This is the main reason why we're doing stable VA mappings for RT
+ * services.
+ *
+ * This flag is used in conjuction with a chicken bit called
+ * "efi=old_map" which can be used as a fallback to the old runtime
+ * services mapping method in case there's some b0rkage with a
+ * particular EFI implementation (haha, it is hard to hold up the
+ * sarcasm here...).
+ */
+#define EFI_OLD_MEMMAP         EFI_ARCH_1
+
 #ifdef CONFIG_X86_32
 
 #define EFI_LOADER_SIGNATURE   "EL32"
@@ -69,24 +87,31 @@ extern u64 efi_call6(void *fp, u64 arg1, u64 arg2, u64 arg3,
        efi_call6((f), (u64)(a1), (u64)(a2), (u64)(a3),         \
                  (u64)(a4), (u64)(a5), (u64)(a6))
 
+#define _efi_call_virtX(x, f, ...)                                     \
+({                                                                     \
+       efi_status_t __s;                                               \
+                                                                       \
+       efi_sync_low_kernel_mappings();                                 \
+       preempt_disable();                                              \
+       __s = efi_call##x((void *)efi.systab->runtime->f, __VA_ARGS__); \
+       preempt_enable();                                               \
+       __s;                                                            \
+})
+
 #define efi_call_virt0(f)                              \
-       efi_call0((efi.systab->runtime->f))
-#define efi_call_virt1(f, a1)                                  \
-       efi_call1((efi.systab->runtime->f), (u64)(a1))
-#define efi_call_virt2(f, a1, a2)                                      \
-       efi_call2((efi.systab->runtime->f), (u64)(a1), (u64)(a2))
-#define efi_call_virt3(f, a1, a2, a3)                                  \
-       efi_call3((efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
-                 (u64)(a3))
-#define efi_call_virt4(f, a1, a2, a3, a4)                              \
-       efi_call4((efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
-                 (u64)(a3), (u64)(a4))
-#define efi_call_virt5(f, a1, a2, a3, a4, a5)                          \
-       efi_call5((efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
-                 (u64)(a3), (u64)(a4), (u64)(a5))
-#define efi_call_virt6(f, a1, a2, a3, a4, a5, a6)                      \
-       efi_call6((efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
-                 (u64)(a3), (u64)(a4), (u64)(a5), (u64)(a6))
+       _efi_call_virtX(0, f)
+#define efi_call_virt1(f, a1)                          \
+       _efi_call_virtX(1, f, (u64)(a1))
+#define efi_call_virt2(f, a1, a2)                      \
+       _efi_call_virtX(2, f, (u64)(a1), (u64)(a2))
+#define efi_call_virt3(f, a1, a2, a3)                  \
+       _efi_call_virtX(3, f, (u64)(a1), (u64)(a2), (u64)(a3))
+#define efi_call_virt4(f, a1, a2, a3, a4)              \
+       _efi_call_virtX(4, f, (u64)(a1), (u64)(a2), (u64)(a3), (u64)(a4))
+#define efi_call_virt5(f, a1, a2, a3, a4, a5)          \
+       _efi_call_virtX(5, f, (u64)(a1), (u64)(a2), (u64)(a3), (u64)(a4), (u64)(a5))
+#define efi_call_virt6(f, a1, a2, a3, a4, a5, a6)      \
+       _efi_call_virtX(6, f, (u64)(a1), (u64)(a2), (u64)(a3), (u64)(a4), (u64)(a5), (u64)(a6))
 
 extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size,
                                 u32 type, u64 attribute);
@@ -95,12 +120,17 @@ extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size,
 
 extern int add_efi_memmap;
 extern unsigned long x86_efi_facility;
+extern struct efi_scratch efi_scratch;
 extern void efi_set_executable(efi_memory_desc_t *md, bool executable);
 extern int efi_memblock_x86_reserve_range(void);
 extern void efi_call_phys_prelog(void);
 extern void efi_call_phys_epilog(void);
 extern void efi_unmap_memmap(void);
 extern void efi_memory_uc(u64 addr, unsigned long size);
+extern void __init efi_map_region(efi_memory_desc_t *md);
+extern void efi_sync_low_kernel_mappings(void);
+extern void efi_setup_page_tables(void);
+extern void __init old_map_region(efi_memory_desc_t *md);
 
 #ifdef CONFIG_EFI
 
index 5b23e605e707cb21e254f7ce964029a48b69ee54..4ad6560847b1f5f7c20644b52e27505339880e79 100644 (file)
@@ -52,7 +52,7 @@ static inline void local_sub(long i, local_t *l)
  */
 static inline int local_sub_and_test(long i, local_t *l)
 {
-       GEN_BINARY_RMWcc(_ASM_SUB, l->a.counter, i, "%0", "e");
+       GEN_BINARY_RMWcc(_ASM_SUB, l->a.counter, "er", i, "%0", "e");
 }
 
 /**
@@ -92,7 +92,7 @@ static inline int local_inc_and_test(local_t *l)
  */
 static inline int local_add_negative(long i, local_t *l)
 {
-       GEN_BINARY_RMWcc(_ASM_ADD, l->a.counter, i, "%0", "s");
+       GEN_BINARY_RMWcc(_ASM_ADD, l->a.counter, "er", i, "%0", "s");
 }
 
 /**
index c87892442e53d4081f4ff1276524e0298cf73617..775873d3be55617a49e15c3460ae22a94dabad75 100644 (file)
@@ -71,6 +71,7 @@ extern bool __virt_addr_valid(unsigned long kaddr);
 #include <asm-generic/getorder.h>
 
 #define __HAVE_ARCH_GATE_AREA 1
+#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_X86_PAGE_H */
index 4d550d04b6099bf444e8291ffdfde9538a4e47df..904f528cc8e82ae638e25a2bdeec23fed332eb7a 100644 (file)
@@ -5,10 +5,6 @@
 
 #ifndef __ASSEMBLY__
 
-#ifdef CONFIG_HUGETLB_PAGE
-#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
-#endif
-
 #define __phys_addr_nodebug(x) ((x) - PAGE_OFFSET)
 #ifdef CONFIG_DEBUG_VIRTUAL
 extern unsigned long __phys_addr(unsigned long);
index 43dcd804ebd5732aea40415e6f4a419e363701c9..8de6d9cf3b954a7f31bcb756c92c20cc08db5759 100644 (file)
 #define __VIRTUAL_MASK_SHIFT   47
 
 /*
- * Kernel image size is limited to 512 MB (see level2_kernel_pgt in
- * arch/x86/kernel/head_64.S), and it is mapped here:
+ * Kernel image size is limited to 1GiB due to the fixmap living in the
+ * next 1GiB (see level2_kernel_pgt in arch/x86/kernel/head_64.S). Use
+ * 512MiB by default, leaving 1.5GiB for modules once the page tables
+ * are fully set up. If kernel ASLR is configured, it can extend the
+ * kernel page table mapping, reducing the size of the modules area.
  */
-#define KERNEL_IMAGE_SIZE      (512 * 1024 * 1024)
+#define KERNEL_IMAGE_SIZE_DEFAULT      (512 * 1024 * 1024)
+#if defined(CONFIG_RANDOMIZE_BASE) && \
+       CONFIG_RANDOMIZE_BASE_MAX_OFFSET > KERNEL_IMAGE_SIZE_DEFAULT
+#define KERNEL_IMAGE_SIZE   CONFIG_RANDOMIZE_BASE_MAX_OFFSET
+#else
+#define KERNEL_IMAGE_SIZE      KERNEL_IMAGE_SIZE_DEFAULT
+#endif
 
 #endif /* _ASM_X86_PAGE_64_DEFS_H */
index 3bf2dd0cf61fec9615253fe3b70d3c3764a35e93..0d193e23464707e3d56111e2d429664104a3649f 100644 (file)
@@ -55,6 +55,13 @@ static inline pmd_t native_pmdp_get_and_clear(pmd_t *xp)
 #define native_pmdp_get_and_clear(xp) native_local_pmdp_get_and_clear(xp)
 #endif
 
+/* Bit manipulation helper on pte/pgoff entry */
+static inline unsigned long pte_bitop(unsigned long value, unsigned int rightshift,
+                                     unsigned long mask, unsigned int leftshift)
+{
+       return ((value >> rightshift) & mask) << leftshift;
+}
+
 #ifdef CONFIG_MEM_SOFT_DIRTY
 
 /*
@@ -71,31 +78,34 @@ static inline pmd_t native_pmdp_get_and_clear(pmd_t *xp)
 #define PTE_FILE_BITS2         (PTE_FILE_SHIFT3 - PTE_FILE_SHIFT2 - 1)
 #define PTE_FILE_BITS3         (PTE_FILE_SHIFT4 - PTE_FILE_SHIFT3 - 1)
 
-#define pte_to_pgoff(pte)                                              \
-       ((((pte).pte_low >> (PTE_FILE_SHIFT1))                          \
-         & ((1U << PTE_FILE_BITS1) - 1)))                              \
-       + ((((pte).pte_low >> (PTE_FILE_SHIFT2))                        \
-           & ((1U << PTE_FILE_BITS2) - 1))                             \
-          << (PTE_FILE_BITS1))                                         \
-       + ((((pte).pte_low >> (PTE_FILE_SHIFT3))                        \
-           & ((1U << PTE_FILE_BITS3) - 1))                             \
-          << (PTE_FILE_BITS1 + PTE_FILE_BITS2))                        \
-       + ((((pte).pte_low >> (PTE_FILE_SHIFT4)))                       \
-           << (PTE_FILE_BITS1 + PTE_FILE_BITS2 + PTE_FILE_BITS3))
-
-#define pgoff_to_pte(off)                                              \
-       ((pte_t) { .pte_low =                                           \
-        ((((off)) & ((1U << PTE_FILE_BITS1) - 1)) << PTE_FILE_SHIFT1)  \
-        + ((((off) >> PTE_FILE_BITS1)                                  \
-            & ((1U << PTE_FILE_BITS2) - 1))                            \
-           << PTE_FILE_SHIFT2)                                         \
-        + ((((off) >> (PTE_FILE_BITS1 + PTE_FILE_BITS2))               \
-            & ((1U << PTE_FILE_BITS3) - 1))                            \
-           << PTE_FILE_SHIFT3)                                         \
-        + ((((off) >>                                                  \
-             (PTE_FILE_BITS1 + PTE_FILE_BITS2 + PTE_FILE_BITS3)))      \
-           << PTE_FILE_SHIFT4)                                         \
-        + _PAGE_FILE })
+#define PTE_FILE_MASK1         ((1U << PTE_FILE_BITS1) - 1)
+#define PTE_FILE_MASK2         ((1U << PTE_FILE_BITS2) - 1)
+#define PTE_FILE_MASK3         ((1U << PTE_FILE_BITS3) - 1)
+
+#define PTE_FILE_LSHIFT2       (PTE_FILE_BITS1)
+#define PTE_FILE_LSHIFT3       (PTE_FILE_BITS1 + PTE_FILE_BITS2)
+#define PTE_FILE_LSHIFT4       (PTE_FILE_BITS1 + PTE_FILE_BITS2 + PTE_FILE_BITS3)
+
+static __always_inline pgoff_t pte_to_pgoff(pte_t pte)
+{
+       return (pgoff_t)
+               (pte_bitop(pte.pte_low, PTE_FILE_SHIFT1, PTE_FILE_MASK1,  0)                +
+                pte_bitop(pte.pte_low, PTE_FILE_SHIFT2, PTE_FILE_MASK2,  PTE_FILE_LSHIFT2) +
+                pte_bitop(pte.pte_low, PTE_FILE_SHIFT3, PTE_FILE_MASK3,  PTE_FILE_LSHIFT3) +
+                pte_bitop(pte.pte_low, PTE_FILE_SHIFT4,           -1UL,  PTE_FILE_LSHIFT4));
+}
+
+static __always_inline pte_t pgoff_to_pte(pgoff_t off)
+{
+       return (pte_t){
+               .pte_low =
+                       pte_bitop(off,                0, PTE_FILE_MASK1,  PTE_FILE_SHIFT1) +
+                       pte_bitop(off, PTE_FILE_LSHIFT2, PTE_FILE_MASK2,  PTE_FILE_SHIFT2) +
+                       pte_bitop(off, PTE_FILE_LSHIFT3, PTE_FILE_MASK3,  PTE_FILE_SHIFT3) +
+                       pte_bitop(off, PTE_FILE_LSHIFT4,           -1UL,  PTE_FILE_SHIFT4) +
+                       _PAGE_FILE,
+       };
+}
 
 #else /* CONFIG_MEM_SOFT_DIRTY */
 
@@ -115,22 +125,30 @@ static inline pmd_t native_pmdp_get_and_clear(pmd_t *xp)
 #define PTE_FILE_BITS1         (PTE_FILE_SHIFT2 - PTE_FILE_SHIFT1 - 1)
 #define PTE_FILE_BITS2         (PTE_FILE_SHIFT3 - PTE_FILE_SHIFT2 - 1)
 
-#define pte_to_pgoff(pte)                                              \
-       ((((pte).pte_low >> PTE_FILE_SHIFT1)                            \
-         & ((1U << PTE_FILE_BITS1) - 1))                               \
-        + ((((pte).pte_low >> PTE_FILE_SHIFT2)                         \
-            & ((1U << PTE_FILE_BITS2) - 1)) << PTE_FILE_BITS1)         \
-        + (((pte).pte_low >> PTE_FILE_SHIFT3)                          \
-           << (PTE_FILE_BITS1 + PTE_FILE_BITS2)))
-
-#define pgoff_to_pte(off)                                              \
-       ((pte_t) { .pte_low =                                           \
-        (((off) & ((1U << PTE_FILE_BITS1) - 1)) << PTE_FILE_SHIFT1)    \
-        + ((((off) >> PTE_FILE_BITS1) & ((1U << PTE_FILE_BITS2) - 1))  \
-           << PTE_FILE_SHIFT2)                                         \
-        + (((off) >> (PTE_FILE_BITS1 + PTE_FILE_BITS2))                \
-           << PTE_FILE_SHIFT3)                                         \
-        + _PAGE_FILE })
+#define PTE_FILE_MASK1         ((1U << PTE_FILE_BITS1) - 1)
+#define PTE_FILE_MASK2         ((1U << PTE_FILE_BITS2) - 1)
+
+#define PTE_FILE_LSHIFT2       (PTE_FILE_BITS1)
+#define PTE_FILE_LSHIFT3       (PTE_FILE_BITS1 + PTE_FILE_BITS2)
+
+static __always_inline pgoff_t pte_to_pgoff(pte_t pte)
+{
+       return (pgoff_t)
+               (pte_bitop(pte.pte_low, PTE_FILE_SHIFT1, PTE_FILE_MASK1,  0)                +
+                pte_bitop(pte.pte_low, PTE_FILE_SHIFT2, PTE_FILE_MASK2,  PTE_FILE_LSHIFT2) +
+                pte_bitop(pte.pte_low, PTE_FILE_SHIFT3,           -1UL,  PTE_FILE_LSHIFT3));
+}
+
+static __always_inline pte_t pgoff_to_pte(pgoff_t off)
+{
+       return (pte_t){
+               .pte_low =
+                       pte_bitop(off,                0, PTE_FILE_MASK1,  PTE_FILE_SHIFT1) +
+                       pte_bitop(off, PTE_FILE_LSHIFT2, PTE_FILE_MASK2,  PTE_FILE_SHIFT2) +
+                       pte_bitop(off, PTE_FILE_LSHIFT3,           -1UL,  PTE_FILE_SHIFT3) +
+                       _PAGE_FILE,
+       };
+}
 
 #endif /* CONFIG_MEM_SOFT_DIRTY */
 
index 2d883440cb9a282f948d7062684c52789e95d90f..c883bf726398a2556d50b984736ad068bc0dd44c 100644 (file)
@@ -58,7 +58,7 @@ typedef struct { pteval_t pte; } pte_t;
 #define VMALLOC_START    _AC(0xffffc90000000000, UL)
 #define VMALLOC_END      _AC(0xffffe8ffffffffff, UL)
 #define VMEMMAP_START   _AC(0xffffea0000000000, UL)
-#define MODULES_VADDR    _AC(0xffffffffa0000000, UL)
+#define MODULES_VADDR    (__START_KERNEL_map + KERNEL_IMAGE_SIZE)
 #define MODULES_END      _AC(0xffffffffff000000, UL)
 #define MODULES_LEN   (MODULES_END - MODULES_VADDR)
 
index 0ecac257fb26cffd2bb9a6ece7b7a5976eca3c84..a83aa44bb1fb831cac7cda82a590c05ea0e47235 100644 (file)
@@ -382,7 +382,8 @@ static inline void update_page_count(int level, unsigned long pages) { }
  */
 extern pte_t *lookup_address(unsigned long address, unsigned int *level);
 extern phys_addr_t slow_virt_to_phys(void *__address);
-
+extern int kernel_map_pages_in_pgd(pgd_t *pgd, u64 pfn, unsigned long address,
+                                  unsigned numpages, unsigned long page_flags);
 #endif /* !__ASSEMBLY__ */
 
 #endif /* _ASM_X86_PGTABLE_DEFS_H */
index 1ff990f1de8e3f58f21fda00bc1a646b96eaba2b..8f7866a5b9a41df67475892353979c005ce8c09b 100644 (file)
@@ -16,8 +16,8 @@ cc_label:                                                             \
 #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))
+#define GEN_BINARY_RMWcc(op, var, vcon, val, arg0, cc)                 \
+       __GEN_RMWcc(op " %1, " arg0, var, cc, vcon (val))
 
 #else /* !CC_HAVE_ASM_GOTO */
 
@@ -33,8 +33,8 @@ do {                                                                  \
 #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))
+#define GEN_BINARY_RMWcc(op, var, vcon, val, arg0, cc)                 \
+       __GEN_RMWcc(op " %2, " arg0, var, cc, vcon (val))
 
 #endif /* CC_HAVE_ASM_GOTO */
 
index 2874df24e7a448cd56631d87f5ac9e0fdd00cbc7..4cab890007a7267ecc7ce148eaa1fdfbee4a49df 100644 (file)
@@ -71,6 +71,17 @@ DEFINE_IRQ_VECTOR_EVENT(x86_platform_ipi);
  */
 DEFINE_IRQ_VECTOR_EVENT(irq_work);
 
+/*
+ * We must dis-allow sampling irq_work_exit() because perf event sampling
+ * itself can cause irq_work, which would lead to an infinite loop;
+ *
+ *  1) irq_work_exit happens
+ *  2) generates perf sample
+ *  3) generates irq_work
+ *  4) goto 1
+ */
+TRACE_EVENT_PERF_PERM(irq_work_exit, is_sampling_event(p_event) ? -EPERM : 0);
+
 /*
  * call_function - called when entering/exiting a call function interrupt
  * vector handler
index 00c77cf78e9e1839973923076053fdf92d75a54e..ccbf857d1d558461eb59139784faa2d0f43cabc9 100644 (file)
@@ -21,9 +21,7 @@
 #include <asm/apic.h>
 #include <asm/ipi.h>
 
-#ifdef CONFIG_ACPI
-#include <acpi/acpi_bus.h>
-#endif
+#include <linux/acpi.h>
 
 static struct apic apic_physflat;
 static struct apic apic_flat;
index e63a5bd2a78f55de2c356b665751558a73bc18da..4d67a7531d4558c6016c9a6e1f16dc07b97205c2 100644 (file)
@@ -37,9 +37,6 @@
 #include <linux/kthread.h>
 #include <linux/jiffies.h>     /* time_after() */
 #include <linux/slab.h>
-#ifdef CONFIG_ACPI
-#include <acpi/acpi_bus.h>
-#endif
 #include <linux/bootmem.h>
 #include <linux/dmar.h>
 #include <linux/hpet.h>
index 47b56a7e99cbcf2e4387fd087cddbfb1c35060bc..6359506a19ee6bbc22ca634b42e0ecec689c86c3 100644 (file)
@@ -36,7 +36,7 @@ obj-$(CONFIG_CPU_SUP_AMD)             += perf_event_amd_iommu.o
 endif
 obj-$(CONFIG_CPU_SUP_INTEL)            += perf_event_p6.o perf_event_knc.o perf_event_p4.o
 obj-$(CONFIG_CPU_SUP_INTEL)            += perf_event_intel_lbr.o perf_event_intel_ds.o perf_event_intel.o
-obj-$(CONFIG_CPU_SUP_INTEL)            += perf_event_intel_uncore.o
+obj-$(CONFIG_CPU_SUP_INTEL)            += perf_event_intel_uncore.o perf_event_intel_rapl.o
 endif
 
 
diff --git a/arch/x86/kernel/cpu/perf_event_intel_rapl.c b/arch/x86/kernel/cpu/perf_event_intel_rapl.c
new file mode 100644 (file)
index 0000000..bf8e4a7
--- /dev/null
@@ -0,0 +1,661 @@
+/*
+ * perf_event_intel_rapl.c: support Intel RAPL energy consumption counters
+ * Copyright (C) 2013 Google, Inc., Stephane Eranian
+ *
+ * Intel RAPL interface is specified in the IA-32 Manual Vol3b
+ * section 14.7.1 (September 2013)
+ *
+ * RAPL provides more controls than just reporting energy consumption
+ * however here we only expose the 3 energy consumption free running
+ * counters (pp0, pkg, dram).
+ *
+ * Each of those counters increments in a power unit defined by the
+ * RAPL_POWER_UNIT MSR. On SandyBridge, this unit is 1/(2^16) Joules
+ * but it can vary.
+ *
+ * Counter to rapl events mappings:
+ *
+ *  pp0 counter: consumption of all physical cores (power plane 0)
+ *       event: rapl_energy_cores
+ *    perf code: 0x1
+ *
+ *  pkg counter: consumption of the whole processor package
+ *       event: rapl_energy_pkg
+ *    perf code: 0x2
+ *
+ * dram counter: consumption of the dram domain (servers only)
+ *       event: rapl_energy_dram
+ *    perf code: 0x3
+ *
+ * We manage those counters as free running (read-only). They may be
+ * use simultaneously by other tools, such as turbostat.
+ *
+ * The events only support system-wide mode counting. There is no
+ * sampling support because it does not make sense and is not
+ * supported by the RAPL hardware.
+ *
+ * Because we want to avoid floating-point operations in the kernel,
+ * the events are all reported in fixed point arithmetic (32.32).
+ * Tools must adjust the counts to convert them to Watts using
+ * the duration of the measurement. Tools may use a function such as
+ * ldexp(raw_count, -32);
+ */
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/perf_event.h>
+#include <asm/cpu_device_id.h>
+#include "perf_event.h"
+
+/*
+ * RAPL energy status counters
+ */
+#define RAPL_IDX_PP0_NRG_STAT  0       /* all cores */
+#define INTEL_RAPL_PP0         0x1     /* pseudo-encoding */
+#define RAPL_IDX_PKG_NRG_STAT  1       /* entire package */
+#define INTEL_RAPL_PKG         0x2     /* pseudo-encoding */
+#define RAPL_IDX_RAM_NRG_STAT  2       /* DRAM */
+#define INTEL_RAPL_RAM         0x3     /* pseudo-encoding */
+
+/* Clients have PP0, PKG */
+#define RAPL_IDX_CLN   (1<<RAPL_IDX_PP0_NRG_STAT|\
+                        1<<RAPL_IDX_PKG_NRG_STAT)
+
+/* Servers have PP0, PKG, RAM */
+#define RAPL_IDX_SRV   (1<<RAPL_IDX_PP0_NRG_STAT|\
+                        1<<RAPL_IDX_PKG_NRG_STAT|\
+                        1<<RAPL_IDX_RAM_NRG_STAT)
+
+/*
+ * event code: LSB 8 bits, passed in attr->config
+ * any other bit is reserved
+ */
+#define RAPL_EVENT_MASK        0xFFULL
+
+#define DEFINE_RAPL_FORMAT_ATTR(_var, _name, _format)          \
+static ssize_t __rapl_##_var##_show(struct kobject *kobj,      \
+                               struct kobj_attribute *attr,    \
+                               char *page)                     \
+{                                                              \
+       BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE);             \
+       return sprintf(page, _format "\n");                     \
+}                                                              \
+static struct kobj_attribute format_attr_##_var =              \
+       __ATTR(_name, 0444, __rapl_##_var##_show, NULL)
+
+#define RAPL_EVENT_DESC(_name, _config)                                \
+{                                                              \
+       .attr   = __ATTR(_name, 0444, rapl_event_show, NULL),   \
+       .config = _config,                                      \
+}
+
+#define RAPL_CNTR_WIDTH 32 /* 32-bit rapl counters */
+
+struct rapl_pmu {
+       spinlock_t       lock;
+       int              hw_unit;  /* 1/2^hw_unit Joule */
+       int              n_active; /* number of active events */
+       struct list_head active_list;
+       struct pmu       *pmu; /* pointer to rapl_pmu_class */
+       ktime_t          timer_interval; /* in ktime_t unit */
+       struct hrtimer   hrtimer;
+};
+
+static struct pmu rapl_pmu_class;
+static cpumask_t rapl_cpu_mask;
+static int rapl_cntr_mask;
+
+static DEFINE_PER_CPU(struct rapl_pmu *, rapl_pmu);
+static DEFINE_PER_CPU(struct rapl_pmu *, rapl_pmu_to_free);
+
+static inline u64 rapl_read_counter(struct perf_event *event)
+{
+       u64 raw;
+       rdmsrl(event->hw.event_base, raw);
+       return raw;
+}
+
+static inline u64 rapl_scale(u64 v)
+{
+       /*
+        * scale delta to smallest unit (1/2^32)
+        * users must then scale back: count * 1/(1e9*2^32) to get Joules
+        * or use ldexp(count, -32).
+        * Watts = Joules/Time delta
+        */
+       return v << (32 - __get_cpu_var(rapl_pmu)->hw_unit);
+}
+
+static u64 rapl_event_update(struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       u64 prev_raw_count, new_raw_count;
+       s64 delta, sdelta;
+       int shift = RAPL_CNTR_WIDTH;
+
+again:
+       prev_raw_count = local64_read(&hwc->prev_count);
+       rdmsrl(event->hw.event_base, new_raw_count);
+
+       if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
+                           new_raw_count) != prev_raw_count) {
+               cpu_relax();
+               goto again;
+       }
+
+       /*
+        * Now we have the new raw value and have updated the prev
+        * timestamp already. We can now calculate the elapsed delta
+        * (event-)time and add that to the generic event.
+        *
+        * Careful, not all hw sign-extends above the physical width
+        * of the count.
+        */
+       delta = (new_raw_count << shift) - (prev_raw_count << shift);
+       delta >>= shift;
+
+       sdelta = rapl_scale(delta);
+
+       local64_add(sdelta, &event->count);
+
+       return new_raw_count;
+}
+
+static void rapl_start_hrtimer(struct rapl_pmu *pmu)
+{
+       __hrtimer_start_range_ns(&pmu->hrtimer,
+                       pmu->timer_interval, 0,
+                       HRTIMER_MODE_REL_PINNED, 0);
+}
+
+static void rapl_stop_hrtimer(struct rapl_pmu *pmu)
+{
+       hrtimer_cancel(&pmu->hrtimer);
+}
+
+static enum hrtimer_restart rapl_hrtimer_handle(struct hrtimer *hrtimer)
+{
+       struct rapl_pmu *pmu = __get_cpu_var(rapl_pmu);
+       struct perf_event *event;
+       unsigned long flags;
+
+       if (!pmu->n_active)
+               return HRTIMER_NORESTART;
+
+       spin_lock_irqsave(&pmu->lock, flags);
+
+       list_for_each_entry(event, &pmu->active_list, active_entry) {
+               rapl_event_update(event);
+       }
+
+       spin_unlock_irqrestore(&pmu->lock, flags);
+
+       hrtimer_forward_now(hrtimer, pmu->timer_interval);
+
+       return HRTIMER_RESTART;
+}
+
+static void rapl_hrtimer_init(struct rapl_pmu *pmu)
+{
+       struct hrtimer *hr = &pmu->hrtimer;
+
+       hrtimer_init(hr, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+       hr->function = rapl_hrtimer_handle;
+}
+
+static void __rapl_pmu_event_start(struct rapl_pmu *pmu,
+                                  struct perf_event *event)
+{
+       if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED)))
+               return;
+
+       event->hw.state = 0;
+
+       list_add_tail(&event->active_entry, &pmu->active_list);
+
+       local64_set(&event->hw.prev_count, rapl_read_counter(event));
+
+       pmu->n_active++;
+       if (pmu->n_active == 1)
+               rapl_start_hrtimer(pmu);
+}
+
+static void rapl_pmu_event_start(struct perf_event *event, int mode)
+{
+       struct rapl_pmu *pmu = __get_cpu_var(rapl_pmu);
+       unsigned long flags;
+
+       spin_lock_irqsave(&pmu->lock, flags);
+       __rapl_pmu_event_start(pmu, event);
+       spin_unlock_irqrestore(&pmu->lock, flags);
+}
+
+static void rapl_pmu_event_stop(struct perf_event *event, int mode)
+{
+       struct rapl_pmu *pmu = __get_cpu_var(rapl_pmu);
+       struct hw_perf_event *hwc = &event->hw;
+       unsigned long flags;
+
+       spin_lock_irqsave(&pmu->lock, flags);
+
+       /* mark event as deactivated and stopped */
+       if (!(hwc->state & PERF_HES_STOPPED)) {
+               WARN_ON_ONCE(pmu->n_active <= 0);
+               pmu->n_active--;
+               if (pmu->n_active == 0)
+                       rapl_stop_hrtimer(pmu);
+
+               list_del(&event->active_entry);
+
+               WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
+               hwc->state |= PERF_HES_STOPPED;
+       }
+
+       /* check if update of sw counter is necessary */
+       if ((mode & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
+               /*
+                * Drain the remaining delta count out of a event
+                * that we are disabling:
+                */
+               rapl_event_update(event);
+               hwc->state |= PERF_HES_UPTODATE;
+       }
+
+       spin_unlock_irqrestore(&pmu->lock, flags);
+}
+
+static int rapl_pmu_event_add(struct perf_event *event, int mode)
+{
+       struct rapl_pmu *pmu = __get_cpu_var(rapl_pmu);
+       struct hw_perf_event *hwc = &event->hw;
+       unsigned long flags;
+
+       spin_lock_irqsave(&pmu->lock, flags);
+
+       hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
+
+       if (mode & PERF_EF_START)
+               __rapl_pmu_event_start(pmu, event);
+
+       spin_unlock_irqrestore(&pmu->lock, flags);
+
+       return 0;
+}
+
+static void rapl_pmu_event_del(struct perf_event *event, int flags)
+{
+       rapl_pmu_event_stop(event, PERF_EF_UPDATE);
+}
+
+static int rapl_pmu_event_init(struct perf_event *event)
+{
+       u64 cfg = event->attr.config & RAPL_EVENT_MASK;
+       int bit, msr, ret = 0;
+
+       /* only look at RAPL events */
+       if (event->attr.type != rapl_pmu_class.type)
+               return -ENOENT;
+
+       /* check only supported bits are set */
+       if (event->attr.config & ~RAPL_EVENT_MASK)
+               return -EINVAL;
+
+       /*
+        * check event is known (determines counter)
+        */
+       switch (cfg) {
+       case INTEL_RAPL_PP0:
+               bit = RAPL_IDX_PP0_NRG_STAT;
+               msr = MSR_PP0_ENERGY_STATUS;
+               break;
+       case INTEL_RAPL_PKG:
+               bit = RAPL_IDX_PKG_NRG_STAT;
+               msr = MSR_PKG_ENERGY_STATUS;
+               break;
+       case INTEL_RAPL_RAM:
+               bit = RAPL_IDX_RAM_NRG_STAT;
+               msr = MSR_DRAM_ENERGY_STATUS;
+               break;
+       default:
+               return -EINVAL;
+       }
+       /* check event supported */
+       if (!(rapl_cntr_mask & (1 << bit)))
+               return -EINVAL;
+
+       /* unsupported modes and filters */
+       if (event->attr.exclude_user   ||
+           event->attr.exclude_kernel ||
+           event->attr.exclude_hv     ||
+           event->attr.exclude_idle   ||
+           event->attr.exclude_host   ||
+           event->attr.exclude_guest  ||
+           event->attr.sample_period) /* no sampling */
+               return -EINVAL;
+
+       /* must be done before validate_group */
+       event->hw.event_base = msr;
+       event->hw.config = cfg;
+       event->hw.idx = bit;
+
+       return ret;
+}
+
+static void rapl_pmu_event_read(struct perf_event *event)
+{
+       rapl_event_update(event);
+}
+
+static ssize_t rapl_get_attr_cpumask(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       int n = cpulist_scnprintf(buf, PAGE_SIZE - 2, &rapl_cpu_mask);
+
+       buf[n++] = '\n';
+       buf[n] = '\0';
+       return n;
+}
+
+static DEVICE_ATTR(cpumask, S_IRUGO, rapl_get_attr_cpumask, NULL);
+
+static struct attribute *rapl_pmu_attrs[] = {
+       &dev_attr_cpumask.attr,
+       NULL,
+};
+
+static struct attribute_group rapl_pmu_attr_group = {
+       .attrs = rapl_pmu_attrs,
+};
+
+EVENT_ATTR_STR(energy-cores, rapl_cores, "event=0x01");
+EVENT_ATTR_STR(energy-pkg  , rapl_pkg, "event=0x02");
+EVENT_ATTR_STR(energy-ram  , rapl_ram, "event=0x03");
+
+EVENT_ATTR_STR(energy-cores.unit, rapl_cores_unit, "Joules");
+EVENT_ATTR_STR(energy-pkg.unit  , rapl_pkg_unit, "Joules");
+EVENT_ATTR_STR(energy-ram.unit  , rapl_ram_unit, "Joules");
+
+/*
+ * we compute in 0.23 nJ increments regardless of MSR
+ */
+EVENT_ATTR_STR(energy-cores.scale, rapl_cores_scale, "2.3283064365386962890625e-10");
+EVENT_ATTR_STR(energy-pkg.scale, rapl_pkg_scale, "2.3283064365386962890625e-10");
+EVENT_ATTR_STR(energy-ram.scale, rapl_ram_scale, "2.3283064365386962890625e-10");
+
+static struct attribute *rapl_events_srv_attr[] = {
+       EVENT_PTR(rapl_cores),
+       EVENT_PTR(rapl_pkg),
+       EVENT_PTR(rapl_ram),
+
+       EVENT_PTR(rapl_cores_unit),
+       EVENT_PTR(rapl_pkg_unit),
+       EVENT_PTR(rapl_ram_unit),
+
+       EVENT_PTR(rapl_cores_scale),
+       EVENT_PTR(rapl_pkg_scale),
+       EVENT_PTR(rapl_ram_scale),
+       NULL,
+};
+
+static struct attribute *rapl_events_cln_attr[] = {
+       EVENT_PTR(rapl_cores),
+       EVENT_PTR(rapl_pkg),
+
+       EVENT_PTR(rapl_cores_unit),
+       EVENT_PTR(rapl_pkg_unit),
+
+       EVENT_PTR(rapl_cores_scale),
+       EVENT_PTR(rapl_pkg_scale),
+       NULL,
+};
+
+static struct attribute_group rapl_pmu_events_group = {
+       .name = "events",
+       .attrs = NULL, /* patched at runtime */
+};
+
+DEFINE_RAPL_FORMAT_ATTR(event, event, "config:0-7");
+static struct attribute *rapl_formats_attr[] = {
+       &format_attr_event.attr,
+       NULL,
+};
+
+static struct attribute_group rapl_pmu_format_group = {
+       .name = "format",
+       .attrs = rapl_formats_attr,
+};
+
+const struct attribute_group *rapl_attr_groups[] = {
+       &rapl_pmu_attr_group,
+       &rapl_pmu_format_group,
+       &rapl_pmu_events_group,
+       NULL,
+};
+
+static struct pmu rapl_pmu_class = {
+       .attr_groups    = rapl_attr_groups,
+       .task_ctx_nr    = perf_invalid_context, /* system-wide only */
+       .event_init     = rapl_pmu_event_init,
+       .add            = rapl_pmu_event_add, /* must have */
+       .del            = rapl_pmu_event_del, /* must have */
+       .start          = rapl_pmu_event_start,
+       .stop           = rapl_pmu_event_stop,
+       .read           = rapl_pmu_event_read,
+};
+
+static void rapl_cpu_exit(int cpu)
+{
+       struct rapl_pmu *pmu = per_cpu(rapl_pmu, cpu);
+       int i, phys_id = topology_physical_package_id(cpu);
+       int target = -1;
+
+       /* find a new cpu on same package */
+       for_each_online_cpu(i) {
+               if (i == cpu)
+                       continue;
+               if (phys_id == topology_physical_package_id(i)) {
+                       target = i;
+                       break;
+               }
+       }
+       /*
+        * clear cpu from cpumask
+        * if was set in cpumask and still some cpu on package,
+        * then move to new cpu
+        */
+       if (cpumask_test_and_clear_cpu(cpu, &rapl_cpu_mask) && target >= 0)
+               cpumask_set_cpu(target, &rapl_cpu_mask);
+
+       WARN_ON(cpumask_empty(&rapl_cpu_mask));
+       /*
+        * migrate events and context to new cpu
+        */
+       if (target >= 0)
+               perf_pmu_migrate_context(pmu->pmu, cpu, target);
+
+       /* cancel overflow polling timer for CPU */
+       rapl_stop_hrtimer(pmu);
+}
+
+static void rapl_cpu_init(int cpu)
+{
+       int i, phys_id = topology_physical_package_id(cpu);
+
+       /* check if phys_is is already covered */
+       for_each_cpu(i, &rapl_cpu_mask) {
+               if (phys_id == topology_physical_package_id(i))
+                       return;
+       }
+       /* was not found, so add it */
+       cpumask_set_cpu(cpu, &rapl_cpu_mask);
+}
+
+static int rapl_cpu_prepare(int cpu)
+{
+       struct rapl_pmu *pmu = per_cpu(rapl_pmu, cpu);
+       int phys_id = topology_physical_package_id(cpu);
+       u64 ms;
+
+       if (pmu)
+               return 0;
+
+       if (phys_id < 0)
+               return -1;
+
+       pmu = kzalloc_node(sizeof(*pmu), GFP_KERNEL, cpu_to_node(cpu));
+       if (!pmu)
+               return -1;
+
+       spin_lock_init(&pmu->lock);
+
+       INIT_LIST_HEAD(&pmu->active_list);
+
+       /*
+        * grab power unit as: 1/2^unit Joules
+        *
+        * we cache in local PMU instance
+        */
+       rdmsrl(MSR_RAPL_POWER_UNIT, pmu->hw_unit);
+       pmu->hw_unit = (pmu->hw_unit >> 8) & 0x1FULL;
+       pmu->pmu = &rapl_pmu_class;
+
+       /*
+        * use reference of 200W for scaling the timeout
+        * to avoid missing counter overflows.
+        * 200W = 200 Joules/sec
+        * divide interval by 2 to avoid lockstep (2 * 100)
+        * if hw unit is 32, then we use 2 ms 1/200/2
+        */
+       if (pmu->hw_unit < 32)
+               ms = (1000 / (2 * 100)) * (1ULL << (32 - pmu->hw_unit - 1));
+       else
+               ms = 2;
+
+       pmu->timer_interval = ms_to_ktime(ms);
+
+       rapl_hrtimer_init(pmu);
+
+       /* set RAPL pmu for this cpu for now */
+       per_cpu(rapl_pmu, cpu) = pmu;
+       per_cpu(rapl_pmu_to_free, cpu) = NULL;
+
+       return 0;
+}
+
+static void rapl_cpu_kfree(int cpu)
+{
+       struct rapl_pmu *pmu = per_cpu(rapl_pmu_to_free, cpu);
+
+       kfree(pmu);
+
+       per_cpu(rapl_pmu_to_free, cpu) = NULL;
+}
+
+static int rapl_cpu_dying(int cpu)
+{
+       struct rapl_pmu *pmu = per_cpu(rapl_pmu, cpu);
+
+       if (!pmu)
+               return 0;
+
+       per_cpu(rapl_pmu, cpu) = NULL;
+
+       per_cpu(rapl_pmu_to_free, cpu) = pmu;
+
+       return 0;
+}
+
+static int rapl_cpu_notifier(struct notifier_block *self,
+                            unsigned long action, void *hcpu)
+{
+       unsigned int cpu = (long)hcpu;
+
+       switch (action & ~CPU_TASKS_FROZEN) {
+       case CPU_UP_PREPARE:
+               rapl_cpu_prepare(cpu);
+               break;
+       case CPU_STARTING:
+               rapl_cpu_init(cpu);
+               break;
+       case CPU_UP_CANCELED:
+       case CPU_DYING:
+               rapl_cpu_dying(cpu);
+               break;
+       case CPU_ONLINE:
+       case CPU_DEAD:
+               rapl_cpu_kfree(cpu);
+               break;
+       case CPU_DOWN_PREPARE:
+               rapl_cpu_exit(cpu);
+               break;
+       default:
+               break;
+       }
+
+       return NOTIFY_OK;
+}
+
+static const struct x86_cpu_id rapl_cpu_match[] = {
+       [0] = { .vendor = X86_VENDOR_INTEL, .family = 6 },
+       [1] = {},
+};
+
+static int __init rapl_pmu_init(void)
+{
+       struct rapl_pmu *pmu;
+       int cpu, ret;
+
+       /*
+        * check for Intel processor family 6
+        */
+       if (!x86_match_cpu(rapl_cpu_match))
+               return 0;
+
+       /* check supported CPU */
+       switch (boot_cpu_data.x86_model) {
+       case 42: /* Sandy Bridge */
+       case 58: /* Ivy Bridge */
+       case 60: /* Haswell */
+               rapl_cntr_mask = RAPL_IDX_CLN;
+               rapl_pmu_events_group.attrs = rapl_events_cln_attr;
+               break;
+       case 45: /* Sandy Bridge-EP */
+       case 62: /* IvyTown */
+               rapl_cntr_mask = RAPL_IDX_SRV;
+               rapl_pmu_events_group.attrs = rapl_events_srv_attr;
+               break;
+
+       default:
+               /* unsupported */
+               return 0;
+       }
+       get_online_cpus();
+
+       for_each_online_cpu(cpu) {
+               rapl_cpu_prepare(cpu);
+               rapl_cpu_init(cpu);
+       }
+
+       perf_cpu_notifier(rapl_cpu_notifier);
+
+       ret = perf_pmu_register(&rapl_pmu_class, "power", -1);
+       if (WARN_ON(ret)) {
+               pr_info("RAPL PMU detected, registration failed (%d), RAPL PMU disabled\n", ret);
+               put_online_cpus();
+               return -1;
+       }
+
+       pmu = __get_cpu_var(rapl_pmu);
+
+       pr_info("RAPL PMU detected, hw unit 2^-%d Joules,"
+               " API unit is 2^-32 Joules,"
+               " %d fixed counters"
+               " %llu ms ovfl timer\n",
+               pmu->hw_unit,
+               hweight32(rapl_cntr_mask),
+               ktime_to_ms(pmu->timer_interval));
+
+       put_online_cpus();
+
+       return 0;
+}
+device_initcall(rapl_pmu_init);
index 88db010845cb26a2594170acc2387cee75a20bbc..384df5105fbc9883626ec5482151babd43ce482a 100644 (file)
@@ -31,20 +31,6 @@ static int __init x86_rdrand_setup(char *s)
 }
 __setup("nordrand", x86_rdrand_setup);
 
-/* We can't use arch_get_random_long() here since alternatives haven't run */
-static inline int rdrand_long(unsigned long *v)
-{
-       int ok;
-       asm volatile("1: " RDRAND_LONG "\n\t"
-                    "jc 2f\n\t"
-                    "decl %0\n\t"
-                    "jnz 1b\n\t"
-                    "2:"
-                    : "=r" (ok), "=a" (*v)
-                    : "0" (RDRAND_RETRY_LOOPS));
-       return ok;
-}
-
 /*
  * Force a reseed cycle; we are architecturally guaranteed a reseed
  * after no more than 512 128-bit chunks of random data.  This also
index da3c599584a3307f024c76f80c94e721016765e3..c752cb43e52f192f431a5f2ab91b9366e42ef5b0 100644 (file)
@@ -558,6 +558,17 @@ void native_machine_shutdown(void)
 {
        /* Stop the cpus and apics */
 #ifdef CONFIG_X86_IO_APIC
+       /*
+        * Disabling IO APIC before local APIC is a workaround for
+        * erratum AVR31 in "Intel Atom Processor C2000 Product Family
+        * Specification Update". In this situation, interrupts that target
+        * a Logical Processor whose Local APIC is either in the process of
+        * being hardware disabled or software disabled are neither delivered
+        * nor discarded. When this erratum occurs, the processor may hang.
+        *
+        * Even without the erratum, it still makes sense to quiet IO APIC
+        * before disabling Local APIC.
+        */
        disable_IO_APIC();
 #endif
 
index cb233bc9dee35681ccf85a2385ece964ee96847d..f97cf4dd4b76fab01db0a7e0db7d33411c0041e4 100644 (file)
@@ -823,6 +823,20 @@ static void __init trim_low_memory_range(void)
        memblock_reserve(0, ALIGN(reserve_low, PAGE_SIZE));
 }
        
+/*
+ * Dump out kernel offset information on panic.
+ */
+static int
+dump_kernel_offset(struct notifier_block *self, unsigned long v, void *p)
+{
+       pr_emerg("Kernel Offset: 0x%lx from 0x%lx "
+                "(relocation range: 0x%lx-0x%lx)\n",
+                (unsigned long)&_text - __START_KERNEL, __START_KERNEL,
+                __START_KERNEL_map, MODULES_VADDR-1);
+
+       return 0;
+}
+
 /*
  * Determine if we were loaded by an EFI loader.  If so, then we have also been
  * passed the efi memmap, systab, etc., so we should use these data structures
@@ -1248,3 +1262,15 @@ void __init i386_reserve_resources(void)
 }
 
 #endif /* CONFIG_X86_32 */
+
+static struct notifier_block kernel_offset_notifier = {
+       .notifier_call = dump_kernel_offset
+};
+
+static int __init register_kernel_offset_dumper(void)
+{
+       atomic_notifier_chain_register(&panic_notifier_list,
+                                       &kernel_offset_notifier);
+       return 0;
+}
+__initcall(register_kernel_offset_dumper);
index a30ca15be21c8a182b3bb937ac612d1863a046ee..dee945d555941a078f40049b24b8b4731aba6f2c 100644 (file)
@@ -186,7 +186,7 @@ ENTRY(copy_user_generic_unrolled)
 30:    shll $6,%ecx
        addl %ecx,%edx
        jmp 60f
-40:    lea (%rdx,%rcx,8),%rdx
+40:    leal (%rdx,%rcx,8),%edx
        jmp 60f
 50:    movl %ecx,%edx
 60:    jmp copy_user_handle_tail /* ecx is zerorest also */
@@ -236,8 +236,6 @@ ENDPROC(copy_user_generic_unrolled)
 ENTRY(copy_user_generic_string)
        CFI_STARTPROC
        ASM_STAC
-       andl %edx,%edx
-       jz 4f
        cmpl $8,%edx
        jb 2f           /* less than 8 bytes, go to byte copy loop */
        ALIGN_DESTINATION
@@ -249,12 +247,12 @@ ENTRY(copy_user_generic_string)
 2:     movl %edx,%ecx
 3:     rep
        movsb
-4:     xorl %eax,%eax
+       xorl %eax,%eax
        ASM_CLAC
        ret
 
        .section .fixup,"ax"
-11:    lea (%rdx,%rcx,8),%rcx
+11:    leal (%rdx,%rcx,8),%ecx
 12:    movl %ecx,%edx          /* ecx is zerorest also */
        jmp copy_user_handle_tail
        .previous
@@ -279,12 +277,10 @@ ENDPROC(copy_user_generic_string)
 ENTRY(copy_user_enhanced_fast_string)
        CFI_STARTPROC
        ASM_STAC
-       andl %edx,%edx
-       jz 2f
        movl %edx,%ecx
 1:     rep
        movsb
-2:     xorl %eax,%eax
+       xorl %eax,%eax
        ASM_CLAC
        ret
 
index 9d980d88b7477a82f757e75d0efda0c867c76d43..8c9f647ff9e111203af86f894a13b450e4513013 100644 (file)
@@ -87,9 +87,7 @@ int pmd_huge_support(void)
 }
 #endif
 
-/* x86_64 also uses this file */
-
-#ifdef HAVE_ARCH_HUGETLB_UNMAPPED_AREA
+#ifdef CONFIG_HUGETLB_PAGE
 static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file,
                unsigned long addr, unsigned long len,
                unsigned long pgoff, unsigned long flags)
@@ -99,7 +97,7 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file,
 
        info.flags = 0;
        info.length = len;
-       info.low_limit = TASK_UNMAPPED_BASE;
+       info.low_limit = current->mm->mmap_legacy_base;
        info.high_limit = TASK_SIZE;
        info.align_mask = PAGE_MASK & ~huge_page_mask(h);
        info.align_offset = 0;
@@ -172,8 +170,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
                return hugetlb_get_unmapped_area_topdown(file, addr, len,
                                pgoff, flags);
 }
-
-#endif /*HAVE_ARCH_HUGETLB_UNMAPPED_AREA*/
+#endif /* CONFIG_HUGETLB_PAGE */
 
 #ifdef CONFIG_X86_64
 static __init int setup_hugepagesz(char *opt)
index 4287f1ffba7ef2e42cc68839a38c3ecc0d6b1304..5bdc5430597cfea9056e08edb7902a098f28535c 100644 (file)
@@ -806,6 +806,9 @@ void __init mem_init(void)
        BUILD_BUG_ON(VMALLOC_START                      >= VMALLOC_END);
 #undef high_memory
 #undef __FIXADDR_TOP
+#ifdef CONFIG_RANDOMIZE_BASE
+       BUILD_BUG_ON(CONFIG_RANDOMIZE_BASE_MAX_OFFSET > KERNEL_IMAGE_SIZE);
+#endif
 
 #ifdef CONFIG_HIGHMEM
        BUG_ON(PKMAP_BASE + LAST_PKMAP*PAGE_SIZE        > FIXADDR_START);
index bb32480c2d713d57a52747f2f6e119a70286dc07..b3b19f46c0164c7169c9259a68836afbaeae1943 100644 (file)
@@ -30,6 +30,7 @@
  */
 struct cpa_data {
        unsigned long   *vaddr;
+       pgd_t           *pgd;
        pgprot_t        mask_set;
        pgprot_t        mask_clr;
        int             numpages;
@@ -322,17 +323,9 @@ static inline pgprot_t static_protections(pgprot_t prot, unsigned long address,
        return prot;
 }
 
-/*
- * Lookup the page table entry for a virtual address. Return a pointer
- * to the entry and the level of the mapping.
- *
- * Note: We return pud and pmd either when the entry is marked large
- * or when the present bit is not set. Otherwise we would return a
- * pointer to a nonexisting mapping.
- */
-pte_t *lookup_address(unsigned long address, unsigned int *level)
+static pte_t *__lookup_address_in_pgd(pgd_t *pgd, unsigned long address,
+                                     unsigned int *level)
 {
-       pgd_t *pgd = pgd_offset_k(address);
        pud_t *pud;
        pmd_t *pmd;
 
@@ -361,8 +354,31 @@ pte_t *lookup_address(unsigned long address, unsigned int *level)
 
        return pte_offset_kernel(pmd, address);
 }
+
+/*
+ * Lookup the page table entry for a virtual address. Return a pointer
+ * to the entry and the level of the mapping.
+ *
+ * Note: We return pud and pmd either when the entry is marked large
+ * or when the present bit is not set. Otherwise we would return a
+ * pointer to a nonexisting mapping.
+ */
+pte_t *lookup_address(unsigned long address, unsigned int *level)
+{
+        return __lookup_address_in_pgd(pgd_offset_k(address), address, level);
+}
 EXPORT_SYMBOL_GPL(lookup_address);
 
+static pte_t *_lookup_address_cpa(struct cpa_data *cpa, unsigned long address,
+                                 unsigned int *level)
+{
+        if (cpa->pgd)
+               return __lookup_address_in_pgd(cpa->pgd + pgd_index(address),
+                                              address, level);
+
+        return lookup_address(address, level);
+}
+
 /*
  * This is necessary because __pa() does not work on some
  * kinds of memory, like vmalloc() or the alloc_remap()
@@ -437,7 +453,7 @@ try_preserve_large_page(pte_t *kpte, unsigned long address,
         * Check for races, another CPU might have split this page
         * up already:
         */
-       tmp = lookup_address(address, &level);
+       tmp = _lookup_address_cpa(cpa, address, &level);
        if (tmp != kpte)
                goto out_unlock;
 
@@ -543,7 +559,8 @@ out_unlock:
 }
 
 static int
-__split_large_page(pte_t *kpte, unsigned long address, struct page *base)
+__split_large_page(struct cpa_data *cpa, pte_t *kpte, unsigned long address,
+                  struct page *base)
 {
        pte_t *pbase = (pte_t *)page_address(base);
        unsigned long pfn, pfninc = 1;
@@ -556,7 +573,7 @@ __split_large_page(pte_t *kpte, unsigned long address, struct page *base)
         * Check for races, another CPU might have split this page
         * up for us already:
         */
-       tmp = lookup_address(address, &level);
+       tmp = _lookup_address_cpa(cpa, address, &level);
        if (tmp != kpte) {
                spin_unlock(&pgd_lock);
                return 1;
@@ -632,7 +649,8 @@ __split_large_page(pte_t *kpte, unsigned long address, struct page *base)
        return 0;
 }
 
-static int split_large_page(pte_t *kpte, unsigned long address)
+static int split_large_page(struct cpa_data *cpa, pte_t *kpte,
+                           unsigned long address)
 {
        struct page *base;
 
@@ -644,15 +662,390 @@ static int split_large_page(pte_t *kpte, unsigned long address)
        if (!base)
                return -ENOMEM;
 
-       if (__split_large_page(kpte, address, base))
+       if (__split_large_page(cpa, kpte, address, base))
                __free_page(base);
 
        return 0;
 }
 
+static bool try_to_free_pte_page(pte_t *pte)
+{
+       int i;
+
+       for (i = 0; i < PTRS_PER_PTE; i++)
+               if (!pte_none(pte[i]))
+                       return false;
+
+       free_page((unsigned long)pte);
+       return true;
+}
+
+static bool try_to_free_pmd_page(pmd_t *pmd)
+{
+       int i;
+
+       for (i = 0; i < PTRS_PER_PMD; i++)
+               if (!pmd_none(pmd[i]))
+                       return false;
+
+       free_page((unsigned long)pmd);
+       return true;
+}
+
+static bool unmap_pte_range(pmd_t *pmd, unsigned long start, unsigned long end)
+{
+       pte_t *pte = pte_offset_kernel(pmd, start);
+
+       while (start < end) {
+               set_pte(pte, __pte(0));
+
+               start += PAGE_SIZE;
+               pte++;
+       }
+
+       if (try_to_free_pte_page((pte_t *)pmd_page_vaddr(*pmd))) {
+               pmd_clear(pmd);
+               return true;
+       }
+       return false;
+}
+
+static void __unmap_pmd_range(pud_t *pud, pmd_t *pmd,
+                             unsigned long start, unsigned long end)
+{
+       if (unmap_pte_range(pmd, start, end))
+               if (try_to_free_pmd_page((pmd_t *)pud_page_vaddr(*pud)))
+                       pud_clear(pud);
+}
+
+static void unmap_pmd_range(pud_t *pud, unsigned long start, unsigned long end)
+{
+       pmd_t *pmd = pmd_offset(pud, start);
+
+       /*
+        * Not on a 2MB page boundary?
+        */
+       if (start & (PMD_SIZE - 1)) {
+               unsigned long next_page = (start + PMD_SIZE) & PMD_MASK;
+               unsigned long pre_end = min_t(unsigned long, end, next_page);
+
+               __unmap_pmd_range(pud, pmd, start, pre_end);
+
+               start = pre_end;
+               pmd++;
+       }
+
+       /*
+        * Try to unmap in 2M chunks.
+        */
+       while (end - start >= PMD_SIZE) {
+               if (pmd_large(*pmd))
+                       pmd_clear(pmd);
+               else
+                       __unmap_pmd_range(pud, pmd, start, start + PMD_SIZE);
+
+               start += PMD_SIZE;
+               pmd++;
+       }
+
+       /*
+        * 4K leftovers?
+        */
+       if (start < end)
+               return __unmap_pmd_range(pud, pmd, start, end);
+
+       /*
+        * Try again to free the PMD page if haven't succeeded above.
+        */
+       if (!pud_none(*pud))
+               if (try_to_free_pmd_page((pmd_t *)pud_page_vaddr(*pud)))
+                       pud_clear(pud);
+}
+
+static void unmap_pud_range(pgd_t *pgd, unsigned long start, unsigned long end)
+{
+       pud_t *pud = pud_offset(pgd, start);
+
+       /*
+        * Not on a GB page boundary?
+        */
+       if (start & (PUD_SIZE - 1)) {
+               unsigned long next_page = (start + PUD_SIZE) & PUD_MASK;
+               unsigned long pre_end   = min_t(unsigned long, end, next_page);
+
+               unmap_pmd_range(pud, start, pre_end);
+
+               start = pre_end;
+               pud++;
+       }
+
+       /*
+        * Try to unmap in 1G chunks?
+        */
+       while (end - start >= PUD_SIZE) {
+
+               if (pud_large(*pud))
+                       pud_clear(pud);
+               else
+                       unmap_pmd_range(pud, start, start + PUD_SIZE);
+
+               start += PUD_SIZE;
+               pud++;
+       }
+
+       /*
+        * 2M leftovers?
+        */
+       if (start < end)
+               unmap_pmd_range(pud, start, end);
+
+       /*
+        * No need to try to free the PUD page because we'll free it in
+        * populate_pgd's error path
+        */
+}
+
+static int alloc_pte_page(pmd_t *pmd)
+{
+       pte_t *pte = (pte_t *)get_zeroed_page(GFP_KERNEL | __GFP_NOTRACK);
+       if (!pte)
+               return -1;
+
+       set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE));
+       return 0;
+}
+
+static int alloc_pmd_page(pud_t *pud)
+{
+       pmd_t *pmd = (pmd_t *)get_zeroed_page(GFP_KERNEL | __GFP_NOTRACK);
+       if (!pmd)
+               return -1;
+
+       set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE));
+       return 0;
+}
+
+static void populate_pte(struct cpa_data *cpa,
+                        unsigned long start, unsigned long end,
+                        unsigned num_pages, pmd_t *pmd, pgprot_t pgprot)
+{
+       pte_t *pte;
+
+       pte = pte_offset_kernel(pmd, start);
+
+       while (num_pages-- && start < end) {
+
+               /* deal with the NX bit */
+               if (!(pgprot_val(pgprot) & _PAGE_NX))
+                       cpa->pfn &= ~_PAGE_NX;
+
+               set_pte(pte, pfn_pte(cpa->pfn >> PAGE_SHIFT, pgprot));
+
+               start    += PAGE_SIZE;
+               cpa->pfn += PAGE_SIZE;
+               pte++;
+       }
+}
+
+static int populate_pmd(struct cpa_data *cpa,
+                       unsigned long start, unsigned long end,
+                       unsigned num_pages, pud_t *pud, pgprot_t pgprot)
+{
+       unsigned int cur_pages = 0;
+       pmd_t *pmd;
+
+       /*
+        * Not on a 2M boundary?
+        */
+       if (start & (PMD_SIZE - 1)) {
+               unsigned long pre_end = start + (num_pages << PAGE_SHIFT);
+               unsigned long next_page = (start + PMD_SIZE) & PMD_MASK;
+
+               pre_end   = min_t(unsigned long, pre_end, next_page);
+               cur_pages = (pre_end - start) >> PAGE_SHIFT;
+               cur_pages = min_t(unsigned int, num_pages, cur_pages);
+
+               /*
+                * Need a PTE page?
+                */
+               pmd = pmd_offset(pud, start);
+               if (pmd_none(*pmd))
+                       if (alloc_pte_page(pmd))
+                               return -1;
+
+               populate_pte(cpa, start, pre_end, cur_pages, pmd, pgprot);
+
+               start = pre_end;
+       }
+
+       /*
+        * We mapped them all?
+        */
+       if (num_pages == cur_pages)
+               return cur_pages;
+
+       while (end - start >= PMD_SIZE) {
+
+               /*
+                * We cannot use a 1G page so allocate a PMD page if needed.
+                */
+               if (pud_none(*pud))
+                       if (alloc_pmd_page(pud))
+                               return -1;
+
+               pmd = pmd_offset(pud, start);
+
+               set_pmd(pmd, __pmd(cpa->pfn | _PAGE_PSE | massage_pgprot(pgprot)));
+
+               start     += PMD_SIZE;
+               cpa->pfn  += PMD_SIZE;
+               cur_pages += PMD_SIZE >> PAGE_SHIFT;
+       }
+
+       /*
+        * Map trailing 4K pages.
+        */
+       if (start < end) {
+               pmd = pmd_offset(pud, start);
+               if (pmd_none(*pmd))
+                       if (alloc_pte_page(pmd))
+                               return -1;
+
+               populate_pte(cpa, start, end, num_pages - cur_pages,
+                            pmd, pgprot);
+       }
+       return num_pages;
+}
+
+static int populate_pud(struct cpa_data *cpa, unsigned long start, pgd_t *pgd,
+                       pgprot_t pgprot)
+{
+       pud_t *pud;
+       unsigned long end;
+       int cur_pages = 0;
+
+       end = start + (cpa->numpages << PAGE_SHIFT);
+
+       /*
+        * Not on a Gb page boundary? => map everything up to it with
+        * smaller pages.
+        */
+       if (start & (PUD_SIZE - 1)) {
+               unsigned long pre_end;
+               unsigned long next_page = (start + PUD_SIZE) & PUD_MASK;
+
+               pre_end   = min_t(unsigned long, end, next_page);
+               cur_pages = (pre_end - start) >> PAGE_SHIFT;
+               cur_pages = min_t(int, (int)cpa->numpages, cur_pages);
+
+               pud = pud_offset(pgd, start);
+
+               /*
+                * Need a PMD page?
+                */
+               if (pud_none(*pud))
+                       if (alloc_pmd_page(pud))
+                               return -1;
+
+               cur_pages = populate_pmd(cpa, start, pre_end, cur_pages,
+                                        pud, pgprot);
+               if (cur_pages < 0)
+                       return cur_pages;
+
+               start = pre_end;
+       }
+
+       /* We mapped them all? */
+       if (cpa->numpages == cur_pages)
+               return cur_pages;
+
+       pud = pud_offset(pgd, start);
+
+       /*
+        * Map everything starting from the Gb boundary, possibly with 1G pages
+        */
+       while (end - start >= PUD_SIZE) {
+               set_pud(pud, __pud(cpa->pfn | _PAGE_PSE | massage_pgprot(pgprot)));
+
+               start     += PUD_SIZE;
+               cpa->pfn  += PUD_SIZE;
+               cur_pages += PUD_SIZE >> PAGE_SHIFT;
+               pud++;
+       }
+
+       /* Map trailing leftover */
+       if (start < end) {
+               int tmp;
+
+               pud = pud_offset(pgd, start);
+               if (pud_none(*pud))
+                       if (alloc_pmd_page(pud))
+                               return -1;
+
+               tmp = populate_pmd(cpa, start, end, cpa->numpages - cur_pages,
+                                  pud, pgprot);
+               if (tmp < 0)
+                       return cur_pages;
+
+               cur_pages += tmp;
+       }
+       return cur_pages;
+}
+
+/*
+ * Restrictions for kernel page table do not necessarily apply when mapping in
+ * an alternate PGD.
+ */
+static int populate_pgd(struct cpa_data *cpa, unsigned long addr)
+{
+       pgprot_t pgprot = __pgprot(_KERNPG_TABLE);
+       bool allocd_pgd = false;
+       pgd_t *pgd_entry;
+       pud_t *pud = NULL;      /* shut up gcc */
+       int ret;
+
+       pgd_entry = cpa->pgd + pgd_index(addr);
+
+       /*
+        * Allocate a PUD page and hand it down for mapping.
+        */
+       if (pgd_none(*pgd_entry)) {
+               pud = (pud_t *)get_zeroed_page(GFP_KERNEL | __GFP_NOTRACK);
+               if (!pud)
+                       return -1;
+
+               set_pgd(pgd_entry, __pgd(__pa(pud) | _KERNPG_TABLE));
+               allocd_pgd = true;
+       }
+
+       pgprot_val(pgprot) &= ~pgprot_val(cpa->mask_clr);
+       pgprot_val(pgprot) |=  pgprot_val(cpa->mask_set);
+
+       ret = populate_pud(cpa, addr, pgd_entry, pgprot);
+       if (ret < 0) {
+               unmap_pud_range(pgd_entry, addr,
+                               addr + (cpa->numpages << PAGE_SHIFT));
+
+               if (allocd_pgd) {
+                       /*
+                        * If I allocated this PUD page, I can just as well
+                        * free it in this error path.
+                        */
+                       pgd_clear(pgd_entry);
+                       free_page((unsigned long)pud);
+               }
+               return ret;
+       }
+       cpa->numpages = ret;
+       return 0;
+}
+
 static int __cpa_process_fault(struct cpa_data *cpa, unsigned long vaddr,
                               int primary)
 {
+       if (cpa->pgd)
+               return populate_pgd(cpa, vaddr);
+
        /*
         * Ignore all non primary paths.
         */
@@ -697,7 +1090,7 @@ static int __change_page_attr(struct cpa_data *cpa, int primary)
        else
                address = *cpa->vaddr;
 repeat:
-       kpte = lookup_address(address, &level);
+       kpte = _lookup_address_cpa(cpa, address, &level);
        if (!kpte)
                return __cpa_process_fault(cpa, address, primary);
 
@@ -761,7 +1154,7 @@ repeat:
        /*
         * We have to split the large page:
         */
-       err = split_large_page(kpte, address);
+       err = split_large_page(cpa, kpte, address);
        if (!err) {
                /*
                 * Do a global flush tlb after splitting the large page
@@ -910,6 +1303,8 @@ static int change_page_attr_set_clr(unsigned long *addr, int numpages,
        int ret, cache, checkalias;
        unsigned long baddr = 0;
 
+       memset(&cpa, 0, sizeof(cpa));
+
        /*
         * Check, if we are requested to change a not supported
         * feature:
@@ -1356,6 +1751,7 @@ static int __set_pages_p(struct page *page, int numpages)
 {
        unsigned long tempaddr = (unsigned long) page_address(page);
        struct cpa_data cpa = { .vaddr = &tempaddr,
+                               .pgd = NULL,
                                .numpages = numpages,
                                .mask_set = __pgprot(_PAGE_PRESENT | _PAGE_RW),
                                .mask_clr = __pgprot(0),
@@ -1374,6 +1770,7 @@ static int __set_pages_np(struct page *page, int numpages)
 {
        unsigned long tempaddr = (unsigned long) page_address(page);
        struct cpa_data cpa = { .vaddr = &tempaddr,
+                               .pgd = NULL,
                                .numpages = numpages,
                                .mask_set = __pgprot(0),
                                .mask_clr = __pgprot(_PAGE_PRESENT | _PAGE_RW),
@@ -1434,6 +1831,36 @@ bool kernel_page_present(struct page *page)
 
 #endif /* CONFIG_DEBUG_PAGEALLOC */
 
+int kernel_map_pages_in_pgd(pgd_t *pgd, u64 pfn, unsigned long address,
+                           unsigned numpages, unsigned long page_flags)
+{
+       int retval = -EINVAL;
+
+       struct cpa_data cpa = {
+               .vaddr = &address,
+               .pfn = pfn,
+               .pgd = pgd,
+               .numpages = numpages,
+               .mask_set = __pgprot(0),
+               .mask_clr = __pgprot(0),
+               .flags = 0,
+       };
+
+       if (!(__supported_pte_mask & _PAGE_NX))
+               goto out;
+
+       if (!(page_flags & _PAGE_NX))
+               cpa.mask_clr = __pgprot(_PAGE_NX);
+
+       cpa.mask_set = __pgprot(_PAGE_PRESENT | page_flags);
+
+       retval = __change_page_attr_set_clr(&cpa, 0);
+       __flush_tlb_all();
+
+out:
+       return retval;
+}
+
 /*
  * The testcases use internal knowledge of the implementation that shouldn't
  * be exposed to the rest of the kernel. Include these directly here.
index 5c90975cdf0f8242db167fa9c471c1ea2bf3e512..43984bc1665a917303ae574b27345138cc9560b6 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/rcupdate.h>
 #include <asm/e820.h>
 #include <asm/pci_x86.h>
-#include <acpi/acpi.h>
 
 /* Assume systems with more busses have correct MCFG */
 #define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG))
index 6599a0027b76bb9ab3b390fe31e5ba0ae10ed124..81b506d5befd46e5a494d6cbef7aa71edceca7f1 100644 (file)
@@ -142,7 +142,7 @@ early_efi_write(struct console *con, const char *str, unsigned int num)
                        efi_y += font->height;
                }
 
-               if (efi_y + font->height >= si->lfb_height) {
+               if (efi_y + font->height > si->lfb_height) {
                        u32 i;
 
                        efi_y -= font->height;
index 92c02344a060f2dacc7997185d6fd6bc04ed225e..f8ec4dafc74e5e94011c3f092f17f4c1b3f40109 100644 (file)
@@ -12,6 +12,8 @@
  *     Bibo Mao <bibo.mao@intel.com>
  *     Chandramouli Narayanan <mouli@linux.intel.com>
  *     Huang Ying <ying.huang@intel.com>
+ * Copyright (C) 2013 SuSE Labs
+ *     Borislav Petkov <bp@suse.de> - runtime services VA mapping
  *
  * Copied from efi_32.c to eliminate the duplicated code between EFI
  * 32/64 support code. --ying 2007-10-26
@@ -51,7 +53,7 @@
 #include <asm/x86_init.h>
 #include <asm/rtc.h>
 
-#define EFI_DEBUG      1
+#define EFI_DEBUG
 
 #define EFI_MIN_RESERVE 5120
 
@@ -398,9 +400,9 @@ int __init efi_memblock_x86_reserve_range(void)
        return 0;
 }
 
-#if EFI_DEBUG
 static void __init print_efi_memmap(void)
 {
+#ifdef EFI_DEBUG
        efi_memory_desc_t *md;
        void *p;
        int i;
@@ -415,8 +417,8 @@ static void __init print_efi_memmap(void)
                        md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT),
                        (md->num_pages >> (20 - EFI_PAGE_SHIFT)));
        }
-}
 #endif  /*  EFI_DEBUG  */
+}
 
 void __init efi_reserve_boot_services(void)
 {
@@ -696,10 +698,7 @@ void __init efi_init(void)
                x86_platform.set_wallclock = efi_set_rtc_mmss;
        }
 #endif
-
-#if EFI_DEBUG
        print_efi_memmap();
-#endif
 }
 
 void __init efi_late_init(void)
@@ -748,21 +747,56 @@ void efi_memory_uc(u64 addr, unsigned long size)
        set_memory_uc(addr, npages);
 }
 
+void __init old_map_region(efi_memory_desc_t *md)
+{
+       u64 start_pfn, end_pfn, end;
+       unsigned long size;
+       void *va;
+
+       start_pfn = PFN_DOWN(md->phys_addr);
+       size      = md->num_pages << PAGE_SHIFT;
+       end       = md->phys_addr + size;
+       end_pfn   = PFN_UP(end);
+
+       if (pfn_range_is_mapped(start_pfn, end_pfn)) {
+               va = __va(md->phys_addr);
+
+               if (!(md->attribute & EFI_MEMORY_WB))
+                       efi_memory_uc((u64)(unsigned long)va, size);
+       } else
+               va = efi_ioremap(md->phys_addr, size,
+                                md->type, md->attribute);
+
+       md->virt_addr = (u64) (unsigned long) va;
+       if (!va)
+               pr_err("ioremap of 0x%llX failed!\n",
+                      (unsigned long long)md->phys_addr);
+}
+
 /*
  * This function will switch the EFI runtime services to virtual mode.
- * Essentially, look through the EFI memmap and map every region that
- * has the runtime attribute bit set in its memory descriptor and update
- * that memory descriptor with the virtual address obtained from ioremap().
- * This enables the runtime services to be called without having to
+ * Essentially, we look through the EFI memmap and map every region that
+ * has the runtime attribute bit set in its memory descriptor into the
+ * ->trampoline_pgd page table using a top-down VA allocation scheme.
+ *
+ * The old method which used to update that memory descriptor with the
+ * virtual address obtained from ioremap() is still supported when the
+ * kernel is booted with efi=old_map on its command line. Same old
+ * method enabled the runtime services to be called without having to
  * thunk back into physical mode for every invocation.
+ *
+ * The new method does a pagetable switch in a preemption-safe manner
+ * so that we're in a different address space when calling a runtime
+ * function. For function arguments passing we do copy the PGDs of the
+ * kernel page table into ->trampoline_pgd prior to each call.
  */
 void __init efi_enter_virtual_mode(void)
 {
        efi_memory_desc_t *md, *prev_md = NULL;
-       efi_status_t status;
+       void *p, *new_memmap = NULL;
        unsigned long size;
-       u64 end, systab, start_pfn, end_pfn;
-       void *p, *va, *new_memmap = NULL;
+       efi_status_t status;
+       u64 end, systab;
        int count = 0;
 
        efi.systab = NULL;
@@ -771,7 +805,6 @@ void __init efi_enter_virtual_mode(void)
         * We don't do virtual mode, since we don't do runtime services, on
         * non-native EFI
         */
-
        if (!efi_is_native()) {
                efi_unmap_memmap();
                return;
@@ -802,6 +835,7 @@ void __init efi_enter_virtual_mode(void)
                        continue;
                }
                prev_md = md;
+
        }
 
        for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
@@ -814,36 +848,24 @@ void __init efi_enter_virtual_mode(void)
                                continue;
                }
 
+               efi_map_region(md);
+
                size = md->num_pages << EFI_PAGE_SHIFT;
                end = md->phys_addr + size;
 
-               start_pfn = PFN_DOWN(md->phys_addr);
-               end_pfn = PFN_UP(end);
-               if (pfn_range_is_mapped(start_pfn, end_pfn)) {
-                       va = __va(md->phys_addr);
-
-                       if (!(md->attribute & EFI_MEMORY_WB))
-                               efi_memory_uc((u64)(unsigned long)va, size);
-               } else
-                       va = efi_ioremap(md->phys_addr, size,
-                                        md->type, md->attribute);
-
-               md->virt_addr = (u64) (unsigned long) va;
-
-               if (!va) {
-                       pr_err("ioremap of 0x%llX failed!\n",
-                              (unsigned long long)md->phys_addr);
-                       continue;
-               }
-
                systab = (u64) (unsigned long) efi_phys.systab;
                if (md->phys_addr <= systab && systab < end) {
                        systab += md->virt_addr - md->phys_addr;
+
                        efi.systab = (efi_system_table_t *) (unsigned long) systab;
                }
+
                new_memmap = krealloc(new_memmap,
                                      (count + 1) * memmap.desc_size,
                                      GFP_KERNEL);
+               if (!new_memmap)
+                       goto err_out;
+
                memcpy(new_memmap + (count * memmap.desc_size), md,
                       memmap.desc_size);
                count++;
@@ -851,6 +873,9 @@ void __init efi_enter_virtual_mode(void)
 
        BUG_ON(!efi.systab);
 
+       efi_setup_page_tables();
+       efi_sync_low_kernel_mappings();
+
        status = phys_efi_set_virtual_address_map(
                memmap.desc_size * count,
                memmap.desc_size,
@@ -883,7 +908,8 @@ void __init efi_enter_virtual_mode(void)
        efi.query_variable_info = virt_efi_query_variable_info;
        efi.update_capsule = virt_efi_update_capsule;
        efi.query_capsule_caps = virt_efi_query_capsule_caps;
-       if (__supported_pte_mask & _PAGE_NX)
+
+       if (efi_enabled(EFI_OLD_MEMMAP) && (__supported_pte_mask & _PAGE_NX))
                runtime_code_page_mkexec();
 
        kfree(new_memmap);
@@ -894,6 +920,11 @@ void __init efi_enter_virtual_mode(void)
                         EFI_VARIABLE_BOOTSERVICE_ACCESS |
                         EFI_VARIABLE_RUNTIME_ACCESS,
                         0, NULL);
+
+       return;
+
+ err_out:
+       pr_err("Error reallocating memory, EFI runtime non-functional!\n");
 }
 
 /*
@@ -1013,3 +1044,15 @@ efi_status_t efi_query_variable_store(u32 attributes, unsigned long size)
        return EFI_SUCCESS;
 }
 EXPORT_SYMBOL_GPL(efi_query_variable_store);
+
+static int __init parse_efi_cmdline(char *str)
+{
+       if (*str == '=')
+               str++;
+
+       if (!strncmp(str, "old_map", 7))
+               set_bit(EFI_OLD_MEMMAP, &x86_efi_facility);
+
+       return 0;
+}
+early_param("efi", parse_efi_cmdline);
index 40e446941dd7eceb587b2b4572c96279631e5f56..e94557cf54878f1c8111a9e800a484d3880192d3 100644 (file)
  * claim EFI runtime service handler exclusively and to duplicate a memory in
  * low memory space say 0 - 3G.
  */
-
 static unsigned long efi_rt_eflags;
 
+void efi_sync_low_kernel_mappings(void) {}
+void efi_setup_page_tables(void) {}
+
+void __init efi_map_region(efi_memory_desc_t *md)
+{
+       old_map_region(md);
+}
+
 void efi_call_phys_prelog(void)
 {
        struct desc_ptr gdt_descr;
index 39a0e7f1f0a3ec1c7601888d30c724a5b8660e19..bf286c386d330272fdb2e4d7cef99ddf108d489c 100644 (file)
 #include <asm/efi.h>
 #include <asm/cacheflush.h>
 #include <asm/fixmap.h>
+#include <asm/realmode.h>
 
 static pgd_t *save_pgd __initdata;
 static unsigned long efi_flags __initdata;
 
+/*
+ * We allocate runtime services regions bottom-up, starting from -4G, i.e.
+ * 0xffff_ffff_0000_0000 and limit EFI VA mapping space to 64G.
+ */
+static u64 efi_va      = -4 * (1UL << 30);
+#define EFI_VA_END     (-68 * (1UL << 30))
+
+/*
+ * Scratch space used for switching the pagetable in the EFI stub
+ */
+struct efi_scratch {
+       u64 r15;
+       u64 prev_cr3;
+       pgd_t *efi_pgt;
+       bool use_pgd;
+};
+
 static void __init early_code_mapping_set_exec(int executable)
 {
        efi_memory_desc_t *md;
@@ -65,6 +83,9 @@ void __init efi_call_phys_prelog(void)
        int pgd;
        int n_pgds;
 
+       if (!efi_enabled(EFI_OLD_MEMMAP))
+               return;
+
        early_code_mapping_set_exec(1);
        local_irq_save(efi_flags);
 
@@ -86,6 +107,10 @@ void __init efi_call_phys_epilog(void)
         */
        int pgd;
        int n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT) , PGDIR_SIZE);
+
+       if (!efi_enabled(EFI_OLD_MEMMAP))
+               return;
+
        for (pgd = 0; pgd < n_pgds; pgd++)
                set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), save_pgd[pgd]);
        kfree(save_pgd);
@@ -94,6 +119,90 @@ void __init efi_call_phys_epilog(void)
        early_code_mapping_set_exec(0);
 }
 
+/*
+ * Add low kernel mappings for passing arguments to EFI functions.
+ */
+void efi_sync_low_kernel_mappings(void)
+{
+       unsigned num_pgds;
+       pgd_t *pgd = (pgd_t *)__va(real_mode_header->trampoline_pgd);
+
+       if (efi_enabled(EFI_OLD_MEMMAP))
+               return;
+
+       num_pgds = pgd_index(MODULES_END - 1) - pgd_index(PAGE_OFFSET);
+
+       memcpy(pgd + pgd_index(PAGE_OFFSET),
+               init_mm.pgd + pgd_index(PAGE_OFFSET),
+               sizeof(pgd_t) * num_pgds);
+}
+
+void efi_setup_page_tables(void)
+{
+       efi_scratch.efi_pgt = (pgd_t *)(unsigned long)real_mode_header->trampoline_pgd;
+
+       if (!efi_enabled(EFI_OLD_MEMMAP))
+               efi_scratch.use_pgd = true;
+}
+
+static void __init __map_region(efi_memory_desc_t *md, u64 va)
+{
+       pgd_t *pgd = (pgd_t *)__va(real_mode_header->trampoline_pgd);
+       unsigned long pf = 0, size;
+       u64 end;
+
+       if (!(md->attribute & EFI_MEMORY_WB))
+               pf |= _PAGE_PCD;
+
+       size = md->num_pages << PAGE_SHIFT;
+       end  = va + size;
+
+       if (kernel_map_pages_in_pgd(pgd, md->phys_addr, va, md->num_pages, pf))
+               pr_warn("Error mapping PA 0x%llx -> VA 0x%llx!\n",
+                          md->phys_addr, va);
+}
+
+void __init efi_map_region(efi_memory_desc_t *md)
+{
+       unsigned long size = md->num_pages << PAGE_SHIFT;
+       u64 pa = md->phys_addr;
+
+       if (efi_enabled(EFI_OLD_MEMMAP))
+               return old_map_region(md);
+
+       /*
+        * Make sure the 1:1 mappings are present as a catch-all for b0rked
+        * firmware which doesn't update all internal pointers after switching
+        * to virtual mode and would otherwise crap on us.
+        */
+       __map_region(md, md->phys_addr);
+
+       efi_va -= size;
+
+       /* Is PA 2M-aligned? */
+       if (!(pa & (PMD_SIZE - 1))) {
+               efi_va &= PMD_MASK;
+       } else {
+               u64 pa_offset = pa & (PMD_SIZE - 1);
+               u64 prev_va = efi_va;
+
+               /* get us the same offset within this 2M page */
+               efi_va = (efi_va & PMD_MASK) + pa_offset;
+
+               if (efi_va > prev_va)
+                       efi_va -= PMD_SIZE;
+       }
+
+       if (efi_va < EFI_VA_END) {
+               pr_warn(FW_WARN "VA address range overflow!\n");
+               return;
+       }
+
+       /* Do the VA map */
+       __map_region(md, efi_va);
+       md->virt_addr = efi_va;
+}
+
 void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size,
                                 u32 type, u64 attribute)
 {
index 4c07ccab8146f0bbed2850f586a68f126b2bc7eb..88073b1402988b49eb6c5e95f9f801a14d40f144 100644 (file)
        mov %rsi, %cr0;                 \
        mov (%rsp), %rsp
 
+       /* stolen from gcc */
+       .macro FLUSH_TLB_ALL
+       movq %r15, efi_scratch(%rip)
+       movq %r14, efi_scratch+8(%rip)
+       movq %cr4, %r15
+       movq %r15, %r14
+       andb $0x7f, %r14b
+       movq %r14, %cr4
+       movq %r15, %cr4
+       movq efi_scratch+8(%rip), %r14
+       movq efi_scratch(%rip), %r15
+       .endm
+
+       .macro SWITCH_PGT
+       cmpb $0, efi_scratch+24(%rip)
+       je 1f
+       movq %r15, efi_scratch(%rip)            # r15
+       # save previous CR3
+       movq %cr3, %r15
+       movq %r15, efi_scratch+8(%rip)          # prev_cr3
+       movq efi_scratch+16(%rip), %r15         # EFI pgt
+       movq %r15, %cr3
+       1:
+       .endm
+
+       .macro RESTORE_PGT
+       cmpb $0, efi_scratch+24(%rip)
+       je 2f
+       movq efi_scratch+8(%rip), %r15
+       movq %r15, %cr3
+       movq efi_scratch(%rip), %r15
+       FLUSH_TLB_ALL
+       2:
+       .endm
+
 ENTRY(efi_call0)
        SAVE_XMM
        subq $32, %rsp
+       SWITCH_PGT
        call *%rdi
+       RESTORE_PGT
        addq $32, %rsp
        RESTORE_XMM
        ret
@@ -47,7 +84,9 @@ ENTRY(efi_call1)
        SAVE_XMM
        subq $32, %rsp
        mov  %rsi, %rcx
+       SWITCH_PGT
        call *%rdi
+       RESTORE_PGT
        addq $32, %rsp
        RESTORE_XMM
        ret
@@ -57,7 +96,9 @@ ENTRY(efi_call2)
        SAVE_XMM
        subq $32, %rsp
        mov  %rsi, %rcx
+       SWITCH_PGT
        call *%rdi
+       RESTORE_PGT
        addq $32, %rsp
        RESTORE_XMM
        ret
@@ -68,7 +109,9 @@ ENTRY(efi_call3)
        subq $32, %rsp
        mov  %rcx, %r8
        mov  %rsi, %rcx
+       SWITCH_PGT
        call *%rdi
+       RESTORE_PGT
        addq $32, %rsp
        RESTORE_XMM
        ret
@@ -80,7 +123,9 @@ ENTRY(efi_call4)
        mov %r8, %r9
        mov %rcx, %r8
        mov %rsi, %rcx
+       SWITCH_PGT
        call *%rdi
+       RESTORE_PGT
        addq $32, %rsp
        RESTORE_XMM
        ret
@@ -93,7 +138,9 @@ ENTRY(efi_call5)
        mov %r8, %r9
        mov %rcx, %r8
        mov %rsi, %rcx
+       SWITCH_PGT
        call *%rdi
+       RESTORE_PGT
        addq $48, %rsp
        RESTORE_XMM
        ret
@@ -109,8 +156,15 @@ ENTRY(efi_call6)
        mov %r8, %r9
        mov %rcx, %r8
        mov %rsi, %rcx
+       SWITCH_PGT
        call *%rdi
+       RESTORE_PGT
        addq $48, %rsp
        RESTORE_XMM
        ret
 ENDPROC(efi_call6)
+
+       .data
+ENTRY(efi_scratch)
+       .fill 3,8,0
+       .byte 0
index 649a12befba92f399895b947cc779e0269ac750d..08e350e757dcd189c29e06d4d0b199a2cd920b9f 100644 (file)
@@ -15,8 +15,7 @@
 #include <linux/power_supply.h>
 #include <linux/olpc-ec.h>
 
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
 #include <asm/olpc.h>
 
 #define DRV_NAME                       "olpc-xo15-sci"
index f7bab68a4b83e4094db9b70c50292fddd88098c1..11f9285a2ff66726b6c62c7eb608e03f516dcc27 100644 (file)
@@ -722,15 +722,25 @@ static void percpu_init(void)
 
 /*
  * Check to see if a symbol lies in the .data..percpu section.
- * For some as yet not understood reason the "__init_begin"
- * symbol which immediately preceeds the .data..percpu section
- * also shows up as it it were part of it so we do an explict
- * check for that symbol name and ignore it.
+ *
+ * The linker incorrectly associates some symbols with the
+ * .data..percpu section so we also need to check the symbol
+ * name to make sure that we classify the symbol correctly.
+ *
+ * The GNU linker incorrectly associates:
+ *     __init_begin
+ *     __per_cpu_load
+ *
+ * The "gold" linker incorrectly associates:
+ *     init_per_cpu__irq_stack_union
+ *     init_per_cpu__gdt_page
  */
 static int is_percpu_sym(ElfW(Sym) *sym, const char *symname)
 {
        return (sym->st_shndx == per_cpu_shndx) &&
-               strcmp(symname, "__init_begin");
+               strcmp(symname, "__init_begin") &&
+               strcmp(symname, "__per_cpu_load") &&
+               strncmp(symname, "init_per_cpu_", 13);
 }
 
 
index 8d24dcb7cdac6df122e6779080b5e31b234a6ee5..70a160be3464aa0858e87d5c29816085308d1ef7 100644 (file)
@@ -9,7 +9,6 @@ config XTENSA
        select GENERIC_CLOCKEVENTS
        select VIRT_TO_BUS
        select GENERIC_IRQ_SHOW
-       select GENERIC_CPU_DEVICES
        select GENERIC_SCHED_CLOCK
        select MODULES_USE_ELF_RELA
        select GENERIC_PCI_IOMAP
@@ -19,6 +18,7 @@ config XTENSA
        select IRQ_DOMAIN
        select HAVE_OPROFILE
        select HAVE_FUNCTION_TRACER
+       select HAVE_IRQ_TIME_ACCOUNTING
        help
          Xtensa processors are 32-bit RISC machines designed by Tensilica
          primarily for embedded systems.  These processors are both
@@ -64,6 +64,9 @@ config MMU
 config VARIANT_IRQ_SWITCH
        def_bool n
 
+config MAY_HAVE_SMP
+       def_bool n
+
 menu "Processor type and features"
 
 choice
@@ -104,6 +107,48 @@ config XTENSA_UNALIGNED_USER
 
 source "kernel/Kconfig.preempt"
 
+config HAVE_SMP
+       bool "System Supports SMP (MX)"
+       depends on MAY_HAVE_SMP
+       select XTENSA_MX
+       help
+         This option is use to indicate that the system-on-a-chip (SOC)
+         supports Multiprocessing. Multiprocessor support implemented above
+         the CPU core definition and currently needs to be selected manually.
+
+         Multiprocessor support in implemented with external cache and
+         interrupt controlers.
+
+         The MX interrupt distributer adds Interprocessor Interrupts
+         and causes the IRQ numbers to be increased by 4 for devices
+         like the open cores ethernet driver and the serial interface.
+
+         You still have to select "Enable SMP" to enable SMP on this SOC.
+
+config SMP
+       bool "Enable Symmetric multi-processing support"
+       depends on HAVE_SMP
+       select USE_GENERIC_SMP_HELPERS
+       select GENERIC_SMP_IDLE_THREAD
+       help
+         Enabled SMP Software; allows more than one CPU/CORE
+         to be activated during startup.
+
+config NR_CPUS
+       depends on SMP
+       int "Maximum number of CPUs (2-32)"
+       range 2 32
+       default "4"
+
+config HOTPLUG_CPU
+       bool "Enable CPU hotplug support"
+       depends on SMP
+       help
+         Say Y here to allow turning CPUs off and on. CPUs can be
+         controlled through /sys/devices/system/cpu.
+
+         Say N if you want to disable CPU hotplug.
+
 config MATH_EMULATION
        bool "Math emulation"
        help
index 7eda6ecf7eef3652cbc096b7f4859b03a66996bd..b042c3f508e66908df6a6972f0fe8e1e955ba3cd 100644 (file)
@@ -26,7 +26,7 @@
        };
 
        pic: pic {
-               compatible = "xtensa,pic";
+               compatible = "cdns,xtensa-pic";
                /* one cell: internal irq number,
                 * two cells: second cell == 0: internal irq number
                 *            second cell == 1: external irq number
index 228d6aee3a16528f0e5972371e5a1fd6feac9a79..5851db291583face7d032c2929dd5c91b58204d6 100644 (file)
@@ -8,7 +8,6 @@ generic-y += emergency-restart.h
 generic-y += errno.h
 generic-y += exec.h
 generic-y += fcntl.h
-generic-y += futex.h
 generic-y += hardirq.h
 generic-y += ioctl.h
 generic-y += irq_regs.h
index ef021677d536538c817021c89f0841ada0ed0c30..8e5e5c980a7a4b1b01708c8160e0559f5ad63963 100644 (file)
@@ -17,7 +17,9 @@
 #define wmb() mb()
 
 #ifdef CONFIG_SMP
-#error smp_* not defined
+#define smp_mb()       mb()
+#define smp_rmb()      rmb()
+#define smp_wmb()      wmb()
 #else
 #define smp_mb()       barrier()
 #define smp_rmb()      barrier()
index 84afe58d5d374bc7cc19f8d02dbcc279b3b0014a..7b6873ae84c295740d8183b52610ba0ce91aad91 100644 (file)
 #include <asm/processor.h>
 #include <asm/byteorder.h>
 
-#ifdef CONFIG_SMP
-# error SMP not supported on this architecture
-#endif
-
-#define smp_mb__before_clear_bit()     barrier()
-#define smp_mb__after_clear_bit()      barrier()
+#define smp_mb__before_clear_bit()     smp_mb()
+#define smp_mb__after_clear_bit()      smp_mb()
 
 #include <asm-generic/bitops/non-atomic.h>
 
index 127cd48883c4274526c63631b181bea6dc366941..555a98a1845363588ced5fd3ec26a2269846e3d8 100644 (file)
@@ -1,18 +1,14 @@
 /*
- * include/asm-xtensa/cacheflush.h
- *
  * 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) 2001 - 2007 Tensilica Inc.
+ * (C) 2001 - 2013 Tensilica Inc.
  */
 
 #ifndef _XTENSA_CACHEFLUSH_H
 #define _XTENSA_CACHEFLUSH_H
 
-#ifdef __KERNEL__
-
 #include <linux/mm.h>
 #include <asm/processor.h>
 #include <asm/page.h>
@@ -51,7 +47,6 @@ extern void __invalidate_icache_page(unsigned long);
 extern void __invalidate_icache_range(unsigned long, unsigned long);
 extern void __invalidate_dcache_range(unsigned long, unsigned long);
 
-
 #if XCHAL_DCACHE_IS_WRITEBACK
 extern void __flush_invalidate_dcache_all(void);
 extern void __flush_dcache_page(unsigned long);
@@ -87,9 +82,22 @@ static inline void __invalidate_icache_page_alias(unsigned long virt,
  * (see also Documentation/cachetlb.txt)
  */
 
-#if (DCACHE_WAY_SIZE > PAGE_SIZE)
+#if (DCACHE_WAY_SIZE > PAGE_SIZE) || defined(CONFIG_SMP)
+
+#ifdef CONFIG_SMP
+void flush_cache_all(void);
+void flush_cache_range(struct vm_area_struct*, ulong, ulong);
+void flush_icache_range(unsigned long start, unsigned long end);
+void flush_cache_page(struct vm_area_struct*,
+                            unsigned long, unsigned long);
+#else
+#define flush_cache_all local_flush_cache_all
+#define flush_cache_range local_flush_cache_range
+#define flush_icache_range local_flush_icache_range
+#define flush_cache_page  local_flush_cache_page
+#endif
 
-#define flush_cache_all()                                              \
+#define local_flush_cache_all()                                                \
        do {                                                            \
                __flush_invalidate_dcache_all();                        \
                __invalidate_icache_all();                              \
@@ -103,9 +111,11 @@ static inline void __invalidate_icache_page_alias(unsigned long virt,
 
 #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
 extern void flush_dcache_page(struct page*);
-extern void flush_cache_range(struct vm_area_struct*, ulong, ulong);
-extern void flush_cache_page(struct vm_area_struct*,
-                            unsigned long, unsigned long);
+
+void local_flush_cache_range(struct vm_area_struct *vma,
+               unsigned long start, unsigned long end);
+void local_flush_cache_page(struct vm_area_struct *vma,
+               unsigned long address, unsigned long pfn);
 
 #else
 
@@ -119,13 +129,14 @@ extern void flush_cache_page(struct vm_area_struct*,
 #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0
 #define flush_dcache_page(page)                                do { } while (0)
 
-#define flush_cache_page(vma,addr,pfn)                 do { } while (0)
-#define flush_cache_range(vma,start,end)               do { } while (0)
+#define flush_icache_range local_flush_icache_range
+#define flush_cache_page(vma, addr, pfn)               do { } while (0)
+#define flush_cache_range(vma, start, end)             do { } while (0)
 
 #endif
 
 /* Ensure consistency between data and instruction cache. */
-#define flush_icache_range(start,end)                                  \
+#define local_flush_icache_range(start, end)                           \
        do {                                                            \
                __flush_dcache_range(start, (end) - (start));           \
                __invalidate_icache_range(start,(end) - (start));       \
@@ -253,5 +264,4 @@ static inline void flush_invalidate_dcache_unaligned(u32 addr, u32 size)
        }
 }
 
-#endif /* __KERNEL__ */
 #endif /* _XTENSA_CACHEFLUSH_H */
index 3899610c1dfff71a53e0144969fd990e59e75f62..742b89f3ca2cf22d535b21441383b97256bf5903 100644 (file)
@@ -19,9 +19,12 @@ extern unsigned long loops_per_jiffy;
 
 static inline void __delay(unsigned long loops)
 {
-       /* 2 cycles per loop. */
-       __asm__ __volatile__ ("1: addi %0, %0, -2; bgeui %0, 2, 1b"
-                             : "=r" (loops) : "0" (loops));
+       if (__builtin_constant_p(loops) && loops < 2)
+               __asm__ __volatile__ ("nop");
+       else if (loops >= 2)
+               /* 2 cycles per loop. */
+               __asm__ __volatile__ ("1: addi %0, %0, -2; bgeui %0, 2, 1b"
+                               : "+r" (loops));
 }
 
 /* For SMP/NUMA systems, change boot_cpu_data to something like
index 73cc3f482304e35f9144d451e3fefab59fe8c6c0..736b9d214d8016012393c7914d03d89fb5eacfa6 100644 (file)
@@ -18,7 +18,7 @@
                __asm__ __volatile__ ( \
                        "mov %0, a0\n" \
                        "mov %1, a1\n" \
-                       : "=r"(a0), "=r"(a1) : : ); \
+                       : "=r"(a0), "=r"(a1)); \
                MAKE_PC_FROM_RA(a0, a1); })
 #ifdef CONFIG_FRAME_POINTER
 extern unsigned long return_address(unsigned level);
diff --git a/arch/xtensa/include/asm/futex.h b/arch/xtensa/include/asm/futex.h
new file mode 100644 (file)
index 0000000..b39531b
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Atomic futex routines
+ *
+ * Based on the PowerPC implementataion
+ *
+ * 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.
+ *
+ * Copyright (C) 2013 TangoTec Ltd.
+ *
+ * Baruch Siach <baruch@tkos.co.il>
+ */
+
+#ifndef _ASM_XTENSA_FUTEX_H
+#define _ASM_XTENSA_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <linux/uaccess.h>
+#include <linux/errno.h>
+
+#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
+       __asm__ __volatile(                             \
+       "1:     l32i    %0, %2, 0\n"                    \
+               insn "\n"                               \
+       "       wsr     %0, scompare1\n"                \
+       "2:     s32c1i  %1, %2, 0\n"                    \
+       "       bne     %1, %0, 1b\n"                   \
+       "       movi    %1, 0\n"                        \
+       "3:\n"                                          \
+       "       .section .fixup,\"ax\"\n"               \
+       "       .align 4\n"                             \
+       "4:     .long   3b\n"                           \
+       "5:     l32r    %0, 4b\n"                       \
+       "       movi    %1, %3\n"                       \
+       "       jx      %0\n"                           \
+       "       .previous\n"                            \
+       "       .section __ex_table,\"a\"\n"            \
+       "       .long 1b,5b,2b,5b\n"                    \
+       "       .previous\n"                            \
+       : "=&r" (oldval), "=&r" (ret)                   \
+       : "r" (uaddr), "I" (-EFAULT), "r" (oparg)       \
+       : "memory")
+
+static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
+{
+       int op = (encoded_op >> 28) & 7;
+       int cmp = (encoded_op >> 24) & 15;
+       int oparg = (encoded_op << 8) >> 20;
+       int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret;
+       if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+               oparg = 1 << oparg;
+
+       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
+               return -EFAULT;
+
+#if !XCHAL_HAVE_S32C1I
+       return -ENOSYS;
+#endif
+
+       pagefault_disable();
+
+       switch (op) {
+       case FUTEX_OP_SET:
+               __futex_atomic_op("mov %1, %4", ret, oldval, uaddr, oparg);
+               break;
+       case FUTEX_OP_ADD:
+               __futex_atomic_op("add %1, %0, %4", ret, oldval, uaddr,
+                               oparg);
+               break;
+       case FUTEX_OP_OR:
+               __futex_atomic_op("or %1, %0, %4", ret, oldval, uaddr,
+                               oparg);
+               break;
+       case FUTEX_OP_ANDN:
+               __futex_atomic_op("and %1, %0, %4", ret, oldval, uaddr,
+                               ~oparg);
+               break;
+       case FUTEX_OP_XOR:
+               __futex_atomic_op("xor %1, %0, %4", ret, oldval, uaddr,
+                               oparg);
+               break;
+       default:
+               ret = -ENOSYS;
+       }
+
+       pagefault_enable();
+
+       if (ret)
+               return ret;
+
+       switch (cmp) {
+       case FUTEX_OP_CMP_EQ: return (oldval == cmparg);
+       case FUTEX_OP_CMP_NE: return (oldval != cmparg);
+       case FUTEX_OP_CMP_LT: return (oldval < cmparg);
+       case FUTEX_OP_CMP_GE: return (oldval >= cmparg);
+       case FUTEX_OP_CMP_LE: return (oldval <= cmparg);
+       case FUTEX_OP_CMP_GT: return (oldval > cmparg);
+       }
+
+       return -ENOSYS;
+}
+
+static inline int
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+                             u32 oldval, u32 newval)
+{
+       int ret = 0;
+       u32 prev;
+
+       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
+               return -EFAULT;
+
+#if !XCHAL_HAVE_S32C1I
+       return -ENOSYS;
+#endif
+
+       __asm__ __volatile__ (
+       "       # futex_atomic_cmpxchg_inatomic\n"
+       "1:     l32i    %1, %3, 0\n"
+       "       mov     %0, %5\n"
+       "       wsr     %1, scompare1\n"
+       "2:     s32c1i  %0, %3, 0\n"
+       "3:\n"
+       "       .section .fixup,\"ax\"\n"
+       "       .align 4\n"
+       "4:     .long   3b\n"
+       "5:     l32r    %1, 4b\n"
+       "       movi    %0, %6\n"
+       "       jx      %1\n"
+       "       .previous\n"
+       "       .section __ex_table,\"a\"\n"
+       "       .long 1b,5b,2b,5b\n"
+       "       .previous\n"
+       : "+r" (ret), "=&r" (prev), "+m" (*uaddr)
+       : "r" (uaddr), "r" (oldval), "r" (newval), "I" (-EFAULT)
+       : "memory");
+
+       *uval = prev;
+       return ret;
+}
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_XTENSA_FUTEX_H */
index 4c0ccc9c4f4c0adf0a8ac6212818567749147fed..f71f88ea7646dcc798067e984dddefa8a659037d 100644 (file)
@@ -43,5 +43,14 @@ static __inline__ int irq_canonicalize(int irq)
 }
 
 struct irqaction;
+struct irq_domain;
+
+void migrate_irqs(void);
+int xtensa_irq_domain_xlate(const u32 *intspec, unsigned int intsize,
+               unsigned long int_irq, unsigned long ext_irq,
+               unsigned long *out_hwirq, unsigned int *out_type);
+int xtensa_irq_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw);
+unsigned xtensa_map_ext_irq(unsigned ext_irq);
+unsigned xtensa_get_ext_irq_no(unsigned irq);
 
 #endif /* _XTENSA_IRQ_H */
index 8554b2c8b17a0128bc873f2d67b194462f89c2bf..71afe418d0e53e2d9239b261cd34a2efc8d4f9ac 100644 (file)
@@ -1,11 +1,9 @@
 /*
- * include/asm-xtensa/mmu.h
- *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
+ * Copyright (C) 2001 - 2013 Tensilica Inc.
  */
 
 #ifndef _XTENSA_MMU_H
 #include <asm-generic/mmu.h>
 #else
 
-/* Default "unsigned long" context */
-typedef unsigned long mm_context_t;
+typedef struct {
+       unsigned long asid[NR_CPUS];
+       unsigned int cpu;
+} mm_context_t;
 
 #endif /* CONFIG_MMU */
 #endif /* _XTENSA_MMU_H */
index d43525a286bbf248b43e36fb878f6ee7fb31fa1e..d33c71a8c9ec69285fc508e653a0acfee3a691fa 100644 (file)
@@ -1,13 +1,11 @@
 /*
- * include/asm-xtensa/mmu_context.h
- *
  * Switch an MMU context.
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
+ * Copyright (C) 2001 - 2013 Tensilica Inc.
  */
 
 #ifndef _XTENSA_MMU_CONTEXT_H
 #include <linux/stringify.h>
 #include <linux/sched.h>
 
-#include <variant/core.h>
+#include <asm/vectors.h>
 
 #include <asm/pgtable.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 #include <asm-generic/mm_hooks.h>
+#include <asm-generic/percpu.h>
 
 #if (XCHAL_HAVE_TLBS != 1)
 # error "Linux must have an MMU!"
 #endif
 
-extern unsigned long asid_cache;
+DECLARE_PER_CPU(unsigned long, asid_cache);
+#define cpu_asid_cache(cpu) per_cpu(asid_cache, cpu)
 
 /*
  * NO_CONTEXT is the invalid ASID value that we don't ever assign to
- * any user or kernel context.
+ * any user or kernel context.  We use the reserved values in the
+ * ASID_INSERT macro below.
  *
  * 0 invalid
  * 1 kernel
@@ -49,6 +50,12 @@ extern unsigned long asid_cache;
 #define ASID_MASK      ((1 << XCHAL_MMU_ASID_BITS) - 1)
 #define ASID_INSERT(x) (0x03020001 | (((x) & ASID_MASK) << 8))
 
+#ifdef CONFIG_MMU
+void init_mmu(void);
+#else
+static inline void init_mmu(void) { }
+#endif
+
 static inline void set_rasid_register (unsigned long val)
 {
        __asm__ __volatile__ (" wsr %0, rasid\n\t"
@@ -62,64 +69,77 @@ static inline unsigned long get_rasid_register (void)
        return tmp;
 }
 
-static inline void
-__get_new_mmu_context(struct mm_struct *mm)
+static inline void get_new_mmu_context(struct mm_struct *mm, unsigned int cpu)
 {
-       extern void flush_tlb_all(void);
-       if (! (++asid_cache & ASID_MASK) ) {
-               flush_tlb_all(); /* start new asid cycle */
-               asid_cache += ASID_USER_FIRST;
+       unsigned long asid = cpu_asid_cache(cpu);
+       if ((++asid & ASID_MASK) == 0) {
+               /*
+                * Start new asid cycle; continue counting with next
+                * incarnation bits; skipping over 0, 1, 2, 3.
+                */
+               local_flush_tlb_all();
+               asid += ASID_USER_FIRST;
        }
-       mm->context = asid_cache;
+       cpu_asid_cache(cpu) = asid;
+       mm->context.asid[cpu] = asid;
+       mm->context.cpu = cpu;
 }
 
-static inline void
-__load_mmu_context(struct mm_struct *mm)
+static inline void get_mmu_context(struct mm_struct *mm, unsigned int cpu)
 {
-       set_rasid_register(ASID_INSERT(mm->context));
+       /*
+        * Check if our ASID is of an older version and thus invalid.
+        */
+
+       if (mm) {
+               unsigned long asid = mm->context.asid[cpu];
+
+               if (asid == NO_CONTEXT ||
+                               ((asid ^ cpu_asid_cache(cpu)) & ~ASID_MASK))
+                       get_new_mmu_context(mm, cpu);
+       }
+}
+
+static inline void activate_context(struct mm_struct *mm, unsigned int cpu)
+{
+       get_mmu_context(mm, cpu);
+       set_rasid_register(ASID_INSERT(mm->context.asid[cpu]));
        invalidate_page_directory();
 }
 
 /*
  * Initialize the context related info for a new mm_struct
- * instance.
+ * instance.  Valid cpu values are 0..(NR_CPUS-1), so initializing
+ * to -1 says the process has never run on any core.
  */
 
-static inline int
-init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+static inline int init_new_context(struct task_struct *tsk,
+               struct mm_struct *mm)
 {
-       mm->context = NO_CONTEXT;
+       int cpu;
+       for_each_possible_cpu(cpu) {
+               mm->context.asid[cpu] = NO_CONTEXT;
+       }
+       mm->context.cpu = -1;
        return 0;
 }
 
-/*
- * After we have set current->mm to a new value, this activates
- * the context for the new mm so we see the new mappings.
- */
-static inline void
-activate_mm(struct mm_struct *prev, struct mm_struct *next)
-{
-       /* Unconditionally get a new ASID.  */
-
-       __get_new_mmu_context(next);
-       __load_mmu_context(next);
-}
-
-
 static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
                             struct task_struct *tsk)
 {
-       unsigned long asid = asid_cache;
-
-       /* Check if our ASID is of an older version and thus invalid */
-
-       if (next->context == NO_CONTEXT || ((next->context^asid) & ~ASID_MASK))
-               __get_new_mmu_context(next);
-
-       __load_mmu_context(next);
+       unsigned int cpu = smp_processor_id();
+       int migrated = next->context.cpu != cpu;
+       /* Flush the icache if we migrated to a new core. */
+       if (migrated) {
+               __invalidate_icache_all();
+               next->context.cpu = cpu;
+       }
+       if (migrated || prev != next)
+               activate_context(next, cpu);
 }
 
-#define deactivate_mm(tsk, mm) do { } while(0)
+#define activate_mm(prev, next)        switch_mm((prev), (next), NULL)
+#define deactivate_mm(tsk, mm) do { } while (0)
 
 /*
  * Destroy context related info for an mm_struct that is about
diff --git a/arch/xtensa/include/asm/mxregs.h b/arch/xtensa/include/asm/mxregs.h
new file mode 100644 (file)
index 0000000..73dcc54
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Xtensa MX interrupt distributor
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2008 - 2013 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_MXREGS_H
+#define _XTENSA_MXREGS_H
+
+/*
+ * RER/WER at, as      Read/write external register
+ *     at: value
+ *     as: address
+ *
+ * Address     Value
+ * 00nn                0...0p..p       Interrupt Routing, route IRQ n to processor p
+ * 01pp                0...0d..d       16 bits (d) 'ored' as single IPI to processor p
+ * 0180                0...0m..m       Clear enable specified by mask (m)
+ * 0184                0...0m..m       Set enable specified by mask (m)
+ * 0190                0...0x..x       8-bit IPI partition register
+ *                             VVVVVVVVPPPPUUUUUUUUUUUUUUUUU
+ *                             V (10-bit) Release/Version
+ *                             P ( 4-bit) Number of cores - 1
+ *                             U (18-bit) ID
+ * 01a0                i.......i       32-bit ConfigID
+ * 0200                0...0m..m       RunStall core 'n'
+ * 0220                c               Cache coherency enabled
+ */
+
+#define MIROUT(irq)    (0x000 + (irq))
+#define MIPICAUSE(cpu) (0x100 + (cpu))
+#define MIPISET(cause) (0x140 + (cause))
+#define MIENG          0x180
+#define MIENGSET       0x184
+#define MIASG          0x188   /* Read Global Assert Register */
+#define MIASGSET       0x18c   /* Set Global Addert Regiter */
+#define MIPIPART       0x190
+#define SYSCFGID       0x1a0
+#define MPSCORE                0x200
+#define CCON           0x220
+
+#endif /* _XTENSA_MXREGS_H */
index 7e409a5b0ec50d8bf38848ff54b9ec4d058141dc..abb59708a3b75bf6ac8398be37e4fc90c349dff0 100644 (file)
@@ -191,5 +191,25 @@ extern unsigned long get_wchan(struct task_struct *p);
 #define set_sr(x,sr) ({unsigned int v=(unsigned int)x; WSR(v,sr);})
 #define get_sr(sr) ({unsigned int v; RSR(v,sr); v; })
 
+#ifndef XCHAL_HAVE_EXTERN_REGS
+#define XCHAL_HAVE_EXTERN_REGS 0
+#endif
+
+#if XCHAL_HAVE_EXTERN_REGS
+
+static inline void set_er(unsigned long value, unsigned long addr)
+{
+       asm volatile ("wer %0, %1" : : "a" (value), "a" (addr) : "memory");
+}
+
+static inline unsigned long get_er(unsigned long addr)
+{
+       register unsigned long value;
+       asm volatile ("rer %0, %1" : "=a" (value) : "a" (addr) : "memory");
+       return value;
+}
+
+#endif /* XCHAL_HAVE_EXTERN_REGS */
+
 #endif /* __ASSEMBLY__ */
 #endif /* _XTENSA_PROCESSOR_H */
index 81f31bc9dde0a857a95e9f794e09e84fa6f6c1d7..598e752dcbcd009392230869af2851afd14e4085 100644 (file)
@@ -59,9 +59,17 @@ struct pt_regs {
        (task_stack_page(tsk) + KERNEL_STACK_SIZE - (XCHAL_NUM_AREGS-16)*4) - 1)
 # define user_mode(regs) (((regs)->ps & 0x00000020)!=0)
 # define instruction_pointer(regs) ((regs)->pc)
+# define return_pointer(regs) (MAKE_PC_FROM_RA((regs)->areg[0], \
+                                              (regs)->areg[1]))
 
 # ifndef CONFIG_SMP
 #  define profile_pc(regs) instruction_pointer(regs)
+# else
+#  define profile_pc(regs)                                             \
+       ({                                                              \
+               in_lock_functions(instruction_pointer(regs)) ?          \
+               return_pointer(regs) : instruction_pointer(regs);       \
+       })
 # endif
 
 #define user_stack_pointer(regs) ((regs)->areg[1])
index 83c569e3bdbd23245dccf2e3ea7e92010589eafe..4e43f564389161687441c59168acb0e2f638b45b 100644 (file)
@@ -1,27 +1,43 @@
 /*
- * include/asm-xtensa/smp.h
- *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
+ * Copyright (C) 2001 - 2013 Tensilica Inc.
  */
 
 #ifndef _XTENSA_SMP_H
 #define _XTENSA_SMP_H
 
-extern struct xtensa_cpuinfo boot_cpu_data;
+#ifdef CONFIG_SMP
 
-#define cpu_data (&boot_cpu_data)
-#define current_cpu_data boot_cpu_data
+#define raw_smp_processor_id() (current_thread_info()->cpu)
+#define cpu_logical_map(cpu)   (cpu)
 
-struct xtensa_cpuinfo {
-       unsigned long   *pgd_cache;
-       unsigned long   *pte_cache;
-       unsigned long   pgtable_cache_sz;
+struct start_info {
+       unsigned long stack;
 };
+extern struct start_info start_info;
 
-#define cpu_logical_map(cpu)   (cpu)
+struct cpumask;
+void arch_send_call_function_ipi_mask(const struct cpumask *mask);
+void arch_send_call_function_single_ipi(int cpu);
+
+void smp_init_cpus(void);
+void secondary_init_irq(void);
+void ipi_init(void);
+struct seq_file;
+void show_ipi_list(struct seq_file *p, int prec);
+
+#ifdef CONFIG_HOTPLUG_CPU
+
+void __cpu_die(unsigned int cpu);
+int __cpu_disable(void);
+void cpu_die(void);
+void cpu_restart(void);
+
+#endif /* CONFIG_HOTPLUG_CPU */
+
+#endif /* CONFIG_SMP */
 
 #endif /* _XTENSA_SMP_H */
index 03975906b36fc34dc6a47abbe979c899ddc4f3e0..1d95fa5dcd10f0121f394e22fb108682c17741aa 100644 (file)
  *    1         somebody owns the spinlock
  */
 
-#define __raw_spin_is_locked(x) ((x)->slock != 0)
-#define __raw_spin_unlock_wait(lock) \
-       do { while (__raw_spin_is_locked(lock)) cpu_relax(); } while (0)
+#define arch_spin_is_locked(x) ((x)->slock != 0)
+#define arch_spin_unlock_wait(lock) \
+       do { while (arch_spin_is_locked(lock)) cpu_relax(); } while (0)
 
-#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
+#define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock)
 
-static inline void __raw_spin_lock(raw_spinlock_t *lock)
+static inline void arch_spin_lock(arch_spinlock_t *lock)
 {
        unsigned long tmp;
 
@@ -51,7 +51,7 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock)
 
 /* Returns 1 if the lock is obtained, 0 otherwise. */
 
-static inline int __raw_spin_trylock(raw_spinlock_t *lock)
+static inline int arch_spin_trylock(arch_spinlock_t *lock)
 {
        unsigned long tmp;
 
@@ -67,7 +67,7 @@ static inline int __raw_spin_trylock(raw_spinlock_t *lock)
        return tmp == 0 ? 1 : 0;
 }
 
-static inline void __raw_spin_unlock(raw_spinlock_t *lock)
+static inline void arch_spin_unlock(arch_spinlock_t *lock)
 {
        unsigned long tmp;
 
@@ -96,9 +96,9 @@ static inline void __raw_spin_unlock(raw_spinlock_t *lock)
  *  0x80000000  one writer owns the rwlock, no other writers, no readers
  */
 
-#define __raw_write_can_lock(x)  ((x)->lock == 0)
+#define arch_write_can_lock(x)  ((x)->lock == 0)
 
-static inline void __raw_write_lock(raw_rwlock_t *rw)
+static inline void arch_write_lock(arch_rwlock_t *rw)
 {
        unsigned long tmp;
 
@@ -116,7 +116,7 @@ static inline void __raw_write_lock(raw_rwlock_t *rw)
 
 /* Returns 1 if the lock is obtained, 0 otherwise. */
 
-static inline int __raw_write_trylock(raw_rwlock_t *rw)
+static inline int arch_write_trylock(arch_rwlock_t *rw)
 {
        unsigned long tmp;
 
@@ -133,7 +133,7 @@ static inline int __raw_write_trylock(raw_rwlock_t *rw)
        return tmp == 0 ? 1 : 0;
 }
 
-static inline void __raw_write_unlock(raw_rwlock_t *rw)
+static inline void arch_write_unlock(arch_rwlock_t *rw)
 {
        unsigned long tmp;
 
@@ -145,7 +145,7 @@ static inline void __raw_write_unlock(raw_rwlock_t *rw)
                        : "memory");
 }
 
-static inline void __raw_read_lock(raw_rwlock_t *rw)
+static inline void arch_read_lock(arch_rwlock_t *rw)
 {
        unsigned long tmp;
        unsigned long result;
@@ -164,7 +164,7 @@ static inline void __raw_read_lock(raw_rwlock_t *rw)
 
 /* Returns 1 if the lock is obtained, 0 otherwise. */
 
-static inline int __raw_read_trylock(raw_rwlock_t *rw)
+static inline int arch_read_trylock(arch_rwlock_t *rw)
 {
        unsigned long result;
        unsigned long tmp;
@@ -184,7 +184,7 @@ static inline int __raw_read_trylock(raw_rwlock_t *rw)
        return result == 0;
 }
 
-static inline void __raw_read_unlock(raw_rwlock_t *rw)
+static inline void arch_read_unlock(arch_rwlock_t *rw)
 {
        unsigned long tmp1, tmp2;
 
@@ -199,4 +199,7 @@ static inline void __raw_read_unlock(raw_rwlock_t *rw)
                        : "memory");
 }
 
+#define arch_read_lock_flags(lock, flags)      arch_read_lock(lock)
+#define arch_write_lock_flags(lock, flags)     arch_write_lock(lock)
+
 #endif /* _XTENSA_SPINLOCK_H */
diff --git a/arch/xtensa/include/asm/spinlock_types.h b/arch/xtensa/include/asm/spinlock_types.h
new file mode 100644 (file)
index 0000000..7ec5ce1
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef __ASM_SPINLOCK_TYPES_H
+#define __ASM_SPINLOCK_TYPES_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+       volatile unsigned int slock;
+} arch_spinlock_t;
+
+#define __ARCH_SPIN_LOCK_UNLOCKED      { 0 }
+
+typedef struct {
+       volatile unsigned int lock;
+} arch_rwlock_t;
+
+#define __ARCH_RW_LOCK_UNLOCKED                { 0 }
+
+#endif
index 27fa3c1706623805168f6914f952d777993edbf2..ca929e6a38b5f70a5e1e2d1492b1cdde5e5f0e2a 100644 (file)
@@ -1,18 +1,14 @@
 /*
- * include/asm-xtensa/timex.h
- *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2001 - 2008 Tensilica Inc.
+ * Copyright (C) 2001 - 2013 Tensilica Inc.
  */
 
 #ifndef _XTENSA_TIMEX_H
 #define _XTENSA_TIMEX_H
 
-#ifdef __KERNEL__
-
 #include <asm/processor.h>
 #include <linux/stringify.h>
 
@@ -39,14 +35,9 @@ extern unsigned long ccount_freq;
 
 typedef unsigned long long cycles_t;
 
-/*
- * Only used for SMP.
- */
-
-extern cycles_t cacheflush_time;
-
 #define get_cycles()   (0)
 
+void local_timer_setup(unsigned cpu);
 
 /*
  * Register access.
@@ -81,5 +72,4 @@ static inline void set_linux_timer (unsigned long ccompare)
        WSR_CCOMPARE(LINUX_TIMER, ccompare);
 }
 
-#endif /* __KERNEL__ */
 #endif /* _XTENSA_TIMEX_H */
index 43dd348a5a478d27daa70f2e8b019b8cfa0fcd22..fc34274ce41bc81b3ddaa167fe887179f04c8ad7 100644 (file)
@@ -1,18 +1,14 @@
 /*
- * include/asm-xtensa/tlbflush.h
- *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
+ * Copyright (C) 2001 - 2013 Tensilica Inc.
  */
 
 #ifndef _XTENSA_TLBFLUSH_H
 #define _XTENSA_TLBFLUSH_H
 
-#ifdef __KERNEL__
-
 #include <linux/stringify.h>
 #include <asm/processor.h>
 
  *  - flush_tlb_range(mm, start, end) flushes a range of pages
  */
 
-extern void flush_tlb_all(void);
-extern void flush_tlb_mm(struct mm_struct*);
-extern void flush_tlb_page(struct vm_area_struct*,unsigned long);
-extern void flush_tlb_range(struct vm_area_struct*,unsigned long,unsigned long);
+void local_flush_tlb_all(void);
+void local_flush_tlb_mm(struct mm_struct *mm);
+void local_flush_tlb_page(struct vm_area_struct *vma,
+               unsigned long page);
+void local_flush_tlb_range(struct vm_area_struct *vma,
+               unsigned long start, unsigned long end);
+
+#ifdef CONFIG_SMP
+
+void flush_tlb_all(void);
+void flush_tlb_mm(struct mm_struct *);
+void flush_tlb_page(struct vm_area_struct *, unsigned long);
+void flush_tlb_range(struct vm_area_struct *, unsigned long,
+               unsigned long);
+
+static inline void flush_tlb_kernel_range(unsigned long start,
+               unsigned long end)
+{
+       flush_tlb_all();
+}
+
+#else /* !CONFIG_SMP */
+
+#define flush_tlb_all()                           local_flush_tlb_all()
+#define flush_tlb_mm(mm)                  local_flush_tlb_mm(mm)
+#define flush_tlb_page(vma, page)         local_flush_tlb_page(vma, page)
+#define flush_tlb_range(vma, vmaddr, end)  local_flush_tlb_range(vma, vmaddr, \
+                                                                end)
+#define flush_tlb_kernel_range(start, end) local_flush_tlb_all()
 
-#define flush_tlb_kernel_range(start,end) flush_tlb_all()
+#endif /* CONFIG_SMP */
 
 /* TLB operations. */
 
@@ -187,5 +208,4 @@ static inline unsigned long read_itlb_translation (int way)
 }
 
 #endif /* __ASSEMBLY__ */
-#endif /* __KERNEL__ */
 #endif /* _XTENSA_TLBFLUSH_H */
index 917488a0ab00f12b9c49ac7e13b72ea5ea28eecb..8c194f6af45e09932976b3f71d8d70a8f556488f 100644 (file)
@@ -19,6 +19,7 @@
  */
 extern void * __init trap_set_handler(int cause, void *handler);
 extern void do_unhandled(struct pt_regs *regs, unsigned long exccause);
+void secondary_trap_init(void);
 
 static inline void spill_registers(void)
 {
index c52b656d0310cb994085844a9b90e32543b36d5b..37e073b21a50e7d0d713ca002fa745ebe3305349 100644 (file)
 
 #if defined(XCHAL_HAVE_PTP_MMU) && XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY
   /* MMU v3  - XCHAL_HAVE_PTP_MMU  == 1 */
-  #define PHYSICAL_MEMORY_ADDRESS      0x00000000
   #define LOAD_MEMORY_ADDRESS          0x00003000
 #else
   /* MMU V2 -  XCHAL_HAVE_PTP_MMU  == 0 */
-  #define PHYSICAL_MEMORY_ADDRESS      0xD0000000
   #define LOAD_MEMORY_ADDRESS          0xD0003000
 #endif
 
@@ -46,7 +44,6 @@
 
   /* Location of the start of the kernel text, _start */
   #define KERNELOFFSET                 0x00003000
-  #define PHYSICAL_MEMORY_ADDRESS      0x00000000
 
   /* Loaded just above possibly live vectors */
   #define LOAD_MEMORY_ADDRESS          0x00003000
@@ -54,7 +51,6 @@
 #endif /* CONFIG_MMU */
 
 #define XC_VADDR(offset)               (VIRTUAL_MEMORY_ADDRESS  + offset)
-#define XC_PADDR(offset)               (PHYSICAL_MEMORY_ADDRESS + offset)
 
 /* Used to set VECBASE register */
 #define VECBASE_RESET_VADDR            VIRTUAL_MEMORY_ADDRESS
@@ -67,7 +63,7 @@
                                                VECBASE_RESET_VADDR)
 #define RESET_VECTOR1_VADDR            XC_VADDR(RESET_VECTOR1_VECOFS)
 
-#if XCHAL_HAVE_VECBASE
+#if defined(XCHAL_HAVE_VECBASE) && XCHAL_HAVE_VECBASE
 
 #define USER_VECTOR_VADDR              XC_VADDR(XCHAL_USER_VECOFS)
 #define KERNEL_VECTOR_VADDR            XC_VADDR(XCHAL_KERNEL_VECOFS)
 
 #define DEBUG_VECTOR_VADDR             XC_VADDR(XCHAL_DEBUG_VECOFS)
 
-#undef  XCHAL_NMI_VECTOR_VADDR
-#define XCHAL_NMI_VECTOR_VADDR         XC_VADDR(XCHAL_NMI_VECOFS)
+#define NMI_VECTOR_VADDR               XC_VADDR(XCHAL_NMI_VECOFS)
 
-#undef  XCHAL_INTLEVEL7_VECTOR_VADDR
-#define XCHAL_INTLEVEL7_VECTOR_VADDR   XC_VADDR(XCHAL_INTLEVEL7_VECOFS)
+#define INTLEVEL7_VECTOR_VADDR         XC_VADDR(XCHAL_INTLEVEL7_VECOFS)
 
 /*
  * These XCHAL_* #defines from varian/core.h
index f90265ec1ccca1bd5fed0849ffb708d6f7d965e8..18d962a8c0c2d1fccc5411fadbdc087bb5b05573 100644 (file)
@@ -12,6 +12,7 @@ obj-$(CONFIG_KGDB) += xtensa-stub.o
 obj-$(CONFIG_PCI) += pci.o
 obj-$(CONFIG_MODULES) += xtensa_ksyms.o module.o
 obj-$(CONFIG_FUNCTION_TRACER) += mcount.o
+obj-$(CONFIG_SMP) += smp.o mxhead.o
 
 AFLAGS_head.o += -mtext-section-literals
 
index 7d740ebbe198ec77a8011601f4172ebc809b9be8..aeeb3cc8a4109e59bc6ce5f23fd88c21c0450f3f 100644 (file)
@@ -19,6 +19,7 @@
 #include <asm/page.h>
 #include <asm/cacheasm.h>
 #include <asm/initialize_mmu.h>
+#include <asm/mxregs.h>
 
 #include <linux/init.h>
 #include <linux/linkage.h>
@@ -54,7 +55,7 @@ ENTRY(_start)
 
        /* Preserve the pointer to the boot parameter list in EXCSAVE_1 */
        wsr     a2, excsave1
-       _j      _SetupMMU
+       _j      _SetupOCD
 
        .align  4
        .literal_position
@@ -62,6 +63,23 @@ ENTRY(_start)
        .word   _startup
 
        .align  4
+_SetupOCD:
+       /*
+        * Initialize WB, WS, and clear PS.EXCM (to allow loop instructions).
+        * Set Interrupt Level just below XCHAL_DEBUGLEVEL to allow
+        * xt-gdb to single step via DEBUG exceptions received directly
+        * by ocd.
+        */
+       movi    a1, 1
+       movi    a0, 0
+       wsr     a1, windowstart
+       wsr     a0, windowbase
+       rsync
+
+       movi    a1, LOCKLEVEL
+       wsr     a1, ps
+       rsync
+
        .global _SetupMMU
 _SetupMMU:
        Offset = _SetupMMU - _start
@@ -85,24 +103,11 @@ _SetupMMU:
 
 ENDPROC(_start)
 
-       __INIT
+       __REF
        .literal_position
 
 ENTRY(_startup)
 
-       /* Disable interrupts and exceptions. */
-
-       movi    a0, LOCKLEVEL
-       wsr     a0, ps
-
-       /* Start with a fresh windowbase and windowstart.  */
-
-       movi    a1, 1
-       movi    a0, 0
-       wsr     a1, windowstart
-       wsr     a0, windowbase
-       rsync
-
        /* Set a0 to 0 for the remaining initialization. */
 
        movi    a0, 0
@@ -154,17 +159,6 @@ ENTRY(_startup)
        wsr     a0, cpenable
 #endif
 
-       /* Set PS.INTLEVEL=LOCKLEVEL, PS.WOE=0, kernel stack, PS.EXCM=0
-        *
-        * Note: PS.EXCM must be cleared before using any loop
-        *       instructions; otherwise, they are silently disabled, and
-        *       at most one iteration of the loop is executed.
-        */
-
-       movi    a1, LOCKLEVEL
-       wsr     a1, ps
-       rsync
-
        /*  Initialize the caches.
         *  a2, a3 are just working registers (clobbered).
         */
@@ -182,6 +176,37 @@ ENTRY(_startup)
 
        isync
 
+#ifdef CONFIG_HAVE_SMP
+       movi    a2, CCON        # MX External Register to Configure Cache
+       movi    a3, 1
+       wer     a3, a2
+#endif
+
+       /* Setup stack and enable window exceptions (keep irqs disabled) */
+
+       movi    a1, start_info
+       l32i    a1, a1, 0
+
+       movi    a2, (1 << PS_WOE_BIT) | LOCKLEVEL
+                                       # WOE=1, INTLEVEL=LOCKLEVEL, UM=0
+       wsr     a2, ps                  # (enable reg-windows; progmode stack)
+       rsync
+
+       /* Set up EXCSAVE[DEBUGLEVEL] to point to the Debug Exception Handler.*/
+
+       movi    a2, debug_exception
+       wsr     a2, SREG_EXCSAVE + XCHAL_DEBUGLEVEL
+
+#ifdef CONFIG_SMP
+       /*
+        * Notice that we assume with SMP that cores have PRID
+        * supported by the cores.
+        */
+       rsr     a2, prid
+       bnez    a2, .Lboot_secondary
+
+#endif  /* CONFIG_SMP */
+
        /* Unpack data sections
         *
         * The linker script used to build the Linux kernel image
@@ -234,24 +259,7 @@ ENTRY(_startup)
        ___invalidate_icache_all a2 a3
        isync
 
-       /* Setup stack and enable window exceptions (keep irqs disabled) */
-
-       movi    a1, init_thread_union
-       addi    a1, a1, KERNEL_STACK_SIZE
-
-       movi    a2, (1 << PS_WOE_BIT) | LOCKLEVEL
-                                       # WOE=1, INTLEVEL=LOCKLEVEL, UM=0
-       wsr     a2, ps                  # (enable reg-windows; progmode stack)
-       rsync
-
-       /* Set up EXCSAVE[DEBUGLEVEL] to point to the Debug Exception Handler.*/
-
-       movi    a2, debug_exception
-       wsr     a2, SREG_EXCSAVE + XCHAL_DEBUGLEVEL
-
-       /* Set up EXCSAVE[1] to point to the exc_table. */
-
-       movi    a6, exc_table
+       movi    a6, 0
        xsr     a6, excsave1
 
        /* init_arch kick-starts the linux kernel */
@@ -265,8 +273,93 @@ ENTRY(_startup)
 should_never_return:
        j       should_never_return
 
+#ifdef CONFIG_SMP
+.Lboot_secondary:
+
+       movi    a2, cpu_start_ccount
+1:
+       l32i    a3, a2, 0
+       beqi    a3, 0, 1b
+       movi    a3, 0
+       s32i    a3, a2, 0
+       memw
+1:
+       l32i    a3, a2, 0
+       beqi    a3, 0, 1b
+       wsr     a3, ccount
+       movi    a3, 0
+       s32i    a3, a2, 0
+       memw
+
+       movi    a6, 0
+       wsr     a6, excsave1
+
+       movi    a4, secondary_start_kernel
+       callx4  a4
+       j       should_never_return
+
+#endif  /* CONFIG_SMP */
+
 ENDPROC(_startup)
 
+#ifdef CONFIG_HOTPLUG_CPU
+
+ENTRY(cpu_restart)
+
+#if XCHAL_DCACHE_IS_WRITEBACK
+       ___flush_invalidate_dcache_all a2 a3
+#else
+       ___invalidate_dcache_all a2 a3
+#endif
+       memw
+       movi    a2, CCON        # MX External Register to Configure Cache
+       movi    a3, 0
+       wer     a3, a2
+       extw
+
+       rsr     a0, prid
+       neg     a2, a0
+       movi    a3, cpu_start_id
+       s32i    a2, a3, 0
+#if XCHAL_DCACHE_IS_WRITEBACK
+       dhwbi   a3, 0
+#endif
+1:
+       l32i    a2, a3, 0
+       dhi     a3, 0
+       bne     a2, a0, 1b
+
+       /*
+        * Initialize WB, WS, and clear PS.EXCM (to allow loop instructions).
+        * Set Interrupt Level just below XCHAL_DEBUGLEVEL to allow
+        * xt-gdb to single step via DEBUG exceptions received directly
+        * by ocd.
+        */
+       movi    a1, 1
+       movi    a0, 0
+       wsr     a1, windowstart
+       wsr     a0, windowbase
+       rsync
+
+       movi    a1, LOCKLEVEL
+       wsr     a1, ps
+       rsync
+
+       j       _startup
+
+ENDPROC(cpu_restart)
+
+#endif  /* CONFIG_HOTPLUG_CPU */
+
+/*
+ * DATA section
+ */
+
+        .section ".data.init.refok"
+        .align  4
+ENTRY(start_info)
+        .long   init_thread_union + KERNEL_STACK_SIZE
+
 /*
  * BSS section
  */
index 6f4f9749cff773f229a76a35bf50373ec18731ab..482868a2de6ebde7995002509445859bf7a002b0 100644 (file)
@@ -4,7 +4,7 @@
  * Xtensa built-in interrupt controller and some generic functions copied
  * from i386.
  *
- * Copyright (C) 2002 - 2006 Tensilica, Inc.
+ * Copyright (C) 2002 - 2013 Tensilica, Inc.
  * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
  *
  *
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/kernel_stat.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/xtensa-mx.h>
+#include <linux/irqchip/xtensa-pic.h>
 #include <linux/irqdomain.h>
 #include <linux/of.h>
 
+#include <asm/mxregs.h>
 #include <asm/uaccess.h>
 #include <asm/platform.h>
 
-static unsigned int cached_irq_mask;
-
 atomic_t irq_err_count;
 
-static struct irq_domain *root_domain;
-
-/*
- * do_IRQ handles all normal device IRQ's (the special
- * SMP cross-CPU interrupts have their own specific
- * handlers).
- */
-
 asmlinkage void do_IRQ(int hwirq, struct pt_regs *regs)
 {
-       struct pt_regs *old_regs = set_irq_regs(regs);
-       int irq = irq_find_mapping(root_domain, hwirq);
+       int irq = irq_find_mapping(NULL, hwirq);
 
        if (hwirq >= NR_IRQS) {
                printk(KERN_EMERG "%s: cannot handle IRQ %d\n",
                                __func__, hwirq);
        }
 
-       irq_enter();
-
 #ifdef CONFIG_DEBUG_STACKOVERFLOW
        /* Debugging check for stack overflow: is there less than 1KB free? */
        {
@@ -62,95 +53,69 @@ asmlinkage void do_IRQ(int hwirq, struct pt_regs *regs)
        }
 #endif
        generic_handle_irq(irq);
-
-       irq_exit();
-       set_irq_regs(old_regs);
 }
 
 int arch_show_interrupts(struct seq_file *p, int prec)
 {
+#ifdef CONFIG_SMP
+       show_ipi_list(p, prec);
+#endif
        seq_printf(p, "%*s: ", prec, "ERR");
        seq_printf(p, "%10u\n", atomic_read(&irq_err_count));
        return 0;
 }
 
-static void xtensa_irq_mask(struct irq_data *d)
-{
-       cached_irq_mask &= ~(1 << d->hwirq);
-       set_sr (cached_irq_mask, intenable);
-}
-
-static void xtensa_irq_unmask(struct irq_data *d)
-{
-       cached_irq_mask |= 1 << d->hwirq;
-       set_sr (cached_irq_mask, intenable);
-}
-
-static void xtensa_irq_enable(struct irq_data *d)
-{
-       variant_irq_enable(d->hwirq);
-       xtensa_irq_unmask(d);
-}
-
-static void xtensa_irq_disable(struct irq_data *d)
-{
-       xtensa_irq_mask(d);
-       variant_irq_disable(d->hwirq);
-}
-
-static void xtensa_irq_ack(struct irq_data *d)
-{
-       set_sr(1 << d->hwirq, intclear);
-}
-
-static int xtensa_irq_retrigger(struct irq_data *d)
+int xtensa_irq_domain_xlate(const u32 *intspec, unsigned int intsize,
+               unsigned long int_irq, unsigned long ext_irq,
+               unsigned long *out_hwirq, unsigned int *out_type)
 {
-       set_sr(1 << d->hwirq, intset);
-       return 1;
+       if (WARN_ON(intsize < 1 || intsize > 2))
+               return -EINVAL;
+       if (intsize == 2 && intspec[1] == 1) {
+               int_irq = xtensa_map_ext_irq(ext_irq);
+               if (int_irq < XCHAL_NUM_INTERRUPTS)
+                       *out_hwirq = int_irq;
+               else
+                       return -EINVAL;
+       } else {
+               *out_hwirq = int_irq;
+       }
+       *out_type = IRQ_TYPE_NONE;
+       return 0;
 }
 
-static struct irq_chip xtensa_irq_chip = {
-       .name           = "xtensa",
-       .irq_enable     = xtensa_irq_enable,
-       .irq_disable    = xtensa_irq_disable,
-       .irq_mask       = xtensa_irq_mask,
-       .irq_unmask     = xtensa_irq_unmask,
-       .irq_ack        = xtensa_irq_ack,
-       .irq_retrigger  = xtensa_irq_retrigger,
-};
-
-static int xtensa_irq_map(struct irq_domain *d, unsigned int irq,
+int xtensa_irq_map(struct irq_domain *d, unsigned int irq,
                irq_hw_number_t hw)
 {
+       struct irq_chip *irq_chip = d->host_data;
        u32 mask = 1 << hw;
 
        if (mask & XCHAL_INTTYPE_MASK_SOFTWARE) {
-               irq_set_chip_and_handler_name(irq, &xtensa_irq_chip,
+               irq_set_chip_and_handler_name(irq, irq_chip,
                                handle_simple_irq, "level");
                irq_set_status_flags(irq, IRQ_LEVEL);
        } else if (mask & XCHAL_INTTYPE_MASK_EXTERN_EDGE) {
-               irq_set_chip_and_handler_name(irq, &xtensa_irq_chip,
+               irq_set_chip_and_handler_name(irq, irq_chip,
                                handle_edge_irq, "edge");
                irq_clear_status_flags(irq, IRQ_LEVEL);
        } else if (mask & XCHAL_INTTYPE_MASK_EXTERN_LEVEL) {
-               irq_set_chip_and_handler_name(irq, &xtensa_irq_chip,
+               irq_set_chip_and_handler_name(irq, irq_chip,
                                handle_level_irq, "level");
                irq_set_status_flags(irq, IRQ_LEVEL);
        } else if (mask & XCHAL_INTTYPE_MASK_TIMER) {
-               irq_set_chip_and_handler_name(irq, &xtensa_irq_chip,
-                               handle_edge_irq, "edge");
+               irq_set_chip_and_handler_name(irq, irq_chip,
+                               handle_percpu_irq, "timer");
                irq_clear_status_flags(irq, IRQ_LEVEL);
        } else {/* XCHAL_INTTYPE_MASK_WRITE_ERROR */
                /* XCHAL_INTTYPE_MASK_NMI */
-
-               irq_set_chip_and_handler_name(irq, &xtensa_irq_chip,
+               irq_set_chip_and_handler_name(irq, irq_chip,
                                handle_level_irq, "level");
                irq_set_status_flags(irq, IRQ_LEVEL);
        }
        return 0;
 }
 
-static unsigned map_ext_irq(unsigned ext_irq)
+unsigned xtensa_map_ext_irq(unsigned ext_irq)
 {
        unsigned mask = XCHAL_INTTYPE_MASK_EXTERN_EDGE |
                XCHAL_INTTYPE_MASK_EXTERN_LEVEL;
@@ -163,55 +128,77 @@ static unsigned map_ext_irq(unsigned ext_irq)
        return XCHAL_NUM_INTERRUPTS;
 }
 
-/*
- * Device Tree IRQ specifier translation function which works with one or
- * two cell bindings. First cell value maps directly to the hwirq number.
- * Second cell if present specifies whether hwirq number is external (1) or
- * internal (0).
- */
-int xtensa_irq_domain_xlate(struct irq_domain *d, struct device_node *ctrlr,
-               const u32 *intspec, unsigned int intsize,
-               unsigned long *out_hwirq, unsigned int *out_type)
+unsigned xtensa_get_ext_irq_no(unsigned irq)
 {
-       if (WARN_ON(intsize < 1 || intsize > 2))
-               return -EINVAL;
-       if (intsize == 2 && intspec[1] == 1) {
-               unsigned int_irq = map_ext_irq(intspec[0]);
-               if (int_irq < XCHAL_NUM_INTERRUPTS)
-                       *out_hwirq = int_irq;
-               else
-                       return -EINVAL;
-       } else {
-               *out_hwirq = intspec[0];
-       }
-       *out_type = IRQ_TYPE_NONE;
-       return 0;
+       unsigned mask = (XCHAL_INTTYPE_MASK_EXTERN_EDGE |
+               XCHAL_INTTYPE_MASK_EXTERN_LEVEL) &
+               ((1u << irq) - 1);
+       return hweight32(mask);
 }
 
-static const struct irq_domain_ops xtensa_irq_domain_ops = {
-       .xlate = xtensa_irq_domain_xlate,
-       .map = xtensa_irq_map,
-};
-
 void __init init_IRQ(void)
 {
-       struct device_node *intc = NULL;
-
-       cached_irq_mask = 0;
-       set_sr(~0, intclear);
-
 #ifdef CONFIG_OF
-       /* The interrupt controller device node is mandatory */
-       intc = of_find_compatible_node(NULL, NULL, "xtensa,pic");
-       BUG_ON(!intc);
-
-       root_domain = irq_domain_add_linear(intc, NR_IRQS,
-                       &xtensa_irq_domain_ops, NULL);
+       irqchip_init();
+#else
+#ifdef CONFIG_HAVE_SMP
+       xtensa_mx_init_legacy(NULL);
 #else
-       root_domain = irq_domain_add_legacy(intc, NR_IRQS, 0, 0,
-                       &xtensa_irq_domain_ops, NULL);
+       xtensa_pic_init_legacy(NULL);
+#endif
 #endif
-       irq_set_default_host(root_domain);
 
+#ifdef CONFIG_SMP
+       ipi_init();
+#endif
        variant_init_irq();
 }
+
+#ifdef CONFIG_HOTPLUG_CPU
+static void route_irq(struct irq_data *data, unsigned int irq, unsigned int cpu)
+{
+       struct irq_desc *desc = irq_to_desc(irq);
+       struct irq_chip *chip = irq_data_get_irq_chip(data);
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&desc->lock, flags);
+       if (chip->irq_set_affinity)
+               chip->irq_set_affinity(data, cpumask_of(cpu), false);
+       raw_spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+/*
+ * The CPU has been marked offline.  Migrate IRQs off this CPU.  If
+ * the affinity settings do not allow other CPUs, force them onto any
+ * available CPU.
+ */
+void migrate_irqs(void)
+{
+       unsigned int i, cpu = smp_processor_id();
+       struct irq_desc *desc;
+
+       for_each_irq_desc(i, desc) {
+               struct irq_data *data = irq_desc_get_irq_data(desc);
+               unsigned int newcpu;
+
+               if (irqd_is_per_cpu(data))
+                       continue;
+
+               if (!cpumask_test_cpu(cpu, data->affinity))
+                       continue;
+
+               newcpu = cpumask_any_and(data->affinity, cpu_online_mask);
+
+               if (newcpu >= nr_cpu_ids) {
+                       pr_info_ratelimited("IRQ%u no longer affine to CPU%u\n",
+                                           i, cpu);
+
+                       cpumask_setall(data->affinity);
+                       newcpu = cpumask_any_and(data->affinity,
+                                                cpu_online_mask);
+               }
+
+               route_irq(data, i, newcpu);
+       }
+}
+#endif /* CONFIG_HOTPLUG_CPU */
diff --git a/arch/xtensa/kernel/mxhead.S b/arch/xtensa/kernel/mxhead.S
new file mode 100644 (file)
index 0000000..77a161a
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Xtensa Secondary Processors startup code.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2013 Tensilica Inc.
+ *
+ * Joe Taylor <joe@tensilica.com>
+ * Chris Zankel <chris@zankel.net>
+ * Marc Gauthier <marc@tensilica.com, marc@alumni.uwaterloo.ca>
+ * Pete Delaney <piet@tensilica.com>
+ */
+
+#include <linux/linkage.h>
+
+#include <asm/cacheasm.h>
+#include <asm/initialize_mmu.h>
+#include <asm/mxregs.h>
+#include <asm/regs.h>
+
+
+       .section .SecondaryResetVector.text, "ax"
+
+
+ENTRY(_SecondaryResetVector)
+       _j _SetupOCD
+
+       .begin  no-absolute-literals
+       .literal_position
+
+_SetupOCD:
+       /*
+        * Initialize WB, WS, and clear PS.EXCM (to allow loop instructions).
+        * Set Interrupt Level just below XCHAL_DEBUGLEVEL to allow
+        * xt-gdb to single step via DEBUG exceptions received directly
+        * by ocd.
+        */
+       movi    a1, 1
+       movi    a0, 0
+       wsr     a1, windowstart
+       wsr     a0, windowbase
+       rsync
+
+       movi    a1, LOCKLEVEL
+       wsr     a1, ps
+       rsync
+
+_SetupMMU:
+       Offset = _SetupMMU - _SecondaryResetVector
+
+#ifdef CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX
+       initialize_mmu
+#endif
+
+       /*
+        * Start Secondary Processors with NULL pointer to boot params.
+        */
+       movi    a2, 0                           #  a2 == NULL
+       movi    a3, _startup
+       jx      a3
+
+       .end    no-absolute-literals
+
+
+       .section        .SecondaryResetVector.remapped_text, "ax"
+       .global         _RemappedSecondaryResetVector
+
+       .org 0                                  # Need to do org before literals
+
+_RemappedSecondaryResetVector:
+       .begin  no-absolute-literals
+       .literal_position
+
+       _j      _RemappedSetupMMU
+       . = _RemappedSecondaryResetVector + Offset
+
+_RemappedSetupMMU:
+
+#ifdef CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX
+       initialize_mmu
+#endif
+
+       .end    no-absolute-literals
index 6e2b6638122de71374c99ac0be7df584b0cf7fd9..d21bfa7a28e0f026b7e28b170279d2aa4dac64bb 100644 (file)
@@ -21,6 +21,8 @@
 #include <linux/screen_info.h>
 #include <linux/bootmem.h>
 #include <linux/kernel.h>
+#include <linux/percpu.h>
+#include <linux/cpu.h>
 #include <linux/of_fdt.h>
 #include <linux/of_platform.h>
 
@@ -37,6 +39,7 @@
 #endif
 
 #include <asm/bootparam.h>
+#include <asm/mmu_context.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/timex.h>
@@ -45,6 +48,7 @@
 #include <asm/setup.h>
 #include <asm/param.h>
 #include <asm/traps.h>
+#include <asm/smp.h>
 
 #include <platform/hardware.h>
 
@@ -85,12 +89,6 @@ static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
 
 sysmem_info_t __initdata sysmem;
 
-#ifdef CONFIG_MMU
-extern void init_mmu(void);
-#else
-static inline void init_mmu(void) { }
-#endif
-
 extern int mem_reserve(unsigned long, unsigned long, int);
 extern void bootmem_init(void);
 extern void zones_init(void);
@@ -354,7 +352,8 @@ static inline int probed_compare_swap(int *v, int cmp, int set)
 
 /* Handle probed exception */
 
-void __init do_probed_exception(struct pt_regs *regs, unsigned long exccause)
+static void __init do_probed_exception(struct pt_regs *regs,
+               unsigned long exccause)
 {
        if (regs->pc == rcw_probe_pc) { /* exception on s32c1i ? */
                regs->pc += 3;          /* skip the s32c1i instruction */
@@ -366,7 +365,7 @@ void __init do_probed_exception(struct pt_regs *regs, unsigned long exccause)
 
 /* Simple test of S32C1I (soc bringup assist) */
 
-void __init check_s32c1i(void)
+static int __init check_s32c1i(void)
 {
        int n, cause1, cause2;
        void *handbus, *handdata, *handaddr; /* temporarily saved handlers */
@@ -421,24 +420,21 @@ void __init check_s32c1i(void)
        trap_set_handler(EXCCAUSE_LOAD_STORE_ERROR, handbus);
        trap_set_handler(EXCCAUSE_LOAD_STORE_DATA_ERROR, handdata);
        trap_set_handler(EXCCAUSE_LOAD_STORE_ADDR_ERROR, handaddr);
+       return 0;
 }
 
 #else /* XCHAL_HAVE_S32C1I */
 
 /* This condition should not occur with a commercially deployed processor.
    Display reminder for early engr test or demo chips / FPGA bitstreams */
-void __init check_s32c1i(void)
+static int __init check_s32c1i(void)
 {
        pr_warn("Processor configuration lacks atomic compare-and-swap support!\n");
+       return 0;
 }
 
 #endif /* XCHAL_HAVE_S32C1I */
-#else /* CONFIG_S32C1I_SELFTEST */
-
-void __init check_s32c1i(void)
-{
-}
-
+early_initcall(check_s32c1i);
 #endif /* CONFIG_S32C1I_SELFTEST */
 
 
@@ -447,8 +443,6 @@ void __init setup_arch(char **cmdline_p)
        strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
        *cmdline_p = command_line;
 
-       check_s32c1i();
-
        /* Reserve some memory regions */
 
 #ifdef CONFIG_BLK_DEV_INITRD
@@ -505,6 +499,10 @@ void __init setup_arch(char **cmdline_p)
 
        platform_setup(cmdline_p);
 
+#ifdef CONFIG_SMP
+       smp_init_cpus();
+#endif
+
        paging_init();
        zones_init();
 
@@ -521,6 +519,22 @@ void __init setup_arch(char **cmdline_p)
 #endif
 }
 
+static DEFINE_PER_CPU(struct cpu, cpu_data);
+
+static int __init topology_init(void)
+{
+       int i;
+
+       for_each_possible_cpu(i) {
+               struct cpu *cpu = &per_cpu(cpu_data, i);
+               cpu->hotpluggable = !!i;
+               register_cpu(cpu, i);
+       }
+
+       return 0;
+}
+subsys_initcall(topology_init);
+
 void machine_restart(char * cmd)
 {
        platform_restart();
@@ -546,21 +560,27 @@ void machine_power_off(void)
 static int
 c_show(struct seq_file *f, void *slot)
 {
+       char buf[NR_CPUS * 5];
+
+       cpulist_scnprintf(buf, sizeof(buf), cpu_online_mask);
        /* high-level stuff */
-       seq_printf(f,"processor\t: 0\n"
-                    "vendor_id\t: Tensilica\n"
-                    "model\t\t: Xtensa " XCHAL_HW_VERSION_NAME "\n"
-                    "core ID\t\t: " XCHAL_CORE_ID "\n"
-                    "build ID\t: 0x%x\n"
-                    "byte order\t: %s\n"
-                    "cpu MHz\t\t: %lu.%02lu\n"
-                    "bogomips\t: %lu.%02lu\n",
-                    XCHAL_BUILD_UNIQUE_ID,
-                    XCHAL_HAVE_BE ?  "big" : "little",
-                    ccount_freq/1000000,
-                    (ccount_freq/10000) % 100,
-                    loops_per_jiffy/(500000/HZ),
-                    (loops_per_jiffy/(5000/HZ)) % 100);
+       seq_printf(f, "CPU count\t: %u\n"
+                     "CPU list\t: %s\n"
+                     "vendor_id\t: Tensilica\n"
+                     "model\t\t: Xtensa " XCHAL_HW_VERSION_NAME "\n"
+                     "core ID\t\t: " XCHAL_CORE_ID "\n"
+                     "build ID\t: 0x%x\n"
+                     "byte order\t: %s\n"
+                     "cpu MHz\t\t: %lu.%02lu\n"
+                     "bogomips\t: %lu.%02lu\n",
+                     num_online_cpus(),
+                     buf,
+                     XCHAL_BUILD_UNIQUE_ID,
+                     XCHAL_HAVE_BE ?  "big" : "little",
+                     ccount_freq/1000000,
+                     (ccount_freq/10000) % 100,
+                     loops_per_jiffy/(500000/HZ),
+                     (loops_per_jiffy/(5000/HZ)) % 100);
 
        seq_printf(f,"flags\t\t: "
 #if XCHAL_HAVE_NMI
@@ -672,7 +692,7 @@ c_show(struct seq_file *f, void *slot)
 static void *
 c_start(struct seq_file *f, loff_t *pos)
 {
-       return (void *) ((*pos == 0) ? (void *)1 : NULL);
+       return (*pos == 0) ? (void *)1 : NULL;
 }
 
 static void *
@@ -688,10 +708,10 @@ c_stop(struct seq_file *f, void *v)
 
 const struct seq_operations cpuinfo_op =
 {
-       start:  c_start,
-       next:   c_next,
-       stop:   c_stop,
-       show:   c_show
+       .start  = c_start,
+       .next   = c_next,
+       .stop   = c_stop,
+       .show   = c_show,
 };
 
 #endif /* CONFIG_PROC_FS */
diff --git a/arch/xtensa/kernel/smp.c b/arch/xtensa/kernel/smp.c
new file mode 100644 (file)
index 0000000..1c7a209
--- /dev/null
@@ -0,0 +1,591 @@
+/*
+ * Xtensa SMP support functions.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2008 - 2013 Tensilica Inc.
+ *
+ * Chris Zankel <chris@zankel.net>
+ * Joe Taylor <joe@tensilica.com>
+ * Pete Delaney <piet@tensilica.com
+ */
+
+#include <linux/cpu.h>
+#include <linux/cpumask.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/irq.h>
+#include <linux/kdebug.h>
+#include <linux/module.h>
+#include <linux/reboot.h>
+#include <linux/seq_file.h>
+#include <linux/smp.h>
+#include <linux/thread_info.h>
+
+#include <asm/cacheflush.h>
+#include <asm/kdebug.h>
+#include <asm/mmu_context.h>
+#include <asm/mxregs.h>
+#include <asm/platform.h>
+#include <asm/tlbflush.h>
+#include <asm/traps.h>
+
+#ifdef CONFIG_SMP
+# if XCHAL_HAVE_S32C1I == 0
+#  error "The S32C1I option is required for SMP."
+# endif
+#endif
+
+static void system_invalidate_dcache_range(unsigned long start,
+               unsigned long size);
+static void system_flush_invalidate_dcache_range(unsigned long start,
+               unsigned long size);
+
+/* IPI (Inter Process Interrupt) */
+
+#define IPI_IRQ        0
+
+static irqreturn_t ipi_interrupt(int irq, void *dev_id);
+static struct irqaction ipi_irqaction = {
+       .handler =      ipi_interrupt,
+       .flags =        IRQF_PERCPU,
+       .name =         "ipi",
+};
+
+void ipi_init(void)
+{
+       unsigned irq = irq_create_mapping(NULL, IPI_IRQ);
+       setup_irq(irq, &ipi_irqaction);
+}
+
+static inline unsigned int get_core_count(void)
+{
+       /* Bits 18..21 of SYSCFGID contain the core count minus 1. */
+       unsigned int syscfgid = get_er(SYSCFGID);
+       return ((syscfgid >> 18) & 0xf) + 1;
+}
+
+static inline int get_core_id(void)
+{
+       /* Bits 0...18 of SYSCFGID contain the core id  */
+       unsigned int core_id = get_er(SYSCFGID);
+       return core_id & 0x3fff;
+}
+
+void __init smp_prepare_cpus(unsigned int max_cpus)
+{
+       unsigned i;
+
+       for (i = 0; i < max_cpus; ++i)
+               set_cpu_present(i, true);
+}
+
+void __init smp_init_cpus(void)
+{
+       unsigned i;
+       unsigned int ncpus = get_core_count();
+       unsigned int core_id = get_core_id();
+
+       pr_info("%s: Core Count = %d\n", __func__, ncpus);
+       pr_info("%s: Core Id = %d\n", __func__, core_id);
+
+       for (i = 0; i < ncpus; ++i)
+               set_cpu_possible(i, true);
+}
+
+void __init smp_prepare_boot_cpu(void)
+{
+       unsigned int cpu = smp_processor_id();
+       BUG_ON(cpu != 0);
+       cpu_asid_cache(cpu) = ASID_USER_FIRST;
+}
+
+void __init smp_cpus_done(unsigned int max_cpus)
+{
+}
+
+static int boot_secondary_processors = 1; /* Set with xt-gdb via .xt-gdb */
+static DECLARE_COMPLETION(cpu_running);
+
+void secondary_start_kernel(void)
+{
+       struct mm_struct *mm = &init_mm;
+       unsigned int cpu = smp_processor_id();
+
+       init_mmu();
+
+#ifdef CONFIG_DEBUG_KERNEL
+       if (boot_secondary_processors == 0) {
+               pr_debug("%s: boot_secondary_processors:%d; Hanging cpu:%d\n",
+                       __func__, boot_secondary_processors, cpu);
+               for (;;)
+                       __asm__ __volatile__ ("waiti " __stringify(LOCKLEVEL));
+       }
+
+       pr_debug("%s: boot_secondary_processors:%d; Booting cpu:%d\n",
+               __func__, boot_secondary_processors, cpu);
+#endif
+       /* Init EXCSAVE1 */
+
+       secondary_trap_init();
+
+       /* All kernel threads share the same mm context. */
+
+       atomic_inc(&mm->mm_users);
+       atomic_inc(&mm->mm_count);
+       current->active_mm = mm;
+       cpumask_set_cpu(cpu, mm_cpumask(mm));
+       enter_lazy_tlb(mm, current);
+
+       preempt_disable();
+       trace_hardirqs_off();
+
+       calibrate_delay();
+
+       notify_cpu_starting(cpu);
+
+       secondary_init_irq();
+       local_timer_setup(cpu);
+
+       local_irq_enable();
+
+       set_cpu_online(cpu, true);
+       complete(&cpu_running);
+
+       cpu_startup_entry(CPUHP_ONLINE);
+}
+
+static void mx_cpu_start(void *p)
+{
+       unsigned cpu = (unsigned)p;
+       unsigned long run_stall_mask = get_er(MPSCORE);
+
+       set_er(run_stall_mask & ~(1u << cpu), MPSCORE);
+       pr_debug("%s: cpu: %d, run_stall_mask: %lx ---> %lx\n",
+                       __func__, cpu, run_stall_mask, get_er(MPSCORE));
+}
+
+static void mx_cpu_stop(void *p)
+{
+       unsigned cpu = (unsigned)p;
+       unsigned long run_stall_mask = get_er(MPSCORE);
+
+       set_er(run_stall_mask | (1u << cpu), MPSCORE);
+       pr_debug("%s: cpu: %d, run_stall_mask: %lx ---> %lx\n",
+                       __func__, cpu, run_stall_mask, get_er(MPSCORE));
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+unsigned long cpu_start_id __cacheline_aligned;
+#endif
+unsigned long cpu_start_ccount;
+
+static int boot_secondary(unsigned int cpu, struct task_struct *ts)
+{
+       unsigned long timeout = jiffies + msecs_to_jiffies(1000);
+       unsigned long ccount;
+       int i;
+
+#ifdef CONFIG_HOTPLUG_CPU
+       cpu_start_id = cpu;
+       system_flush_invalidate_dcache_range(
+                       (unsigned long)&cpu_start_id, sizeof(cpu_start_id));
+#endif
+       smp_call_function_single(0, mx_cpu_start, (void *)cpu, 1);
+
+       for (i = 0; i < 2; ++i) {
+               do
+                       ccount = get_ccount();
+               while (!ccount);
+
+               cpu_start_ccount = ccount;
+
+               while (time_before(jiffies, timeout)) {
+                       mb();
+                       if (!cpu_start_ccount)
+                               break;
+               }
+
+               if (cpu_start_ccount) {
+                       smp_call_function_single(0, mx_cpu_stop,
+                                       (void *)cpu, 1);
+                       cpu_start_ccount = 0;
+                       return -EIO;
+               }
+       }
+       return 0;
+}
+
+int __cpu_up(unsigned int cpu, struct task_struct *idle)
+{
+       int ret = 0;
+
+       if (cpu_asid_cache(cpu) == 0)
+               cpu_asid_cache(cpu) = ASID_USER_FIRST;
+
+       start_info.stack = (unsigned long)task_pt_regs(idle);
+       wmb();
+
+       pr_debug("%s: Calling wakeup_secondary(cpu:%d, idle:%p, sp: %08lx)\n",
+                       __func__, cpu, idle, start_info.stack);
+
+       ret = boot_secondary(cpu, idle);
+       if (ret == 0) {
+               wait_for_completion_timeout(&cpu_running,
+                               msecs_to_jiffies(1000));
+               if (!cpu_online(cpu))
+                       ret = -EIO;
+       }
+
+       if (ret)
+               pr_err("CPU %u failed to boot\n", cpu);
+
+       return ret;
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+
+/*
+ * __cpu_disable runs on the processor to be shutdown.
+ */
+int __cpu_disable(void)
+{
+       unsigned int cpu = smp_processor_id();
+
+       /*
+        * Take this CPU offline.  Once we clear this, we can't return,
+        * and we must not schedule until we're ready to give up the cpu.
+        */
+       set_cpu_online(cpu, false);
+
+       /*
+        * OK - migrate IRQs away from this CPU
+        */
+       migrate_irqs();
+
+       /*
+        * Flush user cache and TLB mappings, and then remove this CPU
+        * from the vm mask set of all processes.
+        */
+       local_flush_cache_all();
+       local_flush_tlb_all();
+       invalidate_page_directory();
+
+       clear_tasks_mm_cpumask(cpu);
+
+       return 0;
+}
+
+static void platform_cpu_kill(unsigned int cpu)
+{
+       smp_call_function_single(0, mx_cpu_stop, (void *)cpu, true);
+}
+
+/*
+ * called on the thread which is asking for a CPU to be shutdown -
+ * waits until shutdown has completed, or it is timed out.
+ */
+void __cpu_die(unsigned int cpu)
+{
+       unsigned long timeout = jiffies + msecs_to_jiffies(1000);
+       while (time_before(jiffies, timeout)) {
+               system_invalidate_dcache_range((unsigned long)&cpu_start_id,
+                               sizeof(cpu_start_id));
+               if (cpu_start_id == -cpu) {
+                       platform_cpu_kill(cpu);
+                       return;
+               }
+       }
+       pr_err("CPU%u: unable to kill\n", cpu);
+}
+
+void arch_cpu_idle_dead(void)
+{
+       cpu_die();
+}
+/*
+ * Called from the idle thread for the CPU which has been shutdown.
+ *
+ * Note that we disable IRQs here, but do not re-enable them
+ * before returning to the caller. This is also the behaviour
+ * of the other hotplug-cpu capable cores, so presumably coming
+ * out of idle fixes this.
+ */
+void __ref cpu_die(void)
+{
+       idle_task_exit();
+       local_irq_disable();
+       __asm__ __volatile__(
+                       "       movi    a2, cpu_restart\n"
+                       "       jx      a2\n");
+}
+
+#endif /* CONFIG_HOTPLUG_CPU */
+
+enum ipi_msg_type {
+       IPI_RESCHEDULE = 0,
+       IPI_CALL_FUNC,
+       IPI_CPU_STOP,
+       IPI_MAX
+};
+
+static const struct {
+       const char *short_text;
+       const char *long_text;
+} ipi_text[] = {
+       { .short_text = "RES", .long_text = "Rescheduling interrupts" },
+       { .short_text = "CAL", .long_text = "Function call interrupts" },
+       { .short_text = "DIE", .long_text = "CPU shutdown interrupts" },
+};
+
+struct ipi_data {
+       unsigned long ipi_count[IPI_MAX];
+};
+
+static DEFINE_PER_CPU(struct ipi_data, ipi_data);
+
+static void send_ipi_message(const struct cpumask *callmask,
+               enum ipi_msg_type msg_id)
+{
+       int index;
+       unsigned long mask = 0;
+
+       for_each_cpu(index, callmask)
+               if (index != smp_processor_id())
+                       mask |= 1 << index;
+
+       set_er(mask, MIPISET(msg_id));
+}
+
+void arch_send_call_function_ipi_mask(const struct cpumask *mask)
+{
+       send_ipi_message(mask, IPI_CALL_FUNC);
+}
+
+void arch_send_call_function_single_ipi(int cpu)
+{
+       send_ipi_message(cpumask_of(cpu), IPI_CALL_FUNC);
+}
+
+void smp_send_reschedule(int cpu)
+{
+       send_ipi_message(cpumask_of(cpu), IPI_RESCHEDULE);
+}
+
+void smp_send_stop(void)
+{
+       struct cpumask targets;
+
+       cpumask_copy(&targets, cpu_online_mask);
+       cpumask_clear_cpu(smp_processor_id(), &targets);
+       send_ipi_message(&targets, IPI_CPU_STOP);
+}
+
+static void ipi_cpu_stop(unsigned int cpu)
+{
+       set_cpu_online(cpu, false);
+       machine_halt();
+}
+
+irqreturn_t ipi_interrupt(int irq, void *dev_id)
+{
+       unsigned int cpu = smp_processor_id();
+       struct ipi_data *ipi = &per_cpu(ipi_data, cpu);
+       unsigned int msg;
+       unsigned i;
+
+       msg = get_er(MIPICAUSE(cpu));
+       for (i = 0; i < IPI_MAX; i++)
+               if (msg & (1 << i)) {
+                       set_er(1 << i, MIPICAUSE(cpu));
+                       ++ipi->ipi_count[i];
+               }
+
+       if (msg & (1 << IPI_RESCHEDULE))
+               scheduler_ipi();
+       if (msg & (1 << IPI_CALL_FUNC))
+               generic_smp_call_function_interrupt();
+       if (msg & (1 << IPI_CPU_STOP))
+               ipi_cpu_stop(cpu);
+
+       return IRQ_HANDLED;
+}
+
+void show_ipi_list(struct seq_file *p, int prec)
+{
+       unsigned int cpu;
+       unsigned i;
+
+       for (i = 0; i < IPI_MAX; ++i) {
+               seq_printf(p, "%*s:", prec, ipi_text[i].short_text);
+               for_each_online_cpu(cpu)
+                       seq_printf(p, " %10lu",
+                                       per_cpu(ipi_data, cpu).ipi_count[i]);
+               seq_printf(p, "   %s\n", ipi_text[i].long_text);
+       }
+}
+
+int setup_profiling_timer(unsigned int multiplier)
+{
+       pr_debug("setup_profiling_timer %d\n", multiplier);
+       return 0;
+}
+
+/* TLB flush functions */
+
+struct flush_data {
+       struct vm_area_struct *vma;
+       unsigned long addr1;
+       unsigned long addr2;
+};
+
+static void ipi_flush_tlb_all(void *arg)
+{
+       local_flush_tlb_all();
+}
+
+void flush_tlb_all(void)
+{
+       on_each_cpu(ipi_flush_tlb_all, NULL, 1);
+}
+
+static void ipi_flush_tlb_mm(void *arg)
+{
+       local_flush_tlb_mm(arg);
+}
+
+void flush_tlb_mm(struct mm_struct *mm)
+{
+       on_each_cpu(ipi_flush_tlb_mm, mm, 1);
+}
+
+static void ipi_flush_tlb_page(void *arg)
+{
+       struct flush_data *fd = arg;
+       local_flush_tlb_page(fd->vma, fd->addr1);
+}
+
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
+{
+       struct flush_data fd = {
+               .vma = vma,
+               .addr1 = addr,
+       };
+       on_each_cpu(ipi_flush_tlb_page, &fd, 1);
+}
+
+static void ipi_flush_tlb_range(void *arg)
+{
+       struct flush_data *fd = arg;
+       local_flush_tlb_range(fd->vma, fd->addr1, fd->addr2);
+}
+
+void flush_tlb_range(struct vm_area_struct *vma,
+                    unsigned long start, unsigned long end)
+{
+       struct flush_data fd = {
+               .vma = vma,
+               .addr1 = start,
+               .addr2 = end,
+       };
+       on_each_cpu(ipi_flush_tlb_range, &fd, 1);
+}
+
+/* Cache flush functions */
+
+static void ipi_flush_cache_all(void *arg)
+{
+       local_flush_cache_all();
+}
+
+void flush_cache_all(void)
+{
+       on_each_cpu(ipi_flush_cache_all, NULL, 1);
+}
+
+static void ipi_flush_cache_page(void *arg)
+{
+       struct flush_data *fd = arg;
+       local_flush_cache_page(fd->vma, fd->addr1, fd->addr2);
+}
+
+void flush_cache_page(struct vm_area_struct *vma,
+                    unsigned long address, unsigned long pfn)
+{
+       struct flush_data fd = {
+               .vma = vma,
+               .addr1 = address,
+               .addr2 = pfn,
+       };
+       on_each_cpu(ipi_flush_cache_page, &fd, 1);
+}
+
+static void ipi_flush_cache_range(void *arg)
+{
+       struct flush_data *fd = arg;
+       local_flush_cache_range(fd->vma, fd->addr1, fd->addr2);
+}
+
+void flush_cache_range(struct vm_area_struct *vma,
+                    unsigned long start, unsigned long end)
+{
+       struct flush_data fd = {
+               .vma = vma,
+               .addr1 = start,
+               .addr2 = end,
+       };
+       on_each_cpu(ipi_flush_cache_range, &fd, 1);
+}
+
+static void ipi_flush_icache_range(void *arg)
+{
+       struct flush_data *fd = arg;
+       local_flush_icache_range(fd->addr1, fd->addr2);
+}
+
+void flush_icache_range(unsigned long start, unsigned long end)
+{
+       struct flush_data fd = {
+               .addr1 = start,
+               .addr2 = end,
+       };
+       on_each_cpu(ipi_flush_icache_range, &fd, 1);
+}
+
+/* ------------------------------------------------------------------------- */
+
+static void ipi_invalidate_dcache_range(void *arg)
+{
+       struct flush_data *fd = arg;
+       __invalidate_dcache_range(fd->addr1, fd->addr2);
+}
+
+static void system_invalidate_dcache_range(unsigned long start,
+               unsigned long size)
+{
+       struct flush_data fd = {
+               .addr1 = start,
+               .addr2 = size,
+       };
+       on_each_cpu(ipi_invalidate_dcache_range, &fd, 1);
+}
+
+static void ipi_flush_invalidate_dcache_range(void *arg)
+{
+       struct flush_data *fd = arg;
+       __flush_invalidate_dcache_range(fd->addr1, fd->addr2);
+}
+
+static void system_flush_invalidate_dcache_range(unsigned long start,
+               unsigned long size)
+{
+       struct flush_data fd = {
+               .addr1 = start,
+               .addr2 = size,
+       };
+       on_each_cpu(ipi_flush_invalidate_dcache_range, &fd, 1);
+}
index 9af3dd88ad7eac172e4fb835e94c70e369547438..60dcb3fcaeae8ad978f8eeec4d073a88abb9f064 100644 (file)
@@ -46,24 +46,19 @@ static struct clocksource ccount_clocksource = {
        .rating = 200,
        .read = ccount_read,
        .mask = CLOCKSOURCE_MASK(32),
+       .flags = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 static int ccount_timer_set_next_event(unsigned long delta,
                struct clock_event_device *dev);
 static void ccount_timer_set_mode(enum clock_event_mode mode,
                struct clock_event_device *evt);
-static struct ccount_timer_t {
+struct ccount_timer {
        struct clock_event_device evt;
        int irq_enabled;
-} ccount_timer = {
-       .evt = {
-               .name           = "ccount_clockevent",
-               .features       = CLOCK_EVT_FEAT_ONESHOT,
-               .rating         = 300,
-               .set_next_event = ccount_timer_set_next_event,
-               .set_mode       = ccount_timer_set_mode,
-       },
+       char name[24];
 };
+static DEFINE_PER_CPU(struct ccount_timer, ccount_timer);
 
 static int ccount_timer_set_next_event(unsigned long delta,
                struct clock_event_device *dev)
@@ -84,8 +79,8 @@ static int ccount_timer_set_next_event(unsigned long delta,
 static void ccount_timer_set_mode(enum clock_event_mode mode,
                struct clock_event_device *evt)
 {
-       struct ccount_timer_t *timer =
-               container_of(evt, struct ccount_timer_t, evt);
+       struct ccount_timer *timer =
+               container_of(evt, struct ccount_timer, evt);
 
        /*
         * There is no way to disable the timer interrupt at the device level,
@@ -117,9 +112,28 @@ static struct irqaction timer_irqaction = {
        .handler =      timer_interrupt,
        .flags =        IRQF_TIMER,
        .name =         "timer",
-       .dev_id =       &ccount_timer,
 };
 
+void local_timer_setup(unsigned cpu)
+{
+       struct ccount_timer *timer = &per_cpu(ccount_timer, cpu);
+       struct clock_event_device *clockevent = &timer->evt;
+
+       timer->irq_enabled = 1;
+       clockevent->name = timer->name;
+       snprintf(timer->name, sizeof(timer->name), "ccount_clockevent_%u", cpu);
+       clockevent->features = CLOCK_EVT_FEAT_ONESHOT;
+       clockevent->rating = 300;
+       clockevent->set_next_event = ccount_timer_set_next_event;
+       clockevent->set_mode = ccount_timer_set_mode;
+       clockevent->cpumask = cpumask_of(cpu);
+       clockevent->irq = irq_create_mapping(NULL, LINUX_TIMER_INT);
+       if (WARN(!clockevent->irq, "error: can't map timer irq"))
+               return;
+       clockevents_config_and_register(clockevent, ccount_freq,
+                                       0xf, 0xffffffff);
+}
+
 void __init time_init(void)
 {
 #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT
@@ -131,16 +145,8 @@ void __init time_init(void)
        ccount_freq = CONFIG_XTENSA_CPU_CLOCK*1000000UL;
 #endif
        clocksource_register_hz(&ccount_clocksource, ccount_freq);
-
-       ccount_timer.evt.cpumask = cpumask_of(0);
-       ccount_timer.evt.irq = irq_create_mapping(NULL, LINUX_TIMER_INT);
-       if (WARN(!ccount_timer.evt.irq, "error: can't map timer irq"))
-               return;
-       clockevents_config_and_register(&ccount_timer.evt, ccount_freq, 0xf,
-                       0xffffffff);
-       setup_irq(ccount_timer.evt.irq, &timer_irqaction);
-       ccount_timer.irq_enabled = 1;
-
+       local_timer_setup(0);
+       setup_irq(this_cpu_ptr(&ccount_timer)->evt.irq, &timer_irqaction);
        setup_sched_clock(ccount_sched_clock_read, 32, ccount_freq);
 }
 
@@ -148,11 +154,11 @@ void __init time_init(void)
  * The timer interrupt is called HZ times per second.
  */
 
-irqreturn_t timer_interrupt (int irq, void *dev_id)
+irqreturn_t timer_interrupt(int irq, void *dev_id)
 {
-       struct ccount_timer_t *timer = dev_id;
-       struct clock_event_device *evt = &timer->evt;
+       struct clock_event_device *evt = &this_cpu_ptr(&ccount_timer)->evt;
 
+       set_linux_timer(get_linux_timer());
        evt->event_handler(evt);
 
        /* Allow platform to do something useful (Wdog). */
index 3e8a05c874cd2719951929ff348b4d24f34c773e..eebbfd8c26fc25121bced6cb18c074a55c6cb5f5 100644 (file)
@@ -157,7 +157,7 @@ COPROCESSOR(7),
  * 2. it is a temporary memory buffer for the exception handlers.
  */
 
-unsigned long exc_table[EXC_TABLE_SIZE/4];
+DEFINE_PER_CPU(unsigned long, exc_table[EXC_TABLE_SIZE/4]);
 
 void die(const char*, struct pt_regs*, long);
 
@@ -212,6 +212,9 @@ void do_interrupt(struct pt_regs *regs)
                XCHAL_INTLEVEL6_MASK,
                XCHAL_INTLEVEL7_MASK,
        };
+       struct pt_regs *old_regs = set_irq_regs(regs);
+
+       irq_enter();
 
        for (;;) {
                unsigned intread = get_sr(interrupt);
@@ -227,21 +230,13 @@ void do_interrupt(struct pt_regs *regs)
                }
 
                if (level == 0)
-                       return;
-
-               /*
-                * Clear the interrupt before processing, in case it's
-                *  edge-triggered or software-generated
-                */
-               while (int_at_level) {
-                       unsigned i = __ffs(int_at_level);
-                       unsigned mask = 1 << i;
-
-                       int_at_level ^= mask;
-                       set_sr(mask, intclear);
-                       do_IRQ(i, regs);
-               }
+                       break;
+
+               do_IRQ(__ffs(int_at_level), regs);
        }
+
+       irq_exit();
+       set_irq_regs(old_regs);
 }
 
 /*
@@ -318,17 +313,31 @@ do_debug(struct pt_regs *regs)
 }
 
 
+static void set_handler(int idx, void *handler)
+{
+       unsigned int cpu;
+
+       for_each_possible_cpu(cpu)
+               per_cpu(exc_table, cpu)[idx] = (unsigned long)handler;
+}
+
 /* Set exception C handler - for temporary use when probing exceptions */
 
 void * __init trap_set_handler(int cause, void *handler)
 {
-       unsigned long *entry = &exc_table[EXC_TABLE_DEFAULT / 4 + cause];
-       void *previous = (void *)*entry;
-       *entry = (unsigned long)handler;
+       void *previous = (void *)per_cpu(exc_table, 0)[
+               EXC_TABLE_DEFAULT / 4 + cause];
+       set_handler(EXC_TABLE_DEFAULT / 4 + cause, handler);
        return previous;
 }
 
 
+static void trap_init_excsave(void)
+{
+       unsigned long excsave1 = (unsigned long)this_cpu_ptr(exc_table);
+       __asm__ __volatile__("wsr  %0, excsave1\n" : : "a" (excsave1));
+}
+
 /*
  * Initialize dispatch tables.
  *
@@ -342,8 +351,6 @@ void * __init trap_set_handler(int cause, void *handler)
  * See vectors.S for more details.
  */
 
-#define set_handler(idx,handler) (exc_table[idx] = (unsigned long) (handler))
-
 void __init trap_init(void)
 {
        int i;
@@ -373,10 +380,15 @@ void __init trap_init(void)
        }
 
        /* Initialize EXCSAVE_1 to hold the address of the exception table. */
+       trap_init_excsave();
+}
 
-       i = (unsigned long)exc_table;
-       __asm__ __volatile__("wsr  %0, excsave1\n" : : "a" (i));
+#ifdef CONFIG_SMP
+void secondary_trap_init(void)
+{
+       trap_init_excsave();
 }
+#endif
 
 /*
  * This function dumps the current valid window frame and other base registers.
index 21acd11b5df2f689f0079f47a3910aaaa4ffbf41..ee32c0085dff4296fb9290e3706733db9402460d 100644 (file)
@@ -165,6 +165,13 @@ SECTIONS
                   .DoubleExceptionVector.text);
     RELOCATE_ENTRY(_DebugInterruptVector_text,
                   .DebugInterruptVector.text);
+#if defined(CONFIG_SMP)
+    RELOCATE_ENTRY(_SecondaryResetVector_literal,
+                  .SecondaryResetVector.literal);
+    RELOCATE_ENTRY(_SecondaryResetVector_text,
+                  .SecondaryResetVector.text);
+#endif
+
   
     __boot_reloc_table_end = ABSOLUTE(.) ;
 
@@ -272,6 +279,25 @@ SECTIONS
                  .DoubleExceptionVector.literal)
 
   . = (LOADADDR( .DoubleExceptionVector.text ) + SIZEOF( .DoubleExceptionVector.text ) + 3) & ~ 3;
+
+#if defined(CONFIG_SMP)
+
+  SECTION_VECTOR (_SecondaryResetVector_literal,
+                 .SecondaryResetVector.literal,
+                 RESET_VECTOR1_VADDR - 4,
+                 SIZEOF(.DoubleExceptionVector.text),
+                 .DoubleExceptionVector.text)
+
+  SECTION_VECTOR (_SecondaryResetVector_text,
+                 .SecondaryResetVector.text,
+                 RESET_VECTOR1_VADDR,
+                 4,
+                 .SecondaryResetVector.literal)
+
+  . = LOADADDR(.SecondaryResetVector.text)+SIZEOF(.SecondaryResetVector.text);
+
+#endif
+
   . = ALIGN(PAGE_SIZE);
 
   __init_end = .;
index 81edeab82d174eb478ad303001da881d6758f2bb..ba4c47f291b17843047a410549b09cb59ba52967 100644 (file)
@@ -118,7 +118,7 @@ void flush_dcache_page(struct page *page)
  * For now, flush the whole cache. FIXME??
  */
 
-void flush_cache_range(struct vm_area_struct* vma,
+void local_flush_cache_range(struct vm_area_struct *vma,
                       unsigned long start, unsigned long end)
 {
        __flush_invalidate_dcache_all();
@@ -132,7 +132,7 @@ void flush_cache_range(struct vm_area_struct* vma,
  * alias versions of the cache flush functions.
  */
 
-void flush_cache_page(struct vm_area_struct* vma, unsigned long address,
+void local_flush_cache_page(struct vm_area_struct *vma, unsigned long address,
                      unsigned long pfn)
 {
        /* Note that we have to use the 'alias' address to avoid multi-hit */
@@ -159,8 +159,7 @@ update_mmu_cache(struct vm_area_struct * vma, unsigned long addr, pte_t *ptep)
 
        /* Invalidate old entry in TLBs */
 
-       invalidate_itlb_mapping(addr);
-       invalidate_dtlb_mapping(addr);
+       flush_tlb_page(vma, addr);
 
 #if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
 
index 70fa7bc42b4a0853012af6f6daaeb254f9c5a086..b57c4f91f487efdc6b2f3f44fe43cfb12e9a7e0c 100644 (file)
@@ -21,7 +21,7 @@
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
 
-unsigned long asid_cache = ASID_USER_FIRST;
+DEFINE_PER_CPU(unsigned long, asid_cache) = ASID_USER_FIRST;
 void bad_page_fault(struct pt_regs*, unsigned long, int);
 
 #undef DEBUG_PAGE_FAULT
index d97ed1ba7b0addd36d81782469ead96889535fc0..1f68558dbcc2264f99f917fcb18659d90f46a8cb 100644 (file)
@@ -140,7 +140,7 @@ ENTRY(clear_user_page)
 
        /* Setup a temporary DTLB with the color of the VPN */
 
-       movi    a4, -PAGE_OFFSET + (PAGE_KERNEL | _PAGE_HW_WRITE)
+       movi    a4, ((PAGE_KERNEL | _PAGE_HW_WRITE) - PAGE_OFFSET) & 0xffffffff
        movi    a5, TLBTEMP_BASE_1                      # virt
        add     a6, a2, a4                              # ppn
        add     a2, a5, a3                              # add 'color'
@@ -194,7 +194,7 @@ ENTRY(copy_user_page)
        or      a9, a9, a8
        slli    a4, a4, PAGE_SHIFT
        s32i    a9, a5, PAGE_FLAGS
-       movi    a5, -PAGE_OFFSET + (PAGE_KERNEL | _PAGE_HW_WRITE)
+       movi    a5, ((PAGE_KERNEL | _PAGE_HW_WRITE) - PAGE_OFFSET) & 0xffffffff
 
        beqz    a6, 1f
 
index c43771c974be94ceea2152bf77cec9777b3c4b1a..5bb8e3c61d850ca05cde23dbdf9872ffe7b262af 100644 (file)
@@ -22,7 +22,7 @@ void __init paging_init(void)
 /*
  * Flush the mmu and reset associated register to default values.
  */
-void __init init_mmu(void)
+void init_mmu(void)
 {
 #if !(XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY)
        /*
@@ -37,7 +37,7 @@ void __init init_mmu(void)
        set_itlbcfg_register(0);
        set_dtlbcfg_register(0);
 #endif
-       flush_tlb_all();
+       local_flush_tlb_all();
 
        /* Set rasid register to a known value. */
 
index ca9d2366bf12b5b85dad9c4fd1295ed14a02d2a5..ade623826788b387f150cfae5a90821f07f6b028 100644 (file)
@@ -48,7 +48,7 @@ static inline void __flush_dtlb_all (void)
 }
 
 
-void flush_tlb_all (void)
+void local_flush_tlb_all(void)
 {
        __flush_itlb_all();
        __flush_dtlb_all();
@@ -60,19 +60,23 @@ void flush_tlb_all (void)
  * a new context will be assigned to it.
  */
 
-void flush_tlb_mm(struct mm_struct *mm)
+void local_flush_tlb_mm(struct mm_struct *mm)
 {
+       int cpu = smp_processor_id();
+
        if (mm == current->active_mm) {
                unsigned long flags;
                local_irq_save(flags);
-               __get_new_mmu_context(mm);
-               __load_mmu_context(mm);
+               mm->context.asid[cpu] = NO_CONTEXT;
+               activate_context(mm, cpu);
                local_irq_restore(flags);
+       } else {
+               mm->context.asid[cpu] = NO_CONTEXT;
+               mm->context.cpu = -1;
        }
-       else
-               mm->context = 0;
 }
 
+
 #define _ITLB_ENTRIES (ITLB_ARF_WAYS << XCHAL_ITLB_ARF_ENTRIES_LOG2)
 #define _DTLB_ENTRIES (DTLB_ARF_WAYS << XCHAL_DTLB_ARF_ENTRIES_LOG2)
 #if _ITLB_ENTRIES > _DTLB_ENTRIES
@@ -81,24 +85,26 @@ void flush_tlb_mm(struct mm_struct *mm)
 # define _TLB_ENTRIES _DTLB_ENTRIES
 #endif
 
-void flush_tlb_range (struct vm_area_struct *vma,
-                     unsigned long start, unsigned long end)
+void local_flush_tlb_range(struct vm_area_struct *vma,
+               unsigned long start, unsigned long end)
 {
+       int cpu = smp_processor_id();
        struct mm_struct *mm = vma->vm_mm;
        unsigned long flags;
 
-       if (mm->context == NO_CONTEXT)
+       if (mm->context.asid[cpu] == NO_CONTEXT)
                return;
 
 #if 0
        printk("[tlbrange<%02lx,%08lx,%08lx>]\n",
-                       (unsigned long)mm->context, start, end);
+                       (unsigned long)mm->context.asid[cpu], start, end);
 #endif
        local_irq_save(flags);
 
        if (end-start + (PAGE_SIZE-1) <= _TLB_ENTRIES << PAGE_SHIFT) {
                int oldpid = get_rasid_register();
-               set_rasid_register (ASID_INSERT(mm->context));
+
+               set_rasid_register(ASID_INSERT(mm->context.asid[cpu]));
                start &= PAGE_MASK;
                if (vma->vm_flags & VM_EXEC)
                        while(start < end) {
@@ -114,24 +120,25 @@ void flush_tlb_range (struct vm_area_struct *vma,
 
                set_rasid_register(oldpid);
        } else {
-               flush_tlb_mm(mm);
+               local_flush_tlb_mm(mm);
        }
        local_irq_restore(flags);
 }
 
-void flush_tlb_page (struct vm_area_struct *vma, unsigned long page)
+void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
 {
+       int cpu = smp_processor_id();
        struct mm_struct* mm = vma->vm_mm;
        unsigned long flags;
        int oldpid;
 
-       if(mm->context == NO_CONTEXT)
+       if (mm->context.asid[cpu] == NO_CONTEXT)
                return;
 
        local_irq_save(flags);
 
        oldpid = get_rasid_register();
-       set_rasid_register(ASID_INSERT(mm->context));
+       set_rasid_register(ASID_INSERT(mm->context.asid[cpu]));
 
        if (vma->vm_flags & VM_EXEC)
                invalidate_itlb_mapping(page);
index e9e1aad8c271048d4fde5bdac7ebef7e1cc79a96..5ae928275db67c6044f348e8922a2a4454050c7b 100644 (file)
@@ -38,7 +38,7 @@
 #define DRIVER_NAME "iss-netdev"
 #define ETH_MAX_PACKET 1500
 #define ETH_HEADER_OTHER 14
-#define ISS_NET_TIMER_VALUE (2 * HZ)
+#define ISS_NET_TIMER_VALUE (HZ / 10)
 
 
 static DEFINE_SPINLOCK(opened_lock);
@@ -56,8 +56,6 @@ static LIST_HEAD(devices);
 
 struct tuntap_info {
        char dev_name[IFNAMSIZ];
-       int fixed_config;
-       unsigned char gw[ETH_ALEN];
        int fd;
 };
 
@@ -67,7 +65,6 @@ struct tuntap_info {
 /* This structure contains out private information for the driver. */
 
 struct iss_net_private {
-
        struct list_head device_list;
        struct list_head opened_list;
 
@@ -83,9 +80,6 @@ struct iss_net_private {
        int index;
        int mtu;
 
-       unsigned char mac[ETH_ALEN];
-       int have_mac;
-
        struct {
                union {
                        struct tuntap_info tuntap;
@@ -118,68 +112,55 @@ static char *split_if_spec(char *str, ...)
                        *arg = str;
                if (end == NULL)
                        return NULL;
-               *end ++ = '\0';
+               *end++ = '\0';
                str = end;
        }
        va_end(ap);
        return str;
 }
 
+/* Set Ethernet address of the specified device. */
 
-#if 0
-/* Adjust SKB. */
-
-struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra)
+static void setup_etheraddr(struct net_device *dev, char *str)
 {
-       if ((skb != NULL) && (skb_tailroom(skb) < extra)) {
-               struct sk_buff *skb2;
-
-               skb2 = skb_copy_expand(skb, 0, extra, GFP_ATOMIC);
-               dev_kfree_skb(skb);
-               skb = skb2;
+       unsigned char *addr = dev->dev_addr;
+       char *end;
+       int i;
+
+       if (str == NULL)
+               goto random;
+
+       for (i = 0; i < ETH_ALEN; i++) {
+               addr[i] = kstrtoul(str, 16, &end);
+               if ((end == str) ||
+                   ((*end != ':') && (*end != ',') && (*end != '\0'))) {
+                       pr_err("%s: failed to parse '%s' as an ethernet address\n",
+                              dev->name, str);
+                       goto random;
+               }
+               str = end + 1;
        }
-       if (skb != NULL)
-               skb_put(skb, extra);
-
-       return skb;
-}
-#endif
-
-/* Return the IP address as a string for a given device. */
-
-static void dev_ip_addr(void *d, char *buf, char *bin_buf)
-{
-       struct net_device *dev = d;
-       struct in_device *ip = dev->ip_ptr;
-       struct in_ifaddr *in;
-       __be32 addr;
-
-       if ((ip == NULL) || ((in = ip->ifa_list) == NULL)) {
-               printk(KERN_WARNING "Device not assigned an IP address!\n");
-               return;
+       if (is_multicast_ether_addr(addr)) {
+               pr_err("%s: attempt to assign a multicast ethernet address\n",
+                      dev->name);
+               goto random;
        }
-
-       addr = in->ifa_address;
-       sprintf(buf, "%d.%d.%d.%d", addr & 0xff, (addr >> 8) & 0xff,
-               (addr >> 16) & 0xff, addr >> 24);
-
-       if (bin_buf) {
-               bin_buf[0] = addr & 0xff;
-               bin_buf[1] = (addr >> 8) & 0xff;
-               bin_buf[2] = (addr >> 16) & 0xff;
-               bin_buf[3] = addr >> 24;
+       if (!is_valid_ether_addr(addr)) {
+               pr_err("%s: attempt to assign an invalid ethernet address\n",
+                      dev->name);
+               goto random;
        }
+       if (!is_local_ether_addr(addr))
+               pr_warn("%s: assigning a globally valid ethernet address\n",
+                       dev->name);
+       return;
+
+random:
+       pr_info("%s: choosing a random ethernet address\n",
+               dev->name);
+       eth_hw_addr_random(dev);
 }
 
-/* Set Ethernet address of the specified device. */
-
-static void inline set_ether_mac(void *d, unsigned char *addr)
-{
-       struct net_device *dev = d;
-       memcpy(dev->dev_addr, addr, ETH_ALEN);
-}
-
-
 /* ======================= TUNTAP TRANSPORT INTERFACE ====================== */
 
 static int tuntap_open(struct iss_net_private *lp)
@@ -189,24 +170,21 @@ static int tuntap_open(struct iss_net_private *lp)
        int err = -EINVAL;
        int fd;
 
-       /* We currently only support a fixed configuration. */
-
-       if (!lp->tp.info.tuntap.fixed_config)
-               return -EINVAL;
-
-       if ((fd = simc_open("/dev/net/tun", 02, 0)) < 0) {      /* O_RDWR */
-               printk("Failed to open /dev/net/tun, returned %d "
-                      "(errno = %d)\n", fd, errno);
+       fd = simc_open("/dev/net/tun", 02, 0); /* O_RDWR */
+       if (fd < 0) {
+               pr_err("%s: failed to open /dev/net/tun, returned %d (errno = %d)\n",
+                      lp->dev->name, fd, errno);
                return fd;
        }
 
-       memset(&ifr, 0, sizeof ifr);
+       memset(&ifr, 0, sizeof(ifr));
        ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
-       strlcpy(ifr.ifr_name, dev_name, sizeof ifr.ifr_name);
+       strlcpy(ifr.ifr_name, dev_name, sizeof(ifr.ifr_name));
 
-       if ((err = simc_ioctl(fd, TUNSETIFF, (void*) &ifr)) < 0) {
-               printk("Failed to set interface, returned %d "
-                      "(errno = %d)\n", err, errno);
+       err = simc_ioctl(fd, TUNSETIFF, &ifr);
+       if (err < 0) {
+               pr_err("%s: failed to set interface %s, returned %d (errno = %d)\n",
+                      lp->dev->name, dev_name, err, errno);
                simc_close(fd);
                return err;
        }
@@ -217,27 +195,17 @@ static int tuntap_open(struct iss_net_private *lp)
 
 static void tuntap_close(struct iss_net_private *lp)
 {
-#if 0
-       if (lp->tp.info.tuntap.fixed_config)
-               iter_addresses(lp->tp.info.tuntap.dev, close_addr, lp->host.dev_name);
-#endif
        simc_close(lp->tp.info.tuntap.fd);
        lp->tp.info.tuntap.fd = -1;
 }
 
-static int tuntap_read (struct iss_net_private *lp, struct sk_buff **skb)
+static int tuntap_read(struct iss_net_private *lp, struct sk_buff **skb)
 {
-#if 0
-       *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER);
-       if (*skb == NULL)
-               return -ENOMEM;
-#endif
-
        return simc_read(lp->tp.info.tuntap.fd,
                        (*skb)->data, (*skb)->dev->mtu + ETH_HEADER_OTHER);
 }
 
-static int tuntap_write (struct iss_net_private *lp, struct sk_buff **skb)
+static int tuntap_write(struct iss_net_private *lp, struct sk_buff **skb)
 {
        return simc_write(lp->tp.info.tuntap.fd, (*skb)->data, (*skb)->len);
 }
@@ -253,45 +221,45 @@ static int tuntap_poll(struct iss_net_private *lp)
 }
 
 /*
- * Currently only a device name is supported.
- * ethX=tuntap[,[mac address][,[device name]]]
+ * ethX=tuntap,[mac address],device name
  */
 
 static int tuntap_probe(struct iss_net_private *lp, int index, char *init)
 {
-       const int len = strlen(TRANSPORT_TUNTAP_NAME);
+       struct net_device *dev = lp->dev;
        char *dev_name = NULL, *mac_str = NULL, *rem = NULL;
 
        /* Transport should be 'tuntap': ethX=tuntap,mac,dev_name */
 
-       if (strncmp(init, TRANSPORT_TUNTAP_NAME, len))
+       if (strncmp(init, TRANSPORT_TUNTAP_NAME,
+                   sizeof(TRANSPORT_TUNTAP_NAME) - 1))
                return 0;
 
-       if (*(init += strlen(TRANSPORT_TUNTAP_NAME)) == ',') {
-               if ((rem=split_if_spec(init+1, &mac_str, &dev_name)) != NULL) {
-                       printk("Extra garbage on specification : '%s'\n", rem);
+       init += sizeof(TRANSPORT_TUNTAP_NAME) - 1;
+       if (*init == ',') {
+               rem = split_if_spec(init + 1, &mac_str, &dev_name);
+               if (rem != NULL) {
+                       pr_err("%s: extra garbage on specification : '%s'\n",
+                              dev->name, rem);
                        return 0;
                }
        } else if (*init != '\0') {
-               printk("Invalid argument: %s. Skipping device!\n", init);
+               pr_err("%s: invalid argument: %s. Skipping device!\n",
+                      dev->name, init);
                return 0;
        }
 
-       if (dev_name) {
-               strncpy(lp->tp.info.tuntap.dev_name, dev_name,
-                        sizeof lp->tp.info.tuntap.dev_name);
-               lp->tp.info.tuntap.fixed_config = 1;
-       } else
-               strcpy(lp->tp.info.tuntap.dev_name, TRANSPORT_TUNTAP_NAME);
+       if (!dev_name) {
+               pr_err("%s: missing tuntap device name\n", dev->name);
+               return 0;
+       }
 
+       strlcpy(lp->tp.info.tuntap.dev_name, dev_name,
+               sizeof(lp->tp.info.tuntap.dev_name));
 
-#if 0
-       if (setup_etheraddr(mac_str, lp->mac))
-               lp->have_mac = 1;
-#endif
-       lp->mtu = TRANSPORT_TUNTAP_MTU;
+       setup_etheraddr(dev, mac_str);
 
-       //lp->info.tuntap.gate_addr = gate_addr;
+       lp->mtu = TRANSPORT_TUNTAP_MTU;
 
        lp->tp.info.tuntap.fd = -1;
 
@@ -302,13 +270,6 @@ static int tuntap_probe(struct iss_net_private *lp, int index, char *init)
        lp->tp.protocol = tuntap_protocol;
        lp->tp.poll = tuntap_poll;
 
-       printk("TUN/TAP backend - ");
-#if 0
-       if (lp->host.gate_addr != NULL)
-               printk("IP = %s", lp->host.gate_addr);
-#endif
-       printk("\n");
-
        return 1;
 }
 
@@ -327,7 +288,8 @@ static int iss_net_rx(struct net_device *dev)
 
        /* Try to allocate memory, if it fails, try again next round. */
 
-       if ((skb = dev_alloc_skb(dev->mtu + 2 + ETH_HEADER_OTHER)) == NULL) {
+       skb = dev_alloc_skb(dev->mtu + 2 + ETH_HEADER_OTHER);
+       if (skb == NULL) {
                lp->stats.rx_dropped++;
                return 0;
        }
@@ -347,7 +309,6 @@ static int iss_net_rx(struct net_device *dev)
 
                lp->stats.rx_bytes += skb->len;
                lp->stats.rx_packets++;
-       //      netif_rx(skb);
                netif_rx_ni(skb);
                return pkt_len;
        }
@@ -378,11 +339,11 @@ static int iss_net_poll(void)
                spin_unlock(&lp->lock);
 
                if (err < 0) {
-                       printk(KERN_ERR "Device '%s' read returned %d, "
-                              "shutting it down\n", lp->dev->name, err);
+                       pr_err("Device '%s' read returned %d, shutting it down\n",
+                              lp->dev->name, err);
                        dev_close(lp->dev);
                } else {
-                       // FIXME reactivate_fd(lp->fd, ISS_ETH_IRQ);
+                       /* FIXME reactivate_fd(lp->fd, ISS_ETH_IRQ); */
                }
        }
 
@@ -393,14 +354,11 @@ static int iss_net_poll(void)
 
 static void iss_net_timer(unsigned long priv)
 {
-       struct iss_net_private* lp = (struct iss_net_private*) priv;
+       struct iss_net_private *lp = (struct iss_net_private *)priv;
 
        spin_lock(&lp->lock);
-
        iss_net_poll();
-
        mod_timer(&lp->timer, jiffies + lp->timer_val);
-
        spin_unlock(&lp->lock);
 }
 
@@ -408,19 +366,14 @@ static void iss_net_timer(unsigned long priv)
 static int iss_net_open(struct net_device *dev)
 {
        struct iss_net_private *lp = netdev_priv(dev);
-       char addr[sizeof "255.255.255.255\0"];
        int err;
 
        spin_lock(&lp->lock);
 
-       if ((err = lp->tp.open(lp)) < 0)
+       err = lp->tp.open(lp);
+       if (err < 0)
                goto out;
 
-       if (!lp->have_mac) {
-               dev_ip_addr(dev, addr, &lp->mac[2]);
-               set_ether_mac(dev, lp->mac);
-       }
-
        netif_start_queue(dev);
 
        /* clear buffer - it can happen that the host side of the interface
@@ -448,7 +401,6 @@ out:
 static int iss_net_close(struct net_device *dev)
 {
        struct iss_net_private *lp = netdev_priv(dev);
-printk("iss_net_close!\n");
        netif_stop_queue(dev);
        spin_lock(&lp->lock);
 
@@ -490,7 +442,7 @@ static int iss_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        } else {
                netif_start_queue(dev);
-               printk(KERN_ERR "iss_net_start_xmit: failed(%d)\n", len);
+               pr_err("%s: %s failed(%d)\n", dev->name, __func__, len);
        }
 
        spin_unlock_irqrestore(&lp->lock, flags);
@@ -508,56 +460,27 @@ static struct net_device_stats *iss_net_get_stats(struct net_device *dev)
 
 static void iss_net_set_multicast_list(struct net_device *dev)
 {
-#if 0
-       if (dev->flags & IFF_PROMISC)
-               return;
-       else if (!netdev_mc_empty(dev))
-               dev->flags |= IFF_ALLMULTI;
-       else
-               dev->flags &= ~IFF_ALLMULTI;
-#endif
 }
 
 static void iss_net_tx_timeout(struct net_device *dev)
 {
-#if 0
-       dev->trans_start = jiffies;
-       netif_wake_queue(dev);
-#endif
 }
 
 static int iss_net_set_mac(struct net_device *dev, void *addr)
 {
-#if 0
        struct iss_net_private *lp = netdev_priv(dev);
        struct sockaddr *hwaddr = addr;
 
+       if (!is_valid_ether_addr(hwaddr->sa_data))
+               return -EADDRNOTAVAIL;
        spin_lock(&lp->lock);
        memcpy(dev->dev_addr, hwaddr->sa_data, ETH_ALEN);
        spin_unlock(&lp->lock);
-#endif
-
        return 0;
 }
 
 static int iss_net_change_mtu(struct net_device *dev, int new_mtu)
 {
-#if 0
-       struct iss_net_private *lp = netdev_priv(dev);
-       int err = 0;
-
-       spin_lock(&lp->lock);
-
-       // FIXME not needed new_mtu = transport_set_mtu(new_mtu, &lp->user);
-
-       if (new_mtu < 0)
-               err = new_mtu;
-       else
-               dev->mtu = new_mtu;
-
-       spin_unlock(&lp->lock);
-       return err;
-#endif
        return -EINVAL;
 }
 
@@ -582,7 +505,6 @@ static const struct net_device_ops iss_netdev_ops = {
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_change_mtu         = iss_net_change_mtu,
        .ndo_set_mac_address    = iss_net_set_mac,
-       //.ndo_do_ioctl         = iss_net_ioctl,
        .ndo_tx_timeout         = iss_net_tx_timeout,
        .ndo_set_rx_mode        = iss_net_set_multicast_list,
 };
@@ -593,24 +515,29 @@ static int iss_net_configure(int index, char *init)
        struct iss_net_private *lp;
        int err;
 
-       if ((dev = alloc_etherdev(sizeof *lp)) == NULL) {
-               printk(KERN_ERR "eth_configure: failed to allocate device\n");
+       dev = alloc_etherdev(sizeof(*lp));
+       if (dev == NULL) {
+               pr_err("eth_configure: failed to allocate device\n");
                return 1;
        }
 
        /* Initialize private element. */
 
        lp = netdev_priv(dev);
-       *lp = ((struct iss_net_private) {
+       *lp = (struct iss_net_private) {
                .device_list            = LIST_HEAD_INIT(lp->device_list),
                .opened_list            = LIST_HEAD_INIT(lp->opened_list),
                .lock                   = __SPIN_LOCK_UNLOCKED(lp.lock),
                .dev                    = dev,
                .index                  = index,
-               //.fd                   = -1,
-               .mac                    = { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0 },
-               .have_mac               = 0,
-               });
+               };
+
+       /*
+        * If this name ends up conflicting with an existing registered
+        * netdevice, that is OK, register_netdev{,ice}() will notice this
+        * and fail.
+        */
+       snprintf(dev->name, sizeof(dev->name), "eth%d", index);
 
        /*
         * Try all transport protocols.
@@ -618,14 +545,12 @@ static int iss_net_configure(int index, char *init)
         */
 
        if (!tuntap_probe(lp, index, init)) {
-               printk("Invalid arguments. Skipping device!\n");
+               pr_err("%s: invalid arguments. Skipping device!\n",
+                      dev->name);
                goto errout;
        }
 
-       printk(KERN_INFO "Netdevice %d ", index);
-       if (lp->have_mac)
-               printk("(%pM) ", lp->mac);
-       printk(": ");
+       pr_info("Netdevice %d (%pM)\n", index, dev->dev_addr);
 
        /* sysfs register */
 
@@ -641,14 +566,7 @@ static int iss_net_configure(int index, char *init)
        lp->pdev.id = index;
        lp->pdev.name = DRIVER_NAME;
        platform_device_register(&lp->pdev);
-       SET_NETDEV_DEV(dev,&lp->pdev.dev);
-
-       /*
-        * If this name ends up conflicting with an existing registered
-        * netdevice, that is OK, register_netdev{,ice}() will notice this
-        * and fail.
-        */
-       snprintf(dev->name, sizeof dev->name, "eth%d", index);
+       SET_NETDEV_DEV(dev, &lp->pdev.dev);
 
        dev->netdev_ops = &iss_netdev_ops;
        dev->mtu = lp->mtu;
@@ -660,7 +578,7 @@ static int iss_net_configure(int index, char *init)
        rtnl_unlock();
 
        if (err) {
-               printk("Error registering net device!\n");
+               pr_err("%s: error registering net device!\n", dev->name);
                /* XXX: should we call ->remove() here? */
                free_netdev(dev);
                return 1;
@@ -669,16 +587,11 @@ static int iss_net_configure(int index, char *init)
        init_timer(&lp->tl);
        lp->tl.function = iss_net_user_timer_expire;
 
-#if 0
-       if (lp->have_mac)
-               set_ether_mac(dev, lp->mac);
-#endif
        return 0;
 
 errout:
-       // FIXME: unregister; free, etc..
+       /* FIXME: unregister; free, etc.. */
        return -EIO;
-
 }
 
 /* ------------------------------------------------------------------------- */
@@ -717,7 +630,8 @@ static int __init iss_net_setup(char *str)
                printk(ERR "Device %d is negative\n", n);
                return 1;
        }
-       if (*(str = end) != '=') {
+       str = end;
+       if (*str != '=') {
                printk(ERR "Expected '=' after device number\n");
                return 1;
        }
@@ -739,7 +653,7 @@ static int __init iss_net_setup(char *str)
 
        new = alloc_bootmem(sizeof(*new));
        if (new == NULL) {
-               printk("Alloc_bootmem failed\n");
+               printk(ERR "Alloc_bootmem failed\n");
                return 1;
        }
 
@@ -753,7 +667,7 @@ static int __init iss_net_setup(char *str)
 
 #undef ERR
 
-__setup("eth=", iss_net_setup);
+__setup("eth", iss_net_setup);
 
 /*
  * Initialize all ISS Ethernet devices previously registered in iss_net_setup.
index 4416773cbde5c1755c17abf3d5028babaf80ef6c..aeb316b7ff8838f9bcff5d8f29202bac7043823c 100644 (file)
 #ifndef __XTENSA_XTAVNET_HARDWARE_H
 #define __XTENSA_XTAVNET_HARDWARE_H
 
-/* By default NO_IRQ is defined to 0 in Linux, but we use the
-   interrupt 0 for UART... */
-#define NO_IRQ                 -1
-
 /* Memory configuration. */
 
 #define PLATFORM_DEFAULT_MEM_START 0x00000000
@@ -30,7 +26,7 @@
 
 /* Default assignment of LX60 devices to external interrupts. */
 
-#ifdef CONFIG_ARCH_HAS_SMP
+#ifdef CONFIG_XTENSA_MX
 #define DUART16552_INTNUM      XCHAL_EXTINT3_NUM
 #define OETH_IRQ               XCHAL_EXTINT4_NUM
 #else
index 97d6fc48deff036b1ea5a1bd940b3d998411deec..39ca751a62551c72cc2d0582a08b0ba8667ca43a 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _XTENSA_S6000_IRQ_H
 #define _XTENSA_S6000_IRQ_H
 
-#define NO_IRQ         (-1)
 #define VARIANT_NR_IRQS 8 /* GPIO interrupts */
 
 extern void variant_irq_enable(unsigned int irq);
index 1610b22edf0992da4cdeb1657688527d5867e76c..86154eab95239fdd6300ddc665f03650b80f1a5b 100644 (file)
@@ -435,9 +435,9 @@ static inline uint64_t blkg_stat_read(struct blkg_stat *stat)
        uint64_t v;
 
        do {
-               start = u64_stats_fetch_begin(&stat->syncp);
+               start = u64_stats_fetch_begin_bh(&stat->syncp);
                v = stat->cnt;
-       } while (u64_stats_fetch_retry(&stat->syncp, start));
+       } while (u64_stats_fetch_retry_bh(&stat->syncp, start));
 
        return v;
 }
@@ -508,9 +508,9 @@ static inline struct blkg_rwstat blkg_rwstat_read(struct blkg_rwstat *rwstat)
        struct blkg_rwstat tmp;
 
        do {
-               start = u64_stats_fetch_begin(&rwstat->syncp);
+               start = u64_stats_fetch_begin_bh(&rwstat->syncp);
                tmp = *rwstat;
-       } while (u64_stats_fetch_retry(&rwstat->syncp, start));
+       } while (u64_stats_fetch_retry_bh(&rwstat->syncp, start));
 
        return tmp;
 }
index 8bdd0121212a51a1dba3c568c5a6a3e070447318..5da8e900d3b18747a90840e0beb286a8bd348185 100644 (file)
@@ -130,7 +130,7 @@ static void req_bio_endio(struct request *rq, struct bio *bio,
        bio_advance(bio, nbytes);
 
        /* don't actually finish bio if it's part of flush sequence */
-       if (bio->bi_size == 0 && !(rq->cmd_flags & REQ_FLUSH_SEQ))
+       if (bio->bi_iter.bi_size == 0 && !(rq->cmd_flags & REQ_FLUSH_SEQ))
                bio_endio(bio, error);
 }
 
@@ -1326,7 +1326,7 @@ void blk_add_request_payload(struct request *rq, struct page *page,
        bio->bi_io_vec->bv_offset = 0;
        bio->bi_io_vec->bv_len = len;
 
-       bio->bi_size = len;
+       bio->bi_iter.bi_size = len;
        bio->bi_vcnt = 1;
        bio->bi_phys_segments = 1;
 
@@ -1351,7 +1351,7 @@ bool bio_attempt_back_merge(struct request_queue *q, struct request *req,
 
        req->biotail->bi_next = bio;
        req->biotail = bio;
-       req->__data_len += bio->bi_size;
+       req->__data_len += bio->bi_iter.bi_size;
        req->ioprio = ioprio_best(req->ioprio, bio_prio(bio));
 
        blk_account_io_start(req, false);
@@ -1380,8 +1380,8 @@ bool bio_attempt_front_merge(struct request_queue *q, struct request *req,
         * not touch req->buffer either...
         */
        req->buffer = bio_data(bio);
-       req->__sector = bio->bi_sector;
-       req->__data_len += bio->bi_size;
+       req->__sector = bio->bi_iter.bi_sector;
+       req->__data_len += bio->bi_iter.bi_size;
        req->ioprio = ioprio_best(req->ioprio, bio_prio(bio));
 
        blk_account_io_start(req, false);
@@ -1459,7 +1459,7 @@ void init_request_from_bio(struct request *req, struct bio *bio)
                req->cmd_flags |= REQ_FAILFAST_MASK;
 
        req->errors = 0;
-       req->__sector = bio->bi_sector;
+       req->__sector = bio->bi_iter.bi_sector;
        req->ioprio = bio_prio(bio);
        blk_rq_bio_prep(req->q, req, bio);
 }
@@ -1583,12 +1583,12 @@ static inline void blk_partition_remap(struct bio *bio)
        if (bio_sectors(bio) && bdev != bdev->bd_contains) {
                struct hd_struct *p = bdev->bd_part;
 
-               bio->bi_sector += p->start_sect;
+               bio->bi_iter.bi_sector += p->start_sect;
                bio->bi_bdev = bdev->bd_contains;
 
                trace_block_bio_remap(bdev_get_queue(bio->bi_bdev), bio,
                                      bdev->bd_dev,
-                                     bio->bi_sector - p->start_sect);
+                                     bio->bi_iter.bi_sector - p->start_sect);
        }
 }
 
@@ -1654,7 +1654,7 @@ static inline int bio_check_eod(struct bio *bio, unsigned int nr_sectors)
        /* Test device or partition size, when known. */
        maxsector = i_size_read(bio->bi_bdev->bd_inode) >> 9;
        if (maxsector) {
-               sector_t sector = bio->bi_sector;
+               sector_t sector = bio->bi_iter.bi_sector;
 
                if (maxsector < nr_sectors || maxsector - nr_sectors < sector) {
                        /*
@@ -1690,7 +1690,7 @@ generic_make_request_checks(struct bio *bio)
                       "generic_make_request: Trying to access "
                        "nonexistent block-device %s (%Lu)\n",
                        bdevname(bio->bi_bdev, b),
-                       (long long) bio->bi_sector);
+                       (long long) bio->bi_iter.bi_sector);
                goto end_io;
        }
 
@@ -1704,9 +1704,9 @@ generic_make_request_checks(struct bio *bio)
        }
 
        part = bio->bi_bdev->bd_part;
-       if (should_fail_request(part, bio->bi_size) ||
+       if (should_fail_request(part, bio->bi_iter.bi_size) ||
            should_fail_request(&part_to_disk(part)->part0,
-                               bio->bi_size))
+                               bio->bi_iter.bi_size))
                goto end_io;
 
        /*
@@ -1865,7 +1865,7 @@ void submit_bio(int rw, struct bio *bio)
                if (rw & WRITE) {
                        count_vm_events(PGPGOUT, count);
                } else {
-                       task_io_account_read(bio->bi_size);
+                       task_io_account_read(bio->bi_iter.bi_size);
                        count_vm_events(PGPGIN, count);
                }
 
@@ -1874,7 +1874,7 @@ void submit_bio(int rw, struct bio *bio)
                        printk(KERN_DEBUG "%s(%d): %s block %Lu on %s (%u sectors)\n",
                        current->comm, task_pid_nr(current),
                                (rw & WRITE) ? "WRITE" : "READ",
-                               (unsigned long long)bio->bi_sector,
+                               (unsigned long long)bio->bi_iter.bi_sector,
                                bdevname(bio->bi_bdev, b),
                                count);
                }
@@ -2007,7 +2007,7 @@ unsigned int blk_rq_err_bytes(const struct request *rq)
        for (bio = rq->bio; bio; bio = bio->bi_next) {
                if ((bio->bi_rw & ff) != ff)
                        break;
-               bytes += bio->bi_size;
+               bytes += bio->bi_iter.bi_size;
        }
 
        /* this could lead to infinite loop */
@@ -2378,9 +2378,9 @@ bool blk_update_request(struct request *req, int error, unsigned int nr_bytes)
        total_bytes = 0;
        while (req->bio) {
                struct bio *bio = req->bio;
-               unsigned bio_bytes = min(bio->bi_size, nr_bytes);
+               unsigned bio_bytes = min(bio->bi_iter.bi_size, nr_bytes);
 
-               if (bio_bytes == bio->bi_size)
+               if (bio_bytes == bio->bi_iter.bi_size)
                        req->bio = bio->bi_next;
 
                req_bio_endio(req, bio, bio_bytes, error);
@@ -2728,7 +2728,7 @@ void blk_rq_bio_prep(struct request_queue *q, struct request *rq,
                rq->nr_phys_segments = bio_phys_segments(q, bio);
                rq->buffer = bio_data(bio);
        }
-       rq->__data_len = bio->bi_size;
+       rq->__data_len = bio->bi_iter.bi_size;
        rq->bio = rq->biotail = bio;
 
        if (bio->bi_bdev)
@@ -2746,10 +2746,10 @@ void blk_rq_bio_prep(struct request_queue *q, struct request *rq,
 void rq_flush_dcache_pages(struct request *rq)
 {
        struct req_iterator iter;
-       struct bio_vec *bvec;
+       struct bio_vec bvec;
 
        rq_for_each_segment(bvec, rq, iter)
-               flush_dcache_page(bvec->bv_page);
+               flush_dcache_page(bvec.bv_page);
 }
 EXPORT_SYMBOL_GPL(rq_flush_dcache_pages);
 #endif
index 331e627301eaacbced43537469cb9f9914b6747c..9288aaf35c21fc8c0f579fa001f316e697a4dfbb 100644 (file)
@@ -502,15 +502,6 @@ void blk_abort_flushes(struct request_queue *q)
        }
 }
 
-static void bio_end_flush(struct bio *bio, int err)
-{
-       if (err)
-               clear_bit(BIO_UPTODATE, &bio->bi_flags);
-       if (bio->bi_private)
-               complete(bio->bi_private);
-       bio_put(bio);
-}
-
 /**
  * blkdev_issue_flush - queue a flush
  * @bdev:      blockdev to issue flush for
@@ -526,7 +517,6 @@ static void bio_end_flush(struct bio *bio, int err)
 int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask,
                sector_t *error_sector)
 {
-       DECLARE_COMPLETION_ONSTACK(wait);
        struct request_queue *q;
        struct bio *bio;
        int ret = 0;
@@ -548,13 +538,9 @@ int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask,
                return -ENXIO;
 
        bio = bio_alloc(gfp_mask, 0);
-       bio->bi_end_io = bio_end_flush;
        bio->bi_bdev = bdev;
-       bio->bi_private = &wait;
 
-       bio_get(bio);
-       submit_bio(WRITE_FLUSH, bio);
-       wait_for_completion_io(&wait);
+       ret = submit_bio_wait(WRITE_FLUSH, bio);
 
        /*
         * The driver must store the error location in ->bi_sector, if
@@ -562,10 +548,7 @@ int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask,
         * copied from blk_rq_pos(rq).
         */
        if (error_sector)
-               *error_sector = bio->bi_sector;
-
-       if (!bio_flagged(bio, BIO_UPTODATE))
-               ret = -EIO;
+               *error_sector = bio->bi_iter.bi_sector;
 
        bio_put(bio);
        return ret;
index 03cf7179e8ef1aac2f1698eae57377e65a94f275..7fbab84399e6c9c602c52c8157596535a2ce2e05 100644 (file)
@@ -43,30 +43,32 @@ static const char *bi_unsupported_name = "unsupported";
  */
 int blk_rq_count_integrity_sg(struct request_queue *q, struct bio *bio)
 {
-       struct bio_vec *iv, *ivprv = NULL;
+       struct bio_vec iv, ivprv = { NULL };
        unsigned int segments = 0;
        unsigned int seg_size = 0;
-       unsigned int i = 0;
+       struct bvec_iter iter;
+       int prev = 0;
 
-       bio_for_each_integrity_vec(iv, bio, i) {
+       bio_for_each_integrity_vec(iv, bio, iter) {
 
-               if (ivprv) {
-                       if (!BIOVEC_PHYS_MERGEABLE(ivprv, iv))
+               if (prev) {
+                       if (!BIOVEC_PHYS_MERGEABLE(&ivprv, &iv))
                                goto new_segment;
 
-                       if (!BIOVEC_SEG_BOUNDARY(q, ivprv, iv))
+                       if (!BIOVEC_SEG_BOUNDARY(q, &ivprv, &iv))
                                goto new_segment;
 
-                       if (seg_size + iv->bv_len > queue_max_segment_size(q))
+                       if (seg_size + iv.bv_len > queue_max_segment_size(q))
                                goto new_segment;
 
-                       seg_size += iv->bv_len;
+                       seg_size += iv.bv_len;
                } else {
 new_segment:
                        segments++;
-                       seg_size = iv->bv_len;
+                       seg_size = iv.bv_len;
                }
 
+               prev = 1;
                ivprv = iv;
        }
 
@@ -87,24 +89,25 @@ EXPORT_SYMBOL(blk_rq_count_integrity_sg);
 int blk_rq_map_integrity_sg(struct request_queue *q, struct bio *bio,
                            struct scatterlist *sglist)
 {
-       struct bio_vec *iv, *ivprv = NULL;
+       struct bio_vec iv, ivprv = { NULL };
        struct scatterlist *sg = NULL;
        unsigned int segments = 0;
-       unsigned int i = 0;
+       struct bvec_iter iter;
+       int prev = 0;
 
-       bio_for_each_integrity_vec(iv, bio, i) {
+       bio_for_each_integrity_vec(iv, bio, iter) {
 
-               if (ivprv) {
-                       if (!BIOVEC_PHYS_MERGEABLE(ivprv, iv))
+               if (prev) {
+                       if (!BIOVEC_PHYS_MERGEABLE(&ivprv, &iv))
                                goto new_segment;
 
-                       if (!BIOVEC_SEG_BOUNDARY(q, ivprv, iv))
+                       if (!BIOVEC_SEG_BOUNDARY(q, &ivprv, &iv))
                                goto new_segment;
 
-                       if (sg->length + iv->bv_len > queue_max_segment_size(q))
+                       if (sg->length + iv.bv_len > queue_max_segment_size(q))
                                goto new_segment;
 
-                       sg->length += iv->bv_len;
+                       sg->length += iv.bv_len;
                } else {
 new_segment:
                        if (!sg)
@@ -114,10 +117,11 @@ new_segment:
                                sg = sg_next(sg);
                        }
 
-                       sg_set_page(sg, iv->bv_page, iv->bv_len, iv->bv_offset);
+                       sg_set_page(sg, iv.bv_page, iv.bv_len, iv.bv_offset);
                        segments++;
                }
 
+               prev = 1;
                ivprv = iv;
        }
 
index 9b5b561cb92812fba2562b3bdb6c5bd8be012905..2da76c999ef3f37bd965f9d91b48dac43196a208 100644 (file)
@@ -108,12 +108,12 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
                        req_sects = end_sect - sector;
                }
 
-               bio->bi_sector = sector;
+               bio->bi_iter.bi_sector = sector;
                bio->bi_end_io = bio_batch_end_io;
                bio->bi_bdev = bdev;
                bio->bi_private = &bb;
 
-               bio->bi_size = req_sects << 9;
+               bio->bi_iter.bi_size = req_sects << 9;
                nr_sects -= req_sects;
                sector = end_sect;
 
@@ -174,7 +174,7 @@ int blkdev_issue_write_same(struct block_device *bdev, sector_t sector,
                        break;
                }
 
-               bio->bi_sector = sector;
+               bio->bi_iter.bi_sector = sector;
                bio->bi_end_io = bio_batch_end_io;
                bio->bi_bdev = bdev;
                bio->bi_private = &bb;
@@ -184,11 +184,11 @@ int blkdev_issue_write_same(struct block_device *bdev, sector_t sector,
                bio->bi_io_vec->bv_len = bdev_logical_block_size(bdev);
 
                if (nr_sects > max_write_same_sectors) {
-                       bio->bi_size = max_write_same_sectors << 9;
+                       bio->bi_iter.bi_size = max_write_same_sectors << 9;
                        nr_sects -= max_write_same_sectors;
                        sector += max_write_same_sectors;
                } else {
-                       bio->bi_size = nr_sects << 9;
+                       bio->bi_iter.bi_size = nr_sects << 9;
                        nr_sects = 0;
                }
 
@@ -240,7 +240,7 @@ int __blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
                        break;
                }
 
-               bio->bi_sector = sector;
+               bio->bi_iter.bi_sector = sector;
                bio->bi_bdev   = bdev;
                bio->bi_end_io = bio_batch_end_io;
                bio->bi_private = &bb;
index 623e1cd4cffe997e71fbb54577bd42f220af64b3..ae4ae1047fd99575473a8b251dff562a151f0719 100644 (file)
@@ -20,7 +20,7 @@ int blk_rq_append_bio(struct request_queue *q, struct request *rq,
                rq->biotail->bi_next = bio;
                rq->biotail = bio;
 
-               rq->__data_len += bio->bi_size;
+               rq->__data_len += bio->bi_iter.bi_size;
        }
        return 0;
 }
@@ -76,7 +76,7 @@ static int __blk_rq_map_user(struct request_queue *q, struct request *rq,
 
        ret = blk_rq_append_bio(q, rq, bio);
        if (!ret)
-               return bio->bi_size;
+               return bio->bi_iter.bi_size;
 
        /* if it was boucned we must call the end io function */
        bio_endio(bio, 0);
@@ -220,7 +220,7 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq,
        if (IS_ERR(bio))
                return PTR_ERR(bio);
 
-       if (bio->bi_size != len) {
+       if (bio->bi_iter.bi_size != len) {
                /*
                 * Grab an extra reference to this bio, as bio_unmap_user()
                 * expects to be able to drop it twice as it happens on the
index 1ffc58977835ff2e581c97faa35ee85ebc9a5095..8f8adaa95466ccc8335cde7e313b551b375ed9b9 100644 (file)
 static unsigned int __blk_recalc_rq_segments(struct request_queue *q,
                                             struct bio *bio)
 {
-       struct bio_vec *bv, *bvprv = NULL;
-       int cluster, i, high, highprv = 1;
+       struct bio_vec bv, bvprv = { NULL };
+       int cluster, high, highprv = 1;
        unsigned int seg_size, nr_phys_segs;
        struct bio *fbio, *bbio;
+       struct bvec_iter iter;
 
        if (!bio)
                return 0;
@@ -25,25 +26,23 @@ static unsigned int __blk_recalc_rq_segments(struct request_queue *q,
        seg_size = 0;
        nr_phys_segs = 0;
        for_each_bio(bio) {
-               bio_for_each_segment(bv, bio, i) {
+               bio_for_each_segment(bv, bio, iter) {
                        /*
                         * the trick here is making sure that a high page is
                         * never considered part of another segment, since that
                         * might change with the bounce page.
                         */
-                       high = page_to_pfn(bv->bv_page) > queue_bounce_pfn(q);
-                       if (high || highprv)
-                               goto new_segment;
-                       if (cluster) {
-                               if (seg_size + bv->bv_len
+                       high = page_to_pfn(bv.bv_page) > queue_bounce_pfn(q);
+                       if (!high && !highprv && cluster) {
+                               if (seg_size + bv.bv_len
                                    > queue_max_segment_size(q))
                                        goto new_segment;
-                               if (!BIOVEC_PHYS_MERGEABLE(bvprv, bv))
+                               if (!BIOVEC_PHYS_MERGEABLE(&bvprv, &bv))
                                        goto new_segment;
-                               if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bv))
+                               if (!BIOVEC_SEG_BOUNDARY(q, &bvprv, &bv))
                                        goto new_segment;
 
-                               seg_size += bv->bv_len;
+                               seg_size += bv.bv_len;
                                bvprv = bv;
                                continue;
                        }
@@ -54,7 +53,7 @@ new_segment:
 
                        nr_phys_segs++;
                        bvprv = bv;
-                       seg_size = bv->bv_len;
+                       seg_size = bv.bv_len;
                        highprv = high;
                }
                bbio = bio;
@@ -87,6 +86,9 @@ EXPORT_SYMBOL(blk_recount_segments);
 static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio,
                                   struct bio *nxt)
 {
+       struct bio_vec end_bv = { NULL }, nxt_bv;
+       struct bvec_iter iter;
+
        if (!blk_queue_cluster(q))
                return 0;
 
@@ -97,34 +99,40 @@ static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio,
        if (!bio_has_data(bio))
                return 1;
 
-       if (!BIOVEC_PHYS_MERGEABLE(__BVEC_END(bio), __BVEC_START(nxt)))
+       bio_for_each_segment(end_bv, bio, iter)
+               if (end_bv.bv_len == iter.bi_size)
+                       break;
+
+       nxt_bv = bio_iovec(nxt);
+
+       if (!BIOVEC_PHYS_MERGEABLE(&end_bv, &nxt_bv))
                return 0;
 
        /*
         * bio and nxt are contiguous in memory; check if the queue allows
         * these two to be merged into one
         */
-       if (BIO_SEG_BOUNDARY(q, bio, nxt))
+       if (BIOVEC_SEG_BOUNDARY(q, &end_bv, &nxt_bv))
                return 1;
 
        return 0;
 }
 
-static void
+static inline void
 __blk_segment_map_sg(struct request_queue *q, struct bio_vec *bvec,
-                    struct scatterlist *sglist, struct bio_vec **bvprv,
+                    struct scatterlist *sglist, struct bio_vec *bvprv,
                     struct scatterlist **sg, int *nsegs, int *cluster)
 {
 
        int nbytes = bvec->bv_len;
 
-       if (*bvprv && *cluster) {
+       if (*sg && *cluster) {
                if ((*sg)->length + nbytes > queue_max_segment_size(q))
                        goto new_segment;
 
-               if (!BIOVEC_PHYS_MERGEABLE(*bvprv, bvec))
+               if (!BIOVEC_PHYS_MERGEABLE(bvprv, bvec))
                        goto new_segment;
-               if (!BIOVEC_SEG_BOUNDARY(q, *bvprv, bvec))
+               if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bvec))
                        goto new_segment;
 
                (*sg)->length += nbytes;
@@ -150,7 +158,7 @@ new_segment:
                sg_set_page(*sg, bvec->bv_page, nbytes, bvec->bv_offset);
                (*nsegs)++;
        }
-       *bvprv = bvec;
+       *bvprv = *bvec;
 }
 
 /*
@@ -160,7 +168,7 @@ new_segment:
 int blk_rq_map_sg(struct request_queue *q, struct request *rq,
                  struct scatterlist *sglist)
 {
-       struct bio_vec *bvec, *bvprv;
+       struct bio_vec bvec, bvprv = { NULL };
        struct req_iterator iter;
        struct scatterlist *sg;
        int nsegs, cluster;
@@ -171,10 +179,9 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq,
        /*
         * for each bio in rq
         */
-       bvprv = NULL;
        sg = NULL;
        rq_for_each_segment(bvec, rq, iter) {
-               __blk_segment_map_sg(q, bvec, sglist, &bvprv, &sg,
+               __blk_segment_map_sg(q, &bvec, sglist, &bvprv, &sg,
                                     &nsegs, &cluster);
        } /* segments in rq */
 
@@ -223,18 +230,17 @@ EXPORT_SYMBOL(blk_rq_map_sg);
 int blk_bio_map_sg(struct request_queue *q, struct bio *bio,
                   struct scatterlist *sglist)
 {
-       struct bio_vec *bvec, *bvprv;
+       struct bio_vec bvec, bvprv = { NULL };
        struct scatterlist *sg;
        int nsegs, cluster;
-       unsigned long i;
+       struct bvec_iter iter;
 
        nsegs = 0;
        cluster = blk_queue_cluster(q);
 
-       bvprv = NULL;
        sg = NULL;
-       bio_for_each_segment(bvec, bio, i) {
-               __blk_segment_map_sg(q, bvec, sglist, &bvprv, &sg,
+       bio_for_each_segment(bvec, bio, iter) {
+               __blk_segment_map_sg(q, &bvec, sglist, &bvprv, &sg,
                                     &nsegs, &cluster);
        } /* segments in bio */
 
@@ -543,9 +549,9 @@ bool blk_rq_merge_ok(struct request *rq, struct bio *bio)
 
 int blk_try_merge(struct request *rq, struct bio *bio)
 {
-       if (blk_rq_pos(rq) + blk_rq_sectors(rq) == bio->bi_sector)
+       if (blk_rq_pos(rq) + blk_rq_sectors(rq) == bio->bi_iter.bi_sector)
                return ELEVATOR_BACK_MERGE;
-       else if (blk_rq_pos(rq) - bio_sectors(bio) == bio->bi_sector)
+       else if (blk_rq_pos(rq) - bio_sectors(bio) == bio->bi_iter.bi_sector)
                return ELEVATOR_FRONT_MERGE;
        return ELEVATOR_NO_MERGE;
 }
index cdc629cf075b74f27f7801565ec3d90f3e299ce0..3929f43d0b03097b2ee96f23413071b9c466499e 100644 (file)
@@ -202,10 +202,12 @@ static struct request *blk_mq_alloc_request_pinned(struct request_queue *q,
                if (rq) {
                        blk_mq_rq_ctx_init(q, ctx, rq, rw);
                        break;
-               } else if (!(gfp & __GFP_WAIT))
-                       break;
+               }
 
                blk_mq_put_ctx(ctx);
+               if (!(gfp & __GFP_WAIT))
+                       break;
+
                __blk_mq_run_hw_queue(hctx);
                blk_mq_wait_for_tags(hctx->tags);
        } while (1);
@@ -222,7 +224,8 @@ struct request *blk_mq_alloc_request(struct request_queue *q, int rw,
                return NULL;
 
        rq = blk_mq_alloc_request_pinned(q, rw, gfp, reserved);
-       blk_mq_put_ctx(rq->mq_ctx);
+       if (rq)
+               blk_mq_put_ctx(rq->mq_ctx);
        return rq;
 }
 
@@ -235,7 +238,8 @@ struct request *blk_mq_alloc_reserved_request(struct request_queue *q, int rw,
                return NULL;
 
        rq = blk_mq_alloc_request_pinned(q, rw, gfp, true);
-       blk_mq_put_ctx(rq->mq_ctx);
+       if (rq)
+               blk_mq_put_ctx(rq->mq_ctx);
        return rq;
 }
 EXPORT_SYMBOL(blk_mq_alloc_reserved_request);
@@ -301,19 +305,19 @@ void blk_mq_complete_request(struct request *rq, int error)
                struct bio *next = bio->bi_next;
 
                bio->bi_next = NULL;
-               bytes += bio->bi_size;
+               bytes += bio->bi_iter.bi_size;
                blk_mq_bio_endio(rq, bio, error);
                bio = next;
        }
 
        blk_account_io_completion(rq, bytes);
 
+       blk_account_io_done(rq);
+
        if (rq->end_io)
                rq->end_io(rq, error);
        else
                blk_mq_free_request(rq);
-
-       blk_account_io_done(rq);
 }
 
 void __blk_mq_end_io(struct request *rq, int error)
index 06534049afbac1eb9d1c9ba77f7fc8369150a139..1474c3ab7e72cb85698ffe8bb3687df66729281b 100644 (file)
@@ -877,14 +877,14 @@ static bool tg_with_in_bps_limit(struct throtl_grp *tg, struct bio *bio,
        do_div(tmp, HZ);
        bytes_allowed = tmp;
 
-       if (tg->bytes_disp[rw] + bio->bi_size <= bytes_allowed) {
+       if (tg->bytes_disp[rw] + bio->bi_iter.bi_size <= bytes_allowed) {
                if (wait)
                        *wait = 0;
                return 1;
        }
 
        /* Calc approx time to dispatch */
-       extra_bytes = tg->bytes_disp[rw] + bio->bi_size - bytes_allowed;
+       extra_bytes = tg->bytes_disp[rw] + bio->bi_iter.bi_size - bytes_allowed;
        jiffy_wait = div64_u64(extra_bytes * HZ, tg->bps[rw]);
 
        if (!jiffy_wait)
@@ -987,7 +987,7 @@ static void throtl_charge_bio(struct throtl_grp *tg, struct bio *bio)
        bool rw = bio_data_dir(bio);
 
        /* Charge the bio to the group */
-       tg->bytes_disp[rw] += bio->bi_size;
+       tg->bytes_disp[rw] += bio->bi_iter.bi_size;
        tg->io_disp[rw]++;
 
        /*
@@ -1003,8 +1003,8 @@ static void throtl_charge_bio(struct throtl_grp *tg, struct bio *bio)
         */
        if (!(bio->bi_rw & REQ_THROTTLED)) {
                bio->bi_rw |= REQ_THROTTLED;
-               throtl_update_dispatch_stats(tg_to_blkg(tg), bio->bi_size,
-                                            bio->bi_rw);
+               throtl_update_dispatch_stats(tg_to_blkg(tg),
+                                            bio->bi_iter.bi_size, bio->bi_rw);
        }
 }
 
@@ -1303,13 +1303,10 @@ static u64 tg_prfill_cpu_rwstat(struct seq_file *sf,
        return __blkg_prfill_rwstat(sf, pd, &rwstat);
 }
 
-static int tg_print_cpu_rwstat(struct cgroup_subsys_state *css,
-                              struct cftype *cft, struct seq_file *sf)
+static int tg_print_cpu_rwstat(struct seq_file *sf, void *v)
 {
-       struct blkcg *blkcg = css_to_blkcg(css);
-
-       blkcg_print_blkgs(sf, blkcg, tg_prfill_cpu_rwstat, &blkcg_policy_throtl,
-                         cft->private, true);
+       blkcg_print_blkgs(sf, css_to_blkcg(seq_css(sf)), tg_prfill_cpu_rwstat,
+                         &blkcg_policy_throtl, seq_cft(sf)->private, true);
        return 0;
 }
 
@@ -1335,19 +1332,17 @@ static u64 tg_prfill_conf_uint(struct seq_file *sf, struct blkg_policy_data *pd,
        return __blkg_prfill_u64(sf, pd, v);
 }
 
-static int tg_print_conf_u64(struct cgroup_subsys_state *css,
-                            struct cftype *cft, struct seq_file *sf)
+static int tg_print_conf_u64(struct seq_file *sf, void *v)
 {
-       blkcg_print_blkgs(sf, css_to_blkcg(css), tg_prfill_conf_u64,
-                         &blkcg_policy_throtl, cft->private, false);
+       blkcg_print_blkgs(sf, css_to_blkcg(seq_css(sf)), tg_prfill_conf_u64,
+                         &blkcg_policy_throtl, seq_cft(sf)->private, false);
        return 0;
 }
 
-static int tg_print_conf_uint(struct cgroup_subsys_state *css,
-                             struct cftype *cft, struct seq_file *sf)
+static int tg_print_conf_uint(struct seq_file *sf, void *v)
 {
-       blkcg_print_blkgs(sf, css_to_blkcg(css), tg_prfill_conf_uint,
-                         &blkcg_policy_throtl, cft->private, false);
+       blkcg_print_blkgs(sf, css_to_blkcg(seq_css(sf)), tg_prfill_conf_uint,
+                         &blkcg_policy_throtl, seq_cft(sf)->private, false);
        return 0;
 }
 
@@ -1428,40 +1423,40 @@ static struct cftype throtl_files[] = {
        {
                .name = "throttle.read_bps_device",
                .private = offsetof(struct throtl_grp, bps[READ]),
-               .read_seq_string = tg_print_conf_u64,
+               .seq_show = tg_print_conf_u64,
                .write_string = tg_set_conf_u64,
                .max_write_len = 256,
        },
        {
                .name = "throttle.write_bps_device",
                .private = offsetof(struct throtl_grp, bps[WRITE]),
-               .read_seq_string = tg_print_conf_u64,
+               .seq_show = tg_print_conf_u64,
                .write_string = tg_set_conf_u64,
                .max_write_len = 256,
        },
        {
                .name = "throttle.read_iops_device",
                .private = offsetof(struct throtl_grp, iops[READ]),
-               .read_seq_string = tg_print_conf_uint,
+               .seq_show = tg_print_conf_uint,
                .write_string = tg_set_conf_uint,
                .max_write_len = 256,
        },
        {
                .name = "throttle.write_iops_device",
                .private = offsetof(struct throtl_grp, iops[WRITE]),
-               .read_seq_string = tg_print_conf_uint,
+               .seq_show = tg_print_conf_uint,
                .write_string = tg_set_conf_uint,
                .max_write_len = 256,
        },
        {
                .name = "throttle.io_service_bytes",
                .private = offsetof(struct tg_stats_cpu, service_bytes),
-               .read_seq_string = tg_print_cpu_rwstat,
+               .seq_show = tg_print_cpu_rwstat,
        },
        {
                .name = "throttle.io_serviced",
                .private = offsetof(struct tg_stats_cpu, serviced),
-               .read_seq_string = tg_print_cpu_rwstat,
+               .seq_show = tg_print_cpu_rwstat,
        },
        { }     /* terminate */
 };
@@ -1508,7 +1503,7 @@ bool blk_throtl_bio(struct request_queue *q, struct bio *bio)
        if (tg) {
                if (!tg->has_rules[rw]) {
                        throtl_update_dispatch_stats(tg_to_blkg(tg),
-                                                    bio->bi_size, bio->bi_rw);
+                                       bio->bi_iter.bi_size, bio->bi_rw);
                        goto out_unlock_rcu;
                }
        }
@@ -1564,7 +1559,7 @@ bool blk_throtl_bio(struct request_queue *q, struct bio *bio)
        /* out-of-limit, queue to @tg */
        throtl_log(sq, "[%c] bio. bdisp=%llu sz=%u bps=%llu iodisp=%u iops=%u queued=%d/%d",
                   rw == READ ? 'R' : 'W',
-                  tg->bytes_disp[rw], bio->bi_size, tg->bps[rw],
+                  tg->bytes_disp[rw], bio->bi_iter.bi_size, tg->bps[rw],
                   tg->io_disp[rw], tg->iops[rw],
                   sq->nr_queued[READ], sq->nr_queued[WRITE]);
 
index 4d5cec1ad80d3e64314f43a84577a79d9e5d2506..744833b630c69c5b56c98c81e76c21b774be29ad 100644 (file)
@@ -1632,11 +1632,11 @@ static u64 cfqg_prfill_weight_device(struct seq_file *sf,
        return __blkg_prfill_u64(sf, pd, cfqg->dev_weight);
 }
 
-static int cfqg_print_weight_device(struct cgroup_subsys_state *css,
-                                   struct cftype *cft, struct seq_file *sf)
+static int cfqg_print_weight_device(struct seq_file *sf, void *v)
 {
-       blkcg_print_blkgs(sf, css_to_blkcg(css), cfqg_prfill_weight_device,
-                         &blkcg_policy_cfq, 0, false);
+       blkcg_print_blkgs(sf, css_to_blkcg(seq_css(sf)),
+                         cfqg_prfill_weight_device, &blkcg_policy_cfq,
+                         0, false);
        return 0;
 }
 
@@ -1650,26 +1650,23 @@ static u64 cfqg_prfill_leaf_weight_device(struct seq_file *sf,
        return __blkg_prfill_u64(sf, pd, cfqg->dev_leaf_weight);
 }
 
-static int cfqg_print_leaf_weight_device(struct cgroup_subsys_state *css,
-                                        struct cftype *cft,
-                                        struct seq_file *sf)
+static int cfqg_print_leaf_weight_device(struct seq_file *sf, void *v)
 {
-       blkcg_print_blkgs(sf, css_to_blkcg(css), cfqg_prfill_leaf_weight_device,
-                         &blkcg_policy_cfq, 0, false);
+       blkcg_print_blkgs(sf, css_to_blkcg(seq_css(sf)),
+                         cfqg_prfill_leaf_weight_device, &blkcg_policy_cfq,
+                         0, false);
        return 0;
 }
 
-static int cfq_print_weight(struct cgroup_subsys_state *css, struct cftype *cft,
-                           struct seq_file *sf)
+static int cfq_print_weight(struct seq_file *sf, void *v)
 {
-       seq_printf(sf, "%u\n", css_to_blkcg(css)->cfq_weight);
+       seq_printf(sf, "%u\n", css_to_blkcg(seq_css(sf))->cfq_weight);
        return 0;
 }
 
-static int cfq_print_leaf_weight(struct cgroup_subsys_state *css,
-                                struct cftype *cft, struct seq_file *sf)
+static int cfq_print_leaf_weight(struct seq_file *sf, void *v)
 {
-       seq_printf(sf, "%u\n", css_to_blkcg(css)->cfq_leaf_weight);
+       seq_printf(sf, "%u\n", css_to_blkcg(seq_css(sf))->cfq_leaf_weight);
        return 0;
 }
 
@@ -1762,23 +1759,17 @@ static int cfq_set_leaf_weight(struct cgroup_subsys_state *css,
        return __cfq_set_weight(css, cft, val, true);
 }
 
-static int cfqg_print_stat(struct cgroup_subsys_state *css, struct cftype *cft,
-                          struct seq_file *sf)
+static int cfqg_print_stat(struct seq_file *sf, void *v)
 {
-       struct blkcg *blkcg = css_to_blkcg(css);
-
-       blkcg_print_blkgs(sf, blkcg, blkg_prfill_stat, &blkcg_policy_cfq,
-                         cft->private, false);
+       blkcg_print_blkgs(sf, css_to_blkcg(seq_css(sf)), blkg_prfill_stat,
+                         &blkcg_policy_cfq, seq_cft(sf)->private, false);
        return 0;
 }
 
-static int cfqg_print_rwstat(struct cgroup_subsys_state *css,
-                            struct cftype *cft, struct seq_file *sf)
+static int cfqg_print_rwstat(struct seq_file *sf, void *v)
 {
-       struct blkcg *blkcg = css_to_blkcg(css);
-
-       blkcg_print_blkgs(sf, blkcg, blkg_prfill_rwstat, &blkcg_policy_cfq,
-                         cft->private, true);
+       blkcg_print_blkgs(sf, css_to_blkcg(seq_css(sf)), blkg_prfill_rwstat,
+                         &blkcg_policy_cfq, seq_cft(sf)->private, true);
        return 0;
 }
 
@@ -1798,23 +1789,19 @@ static u64 cfqg_prfill_rwstat_recursive(struct seq_file *sf,
        return __blkg_prfill_rwstat(sf, pd, &sum);
 }
 
-static int cfqg_print_stat_recursive(struct cgroup_subsys_state *css,
-                                    struct cftype *cft, struct seq_file *sf)
+static int cfqg_print_stat_recursive(struct seq_file *sf, void *v)
 {
-       struct blkcg *blkcg = css_to_blkcg(css);
-
-       blkcg_print_blkgs(sf, blkcg, cfqg_prfill_stat_recursive,
-                         &blkcg_policy_cfq, cft->private, false);
+       blkcg_print_blkgs(sf, css_to_blkcg(seq_css(sf)),
+                         cfqg_prfill_stat_recursive, &blkcg_policy_cfq,
+                         seq_cft(sf)->private, false);
        return 0;
 }
 
-static int cfqg_print_rwstat_recursive(struct cgroup_subsys_state *css,
-                                      struct cftype *cft, struct seq_file *sf)
+static int cfqg_print_rwstat_recursive(struct seq_file *sf, void *v)
 {
-       struct blkcg *blkcg = css_to_blkcg(css);
-
-       blkcg_print_blkgs(sf, blkcg, cfqg_prfill_rwstat_recursive,
-                         &blkcg_policy_cfq, cft->private, true);
+       blkcg_print_blkgs(sf, css_to_blkcg(seq_css(sf)),
+                         cfqg_prfill_rwstat_recursive, &blkcg_policy_cfq,
+                         seq_cft(sf)->private, true);
        return 0;
 }
 
@@ -1835,13 +1822,11 @@ static u64 cfqg_prfill_avg_queue_size(struct seq_file *sf,
 }
 
 /* print avg_queue_size */
-static int cfqg_print_avg_queue_size(struct cgroup_subsys_state *css,
-                                    struct cftype *cft, struct seq_file *sf)
+static int cfqg_print_avg_queue_size(struct seq_file *sf, void *v)
 {
-       struct blkcg *blkcg = css_to_blkcg(css);
-
-       blkcg_print_blkgs(sf, blkcg, cfqg_prfill_avg_queue_size,
-                         &blkcg_policy_cfq, 0, false);
+       blkcg_print_blkgs(sf, css_to_blkcg(seq_css(sf)),
+                         cfqg_prfill_avg_queue_size, &blkcg_policy_cfq,
+                         0, false);
        return 0;
 }
 #endif /* CONFIG_DEBUG_BLK_CGROUP */
@@ -1851,14 +1836,14 @@ static struct cftype cfq_blkcg_files[] = {
        {
                .name = "weight_device",
                .flags = CFTYPE_ONLY_ON_ROOT,
-               .read_seq_string = cfqg_print_leaf_weight_device,
+               .seq_show = cfqg_print_leaf_weight_device,
                .write_string = cfqg_set_leaf_weight_device,
                .max_write_len = 256,
        },
        {
                .name = "weight",
                .flags = CFTYPE_ONLY_ON_ROOT,
-               .read_seq_string = cfq_print_leaf_weight,
+               .seq_show = cfq_print_leaf_weight,
                .write_u64 = cfq_set_leaf_weight,
        },
 
@@ -1866,26 +1851,26 @@ static struct cftype cfq_blkcg_files[] = {
        {
                .name = "weight_device",
                .flags = CFTYPE_NOT_ON_ROOT,
-               .read_seq_string = cfqg_print_weight_device,
+               .seq_show = cfqg_print_weight_device,
                .write_string = cfqg_set_weight_device,
                .max_write_len = 256,
        },
        {
                .name = "weight",
                .flags = CFTYPE_NOT_ON_ROOT,
-               .read_seq_string = cfq_print_weight,
+               .seq_show = cfq_print_weight,
                .write_u64 = cfq_set_weight,
        },
 
        {
                .name = "leaf_weight_device",
-               .read_seq_string = cfqg_print_leaf_weight_device,
+               .seq_show = cfqg_print_leaf_weight_device,
                .write_string = cfqg_set_leaf_weight_device,
                .max_write_len = 256,
        },
        {
                .name = "leaf_weight",
-               .read_seq_string = cfq_print_leaf_weight,
+               .seq_show = cfq_print_leaf_weight,
                .write_u64 = cfq_set_leaf_weight,
        },
 
@@ -1893,114 +1878,114 @@ static struct cftype cfq_blkcg_files[] = {
        {
                .name = "time",
                .private = offsetof(struct cfq_group, stats.time),
-               .read_seq_string = cfqg_print_stat,
+               .seq_show = cfqg_print_stat,
        },
        {
                .name = "sectors",
                .private = offsetof(struct cfq_group, stats.sectors),
-               .read_seq_string = cfqg_print_stat,
+               .seq_show = cfqg_print_stat,
        },
        {
                .name = "io_service_bytes",
                .private = offsetof(struct cfq_group, stats.service_bytes),
-               .read_seq_string = cfqg_print_rwstat,
+               .seq_show = cfqg_print_rwstat,
        },
        {
                .name = "io_serviced",
                .private = offsetof(struct cfq_group, stats.serviced),
-               .read_seq_string = cfqg_print_rwstat,
+               .seq_show = cfqg_print_rwstat,
        },
        {
                .name = "io_service_time",
                .private = offsetof(struct cfq_group, stats.service_time),
-               .read_seq_string = cfqg_print_rwstat,
+               .seq_show = cfqg_print_rwstat,
        },
        {
                .name = "io_wait_time",
                .private = offsetof(struct cfq_group, stats.wait_time),
-               .read_seq_string = cfqg_print_rwstat,
+               .seq_show = cfqg_print_rwstat,
        },
        {
                .name = "io_merged",
                .private = offsetof(struct cfq_group, stats.merged),
-               .read_seq_string = cfqg_print_rwstat,
+               .seq_show = cfqg_print_rwstat,
        },
        {
                .name = "io_queued",
                .private = offsetof(struct cfq_group, stats.queued),
-               .read_seq_string = cfqg_print_rwstat,
+               .seq_show = cfqg_print_rwstat,
        },
 
        /* the same statictics which cover the cfqg and its descendants */
        {
                .name = "time_recursive",
                .private = offsetof(struct cfq_group, stats.time),
-               .read_seq_string = cfqg_print_stat_recursive,
+               .seq_show = cfqg_print_stat_recursive,
        },
        {
                .name = "sectors_recursive",
                .private = offsetof(struct cfq_group, stats.sectors),
-               .read_seq_string = cfqg_print_stat_recursive,
+               .seq_show = cfqg_print_stat_recursive,
        },
        {
                .name = "io_service_bytes_recursive",
                .private = offsetof(struct cfq_group, stats.service_bytes),
-               .read_seq_string = cfqg_print_rwstat_recursive,
+               .seq_show = cfqg_print_rwstat_recursive,
        },
        {
                .name = "io_serviced_recursive",
                .private = offsetof(struct cfq_group, stats.serviced),
-               .read_seq_string = cfqg_print_rwstat_recursive,
+               .seq_show = cfqg_print_rwstat_recursive,
        },
        {
                .name = "io_service_time_recursive",
                .private = offsetof(struct cfq_group, stats.service_time),
-               .read_seq_string = cfqg_print_rwstat_recursive,
+               .seq_show = cfqg_print_rwstat_recursive,
        },
        {
                .name = "io_wait_time_recursive",
                .private = offsetof(struct cfq_group, stats.wait_time),
-               .read_seq_string = cfqg_print_rwstat_recursive,
+               .seq_show = cfqg_print_rwstat_recursive,
        },
        {
                .name = "io_merged_recursive",
                .private = offsetof(struct cfq_group, stats.merged),
-               .read_seq_string = cfqg_print_rwstat_recursive,
+               .seq_show = cfqg_print_rwstat_recursive,
        },
        {
                .name = "io_queued_recursive",
                .private = offsetof(struct cfq_group, stats.queued),
-               .read_seq_string = cfqg_print_rwstat_recursive,
+               .seq_show = cfqg_print_rwstat_recursive,
        },
 #ifdef CONFIG_DEBUG_BLK_CGROUP
        {
                .name = "avg_queue_size",
-               .read_seq_string = cfqg_print_avg_queue_size,
+               .seq_show = cfqg_print_avg_queue_size,
        },
        {
                .name = "group_wait_time",
                .private = offsetof(struct cfq_group, stats.group_wait_time),
-               .read_seq_string = cfqg_print_stat,
+               .seq_show = cfqg_print_stat,
        },
        {
                .name = "idle_time",
                .private = offsetof(struct cfq_group, stats.idle_time),
-               .read_seq_string = cfqg_print_stat,
+               .seq_show = cfqg_print_stat,
        },
        {
                .name = "empty_time",
                .private = offsetof(struct cfq_group, stats.empty_time),
-               .read_seq_string = cfqg_print_stat,
+               .seq_show = cfqg_print_stat,
        },
        {
                .name = "dequeue",
                .private = offsetof(struct cfq_group, stats.dequeue),
-               .read_seq_string = cfqg_print_stat,
+               .seq_show = cfqg_print_stat,
        },
        {
                .name = "unaccounted_time",
                .private = offsetof(struct cfq_group, stats.unaccounted_time),
-               .read_seq_string = cfqg_print_stat,
+               .seq_show = cfqg_print_stat,
        },
 #endif /* CONFIG_DEBUG_BLK_CGROUP */
        { }     /* terminate */
index b7ff2861b6bdc0bd8e57528ac776fc9b923b5c70..42c45a7d67144a5598f5d7b2242a63eb9d58e292 100644 (file)
@@ -440,7 +440,7 @@ int elv_merge(struct request_queue *q, struct request **req, struct bio *bio)
        /*
         * See if our hash lookup can find a potential backmerge.
         */
-       __rq = elv_rqhash_find(q, bio->bi_sector);
+       __rq = elv_rqhash_find(q, bio->bi_iter.bi_sector);
        if (__rq && elv_rq_merge_ok(__rq, bio)) {
                *req = __rq;
                return ELEVATOR_BACK_MERGE;
index 989c510da8cc98af911976874d6c16db865ee1b3..b29402a7b9b581227e57f68e362b474350fd0da4 100644 (file)
@@ -2,11 +2,6 @@
 # Cryptographic API
 #
 
-# memneq MUST be built with -Os or -O0 to prevent early-return optimizations
-# that will defeat memneq's actual purpose to prevent timing attacks.
-CFLAGS_REMOVE_memneq.o := -O1 -O2 -O3
-CFLAGS_memneq.o := -Os
-
 obj-$(CONFIG_CRYPTO) += crypto.o
 crypto-y := api.o cipher.o compress.o memneq.o
 
index ef5356cd280a54c086e4f8ff964245e38748a391..850246206b1258a697f83e86c39acc9b0a17f973 100644 (file)
@@ -114,6 +114,9 @@ static ssize_t hash_sendpage(struct socket *sock, struct page *page,
        struct hash_ctx *ctx = ask->private;
        int err;
 
+       if (flags & MSG_SENDPAGE_NOTLAST)
+               flags |= MSG_MORE;
+
        lock_sock(sk);
        sg_init_table(ctx->sgl.sg, 1);
        sg_set_page(ctx->sgl.sg, page, size, offset);
index 6a6dfc062d2a47f04449fbb0e1c3f3852be337dc..a19c027b29bde504ac8eae4b4572947a69ed2335 100644 (file)
@@ -378,6 +378,9 @@ static ssize_t skcipher_sendpage(struct socket *sock, struct page *page,
        struct skcipher_sg_list *sgl;
        int err = -EINVAL;
 
+       if (flags & MSG_SENDPAGE_NOTLAST)
+               flags |= MSG_MORE;
+
        lock_sock(sk);
        if (!ctx->more && ctx->used)
                goto unlock;
index 1875e7026e8f7fad661e2051cdc139f733d6c19a..e1223559d5dfd233cbc15184c9dc607fb34fae2e 100644 (file)
@@ -380,9 +380,10 @@ static void crypto_authenc_encrypt_done(struct crypto_async_request *req,
        if (!err) {
                struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
                struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
-               struct ablkcipher_request *abreq = aead_request_ctx(areq);
-               u8 *iv = (u8 *)(abreq + 1) +
-                        crypto_ablkcipher_reqsize(ctx->enc);
+               struct authenc_request_ctx *areq_ctx = aead_request_ctx(areq);
+               struct ablkcipher_request *abreq = (void *)(areq_ctx->tail
+                                                           + ctx->reqoff);
+               u8 *iv = (u8 *)abreq - crypto_ablkcipher_ivsize(ctx->enc);
 
                err = crypto_authenc_genicv(areq, iv, 0);
        }
index 3e05499d183aa8e49d41b83be448e7f52d76b10c..1df84217f7c9320dbfc5174f91ce394667c36447 100644 (file)
@@ -271,7 +271,8 @@ static int crypto_ccm_auth(struct aead_request *req, struct scatterlist *plain,
        }
 
        /* compute plaintext into mac */
-       get_data_to_compute(cipher, pctx, plain, cryptlen);
+       if (cryptlen)
+               get_data_to_compute(cipher, pctx, plain, cryptlen);
 
 out:
        return err;
index cd0162221c141855fcaf1920ceb9466a6baf875a..afed1bd16aee0b53f63a4bdc11aecab56927821d 100644 (file)
@@ -72,6 +72,7 @@ __crypto_memneq_generic(const void *a, const void *b, size_t size)
 #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
        while (size >= sizeof(unsigned long)) {
                neq |= *(unsigned long *)a ^ *(unsigned long *)b;
+               OPTIMIZER_HIDE_VAR(neq);
                a += sizeof(unsigned long);
                b += sizeof(unsigned long);
                size -= sizeof(unsigned long);
@@ -79,6 +80,7 @@ __crypto_memneq_generic(const void *a, const void *b, size_t size)
 #endif /* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS */
        while (size > 0) {
                neq |= *(unsigned char *)a ^ *(unsigned char *)b;
+               OPTIMIZER_HIDE_VAR(neq);
                a += 1;
                b += 1;
                size -= 1;
@@ -89,33 +91,61 @@ __crypto_memneq_generic(const void *a, const void *b, size_t size)
 /* Loop-free fast-path for frequently used 16-byte size */
 static inline unsigned long __crypto_memneq_16(const void *a, const void *b)
 {
+       unsigned long neq = 0;
+
 #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
-       if (sizeof(unsigned long) == 8)
-               return ((*(unsigned long *)(a)   ^ *(unsigned long *)(b))
-                     | (*(unsigned long *)(a+8) ^ *(unsigned long *)(b+8)));
-       else if (sizeof(unsigned int) == 4)
-               return ((*(unsigned int *)(a)    ^ *(unsigned int *)(b))
-                      | (*(unsigned int *)(a+4)  ^ *(unsigned int *)(b+4))
-                     | (*(unsigned int *)(a+8)  ^ *(unsigned int *)(b+8))
-                     | (*(unsigned int *)(a+12) ^ *(unsigned int *)(b+12)));
-       else
+       if (sizeof(unsigned long) == 8) {
+               neq |= *(unsigned long *)(a)   ^ *(unsigned long *)(b);
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= *(unsigned long *)(a+8) ^ *(unsigned long *)(b+8);
+               OPTIMIZER_HIDE_VAR(neq);
+       } else if (sizeof(unsigned int) == 4) {
+               neq |= *(unsigned int *)(a)    ^ *(unsigned int *)(b);
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= *(unsigned int *)(a+4)  ^ *(unsigned int *)(b+4);
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= *(unsigned int *)(a+8)  ^ *(unsigned int *)(b+8);
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= *(unsigned int *)(a+12) ^ *(unsigned int *)(b+12);
+               OPTIMIZER_HIDE_VAR(neq);
+       } else
 #endif /* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS */
-               return ((*(unsigned char *)(a)    ^ *(unsigned char *)(b))
-                     | (*(unsigned char *)(a+1)  ^ *(unsigned char *)(b+1))
-                     | (*(unsigned char *)(a+2)  ^ *(unsigned char *)(b+2))
-                     | (*(unsigned char *)(a+3)  ^ *(unsigned char *)(b+3))
-                     | (*(unsigned char *)(a+4)  ^ *(unsigned char *)(b+4))
-                     | (*(unsigned char *)(a+5)  ^ *(unsigned char *)(b+5))
-                     | (*(unsigned char *)(a+6)  ^ *(unsigned char *)(b+6))
-                     | (*(unsigned char *)(a+7)  ^ *(unsigned char *)(b+7))
-                     | (*(unsigned char *)(a+8)  ^ *(unsigned char *)(b+8))
-                     | (*(unsigned char *)(a+9)  ^ *(unsigned char *)(b+9))
-                     | (*(unsigned char *)(a+10) ^ *(unsigned char *)(b+10))
-                     | (*(unsigned char *)(a+11) ^ *(unsigned char *)(b+11))
-                     | (*(unsigned char *)(a+12) ^ *(unsigned char *)(b+12))
-                     | (*(unsigned char *)(a+13) ^ *(unsigned char *)(b+13))
-                     | (*(unsigned char *)(a+14) ^ *(unsigned char *)(b+14))
-                     | (*(unsigned char *)(a+15) ^ *(unsigned char *)(b+15)));
+       {
+               neq |= *(unsigned char *)(a)    ^ *(unsigned char *)(b);
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= *(unsigned char *)(a+1)  ^ *(unsigned char *)(b+1);
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= *(unsigned char *)(a+2)  ^ *(unsigned char *)(b+2);
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= *(unsigned char *)(a+3)  ^ *(unsigned char *)(b+3);
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= *(unsigned char *)(a+4)  ^ *(unsigned char *)(b+4);
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= *(unsigned char *)(a+5)  ^ *(unsigned char *)(b+5);
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= *(unsigned char *)(a+6)  ^ *(unsigned char *)(b+6);
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= *(unsigned char *)(a+7)  ^ *(unsigned char *)(b+7);
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= *(unsigned char *)(a+8)  ^ *(unsigned char *)(b+8);
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= *(unsigned char *)(a+9)  ^ *(unsigned char *)(b+9);
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= *(unsigned char *)(a+10) ^ *(unsigned char *)(b+10);
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= *(unsigned char *)(a+11) ^ *(unsigned char *)(b+11);
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= *(unsigned char *)(a+12) ^ *(unsigned char *)(b+12);
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= *(unsigned char *)(a+13) ^ *(unsigned char *)(b+13);
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= *(unsigned char *)(a+14) ^ *(unsigned char *)(b+14);
+               OPTIMIZER_HIDE_VAR(neq);
+               neq |= *(unsigned char *)(a+15) ^ *(unsigned char *)(b+15);
+               OPTIMIZER_HIDE_VAR(neq);
+       }
+
+       return neq;
 }
 
 /* Compare two areas of memory without leaking timing information,
index f8c920cafe639c8451349e15b3f1e22e19da80e4..309d345ead9582896bde8c5f5c170bf5d0315f66 100644 (file)
@@ -78,7 +78,7 @@ static int pcrypt_do_parallel(struct padata_priv *padata, unsigned int *cb_cpu,
        cpu = *cb_cpu;
 
        rcu_read_lock_bh();
-       cpumask = rcu_dereference(pcrypt->cb_cpumask);
+       cpumask = rcu_dereference_bh(pcrypt->cb_cpumask);
        if (cpumask_test_cpu(cpu, cpumask->mask))
                        goto out;
 
index 1ab8258fcf560735237a198b2037c102e229d20b..001f07cdb828d59101521162109b9f101c34a319 100644 (file)
@@ -1242,6 +1242,10 @@ static int do_test(int m)
                ret += tcrypt_test("cmac(des3_ede)");
                break;
 
+       case 155:
+               ret += tcrypt_test("authenc(hmac(sha1),cbc(aes))");
+               break;
+
        case 200:
                test_cipher_speed("ecb(aes)", ENCRYPT, sec, NULL, 0,
                                speed_template_16_24_32);
index 432afc03e7c3f9c1040ac54033950eb9e17c0727..77955507f6f1f73a044554a7d738074c98f9829e 100644 (file)
@@ -503,16 +503,16 @@ static int __test_aead(struct crypto_aead *tfm, int enc,
                                goto out;
                        }
 
-                       sg_init_one(&sg[0], input,
-                                   template[i].ilen + (enc ? authsize : 0));
-
                        if (diff_dst) {
                                output = xoutbuf[0];
                                output += align_offset;
+                               sg_init_one(&sg[0], input, template[i].ilen);
                                sg_init_one(&sgout[0], output,
+                                           template[i].rlen);
+                       } else {
+                               sg_init_one(&sg[0], input,
                                            template[i].ilen +
                                                (enc ? authsize : 0));
-                       } else {
                                output = input;
                        }
 
@@ -612,12 +612,6 @@ static int __test_aead(struct crypto_aead *tfm, int enc,
                                memcpy(q, template[i].input + temp,
                                       template[i].tap[k]);
 
-                               n = template[i].tap[k];
-                               if (k == template[i].np - 1 && enc)
-                                       n += authsize;
-                               if (offset_in_page(q) + n < PAGE_SIZE)
-                                       q[n] = 0;
-
                                sg_set_buf(&sg[k], q, template[i].tap[k]);
 
                                if (diff_dst) {
@@ -625,13 +619,17 @@ static int __test_aead(struct crypto_aead *tfm, int enc,
                                            offset_in_page(IDX[k]);
 
                                        memset(q, 0, template[i].tap[k]);
-                                       if (offset_in_page(q) + n < PAGE_SIZE)
-                                               q[n] = 0;
 
                                        sg_set_buf(&sgout[k], q,
                                                   template[i].tap[k]);
                                }
 
+                               n = template[i].tap[k];
+                               if (k == template[i].np - 1 && enc)
+                                       n += authsize;
+                               if (offset_in_page(q) + n < PAGE_SIZE)
+                                       q[n] = 0;
+
                                temp += template[i].tap[k];
                        }
 
@@ -650,10 +648,10 @@ static int __test_aead(struct crypto_aead *tfm, int enc,
                                        goto out;
                                }
 
-                               sg[k - 1].length += authsize;
-
                                if (diff_dst)
                                        sgout[k - 1].length += authsize;
+                               else
+                                       sg[k - 1].length += authsize;
                        }
 
                        sg_init_table(asg, template[i].anp);
index 3cc8214f9b26630e86eddcb37ac35f7a5f57e4a1..8e3b8b06c0b2e26a90308b9f15457bfa9da06b13 100644 (file)
@@ -118,7 +118,7 @@ obj-$(CONFIG_SGI_SN)                += sn/
 obj-y                          += firmware/
 obj-$(CONFIG_CRYPTO)           += crypto/
 obj-$(CONFIG_SUPERH)           += sh/
-obj-$(CONFIG_ARCH_SHMOBILE)    += sh/
+obj-$(CONFIG_ARCH_SHMOBILE_LEGACY)     += sh/
 ifndef CONFIG_ARCH_USES_GETTIMEOFFSET
 obj-y                          += clocksource/
 endif
index 8711e3797165fa73fd0c401cedbb54c61eb68e4a..8095943e6e112da4b0dd3e77b92e331270624020 100644 (file)
@@ -32,8 +32,7 @@
 #include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/power_supply.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
 
 #define PREFIX "ACPI: "
 
index a6869e110ce5650a86b6f666bc28347031c16275..2635a01c5b3edc077eb80a704db6e316b2395857 100644 (file)
@@ -9,7 +9,6 @@
 
 #include <linux/module.h>
 #include <linux/acpi.h>
-#include <acpi/acpi_bus.h>
 #include <linux/cper.h>
 #include <linux/ratelimit.h>
 #include <asm/cpu.h>
index 6745fe137b9ea541ae729429035eaeca8fc8fc07..e603905973721c415a912c04e2c7f3926fcd5634 100644 (file)
@@ -162,6 +162,7 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = {
        { "80860F14", (unsigned long)&byt_sdio_dev_desc },
        { "80860F41", (unsigned long)&byt_i2c_dev_desc },
        { "INT33B2", },
+       { "INT33FC", },
 
        { "INT3430", (unsigned long)&lpt_dev_desc },
        { "INT3431", (unsigned long)&lpt_dev_desc },
index 551dad712ffec451364a08c01487a1987c10d7db..9aeacdfca4106ac8376d74d049293bd26d4e3075 100644 (file)
@@ -180,14 +180,14 @@ static unsigned long acpi_meminfo_end_pfn(struct acpi_memory_info *info)
 
 static int acpi_bind_memblk(struct memory_block *mem, void *arg)
 {
-       return acpi_bind_one(&mem->dev, (acpi_handle)arg);
+       return acpi_bind_one(&mem->dev, arg);
 }
 
 static int acpi_bind_memory_blocks(struct acpi_memory_info *info,
-                                  acpi_handle handle)
+                                  struct acpi_device *adev)
 {
        return walk_memory_range(acpi_meminfo_start_pfn(info),
-                                acpi_meminfo_end_pfn(info), (void *)handle,
+                                acpi_meminfo_end_pfn(info), adev,
                                 acpi_bind_memblk);
 }
 
@@ -197,8 +197,7 @@ static int acpi_unbind_memblk(struct memory_block *mem, void *arg)
        return 0;
 }
 
-static void acpi_unbind_memory_blocks(struct acpi_memory_info *info,
-                                     acpi_handle handle)
+static void acpi_unbind_memory_blocks(struct acpi_memory_info *info)
 {
        walk_memory_range(acpi_meminfo_start_pfn(info),
                          acpi_meminfo_end_pfn(info), NULL, acpi_unbind_memblk);
@@ -242,9 +241,9 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
                if (result && result != -EEXIST)
                        continue;
 
-               result = acpi_bind_memory_blocks(info, handle);
+               result = acpi_bind_memory_blocks(info, mem_device->device);
                if (result) {
-                       acpi_unbind_memory_blocks(info, handle);
+                       acpi_unbind_memory_blocks(info);
                        return -ENODEV;
                }
 
@@ -285,7 +284,7 @@ static void acpi_memory_remove_memory(struct acpi_memory_device *mem_device)
                if (nid == NUMA_NO_NODE)
                        nid = memory_add_physaddr_to_nid(info->start_addr);
 
-               acpi_unbind_memory_blocks(info, handle);
+               acpi_unbind_memory_blocks(info);
                remove_memory(nid, info->start_addr, info->length);
                list_del(&info->list);
                kfree(info);
index fc6008fbce35bd99f390d15af6e7471b1ca0438a..65610c0e7243d3d9cd4f8e5d757ca9d602b94816 100644 (file)
@@ -28,8 +28,7 @@
 #include <linux/cpu.h>
 #include <linux/clockchips.h>
 #include <linux/slab.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
 #include <asm/mwait.h>
 
 #define ACPI_PROCESSOR_AGGREGATOR_CLASS        "acpi_pad"
index 3c1d6b0c09a4b7d1eeeb9347a7c743d1c7487988..d58a2aba09308a31fd6f80355bba51fb6df6724f 100644 (file)
@@ -395,7 +395,7 @@ static int acpi_processor_add(struct acpi_device *device,
                goto err;
        }
 
-       result = acpi_bind_one(dev, pr->handle);
+       result = acpi_bind_one(dev, device);
        if (result)
                goto err;
 
index fb57d03e698bd3b7ae2d4194d69dc3478ca09025..ca0c6d7ec0d4181cfdd3fa9b91547a84cd545e2f 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/nmi.h>
 #include <linux/delay.h>
 #include <linux/mm.h>
-#include <acpi/acpi.h>
 
 #include "apei-internal.h"
 
index fbf1aceda8b8ab915a7d2476d78db2b6e2b94e68..e90ef8b96f266086ade6178162d3f87e2b3f6aa1 100644 (file)
@@ -36,8 +36,7 @@
 #include <linux/suspend.h>
 #include <asm/unaligned.h>
 
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
 #include <linux/power_supply.h>
 
 #define PREFIX "ACPI: "
index 078c4f7fe2dd97c42d3e13ea11ebde804e3ae4f0..05ee8f61bfb59d8a53d75347d468eb9d56bc463c 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/acpi.h>
-#include <acpi/acpi_bus.h>
 #include <linux/dmi.h>
 
 #include "internal.h"
index bba9b72e25f8235e6d12593bdd16bb378c7af25a..2c38ae22c17f1dad8283f4c6aa03b365a0232a69 100644 (file)
@@ -37,8 +37,6 @@
 #include <asm/mpspec.h>
 #endif
 #include <linux/pci.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
 #include <acpi/apei.h>
 #include <linux/dmi.h>
 #include <linux/suspend.h>
@@ -52,9 +50,6 @@ struct acpi_device *acpi_root;
 struct proc_dir_entry *acpi_root_dir;
 EXPORT_SYMBOL(acpi_root_dir);
 
-#define STRUCT_TO_INT(s)       (*((int*)&s))
-
-
 #ifdef CONFIG_X86
 static int set_copy_dsdt(const struct dmi_system_id *id)
 {
@@ -115,18 +110,16 @@ int acpi_bus_get_status(struct acpi_device *device)
        if (ACPI_FAILURE(status))
                return -ENODEV;
 
-       STRUCT_TO_INT(device->status) = (int) sta;
+       acpi_set_device_status(device, sta);
 
        if (device->status.functional && !device->status.present) {
                ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]: "
                       "functional but not present;\n",
-                       device->pnp.bus_id,
-                       (u32) STRUCT_TO_INT(device->status)));
+                       device->pnp.bus_id, (u32)sta));
        }
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]\n",
-                         device->pnp.bus_id,
-                         (u32) STRUCT_TO_INT(device->status)));
+                         device->pnp.bus_id, (u32)sta));
        return 0;
 }
 EXPORT_SYMBOL(acpi_bus_get_status);
@@ -329,58 +322,6 @@ static void acpi_bus_osc_support(void)
                              Notification Handling
    -------------------------------------------------------------------------- */
 
-static void acpi_bus_check_device(acpi_handle handle)
-{
-       struct acpi_device *device;
-       acpi_status status;
-       struct acpi_device_status old_status;
-
-       if (acpi_bus_get_device(handle, &device))
-               return;
-       if (!device)
-               return;
-
-       old_status = device->status;
-
-       /*
-        * Make sure this device's parent is present before we go about
-        * messing with the device.
-        */
-       if (device->parent && !device->parent->status.present) {
-               device->status = device->parent->status;
-               return;
-       }
-
-       status = acpi_bus_get_status(device);
-       if (ACPI_FAILURE(status))
-               return;
-
-       if (STRUCT_TO_INT(old_status) == STRUCT_TO_INT(device->status))
-               return;
-
-       /*
-        * Device Insertion/Removal
-        */
-       if ((device->status.present) && !(old_status.present)) {
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device insertion detected\n"));
-               /* TBD: Handle device insertion */
-       } else if (!(device->status.present) && (old_status.present)) {
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device removal detected\n"));
-               /* TBD: Handle device removal */
-       }
-}
-
-static void acpi_bus_check_scope(acpi_handle handle)
-{
-       /* Status Change? */
-       acpi_bus_check_device(handle);
-
-       /*
-        * TBD: Enumerate child devices within this device's scope and
-        *       run acpi_bus_check_device()'s on them.
-        */
-}
-
 /**
  * acpi_bus_notify
  * ---------------
@@ -397,19 +338,11 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
        switch (type) {
 
        case ACPI_NOTIFY_BUS_CHECK:
-               acpi_bus_check_scope(handle);
-               /*
-                * TBD: We'll need to outsource certain events to non-ACPI
-                *      drivers via the device manager (device.c).
-                */
+               /* TBD */
                break;
 
        case ACPI_NOTIFY_DEVICE_CHECK:
-               acpi_bus_check_device(handle);
-               /*
-                * TBD: We'll need to outsource certain events to non-ACPI
-                *      drivers via the device manager (device.c).
-                */
+               /* TBD */
                break;
 
        case ACPI_NOTIFY_DEVICE_WAKE:
index c971929d75c20090b69afda2ab65b073bc95b140..9e3a6cb99f90eb7de2e4c0f078ef316fc0cb895a 100644 (file)
@@ -31,8 +31,7 @@
 #include <linux/seq_file.h>
 #include <linux/input.h>
 #include <linux/slab.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
 #include <acpi/button.h>
 
 #define PREFIX "ACPI: "
index e2315166765501b479259269ea5888d44042868b..83d232c10f139d697513be3e718cbff8b2342bb9 100644 (file)
@@ -44,19 +44,24 @@ static const struct acpi_device_id container_device_ids[] = {
        {"", 0},
 };
 
-static int container_device_attach(struct acpi_device *device,
+static int container_device_attach(struct acpi_device *adev,
                                   const struct acpi_device_id *not_used)
 {
-       /* This is necessary for container hotplug to work. */
+       kobject_uevent(&adev->dev.kobj, KOBJ_ONLINE);
        return 1;
 }
 
+static void container_device_detach(struct acpi_device *adev)
+{
+       kobject_uevent(&adev->dev.kobj, KOBJ_OFFLINE);
+}
+
 static struct acpi_scan_handler container_handler = {
        .ids = container_device_ids,
        .attach = container_device_attach,
+       .detach = container_device_detach,
        .hotplug = {
                .enabled = true,
-               .mode = AHM_CONTAINER,
        },
 };
 
index 12b62f2cdb3f0ad507748e9280a961eb1d7667b3..c68e72414a67a9b00231b095335945d5cdd2f31e 100644 (file)
@@ -7,7 +7,7 @@
 #include <linux/kernel.h>
 #include <linux/uaccess.h>
 #include <linux/debugfs.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
 
 #include "internal.h"
 
index b55d6a20dc0eda9a78419f29bb8eb229cc157930..6b1919f6bd8212248f8a7399c21f73b1303a254e 100644 (file)
@@ -5,7 +5,7 @@
 #include <linux/export.h>
 #include <linux/init.h>
 #include <linux/debugfs.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
 
 #define _COMPONENT             ACPI_SYSTEM_COMPONENT
 ACPI_MODULE_NAME("debugfs");
index b3480cf7db1a1d1eba0e8d884cb456f92b76b660..d49f1e46470370908d72b6efb7677d70f80ded98 100644 (file)
@@ -256,6 +256,8 @@ int acpi_bus_init_power(struct acpi_device *device)
                return -EINVAL;
 
        device->power.state = ACPI_STATE_UNKNOWN;
+       if (!acpi_device_is_present(device))
+               return 0;
 
        result = acpi_device_get_power(device, &state);
        if (result)
@@ -302,15 +304,18 @@ int acpi_device_fix_up_power(struct acpi_device *device)
        return ret;
 }
 
-int acpi_bus_update_power(acpi_handle handle, int *state_p)
+int acpi_device_update_power(struct acpi_device *device, int *state_p)
 {
-       struct acpi_device *device;
        int state;
        int result;
 
-       result = acpi_bus_get_device(handle, &device);
-       if (result)
+       if (device->power.state == ACPI_STATE_UNKNOWN) {
+               result = acpi_bus_init_power(device);
+               if (!result && state_p)
+                       *state_p = device->power.state;
+
                return result;
+       }
 
        result = acpi_device_get_power(device, &state);
        if (result)
@@ -338,6 +343,15 @@ int acpi_bus_update_power(acpi_handle handle, int *state_p)
 
        return 0;
 }
+
+int acpi_bus_update_power(acpi_handle handle, int *state_p)
+{
+       struct acpi_device *device;
+       int result;
+
+       result = acpi_bus_get_device(handle, &device);
+       return result ? result : acpi_device_update_power(device, state_p);
+}
 EXPORT_SYMBOL_GPL(acpi_bus_update_power);
 
 bool acpi_bus_power_manageable(acpi_handle handle)
index dcd73ccb514c601df4efdee7043f2a7cffeb718e..8da6be99ba4206b8ebc82eb669be2f447e53b3ab 100644 (file)
@@ -32,8 +32,6 @@
 #include <linux/jiffies.h>
 #include <linux/stddef.h>
 #include <linux/acpi.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
 
 #define PREFIX "ACPI: "
 
@@ -323,14 +321,11 @@ static int dock_present(struct dock_station *ds)
  */
 static void dock_create_acpi_device(acpi_handle handle)
 {
-       struct acpi_device *device;
+       struct acpi_device *device = NULL;
        int ret;
 
-       if (acpi_bus_get_device(handle, &device)) {
-               /*
-                * no device created for this object,
-                * so we should create one.
-                */
+       acpi_bus_get_device(handle, &device);
+       if (!acpi_device_enumerated(device)) {
                ret = acpi_bus_scan(handle);
                if (ret)
                        pr_debug("error adding bus, %x\n", -ret);
index ba5b56db9d27c7fafa3b19c6d1f5d2549308aea6..ff40120e930e5ae3c3506db53481f4fe6809a680 100644 (file)
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
-#include <asm/io.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
 #include <linux/dmi.h>
+#include <asm/io.h>
 
 #include "internal.h"
 
index cae3b387b867a99ab7013cfc2b731b2125abc961..ef2d730734dcca90a9690e48021d1d9a1d925791 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/init.h>
 #include <linux/poll.h>
 #include <linux/gfp.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
 #include <net/netlink.h>
 #include <net/genetlink.h>
 
index ba3da88cee45a20479df62023ee560aa422dff22..1fb62900f32a9c57d329fd3e5480bc0dc7c305b8 100644 (file)
@@ -29,8 +29,7 @@
 #include <linux/types.h>
 #include <asm/uaccess.h>
 #include <linux/thermal.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
 
 #define PREFIX "ACPI: "
 
index a22a295edb692347f16066bff26d145973ab2523..0c789224d40d4da34aa3c7f1a9314bb12ba7b459 100644 (file)
@@ -37,7 +37,7 @@ int register_acpi_bus_type(struct acpi_bus_type *type)
 {
        if (acpi_disabled)
                return -ENODEV;
-       if (type && type->match && type->find_device) {
+       if (type && type->match && type->find_companion) {
                down_write(&bus_type_sem);
                list_add_tail(&type->list, &bus_type_list);
                up_write(&bus_type_sem);
@@ -82,109 +82,74 @@ static struct acpi_bus_type *acpi_get_bus_type(struct device *dev)
 #define FIND_CHILD_MIN_SCORE   1
 #define FIND_CHILD_MAX_SCORE   2
 
-static acpi_status acpi_dev_present(acpi_handle handle, u32 lvl_not_used,
-                                 void *not_used, void **ret_p)
-{
-       struct acpi_device *adev = NULL;
-
-       acpi_bus_get_device(handle, &adev);
-       if (adev) {
-               *ret_p = handle;
-               return AE_CTRL_TERMINATE;
-       }
-       return AE_OK;
-}
-
-static int do_find_child_checks(acpi_handle handle, bool is_bridge)
+static int find_child_checks(struct acpi_device *adev, bool check_children)
 {
        bool sta_present = true;
        unsigned long long sta;
        acpi_status status;
 
-       status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
+       status = acpi_evaluate_integer(adev->handle, "_STA", NULL, &sta);
        if (status == AE_NOT_FOUND)
                sta_present = false;
        else if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_ENABLED))
                return -ENODEV;
 
-       if (is_bridge) {
-               void *test = NULL;
+       if (check_children && list_empty(&adev->children))
+               return -ENODEV;
 
-               /* Check if this object has at least one child device. */
-               acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
-                                   acpi_dev_present, NULL, NULL, &test);
-               if (!test)
-                       return -ENODEV;
-       }
        return sta_present ? FIND_CHILD_MAX_SCORE : FIND_CHILD_MIN_SCORE;
 }
 
-struct find_child_context {
-       u64 addr;
-       bool is_bridge;
-       acpi_handle ret;
-       int ret_score;
-};
-
-static acpi_status do_find_child(acpi_handle handle, u32 lvl_not_used,
-                                void *data, void **not_used)
-{
-       struct find_child_context *context = data;
-       unsigned long long addr;
-       acpi_status status;
-       int score;
-
-       status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &addr);
-       if (ACPI_FAILURE(status) || addr != context->addr)
-               return AE_OK;
-
-       if (!context->ret) {
-               /* This is the first matching object.  Save its handle. */
-               context->ret = handle;
-               return AE_OK;
-       }
-       /*
-        * There is more than one matching object with the same _ADR value.
-        * That really is unexpected, so we are kind of beyond the scope of the
-        * spec here.  We have to choose which one to return, though.
-        *
-        * First, check if the previously found object is good enough and return
-        * its handle if so.  Second, check the same for the object that we've
-        * just found.
-        */
-       if (!context->ret_score) {
-               score = do_find_child_checks(context->ret, context->is_bridge);
-               if (score == FIND_CHILD_MAX_SCORE)
-                       return AE_CTRL_TERMINATE;
-               else
-                       context->ret_score = score;
-       }
-       score = do_find_child_checks(handle, context->is_bridge);
-       if (score == FIND_CHILD_MAX_SCORE) {
-               context->ret = handle;
-               return AE_CTRL_TERMINATE;
-       } else if (score > context->ret_score) {
-               context->ret = handle;
-               context->ret_score = score;
-       }
-       return AE_OK;
-}
-
-acpi_handle acpi_find_child(acpi_handle parent, u64 addr, bool is_bridge)
+struct acpi_device *acpi_find_child_device(struct acpi_device *parent,
+                                          u64 address, bool check_children)
 {
-       if (parent) {
-               struct find_child_context context = {
-                       .addr = addr,
-                       .is_bridge = is_bridge,
-               };
-
-               acpi_walk_namespace(ACPI_TYPE_DEVICE, parent, 1, do_find_child,
-                                   NULL, &context, NULL);
-               return context.ret;
+       struct acpi_device *adev, *ret = NULL;
+       int ret_score = 0;
+
+       if (!parent)
+               return NULL;
+
+       list_for_each_entry(adev, &parent->children, node) {
+               unsigned long long addr;
+               acpi_status status;
+               int score;
+
+               status = acpi_evaluate_integer(adev->handle, METHOD_NAME__ADR,
+                                              NULL, &addr);
+               if (ACPI_FAILURE(status) || addr != address)
+                       continue;
+
+               if (!ret) {
+                       /* This is the first matching object.  Save it. */
+                       ret = adev;
+                       continue;
+               }
+               /*
+                * There is more than one matching device object with the same
+                * _ADR value.  That really is unexpected, so we are kind of
+                * beyond the scope of the spec here.  We have to choose which
+                * one to return, though.
+                *
+                * First, check if the previously found object is good enough
+                * and return it if so.  Second, do the same for the object that
+                * we've just found.
+                */
+               if (!ret_score) {
+                       ret_score = find_child_checks(ret, check_children);
+                       if (ret_score == FIND_CHILD_MAX_SCORE)
+                               return ret;
+               }
+               score = find_child_checks(adev, check_children);
+               if (score == FIND_CHILD_MAX_SCORE) {
+                       return adev;
+               } else if (score > ret_score) {
+                       ret = adev;
+                       ret_score = score;
+               }
        }
-       return NULL;
+       return ret;
 }
-EXPORT_SYMBOL_GPL(acpi_find_child);
+EXPORT_SYMBOL_GPL(acpi_find_child_device);
 
 static void acpi_physnode_link_name(char *buf, unsigned int node_id)
 {
@@ -195,9 +160,8 @@ static void acpi_physnode_link_name(char *buf, unsigned int node_id)
                strcpy(buf, PHYSICAL_NODE_STRING);
 }
 
-int acpi_bind_one(struct device *dev, acpi_handle handle)
+int acpi_bind_one(struct device *dev, struct acpi_device *acpi_dev)
 {
-       struct acpi_device *acpi_dev = NULL;
        struct acpi_device_physical_node *physical_node, *pn;
        char physical_node_name[PHYSICAL_NODE_NAME_SIZE];
        struct list_head *physnode_list;
@@ -205,14 +169,12 @@ int acpi_bind_one(struct device *dev, acpi_handle handle)
        int retval = -EINVAL;
 
        if (ACPI_COMPANION(dev)) {
-               if (handle) {
+               if (acpi_dev) {
                        dev_warn(dev, "ACPI companion already set\n");
                        return -EINVAL;
                } else {
                        acpi_dev = ACPI_COMPANION(dev);
                }
-       } else {
-               acpi_bus_get_device(handle, &acpi_dev);
        }
        if (!acpi_dev)
                return -EINVAL;
@@ -322,29 +284,22 @@ int acpi_unbind_one(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(acpi_unbind_one);
 
-void acpi_preset_companion(struct device *dev, acpi_handle parent, u64 addr)
-{
-       struct acpi_device *adev;
-
-       if (!acpi_bus_get_device(acpi_get_child(parent, addr), &adev))
-               ACPI_COMPANION_SET(dev, adev);
-}
-EXPORT_SYMBOL_GPL(acpi_preset_companion);
-
 static int acpi_platform_notify(struct device *dev)
 {
        struct acpi_bus_type *type = acpi_get_bus_type(dev);
-       acpi_handle handle;
        int ret;
 
        ret = acpi_bind_one(dev, NULL);
        if (ret && type) {
-               ret = type->find_device(dev, &handle);
-               if (ret) {
+               struct acpi_device *adev;
+
+               adev = type->find_companion(dev);
+               if (!adev) {
                        DBG("Unable to get handle for %s\n", dev_name(dev));
+                       ret = -ENODEV;
                        goto out;
                }
-               ret = acpi_bind_one(dev, handle);
+               ret = acpi_bind_one(dev, adev);
                if (ret)
                        goto out;
        }
index 13b1d39d7cdf57c463534c3a29cfd797e22abfe0..aafe3ca829c28b4a22a8f2a708df6d69093349e9 100644 (file)
@@ -25,8 +25,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/acpi.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
 #include <acpi/hed.h>
 
 static struct acpi_device_id acpi_hed_ids[] = {
index a29739c0ba790af9c967efc29ef6907bf06b63d6..b125fdb0b30cc4affcdf50c9c131a9ad7a9e842e 100644 (file)
@@ -28,7 +28,6 @@ int init_acpi_device_notify(void);
 int acpi_scan_init(void);
 void acpi_pci_root_init(void);
 void acpi_pci_link_init(void);
-void acpi_pci_root_hp_init(void);
 void acpi_processor_init(void);
 void acpi_platform_init(void);
 int acpi_sysfs_init(void);
@@ -73,6 +72,8 @@ void acpi_lpss_init(void);
 static inline void acpi_lpss_init(void) {}
 #endif
 
+bool acpi_queue_hotplug_work(struct work_struct *work);
+
 /* --------------------------------------------------------------------------
                      Device Node Initialization / Removal
    -------------------------------------------------------------------------- */
@@ -85,9 +86,9 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
                             int type, unsigned long long sta);
 void acpi_device_add_finalize(struct acpi_device *device);
 void acpi_free_pnp_ids(struct acpi_device_pnp *pnp);
-int acpi_bind_one(struct device *dev, acpi_handle handle);
+int acpi_bind_one(struct device *dev, struct acpi_device *adev);
 int acpi_unbind_one(struct device *dev);
-void acpi_bus_device_eject(void *data, u32 ost_src);
+bool acpi_device_is_present(struct acpi_device *adev);
 
 /* --------------------------------------------------------------------------
                                   Power Resource
@@ -105,6 +106,8 @@ int acpi_power_get_inferred_state(struct acpi_device *device, int *state);
 int acpi_power_on_resources(struct acpi_device *device, int state);
 int acpi_power_transition(struct acpi_device *device, int state);
 
+int acpi_device_update_power(struct acpi_device *device, int *state_p);
+
 int acpi_wakeup_device_init(void);
 void acpi_early_processor_set_pdc(void);
 
index a2343a1d9e0b1a0e77f3b7a7caf6676499c5f989..9e6816ef280ab7a5def6586cfabd3f60b7cd0ccb 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/errno.h>
 #include <linux/acpi.h>
 #include <linux/numa.h>
-#include <acpi/acpi_bus.h>
 
 #define PREFIX "ACPI: "
 
index 54a20ff4b864d90881cf41be6fbebd33de1c32a9..7e2d8140c33464336cd1eff96bb4a132fceeef5a 100644 (file)
@@ -49,9 +49,6 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
-#include <acpi/acpi.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/processor.h>
 #include "internal.h"
 
 #define _COMPONENT             ACPI_OS_SERVICES
@@ -1215,6 +1212,10 @@ acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src)
        return AE_OK;
 }
 
+bool acpi_queue_hotplug_work(struct work_struct *work)
+{
+       return queue_work(kacpi_hotplug_wq, work);
+}
 
 acpi_status
 acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle)
@@ -1794,7 +1795,7 @@ acpi_status __init acpi_os_initialize1(void)
 {
        kacpid_wq = alloc_workqueue("kacpid", 0, 1);
        kacpi_notify_wq = alloc_workqueue("kacpi_notify", 0, 1);
-       kacpi_hotplug_wq = alloc_workqueue("kacpi_hotplug", 0, 1);
+       kacpi_hotplug_wq = alloc_ordered_workqueue("kacpi_hotplug", 0);
        BUG_ON(!kacpid_wq);
        BUG_ON(!kacpi_notify_wq);
        BUG_ON(!kacpi_hotplug_wq);
index 41c5e1b799ef938ff1eed92e4cf48a7c7677f8bd..52d45ea2bc4f63efcfb7e8912b087b1a568d49cc 100644 (file)
@@ -37,8 +37,6 @@
 #include <linux/pci.h>
 #include <linux/acpi.h>
 #include <linux/slab.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
 
 #define PREFIX "ACPI: "
 
index 2652a614deebe8062c71bb4e3c7f26fe8d315a45..ea6b8d16dcc82efb90a8f61f8181d90608461774 100644 (file)
@@ -39,9 +39,7 @@
 #include <linux/pci.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
-
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
 
 #define PREFIX "ACPI: "
 
index 20360e480bd8d81c0070cc25b5cd2cddd05d0447..afafee56cf8be2b7d1dfe5d2de91180ba30a370c 100644 (file)
@@ -35,9 +35,7 @@
 #include <linux/pci-aspm.h>
 #include <linux/acpi.h>
 #include <linux/slab.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
-#include <acpi/apei.h>
+#include <acpi/apei.h> /* for acpi_hest_init() */
 
 #include "internal.h"
 
@@ -51,6 +49,12 @@ 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);
 
+static int acpi_pci_root_scan_dependent(struct acpi_device *adev)
+{
+       acpiphp_check_host_bridge(adev->handle);
+       return 0;
+}
+
 #define ACPI_PCIE_REQ_SUPPORT (OSC_PCI_EXT_CONFIG_SUPPORT \
                                | OSC_PCI_ASPM_SUPPORT \
                                | OSC_PCI_CLOCK_PM_SUPPORT \
@@ -66,7 +70,8 @@ static struct acpi_scan_handler pci_root_handler = {
        .attach = acpi_pci_root_add,
        .detach = acpi_pci_root_remove,
        .hotplug = {
-               .ignore = true,
+               .enabled = true,
+               .scan_dependent = acpi_pci_root_scan_dependent,
        },
 };
 
@@ -624,116 +629,9 @@ static void acpi_pci_root_remove(struct acpi_device *device)
 void __init acpi_pci_root_init(void)
 {
        acpi_hest_init();
-
-       if (!acpi_pci_disabled) {
-               pci_acpi_crs_quirks();
-               acpi_scan_add_handler(&pci_root_handler);
-       }
-}
-/* Support root bridge hotplug */
-
-static void handle_root_bridge_insertion(acpi_handle handle)
-{
-       struct acpi_device *device;
-
-       if (!acpi_bus_get_device(handle, &device)) {
-               dev_printk(KERN_DEBUG, &device->dev,
-                          "acpi device already exists; ignoring notify\n");
+       if (acpi_pci_disabled)
                return;
-       }
-
-       if (acpi_bus_scan(handle))
-               acpi_handle_err(handle, "cannot add bridge to acpi list\n");
-}
-
-static void hotplug_event_root(void *data, u32 type)
-{
-       acpi_handle handle = data;
-       struct acpi_pci_root *root;
-
-       acpi_scan_lock_acquire();
-
-       root = acpi_pci_find_root(handle);
-
-       switch (type) {
-       case ACPI_NOTIFY_BUS_CHECK:
-               /* bus enumerate */
-               acpi_handle_printk(KERN_DEBUG, handle,
-                                  "Bus check notify on %s\n", __func__);
-               if (root)
-                       acpiphp_check_host_bridge(handle);
-               else
-                       handle_root_bridge_insertion(handle);
-
-               break;
-
-       case ACPI_NOTIFY_DEVICE_CHECK:
-               /* device check */
-               acpi_handle_printk(KERN_DEBUG, handle,
-                                  "Device check notify on %s\n", __func__);
-               if (!root)
-                       handle_root_bridge_insertion(handle);
-               break;
-
-       case ACPI_NOTIFY_EJECT_REQUEST:
-               /* request device eject */
-               acpi_handle_printk(KERN_DEBUG, handle,
-                                  "Device eject notify on %s\n", __func__);
-               if (!root)
-                       break;
-
-               get_device(&root->device->dev);
-
-               acpi_scan_lock_release();
-
-               acpi_bus_device_eject(root->device, ACPI_NOTIFY_EJECT_REQUEST);
-               return;
-       default:
-               acpi_handle_warn(handle,
-                                "notify_handler: unknown event type 0x%x\n",
-                                type);
-               break;
-       }
-
-       acpi_scan_lock_release();
-}
-
-static void handle_hotplug_event_root(acpi_handle handle, u32 type,
-                                       void *context)
-{
-       acpi_hotplug_execute(hotplug_event_root, handle, type);
-}
-
-static acpi_status __init
-find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
-{
-       acpi_status status;
-       int *count = (int *)context;
-
-       if (!acpi_is_root_bridge(handle))
-               return AE_OK;
-
-       (*count)++;
-
-       status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-                                       handle_hotplug_event_root, NULL);
-       if (ACPI_FAILURE(status))
-               acpi_handle_printk(KERN_DEBUG, handle,
-                       "notify handler is not installed, exit status: %u\n",
-                        (unsigned int)status);
-       else
-               acpi_handle_printk(KERN_DEBUG, handle,
-                                  "notify handler is installed\n");
-
-       return AE_OK;
-}
-
-void __init acpi_pci_root_hp_init(void)
-{
-       int num = 0;
-
-       acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
-               ACPI_UINT32_MAX, find_root_bridges, NULL, &num, NULL);
 
-       printk(KERN_DEBUG "Found %d acpi root devices\n", num);
+       pci_acpi_crs_quirks();
+       acpi_scan_add_handler_with_hotplug(&pci_root_handler, "pci_root");
 }
index c2ad391d8041ecb6a354e2df07b9d813d817a744..ad7da686e6e6f8d9745a4edf866e174b99b08538 100644 (file)
@@ -42,8 +42,7 @@
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
 #include <linux/sysfs.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
 #include "sleep.h"
 #include "internal.h"
 
index 6a5b152ad4d070511d08d74439155fa17a83ed8a..db061bfd95a8de20aea42e95ae0bda75c6b68a9f 100644 (file)
@@ -3,11 +3,9 @@
 #include <linux/export.h>
 #include <linux/suspend.h>
 #include <linux/bcd.h>
+#include <linux/acpi.h>
 #include <asm/uaccess.h>
 
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
-
 #include "sleep.h"
 
 #define _COMPONENT             ACPI_SYSTEM_COMPONENT
index b3171f30b319c1244007e686a0b516833443191d..34e7b3c6a08de157c6c962bd0643ddb67176bd5e 100644 (file)
@@ -10,8 +10,7 @@
 #include <linux/export.h>
 #include <linux/dmi.h>
 #include <linux/slab.h>
-
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
 #include <acpi/processor.h>
 
 #include "internal.h"
index 644516d9bde6cf18a824d29c3ae1730de30fd1a6..d2d44e0190a31ba64970d3281698179767d08541 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/clockchips.h>
 #include <linux/cpuidle.h>
 #include <linux/syscore_ops.h>
+#include <acpi/processor.h>
 
 /*
  * Include the apic definitions for x86 to have the APIC timer related defines
@@ -46,9 +47,6 @@
 #include <asm/apic.h>
 #endif
 
-#include <acpi/acpi_bus.h>
-#include <acpi/processor.h>
-
 #define PREFIX "ACPI: "
 
 #define ACPI_PROCESSOR_CLASS            "processor"
index 60a7c28fc1674cc21bc38802fed869dc7daf0608..ff90054f04fdb88e15e1279b23b43d78884596f9 100644 (file)
 #include <linux/init.h>
 #include <linux/cpufreq.h>
 #include <linux/slab.h>
-
+#include <linux/acpi.h>
+#include <acpi/processor.h>
 #ifdef CONFIG_X86
 #include <asm/cpufeature.h>
 #endif
 
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
-#include <acpi/processor.h>
-
 #define PREFIX "ACPI: "
 
 #define ACPI_PROCESSOR_CLASS           "processor"
index d1d2e7fb5b30778f26d46ce6e72eecb03350ddfc..f95e7584d6e680bfe2b8cc49bc16f7c3a492a517 100644 (file)
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/cpufreq.h>
-
-#include <asm/uaccess.h>
-
-#include <acpi/acpi_bus.h>
+#include <linux/acpi.h>
 #include <acpi/processor.h>
-#include <acpi/acpi_drivers.h>
+#include <asm/uaccess.h>
 
 #define PREFIX "ACPI: "
 
index e7dd2c1fee79b4a097f9b3249a9b0bdaeaa2592a..28baa05b8018dd6c6e6e1db93c1a5ceed74d4d74 100644 (file)
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/cpufreq.h>
-
+#include <linux/acpi.h>
+#include <acpi/processor.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
-#include <acpi/processor.h>
-
 #define PREFIX "ACPI: "
 
 #define ACPI_PROCESSOR_CLASS            "processor"
index b78bc605837e19a8f7461f48a59cdc90d64f5128..26e5b50605230e2e34a46d8118486fb1ba2eb939 100644 (file)
@@ -8,8 +8,7 @@
  * the Free Software Foundation version 2.
  */
 
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
 #include <linux/wait.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
index fd39459926b1564c2faa3d367a4dbbf05aa60031..5383c81a8a1bdb4b2fe6b6d7d6547efa3b328cc5 100644 (file)
 #include <linux/dmi.h>
 #include <linux/nls.h>
 
-#include <acpi/acpi_drivers.h>
+#include <asm/pgtable.h>
 
 #include "internal.h"
 
 #define _COMPONENT             ACPI_BUS_COMPONENT
 ACPI_MODULE_NAME("scan");
-#define STRUCT_TO_INT(s)       (*((int*)&s))
 extern struct acpi_device *acpi_root;
 
 #define ACPI_BUS_CLASS                 "system_bus"
@@ -27,6 +26,8 @@ extern struct acpi_device *acpi_root;
 
 #define ACPI_IS_ROOT_DEVICE(device)    (!(device)->parent)
 
+#define INVALID_ACPI_HANDLE    ((acpi_handle)empty_zero_page)
+
 /*
  * If set, devices will be hot-removed even if they cannot be put offline
  * gracefully (from the kernel's standpoint).
@@ -202,13 +203,6 @@ static int acpi_scan_hot_remove(struct acpi_device *device)
        acpi_status status;
        unsigned long long sta;
 
-       /* If there is no handle, the device node has been unregistered. */
-       if (!handle) {
-               dev_dbg(&device->dev, "ACPI handle missing\n");
-               put_device(&device->dev);
-               return -EINVAL;
-       }
-
        /*
         * Carry out two passes here and ignore errors in the first pass,
         * because if the devices in question are memory blocks and
@@ -226,7 +220,6 @@ static int acpi_scan_hot_remove(struct acpi_device *device)
                dev_warn(errdev, "Offline disabled.\n");
                acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
                                    acpi_bus_online, NULL, NULL, NULL);
-               put_device(&device->dev);
                return -EPERM;
        }
        acpi_bus_offline(handle, 0, (void *)false, (void **)&errdev);
@@ -245,7 +238,6 @@ static int acpi_scan_hot_remove(struct acpi_device *device)
                        acpi_walk_namespace(ACPI_TYPE_ANY, handle,
                                            ACPI_UINT32_MAX, acpi_bus_online,
                                            NULL, NULL, NULL);
-                       put_device(&device->dev);
                        return -EBUSY;
                }
        }
@@ -255,10 +247,6 @@ static int acpi_scan_hot_remove(struct acpi_device *device)
 
        acpi_bus_trim(device);
 
-       /* Device node has been unregistered. */
-       put_device(&device->dev);
-       device = NULL;
-
        acpi_evaluate_lck(handle, 0);
        /*
         * TBD: _EJD support.
@@ -285,115 +273,127 @@ static int acpi_scan_hot_remove(struct acpi_device *device)
        return 0;
 }
 
-void acpi_bus_device_eject(void *data, u32 ost_src)
+static int acpi_scan_device_not_present(struct acpi_device *adev)
 {
-       struct acpi_device *device = data;
-       acpi_handle handle = device->handle;
-       u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
-       int error;
+       if (!acpi_device_enumerated(adev)) {
+               dev_warn(&adev->dev, "Still not present\n");
+               return -EALREADY;
+       }
+       acpi_bus_trim(adev);
+       return 0;
+}
 
-       lock_device_hotplug();
-       mutex_lock(&acpi_scan_lock);
+static int acpi_scan_device_check(struct acpi_device *adev)
+{
+       int error;
 
-       if (ost_src == ACPI_NOTIFY_EJECT_REQUEST)
-               acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
-                                         ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
+       acpi_bus_get_status(adev);
+       if (adev->status.present || adev->status.functional) {
+               /*
+                * This function is only called for device objects for which
+                * matching scan handlers exist.  The only situation in which
+                * the scan handler is not attached to this device object yet
+                * is when the device has just appeared (either it wasn't
+                * present at all before or it was removed and then added
+                * again).
+                */
+               if (adev->handler) {
+                       dev_warn(&adev->dev, "Already enumerated\n");
+                       return -EALREADY;
+               }
+               error = acpi_bus_scan(adev->handle);
+               if (error) {
+                       dev_warn(&adev->dev, "Namespace scan failure\n");
+                       return error;
+               }
+               if (!adev->handler) {
+                       dev_warn(&adev->dev, "Enumeration failure\n");
+                       error = -ENODEV;
+               }
+       } else {
+               error = acpi_scan_device_not_present(adev);
+       }
+       return error;
+}
 
-       if (device->handler && device->handler->hotplug.mode == AHM_CONTAINER)
-               kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
+static int acpi_scan_bus_check(struct acpi_device *adev)
+{
+       struct acpi_scan_handler *handler = adev->handler;
+       struct acpi_device *child;
+       int error;
 
-       error = acpi_scan_hot_remove(device);
-       if (error == -EPERM) {
-               goto err_support;
-       } else if (error) {
-               goto err_out;
+       acpi_bus_get_status(adev);
+       if (!(adev->status.present || adev->status.functional)) {
+               acpi_scan_device_not_present(adev);
+               return 0;
        }
+       if (handler && handler->hotplug.scan_dependent)
+               return handler->hotplug.scan_dependent(adev);
 
- out:
-       mutex_unlock(&acpi_scan_lock);
-       unlock_device_hotplug();
-       return;
-
- err_support:
-       ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
- err_out:
-       acpi_evaluate_hotplug_ost(handle, ost_src, ost_code, NULL);
-       goto out;
+       error = acpi_bus_scan(adev->handle);
+       if (error) {
+               dev_warn(&adev->dev, "Namespace scan failure\n");
+               return error;
+       }
+       list_for_each_entry(child, &adev->children, node) {
+               error = acpi_scan_bus_check(child);
+               if (error)
+                       return error;
+       }
+       return 0;
 }
 
-static void acpi_scan_bus_device_check(void *data, u32 ost_source)
+static void acpi_device_hotplug(void *data, u32 src)
 {
-       acpi_handle handle = data;
-       struct acpi_device *device = NULL;
        u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
+       struct acpi_device *adev = data;
        int error;
 
        lock_device_hotplug();
        mutex_lock(&acpi_scan_lock);
 
-       if (ost_source != ACPI_NOTIFY_BUS_CHECK) {
-               acpi_bus_get_device(handle, &device);
-               if (device) {
-                       dev_warn(&device->dev, "Attempt to re-insert\n");
-                       goto out;
-               }
-       }
-       error = acpi_bus_scan(handle);
-       if (error) {
-               acpi_handle_warn(handle, "Namespace scan failure\n");
-               goto out;
-       }
-       error = acpi_bus_get_device(handle, &device);
-       if (error) {
-               acpi_handle_warn(handle, "Missing device node object\n");
+       /*
+        * The device object's ACPI handle cannot become invalid as long as we
+        * are holding acpi_scan_lock, but it may have become invalid before
+        * that lock was acquired.
+        */
+       if (adev->handle == INVALID_ACPI_HANDLE)
                goto out;
-       }
-       ost_code = ACPI_OST_SC_SUCCESS;
-       if (device->handler && device->handler->hotplug.mode == AHM_CONTAINER)
-               kobject_uevent(&device->dev.kobj, KOBJ_ONLINE);
-
- out:
-       acpi_evaluate_hotplug_ost(handle, ost_source, ost_code, NULL);
-       mutex_unlock(&acpi_scan_lock);
-       unlock_device_hotplug();
-}
 
-static void acpi_hotplug_unsupported(acpi_handle handle, u32 type)
-{
-       u32 ost_status;
-
-       switch (type) {
+       switch (src) {
        case ACPI_NOTIFY_BUS_CHECK:
-               acpi_handle_debug(handle,
-                       "ACPI_NOTIFY_BUS_CHECK event: unsupported\n");
-               ost_status = ACPI_OST_SC_INSERT_NOT_SUPPORTED;
+               error = acpi_scan_bus_check(adev);
                break;
        case ACPI_NOTIFY_DEVICE_CHECK:
-               acpi_handle_debug(handle,
-                       "ACPI_NOTIFY_DEVICE_CHECK event: unsupported\n");
-               ost_status = ACPI_OST_SC_INSERT_NOT_SUPPORTED;
+               error = acpi_scan_device_check(adev);
                break;
        case ACPI_NOTIFY_EJECT_REQUEST:
-               acpi_handle_debug(handle,
-                       "ACPI_NOTIFY_EJECT_REQUEST event: unsupported\n");
-               ost_status = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
+       case ACPI_OST_EC_OSPM_EJECT:
+               error = acpi_scan_hot_remove(adev);
                break;
        default:
-               /* non-hotplug event; possibly handled by other handler */
-               return;
+               error = -EINVAL;
+               break;
        }
+       if (!error)
+               ost_code = ACPI_OST_SC_SUCCESS;
 
-       acpi_evaluate_hotplug_ost(handle, type, ost_status, NULL);
+ out:
+       acpi_evaluate_hotplug_ost(adev->handle, src, ost_code, NULL);
+       put_device(&adev->dev);
+       mutex_unlock(&acpi_scan_lock);
+       unlock_device_hotplug();
 }
 
 static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
 {
+       u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
        struct acpi_scan_handler *handler = data;
        struct acpi_device *adev;
        acpi_status status;
 
-       if (!handler->hotplug.enabled)
-               return acpi_hotplug_unsupported(handle, type);
+       if (acpi_bus_get_device(handle, &adev))
+               goto err_out;
 
        switch (type) {
        case ACPI_NOTIFY_BUS_CHECK:
@@ -404,27 +404,27 @@ static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
                break;
        case ACPI_NOTIFY_EJECT_REQUEST:
                acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
-               if (acpi_bus_get_device(handle, &adev))
+               if (!handler->hotplug.enabled) {
+                       acpi_handle_err(handle, "Eject disabled\n");
+                       ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
                        goto err_out;
-
-               get_device(&adev->dev);
-               status = acpi_hotplug_execute(acpi_bus_device_eject, adev, type);
-               if (ACPI_SUCCESS(status))
-                       return;
-
-               put_device(&adev->dev);
-               goto err_out;
+               }
+               acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
+                                         ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
+               break;
        default:
                /* non-hotplug event; possibly handled by other handler */
                return;
        }
-       status = acpi_hotplug_execute(acpi_scan_bus_device_check, handle, type);
+       get_device(&adev->dev);
+       status = acpi_hotplug_execute(acpi_device_hotplug, adev, type);
        if (ACPI_SUCCESS(status))
                return;
 
+       put_device(&adev->dev);
+
  err_out:
-       acpi_evaluate_hotplug_ost(handle, type,
-                                 ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL);
+       acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
 }
 
 static ssize_t real_power_state_show(struct device *dev,
@@ -475,7 +475,7 @@ acpi_eject_store(struct device *d, struct device_attribute *attr,
        acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT,
                                  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
        get_device(&acpi_device->dev);
-       status = acpi_hotplug_execute(acpi_bus_device_eject, acpi_device,
+       status = acpi_hotplug_execute(acpi_device_hotplug, acpi_device,
                                      ACPI_OST_EC_OSPM_EJECT);
        if (ACPI_SUCCESS(status))
                return count;
@@ -907,9 +907,91 @@ struct bus_type acpi_bus_type = {
        .uevent         = acpi_device_uevent,
 };
 
-static void acpi_bus_data_handler(acpi_handle handle, void *context)
+static void acpi_device_del(struct acpi_device *device)
 {
-       /* Intentionally empty. */
+       mutex_lock(&acpi_device_lock);
+       if (device->parent)
+               list_del(&device->node);
+
+       list_del(&device->wakeup_list);
+       mutex_unlock(&acpi_device_lock);
+
+       acpi_power_add_remove_device(device, false);
+       acpi_device_remove_files(device);
+       if (device->remove)
+               device->remove(device);
+
+       device_del(&device->dev);
+}
+
+static LIST_HEAD(acpi_device_del_list);
+static DEFINE_MUTEX(acpi_device_del_lock);
+
+static void acpi_device_del_work_fn(struct work_struct *work_not_used)
+{
+       for (;;) {
+               struct acpi_device *adev;
+
+               mutex_lock(&acpi_device_del_lock);
+
+               if (list_empty(&acpi_device_del_list)) {
+                       mutex_unlock(&acpi_device_del_lock);
+                       break;
+               }
+               adev = list_first_entry(&acpi_device_del_list,
+                                       struct acpi_device, del_list);
+               list_del(&adev->del_list);
+
+               mutex_unlock(&acpi_device_del_lock);
+
+               acpi_device_del(adev);
+               /*
+                * Drop references to all power resources that might have been
+                * used by the device.
+                */
+               acpi_power_transition(adev, ACPI_STATE_D3_COLD);
+               put_device(&adev->dev);
+       }
+}
+
+/**
+ * acpi_scan_drop_device - Drop an ACPI device object.
+ * @handle: Handle of an ACPI namespace node, not used.
+ * @context: Address of the ACPI device object to drop.
+ *
+ * This is invoked by acpi_ns_delete_node() during the removal of the ACPI
+ * namespace node the device object pointed to by @context is attached to.
+ *
+ * The unregistration is carried out asynchronously to avoid running
+ * acpi_device_del() under the ACPICA's namespace mutex and the list is used to
+ * ensure the correct ordering (the device objects must be unregistered in the
+ * same order in which the corresponding namespace nodes are deleted).
+ */
+static void acpi_scan_drop_device(acpi_handle handle, void *context)
+{
+       static DECLARE_WORK(work, acpi_device_del_work_fn);
+       struct acpi_device *adev = context;
+
+       mutex_lock(&acpi_device_del_lock);
+
+       /*
+        * Use the ACPI hotplug workqueue which is ordered, so this work item
+        * won't run after any hotplug work items submitted subsequently.  That
+        * prevents attempts to register device objects identical to those being
+        * deleted from happening concurrently (such attempts result from
+        * hotplug events handled via the ACPI hotplug workqueue).  It also will
+        * run after all of the work items submitted previosuly, which helps
+        * those work items to ensure that they are not accessing stale device
+        * objects.
+        */
+       if (list_empty(&acpi_device_del_list))
+               acpi_queue_hotplug_work(&work);
+
+       list_add_tail(&adev->del_list, &acpi_device_del_list);
+       /* Make acpi_ns_validate_handle() return NULL for this handle. */
+       adev->handle = INVALID_ACPI_HANDLE;
+
+       mutex_unlock(&acpi_device_del_lock);
 }
 
 int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device)
@@ -919,7 +1001,7 @@ int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device)
        if (!device)
                return -EINVAL;
 
-       status = acpi_get_data(handle, acpi_bus_data_handler, (void **)device);
+       status = acpi_get_data(handle, acpi_scan_drop_device, (void **)device);
        if (ACPI_FAILURE(status) || !*device) {
                ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n",
                                  handle));
@@ -939,7 +1021,7 @@ int acpi_device_add(struct acpi_device *device,
        if (device->handle) {
                acpi_status status;
 
-               status = acpi_attach_data(device->handle, acpi_bus_data_handler,
+               status = acpi_attach_data(device->handle, acpi_scan_drop_device,
                                          device);
                if (ACPI_FAILURE(status)) {
                        acpi_handle_err(device->handle,
@@ -957,6 +1039,7 @@ int acpi_device_add(struct acpi_device *device,
        INIT_LIST_HEAD(&device->node);
        INIT_LIST_HEAD(&device->wakeup_list);
        INIT_LIST_HEAD(&device->physical_node_list);
+       INIT_LIST_HEAD(&device->del_list);
        mutex_init(&device->physical_node_lock);
 
        new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL);
@@ -1020,37 +1103,10 @@ int acpi_device_add(struct acpi_device *device,
        mutex_unlock(&acpi_device_lock);
 
  err_detach:
-       acpi_detach_data(device->handle, acpi_bus_data_handler);
+       acpi_detach_data(device->handle, acpi_scan_drop_device);
        return result;
 }
 
-static void acpi_device_unregister(struct acpi_device *device)
-{
-       mutex_lock(&acpi_device_lock);
-       if (device->parent)
-               list_del(&device->node);
-
-       list_del(&device->wakeup_list);
-       mutex_unlock(&acpi_device_lock);
-
-       acpi_detach_data(device->handle, acpi_bus_data_handler);
-
-       acpi_power_add_remove_device(device, false);
-       acpi_device_remove_files(device);
-       if (device->remove)
-               device->remove(device);
-
-       device_del(&device->dev);
-       /*
-        * Transition the device to D3cold to drop the reference counts of all
-        * power resources the device depends on and turn off the ones that have
-        * no more references.
-        */
-       acpi_device_set_power(device, ACPI_STATE_D3_COLD);
-       device->handle = NULL;
-       put_device(&device->dev);
-}
-
 /* --------------------------------------------------------------------------
                                  Driver Management
    -------------------------------------------------------------------------- */
@@ -1624,11 +1680,13 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
        device->device_type = type;
        device->handle = handle;
        device->parent = acpi_bus_get_parent(handle);
-       STRUCT_TO_INT(device->status) = sta;
+       acpi_set_device_status(device, sta);
        acpi_device_get_busid(device);
        acpi_set_pnp_ids(handle, &device->pnp, type);
        acpi_bus_get_flags(device);
        device->flags.match_driver = false;
+       device->flags.initialized = true;
+       device->flags.visited = false;
        device_initialize(&device->dev);
        dev_set_uevent_suppress(&device->dev, true);
 }
@@ -1713,6 +1771,15 @@ static int acpi_bus_type_and_status(acpi_handle handle, int *type,
        return 0;
 }
 
+bool acpi_device_is_present(struct acpi_device *adev)
+{
+       if (adev->status.present || adev->status.functional)
+               return true;
+
+       adev->flags.initialized = false;
+       return false;
+}
+
 static bool acpi_scan_handler_matching(struct acpi_scan_handler *handler,
                                       char *idstr,
                                       const struct acpi_device_id **matchid)
@@ -1772,7 +1839,7 @@ static void acpi_scan_init_hotplug(acpi_handle handle, int type)
         */
        list_for_each_entry(hwid, &pnp.ids, list) {
                handler = acpi_scan_match_handler(hwid->id, NULL);
-               if (handler && !handler->hotplug.ignore) {
+               if (handler) {
                        acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
                                        acpi_hotplug_notify_cb, handler);
                        break;
@@ -1806,18 +1873,6 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
 
        acpi_scan_init_hotplug(handle, type);
 
-       if (!(sta & ACPI_STA_DEVICE_PRESENT) &&
-           !(sta & ACPI_STA_DEVICE_FUNCTIONING)) {
-               struct acpi_device_wakeup wakeup;
-
-               if (acpi_has_method(handle, "_PRW")) {
-                       acpi_bus_extract_wakeup_device_power_package(handle,
-                                                                    &wakeup);
-                       acpi_power_resources_list_free(&wakeup.resources);
-               }
-               return AE_CTRL_DEPTH;
-       }
-
        acpi_add_single_object(&device, handle, type, sta);
        if (!device)
                return AE_CTRL_DEPTH;
@@ -1852,36 +1907,40 @@ static int acpi_scan_attach_handler(struct acpi_device *device)
        return ret;
 }
 
-static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used,
-                                         void *not_used, void **ret_not_used)
+static void acpi_bus_attach(struct acpi_device *device)
 {
-       struct acpi_device *device;
-       unsigned long long sta_not_used;
+       struct acpi_device *child;
        int ret;
 
-       /*
-        * Ignore errors ignored by acpi_bus_check_add() to avoid terminating
-        * namespace walks prematurely.
-        */
-       if (acpi_bus_type_and_status(handle, &ret, &sta_not_used))
-               return AE_OK;
-
-       if (acpi_bus_get_device(handle, &device))
-               return AE_CTRL_DEPTH;
-
+       acpi_bus_get_status(device);
+       /* Skip devices that are not present. */
+       if (!acpi_device_is_present(device)) {
+               device->flags.visited = false;
+               return;
+       }
        if (device->handler)
-               return AE_OK;
+               goto ok;
 
+       if (!device->flags.initialized) {
+               acpi_bus_update_power(device, NULL);
+               device->flags.initialized = true;
+       }
+       device->flags.visited = false;
        ret = acpi_scan_attach_handler(device);
        if (ret < 0)
-               return AE_CTRL_DEPTH;
+               return;
 
        device->flags.match_driver = true;
-       if (ret > 0)
-               return AE_OK;
+       if (!ret) {
+               ret = device_attach(&device->dev);
+               if (ret < 0)
+                       return;
+       }
+       device->flags.visited = true;
 
-       ret = device_attach(&device->dev);
-       return ret >= 0 ? AE_OK : AE_CTRL_DEPTH;
+ ok:
+       list_for_each_entry(child, &device->children, node)
+               acpi_bus_attach(child);
 }
 
 /**
@@ -1901,75 +1960,48 @@ static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used,
 int acpi_bus_scan(acpi_handle handle)
 {
        void *device = NULL;
-       int error = 0;
 
        if (ACPI_SUCCESS(acpi_bus_check_add(handle, 0, NULL, &device)))
                acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
                                    acpi_bus_check_add, NULL, NULL, &device);
 
-       if (!device)
-               error = -ENODEV;
-       else if (ACPI_SUCCESS(acpi_bus_device_attach(handle, 0, NULL, NULL)))
-               acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
-                                   acpi_bus_device_attach, NULL, NULL, NULL);
-
-       return error;
-}
-EXPORT_SYMBOL(acpi_bus_scan);
-
-static acpi_status acpi_bus_device_detach(acpi_handle handle, u32 lvl_not_used,
-                                         void *not_used, void **ret_not_used)
-{
-       struct acpi_device *device = NULL;
-
-       if (!acpi_bus_get_device(handle, &device)) {
-               struct acpi_scan_handler *dev_handler = device->handler;
-
-               if (dev_handler) {
-                       if (dev_handler->detach)
-                               dev_handler->detach(device);
-
-                       device->handler = NULL;
-               } else {
-                       device_release_driver(&device->dev);
-               }
+       if (device) {
+               acpi_bus_attach(device);
+               return 0;
        }
-       return AE_OK;
-}
-
-static acpi_status acpi_bus_remove(acpi_handle handle, u32 lvl_not_used,
-                                  void *not_used, void **ret_not_used)
-{
-       struct acpi_device *device = NULL;
-
-       if (!acpi_bus_get_device(handle, &device))
-               acpi_device_unregister(device);
-
-       return AE_OK;
+       return -ENODEV;
 }
+EXPORT_SYMBOL(acpi_bus_scan);
 
 /**
- * acpi_bus_trim - Remove ACPI device node and all of its descendants
- * @start: Root of the ACPI device nodes subtree to remove.
+ * acpi_bus_trim - Detach scan handlers and drivers from ACPI device objects.
+ * @adev: Root of the ACPI namespace scope to walk.
  *
  * Must be called under acpi_scan_lock.
  */
-void acpi_bus_trim(struct acpi_device *start)
+void acpi_bus_trim(struct acpi_device *adev)
 {
+       struct acpi_scan_handler *handler = adev->handler;
+       struct acpi_device *child;
+
+       list_for_each_entry_reverse(child, &adev->children, node)
+               acpi_bus_trim(child);
+
+       if (handler) {
+               if (handler->detach)
+                       handler->detach(adev);
+
+               adev->handler = NULL;
+       } else {
+               device_release_driver(&adev->dev);
+       }
        /*
-        * Execute acpi_bus_device_detach() as a post-order callback to detach
-        * all ACPI drivers from the device nodes being removed.
-        */
-       acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL,
-                           acpi_bus_device_detach, NULL, NULL);
-       acpi_bus_device_detach(start->handle, 0, NULL, NULL);
-       /*
-        * Execute acpi_bus_remove() as a post-order callback to remove device
-        * nodes in the given namespace scope.
+        * Most likely, the device is going away, so put it into D3cold before
+        * that.
         */
-       acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL,
-                           acpi_bus_remove, NULL, NULL);
-       acpi_bus_remove(start->handle, 0, NULL, NULL);
+       acpi_device_set_power(adev, ACPI_STATE_D3_COLD);
+       adev->flags.initialized = false;
+       adev->flags.visited = false;
 }
 EXPORT_SYMBOL_GPL(acpi_bus_trim);
 
@@ -2047,14 +2079,14 @@ int __init acpi_scan_init(void)
 
        result = acpi_bus_scan_fixed();
        if (result) {
-               acpi_device_unregister(acpi_root);
+               acpi_detach_data(acpi_root->handle, acpi_scan_drop_device);
+               acpi_device_del(acpi_root);
+               put_device(&acpi_root->dev);
                goto out;
        }
 
        acpi_update_all_gpes();
 
-       acpi_pci_root_hp_init();
-
  out:
        mutex_unlock(&acpi_scan_lock);
        return result;
index 721e949e606edff0e2b62dc1e4d12e201bbbad4d..208ac8c8503a7c6e702b99ca033da56b3aef935f 100644 (file)
 #include <linux/reboot.h>
 #include <linux/acpi.h>
 #include <linux/module.h>
-
 #include <asm/io.h>
 
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
-
 #include "internal.h"
 #include "sleep.h"
 
index 6dbc3ca45223a1ba30f995f016ecd965dd4861f7..443dc9366052f623b14b6ce278a2bafff81e15ac 100644 (file)
@@ -5,7 +5,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/moduleparam.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
 
 #include "internal.h"
 
index 0d9f46b5ae6d100a64ca3c3410ab23ac2af361fe..1fd21ad69c98f5613743922d6a61224359c18e94 100644 (file)
 #include <linux/kmod.h>
 #include <linux/reboot.h>
 #include <linux/device.h>
-#include <asm/uaccess.h>
 #include <linux/thermal.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
+#include <asm/uaccess.h>
 
 #define PREFIX "ACPI: "
 
index 6d408bfbbb1d0c66dbef28d02137dbda0777d9f4..1336b9151479dd1cab2fa7972c2ba04996d7762c 100644 (file)
@@ -30,8 +30,6 @@
 #include <linux/types.h>
 #include <linux/hardirq.h>
 #include <linux/acpi.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
 
 #include "internal.h"
 
index 995e91bcb97b7b4d5f21d585de1f5a7e46bd9ebd..b727d105046d234ae8ef2a5669e53e61b82e7123 100644 (file)
 #include <linux/pci.h>
 #include <linux/pci_ids.h>
 #include <linux/slab.h>
-#include <asm/uaccess.h>
 #include <linux/dmi.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
 #include <linux/suspend.h>
+#include <linux/acpi.h>
 #include <acpi/video.h>
+#include <asm/uaccess.h>
 
 #include "internal.h"
 
index 7bfbe40bc43bcb5e736c4c77788d4b7d577de160..1638401ab282ef2dc554fff498ebaba8babf8daf 100644 (file)
@@ -5,7 +5,6 @@
 
 #include <linux/init.h>
 #include <linux/acpi.h>
-#include <acpi/acpi_drivers.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 
index c4876ac9151a56bc95a05df647e0850cea3182c4..9e602910560725acb6a2df4da885bde5312c9919 100644 (file)
@@ -83,162 +83,6 @@ static struct device_attribute amba_dev_attrs[] = {
        __ATTR_NULL,
 };
 
-#ifdef CONFIG_PM_SLEEP
-
-static int amba_legacy_suspend(struct device *dev, pm_message_t mesg)
-{
-       struct amba_driver *adrv = to_amba_driver(dev->driver);
-       struct amba_device *adev = to_amba_device(dev);
-       int ret = 0;
-
-       if (dev->driver && adrv->suspend)
-               ret = adrv->suspend(adev, mesg);
-
-       return ret;
-}
-
-static int amba_legacy_resume(struct device *dev)
-{
-       struct amba_driver *adrv = to_amba_driver(dev->driver);
-       struct amba_device *adev = to_amba_device(dev);
-       int ret = 0;
-
-       if (dev->driver && adrv->resume)
-               ret = adrv->resume(adev);
-
-       return ret;
-}
-
-#endif /* CONFIG_PM_SLEEP */
-
-#ifdef CONFIG_SUSPEND
-
-static int amba_pm_suspend(struct device *dev)
-{
-       struct device_driver *drv = dev->driver;
-       int ret = 0;
-
-       if (!drv)
-               return 0;
-
-       if (drv->pm) {
-               if (drv->pm->suspend)
-                       ret = drv->pm->suspend(dev);
-       } else {
-               ret = amba_legacy_suspend(dev, PMSG_SUSPEND);
-       }
-
-       return ret;
-}
-
-static int amba_pm_resume(struct device *dev)
-{
-       struct device_driver *drv = dev->driver;
-       int ret = 0;
-
-       if (!drv)
-               return 0;
-
-       if (drv->pm) {
-               if (drv->pm->resume)
-                       ret = drv->pm->resume(dev);
-       } else {
-               ret = amba_legacy_resume(dev);
-       }
-
-       return ret;
-}
-
-#else /* !CONFIG_SUSPEND */
-
-#define amba_pm_suspend                NULL
-#define amba_pm_resume         NULL
-
-#endif /* !CONFIG_SUSPEND */
-
-#ifdef CONFIG_HIBERNATE_CALLBACKS
-
-static int amba_pm_freeze(struct device *dev)
-{
-       struct device_driver *drv = dev->driver;
-       int ret = 0;
-
-       if (!drv)
-               return 0;
-
-       if (drv->pm) {
-               if (drv->pm->freeze)
-                       ret = drv->pm->freeze(dev);
-       } else {
-               ret = amba_legacy_suspend(dev, PMSG_FREEZE);
-       }
-
-       return ret;
-}
-
-static int amba_pm_thaw(struct device *dev)
-{
-       struct device_driver *drv = dev->driver;
-       int ret = 0;
-
-       if (!drv)
-               return 0;
-
-       if (drv->pm) {
-               if (drv->pm->thaw)
-                       ret = drv->pm->thaw(dev);
-       } else {
-               ret = amba_legacy_resume(dev);
-       }
-
-       return ret;
-}
-
-static int amba_pm_poweroff(struct device *dev)
-{
-       struct device_driver *drv = dev->driver;
-       int ret = 0;
-
-       if (!drv)
-               return 0;
-
-       if (drv->pm) {
-               if (drv->pm->poweroff)
-                       ret = drv->pm->poweroff(dev);
-       } else {
-               ret = amba_legacy_suspend(dev, PMSG_HIBERNATE);
-       }
-
-       return ret;
-}
-
-static int amba_pm_restore(struct device *dev)
-{
-       struct device_driver *drv = dev->driver;
-       int ret = 0;
-
-       if (!drv)
-               return 0;
-
-       if (drv->pm) {
-               if (drv->pm->restore)
-                       ret = drv->pm->restore(dev);
-       } else {
-               ret = amba_legacy_resume(dev);
-       }
-
-       return ret;
-}
-
-#else /* !CONFIG_HIBERNATE_CALLBACKS */
-
-#define amba_pm_freeze         NULL
-#define amba_pm_thaw           NULL
-#define amba_pm_poweroff               NULL
-#define amba_pm_restore                NULL
-
-#endif /* !CONFIG_HIBERNATE_CALLBACKS */
-
 #ifdef CONFIG_PM_RUNTIME
 /*
  * Hooks to provide runtime PM of the pclk (bus clock).  It is safe to
@@ -251,7 +95,7 @@ static int amba_pm_runtime_suspend(struct device *dev)
        int ret = pm_generic_runtime_suspend(dev);
 
        if (ret == 0 && dev->driver)
-               clk_disable(pcdev->pclk);
+               clk_disable_unprepare(pcdev->pclk);
 
        return ret;
 }
@@ -262,7 +106,7 @@ static int amba_pm_runtime_resume(struct device *dev)
        int ret;
 
        if (dev->driver) {
-               ret = clk_enable(pcdev->pclk);
+               ret = clk_prepare_enable(pcdev->pclk);
                /* Failure is probably fatal to the system, but... */
                if (ret)
                        return ret;
@@ -272,15 +116,13 @@ static int amba_pm_runtime_resume(struct device *dev)
 }
 #endif
 
-#ifdef CONFIG_PM
-
 static const struct dev_pm_ops amba_pm = {
-       .suspend        = amba_pm_suspend,
-       .resume         = amba_pm_resume,
-       .freeze         = amba_pm_freeze,
-       .thaw           = amba_pm_thaw,
-       .poweroff       = amba_pm_poweroff,
-       .restore        = amba_pm_restore,
+       .suspend        = pm_generic_suspend,
+       .resume         = pm_generic_resume,
+       .freeze         = pm_generic_freeze,
+       .thaw           = pm_generic_thaw,
+       .poweroff       = pm_generic_poweroff,
+       .restore        = pm_generic_restore,
        SET_RUNTIME_PM_OPS(
                amba_pm_runtime_suspend,
                amba_pm_runtime_resume,
@@ -288,14 +130,6 @@ static const struct dev_pm_ops amba_pm = {
        )
 };
 
-#define AMBA_PM (&amba_pm)
-
-#else /* !CONFIG_PM */
-
-#define AMBA_PM        NULL
-
-#endif /* !CONFIG_PM */
-
 /*
  * Primecells are part of the Advanced Microcontroller Bus Architecture,
  * so we call the bus "amba".
@@ -305,7 +139,7 @@ struct bus_type amba_bustype = {
        .dev_attrs      = amba_dev_attrs,
        .match          = amba_match,
        .uevent         = amba_uevent,
-       .pm             = AMBA_PM,
+       .pm             = &amba_pm,
 };
 
 static int __init amba_init(void)
@@ -317,36 +151,23 @@ postcore_initcall(amba_init);
 
 static int amba_get_enable_pclk(struct amba_device *pcdev)
 {
-       struct clk *pclk = clk_get(&pcdev->dev, "apb_pclk");
        int ret;
 
-       pcdev->pclk = pclk;
-
-       if (IS_ERR(pclk))
-               return PTR_ERR(pclk);
+       pcdev->pclk = clk_get(&pcdev->dev, "apb_pclk");
+       if (IS_ERR(pcdev->pclk))
+               return PTR_ERR(pcdev->pclk);
 
-       ret = clk_prepare(pclk);
-       if (ret) {
-               clk_put(pclk);
-               return ret;
-       }
-
-       ret = clk_enable(pclk);
-       if (ret) {
-               clk_unprepare(pclk);
-               clk_put(pclk);
-       }
+       ret = clk_prepare_enable(pcdev->pclk);
+       if (ret)
+               clk_put(pcdev->pclk);
 
        return ret;
 }
 
 static void amba_put_disable_pclk(struct amba_device *pcdev)
 {
-       struct clk *pclk = pcdev->pclk;
-
-       clk_disable(pclk);
-       clk_unprepare(pclk);
-       clk_put(pclk);
+       clk_disable_unprepare(pcdev->pclk);
+       clk_put(pcdev->pclk);
 }
 
 /*
index 14f1e95063380a5e2a315428fc8a4d5e8bcc39d3..ef8642e12a7627e364b92ff4002a7ed632d209db 100644 (file)
@@ -83,6 +83,8 @@ enum board_ids {
 static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
 static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
                                 unsigned long deadline);
+static void ahci_mcp89_apple_enable(struct pci_dev *pdev);
+static bool is_mcp89_apple(struct pci_dev *pdev);
 static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
                                unsigned long deadline);
 #ifdef CONFIG_PM
@@ -661,6 +663,10 @@ static int ahci_pci_device_resume(struct pci_dev *pdev)
        if (rc)
                return rc;
 
+       /* Apple BIOS helpfully mangles the registers on resume */
+       if (is_mcp89_apple(pdev))
+               ahci_mcp89_apple_enable(pdev);
+
        if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
                rc = ahci_pci_reset_controller(host);
                if (rc)
@@ -777,6 +783,48 @@ static void ahci_p5wdh_workaround(struct ata_host *host)
        }
 }
 
+/*
+ * Macbook7,1 firmware forcibly disables MCP89 AHCI and changes PCI ID when
+ * booting in BIOS compatibility mode.  We restore the registers but not ID.
+ */
+static void ahci_mcp89_apple_enable(struct pci_dev *pdev)
+{
+       u32 val;
+
+       printk(KERN_INFO "ahci: enabling MCP89 AHCI mode\n");
+
+       pci_read_config_dword(pdev, 0xf8, &val);
+       val |= 1 << 0x1b;
+       /* the following changes the device ID, but appears not to affect function */
+       /* val = (val & ~0xf0000000) | 0x80000000; */
+       pci_write_config_dword(pdev, 0xf8, val);
+
+       pci_read_config_dword(pdev, 0x54c, &val);
+       val |= 1 << 0xc;
+       pci_write_config_dword(pdev, 0x54c, val);
+
+       pci_read_config_dword(pdev, 0x4a4, &val);
+       val &= 0xff;
+       val |= 0x01060100;
+       pci_write_config_dword(pdev, 0x4a4, val);
+
+       pci_read_config_dword(pdev, 0x54c, &val);
+       val &= ~(1 << 0xc);
+       pci_write_config_dword(pdev, 0x54c, val);
+
+       pci_read_config_dword(pdev, 0xf8, &val);
+       val &= ~(1 << 0x1b);
+       pci_write_config_dword(pdev, 0xf8, val);
+}
+
+static bool is_mcp89_apple(struct pci_dev *pdev)
+{
+       return pdev->vendor == PCI_VENDOR_ID_NVIDIA &&
+               pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA &&
+               pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE &&
+               pdev->subsystem_device == 0xcb89;
+}
+
 /* only some SB600 ahci controllers can do 64bit DMA */
 static bool ahci_sb600_enable_64bit(struct pci_dev *pdev)
 {
@@ -1209,15 +1257,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable)
                return -ENODEV;
 
-       /*
-        * For some reason, MCP89 on MacBook 7,1 doesn't work with
-        * ahci, use ata_generic instead.
-        */
-       if (pdev->vendor == PCI_VENDOR_ID_NVIDIA &&
-           pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA &&
-           pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE &&
-           pdev->subsystem_device == 0xcb89)
-               return -ENODEV;
+       /* Apple BIOS on MCP89 prevents us using AHCI */
+       if (is_mcp89_apple(pdev))
+               ahci_mcp89_apple_enable(pdev);
 
        /* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode.
         * At the moment, we can only use the AHCI mode. Let the users know
index ae2d73fe321e2f2c62d8e5709a788905edfd5a89..2daa28891b7f466864ae8874a83f764d9e29675c 100644 (file)
@@ -34,10 +34,21 @@ enum {
        HOST_TIMER1MS = 0xe0,                   /* Timer 1-ms */
 };
 
+enum ahci_imx_type {
+       AHCI_IMX53,
+       AHCI_IMX6Q,
+};
+
 struct imx_ahci_priv {
        struct platform_device *ahci_pdev;
+       enum ahci_imx_type type;
+
+       /* i.MX53 clock */
+       struct clk *sata_gate_clk;
+       /* Common clock */
        struct clk *sata_ref_clk;
        struct clk *ahb_clk;
+
        struct regmap *gpr;
        bool no_device;
        bool first_time;
@@ -47,6 +58,59 @@ static int ahci_imx_hotplug;
 module_param_named(hotplug, ahci_imx_hotplug, int, 0644);
 MODULE_PARM_DESC(hotplug, "AHCI IMX hot-plug support (0=Don't support, 1=support)");
 
+static int imx_sata_clock_enable(struct device *dev)
+{
+       struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);
+       int ret;
+
+       if (imxpriv->type == AHCI_IMX53) {
+               ret = clk_prepare_enable(imxpriv->sata_gate_clk);
+               if (ret < 0) {
+                       dev_err(dev, "prepare-enable sata_gate clock err:%d\n",
+                               ret);
+                       return ret;
+               }
+       }
+
+       ret = clk_prepare_enable(imxpriv->sata_ref_clk);
+       if (ret < 0) {
+               dev_err(dev, "prepare-enable sata_ref clock err:%d\n",
+                       ret);
+               goto clk_err;
+       }
+
+       if (imxpriv->type == AHCI_IMX6Q) {
+               regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
+                                  IMX6Q_GPR13_SATA_MPLL_CLK_EN,
+                                  IMX6Q_GPR13_SATA_MPLL_CLK_EN);
+       }
+
+       usleep_range(1000, 2000);
+
+       return 0;
+
+clk_err:
+       if (imxpriv->type == AHCI_IMX53)
+               clk_disable_unprepare(imxpriv->sata_gate_clk);
+       return ret;
+}
+
+static void imx_sata_clock_disable(struct device *dev)
+{
+       struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);
+
+       if (imxpriv->type == AHCI_IMX6Q) {
+               regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
+                                  IMX6Q_GPR13_SATA_MPLL_CLK_EN,
+                                  !IMX6Q_GPR13_SATA_MPLL_CLK_EN);
+       }
+
+       clk_disable_unprepare(imxpriv->sata_ref_clk);
+
+       if (imxpriv->type == AHCI_IMX53)
+               clk_disable_unprepare(imxpriv->sata_gate_clk);
+}
+
 static void ahci_imx_error_handler(struct ata_port *ap)
 {
        u32 reg_val;
@@ -72,16 +136,29 @@ static void ahci_imx_error_handler(struct ata_port *ap)
         */
        reg_val = readl(mmio + PORT_PHY_CTL);
        writel(reg_val | PORT_PHY_CTL_PDDQ_LOC, mmio + PORT_PHY_CTL);
-       regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
-                       IMX6Q_GPR13_SATA_MPLL_CLK_EN,
-                       !IMX6Q_GPR13_SATA_MPLL_CLK_EN);
-       clk_disable_unprepare(imxpriv->sata_ref_clk);
+       imx_sata_clock_disable(ap->dev);
        imxpriv->no_device = true;
 }
 
+static int ahci_imx_softreset(struct ata_link *link, unsigned int *class,
+                      unsigned long deadline)
+{
+       struct ata_port *ap = link->ap;
+       struct imx_ahci_priv *imxpriv = dev_get_drvdata(ap->dev->parent);
+       int ret = -EIO;
+
+       if (imxpriv->type == AHCI_IMX53)
+               ret = ahci_pmp_retry_srst_ops.softreset(link, class, deadline);
+       else if (imxpriv->type == AHCI_IMX6Q)
+               ret = ahci_ops.softreset(link, class, deadline);
+
+       return ret;
+}
+
 static struct ata_port_operations ahci_imx_ops = {
        .inherits       = &ahci_platform_ops,
        .error_handler  = ahci_imx_error_handler,
+       .softreset      = ahci_imx_softreset,
 };
 
 static const struct ata_port_info ahci_imx_port_info = {
@@ -91,51 +168,15 @@ static const struct ata_port_info ahci_imx_port_info = {
        .port_ops       = &ahci_imx_ops,
 };
 
-static int imx6q_sata_init(struct device *dev, void __iomem *mmio)
+static int imx_sata_init(struct device *dev, void __iomem *mmio)
 {
        int ret = 0;
        unsigned int reg_val;
        struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);
 
-       imxpriv->gpr =
-               syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
-       if (IS_ERR(imxpriv->gpr)) {
-               dev_err(dev, "failed to find fsl,imx6q-iomux-gpr regmap\n");
-               return PTR_ERR(imxpriv->gpr);
-       }
-
-       ret = clk_prepare_enable(imxpriv->sata_ref_clk);
-       if (ret < 0) {
-               dev_err(dev, "prepare-enable sata_ref clock err:%d\n", ret);
+       ret = imx_sata_clock_enable(dev);
+       if (ret < 0)
                return ret;
-       }
-
-       /*
-        * set PHY Paremeters, two steps to configure the GPR13,
-        * one write for rest of parameters, mask of first write
-        * is 0x07fffffd, and the other one write for setting
-        * the mpll_clk_en.
-        */
-       regmap_update_bits(imxpriv->gpr, 0x34, IMX6Q_GPR13_SATA_RX_EQ_VAL_MASK
-                       | IMX6Q_GPR13_SATA_RX_LOS_LVL_MASK
-                       | IMX6Q_GPR13_SATA_RX_DPLL_MODE_MASK
-                       | IMX6Q_GPR13_SATA_SPD_MODE_MASK
-                       | IMX6Q_GPR13_SATA_MPLL_SS_EN
-                       | IMX6Q_GPR13_SATA_TX_ATTEN_MASK
-                       | IMX6Q_GPR13_SATA_TX_BOOST_MASK
-                       | IMX6Q_GPR13_SATA_TX_LVL_MASK
-                       | IMX6Q_GPR13_SATA_TX_EDGE_RATE
-                       , IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB
-                       | IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M
-                       | IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F
-                       | IMX6Q_GPR13_SATA_SPD_MODE_3P0G
-                       | IMX6Q_GPR13_SATA_MPLL_SS_EN
-                       | IMX6Q_GPR13_SATA_TX_ATTEN_9_16
-                       | IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB
-                       | IMX6Q_GPR13_SATA_TX_LVL_1_025_V);
-       regmap_update_bits(imxpriv->gpr, 0x34, IMX6Q_GPR13_SATA_MPLL_CLK_EN,
-                       IMX6Q_GPR13_SATA_MPLL_CLK_EN);
-       usleep_range(100, 200);
 
        /*
         * Configure the HWINIT bits of the HOST_CAP and HOST_PORTS_IMPL,
@@ -161,13 +202,9 @@ static int imx6q_sata_init(struct device *dev, void __iomem *mmio)
        return 0;
 }
 
-static void imx6q_sata_exit(struct device *dev)
+static void imx_sata_exit(struct device *dev)
 {
-       struct imx_ahci_priv *imxpriv =  dev_get_drvdata(dev->parent);
-
-       regmap_update_bits(imxpriv->gpr, 0x34, IMX6Q_GPR13_SATA_MPLL_CLK_EN,
-                       !IMX6Q_GPR13_SATA_MPLL_CLK_EN);
-       clk_disable_unprepare(imxpriv->sata_ref_clk);
+       imx_sata_clock_disable(dev);
 }
 
 static int imx_ahci_suspend(struct device *dev)
@@ -178,12 +215,8 @@ static int imx_ahci_suspend(struct device *dev)
         * If no_device is set, The CLKs had been gated off in the
         * initialization so don't do it again here.
         */
-       if (!imxpriv->no_device) {
-               regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
-                               IMX6Q_GPR13_SATA_MPLL_CLK_EN,
-                               !IMX6Q_GPR13_SATA_MPLL_CLK_EN);
-               clk_disable_unprepare(imxpriv->sata_ref_clk);
-       }
+       if (!imxpriv->no_device)
+               imx_sata_clock_disable(dev);
 
        return 0;
 }
@@ -191,34 +224,26 @@ static int imx_ahci_suspend(struct device *dev)
 static int imx_ahci_resume(struct device *dev)
 {
        struct imx_ahci_priv *imxpriv =  dev_get_drvdata(dev->parent);
-       int ret;
-
-       if (!imxpriv->no_device) {
-               ret = clk_prepare_enable(imxpriv->sata_ref_clk);
-               if (ret < 0) {
-                       dev_err(dev, "pre-enable sata_ref clock err:%d\n", ret);
-                       return ret;
-               }
+       int ret = 0;
 
-               regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
-                               IMX6Q_GPR13_SATA_MPLL_CLK_EN,
-                               IMX6Q_GPR13_SATA_MPLL_CLK_EN);
-               usleep_range(1000, 2000);
-       }
+       if (!imxpriv->no_device)
+               ret = imx_sata_clock_enable(dev);
 
-       return 0;
+       return ret;
 }
 
-static struct ahci_platform_data imx6q_sata_pdata = {
-       .init = imx6q_sata_init,
-       .exit = imx6q_sata_exit,
-       .ata_port_info = &ahci_imx_port_info,
-       .suspend = imx_ahci_suspend,
-       .resume = imx_ahci_resume,
+static struct ahci_platform_data imx_sata_pdata = {
+       .init           = imx_sata_init,
+       .exit           = imx_sata_exit,
+       .ata_port_info  = &ahci_imx_port_info,
+       .suspend        = imx_ahci_suspend,
+       .resume         = imx_ahci_resume,
+
 };
 
 static const struct of_device_id imx_ahci_of_match[] = {
-       { .compatible = "fsl,imx6q-ahci", .data = &imx6q_sata_pdata},
+       { .compatible = "fsl,imx53-ahci", .data = (void *)AHCI_IMX53 },
+       { .compatible = "fsl,imx6q-ahci", .data = (void *)AHCI_IMX6Q },
        {},
 };
 MODULE_DEVICE_TABLE(of, imx_ahci_of_match);
@@ -228,12 +253,20 @@ static int imx_ahci_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        struct resource *mem, *irq, res[2];
        const struct of_device_id *of_id;
+       enum ahci_imx_type type;
        const struct ahci_platform_data *pdata = NULL;
        struct imx_ahci_priv *imxpriv;
        struct device *ahci_dev;
        struct platform_device *ahci_pdev;
        int ret;
 
+       of_id = of_match_device(imx_ahci_of_match, dev);
+       if (!of_id)
+               return -EINVAL;
+
+       type = (enum ahci_imx_type)of_id->data;
+       pdata = &imx_sata_pdata;
+
        imxpriv = devm_kzalloc(dev, sizeof(*imxpriv), GFP_KERNEL);
        if (!imxpriv) {
                dev_err(dev, "can't alloc ahci_host_priv\n");
@@ -249,6 +282,8 @@ static int imx_ahci_probe(struct platform_device *pdev)
 
        imxpriv->no_device = false;
        imxpriv->first_time = true;
+       imxpriv->type = type;
+
        imxpriv->ahb_clk = devm_clk_get(dev, "ahb");
        if (IS_ERR(imxpriv->ahb_clk)) {
                dev_err(dev, "can't get ahb clock.\n");
@@ -256,6 +291,15 @@ static int imx_ahci_probe(struct platform_device *pdev)
                goto err_out;
        }
 
+       if (type == AHCI_IMX53) {
+               imxpriv->sata_gate_clk = devm_clk_get(dev, "sata_gate");
+               if (IS_ERR(imxpriv->sata_gate_clk)) {
+                       dev_err(dev, "can't get sata_gate clock.\n");
+                       ret = PTR_ERR(imxpriv->sata_gate_clk);
+                       goto err_out;
+               }
+       }
+
        imxpriv->sata_ref_clk = devm_clk_get(dev, "sata_ref");
        if (IS_ERR(imxpriv->sata_ref_clk)) {
                dev_err(dev, "can't get sata_ref clock.\n");
@@ -266,14 +310,6 @@ static int imx_ahci_probe(struct platform_device *pdev)
        imxpriv->ahci_pdev = ahci_pdev;
        platform_set_drvdata(pdev, imxpriv);
 
-       of_id = of_match_device(imx_ahci_of_match, dev);
-       if (of_id) {
-               pdata = of_id->data;
-       } else {
-               ret = -EINVAL;
-               goto err_out;
-       }
-
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
        if (!mem || !irq) {
@@ -289,6 +325,42 @@ static int imx_ahci_probe(struct platform_device *pdev)
        ahci_dev->dma_mask = &ahci_dev->coherent_dma_mask;
        ahci_dev->of_node = dev->of_node;
 
+       if (type == AHCI_IMX6Q) {
+               imxpriv->gpr = syscon_regmap_lookup_by_compatible(
+                                                       "fsl,imx6q-iomuxc-gpr");
+               if (IS_ERR(imxpriv->gpr)) {
+                       dev_err(dev,
+                               "failed to find fsl,imx6q-iomux-gpr regmap\n");
+                       return PTR_ERR(imxpriv->gpr);
+               }
+
+               /*
+                * Set PHY Paremeters, two steps to configure the GPR13,
+                * one write for rest of parameters, mask of first write
+                * is 0x07fffffe, and the other one write for setting
+                * the mpll_clk_en happens in imx_sata_clock_enable().
+                */
+               regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
+                                  IMX6Q_GPR13_SATA_RX_EQ_VAL_MASK |
+                                  IMX6Q_GPR13_SATA_RX_LOS_LVL_MASK |
+                                  IMX6Q_GPR13_SATA_RX_DPLL_MODE_MASK |
+                                  IMX6Q_GPR13_SATA_SPD_MODE_MASK |
+                                  IMX6Q_GPR13_SATA_MPLL_SS_EN |
+                                  IMX6Q_GPR13_SATA_TX_ATTEN_MASK |
+                                  IMX6Q_GPR13_SATA_TX_BOOST_MASK |
+                                  IMX6Q_GPR13_SATA_TX_LVL_MASK |
+                                  IMX6Q_GPR13_SATA_MPLL_CLK_EN |
+                                  IMX6Q_GPR13_SATA_TX_EDGE_RATE,
+                                  IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB |
+                                  IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M |
+                                  IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F |
+                                  IMX6Q_GPR13_SATA_SPD_MODE_3P0G |
+                                  IMX6Q_GPR13_SATA_MPLL_SS_EN |
+                                  IMX6Q_GPR13_SATA_TX_ATTEN_9_16 |
+                                  IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB |
+                                  IMX6Q_GPR13_SATA_TX_LVL_1_025_V);
+       }
+
        ret = platform_device_add_resources(ahci_pdev, res, 2);
        if (ret)
                goto err_out;
index f8f38a08abc570e271b487f3ab761d26ceef0f27..7d196656adb5581533517a6ed0ec49d8c2966b58 100644 (file)
@@ -221,13 +221,6 @@ static struct pci_device_id ata_generic[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_OPTI,   PCI_DEVICE_ID_OPTI_82C558), },
        { PCI_DEVICE(PCI_VENDOR_ID_CENATEK,PCI_DEVICE_ID_CENATEK_IDE),
          .driver_data = ATA_GEN_FORCE_DMA },
-       /*
-        * For some reason, MCP89 on MacBook 7,1 doesn't work with
-        * ahci, use ata_generic instead.
-        */
-       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA,
-         PCI_VENDOR_ID_APPLE, 0xcb89,
-         .driver_data = ATA_GEN_FORCE_DMA },
 #if !defined(CONFIG_PATA_TOSHIBA) && !defined(CONFIG_PATA_TOSHIBA_MODULE)
        { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1), },
        { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2),  },
index 4372cfa883c9c36cf2624f88186ef3e0e7b27d31..9e69a5308693de59abd5c596244033af43f7b3a8 100644 (file)
@@ -20,8 +20,6 @@
 #include <scsi/scsi_device.h>
 #include "libata.h"
 
-#include <acpi/acpi_bus.h>
-
 unsigned int ata_acpi_gtf_filter = ATA_ACPI_FILTER_DEFAULT;
 module_param_named(acpi_gtf_filter, ata_acpi_gtf_filter, int, 0644);
 MODULE_PARM_DESC(acpi_gtf_filter, "filter mask for ACPI _GTF commands, set to filter out (0x1=set xfermode, 0x2=lock/freeze lock, 0x4=DIPM, 0x8=FPDMA non-zero offset, 0x10=FPDMA DMA Setup FIS auto-activate)");
@@ -180,12 +178,12 @@ static const struct acpi_dock_ops ata_acpi_ap_dock_ops = {
 /* bind acpi handle to pata port */
 void ata_acpi_bind_port(struct ata_port *ap)
 {
-       acpi_handle host_handle = ACPI_HANDLE(ap->host->dev);
+       struct acpi_device *host_companion = ACPI_COMPANION(ap->host->dev);
 
-       if (libata_noacpi || ap->flags & ATA_FLAG_ACPI_SATA || !host_handle)
+       if (libata_noacpi || ap->flags & ATA_FLAG_ACPI_SATA || !host_companion)
                return;
 
-       acpi_preset_companion(&ap->tdev, host_handle, ap->port_no);
+       acpi_preset_companion(&ap->tdev, host_companion, ap->port_no);
 
        if (ata_acpi_gtm(ap, &ap->__acpi_init_gtm) == 0)
                ap->pflags |= ATA_PFLAG_INIT_GTM_VALID;
@@ -198,17 +196,17 @@ void ata_acpi_bind_port(struct ata_port *ap)
 void ata_acpi_bind_dev(struct ata_device *dev)
 {
        struct ata_port *ap = dev->link->ap;
-       acpi_handle port_handle = ACPI_HANDLE(&ap->tdev);
-       acpi_handle host_handle = ACPI_HANDLE(ap->host->dev);
-       acpi_handle parent_handle;
+       struct acpi_device *port_companion = ACPI_COMPANION(&ap->tdev);
+       struct acpi_device *host_companion = ACPI_COMPANION(ap->host->dev);
+       struct acpi_device *parent;
        u64 adr;
 
        /*
-        * For both sata/pata devices, host handle is required.
-        * For pata device, port handle is also required.
+        * For both sata/pata devices, host companion device is required.
+        * For pata device, port companion device is also required.
         */
-       if (libata_noacpi || !host_handle ||
-                       (!(ap->flags & ATA_FLAG_ACPI_SATA) && !port_handle))
+       if (libata_noacpi || !host_companion ||
+                       (!(ap->flags & ATA_FLAG_ACPI_SATA) && !port_companion))
                return;
 
        if (ap->flags & ATA_FLAG_ACPI_SATA) {
@@ -216,13 +214,13 @@ void ata_acpi_bind_dev(struct ata_device *dev)
                        adr = SATA_ADR(ap->port_no, NO_PORT_MULT);
                else
                        adr = SATA_ADR(ap->port_no, dev->link->pmp);
-               parent_handle = host_handle;
+               parent = host_companion;
        } else {
                adr = dev->devno;
-               parent_handle = port_handle;
+               parent = port_companion;
        }
 
-       acpi_preset_companion(&dev->tdev, parent_handle, adr);
+       acpi_preset_companion(&dev->tdev, parent, adr);
 
        register_hotplug_dock_device(ata_dev_acpi_handle(dev),
                                     &ata_acpi_dev_dock_ops, dev, NULL, NULL);
index 75b93678bbcd7f4231e0c2028995795487db671c..dae73efe5dbf7efc4ea40cd0ee5c27958b12c5f3 100644 (file)
@@ -4156,6 +4156,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        { "ST3320[68]13AS",     "SD1[5-9]",     ATA_HORKAGE_NONCQ |
                                                ATA_HORKAGE_FIRMWARE_WARN },
 
+       /* Seagate Momentus SpinPoint M8 seem to have FPMDA_AA issues */
+       { "ST1000LM024 HN-M101MBB", "2AR10001", ATA_HORKAGE_BROKEN_FPDMA_AA },
+
        /* Blacklist entries taken from Silicon Image 3124/3132
           Windows driver .inf file - also several Linux problem reports */
        { "HTS541060G9SA00",    "MB3OC60D",     ATA_HORKAGE_NONCQ, },
index 92d7797223be12c41fb8cbcef92035781a779111..6d87570083187bbbe749fe566195f854707a641c 100644 (file)
@@ -2402,7 +2402,7 @@ static void ata_eh_link_report(struct ata_link *link)
        struct ata_port *ap = link->ap;
        struct ata_eh_context *ehc = &link->eh_context;
        const char *frozen, *desc;
-       char tries_buf[6];
+       char tries_buf[6] = "";
        int tag, nr_failed = 0;
 
        if (ehc->i.flags & ATA_EHI_QUIET)
@@ -2433,9 +2433,8 @@ static void ata_eh_link_report(struct ata_link *link)
        if (ap->pflags & ATA_PFLAG_FROZEN)
                frozen = " frozen";
 
-       memset(tries_buf, 0, sizeof(tries_buf));
        if (ap->eh_tries < ATA_EH_MAX_TRIES)
-               snprintf(tries_buf, sizeof(tries_buf) - 1, " t%d",
+               snprintf(tries_buf, sizeof(tries_buf), " t%d",
                         ap->eh_tries);
 
        if (ehc->i.dev) {
index db6dfcfa3e2ee932190069290814f2a71bc8f3f6..ab58556d347c19120c9724389583c2ae67a2d81e 100644 (file)
@@ -3625,6 +3625,7 @@ int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht)
                shost->max_lun = 1;
                shost->max_channel = 1;
                shost->max_cmd_len = 16;
+               shost->no_write_same = 1;
 
                /* Schedule policy is determined by ->qc_defer()
                 * callback and it needs to see every deferred qc.
index 73212c9c6d5bfb90b1193dddb2f30135b9edd9a9..62c9ac80c6e96ed1f0a4421fb22b7ee3629ae2e9 100644 (file)
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/gfp.h>
-#include <scsi/scsi_host.h>
-#include <acpi/acpi_bus.h>
-
+#include <linux/acpi.h>
 #include <linux/libata.h>
 #include <linux/ata.h>
+#include <scsi/scsi_host.h>
 
 #define DRV_NAME       "pata_acpi"
 #define DRV_VERSION    "0.2.3"
index 1dae9a9009f785d9e442bfac7e6552657161dd48..2b25bd83fc9d46a2682a0affb409ccf7488abe3d 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/module.h>
 #include <linux/ata.h>
 #include <linux/libata.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/err.h>
 
 #define SATA_RCAR_DMA_BOUNDARY         0x1FFFFFFEUL
 
+/* Gen2 Physical Layer Control Registers */
+#define RCAR_GEN2_PHY_CTL1_REG         0x1704
+#define RCAR_GEN2_PHY_CTL1             0x34180002
+#define RCAR_GEN2_PHY_CTL1_SS          0xC180  /* Spread Spectrum */
+
+#define RCAR_GEN2_PHY_CTL2_REG         0x170C
+#define RCAR_GEN2_PHY_CTL2             0x00002303
+
+#define RCAR_GEN2_PHY_CTL3_REG         0x171C
+#define RCAR_GEN2_PHY_CTL3             0x000B0194
+
+#define RCAR_GEN2_PHY_CTL4_REG         0x1724
+#define RCAR_GEN2_PHY_CTL4             0x00030994
+
+#define RCAR_GEN2_PHY_CTL5_REG         0x1740
+#define RCAR_GEN2_PHY_CTL5             0x03004001
+#define RCAR_GEN2_PHY_CTL5_DC          BIT(1)  /* DC connection */
+#define RCAR_GEN2_PHY_CTL5_TR          BIT(2)  /* Termination Resistor */
+
+enum sata_rcar_type {
+       RCAR_GEN1_SATA,
+       RCAR_GEN2_SATA,
+};
+
 struct sata_rcar_priv {
        void __iomem *base;
        struct clk *clk;
+       enum sata_rcar_type type;
 };
 
-static void sata_rcar_phy_initialize(struct sata_rcar_priv *priv)
+static void sata_rcar_gen1_phy_preinit(struct sata_rcar_priv *priv)
 {
        void __iomem *base = priv->base;
 
@@ -141,8 +167,8 @@ static void sata_rcar_phy_initialize(struct sata_rcar_priv *priv)
        iowrite32(0, base + SATAPHYRESET_REG);
 }
 
-static void sata_rcar_phy_write(struct sata_rcar_priv *priv, u16 reg, u32 val,
-                               int group)
+static void sata_rcar_gen1_phy_write(struct sata_rcar_priv *priv, u16 reg,
+                                    u32 val, int group)
 {
        void __iomem *base = priv->base;
        int timeout;
@@ -170,6 +196,29 @@ static void sata_rcar_phy_write(struct sata_rcar_priv *priv, u16 reg, u32 val,
        iowrite32(0, base + SATAPHYADDR_REG);
 }
 
+static void sata_rcar_gen1_phy_init(struct sata_rcar_priv *priv)
+{
+       sata_rcar_gen1_phy_preinit(priv);
+       sata_rcar_gen1_phy_write(priv, SATAPCTLR1_REG, 0x00200188, 0);
+       sata_rcar_gen1_phy_write(priv, SATAPCTLR1_REG, 0x00200188, 1);
+       sata_rcar_gen1_phy_write(priv, SATAPCTLR3_REG, 0x0000A061, 0);
+       sata_rcar_gen1_phy_write(priv, SATAPCTLR2_REG, 0x20000000, 0);
+       sata_rcar_gen1_phy_write(priv, SATAPCTLR2_REG, 0x20000000, 1);
+       sata_rcar_gen1_phy_write(priv, SATAPCTLR4_REG, 0x28E80000, 0);
+}
+
+static void sata_rcar_gen2_phy_init(struct sata_rcar_priv *priv)
+{
+       void __iomem *base = priv->base;
+
+       iowrite32(RCAR_GEN2_PHY_CTL1, base + RCAR_GEN2_PHY_CTL1_REG);
+       iowrite32(RCAR_GEN2_PHY_CTL2, base + RCAR_GEN2_PHY_CTL2_REG);
+       iowrite32(RCAR_GEN2_PHY_CTL3, base + RCAR_GEN2_PHY_CTL3_REG);
+       iowrite32(RCAR_GEN2_PHY_CTL4, base + RCAR_GEN2_PHY_CTL4_REG);
+       iowrite32(RCAR_GEN2_PHY_CTL5 | RCAR_GEN2_PHY_CTL5_DC |
+                 RCAR_GEN2_PHY_CTL5_TR, base + RCAR_GEN2_PHY_CTL5_REG);
+}
+
 static void sata_rcar_freeze(struct ata_port *ap)
 {
        struct sata_rcar_priv *priv = ap->host->private_data;
@@ -738,13 +787,17 @@ static void sata_rcar_init_controller(struct ata_host *host)
        u32 val;
 
        /* reset and setup phy */
-       sata_rcar_phy_initialize(priv);
-       sata_rcar_phy_write(priv, SATAPCTLR1_REG, 0x00200188, 0);
-       sata_rcar_phy_write(priv, SATAPCTLR1_REG, 0x00200188, 1);
-       sata_rcar_phy_write(priv, SATAPCTLR3_REG, 0x0000A061, 0);
-       sata_rcar_phy_write(priv, SATAPCTLR2_REG, 0x20000000, 0);
-       sata_rcar_phy_write(priv, SATAPCTLR2_REG, 0x20000000, 1);
-       sata_rcar_phy_write(priv, SATAPCTLR4_REG, 0x28E80000, 0);
+       switch (priv->type) {
+       case RCAR_GEN1_SATA:
+               sata_rcar_gen1_phy_init(priv);
+               break;
+       case RCAR_GEN2_SATA:
+               sata_rcar_gen2_phy_init(priv);
+               break;
+       default:
+               dev_warn(host->dev, "SATA phy is not initialized\n");
+               break;
+       }
 
        /* SATA-IP reset state */
        val = ioread32(base + ATAPI_CONTROL1_REG);
@@ -770,8 +823,40 @@ static void sata_rcar_init_controller(struct ata_host *host)
        iowrite32(ATAPI_INT_ENABLE_SATAINT, base + ATAPI_INT_ENABLE_REG);
 }
 
+static struct of_device_id sata_rcar_match[] = {
+       {
+               /* Deprecated by "renesas,sata-r8a7779" */
+               .compatible = "renesas,rcar-sata",
+               .data = (void *)RCAR_GEN1_SATA,
+       },
+       {
+               .compatible = "renesas,sata-r8a7779",
+               .data = (void *)RCAR_GEN1_SATA,
+       },
+       {
+               .compatible = "renesas,sata-r8a7790",
+               .data = (void *)RCAR_GEN2_SATA
+       },
+       {
+               .compatible = "renesas,sata-r8a7791",
+               .data = (void *)RCAR_GEN2_SATA
+       },
+       { },
+};
+MODULE_DEVICE_TABLE(of, sata_rcar_match);
+
+static const struct platform_device_id sata_rcar_id_table[] = {
+       { "sata_rcar", RCAR_GEN1_SATA }, /* Deprecated by "sata-r8a7779" */
+       { "sata-r8a7779", RCAR_GEN1_SATA },
+       { "sata-r8a7790", RCAR_GEN2_SATA },
+       { "sata-r8a7791", RCAR_GEN2_SATA },
+       { },
+};
+MODULE_DEVICE_TABLE(platform, sata_rcar_id_table);
+
 static int sata_rcar_probe(struct platform_device *pdev)
 {
+       const struct of_device_id *of_id;
        struct ata_host *host;
        struct sata_rcar_priv *priv;
        struct resource *mem;
@@ -787,6 +872,12 @@ static int sata_rcar_probe(struct platform_device *pdev)
        if (!priv)
                return -ENOMEM;
 
+       of_id = of_match_device(sata_rcar_match, &pdev->dev);
+       if (of_id)
+               priv->type = (enum sata_rcar_type)of_id->data;
+       else
+               priv->type = platform_get_device_id(pdev)->driver_data;
+
        priv->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(priv->clk)) {
                dev_err(&pdev->dev, "failed to get access to sata clock\n");
@@ -892,15 +983,10 @@ static const struct dev_pm_ops sata_rcar_pm_ops = {
 };
 #endif
 
-static struct of_device_id sata_rcar_match[] = {
-       { .compatible = "renesas,rcar-sata", },
-       {},
-};
-MODULE_DEVICE_TABLE(of, sata_rcar_match);
-
 static struct platform_driver sata_rcar_driver = {
        .probe          = sata_rcar_probe,
        .remove         = sata_rcar_remove,
+       .id_table       = sata_rcar_id_table,
        .driver = {
                .name           = DRV_NAME,
                .owner          = THIS_MODULE,
index 8557adcd34ee88a82cfb9a805859cba5ad79bef2..aa6be2698669652ada3e9bbebf3ad597831b24ec 100644 (file)
@@ -419,7 +419,6 @@ static void he_remove_one(struct pci_dev *pci_dev)
        atm_dev_deregister(atm_dev);
        kfree(he_dev);
 
-       pci_set_drvdata(pci_dev, NULL);
        pci_disable_device(pci_dev);
 }
 
index 32784d18d1f7c321fd88421aba83551fd4463b4d..e3fb496c71630a643a1dea0b472fab3238fa755e 100644 (file)
@@ -1335,7 +1335,6 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
        
  out_unmap_both:
        kfree(card->dma_bounce);
-       pci_set_drvdata(dev, NULL);
        pci_iounmap(dev, card->buffers);
  out_unmap_config:
        pci_iounmap(dev, card->config_regs);
@@ -1457,7 +1456,6 @@ static void fpga_remove(struct pci_dev *dev)
        pci_release_regions(dev);
        pci_disable_device(dev);
 
-       pci_set_drvdata(dev, NULL);
        kfree(card);
 }
 
index 6fb98b53533f9d708dfc2a530e1033f3f09008b9..e333305363aa0491b9ce7fef3473e1a2cbbf1e07 100644 (file)
@@ -238,7 +238,6 @@ static void bcma_host_pci_remove(struct pci_dev *dev)
        pci_release_regions(dev);
        pci_disable_device(dev);
        kfree(bus);
-       pci_set_drvdata(dev, NULL);
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -270,7 +269,7 @@ static SIMPLE_DEV_PM_OPS(bcma_pm_ops, bcma_host_pci_suspend,
 
 #endif /* CONFIG_PM_SLEEP */
 
-static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = {
+static const struct pci_device_id bcma_pci_bridge_tbl[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4313) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43224) },
index 8cc98cd0d4a8578485694e95735af1fd25514bff..816d979c32667f9549b7ef313f38f386b8790705 100644 (file)
@@ -31,7 +31,6 @@ obj-$(CONFIG_BLK_DEV_NBD)     += nbd.o
 obj-$(CONFIG_BLK_DEV_CRYPTOLOOP) += cryptoloop.o
 obj-$(CONFIG_VIRTIO_BLK)       += virtio_blk.o
 
-obj-$(CONFIG_VIODASD)          += viodasd.o
 obj-$(CONFIG_BLK_DEV_SX8)      += sx8.o
 obj-$(CONFIG_BLK_DEV_HD)       += hd.o
 
index 14a9d1912318b99fe764108420b143159c2bca32..9220f8e833d08228297373d116c308176c8d44a8 100644 (file)
@@ -100,11 +100,8 @@ enum {
 
 struct buf {
        ulong nframesout;
-       ulong resid;
-       ulong bv_resid;
-       sector_t sector;
        struct bio *bio;
-       struct bio_vec *bv;
+       struct bvec_iter iter;
        struct request *rq;
 };
 
@@ -120,13 +117,10 @@ struct frame {
        ulong waited;
        ulong waited_total;
        struct aoetgt *t;               /* parent target I belong to */
-       sector_t lba;
        struct sk_buff *skb;            /* command skb freed on module exit */
        struct sk_buff *r_skb;          /* response skb for async processing */
        struct buf *buf;
-       struct bio_vec *bv;
-       ulong bcnt;
-       ulong bv_off;
+       struct bvec_iter iter;
        char flags;
 };
 
index d2515435e23f2f87215558ec703f5a625ab8ac80..8184451b57c04999bd23c286080e14ca7f069031 100644 (file)
@@ -196,8 +196,7 @@ aoe_freetframe(struct frame *f)
 
        t = f->t;
        f->buf = NULL;
-       f->lba = 0;
-       f->bv = NULL;
+       memset(&f->iter, 0, sizeof(f->iter));
        f->r_skb = NULL;
        f->flags = 0;
        list_add(&f->head, &t->ffree);
@@ -295,21 +294,14 @@ newframe(struct aoedev *d)
 }
 
 static void
-skb_fillup(struct sk_buff *skb, struct bio_vec *bv, ulong off, ulong cnt)
+skb_fillup(struct sk_buff *skb, struct bio *bio, struct bvec_iter iter)
 {
        int frag = 0;
-       ulong fcnt;
-loop:
-       fcnt = bv->bv_len - (off - bv->bv_offset);
-       if (fcnt > cnt)
-               fcnt = cnt;
-       skb_fill_page_desc(skb, frag++, bv->bv_page, off, fcnt);
-       cnt -= fcnt;
-       if (cnt <= 0)
-               return;
-       bv++;
-       off = bv->bv_offset;
-       goto loop;
+       struct bio_vec bv;
+
+       __bio_for_each_segment(bv, bio, iter, iter)
+               skb_fill_page_desc(skb, frag++, bv.bv_page,
+                                  bv.bv_offset, bv.bv_len);
 }
 
 static void
@@ -346,12 +338,10 @@ ata_rw_frameinit(struct frame *f)
        t->nout++;
        f->waited = 0;
        f->waited_total = 0;
-       if (f->buf)
-               f->lba = f->buf->sector;
 
        /* set up ata header */
-       ah->scnt = f->bcnt >> 9;
-       put_lba(ah, f->lba);
+       ah->scnt = f->iter.bi_size >> 9;
+       put_lba(ah, f->iter.bi_sector);
        if (t->d->flags & DEVFL_EXT) {
                ah->aflags |= AOEAFL_EXT;
        } else {
@@ -360,11 +350,11 @@ ata_rw_frameinit(struct frame *f)
                ah->lba3 |= 0xe0;       /* LBA bit + obsolete 0xa0 */
        }
        if (f->buf && bio_data_dir(f->buf->bio) == WRITE) {
-               skb_fillup(skb, f->bv, f->bv_off, f->bcnt);
+               skb_fillup(skb, f->buf->bio, f->iter);
                ah->aflags |= AOEAFL_WRITE;
-               skb->len += f->bcnt;
-               skb->data_len = f->bcnt;
-               skb->truesize += f->bcnt;
+               skb->len += f->iter.bi_size;
+               skb->data_len = f->iter.bi_size;
+               skb->truesize += f->iter.bi_size;
                t->wpkts++;
        } else {
                t->rpkts++;
@@ -382,7 +372,6 @@ aoecmd_ata_rw(struct aoedev *d)
        struct buf *buf;
        struct sk_buff *skb;
        struct sk_buff_head queue;
-       ulong bcnt, fbcnt;
 
        buf = nextbuf(d);
        if (buf == NULL)
@@ -390,39 +379,22 @@ aoecmd_ata_rw(struct aoedev *d)
        f = newframe(d);
        if (f == NULL)
                return 0;
-       bcnt = d->maxbcnt;
-       if (bcnt == 0)
-               bcnt = DEFAULTBCNT;
-       if (bcnt > buf->resid)
-               bcnt = buf->resid;
-       fbcnt = bcnt;
-       f->bv = buf->bv;
-       f->bv_off = f->bv->bv_offset + (f->bv->bv_len - buf->bv_resid);
-       do {
-               if (fbcnt < buf->bv_resid) {
-                       buf->bv_resid -= fbcnt;
-                       buf->resid -= fbcnt;
-                       break;
-               }
-               fbcnt -= buf->bv_resid;
-               buf->resid -= buf->bv_resid;
-               if (buf->resid == 0) {
-                       d->ip.buf = NULL;
-                       break;
-               }
-               buf->bv++;
-               buf->bv_resid = buf->bv->bv_len;
-               WARN_ON(buf->bv_resid == 0);
-       } while (fbcnt);
 
        /* initialize the headers & frame */
        f->buf = buf;
-       f->bcnt = bcnt;
-       ata_rw_frameinit(f);
+       f->iter = buf->iter;
+       f->iter.bi_size = min_t(unsigned long,
+                               d->maxbcnt ?: DEFAULTBCNT,
+                               f->iter.bi_size);
+       bio_advance_iter(buf->bio, &buf->iter, f->iter.bi_size);
+
+       if (!buf->iter.bi_size)
+               d->ip.buf = NULL;
 
        /* mark all tracking fields and load out */
        buf->nframesout += 1;
-       buf->sector += bcnt >> 9;
+
+       ata_rw_frameinit(f);
 
        skb = skb_clone(f->skb, GFP_ATOMIC);
        if (skb) {
@@ -613,10 +585,7 @@ reassign_frame(struct frame *f)
        skb = nf->skb;
        nf->skb = f->skb;
        nf->buf = f->buf;
-       nf->bcnt = f->bcnt;
-       nf->lba = f->lba;
-       nf->bv = f->bv;
-       nf->bv_off = f->bv_off;
+       nf->iter = f->iter;
        nf->waited = 0;
        nf->waited_total = f->waited_total;
        nf->sent = f->sent;
@@ -648,19 +617,19 @@ probe(struct aoetgt *t)
        }
        f->flags |= FFL_PROBE;
        ifrotate(t);
-       f->bcnt = t->d->maxbcnt ? t->d->maxbcnt : DEFAULTBCNT;
+       f->iter.bi_size = t->d->maxbcnt ? t->d->maxbcnt : DEFAULTBCNT;
        ata_rw_frameinit(f);
        skb = f->skb;
-       for (frag = 0, n = f->bcnt; n > 0; ++frag, n -= m) {
+       for (frag = 0, n = f->iter.bi_size; n > 0; ++frag, n -= m) {
                if (n < PAGE_SIZE)
                        m = n;
                else
                        m = PAGE_SIZE;
                skb_fill_page_desc(skb, frag, empty_page, 0, m);
        }
-       skb->len += f->bcnt;
-       skb->data_len = f->bcnt;
-       skb->truesize += f->bcnt;
+       skb->len += f->iter.bi_size;
+       skb->data_len = f->iter.bi_size;
+       skb->truesize += f->iter.bi_size;
 
        skb = skb_clone(f->skb, GFP_ATOMIC);
        if (skb) {
@@ -897,15 +866,15 @@ rqbiocnt(struct request *r)
 static void
 bio_pageinc(struct bio *bio)
 {
-       struct bio_vec *bv;
+       struct bio_vec bv;
        struct page *page;
-       int i;
+       struct bvec_iter iter;
 
-       bio_for_each_segment(bv, bio, i) {
+       bio_for_each_segment(bv, bio, iter) {
                /* Non-zero page count for non-head members of
                 * compound pages is no longer allowed by the kernel.
                 */
-               page = compound_trans_head(bv->bv_page);
+               page = compound_trans_head(bv.bv_page);
                atomic_inc(&page->_count);
        }
 }
@@ -913,12 +882,12 @@ bio_pageinc(struct bio *bio)
 static void
 bio_pagedec(struct bio *bio)
 {
-       struct bio_vec *bv;
        struct page *page;
-       int i;
+       struct bio_vec bv;
+       struct bvec_iter iter;
 
-       bio_for_each_segment(bv, bio, i) {
-               page = compound_trans_head(bv->bv_page);
+       bio_for_each_segment(bv, bio, iter) {
+               page = compound_trans_head(bv.bv_page);
                atomic_dec(&page->_count);
        }
 }
@@ -929,12 +898,8 @@ bufinit(struct buf *buf, struct request *rq, struct bio *bio)
        memset(buf, 0, sizeof(*buf));
        buf->rq = rq;
        buf->bio = bio;
-       buf->resid = bio->bi_size;
-       buf->sector = bio->bi_sector;
+       buf->iter = bio->bi_iter;
        bio_pageinc(bio);
-       buf->bv = bio_iovec(bio);
-       buf->bv_resid = buf->bv->bv_len;
-       WARN_ON(buf->bv_resid == 0);
 }
 
 static struct buf *
@@ -1119,24 +1084,18 @@ gettgt(struct aoedev *d, char *addr)
 }
 
 static void
-bvcpy(struct bio_vec *bv, ulong off, struct sk_buff *skb, long cnt)
+bvcpy(struct sk_buff *skb, struct bio *bio, struct bvec_iter iter, long cnt)
 {
-       ulong fcnt;
-       char *p;
        int soff = 0;
-loop:
-       fcnt = bv->bv_len - (off - bv->bv_offset);
-       if (fcnt > cnt)
-               fcnt = cnt;
-       p = page_address(bv->bv_page) + off;
-       skb_copy_bits(skb, soff, p, fcnt);
-       soff += fcnt;
-       cnt -= fcnt;
-       if (cnt <= 0)
-               return;
-       bv++;
-       off = bv->bv_offset;
-       goto loop;
+       struct bio_vec bv;
+
+       iter.bi_size = cnt;
+
+       __bio_for_each_segment(bv, bio, iter, iter) {
+               char *p = page_address(bv.bv_page) + bv.bv_offset;
+               skb_copy_bits(skb, soff, p, bv.bv_len);
+               soff += bv.bv_len;
+       }
 }
 
 void
@@ -1152,7 +1111,7 @@ aoe_end_request(struct aoedev *d, struct request *rq, int fastfail)
        do {
                bio = rq->bio;
                bok = !fastfail && test_bit(BIO_UPTODATE, &bio->bi_flags);
-       } while (__blk_end_request(rq, bok ? 0 : -EIO, bio->bi_size));
+       } while (__blk_end_request(rq, bok ? 0 : -EIO, bio->bi_iter.bi_size));
 
        /* cf. http://lkml.org/lkml/2006/10/31/28 */
        if (!fastfail)
@@ -1229,7 +1188,15 @@ noskb:           if (buf)
                        clear_bit(BIO_UPTODATE, &buf->bio->bi_flags);
                        break;
                }
-               bvcpy(f->bv, f->bv_off, skb, n);
+               if (n > f->iter.bi_size) {
+                       pr_err_ratelimited("%s e%ld.%d.  bytes=%ld need=%u\n",
+                               "aoe: too-large data size in read from",
+                               (long) d->aoemajor, d->aoeminor,
+                               n, f->iter.bi_size);
+                       clear_bit(BIO_UPTODATE, &buf->bio->bi_flags);
+                       break;
+               }
+               bvcpy(skb, f->buf->bio, f->iter, n);
        case ATA_CMD_PIO_WRITE:
        case ATA_CMD_PIO_WRITE_EXT:
                spin_lock_irq(&d->lock);
@@ -1272,7 +1239,7 @@ out:
 
        aoe_freetframe(f);
 
-       if (buf && --buf->nframesout == 0 && buf->resid == 0)
+       if (buf && --buf->nframesout == 0 && buf->iter.bi_size == 0)
                aoe_end_buf(d, buf);
 
        spin_unlock_irq(&d->lock);
@@ -1727,7 +1694,7 @@ aoe_failbuf(struct aoedev *d, struct buf *buf)
 {
        if (buf == NULL)
                return;
-       buf->resid = 0;
+       buf->iter.bi_size = 0;
        clear_bit(BIO_UPTODATE, &buf->bio->bi_flags);
        if (buf->nframesout == 0)
                aoe_end_buf(d, buf);
index d91f1a56e8617f56c019bfb6389bb79f71fa8ad2..e73b85cf0756876adbf4ad9b8220fc466bcdb412 100644 (file)
@@ -328,18 +328,18 @@ static void brd_make_request(struct request_queue *q, struct bio *bio)
        struct block_device *bdev = bio->bi_bdev;
        struct brd_device *brd = bdev->bd_disk->private_data;
        int rw;
-       struct bio_vec *bvec;
+       struct bio_vec bvec;
        sector_t sector;
-       int i;
+       struct bvec_iter iter;
        int err = -EIO;
 
-       sector = bio->bi_sector;
+       sector = bio->bi_iter.bi_sector;
        if (bio_end_sector(bio) > get_capacity(bdev->bd_disk))
                goto out;
 
        if (unlikely(bio->bi_rw & REQ_DISCARD)) {
                err = 0;
-               discard_from_brd(brd, sector, bio->bi_size);
+               discard_from_brd(brd, sector, bio->bi_iter.bi_size);
                goto out;
        }
 
@@ -347,10 +347,10 @@ static void brd_make_request(struct request_queue *q, struct bio *bio)
        if (rw == READA)
                rw = READ;
 
-       bio_for_each_segment(bvec, bio, i) {
-               unsigned int len = bvec->bv_len;
-               err = brd_do_bvec(brd, bvec->bv_page, len,
-                                       bvec->bv_offset, rw, sector);
+       bio_for_each_segment(bvec, bio, iter) {
+               unsigned int len = bvec.bv_len;
+               err = brd_do_bvec(brd, bvec.bv_page, len,
+                                       bvec.bv_offset, rw, sector);
                if (err)
                        break;
                sector += len >> SECTOR_SHIFT;
index 28c73ca320a8f7f9b1741492785fa2f18e042d8c..a9b13f2cc420b055b8089fde687d601a23b8e635 100644 (file)
@@ -159,7 +159,7 @@ static int _drbd_md_sync_page_io(struct drbd_conf *mdev,
 
        bio = bio_alloc_drbd(GFP_NOIO);
        bio->bi_bdev = bdev->md_bdev;
-       bio->bi_sector = sector;
+       bio->bi_iter.bi_sector = sector;
        err = -EIO;
        if (bio_add_page(bio, page, size, 0) != size)
                goto out;
index b12c11ec4bd21e405fe75276d656e3519c8ad873..597f111df67b3597987eb816f8ff2ca2ec17c285 100644 (file)
@@ -1028,7 +1028,7 @@ static void bm_page_io_async(struct bm_aio_ctx *ctx, int page_nr, int rw) __must
        } else
                page = b->bm_pages[page_nr];
        bio->bi_bdev = mdev->ldev->md_bdev;
-       bio->bi_sector = on_disk_sector;
+       bio->bi_iter.bi_sector = on_disk_sector;
        /* bio_add_page of a single page to an empty bio will always succeed,
         * according to api.  Do we want to assert that? */
        bio_add_page(bio, page, len, 0);
index 9e3818b1bc8321e5883a1ef1b3dfe9542e7ea619..929468e1512a687d44bb310b8e3cc94a6b15161d 100644 (file)
@@ -1537,15 +1537,17 @@ static int _drbd_send_page(struct drbd_conf *mdev, struct page *page,
 
 static int _drbd_send_bio(struct drbd_conf *mdev, struct bio *bio)
 {
-       struct bio_vec *bvec;
-       int i;
+       struct bio_vec bvec;
+       struct bvec_iter iter;
+
        /* hint all but last page with MSG_MORE */
-       bio_for_each_segment(bvec, bio, i) {
+       bio_for_each_segment(bvec, bio, iter) {
                int err;
 
-               err = _drbd_no_send_page(mdev, bvec->bv_page,
-                                        bvec->bv_offset, bvec->bv_len,
-                                        i == bio->bi_vcnt - 1 ? 0 : MSG_MORE);
+               err = _drbd_no_send_page(mdev, bvec.bv_page,
+                                        bvec.bv_offset, bvec.bv_len,
+                                        bio_iter_last(bvec, iter)
+                                        ? 0 : MSG_MORE);
                if (err)
                        return err;
        }
@@ -1554,15 +1556,16 @@ static int _drbd_send_bio(struct drbd_conf *mdev, struct bio *bio)
 
 static int _drbd_send_zc_bio(struct drbd_conf *mdev, struct bio *bio)
 {
-       struct bio_vec *bvec;
-       int i;
+       struct bio_vec bvec;
+       struct bvec_iter iter;
+
        /* hint all but last page with MSG_MORE */
-       bio_for_each_segment(bvec, bio, i) {
+       bio_for_each_segment(bvec, bio, iter) {
                int err;
 
-               err = _drbd_send_page(mdev, bvec->bv_page,
-                                     bvec->bv_offset, bvec->bv_len,
-                                     i == bio->bi_vcnt - 1 ? 0 : MSG_MORE);
+               err = _drbd_send_page(mdev, bvec.bv_page,
+                                     bvec.bv_offset, bvec.bv_len,
+                                     bio_iter_last(bvec, iter) ? 0 : MSG_MORE);
                if (err)
                        return err;
        }
index 6fa6673b36b396765b58142e8e8abcdc4beaae05..d073305ffd5e76e17a7d0804ad92be1ad82bba67 100644 (file)
@@ -1333,7 +1333,7 @@ next_bio:
                goto fail;
        }
        /* > peer_req->i.sector, unless this is the first bio */
-       bio->bi_sector = sector;
+       bio->bi_iter.bi_sector = sector;
        bio->bi_bdev = mdev->ldev->backing_bdev;
        bio->bi_rw = rw;
        bio->bi_private = peer_req;
@@ -1353,7 +1353,7 @@ next_bio:
                                dev_err(DEV,
                                        "bio_add_page failed for len=%u, "
                                        "bi_vcnt=0 (bi_sector=%llu)\n",
-                                       len, (unsigned long long)bio->bi_sector);
+                                       len, (uint64_t)bio->bi_iter.bi_sector);
                                err = -ENOSPC;
                                goto fail;
                        }
@@ -1595,9 +1595,10 @@ static int drbd_drain_block(struct drbd_conf *mdev, int data_size)
 static int recv_dless_read(struct drbd_conf *mdev, struct drbd_request *req,
                           sector_t sector, int data_size)
 {
-       struct bio_vec *bvec;
+       struct bio_vec bvec;
+       struct bvec_iter iter;
        struct bio *bio;
-       int dgs, err, i, expect;
+       int dgs, err, expect;
        void *dig_in = mdev->tconn->int_dig_in;
        void *dig_vv = mdev->tconn->int_dig_vv;
 
@@ -1615,13 +1616,13 @@ static int recv_dless_read(struct drbd_conf *mdev, struct drbd_request *req,
        mdev->recv_cnt += data_size>>9;
 
        bio = req->master_bio;
-       D_ASSERT(sector == bio->bi_sector);
+       D_ASSERT(sector == bio->bi_iter.bi_sector);
 
-       bio_for_each_segment(bvec, bio, i) {
-               void *mapped = kmap(bvec->bv_page) + bvec->bv_offset;
-               expect = min_t(int, data_size, bvec->bv_len);
+       bio_for_each_segment(bvec, bio, iter) {
+               void *mapped = kmap(bvec.bv_page) + bvec.bv_offset;
+               expect = min_t(int, data_size, bvec.bv_len);
                err = drbd_recv_all_warn(mdev->tconn, mapped, expect);
-               kunmap(bvec->bv_page);
+               kunmap(bvec.bv_page);
                if (err)
                        return err;
                data_size -= expect;
index fec7bef44994cf8b76e595f69b5e34b42cdaf230..104a040f24de74141274b364ee625aa49eefbb94 100644 (file)
@@ -77,8 +77,8 @@ static struct drbd_request *drbd_req_new(struct drbd_conf *mdev,
        req->epoch       = 0;
 
        drbd_clear_interval(&req->i);
-       req->i.sector     = bio_src->bi_sector;
-       req->i.size      = bio_src->bi_size;
+       req->i.sector     = bio_src->bi_iter.bi_sector;
+       req->i.size      = bio_src->bi_iter.bi_size;
        req->i.local = true;
        req->i.waiting = false;
 
@@ -1280,7 +1280,7 @@ void drbd_make_request(struct request_queue *q, struct bio *bio)
        /*
         * what we "blindly" assume:
         */
-       D_ASSERT(IS_ALIGNED(bio->bi_size, 512));
+       D_ASSERT(IS_ALIGNED(bio->bi_iter.bi_size, 512));
 
        inc_ap_bio(mdev);
        __drbd_make_request(mdev, bio, start_time);
index 978cb1addc98845fb8ca49838cfb5ec2478170f7..28e15d91197af1b234e43136740709adc090bcde 100644 (file)
@@ -269,7 +269,7 @@ static inline void drbd_req_make_private_bio(struct drbd_request *req, struct bi
 
 /* Short lived temporary struct on the stack.
  * We could squirrel the error to be returned into
- * bio->bi_size, or similar. But that would be too ugly. */
+ * bio->bi_iter.bi_size, or similar. But that would be too ugly. */
 struct bio_and_error {
        struct bio *bio;
        int error;
index 891c0ecaa292c84998f7357b82e3a80cdc0f6484..84d3175d493aaef91edabd97297238a717f6973c 100644 (file)
@@ -313,8 +313,8 @@ void drbd_csum_bio(struct drbd_conf *mdev, struct crypto_hash *tfm, struct bio *
 {
        struct hash_desc desc;
        struct scatterlist sg;
-       struct bio_vec *bvec;
-       int i;
+       struct bio_vec bvec;
+       struct bvec_iter iter;
 
        desc.tfm = tfm;
        desc.flags = 0;
@@ -322,8 +322,8 @@ void drbd_csum_bio(struct drbd_conf *mdev, struct crypto_hash *tfm, struct bio *
        sg_init_table(&sg, 1);
        crypto_hash_init(&desc);
 
-       bio_for_each_segment(bvec, bio, i) {
-               sg_set_page(&sg, bvec->bv_page, bvec->bv_len, bvec->bv_offset);
+       bio_for_each_segment(bvec, bio, iter) {
+               sg_set_page(&sg, bvec.bv_page, bvec.bv_len, bvec.bv_offset);
                crypto_hash_update(&desc, &sg, sg.length);
        }
        crypto_hash_final(&desc, digest);
index 000abe2f105c60f06d5fac31a2a4889cddd22b15..6b29c4422828a4dc5442bf19b1a2c719d5d2377c 100644 (file)
@@ -2351,7 +2351,7 @@ static void rw_interrupt(void)
 /* Compute maximal contiguous buffer size. */
 static int buffer_chain_size(void)
 {
-       struct bio_vec *bv;
+       struct bio_vec bv;
        int size;
        struct req_iterator iter;
        char *base;
@@ -2360,10 +2360,10 @@ static int buffer_chain_size(void)
        size = 0;
 
        rq_for_each_segment(bv, current_req, iter) {
-               if (page_address(bv->bv_page) + bv->bv_offset != base + size)
+               if (page_address(bv.bv_page) + bv.bv_offset != base + size)
                        break;
 
-               size += bv->bv_len;
+               size += bv.bv_len;
        }
 
        return size >> 9;
@@ -2389,7 +2389,7 @@ static int transfer_size(int ssize, int max_sector, int max_size)
 static void copy_buffer(int ssize, int max_sector, int max_sector_2)
 {
        int remaining;          /* number of transferred 512-byte sectors */
-       struct bio_vec *bv;
+       struct bio_vec bv;
        char *buffer;
        char *dma_buffer;
        int size;
@@ -2427,10 +2427,10 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2)
                if (!remaining)
                        break;
 
-               size = bv->bv_len;
+               size = bv.bv_len;
                SUPBOUND(size, remaining);
 
-               buffer = page_address(bv->bv_page) + bv->bv_offset;
+               buffer = page_address(bv.bv_page) + bv.bv_offset;
                if (dma_buffer + size >
                    floppy_track_buffer + (max_buffer_sectors << 10) ||
                    dma_buffer < floppy_track_buffer) {
@@ -3775,9 +3775,9 @@ static int __floppy_read_block_0(struct block_device *bdev)
        bio_vec.bv_len = size;
        bio_vec.bv_offset = 0;
        bio.bi_vcnt = 1;
-       bio.bi_size = size;
+       bio.bi_iter.bi_size = size;
        bio.bi_bdev = bdev;
-       bio.bi_sector = 0;
+       bio.bi_iter.bi_sector = 0;
        bio.bi_flags = (1 << BIO_QUIET);
        init_completion(&complete);
        bio.bi_private = &complete;
index c8dac730524408f63e78cb9acdae8294aaf8dafa..33fde3a3975954c793d0d2e9feb846e5e6a2bdc2 100644 (file)
@@ -288,9 +288,10 @@ static int lo_send(struct loop_device *lo, struct bio *bio, loff_t pos)
 {
        int (*do_lo_send)(struct loop_device *, struct bio_vec *, loff_t,
                        struct page *page);
-       struct bio_vec *bvec;
+       struct bio_vec bvec;
+       struct bvec_iter iter;
        struct page *page = NULL;
-       int i, ret = 0;
+       int ret = 0;
 
        if (lo->transfer != transfer_none) {
                page = alloc_page(GFP_NOIO | __GFP_HIGHMEM);
@@ -302,11 +303,11 @@ static int lo_send(struct loop_device *lo, struct bio *bio, loff_t pos)
                do_lo_send = do_lo_send_direct_write;
        }
 
-       bio_for_each_segment(bvec, bio, i) {
-               ret = do_lo_send(lo, bvec, pos, page);
+       bio_for_each_segment(bvec, bio, iter) {
+               ret = do_lo_send(lo, &bvec, pos, page);
                if (ret < 0)
                        break;
-               pos += bvec->bv_len;
+               pos += bvec.bv_len;
        }
        if (page) {
                kunmap(page);
@@ -392,20 +393,20 @@ do_lo_receive(struct loop_device *lo,
 static int
 lo_receive(struct loop_device *lo, struct bio *bio, int bsize, loff_t pos)
 {
-       struct bio_vec *bvec;
+       struct bio_vec bvec;
+       struct bvec_iter iter;
        ssize_t s;
-       int i;
 
-       bio_for_each_segment(bvec, bio, i) {
-               s = do_lo_receive(lo, bvec, bsize, pos);
+       bio_for_each_segment(bvec, bio, iter) {
+               s = do_lo_receive(lo, &bvec, bsize, pos);
                if (s < 0)
                        return s;
 
-               if (s != bvec->bv_len) {
+               if (s != bvec.bv_len) {
                        zero_fill_bio(bio);
                        break;
                }
-               pos += bvec->bv_len;
+               pos += bvec.bv_len;
        }
        return 0;
 }
@@ -415,7 +416,7 @@ static int do_bio_filebacked(struct loop_device *lo, struct bio *bio)
        loff_t pos;
        int ret;
 
-       pos = ((loff_t) bio->bi_sector << 9) + lo->lo_offset;
+       pos = ((loff_t) bio->bi_iter.bi_sector << 9) + lo->lo_offset;
 
        if (bio_rw(bio) == WRITE) {
                struct file *file = lo->lo_backing_file;
@@ -444,7 +445,7 @@ static int do_bio_filebacked(struct loop_device *lo, struct bio *bio)
                                goto out;
                        }
                        ret = file->f_op->fallocate(file, mode, pos,
-                                                   bio->bi_size);
+                                                   bio->bi_iter.bi_size);
                        if (unlikely(ret && ret != -EINVAL &&
                                     ret != -EOPNOTSUPP))
                                ret = -EIO;
index 050c71267f146340281992e341ab86c93d79c33d..52b2f2a714708a756b4adcee140e8ae2a91f5006 100644 (file)
@@ -3962,8 +3962,9 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio)
 {
        struct driver_data *dd = queue->queuedata;
        struct scatterlist *sg;
-       struct bio_vec *bvec;
-       int i, nents = 0;
+       struct bio_vec bvec;
+       struct bvec_iter iter;
+       int nents = 0;
        int tag = 0, unaligned = 0;
 
        if (unlikely(dd->dd_flag & MTIP_DDF_STOP_IO)) {
@@ -3993,7 +3994,7 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio)
        }
 
        if (unlikely(bio->bi_rw & REQ_DISCARD)) {
-               bio_endio(bio, mtip_send_trim(dd, bio->bi_sector,
+               bio_endio(bio, mtip_send_trim(dd, bio->bi_iter.bi_sector,
                                                bio_sectors(bio)));
                return;
        }
@@ -4006,7 +4007,8 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio)
 
        if (bio_data_dir(bio) == WRITE && bio_sectors(bio) <= 64 &&
                                                        dd->unal_qdepth) {
-               if (bio->bi_sector % 8 != 0) /* Unaligned on 4k boundaries */
+               if (bio->bi_iter.bi_sector % 8 != 0)
+                       /* Unaligned on 4k boundaries */
                        unaligned = 1;
                else if (bio_sectors(bio) % 8 != 0) /* Aligned but not 4k/8k */
                        unaligned = 1;
@@ -4025,17 +4027,17 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio)
                }
 
                /* Create the scatter list for this bio. */
-               bio_for_each_segment(bvec, bio, i) {
+               bio_for_each_segment(bvec, bio, iter) {
                        sg_set_page(&sg[nents],
-                                       bvec->bv_page,
-                                       bvec->bv_len,
-                                       bvec->bv_offset);
+                                       bvec.bv_page,
+                                       bvec.bv_len,
+                                       bvec.bv_offset);
                        nents++;
                }
 
                /* Issue the read/write. */
                mtip_hw_submit_io(dd,
-                               bio->bi_sector,
+                               bio->bi_iter.bi_sector,
                                bio_sectors(bio),
                                nents,
                                tag,
index 2dc3b5153f0d82b42cfab720464e17bd963223f8..55298db36b2d61a113f25c22905fffb0f22ddd32 100644 (file)
@@ -271,18 +271,18 @@ static int nbd_send_req(struct nbd_device *nbd, struct request *req)
 
        if (nbd_cmd(req) == NBD_CMD_WRITE) {
                struct req_iterator iter;
-               struct bio_vec *bvec;
+               struct bio_vec bvec;
                /*
                 * we are really probing at internals to determine
                 * whether to set MSG_MORE or not...
                 */
                rq_for_each_segment(bvec, req, iter) {
                        flags = 0;
-                       if (!rq_iter_last(req, iter))
+                       if (!rq_iter_last(bvec, iter))
                                flags = MSG_MORE;
                        dprintk(DBG_TX, "%s: request %p: sending %d bytes data\n",
-                                       nbd->disk->disk_name, req, bvec->bv_len);
-                       result = sock_send_bvec(nbd, bvec, flags);
+                                       nbd->disk->disk_name, req, bvec.bv_len);
+                       result = sock_send_bvec(nbd, &bvec, flags);
                        if (result <= 0) {
                                dev_err(disk_to_dev(nbd->disk),
                                        "Send data failed (result %d)\n",
@@ -378,10 +378,10 @@ static struct request *nbd_read_stat(struct nbd_device *nbd)
                        nbd->disk->disk_name, req);
        if (nbd_cmd(req) == NBD_CMD_READ) {
                struct req_iterator iter;
-               struct bio_vec *bvec;
+               struct bio_vec bvec;
 
                rq_for_each_segment(bvec, req, iter) {
-                       result = sock_recv_bvec(nbd, bvec);
+                       result = sock_recv_bvec(nbd, &bvec);
                        if (result <= 0) {
                                dev_err(disk_to_dev(nbd->disk), "Receive data failed (result %d)\n",
                                        result);
@@ -389,7 +389,7 @@ static struct request *nbd_read_stat(struct nbd_device *nbd)
                                return req;
                        }
                        dprintk(DBG_RX, "%s: request %p: got %d bytes data\n",
-                               nbd->disk->disk_name, req, bvec->bv_len);
+                               nbd->disk->disk_name, req, bvec.bv_len);
                }
        }
        return req;
index 26d03fa0bf26696d9e004b3983a580d409d3d006..1f14ac4039450e84137b4eab0dacf043aa46d16e 100644 (file)
@@ -441,104 +441,19 @@ int nvme_setup_prps(struct nvme_dev *dev, struct nvme_common_command *cmd,
        return total_len;
 }
 
-struct nvme_bio_pair {
-       struct bio b1, b2, *parent;
-       struct bio_vec *bv1, *bv2;
-       int err;
-       atomic_t cnt;
-};
-
-static void nvme_bio_pair_endio(struct bio *bio, int err)
-{
-       struct nvme_bio_pair *bp = bio->bi_private;
-
-       if (err)
-               bp->err = err;
-
-       if (atomic_dec_and_test(&bp->cnt)) {
-               bio_endio(bp->parent, bp->err);
-               kfree(bp->bv1);
-               kfree(bp->bv2);
-               kfree(bp);
-       }
-}
-
-static struct nvme_bio_pair *nvme_bio_split(struct bio *bio, int idx,
-                                                       int len, int offset)
-{
-       struct nvme_bio_pair *bp;
-
-       BUG_ON(len > bio->bi_size);
-       BUG_ON(idx > bio->bi_vcnt);
-
-       bp = kmalloc(sizeof(*bp), GFP_ATOMIC);
-       if (!bp)
-               return NULL;
-       bp->err = 0;
-
-       bp->b1 = *bio;
-       bp->b2 = *bio;
-
-       bp->b1.bi_size = len;
-       bp->b2.bi_size -= len;
-       bp->b1.bi_vcnt = idx;
-       bp->b2.bi_idx = idx;
-       bp->b2.bi_sector += len >> 9;
-
-       if (offset) {
-               bp->bv1 = kmalloc(bio->bi_max_vecs * sizeof(struct bio_vec),
-                                                               GFP_ATOMIC);
-               if (!bp->bv1)
-                       goto split_fail_1;
-
-               bp->bv2 = kmalloc(bio->bi_max_vecs * sizeof(struct bio_vec),
-                                                               GFP_ATOMIC);
-               if (!bp->bv2)
-                       goto split_fail_2;
-
-               memcpy(bp->bv1, bio->bi_io_vec,
-                       bio->bi_max_vecs * sizeof(struct bio_vec));
-               memcpy(bp->bv2, bio->bi_io_vec,
-                       bio->bi_max_vecs * sizeof(struct bio_vec));
-
-               bp->b1.bi_io_vec = bp->bv1;
-               bp->b2.bi_io_vec = bp->bv2;
-               bp->b2.bi_io_vec[idx].bv_offset += offset;
-               bp->b2.bi_io_vec[idx].bv_len -= offset;
-               bp->b1.bi_io_vec[idx].bv_len = offset;
-               bp->b1.bi_vcnt++;
-       } else
-               bp->bv1 = bp->bv2 = NULL;
-
-       bp->b1.bi_private = bp;
-       bp->b2.bi_private = bp;
-
-       bp->b1.bi_end_io = nvme_bio_pair_endio;
-       bp->b2.bi_end_io = nvme_bio_pair_endio;
-
-       bp->parent = bio;
-       atomic_set(&bp->cnt, 2);
-
-       return bp;
-
- split_fail_2:
-       kfree(bp->bv1);
- split_fail_1:
-       kfree(bp);
-       return NULL;
-}
-
 static int nvme_split_and_submit(struct bio *bio, struct nvme_queue *nvmeq,
-                                               int idx, int len, int offset)
+                                int len)
 {
-       struct nvme_bio_pair *bp = nvme_bio_split(bio, idx, len, offset);
-       if (!bp)
+       struct bio *split = bio_split(bio, len >> 9, GFP_ATOMIC, NULL);
+       if (!split)
                return -ENOMEM;
 
+       bio_chain(split, bio);
+
        if (bio_list_empty(&nvmeq->sq_cong))
                add_wait_queue(&nvmeq->sq_full, &nvmeq->sq_cong_wait);
-       bio_list_add(&nvmeq->sq_cong, &bp->b1);
-       bio_list_add(&nvmeq->sq_cong, &bp->b2);
+       bio_list_add(&nvmeq->sq_cong, split);
+       bio_list_add(&nvmeq->sq_cong, bio);
 
        return 0;
 }
@@ -550,41 +465,44 @@ static int nvme_split_and_submit(struct bio *bio, struct nvme_queue *nvmeq,
 static int nvme_map_bio(struct nvme_queue *nvmeq, struct nvme_iod *iod,
                struct bio *bio, enum dma_data_direction dma_dir, int psegs)
 {
-       struct bio_vec *bvec, *bvprv = NULL;
+       struct bio_vec bvec, bvprv;
+       struct bvec_iter iter;
        struct scatterlist *sg = NULL;
-       int i, length = 0, nsegs = 0, split_len = bio->bi_size;
+       int length = 0, nsegs = 0, split_len = bio->bi_iter.bi_size;
+       int first = 1;
 
        if (nvmeq->dev->stripe_size)
                split_len = nvmeq->dev->stripe_size -
-                       ((bio->bi_sector << 9) & (nvmeq->dev->stripe_size - 1));
+                       ((bio->bi_iter.bi_sector << 9) &
+                        (nvmeq->dev->stripe_size - 1));
 
        sg_init_table(iod->sg, psegs);
-       bio_for_each_segment(bvec, bio, i) {
-               if (bvprv && BIOVEC_PHYS_MERGEABLE(bvprv, bvec)) {
-                       sg->length += bvec->bv_len;
+       bio_for_each_segment(bvec, bio, iter) {
+               if (!first && BIOVEC_PHYS_MERGEABLE(&bvprv, &bvec)) {
+                       sg->length += bvec.bv_len;
                } else {
-                       if (bvprv && BIOVEC_NOT_VIRT_MERGEABLE(bvprv, bvec))
-                               return nvme_split_and_submit(bio, nvmeq, i,
-                                                               length, 0);
+                       if (!first && BIOVEC_NOT_VIRT_MERGEABLE(&bvprv, &bvec))
+                               return nvme_split_and_submit(bio, nvmeq,
+                                                            length);
 
                        sg = sg ? sg + 1 : iod->sg;
-                       sg_set_page(sg, bvec->bv_page, bvec->bv_len,
-                                                       bvec->bv_offset);
+                       sg_set_page(sg, bvec.bv_page,
+                                   bvec.bv_len, bvec.bv_offset);
                        nsegs++;
                }
 
-               if (split_len - length < bvec->bv_len)
-                       return nvme_split_and_submit(bio, nvmeq, i, split_len,
-                                                       split_len - length);
-               length += bvec->bv_len;
+               if (split_len - length < bvec.bv_len)
+                       return nvme_split_and_submit(bio, nvmeq, split_len);
+               length += bvec.bv_len;
                bvprv = bvec;
+               first = 0;
        }
        iod->nents = nsegs;
        sg_mark_end(sg);
        if (dma_map_sg(nvmeq->q_dmadev, iod->sg, iod->nents, dma_dir) == 0)
                return -ENOMEM;
 
-       BUG_ON(length != bio->bi_size);
+       BUG_ON(length != bio->bi_iter.bi_size);
        return length;
 }
 
@@ -608,8 +526,8 @@ static int nvme_submit_discard(struct nvme_queue *nvmeq, struct nvme_ns *ns,
        iod->npages = 0;
 
        range->cattr = cpu_to_le32(0);
-       range->nlb = cpu_to_le32(bio->bi_size >> ns->lba_shift);
-       range->slba = cpu_to_le64(nvme_block_nr(ns, bio->bi_sector));
+       range->nlb = cpu_to_le32(bio->bi_iter.bi_size >> ns->lba_shift);
+       range->slba = cpu_to_le64(nvme_block_nr(ns, bio->bi_iter.bi_sector));
 
        memset(cmnd, 0, sizeof(*cmnd));
        cmnd->dsm.opcode = nvme_cmd_dsm;
@@ -674,7 +592,7 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns,
        }
 
        result = -ENOMEM;
-       iod = nvme_alloc_iod(psegs, bio->bi_size, GFP_ATOMIC);
+       iod = nvme_alloc_iod(psegs, bio->bi_iter.bi_size, GFP_ATOMIC);
        if (!iod)
                goto nomem;
        iod->private = bio;
@@ -723,7 +641,7 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns,
        cmnd->rw.nsid = cpu_to_le32(ns->ns_id);
        length = nvme_setup_prps(nvmeq->dev, &cmnd->common, iod, length,
                                                                GFP_ATOMIC);
-       cmnd->rw.slba = cpu_to_le64(nvme_block_nr(ns, bio->bi_sector));
+       cmnd->rw.slba = cpu_to_le64(nvme_block_nr(ns, bio->bi_iter.bi_sector));
        cmnd->rw.length = cpu_to_le16((length >> ns->lba_shift) - 1);
        cmnd->rw.control = cpu_to_le16(control);
        cmnd->rw.dsmgmt = cpu_to_le32(dsmgmt);
index ff8668c5efb10eebc1a02736d306cce1f43ad7ff..3dda09a5ec4172bc7e57f6e18dff272ecd8deaba 100644 (file)
@@ -651,7 +651,7 @@ static struct pkt_rb_node *pkt_rbtree_find(struct pktcdvd_device *pd, sector_t s
 
        for (;;) {
                tmp = rb_entry(n, struct pkt_rb_node, rb_node);
-               if (s <= tmp->bio->bi_sector)
+               if (s <= tmp->bio->bi_iter.bi_sector)
                        next = n->rb_left;
                else
                        next = n->rb_right;
@@ -660,12 +660,12 @@ static struct pkt_rb_node *pkt_rbtree_find(struct pktcdvd_device *pd, sector_t s
                n = next;
        }
 
-       if (s > tmp->bio->bi_sector) {
+       if (s > tmp->bio->bi_iter.bi_sector) {
                tmp = pkt_rbtree_next(tmp);
                if (!tmp)
                        return NULL;
        }
-       BUG_ON(s > tmp->bio->bi_sector);
+       BUG_ON(s > tmp->bio->bi_iter.bi_sector);
        return tmp;
 }
 
@@ -676,13 +676,13 @@ static void pkt_rbtree_insert(struct pktcdvd_device *pd, struct pkt_rb_node *nod
 {
        struct rb_node **p = &pd->bio_queue.rb_node;
        struct rb_node *parent = NULL;
-       sector_t s = node->bio->bi_sector;
+       sector_t s = node->bio->bi_iter.bi_sector;
        struct pkt_rb_node *tmp;
 
        while (*p) {
                parent = *p;
                tmp = rb_entry(parent, struct pkt_rb_node, rb_node);
-               if (s < tmp->bio->bi_sector)
+               if (s < tmp->bio->bi_iter.bi_sector)
                        p = &(*p)->rb_left;
                else
                        p = &(*p)->rb_right;
@@ -857,7 +857,8 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd)
                        spin_lock(&pd->iosched.lock);
                        bio = bio_list_peek(&pd->iosched.write_queue);
                        spin_unlock(&pd->iosched.lock);
-                       if (bio && (bio->bi_sector == pd->iosched.last_write))
+                       if (bio && (bio->bi_iter.bi_sector ==
+                                   pd->iosched.last_write))
                                need_write_seek = 0;
                        if (need_write_seek && reads_queued) {
                                if (atomic_read(&pd->cdrw.pending_bios) > 0) {
@@ -888,7 +889,8 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd)
                        continue;
 
                if (bio_data_dir(bio) == READ)
-                       pd->iosched.successive_reads += bio->bi_size >> 10;
+                       pd->iosched.successive_reads +=
+                               bio->bi_iter.bi_size >> 10;
                else {
                        pd->iosched.successive_reads = 0;
                        pd->iosched.last_write = bio_end_sector(bio);
@@ -978,7 +980,7 @@ static void pkt_end_io_read(struct bio *bio, int err)
 
        pkt_dbg(2, pd, "bio=%p sec0=%llx sec=%llx err=%d\n",
                bio, (unsigned long long)pkt->sector,
-               (unsigned long long)bio->bi_sector, err);
+               (unsigned long long)bio->bi_iter.bi_sector, err);
 
        if (err)
                atomic_inc(&pkt->io_errors);
@@ -1026,8 +1028,9 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt)
        memset(written, 0, sizeof(written));
        spin_lock(&pkt->lock);
        bio_list_for_each(bio, &pkt->orig_bios) {
-               int first_frame = (bio->bi_sector - pkt->sector) / (CD_FRAMESIZE >> 9);
-               int num_frames = bio->bi_size / CD_FRAMESIZE;
+               int first_frame = (bio->bi_iter.bi_sector - pkt->sector) /
+                       (CD_FRAMESIZE >> 9);
+               int num_frames = bio->bi_iter.bi_size / CD_FRAMESIZE;
                pd->stats.secs_w += num_frames * (CD_FRAMESIZE >> 9);
                BUG_ON(first_frame < 0);
                BUG_ON(first_frame + num_frames > pkt->frames);
@@ -1053,7 +1056,7 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt)
 
                bio = pkt->r_bios[f];
                bio_reset(bio);
-               bio->bi_sector = pkt->sector + f * (CD_FRAMESIZE >> 9);
+               bio->bi_iter.bi_sector = pkt->sector + f * (CD_FRAMESIZE >> 9);
                bio->bi_bdev = pd->bdev;
                bio->bi_end_io = pkt_end_io_read;
                bio->bi_private = pkt;
@@ -1150,8 +1153,8 @@ static int pkt_start_recovery(struct packet_data *pkt)
        bio_reset(pkt->bio);
        pkt->bio->bi_bdev = pd->bdev;
        pkt->bio->bi_rw = REQ_WRITE;
-       pkt->bio->bi_sector = new_sector;
-       pkt->bio->bi_size = pkt->frames * CD_FRAMESIZE;
+       pkt->bio->bi_iter.bi_sector = new_sector;
+       pkt->bio->bi_iter.bi_size = pkt->frames * CD_FRAMESIZE;
        pkt->bio->bi_vcnt = pkt->frames;
 
        pkt->bio->bi_end_io = pkt_end_io_packet_write;
@@ -1213,7 +1216,7 @@ static int pkt_handle_queue(struct pktcdvd_device *pd)
        node = first_node;
        while (node) {
                bio = node->bio;
-               zone = get_zone(bio->bi_sector, pd);
+               zone = get_zone(bio->bi_iter.bi_sector, pd);
                list_for_each_entry(p, &pd->cdrw.pkt_active_list, list) {
                        if (p->sector == zone) {
                                bio = NULL;
@@ -1252,14 +1255,14 @@ try_next_bio:
        pkt_dbg(2, pd, "looking for zone %llx\n", (unsigned long long)zone);
        while ((node = pkt_rbtree_find(pd, zone)) != NULL) {
                bio = node->bio;
-               pkt_dbg(2, pd, "found zone=%llx\n",
-                       (unsigned long long)get_zone(bio->bi_sector, pd));
-               if (get_zone(bio->bi_sector, pd) != zone)
+               pkt_dbg(2, pd, "found zone=%llx\n", (unsigned long long)
+                       get_zone(bio->bi_iter.bi_sector, pd));
+               if (get_zone(bio->bi_iter.bi_sector, pd) != zone)
                        break;
                pkt_rbtree_erase(pd, node);
                spin_lock(&pkt->lock);
                bio_list_add(&pkt->orig_bios, bio);
-               pkt->write_size += bio->bi_size / CD_FRAMESIZE;
+               pkt->write_size += bio->bi_iter.bi_size / CD_FRAMESIZE;
                spin_unlock(&pkt->lock);
        }
        /* check write congestion marks, and if bio_queue_size is
@@ -1293,7 +1296,7 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
        struct bio_vec *bvec = pkt->w_bio->bi_io_vec;
 
        bio_reset(pkt->w_bio);
-       pkt->w_bio->bi_sector = pkt->sector;
+       pkt->w_bio->bi_iter.bi_sector = pkt->sector;
        pkt->w_bio->bi_bdev = pd->bdev;
        pkt->w_bio->bi_end_io = pkt_end_io_packet_write;
        pkt->w_bio->bi_private = pkt;
@@ -2335,75 +2338,29 @@ static void pkt_end_io_read_cloned(struct bio *bio, int err)
        pkt_bio_finished(pd);
 }
 
-static void pkt_make_request(struct request_queue *q, struct bio *bio)
+static void pkt_make_request_read(struct pktcdvd_device *pd, struct bio *bio)
 {
-       struct pktcdvd_device *pd;
-       char b[BDEVNAME_SIZE];
+       struct bio *cloned_bio = bio_clone(bio, GFP_NOIO);
+       struct packet_stacked_data *psd = mempool_alloc(psd_pool, GFP_NOIO);
+
+       psd->pd = pd;
+       psd->bio = bio;
+       cloned_bio->bi_bdev = pd->bdev;
+       cloned_bio->bi_private = psd;
+       cloned_bio->bi_end_io = pkt_end_io_read_cloned;
+       pd->stats.secs_r += bio_sectors(bio);
+       pkt_queue_bio(pd, cloned_bio);
+}
+
+static void pkt_make_request_write(struct request_queue *q, struct bio *bio)
+{
+       struct pktcdvd_device *pd = q->queuedata;
        sector_t zone;
        struct packet_data *pkt;
        int was_empty, blocked_bio;
        struct pkt_rb_node *node;
 
-       pd = q->queuedata;
-       if (!pd) {
-               pr_err("%s incorrect request queue\n",
-                      bdevname(bio->bi_bdev, b));
-               goto end_io;
-       }
-
-       /*
-        * Clone READ bios so we can have our own bi_end_io callback.
-        */
-       if (bio_data_dir(bio) == READ) {
-               struct bio *cloned_bio = bio_clone(bio, GFP_NOIO);
-               struct packet_stacked_data *psd = mempool_alloc(psd_pool, GFP_NOIO);
-
-               psd->pd = pd;
-               psd->bio = bio;
-               cloned_bio->bi_bdev = pd->bdev;
-               cloned_bio->bi_private = psd;
-               cloned_bio->bi_end_io = pkt_end_io_read_cloned;
-               pd->stats.secs_r += bio_sectors(bio);
-               pkt_queue_bio(pd, cloned_bio);
-               return;
-       }
-
-       if (!test_bit(PACKET_WRITABLE, &pd->flags)) {
-               pkt_notice(pd, "WRITE for ro device (%llu)\n",
-                          (unsigned long long)bio->bi_sector);
-               goto end_io;
-       }
-
-       if (!bio->bi_size || (bio->bi_size % CD_FRAMESIZE)) {
-               pkt_err(pd, "wrong bio size\n");
-               goto end_io;
-       }
-
-       blk_queue_bounce(q, &bio);
-
-       zone = get_zone(bio->bi_sector, pd);
-       pkt_dbg(2, pd, "start = %6llx stop = %6llx\n",
-               (unsigned long long)bio->bi_sector,
-               (unsigned long long)bio_end_sector(bio));
-
-       /* Check if we have to split the bio */
-       {
-               struct bio_pair *bp;
-               sector_t last_zone;
-               int first_sectors;
-
-               last_zone = get_zone(bio_end_sector(bio) - 1, pd);
-               if (last_zone != zone) {
-                       BUG_ON(last_zone != zone + pd->settings.size);
-                       first_sectors = last_zone - bio->bi_sector;
-                       bp = bio_split(bio, first_sectors);
-                       BUG_ON(!bp);
-                       pkt_make_request(q, &bp->bio1);
-                       pkt_make_request(q, &bp->bio2);
-                       bio_pair_release(bp);
-                       return;
-               }
-       }
+       zone = get_zone(bio->bi_iter.bi_sector, pd);
 
        /*
         * If we find a matching packet in state WAITING or READ_WAIT, we can
@@ -2417,7 +2374,8 @@ static void pkt_make_request(struct request_queue *q, struct bio *bio)
                        if ((pkt->state == PACKET_WAITING_STATE) ||
                            (pkt->state == PACKET_READ_WAIT_STATE)) {
                                bio_list_add(&pkt->orig_bios, bio);
-                               pkt->write_size += bio->bi_size / CD_FRAMESIZE;
+                               pkt->write_size +=
+                                       bio->bi_iter.bi_size / CD_FRAMESIZE;
                                if ((pkt->write_size >= pkt->frames) &&
                                    (pkt->state == PACKET_WAITING_STATE)) {
                                        atomic_inc(&pkt->run_sm);
@@ -2476,6 +2434,64 @@ static void pkt_make_request(struct request_queue *q, struct bio *bio)
                 */
                wake_up(&pd->wqueue);
        }
+}
+
+static void pkt_make_request(struct request_queue *q, struct bio *bio)
+{
+       struct pktcdvd_device *pd;
+       char b[BDEVNAME_SIZE];
+       struct bio *split;
+
+       pd = q->queuedata;
+       if (!pd) {
+               pr_err("%s incorrect request queue\n",
+                      bdevname(bio->bi_bdev, b));
+               goto end_io;
+       }
+
+       pkt_dbg(2, pd, "start = %6llx stop = %6llx\n",
+               (unsigned long long)bio->bi_iter.bi_sector,
+               (unsigned long long)bio_end_sector(bio));
+
+       /*
+        * Clone READ bios so we can have our own bi_end_io callback.
+        */
+       if (bio_data_dir(bio) == READ) {
+               pkt_make_request_read(pd, bio);
+               return;
+       }
+
+       if (!test_bit(PACKET_WRITABLE, &pd->flags)) {
+               pkt_notice(pd, "WRITE for ro device (%llu)\n",
+                          (unsigned long long)bio->bi_iter.bi_sector);
+               goto end_io;
+       }
+
+       if (!bio->bi_iter.bi_size || (bio->bi_iter.bi_size % CD_FRAMESIZE)) {
+               pkt_err(pd, "wrong bio size\n");
+               goto end_io;
+       }
+
+       blk_queue_bounce(q, &bio);
+
+       do {
+               sector_t zone = get_zone(bio->bi_iter.bi_sector, pd);
+               sector_t last_zone = get_zone(bio_end_sector(bio) - 1, pd);
+
+               if (last_zone != zone) {
+                       BUG_ON(last_zone != zone + pd->settings.size);
+
+                       split = bio_split(bio, last_zone -
+                                         bio->bi_iter.bi_sector,
+                                         GFP_NOIO, fs_bio_set);
+                       bio_chain(split, bio);
+               } else {
+                       split = bio;
+               }
+
+               pkt_make_request_write(q, split);
+       } while (split != bio);
+
        return;
 end_io:
        bio_io_error(bio);
index d754a88d75858ef46f8553ac54b0163ff7b60d8a..c120d70d3fb3b31fdfb584859a8cdd5bf0849dab 100644 (file)
@@ -94,26 +94,25 @@ static void ps3disk_scatter_gather(struct ps3_storage_device *dev,
 {
        unsigned int offset = 0;
        struct req_iterator iter;
-       struct bio_vec *bvec;
+       struct bio_vec bvec;
        unsigned int i = 0;
        size_t size;
        void *buf;
 
        rq_for_each_segment(bvec, req, iter) {
                unsigned long flags;
-               dev_dbg(&dev->sbd.core,
-                       "%s:%u: bio %u: %u segs %u sectors from %lu\n",
-                       __func__, __LINE__, i, bio_segments(iter.bio),
-                       bio_sectors(iter.bio), iter.bio->bi_sector);
+               dev_dbg(&dev->sbd.core, "%s:%u: bio %u: %u sectors from %lu\n",
+                       __func__, __LINE__, i, bio_sectors(iter.bio),
+                       iter.bio->bi_iter.bi_sector);
 
-               size = bvec->bv_len;
-               buf = bvec_kmap_irq(bvec, &flags);
+               size = bvec.bv_len;
+               buf = bvec_kmap_irq(&bvec, &flags);
                if (gather)
                        memcpy(dev->bounce_buf+offset, buf, size);
                else
                        memcpy(buf, dev->bounce_buf+offset, size);
                offset += size;
-               flush_kernel_dcache_page(bvec->bv_page);
+               flush_kernel_dcache_page(bvec.bv_page);
                bvec_kunmap_irq(buf, &flags);
                i++;
        }
@@ -130,7 +129,7 @@ static int ps3disk_submit_request_sg(struct ps3_storage_device *dev,
 
 #ifdef DEBUG
        unsigned int n = 0;
-       struct bio_vec *bv;
+       struct bio_vec bv;
        struct req_iterator iter;
 
        rq_for_each_segment(bv, req, iter)
index 06a2e53e5f37299191b1d9c7fe5e2caf036461a6..ef45cfb98fd2f12278d9f9caa6d044c1336e7baa 100644 (file)
@@ -553,16 +553,16 @@ static struct bio *ps3vram_do_bio(struct ps3_system_bus_device *dev,
        struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
        int write = bio_data_dir(bio) == WRITE;
        const char *op = write ? "write" : "read";
-       loff_t offset = bio->bi_sector << 9;
+       loff_t offset = bio->bi_iter.bi_sector << 9;
        int error = 0;
-       struct bio_vec *bvec;
-       unsigned int i;
+       struct bio_vec bvec;
+       struct bvec_iter iter;
        struct bio *next;
 
-       bio_for_each_segment(bvec, bio, i) {
+       bio_for_each_segment(bvec, bio, iter) {
                /* PS3 is ppc64, so we don't handle highmem */
-               char *ptr = page_address(bvec->bv_page) + bvec->bv_offset;
-               size_t len = bvec->bv_len, retlen;
+               char *ptr = page_address(bvec.bv_page) + bvec.bv_offset;
+               size_t len = bvec.bv_len, retlen;
 
                dev_dbg(&dev->core, "    %s %zu bytes at offset %llu\n", op,
                        len, offset);
index cb1db2979d3d7b5417a8a4b131e09c5c5f6767c0..3624368b910dd30fe841cb42e2f13a8ec5109bc8 100644 (file)
@@ -1109,23 +1109,23 @@ static void bio_chain_put(struct bio *chain)
  */
 static void zero_bio_chain(struct bio *chain, int start_ofs)
 {
-       struct bio_vec *bv;
+       struct bio_vec bv;
+       struct bvec_iter iter;
        unsigned long flags;
        void *buf;
-       int i;
        int pos = 0;
 
        while (chain) {
-               bio_for_each_segment(bv, chain, i) {
-                       if (pos + bv->bv_len > start_ofs) {
+               bio_for_each_segment(bv, chain, iter) {
+                       if (pos + bv.bv_len > start_ofs) {
                                int remainder = max(start_ofs - pos, 0);
-                               buf = bvec_kmap_irq(bv, &flags);
+                               buf = bvec_kmap_irq(&bv, &flags);
                                memset(buf + remainder, 0,
-                                      bv->bv_len - remainder);
-                               flush_dcache_page(bv->bv_page);
+                                      bv.bv_len - remainder);
+                               flush_dcache_page(bv.bv_page);
                                bvec_kunmap_irq(buf, &flags);
                        }
-                       pos += bv->bv_len;
+                       pos += bv.bv_len;
                }
 
                chain = chain->bi_next;
@@ -1173,74 +1173,14 @@ static struct bio *bio_clone_range(struct bio *bio_src,
                                        unsigned int len,
                                        gfp_t gfpmask)
 {
-       struct bio_vec *bv;
-       unsigned int resid;
-       unsigned short idx;
-       unsigned int voff;
-       unsigned short end_idx;
-       unsigned short vcnt;
        struct bio *bio;
 
-       /* Handle the easy case for the caller */
-
-       if (!offset && len == bio_src->bi_size)
-               return bio_clone(bio_src, gfpmask);
-
-       if (WARN_ON_ONCE(!len))
-               return NULL;
-       if (WARN_ON_ONCE(len > bio_src->bi_size))
-               return NULL;
-       if (WARN_ON_ONCE(offset > bio_src->bi_size - len))
-               return NULL;
-
-       /* Find first affected segment... */
-
-       resid = offset;
-       bio_for_each_segment(bv, bio_src, idx) {
-               if (resid < bv->bv_len)
-                       break;
-               resid -= bv->bv_len;
-       }
-       voff = resid;
-
-       /* ...and the last affected segment */
-
-       resid += len;
-       __bio_for_each_segment(bv, bio_src, end_idx, idx) {
-               if (resid <= bv->bv_len)
-                       break;
-               resid -= bv->bv_len;
-       }
-       vcnt = end_idx - idx + 1;
-
-       /* Build the clone */
-
-       bio = bio_alloc(gfpmask, (unsigned int) vcnt);
+       bio = bio_clone(bio_src, gfpmask);
        if (!bio)
                return NULL;    /* ENOMEM */
 
-       bio->bi_bdev = bio_src->bi_bdev;
-       bio->bi_sector = bio_src->bi_sector + (offset >> SECTOR_SHIFT);
-       bio->bi_rw = bio_src->bi_rw;
-       bio->bi_flags |= 1 << BIO_CLONED;
-
-       /*
-        * Copy over our part of the bio_vec, then update the first
-        * and last (or only) entries.
-        */
-       memcpy(&bio->bi_io_vec[0], &bio_src->bi_io_vec[idx],
-                       vcnt * sizeof (struct bio_vec));
-       bio->bi_io_vec[0].bv_offset += voff;
-       if (vcnt > 1) {
-               bio->bi_io_vec[0].bv_len -= voff;
-               bio->bi_io_vec[vcnt - 1].bv_len = resid;
-       } else {
-               bio->bi_io_vec[0].bv_len = len;
-       }
-
-       bio->bi_vcnt = vcnt;
-       bio->bi_size = len;
-       bio->bi_idx = 0;
+       bio_advance(bio, offset);
+       bio->bi_iter.bi_size = len;
 
        return bio;
 }
@@ -1271,7 +1211,7 @@ static struct bio *bio_chain_clone_range(struct bio **bio_src,
 
        /* Build up a chain of clone bios up to the limit */
 
-       if (!bi || off >= bi->bi_size || !len)
+       if (!bi || off >= bi->bi_iter.bi_size || !len)
                return NULL;            /* Nothing to clone */
 
        end = &chain;
@@ -1283,7 +1223,7 @@ static struct bio *bio_chain_clone_range(struct bio **bio_src,
                        rbd_warn(NULL, "bio_chain exhausted with %u left", len);
                        goto out_err;   /* EINVAL; ran out of bio's */
                }
-               bi_size = min_t(unsigned int, bi->bi_size - off, len);
+               bi_size = min_t(unsigned int, bi->bi_iter.bi_size - off, len);
                bio = bio_clone_range(bi, off, bi_size, gfpmask);
                if (!bio)
                        goto out_err;   /* ENOMEM */
@@ -1292,7 +1232,7 @@ static struct bio *bio_chain_clone_range(struct bio **bio_src,
                end = &bio->bi_next;
 
                off += bi_size;
-               if (off == bi->bi_size) {
+               if (off == bi->bi_iter.bi_size) {
                        bi = bi->bi_next;
                        off = 0;
                }
@@ -2186,7 +2126,8 @@ static int rbd_img_request_fill(struct rbd_img_request *img_request,
 
        if (type == OBJ_REQUEST_BIO) {
                bio_list = data_desc;
-               rbd_assert(img_offset == bio_list->bi_sector << SECTOR_SHIFT);
+               rbd_assert(img_offset ==
+                          bio_list->bi_iter.bi_sector << SECTOR_SHIFT);
        } else {
                rbd_assert(type == OBJ_REQUEST_PAGES);
                pages = data_desc;
index 2284f5d3a54ad00dd05c512b30b7bfed30411482..2839d37e5af77922051cb1d48561602ea3a3c2b7 100644 (file)
@@ -174,7 +174,7 @@ static void rsxx_make_request(struct request_queue *q, struct bio *bio)
        if (!card)
                goto req_err;
 
-       if (bio->bi_sector + (bio->bi_size >> 9) > get_capacity(card->gendisk))
+       if (bio_end_sector(bio) > get_capacity(card->gendisk))
                goto req_err;
 
        if (unlikely(card->halt)) {
@@ -187,7 +187,7 @@ static void rsxx_make_request(struct request_queue *q, struct bio *bio)
                goto req_err;
        }
 
-       if (bio->bi_size == 0) {
+       if (bio->bi_iter.bi_size == 0) {
                dev_err(CARD_TO_DEV(card), "size zero BIO!\n");
                goto req_err;
        }
@@ -208,7 +208,7 @@ static void rsxx_make_request(struct request_queue *q, struct bio *bio)
 
        dev_dbg(CARD_TO_DEV(card), "BIO[%c]: meta: %p addr8: x%llx size: %d\n",
                 bio_data_dir(bio) ? 'W' : 'R', bio_meta,
-                (u64)bio->bi_sector << 9, bio->bi_size);
+                (u64)bio->bi_iter.bi_sector << 9, bio->bi_iter.bi_size);
 
        st = rsxx_dma_queue_bio(card, bio, &bio_meta->pending_dmas,
                                    bio_dma_done_cb, bio_meta);
index fc88ba3e1bd27835ecf170d5ba321cf8313a6cea..cf8cd293abb51d338cd6d0ae7762070c80be99a2 100644 (file)
@@ -684,7 +684,8 @@ int rsxx_dma_queue_bio(struct rsxx_cardinfo *card,
                           void *cb_data)
 {
        struct list_head dma_list[RSXX_MAX_TARGETS];
-       struct bio_vec *bvec;
+       struct bio_vec bvec;
+       struct bvec_iter iter;
        unsigned long long addr8;
        unsigned int laddr;
        unsigned int bv_len;
@@ -696,7 +697,7 @@ int rsxx_dma_queue_bio(struct rsxx_cardinfo *card,
        int st;
        int i;
 
-       addr8 = bio->bi_sector << 9; /* sectors are 512 bytes */
+       addr8 = bio->bi_iter.bi_sector << 9; /* sectors are 512 bytes */
        atomic_set(n_dmas, 0);
 
        for (i = 0; i < card->n_targets; i++) {
@@ -705,7 +706,7 @@ int rsxx_dma_queue_bio(struct rsxx_cardinfo *card,
        }
 
        if (bio->bi_rw & REQ_DISCARD) {
-               bv_len = bio->bi_size;
+               bv_len = bio->bi_iter.bi_size;
 
                while (bv_len > 0) {
                        tgt   = rsxx_get_dma_tgt(card, addr8);
@@ -722,9 +723,9 @@ int rsxx_dma_queue_bio(struct rsxx_cardinfo *card,
                        bv_len -= RSXX_HW_BLK_SIZE;
                }
        } else {
-               bio_for_each_segment(bvec, bio, i) {
-                       bv_len = bvec->bv_len;
-                       bv_off = bvec->bv_offset;
+               bio_for_each_segment(bvec, bio, iter) {
+                       bv_len = bvec.bv_len;
+                       bv_off = bvec.bv_offset;
 
                        while (bv_len > 0) {
                                tgt   = rsxx_get_dma_tgt(card, addr8);
@@ -736,7 +737,7 @@ int rsxx_dma_queue_bio(struct rsxx_cardinfo *card,
                                st = rsxx_queue_dma(card, &dma_list[tgt],
                                                        bio_data_dir(bio),
                                                        dma_off, dma_len,
-                                                       laddr, bvec->bv_page,
+                                                       laddr, bvec.bv_page,
                                                        bv_off, cb, cb_data);
                                if (st)
                                        goto bvec_err;
index ad70868f8a967b40bc866bc5430387b55f4601ac..4cf81b5bf0f7fba42a243a7e717ead98b2144759 100644 (file)
@@ -108,8 +108,7 @@ struct cardinfo {
                                    * have been written
                                    */
        struct bio      *bio, *currentbio, **biotail;
-       int             current_idx;
-       sector_t        current_sector;
+       struct bvec_iter current_iter;
 
        struct request_queue *queue;
 
@@ -118,7 +117,7 @@ struct cardinfo {
                struct mm_dma_desc      *desc;
                int                     cnt, headcnt;
                struct bio              *bio, **biotail;
-               int                     idx;
+               struct bvec_iter        iter;
        } mm_pages[2];
 #define DESC_PER_PAGE ((PAGE_SIZE*2)/sizeof(struct mm_dma_desc))
 
@@ -344,16 +343,13 @@ static int add_bio(struct cardinfo *card)
        dma_addr_t dma_handle;
        int offset;
        struct bio *bio;
-       struct bio_vec *vec;
-       int idx;
+       struct bio_vec vec;
        int rw;
-       int len;
 
        bio = card->currentbio;
        if (!bio && card->bio) {
                card->currentbio = card->bio;
-               card->current_idx = card->bio->bi_idx;
-               card->current_sector = card->bio->bi_sector;
+               card->current_iter = card->bio->bi_iter;
                card->bio = card->bio->bi_next;
                if (card->bio == NULL)
                        card->biotail = &card->bio;
@@ -362,18 +358,17 @@ static int add_bio(struct cardinfo *card)
        }
        if (!bio)
                return 0;
-       idx = card->current_idx;
 
        rw = bio_rw(bio);
        if (card->mm_pages[card->Ready].cnt >= DESC_PER_PAGE)
                return 0;
 
-       vec = bio_iovec_idx(bio, idx);
-       len = vec->bv_len;
+       vec = bio_iter_iovec(bio, card->current_iter);
+
        dma_handle = pci_map_page(card->dev,
-                                 vec->bv_page,
-                                 vec->bv_offset,
-                                 len,
+                                 vec.bv_page,
+                                 vec.bv_offset,
+                                 vec.bv_len,
                                  (rw == READ) ?
                                  PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
 
@@ -381,7 +376,7 @@ static int add_bio(struct cardinfo *card)
        desc = &p->desc[p->cnt];
        p->cnt++;
        if (p->bio == NULL)
-               p->idx = idx;
+               p->iter = card->current_iter;
        if ((p->biotail) != &bio->bi_next) {
                *(p->biotail) = bio;
                p->biotail = &(bio->bi_next);
@@ -391,8 +386,8 @@ static int add_bio(struct cardinfo *card)
        desc->data_dma_handle = dma_handle;
 
        desc->pci_addr = cpu_to_le64((u64)desc->data_dma_handle);
-       desc->local_addr = cpu_to_le64(card->current_sector << 9);
-       desc->transfer_size = cpu_to_le32(len);
+       desc->local_addr = cpu_to_le64(card->current_iter.bi_sector << 9);
+       desc->transfer_size = cpu_to_le32(vec.bv_len);
        offset = (((char *)&desc->sem_control_bits) - ((char *)p->desc));
        desc->sem_addr = cpu_to_le64((u64)(p->page_dma+offset));
        desc->zero1 = desc->zero2 = 0;
@@ -407,10 +402,9 @@ static int add_bio(struct cardinfo *card)
                desc->control_bits |= cpu_to_le32(DMASCR_TRANSFER_READ);
        desc->sem_control_bits = desc->control_bits;
 
-       card->current_sector += (len >> 9);
-       idx++;
-       card->current_idx = idx;
-       if (idx >= bio->bi_vcnt)
+
+       bio_advance_iter(bio, &card->current_iter, vec.bv_len);
+       if (!card->current_iter.bi_size)
                card->currentbio = NULL;
 
        return 1;
@@ -439,23 +433,25 @@ static void process_page(unsigned long data)
                struct mm_dma_desc *desc = &page->desc[page->headcnt];
                int control = le32_to_cpu(desc->sem_control_bits);
                int last = 0;
-               int idx;
+               struct bio_vec vec;
 
                if (!(control & DMASCR_DMA_COMPLETE)) {
                        control = dma_status;
                        last = 1;
                }
+
                page->headcnt++;
-               idx = page->idx;
-               page->idx++;
-               if (page->idx >= bio->bi_vcnt) {
+               vec = bio_iter_iovec(bio, page->iter);
+               bio_advance_iter(bio, &page->iter, vec.bv_len);
+
+               if (!page->iter.bi_size) {
                        page->bio = bio->bi_next;
                        if (page->bio)
-                               page->idx = page->bio->bi_idx;
+                               page->iter = page->bio->bi_iter;
                }
 
                pci_unmap_page(card->dev, desc->data_dma_handle,
-                              bio_iovec_idx(bio, idx)->bv_len,
+                              vec.bv_len,
                                 (control & DMASCR_TRANSFER_READ) ?
                                PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
                if (control & DMASCR_HARD_ERROR) {
@@ -532,7 +528,8 @@ static void mm_make_request(struct request_queue *q, struct bio *bio)
 {
        struct cardinfo *card = q->queuedata;
        pr_debug("mm_make_request %llu %u\n",
-                (unsigned long long)bio->bi_sector, bio->bi_size);
+                (unsigned long long)bio->bi_iter.bi_sector,
+                bio->bi_iter.bi_size);
 
        spin_lock_irq(&card->lock);
        *card->biotail = bio;
index 6620b73d04906191132d771dade31f9e00043e07..4b97b86da9265b4ca5dcb3a7ab562dbf1eb5bac0 100644 (file)
@@ -1257,7 +1257,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
                        bio->bi_bdev    = preq.bdev;
                        bio->bi_private = pending_req;
                        bio->bi_end_io  = end_block_io_op;
-                       bio->bi_sector  = preq.sector_number;
+                       bio->bi_iter.bi_sector  = preq.sector_number;
                }
 
                preq.sector_number += seg[i].nsec;
index 432db1b59b003a837679cd187c4743f98ca9b152..26ad7923e3319c802a4ab252001ecdf8785b8d60 100644 (file)
@@ -489,7 +489,7 @@ static int blkif_queue_request(struct request *req)
 
                        if ((ring_req->operation == BLKIF_OP_INDIRECT) &&
                            (i % SEGS_PER_INDIRECT_FRAME == 0)) {
-                               unsigned long pfn;
+                               unsigned long uninitialized_var(pfn);
 
                                if (segments)
                                        kunmap_atomic(segments);
@@ -1547,7 +1547,7 @@ static int blkif_recover(struct blkfront_info *info)
                        for (i = 0; i < pending; i++) {
                                offset = (i * segs * PAGE_SIZE) >> 9;
                                size = min((unsigned int)(segs * PAGE_SIZE) >> 9,
-                                          (unsigned int)(bio->bi_size >> 9) - offset);
+                                          (unsigned int)bio_sectors(bio) - offset);
                                cloned_bio = bio_clone(bio, GFP_NOIO);
                                BUG_ON(cloned_bio == NULL);
                                bio_trim(cloned_bio, offset, size);
@@ -2011,6 +2011,10 @@ static void blkif_release(struct gendisk *disk, fmode_t mode)
 
        bdev = bdget_disk(disk, 0);
 
+       if (!bdev) {
+               WARN(1, "Block device %s yanked out from us!\n", disk->disk_name);
+               goto out_mutex;
+       }
        if (bdev->bd_openers)
                goto out;
 
@@ -2041,6 +2045,7 @@ static void blkif_release(struct gendisk *disk, fmode_t mode)
 
 out:
        bdput(bdev);
+out_mutex:
        mutex_unlock(&blkfront_mutex);
 }
 
index 5a95baf4b104e4c2dc559534867effa53e6327a2..27de5046708a233cbc99e42a4349387f9f5157cb 100644 (file)
@@ -43,9 +43,6 @@
 #include <linux/zorro.h>
 
 
-extern int m68k_realnum_memory;
-extern struct mem_info m68k_memory[NUM_MEMINFO];
-
 #define Z2MINOR_COMBINED      (0)
 #define Z2MINOR_Z2ONLY        (1)
 #define Z2MINOR_CHIPONLY      (2)
@@ -116,8 +113,8 @@ get_z2ram( void )
        if ( test_bit( i, zorro_unused_z2ram ) )
        {
            z2_count++;
-           z2ram_map[ z2ram_size++ ] = 
-               ZTWO_VADDR( Z2RAM_START ) + ( i << Z2RAM_CHUNKSHIFT );
+           z2ram_map[z2ram_size++] = (unsigned long)ZTWO_VADDR(Z2RAM_START) +
+                                     (i << Z2RAM_CHUNKSHIFT);
            clear_bit( i, zorro_unused_z2ram );
        }
     }
index 6bfc1bb318f6399397ca8f169cc07fd98b46256d..d3fdc32b579d72afcee794d9ba68c68b1f4c367d 100644 (file)
@@ -83,6 +83,7 @@ static const struct usb_device_id ath3k_table[] = {
        { USB_DEVICE(0x04CA, 0x3005) },
        { USB_DEVICE(0x04CA, 0x3006) },
        { USB_DEVICE(0x04CA, 0x3008) },
+       { USB_DEVICE(0x04CA, 0x300b) },
        { USB_DEVICE(0x13d3, 0x3362) },
        { USB_DEVICE(0x0CF3, 0xE004) },
        { USB_DEVICE(0x0CF3, 0xE005) },
@@ -96,6 +97,7 @@ static const struct usb_device_id ath3k_table[] = {
        { USB_DEVICE(0x13d3, 0x3402) },
        { USB_DEVICE(0x0cf3, 0x3121) },
        { USB_DEVICE(0x0cf3, 0xe003) },
+       { USB_DEVICE(0x0489, 0xe05f) },
 
        /* Atheros AR5BBU12 with sflash firmware */
        { USB_DEVICE(0x0489, 0xE02C) },
@@ -125,6 +127,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
        { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x04ca, 0x300b), .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 },
@@ -138,6 +141,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
        { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 },
 
        /* Atheros AR5BBU22 with sflash firmware */
        { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 },
index f9d183387f4585b37e0642aef9e269e17c6be1a4..7399303d7d9978447ff722d823c1dcece408029a 100644 (file)
@@ -23,8 +23,6 @@
 #include <linux/bitops.h>
 #include <linux/slab.h>
 #include <net/bluetooth/bluetooth.h>
-#include <linux/ctype.h>
-#include <linux/firmware.h>
 
 #define BTM_HEADER_LEN                 4
 #define BTM_UPLD_SIZE                  2312
@@ -43,8 +41,6 @@ struct btmrvl_thread {
 struct btmrvl_device {
        void *card;
        struct hci_dev *hcidev;
-       struct device *dev;
-       const char *cal_data;
 
        u8 dev_type;
 
@@ -90,12 +86,12 @@ struct btmrvl_private {
 
 #define MRVL_VENDOR_PKT                        0xFE
 
-/* Bluetooth commands  */
-#define BT_CMD_AUTO_SLEEP_MODE         0x23
-#define BT_CMD_HOST_SLEEP_CONFIG       0x59
-#define BT_CMD_HOST_SLEEP_ENABLE       0x5A
-#define BT_CMD_MODULE_CFG_REQ          0x5B
-#define BT_CMD_LOAD_CONFIG_DATA                0x61
+/* Vendor specific Bluetooth commands */
+#define BT_CMD_AUTO_SLEEP_MODE         0xFC23
+#define BT_CMD_HOST_SLEEP_CONFIG       0xFC59
+#define BT_CMD_HOST_SLEEP_ENABLE       0xFC5A
+#define BT_CMD_MODULE_CFG_REQ          0xFC5B
+#define BT_CMD_LOAD_CONFIG_DATA                0xFC61
 
 /* Sub-commands: Module Bringup/Shutdown Request/Response */
 #define MODULE_BRINGUP_REQ             0xF1
@@ -104,6 +100,11 @@ struct btmrvl_private {
 
 #define MODULE_SHUTDOWN_REQ            0xF2
 
+/* Vendor specific Bluetooth events */
+#define BT_EVENT_AUTO_SLEEP_MODE       0x23
+#define BT_EVENT_HOST_SLEEP_CONFIG     0x59
+#define BT_EVENT_HOST_SLEEP_ENABLE     0x5A
+#define BT_EVENT_MODULE_CFG_REQ                0x5B
 #define BT_EVENT_POWER_STATE           0x20
 
 /* Bluetooth Power States */
@@ -111,8 +112,6 @@ struct btmrvl_private {
 #define BT_PS_DISABLE                  0x03
 #define BT_PS_SLEEP                    0x01
 
-#define OGF                            0x3F
-
 /* Host Sleep states */
 #define HS_ACTIVATED                   0x01
 #define HS_DEACTIVATED                 0x00
@@ -121,7 +120,7 @@ struct btmrvl_private {
 #define PS_SLEEP                       0x01
 #define PS_AWAKE                       0x00
 
-#define BT_CMD_DATA_SIZE               32
+#define BT_CAL_HDR_LEN                 4
 #define BT_CAL_DATA_SIZE               28
 
 struct btmrvl_event {
index 5cf31c4fe6d1cf552c9846c8fe7a79857851c9b6..1e0320af00c63be9a1fdd808e8c0301dedf7ad0a 100644 (file)
@@ -19,7 +19,7 @@
  **/
 
 #include <linux/module.h>
-
+#include <linux/of.h>
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 
@@ -50,12 +50,10 @@ bool btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb)
 
        if (hdr->evt == HCI_EV_CMD_COMPLETE) {
                struct hci_ev_cmd_complete *ec;
-               u16 opcode, ocf, ogf;
+               u16 opcode;
 
                ec = (void *) (skb->data + HCI_EVENT_HDR_SIZE);
                opcode = __le16_to_cpu(ec->opcode);
-               ocf = hci_opcode_ocf(opcode);
-               ogf = hci_opcode_ogf(opcode);
 
                if (priv->btmrvl_dev.sendcmdflag) {
                        priv->btmrvl_dev.sendcmdflag = false;
@@ -63,9 +61,8 @@ bool btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb)
                        wake_up_interruptible(&priv->adapter->cmd_wait_q);
                }
 
-               if (ogf == OGF) {
-                       BT_DBG("vendor event skipped: ogf 0x%4.4x ocf 0x%4.4x",
-                              ogf, ocf);
+               if (hci_opcode_ogf(opcode) == 0x3F) {
+                       BT_DBG("vendor event skipped: opcode=%#4.4x", opcode);
                        kfree_skb(skb);
                        return false;
                }
@@ -89,7 +86,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
        }
 
        switch (event->data[0]) {
-       case BT_CMD_AUTO_SLEEP_MODE:
+       case BT_EVENT_AUTO_SLEEP_MODE:
                if (!event->data[2]) {
                        if (event->data[1] == BT_PS_ENABLE)
                                adapter->psmode = 1;
@@ -102,7 +99,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
                }
                break;
 
-       case BT_CMD_HOST_SLEEP_CONFIG:
+       case BT_EVENT_HOST_SLEEP_CONFIG:
                if (!event->data[3])
                        BT_DBG("gpio=%x, gap=%x", event->data[1],
                                                        event->data[2]);
@@ -110,7 +107,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
                        BT_DBG("HSCFG command failed");
                break;
 
-       case BT_CMD_HOST_SLEEP_ENABLE:
+       case BT_EVENT_HOST_SLEEP_ENABLE:
                if (!event->data[1]) {
                        adapter->hs_state = HS_ACTIVATED;
                        if (adapter->psmode)
@@ -121,7 +118,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
                }
                break;
 
-       case BT_CMD_MODULE_CFG_REQ:
+       case BT_EVENT_MODULE_CFG_REQ:
                if (priv->btmrvl_dev.sendcmdflag &&
                                event->data[1] == MODULE_BRINGUP_REQ) {
                        BT_DBG("EVENT:%s",
@@ -166,7 +163,7 @@ exit:
 }
 EXPORT_SYMBOL_GPL(btmrvl_process_event);
 
-static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 cmd_no,
+static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 opcode,
                                const void *param, u8 len)
 {
        struct sk_buff *skb;
@@ -179,7 +176,7 @@ static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 cmd_no,
        }
 
        hdr = (struct hci_command_hdr *)skb_put(skb, HCI_COMMAND_HDR_SIZE);
-       hdr->opcode = cpu_to_le16(hci_opcode_pack(OGF, cmd_no));
+       hdr->opcode = cpu_to_le16(opcode);
        hdr->plen = len;
 
        if (len)
@@ -417,127 +414,62 @@ static int btmrvl_open(struct hci_dev *hdev)
        return 0;
 }
 
-/*
- * This function parses provided calibration data input. It should contain
- * hex bytes separated by space or new line character. Here is an example.
- * 00 1C 01 37 FF FF FF FF 02 04 7F 01
- * CE BA 00 00 00 2D C6 C0 00 00 00 00
- * 00 F0 00 00
- */
-static int btmrvl_parse_cal_cfg(const u8 *src, u32 len, u8 *dst, u32 dst_size)
+static int btmrvl_download_cal_data(struct btmrvl_private *priv,
+                                   u8 *data, int len)
 {
-       const u8 *s = src;
-       u8 *d = dst;
        int ret;
-       u8 tmp[3];
-
-       tmp[2] = '\0';
-       while ((s - src) <= len - 2) {
-               if (isspace(*s)) {
-                       s++;
-                       continue;
-               }
-
-               if (isxdigit(*s)) {
-                       if ((d - dst) >= dst_size) {
-                               BT_ERR("calibration data file too big!!!");
-                               return -EINVAL;
-                       }
-
-                       memcpy(tmp, s, 2);
-
-                       ret = kstrtou8(tmp, 16, d++);
-                       if (ret < 0)
-                               return ret;
-
-                       s += 2;
-               } else {
-                       return -EINVAL;
-               }
-       }
-       if (d == dst)
-               return -EINVAL;
-
-       return 0;
-}
-
-static int btmrvl_load_cal_data(struct btmrvl_private *priv,
-                               u8 *config_data)
-{
-       int i, ret;
-       u8 data[BT_CMD_DATA_SIZE];
 
        data[0] = 0x00;
        data[1] = 0x00;
        data[2] = 0x00;
-       data[3] = BT_CMD_DATA_SIZE - 4;
-
-       /* Swap cal-data bytes. Each four bytes are swapped. Considering 4
-        * byte SDIO header offset, mapping of input and output bytes will be
-        * {3, 2, 1, 0} -> {0+4, 1+4, 2+4, 3+4},
-        * {7, 6, 5, 4} -> {4+4, 5+4, 6+4, 7+4} */
-       for (i = 4; i < BT_CMD_DATA_SIZE; i++)
-               data[i] = config_data[(i / 4) * 8 - 1 - i];
+       data[3] = len;
 
        print_hex_dump_bytes("Calibration data: ",
-                            DUMP_PREFIX_OFFSET, data, BT_CMD_DATA_SIZE);
+                            DUMP_PREFIX_OFFSET, data, BT_CAL_HDR_LEN + len);
 
        ret = btmrvl_send_sync_cmd(priv, BT_CMD_LOAD_CONFIG_DATA, data,
-                                  BT_CMD_DATA_SIZE);
+                                  BT_CAL_HDR_LEN + len);
        if (ret)
                BT_ERR("Failed to download caibration data\n");
 
        return 0;
 }
 
-static int
-btmrvl_process_cal_cfg(struct btmrvl_private *priv, u8 *data, u32 size)
+static int btmrvl_cal_data_dt(struct btmrvl_private *priv)
 {
-       u8 cal_data[BT_CAL_DATA_SIZE];
+       struct device_node *dt_node;
+       u8 cal_data[BT_CAL_HDR_LEN + BT_CAL_DATA_SIZE];
+       const char name[] = "btmrvl_caldata";
+       const char property[] = "btmrvl,caldata";
        int ret;
 
-       ret = btmrvl_parse_cal_cfg(data, size, cal_data, sizeof(cal_data));
+       dt_node = of_find_node_by_name(NULL, name);
+       if (!dt_node)
+               return -ENODEV;
+
+       ret = of_property_read_u8_array(dt_node, property,
+                                       cal_data + BT_CAL_HDR_LEN,
+                                       BT_CAL_DATA_SIZE);
        if (ret)
                return ret;
 
-       ret = btmrvl_load_cal_data(priv, cal_data);
+       BT_DBG("Use cal data from device tree");
+       ret = btmrvl_download_cal_data(priv, cal_data, BT_CAL_DATA_SIZE);
        if (ret) {
-               BT_ERR("Fail to load calibrate data");
+               BT_ERR("Fail to download calibrate data");
                return ret;
        }
 
        return 0;
 }
 
-static int btmrvl_cal_data_config(struct btmrvl_private *priv)
-{
-       const struct firmware *cfg;
-       int ret;
-       const char *cal_data = priv->btmrvl_dev.cal_data;
-
-       if (!cal_data)
-               return 0;
-
-       ret = request_firmware(&cfg, cal_data, priv->btmrvl_dev.dev);
-       if (ret < 0) {
-               BT_DBG("Failed to get %s file, skipping cal data download",
-                      cal_data);
-               return 0;
-       }
-
-       ret = btmrvl_process_cal_cfg(priv, (u8 *)cfg->data, cfg->size);
-       release_firmware(cfg);
-       return ret;
-}
-
 static int btmrvl_setup(struct hci_dev *hdev)
 {
        struct btmrvl_private *priv = hci_get_drvdata(hdev);
 
        btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
 
-       if (btmrvl_cal_data_config(priv))
-               BT_ERR("Set cal data failed");
+       btmrvl_cal_data_dt(priv);
 
        priv->btmrvl_dev.psmode = 1;
        btmrvl_enable_ps(priv);
index fabcf5bb48afbb1c62cf5145d5a12f60eb3a05a8..1b52c9f5230d324d0476a2d7dd3f308e7fd723d8 100644 (file)
@@ -18,6 +18,7 @@
  * this warranty disclaimer.
  **/
 
+#include <linux/firmware.h>
 #include <linux/slab.h>
 
 #include <linux/mmc/sdio_ids.h>
@@ -101,7 +102,6 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_88xx = {
 static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
        .helper         = "mrvl/sd8688_helper.bin",
        .firmware       = "mrvl/sd8688.bin",
-       .cal_data       = NULL,
        .reg            = &btmrvl_reg_8688,
        .sd_blksz_fw_dl = 64,
 };
@@ -109,7 +109,6 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
 static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = {
        .helper         = NULL,
        .firmware       = "mrvl/sd8787_uapsta.bin",
-       .cal_data       = NULL,
        .reg            = &btmrvl_reg_87xx,
        .sd_blksz_fw_dl = 256,
 };
@@ -117,7 +116,6 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = {
 static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = {
        .helper         = NULL,
        .firmware       = "mrvl/sd8797_uapsta.bin",
-       .cal_data       = "mrvl/sd8797_caldata.conf",
        .reg            = &btmrvl_reg_87xx,
        .sd_blksz_fw_dl = 256,
 };
@@ -125,7 +123,6 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = {
 static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = {
        .helper         = NULL,
        .firmware       = "mrvl/sd8897_uapsta.bin",
-       .cal_data       = NULL,
        .reg            = &btmrvl_reg_88xx,
        .sd_blksz_fw_dl = 256,
 };
@@ -1007,7 +1004,6 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
                struct btmrvl_sdio_device *data = (void *) id->driver_data;
                card->helper = data->helper;
                card->firmware = data->firmware;
-               card->cal_data = data->cal_data;
                card->reg = data->reg;
                card->sd_blksz_fw_dl = data->sd_blksz_fw_dl;
        }
@@ -1036,8 +1032,6 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
        }
 
        card->priv = priv;
-       priv->btmrvl_dev.dev = &card->func->dev;
-       priv->btmrvl_dev.cal_data = card->cal_data;
 
        /* Initialize the interface specific function pointers */
        priv->hw_host_to_card = btmrvl_sdio_host_to_card;
@@ -1220,5 +1214,4 @@ MODULE_FIRMWARE("mrvl/sd8688_helper.bin");
 MODULE_FIRMWARE("mrvl/sd8688.bin");
 MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
 MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin");
-MODULE_FIRMWARE("mrvl/sd8797_caldata.conf");
 MODULE_FIRMWARE("mrvl/sd8897_uapsta.bin");
index 6872d9ecac074ba04792c22776b3baee3971c9de..43d35a609ca9a94795afb731d230fa88ca109bef 100644 (file)
@@ -85,7 +85,6 @@ struct btmrvl_sdio_card {
        u32 ioport;
        const char *helper;
        const char *firmware;
-       const char *cal_data;
        const struct btmrvl_sdio_card_reg *reg;
        u16 sd_blksz_fw_dl;
        u8 rx_unit;
@@ -95,7 +94,6 @@ struct btmrvl_sdio_card {
 struct btmrvl_sdio_device {
        const char *helper;
        const char *firmware;
-       const char *cal_data;
        const struct btmrvl_sdio_card_reg *reg;
        u16 sd_blksz_fw_dl;
 };
index c0ff34f2d2df577efffe902562f9578690ea4e39..bfbcc5a772a61ecb1619d6bbb988eb22bb9f0fef 100644 (file)
@@ -150,6 +150,7 @@ static const struct usb_device_id blacklist_table[] = {
        { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x04ca, 0x300b), .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 },
@@ -163,6 +164,7 @@ static const struct usb_device_id blacklist_table[] = {
        { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 },
 
        /* Atheros AR5BBU12 with sflash firmware */
        { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
@@ -223,6 +225,7 @@ static const struct usb_device_id blacklist_table[] = {
 
        /* Intel Bluetooth device */
        { USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL },
+       { USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL },
 
        { }     /* Terminating entry */
 };
@@ -1435,8 +1438,10 @@ static int btusb_probe(struct usb_interface *intf,
        if (id->driver_info & BTUSB_BCM92035)
                hdev->setup = btusb_setup_bcm92035;
 
-       if (id->driver_info & BTUSB_INTEL)
+       if (id->driver_info & BTUSB_INTEL) {
+               usb_enable_autosuspend(data->udev);
                hdev->setup = btusb_setup_intel;
+       }
 
        /* Interface numbers are hardcoded in the specification */
        data->isoc = usb_ifnum_to_if(data->udev, 1);
index 2394e9753ef56b47e93d91bd7499eeb657c51383..725c46162bbd1cb0ad05624502ad16030e5991ca 100644 (file)
@@ -588,12 +588,6 @@ static const struct mvebu_mbus_soc_data mv78xx0_mbus_data = {
        .show_cpu_target     = mvebu_sdram_debug_show_orion,
 };
 
-/*
- * The driver doesn't yet have a DT binding because the details of
- * this DT binding still need to be sorted out. However, as a
- * preparation, we already use of_device_id to match a SoC description
- * string against the SoC specific details of this driver.
- */
 static const struct of_device_id of_mvebu_mbus_ids[] = {
        { .compatible = "marvell,armada370-mbus",
          .data = &armada_370_xp_mbus_data, },
@@ -734,11 +728,11 @@ int __init mvebu_mbus_init(const char *soc, phys_addr_t mbuswins_phys_base,
 {
        const struct of_device_id *of_id;
 
-       for (of_id = of_mvebu_mbus_ids; of_id->compatible; of_id++)
+       for (of_id = of_mvebu_mbus_ids; of_id->compatible[0]; of_id++)
                if (!strcmp(of_id->compatible, soc))
                        break;
 
-       if (!of_id->compatible) {
+       if (!of_id->compatible[0]) {
                pr_err("could not find a matching SoC family\n");
                return -ENODEV;
        }
index ecf85fda0fc100d136afa85ab983b22767ab147f..8ffde4f8ab9ae53f3f6007890a709ce795d19d8f 100644 (file)
@@ -10,5 +10,4 @@ obj-$(CONFIG_BLK_DEV_SR)      +=              cdrom.o
 obj-$(CONFIG_PARIDE_PCD)       +=              cdrom.o
 obj-$(CONFIG_CDROM_PKTCDVD)    +=              cdrom.o
 
-obj-$(CONFIG_VIOCD)            += viocd.o      cdrom.o
 obj-$(CONFIG_GDROM)            += gdrom.o      cdrom.o
index 5980cb9af857891491baee6026efe16cb84694de..51e75ad964223e07268e0781caa5fa9230f43824 100644 (file)
@@ -561,11 +561,11 @@ static int gdrom_set_interrupt_handlers(void)
        int err;
 
        err = request_irq(HW_EVENT_GDROM_CMD, gdrom_command_interrupt,
-               IRQF_DISABLED, "gdrom_command", &gd);
+               0, "gdrom_command", &gd);
        if (err)
                return err;
        err = request_irq(HW_EVENT_GDROM_DMA, gdrom_dma_interrupt,
-               IRQF_DISABLED, "gdrom_dma", &gd);
+               0, "gdrom_dma", &gd);
        if (err)
                free_irq(HW_EVENT_GDROM_CMD, &gd);
        return err;
index 7ff1d0d208a7c3f89f6827fd3e9ba8815dad202d..a324f9303e36da8e9c63c423f3405d777f05cdbb 100644 (file)
@@ -13,7 +13,6 @@ obj-$(CONFIG_MSM_SMD_PKT)     += msm_smd_pkt.o
 obj-$(CONFIG_MSPEC)            += mspec.o
 obj-$(CONFIG_MMTIMER)          += mmtimer.o
 obj-$(CONFIG_UV_MMTIMER)       += uv_mmtimer.o
-obj-$(CONFIG_VIOTAPE)          += viotape.o
 obj-$(CONFIG_IBM_BSR)          += bsr.o
 obj-$(CONFIG_SGI_MBCS)         += mbcs.o
 obj-$(CONFIG_BFIN_OTP)         += bfin-otp.o
@@ -50,7 +49,7 @@ obj-$(CONFIG_GPIO_TB0219)     += tb0219.o
 obj-$(CONFIG_TELCLOCK)         += tlclk.o
 
 obj-$(CONFIG_MWAVE)            += mwave/
-obj-$(CONFIG_AGP)              += agp/
+obj-y                          += agp/
 obj-$(CONFIG_PCMCIA)           += pcmcia/
 
 obj-$(CONFIG_HANGCHECK_TIMER)  += hangcheck-timer.o
index d8b1b576556cf8eba8c2fa398c6c9bc8d6960803..c528f96ee204fb3f480e29d96992e1e0c1870272 100644 (file)
@@ -68,6 +68,7 @@ config AGP_AMD64
 config AGP_INTEL
        tristate "Intel 440LX/BX/GX, I8xx and E7x05 chipset support"
        depends on AGP && X86
+       select INTEL_GTT
        help
          This option gives you AGP support for the GLX component of X
          on Intel 440LX/BX/GX, 815, 820, 830, 840, 845, 850, 860, 875,
@@ -155,3 +156,7 @@ config AGP_SGI_TIOCA
           This option gives you AGP GART support for the SGI TIO chipset
           for IA64 processors.
 
+config INTEL_GTT
+       tristate
+       depends on X86 && PCI
+
index 8eb56e273e75719f51d617fe3a2ed5c4b9cc06f2..604489bcdbf9b6c70b51e89f093accfdb34f4d25 100644 (file)
@@ -13,7 +13,7 @@ obj-$(CONFIG_AGP_HP_ZX1)      += hp-agp.o
 obj-$(CONFIG_AGP_PARISC)       += parisc-agp.o
 obj-$(CONFIG_AGP_I460)         += i460-agp.o
 obj-$(CONFIG_AGP_INTEL)                += intel-agp.o
-obj-$(CONFIG_AGP_INTEL)                += intel-gtt.o
+obj-$(CONFIG_INTEL_GTT)                += intel-gtt.o
 obj-$(CONFIG_AGP_NVIDIA)       += nvidia-agp.o
 obj-$(CONFIG_AGP_SGI_TIOCA)    += sgi-agp.o
 obj-$(CONFIG_AGP_SIS)          += sis-agp.o
index a426ee1f57a6fd71b30fbd80429cac7c97aa1b4c..9ef0a48a5b28196600a780e4f76ec33ab4120c5e 100644 (file)
@@ -14,9 +14,6 @@
 #include "intel-agp.h"
 #include <drm/intel-gtt.h>
 
-int intel_agp_enabled;
-EXPORT_SYMBOL(intel_agp_enabled);
-
 static int intel_fetch_size(void)
 {
        int i;
@@ -814,8 +811,6 @@ static int agp_intel_probe(struct pci_dev *pdev,
 found_gmch:
        pci_set_drvdata(pdev, bridge);
        err = agp_add_bridge(bridge);
-       if (!err)
-               intel_agp_enabled = 1;
        return err;
 }
 
index b8e2014cb9cb0681d8fa1a21d7930b13e1e2a261..078968d8d07d933b974c8183b6cbd1f9a7163011 100644 (file)
@@ -94,6 +94,7 @@ static struct _intel_private {
 #define IS_IRONLAKE    intel_private.driver->is_ironlake
 #define HAS_PGTBL_EN   intel_private.driver->has_pgtbl_enable
 
+#if IS_ENABLED(CONFIG_AGP_INTEL)
 static int intel_gtt_map_memory(struct page **pages,
                                unsigned int num_entries,
                                struct sg_table *st)
@@ -168,6 +169,7 @@ static void i8xx_destroy_pages(struct page *page)
        __free_pages(page, 2);
        atomic_dec(&agp_bridge->current_memory_agp);
 }
+#endif
 
 #define I810_GTT_ORDER 4
 static int i810_setup(void)
@@ -209,6 +211,7 @@ static void i810_cleanup(void)
        free_gatt_pages(intel_private.i81x_gtt_table, I810_GTT_ORDER);
 }
 
+#if IS_ENABLED(CONFIG_AGP_INTEL)
 static int i810_insert_dcache_entries(struct agp_memory *mem, off_t pg_start,
                                      int type)
 {
@@ -289,6 +292,7 @@ static void intel_i810_free_by_type(struct agp_memory *curr)
        }
        kfree(curr);
 }
+#endif
 
 static int intel_gtt_setup_scratch_page(void)
 {
@@ -647,7 +651,9 @@ static int intel_gtt_init(void)
                return -ENOMEM;
        }
 
+#if IS_ENABLED(CONFIG_AGP_INTEL)
        global_cache_flush();   /* FIXME: ? */
+#endif
 
        intel_private.stolen_size = intel_gtt_stolen_size();
 
@@ -671,6 +677,7 @@ static int intel_gtt_init(void)
        return 0;
 }
 
+#if IS_ENABLED(CONFIG_AGP_INTEL)
 static int intel_fake_agp_fetch_size(void)
 {
        int num_sizes = ARRAY_SIZE(intel_fake_agp_sizes);
@@ -689,6 +696,7 @@ static int intel_fake_agp_fetch_size(void)
 
        return 0;
 }
+#endif
 
 static void i830_cleanup(void)
 {
@@ -801,6 +809,7 @@ static int i830_setup(void)
        return 0;
 }
 
+#if IS_ENABLED(CONFIG_AGP_INTEL)
 static int intel_fake_agp_create_gatt_table(struct agp_bridge_data *bridge)
 {
        agp_bridge->gatt_table_real = NULL;
@@ -825,6 +834,7 @@ static int intel_fake_agp_configure(void)
 
        return 0;
 }
+#endif
 
 static bool i830_check_flags(unsigned int flags)
 {
@@ -863,6 +873,7 @@ void intel_gtt_insert_sg_entries(struct sg_table *st,
 }
 EXPORT_SYMBOL(intel_gtt_insert_sg_entries);
 
+#if IS_ENABLED(CONFIG_AGP_INTEL)
 static void intel_gtt_insert_pages(unsigned int first_entry,
                                   unsigned int num_entries,
                                   struct page **pages,
@@ -928,6 +939,7 @@ out_err:
        mem->is_flushed = true;
        return ret;
 }
+#endif
 
 void intel_gtt_clear_range(unsigned int first_entry, unsigned int num_entries)
 {
@@ -941,6 +953,7 @@ void intel_gtt_clear_range(unsigned int first_entry, unsigned int num_entries)
 }
 EXPORT_SYMBOL(intel_gtt_clear_range);
 
+#if IS_ENABLED(CONFIG_AGP_INTEL)
 static int intel_fake_agp_remove_entries(struct agp_memory *mem,
                                         off_t pg_start, int type)
 {
@@ -982,6 +995,7 @@ static struct agp_memory *intel_fake_agp_alloc_by_type(size_t pg_count,
        /* always return NULL for other allocation types for now */
        return NULL;
 }
+#endif
 
 static int intel_alloc_chipset_flush_resource(void)
 {
@@ -1138,6 +1152,7 @@ static int i9xx_setup(void)
        return 0;
 }
 
+#if IS_ENABLED(CONFIG_AGP_INTEL)
 static const struct agp_bridge_driver intel_fake_agp_driver = {
        .owner                  = THIS_MODULE,
        .size_type              = FIXED_APER_SIZE,
@@ -1159,6 +1174,7 @@ static const struct agp_bridge_driver intel_fake_agp_driver = {
        .agp_destroy_page       = agp_generic_destroy_page,
        .agp_destroy_pages      = agp_generic_destroy_pages,
 };
+#endif
 
 static const struct intel_gtt_driver i81x_gtt_driver = {
        .gen = 1,
@@ -1376,11 +1392,13 @@ int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev,
 
        intel_private.refcount++;
 
+#if IS_ENABLED(CONFIG_AGP_INTEL)
        if (bridge) {
                bridge->driver = &intel_fake_agp_driver;
                bridge->dev_private_data = &intel_private;
                bridge->dev = bridge_pdev;
        }
+#endif
 
        intel_private.bridge_dev = pci_dev_get(bridge_pdev);
 
index 5d9c31dfc905eac973f167d4f77d1c8b628de0b0..d5d4cd82b9f7dac435af267806ff541777f3ebdb 100644 (file)
 #include <linux/uaccess.h>
 #include <linux/slab.h>
 #include <linux/io.h>
-
+#include <linux/acpi.h>
+#include <linux/hpet.h>
 #include <asm/current.h>
 #include <asm/irq.h>
 #include <asm/div64.h>
 
-#include <linux/acpi.h>
-#include <acpi/acpi_bus.h>
-#include <linux/hpet.h>
-
 /*
  * The High Precision Event Timer driver.
  * This driver is closely modelled after the rtc.c driver.
index 40cc0cf2ded639f6b4e3f28cfb1b093660c19ae1..e6939e13e3388e0b05132f72320d8eec0c757a57 100644 (file)
@@ -664,6 +664,13 @@ static struct dmi_system_id __initdata i8k_dmi_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Vostro"),
                },
        },
+       {
+               .ident = "Dell XPS421",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "XPS L421X"),
+               },
+       },
         { }
 };
 
index 64420b3396a294ccd56c2b6e727b1aaa0459a34b..b9a57fa4b710301d3844cf9ea9b659830b871d0f 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/security.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <acpi/acpi.h>
+#include <linux/acpi.h>
 
 #include "tpm.h"
 #include "tpm_eventlog.h"
index 8e562dc656016cd9c4dbeaaa3dac0a96a02d0f26..dd60ef336f8d8bf4fba5c6bb9ab473724d578a61 100644 (file)
@@ -1,5 +1,4 @@
 #include <linux/acpi.h>
-#include <acpi/acpi_drivers.h>
 #include "tpm.h"
 
 static const u8 tpm_ppi_uuid[] = {
index 7a10bc9a23e7b3f11403a1e500504b80715c3557..ace7309c43699f0afc6df7b406416dbce45f8ab3 100644 (file)
@@ -35,6 +35,7 @@ obj-$(CONFIG_ARCH_TEGRA)      += tegra/
 obj-$(CONFIG_PLAT_SAMSUNG)     += samsung/
 obj-$(CONFIG_COMMON_CLK_XGENE)  += clk-xgene.o
 obj-$(CONFIG_COMMON_CLK_KEYSTONE)      += keystone/
+obj-$(CONFIG_COMMON_CLK_AT91)  += at91/
 
 obj-$(CONFIG_X86)              += x86/
 
diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile
new file mode 100644 (file)
index 0000000..0e92b71
--- /dev/null
@@ -0,0 +1,12 @@
+#
+# Makefile for at91 specific clk
+#
+
+obj-y += pmc.o
+obj-y += clk-main.o clk-pll.o clk-plldiv.o clk-master.o
+obj-y += clk-system.o clk-peripheral.o
+
+obj-$(CONFIG_AT91_PROGRAMMABLE_CLOCKS) += clk-programmable.o
+obj-$(CONFIG_HAVE_AT91_UTMI)           += clk-utmi.o
+obj-$(CONFIG_HAVE_AT91_USB_CLK)                += clk-usb.o
+obj-$(CONFIG_HAVE_AT91_SMD)            += clk-smd.o
diff --git a/drivers/clk/at91/clk-main.c b/drivers/clk/at91/clk-main.c
new file mode 100644 (file)
index 0000000..8e9e8cc
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ *  Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.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.
+ *
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/clk/at91_pmc.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+
+#include "pmc.h"
+
+#define SLOW_CLOCK_FREQ                32768
+#define MAINF_DIV              16
+#define MAINFRDY_TIMEOUT       (((MAINF_DIV + 1) * USEC_PER_SEC) / \
+                                SLOW_CLOCK_FREQ)
+#define MAINF_LOOP_MIN_WAIT    (USEC_PER_SEC / SLOW_CLOCK_FREQ)
+#define MAINF_LOOP_MAX_WAIT    MAINFRDY_TIMEOUT
+
+struct clk_main {
+       struct clk_hw hw;
+       struct at91_pmc *pmc;
+       unsigned long rate;
+       unsigned int irq;
+       wait_queue_head_t wait;
+};
+
+#define to_clk_main(hw) container_of(hw, struct clk_main, hw)
+
+static irqreturn_t clk_main_irq_handler(int irq, void *dev_id)
+{
+       struct clk_main *clkmain = (struct clk_main *)dev_id;
+
+       wake_up(&clkmain->wait);
+       disable_irq_nosync(clkmain->irq);
+
+       return IRQ_HANDLED;
+}
+
+static int clk_main_prepare(struct clk_hw *hw)
+{
+       struct clk_main *clkmain = to_clk_main(hw);
+       struct at91_pmc *pmc = clkmain->pmc;
+       unsigned long halt_time, timeout;
+       u32 tmp;
+
+       while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCS)) {
+               enable_irq(clkmain->irq);
+               wait_event(clkmain->wait,
+                          pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCS);
+       }
+
+       if (clkmain->rate)
+               return 0;
+
+       timeout = jiffies + usecs_to_jiffies(MAINFRDY_TIMEOUT);
+       do {
+               halt_time = jiffies;
+               tmp = pmc_read(pmc, AT91_CKGR_MCFR);
+               if (tmp & AT91_PMC_MAINRDY)
+                       return 0;
+               usleep_range(MAINF_LOOP_MIN_WAIT, MAINF_LOOP_MAX_WAIT);
+       } while (time_before(halt_time, timeout));
+
+       return 0;
+}
+
+static int clk_main_is_prepared(struct clk_hw *hw)
+{
+       struct clk_main *clkmain = to_clk_main(hw);
+
+       return !!(pmc_read(clkmain->pmc, AT91_PMC_SR) & AT91_PMC_MOSCS);
+}
+
+static unsigned long clk_main_recalc_rate(struct clk_hw *hw,
+                                         unsigned long parent_rate)
+{
+       u32 tmp;
+       struct clk_main *clkmain = to_clk_main(hw);
+       struct at91_pmc *pmc = clkmain->pmc;
+
+       if (clkmain->rate)
+               return clkmain->rate;
+
+       tmp = pmc_read(pmc, AT91_CKGR_MCFR) & AT91_PMC_MAINF;
+       clkmain->rate = (tmp * parent_rate) / MAINF_DIV;
+
+       return clkmain->rate;
+}
+
+static const struct clk_ops main_ops = {
+       .prepare = clk_main_prepare,
+       .is_prepared = clk_main_is_prepared,
+       .recalc_rate = clk_main_recalc_rate,
+};
+
+static struct clk * __init
+at91_clk_register_main(struct at91_pmc *pmc,
+                      unsigned int irq,
+                      const char *name,
+                      const char *parent_name,
+                      unsigned long rate)
+{
+       int ret;
+       struct clk_main *clkmain;
+       struct clk *clk = NULL;
+       struct clk_init_data init;
+
+       if (!pmc || !irq || !name)
+               return ERR_PTR(-EINVAL);
+
+       if (!rate && !parent_name)
+               return ERR_PTR(-EINVAL);
+
+       clkmain = kzalloc(sizeof(*clkmain), GFP_KERNEL);
+       if (!clkmain)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = name;
+       init.ops = &main_ops;
+       init.parent_names = parent_name ? &parent_name : NULL;
+       init.num_parents = parent_name ? 1 : 0;
+       init.flags = parent_name ? 0 : CLK_IS_ROOT;
+
+       clkmain->hw.init = &init;
+       clkmain->rate = rate;
+       clkmain->pmc = pmc;
+       clkmain->irq = irq;
+       init_waitqueue_head(&clkmain->wait);
+       irq_set_status_flags(clkmain->irq, IRQ_NOAUTOEN);
+       ret = request_irq(clkmain->irq, clk_main_irq_handler,
+                         IRQF_TRIGGER_HIGH, "clk-main", clkmain);
+       if (ret)
+               return ERR_PTR(ret);
+
+       clk = clk_register(NULL, &clkmain->hw);
+       if (IS_ERR(clk)) {
+               free_irq(clkmain->irq, clkmain);
+               kfree(clkmain);
+       }
+
+       return clk;
+}
+
+
+
+static void __init
+of_at91_clk_main_setup(struct device_node *np, struct at91_pmc *pmc)
+{
+       struct clk *clk;
+       unsigned int irq;
+       const char *parent_name;
+       const char *name = np->name;
+       u32 rate = 0;
+
+       parent_name = of_clk_get_parent_name(np, 0);
+       of_property_read_string(np, "clock-output-names", &name);
+       of_property_read_u32(np, "clock-frequency", &rate);
+       irq = irq_of_parse_and_map(np, 0);
+       if (!irq)
+               return;
+
+       clk = at91_clk_register_main(pmc, irq, name, parent_name, rate);
+       if (IS_ERR(clk))
+               return;
+
+       of_clk_add_provider(np, of_clk_src_simple_get, clk);
+}
+
+void __init of_at91rm9200_clk_main_setup(struct device_node *np,
+                                        struct at91_pmc *pmc)
+{
+       of_at91_clk_main_setup(np, pmc);
+}
diff --git a/drivers/clk/at91/clk-master.c b/drivers/clk/at91/clk-master.c
new file mode 100644 (file)
index 0000000..bd313f7
--- /dev/null
@@ -0,0 +1,270 @@
+/*
+ *  Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.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.
+ *
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/clk/at91_pmc.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/io.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#include "pmc.h"
+
+#define MASTER_SOURCE_MAX      4
+
+#define MASTER_PRES_MASK       0x7
+#define MASTER_PRES_MAX                MASTER_PRES_MASK
+#define MASTER_DIV_SHIFT       8
+#define MASTER_DIV_MASK                0x3
+
+struct clk_master_characteristics {
+       struct clk_range output;
+       u32 divisors[4];
+       u8 have_div3_pres;
+};
+
+struct clk_master_layout {
+       u32 mask;
+       u8 pres_shift;
+};
+
+#define to_clk_master(hw) container_of(hw, struct clk_master, hw)
+
+struct clk_master {
+       struct clk_hw hw;
+       struct at91_pmc *pmc;
+       unsigned int irq;
+       wait_queue_head_t wait;
+       const struct clk_master_layout *layout;
+       const struct clk_master_characteristics *characteristics;
+};
+
+static irqreturn_t clk_master_irq_handler(int irq, void *dev_id)
+{
+       struct clk_master *master = (struct clk_master *)dev_id;
+
+       wake_up(&master->wait);
+       disable_irq_nosync(master->irq);
+
+       return IRQ_HANDLED;
+}
+static int clk_master_prepare(struct clk_hw *hw)
+{
+       struct clk_master *master = to_clk_master(hw);
+       struct at91_pmc *pmc = master->pmc;
+
+       while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MCKRDY)) {
+               enable_irq(master->irq);
+               wait_event(master->wait,
+                          pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MCKRDY);
+       }
+
+       return 0;
+}
+
+static int clk_master_is_prepared(struct clk_hw *hw)
+{
+       struct clk_master *master = to_clk_master(hw);
+
+       return !!(pmc_read(master->pmc, AT91_PMC_SR) & AT91_PMC_MCKRDY);
+}
+
+static unsigned long clk_master_recalc_rate(struct clk_hw *hw,
+                                           unsigned long parent_rate)
+{
+       u8 pres;
+       u8 div;
+       unsigned long rate = parent_rate;
+       struct clk_master *master = to_clk_master(hw);
+       struct at91_pmc *pmc = master->pmc;
+       const struct clk_master_layout *layout = master->layout;
+       const struct clk_master_characteristics *characteristics =
+                                               master->characteristics;
+       u32 tmp;
+
+       pmc_lock(pmc);
+       tmp = pmc_read(pmc, AT91_PMC_MCKR) & layout->mask;
+       pmc_unlock(pmc);
+
+       pres = (tmp >> layout->pres_shift) & MASTER_PRES_MASK;
+       div = (tmp >> MASTER_DIV_SHIFT) & MASTER_DIV_MASK;
+
+       if (characteristics->have_div3_pres && pres == MASTER_PRES_MAX)
+               rate /= 3;
+       else
+               rate >>= pres;
+
+       rate /= characteristics->divisors[div];
+
+       if (rate < characteristics->output.min)
+               pr_warn("master clk is underclocked");
+       else if (rate > characteristics->output.max)
+               pr_warn("master clk is overclocked");
+
+       return rate;
+}
+
+static u8 clk_master_get_parent(struct clk_hw *hw)
+{
+       struct clk_master *master = to_clk_master(hw);
+       struct at91_pmc *pmc = master->pmc;
+
+       return pmc_read(pmc, AT91_PMC_MCKR) & AT91_PMC_CSS;
+}
+
+static const struct clk_ops master_ops = {
+       .prepare = clk_master_prepare,
+       .is_prepared = clk_master_is_prepared,
+       .recalc_rate = clk_master_recalc_rate,
+       .get_parent = clk_master_get_parent,
+};
+
+static struct clk * __init
+at91_clk_register_master(struct at91_pmc *pmc, unsigned int irq,
+               const char *name, int num_parents,
+               const char **parent_names,
+               const struct clk_master_layout *layout,
+               const struct clk_master_characteristics *characteristics)
+{
+       int ret;
+       struct clk_master *master;
+       struct clk *clk = NULL;
+       struct clk_init_data init;
+
+       if (!pmc || !irq || !name || !num_parents || !parent_names)
+               return ERR_PTR(-EINVAL);
+
+       master = kzalloc(sizeof(*master), GFP_KERNEL);
+       if (!master)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = name;
+       init.ops = &master_ops;
+       init.parent_names = parent_names;
+       init.num_parents = num_parents;
+       init.flags = 0;
+
+       master->hw.init = &init;
+       master->layout = layout;
+       master->characteristics = characteristics;
+       master->pmc = pmc;
+       master->irq = irq;
+       init_waitqueue_head(&master->wait);
+       irq_set_status_flags(master->irq, IRQ_NOAUTOEN);
+       ret = request_irq(master->irq, clk_master_irq_handler,
+                         IRQF_TRIGGER_HIGH, "clk-master", master);
+       if (ret)
+               return ERR_PTR(ret);
+
+       clk = clk_register(NULL, &master->hw);
+       if (IS_ERR(clk))
+               kfree(master);
+
+       return clk;
+}
+
+
+static const struct clk_master_layout at91rm9200_master_layout = {
+       .mask = 0x31F,
+       .pres_shift = 2,
+};
+
+static const struct clk_master_layout at91sam9x5_master_layout = {
+       .mask = 0x373,
+       .pres_shift = 4,
+};
+
+
+static struct clk_master_characteristics * __init
+of_at91_clk_master_get_characteristics(struct device_node *np)
+{
+       struct clk_master_characteristics *characteristics;
+
+       characteristics = kzalloc(sizeof(*characteristics), GFP_KERNEL);
+       if (!characteristics)
+               return NULL;
+
+       if (of_at91_get_clk_range(np, "atmel,clk-output-range", &characteristics->output))
+               goto out_free_characteristics;
+
+       of_property_read_u32_array(np, "atmel,clk-divisors",
+                                  characteristics->divisors, 4);
+
+       characteristics->have_div3_pres =
+               of_property_read_bool(np, "atmel,master-clk-have-div3-pres");
+
+       return characteristics;
+
+out_free_characteristics:
+       kfree(characteristics);
+       return NULL;
+}
+
+static void __init
+of_at91_clk_master_setup(struct device_node *np, struct at91_pmc *pmc,
+                        const struct clk_master_layout *layout)
+{
+       struct clk *clk;
+       int num_parents;
+       int i;
+       unsigned int irq;
+       const char *parent_names[MASTER_SOURCE_MAX];
+       const char *name = np->name;
+       struct clk_master_characteristics *characteristics;
+
+       num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+       if (num_parents <= 0 || num_parents > MASTER_SOURCE_MAX)
+               return;
+
+       for (i = 0; i < num_parents; ++i) {
+               parent_names[i] = of_clk_get_parent_name(np, i);
+               if (!parent_names[i])
+                       return;
+       }
+
+       of_property_read_string(np, "clock-output-names", &name);
+
+       characteristics = of_at91_clk_master_get_characteristics(np);
+       if (!characteristics)
+               return;
+
+       irq = irq_of_parse_and_map(np, 0);
+       if (!irq)
+               return;
+
+       clk = at91_clk_register_master(pmc, irq, name, num_parents,
+                                      parent_names, layout,
+                                      characteristics);
+       if (IS_ERR(clk))
+               goto out_free_characteristics;
+
+       of_clk_add_provider(np, of_clk_src_simple_get, clk);
+       return;
+
+out_free_characteristics:
+       kfree(characteristics);
+}
+
+void __init of_at91rm9200_clk_master_setup(struct device_node *np,
+                                          struct at91_pmc *pmc)
+{
+       of_at91_clk_master_setup(np, pmc, &at91rm9200_master_layout);
+}
+
+void __init of_at91sam9x5_clk_master_setup(struct device_node *np,
+                                          struct at91_pmc *pmc)
+{
+       of_at91_clk_master_setup(np, pmc, &at91sam9x5_master_layout);
+}
diff --git a/drivers/clk/at91/clk-peripheral.c b/drivers/clk/at91/clk-peripheral.c
new file mode 100644 (file)
index 0000000..597fed4
--- /dev/null
@@ -0,0 +1,410 @@
+/*
+ *  Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.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.
+ *
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/clk/at91_pmc.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+
+#include "pmc.h"
+
+#define PERIPHERAL_MAX         64
+
+#define PERIPHERAL_AT91RM9200  0
+#define PERIPHERAL_AT91SAM9X5  1
+
+#define PERIPHERAL_ID_MIN      2
+#define PERIPHERAL_ID_MAX      31
+#define PERIPHERAL_MASK(id)    (1 << ((id) & PERIPHERAL_ID_MAX))
+
+#define PERIPHERAL_RSHIFT_MASK 0x3
+#define PERIPHERAL_RSHIFT(val) (((val) >> 16) & PERIPHERAL_RSHIFT_MASK)
+
+#define PERIPHERAL_MAX_SHIFT   4
+
+struct clk_peripheral {
+       struct clk_hw hw;
+       struct at91_pmc *pmc;
+       u32 id;
+};
+
+#define to_clk_peripheral(hw) container_of(hw, struct clk_peripheral, hw)
+
+struct clk_sam9x5_peripheral {
+       struct clk_hw hw;
+       struct at91_pmc *pmc;
+       struct clk_range range;
+       u32 id;
+       u32 div;
+       bool auto_div;
+};
+
+#define to_clk_sam9x5_peripheral(hw) \
+       container_of(hw, struct clk_sam9x5_peripheral, hw)
+
+static int clk_peripheral_enable(struct clk_hw *hw)
+{
+       struct clk_peripheral *periph = to_clk_peripheral(hw);
+       struct at91_pmc *pmc = periph->pmc;
+       int offset = AT91_PMC_PCER;
+       u32 id = periph->id;
+
+       if (id < PERIPHERAL_ID_MIN)
+               return 0;
+       if (id > PERIPHERAL_ID_MAX)
+               offset = AT91_PMC_PCER1;
+       pmc_write(pmc, offset, PERIPHERAL_MASK(id));
+       return 0;
+}
+
+static void clk_peripheral_disable(struct clk_hw *hw)
+{
+       struct clk_peripheral *periph = to_clk_peripheral(hw);
+       struct at91_pmc *pmc = periph->pmc;
+       int offset = AT91_PMC_PCDR;
+       u32 id = periph->id;
+
+       if (id < PERIPHERAL_ID_MIN)
+               return;
+       if (id > PERIPHERAL_ID_MAX)
+               offset = AT91_PMC_PCDR1;
+       pmc_write(pmc, offset, PERIPHERAL_MASK(id));
+}
+
+static int clk_peripheral_is_enabled(struct clk_hw *hw)
+{
+       struct clk_peripheral *periph = to_clk_peripheral(hw);
+       struct at91_pmc *pmc = periph->pmc;
+       int offset = AT91_PMC_PCSR;
+       u32 id = periph->id;
+
+       if (id < PERIPHERAL_ID_MIN)
+               return 1;
+       if (id > PERIPHERAL_ID_MAX)
+               offset = AT91_PMC_PCSR1;
+       return !!(pmc_read(pmc, offset) & PERIPHERAL_MASK(id));
+}
+
+static const struct clk_ops peripheral_ops = {
+       .enable = clk_peripheral_enable,
+       .disable = clk_peripheral_disable,
+       .is_enabled = clk_peripheral_is_enabled,
+};
+
+static struct clk * __init
+at91_clk_register_peripheral(struct at91_pmc *pmc, const char *name,
+                            const char *parent_name, u32 id)
+{
+       struct clk_peripheral *periph;
+       struct clk *clk = NULL;
+       struct clk_init_data init;
+
+       if (!pmc || !name || !parent_name || id > PERIPHERAL_ID_MAX)
+               return ERR_PTR(-EINVAL);
+
+       periph = kzalloc(sizeof(*periph), GFP_KERNEL);
+       if (!periph)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = name;
+       init.ops = &peripheral_ops;
+       init.parent_names = (parent_name ? &parent_name : NULL);
+       init.num_parents = (parent_name ? 1 : 0);
+       init.flags = 0;
+
+       periph->id = id;
+       periph->hw.init = &init;
+       periph->pmc = pmc;
+
+       clk = clk_register(NULL, &periph->hw);
+       if (IS_ERR(clk))
+               kfree(periph);
+
+       return clk;
+}
+
+static void clk_sam9x5_peripheral_autodiv(struct clk_sam9x5_peripheral *periph)
+{
+       struct clk *parent;
+       unsigned long parent_rate;
+       int shift = 0;
+
+       if (!periph->auto_div)
+               return;
+
+       if (periph->range.max) {
+               parent = clk_get_parent_by_index(periph->hw.clk, 0);
+               parent_rate = __clk_get_rate(parent);
+               if (!parent_rate)
+                       return;
+
+               for (; shift < PERIPHERAL_MAX_SHIFT; shift++) {
+                       if (parent_rate >> shift <= periph->range.max)
+                               break;
+               }
+       }
+
+       periph->auto_div = false;
+       periph->div = shift;
+}
+
+static int clk_sam9x5_peripheral_enable(struct clk_hw *hw)
+{
+       struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
+       struct at91_pmc *pmc = periph->pmc;
+
+       if (periph->id < PERIPHERAL_ID_MIN)
+               return 0;
+
+       pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID) |
+                                    AT91_PMC_PCR_CMD |
+                                    AT91_PMC_PCR_DIV(periph->div) |
+                                    AT91_PMC_PCR_EN);
+       return 0;
+}
+
+static void clk_sam9x5_peripheral_disable(struct clk_hw *hw)
+{
+       struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
+       struct at91_pmc *pmc = periph->pmc;
+
+       if (periph->id < PERIPHERAL_ID_MIN)
+               return;
+
+       pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID) |
+                                    AT91_PMC_PCR_CMD);
+}
+
+static int clk_sam9x5_peripheral_is_enabled(struct clk_hw *hw)
+{
+       struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
+       struct at91_pmc *pmc = periph->pmc;
+       int ret;
+
+       if (periph->id < PERIPHERAL_ID_MIN)
+               return 1;
+
+       pmc_lock(pmc);
+       pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID));
+       ret = !!(pmc_read(pmc, AT91_PMC_PCR) & AT91_PMC_PCR_EN);
+       pmc_unlock(pmc);
+
+       return ret;
+}
+
+static unsigned long
+clk_sam9x5_peripheral_recalc_rate(struct clk_hw *hw,
+                                 unsigned long parent_rate)
+{
+       struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
+       struct at91_pmc *pmc = periph->pmc;
+       u32 tmp;
+
+       if (periph->id < PERIPHERAL_ID_MIN)
+               return parent_rate;
+
+       pmc_lock(pmc);
+       pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID));
+       tmp = pmc_read(pmc, AT91_PMC_PCR);
+       pmc_unlock(pmc);
+
+       if (tmp & AT91_PMC_PCR_EN) {
+               periph->div = PERIPHERAL_RSHIFT(tmp);
+               periph->auto_div = false;
+       } else {
+               clk_sam9x5_peripheral_autodiv(periph);
+       }
+
+       return parent_rate >> periph->div;
+}
+
+static long clk_sam9x5_peripheral_round_rate(struct clk_hw *hw,
+                                            unsigned long rate,
+                                            unsigned long *parent_rate)
+{
+       int shift = 0;
+       unsigned long best_rate;
+       unsigned long best_diff;
+       unsigned long cur_rate = *parent_rate;
+       unsigned long cur_diff;
+       struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
+
+       if (periph->id < PERIPHERAL_ID_MIN || !periph->range.max)
+               return *parent_rate;
+
+       if (periph->range.max) {
+               for (; shift < PERIPHERAL_MAX_SHIFT; shift++) {
+                       cur_rate = *parent_rate >> shift;
+                       if (cur_rate <= periph->range.max)
+                               break;
+               }
+       }
+
+       if (rate >= cur_rate)
+               return cur_rate;
+
+       best_diff = cur_rate - rate;
+       best_rate = cur_rate;
+       for (; shift < PERIPHERAL_MAX_SHIFT; shift++) {
+               cur_rate = *parent_rate >> shift;
+               if (cur_rate < rate)
+                       cur_diff = rate - cur_rate;
+               else
+                       cur_diff = cur_rate - rate;
+
+               if (cur_diff < best_diff) {
+                       best_diff = cur_diff;
+                       best_rate = cur_rate;
+               }
+
+               if (!best_diff || cur_rate < rate)
+                       break;
+       }
+
+       return best_rate;
+}
+
+static int clk_sam9x5_peripheral_set_rate(struct clk_hw *hw,
+                                         unsigned long rate,
+                                         unsigned long parent_rate)
+{
+       int shift;
+       struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
+       if (periph->id < PERIPHERAL_ID_MIN || !periph->range.max) {
+               if (parent_rate == rate)
+                       return 0;
+               else
+                       return -EINVAL;
+       }
+
+       if (periph->range.max && rate > periph->range.max)
+               return -EINVAL;
+
+       for (shift = 0; shift < PERIPHERAL_MAX_SHIFT; shift++) {
+               if (parent_rate >> shift == rate) {
+                       periph->auto_div = false;
+                       periph->div = shift;
+                       return 0;
+               }
+       }
+
+       return -EINVAL;
+}
+
+static const struct clk_ops sam9x5_peripheral_ops = {
+       .enable = clk_sam9x5_peripheral_enable,
+       .disable = clk_sam9x5_peripheral_disable,
+       .is_enabled = clk_sam9x5_peripheral_is_enabled,
+       .recalc_rate = clk_sam9x5_peripheral_recalc_rate,
+       .round_rate = clk_sam9x5_peripheral_round_rate,
+       .set_rate = clk_sam9x5_peripheral_set_rate,
+};
+
+static struct clk * __init
+at91_clk_register_sam9x5_peripheral(struct at91_pmc *pmc, const char *name,
+                                   const char *parent_name, u32 id,
+                                   const struct clk_range *range)
+{
+       struct clk_sam9x5_peripheral *periph;
+       struct clk *clk = NULL;
+       struct clk_init_data init;
+
+       if (!pmc || !name || !parent_name)
+               return ERR_PTR(-EINVAL);
+
+       periph = kzalloc(sizeof(*periph), GFP_KERNEL);
+       if (!periph)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = name;
+       init.ops = &sam9x5_peripheral_ops;
+       init.parent_names = (parent_name ? &parent_name : NULL);
+       init.num_parents = (parent_name ? 1 : 0);
+       init.flags = 0;
+
+       periph->id = id;
+       periph->hw.init = &init;
+       periph->div = 0;
+       periph->pmc = pmc;
+       periph->auto_div = true;
+       periph->range = *range;
+
+       clk = clk_register(NULL, &periph->hw);
+       if (IS_ERR(clk))
+               kfree(periph);
+       else
+               clk_sam9x5_peripheral_autodiv(periph);
+
+       return clk;
+}
+
+static void __init
+of_at91_clk_periph_setup(struct device_node *np, struct at91_pmc *pmc, u8 type)
+{
+       int num;
+       u32 id;
+       struct clk *clk;
+       const char *parent_name;
+       const char *name;
+       struct device_node *periphclknp;
+
+       parent_name = of_clk_get_parent_name(np, 0);
+       if (!parent_name)
+               return;
+
+       num = of_get_child_count(np);
+       if (!num || num > PERIPHERAL_MAX)
+               return;
+
+       for_each_child_of_node(np, periphclknp) {
+               if (of_property_read_u32(periphclknp, "reg", &id))
+                       continue;
+
+               if (id >= PERIPHERAL_MAX)
+                       continue;
+
+               if (of_property_read_string(np, "clock-output-names", &name))
+                       name = periphclknp->name;
+
+               if (type == PERIPHERAL_AT91RM9200) {
+                       clk = at91_clk_register_peripheral(pmc, name,
+                                                          parent_name, id);
+               } else {
+                       struct clk_range range = CLK_RANGE(0, 0);
+
+                       of_at91_get_clk_range(periphclknp,
+                                             "atmel,clk-output-range",
+                                             &range);
+
+                       clk = at91_clk_register_sam9x5_peripheral(pmc, name,
+                                                                 parent_name,
+                                                                 id, &range);
+               }
+
+               if (IS_ERR(clk))
+                       continue;
+
+               of_clk_add_provider(periphclknp, of_clk_src_simple_get, clk);
+       }
+}
+
+void __init of_at91rm9200_clk_periph_setup(struct device_node *np,
+                                          struct at91_pmc *pmc)
+{
+       of_at91_clk_periph_setup(np, pmc, PERIPHERAL_AT91RM9200);
+}
+
+void __init of_at91sam9x5_clk_periph_setup(struct device_node *np,
+                                          struct at91_pmc *pmc)
+{
+       of_at91_clk_periph_setup(np, pmc, PERIPHERAL_AT91SAM9X5);
+}
diff --git a/drivers/clk/at91/clk-pll.c b/drivers/clk/at91/clk-pll.c
new file mode 100644 (file)
index 0000000..cf6ed02
--- /dev/null
@@ -0,0 +1,531 @@
+/*
+ *  Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.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.
+ *
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/clk/at91_pmc.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/io.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#include "pmc.h"
+
+#define PLL_STATUS_MASK(id)    (1 << (1 + (id)))
+#define PLL_REG(id)            (AT91_CKGR_PLLAR + ((id) * 4))
+#define PLL_DIV_MASK           0xff
+#define PLL_DIV_MAX            PLL_DIV_MASK
+#define PLL_DIV(reg)           ((reg) & PLL_DIV_MASK)
+#define PLL_MUL(reg, layout)   (((reg) >> (layout)->mul_shift) & \
+                                (layout)->mul_mask)
+#define PLL_ICPR_SHIFT(id)     ((id) * 16)
+#define PLL_ICPR_MASK(id)      (0xffff << PLL_ICPR_SHIFT(id))
+#define PLL_MAX_COUNT          0x3ff
+#define PLL_COUNT_SHIFT                8
+#define PLL_OUT_SHIFT          14
+#define PLL_MAX_ID             1
+
+struct clk_pll_characteristics {
+       struct clk_range input;
+       int num_output;
+       struct clk_range *output;
+       u16 *icpll;
+       u8 *out;
+};
+
+struct clk_pll_layout {
+       u32 pllr_mask;
+       u16 mul_mask;
+       u8 mul_shift;
+};
+
+#define to_clk_pll(hw) container_of(hw, struct clk_pll, hw)
+
+struct clk_pll {
+       struct clk_hw hw;
+       struct at91_pmc *pmc;
+       unsigned int irq;
+       wait_queue_head_t wait;
+       u8 id;
+       u8 div;
+       u8 range;
+       u16 mul;
+       const struct clk_pll_layout *layout;
+       const struct clk_pll_characteristics *characteristics;
+};
+
+static irqreturn_t clk_pll_irq_handler(int irq, void *dev_id)
+{
+       struct clk_pll *pll = (struct clk_pll *)dev_id;
+
+       wake_up(&pll->wait);
+       disable_irq_nosync(pll->irq);
+
+       return IRQ_HANDLED;
+}
+
+static int clk_pll_prepare(struct clk_hw *hw)
+{
+       struct clk_pll *pll = to_clk_pll(hw);
+       struct at91_pmc *pmc = pll->pmc;
+       const struct clk_pll_layout *layout = pll->layout;
+       const struct clk_pll_characteristics *characteristics =
+                                                       pll->characteristics;
+       u8 id = pll->id;
+       u32 mask = PLL_STATUS_MASK(id);
+       int offset = PLL_REG(id);
+       u8 out = 0;
+       u32 pllr, icpr;
+       u8 div;
+       u16 mul;
+
+       pllr = pmc_read(pmc, offset);
+       div = PLL_DIV(pllr);
+       mul = PLL_MUL(pllr, layout);
+
+       if ((pmc_read(pmc, AT91_PMC_SR) & mask) &&
+           (div == pll->div && mul == pll->mul))
+               return 0;
+
+       if (characteristics->out)
+               out = characteristics->out[pll->range];
+       if (characteristics->icpll) {
+               icpr = pmc_read(pmc, AT91_PMC_PLLICPR) & ~PLL_ICPR_MASK(id);
+               icpr |= (characteristics->icpll[pll->range] <<
+                       PLL_ICPR_SHIFT(id));
+               pmc_write(pmc, AT91_PMC_PLLICPR, icpr);
+       }
+
+       pllr &= ~layout->pllr_mask;
+       pllr |= layout->pllr_mask &
+              (pll->div | (PLL_MAX_COUNT << PLL_COUNT_SHIFT) |
+               (out << PLL_OUT_SHIFT) |
+               ((pll->mul & layout->mul_mask) << layout->mul_shift));
+       pmc_write(pmc, offset, pllr);
+
+       while (!(pmc_read(pmc, AT91_PMC_SR) & mask)) {
+               enable_irq(pll->irq);
+               wait_event(pll->wait,
+                          pmc_read(pmc, AT91_PMC_SR) & mask);
+       }
+
+       return 0;
+}
+
+static int clk_pll_is_prepared(struct clk_hw *hw)
+{
+       struct clk_pll *pll = to_clk_pll(hw);
+       struct at91_pmc *pmc = pll->pmc;
+
+       return !!(pmc_read(pmc, AT91_PMC_SR) &
+                 PLL_STATUS_MASK(pll->id));
+}
+
+static void clk_pll_unprepare(struct clk_hw *hw)
+{
+       struct clk_pll *pll = to_clk_pll(hw);
+       struct at91_pmc *pmc = pll->pmc;
+       const struct clk_pll_layout *layout = pll->layout;
+       int offset = PLL_REG(pll->id);
+       u32 tmp = pmc_read(pmc, offset) & ~(layout->pllr_mask);
+
+       pmc_write(pmc, offset, tmp);
+}
+
+static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
+                                        unsigned long parent_rate)
+{
+       struct clk_pll *pll = to_clk_pll(hw);
+       const struct clk_pll_layout *layout = pll->layout;
+       struct at91_pmc *pmc = pll->pmc;
+       int offset = PLL_REG(pll->id);
+       u32 tmp = pmc_read(pmc, offset) & layout->pllr_mask;
+       u8 div = PLL_DIV(tmp);
+       u16 mul = PLL_MUL(tmp, layout);
+       if (!div || !mul)
+               return 0;
+
+       return (parent_rate * (mul + 1)) / div;
+}
+
+static long clk_pll_get_best_div_mul(struct clk_pll *pll, unsigned long rate,
+                                    unsigned long parent_rate,
+                                    u32 *div, u32 *mul,
+                                    u32 *index) {
+       unsigned long maxrate;
+       unsigned long minrate;
+       unsigned long divrate;
+       unsigned long bestdiv = 1;
+       unsigned long bestmul;
+       unsigned long tmpdiv;
+       unsigned long roundup;
+       unsigned long rounddown;
+       unsigned long remainder;
+       unsigned long bestremainder;
+       unsigned long maxmul;
+       unsigned long maxdiv;
+       unsigned long mindiv;
+       int i = 0;
+       const struct clk_pll_layout *layout = pll->layout;
+       const struct clk_pll_characteristics *characteristics =
+                                                       pll->characteristics;
+
+       /* Minimum divider = 1 */
+       /* Maximum multiplier = max_mul */
+       maxmul = layout->mul_mask + 1;
+       maxrate = (parent_rate * maxmul) / 1;
+
+       /* Maximum divider = max_div */
+       /* Minimum multiplier = 2 */
+       maxdiv = PLL_DIV_MAX;
+       minrate = (parent_rate * 2) / maxdiv;
+
+       if (parent_rate < characteristics->input.min ||
+           parent_rate < characteristics->input.max)
+               return -ERANGE;
+
+       if (parent_rate < minrate || parent_rate > maxrate)
+               return -ERANGE;
+
+       for (i = 0; i < characteristics->num_output; i++) {
+               if (parent_rate >= characteristics->output[i].min &&
+                   parent_rate <= characteristics->output[i].max)
+                       break;
+       }
+
+       if (i >= characteristics->num_output)
+               return -ERANGE;
+
+       bestmul = rate / parent_rate;
+       rounddown = parent_rate % rate;
+       roundup = rate - rounddown;
+       bestremainder = roundup < rounddown ? roundup : rounddown;
+
+       if (!bestremainder) {
+               if (div)
+                       *div = bestdiv;
+               if (mul)
+                       *mul = bestmul;
+               if (index)
+                       *index = i;
+               return rate;
+       }
+
+       maxdiv = 255 / (bestmul + 1);
+       if (parent_rate / maxdiv < characteristics->input.min)
+               maxdiv = parent_rate / characteristics->input.min;
+       mindiv = parent_rate / characteristics->input.max;
+       if (parent_rate % characteristics->input.max)
+               mindiv++;
+
+       for (tmpdiv = mindiv; tmpdiv < maxdiv; tmpdiv++) {
+               divrate = parent_rate / tmpdiv;
+
+               rounddown = rate % divrate;
+               roundup = divrate - rounddown;
+               remainder = roundup < rounddown ? roundup : rounddown;
+
+               if (remainder < bestremainder) {
+                       bestremainder = remainder;
+                       bestmul = rate / divrate;
+                       bestdiv = tmpdiv;
+               }
+
+               if (!remainder)
+                       break;
+       }
+
+       rate = (parent_rate / bestdiv) * bestmul;
+
+       if (div)
+               *div = bestdiv;
+       if (mul)
+               *mul = bestmul;
+       if (index)
+               *index = i;
+
+       return rate;
+}
+
+static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+                                       unsigned long *parent_rate)
+{
+       struct clk_pll *pll = to_clk_pll(hw);
+
+       return clk_pll_get_best_div_mul(pll, rate, *parent_rate,
+                                       NULL, NULL, NULL);
+}
+
+static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+                           unsigned long parent_rate)
+{
+       struct clk_pll *pll = to_clk_pll(hw);
+       long ret;
+       u32 div;
+       u32 mul;
+       u32 index;
+
+       ret = clk_pll_get_best_div_mul(pll, rate, parent_rate,
+                                      &div, &mul, &index);
+       if (ret < 0)
+               return ret;
+
+       pll->range = index;
+       pll->div = div;
+       pll->mul = mul;
+
+       return 0;
+}
+
+static const struct clk_ops pll_ops = {
+       .prepare = clk_pll_prepare,
+       .unprepare = clk_pll_unprepare,
+       .is_prepared = clk_pll_is_prepared,
+       .recalc_rate = clk_pll_recalc_rate,
+       .round_rate = clk_pll_round_rate,
+       .set_rate = clk_pll_set_rate,
+};
+
+static struct clk * __init
+at91_clk_register_pll(struct at91_pmc *pmc, unsigned int irq, const char *name,
+                     const char *parent_name, u8 id,
+                     const struct clk_pll_layout *layout,
+                     const struct clk_pll_characteristics *characteristics)
+{
+       struct clk_pll *pll;
+       struct clk *clk = NULL;
+       struct clk_init_data init;
+       int ret;
+       int offset = PLL_REG(id);
+       u32 tmp;
+
+       if (id > PLL_MAX_ID)
+               return ERR_PTR(-EINVAL);
+
+       pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+       if (!pll)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = name;
+       init.ops = &pll_ops;
+       init.parent_names = &parent_name;
+       init.num_parents = 1;
+       init.flags = CLK_SET_RATE_GATE;
+
+       pll->id = id;
+       pll->hw.init = &init;
+       pll->layout = layout;
+       pll->characteristics = characteristics;
+       pll->pmc = pmc;
+       pll->irq = irq;
+       tmp = pmc_read(pmc, offset) & layout->pllr_mask;
+       pll->div = PLL_DIV(tmp);
+       pll->mul = PLL_MUL(tmp, layout);
+       init_waitqueue_head(&pll->wait);
+       irq_set_status_flags(pll->irq, IRQ_NOAUTOEN);
+       ret = request_irq(pll->irq, clk_pll_irq_handler, IRQF_TRIGGER_HIGH,
+                         id ? "clk-pllb" : "clk-plla", pll);
+       if (ret)
+               return ERR_PTR(ret);
+
+       clk = clk_register(NULL, &pll->hw);
+       if (IS_ERR(clk))
+               kfree(pll);
+
+       return clk;
+}
+
+
+static const struct clk_pll_layout at91rm9200_pll_layout = {
+       .pllr_mask = 0x7FFFFFF,
+       .mul_shift = 16,
+       .mul_mask = 0x7FF,
+};
+
+static const struct clk_pll_layout at91sam9g45_pll_layout = {
+       .pllr_mask = 0xFFFFFF,
+       .mul_shift = 16,
+       .mul_mask = 0xFF,
+};
+
+static const struct clk_pll_layout at91sam9g20_pllb_layout = {
+       .pllr_mask = 0x3FFFFF,
+       .mul_shift = 16,
+       .mul_mask = 0x3F,
+};
+
+static const struct clk_pll_layout sama5d3_pll_layout = {
+       .pllr_mask = 0x1FFFFFF,
+       .mul_shift = 18,
+       .mul_mask = 0x7F,
+};
+
+
+static struct clk_pll_characteristics * __init
+of_at91_clk_pll_get_characteristics(struct device_node *np)
+{
+       int i;
+       int offset;
+       u32 tmp;
+       int num_output;
+       u32 num_cells;
+       struct clk_range input;
+       struct clk_range *output;
+       u8 *out = NULL;
+       u16 *icpll = NULL;
+       struct clk_pll_characteristics *characteristics;
+
+       if (of_at91_get_clk_range(np, "atmel,clk-input-range", &input))
+               return NULL;
+
+       if (of_property_read_u32(np, "#atmel,pll-clk-output-range-cells",
+                                &num_cells))
+               return NULL;
+
+       if (num_cells < 2 || num_cells > 4)
+               return NULL;
+
+       if (!of_get_property(np, "atmel,pll-clk-output-ranges", &tmp))
+               return NULL;
+       num_output = tmp / (sizeof(u32) * num_cells);
+
+       characteristics = kzalloc(sizeof(*characteristics), GFP_KERNEL);
+       if (!characteristics)
+               return NULL;
+
+       output = kzalloc(sizeof(*output) * num_output, GFP_KERNEL);
+       if (!output)
+               goto out_free_characteristics;
+
+       if (num_cells > 2) {
+               out = kzalloc(sizeof(*out) * num_output, GFP_KERNEL);
+               if (!out)
+                       goto out_free_output;
+       }
+
+       if (num_cells > 3) {
+               icpll = kzalloc(sizeof(*icpll) * num_output, GFP_KERNEL);
+               if (!icpll)
+                       goto out_free_output;
+       }
+
+       for (i = 0; i < num_output; i++) {
+               offset = i * num_cells;
+               if (of_property_read_u32_index(np,
+                                              "atmel,pll-clk-output-ranges",
+                                              offset, &tmp))
+                       goto out_free_output;
+               output[i].min = tmp;
+               if (of_property_read_u32_index(np,
+                                              "atmel,pll-clk-output-ranges",
+                                              offset + 1, &tmp))
+                       goto out_free_output;
+               output[i].max = tmp;
+
+               if (num_cells == 2)
+                       continue;
+
+               if (of_property_read_u32_index(np,
+                                              "atmel,pll-clk-output-ranges",
+                                              offset + 2, &tmp))
+                       goto out_free_output;
+               out[i] = tmp;
+
+               if (num_cells == 3)
+                       continue;
+
+               if (of_property_read_u32_index(np,
+                                              "atmel,pll-clk-output-ranges",
+                                              offset + 3, &tmp))
+                       goto out_free_output;
+               icpll[i] = tmp;
+       }
+
+       characteristics->input = input;
+       characteristics->num_output = num_output;
+       characteristics->output = output;
+       characteristics->out = out;
+       characteristics->icpll = icpll;
+       return characteristics;
+
+out_free_output:
+       kfree(icpll);
+       kfree(out);
+       kfree(output);
+out_free_characteristics:
+       kfree(characteristics);
+       return NULL;
+}
+
+static void __init
+of_at91_clk_pll_setup(struct device_node *np, struct at91_pmc *pmc,
+                     const struct clk_pll_layout *layout)
+{
+       u32 id;
+       unsigned int irq;
+       struct clk *clk;
+       const char *parent_name;
+       const char *name = np->name;
+       struct clk_pll_characteristics *characteristics;
+
+       if (of_property_read_u32(np, "reg", &id))
+               return;
+
+       parent_name = of_clk_get_parent_name(np, 0);
+
+       of_property_read_string(np, "clock-output-names", &name);
+
+       characteristics = of_at91_clk_pll_get_characteristics(np);
+       if (!characteristics)
+               return;
+
+       irq = irq_of_parse_and_map(np, 0);
+       if (!irq)
+               return;
+
+       clk = at91_clk_register_pll(pmc, irq, name, parent_name, id, layout,
+                                   characteristics);
+       if (IS_ERR(clk))
+               goto out_free_characteristics;
+
+       of_clk_add_provider(np, of_clk_src_simple_get, clk);
+       return;
+
+out_free_characteristics:
+       kfree(characteristics);
+}
+
+void __init of_at91rm9200_clk_pll_setup(struct device_node *np,
+                                              struct at91_pmc *pmc)
+{
+       of_at91_clk_pll_setup(np, pmc, &at91rm9200_pll_layout);
+}
+
+void __init of_at91sam9g45_clk_pll_setup(struct device_node *np,
+                                               struct at91_pmc *pmc)
+{
+       of_at91_clk_pll_setup(np, pmc, &at91sam9g45_pll_layout);
+}
+
+void __init of_at91sam9g20_clk_pllb_setup(struct device_node *np,
+                                                struct at91_pmc *pmc)
+{
+       of_at91_clk_pll_setup(np, pmc, &at91sam9g20_pllb_layout);
+}
+
+void __init of_sama5d3_clk_pll_setup(struct device_node *np,
+                                           struct at91_pmc *pmc)
+{
+       of_at91_clk_pll_setup(np, pmc, &sama5d3_pll_layout);
+}
diff --git a/drivers/clk/at91/clk-plldiv.c b/drivers/clk/at91/clk-plldiv.c
new file mode 100644 (file)
index 0000000..ea22656
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ *  Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.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.
+ *
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/clk/at91_pmc.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+
+#include "pmc.h"
+
+#define to_clk_plldiv(hw) container_of(hw, struct clk_plldiv, hw)
+
+struct clk_plldiv {
+       struct clk_hw hw;
+       struct at91_pmc *pmc;
+};
+
+static unsigned long clk_plldiv_recalc_rate(struct clk_hw *hw,
+                                           unsigned long parent_rate)
+{
+       struct clk_plldiv *plldiv = to_clk_plldiv(hw);
+       struct at91_pmc *pmc = plldiv->pmc;
+
+       if (pmc_read(pmc, AT91_PMC_MCKR) & AT91_PMC_PLLADIV2)
+               return parent_rate / 2;
+
+       return parent_rate;
+}
+
+static long clk_plldiv_round_rate(struct clk_hw *hw, unsigned long rate,
+                                       unsigned long *parent_rate)
+{
+       unsigned long div;
+
+       if (rate > *parent_rate)
+               return *parent_rate;
+       div = *parent_rate / 2;
+       if (rate < div)
+               return div;
+
+       if (rate - div < *parent_rate - rate)
+               return div;
+
+       return *parent_rate;
+}
+
+static int clk_plldiv_set_rate(struct clk_hw *hw, unsigned long rate,
+                              unsigned long parent_rate)
+{
+       struct clk_plldiv *plldiv = to_clk_plldiv(hw);
+       struct at91_pmc *pmc = plldiv->pmc;
+       u32 tmp;
+
+       if (parent_rate != rate && (parent_rate / 2) != rate)
+               return -EINVAL;
+
+       pmc_lock(pmc);
+       tmp = pmc_read(pmc, AT91_PMC_MCKR) & ~AT91_PMC_PLLADIV2;
+       if ((parent_rate / 2) == rate)
+               tmp |= AT91_PMC_PLLADIV2;
+       pmc_write(pmc, AT91_PMC_MCKR, tmp);
+       pmc_unlock(pmc);
+
+       return 0;
+}
+
+static const struct clk_ops plldiv_ops = {
+       .recalc_rate = clk_plldiv_recalc_rate,
+       .round_rate = clk_plldiv_round_rate,
+       .set_rate = clk_plldiv_set_rate,
+};
+
+static struct clk * __init
+at91_clk_register_plldiv(struct at91_pmc *pmc, const char *name,
+                        const char *parent_name)
+{
+       struct clk_plldiv *plldiv;
+       struct clk *clk = NULL;
+       struct clk_init_data init;
+
+       plldiv = kzalloc(sizeof(*plldiv), GFP_KERNEL);
+       if (!plldiv)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = name;
+       init.ops = &plldiv_ops;
+       init.parent_names = parent_name ? &parent_name : NULL;
+       init.num_parents = parent_name ? 1 : 0;
+       init.flags = CLK_SET_RATE_GATE;
+
+       plldiv->hw.init = &init;
+       plldiv->pmc = pmc;
+
+       clk = clk_register(NULL, &plldiv->hw);
+
+       if (IS_ERR(clk))
+               kfree(plldiv);
+
+       return clk;
+}
+
+static void __init
+of_at91_clk_plldiv_setup(struct device_node *np, struct at91_pmc *pmc)
+{
+       struct clk *clk;
+       const char *parent_name;
+       const char *name = np->name;
+
+       parent_name = of_clk_get_parent_name(np, 0);
+
+       of_property_read_string(np, "clock-output-names", &name);
+
+       clk = at91_clk_register_plldiv(pmc, name, parent_name);
+
+       if (IS_ERR(clk))
+               return;
+
+       of_clk_add_provider(np, of_clk_src_simple_get, clk);
+       return;
+}
+
+void __init of_at91sam9x5_clk_plldiv_setup(struct device_node *np,
+                                          struct at91_pmc *pmc)
+{
+       of_at91_clk_plldiv_setup(np, pmc);
+}
diff --git a/drivers/clk/at91/clk-programmable.c b/drivers/clk/at91/clk-programmable.c
new file mode 100644 (file)
index 0000000..fd792b2
--- /dev/null
@@ -0,0 +1,366 @@
+/*
+ *  Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.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.
+ *
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/clk/at91_pmc.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/io.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#include "pmc.h"
+
+#define PROG_SOURCE_MAX                5
+#define PROG_ID_MAX            7
+
+#define PROG_STATUS_MASK(id)   (1 << ((id) + 8))
+#define PROG_PRES_MASK         0x7
+#define PROG_MAX_RM9200_CSS    3
+
+struct clk_programmable_layout {
+       u8 pres_shift;
+       u8 css_mask;
+       u8 have_slck_mck;
+};
+
+struct clk_programmable {
+       struct clk_hw hw;
+       struct at91_pmc *pmc;
+       unsigned int irq;
+       wait_queue_head_t wait;
+       u8 id;
+       u8 css;
+       u8 pres;
+       u8 slckmck;
+       const struct clk_programmable_layout *layout;
+};
+
+#define to_clk_programmable(hw) container_of(hw, struct clk_programmable, hw)
+
+
+static irqreturn_t clk_programmable_irq_handler(int irq, void *dev_id)
+{
+       struct clk_programmable *prog = (struct clk_programmable *)dev_id;
+
+       wake_up(&prog->wait);
+
+       return IRQ_HANDLED;
+}
+
+static int clk_programmable_prepare(struct clk_hw *hw)
+{
+       u32 tmp;
+       struct clk_programmable *prog = to_clk_programmable(hw);
+       struct at91_pmc *pmc = prog->pmc;
+       const struct clk_programmable_layout *layout = prog->layout;
+       u8 id = prog->id;
+       u32 mask = PROG_STATUS_MASK(id);
+
+       tmp = prog->css | (prog->pres << layout->pres_shift);
+       if (layout->have_slck_mck && prog->slckmck)
+               tmp |= AT91_PMC_CSSMCK_MCK;
+
+       pmc_write(pmc, AT91_PMC_PCKR(id), tmp);
+
+       while (!(pmc_read(pmc, AT91_PMC_SR) & mask))
+               wait_event(prog->wait, pmc_read(pmc, AT91_PMC_SR) & mask);
+
+       return 0;
+}
+
+static int clk_programmable_is_ready(struct clk_hw *hw)
+{
+       struct clk_programmable *prog = to_clk_programmable(hw);
+       struct at91_pmc *pmc = prog->pmc;
+
+       return !!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_PCKR(prog->id));
+}
+
+static unsigned long clk_programmable_recalc_rate(struct clk_hw *hw,
+                                                 unsigned long parent_rate)
+{
+       u32 tmp;
+       struct clk_programmable *prog = to_clk_programmable(hw);
+       struct at91_pmc *pmc = prog->pmc;
+       const struct clk_programmable_layout *layout = prog->layout;
+
+       tmp = pmc_read(pmc, AT91_PMC_PCKR(prog->id));
+       prog->pres = (tmp >> layout->pres_shift) & PROG_PRES_MASK;
+
+       return parent_rate >> prog->pres;
+}
+
+static long clk_programmable_round_rate(struct clk_hw *hw, unsigned long rate,
+                                       unsigned long *parent_rate)
+{
+       unsigned long best_rate = *parent_rate;
+       unsigned long best_diff;
+       unsigned long new_diff;
+       unsigned long cur_rate;
+       int shift = shift;
+
+       if (rate > *parent_rate)
+               return *parent_rate;
+       else
+               best_diff = *parent_rate - rate;
+
+       if (!best_diff)
+               return best_rate;
+
+       for (shift = 1; shift < PROG_PRES_MASK; shift++) {
+               cur_rate = *parent_rate >> shift;
+
+               if (cur_rate > rate)
+                       new_diff = cur_rate - rate;
+               else
+                       new_diff = rate - cur_rate;
+
+               if (!new_diff)
+                       return cur_rate;
+
+               if (new_diff < best_diff) {
+                       best_diff = new_diff;
+                       best_rate = cur_rate;
+               }
+
+               if (rate > cur_rate)
+                       break;
+       }
+
+       return best_rate;
+}
+
+static int clk_programmable_set_parent(struct clk_hw *hw, u8 index)
+{
+       struct clk_programmable *prog = to_clk_programmable(hw);
+       const struct clk_programmable_layout *layout = prog->layout;
+       if (index > layout->css_mask) {
+               if (index > PROG_MAX_RM9200_CSS && layout->have_slck_mck) {
+                       prog->css = 0;
+                       prog->slckmck = 1;
+                       return 0;
+               } else {
+                       return -EINVAL;
+               }
+       }
+
+       prog->css = index;
+       return 0;
+}
+
+static u8 clk_programmable_get_parent(struct clk_hw *hw)
+{
+       u32 tmp;
+       u8 ret;
+       struct clk_programmable *prog = to_clk_programmable(hw);
+       struct at91_pmc *pmc = prog->pmc;
+       const struct clk_programmable_layout *layout = prog->layout;
+
+       tmp = pmc_read(pmc, AT91_PMC_PCKR(prog->id));
+       prog->css = tmp & layout->css_mask;
+       ret = prog->css;
+       if (layout->have_slck_mck) {
+               prog->slckmck = !!(tmp & AT91_PMC_CSSMCK_MCK);
+               if (prog->slckmck && !ret)
+                       ret = PROG_MAX_RM9200_CSS + 1;
+       }
+
+       return ret;
+}
+
+static int clk_programmable_set_rate(struct clk_hw *hw, unsigned long rate,
+                                    unsigned long parent_rate)
+{
+       struct clk_programmable *prog = to_clk_programmable(hw);
+       unsigned long best_rate = parent_rate;
+       unsigned long best_diff;
+       unsigned long new_diff;
+       unsigned long cur_rate;
+       int shift = 0;
+
+       if (rate > parent_rate)
+               return parent_rate;
+       else
+               best_diff = parent_rate - rate;
+
+       if (!best_diff) {
+               prog->pres = shift;
+               return 0;
+       }
+
+       for (shift = 1; shift < PROG_PRES_MASK; shift++) {
+               cur_rate = parent_rate >> shift;
+
+               if (cur_rate > rate)
+                       new_diff = cur_rate - rate;
+               else
+                       new_diff = rate - cur_rate;
+
+               if (!new_diff)
+                       break;
+
+               if (new_diff < best_diff) {
+                       best_diff = new_diff;
+                       best_rate = cur_rate;
+               }
+
+               if (rate > cur_rate)
+                       break;
+       }
+
+       prog->pres = shift;
+       return 0;
+}
+
+static const struct clk_ops programmable_ops = {
+       .prepare = clk_programmable_prepare,
+       .is_prepared = clk_programmable_is_ready,
+       .recalc_rate = clk_programmable_recalc_rate,
+       .round_rate = clk_programmable_round_rate,
+       .get_parent = clk_programmable_get_parent,
+       .set_parent = clk_programmable_set_parent,
+       .set_rate = clk_programmable_set_rate,
+};
+
+static struct clk * __init
+at91_clk_register_programmable(struct at91_pmc *pmc, unsigned int irq,
+                              const char *name, const char **parent_names,
+                              u8 num_parents, u8 id,
+                              const struct clk_programmable_layout *layout)
+{
+       int ret;
+       struct clk_programmable *prog;
+       struct clk *clk = NULL;
+       struct clk_init_data init;
+       char irq_name[11];
+
+       if (id > PROG_ID_MAX)
+               return ERR_PTR(-EINVAL);
+
+       prog = kzalloc(sizeof(*prog), GFP_KERNEL);
+       if (!prog)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = name;
+       init.ops = &programmable_ops;
+       init.parent_names = parent_names;
+       init.num_parents = num_parents;
+       init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
+
+       prog->id = id;
+       prog->layout = layout;
+       prog->hw.init = &init;
+       prog->pmc = pmc;
+       prog->irq = irq;
+       init_waitqueue_head(&prog->wait);
+       irq_set_status_flags(prog->irq, IRQ_NOAUTOEN);
+       snprintf(irq_name, sizeof(irq_name), "clk-prog%d", id);
+       ret = request_irq(prog->irq, clk_programmable_irq_handler,
+                         IRQF_TRIGGER_HIGH, irq_name, prog);
+       if (ret)
+               return ERR_PTR(ret);
+
+       clk = clk_register(NULL, &prog->hw);
+       if (IS_ERR(clk))
+               kfree(prog);
+
+       return clk;
+}
+
+static const struct clk_programmable_layout at91rm9200_programmable_layout = {
+       .pres_shift = 2,
+       .css_mask = 0x3,
+       .have_slck_mck = 0,
+};
+
+static const struct clk_programmable_layout at91sam9g45_programmable_layout = {
+       .pres_shift = 2,
+       .css_mask = 0x3,
+       .have_slck_mck = 1,
+};
+
+static const struct clk_programmable_layout at91sam9x5_programmable_layout = {
+       .pres_shift = 4,
+       .css_mask = 0x7,
+       .have_slck_mck = 0,
+};
+
+static void __init
+of_at91_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc,
+                      const struct clk_programmable_layout *layout)
+{
+       int num;
+       u32 id;
+       int i;
+       unsigned int irq;
+       struct clk *clk;
+       int num_parents;
+       const char *parent_names[PROG_SOURCE_MAX];
+       const char *name;
+       struct device_node *progclknp;
+
+       num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+       if (num_parents <= 0 || num_parents > PROG_SOURCE_MAX)
+               return;
+
+       for (i = 0; i < num_parents; ++i) {
+               parent_names[i] = of_clk_get_parent_name(np, i);
+               if (!parent_names[i])
+                       return;
+       }
+
+       num = of_get_child_count(np);
+       if (!num || num > (PROG_ID_MAX + 1))
+               return;
+
+       for_each_child_of_node(np, progclknp) {
+               if (of_property_read_u32(progclknp, "reg", &id))
+                       continue;
+
+               if (of_property_read_string(np, "clock-output-names", &name))
+                       name = progclknp->name;
+
+               irq = irq_of_parse_and_map(progclknp, 0);
+               if (!irq)
+                       continue;
+
+               clk = at91_clk_register_programmable(pmc, irq, name,
+                                                    parent_names, num_parents,
+                                                    id, layout);
+               if (IS_ERR(clk))
+                       continue;
+
+               of_clk_add_provider(progclknp, of_clk_src_simple_get, clk);
+       }
+}
+
+
+void __init of_at91rm9200_clk_prog_setup(struct device_node *np,
+                                        struct at91_pmc *pmc)
+{
+       of_at91_clk_prog_setup(np, pmc, &at91rm9200_programmable_layout);
+}
+
+void __init of_at91sam9g45_clk_prog_setup(struct device_node *np,
+                                         struct at91_pmc *pmc)
+{
+       of_at91_clk_prog_setup(np, pmc, &at91sam9g45_programmable_layout);
+}
+
+void __init of_at91sam9x5_clk_prog_setup(struct device_node *np,
+                                        struct at91_pmc *pmc)
+{
+       of_at91_clk_prog_setup(np, pmc, &at91sam9x5_programmable_layout);
+}
diff --git a/drivers/clk/at91/clk-smd.c b/drivers/clk/at91/clk-smd.c
new file mode 100644 (file)
index 0000000..144d47e
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ *  Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.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.
+ *
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/clk/at91_pmc.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+
+#include "pmc.h"
+
+#define SMD_SOURCE_MAX         2
+
+#define SMD_DIV_SHIFT          8
+#define SMD_MAX_DIV            0xf
+
+struct at91sam9x5_clk_smd {
+       struct clk_hw hw;
+       struct at91_pmc *pmc;
+};
+
+#define to_at91sam9x5_clk_smd(hw) \
+       container_of(hw, struct at91sam9x5_clk_smd, hw)
+
+static unsigned long at91sam9x5_clk_smd_recalc_rate(struct clk_hw *hw,
+                                                   unsigned long parent_rate)
+{
+       u32 tmp;
+       u8 smddiv;
+       struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw);
+       struct at91_pmc *pmc = smd->pmc;
+
+       tmp = pmc_read(pmc, AT91_PMC_SMD);
+       smddiv = (tmp & AT91_PMC_SMD_DIV) >> SMD_DIV_SHIFT;
+       return parent_rate / (smddiv + 1);
+}
+
+static long at91sam9x5_clk_smd_round_rate(struct clk_hw *hw, unsigned long rate,
+                                         unsigned long *parent_rate)
+{
+       unsigned long div;
+       unsigned long bestrate;
+       unsigned long tmp;
+
+       if (rate >= *parent_rate)
+               return *parent_rate;
+
+       div = *parent_rate / rate;
+       if (div > SMD_MAX_DIV)
+               return *parent_rate / (SMD_MAX_DIV + 1);
+
+       bestrate = *parent_rate / div;
+       tmp = *parent_rate / (div + 1);
+       if (bestrate - rate > rate - tmp)
+               bestrate = tmp;
+
+       return bestrate;
+}
+
+static int at91sam9x5_clk_smd_set_parent(struct clk_hw *hw, u8 index)
+{
+       u32 tmp;
+       struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw);
+       struct at91_pmc *pmc = smd->pmc;
+
+       if (index > 1)
+               return -EINVAL;
+       tmp = pmc_read(pmc, AT91_PMC_SMD) & ~AT91_PMC_SMDS;
+       if (index)
+               tmp |= AT91_PMC_SMDS;
+       pmc_write(pmc, AT91_PMC_SMD, tmp);
+       return 0;
+}
+
+static u8 at91sam9x5_clk_smd_get_parent(struct clk_hw *hw)
+{
+       struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw);
+       struct at91_pmc *pmc = smd->pmc;
+
+       return pmc_read(pmc, AT91_PMC_SMD) & AT91_PMC_SMDS;
+}
+
+static int at91sam9x5_clk_smd_set_rate(struct clk_hw *hw, unsigned long rate,
+                                      unsigned long parent_rate)
+{
+       u32 tmp;
+       struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw);
+       struct at91_pmc *pmc = smd->pmc;
+       unsigned long div = parent_rate / rate;
+
+       if (parent_rate % rate || div < 1 || div > (SMD_MAX_DIV + 1))
+               return -EINVAL;
+       tmp = pmc_read(pmc, AT91_PMC_SMD) & ~AT91_PMC_SMD_DIV;
+       tmp |= (div - 1) << SMD_DIV_SHIFT;
+       pmc_write(pmc, AT91_PMC_SMD, tmp);
+
+       return 0;
+}
+
+static const struct clk_ops at91sam9x5_smd_ops = {
+       .recalc_rate = at91sam9x5_clk_smd_recalc_rate,
+       .round_rate = at91sam9x5_clk_smd_round_rate,
+       .get_parent = at91sam9x5_clk_smd_get_parent,
+       .set_parent = at91sam9x5_clk_smd_set_parent,
+       .set_rate = at91sam9x5_clk_smd_set_rate,
+};
+
+static struct clk * __init
+at91sam9x5_clk_register_smd(struct at91_pmc *pmc, const char *name,
+                           const char **parent_names, u8 num_parents)
+{
+       struct at91sam9x5_clk_smd *smd;
+       struct clk *clk = NULL;
+       struct clk_init_data init;
+
+       smd = kzalloc(sizeof(*smd), GFP_KERNEL);
+       if (!smd)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = name;
+       init.ops = &at91sam9x5_smd_ops;
+       init.parent_names = parent_names;
+       init.num_parents = num_parents;
+       init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
+
+       smd->hw.init = &init;
+       smd->pmc = pmc;
+
+       clk = clk_register(NULL, &smd->hw);
+       if (IS_ERR(clk))
+               kfree(smd);
+
+       return clk;
+}
+
+void __init of_at91sam9x5_clk_smd_setup(struct device_node *np,
+                                       struct at91_pmc *pmc)
+{
+       struct clk *clk;
+       int i;
+       int num_parents;
+       const char *parent_names[SMD_SOURCE_MAX];
+       const char *name = np->name;
+
+       num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+       if (num_parents <= 0 || num_parents > SMD_SOURCE_MAX)
+               return;
+
+       for (i = 0; i < num_parents; i++) {
+               parent_names[i] = of_clk_get_parent_name(np, i);
+               if (!parent_names[i])
+                       return;
+       }
+
+       of_property_read_string(np, "clock-output-names", &name);
+
+       clk = at91sam9x5_clk_register_smd(pmc, name, parent_names,
+                                         num_parents);
+       if (IS_ERR(clk))
+               return;
+
+       of_clk_add_provider(np, of_clk_src_simple_get, clk);
+}
diff --git a/drivers/clk/at91/clk-system.c b/drivers/clk/at91/clk-system.c
new file mode 100644 (file)
index 0000000..8f7c043
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ *  Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.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.
+ *
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/clk/at91_pmc.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+
+#include "pmc.h"
+
+#define SYSTEM_MAX_ID          31
+
+#define SYSTEM_MAX_NAME_SZ     32
+
+#define to_clk_system(hw) container_of(hw, struct clk_system, hw)
+struct clk_system {
+       struct clk_hw hw;
+       struct at91_pmc *pmc;
+       u8 id;
+};
+
+static int clk_system_enable(struct clk_hw *hw)
+{
+       struct clk_system *sys = to_clk_system(hw);
+       struct at91_pmc *pmc = sys->pmc;
+
+       pmc_write(pmc, AT91_PMC_SCER, 1 << sys->id);
+       return 0;
+}
+
+static void clk_system_disable(struct clk_hw *hw)
+{
+       struct clk_system *sys = to_clk_system(hw);
+       struct at91_pmc *pmc = sys->pmc;
+
+       pmc_write(pmc, AT91_PMC_SCDR, 1 << sys->id);
+}
+
+static int clk_system_is_enabled(struct clk_hw *hw)
+{
+       struct clk_system *sys = to_clk_system(hw);
+       struct at91_pmc *pmc = sys->pmc;
+
+       return !!(pmc_read(pmc, AT91_PMC_SCSR) & (1 << sys->id));
+}
+
+static const struct clk_ops system_ops = {
+       .enable = clk_system_enable,
+       .disable = clk_system_disable,
+       .is_enabled = clk_system_is_enabled,
+};
+
+static struct clk * __init
+at91_clk_register_system(struct at91_pmc *pmc, const char *name,
+                        const char *parent_name, u8 id)
+{
+       struct clk_system *sys;
+       struct clk *clk = NULL;
+       struct clk_init_data init;
+
+       if (!parent_name || id > SYSTEM_MAX_ID)
+               return ERR_PTR(-EINVAL);
+
+       sys = kzalloc(sizeof(*sys), GFP_KERNEL);
+       if (!sys)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = name;
+       init.ops = &system_ops;
+       init.parent_names = &parent_name;
+       init.num_parents = 1;
+       /*
+        * CLK_IGNORE_UNUSED is used to avoid ddrck switch off.
+        * TODO : we should implement a driver supporting at91 ddr controller
+        * (see drivers/memory) which would request and enable the ddrck clock.
+        * When this is done we will be able to remove CLK_IGNORE_UNUSED flag.
+        */
+       init.flags = CLK_IGNORE_UNUSED;
+
+       sys->id = id;
+       sys->hw.init = &init;
+       sys->pmc = pmc;
+
+       clk = clk_register(NULL, &sys->hw);
+       if (IS_ERR(clk))
+               kfree(sys);
+
+       return clk;
+}
+
+static void __init
+of_at91_clk_sys_setup(struct device_node *np, struct at91_pmc *pmc)
+{
+       int num;
+       u32 id;
+       struct clk *clk;
+       const char *name;
+       struct device_node *sysclknp;
+       const char *parent_name;
+
+       num = of_get_child_count(np);
+       if (num > (SYSTEM_MAX_ID + 1))
+               return;
+
+       for_each_child_of_node(np, sysclknp) {
+               if (of_property_read_u32(sysclknp, "reg", &id))
+                       continue;
+
+               if (of_property_read_string(np, "clock-output-names", &name))
+                       name = sysclknp->name;
+
+               parent_name = of_clk_get_parent_name(sysclknp, 0);
+
+               clk = at91_clk_register_system(pmc, name, parent_name, id);
+               if (IS_ERR(clk))
+                       continue;
+
+               of_clk_add_provider(sysclknp, of_clk_src_simple_get, clk);
+       }
+}
+
+void __init of_at91rm9200_clk_sys_setup(struct device_node *np,
+                                       struct at91_pmc *pmc)
+{
+       of_at91_clk_sys_setup(np, pmc);
+}
diff --git a/drivers/clk/at91/clk-usb.c b/drivers/clk/at91/clk-usb.c
new file mode 100644 (file)
index 0000000..7d1d26a
--- /dev/null
@@ -0,0 +1,398 @@
+/*
+ *  Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.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.
+ *
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/clk/at91_pmc.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+
+#include "pmc.h"
+
+#define USB_SOURCE_MAX         2
+
+#define SAM9X5_USB_DIV_SHIFT   8
+#define SAM9X5_USB_MAX_DIV     0xf
+
+#define RM9200_USB_DIV_SHIFT   28
+#define RM9200_USB_DIV_TAB_SIZE        4
+
+struct at91sam9x5_clk_usb {
+       struct clk_hw hw;
+       struct at91_pmc *pmc;
+};
+
+#define to_at91sam9x5_clk_usb(hw) \
+       container_of(hw, struct at91sam9x5_clk_usb, hw)
+
+struct at91rm9200_clk_usb {
+       struct clk_hw hw;
+       struct at91_pmc *pmc;
+       u32 divisors[4];
+};
+
+#define to_at91rm9200_clk_usb(hw) \
+       container_of(hw, struct at91rm9200_clk_usb, hw)
+
+static unsigned long at91sam9x5_clk_usb_recalc_rate(struct clk_hw *hw,
+                                                   unsigned long parent_rate)
+{
+       u32 tmp;
+       u8 usbdiv;
+       struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
+       struct at91_pmc *pmc = usb->pmc;
+
+       tmp = pmc_read(pmc, AT91_PMC_USB);
+       usbdiv = (tmp & AT91_PMC_OHCIUSBDIV) >> SAM9X5_USB_DIV_SHIFT;
+       return parent_rate / (usbdiv + 1);
+}
+
+static long at91sam9x5_clk_usb_round_rate(struct clk_hw *hw, unsigned long rate,
+                                         unsigned long *parent_rate)
+{
+       unsigned long div;
+       unsigned long bestrate;
+       unsigned long tmp;
+
+       if (rate >= *parent_rate)
+               return *parent_rate;
+
+       div = *parent_rate / rate;
+       if (div >= SAM9X5_USB_MAX_DIV)
+               return *parent_rate / (SAM9X5_USB_MAX_DIV + 1);
+
+       bestrate = *parent_rate / div;
+       tmp = *parent_rate / (div + 1);
+       if (bestrate - rate > rate - tmp)
+               bestrate = tmp;
+
+       return bestrate;
+}
+
+static int at91sam9x5_clk_usb_set_parent(struct clk_hw *hw, u8 index)
+{
+       u32 tmp;
+       struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
+       struct at91_pmc *pmc = usb->pmc;
+
+       if (index > 1)
+               return -EINVAL;
+       tmp = pmc_read(pmc, AT91_PMC_USB) & ~AT91_PMC_USBS;
+       if (index)
+               tmp |= AT91_PMC_USBS;
+       pmc_write(pmc, AT91_PMC_USB, tmp);
+       return 0;
+}
+
+static u8 at91sam9x5_clk_usb_get_parent(struct clk_hw *hw)
+{
+       struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
+       struct at91_pmc *pmc = usb->pmc;
+
+       return pmc_read(pmc, AT91_PMC_USB) & AT91_PMC_USBS;
+}
+
+static int at91sam9x5_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate,
+                                      unsigned long parent_rate)
+{
+       u32 tmp;
+       struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
+       struct at91_pmc *pmc = usb->pmc;
+       unsigned long div = parent_rate / rate;
+
+       if (parent_rate % rate || div < 1 || div >= SAM9X5_USB_MAX_DIV)
+               return -EINVAL;
+
+       tmp = pmc_read(pmc, AT91_PMC_USB) & ~AT91_PMC_OHCIUSBDIV;
+       tmp |= (div - 1) << SAM9X5_USB_DIV_SHIFT;
+       pmc_write(pmc, AT91_PMC_USB, tmp);
+
+       return 0;
+}
+
+static const struct clk_ops at91sam9x5_usb_ops = {
+       .recalc_rate = at91sam9x5_clk_usb_recalc_rate,
+       .round_rate = at91sam9x5_clk_usb_round_rate,
+       .get_parent = at91sam9x5_clk_usb_get_parent,
+       .set_parent = at91sam9x5_clk_usb_set_parent,
+       .set_rate = at91sam9x5_clk_usb_set_rate,
+};
+
+static int at91sam9n12_clk_usb_enable(struct clk_hw *hw)
+{
+       struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
+       struct at91_pmc *pmc = usb->pmc;
+
+       pmc_write(pmc, AT91_PMC_USB,
+                 pmc_read(pmc, AT91_PMC_USB) | AT91_PMC_USBS);
+       return 0;
+}
+
+static void at91sam9n12_clk_usb_disable(struct clk_hw *hw)
+{
+       struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
+       struct at91_pmc *pmc = usb->pmc;
+
+       pmc_write(pmc, AT91_PMC_USB,
+                 pmc_read(pmc, AT91_PMC_USB) & ~AT91_PMC_USBS);
+}
+
+static int at91sam9n12_clk_usb_is_enabled(struct clk_hw *hw)
+{
+       struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
+       struct at91_pmc *pmc = usb->pmc;
+
+       return !!(pmc_read(pmc, AT91_PMC_USB) & AT91_PMC_USBS);
+}
+
+static const struct clk_ops at91sam9n12_usb_ops = {
+       .enable = at91sam9n12_clk_usb_enable,
+       .disable = at91sam9n12_clk_usb_disable,
+       .is_enabled = at91sam9n12_clk_usb_is_enabled,
+       .recalc_rate = at91sam9x5_clk_usb_recalc_rate,
+       .round_rate = at91sam9x5_clk_usb_round_rate,
+       .set_rate = at91sam9x5_clk_usb_set_rate,
+};
+
+static struct clk * __init
+at91sam9x5_clk_register_usb(struct at91_pmc *pmc, const char *name,
+                           const char **parent_names, u8 num_parents)
+{
+       struct at91sam9x5_clk_usb *usb;
+       struct clk *clk = NULL;
+       struct clk_init_data init;
+
+       usb = kzalloc(sizeof(*usb), GFP_KERNEL);
+       if (!usb)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = name;
+       init.ops = &at91sam9x5_usb_ops;
+       init.parent_names = parent_names;
+       init.num_parents = num_parents;
+       init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
+
+       usb->hw.init = &init;
+       usb->pmc = pmc;
+
+       clk = clk_register(NULL, &usb->hw);
+       if (IS_ERR(clk))
+               kfree(usb);
+
+       return clk;
+}
+
+static struct clk * __init
+at91sam9n12_clk_register_usb(struct at91_pmc *pmc, const char *name,
+                            const char *parent_name)
+{
+       struct at91sam9x5_clk_usb *usb;
+       struct clk *clk = NULL;
+       struct clk_init_data init;
+
+       usb = kzalloc(sizeof(*usb), GFP_KERNEL);
+       if (!usb)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = name;
+       init.ops = &at91sam9n12_usb_ops;
+       init.parent_names = &parent_name;
+       init.num_parents = 1;
+       init.flags = CLK_SET_RATE_GATE;
+
+       usb->hw.init = &init;
+       usb->pmc = pmc;
+
+       clk = clk_register(NULL, &usb->hw);
+       if (IS_ERR(clk))
+               kfree(usb);
+
+       return clk;
+}
+
+static unsigned long at91rm9200_clk_usb_recalc_rate(struct clk_hw *hw,
+                                                   unsigned long parent_rate)
+{
+       struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw);
+       struct at91_pmc *pmc = usb->pmc;
+       u32 tmp;
+       u8 usbdiv;
+
+       tmp = pmc_read(pmc, AT91_CKGR_PLLBR);
+       usbdiv = (tmp & AT91_PMC_USBDIV) >> RM9200_USB_DIV_SHIFT;
+       if (usb->divisors[usbdiv])
+               return parent_rate / usb->divisors[usbdiv];
+
+       return 0;
+}
+
+static long at91rm9200_clk_usb_round_rate(struct clk_hw *hw, unsigned long rate,
+                                         unsigned long *parent_rate)
+{
+       struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw);
+       unsigned long bestrate = 0;
+       int bestdiff = -1;
+       unsigned long tmprate;
+       int tmpdiff;
+       int i = 0;
+
+       for (i = 0; i < 4; i++) {
+               if (!usb->divisors[i])
+                       continue;
+               tmprate = *parent_rate / usb->divisors[i];
+               if (tmprate < rate)
+                       tmpdiff = rate - tmprate;
+               else
+                       tmpdiff = tmprate - rate;
+
+               if (bestdiff < 0 || bestdiff > tmpdiff) {
+                       bestrate = tmprate;
+                       bestdiff = tmpdiff;
+               }
+
+               if (!bestdiff)
+                       break;
+       }
+
+       return bestrate;
+}
+
+static int at91rm9200_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate,
+                                      unsigned long parent_rate)
+{
+       u32 tmp;
+       int i;
+       struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw);
+       struct at91_pmc *pmc = usb->pmc;
+       unsigned long div = parent_rate / rate;
+
+       if (parent_rate % rate)
+               return -EINVAL;
+       for (i = 0; i < RM9200_USB_DIV_TAB_SIZE; i++) {
+               if (usb->divisors[i] == div) {
+                       tmp = pmc_read(pmc, AT91_CKGR_PLLBR) &
+                             ~AT91_PMC_USBDIV;
+                       tmp |= i << RM9200_USB_DIV_SHIFT;
+                       pmc_write(pmc, AT91_CKGR_PLLBR, tmp);
+                       return 0;
+               }
+       }
+
+       return -EINVAL;
+}
+
+static const struct clk_ops at91rm9200_usb_ops = {
+       .recalc_rate = at91rm9200_clk_usb_recalc_rate,
+       .round_rate = at91rm9200_clk_usb_round_rate,
+       .set_rate = at91rm9200_clk_usb_set_rate,
+};
+
+static struct clk * __init
+at91rm9200_clk_register_usb(struct at91_pmc *pmc, const char *name,
+                           const char *parent_name, const u32 *divisors)
+{
+       struct at91rm9200_clk_usb *usb;
+       struct clk *clk = NULL;
+       struct clk_init_data init;
+
+       usb = kzalloc(sizeof(*usb), GFP_KERNEL);
+       if (!usb)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = name;
+       init.ops = &at91rm9200_usb_ops;
+       init.parent_names = &parent_name;
+       init.num_parents = 1;
+       init.flags = 0;
+
+       usb->hw.init = &init;
+       usb->pmc = pmc;
+       memcpy(usb->divisors, divisors, sizeof(usb->divisors));
+
+       clk = clk_register(NULL, &usb->hw);
+       if (IS_ERR(clk))
+               kfree(usb);
+
+       return clk;
+}
+
+void __init of_at91sam9x5_clk_usb_setup(struct device_node *np,
+                                       struct at91_pmc *pmc)
+{
+       struct clk *clk;
+       int i;
+       int num_parents;
+       const char *parent_names[USB_SOURCE_MAX];
+       const char *name = np->name;
+
+       num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+       if (num_parents <= 0 || num_parents > USB_SOURCE_MAX)
+               return;
+
+       for (i = 0; i < num_parents; i++) {
+               parent_names[i] = of_clk_get_parent_name(np, i);
+               if (!parent_names[i])
+                       return;
+       }
+
+       of_property_read_string(np, "clock-output-names", &name);
+
+       clk = at91sam9x5_clk_register_usb(pmc, name, parent_names, num_parents);
+       if (IS_ERR(clk))
+               return;
+
+       of_clk_add_provider(np, of_clk_src_simple_get, clk);
+}
+
+void __init of_at91sam9n12_clk_usb_setup(struct device_node *np,
+                                        struct at91_pmc *pmc)
+{
+       struct clk *clk;
+       const char *parent_name;
+       const char *name = np->name;
+
+       parent_name = of_clk_get_parent_name(np, 0);
+       if (!parent_name)
+               return;
+
+       of_property_read_string(np, "clock-output-names", &name);
+
+       clk = at91sam9n12_clk_register_usb(pmc, name, parent_name);
+       if (IS_ERR(clk))
+               return;
+
+       of_clk_add_provider(np, of_clk_src_simple_get, clk);
+}
+
+void __init of_at91rm9200_clk_usb_setup(struct device_node *np,
+                                       struct at91_pmc *pmc)
+{
+       struct clk *clk;
+       const char *parent_name;
+       const char *name = np->name;
+       u32 divisors[4] = {0, 0, 0, 0};
+
+       parent_name = of_clk_get_parent_name(np, 0);
+       if (!parent_name)
+               return;
+
+       of_property_read_u32_array(np, "atmel,clk-divisors", divisors, 4);
+       if (!divisors[0])
+               return;
+
+       of_property_read_string(np, "clock-output-names", &name);
+
+       clk = at91rm9200_clk_register_usb(pmc, name, parent_name, divisors);
+       if (IS_ERR(clk))
+               return;
+
+       of_clk_add_provider(np, of_clk_src_simple_get, clk);
+}
diff --git a/drivers/clk/at91/clk-utmi.c b/drivers/clk/at91/clk-utmi.c
new file mode 100644 (file)
index 0000000..ae3263b
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ *  Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.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.
+ *
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/clk/at91_pmc.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/io.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+
+#include "pmc.h"
+
+#define UTMI_FIXED_MUL         40
+
+struct clk_utmi {
+       struct clk_hw hw;
+       struct at91_pmc *pmc;
+       unsigned int irq;
+       wait_queue_head_t wait;
+};
+
+#define to_clk_utmi(hw) container_of(hw, struct clk_utmi, hw)
+
+static irqreturn_t clk_utmi_irq_handler(int irq, void *dev_id)
+{
+       struct clk_utmi *utmi = (struct clk_utmi *)dev_id;
+
+       wake_up(&utmi->wait);
+       disable_irq_nosync(utmi->irq);
+
+       return IRQ_HANDLED;
+}
+
+static int clk_utmi_prepare(struct clk_hw *hw)
+{
+       struct clk_utmi *utmi = to_clk_utmi(hw);
+       struct at91_pmc *pmc = utmi->pmc;
+       u32 tmp = at91_pmc_read(AT91_CKGR_UCKR) | AT91_PMC_UPLLEN |
+                 AT91_PMC_UPLLCOUNT | AT91_PMC_BIASEN;
+
+       pmc_write(pmc, AT91_CKGR_UCKR, tmp);
+
+       while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_LOCKU)) {
+               enable_irq(utmi->irq);
+               wait_event(utmi->wait,
+                          pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_LOCKU);
+       }
+
+       return 0;
+}
+
+static int clk_utmi_is_prepared(struct clk_hw *hw)
+{
+       struct clk_utmi *utmi = to_clk_utmi(hw);
+       struct at91_pmc *pmc = utmi->pmc;
+
+       return !!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_LOCKU);
+}
+
+static void clk_utmi_unprepare(struct clk_hw *hw)
+{
+       struct clk_utmi *utmi = to_clk_utmi(hw);
+       struct at91_pmc *pmc = utmi->pmc;
+       u32 tmp = at91_pmc_read(AT91_CKGR_UCKR) & ~AT91_PMC_UPLLEN;
+
+       pmc_write(pmc, AT91_CKGR_UCKR, tmp);
+}
+
+static unsigned long clk_utmi_recalc_rate(struct clk_hw *hw,
+                                         unsigned long parent_rate)
+{
+       /* UTMI clk is a fixed clk multiplier */
+       return parent_rate * UTMI_FIXED_MUL;
+}
+
+static const struct clk_ops utmi_ops = {
+       .prepare = clk_utmi_prepare,
+       .unprepare = clk_utmi_unprepare,
+       .is_prepared = clk_utmi_is_prepared,
+       .recalc_rate = clk_utmi_recalc_rate,
+};
+
+static struct clk * __init
+at91_clk_register_utmi(struct at91_pmc *pmc, unsigned int irq,
+                      const char *name, const char *parent_name)
+{
+       int ret;
+       struct clk_utmi *utmi;
+       struct clk *clk = NULL;
+       struct clk_init_data init;
+
+       utmi = kzalloc(sizeof(*utmi), GFP_KERNEL);
+       if (!utmi)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = name;
+       init.ops = &utmi_ops;
+       init.parent_names = parent_name ? &parent_name : NULL;
+       init.num_parents = parent_name ? 1 : 0;
+       init.flags = CLK_SET_RATE_GATE;
+
+       utmi->hw.init = &init;
+       utmi->pmc = pmc;
+       utmi->irq = irq;
+       init_waitqueue_head(&utmi->wait);
+       irq_set_status_flags(utmi->irq, IRQ_NOAUTOEN);
+       ret = request_irq(utmi->irq, clk_utmi_irq_handler,
+                         IRQF_TRIGGER_HIGH, "clk-utmi", utmi);
+       if (ret)
+               return ERR_PTR(ret);
+
+       clk = clk_register(NULL, &utmi->hw);
+       if (IS_ERR(clk))
+               kfree(utmi);
+
+       return clk;
+}
+
+static void __init
+of_at91_clk_utmi_setup(struct device_node *np, struct at91_pmc *pmc)
+{
+       unsigned int irq;
+       struct clk *clk;
+       const char *parent_name;
+       const char *name = np->name;
+
+       parent_name = of_clk_get_parent_name(np, 0);
+
+       of_property_read_string(np, "clock-output-names", &name);
+
+       irq = irq_of_parse_and_map(np, 0);
+       if (!irq)
+               return;
+
+       clk = at91_clk_register_utmi(pmc, irq, name, parent_name);
+       if (IS_ERR(clk))
+               return;
+
+       of_clk_add_provider(np, of_clk_src_simple_get, clk);
+       return;
+}
+
+void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np,
+                                        struct at91_pmc *pmc)
+{
+       of_at91_clk_utmi_setup(np, pmc);
+}
diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c
new file mode 100644 (file)
index 0000000..7b9db60
--- /dev/null
@@ -0,0 +1,397 @@
+/*
+ *  Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.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.
+ *
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/clk/at91_pmc.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+
+#include <asm/proc-fns.h>
+
+#include "pmc.h"
+
+void __iomem *at91_pmc_base;
+EXPORT_SYMBOL_GPL(at91_pmc_base);
+
+void at91sam9_idle(void)
+{
+       at91_pmc_write(AT91_PMC_SCDR, AT91_PMC_PCK);
+       cpu_do_idle();
+}
+
+int of_at91_get_clk_range(struct device_node *np, const char *propname,
+                         struct clk_range *range)
+{
+       u32 min, max;
+       int ret;
+
+       ret = of_property_read_u32_index(np, propname, 0, &min);
+       if (ret)
+               return ret;
+
+       ret = of_property_read_u32_index(np, propname, 1, &max);
+       if (ret)
+               return ret;
+
+       if (range) {
+               range->min = min;
+               range->max = max;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(of_at91_get_clk_range);
+
+static void pmc_irq_mask(struct irq_data *d)
+{
+       struct at91_pmc *pmc = irq_data_get_irq_chip_data(d);
+
+       pmc_write(pmc, AT91_PMC_IDR, 1 << d->hwirq);
+}
+
+static void pmc_irq_unmask(struct irq_data *d)
+{
+       struct at91_pmc *pmc = irq_data_get_irq_chip_data(d);
+
+       pmc_write(pmc, AT91_PMC_IER, 1 << d->hwirq);
+}
+
+static int pmc_irq_set_type(struct irq_data *d, unsigned type)
+{
+       if (type != IRQ_TYPE_LEVEL_HIGH) {
+               pr_warn("PMC: type not supported (support only IRQ_TYPE_LEVEL_HIGH type)\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static struct irq_chip pmc_irq = {
+       .name = "PMC",
+       .irq_disable = pmc_irq_mask,
+       .irq_mask = pmc_irq_mask,
+       .irq_unmask = pmc_irq_unmask,
+       .irq_set_type = pmc_irq_set_type,
+};
+
+static struct lock_class_key pmc_lock_class;
+
+static int pmc_irq_map(struct irq_domain *h, unsigned int virq,
+                      irq_hw_number_t hw)
+{
+       struct at91_pmc *pmc = h->host_data;
+
+       irq_set_lockdep_class(virq, &pmc_lock_class);
+
+       irq_set_chip_and_handler(virq, &pmc_irq,
+                                handle_level_irq);
+       set_irq_flags(virq, IRQF_VALID);
+       irq_set_chip_data(virq, pmc);
+
+       return 0;
+}
+
+static int pmc_irq_domain_xlate(struct irq_domain *d,
+                               struct device_node *ctrlr,
+                               const u32 *intspec, unsigned int intsize,
+                               irq_hw_number_t *out_hwirq,
+                               unsigned int *out_type)
+{
+       struct at91_pmc *pmc = d->host_data;
+       const struct at91_pmc_caps *caps = pmc->caps;
+
+       if (WARN_ON(intsize < 1))
+               return -EINVAL;
+
+       *out_hwirq = intspec[0];
+
+       if (!(caps->available_irqs & (1 << *out_hwirq)))
+               return -EINVAL;
+
+       *out_type = IRQ_TYPE_LEVEL_HIGH;
+
+       return 0;
+}
+
+static struct irq_domain_ops pmc_irq_ops = {
+       .map    = pmc_irq_map,
+       .xlate  = pmc_irq_domain_xlate,
+};
+
+static irqreturn_t pmc_irq_handler(int irq, void *data)
+{
+       struct at91_pmc *pmc = (struct at91_pmc *)data;
+       unsigned long sr;
+       int n;
+
+       sr = pmc_read(pmc, AT91_PMC_SR) & pmc_read(pmc, AT91_PMC_IMR);
+       if (!sr)
+               return IRQ_NONE;
+
+       for_each_set_bit(n, &sr, BITS_PER_LONG)
+               generic_handle_irq(irq_find_mapping(pmc->irqdomain, n));
+
+       return IRQ_HANDLED;
+}
+
+static const struct at91_pmc_caps at91rm9200_caps = {
+       .available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_LOCKB |
+                         AT91_PMC_MCKRDY | AT91_PMC_PCK0RDY |
+                         AT91_PMC_PCK1RDY | AT91_PMC_PCK2RDY |
+                         AT91_PMC_PCK3RDY,
+};
+
+static const struct at91_pmc_caps at91sam9260_caps = {
+       .available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_LOCKB |
+                         AT91_PMC_MCKRDY | AT91_PMC_PCK0RDY |
+                         AT91_PMC_PCK1RDY,
+};
+
+static const struct at91_pmc_caps at91sam9g45_caps = {
+       .available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_MCKRDY |
+                         AT91_PMC_LOCKU | AT91_PMC_PCK0RDY |
+                         AT91_PMC_PCK1RDY,
+};
+
+static const struct at91_pmc_caps at91sam9n12_caps = {
+       .available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_LOCKB |
+                         AT91_PMC_MCKRDY | AT91_PMC_PCK0RDY |
+                         AT91_PMC_PCK1RDY | AT91_PMC_MOSCSELS |
+                         AT91_PMC_MOSCRCS | AT91_PMC_CFDEV,
+};
+
+static const struct at91_pmc_caps at91sam9x5_caps = {
+       .available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_MCKRDY |
+                         AT91_PMC_LOCKU | AT91_PMC_PCK0RDY |
+                         AT91_PMC_PCK1RDY | AT91_PMC_MOSCSELS |
+                         AT91_PMC_MOSCRCS | AT91_PMC_CFDEV,
+};
+
+static const struct at91_pmc_caps sama5d3_caps = {
+       .available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_MCKRDY |
+                         AT91_PMC_LOCKU | AT91_PMC_PCK0RDY |
+                         AT91_PMC_PCK1RDY | AT91_PMC_PCK2RDY |
+                         AT91_PMC_MOSCSELS | AT91_PMC_MOSCRCS |
+                         AT91_PMC_CFDEV,
+};
+
+static struct at91_pmc *__init at91_pmc_init(struct device_node *np,
+                                            void __iomem *regbase, int virq,
+                                            const struct at91_pmc_caps *caps)
+{
+       struct at91_pmc *pmc;
+
+       if (!regbase || !virq ||  !caps)
+               return NULL;
+
+       at91_pmc_base = regbase;
+
+       pmc = kzalloc(sizeof(*pmc), GFP_KERNEL);
+       if (!pmc)
+               return NULL;
+
+       spin_lock_init(&pmc->lock);
+       pmc->regbase = regbase;
+       pmc->virq = virq;
+       pmc->caps = caps;
+
+       pmc->irqdomain = irq_domain_add_linear(np, 32, &pmc_irq_ops, pmc);
+
+       if (!pmc->irqdomain)
+               goto out_free_pmc;
+
+       pmc_write(pmc, AT91_PMC_IDR, 0xffffffff);
+       if (request_irq(pmc->virq, pmc_irq_handler, IRQF_SHARED, "pmc", pmc))
+               goto out_remove_irqdomain;
+
+       return pmc;
+
+out_remove_irqdomain:
+       irq_domain_remove(pmc->irqdomain);
+out_free_pmc:
+       kfree(pmc);
+
+       return NULL;
+}
+
+static const struct of_device_id pmc_clk_ids[] __initdata = {
+       /* Main clock */
+       {
+               .compatible = "atmel,at91rm9200-clk-main",
+               .data = of_at91rm9200_clk_main_setup,
+       },
+       /* PLL clocks */
+       {
+               .compatible = "atmel,at91rm9200-clk-pll",
+               .data = of_at91rm9200_clk_pll_setup,
+       },
+       {
+               .compatible = "atmel,at91sam9g45-clk-pll",
+               .data = of_at91sam9g45_clk_pll_setup,
+       },
+       {
+               .compatible = "atmel,at91sam9g20-clk-pllb",
+               .data = of_at91sam9g20_clk_pllb_setup,
+       },
+       {
+               .compatible = "atmel,sama5d3-clk-pll",
+               .data = of_sama5d3_clk_pll_setup,
+       },
+       {
+               .compatible = "atmel,at91sam9x5-clk-plldiv",
+               .data = of_at91sam9x5_clk_plldiv_setup,
+       },
+       /* Master clock */
+       {
+               .compatible = "atmel,at91rm9200-clk-master",
+               .data = of_at91rm9200_clk_master_setup,
+       },
+       {
+               .compatible = "atmel,at91sam9x5-clk-master",
+               .data = of_at91sam9x5_clk_master_setup,
+       },
+       /* System clocks */
+       {
+               .compatible = "atmel,at91rm9200-clk-system",
+               .data = of_at91rm9200_clk_sys_setup,
+       },
+       /* Peripheral clocks */
+       {
+               .compatible = "atmel,at91rm9200-clk-peripheral",
+               .data = of_at91rm9200_clk_periph_setup,
+       },
+       {
+               .compatible = "atmel,at91sam9x5-clk-peripheral",
+               .data = of_at91sam9x5_clk_periph_setup,
+       },
+       /* Programmable clocks */
+#if defined(CONFIG_AT91_PROGRAMMABLE_CLOCKS)
+       {
+               .compatible = "atmel,at91rm9200-clk-programmable",
+               .data = of_at91rm9200_clk_prog_setup,
+       },
+       {
+               .compatible = "atmel,at91sam9g45-clk-programmable",
+               .data = of_at91sam9g45_clk_prog_setup,
+       },
+       {
+               .compatible = "atmel,at91sam9x5-clk-programmable",
+               .data = of_at91sam9x5_clk_prog_setup,
+       },
+#endif
+       /* UTMI clock */
+#if defined(CONFIG_HAVE_AT91_UTMI)
+       {
+               .compatible = "atmel,at91sam9x5-clk-utmi",
+               .data = of_at91sam9x5_clk_utmi_setup,
+       },
+#endif
+       /* USB clock */
+#if defined(CONFIG_HAVE_AT91_USB_CLK)
+       {
+               .compatible = "atmel,at91rm9200-clk-usb",
+               .data = of_at91rm9200_clk_usb_setup,
+       },
+       {
+               .compatible = "atmel,at91sam9x5-clk-usb",
+               .data = of_at91sam9x5_clk_usb_setup,
+       },
+       {
+               .compatible = "atmel,at91sam9n12-clk-usb",
+               .data = of_at91sam9n12_clk_usb_setup,
+       },
+#endif
+       /* SMD clock */
+#if defined(CONFIG_HAVE_AT91_SMD)
+       {
+               .compatible = "atmel,at91sam9x5-clk-smd",
+               .data = of_at91sam9x5_clk_smd_setup,
+       },
+#endif
+       { /*sentinel*/ }
+};
+
+static void __init of_at91_pmc_setup(struct device_node *np,
+                                    const struct at91_pmc_caps *caps)
+{
+       struct at91_pmc *pmc;
+       struct device_node *childnp;
+       void (*clk_setup)(struct device_node *, struct at91_pmc *);
+       const struct of_device_id *clk_id;
+       void __iomem *regbase = of_iomap(np, 0);
+       int virq;
+
+       if (!regbase)
+               return;
+
+       virq = irq_of_parse_and_map(np, 0);
+       if (!virq)
+               return;
+
+       pmc = at91_pmc_init(np, regbase, virq, caps);
+       if (!pmc)
+               return;
+       for_each_child_of_node(np, childnp) {
+               clk_id = of_match_node(pmc_clk_ids, childnp);
+               if (!clk_id)
+                       continue;
+               clk_setup = clk_id->data;
+               clk_setup(childnp, pmc);
+       }
+}
+
+static void __init of_at91rm9200_pmc_setup(struct device_node *np)
+{
+       of_at91_pmc_setup(np, &at91rm9200_caps);
+}
+CLK_OF_DECLARE(at91rm9200_clk_pmc, "atmel,at91rm9200-pmc",
+              of_at91rm9200_pmc_setup);
+
+static void __init of_at91sam9260_pmc_setup(struct device_node *np)
+{
+       of_at91_pmc_setup(np, &at91sam9260_caps);
+}
+CLK_OF_DECLARE(at91sam9260_clk_pmc, "atmel,at91sam9260-pmc",
+              of_at91sam9260_pmc_setup);
+
+static void __init of_at91sam9g45_pmc_setup(struct device_node *np)
+{
+       of_at91_pmc_setup(np, &at91sam9g45_caps);
+}
+CLK_OF_DECLARE(at91sam9g45_clk_pmc, "atmel,at91sam9g45-pmc",
+              of_at91sam9g45_pmc_setup);
+
+static void __init of_at91sam9n12_pmc_setup(struct device_node *np)
+{
+       of_at91_pmc_setup(np, &at91sam9n12_caps);
+}
+CLK_OF_DECLARE(at91sam9n12_clk_pmc, "atmel,at91sam9n12-pmc",
+              of_at91sam9n12_pmc_setup);
+
+static void __init of_at91sam9x5_pmc_setup(struct device_node *np)
+{
+       of_at91_pmc_setup(np, &at91sam9x5_caps);
+}
+CLK_OF_DECLARE(at91sam9x5_clk_pmc, "atmel,at91sam9x5-pmc",
+              of_at91sam9x5_pmc_setup);
+
+static void __init of_sama5d3_pmc_setup(struct device_node *np)
+{
+       of_at91_pmc_setup(np, &sama5d3_caps);
+}
+CLK_OF_DECLARE(sama5d3_clk_pmc, "atmel,sama5d3-pmc",
+              of_sama5d3_pmc_setup);
diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h
new file mode 100644 (file)
index 0000000..ba8d142
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * drivers/clk/at91/pmc.h
+ *
+ *  Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.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.
+ */
+
+#ifndef __PMC_H_
+#define __PMC_H_
+
+#include <linux/io.h>
+#include <linux/irqdomain.h>
+#include <linux/spinlock.h>
+
+struct clk_range {
+       unsigned long min;
+       unsigned long max;
+};
+
+#define CLK_RANGE(MIN, MAX) {.min = MIN, .max = MAX,}
+
+struct at91_pmc_caps {
+       u32 available_irqs;
+};
+
+struct at91_pmc {
+       void __iomem *regbase;
+       int virq;
+       spinlock_t lock;
+       const struct at91_pmc_caps *caps;
+       struct irq_domain *irqdomain;
+};
+
+static inline void pmc_lock(struct at91_pmc *pmc)
+{
+       spin_lock(&pmc->lock);
+}
+
+static inline void pmc_unlock(struct at91_pmc *pmc)
+{
+       spin_unlock(&pmc->lock);
+}
+
+static inline u32 pmc_read(struct at91_pmc *pmc, int offset)
+{
+       return readl(pmc->regbase + offset);
+}
+
+static inline void pmc_write(struct at91_pmc *pmc, int offset, u32 value)
+{
+       writel(value, pmc->regbase + offset);
+}
+
+int of_at91_get_clk_range(struct device_node *np, const char *propname,
+                         struct clk_range *range);
+
+extern void __init of_at91rm9200_clk_main_setup(struct device_node *np,
+                                               struct at91_pmc *pmc);
+
+extern void __init of_at91rm9200_clk_pll_setup(struct device_node *np,
+                                              struct at91_pmc *pmc);
+extern void __init of_at91sam9g45_clk_pll_setup(struct device_node *np,
+                                               struct at91_pmc *pmc);
+extern void __init of_at91sam9g20_clk_pllb_setup(struct device_node *np,
+                                                struct at91_pmc *pmc);
+extern void __init of_sama5d3_clk_pll_setup(struct device_node *np,
+                                           struct at91_pmc *pmc);
+extern void __init of_at91sam9x5_clk_plldiv_setup(struct device_node *np,
+                                                 struct at91_pmc *pmc);
+
+extern void __init of_at91rm9200_clk_master_setup(struct device_node *np,
+                                                 struct at91_pmc *pmc);
+extern void __init of_at91sam9x5_clk_master_setup(struct device_node *np,
+                                                 struct at91_pmc *pmc);
+
+extern void __init of_at91rm9200_clk_sys_setup(struct device_node *np,
+                                              struct at91_pmc *pmc);
+
+extern void __init of_at91rm9200_clk_periph_setup(struct device_node *np,
+                                                 struct at91_pmc *pmc);
+extern void __init of_at91sam9x5_clk_periph_setup(struct device_node *np,
+                                                 struct at91_pmc *pmc);
+
+#if defined(CONFIG_AT91_PROGRAMMABLE_CLOCKS)
+extern void __init of_at91rm9200_clk_prog_setup(struct device_node *np,
+                                               struct at91_pmc *pmc);
+extern void __init of_at91sam9g45_clk_prog_setup(struct device_node *np,
+                                                struct at91_pmc *pmc);
+extern void __init of_at91sam9x5_clk_prog_setup(struct device_node *np,
+                                               struct at91_pmc *pmc);
+#endif
+
+#if defined(CONFIG_HAVE_AT91_UTMI)
+extern void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np,
+                                               struct at91_pmc *pmc);
+#endif
+
+#if defined(CONFIG_HAVE_AT91_USB_CLK)
+extern void __init of_at91rm9200_clk_usb_setup(struct device_node *np,
+                                              struct at91_pmc *pmc);
+extern void __init of_at91sam9x5_clk_usb_setup(struct device_node *np,
+                                              struct at91_pmc *pmc);
+extern void __init of_at91sam9n12_clk_usb_setup(struct device_node *np,
+                                               struct at91_pmc *pmc);
+#endif
+
+#if defined(CONFIG_HAVE_AT91_SMD)
+extern void __init of_at91sam9x5_clk_smd_setup(struct device_node *np,
+                                              struct at91_pmc *pmc);
+#endif
+
+#endif /* __PMC_H_ */
index 0b0f3e729cf7ca5ec18c322a6322ab2001a55a70..c339b829d3e33fe60af81cbfb0317cecdb12add5 100644 (file)
@@ -4,15 +4,20 @@ config MVEBU_CLK_COMMON
 config MVEBU_CLK_CPU
        bool
 
+config MVEBU_CLK_COREDIV
+       bool
+
 config ARMADA_370_CLK
        bool
        select MVEBU_CLK_COMMON
        select MVEBU_CLK_CPU
+       select MVEBU_CLK_COREDIV
 
 config ARMADA_XP_CLK
        bool
        select MVEBU_CLK_COMMON
        select MVEBU_CLK_CPU
+       select MVEBU_CLK_COREDIV
 
 config DOVE_CLK
        bool
index 1c7e70c63fb26b80145b5e506015874b5da16b64..21bbfb4a9f42e9edcda25a0705ff1f9f701ac8bd 100644 (file)
@@ -1,5 +1,6 @@
 obj-$(CONFIG_MVEBU_CLK_COMMON) += common.o
 obj-$(CONFIG_MVEBU_CLK_CPU)    += clk-cpu.o
+obj-$(CONFIG_MVEBU_CLK_COREDIV)        += clk-corediv.o
 
 obj-$(CONFIG_ARMADA_370_CLK)   += armada-370.o
 obj-$(CONFIG_ARMADA_XP_CLK)    += armada-xp.o
diff --git a/drivers/clk/mvebu/clk-corediv.c b/drivers/clk/mvebu/clk-corediv.c
new file mode 100644 (file)
index 0000000..7162615
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * MVEBU Core divider clock
+ *
+ * Copyright (C) 2013 Marvell
+ *
+ * Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "common.h"
+
+#define CORE_CLK_DIV_RATIO_MASK                0xff
+#define CORE_CLK_DIV_RATIO_RELOAD      BIT(8)
+#define CORE_CLK_DIV_ENABLE_OFFSET     24
+#define CORE_CLK_DIV_RATIO_OFFSET      0x8
+
+struct clk_corediv_desc {
+       unsigned int mask;
+       unsigned int offset;
+       unsigned int fieldbit;
+};
+
+struct clk_corediv {
+       struct clk_hw hw;
+       void __iomem *reg;
+       struct clk_corediv_desc desc;
+       spinlock_t lock;
+};
+
+static struct clk_onecell_data clk_data;
+
+static const struct clk_corediv_desc mvebu_corediv_desc[] __initconst = {
+       { .mask = 0x3f, .offset = 8, .fieldbit = 1 }, /* NAND clock */
+};
+
+#define to_corediv_clk(p) container_of(p, struct clk_corediv, hw)
+
+static int clk_corediv_is_enabled(struct clk_hw *hwclk)
+{
+       struct clk_corediv *corediv = to_corediv_clk(hwclk);
+       struct clk_corediv_desc *desc = &corediv->desc;
+       u32 enable_mask = BIT(desc->fieldbit) << CORE_CLK_DIV_ENABLE_OFFSET;
+
+       return !!(readl(corediv->reg) & enable_mask);
+}
+
+static int clk_corediv_enable(struct clk_hw *hwclk)
+{
+       struct clk_corediv *corediv = to_corediv_clk(hwclk);
+       struct clk_corediv_desc *desc = &corediv->desc;
+       unsigned long flags = 0;
+       u32 reg;
+
+       spin_lock_irqsave(&corediv->lock, flags);
+
+       reg = readl(corediv->reg);
+       reg |= (BIT(desc->fieldbit) << CORE_CLK_DIV_ENABLE_OFFSET);
+       writel(reg, corediv->reg);
+
+       spin_unlock_irqrestore(&corediv->lock, flags);
+
+       return 0;
+}
+
+static void clk_corediv_disable(struct clk_hw *hwclk)
+{
+       struct clk_corediv *corediv = to_corediv_clk(hwclk);
+       struct clk_corediv_desc *desc = &corediv->desc;
+       unsigned long flags = 0;
+       u32 reg;
+
+       spin_lock_irqsave(&corediv->lock, flags);
+
+       reg = readl(corediv->reg);
+       reg &= ~(BIT(desc->fieldbit) << CORE_CLK_DIV_ENABLE_OFFSET);
+       writel(reg, corediv->reg);
+
+       spin_unlock_irqrestore(&corediv->lock, flags);
+}
+
+static unsigned long clk_corediv_recalc_rate(struct clk_hw *hwclk,
+                                        unsigned long parent_rate)
+{
+       struct clk_corediv *corediv = to_corediv_clk(hwclk);
+       struct clk_corediv_desc *desc = &corediv->desc;
+       u32 reg, div;
+
+       reg = readl(corediv->reg + CORE_CLK_DIV_RATIO_OFFSET);
+       div = (reg >> desc->offset) & desc->mask;
+       return parent_rate / div;
+}
+
+static long clk_corediv_round_rate(struct clk_hw *hwclk, unsigned long rate,
+                              unsigned long *parent_rate)
+{
+       /* Valid ratio are 1:4, 1:5, 1:6 and 1:8 */
+       u32 div;
+
+       div = *parent_rate / rate;
+       if (div < 4)
+               div = 4;
+       else if (div > 6)
+               div = 8;
+
+       return *parent_rate / div;
+}
+
+static int clk_corediv_set_rate(struct clk_hw *hwclk, unsigned long rate,
+                           unsigned long parent_rate)
+{
+       struct clk_corediv *corediv = to_corediv_clk(hwclk);
+       struct clk_corediv_desc *desc = &corediv->desc;
+       unsigned long flags = 0;
+       u32 reg, div;
+
+       div = parent_rate / rate;
+
+       spin_lock_irqsave(&corediv->lock, flags);
+
+       /* Write new divider to the divider ratio register */
+       reg = readl(corediv->reg + CORE_CLK_DIV_RATIO_OFFSET);
+       reg &= ~(desc->mask << desc->offset);
+       reg |= (div & desc->mask) << desc->offset;
+       writel(reg, corediv->reg + CORE_CLK_DIV_RATIO_OFFSET);
+
+       /* Set reload-force for this clock */
+       reg = readl(corediv->reg) | BIT(desc->fieldbit);
+       writel(reg, corediv->reg);
+
+       /* Now trigger the clock update */
+       reg = readl(corediv->reg) | CORE_CLK_DIV_RATIO_RELOAD;
+       writel(reg, corediv->reg);
+
+       /*
+        * Wait for clocks to settle down, and then clear all the
+        * ratios request and the reload request.
+        */
+       udelay(1000);
+       reg &= ~(CORE_CLK_DIV_RATIO_MASK | CORE_CLK_DIV_RATIO_RELOAD);
+       writel(reg, corediv->reg);
+       udelay(1000);
+
+       spin_unlock_irqrestore(&corediv->lock, flags);
+
+       return 0;
+}
+
+static const struct clk_ops corediv_ops = {
+       .enable = clk_corediv_enable,
+       .disable = clk_corediv_disable,
+       .is_enabled = clk_corediv_is_enabled,
+       .recalc_rate = clk_corediv_recalc_rate,
+       .round_rate = clk_corediv_round_rate,
+       .set_rate = clk_corediv_set_rate,
+};
+
+static void __init mvebu_corediv_clk_init(struct device_node *node)
+{
+       struct clk_init_data init;
+       struct clk_corediv *corediv;
+       struct clk **clks;
+       void __iomem *base;
+       const char *parent_name;
+       const char *clk_name;
+       int i;
+
+       base = of_iomap(node, 0);
+       if (WARN_ON(!base))
+               return;
+
+       parent_name = of_clk_get_parent_name(node, 0);
+
+       clk_data.clk_num = ARRAY_SIZE(mvebu_corediv_desc);
+
+       /* clks holds the clock array */
+       clks = kcalloc(clk_data.clk_num, sizeof(struct clk *),
+                               GFP_KERNEL);
+       if (WARN_ON(!clks))
+               goto err_unmap;
+       /* corediv holds the clock specific array */
+       corediv = kcalloc(clk_data.clk_num, sizeof(struct clk_corediv),
+                               GFP_KERNEL);
+       if (WARN_ON(!corediv))
+               goto err_free_clks;
+
+       spin_lock_init(&corediv->lock);
+
+       for (i = 0; i < clk_data.clk_num; i++) {
+               of_property_read_string_index(node, "clock-output-names",
+                                             i, &clk_name);
+               init.num_parents = 1;
+               init.parent_names = &parent_name;
+               init.name = clk_name;
+               init.ops = &corediv_ops;
+               init.flags = 0;
+
+               corediv[i].desc = mvebu_corediv_desc[i];
+               corediv[i].reg = base;
+               corediv[i].hw.init = &init;
+
+               clks[i] = clk_register(NULL, &corediv[i].hw);
+               WARN_ON(IS_ERR(clks[i]));
+       }
+
+       clk_data.clks = clks;
+       of_clk_add_provider(node, of_clk_src_onecell_get, &clk_data);
+       return;
+
+err_free_clks:
+       kfree(clks);
+err_unmap:
+       iounmap(base);
+}
+CLK_OF_DECLARE(mvebu_corediv_clk, "marvell,armada-370-corediv-clock",
+              mvebu_corediv_clk_init);
index 1466865b0743bf2110b74a6832acbef832743b77..8ebf757d29e2d0885791442bfbac5efd586db22b 100644 (file)
@@ -101,7 +101,7 @@ static const struct clk_ops cpu_ops = {
        .set_rate = clk_cpu_set_rate,
 };
 
-void __init of_cpu_clk_setup(struct device_node *node)
+static void __init of_cpu_clk_setup(struct device_node *node)
 {
        struct cpu_clk *cpuclk;
        void __iomem *clock_complex_base = of_iomap(node, 0);
index 7d2c84265947a1b2e85ebf92c8c6e9cb8d9303f8..8e27aee6887eed36c2ebaf7c82bd705672ab5784 100644 (file)
@@ -331,8 +331,8 @@ static struct samsung_clock_alias s3c64xx_clock_aliases[] = {
        ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "mmc_busclk.0"),
        ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "hsmmc"),
        ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "mmc_busclk.0"),
-       ALIAS(HCLK_DMA1, NULL, "dma1"),
-       ALIAS(HCLK_DMA0, NULL, "dma0"),
+       ALIAS(HCLK_DMA1, "dma-pl080s.1", "apb_pclk"),
+       ALIAS(HCLK_DMA0, "dma-pl080s.0", "apb_pclk"),
        ALIAS(HCLK_CAMIF, "s3c-camif", "camif"),
        ALIAS(HCLK_LCD, "s3c-fb", "lcd"),
        ALIAS(PCLK_SPI1, "s3c6410-spi.1", "spi"),
index bdb953e15d2a88d201c3997ca86e80f15a00e5cf..5c07a56962dbcffc038b81eb09305e61ee1d83e6 100644 (file)
@@ -87,6 +87,7 @@ config ARM_ARCH_TIMER
 config ARM_ARCH_TIMER_EVTSTREAM
        bool "Support for ARM architected timer event stream generation"
        default y if ARM_ARCH_TIMER
+       depends on ARM_ARCH_TIMER
        help
          This option enables support for event stream generation based on
          the ARM architected timer. It is used for waking up CPUs executing
index 62b0de6a18370fade34eca20205557bd5871cc3a..48f76bc05da0d8fb5b5515cd6c919a9cf3c373f6 100644 (file)
@@ -71,6 +71,10 @@ enum {
        MCT_L1_IRQ,
        MCT_L2_IRQ,
        MCT_L3_IRQ,
+       MCT_L4_IRQ,
+       MCT_L5_IRQ,
+       MCT_L6_IRQ,
+       MCT_L7_IRQ,
        MCT_NR_IRQS,
 };
 
index ed7b73b508e096bb06a3e87a1843aa813f835430..f00b5c9ce8b6dbc9599dc921eeea07e5db4d6423 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/jiffies.h>
 #include <linux/delay.h>
 #include <linux/err.h>
-#include <linux/platform_data/clocksource-nomadik-mtu.h>
 #include <linux/sched_clock.h>
 #include <asm/mach/time.h>
 
@@ -103,7 +102,7 @@ static int nmdk_clkevt_next(unsigned long evt, struct clock_event_device *ev)
        return 0;
 }
 
-void nmdk_clkevt_reset(void)
+static void nmdk_clkevt_reset(void)
 {
        if (clkevt_periodic) {
                /* Timer: configure load and background-load, and fire it up */
@@ -144,7 +143,7 @@ static void nmdk_clkevt_mode(enum clock_event_mode mode,
        }
 }
 
-void nmdk_clksrc_reset(void)
+static void nmdk_clksrc_reset(void)
 {
        /* Disable */
        writel(0, mtu_base + MTU_CR(0));
@@ -192,8 +191,8 @@ static struct irqaction nmdk_timer_irq = {
        .dev_id         = &nmdk_clkevt,
 };
 
-static void __init __nmdk_timer_init(void __iomem *base, int irq,
-                                    struct clk *pclk, struct clk *clk)
+static void __init nmdk_timer_init(void __iomem *base, int irq,
+                                  struct clk *pclk, struct clk *clk)
 {
        unsigned long rate;
 
@@ -245,18 +244,6 @@ static void __init __nmdk_timer_init(void __iomem *base, int irq,
        register_current_timer_delay(&mtu_delay_timer);
 }
 
-void __init nmdk_timer_init(void __iomem *base, int irq)
-{
-       struct clk *clk0, *pclk0;
-
-       pclk0 = clk_get_sys("mtu0", "apb_pclk");
-       BUG_ON(IS_ERR(pclk0));
-       clk0 = clk_get_sys("mtu0", NULL);
-       BUG_ON(IS_ERR(clk0));
-
-       __nmdk_timer_init(base, irq, pclk0, clk0);
-}
-
 static void __init nmdk_timer_of_init(struct device_node *node)
 {
        struct clk *pclk;
@@ -280,7 +267,7 @@ static void __init nmdk_timer_of_init(struct device_node *node)
        if (irq <= 0)
                panic("Can't parse IRQ");
 
-       __nmdk_timer_init(base, irq, pclk, clk);
+       nmdk_timer_init(base, irq, pclk, clk);
 }
 CLOCKSOURCE_OF_DECLARE(nomadik_mtu, "st,nomadik-mtu",
                       nmdk_timer_of_init);
index 4aac9ee0d0c054a7ba953b17ac3272946af7b47d..3cf12834681e8335fa7f49dd032eb3cb57ad128a 100644 (file)
@@ -313,8 +313,20 @@ static int sh_mtu2_setup(struct sh_mtu2_priv *p, struct platform_device *pdev)
                goto err1;
        }
 
-       return sh_mtu2_register(p, (char *)dev_name(&p->pdev->dev),
-                               cfg->clockevent_rating);
+       ret = clk_prepare(p->clk);
+       if (ret < 0)
+               goto err2;
+
+       ret = sh_mtu2_register(p, (char *)dev_name(&p->pdev->dev),
+                              cfg->clockevent_rating);
+       if (ret < 0)
+               goto err3;
+
+       return 0;
+ err3:
+       clk_unprepare(p->clk);
+ err2:
+       clk_put(p->clk);
  err1:
        iounmap(p->mapbase);
  err0:
index 78b8dae49628cce42fb45ebdff2b32ece5045a52..63557cda0a7d599e352c402f2db23b348481e365 100644 (file)
@@ -472,12 +472,26 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev)
                ret = PTR_ERR(p->clk);
                goto err1;
        }
+
+       ret = clk_prepare(p->clk);
+       if (ret < 0)
+               goto err2;
+
        p->cs_enabled = false;
        p->enable_count = 0;
 
-       return sh_tmu_register(p, (char *)dev_name(&p->pdev->dev),
-                              cfg->clockevent_rating,
-                              cfg->clocksource_rating);
+       ret = sh_tmu_register(p, (char *)dev_name(&p->pdev->dev),
+                             cfg->clockevent_rating,
+                             cfg->clocksource_rating);
+       if (ret < 0)
+               goto err3;
+
+       return 0;
+
+ err3:
+       clk_unprepare(p->clk);
+ err2:
+       clk_put(p->clk);
  err1:
        iounmap(p->mapbase);
  err0:
index 856ad80418ae5b92610e23e98922f0ff6505d34e..7c03dd84f66a35cabbde683eece8e23f73585743 100644 (file)
@@ -58,7 +58,7 @@ static int at32_set_target(struct cpufreq_policy *policy, unsigned int index)
        return 0;
 }
 
-static int __init at32_cpufreq_driver_init(struct cpufreq_policy *policy)
+static int at32_cpufreq_driver_init(struct cpufreq_policy *policy)
 {
        unsigned int frequency, rate, min_freq;
        int retval, steps, i;
index d4585ce2346cf187a0c5511fafdd7ac08204f1bb..0faf756f6197d216fbb8ddf6d276fdf7f86d3b7f 100644 (file)
@@ -44,7 +44,7 @@ static int cpu0_set_target(struct cpufreq_policy *policy, unsigned int index)
        int ret;
 
        freq_Hz = clk_round_rate(cpu_clk, freq_table[index].frequency * 1000);
-       if (freq_Hz < 0)
+       if (freq_Hz <= 0)
                freq_Hz = freq_table[index].frequency * 1000;
 
        freq_exact = freq_Hz;
index d02ccd19c9c4f20e4b5a3cfdcf1035b0c15c97fd..45ea4c094542d677bf2edd83f642b0173ed90541 100644 (file)
@@ -138,7 +138,7 @@ static int spear_cpufreq_target(struct cpufreq_policy *policy,
        }
 
        newfreq = clk_round_rate(srcclk, newfreq * mult);
-       if (newfreq < 0) {
+       if (newfreq <= 0) {
                pr_err("clk_round_rate failed for cpu src clock\n");
                return newfreq;
        }
index 2a991e468f78190e1dfab933225d33cfef69d710..a55e68f2cfc8bfad02a85957c9d9ddc55823c6fe 100644 (file)
@@ -400,7 +400,7 @@ EXPORT_SYMBOL_GPL(cpuidle_register_device);
  */
 void cpuidle_unregister_device(struct cpuidle_device *dev)
 {
-       if (dev->registered == 0)
+       if (!dev || dev->registered == 0)
                return;
 
        cpuidle_pause_and_lock();
index f4fd837bcb82a82530485f1f54a55dc75e362fdf..4954d7579c5b8656d647f4139c152f7da2f32ead 100644 (file)
@@ -399,4 +399,16 @@ config CRYPTO_DEV_ATMEL_SHA
          To compile this driver as a module, choose M here: the module
          will be called atmel-sha.
 
+config CRYPTO_DEV_CCP
+       bool "Support for AMD Cryptographic Coprocessor"
+       depends on X86
+       default n
+       help
+         The AMD Cryptographic Coprocessor provides hardware support
+         for encryption, hashing and related operations.
+
+if CRYPTO_DEV_CCP
+       source "drivers/crypto/ccp/Kconfig"
+endif
+
 endif # CRYPTO_HW
index b4946ddd25505ad454960616f792de2e9e71e1ca..8a6c86a2e2c9dc671f32f61258d2cd2865fca8da 100644 (file)
@@ -22,3 +22,4 @@ obj-$(CONFIG_CRYPTO_DEV_NX) += nx/
 obj-$(CONFIG_CRYPTO_DEV_ATMEL_AES) += atmel-aes.o
 obj-$(CONFIG_CRYPTO_DEV_ATMEL_TDES) += atmel-tdes.o
 obj-$(CONFIG_CRYPTO_DEV_ATMEL_SHA) += atmel-sha.o
+obj-$(CONFIG_CRYPTO_DEV_CCP) += ccp/
index 4f44b71b9e24a14a6bc5f99c37e4184970dbb035..4cf5dec826e1e283aa8b5991cd1a4b80a0dbdba6 100644 (file)
@@ -818,7 +818,7 @@ static void aead_decrypt_done(struct device *jrdev, u32 *desc, u32 err,
                       ivsize, 1);
        print_hex_dump(KERN_ERR, "dst    @"__stringify(__LINE__)": ",
                       DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->dst),
-                      req->cryptlen, 1);
+                      req->cryptlen - ctx->authsize, 1);
 #endif
 
        if (err) {
@@ -972,12 +972,9 @@ static void init_aead_job(u32 *sh_desc, dma_addr_t ptr,
                                 (edesc->src_nents ? : 1);
                in_options = LDST_SGF;
        }
-       if (encrypt)
-               append_seq_in_ptr(desc, src_dma, req->assoclen + ivsize +
-                                 req->cryptlen - authsize, in_options);
-       else
-               append_seq_in_ptr(desc, src_dma, req->assoclen + ivsize +
-                                 req->cryptlen, in_options);
+
+       append_seq_in_ptr(desc, src_dma, req->assoclen + ivsize + req->cryptlen,
+                         in_options);
 
        if (likely(req->src == req->dst)) {
                if (all_contig) {
@@ -998,7 +995,8 @@ static void init_aead_job(u32 *sh_desc, dma_addr_t ptr,
                }
        }
        if (encrypt)
-               append_seq_out_ptr(desc, dst_dma, req->cryptlen, out_options);
+               append_seq_out_ptr(desc, dst_dma, req->cryptlen + authsize,
+                                  out_options);
        else
                append_seq_out_ptr(desc, dst_dma, req->cryptlen - authsize,
                                   out_options);
@@ -1048,8 +1046,8 @@ static void init_aead_giv_job(u32 *sh_desc, dma_addr_t ptr,
                sec4_sg_index += edesc->assoc_nents + 1 + edesc->src_nents;
                in_options = LDST_SGF;
        }
-       append_seq_in_ptr(desc, src_dma, req->assoclen + ivsize +
-                         req->cryptlen - authsize, in_options);
+       append_seq_in_ptr(desc, src_dma, req->assoclen + ivsize + req->cryptlen,
+                         in_options);
 
        if (contig & GIV_DST_CONTIG) {
                dst_dma = edesc->iv_dma;
@@ -1066,7 +1064,8 @@ static void init_aead_giv_job(u32 *sh_desc, dma_addr_t ptr,
                }
        }
 
-       append_seq_out_ptr(desc, dst_dma, ivsize + req->cryptlen, out_options);
+       append_seq_out_ptr(desc, dst_dma, ivsize + req->cryptlen + authsize,
+                          out_options);
 }
 
 /*
@@ -1130,7 +1129,8 @@ static void init_ablkcipher_job(u32 *sh_desc, dma_addr_t ptr,
  * allocate and map the aead extended descriptor
  */
 static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
-                                          int desc_bytes, bool *all_contig_ptr)
+                                          int desc_bytes, bool *all_contig_ptr,
+                                          bool encrypt)
 {
        struct crypto_aead *aead = crypto_aead_reqtfm(req);
        struct caam_ctx *ctx = crypto_aead_ctx(aead);
@@ -1145,12 +1145,22 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
        bool assoc_chained = false, src_chained = false, dst_chained = false;
        int ivsize = crypto_aead_ivsize(aead);
        int sec4_sg_index, sec4_sg_len = 0, sec4_sg_bytes;
+       unsigned int authsize = ctx->authsize;
 
        assoc_nents = sg_count(req->assoc, req->assoclen, &assoc_chained);
-       src_nents = sg_count(req->src, req->cryptlen, &src_chained);
 
-       if (unlikely(req->dst != req->src))
-               dst_nents = sg_count(req->dst, req->cryptlen, &dst_chained);
+       if (unlikely(req->dst != req->src)) {
+               src_nents = sg_count(req->src, req->cryptlen, &src_chained);
+               dst_nents = sg_count(req->dst,
+                                    req->cryptlen +
+                                       (encrypt ? authsize : (-authsize)),
+                                    &dst_chained);
+       } else {
+               src_nents = sg_count(req->src,
+                                    req->cryptlen +
+                                       (encrypt ? authsize : 0),
+                                    &src_chained);
+       }
 
        sgc = dma_map_sg_chained(jrdev, req->assoc, assoc_nents ? : 1,
                                 DMA_TO_DEVICE, assoc_chained);
@@ -1234,11 +1244,9 @@ static int aead_encrypt(struct aead_request *req)
        u32 *desc;
        int ret = 0;
 
-       req->cryptlen += ctx->authsize;
-
        /* allocate extended descriptor */
        edesc = aead_edesc_alloc(req, DESC_JOB_IO_LEN *
-                                CAAM_CMD_SZ, &all_contig);
+                                CAAM_CMD_SZ, &all_contig, true);
        if (IS_ERR(edesc))
                return PTR_ERR(edesc);
 
@@ -1275,7 +1283,7 @@ static int aead_decrypt(struct aead_request *req)
 
        /* allocate extended descriptor */
        edesc = aead_edesc_alloc(req, DESC_JOB_IO_LEN *
-                                CAAM_CMD_SZ, &all_contig);
+                                CAAM_CMD_SZ, &all_contig, false);
        if (IS_ERR(edesc))
                return PTR_ERR(edesc);
 
@@ -1332,7 +1340,8 @@ static struct aead_edesc *aead_giv_edesc_alloc(struct aead_givcrypt_request
        src_nents = sg_count(req->src, req->cryptlen, &src_chained);
 
        if (unlikely(req->dst != req->src))
-               dst_nents = sg_count(req->dst, req->cryptlen, &dst_chained);
+               dst_nents = sg_count(req->dst, req->cryptlen + ctx->authsize,
+                                    &dst_chained);
 
        sgc = dma_map_sg_chained(jrdev, req->assoc, assoc_nents ? : 1,
                                 DMA_TO_DEVICE, assoc_chained);
@@ -1426,8 +1435,6 @@ static int aead_givencrypt(struct aead_givcrypt_request *areq)
        u32 *desc;
        int ret = 0;
 
-       req->cryptlen += ctx->authsize;
-
        /* allocate extended descriptor */
        edesc = aead_giv_edesc_alloc(areq, DESC_JOB_IO_LEN *
                                     CAAM_CMD_SZ, &contig);
index d23356d20e1ca430e5993aaf77b88b39b82fe651..1d80bd3636c5b1f2cf4dc078d4934e64befc7f68 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include <linux/of_irq.h>
+#include <linux/of_address.h>
 
 #include "compat.h"
 #include "regs.h"
diff --git a/drivers/crypto/ccp/Kconfig b/drivers/crypto/ccp/Kconfig
new file mode 100644 (file)
index 0000000..335ed5c
--- /dev/null
@@ -0,0 +1,23 @@
+config CRYPTO_DEV_CCP_DD
+       tristate "Cryptographic Coprocessor device driver"
+       depends on CRYPTO_DEV_CCP
+       default m
+       help
+         Provides the interface to use the AMD Cryptographic Coprocessor
+         which can be used to accelerate or offload encryption operations
+         such as SHA, AES and more. If you choose 'M' here, this module
+         will be called ccp.
+
+config CRYPTO_DEV_CCP_CRYPTO
+       tristate "Encryption and hashing acceleration support"
+       depends on CRYPTO_DEV_CCP_DD
+       default m
+       select CRYPTO_ALGAPI
+       select CRYPTO_HASH
+       select CRYPTO_BLKCIPHER
+       select CRYPTO_AUTHENC
+       help
+         Support for using the cryptographic API with the AMD Cryptographic
+         Coprocessor. This module supports acceleration and offload of SHA
+         and AES algorithms.  If you choose 'M' here, this module will be
+         called ccp_crypto.
diff --git a/drivers/crypto/ccp/Makefile b/drivers/crypto/ccp/Makefile
new file mode 100644 (file)
index 0000000..d3505a0
--- /dev/null
@@ -0,0 +1,10 @@
+obj-$(CONFIG_CRYPTO_DEV_CCP_DD) += ccp.o
+ccp-objs := ccp-dev.o ccp-ops.o
+ccp-objs += ccp-pci.o
+
+obj-$(CONFIG_CRYPTO_DEV_CCP_CRYPTO) += ccp-crypto.o
+ccp-crypto-objs := ccp-crypto-main.o \
+                  ccp-crypto-aes.o \
+                  ccp-crypto-aes-cmac.o \
+                  ccp-crypto-aes-xts.o \
+                  ccp-crypto-sha.o
diff --git a/drivers/crypto/ccp/ccp-crypto-aes-cmac.c b/drivers/crypto/ccp/ccp-crypto-aes-cmac.c
new file mode 100644 (file)
index 0000000..5b9cd98
--- /dev/null
@@ -0,0 +1,355 @@
+/*
+ * AMD Cryptographic Coprocessor (CCP) AES CMAC crypto API support
+ *
+ * Copyright (C) 2013 Advanced Micro Devices, Inc.
+ *
+ * Author: Tom Lendacky <thomas.lendacky@amd.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/module.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/scatterlist.h>
+#include <linux/crypto.h>
+#include <crypto/algapi.h>
+#include <crypto/aes.h>
+#include <crypto/hash.h>
+#include <crypto/internal/hash.h>
+#include <crypto/scatterwalk.h>
+
+#include "ccp-crypto.h"
+
+
+static int ccp_aes_cmac_complete(struct crypto_async_request *async_req,
+                                int ret)
+{
+       struct ahash_request *req = ahash_request_cast(async_req);
+       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+       struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx(req);
+       unsigned int digest_size = crypto_ahash_digestsize(tfm);
+
+       if (ret)
+               goto e_free;
+
+       if (rctx->hash_rem) {
+               /* Save remaining data to buffer */
+               scatterwalk_map_and_copy(rctx->buf, rctx->cmd.u.aes.src,
+                                        rctx->hash_cnt, rctx->hash_rem, 0);
+               rctx->buf_count = rctx->hash_rem;
+       } else
+               rctx->buf_count = 0;
+
+       memcpy(req->result, rctx->iv, digest_size);
+
+e_free:
+       sg_free_table(&rctx->data_sg);
+
+       return ret;
+}
+
+static int ccp_do_cmac_update(struct ahash_request *req, unsigned int nbytes,
+                             unsigned int final)
+{
+       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+       struct ccp_ctx *ctx = crypto_ahash_ctx(tfm);
+       struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx(req);
+       struct scatterlist *sg, *cmac_key_sg = NULL;
+       unsigned int block_size =
+               crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
+       unsigned int len, need_pad, sg_count;
+       int ret;
+
+       if (!ctx->u.aes.key_len) {
+               pr_err("AES key not set\n");
+               return -EINVAL;
+       }
+
+       if (nbytes)
+               rctx->null_msg = 0;
+
+       if (!final && ((nbytes + rctx->buf_count) <= block_size)) {
+               scatterwalk_map_and_copy(rctx->buf + rctx->buf_count, req->src,
+                                        0, nbytes, 0);
+               rctx->buf_count += nbytes;
+
+               return 0;
+       }
+
+       len = rctx->buf_count + nbytes;
+
+       rctx->final = final;
+       rctx->hash_cnt = final ? len : len & ~(block_size - 1);
+       rctx->hash_rem = final ?   0 : len &  (block_size - 1);
+       if (!final && (rctx->hash_cnt == len)) {
+               /* CCP can't do zero length final, so keep some data around */
+               rctx->hash_cnt -= block_size;
+               rctx->hash_rem = block_size;
+       }
+
+       if (final && (rctx->null_msg || (len & (block_size - 1))))
+               need_pad = 1;
+       else
+               need_pad = 0;
+
+       sg_init_one(&rctx->iv_sg, rctx->iv, sizeof(rctx->iv));
+
+       /* Build the data scatterlist table - allocate enough entries for all
+        * possible data pieces (buffer, input data, padding)
+        */
+       sg_count = (nbytes) ? sg_nents(req->src) + 2 : 2;
+       ret = sg_alloc_table(&rctx->data_sg, sg_count, GFP_KERNEL);
+       if (ret)
+               return ret;
+
+       sg = NULL;
+       if (rctx->buf_count) {
+               sg_init_one(&rctx->buf_sg, rctx->buf, rctx->buf_count);
+               sg = ccp_crypto_sg_table_add(&rctx->data_sg, &rctx->buf_sg);
+       }
+
+       if (nbytes)
+               sg = ccp_crypto_sg_table_add(&rctx->data_sg, req->src);
+
+       if (need_pad) {
+               int pad_length = block_size - (len & (block_size - 1));
+
+               rctx->hash_cnt += pad_length;
+
+               memset(rctx->pad, 0, sizeof(rctx->pad));
+               rctx->pad[0] = 0x80;
+               sg_init_one(&rctx->pad_sg, rctx->pad, pad_length);
+               sg = ccp_crypto_sg_table_add(&rctx->data_sg, &rctx->pad_sg);
+       }
+       if (sg)
+               sg_mark_end(sg);
+
+       /* Initialize the K1/K2 scatterlist */
+       if (final)
+               cmac_key_sg = (need_pad) ? &ctx->u.aes.k2_sg
+                                        : &ctx->u.aes.k1_sg;
+
+       memset(&rctx->cmd, 0, sizeof(rctx->cmd));
+       INIT_LIST_HEAD(&rctx->cmd.entry);
+       rctx->cmd.engine = CCP_ENGINE_AES;
+       rctx->cmd.u.aes.type = ctx->u.aes.type;
+       rctx->cmd.u.aes.mode = ctx->u.aes.mode;
+       rctx->cmd.u.aes.action = CCP_AES_ACTION_ENCRYPT;
+       rctx->cmd.u.aes.key = &ctx->u.aes.key_sg;
+       rctx->cmd.u.aes.key_len = ctx->u.aes.key_len;
+       rctx->cmd.u.aes.iv = &rctx->iv_sg;
+       rctx->cmd.u.aes.iv_len = AES_BLOCK_SIZE;
+       rctx->cmd.u.aes.src = (sg) ? rctx->data_sg.sgl : NULL;
+       rctx->cmd.u.aes.src_len = rctx->hash_cnt;
+       rctx->cmd.u.aes.dst = NULL;
+       rctx->cmd.u.aes.cmac_key = cmac_key_sg;
+       rctx->cmd.u.aes.cmac_key_len = ctx->u.aes.kn_len;
+       rctx->cmd.u.aes.cmac_final = final;
+
+       ret = ccp_crypto_enqueue_request(&req->base, &rctx->cmd);
+
+       return ret;
+}
+
+static int ccp_aes_cmac_init(struct ahash_request *req)
+{
+       struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx(req);
+
+       memset(rctx, 0, sizeof(*rctx));
+
+       rctx->null_msg = 1;
+
+       return 0;
+}
+
+static int ccp_aes_cmac_update(struct ahash_request *req)
+{
+       return ccp_do_cmac_update(req, req->nbytes, 0);
+}
+
+static int ccp_aes_cmac_final(struct ahash_request *req)
+{
+       return ccp_do_cmac_update(req, 0, 1);
+}
+
+static int ccp_aes_cmac_finup(struct ahash_request *req)
+{
+       return ccp_do_cmac_update(req, req->nbytes, 1);
+}
+
+static int ccp_aes_cmac_digest(struct ahash_request *req)
+{
+       int ret;
+
+       ret = ccp_aes_cmac_init(req);
+       if (ret)
+               return ret;
+
+       return ccp_do_cmac_update(req, req->nbytes, 1);
+}
+
+static int ccp_aes_cmac_setkey(struct crypto_ahash *tfm, const u8 *key,
+                          unsigned int key_len)
+{
+       struct ccp_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
+       struct ccp_crypto_ahash_alg *alg =
+               ccp_crypto_ahash_alg(crypto_ahash_tfm(tfm));
+       u64 k0_hi, k0_lo, k1_hi, k1_lo, k2_hi, k2_lo;
+       u64 rb_hi = 0x00, rb_lo = 0x87;
+       __be64 *gk;
+       int ret;
+
+       switch (key_len) {
+       case AES_KEYSIZE_128:
+               ctx->u.aes.type = CCP_AES_TYPE_128;
+               break;
+       case AES_KEYSIZE_192:
+               ctx->u.aes.type = CCP_AES_TYPE_192;
+               break;
+       case AES_KEYSIZE_256:
+               ctx->u.aes.type = CCP_AES_TYPE_256;
+               break;
+       default:
+               crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+               return -EINVAL;
+       }
+       ctx->u.aes.mode = alg->mode;
+
+       /* Set to zero until complete */
+       ctx->u.aes.key_len = 0;
+
+       /* Set the key for the AES cipher used to generate the keys */
+       ret = crypto_cipher_setkey(ctx->u.aes.tfm_cipher, key, key_len);
+       if (ret)
+               return ret;
+
+       /* Encrypt a block of zeroes - use key area in context */
+       memset(ctx->u.aes.key, 0, sizeof(ctx->u.aes.key));
+       crypto_cipher_encrypt_one(ctx->u.aes.tfm_cipher, ctx->u.aes.key,
+                                 ctx->u.aes.key);
+
+       /* Generate K1 and K2 */
+       k0_hi = be64_to_cpu(*((__be64 *)ctx->u.aes.key));
+       k0_lo = be64_to_cpu(*((__be64 *)ctx->u.aes.key + 1));
+
+       k1_hi = (k0_hi << 1) | (k0_lo >> 63);
+       k1_lo = k0_lo << 1;
+       if (ctx->u.aes.key[0] & 0x80) {
+               k1_hi ^= rb_hi;
+               k1_lo ^= rb_lo;
+       }
+       gk = (__be64 *)ctx->u.aes.k1;
+       *gk = cpu_to_be64(k1_hi);
+       gk++;
+       *gk = cpu_to_be64(k1_lo);
+
+       k2_hi = (k1_hi << 1) | (k1_lo >> 63);
+       k2_lo = k1_lo << 1;
+       if (ctx->u.aes.k1[0] & 0x80) {
+               k2_hi ^= rb_hi;
+               k2_lo ^= rb_lo;
+       }
+       gk = (__be64 *)ctx->u.aes.k2;
+       *gk = cpu_to_be64(k2_hi);
+       gk++;
+       *gk = cpu_to_be64(k2_lo);
+
+       ctx->u.aes.kn_len = sizeof(ctx->u.aes.k1);
+       sg_init_one(&ctx->u.aes.k1_sg, ctx->u.aes.k1, sizeof(ctx->u.aes.k1));
+       sg_init_one(&ctx->u.aes.k2_sg, ctx->u.aes.k2, sizeof(ctx->u.aes.k2));
+
+       /* Save the supplied key */
+       memset(ctx->u.aes.key, 0, sizeof(ctx->u.aes.key));
+       memcpy(ctx->u.aes.key, key, key_len);
+       ctx->u.aes.key_len = key_len;
+       sg_init_one(&ctx->u.aes.key_sg, ctx->u.aes.key, key_len);
+
+       return ret;
+}
+
+static int ccp_aes_cmac_cra_init(struct crypto_tfm *tfm)
+{
+       struct ccp_ctx *ctx = crypto_tfm_ctx(tfm);
+       struct crypto_ahash *ahash = __crypto_ahash_cast(tfm);
+       struct crypto_cipher *cipher_tfm;
+
+       ctx->complete = ccp_aes_cmac_complete;
+       ctx->u.aes.key_len = 0;
+
+       crypto_ahash_set_reqsize(ahash, sizeof(struct ccp_aes_cmac_req_ctx));
+
+       cipher_tfm = crypto_alloc_cipher("aes", 0,
+                       CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK);
+       if (IS_ERR(cipher_tfm)) {
+               pr_warn("could not load aes cipher driver\n");
+               return PTR_ERR(cipher_tfm);
+       }
+       ctx->u.aes.tfm_cipher = cipher_tfm;
+
+       return 0;
+}
+
+static void ccp_aes_cmac_cra_exit(struct crypto_tfm *tfm)
+{
+       struct ccp_ctx *ctx = crypto_tfm_ctx(tfm);
+
+       if (ctx->u.aes.tfm_cipher)
+               crypto_free_cipher(ctx->u.aes.tfm_cipher);
+       ctx->u.aes.tfm_cipher = NULL;
+}
+
+int ccp_register_aes_cmac_algs(struct list_head *head)
+{
+       struct ccp_crypto_ahash_alg *ccp_alg;
+       struct ahash_alg *alg;
+       struct hash_alg_common *halg;
+       struct crypto_alg *base;
+       int ret;
+
+       ccp_alg = kzalloc(sizeof(*ccp_alg), GFP_KERNEL);
+       if (!ccp_alg)
+               return -ENOMEM;
+
+       INIT_LIST_HEAD(&ccp_alg->entry);
+       ccp_alg->mode = CCP_AES_MODE_CMAC;
+
+       alg = &ccp_alg->alg;
+       alg->init = ccp_aes_cmac_init;
+       alg->update = ccp_aes_cmac_update;
+       alg->final = ccp_aes_cmac_final;
+       alg->finup = ccp_aes_cmac_finup;
+       alg->digest = ccp_aes_cmac_digest;
+       alg->setkey = ccp_aes_cmac_setkey;
+
+       halg = &alg->halg;
+       halg->digestsize = AES_BLOCK_SIZE;
+
+       base = &halg->base;
+       snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME, "cmac(aes)");
+       snprintf(base->cra_driver_name, CRYPTO_MAX_ALG_NAME, "cmac-aes-ccp");
+       base->cra_flags = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC |
+                         CRYPTO_ALG_KERN_DRIVER_ONLY |
+                         CRYPTO_ALG_NEED_FALLBACK;
+       base->cra_blocksize = AES_BLOCK_SIZE;
+       base->cra_ctxsize = sizeof(struct ccp_ctx);
+       base->cra_priority = CCP_CRA_PRIORITY;
+       base->cra_type = &crypto_ahash_type;
+       base->cra_init = ccp_aes_cmac_cra_init;
+       base->cra_exit = ccp_aes_cmac_cra_exit;
+       base->cra_module = THIS_MODULE;
+
+       ret = crypto_register_ahash(alg);
+       if (ret) {
+               pr_err("%s ahash algorithm registration error (%d)\n",
+                       base->cra_name, ret);
+               kfree(ccp_alg);
+               return ret;
+       }
+
+       list_add(&ccp_alg->entry, head);
+
+       return 0;
+}
diff --git a/drivers/crypto/ccp/ccp-crypto-aes-xts.c b/drivers/crypto/ccp/ccp-crypto-aes-xts.c
new file mode 100644 (file)
index 0000000..d100b48
--- /dev/null
@@ -0,0 +1,285 @@
+/*
+ * AMD Cryptographic Coprocessor (CCP) AES XTS crypto API support
+ *
+ * Copyright (C) 2013 Advanced Micro Devices, Inc.
+ *
+ * Author: Tom Lendacky <thomas.lendacky@amd.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/module.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/scatterlist.h>
+#include <linux/crypto.h>
+#include <crypto/algapi.h>
+#include <crypto/aes.h>
+#include <crypto/scatterwalk.h>
+
+#include "ccp-crypto.h"
+
+
+struct ccp_aes_xts_def {
+       const char *name;
+       const char *drv_name;
+};
+
+static struct ccp_aes_xts_def aes_xts_algs[] = {
+       {
+               .name           = "xts(aes)",
+               .drv_name       = "xts-aes-ccp",
+       },
+};
+
+struct ccp_unit_size_map {
+       unsigned int size;
+       u32 value;
+};
+
+static struct ccp_unit_size_map unit_size_map[] = {
+       {
+               .size   = 4096,
+               .value  = CCP_XTS_AES_UNIT_SIZE_4096,
+       },
+       {
+               .size   = 2048,
+               .value  = CCP_XTS_AES_UNIT_SIZE_2048,
+       },
+       {
+               .size   = 1024,
+               .value  = CCP_XTS_AES_UNIT_SIZE_1024,
+       },
+       {
+               .size   = 512,
+               .value  = CCP_XTS_AES_UNIT_SIZE_512,
+       },
+       {
+               .size   = 256,
+               .value  = CCP_XTS_AES_UNIT_SIZE__LAST,
+       },
+       {
+               .size   = 128,
+               .value  = CCP_XTS_AES_UNIT_SIZE__LAST,
+       },
+       {
+               .size   = 64,
+               .value  = CCP_XTS_AES_UNIT_SIZE__LAST,
+       },
+       {
+               .size   = 32,
+               .value  = CCP_XTS_AES_UNIT_SIZE__LAST,
+       },
+       {
+               .size   = 16,
+               .value  = CCP_XTS_AES_UNIT_SIZE_16,
+       },
+       {
+               .size   = 1,
+               .value  = CCP_XTS_AES_UNIT_SIZE__LAST,
+       },
+};
+
+static int ccp_aes_xts_complete(struct crypto_async_request *async_req, int ret)
+{
+       struct ablkcipher_request *req = ablkcipher_request_cast(async_req);
+       struct ccp_aes_req_ctx *rctx = ablkcipher_request_ctx(req);
+
+       if (ret)
+               return ret;
+
+       memcpy(req->info, rctx->iv, AES_BLOCK_SIZE);
+
+       return 0;
+}
+
+static int ccp_aes_xts_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
+                             unsigned int key_len)
+{
+       struct ccp_ctx *ctx = crypto_tfm_ctx(crypto_ablkcipher_tfm(tfm));
+
+       /* Only support 128-bit AES key with a 128-bit Tweak key,
+        * otherwise use the fallback
+        */
+       switch (key_len) {
+       case AES_KEYSIZE_128 * 2:
+               memcpy(ctx->u.aes.key, key, key_len);
+               break;
+       }
+       ctx->u.aes.key_len = key_len / 2;
+       sg_init_one(&ctx->u.aes.key_sg, ctx->u.aes.key, key_len);
+
+       return crypto_ablkcipher_setkey(ctx->u.aes.tfm_ablkcipher, key,
+                                       key_len);
+}
+
+static int ccp_aes_xts_crypt(struct ablkcipher_request *req,
+                            unsigned int encrypt)
+{
+       struct crypto_tfm *tfm =
+               crypto_ablkcipher_tfm(crypto_ablkcipher_reqtfm(req));
+       struct ccp_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
+       struct ccp_aes_req_ctx *rctx = ablkcipher_request_ctx(req);
+       unsigned int unit;
+       int ret;
+
+       if (!ctx->u.aes.key_len) {
+               pr_err("AES key not set\n");
+               return -EINVAL;
+       }
+
+       if (req->nbytes & (AES_BLOCK_SIZE - 1)) {
+               pr_err("AES request size is not a multiple of the block size\n");
+               return -EINVAL;
+       }
+
+       if (!req->info) {
+               pr_err("AES IV not supplied");
+               return -EINVAL;
+       }
+
+       for (unit = 0; unit < ARRAY_SIZE(unit_size_map); unit++)
+               if (!(req->nbytes & (unit_size_map[unit].size - 1)))
+                       break;
+
+       if ((unit_size_map[unit].value == CCP_XTS_AES_UNIT_SIZE__LAST) ||
+           (ctx->u.aes.key_len != AES_KEYSIZE_128)) {
+               /* Use the fallback to process the request for any
+                * unsupported unit sizes or key sizes
+                */
+               ablkcipher_request_set_tfm(req, ctx->u.aes.tfm_ablkcipher);
+               ret = (encrypt) ? crypto_ablkcipher_encrypt(req) :
+                                 crypto_ablkcipher_decrypt(req);
+               ablkcipher_request_set_tfm(req, __crypto_ablkcipher_cast(tfm));
+
+               return ret;
+       }
+
+       memcpy(rctx->iv, req->info, AES_BLOCK_SIZE);
+       sg_init_one(&rctx->iv_sg, rctx->iv, AES_BLOCK_SIZE);
+
+       memset(&rctx->cmd, 0, sizeof(rctx->cmd));
+       INIT_LIST_HEAD(&rctx->cmd.entry);
+       rctx->cmd.engine = CCP_ENGINE_XTS_AES_128;
+       rctx->cmd.u.xts.action = (encrypt) ? CCP_AES_ACTION_ENCRYPT
+                                          : CCP_AES_ACTION_DECRYPT;
+       rctx->cmd.u.xts.unit_size = unit_size_map[unit].value;
+       rctx->cmd.u.xts.key = &ctx->u.aes.key_sg;
+       rctx->cmd.u.xts.key_len = ctx->u.aes.key_len;
+       rctx->cmd.u.xts.iv = &rctx->iv_sg;
+       rctx->cmd.u.xts.iv_len = AES_BLOCK_SIZE;
+       rctx->cmd.u.xts.src = req->src;
+       rctx->cmd.u.xts.src_len = req->nbytes;
+       rctx->cmd.u.xts.dst = req->dst;
+
+       ret = ccp_crypto_enqueue_request(&req->base, &rctx->cmd);
+
+       return ret;
+}
+
+static int ccp_aes_xts_encrypt(struct ablkcipher_request *req)
+{
+       return ccp_aes_xts_crypt(req, 1);
+}
+
+static int ccp_aes_xts_decrypt(struct ablkcipher_request *req)
+{
+       return ccp_aes_xts_crypt(req, 0);
+}
+
+static int ccp_aes_xts_cra_init(struct crypto_tfm *tfm)
+{
+       struct ccp_ctx *ctx = crypto_tfm_ctx(tfm);
+       struct crypto_ablkcipher *fallback_tfm;
+
+       ctx->complete = ccp_aes_xts_complete;
+       ctx->u.aes.key_len = 0;
+
+       fallback_tfm = crypto_alloc_ablkcipher(tfm->__crt_alg->cra_name, 0,
+                                              CRYPTO_ALG_ASYNC |
+                                              CRYPTO_ALG_NEED_FALLBACK);
+       if (IS_ERR(fallback_tfm)) {
+               pr_warn("could not load fallback driver %s\n",
+                       tfm->__crt_alg->cra_name);
+               return PTR_ERR(fallback_tfm);
+       }
+       ctx->u.aes.tfm_ablkcipher = fallback_tfm;
+
+       tfm->crt_ablkcipher.reqsize = sizeof(struct ccp_aes_req_ctx) +
+                                     fallback_tfm->base.crt_ablkcipher.reqsize;
+
+       return 0;
+}
+
+static void ccp_aes_xts_cra_exit(struct crypto_tfm *tfm)
+{
+       struct ccp_ctx *ctx = crypto_tfm_ctx(tfm);
+
+       if (ctx->u.aes.tfm_ablkcipher)
+               crypto_free_ablkcipher(ctx->u.aes.tfm_ablkcipher);
+       ctx->u.aes.tfm_ablkcipher = NULL;
+}
+
+
+static int ccp_register_aes_xts_alg(struct list_head *head,
+                                   const struct ccp_aes_xts_def *def)
+{
+       struct ccp_crypto_ablkcipher_alg *ccp_alg;
+       struct crypto_alg *alg;
+       int ret;
+
+       ccp_alg = kzalloc(sizeof(*ccp_alg), GFP_KERNEL);
+       if (!ccp_alg)
+               return -ENOMEM;
+
+       INIT_LIST_HEAD(&ccp_alg->entry);
+
+       alg = &ccp_alg->alg;
+
+       snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name);
+       snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
+                def->drv_name);
+       alg->cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC |
+                        CRYPTO_ALG_KERN_DRIVER_ONLY |
+                        CRYPTO_ALG_NEED_FALLBACK;
+       alg->cra_blocksize = AES_BLOCK_SIZE;
+       alg->cra_ctxsize = sizeof(struct ccp_ctx);
+       alg->cra_priority = CCP_CRA_PRIORITY;
+       alg->cra_type = &crypto_ablkcipher_type;
+       alg->cra_ablkcipher.setkey = ccp_aes_xts_setkey;
+       alg->cra_ablkcipher.encrypt = ccp_aes_xts_encrypt;
+       alg->cra_ablkcipher.decrypt = ccp_aes_xts_decrypt;
+       alg->cra_ablkcipher.min_keysize = AES_MIN_KEY_SIZE * 2;
+       alg->cra_ablkcipher.max_keysize = AES_MAX_KEY_SIZE * 2;
+       alg->cra_ablkcipher.ivsize = AES_BLOCK_SIZE;
+       alg->cra_init = ccp_aes_xts_cra_init;
+       alg->cra_exit = ccp_aes_xts_cra_exit;
+       alg->cra_module = THIS_MODULE;
+
+       ret = crypto_register_alg(alg);
+       if (ret) {
+               pr_err("%s ablkcipher algorithm registration error (%d)\n",
+                       alg->cra_name, ret);
+               kfree(ccp_alg);
+               return ret;
+       }
+
+       list_add(&ccp_alg->entry, head);
+
+       return 0;
+}
+
+int ccp_register_aes_xts_algs(struct list_head *head)
+{
+       int i, ret;
+
+       for (i = 0; i < ARRAY_SIZE(aes_xts_algs); i++) {
+               ret = ccp_register_aes_xts_alg(head, &aes_xts_algs[i]);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
diff --git a/drivers/crypto/ccp/ccp-crypto-aes.c b/drivers/crypto/ccp/ccp-crypto-aes.c
new file mode 100644 (file)
index 0000000..c0befdb
--- /dev/null
@@ -0,0 +1,375 @@
+/*
+ * AMD Cryptographic Coprocessor (CCP) AES crypto API support
+ *
+ * Copyright (C) 2013 Advanced Micro Devices, Inc.
+ *
+ * Author: Tom Lendacky <thomas.lendacky@amd.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/module.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/scatterlist.h>
+#include <linux/crypto.h>
+#include <crypto/algapi.h>
+#include <crypto/aes.h>
+#include <crypto/ctr.h>
+#include <crypto/scatterwalk.h>
+
+#include "ccp-crypto.h"
+
+
+static int ccp_aes_complete(struct crypto_async_request *async_req, int ret)
+{
+       struct ablkcipher_request *req = ablkcipher_request_cast(async_req);
+       struct ccp_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
+       struct ccp_aes_req_ctx *rctx = ablkcipher_request_ctx(req);
+
+       if (ret)
+               return ret;
+
+       if (ctx->u.aes.mode != CCP_AES_MODE_ECB)
+               memcpy(req->info, rctx->iv, AES_BLOCK_SIZE);
+
+       return 0;
+}
+
+static int ccp_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
+                         unsigned int key_len)
+{
+       struct ccp_ctx *ctx = crypto_tfm_ctx(crypto_ablkcipher_tfm(tfm));
+       struct ccp_crypto_ablkcipher_alg *alg =
+               ccp_crypto_ablkcipher_alg(crypto_ablkcipher_tfm(tfm));
+
+       switch (key_len) {
+       case AES_KEYSIZE_128:
+               ctx->u.aes.type = CCP_AES_TYPE_128;
+               break;
+       case AES_KEYSIZE_192:
+               ctx->u.aes.type = CCP_AES_TYPE_192;
+               break;
+       case AES_KEYSIZE_256:
+               ctx->u.aes.type = CCP_AES_TYPE_256;
+               break;
+       default:
+               crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+               return -EINVAL;
+       }
+       ctx->u.aes.mode = alg->mode;
+       ctx->u.aes.key_len = key_len;
+
+       memcpy(ctx->u.aes.key, key, key_len);
+       sg_init_one(&ctx->u.aes.key_sg, ctx->u.aes.key, key_len);
+
+       return 0;
+}
+
+static int ccp_aes_crypt(struct ablkcipher_request *req, bool encrypt)
+{
+       struct ccp_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
+       struct ccp_aes_req_ctx *rctx = ablkcipher_request_ctx(req);
+       struct scatterlist *iv_sg = NULL;
+       unsigned int iv_len = 0;
+       int ret;
+
+       if (!ctx->u.aes.key_len) {
+               pr_err("AES key not set\n");
+               return -EINVAL;
+       }
+
+       if (((ctx->u.aes.mode == CCP_AES_MODE_ECB) ||
+            (ctx->u.aes.mode == CCP_AES_MODE_CBC) ||
+            (ctx->u.aes.mode == CCP_AES_MODE_CFB)) &&
+           (req->nbytes & (AES_BLOCK_SIZE - 1))) {
+               pr_err("AES request size is not a multiple of the block size\n");
+               return -EINVAL;
+       }
+
+       if (ctx->u.aes.mode != CCP_AES_MODE_ECB) {
+               if (!req->info) {
+                       pr_err("AES IV not supplied");
+                       return -EINVAL;
+               }
+
+               memcpy(rctx->iv, req->info, AES_BLOCK_SIZE);
+               iv_sg = &rctx->iv_sg;
+               iv_len = AES_BLOCK_SIZE;
+               sg_init_one(iv_sg, rctx->iv, iv_len);
+       }
+
+       memset(&rctx->cmd, 0, sizeof(rctx->cmd));
+       INIT_LIST_HEAD(&rctx->cmd.entry);
+       rctx->cmd.engine = CCP_ENGINE_AES;
+       rctx->cmd.u.aes.type = ctx->u.aes.type;
+       rctx->cmd.u.aes.mode = ctx->u.aes.mode;
+       rctx->cmd.u.aes.action =
+               (encrypt) ? CCP_AES_ACTION_ENCRYPT : CCP_AES_ACTION_DECRYPT;
+       rctx->cmd.u.aes.key = &ctx->u.aes.key_sg;
+       rctx->cmd.u.aes.key_len = ctx->u.aes.key_len;
+       rctx->cmd.u.aes.iv = iv_sg;
+       rctx->cmd.u.aes.iv_len = iv_len;
+       rctx->cmd.u.aes.src = req->src;
+       rctx->cmd.u.aes.src_len = req->nbytes;
+       rctx->cmd.u.aes.dst = req->dst;
+
+       ret = ccp_crypto_enqueue_request(&req->base, &rctx->cmd);
+
+       return ret;
+}
+
+static int ccp_aes_encrypt(struct ablkcipher_request *req)
+{
+       return ccp_aes_crypt(req, true);
+}
+
+static int ccp_aes_decrypt(struct ablkcipher_request *req)
+{
+       return ccp_aes_crypt(req, false);
+}
+
+static int ccp_aes_cra_init(struct crypto_tfm *tfm)
+{
+       struct ccp_ctx *ctx = crypto_tfm_ctx(tfm);
+
+       ctx->complete = ccp_aes_complete;
+       ctx->u.aes.key_len = 0;
+
+       tfm->crt_ablkcipher.reqsize = sizeof(struct ccp_aes_req_ctx);
+
+       return 0;
+}
+
+static void ccp_aes_cra_exit(struct crypto_tfm *tfm)
+{
+}
+
+static int ccp_aes_rfc3686_complete(struct crypto_async_request *async_req,
+                                   int ret)
+{
+       struct ablkcipher_request *req = ablkcipher_request_cast(async_req);
+       struct ccp_aes_req_ctx *rctx = ablkcipher_request_ctx(req);
+
+       /* Restore the original pointer */
+       req->info = rctx->rfc3686_info;
+
+       return ccp_aes_complete(async_req, ret);
+}
+
+static int ccp_aes_rfc3686_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
+                                 unsigned int key_len)
+{
+       struct ccp_ctx *ctx = crypto_tfm_ctx(crypto_ablkcipher_tfm(tfm));
+
+       if (key_len < CTR_RFC3686_NONCE_SIZE)
+               return -EINVAL;
+
+       key_len -= CTR_RFC3686_NONCE_SIZE;
+       memcpy(ctx->u.aes.nonce, key + key_len, CTR_RFC3686_NONCE_SIZE);
+
+       return ccp_aes_setkey(tfm, key, key_len);
+}
+
+static int ccp_aes_rfc3686_crypt(struct ablkcipher_request *req, bool encrypt)
+{
+       struct ccp_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
+       struct ccp_aes_req_ctx *rctx = ablkcipher_request_ctx(req);
+       u8 *iv;
+
+       /* Initialize the CTR block */
+       iv = rctx->rfc3686_iv;
+       memcpy(iv, ctx->u.aes.nonce, CTR_RFC3686_NONCE_SIZE);
+
+       iv += CTR_RFC3686_NONCE_SIZE;
+       memcpy(iv, req->info, CTR_RFC3686_IV_SIZE);
+
+       iv += CTR_RFC3686_IV_SIZE;
+       *(__be32 *)iv = cpu_to_be32(1);
+
+       /* Point to the new IV */
+       rctx->rfc3686_info = req->info;
+       req->info = rctx->rfc3686_iv;
+
+       return ccp_aes_crypt(req, encrypt);
+}
+
+static int ccp_aes_rfc3686_encrypt(struct ablkcipher_request *req)
+{
+       return ccp_aes_rfc3686_crypt(req, true);
+}
+
+static int ccp_aes_rfc3686_decrypt(struct ablkcipher_request *req)
+{
+       return ccp_aes_rfc3686_crypt(req, false);
+}
+
+static int ccp_aes_rfc3686_cra_init(struct crypto_tfm *tfm)
+{
+       struct ccp_ctx *ctx = crypto_tfm_ctx(tfm);
+
+       ctx->complete = ccp_aes_rfc3686_complete;
+       ctx->u.aes.key_len = 0;
+
+       tfm->crt_ablkcipher.reqsize = sizeof(struct ccp_aes_req_ctx);
+
+       return 0;
+}
+
+static void ccp_aes_rfc3686_cra_exit(struct crypto_tfm *tfm)
+{
+}
+
+static struct crypto_alg ccp_aes_defaults = {
+       .cra_flags      = CRYPTO_ALG_TYPE_ABLKCIPHER |
+                         CRYPTO_ALG_ASYNC |
+                         CRYPTO_ALG_KERN_DRIVER_ONLY |
+                         CRYPTO_ALG_NEED_FALLBACK,
+       .cra_blocksize  = AES_BLOCK_SIZE,
+       .cra_ctxsize    = sizeof(struct ccp_ctx),
+       .cra_priority   = CCP_CRA_PRIORITY,
+       .cra_type       = &crypto_ablkcipher_type,
+       .cra_init       = ccp_aes_cra_init,
+       .cra_exit       = ccp_aes_cra_exit,
+       .cra_module     = THIS_MODULE,
+       .cra_ablkcipher = {
+               .setkey         = ccp_aes_setkey,
+               .encrypt        = ccp_aes_encrypt,
+               .decrypt        = ccp_aes_decrypt,
+               .min_keysize    = AES_MIN_KEY_SIZE,
+               .max_keysize    = AES_MAX_KEY_SIZE,
+       },
+};
+
+static struct crypto_alg ccp_aes_rfc3686_defaults = {
+       .cra_flags      = CRYPTO_ALG_TYPE_ABLKCIPHER |
+                          CRYPTO_ALG_ASYNC |
+                          CRYPTO_ALG_KERN_DRIVER_ONLY |
+                          CRYPTO_ALG_NEED_FALLBACK,
+       .cra_blocksize  = CTR_RFC3686_BLOCK_SIZE,
+       .cra_ctxsize    = sizeof(struct ccp_ctx),
+       .cra_priority   = CCP_CRA_PRIORITY,
+       .cra_type       = &crypto_ablkcipher_type,
+       .cra_init       = ccp_aes_rfc3686_cra_init,
+       .cra_exit       = ccp_aes_rfc3686_cra_exit,
+       .cra_module     = THIS_MODULE,
+       .cra_ablkcipher = {
+               .setkey         = ccp_aes_rfc3686_setkey,
+               .encrypt        = ccp_aes_rfc3686_encrypt,
+               .decrypt        = ccp_aes_rfc3686_decrypt,
+               .min_keysize    = AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
+               .max_keysize    = AES_MAX_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
+       },
+};
+
+struct ccp_aes_def {
+       enum ccp_aes_mode mode;
+       const char *name;
+       const char *driver_name;
+       unsigned int blocksize;
+       unsigned int ivsize;
+       struct crypto_alg *alg_defaults;
+};
+
+static struct ccp_aes_def aes_algs[] = {
+       {
+               .mode           = CCP_AES_MODE_ECB,
+               .name           = "ecb(aes)",
+               .driver_name    = "ecb-aes-ccp",
+               .blocksize      = AES_BLOCK_SIZE,
+               .ivsize         = 0,
+               .alg_defaults   = &ccp_aes_defaults,
+       },
+       {
+               .mode           = CCP_AES_MODE_CBC,
+               .name           = "cbc(aes)",
+               .driver_name    = "cbc-aes-ccp",
+               .blocksize      = AES_BLOCK_SIZE,
+               .ivsize         = AES_BLOCK_SIZE,
+               .alg_defaults   = &ccp_aes_defaults,
+       },
+       {
+               .mode           = CCP_AES_MODE_CFB,
+               .name           = "cfb(aes)",
+               .driver_name    = "cfb-aes-ccp",
+               .blocksize      = AES_BLOCK_SIZE,
+               .ivsize         = AES_BLOCK_SIZE,
+               .alg_defaults   = &ccp_aes_defaults,
+       },
+       {
+               .mode           = CCP_AES_MODE_OFB,
+               .name           = "ofb(aes)",
+               .driver_name    = "ofb-aes-ccp",
+               .blocksize      = 1,
+               .ivsize         = AES_BLOCK_SIZE,
+               .alg_defaults   = &ccp_aes_defaults,
+       },
+       {
+               .mode           = CCP_AES_MODE_CTR,
+               .name           = "ctr(aes)",
+               .driver_name    = "ctr-aes-ccp",
+               .blocksize      = 1,
+               .ivsize         = AES_BLOCK_SIZE,
+               .alg_defaults   = &ccp_aes_defaults,
+       },
+       {
+               .mode           = CCP_AES_MODE_CTR,
+               .name           = "rfc3686(ctr(aes))",
+               .driver_name    = "rfc3686-ctr-aes-ccp",
+               .blocksize      = 1,
+               .ivsize         = CTR_RFC3686_IV_SIZE,
+               .alg_defaults   = &ccp_aes_rfc3686_defaults,
+       },
+};
+
+static int ccp_register_aes_alg(struct list_head *head,
+                               const struct ccp_aes_def *def)
+{
+       struct ccp_crypto_ablkcipher_alg *ccp_alg;
+       struct crypto_alg *alg;
+       int ret;
+
+       ccp_alg = kzalloc(sizeof(*ccp_alg), GFP_KERNEL);
+       if (!ccp_alg)
+               return -ENOMEM;
+
+       INIT_LIST_HEAD(&ccp_alg->entry);
+
+       ccp_alg->mode = def->mode;
+
+       /* Copy the defaults and override as necessary */
+       alg = &ccp_alg->alg;
+       *alg = *def->alg_defaults;
+       snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name);
+       snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
+                def->driver_name);
+       alg->cra_blocksize = def->blocksize;
+       alg->cra_ablkcipher.ivsize = def->ivsize;
+
+       ret = crypto_register_alg(alg);
+       if (ret) {
+               pr_err("%s ablkcipher algorithm registration error (%d)\n",
+                       alg->cra_name, ret);
+               kfree(ccp_alg);
+               return ret;
+       }
+
+       list_add(&ccp_alg->entry, head);
+
+       return 0;
+}
+
+int ccp_register_aes_algs(struct list_head *head)
+{
+       int i, ret;
+
+       for (i = 0; i < ARRAY_SIZE(aes_algs); i++) {
+               ret = ccp_register_aes_alg(head, &aes_algs[i]);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
diff --git a/drivers/crypto/ccp/ccp-crypto-main.c b/drivers/crypto/ccp/ccp-crypto-main.c
new file mode 100644 (file)
index 0000000..2636f04
--- /dev/null
@@ -0,0 +1,432 @@
+/*
+ * AMD Cryptographic Coprocessor (CCP) crypto API support
+ *
+ * Copyright (C) 2013 Advanced Micro Devices, Inc.
+ *
+ * Author: Tom Lendacky <thomas.lendacky@amd.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/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/ccp.h>
+#include <linux/scatterlist.h>
+#include <crypto/internal/hash.h>
+
+#include "ccp-crypto.h"
+
+MODULE_AUTHOR("Tom Lendacky <thomas.lendacky@amd.com>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0.0");
+MODULE_DESCRIPTION("AMD Cryptographic Coprocessor crypto API support");
+
+
+/* List heads for the supported algorithms */
+static LIST_HEAD(hash_algs);
+static LIST_HEAD(cipher_algs);
+
+/* For any tfm, requests for that tfm on the same CPU must be returned
+ * in the order received.  With multiple queues available, the CCP can
+ * process more than one cmd at a time.  Therefore we must maintain
+ * a cmd list to insure the proper ordering of requests on a given tfm/cpu
+ * combination.
+ */
+struct ccp_crypto_cpu_queue {
+       struct list_head cmds;
+       struct list_head *backlog;
+       unsigned int cmd_count;
+};
+#define CCP_CRYPTO_MAX_QLEN    50
+
+struct ccp_crypto_percpu_queue {
+       struct ccp_crypto_cpu_queue __percpu *cpu_queue;
+};
+static struct ccp_crypto_percpu_queue req_queue;
+
+struct ccp_crypto_cmd {
+       struct list_head entry;
+
+       struct ccp_cmd *cmd;
+
+       /* Save the crypto_tfm and crypto_async_request addresses
+        * separately to avoid any reference to a possibly invalid
+        * crypto_async_request structure after invoking the request
+        * callback
+        */
+       struct crypto_async_request *req;
+       struct crypto_tfm *tfm;
+
+       /* Used for held command processing to determine state */
+       int ret;
+
+       int cpu;
+};
+
+struct ccp_crypto_cpu {
+       struct work_struct work;
+       struct completion completion;
+       struct ccp_crypto_cmd *crypto_cmd;
+       int err;
+};
+
+
+static inline bool ccp_crypto_success(int err)
+{
+       if (err && (err != -EINPROGRESS) && (err != -EBUSY))
+               return false;
+
+       return true;
+}
+
+/*
+ * ccp_crypto_cmd_complete must be called while running on the appropriate
+ * cpu and the caller must have done a get_cpu to disable preemption
+ */
+static struct ccp_crypto_cmd *ccp_crypto_cmd_complete(
+       struct ccp_crypto_cmd *crypto_cmd, struct ccp_crypto_cmd **backlog)
+{
+       struct ccp_crypto_cpu_queue *cpu_queue;
+       struct ccp_crypto_cmd *held = NULL, *tmp;
+
+       *backlog = NULL;
+
+       cpu_queue = this_cpu_ptr(req_queue.cpu_queue);
+
+       /* Held cmds will be after the current cmd in the queue so start
+        * searching for a cmd with a matching tfm for submission.
+        */
+       tmp = crypto_cmd;
+       list_for_each_entry_continue(tmp, &cpu_queue->cmds, entry) {
+               if (crypto_cmd->tfm != tmp->tfm)
+                       continue;
+               held = tmp;
+               break;
+       }
+
+       /* Process the backlog:
+        *   Because cmds can be executed from any point in the cmd list
+        *   special precautions have to be taken when handling the backlog.
+        */
+       if (cpu_queue->backlog != &cpu_queue->cmds) {
+               /* Skip over this cmd if it is the next backlog cmd */
+               if (cpu_queue->backlog == &crypto_cmd->entry)
+                       cpu_queue->backlog = crypto_cmd->entry.next;
+
+               *backlog = container_of(cpu_queue->backlog,
+                                       struct ccp_crypto_cmd, entry);
+               cpu_queue->backlog = cpu_queue->backlog->next;
+
+               /* Skip over this cmd if it is now the next backlog cmd */
+               if (cpu_queue->backlog == &crypto_cmd->entry)
+                       cpu_queue->backlog = crypto_cmd->entry.next;
+       }
+
+       /* Remove the cmd entry from the list of cmds */
+       cpu_queue->cmd_count--;
+       list_del(&crypto_cmd->entry);
+
+       return held;
+}
+
+static void ccp_crypto_complete_on_cpu(struct work_struct *work)
+{
+       struct ccp_crypto_cpu *cpu_work =
+               container_of(work, struct ccp_crypto_cpu, work);
+       struct ccp_crypto_cmd *crypto_cmd = cpu_work->crypto_cmd;
+       struct ccp_crypto_cmd *held, *next, *backlog;
+       struct crypto_async_request *req = crypto_cmd->req;
+       struct ccp_ctx *ctx = crypto_tfm_ctx(req->tfm);
+       int cpu, ret;
+
+       cpu = get_cpu();
+
+       if (cpu_work->err == -EINPROGRESS) {
+               /* Only propogate the -EINPROGRESS if necessary */
+               if (crypto_cmd->ret == -EBUSY) {
+                       crypto_cmd->ret = -EINPROGRESS;
+                       req->complete(req, -EINPROGRESS);
+               }
+
+               goto e_cpu;
+       }
+
+       /* Operation has completed - update the queue before invoking
+        * the completion callbacks and retrieve the next cmd (cmd with
+        * a matching tfm) that can be submitted to the CCP.
+        */
+       held = ccp_crypto_cmd_complete(crypto_cmd, &backlog);
+       if (backlog) {
+               backlog->ret = -EINPROGRESS;
+               backlog->req->complete(backlog->req, -EINPROGRESS);
+       }
+
+       /* Transition the state from -EBUSY to -EINPROGRESS first */
+       if (crypto_cmd->ret == -EBUSY)
+               req->complete(req, -EINPROGRESS);
+
+       /* Completion callbacks */
+       ret = cpu_work->err;
+       if (ctx->complete)
+               ret = ctx->complete(req, ret);
+       req->complete(req, ret);
+
+       /* Submit the next cmd */
+       while (held) {
+               ret = ccp_enqueue_cmd(held->cmd);
+               if (ccp_crypto_success(ret))
+                       break;
+
+               /* Error occurred, report it and get the next entry */
+               held->req->complete(held->req, ret);
+
+               next = ccp_crypto_cmd_complete(held, &backlog);
+               if (backlog) {
+                       backlog->ret = -EINPROGRESS;
+                       backlog->req->complete(backlog->req, -EINPROGRESS);
+               }
+
+               kfree(held);
+               held = next;
+       }
+
+       kfree(crypto_cmd);
+
+e_cpu:
+       put_cpu();
+
+       complete(&cpu_work->completion);
+}
+
+static void ccp_crypto_complete(void *data, int err)
+{
+       struct ccp_crypto_cmd *crypto_cmd = data;
+       struct ccp_crypto_cpu cpu_work;
+
+       INIT_WORK(&cpu_work.work, ccp_crypto_complete_on_cpu);
+       init_completion(&cpu_work.completion);
+       cpu_work.crypto_cmd = crypto_cmd;
+       cpu_work.err = err;
+
+       schedule_work_on(crypto_cmd->cpu, &cpu_work.work);
+
+       /* Keep the completion call synchronous */
+       wait_for_completion(&cpu_work.completion);
+}
+
+static int ccp_crypto_enqueue_cmd(struct ccp_crypto_cmd *crypto_cmd)
+{
+       struct ccp_crypto_cpu_queue *cpu_queue;
+       struct ccp_crypto_cmd *active = NULL, *tmp;
+       int cpu, ret;
+
+       cpu = get_cpu();
+       crypto_cmd->cpu = cpu;
+
+       cpu_queue = this_cpu_ptr(req_queue.cpu_queue);
+
+       /* Check if the cmd can/should be queued */
+       if (cpu_queue->cmd_count >= CCP_CRYPTO_MAX_QLEN) {
+               ret = -EBUSY;
+               if (!(crypto_cmd->cmd->flags & CCP_CMD_MAY_BACKLOG))
+                       goto e_cpu;
+       }
+
+       /* Look for an entry with the same tfm.  If there is a cmd
+        * with the same tfm in the list for this cpu then the current
+        * cmd cannot be submitted to the CCP yet.
+        */
+       list_for_each_entry(tmp, &cpu_queue->cmds, entry) {
+               if (crypto_cmd->tfm != tmp->tfm)
+                       continue;
+               active = tmp;
+               break;
+       }
+
+       ret = -EINPROGRESS;
+       if (!active) {
+               ret = ccp_enqueue_cmd(crypto_cmd->cmd);
+               if (!ccp_crypto_success(ret))
+                       goto e_cpu;
+       }
+
+       if (cpu_queue->cmd_count >= CCP_CRYPTO_MAX_QLEN) {
+               ret = -EBUSY;
+               if (cpu_queue->backlog == &cpu_queue->cmds)
+                       cpu_queue->backlog = &crypto_cmd->entry;
+       }
+       crypto_cmd->ret = ret;
+
+       cpu_queue->cmd_count++;
+       list_add_tail(&crypto_cmd->entry, &cpu_queue->cmds);
+
+e_cpu:
+       put_cpu();
+
+       return ret;
+}
+
+/**
+ * ccp_crypto_enqueue_request - queue an crypto async request for processing
+ *                             by the CCP
+ *
+ * @req: crypto_async_request struct to be processed
+ * @cmd: ccp_cmd struct to be sent to the CCP
+ */
+int ccp_crypto_enqueue_request(struct crypto_async_request *req,
+                              struct ccp_cmd *cmd)
+{
+       struct ccp_crypto_cmd *crypto_cmd;
+       gfp_t gfp;
+       int ret;
+
+       gfp = req->flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL : GFP_ATOMIC;
+
+       crypto_cmd = kzalloc(sizeof(*crypto_cmd), gfp);
+       if (!crypto_cmd)
+               return -ENOMEM;
+
+       /* The tfm pointer must be saved and not referenced from the
+        * crypto_async_request (req) pointer because it is used after
+        * completion callback for the request and the req pointer
+        * might not be valid anymore.
+        */
+       crypto_cmd->cmd = cmd;
+       crypto_cmd->req = req;
+       crypto_cmd->tfm = req->tfm;
+
+       cmd->callback = ccp_crypto_complete;
+       cmd->data = crypto_cmd;
+
+       if (req->flags & CRYPTO_TFM_REQ_MAY_BACKLOG)
+               cmd->flags |= CCP_CMD_MAY_BACKLOG;
+       else
+               cmd->flags &= ~CCP_CMD_MAY_BACKLOG;
+
+       ret = ccp_crypto_enqueue_cmd(crypto_cmd);
+       if (!ccp_crypto_success(ret))
+               kfree(crypto_cmd);
+
+       return ret;
+}
+
+struct scatterlist *ccp_crypto_sg_table_add(struct sg_table *table,
+                                           struct scatterlist *sg_add)
+{
+       struct scatterlist *sg, *sg_last = NULL;
+
+       for (sg = table->sgl; sg; sg = sg_next(sg))
+               if (!sg_page(sg))
+                       break;
+       BUG_ON(!sg);
+
+       for (; sg && sg_add; sg = sg_next(sg), sg_add = sg_next(sg_add)) {
+               sg_set_page(sg, sg_page(sg_add), sg_add->length,
+                           sg_add->offset);
+               sg_last = sg;
+       }
+       BUG_ON(sg_add);
+
+       return sg_last;
+}
+
+static int ccp_register_algs(void)
+{
+       int ret;
+
+       ret = ccp_register_aes_algs(&cipher_algs);
+       if (ret)
+               return ret;
+
+       ret = ccp_register_aes_cmac_algs(&hash_algs);
+       if (ret)
+               return ret;
+
+       ret = ccp_register_aes_xts_algs(&cipher_algs);
+       if (ret)
+               return ret;
+
+       ret = ccp_register_sha_algs(&hash_algs);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static void ccp_unregister_algs(void)
+{
+       struct ccp_crypto_ahash_alg *ahash_alg, *ahash_tmp;
+       struct ccp_crypto_ablkcipher_alg *ablk_alg, *ablk_tmp;
+
+       list_for_each_entry_safe(ahash_alg, ahash_tmp, &hash_algs, entry) {
+               crypto_unregister_ahash(&ahash_alg->alg);
+               list_del(&ahash_alg->entry);
+               kfree(ahash_alg);
+       }
+
+       list_for_each_entry_safe(ablk_alg, ablk_tmp, &cipher_algs, entry) {
+               crypto_unregister_alg(&ablk_alg->alg);
+               list_del(&ablk_alg->entry);
+               kfree(ablk_alg);
+       }
+}
+
+static int ccp_init_queues(void)
+{
+       struct ccp_crypto_cpu_queue *cpu_queue;
+       int cpu;
+
+       req_queue.cpu_queue = alloc_percpu(struct ccp_crypto_cpu_queue);
+       if (!req_queue.cpu_queue)
+               return -ENOMEM;
+
+       for_each_possible_cpu(cpu) {
+               cpu_queue = per_cpu_ptr(req_queue.cpu_queue, cpu);
+               INIT_LIST_HEAD(&cpu_queue->cmds);
+               cpu_queue->backlog = &cpu_queue->cmds;
+               cpu_queue->cmd_count = 0;
+       }
+
+       return 0;
+}
+
+static void ccp_fini_queue(void)
+{
+       struct ccp_crypto_cpu_queue *cpu_queue;
+       int cpu;
+
+       for_each_possible_cpu(cpu) {
+               cpu_queue = per_cpu_ptr(req_queue.cpu_queue, cpu);
+               BUG_ON(!list_empty(&cpu_queue->cmds));
+       }
+       free_percpu(req_queue.cpu_queue);
+}
+
+static int ccp_crypto_init(void)
+{
+       int ret;
+
+       ret = ccp_init_queues();
+       if (ret)
+               return ret;
+
+       ret = ccp_register_algs();
+       if (ret) {
+               ccp_unregister_algs();
+               ccp_fini_queue();
+       }
+
+       return ret;
+}
+
+static void ccp_crypto_exit(void)
+{
+       ccp_unregister_algs();
+       ccp_fini_queue();
+}
+
+module_init(ccp_crypto_init);
+module_exit(ccp_crypto_exit);
diff --git a/drivers/crypto/ccp/ccp-crypto-sha.c b/drivers/crypto/ccp/ccp-crypto-sha.c
new file mode 100644 (file)
index 0000000..a6ef183
--- /dev/null
@@ -0,0 +1,497 @@
+/*
+ * AMD Cryptographic Coprocessor (CCP) SHA crypto API support
+ *
+ * Copyright (C) 2013 Advanced Micro Devices, Inc.
+ *
+ * Author: Tom Lendacky <thomas.lendacky@amd.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/module.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/scatterlist.h>
+#include <linux/crypto.h>
+#include <crypto/algapi.h>
+#include <crypto/hash.h>
+#include <crypto/internal/hash.h>
+#include <crypto/sha.h>
+#include <crypto/scatterwalk.h>
+
+#include "ccp-crypto.h"
+
+
+struct ccp_sha_result {
+       struct completion completion;
+       int err;
+};
+
+static void ccp_sync_hash_complete(struct crypto_async_request *req, int err)
+{
+       struct ccp_sha_result *result = req->data;
+
+       if (err == -EINPROGRESS)
+               return;
+
+       result->err = err;
+       complete(&result->completion);
+}
+
+static int ccp_sync_hash(struct crypto_ahash *tfm, u8 *buf,
+                        struct scatterlist *sg, unsigned int len)
+{
+       struct ccp_sha_result result;
+       struct ahash_request *req;
+       int ret;
+
+       init_completion(&result.completion);
+
+       req = ahash_request_alloc(tfm, GFP_KERNEL);
+       if (!req)
+               return -ENOMEM;
+
+       ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+                                  ccp_sync_hash_complete, &result);
+       ahash_request_set_crypt(req, sg, buf, len);
+
+       ret = crypto_ahash_digest(req);
+       if ((ret == -EINPROGRESS) || (ret == -EBUSY)) {
+               ret = wait_for_completion_interruptible(&result.completion);
+               if (!ret)
+                       ret = result.err;
+       }
+
+       ahash_request_free(req);
+
+       return ret;
+}
+
+static int ccp_sha_finish_hmac(struct crypto_async_request *async_req)
+{
+       struct ahash_request *req = ahash_request_cast(async_req);
+       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+       struct ccp_ctx *ctx = crypto_ahash_ctx(tfm);
+       struct scatterlist sg[2];
+       unsigned int block_size =
+               crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
+       unsigned int digest_size = crypto_ahash_digestsize(tfm);
+
+       sg_init_table(sg, ARRAY_SIZE(sg));
+       sg_set_buf(&sg[0], ctx->u.sha.opad, block_size);
+       sg_set_buf(&sg[1], req->result, digest_size);
+
+       return ccp_sync_hash(ctx->u.sha.hmac_tfm, req->result, sg,
+                            block_size + digest_size);
+}
+
+static int ccp_sha_complete(struct crypto_async_request *async_req, int ret)
+{
+       struct ahash_request *req = ahash_request_cast(async_req);
+       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+       struct ccp_ctx *ctx = crypto_ahash_ctx(tfm);
+       struct ccp_sha_req_ctx *rctx = ahash_request_ctx(req);
+       unsigned int digest_size = crypto_ahash_digestsize(tfm);
+
+       if (ret)
+               goto e_free;
+
+       if (rctx->hash_rem) {
+               /* Save remaining data to buffer */
+               scatterwalk_map_and_copy(rctx->buf, rctx->cmd.u.sha.src,
+                                        rctx->hash_cnt, rctx->hash_rem, 0);
+               rctx->buf_count = rctx->hash_rem;
+       } else
+               rctx->buf_count = 0;
+
+       memcpy(req->result, rctx->ctx, digest_size);
+
+       /* If we're doing an HMAC, we need to perform that on the final op */
+       if (rctx->final && ctx->u.sha.key_len)
+               ret = ccp_sha_finish_hmac(async_req);
+
+e_free:
+       sg_free_table(&rctx->data_sg);
+
+       return ret;
+}
+
+static int ccp_do_sha_update(struct ahash_request *req, unsigned int nbytes,
+                            unsigned int final)
+{
+       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+       struct ccp_ctx *ctx = crypto_ahash_ctx(tfm);
+       struct ccp_sha_req_ctx *rctx = ahash_request_ctx(req);
+       struct scatterlist *sg;
+       unsigned int block_size =
+               crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
+       unsigned int len, sg_count;
+       int ret;
+
+       if (!final && ((nbytes + rctx->buf_count) <= block_size)) {
+               scatterwalk_map_and_copy(rctx->buf + rctx->buf_count, req->src,
+                                        0, nbytes, 0);
+               rctx->buf_count += nbytes;
+
+               return 0;
+       }
+
+       len = rctx->buf_count + nbytes;
+
+       rctx->final = final;
+       rctx->hash_cnt = final ? len : len & ~(block_size - 1);
+       rctx->hash_rem = final ?   0 : len &  (block_size - 1);
+       if (!final && (rctx->hash_cnt == len)) {
+               /* CCP can't do zero length final, so keep some data around */
+               rctx->hash_cnt -= block_size;
+               rctx->hash_rem = block_size;
+       }
+
+       /* Initialize the context scatterlist */
+       sg_init_one(&rctx->ctx_sg, rctx->ctx, sizeof(rctx->ctx));
+
+       /* Build the data scatterlist table - allocate enough entries for all
+        * possible data pieces (hmac ipad, buffer, input data)
+        */
+       sg_count = (nbytes) ? sg_nents(req->src) + 2 : 2;
+       ret = sg_alloc_table(&rctx->data_sg, sg_count, GFP_KERNEL);
+       if (ret)
+               return ret;
+
+       sg = NULL;
+       if (rctx->first && ctx->u.sha.key_len) {
+               rctx->hash_cnt += block_size;
+
+               sg_init_one(&rctx->pad_sg, ctx->u.sha.ipad, block_size);
+               sg = ccp_crypto_sg_table_add(&rctx->data_sg, &rctx->pad_sg);
+       }
+
+       if (rctx->buf_count) {
+               sg_init_one(&rctx->buf_sg, rctx->buf, rctx->buf_count);
+               sg = ccp_crypto_sg_table_add(&rctx->data_sg, &rctx->buf_sg);
+       }
+
+       if (nbytes)
+               sg = ccp_crypto_sg_table_add(&rctx->data_sg, req->src);
+
+       if (sg)
+               sg_mark_end(sg);
+
+       rctx->msg_bits += (rctx->hash_cnt << 3);        /* Total in bits */
+
+       memset(&rctx->cmd, 0, sizeof(rctx->cmd));
+       INIT_LIST_HEAD(&rctx->cmd.entry);
+       rctx->cmd.engine = CCP_ENGINE_SHA;
+       rctx->cmd.u.sha.type = rctx->type;
+       rctx->cmd.u.sha.ctx = &rctx->ctx_sg;
+       rctx->cmd.u.sha.ctx_len = sizeof(rctx->ctx);
+       rctx->cmd.u.sha.src = (sg) ? rctx->data_sg.sgl : NULL;
+       rctx->cmd.u.sha.src_len = rctx->hash_cnt;
+       rctx->cmd.u.sha.final = rctx->final;
+       rctx->cmd.u.sha.msg_bits = rctx->msg_bits;
+
+       rctx->first = 0;
+
+       ret = ccp_crypto_enqueue_request(&req->base, &rctx->cmd);
+
+       return ret;
+}
+
+static int ccp_sha_init(struct ahash_request *req)
+{
+       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+       struct ccp_sha_req_ctx *rctx = ahash_request_ctx(req);
+       struct ccp_crypto_ahash_alg *alg =
+               ccp_crypto_ahash_alg(crypto_ahash_tfm(tfm));
+
+       memset(rctx, 0, sizeof(*rctx));
+
+       memcpy(rctx->ctx, alg->init, sizeof(rctx->ctx));
+       rctx->type = alg->type;
+       rctx->first = 1;
+
+       return 0;
+}
+
+static int ccp_sha_update(struct ahash_request *req)
+{
+       return ccp_do_sha_update(req, req->nbytes, 0);
+}
+
+static int ccp_sha_final(struct ahash_request *req)
+{
+       return ccp_do_sha_update(req, 0, 1);
+}
+
+static int ccp_sha_finup(struct ahash_request *req)
+{
+       return ccp_do_sha_update(req, req->nbytes, 1);
+}
+
+static int ccp_sha_digest(struct ahash_request *req)
+{
+       ccp_sha_init(req);
+
+       return ccp_do_sha_update(req, req->nbytes, 1);
+}
+
+static int ccp_sha_setkey(struct crypto_ahash *tfm, const u8 *key,
+                         unsigned int key_len)
+{
+       struct ccp_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
+       struct scatterlist sg;
+       unsigned int block_size =
+               crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
+       unsigned int digest_size = crypto_ahash_digestsize(tfm);
+       int i, ret;
+
+       /* Set to zero until complete */
+       ctx->u.sha.key_len = 0;
+
+       /* Clear key area to provide zero padding for keys smaller
+        * than the block size
+        */
+       memset(ctx->u.sha.key, 0, sizeof(ctx->u.sha.key));
+
+       if (key_len > block_size) {
+               /* Must hash the input key */
+               sg_init_one(&sg, key, key_len);
+               ret = ccp_sync_hash(tfm, ctx->u.sha.key, &sg, key_len);
+               if (ret) {
+                       crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+                       return -EINVAL;
+               }
+
+               key_len = digest_size;
+       } else
+               memcpy(ctx->u.sha.key, key, key_len);
+
+       for (i = 0; i < block_size; i++) {
+               ctx->u.sha.ipad[i] = ctx->u.sha.key[i] ^ 0x36;
+               ctx->u.sha.opad[i] = ctx->u.sha.key[i] ^ 0x5c;
+       }
+
+       ctx->u.sha.key_len = key_len;
+
+       return 0;
+}
+
+static int ccp_sha_cra_init(struct crypto_tfm *tfm)
+{
+       struct ccp_ctx *ctx = crypto_tfm_ctx(tfm);
+       struct crypto_ahash *ahash = __crypto_ahash_cast(tfm);
+
+       ctx->complete = ccp_sha_complete;
+       ctx->u.sha.key_len = 0;
+
+       crypto_ahash_set_reqsize(ahash, sizeof(struct ccp_sha_req_ctx));
+
+       return 0;
+}
+
+static void ccp_sha_cra_exit(struct crypto_tfm *tfm)
+{
+}
+
+static int ccp_hmac_sha_cra_init(struct crypto_tfm *tfm)
+{
+       struct ccp_ctx *ctx = crypto_tfm_ctx(tfm);
+       struct ccp_crypto_ahash_alg *alg = ccp_crypto_ahash_alg(tfm);
+       struct crypto_ahash *hmac_tfm;
+
+       hmac_tfm = crypto_alloc_ahash(alg->child_alg,
+                                     CRYPTO_ALG_TYPE_AHASH, 0);
+       if (IS_ERR(hmac_tfm)) {
+               pr_warn("could not load driver %s need for HMAC support\n",
+                       alg->child_alg);
+               return PTR_ERR(hmac_tfm);
+       }
+
+       ctx->u.sha.hmac_tfm = hmac_tfm;
+
+       return ccp_sha_cra_init(tfm);
+}
+
+static void ccp_hmac_sha_cra_exit(struct crypto_tfm *tfm)
+{
+       struct ccp_ctx *ctx = crypto_tfm_ctx(tfm);
+
+       if (ctx->u.sha.hmac_tfm)
+               crypto_free_ahash(ctx->u.sha.hmac_tfm);
+
+       ccp_sha_cra_exit(tfm);
+}
+
+static const u32 sha1_init[CCP_SHA_CTXSIZE / sizeof(u32)] = {
+       cpu_to_be32(SHA1_H0), cpu_to_be32(SHA1_H1),
+       cpu_to_be32(SHA1_H2), cpu_to_be32(SHA1_H3),
+       cpu_to_be32(SHA1_H4), 0, 0, 0,
+};
+
+static const u32 sha224_init[CCP_SHA_CTXSIZE / sizeof(u32)] = {
+       cpu_to_be32(SHA224_H0), cpu_to_be32(SHA224_H1),
+       cpu_to_be32(SHA224_H2), cpu_to_be32(SHA224_H3),
+       cpu_to_be32(SHA224_H4), cpu_to_be32(SHA224_H5),
+       cpu_to_be32(SHA224_H6), cpu_to_be32(SHA224_H7),
+};
+
+static const u32 sha256_init[CCP_SHA_CTXSIZE / sizeof(u32)] = {
+       cpu_to_be32(SHA256_H0), cpu_to_be32(SHA256_H1),
+       cpu_to_be32(SHA256_H2), cpu_to_be32(SHA256_H3),
+       cpu_to_be32(SHA256_H4), cpu_to_be32(SHA256_H5),
+       cpu_to_be32(SHA256_H6), cpu_to_be32(SHA256_H7),
+};
+
+struct ccp_sha_def {
+       const char *name;
+       const char *drv_name;
+       const u32 *init;
+       enum ccp_sha_type type;
+       u32 digest_size;
+       u32 block_size;
+};
+
+static struct ccp_sha_def sha_algs[] = {
+       {
+               .name           = "sha1",
+               .drv_name       = "sha1-ccp",
+               .init           = sha1_init,
+               .type           = CCP_SHA_TYPE_1,
+               .digest_size    = SHA1_DIGEST_SIZE,
+               .block_size     = SHA1_BLOCK_SIZE,
+       },
+       {
+               .name           = "sha224",
+               .drv_name       = "sha224-ccp",
+               .init           = sha224_init,
+               .type           = CCP_SHA_TYPE_224,
+               .digest_size    = SHA224_DIGEST_SIZE,
+               .block_size     = SHA224_BLOCK_SIZE,
+       },
+       {
+               .name           = "sha256",
+               .drv_name       = "sha256-ccp",
+               .init           = sha256_init,
+               .type           = CCP_SHA_TYPE_256,
+               .digest_size    = SHA256_DIGEST_SIZE,
+               .block_size     = SHA256_BLOCK_SIZE,
+       },
+};
+
+static int ccp_register_hmac_alg(struct list_head *head,
+                                const struct ccp_sha_def *def,
+                                const struct ccp_crypto_ahash_alg *base_alg)
+{
+       struct ccp_crypto_ahash_alg *ccp_alg;
+       struct ahash_alg *alg;
+       struct hash_alg_common *halg;
+       struct crypto_alg *base;
+       int ret;
+
+       ccp_alg = kzalloc(sizeof(*ccp_alg), GFP_KERNEL);
+       if (!ccp_alg)
+               return -ENOMEM;
+
+       /* Copy the base algorithm and only change what's necessary */
+       *ccp_alg = *base_alg;
+       INIT_LIST_HEAD(&ccp_alg->entry);
+
+       strncpy(ccp_alg->child_alg, def->name, CRYPTO_MAX_ALG_NAME);
+
+       alg = &ccp_alg->alg;
+       alg->setkey = ccp_sha_setkey;
+
+       halg = &alg->halg;
+
+       base = &halg->base;
+       snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME, "hmac(%s)", def->name);
+       snprintf(base->cra_driver_name, CRYPTO_MAX_ALG_NAME, "hmac-%s",
+                def->drv_name);
+       base->cra_init = ccp_hmac_sha_cra_init;
+       base->cra_exit = ccp_hmac_sha_cra_exit;
+
+       ret = crypto_register_ahash(alg);
+       if (ret) {
+               pr_err("%s ahash algorithm registration error (%d)\n",
+                       base->cra_name, ret);
+               kfree(ccp_alg);
+               return ret;
+       }
+
+       list_add(&ccp_alg->entry, head);
+
+       return ret;
+}
+
+static int ccp_register_sha_alg(struct list_head *head,
+                               const struct ccp_sha_def *def)
+{
+       struct ccp_crypto_ahash_alg *ccp_alg;
+       struct ahash_alg *alg;
+       struct hash_alg_common *halg;
+       struct crypto_alg *base;
+       int ret;
+
+       ccp_alg = kzalloc(sizeof(*ccp_alg), GFP_KERNEL);
+       if (!ccp_alg)
+               return -ENOMEM;
+
+       INIT_LIST_HEAD(&ccp_alg->entry);
+
+       ccp_alg->init = def->init;
+       ccp_alg->type = def->type;
+
+       alg = &ccp_alg->alg;
+       alg->init = ccp_sha_init;
+       alg->update = ccp_sha_update;
+       alg->final = ccp_sha_final;
+       alg->finup = ccp_sha_finup;
+       alg->digest = ccp_sha_digest;
+
+       halg = &alg->halg;
+       halg->digestsize = def->digest_size;
+
+       base = &halg->base;
+       snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name);
+       snprintf(base->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
+                def->drv_name);
+       base->cra_flags = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC |
+                         CRYPTO_ALG_KERN_DRIVER_ONLY |
+                         CRYPTO_ALG_NEED_FALLBACK;
+       base->cra_blocksize = def->block_size;
+       base->cra_ctxsize = sizeof(struct ccp_ctx);
+       base->cra_priority = CCP_CRA_PRIORITY;
+       base->cra_type = &crypto_ahash_type;
+       base->cra_init = ccp_sha_cra_init;
+       base->cra_exit = ccp_sha_cra_exit;
+       base->cra_module = THIS_MODULE;
+
+       ret = crypto_register_ahash(alg);
+       if (ret) {
+               pr_err("%s ahash algorithm registration error (%d)\n",
+                       base->cra_name, ret);
+               kfree(ccp_alg);
+               return ret;
+       }
+
+       list_add(&ccp_alg->entry, head);
+
+       ret = ccp_register_hmac_alg(head, def, ccp_alg);
+
+       return ret;
+}
+
+int ccp_register_sha_algs(struct list_head *head)
+{
+       int i, ret;
+
+       for (i = 0; i < ARRAY_SIZE(sha_algs); i++) {
+               ret = ccp_register_sha_alg(head, &sha_algs[i]);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
diff --git a/drivers/crypto/ccp/ccp-crypto.h b/drivers/crypto/ccp/ccp-crypto.h
new file mode 100644 (file)
index 0000000..45f17c3
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * AMD Cryptographic Coprocessor (CCP) crypto API support
+ *
+ * Copyright (C) 2013 Advanced Micro Devices, Inc.
+ *
+ * Author: Tom Lendacky <thomas.lendacky@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __CCP_CRYPTO_H__
+#define __CCP_CRYPTO_H__
+
+
+#include <linux/list.h>
+#include <linux/wait.h>
+#include <linux/pci.h>
+#include <linux/ccp.h>
+#include <linux/crypto.h>
+#include <crypto/algapi.h>
+#include <crypto/aes.h>
+#include <crypto/ctr.h>
+#include <crypto/hash.h>
+#include <crypto/sha.h>
+
+
+#define CCP_CRA_PRIORITY       300
+
+struct ccp_crypto_ablkcipher_alg {
+       struct list_head entry;
+
+       u32 mode;
+
+       struct crypto_alg alg;
+};
+
+struct ccp_crypto_ahash_alg {
+       struct list_head entry;
+
+       const u32 *init;
+       u32 type;
+       u32 mode;
+
+       /* Child algorithm used for HMAC, CMAC, etc */
+       char child_alg[CRYPTO_MAX_ALG_NAME];
+
+       struct ahash_alg alg;
+};
+
+static inline struct ccp_crypto_ablkcipher_alg *
+       ccp_crypto_ablkcipher_alg(struct crypto_tfm *tfm)
+{
+       struct crypto_alg *alg = tfm->__crt_alg;
+
+       return container_of(alg, struct ccp_crypto_ablkcipher_alg, alg);
+}
+
+static inline struct ccp_crypto_ahash_alg *
+       ccp_crypto_ahash_alg(struct crypto_tfm *tfm)
+{
+       struct crypto_alg *alg = tfm->__crt_alg;
+       struct ahash_alg *ahash_alg;
+
+       ahash_alg = container_of(alg, struct ahash_alg, halg.base);
+
+       return container_of(ahash_alg, struct ccp_crypto_ahash_alg, alg);
+}
+
+
+/***** AES related defines *****/
+struct ccp_aes_ctx {
+       /* Fallback cipher for XTS with unsupported unit sizes */
+       struct crypto_ablkcipher *tfm_ablkcipher;
+
+       /* Cipher used to generate CMAC K1/K2 keys */
+       struct crypto_cipher *tfm_cipher;
+
+       enum ccp_engine engine;
+       enum ccp_aes_type type;
+       enum ccp_aes_mode mode;
+
+       struct scatterlist key_sg;
+       unsigned int key_len;
+       u8 key[AES_MAX_KEY_SIZE];
+
+       u8 nonce[CTR_RFC3686_NONCE_SIZE];
+
+       /* CMAC key structures */
+       struct scatterlist k1_sg;
+       struct scatterlist k2_sg;
+       unsigned int kn_len;
+       u8 k1[AES_BLOCK_SIZE];
+       u8 k2[AES_BLOCK_SIZE];
+};
+
+struct ccp_aes_req_ctx {
+       struct scatterlist iv_sg;
+       u8 iv[AES_BLOCK_SIZE];
+
+       /* Fields used for RFC3686 requests */
+       u8 *rfc3686_info;
+       u8 rfc3686_iv[AES_BLOCK_SIZE];
+
+       struct ccp_cmd cmd;
+};
+
+struct ccp_aes_cmac_req_ctx {
+       unsigned int null_msg;
+       unsigned int final;
+
+       unsigned int hash_cnt;
+       unsigned int hash_rem;
+
+       struct sg_table data_sg;
+
+       struct scatterlist iv_sg;
+       u8 iv[AES_BLOCK_SIZE];
+
+       struct scatterlist buf_sg;
+       unsigned int buf_count;
+       u8 buf[AES_BLOCK_SIZE];
+
+       struct scatterlist pad_sg;
+       unsigned int pad_count;
+       u8 pad[AES_BLOCK_SIZE];
+
+       struct ccp_cmd cmd;
+};
+
+/***** SHA related defines *****/
+#define MAX_SHA_CONTEXT_SIZE   SHA256_DIGEST_SIZE
+#define MAX_SHA_BLOCK_SIZE     SHA256_BLOCK_SIZE
+
+struct ccp_sha_ctx {
+       unsigned int key_len;
+       u8 key[MAX_SHA_BLOCK_SIZE];
+       u8 ipad[MAX_SHA_BLOCK_SIZE];
+       u8 opad[MAX_SHA_BLOCK_SIZE];
+       struct crypto_ahash *hmac_tfm;
+};
+
+struct ccp_sha_req_ctx {
+       enum ccp_sha_type type;
+
+       u64 msg_bits;
+
+       unsigned int first;
+       unsigned int final;
+
+       unsigned int hash_cnt;
+       unsigned int hash_rem;
+
+       struct sg_table data_sg;
+
+       struct scatterlist ctx_sg;
+       u8 ctx[MAX_SHA_CONTEXT_SIZE];
+
+       struct scatterlist buf_sg;
+       unsigned int buf_count;
+       u8 buf[MAX_SHA_BLOCK_SIZE];
+
+       /* HMAC support field */
+       struct scatterlist pad_sg;
+
+       /* CCP driver command */
+       struct ccp_cmd cmd;
+};
+
+/***** Common Context Structure *****/
+struct ccp_ctx {
+       int (*complete)(struct crypto_async_request *req, int ret);
+
+       union {
+               struct ccp_aes_ctx aes;
+               struct ccp_sha_ctx sha;
+       } u;
+};
+
+int ccp_crypto_enqueue_request(struct crypto_async_request *req,
+                              struct ccp_cmd *cmd);
+struct scatterlist *ccp_crypto_sg_table_add(struct sg_table *table,
+                                           struct scatterlist *sg_add);
+
+int ccp_register_aes_algs(struct list_head *head);
+int ccp_register_aes_cmac_algs(struct list_head *head);
+int ccp_register_aes_xts_algs(struct list_head *head);
+int ccp_register_sha_algs(struct list_head *head);
+
+#endif
diff --git a/drivers/crypto/ccp/ccp-dev.c b/drivers/crypto/ccp/ccp-dev.c
new file mode 100644 (file)
index 0000000..b2038a7
--- /dev/null
@@ -0,0 +1,582 @@
+/*
+ * AMD Cryptographic Coprocessor (CCP) driver
+ *
+ * Copyright (C) 2013 Advanced Micro Devices, Inc.
+ *
+ * Author: Tom Lendacky <thomas.lendacky@amd.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/module.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/hw_random.h>
+#include <linux/cpu.h>
+#include <asm/cpu_device_id.h>
+#include <linux/ccp.h>
+
+#include "ccp-dev.h"
+
+MODULE_AUTHOR("Tom Lendacky <thomas.lendacky@amd.com>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0.0");
+MODULE_DESCRIPTION("AMD Cryptographic Coprocessor driver");
+
+
+static struct ccp_device *ccp_dev;
+static inline struct ccp_device *ccp_get_device(void)
+{
+       return ccp_dev;
+}
+
+static inline void ccp_add_device(struct ccp_device *ccp)
+{
+       ccp_dev = ccp;
+}
+
+static inline void ccp_del_device(struct ccp_device *ccp)
+{
+       ccp_dev = NULL;
+}
+
+/**
+ * ccp_enqueue_cmd - queue an operation for processing by the CCP
+ *
+ * @cmd: ccp_cmd struct to be processed
+ *
+ * Queue a cmd to be processed by the CCP. If queueing the cmd
+ * would exceed the defined length of the cmd queue the cmd will
+ * only be queued if the CCP_CMD_MAY_BACKLOG flag is set and will
+ * result in a return code of -EBUSY.
+ *
+ * The callback routine specified in the ccp_cmd struct will be
+ * called to notify the caller of completion (if the cmd was not
+ * backlogged) or advancement out of the backlog. If the cmd has
+ * advanced out of the backlog the "err" value of the callback
+ * will be -EINPROGRESS. Any other "err" value during callback is
+ * the result of the operation.
+ *
+ * The cmd has been successfully queued if:
+ *   the return code is -EINPROGRESS or
+ *   the return code is -EBUSY and CCP_CMD_MAY_BACKLOG flag is set
+ */
+int ccp_enqueue_cmd(struct ccp_cmd *cmd)
+{
+       struct ccp_device *ccp = ccp_get_device();
+       unsigned long flags;
+       unsigned int i;
+       int ret;
+
+       if (!ccp)
+               return -ENODEV;
+
+       /* Caller must supply a callback routine */
+       if (!cmd->callback)
+               return -EINVAL;
+
+       cmd->ccp = ccp;
+
+       spin_lock_irqsave(&ccp->cmd_lock, flags);
+
+       i = ccp->cmd_q_count;
+
+       if (ccp->cmd_count >= MAX_CMD_QLEN) {
+               ret = -EBUSY;
+               if (cmd->flags & CCP_CMD_MAY_BACKLOG)
+                       list_add_tail(&cmd->entry, &ccp->backlog);
+       } else {
+               ret = -EINPROGRESS;
+               ccp->cmd_count++;
+               list_add_tail(&cmd->entry, &ccp->cmd);
+
+               /* Find an idle queue */
+               if (!ccp->suspending) {
+                       for (i = 0; i < ccp->cmd_q_count; i++) {
+                               if (ccp->cmd_q[i].active)
+                                       continue;
+
+                               break;
+                       }
+               }
+       }
+
+       spin_unlock_irqrestore(&ccp->cmd_lock, flags);
+
+       /* If we found an idle queue, wake it up */
+       if (i < ccp->cmd_q_count)
+               wake_up_process(ccp->cmd_q[i].kthread);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(ccp_enqueue_cmd);
+
+static void ccp_do_cmd_backlog(struct work_struct *work)
+{
+       struct ccp_cmd *cmd = container_of(work, struct ccp_cmd, work);
+       struct ccp_device *ccp = cmd->ccp;
+       unsigned long flags;
+       unsigned int i;
+
+       cmd->callback(cmd->data, -EINPROGRESS);
+
+       spin_lock_irqsave(&ccp->cmd_lock, flags);
+
+       ccp->cmd_count++;
+       list_add_tail(&cmd->entry, &ccp->cmd);
+
+       /* Find an idle queue */
+       for (i = 0; i < ccp->cmd_q_count; i++) {
+               if (ccp->cmd_q[i].active)
+                       continue;
+
+               break;
+       }
+
+       spin_unlock_irqrestore(&ccp->cmd_lock, flags);
+
+       /* If we found an idle queue, wake it up */
+       if (i < ccp->cmd_q_count)
+               wake_up_process(ccp->cmd_q[i].kthread);
+}
+
+static struct ccp_cmd *ccp_dequeue_cmd(struct ccp_cmd_queue *cmd_q)
+{
+       struct ccp_device *ccp = cmd_q->ccp;
+       struct ccp_cmd *cmd = NULL;
+       struct ccp_cmd *backlog = NULL;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ccp->cmd_lock, flags);
+
+       cmd_q->active = 0;
+
+       if (ccp->suspending) {
+               cmd_q->suspended = 1;
+
+               spin_unlock_irqrestore(&ccp->cmd_lock, flags);
+               wake_up_interruptible(&ccp->suspend_queue);
+
+               return NULL;
+       }
+
+       if (ccp->cmd_count) {
+               cmd_q->active = 1;
+
+               cmd = list_first_entry(&ccp->cmd, struct ccp_cmd, entry);
+               list_del(&cmd->entry);
+
+               ccp->cmd_count--;
+       }
+
+       if (!list_empty(&ccp->backlog)) {
+               backlog = list_first_entry(&ccp->backlog, struct ccp_cmd,
+                                          entry);
+               list_del(&backlog->entry);
+       }
+
+       spin_unlock_irqrestore(&ccp->cmd_lock, flags);
+
+       if (backlog) {
+               INIT_WORK(&backlog->work, ccp_do_cmd_backlog);
+               schedule_work(&backlog->work);
+       }
+
+       return cmd;
+}
+
+static void ccp_do_cmd_complete(struct work_struct *work)
+{
+       struct ccp_cmd *cmd = container_of(work, struct ccp_cmd, work);
+
+       cmd->callback(cmd->data, cmd->ret);
+}
+
+static int ccp_cmd_queue_thread(void *data)
+{
+       struct ccp_cmd_queue *cmd_q = (struct ccp_cmd_queue *)data;
+       struct ccp_cmd *cmd;
+
+       set_current_state(TASK_INTERRUPTIBLE);
+       while (!kthread_should_stop()) {
+               schedule();
+
+               set_current_state(TASK_INTERRUPTIBLE);
+
+               cmd = ccp_dequeue_cmd(cmd_q);
+               if (!cmd)
+                       continue;
+
+               __set_current_state(TASK_RUNNING);
+
+               /* Execute the command */
+               cmd->ret = ccp_run_cmd(cmd_q, cmd);
+
+               /* Schedule the completion callback */
+               INIT_WORK(&cmd->work, ccp_do_cmd_complete);
+               schedule_work(&cmd->work);
+       }
+
+       __set_current_state(TASK_RUNNING);
+
+       return 0;
+}
+
+static int ccp_trng_read(struct hwrng *rng, void *data, size_t max, bool wait)
+{
+       struct ccp_device *ccp = container_of(rng, struct ccp_device, hwrng);
+       u32 trng_value;
+       int len = min_t(int, sizeof(trng_value), max);
+
+       /*
+        * Locking is provided by the caller so we can update device
+        * hwrng-related fields safely
+        */
+       trng_value = ioread32(ccp->io_regs + TRNG_OUT_REG);
+       if (!trng_value) {
+               /* Zero is returned if not data is available or if a
+                * bad-entropy error is present. Assume an error if
+                * we exceed TRNG_RETRIES reads of zero.
+                */
+               if (ccp->hwrng_retries++ > TRNG_RETRIES)
+                       return -EIO;
+
+               return 0;
+       }
+
+       /* Reset the counter and save the rng value */
+       ccp->hwrng_retries = 0;
+       memcpy(data, &trng_value, len);
+
+       return len;
+}
+
+/**
+ * ccp_alloc_struct - allocate and initialize the ccp_device struct
+ *
+ * @dev: device struct of the CCP
+ */
+struct ccp_device *ccp_alloc_struct(struct device *dev)
+{
+       struct ccp_device *ccp;
+
+       ccp = kzalloc(sizeof(*ccp), GFP_KERNEL);
+       if (ccp == NULL) {
+               dev_err(dev, "unable to allocate device struct\n");
+               return NULL;
+       }
+       ccp->dev = dev;
+
+       INIT_LIST_HEAD(&ccp->cmd);
+       INIT_LIST_HEAD(&ccp->backlog);
+
+       spin_lock_init(&ccp->cmd_lock);
+       mutex_init(&ccp->req_mutex);
+       mutex_init(&ccp->ksb_mutex);
+       ccp->ksb_count = KSB_COUNT;
+       ccp->ksb_start = 0;
+
+       return ccp;
+}
+
+/**
+ * ccp_init - initialize the CCP device
+ *
+ * @ccp: ccp_device struct
+ */
+int ccp_init(struct ccp_device *ccp)
+{
+       struct device *dev = ccp->dev;
+       struct ccp_cmd_queue *cmd_q;
+       struct dma_pool *dma_pool;
+       char dma_pool_name[MAX_DMAPOOL_NAME_LEN];
+       unsigned int qmr, qim, i;
+       int ret;
+
+       /* Find available queues */
+       qim = 0;
+       qmr = ioread32(ccp->io_regs + Q_MASK_REG);
+       for (i = 0; i < MAX_HW_QUEUES; i++) {
+               if (!(qmr & (1 << i)))
+                       continue;
+
+               /* Allocate a dma pool for this queue */
+               snprintf(dma_pool_name, sizeof(dma_pool_name), "ccp_q%d", i);
+               dma_pool = dma_pool_create(dma_pool_name, dev,
+                                          CCP_DMAPOOL_MAX_SIZE,
+                                          CCP_DMAPOOL_ALIGN, 0);
+               if (!dma_pool) {
+                       dev_err(dev, "unable to allocate dma pool\n");
+                       ret = -ENOMEM;
+                       goto e_pool;
+               }
+
+               cmd_q = &ccp->cmd_q[ccp->cmd_q_count];
+               ccp->cmd_q_count++;
+
+               cmd_q->ccp = ccp;
+               cmd_q->id = i;
+               cmd_q->dma_pool = dma_pool;
+
+               /* Reserve 2 KSB regions for the queue */
+               cmd_q->ksb_key = KSB_START + ccp->ksb_start++;
+               cmd_q->ksb_ctx = KSB_START + ccp->ksb_start++;
+               ccp->ksb_count -= 2;
+
+               /* Preset some register values and masks that are queue
+                * number dependent
+                */
+               cmd_q->reg_status = ccp->io_regs + CMD_Q_STATUS_BASE +
+                                   (CMD_Q_STATUS_INCR * i);
+               cmd_q->reg_int_status = ccp->io_regs + CMD_Q_INT_STATUS_BASE +
+                                       (CMD_Q_STATUS_INCR * i);
+               cmd_q->int_ok = 1 << (i * 2);
+               cmd_q->int_err = 1 << ((i * 2) + 1);
+
+               cmd_q->free_slots = CMD_Q_DEPTH(ioread32(cmd_q->reg_status));
+
+               init_waitqueue_head(&cmd_q->int_queue);
+
+               /* Build queue interrupt mask (two interrupts per queue) */
+               qim |= cmd_q->int_ok | cmd_q->int_err;
+
+               dev_dbg(dev, "queue #%u available\n", i);
+       }
+       if (ccp->cmd_q_count == 0) {
+               dev_notice(dev, "no command queues available\n");
+               ret = -EIO;
+               goto e_pool;
+       }
+       dev_notice(dev, "%u command queues available\n", ccp->cmd_q_count);
+
+       /* Disable and clear interrupts until ready */
+       iowrite32(0x00, ccp->io_regs + IRQ_MASK_REG);
+       for (i = 0; i < ccp->cmd_q_count; i++) {
+               cmd_q = &ccp->cmd_q[i];
+
+               ioread32(cmd_q->reg_int_status);
+               ioread32(cmd_q->reg_status);
+       }
+       iowrite32(qim, ccp->io_regs + IRQ_STATUS_REG);
+
+       /* Request an irq */
+       ret = ccp->get_irq(ccp);
+       if (ret) {
+               dev_err(dev, "unable to allocate an IRQ\n");
+               goto e_pool;
+       }
+
+       /* Initialize the queues used to wait for KSB space and suspend */
+       init_waitqueue_head(&ccp->ksb_queue);
+       init_waitqueue_head(&ccp->suspend_queue);
+
+       /* Create a kthread for each queue */
+       for (i = 0; i < ccp->cmd_q_count; i++) {
+               struct task_struct *kthread;
+
+               cmd_q = &ccp->cmd_q[i];
+
+               kthread = kthread_create(ccp_cmd_queue_thread, cmd_q,
+                                        "ccp-q%u", cmd_q->id);
+               if (IS_ERR(kthread)) {
+                       dev_err(dev, "error creating queue thread (%ld)\n",
+                               PTR_ERR(kthread));
+                       ret = PTR_ERR(kthread);
+                       goto e_kthread;
+               }
+
+               cmd_q->kthread = kthread;
+               wake_up_process(kthread);
+       }
+
+       /* Register the RNG */
+       ccp->hwrng.name = "ccp-rng";
+       ccp->hwrng.read = ccp_trng_read;
+       ret = hwrng_register(&ccp->hwrng);
+       if (ret) {
+               dev_err(dev, "error registering hwrng (%d)\n", ret);
+               goto e_kthread;
+       }
+
+       /* Make the device struct available before enabling interrupts */
+       ccp_add_device(ccp);
+
+       /* Enable interrupts */
+       iowrite32(qim, ccp->io_regs + IRQ_MASK_REG);
+
+       return 0;
+
+e_kthread:
+       for (i = 0; i < ccp->cmd_q_count; i++)
+               if (ccp->cmd_q[i].kthread)
+                       kthread_stop(ccp->cmd_q[i].kthread);
+
+       ccp->free_irq(ccp);
+
+e_pool:
+       for (i = 0; i < ccp->cmd_q_count; i++)
+               dma_pool_destroy(ccp->cmd_q[i].dma_pool);
+
+       return ret;
+}
+
+/**
+ * ccp_destroy - tear down the CCP device
+ *
+ * @ccp: ccp_device struct
+ */
+void ccp_destroy(struct ccp_device *ccp)
+{
+       struct ccp_cmd_queue *cmd_q;
+       struct ccp_cmd *cmd;
+       unsigned int qim, i;
+
+       /* Remove general access to the device struct */
+       ccp_del_device(ccp);
+
+       /* Unregister the RNG */
+       hwrng_unregister(&ccp->hwrng);
+
+       /* Stop the queue kthreads */
+       for (i = 0; i < ccp->cmd_q_count; i++)
+               if (ccp->cmd_q[i].kthread)
+                       kthread_stop(ccp->cmd_q[i].kthread);
+
+       /* Build queue interrupt mask (two interrupt masks per queue) */
+       qim = 0;
+       for (i = 0; i < ccp->cmd_q_count; i++) {
+               cmd_q = &ccp->cmd_q[i];
+               qim |= cmd_q->int_ok | cmd_q->int_err;
+       }
+
+       /* Disable and clear interrupts */
+       iowrite32(0x00, ccp->io_regs + IRQ_MASK_REG);
+       for (i = 0; i < ccp->cmd_q_count; i++) {
+               cmd_q = &ccp->cmd_q[i];
+
+               ioread32(cmd_q->reg_int_status);
+               ioread32(cmd_q->reg_status);
+       }
+       iowrite32(qim, ccp->io_regs + IRQ_STATUS_REG);
+
+       ccp->free_irq(ccp);
+
+       for (i = 0; i < ccp->cmd_q_count; i++)
+               dma_pool_destroy(ccp->cmd_q[i].dma_pool);
+
+       /* Flush the cmd and backlog queue */
+       while (!list_empty(&ccp->cmd)) {
+               /* Invoke the callback directly with an error code */
+               cmd = list_first_entry(&ccp->cmd, struct ccp_cmd, entry);
+               list_del(&cmd->entry);
+               cmd->callback(cmd->data, -ENODEV);
+       }
+       while (!list_empty(&ccp->backlog)) {
+               /* Invoke the callback directly with an error code */
+               cmd = list_first_entry(&ccp->backlog, struct ccp_cmd, entry);
+               list_del(&cmd->entry);
+               cmd->callback(cmd->data, -ENODEV);
+       }
+}
+
+/**
+ * ccp_irq_handler - handle interrupts generated by the CCP device
+ *
+ * @irq: the irq associated with the interrupt
+ * @data: the data value supplied when the irq was created
+ */
+irqreturn_t ccp_irq_handler(int irq, void *data)
+{
+       struct device *dev = data;
+       struct ccp_device *ccp = dev_get_drvdata(dev);
+       struct ccp_cmd_queue *cmd_q;
+       u32 q_int, status;
+       unsigned int i;
+
+       status = ioread32(ccp->io_regs + IRQ_STATUS_REG);
+
+       for (i = 0; i < ccp->cmd_q_count; i++) {
+               cmd_q = &ccp->cmd_q[i];
+
+               q_int = status & (cmd_q->int_ok | cmd_q->int_err);
+               if (q_int) {
+                       cmd_q->int_status = status;
+                       cmd_q->q_status = ioread32(cmd_q->reg_status);
+                       cmd_q->q_int_status = ioread32(cmd_q->reg_int_status);
+
+                       /* On error, only save the first error value */
+                       if ((q_int & cmd_q->int_err) && !cmd_q->cmd_error)
+                               cmd_q->cmd_error = CMD_Q_ERROR(cmd_q->q_status);
+
+                       cmd_q->int_rcvd = 1;
+
+                       /* Acknowledge the interrupt and wake the kthread */
+                       iowrite32(q_int, ccp->io_regs + IRQ_STATUS_REG);
+                       wake_up_interruptible(&cmd_q->int_queue);
+               }
+       }
+
+       return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_PM
+bool ccp_queues_suspended(struct ccp_device *ccp)
+{
+       unsigned int suspended = 0;
+       unsigned long flags;
+       unsigned int i;
+
+       spin_lock_irqsave(&ccp->cmd_lock, flags);
+
+       for (i = 0; i < ccp->cmd_q_count; i++)
+               if (ccp->cmd_q[i].suspended)
+                       suspended++;
+
+       spin_unlock_irqrestore(&ccp->cmd_lock, flags);
+
+       return ccp->cmd_q_count == suspended;
+}
+#endif
+
+static const struct x86_cpu_id ccp_support[] = {
+       { X86_VENDOR_AMD, 22, },
+};
+
+static int __init ccp_mod_init(void)
+{
+       struct cpuinfo_x86 *cpuinfo = &boot_cpu_data;
+
+       if (!x86_match_cpu(ccp_support))
+               return -ENODEV;
+
+       switch (cpuinfo->x86) {
+       case 22:
+               if ((cpuinfo->x86_model < 48) || (cpuinfo->x86_model > 63))
+                       return -ENODEV;
+               return ccp_pci_init();
+               break;
+       }
+
+       return -ENODEV;
+}
+
+static void __exit ccp_mod_exit(void)
+{
+       struct cpuinfo_x86 *cpuinfo = &boot_cpu_data;
+
+       switch (cpuinfo->x86) {
+       case 22:
+               ccp_pci_exit();
+               break;
+       }
+}
+
+module_init(ccp_mod_init);
+module_exit(ccp_mod_exit);
diff --git a/drivers/crypto/ccp/ccp-dev.h b/drivers/crypto/ccp/ccp-dev.h
new file mode 100644 (file)
index 0000000..7ec536e
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ * AMD Cryptographic Coprocessor (CCP) driver
+ *
+ * Copyright (C) 2013 Advanced Micro Devices, Inc.
+ *
+ * Author: Tom Lendacky <thomas.lendacky@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __CCP_DEV_H__
+#define __CCP_DEV_H__
+
+#include <linux/device.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+#include <linux/list.h>
+#include <linux/wait.h>
+#include <linux/dmapool.h>
+#include <linux/hw_random.h>
+
+
+#define IO_OFFSET                      0x20000
+
+#define MAX_DMAPOOL_NAME_LEN           32
+
+#define MAX_HW_QUEUES                  5
+#define MAX_CMD_QLEN                   100
+
+#define TRNG_RETRIES                   10
+
+
+/****** Register Mappings ******/
+#define Q_MASK_REG                     0x000
+#define TRNG_OUT_REG                   0x00c
+#define IRQ_MASK_REG                   0x040
+#define IRQ_STATUS_REG                 0x200
+
+#define DEL_CMD_Q_JOB                  0x124
+#define DEL_Q_ACTIVE                   0x00000200
+#define DEL_Q_ID_SHIFT                 6
+
+#define CMD_REQ0                       0x180
+#define CMD_REQ_INCR                   0x04
+
+#define CMD_Q_STATUS_BASE              0x210
+#define CMD_Q_INT_STATUS_BASE          0x214
+#define CMD_Q_STATUS_INCR              0x20
+
+#define CMD_Q_CACHE                    0x228
+#define CMD_Q_CACHE_INC                        0x20
+
+#define CMD_Q_ERROR(__qs)              ((__qs) & 0x0000003f);
+#define CMD_Q_DEPTH(__qs)              (((__qs) >> 12) & 0x0000000f);
+
+/****** REQ0 Related Values ******/
+#define REQ0_WAIT_FOR_WRITE            0x00000004
+#define REQ0_INT_ON_COMPLETE           0x00000002
+#define REQ0_STOP_ON_COMPLETE          0x00000001
+
+#define REQ0_CMD_Q_SHIFT               9
+#define REQ0_JOBID_SHIFT               3
+
+/****** REQ1 Related Values ******/
+#define REQ1_PROTECT_SHIFT             27
+#define REQ1_ENGINE_SHIFT              23
+#define REQ1_KEY_KSB_SHIFT             2
+
+#define REQ1_EOM                       0x00000002
+#define REQ1_INIT                      0x00000001
+
+/* AES Related Values */
+#define REQ1_AES_TYPE_SHIFT            21
+#define REQ1_AES_MODE_SHIFT            18
+#define REQ1_AES_ACTION_SHIFT          17
+#define REQ1_AES_CFB_SIZE_SHIFT                10
+
+/* XTS-AES Related Values */
+#define REQ1_XTS_AES_SIZE_SHIFT                10
+
+/* SHA Related Values */
+#define REQ1_SHA_TYPE_SHIFT            21
+
+/* RSA Related Values */
+#define REQ1_RSA_MOD_SIZE_SHIFT                10
+
+/* Pass-Through Related Values */
+#define REQ1_PT_BW_SHIFT               12
+#define REQ1_PT_BS_SHIFT               10
+
+/* ECC Related Values */
+#define REQ1_ECC_AFFINE_CONVERT                0x00200000
+#define REQ1_ECC_FUNCTION_SHIFT                18
+
+/****** REQ4 Related Values ******/
+#define REQ4_KSB_SHIFT                 18
+#define REQ4_MEMTYPE_SHIFT             16
+
+/****** REQ6 Related Values ******/
+#define REQ6_MEMTYPE_SHIFT             16
+
+
+/****** Key Storage Block ******/
+#define KSB_START                      77
+#define KSB_END                                127
+#define KSB_COUNT                      (KSB_END - KSB_START + 1)
+#define CCP_KSB_BITS                   256
+#define CCP_KSB_BYTES                  32
+
+#define CCP_JOBID_MASK                 0x0000003f
+
+#define CCP_DMAPOOL_MAX_SIZE           64
+#define CCP_DMAPOOL_ALIGN              (1 << 5)
+
+#define CCP_REVERSE_BUF_SIZE           64
+
+#define CCP_AES_KEY_KSB_COUNT          1
+#define CCP_AES_CTX_KSB_COUNT          1
+
+#define CCP_XTS_AES_KEY_KSB_COUNT      1
+#define CCP_XTS_AES_CTX_KSB_COUNT      1
+
+#define CCP_SHA_KSB_COUNT              1
+
+#define CCP_RSA_MAX_WIDTH              4096
+
+#define CCP_PASSTHRU_BLOCKSIZE         256
+#define CCP_PASSTHRU_MASKSIZE          32
+#define CCP_PASSTHRU_KSB_COUNT         1
+
+#define CCP_ECC_MODULUS_BYTES          48      /* 384-bits */
+#define CCP_ECC_MAX_OPERANDS           6
+#define CCP_ECC_MAX_OUTPUTS            3
+#define CCP_ECC_SRC_BUF_SIZE           448
+#define CCP_ECC_DST_BUF_SIZE           192
+#define CCP_ECC_OPERAND_SIZE           64
+#define CCP_ECC_OUTPUT_SIZE            64
+#define CCP_ECC_RESULT_OFFSET          60
+#define CCP_ECC_RESULT_SUCCESS         0x0001
+
+
+struct ccp_device;
+struct ccp_cmd;
+
+struct ccp_cmd_queue {
+       struct ccp_device *ccp;
+
+       /* Queue identifier */
+       u32 id;
+
+       /* Queue dma pool */
+       struct dma_pool *dma_pool;
+
+       /* Queue reserved KSB regions */
+       u32 ksb_key;
+       u32 ksb_ctx;
+
+       /* Queue processing thread */
+       struct task_struct *kthread;
+       unsigned int active;
+       unsigned int suspended;
+
+       /* Number of free command slots available */
+       unsigned int free_slots;
+
+       /* Interrupt masks */
+       u32 int_ok;
+       u32 int_err;
+
+       /* Register addresses for queue */
+       void __iomem *reg_status;
+       void __iomem *reg_int_status;
+
+       /* Status values from job */
+       u32 int_status;
+       u32 q_status;
+       u32 q_int_status;
+       u32 cmd_error;
+
+       /* Interrupt wait queue */
+       wait_queue_head_t int_queue;
+       unsigned int int_rcvd;
+} ____cacheline_aligned;
+
+struct ccp_device {
+       struct device *dev;
+
+       /*
+        * Bus specific device information
+        */
+       void *dev_specific;
+       int (*get_irq)(struct ccp_device *ccp);
+       void (*free_irq)(struct ccp_device *ccp);
+
+       /*
+        * I/O area used for device communication. The register mapping
+        * starts at an offset into the mapped bar.
+        *   The CMD_REQx registers and the Delete_Cmd_Queue_Job register
+        *   need to be protected while a command queue thread is accessing
+        *   them.
+        */
+       struct mutex req_mutex ____cacheline_aligned;
+       void __iomem *io_map;
+       void __iomem *io_regs;
+
+       /*
+        * Master lists that all cmds are queued on. Because there can be
+        * more than one CCP command queue that can process a cmd a separate
+        * backlog list is neeeded so that the backlog completion call
+        * completes before the cmd is available for execution.
+        */
+       spinlock_t cmd_lock ____cacheline_aligned;
+       unsigned int cmd_count;
+       struct list_head cmd;
+       struct list_head backlog;
+
+       /*
+        * The command queues. These represent the queues available on the
+        * CCP that are available for processing cmds
+        */
+       struct ccp_cmd_queue cmd_q[MAX_HW_QUEUES];
+       unsigned int cmd_q_count;
+
+       /*
+        * Support for the CCP True RNG
+        */
+       struct hwrng hwrng;
+       unsigned int hwrng_retries;
+
+       /*
+        * A counter used to generate job-ids for cmds submitted to the CCP
+        */
+       atomic_t current_id ____cacheline_aligned;
+
+       /*
+        * The CCP uses key storage blocks (KSB) to maintain context for certain
+        * operations. To prevent multiple cmds from using the same KSB range
+        * a command queue reserves a KSB range for the duration of the cmd.
+        * Each queue, will however, reserve 2 KSB blocks for operations that
+        * only require single KSB entries (eg. AES context/iv and key) in order
+        * to avoid allocation contention.  This will reserve at most 10 KSB
+        * entries, leaving 40 KSB entries available for dynamic allocation.
+        */
+       struct mutex ksb_mutex ____cacheline_aligned;
+       DECLARE_BITMAP(ksb, KSB_COUNT);
+       wait_queue_head_t ksb_queue;
+       unsigned int ksb_avail;
+       unsigned int ksb_count;
+       u32 ksb_start;
+
+       /* Suspend support */
+       unsigned int suspending;
+       wait_queue_head_t suspend_queue;
+};
+
+
+int ccp_pci_init(void);
+void ccp_pci_exit(void);
+
+struct ccp_device *ccp_alloc_struct(struct device *dev);
+int ccp_init(struct ccp_device *ccp);
+void ccp_destroy(struct ccp_device *ccp);
+bool ccp_queues_suspended(struct ccp_device *ccp);
+
+irqreturn_t ccp_irq_handler(int irq, void *data);
+
+int ccp_run_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd);
+
+#endif
diff --git a/drivers/crypto/ccp/ccp-ops.c b/drivers/crypto/ccp/ccp-ops.c
new file mode 100644 (file)
index 0000000..4be0910
--- /dev/null
@@ -0,0 +1,2020 @@
+/*
+ * AMD Cryptographic Coprocessor (CCP) driver
+ *
+ * Copyright (C) 2013 Advanced Micro Devices, Inc.
+ *
+ * Author: Tom Lendacky <thomas.lendacky@amd.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/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/kthread.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/ccp.h>
+#include <linux/scatterlist.h>
+#include <crypto/scatterwalk.h>
+
+#include "ccp-dev.h"
+
+
+enum ccp_memtype {
+       CCP_MEMTYPE_SYSTEM = 0,
+       CCP_MEMTYPE_KSB,
+       CCP_MEMTYPE_LOCAL,
+       CCP_MEMTYPE__LAST,
+};
+
+struct ccp_dma_info {
+       dma_addr_t address;
+       unsigned int offset;
+       unsigned int length;
+       enum dma_data_direction dir;
+};
+
+struct ccp_dm_workarea {
+       struct device *dev;
+       struct dma_pool *dma_pool;
+       unsigned int length;
+
+       u8 *address;
+       struct ccp_dma_info dma;
+};
+
+struct ccp_sg_workarea {
+       struct scatterlist *sg;
+       unsigned int nents;
+       unsigned int length;
+
+       struct scatterlist *dma_sg;
+       struct device *dma_dev;
+       unsigned int dma_count;
+       enum dma_data_direction dma_dir;
+
+       u32 sg_used;
+
+       u32 bytes_left;
+};
+
+struct ccp_data {
+       struct ccp_sg_workarea sg_wa;
+       struct ccp_dm_workarea dm_wa;
+};
+
+struct ccp_mem {
+       enum ccp_memtype type;
+       union {
+               struct ccp_dma_info dma;
+               u32 ksb;
+       } u;
+};
+
+struct ccp_aes_op {
+       enum ccp_aes_type type;
+       enum ccp_aes_mode mode;
+       enum ccp_aes_action action;
+};
+
+struct ccp_xts_aes_op {
+       enum ccp_aes_action action;
+       enum ccp_xts_aes_unit_size unit_size;
+};
+
+struct ccp_sha_op {
+       enum ccp_sha_type type;
+       u64 msg_bits;
+};
+
+struct ccp_rsa_op {
+       u32 mod_size;
+       u32 input_len;
+};
+
+struct ccp_passthru_op {
+       enum ccp_passthru_bitwise bit_mod;
+       enum ccp_passthru_byteswap byte_swap;
+};
+
+struct ccp_ecc_op {
+       enum ccp_ecc_function function;
+};
+
+struct ccp_op {
+       struct ccp_cmd_queue *cmd_q;
+
+       u32 jobid;
+       u32 ioc;
+       u32 soc;
+       u32 ksb_key;
+       u32 ksb_ctx;
+       u32 init;
+       u32 eom;
+
+       struct ccp_mem src;
+       struct ccp_mem dst;
+
+       union {
+               struct ccp_aes_op aes;
+               struct ccp_xts_aes_op xts;
+               struct ccp_sha_op sha;
+               struct ccp_rsa_op rsa;
+               struct ccp_passthru_op passthru;
+               struct ccp_ecc_op ecc;
+       } u;
+};
+
+/* The CCP cannot perform zero-length sha operations so the caller
+ * is required to buffer data for the final operation.  However, a
+ * sha operation for a message with a total length of zero is valid
+ * so known values are required to supply the result.
+ */
+static const u8 ccp_sha1_zero[CCP_SHA_CTXSIZE] = {
+       0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d,
+       0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90,
+       0xaf, 0xd8, 0x07, 0x09, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static const u8 ccp_sha224_zero[CCP_SHA_CTXSIZE] = {
+       0xd1, 0x4a, 0x02, 0x8c, 0x2a, 0x3a, 0x2b, 0xc9,
+       0x47, 0x61, 0x02, 0xbb, 0x28, 0x82, 0x34, 0xc4,
+       0x15, 0xa2, 0xb0, 0x1f, 0x82, 0x8e, 0xa6, 0x2a,
+       0xc5, 0xb3, 0xe4, 0x2f, 0x00, 0x00, 0x00, 0x00,
+};
+
+static const u8 ccp_sha256_zero[CCP_SHA_CTXSIZE] = {
+       0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
+       0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
+       0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
+       0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55,
+};
+
+static u32 ccp_addr_lo(struct ccp_dma_info *info)
+{
+       return lower_32_bits(info->address + info->offset);
+}
+
+static u32 ccp_addr_hi(struct ccp_dma_info *info)
+{
+       return upper_32_bits(info->address + info->offset) & 0x0000ffff;
+}
+
+static int ccp_do_cmd(struct ccp_op *op, u32 *cr, unsigned int cr_count)
+{
+       struct ccp_cmd_queue *cmd_q = op->cmd_q;
+       struct ccp_device *ccp = cmd_q->ccp;
+       void __iomem *cr_addr;
+       u32 cr0, cmd;
+       unsigned int i;
+       int ret = 0;
+
+       /* We could read a status register to see how many free slots
+        * are actually available, but reading that register resets it
+        * and you could lose some error information.
+        */
+       cmd_q->free_slots--;
+
+       cr0 = (cmd_q->id << REQ0_CMD_Q_SHIFT)
+             | (op->jobid << REQ0_JOBID_SHIFT)
+             | REQ0_WAIT_FOR_WRITE;
+
+       if (op->soc)
+               cr0 |= REQ0_STOP_ON_COMPLETE
+                      | REQ0_INT_ON_COMPLETE;
+
+       if (op->ioc || !cmd_q->free_slots)
+               cr0 |= REQ0_INT_ON_COMPLETE;
+
+       /* Start at CMD_REQ1 */
+       cr_addr = ccp->io_regs + CMD_REQ0 + CMD_REQ_INCR;
+
+       mutex_lock(&ccp->req_mutex);
+
+       /* Write CMD_REQ1 through CMD_REQx first */
+       for (i = 0; i < cr_count; i++, cr_addr += CMD_REQ_INCR)
+               iowrite32(*(cr + i), cr_addr);
+
+       /* Tell the CCP to start */
+       wmb();
+       iowrite32(cr0, ccp->io_regs + CMD_REQ0);
+
+       mutex_unlock(&ccp->req_mutex);
+
+       if (cr0 & REQ0_INT_ON_COMPLETE) {
+               /* Wait for the job to complete */
+               ret = wait_event_interruptible(cmd_q->int_queue,
+                                              cmd_q->int_rcvd);
+               if (ret || cmd_q->cmd_error) {
+                       /* On error delete all related jobs from the queue */
+                       cmd = (cmd_q->id << DEL_Q_ID_SHIFT)
+                             | op->jobid;
+
+                       iowrite32(cmd, ccp->io_regs + DEL_CMD_Q_JOB);
+
+                       if (!ret)
+                               ret = -EIO;
+               } else if (op->soc) {
+                       /* Delete just head job from the queue on SoC */
+                       cmd = DEL_Q_ACTIVE
+                             | (cmd_q->id << DEL_Q_ID_SHIFT)
+                             | op->jobid;
+
+                       iowrite32(cmd, ccp->io_regs + DEL_CMD_Q_JOB);
+               }
+
+               cmd_q->free_slots = CMD_Q_DEPTH(cmd_q->q_status);
+
+               cmd_q->int_rcvd = 0;
+       }
+
+       return ret;
+}
+
+static int ccp_perform_aes(struct ccp_op *op)
+{
+       u32 cr[6];
+
+       /* Fill out the register contents for REQ1 through REQ6 */
+       cr[0] = (CCP_ENGINE_AES << REQ1_ENGINE_SHIFT)
+               | (op->u.aes.type << REQ1_AES_TYPE_SHIFT)
+               | (op->u.aes.mode << REQ1_AES_MODE_SHIFT)
+               | (op->u.aes.action << REQ1_AES_ACTION_SHIFT)
+               | (op->ksb_key << REQ1_KEY_KSB_SHIFT);
+       cr[1] = op->src.u.dma.length - 1;
+       cr[2] = ccp_addr_lo(&op->src.u.dma);
+       cr[3] = (op->ksb_ctx << REQ4_KSB_SHIFT)
+               | (CCP_MEMTYPE_SYSTEM << REQ4_MEMTYPE_SHIFT)
+               | ccp_addr_hi(&op->src.u.dma);
+       cr[4] = ccp_addr_lo(&op->dst.u.dma);
+       cr[5] = (CCP_MEMTYPE_SYSTEM << REQ6_MEMTYPE_SHIFT)
+               | ccp_addr_hi(&op->dst.u.dma);
+
+       if (op->u.aes.mode == CCP_AES_MODE_CFB)
+               cr[0] |= ((0x7f) << REQ1_AES_CFB_SIZE_SHIFT);
+
+       if (op->eom)
+               cr[0] |= REQ1_EOM;
+
+       if (op->init)
+               cr[0] |= REQ1_INIT;
+
+       return ccp_do_cmd(op, cr, ARRAY_SIZE(cr));
+}
+
+static int ccp_perform_xts_aes(struct ccp_op *op)
+{
+       u32 cr[6];
+
+       /* Fill out the register contents for REQ1 through REQ6 */
+       cr[0] = (CCP_ENGINE_XTS_AES_128 << REQ1_ENGINE_SHIFT)
+               | (op->u.xts.action << REQ1_AES_ACTION_SHIFT)
+               | (op->u.xts.unit_size << REQ1_XTS_AES_SIZE_SHIFT)
+               | (op->ksb_key << REQ1_KEY_KSB_SHIFT);
+       cr[1] = op->src.u.dma.length - 1;
+       cr[2] = ccp_addr_lo(&op->src.u.dma);
+       cr[3] = (op->ksb_ctx << REQ4_KSB_SHIFT)
+               | (CCP_MEMTYPE_SYSTEM << REQ4_MEMTYPE_SHIFT)
+               | ccp_addr_hi(&op->src.u.dma);
+       cr[4] = ccp_addr_lo(&op->dst.u.dma);
+       cr[5] = (CCP_MEMTYPE_SYSTEM << REQ6_MEMTYPE_SHIFT)
+               | ccp_addr_hi(&op->dst.u.dma);
+
+       if (op->eom)
+               cr[0] |= REQ1_EOM;
+
+       if (op->init)
+               cr[0] |= REQ1_INIT;
+
+       return ccp_do_cmd(op, cr, ARRAY_SIZE(cr));
+}
+
+static int ccp_perform_sha(struct ccp_op *op)
+{
+       u32 cr[6];
+
+       /* Fill out the register contents for REQ1 through REQ6 */
+       cr[0] = (CCP_ENGINE_SHA << REQ1_ENGINE_SHIFT)
+               | (op->u.sha.type << REQ1_SHA_TYPE_SHIFT)
+               | REQ1_INIT;
+       cr[1] = op->src.u.dma.length - 1;
+       cr[2] = ccp_addr_lo(&op->src.u.dma);
+       cr[3] = (op->ksb_ctx << REQ4_KSB_SHIFT)
+               | (CCP_MEMTYPE_SYSTEM << REQ4_MEMTYPE_SHIFT)
+               | ccp_addr_hi(&op->src.u.dma);
+
+       if (op->eom) {
+               cr[0] |= REQ1_EOM;
+               cr[4] = lower_32_bits(op->u.sha.msg_bits);
+               cr[5] = upper_32_bits(op->u.sha.msg_bits);
+       } else {
+               cr[4] = 0;
+               cr[5] = 0;
+       }
+
+       return ccp_do_cmd(op, cr, ARRAY_SIZE(cr));
+}
+
+static int ccp_perform_rsa(struct ccp_op *op)
+{
+       u32 cr[6];
+
+       /* Fill out the register contents for REQ1 through REQ6 */
+       cr[0] = (CCP_ENGINE_RSA << REQ1_ENGINE_SHIFT)
+               | (op->u.rsa.mod_size << REQ1_RSA_MOD_SIZE_SHIFT)
+               | (op->ksb_key << REQ1_KEY_KSB_SHIFT)
+               | REQ1_EOM;
+       cr[1] = op->u.rsa.input_len - 1;
+       cr[2] = ccp_addr_lo(&op->src.u.dma);
+       cr[3] = (op->ksb_ctx << REQ4_KSB_SHIFT)
+               | (CCP_MEMTYPE_SYSTEM << REQ4_MEMTYPE_SHIFT)
+               | ccp_addr_hi(&op->src.u.dma);
+       cr[4] = ccp_addr_lo(&op->dst.u.dma);
+       cr[5] = (CCP_MEMTYPE_SYSTEM << REQ6_MEMTYPE_SHIFT)
+               | ccp_addr_hi(&op->dst.u.dma);
+
+       return ccp_do_cmd(op, cr, ARRAY_SIZE(cr));
+}
+
+static int ccp_perform_passthru(struct ccp_op *op)
+{
+       u32 cr[6];
+
+       /* Fill out the register contents for REQ1 through REQ6 */
+       cr[0] = (CCP_ENGINE_PASSTHRU << REQ1_ENGINE_SHIFT)
+               | (op->u.passthru.bit_mod << REQ1_PT_BW_SHIFT)
+               | (op->u.passthru.byte_swap << REQ1_PT_BS_SHIFT);
+
+       if (op->src.type == CCP_MEMTYPE_SYSTEM)
+               cr[1] = op->src.u.dma.length - 1;
+       else
+               cr[1] = op->dst.u.dma.length - 1;
+
+       if (op->src.type == CCP_MEMTYPE_SYSTEM) {
+               cr[2] = ccp_addr_lo(&op->src.u.dma);
+               cr[3] = (CCP_MEMTYPE_SYSTEM << REQ4_MEMTYPE_SHIFT)
+                       | ccp_addr_hi(&op->src.u.dma);
+
+               if (op->u.passthru.bit_mod != CCP_PASSTHRU_BITWISE_NOOP)
+                       cr[3] |= (op->ksb_key << REQ4_KSB_SHIFT);
+       } else {
+               cr[2] = op->src.u.ksb * CCP_KSB_BYTES;
+               cr[3] = (CCP_MEMTYPE_KSB << REQ4_MEMTYPE_SHIFT);
+       }
+
+       if (op->dst.type == CCP_MEMTYPE_SYSTEM) {
+               cr[4] = ccp_addr_lo(&op->dst.u.dma);
+               cr[5] = (CCP_MEMTYPE_SYSTEM << REQ6_MEMTYPE_SHIFT)
+                       | ccp_addr_hi(&op->dst.u.dma);
+       } else {
+               cr[4] = op->dst.u.ksb * CCP_KSB_BYTES;
+               cr[5] = (CCP_MEMTYPE_KSB << REQ6_MEMTYPE_SHIFT);
+       }
+
+       if (op->eom)
+               cr[0] |= REQ1_EOM;
+
+       return ccp_do_cmd(op, cr, ARRAY_SIZE(cr));
+}
+
+static int ccp_perform_ecc(struct ccp_op *op)
+{
+       u32 cr[6];
+
+       /* Fill out the register contents for REQ1 through REQ6 */
+       cr[0] = REQ1_ECC_AFFINE_CONVERT
+               | (CCP_ENGINE_ECC << REQ1_ENGINE_SHIFT)
+               | (op->u.ecc.function << REQ1_ECC_FUNCTION_SHIFT)
+               | REQ1_EOM;
+       cr[1] = op->src.u.dma.length - 1;
+       cr[2] = ccp_addr_lo(&op->src.u.dma);
+       cr[3] = (CCP_MEMTYPE_SYSTEM << REQ4_MEMTYPE_SHIFT)
+               | ccp_addr_hi(&op->src.u.dma);
+       cr[4] = ccp_addr_lo(&op->dst.u.dma);
+       cr[5] = (CCP_MEMTYPE_SYSTEM << REQ6_MEMTYPE_SHIFT)
+               | ccp_addr_hi(&op->dst.u.dma);
+
+       return ccp_do_cmd(op, cr, ARRAY_SIZE(cr));
+}
+
+static u32 ccp_alloc_ksb(struct ccp_device *ccp, unsigned int count)
+{
+       int start;
+
+       for (;;) {
+               mutex_lock(&ccp->ksb_mutex);
+
+               start = (u32)bitmap_find_next_zero_area(ccp->ksb,
+                                                       ccp->ksb_count,
+                                                       ccp->ksb_start,
+                                                       count, 0);
+               if (start <= ccp->ksb_count) {
+                       bitmap_set(ccp->ksb, start, count);
+
+                       mutex_unlock(&ccp->ksb_mutex);
+                       break;
+               }
+
+               ccp->ksb_avail = 0;
+
+               mutex_unlock(&ccp->ksb_mutex);
+
+               /* Wait for KSB entries to become available */
+               if (wait_event_interruptible(ccp->ksb_queue, ccp->ksb_avail))
+                       return 0;
+       }
+
+       return KSB_START + start;
+}
+
+static void ccp_free_ksb(struct ccp_device *ccp, unsigned int start,
+                        unsigned int count)
+{
+       if (!start)
+               return;
+
+       mutex_lock(&ccp->ksb_mutex);
+
+       bitmap_clear(ccp->ksb, start - KSB_START, count);
+
+       ccp->ksb_avail = 1;
+
+       mutex_unlock(&ccp->ksb_mutex);
+
+       wake_up_interruptible_all(&ccp->ksb_queue);
+}
+
+static u32 ccp_gen_jobid(struct ccp_device *ccp)
+{
+       return atomic_inc_return(&ccp->current_id) & CCP_JOBID_MASK;
+}
+
+static void ccp_sg_free(struct ccp_sg_workarea *wa)
+{
+       if (wa->dma_count)
+               dma_unmap_sg(wa->dma_dev, wa->dma_sg, wa->nents, wa->dma_dir);
+
+       wa->dma_count = 0;
+}
+
+static int ccp_init_sg_workarea(struct ccp_sg_workarea *wa, struct device *dev,
+                               struct scatterlist *sg, unsigned int len,
+                               enum dma_data_direction dma_dir)
+{
+       memset(wa, 0, sizeof(*wa));
+
+       wa->sg = sg;
+       if (!sg)
+               return 0;
+
+       wa->nents = sg_nents(sg);
+       wa->length = sg->length;
+       wa->bytes_left = len;
+       wa->sg_used = 0;
+
+       if (len == 0)
+               return 0;
+
+       if (dma_dir == DMA_NONE)
+               return 0;
+
+       wa->dma_sg = sg;
+       wa->dma_dev = dev;
+       wa->dma_dir = dma_dir;
+       wa->dma_count = dma_map_sg(dev, sg, wa->nents, dma_dir);
+       if (!wa->dma_count)
+               return -ENOMEM;
+
+
+       return 0;
+}
+
+static void ccp_update_sg_workarea(struct ccp_sg_workarea *wa, unsigned int len)
+{
+       unsigned int nbytes = min(len, wa->bytes_left);
+
+       if (!wa->sg)
+               return;
+
+       wa->sg_used += nbytes;
+       wa->bytes_left -= nbytes;
+       if (wa->sg_used == wa->sg->length) {
+               wa->sg = sg_next(wa->sg);
+               wa->sg_used = 0;
+       }
+}
+
+static void ccp_dm_free(struct ccp_dm_workarea *wa)
+{
+       if (wa->length <= CCP_DMAPOOL_MAX_SIZE) {
+               if (wa->address)
+                       dma_pool_free(wa->dma_pool, wa->address,
+                                     wa->dma.address);
+       } else {
+               if (wa->dma.address)
+                       dma_unmap_single(wa->dev, wa->dma.address, wa->length,
+                                        wa->dma.dir);
+               kfree(wa->address);
+       }
+
+       wa->address = NULL;
+       wa->dma.address = 0;
+}
+
+static int ccp_init_dm_workarea(struct ccp_dm_workarea *wa,
+                               struct ccp_cmd_queue *cmd_q,
+                               unsigned int len,
+                               enum dma_data_direction dir)
+{
+       memset(wa, 0, sizeof(*wa));
+
+       if (!len)
+               return 0;
+
+       wa->dev = cmd_q->ccp->dev;
+       wa->length = len;
+
+       if (len <= CCP_DMAPOOL_MAX_SIZE) {
+               wa->dma_pool = cmd_q->dma_pool;
+
+               wa->address = dma_pool_alloc(wa->dma_pool, GFP_KERNEL,
+                                            &wa->dma.address);
+               if (!wa->address)
+                       return -ENOMEM;
+
+               wa->dma.length = CCP_DMAPOOL_MAX_SIZE;
+
+               memset(wa->address, 0, CCP_DMAPOOL_MAX_SIZE);
+       } else {
+               wa->address = kzalloc(len, GFP_KERNEL);
+               if (!wa->address)
+                       return -ENOMEM;
+
+               wa->dma.address = dma_map_single(wa->dev, wa->address, len,
+                                                dir);
+               if (!wa->dma.address)
+                       return -ENOMEM;
+
+               wa->dma.length = len;
+       }
+       wa->dma.dir = dir;
+
+       return 0;
+}
+
+static void ccp_set_dm_area(struct ccp_dm_workarea *wa, unsigned int wa_offset,
+                           struct scatterlist *sg, unsigned int sg_offset,
+                           unsigned int len)
+{
+       WARN_ON(!wa->address);
+
+       scatterwalk_map_and_copy(wa->address + wa_offset, sg, sg_offset, len,
+                                0);
+}
+
+static void ccp_get_dm_area(struct ccp_dm_workarea *wa, unsigned int wa_offset,
+                           struct scatterlist *sg, unsigned int sg_offset,
+                           unsigned int len)
+{
+       WARN_ON(!wa->address);
+
+       scatterwalk_map_and_copy(wa->address + wa_offset, sg, sg_offset, len,
+                                1);
+}
+
+static void ccp_reverse_set_dm_area(struct ccp_dm_workarea *wa,
+                                   struct scatterlist *sg,
+                                   unsigned int len, unsigned int se_len,
+                                   bool sign_extend)
+{
+       unsigned int nbytes, sg_offset, dm_offset, ksb_len, i;
+       u8 buffer[CCP_REVERSE_BUF_SIZE];
+
+       BUG_ON(se_len > sizeof(buffer));
+
+       sg_offset = len;
+       dm_offset = 0;
+       nbytes = len;
+       while (nbytes) {
+               ksb_len = min_t(unsigned int, nbytes, se_len);
+               sg_offset -= ksb_len;
+
+               scatterwalk_map_and_copy(buffer, sg, sg_offset, ksb_len, 0);
+               for (i = 0; i < ksb_len; i++)
+                       wa->address[dm_offset + i] = buffer[ksb_len - i - 1];
+
+               dm_offset += ksb_len;
+               nbytes -= ksb_len;
+
+               if ((ksb_len != se_len) && sign_extend) {
+                       /* Must sign-extend to nearest sign-extend length */
+                       if (wa->address[dm_offset - 1] & 0x80)
+                               memset(wa->address + dm_offset, 0xff,
+                                      se_len - ksb_len);
+               }
+       }
+}
+
+static void ccp_reverse_get_dm_area(struct ccp_dm_workarea *wa,
+                                   struct scatterlist *sg,
+                                   unsigned int len)
+{
+       unsigned int nbytes, sg_offset, dm_offset, ksb_len, i;
+       u8 buffer[CCP_REVERSE_BUF_SIZE];
+
+       sg_offset = 0;
+       dm_offset = len;
+       nbytes = len;
+       while (nbytes) {
+               ksb_len = min_t(unsigned int, nbytes, sizeof(buffer));
+               dm_offset -= ksb_len;
+
+               for (i = 0; i < ksb_len; i++)
+                       buffer[ksb_len - i - 1] = wa->address[dm_offset + i];
+               scatterwalk_map_and_copy(buffer, sg, sg_offset, ksb_len, 1);
+
+               sg_offset += ksb_len;
+               nbytes -= ksb_len;
+       }
+}
+
+static void ccp_free_data(struct ccp_data *data, struct ccp_cmd_queue *cmd_q)
+{
+       ccp_dm_free(&data->dm_wa);
+       ccp_sg_free(&data->sg_wa);
+}
+
+static int ccp_init_data(struct ccp_data *data, struct ccp_cmd_queue *cmd_q,
+                        struct scatterlist *sg, unsigned int sg_len,
+                        unsigned int dm_len,
+                        enum dma_data_direction dir)
+{
+       int ret;
+
+       memset(data, 0, sizeof(*data));
+
+       ret = ccp_init_sg_workarea(&data->sg_wa, cmd_q->ccp->dev, sg, sg_len,
+                                  dir);
+       if (ret)
+               goto e_err;
+
+       ret = ccp_init_dm_workarea(&data->dm_wa, cmd_q, dm_len, dir);
+       if (ret)
+               goto e_err;
+
+       return 0;
+
+e_err:
+       ccp_free_data(data, cmd_q);
+
+       return ret;
+}
+
+static unsigned int ccp_queue_buf(struct ccp_data *data, unsigned int from)
+{
+       struct ccp_sg_workarea *sg_wa = &data->sg_wa;
+       struct ccp_dm_workarea *dm_wa = &data->dm_wa;
+       unsigned int buf_count, nbytes;
+
+       /* Clear the buffer if setting it */
+       if (!from)
+               memset(dm_wa->address, 0, dm_wa->length);
+
+       if (!sg_wa->sg)
+               return 0;
+
+       /* Perform the copy operation */
+       nbytes = min(sg_wa->bytes_left, dm_wa->length);
+       scatterwalk_map_and_copy(dm_wa->address, sg_wa->sg, sg_wa->sg_used,
+                                nbytes, from);
+
+       /* Update the structures and generate the count */
+       buf_count = 0;
+       while (sg_wa->bytes_left && (buf_count < dm_wa->length)) {
+               nbytes = min3(sg_wa->sg->length - sg_wa->sg_used,
+                             dm_wa->length - buf_count,
+                             sg_wa->bytes_left);
+
+               buf_count += nbytes;
+               ccp_update_sg_workarea(sg_wa, nbytes);
+       }
+
+       return buf_count;
+}
+
+static unsigned int ccp_fill_queue_buf(struct ccp_data *data)
+{
+       return ccp_queue_buf(data, 0);
+}
+
+static unsigned int ccp_empty_queue_buf(struct ccp_data *data)
+{
+       return ccp_queue_buf(data, 1);
+}
+
+static void ccp_prepare_data(struct ccp_data *src, struct ccp_data *dst,
+                            struct ccp_op *op, unsigned int block_size,
+                            bool blocksize_op)
+{
+       unsigned int sg_src_len, sg_dst_len, op_len;
+
+       /* The CCP can only DMA from/to one address each per operation. This
+        * requires that we find the smallest DMA area between the source
+        * and destination.
+        */
+       sg_src_len = min(sg_dma_len(src->sg_wa.sg) - src->sg_wa.sg_used,
+                        src->sg_wa.bytes_left);
+
+       if (dst) {
+               sg_dst_len = min(sg_dma_len(dst->sg_wa.sg) - dst->sg_wa.sg_used,
+                                src->sg_wa.bytes_left);
+               op_len = min(sg_src_len, sg_dst_len);
+       } else
+               op_len = sg_src_len;
+
+       /* The data operation length will be at least block_size in length
+        * or the smaller of available sg room remaining for the source or
+        * the destination
+        */
+       op_len = max(op_len, block_size);
+
+       /* Unless we have to buffer data, there's no reason to wait */
+       op->soc = 0;
+
+       if (sg_src_len < block_size) {
+               /* Not enough data in the sg element, so it
+                * needs to be buffered into a blocksize chunk
+                */
+               int cp_len = ccp_fill_queue_buf(src);
+
+               op->soc = 1;
+               op->src.u.dma.address = src->dm_wa.dma.address;
+               op->src.u.dma.offset = 0;
+               op->src.u.dma.length = (blocksize_op) ? block_size : cp_len;
+       } else {
+               /* Enough data in the sg element, but we need to
+                * adjust for any previously copied data
+                */
+               op->src.u.dma.address = sg_dma_address(src->sg_wa.sg);
+               op->src.u.dma.offset = src->sg_wa.sg_used;
+               op->src.u.dma.length = op_len & ~(block_size - 1);
+
+               ccp_update_sg_workarea(&src->sg_wa, op->src.u.dma.length);
+       }
+
+       if (dst) {
+               if (sg_dst_len < block_size) {
+                       /* Not enough room in the sg element or we're on the
+                        * last piece of data (when using padding), so the
+                        * output needs to be buffered into a blocksize chunk
+                        */
+                       op->soc = 1;
+                       op->dst.u.dma.address = dst->dm_wa.dma.address;
+                       op->dst.u.dma.offset = 0;
+                       op->dst.u.dma.length = op->src.u.dma.length;
+               } else {
+                       /* Enough room in the sg element, but we need to
+                        * adjust for any previously used area
+                        */
+                       op->dst.u.dma.address = sg_dma_address(dst->sg_wa.sg);
+                       op->dst.u.dma.offset = dst->sg_wa.sg_used;
+                       op->dst.u.dma.length = op->src.u.dma.length;
+               }
+       }
+}
+
+static void ccp_process_data(struct ccp_data *src, struct ccp_data *dst,
+                            struct ccp_op *op)
+{
+       op->init = 0;
+
+       if (dst) {
+               if (op->dst.u.dma.address == dst->dm_wa.dma.address)
+                       ccp_empty_queue_buf(dst);
+               else
+                       ccp_update_sg_workarea(&dst->sg_wa,
+                                              op->dst.u.dma.length);
+       }
+}
+
+static int ccp_copy_to_from_ksb(struct ccp_cmd_queue *cmd_q,
+                               struct ccp_dm_workarea *wa, u32 jobid, u32 ksb,
+                               u32 byte_swap, bool from)
+{
+       struct ccp_op op;
+
+       memset(&op, 0, sizeof(op));
+
+       op.cmd_q = cmd_q;
+       op.jobid = jobid;
+       op.eom = 1;
+
+       if (from) {
+               op.soc = 1;
+               op.src.type = CCP_MEMTYPE_KSB;
+               op.src.u.ksb = ksb;
+               op.dst.type = CCP_MEMTYPE_SYSTEM;
+               op.dst.u.dma.address = wa->dma.address;
+               op.dst.u.dma.length = wa->length;
+       } else {
+               op.src.type = CCP_MEMTYPE_SYSTEM;
+               op.src.u.dma.address = wa->dma.address;
+               op.src.u.dma.length = wa->length;
+               op.dst.type = CCP_MEMTYPE_KSB;
+               op.dst.u.ksb = ksb;
+       }
+
+       op.u.passthru.byte_swap = byte_swap;
+
+       return ccp_perform_passthru(&op);
+}
+
+static int ccp_copy_to_ksb(struct ccp_cmd_queue *cmd_q,
+                          struct ccp_dm_workarea *wa, u32 jobid, u32 ksb,
+                          u32 byte_swap)
+{
+       return ccp_copy_to_from_ksb(cmd_q, wa, jobid, ksb, byte_swap, false);
+}
+
+static int ccp_copy_from_ksb(struct ccp_cmd_queue *cmd_q,
+                            struct ccp_dm_workarea *wa, u32 jobid, u32 ksb,
+                            u32 byte_swap)
+{
+       return ccp_copy_to_from_ksb(cmd_q, wa, jobid, ksb, byte_swap, true);
+}
+
+static int ccp_run_aes_cmac_cmd(struct ccp_cmd_queue *cmd_q,
+                               struct ccp_cmd *cmd)
+{
+       struct ccp_aes_engine *aes = &cmd->u.aes;
+       struct ccp_dm_workarea key, ctx;
+       struct ccp_data src;
+       struct ccp_op op;
+       unsigned int dm_offset;
+       int ret;
+
+       if (!((aes->key_len == AES_KEYSIZE_128) ||
+             (aes->key_len == AES_KEYSIZE_192) ||
+             (aes->key_len == AES_KEYSIZE_256)))
+               return -EINVAL;
+
+       if (aes->src_len & (AES_BLOCK_SIZE - 1))
+               return -EINVAL;
+
+       if (aes->iv_len != AES_BLOCK_SIZE)
+               return -EINVAL;
+
+       if (!aes->key || !aes->iv || !aes->src)
+               return -EINVAL;
+
+       if (aes->cmac_final) {
+               if (aes->cmac_key_len != AES_BLOCK_SIZE)
+                       return -EINVAL;
+
+               if (!aes->cmac_key)
+                       return -EINVAL;
+       }
+
+       BUILD_BUG_ON(CCP_AES_KEY_KSB_COUNT != 1);
+       BUILD_BUG_ON(CCP_AES_CTX_KSB_COUNT != 1);
+
+       ret = -EIO;
+       memset(&op, 0, sizeof(op));
+       op.cmd_q = cmd_q;
+       op.jobid = ccp_gen_jobid(cmd_q->ccp);
+       op.ksb_key = cmd_q->ksb_key;
+       op.ksb_ctx = cmd_q->ksb_ctx;
+       op.init = 1;
+       op.u.aes.type = aes->type;
+       op.u.aes.mode = aes->mode;
+       op.u.aes.action = aes->action;
+
+       /* All supported key sizes fit in a single (32-byte) KSB entry
+        * and must be in little endian format. Use the 256-bit byte
+        * swap passthru option to convert from big endian to little
+        * endian.
+        */
+       ret = ccp_init_dm_workarea(&key, cmd_q,
+                                  CCP_AES_KEY_KSB_COUNT * CCP_KSB_BYTES,
+                                  DMA_TO_DEVICE);
+       if (ret)
+               return ret;
+
+       dm_offset = CCP_KSB_BYTES - aes->key_len;
+       ccp_set_dm_area(&key, dm_offset, aes->key, 0, aes->key_len);
+       ret = ccp_copy_to_ksb(cmd_q, &key, op.jobid, op.ksb_key,
+                             CCP_PASSTHRU_BYTESWAP_256BIT);
+       if (ret) {
+               cmd->engine_error = cmd_q->cmd_error;
+               goto e_key;
+       }
+
+       /* The AES context fits in a single (32-byte) KSB entry and
+        * must be in little endian format. Use the 256-bit byte swap
+        * passthru option to convert from big endian to little endian.
+        */
+       ret = ccp_init_dm_workarea(&ctx, cmd_q,
+                                  CCP_AES_CTX_KSB_COUNT * CCP_KSB_BYTES,
+                                  DMA_BIDIRECTIONAL);
+       if (ret)
+               goto e_key;
+
+       dm_offset = CCP_KSB_BYTES - AES_BLOCK_SIZE;
+       ccp_set_dm_area(&ctx, dm_offset, aes->iv, 0, aes->iv_len);
+       ret = ccp_copy_to_ksb(cmd_q, &ctx, op.jobid, op.ksb_ctx,
+                             CCP_PASSTHRU_BYTESWAP_256BIT);
+       if (ret) {
+               cmd->engine_error = cmd_q->cmd_error;
+               goto e_ctx;
+       }
+
+       /* Send data to the CCP AES engine */
+       ret = ccp_init_data(&src, cmd_q, aes->src, aes->src_len,
+                           AES_BLOCK_SIZE, DMA_TO_DEVICE);
+       if (ret)
+               goto e_ctx;
+
+       while (src.sg_wa.bytes_left) {
+               ccp_prepare_data(&src, NULL, &op, AES_BLOCK_SIZE, true);
+               if (aes->cmac_final && !src.sg_wa.bytes_left) {
+                       op.eom = 1;
+
+                       /* Push the K1/K2 key to the CCP now */
+                       ret = ccp_copy_from_ksb(cmd_q, &ctx, op.jobid,
+                                               op.ksb_ctx,
+                                               CCP_PASSTHRU_BYTESWAP_256BIT);
+                       if (ret) {
+                               cmd->engine_error = cmd_q->cmd_error;
+                               goto e_src;
+                       }
+
+                       ccp_set_dm_area(&ctx, 0, aes->cmac_key, 0,
+                                       aes->cmac_key_len);
+                       ret = ccp_copy_to_ksb(cmd_q, &ctx, op.jobid, op.ksb_ctx,
+                                             CCP_PASSTHRU_BYTESWAP_256BIT);
+                       if (ret) {
+                               cmd->engine_error = cmd_q->cmd_error;
+                               goto e_src;
+                       }
+               }
+
+               ret = ccp_perform_aes(&op);
+               if (ret) {
+                       cmd->engine_error = cmd_q->cmd_error;
+                       goto e_src;
+               }
+
+               ccp_process_data(&src, NULL, &op);
+       }
+
+       /* Retrieve the AES context - convert from LE to BE using
+        * 32-byte (256-bit) byteswapping
+        */
+       ret = ccp_copy_from_ksb(cmd_q, &ctx, op.jobid, op.ksb_ctx,
+                               CCP_PASSTHRU_BYTESWAP_256BIT);
+       if (ret) {
+               cmd->engine_error = cmd_q->cmd_error;
+               goto e_src;
+       }
+
+       /* ...but we only need AES_BLOCK_SIZE bytes */
+       dm_offset = CCP_KSB_BYTES - AES_BLOCK_SIZE;
+       ccp_get_dm_area(&ctx, dm_offset, aes->iv, 0, aes->iv_len);
+
+e_src:
+       ccp_free_data(&src, cmd_q);
+
+e_ctx:
+       ccp_dm_free(&ctx);
+
+e_key:
+       ccp_dm_free(&key);
+
+       return ret;
+}
+
+static int ccp_run_aes_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
+{
+       struct ccp_aes_engine *aes = &cmd->u.aes;
+       struct ccp_dm_workarea key, ctx;
+       struct ccp_data src, dst;
+       struct ccp_op op;
+       unsigned int dm_offset;
+       bool in_place = false;
+       int ret;
+
+       if (aes->mode == CCP_AES_MODE_CMAC)
+               return ccp_run_aes_cmac_cmd(cmd_q, cmd);
+
+       if (!((aes->key_len == AES_KEYSIZE_128) ||
+             (aes->key_len == AES_KEYSIZE_192) ||
+             (aes->key_len == AES_KEYSIZE_256)))
+               return -EINVAL;
+
+       if (((aes->mode == CCP_AES_MODE_ECB) ||
+            (aes->mode == CCP_AES_MODE_CBC) ||
+            (aes->mode == CCP_AES_MODE_CFB)) &&
+           (aes->src_len & (AES_BLOCK_SIZE - 1)))
+               return -EINVAL;
+
+       if (!aes->key || !aes->src || !aes->dst)
+               return -EINVAL;
+
+       if (aes->mode != CCP_AES_MODE_ECB) {
+               if (aes->iv_len != AES_BLOCK_SIZE)
+                       return -EINVAL;
+
+               if (!aes->iv)
+                       return -EINVAL;
+       }
+
+       BUILD_BUG_ON(CCP_AES_KEY_KSB_COUNT != 1);
+       BUILD_BUG_ON(CCP_AES_CTX_KSB_COUNT != 1);
+
+       ret = -EIO;
+       memset(&op, 0, sizeof(op));
+       op.cmd_q = cmd_q;
+       op.jobid = ccp_gen_jobid(cmd_q->ccp);
+       op.ksb_key = cmd_q->ksb_key;
+       op.ksb_ctx = cmd_q->ksb_ctx;
+       op.init = (aes->mode == CCP_AES_MODE_ECB) ? 0 : 1;
+       op.u.aes.type = aes->type;
+       op.u.aes.mode = aes->mode;
+       op.u.aes.action = aes->action;
+
+       /* All supported key sizes fit in a single (32-byte) KSB entry
+        * and must be in little endian format. Use the 256-bit byte
+        * swap passthru option to convert from big endian to little
+        * endian.
+        */
+       ret = ccp_init_dm_workarea(&key, cmd_q,
+                                  CCP_AES_KEY_KSB_COUNT * CCP_KSB_BYTES,
+                                  DMA_TO_DEVICE);
+       if (ret)
+               return ret;
+
+       dm_offset = CCP_KSB_BYTES - aes->key_len;
+       ccp_set_dm_area(&key, dm_offset, aes->key, 0, aes->key_len);
+       ret = ccp_copy_to_ksb(cmd_q, &key, op.jobid, op.ksb_key,
+                             CCP_PASSTHRU_BYTESWAP_256BIT);
+       if (ret) {
+               cmd->engine_error = cmd_q->cmd_error;
+               goto e_key;
+       }
+
+       /* The AES context fits in a single (32-byte) KSB entry and
+        * must be in little endian format. Use the 256-bit byte swap
+        * passthru option to convert from big endian to little endian.
+        */
+       ret = ccp_init_dm_workarea(&ctx, cmd_q,
+                                  CCP_AES_CTX_KSB_COUNT * CCP_KSB_BYTES,
+                                  DMA_BIDIRECTIONAL);
+       if (ret)
+               goto e_key;
+
+       if (aes->mode != CCP_AES_MODE_ECB) {
+               /* Load the AES context - conver to LE */
+               dm_offset = CCP_KSB_BYTES - AES_BLOCK_SIZE;
+               ccp_set_dm_area(&ctx, dm_offset, aes->iv, 0, aes->iv_len);
+               ret = ccp_copy_to_ksb(cmd_q, &ctx, op.jobid, op.ksb_ctx,
+                                     CCP_PASSTHRU_BYTESWAP_256BIT);
+               if (ret) {
+                       cmd->engine_error = cmd_q->cmd_error;
+                       goto e_ctx;
+               }
+       }
+
+       /* Prepare the input and output data workareas. For in-place
+        * operations we need to set the dma direction to BIDIRECTIONAL
+        * and copy the src workarea to the dst workarea.
+        */
+       if (sg_virt(aes->src) == sg_virt(aes->dst))
+               in_place = true;
+
+       ret = ccp_init_data(&src, cmd_q, aes->src, aes->src_len,
+                           AES_BLOCK_SIZE,
+                           in_place ? DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
+       if (ret)
+               goto e_ctx;
+
+       if (in_place)
+               dst = src;
+       else {
+               ret = ccp_init_data(&dst, cmd_q, aes->dst, aes->src_len,
+                                   AES_BLOCK_SIZE, DMA_FROM_DEVICE);
+               if (ret)
+                       goto e_src;
+       }
+
+       /* Send data to the CCP AES engine */
+       while (src.sg_wa.bytes_left) {
+               ccp_prepare_data(&src, &dst, &op, AES_BLOCK_SIZE, true);
+               if (!src.sg_wa.bytes_left) {
+                       op.eom = 1;
+
+                       /* Since we don't retrieve the AES context in ECB
+                        * mode we have to wait for the operation to complete
+                        * on the last piece of data
+                        */
+                       if (aes->mode == CCP_AES_MODE_ECB)
+                               op.soc = 1;
+               }
+
+               ret = ccp_perform_aes(&op);
+               if (ret) {
+                       cmd->engine_error = cmd_q->cmd_error;
+                       goto e_dst;
+               }
+
+               ccp_process_data(&src, &dst, &op);
+       }
+
+       if (aes->mode != CCP_AES_MODE_ECB) {
+               /* Retrieve the AES context - convert from LE to BE using
+                * 32-byte (256-bit) byteswapping
+                */
+               ret = ccp_copy_from_ksb(cmd_q, &ctx, op.jobid, op.ksb_ctx,
+                                       CCP_PASSTHRU_BYTESWAP_256BIT);
+               if (ret) {
+                       cmd->engine_error = cmd_q->cmd_error;
+                       goto e_dst;
+               }
+
+               /* ...but we only need AES_BLOCK_SIZE bytes */
+               dm_offset = CCP_KSB_BYTES - AES_BLOCK_SIZE;
+               ccp_get_dm_area(&ctx, dm_offset, aes->iv, 0, aes->iv_len);
+       }
+
+e_dst:
+       if (!in_place)
+               ccp_free_data(&dst, cmd_q);
+
+e_src:
+       ccp_free_data(&src, cmd_q);
+
+e_ctx:
+       ccp_dm_free(&ctx);
+
+e_key:
+       ccp_dm_free(&key);
+
+       return ret;
+}
+
+static int ccp_run_xts_aes_cmd(struct ccp_cmd_queue *cmd_q,
+                              struct ccp_cmd *cmd)
+{
+       struct ccp_xts_aes_engine *xts = &cmd->u.xts;
+       struct ccp_dm_workarea key, ctx;
+       struct ccp_data src, dst;
+       struct ccp_op op;
+       unsigned int unit_size, dm_offset;
+       bool in_place = false;
+       int ret;
+
+       switch (xts->unit_size) {
+       case CCP_XTS_AES_UNIT_SIZE_16:
+               unit_size = 16;
+               break;
+       case CCP_XTS_AES_UNIT_SIZE_512:
+               unit_size = 512;
+               break;
+       case CCP_XTS_AES_UNIT_SIZE_1024:
+               unit_size = 1024;
+               break;
+       case CCP_XTS_AES_UNIT_SIZE_2048:
+               unit_size = 2048;
+               break;
+       case CCP_XTS_AES_UNIT_SIZE_4096:
+               unit_size = 4096;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       if (xts->key_len != AES_KEYSIZE_128)
+               return -EINVAL;
+
+       if (!xts->final && (xts->src_len & (AES_BLOCK_SIZE - 1)))
+               return -EINVAL;
+
+       if (xts->iv_len != AES_BLOCK_SIZE)
+               return -EINVAL;
+
+       if (!xts->key || !xts->iv || !xts->src || !xts->dst)
+               return -EINVAL;
+
+       BUILD_BUG_ON(CCP_XTS_AES_KEY_KSB_COUNT != 1);
+       BUILD_BUG_ON(CCP_XTS_AES_CTX_KSB_COUNT != 1);
+
+       ret = -EIO;
+       memset(&op, 0, sizeof(op));
+       op.cmd_q = cmd_q;
+       op.jobid = ccp_gen_jobid(cmd_q->ccp);
+       op.ksb_key = cmd_q->ksb_key;
+       op.ksb_ctx = cmd_q->ksb_ctx;
+       op.init = 1;
+       op.u.xts.action = xts->action;
+       op.u.xts.unit_size = xts->unit_size;
+
+       /* All supported key sizes fit in a single (32-byte) KSB entry
+        * and must be in little endian format. Use the 256-bit byte
+        * swap passthru option to convert from big endian to little
+        * endian.
+        */
+       ret = ccp_init_dm_workarea(&key, cmd_q,
+                                  CCP_XTS_AES_KEY_KSB_COUNT * CCP_KSB_BYTES,
+                                  DMA_TO_DEVICE);
+       if (ret)
+               return ret;
+
+       dm_offset = CCP_KSB_BYTES - AES_KEYSIZE_128;
+       ccp_set_dm_area(&key, dm_offset, xts->key, 0, xts->key_len);
+       ccp_set_dm_area(&key, 0, xts->key, dm_offset, xts->key_len);
+       ret = ccp_copy_to_ksb(cmd_q, &key, op.jobid, op.ksb_key,
+                             CCP_PASSTHRU_BYTESWAP_256BIT);
+       if (ret) {
+               cmd->engine_error = cmd_q->cmd_error;
+               goto e_key;
+       }
+
+       /* The AES context fits in a single (32-byte) KSB entry and
+        * for XTS is already in little endian format so no byte swapping
+        * is needed.
+        */
+       ret = ccp_init_dm_workarea(&ctx, cmd_q,
+                                  CCP_XTS_AES_CTX_KSB_COUNT * CCP_KSB_BYTES,
+                                  DMA_BIDIRECTIONAL);
+       if (ret)
+               goto e_key;
+
+       ccp_set_dm_area(&ctx, 0, xts->iv, 0, xts->iv_len);
+       ret = ccp_copy_to_ksb(cmd_q, &ctx, op.jobid, op.ksb_ctx,
+                             CCP_PASSTHRU_BYTESWAP_NOOP);
+       if (ret) {
+               cmd->engine_error = cmd_q->cmd_error;
+               goto e_ctx;
+       }
+
+       /* Prepare the input and output data workareas. For in-place
+        * operations we need to set the dma direction to BIDIRECTIONAL
+        * and copy the src workarea to the dst workarea.
+        */
+       if (sg_virt(xts->src) == sg_virt(xts->dst))
+               in_place = true;
+
+       ret = ccp_init_data(&src, cmd_q, xts->src, xts->src_len,
+                           unit_size,
+                           in_place ? DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
+       if (ret)
+               goto e_ctx;
+
+       if (in_place)
+               dst = src;
+       else {
+               ret = ccp_init_data(&dst, cmd_q, xts->dst, xts->src_len,
+                                   unit_size, DMA_FROM_DEVICE);
+               if (ret)
+                       goto e_src;
+       }
+
+       /* Send data to the CCP AES engine */
+       while (src.sg_wa.bytes_left) {
+               ccp_prepare_data(&src, &dst, &op, unit_size, true);
+               if (!src.sg_wa.bytes_left)
+                       op.eom = 1;
+
+               ret = ccp_perform_xts_aes(&op);
+               if (ret) {
+                       cmd->engine_error = cmd_q->cmd_error;
+                       goto e_dst;
+               }
+
+               ccp_process_data(&src, &dst, &op);
+       }
+
+       /* Retrieve the AES context - convert from LE to BE using
+        * 32-byte (256-bit) byteswapping
+        */
+       ret = ccp_copy_from_ksb(cmd_q, &ctx, op.jobid, op.ksb_ctx,
+                               CCP_PASSTHRU_BYTESWAP_256BIT);
+       if (ret) {
+               cmd->engine_error = cmd_q->cmd_error;
+               goto e_dst;
+       }
+
+       /* ...but we only need AES_BLOCK_SIZE bytes */
+       dm_offset = CCP_KSB_BYTES - AES_BLOCK_SIZE;
+       ccp_get_dm_area(&ctx, dm_offset, xts->iv, 0, xts->iv_len);
+
+e_dst:
+       if (!in_place)
+               ccp_free_data(&dst, cmd_q);
+
+e_src:
+       ccp_free_data(&src, cmd_q);
+
+e_ctx:
+       ccp_dm_free(&ctx);
+
+e_key:
+       ccp_dm_free(&key);
+
+       return ret;
+}
+
+static int ccp_run_sha_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
+{
+       struct ccp_sha_engine *sha = &cmd->u.sha;
+       struct ccp_dm_workarea ctx;
+       struct ccp_data src;
+       struct ccp_op op;
+       int ret;
+
+       if (sha->ctx_len != CCP_SHA_CTXSIZE)
+               return -EINVAL;
+
+       if (!sha->ctx)
+               return -EINVAL;
+
+       if (!sha->final && (sha->src_len & (CCP_SHA_BLOCKSIZE - 1)))
+               return -EINVAL;
+
+       if (!sha->src_len) {
+               const u8 *sha_zero;
+
+               /* Not final, just return */
+               if (!sha->final)
+                       return 0;
+
+               /* CCP can't do a zero length sha operation so the caller
+                * must buffer the data.
+                */
+               if (sha->msg_bits)
+                       return -EINVAL;
+
+               /* A sha operation for a message with a total length of zero,
+                * return known result.
+                */
+               switch (sha->type) {
+               case CCP_SHA_TYPE_1:
+                       sha_zero = ccp_sha1_zero;
+                       break;
+               case CCP_SHA_TYPE_224:
+                       sha_zero = ccp_sha224_zero;
+                       break;
+               case CCP_SHA_TYPE_256:
+                       sha_zero = ccp_sha256_zero;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+
+               scatterwalk_map_and_copy((void *)sha_zero, sha->ctx, 0,
+                                        sha->ctx_len, 1);
+
+               return 0;
+       }
+
+       if (!sha->src)
+               return -EINVAL;
+
+       BUILD_BUG_ON(CCP_SHA_KSB_COUNT != 1);
+
+       memset(&op, 0, sizeof(op));
+       op.cmd_q = cmd_q;
+       op.jobid = ccp_gen_jobid(cmd_q->ccp);
+       op.ksb_ctx = cmd_q->ksb_ctx;
+       op.u.sha.type = sha->type;
+       op.u.sha.msg_bits = sha->msg_bits;
+
+       /* The SHA context fits in a single (32-byte) KSB entry and
+        * must be in little endian format. Use the 256-bit byte swap
+        * passthru option to convert from big endian to little endian.
+        */
+       ret = ccp_init_dm_workarea(&ctx, cmd_q,
+                                  CCP_SHA_KSB_COUNT * CCP_KSB_BYTES,
+                                  DMA_BIDIRECTIONAL);
+       if (ret)
+               return ret;
+
+       ccp_set_dm_area(&ctx, 0, sha->ctx, 0, sha->ctx_len);
+       ret = ccp_copy_to_ksb(cmd_q, &ctx, op.jobid, op.ksb_ctx,
+                             CCP_PASSTHRU_BYTESWAP_256BIT);
+       if (ret) {
+               cmd->engine_error = cmd_q->cmd_error;
+               goto e_ctx;
+       }
+
+       /* Send data to the CCP SHA engine */
+       ret = ccp_init_data(&src, cmd_q, sha->src, sha->src_len,
+                           CCP_SHA_BLOCKSIZE, DMA_TO_DEVICE);
+       if (ret)
+               goto e_ctx;
+
+       while (src.sg_wa.bytes_left) {
+               ccp_prepare_data(&src, NULL, &op, CCP_SHA_BLOCKSIZE, false);
+               if (sha->final && !src.sg_wa.bytes_left)
+                       op.eom = 1;
+
+               ret = ccp_perform_sha(&op);
+               if (ret) {
+                       cmd->engine_error = cmd_q->cmd_error;
+                       goto e_data;
+               }
+
+               ccp_process_data(&src, NULL, &op);
+       }
+
+       /* Retrieve the SHA context - convert from LE to BE using
+        * 32-byte (256-bit) byteswapping to BE
+        */
+       ret = ccp_copy_from_ksb(cmd_q, &ctx, op.jobid, op.ksb_ctx,
+                               CCP_PASSTHRU_BYTESWAP_256BIT);
+       if (ret) {
+               cmd->engine_error = cmd_q->cmd_error;
+               goto e_data;
+       }
+
+       ccp_get_dm_area(&ctx, 0, sha->ctx, 0, sha->ctx_len);
+
+e_data:
+       ccp_free_data(&src, cmd_q);
+
+e_ctx:
+       ccp_dm_free(&ctx);
+
+       return ret;
+}
+
+static int ccp_run_rsa_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
+{
+       struct ccp_rsa_engine *rsa = &cmd->u.rsa;
+       struct ccp_dm_workarea exp, src;
+       struct ccp_data dst;
+       struct ccp_op op;
+       unsigned int ksb_count, i_len, o_len;
+       int ret;
+
+       if (rsa->key_size > CCP_RSA_MAX_WIDTH)
+               return -EINVAL;
+
+       if (!rsa->exp || !rsa->mod || !rsa->src || !rsa->dst)
+               return -EINVAL;
+
+       /* The RSA modulus must precede the message being acted upon, so
+        * it must be copied to a DMA area where the message and the
+        * modulus can be concatenated.  Therefore the input buffer
+        * length required is twice the output buffer length (which
+        * must be a multiple of 256-bits).
+        */
+       o_len = ((rsa->key_size + 255) / 256) * 32;
+       i_len = o_len * 2;
+
+       ksb_count = o_len / CCP_KSB_BYTES;
+
+       memset(&op, 0, sizeof(op));
+       op.cmd_q = cmd_q;
+       op.jobid = ccp_gen_jobid(cmd_q->ccp);
+       op.ksb_key = ccp_alloc_ksb(cmd_q->ccp, ksb_count);
+       if (!op.ksb_key)
+               return -EIO;
+
+       /* The RSA exponent may span multiple (32-byte) KSB entries and must
+        * be in little endian format. Reverse copy each 32-byte chunk
+        * of the exponent (En chunk to E0 chunk, E(n-1) chunk to E1 chunk)
+        * and each byte within that chunk and do not perform any byte swap
+        * operations on the passthru operation.
+        */
+       ret = ccp_init_dm_workarea(&exp, cmd_q, o_len, DMA_TO_DEVICE);
+       if (ret)
+               goto e_ksb;
+
+       ccp_reverse_set_dm_area(&exp, rsa->exp, rsa->exp_len, CCP_KSB_BYTES,
+                               true);
+       ret = ccp_copy_to_ksb(cmd_q, &exp, op.jobid, op.ksb_key,
+                             CCP_PASSTHRU_BYTESWAP_NOOP);
+       if (ret) {
+               cmd->engine_error = cmd_q->cmd_error;
+               goto e_exp;
+       }
+
+       /* Concatenate the modulus and the message. Both the modulus and
+        * the operands must be in little endian format.  Since the input
+        * is in big endian format it must be converted.
+        */
+       ret = ccp_init_dm_workarea(&src, cmd_q, i_len, DMA_TO_DEVICE);
+       if (ret)
+               goto e_exp;
+
+       ccp_reverse_set_dm_area(&src, rsa->mod, rsa->mod_len, CCP_KSB_BYTES,
+                               true);
+       src.address += o_len;   /* Adjust the address for the copy operation */
+       ccp_reverse_set_dm_area(&src, rsa->src, rsa->src_len, CCP_KSB_BYTES,
+                               true);
+       src.address -= o_len;   /* Reset the address to original value */
+
+       /* Prepare the output area for the operation */
+       ret = ccp_init_data(&dst, cmd_q, rsa->dst, rsa->mod_len,
+                           o_len, DMA_FROM_DEVICE);
+       if (ret)
+               goto e_src;
+
+       op.soc = 1;
+       op.src.u.dma.address = src.dma.address;
+       op.src.u.dma.offset = 0;
+       op.src.u.dma.length = i_len;
+       op.dst.u.dma.address = dst.dm_wa.dma.address;
+       op.dst.u.dma.offset = 0;
+       op.dst.u.dma.length = o_len;
+
+       op.u.rsa.mod_size = rsa->key_size;
+       op.u.rsa.input_len = i_len;
+
+       ret = ccp_perform_rsa(&op);
+       if (ret) {
+               cmd->engine_error = cmd_q->cmd_error;
+               goto e_dst;
+       }
+
+       ccp_reverse_get_dm_area(&dst.dm_wa, rsa->dst, rsa->mod_len);
+
+e_dst:
+       ccp_free_data(&dst, cmd_q);
+
+e_src:
+       ccp_dm_free(&src);
+
+e_exp:
+       ccp_dm_free(&exp);
+
+e_ksb:
+       ccp_free_ksb(cmd_q->ccp, op.ksb_key, ksb_count);
+
+       return ret;
+}
+
+static int ccp_run_passthru_cmd(struct ccp_cmd_queue *cmd_q,
+                               struct ccp_cmd *cmd)
+{
+       struct ccp_passthru_engine *pt = &cmd->u.passthru;
+       struct ccp_dm_workarea mask;
+       struct ccp_data src, dst;
+       struct ccp_op op;
+       bool in_place = false;
+       unsigned int i;
+       int ret;
+
+       if (!pt->final && (pt->src_len & (CCP_PASSTHRU_BLOCKSIZE - 1)))
+               return -EINVAL;
+
+       if (!pt->src || !pt->dst)
+               return -EINVAL;
+
+       if (pt->bit_mod != CCP_PASSTHRU_BITWISE_NOOP) {
+               if (pt->mask_len != CCP_PASSTHRU_MASKSIZE)
+                       return -EINVAL;
+               if (!pt->mask)
+                       return -EINVAL;
+       }
+
+       BUILD_BUG_ON(CCP_PASSTHRU_KSB_COUNT != 1);
+
+       memset(&op, 0, sizeof(op));
+       op.cmd_q = cmd_q;
+       op.jobid = ccp_gen_jobid(cmd_q->ccp);
+
+       if (pt->bit_mod != CCP_PASSTHRU_BITWISE_NOOP) {
+               /* Load the mask */
+               op.ksb_key = cmd_q->ksb_key;
+
+               ret = ccp_init_dm_workarea(&mask, cmd_q,
+                                          CCP_PASSTHRU_KSB_COUNT *
+                                          CCP_KSB_BYTES,
+                                          DMA_TO_DEVICE);
+               if (ret)
+                       return ret;
+
+               ccp_set_dm_area(&mask, 0, pt->mask, 0, pt->mask_len);
+               ret = ccp_copy_to_ksb(cmd_q, &mask, op.jobid, op.ksb_key,
+                                     CCP_PASSTHRU_BYTESWAP_NOOP);
+               if (ret) {
+                       cmd->engine_error = cmd_q->cmd_error;
+                       goto e_mask;
+               }
+       }
+
+       /* Prepare the input and output data workareas. For in-place
+        * operations we need to set the dma direction to BIDIRECTIONAL
+        * and copy the src workarea to the dst workarea.
+        */
+       if (sg_virt(pt->src) == sg_virt(pt->dst))
+               in_place = true;
+
+       ret = ccp_init_data(&src, cmd_q, pt->src, pt->src_len,
+                           CCP_PASSTHRU_MASKSIZE,
+                           in_place ? DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
+       if (ret)
+               goto e_mask;
+
+       if (in_place)
+               dst = src;
+       else {
+               ret = ccp_init_data(&dst, cmd_q, pt->dst, pt->src_len,
+                                   CCP_PASSTHRU_MASKSIZE, DMA_FROM_DEVICE);
+               if (ret)
+                       goto e_src;
+       }
+
+       /* Send data to the CCP Passthru engine
+        *   Because the CCP engine works on a single source and destination
+        *   dma address at a time, each entry in the source scatterlist
+        *   (after the dma_map_sg call) must be less than or equal to the
+        *   (remaining) length in the destination scatterlist entry and the
+        *   length must be a multiple of CCP_PASSTHRU_BLOCKSIZE
+        */
+       dst.sg_wa.sg_used = 0;
+       for (i = 1; i <= src.sg_wa.dma_count; i++) {
+               if (!dst.sg_wa.sg ||
+                   (dst.sg_wa.sg->length < src.sg_wa.sg->length)) {
+                       ret = -EINVAL;
+                       goto e_dst;
+               }
+
+               if (i == src.sg_wa.dma_count) {
+                       op.eom = 1;
+                       op.soc = 1;
+               }
+
+               op.src.type = CCP_MEMTYPE_SYSTEM;
+               op.src.u.dma.address = sg_dma_address(src.sg_wa.sg);
+               op.src.u.dma.offset = 0;
+               op.src.u.dma.length = sg_dma_len(src.sg_wa.sg);
+
+               op.dst.type = CCP_MEMTYPE_SYSTEM;
+               op.dst.u.dma.address = sg_dma_address(dst.sg_wa.sg);
+               op.src.u.dma.offset = dst.sg_wa.sg_used;
+               op.src.u.dma.length = op.src.u.dma.length;
+
+               ret = ccp_perform_passthru(&op);
+               if (ret) {
+                       cmd->engine_error = cmd_q->cmd_error;
+                       goto e_dst;
+               }
+
+               dst.sg_wa.sg_used += src.sg_wa.sg->length;
+               if (dst.sg_wa.sg_used == dst.sg_wa.sg->length) {
+                       dst.sg_wa.sg = sg_next(dst.sg_wa.sg);
+                       dst.sg_wa.sg_used = 0;
+               }
+               src.sg_wa.sg = sg_next(src.sg_wa.sg);
+       }
+
+e_dst:
+       if (!in_place)
+               ccp_free_data(&dst, cmd_q);
+
+e_src:
+       ccp_free_data(&src, cmd_q);
+
+e_mask:
+       if (pt->bit_mod != CCP_PASSTHRU_BITWISE_NOOP)
+               ccp_dm_free(&mask);
+
+       return ret;
+}
+
+static int ccp_run_ecc_mm_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
+{
+       struct ccp_ecc_engine *ecc = &cmd->u.ecc;
+       struct ccp_dm_workarea src, dst;
+       struct ccp_op op;
+       int ret;
+       u8 *save;
+
+       if (!ecc->u.mm.operand_1 ||
+           (ecc->u.mm.operand_1_len > CCP_ECC_MODULUS_BYTES))
+               return -EINVAL;
+
+       if (ecc->function != CCP_ECC_FUNCTION_MINV_384BIT)
+               if (!ecc->u.mm.operand_2 ||
+                   (ecc->u.mm.operand_2_len > CCP_ECC_MODULUS_BYTES))
+                       return -EINVAL;
+
+       if (!ecc->u.mm.result ||
+           (ecc->u.mm.result_len < CCP_ECC_MODULUS_BYTES))
+               return -EINVAL;
+
+       memset(&op, 0, sizeof(op));
+       op.cmd_q = cmd_q;
+       op.jobid = ccp_gen_jobid(cmd_q->ccp);
+
+       /* Concatenate the modulus and the operands. Both the modulus and
+        * the operands must be in little endian format.  Since the input
+        * is in big endian format it must be converted and placed in a
+        * fixed length buffer.
+        */
+       ret = ccp_init_dm_workarea(&src, cmd_q, CCP_ECC_SRC_BUF_SIZE,
+                                  DMA_TO_DEVICE);
+       if (ret)
+               return ret;
+
+       /* Save the workarea address since it is updated in order to perform
+        * the concatenation
+        */
+       save = src.address;
+
+       /* Copy the ECC modulus */
+       ccp_reverse_set_dm_area(&src, ecc->mod, ecc->mod_len,
+                               CCP_ECC_OPERAND_SIZE, true);
+       src.address += CCP_ECC_OPERAND_SIZE;
+
+       /* Copy the first operand */
+       ccp_reverse_set_dm_area(&src, ecc->u.mm.operand_1,
+                               ecc->u.mm.operand_1_len,
+                               CCP_ECC_OPERAND_SIZE, true);
+       src.address += CCP_ECC_OPERAND_SIZE;
+
+       if (ecc->function != CCP_ECC_FUNCTION_MINV_384BIT) {
+               /* Copy the second operand */
+               ccp_reverse_set_dm_area(&src, ecc->u.mm.operand_2,
+                                       ecc->u.mm.operand_2_len,
+                                       CCP_ECC_OPERAND_SIZE, true);
+               src.address += CCP_ECC_OPERAND_SIZE;
+       }
+
+       /* Restore the workarea address */
+       src.address = save;
+
+       /* Prepare the output area for the operation */
+       ret = ccp_init_dm_workarea(&dst, cmd_q, CCP_ECC_DST_BUF_SIZE,
+                                  DMA_FROM_DEVICE);
+       if (ret)
+               goto e_src;
+
+       op.soc = 1;
+       op.src.u.dma.address = src.dma.address;
+       op.src.u.dma.offset = 0;
+       op.src.u.dma.length = src.length;
+       op.dst.u.dma.address = dst.dma.address;
+       op.dst.u.dma.offset = 0;
+       op.dst.u.dma.length = dst.length;
+
+       op.u.ecc.function = cmd->u.ecc.function;
+
+       ret = ccp_perform_ecc(&op);
+       if (ret) {
+               cmd->engine_error = cmd_q->cmd_error;
+               goto e_dst;
+       }
+
+       ecc->ecc_result = le16_to_cpup(
+               (const __le16 *)(dst.address + CCP_ECC_RESULT_OFFSET));
+       if (!(ecc->ecc_result & CCP_ECC_RESULT_SUCCESS)) {
+               ret = -EIO;
+               goto e_dst;
+       }
+
+       /* Save the ECC result */
+       ccp_reverse_get_dm_area(&dst, ecc->u.mm.result, CCP_ECC_MODULUS_BYTES);
+
+e_dst:
+       ccp_dm_free(&dst);
+
+e_src:
+       ccp_dm_free(&src);
+
+       return ret;
+}
+
+static int ccp_run_ecc_pm_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
+{
+       struct ccp_ecc_engine *ecc = &cmd->u.ecc;
+       struct ccp_dm_workarea src, dst;
+       struct ccp_op op;
+       int ret;
+       u8 *save;
+
+       if (!ecc->u.pm.point_1.x ||
+           (ecc->u.pm.point_1.x_len > CCP_ECC_MODULUS_BYTES) ||
+           !ecc->u.pm.point_1.y ||
+           (ecc->u.pm.point_1.y_len > CCP_ECC_MODULUS_BYTES))
+               return -EINVAL;
+
+       if (ecc->function == CCP_ECC_FUNCTION_PADD_384BIT) {
+               if (!ecc->u.pm.point_2.x ||
+                   (ecc->u.pm.point_2.x_len > CCP_ECC_MODULUS_BYTES) ||
+                   !ecc->u.pm.point_2.y ||
+                   (ecc->u.pm.point_2.y_len > CCP_ECC_MODULUS_BYTES))
+                       return -EINVAL;
+       } else {
+               if (!ecc->u.pm.domain_a ||
+                   (ecc->u.pm.domain_a_len > CCP_ECC_MODULUS_BYTES))
+                       return -EINVAL;
+
+               if (ecc->function == CCP_ECC_FUNCTION_PMUL_384BIT)
+                       if (!ecc->u.pm.scalar ||
+                           (ecc->u.pm.scalar_len > CCP_ECC_MODULUS_BYTES))
+                               return -EINVAL;
+       }
+
+       if (!ecc->u.pm.result.x ||
+           (ecc->u.pm.result.x_len < CCP_ECC_MODULUS_BYTES) ||
+           !ecc->u.pm.result.y ||
+           (ecc->u.pm.result.y_len < CCP_ECC_MODULUS_BYTES))
+               return -EINVAL;
+
+       memset(&op, 0, sizeof(op));
+       op.cmd_q = cmd_q;
+       op.jobid = ccp_gen_jobid(cmd_q->ccp);
+
+       /* Concatenate the modulus and the operands. Both the modulus and
+        * the operands must be in little endian format.  Since the input
+        * is in big endian format it must be converted and placed in a
+        * fixed length buffer.
+        */
+       ret = ccp_init_dm_workarea(&src, cmd_q, CCP_ECC_SRC_BUF_SIZE,
+                                  DMA_TO_DEVICE);
+       if (ret)
+               return ret;
+
+       /* Save the workarea address since it is updated in order to perform
+        * the concatenation
+        */
+       save = src.address;
+
+       /* Copy the ECC modulus */
+       ccp_reverse_set_dm_area(&src, ecc->mod, ecc->mod_len,
+                               CCP_ECC_OPERAND_SIZE, true);
+       src.address += CCP_ECC_OPERAND_SIZE;
+
+       /* Copy the first point X and Y coordinate */
+       ccp_reverse_set_dm_area(&src, ecc->u.pm.point_1.x,
+                               ecc->u.pm.point_1.x_len,
+                               CCP_ECC_OPERAND_SIZE, true);
+       src.address += CCP_ECC_OPERAND_SIZE;
+       ccp_reverse_set_dm_area(&src, ecc->u.pm.point_1.y,
+                               ecc->u.pm.point_1.y_len,
+                               CCP_ECC_OPERAND_SIZE, true);
+       src.address += CCP_ECC_OPERAND_SIZE;
+
+       /* Set the first point Z coordianate to 1 */
+       *(src.address) = 0x01;
+       src.address += CCP_ECC_OPERAND_SIZE;
+
+       if (ecc->function == CCP_ECC_FUNCTION_PADD_384BIT) {
+               /* Copy the second point X and Y coordinate */
+               ccp_reverse_set_dm_area(&src, ecc->u.pm.point_2.x,
+                                       ecc->u.pm.point_2.x_len,
+                                       CCP_ECC_OPERAND_SIZE, true);
+               src.address += CCP_ECC_OPERAND_SIZE;
+               ccp_reverse_set_dm_area(&src, ecc->u.pm.point_2.y,
+                                       ecc->u.pm.point_2.y_len,
+                                       CCP_ECC_OPERAND_SIZE, true);
+               src.address += CCP_ECC_OPERAND_SIZE;
+
+               /* Set the second point Z coordianate to 1 */
+               *(src.address) = 0x01;
+               src.address += CCP_ECC_OPERAND_SIZE;
+       } else {
+               /* Copy the Domain "a" parameter */
+               ccp_reverse_set_dm_area(&src, ecc->u.pm.domain_a,
+                                       ecc->u.pm.domain_a_len,
+                                       CCP_ECC_OPERAND_SIZE, true);
+               src.address += CCP_ECC_OPERAND_SIZE;
+
+               if (ecc->function == CCP_ECC_FUNCTION_PMUL_384BIT) {
+                       /* Copy the scalar value */
+                       ccp_reverse_set_dm_area(&src, ecc->u.pm.scalar,
+                                               ecc->u.pm.scalar_len,
+                                               CCP_ECC_OPERAND_SIZE, true);
+                       src.address += CCP_ECC_OPERAND_SIZE;
+               }
+       }
+
+       /* Restore the workarea address */
+       src.address = save;
+
+       /* Prepare the output area for the operation */
+       ret = ccp_init_dm_workarea(&dst, cmd_q, CCP_ECC_DST_BUF_SIZE,
+                                  DMA_FROM_DEVICE);
+       if (ret)
+               goto e_src;
+
+       op.soc = 1;
+       op.src.u.dma.address = src.dma.address;
+       op.src.u.dma.offset = 0;
+       op.src.u.dma.length = src.length;
+       op.dst.u.dma.address = dst.dma.address;
+       op.dst.u.dma.offset = 0;
+       op.dst.u.dma.length = dst.length;
+
+       op.u.ecc.function = cmd->u.ecc.function;
+
+       ret = ccp_perform_ecc(&op);
+       if (ret) {
+               cmd->engine_error = cmd_q->cmd_error;
+               goto e_dst;
+       }
+
+       ecc->ecc_result = le16_to_cpup(
+               (const __le16 *)(dst.address + CCP_ECC_RESULT_OFFSET));
+       if (!(ecc->ecc_result & CCP_ECC_RESULT_SUCCESS)) {
+               ret = -EIO;
+               goto e_dst;
+       }
+
+       /* Save the workarea address since it is updated as we walk through
+        * to copy the point math result
+        */
+       save = dst.address;
+
+       /* Save the ECC result X and Y coordinates */
+       ccp_reverse_get_dm_area(&dst, ecc->u.pm.result.x,
+                               CCP_ECC_MODULUS_BYTES);
+       dst.address += CCP_ECC_OUTPUT_SIZE;
+       ccp_reverse_get_dm_area(&dst, ecc->u.pm.result.y,
+                               CCP_ECC_MODULUS_BYTES);
+       dst.address += CCP_ECC_OUTPUT_SIZE;
+
+       /* Restore the workarea address */
+       dst.address = save;
+
+e_dst:
+       ccp_dm_free(&dst);
+
+e_src:
+       ccp_dm_free(&src);
+
+       return ret;
+}
+
+static int ccp_run_ecc_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
+{
+       struct ccp_ecc_engine *ecc = &cmd->u.ecc;
+
+       ecc->ecc_result = 0;
+
+       if (!ecc->mod ||
+           (ecc->mod_len > CCP_ECC_MODULUS_BYTES))
+               return -EINVAL;
+
+       switch (ecc->function) {
+       case CCP_ECC_FUNCTION_MMUL_384BIT:
+       case CCP_ECC_FUNCTION_MADD_384BIT:
+       case CCP_ECC_FUNCTION_MINV_384BIT:
+               return ccp_run_ecc_mm_cmd(cmd_q, cmd);
+
+       case CCP_ECC_FUNCTION_PADD_384BIT:
+       case CCP_ECC_FUNCTION_PMUL_384BIT:
+       case CCP_ECC_FUNCTION_PDBL_384BIT:
+               return ccp_run_ecc_pm_cmd(cmd_q, cmd);
+
+       default:
+               return -EINVAL;
+       }
+}
+
+int ccp_run_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
+{
+       int ret;
+
+       cmd->engine_error = 0;
+       cmd_q->cmd_error = 0;
+       cmd_q->int_rcvd = 0;
+       cmd_q->free_slots = CMD_Q_DEPTH(ioread32(cmd_q->reg_status));
+
+       switch (cmd->engine) {
+       case CCP_ENGINE_AES:
+               ret = ccp_run_aes_cmd(cmd_q, cmd);
+               break;
+       case CCP_ENGINE_XTS_AES_128:
+               ret = ccp_run_xts_aes_cmd(cmd_q, cmd);
+               break;
+       case CCP_ENGINE_SHA:
+               ret = ccp_run_sha_cmd(cmd_q, cmd);
+               break;
+       case CCP_ENGINE_RSA:
+               ret = ccp_run_rsa_cmd(cmd_q, cmd);
+               break;
+       case CCP_ENGINE_PASSTHRU:
+               ret = ccp_run_passthru_cmd(cmd_q, cmd);
+               break;
+       case CCP_ENGINE_ECC:
+               ret = ccp_run_ecc_cmd(cmd_q, cmd);
+               break;
+       default:
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
diff --git a/drivers/crypto/ccp/ccp-pci.c b/drivers/crypto/ccp/ccp-pci.c
new file mode 100644 (file)
index 0000000..1fbeaf1
--- /dev/null
@@ -0,0 +1,360 @@
+/*
+ * AMD Cryptographic Coprocessor (CCP) driver
+ *
+ * Copyright (C) 2013 Advanced Micro Devices, Inc.
+ *
+ * Author: Tom Lendacky <thomas.lendacky@amd.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/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/kthread.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/ccp.h>
+
+#include "ccp-dev.h"
+
+#define IO_BAR                         2
+#define MSIX_VECTORS                   2
+
+struct ccp_msix {
+       u32 vector;
+       char name[16];
+};
+
+struct ccp_pci {
+       int msix_count;
+       struct ccp_msix msix[MSIX_VECTORS];
+};
+
+static int ccp_get_msix_irqs(struct ccp_device *ccp)
+{
+       struct ccp_pci *ccp_pci = ccp->dev_specific;
+       struct device *dev = ccp->dev;
+       struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+       struct msix_entry msix_entry[MSIX_VECTORS];
+       unsigned int name_len = sizeof(ccp_pci->msix[0].name) - 1;
+       int v, ret;
+
+       for (v = 0; v < ARRAY_SIZE(msix_entry); v++)
+               msix_entry[v].entry = v;
+
+       while ((ret = pci_enable_msix(pdev, msix_entry, v)) > 0)
+               v = ret;
+       if (ret)
+               return ret;
+
+       ccp_pci->msix_count = v;
+       for (v = 0; v < ccp_pci->msix_count; v++) {
+               /* Set the interrupt names and request the irqs */
+               snprintf(ccp_pci->msix[v].name, name_len, "ccp-%u", v);
+               ccp_pci->msix[v].vector = msix_entry[v].vector;
+               ret = request_irq(ccp_pci->msix[v].vector, ccp_irq_handler,
+                                 0, ccp_pci->msix[v].name, dev);
+               if (ret) {
+                       dev_notice(dev, "unable to allocate MSI-X IRQ (%d)\n",
+                                  ret);
+                       goto e_irq;
+               }
+       }
+
+       return 0;
+
+e_irq:
+       while (v--)
+               free_irq(ccp_pci->msix[v].vector, dev);
+
+       pci_disable_msix(pdev);
+
+       ccp_pci->msix_count = 0;
+
+       return ret;
+}
+
+static int ccp_get_msi_irq(struct ccp_device *ccp)
+{
+       struct device *dev = ccp->dev;
+       struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+       int ret;
+
+       ret = pci_enable_msi(pdev);
+       if (ret)
+               return ret;
+
+       ret = request_irq(pdev->irq, ccp_irq_handler, 0, "ccp", dev);
+       if (ret) {
+               dev_notice(dev, "unable to allocate MSI IRQ (%d)\n", ret);
+               goto e_msi;
+       }
+
+       return 0;
+
+e_msi:
+       pci_disable_msi(pdev);
+
+       return ret;
+}
+
+static int ccp_get_irqs(struct ccp_device *ccp)
+{
+       struct device *dev = ccp->dev;
+       int ret;
+
+       ret = ccp_get_msix_irqs(ccp);
+       if (!ret)
+               return 0;
+
+       /* Couldn't get MSI-X vectors, try MSI */
+       dev_notice(dev, "could not enable MSI-X (%d), trying MSI\n", ret);
+       ret = ccp_get_msi_irq(ccp);
+       if (!ret)
+               return 0;
+
+       /* Couldn't get MSI interrupt */
+       dev_notice(dev, "could not enable MSI (%d)\n", ret);
+
+       return ret;
+}
+
+static void ccp_free_irqs(struct ccp_device *ccp)
+{
+       struct ccp_pci *ccp_pci = ccp->dev_specific;
+       struct device *dev = ccp->dev;
+       struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+
+       if (ccp_pci->msix_count) {
+               while (ccp_pci->msix_count--)
+                       free_irq(ccp_pci->msix[ccp_pci->msix_count].vector,
+                                dev);
+               pci_disable_msix(pdev);
+       } else {
+               free_irq(pdev->irq, dev);
+               pci_disable_msi(pdev);
+       }
+}
+
+static int ccp_find_mmio_area(struct ccp_device *ccp)
+{
+       struct device *dev = ccp->dev;
+       struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+       resource_size_t io_len;
+       unsigned long io_flags;
+       int bar;
+
+       io_flags = pci_resource_flags(pdev, IO_BAR);
+       io_len = pci_resource_len(pdev, IO_BAR);
+       if ((io_flags & IORESOURCE_MEM) && (io_len >= (IO_OFFSET + 0x800)))
+               return IO_BAR;
+
+       for (bar = 0; bar < PCI_STD_RESOURCE_END; bar++) {
+               io_flags = pci_resource_flags(pdev, bar);
+               io_len = pci_resource_len(pdev, bar);
+               if ((io_flags & IORESOURCE_MEM) &&
+                   (io_len >= (IO_OFFSET + 0x800)))
+                       return bar;
+       }
+
+       return -EIO;
+}
+
+static int ccp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+       struct ccp_device *ccp;
+       struct ccp_pci *ccp_pci;
+       struct device *dev = &pdev->dev;
+       unsigned int bar;
+       int ret;
+
+       ret = -ENOMEM;
+       ccp = ccp_alloc_struct(dev);
+       if (!ccp)
+               goto e_err;
+
+       ccp_pci = kzalloc(sizeof(*ccp_pci), GFP_KERNEL);
+       if (!ccp_pci) {
+               ret = -ENOMEM;
+               goto e_free1;
+       }
+       ccp->dev_specific = ccp_pci;
+       ccp->get_irq = ccp_get_irqs;
+       ccp->free_irq = ccp_free_irqs;
+
+       ret = pci_request_regions(pdev, "ccp");
+       if (ret) {
+               dev_err(dev, "pci_request_regions failed (%d)\n", ret);
+               goto e_free2;
+       }
+
+       ret = pci_enable_device(pdev);
+       if (ret) {
+               dev_err(dev, "pci_enable_device failed (%d)\n", ret);
+               goto e_regions;
+       }
+
+       pci_set_master(pdev);
+
+       ret = ccp_find_mmio_area(ccp);
+       if (ret < 0)
+               goto e_device;
+       bar = ret;
+
+       ret = -EIO;
+       ccp->io_map = pci_iomap(pdev, bar, 0);
+       if (ccp->io_map == NULL) {
+               dev_err(dev, "pci_iomap failed\n");
+               goto e_device;
+       }
+       ccp->io_regs = ccp->io_map + IO_OFFSET;
+
+       ret = dma_set_mask(dev, DMA_BIT_MASK(48));
+       if (ret == 0) {
+               ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(48));
+               if (ret) {
+                       dev_err(dev,
+                               "pci_set_consistent_dma_mask failed (%d)\n",
+                               ret);
+                       goto e_bar0;
+               }
+       } else {
+               ret = dma_set_mask(dev, DMA_BIT_MASK(32));
+               if (ret) {
+                       dev_err(dev, "pci_set_dma_mask failed (%d)\n", ret);
+                       goto e_bar0;
+               }
+       }
+
+       dev_set_drvdata(dev, ccp);
+
+       ret = ccp_init(ccp);
+       if (ret)
+               goto e_bar0;
+
+       dev_notice(dev, "enabled\n");
+
+       return 0;
+
+e_bar0:
+       pci_iounmap(pdev, ccp->io_map);
+
+e_device:
+       pci_disable_device(pdev);
+       dev_set_drvdata(dev, NULL);
+
+e_regions:
+       pci_release_regions(pdev);
+
+e_free2:
+       kfree(ccp_pci);
+
+e_free1:
+       kfree(ccp);
+
+e_err:
+       dev_notice(dev, "initialization failed\n");
+       return ret;
+}
+
+static void ccp_pci_remove(struct pci_dev *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct ccp_device *ccp = dev_get_drvdata(dev);
+
+       ccp_destroy(ccp);
+
+       pci_iounmap(pdev, ccp->io_map);
+
+       pci_disable_device(pdev);
+       dev_set_drvdata(dev, NULL);
+
+       pci_release_regions(pdev);
+
+       kfree(ccp);
+
+       dev_notice(dev, "disabled\n");
+}
+
+#ifdef CONFIG_PM
+static int ccp_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       struct device *dev = &pdev->dev;
+       struct ccp_device *ccp = dev_get_drvdata(dev);
+       unsigned long flags;
+       unsigned int i;
+
+       spin_lock_irqsave(&ccp->cmd_lock, flags);
+
+       ccp->suspending = 1;
+
+       /* Wake all the queue kthreads to prepare for suspend */
+       for (i = 0; i < ccp->cmd_q_count; i++)
+               wake_up_process(ccp->cmd_q[i].kthread);
+
+       spin_unlock_irqrestore(&ccp->cmd_lock, flags);
+
+       /* Wait for all queue kthreads to say they're done */
+       while (!ccp_queues_suspended(ccp))
+               wait_event_interruptible(ccp->suspend_queue,
+                                        ccp_queues_suspended(ccp));
+
+       return 0;
+}
+
+static int ccp_pci_resume(struct pci_dev *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct ccp_device *ccp = dev_get_drvdata(dev);
+       unsigned long flags;
+       unsigned int i;
+
+       spin_lock_irqsave(&ccp->cmd_lock, flags);
+
+       ccp->suspending = 0;
+
+       /* Wake up all the kthreads */
+       for (i = 0; i < ccp->cmd_q_count; i++) {
+               ccp->cmd_q[i].suspended = 0;
+               wake_up_process(ccp->cmd_q[i].kthread);
+       }
+
+       spin_unlock_irqrestore(&ccp->cmd_lock, flags);
+
+       return 0;
+}
+#endif
+
+static DEFINE_PCI_DEVICE_TABLE(ccp_pci_table) = {
+       { PCI_VDEVICE(AMD, 0x1537), },
+       /* Last entry must be zero */
+       { 0, }
+};
+MODULE_DEVICE_TABLE(pci, ccp_pci_table);
+
+static struct pci_driver ccp_pci_driver = {
+       .name = "AMD Cryptographic Coprocessor",
+       .id_table = ccp_pci_table,
+       .probe = ccp_pci_probe,
+       .remove = ccp_pci_remove,
+#ifdef CONFIG_PM
+       .suspend = ccp_pci_suspend,
+       .resume = ccp_pci_resume,
+#endif
+};
+
+int ccp_pci_init(void)
+{
+       return pci_register_driver(&ccp_pci_driver);
+}
+
+void ccp_pci_exit(void)
+{
+       pci_unregister_driver(&ccp_pci_driver);
+}
index a9ccbf14096e3c03a9c193042baddc6d5b0e4925..dde41f1df6080a0e067a35d5dad2302c0ba6eb98 100644 (file)
@@ -784,6 +784,7 @@ static int omap_aes_ctr_decrypt(struct ablkcipher_request *req)
 static int omap_aes_cra_init(struct crypto_tfm *tfm)
 {
        struct omap_aes_dev *dd = NULL;
+       int err;
 
        /* Find AES device, currently picks the first device */
        spin_lock_bh(&list_lock);
@@ -792,7 +793,13 @@ static int omap_aes_cra_init(struct crypto_tfm *tfm)
        }
        spin_unlock_bh(&list_lock);
 
-       pm_runtime_get_sync(dd->dev);
+       err = pm_runtime_get_sync(dd->dev);
+       if (err < 0) {
+               dev_err(dd->dev, "%s: failed to get_sync(%d)\n",
+                       __func__, err);
+               return err;
+       }
+
        tfm->crt_ablkcipher.reqsize = sizeof(struct omap_aes_reqctx);
 
        return 0;
@@ -1182,7 +1189,12 @@ static int omap_aes_probe(struct platform_device *pdev)
        dd->phys_base = res.start;
 
        pm_runtime_enable(dev);
-       pm_runtime_get_sync(dev);
+       err = pm_runtime_get_sync(dev);
+       if (err < 0) {
+               dev_err(dev, "%s: failed to get_sync(%d)\n",
+                       __func__, err);
+               goto err_res;
+       }
 
        omap_aes_dma_stop(dd);
 
index e45aaaf0db3069d5c99cef88664dfdc62a87d434..831f9a438b03fd302f4354f3a38b84b11f940e00 100644 (file)
@@ -1970,7 +1970,8 @@ err_algs:
                        crypto_unregister_ahash(
                                        &dd->pdata->algs_info[i].algs_list[j]);
        pm_runtime_disable(dev);
-       dma_release_channel(dd->dma_lch);
+       if (dd->dma_lch)
+               dma_release_channel(dd->dma_lch);
 data_err:
        dev_err(dev, "initialization failed.\n");
 
@@ -1994,7 +1995,9 @@ static int omap_sham_remove(struct platform_device *pdev)
                                        &dd->pdata->algs_info[i].algs_list[j]);
        tasklet_kill(&dd->done_task);
        pm_runtime_disable(&pdev->dev);
-       dma_release_channel(dd->dma_lch);
+
+       if (dd->dma_lch)
+               dma_release_channel(dd->dma_lch);
 
        return 0;
 }
index 905de4427e7c4d1630604db45ffa2ba158983918..a3d2e9b88c41ffd1e39f73cda9959e0b61ac782d 100644 (file)
@@ -338,20 +338,29 @@ DEF_TALITOS_DONE(ch1_3, TALITOS_ISR_CH_1_3_DONE)
 static u32 current_desc_hdr(struct device *dev, int ch)
 {
        struct talitos_private *priv = dev_get_drvdata(dev);
-       int tail = priv->chan[ch].tail;
+       int tail, iter;
        dma_addr_t cur_desc;
 
-       cur_desc = in_be32(priv->chan[ch].reg + TALITOS_CDPR_LO);
+       cur_desc = ((u64)in_be32(priv->chan[ch].reg + TALITOS_CDPR)) << 32;
+       cur_desc |= in_be32(priv->chan[ch].reg + TALITOS_CDPR_LO);
 
-       while (priv->chan[ch].fifo[tail].dma_desc != cur_desc) {
-               tail = (tail + 1) & (priv->fifo_len - 1);
-               if (tail == priv->chan[ch].tail) {
+       if (!cur_desc) {
+               dev_err(dev, "CDPR is NULL, giving up search for offending descriptor\n");
+               return 0;
+       }
+
+       tail = priv->chan[ch].tail;
+
+       iter = tail;
+       while (priv->chan[ch].fifo[iter].dma_desc != cur_desc) {
+               iter = (iter + 1) & (priv->fifo_len - 1);
+               if (iter == tail) {
                        dev_err(dev, "couldn't locate current descriptor\n");
                        return 0;
                }
        }
 
-       return priv->chan[ch].fifo[tail].desc->hdr;
+       return priv->chan[ch].fifo[iter].desc->hdr;
 }
 
 /*
@@ -790,7 +799,7 @@ static void ipsec_esp_unmap(struct device *dev,
 
        if (edesc->assoc_chained)
                talitos_unmap_sg_chain(dev, areq->assoc, DMA_TO_DEVICE);
-       else
+       else if (areq->assoclen)
                /* assoc_nents counts also for IV in non-contiguous cases */
                dma_unmap_sg(dev, areq->assoc,
                             edesc->assoc_nents ? edesc->assoc_nents - 1 : 1,
@@ -973,7 +982,11 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
                dma_sync_single_for_device(dev, edesc->dma_link_tbl,
                                           edesc->dma_len, DMA_BIDIRECTIONAL);
        } else {
-               to_talitos_ptr(&desc->ptr[1], sg_dma_address(areq->assoc));
+               if (areq->assoclen)
+                       to_talitos_ptr(&desc->ptr[1],
+                                      sg_dma_address(areq->assoc));
+               else
+                       to_talitos_ptr(&desc->ptr[1], edesc->iv_dma);
                desc->ptr[1].j_extent = 0;
        }
 
@@ -1108,7 +1121,8 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
                                                 unsigned int authsize,
                                                 unsigned int ivsize,
                                                 int icv_stashing,
-                                                u32 cryptoflags)
+                                                u32 cryptoflags,
+                                                bool encrypt)
 {
        struct talitos_edesc *edesc;
        int assoc_nents = 0, src_nents, dst_nents, alloc_len, dma_len;
@@ -1122,10 +1136,10 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
                return ERR_PTR(-EINVAL);
        }
 
-       if (iv)
+       if (ivsize)
                iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE);
 
-       if (assoc) {
+       if (assoclen) {
                /*
                 * Currently it is assumed that iv is provided whenever assoc
                 * is.
@@ -1141,19 +1155,17 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
                        assoc_nents = assoc_nents ? assoc_nents + 1 : 2;
        }
 
-       src_nents = sg_count(src, cryptlen + authsize, &src_chained);
-       src_nents = (src_nents == 1) ? 0 : src_nents;
-
-       if (!dst) {
-               dst_nents = 0;
-       } else {
-               if (dst == src) {
-                       dst_nents = src_nents;
-               } else {
-                       dst_nents = sg_count(dst, cryptlen + authsize,
-                                            &dst_chained);
-                       dst_nents = (dst_nents == 1) ? 0 : dst_nents;
-               }
+       if (!dst || dst == src) {
+               src_nents = sg_count(src, cryptlen + authsize, &src_chained);
+               src_nents = (src_nents == 1) ? 0 : src_nents;
+               dst_nents = dst ? src_nents : 0;
+       } else { /* dst && dst != src*/
+               src_nents = sg_count(src, cryptlen + (encrypt ? 0 : authsize),
+                                    &src_chained);
+               src_nents = (src_nents == 1) ? 0 : src_nents;
+               dst_nents = sg_count(dst, cryptlen + (encrypt ? authsize : 0),
+                                    &dst_chained);
+               dst_nents = (dst_nents == 1) ? 0 : dst_nents;
        }
 
        /*
@@ -1173,9 +1185,16 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
 
        edesc = kmalloc(alloc_len, GFP_DMA | flags);
        if (!edesc) {
-               talitos_unmap_sg_chain(dev, assoc, DMA_TO_DEVICE);
+               if (assoc_chained)
+                       talitos_unmap_sg_chain(dev, assoc, DMA_TO_DEVICE);
+               else if (assoclen)
+                       dma_unmap_sg(dev, assoc,
+                                    assoc_nents ? assoc_nents - 1 : 1,
+                                    DMA_TO_DEVICE);
+
                if (iv_dma)
                        dma_unmap_single(dev, iv_dma, ivsize, DMA_TO_DEVICE);
+
                dev_err(dev, "could not allocate edescriptor\n");
                return ERR_PTR(-ENOMEM);
        }
@@ -1197,7 +1216,7 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
 }
 
 static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
-                                             int icv_stashing)
+                                             int icv_stashing, bool encrypt)
 {
        struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
        struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
@@ -1206,7 +1225,7 @@ static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
        return talitos_edesc_alloc(ctx->dev, areq->assoc, areq->src, areq->dst,
                                   iv, areq->assoclen, areq->cryptlen,
                                   ctx->authsize, ivsize, icv_stashing,
-                                  areq->base.flags);
+                                  areq->base.flags, encrypt);
 }
 
 static int aead_encrypt(struct aead_request *req)
@@ -1216,7 +1235,7 @@ static int aead_encrypt(struct aead_request *req)
        struct talitos_edesc *edesc;
 
        /* allocate extended descriptor */
-       edesc = aead_edesc_alloc(req, req->iv, 0);
+       edesc = aead_edesc_alloc(req, req->iv, 0, true);
        if (IS_ERR(edesc))
                return PTR_ERR(edesc);
 
@@ -1239,7 +1258,7 @@ static int aead_decrypt(struct aead_request *req)
        req->cryptlen -= authsize;
 
        /* allocate extended descriptor */
-       edesc = aead_edesc_alloc(req, req->iv, 1);
+       edesc = aead_edesc_alloc(req, req->iv, 1, false);
        if (IS_ERR(edesc))
                return PTR_ERR(edesc);
 
@@ -1285,7 +1304,7 @@ static int aead_givencrypt(struct aead_givcrypt_request *req)
        struct talitos_edesc *edesc;
 
        /* allocate extended descriptor */
-       edesc = aead_edesc_alloc(areq, req->giv, 0);
+       edesc = aead_edesc_alloc(areq, req->giv, 0, true);
        if (IS_ERR(edesc))
                return PTR_ERR(edesc);
 
@@ -1441,7 +1460,7 @@ static int common_nonsnoop(struct talitos_edesc *edesc,
 }
 
 static struct talitos_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request *
-                                                   areq)
+                                                   areq, bool encrypt)
 {
        struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
        struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
@@ -1449,7 +1468,7 @@ static struct talitos_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request *
 
        return talitos_edesc_alloc(ctx->dev, NULL, areq->src, areq->dst,
                                   areq->info, 0, areq->nbytes, 0, ivsize, 0,
-                                  areq->base.flags);
+                                  areq->base.flags, encrypt);
 }
 
 static int ablkcipher_encrypt(struct ablkcipher_request *areq)
@@ -1459,7 +1478,7 @@ static int ablkcipher_encrypt(struct ablkcipher_request *areq)
        struct talitos_edesc *edesc;
 
        /* allocate extended descriptor */
-       edesc = ablkcipher_edesc_alloc(areq);
+       edesc = ablkcipher_edesc_alloc(areq, true);
        if (IS_ERR(edesc))
                return PTR_ERR(edesc);
 
@@ -1476,7 +1495,7 @@ static int ablkcipher_decrypt(struct ablkcipher_request *areq)
        struct talitos_edesc *edesc;
 
        /* allocate extended descriptor */
-       edesc = ablkcipher_edesc_alloc(areq);
+       edesc = ablkcipher_edesc_alloc(areq, false);
        if (IS_ERR(edesc))
                return PTR_ERR(edesc);
 
@@ -1628,7 +1647,7 @@ static struct talitos_edesc *ahash_edesc_alloc(struct ahash_request *areq,
        struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
 
        return talitos_edesc_alloc(ctx->dev, NULL, req_ctx->psrc, NULL, NULL, 0,
-                                  nbytes, 0, 0, 0, areq->base.flags);
+                                  nbytes, 0, 0, 0, areq->base.flags, false);
 }
 
 static int ahash_init(struct ahash_request *areq)
index cede6f71cd63feb5afebde508199b9be9a507778..bbbfe6853b18b96b6e6fbcba1707b9d89553a4de 100644 (file)
@@ -116,7 +116,7 @@ static struct bus_opp_table exynos4210_busclk_table[] = {
 };
 
 /*
- * MIF is the main control knob clock for exynox4x12 MIF/INT
+ * MIF is the main control knob clock for Exynos4x12 MIF/INT
  * clock and voltage of both mif/int are controlled.
  */
 static struct bus_opp_table exynos4x12_mifclk_table[] = {
index 446687cc2334ed2f60a0b6f0170382fe733aae01..132a4fd375b2e4e165a6d1464c3af0af06f4000b 100644 (file)
@@ -62,6 +62,7 @@ config INTEL_IOATDMA
        tristate "Intel I/OAT DMA support"
        depends on PCI && X86
        select DMA_ENGINE
+       select DMA_ENGINE_RAID
        select DCA
        help
          Enable support for the Intel(R) I/OAT DMA engine present
@@ -112,6 +113,7 @@ config MV_XOR
        bool "Marvell XOR engine support"
        depends on PLAT_ORION
        select DMA_ENGINE
+       select DMA_ENGINE_RAID
        select ASYNC_TX_ENABLE_CHANNEL_SWITCH
        ---help---
          Enable support for the Marvell XOR engine.
@@ -187,6 +189,7 @@ config AMCC_PPC440SPE_ADMA
        tristate "AMCC PPC440SPe ADMA support"
        depends on 440SPe || 440SP
        select DMA_ENGINE
+       select DMA_ENGINE_RAID
        select ARCH_HAS_ASYNC_TX_FIND_CHANNEL
        select ASYNC_TX_ENABLE_CHANNEL_SWITCH
        help
@@ -377,4 +380,7 @@ config DMATEST
          Simple DMA test client. Say N unless you're debugging a
          DMA Device driver.
 
+config DMA_ENGINE_RAID
+       bool
+
 endif
index 16a2aa28f85672689f66c37039a8e72230e71b02..ec4ee5c1fe9dc2115e029d0c472bd32f48cb281c 100644 (file)
@@ -1169,7 +1169,7 @@ static void pl08x_desc_free(struct virt_dma_desc *vd)
        struct pl08x_txd *txd = to_pl08x_txd(&vd->tx);
        struct pl08x_dma_chan *plchan = to_pl08x_chan(vd->tx.chan);
 
-       dma_descriptor_unmap(txd);
+       dma_descriptor_unmap(&vd->tx);
        if (!txd->done)
                pl08x_release_mux(plchan);
 
index f31d647acdfaac3730371e1366ff964e245435ac..2787aba60c6bdee8ed0489cb932338d6a81528ac 100644 (file)
@@ -347,10 +347,6 @@ static struct device *chan2dev(struct dma_chan *chan)
 {
        return &chan->dev->device;
 }
-static struct device *chan2parent(struct dma_chan *chan)
-{
-       return chan->dev->device.parent;
-}
 
 #if defined(VERBOSE_DEBUG)
 static void vdbg_dump_regs(struct at_dma_chan *atchan)
index ea806bdc12ef92418c528be0b950758de59c3ee7..d70aff6a64490b7e828aa57c87e5c5a44363752c 100644 (file)
@@ -535,11 +535,41 @@ struct dma_chan *dma_get_slave_channel(struct dma_chan *chan)
 }
 EXPORT_SYMBOL_GPL(dma_get_slave_channel);
 
+struct dma_chan *dma_get_any_slave_channel(struct dma_device *device)
+{
+       dma_cap_mask_t mask;
+       struct dma_chan *chan;
+       int err;
+
+       dma_cap_zero(mask);
+       dma_cap_set(DMA_SLAVE, mask);
+
+       /* lock against __dma_request_channel */
+       mutex_lock(&dma_list_mutex);
+
+       chan = private_candidate(&mask, device, NULL, NULL);
+       if (chan) {
+               err = dma_chan_get(chan);
+               if (err) {
+                       pr_debug("%s: failed to get %s: (%d)\n",
+                               __func__, dma_chan_name(chan), err);
+                       chan = NULL;
+               }
+       }
+
+       mutex_unlock(&dma_list_mutex);
+
+       return chan;
+}
+EXPORT_SYMBOL_GPL(dma_get_any_slave_channel);
+
 /**
  * __dma_request_channel - try to allocate an exclusive channel
  * @mask: capabilities that the channel must satisfy
  * @fn: optional callback to disposition available channels
  * @fn_param: opaque parameter to pass to dma_filter_fn
+ *
+ * Returns pointer to appropriate DMA channel on success or NULL.
  */
 struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask,
                                       dma_filter_fn fn, void *fn_param)
@@ -591,18 +621,43 @@ EXPORT_SYMBOL_GPL(__dma_request_channel);
  * dma_request_slave_channel - try to allocate an exclusive slave channel
  * @dev:       pointer to client device structure
  * @name:      slave channel name
+ *
+ * Returns pointer to appropriate DMA channel on success or an error pointer.
  */
-struct dma_chan *dma_request_slave_channel(struct device *dev, const char *name)
+struct dma_chan *dma_request_slave_channel_reason(struct device *dev,
+                                                 const char *name)
 {
+       struct dma_chan *chan;
+
        /* If device-tree is present get slave info from here */
        if (dev->of_node)
                return of_dma_request_slave_channel(dev->of_node, name);
 
        /* If device was enumerated by ACPI get slave info from here */
-       if (ACPI_HANDLE(dev))
-               return acpi_dma_request_slave_chan_by_name(dev, name);
+       if (ACPI_HANDLE(dev)) {
+               chan = acpi_dma_request_slave_chan_by_name(dev, name);
+               if (chan)
+                       return chan;
+       }
 
-       return NULL;
+       return ERR_PTR(-ENODEV);
+}
+EXPORT_SYMBOL_GPL(dma_request_slave_channel_reason);
+
+/**
+ * dma_request_slave_channel - try to allocate an exclusive slave channel
+ * @dev:       pointer to client device structure
+ * @name:      slave channel name
+ *
+ * Returns pointer to appropriate DMA channel on success or NULL.
+ */
+struct dma_chan *dma_request_slave_channel(struct device *dev,
+                                          const char *name)
+{
+       struct dma_chan *ch = dma_request_slave_channel_reason(dev, name);
+       if (IS_ERR(ch))
+               return NULL;
+       return ch;
 }
 EXPORT_SYMBOL_GPL(dma_request_slave_channel);
 
@@ -912,7 +967,7 @@ struct dmaengine_unmap_pool {
 #define __UNMAP_POOL(x) { .size = x, .name = "dmaengine-unmap-" __stringify(x) }
 static struct dmaengine_unmap_pool unmap_pool[] = {
        __UNMAP_POOL(2),
-       #if IS_ENABLED(CONFIG_ASYNC_TX_DMA)
+       #if IS_ENABLED(CONFIG_DMA_ENGINE_RAID)
        __UNMAP_POOL(16),
        __UNMAP_POOL(128),
        __UNMAP_POOL(256),
index 20f9a3aaf9266ea6daa71a18f08d258afa8a1a1e..9dfcaf5c12888d3de80483329ffccc7fbbacd02a 100644 (file)
@@ -539,9 +539,9 @@ static int dmatest_func(void *data)
 
                um->len = params->buf_size;
                for (i = 0; i < src_cnt; i++) {
-                       unsigned long buf = (unsigned long) thread->srcs[i];
+                       void *buf = thread->srcs[i];
                        struct page *pg = virt_to_page(buf);
-                       unsigned pg_off = buf & ~PAGE_MASK;
+                       unsigned pg_off = (unsigned long) buf & ~PAGE_MASK;
 
                        um->addr[i] = dma_map_page(dev->dev, pg, pg_off,
                                                   um->len, DMA_TO_DEVICE);
@@ -559,9 +559,9 @@ static int dmatest_func(void *data)
                /* map with DMA_BIDIRECTIONAL to force writeback/invalidate */
                dsts = &um->addr[src_cnt];
                for (i = 0; i < dst_cnt; i++) {
-                       unsigned long buf = (unsigned long) thread->dsts[i];
+                       void *buf = thread->dsts[i];
                        struct page *pg = virt_to_page(buf);
-                       unsigned pg_off = buf & ~PAGE_MASK;
+                       unsigned pg_off = (unsigned long) buf & ~PAGE_MASK;
 
                        dsts[i] = dma_map_page(dev->dev, pg, pg_off, um->len,
                                               DMA_BIDIRECTIONAL);
index 7086a16a55f2ed488573e475e615600c80be767e..f157c6f76b32b8c98dce28eed6253db033acc258 100644 (file)
@@ -86,11 +86,6 @@ static void set_desc_cnt(struct fsldma_chan *chan,
        hw->count = CPU_TO_DMA(chan, count, 32);
 }
 
-static u32 get_desc_cnt(struct fsldma_chan *chan, struct fsl_desc_sw *desc)
-{
-       return DMA_TO_CPU(chan, desc->hw.count, 32);
-}
-
 static void set_desc_src(struct fsldma_chan *chan,
                         struct fsl_dma_ld_hw *hw, dma_addr_t src)
 {
@@ -101,16 +96,6 @@ static void set_desc_src(struct fsldma_chan *chan,
        hw->src_addr = CPU_TO_DMA(chan, snoop_bits | src, 64);
 }
 
-static dma_addr_t get_desc_src(struct fsldma_chan *chan,
-                              struct fsl_desc_sw *desc)
-{
-       u64 snoop_bits;
-
-       snoop_bits = ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX)
-               ? ((u64)FSL_DMA_SATR_SREADTYPE_SNOOP_READ << 32) : 0;
-       return DMA_TO_CPU(chan, desc->hw.src_addr, 64) & ~snoop_bits;
-}
-
 static void set_desc_dst(struct fsldma_chan *chan,
                         struct fsl_dma_ld_hw *hw, dma_addr_t dst)
 {
@@ -121,16 +106,6 @@ static void set_desc_dst(struct fsldma_chan *chan,
        hw->dst_addr = CPU_TO_DMA(chan, snoop_bits | dst, 64);
 }
 
-static dma_addr_t get_desc_dst(struct fsldma_chan *chan,
-                              struct fsl_desc_sw *desc)
-{
-       u64 snoop_bits;
-
-       snoop_bits = ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX)
-               ? ((u64)FSL_DMA_DATR_DWRITETYPE_SNOOP_WRITE << 32) : 0;
-       return DMA_TO_CPU(chan, desc->hw.dst_addr, 64) & ~snoop_bits;
-}
-
 static void set_desc_next(struct fsldma_chan *chan,
                          struct fsl_dma_ld_hw *hw, dma_addr_t next)
 {
@@ -408,7 +383,7 @@ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
        struct fsl_desc_sw *desc = tx_to_fsl_desc(tx);
        struct fsl_desc_sw *child;
        unsigned long flags;
-       dma_cookie_t cookie;
+       dma_cookie_t cookie = -EINVAL;
 
        spin_lock_irqsave(&chan->desc_lock, flags);
 
@@ -854,10 +829,6 @@ static void fsldma_cleanup_descriptor(struct fsldma_chan *chan,
                                      struct fsl_desc_sw *desc)
 {
        struct dma_async_tx_descriptor *txd = &desc->async_tx;
-       struct device *dev = chan->common.device->dev;
-       dma_addr_t src = get_desc_src(chan, desc);
-       dma_addr_t dst = get_desc_dst(chan, desc);
-       u32 len = get_desc_cnt(chan, desc);
 
        /* Run the link descriptor callback function */
        if (txd->callback) {
index c75679d420286c522679cdb9c344549c97e7a0c4..152247675febf42c805b57592c222fc716c8d516 100644 (file)
@@ -323,6 +323,7 @@ struct sdma_engine {
        struct clk                      *clk_ipg;
        struct clk                      *clk_ahb;
        spinlock_t                      channel_0_lock;
+       u32                             script_number;
        struct sdma_script_start_addrs  *script_addrs;
        const struct sdma_driver_data   *drvdata;
 };
@@ -724,6 +725,10 @@ static void sdma_get_pc(struct sdma_channel *sdmac,
                per_2_emi = sdma->script_addrs->app_2_mcu_addr;
                emi_2_per = sdma->script_addrs->mcu_2_app_addr;
                break;
+       case IMX_DMATYPE_SSI_DUAL:
+               per_2_emi = sdma->script_addrs->ssish_2_mcu_addr;
+               emi_2_per = sdma->script_addrs->mcu_2_ssish_addr;
+               break;
        case IMX_DMATYPE_SSI_SP:
        case IMX_DMATYPE_MMC:
        case IMX_DMATYPE_SDHC:
@@ -1238,6 +1243,7 @@ static void sdma_issue_pending(struct dma_chan *chan)
 }
 
 #define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1        34
+#define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V2        38
 
 static void sdma_add_scripts(struct sdma_engine *sdma,
                const struct sdma_script_start_addrs *addr)
@@ -1246,7 +1252,7 @@ static void sdma_add_scripts(struct sdma_engine *sdma,
        s32 *saddr_arr = (u32 *)sdma->script_addrs;
        int i;
 
-       for (i = 0; i < SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1; i++)
+       for (i = 0; i < sdma->script_number; i++)
                if (addr_arr[i] > 0)
                        saddr_arr[i] = addr_arr[i];
 }
@@ -1272,6 +1278,17 @@ static void sdma_load_firmware(const struct firmware *fw, void *context)
                goto err_firmware;
        if (header->ram_code_start + header->ram_code_size > fw->size)
                goto err_firmware;
+       switch (header->version_major) {
+               case 1:
+                       sdma->script_number = SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1;
+                       break;
+               case 2:
+                       sdma->script_number = SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V2;
+                       break;
+               default:
+                       dev_err(sdma->dev, "unknown firmware version\n");
+                       goto err_firmware;
+       }
 
        addr = (void *)header + header->script_addrs_start;
        ram_code = (void *)header + header->ram_code_start;
index dcb1e05149a7664c6e65a214d783080d540aaafd..6e7a7c842f179ea2e577bc52c34636a84b90441d 100644 (file)
@@ -5,6 +5,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+
 #include <linux/err.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #define DTADR          0x0208
 #define DCMD           0x020c
 
-#define DCSR_RUN       (1 << 31)       /* Run Bit (read / write) */
-#define DCSR_NODESC    (1 << 30)       /* No-Descriptor Fetch (read / write) */
-#define DCSR_STOPIRQEN (1 << 29)       /* Stop Interrupt Enable (read / write) */
-#define DCSR_REQPEND   (1 << 8)        /* Request Pending (read-only) */
-#define DCSR_STOPSTATE (1 << 3)        /* Stop State (read-only) */
-#define DCSR_ENDINTR   (1 << 2)        /* End Interrupt (read / write) */
-#define DCSR_STARTINTR (1 << 1)        /* Start Interrupt (read / write) */
-#define DCSR_BUSERR    (1 << 0)        /* Bus Error Interrupt (read / write) */
-
-#define DCSR_EORIRQEN  (1 << 28)       /* End of Receive Interrupt Enable (R/W) */
-#define DCSR_EORJMPEN  (1 << 27)       /* Jump to next descriptor on EOR */
-#define DCSR_EORSTOPEN (1 << 26)       /* STOP on an EOR */
-#define DCSR_SETCMPST  (1 << 25)       /* Set Descriptor Compare Status */
-#define DCSR_CLRCMPST  (1 << 24)       /* Clear Descriptor Compare Status */
-#define DCSR_CMPST     (1 << 10)       /* The Descriptor Compare Status */
-#define DCSR_EORINTR   (1 << 9)        /* The end of Receive */
-
-#define DRCMR(n)       ((((n) < 64) ? 0x0100 : 0x1100) + \
-                                (((n) & 0x3f) << 2))
-#define DRCMR_MAPVLD   (1 << 7)        /* Map Valid (read / write) */
-#define DRCMR_CHLNUM   0x1f            /* mask for Channel Number (read / write) */
+#define DCSR_RUN       BIT(31) /* Run Bit (read / write) */
+#define DCSR_NODESC    BIT(30) /* No-Descriptor Fetch (read / write) */
+#define DCSR_STOPIRQEN BIT(29) /* Stop Interrupt Enable (read / write) */
+#define DCSR_REQPEND   BIT(8)  /* Request Pending (read-only) */
+#define DCSR_STOPSTATE BIT(3)  /* Stop State (read-only) */
+#define DCSR_ENDINTR   BIT(2)  /* End Interrupt (read / write) */
+#define DCSR_STARTINTR BIT(1)  /* Start Interrupt (read / write) */
+#define DCSR_BUSERR    BIT(0)  /* Bus Error Interrupt (read / write) */
+
+#define DCSR_EORIRQEN  BIT(28) /* End of Receive Interrupt Enable (R/W) */
+#define DCSR_EORJMPEN  BIT(27) /* Jump to next descriptor on EOR */
+#define DCSR_EORSTOPEN BIT(26) /* STOP on an EOR */
+#define DCSR_SETCMPST  BIT(25) /* Set Descriptor Compare Status */
+#define DCSR_CLRCMPST  BIT(24) /* Clear Descriptor Compare Status */
+#define DCSR_CMPST     BIT(10) /* The Descriptor Compare Status */
+#define DCSR_EORINTR   BIT(9)  /* The end of Receive */
+
+#define DRCMR(n)       ((((n) < 64) ? 0x0100 : 0x1100) + (((n) & 0x3f) << 2))
+#define DRCMR_MAPVLD   BIT(7)  /* Map Valid (read / write) */
+#define DRCMR_CHLNUM   0x1f    /* mask for Channel Number (read / write) */
 
 #define DDADR_DESCADDR 0xfffffff0      /* Address of next descriptor (mask) */
-#define DDADR_STOP     (1 << 0)        /* Stop (read / write) */
-
-#define DCMD_INCSRCADDR        (1 << 31)       /* Source Address Increment Setting. */
-#define DCMD_INCTRGADDR        (1 << 30)       /* Target Address Increment Setting. */
-#define DCMD_FLOWSRC   (1 << 29)       /* Flow Control by the source. */
-#define DCMD_FLOWTRG   (1 << 28)       /* Flow Control by the target. */
-#define DCMD_STARTIRQEN        (1 << 22)       /* Start Interrupt Enable */
-#define DCMD_ENDIRQEN  (1 << 21)       /* End Interrupt Enable */
-#define DCMD_ENDIAN    (1 << 18)       /* Device Endian-ness. */
+#define DDADR_STOP     BIT(0)  /* Stop (read / write) */
+
+#define DCMD_INCSRCADDR        BIT(31) /* Source Address Increment Setting. */
+#define DCMD_INCTRGADDR        BIT(30) /* Target Address Increment Setting. */
+#define DCMD_FLOWSRC   BIT(29) /* Flow Control by the source. */
+#define DCMD_FLOWTRG   BIT(28) /* Flow Control by the target. */
+#define DCMD_STARTIRQEN        BIT(22) /* Start Interrupt Enable */
+#define DCMD_ENDIRQEN  BIT(21) /* End Interrupt Enable */
+#define DCMD_ENDIAN    BIT(18) /* Device Endian-ness. */
 #define DCMD_BURST8    (1 << 16)       /* 8 byte burst */
 #define DCMD_BURST16   (2 << 16)       /* 16 byte burst */
 #define DCMD_BURST32   (3 << 16)       /* 32 byte burst */
@@ -132,10 +132,14 @@ struct mmp_pdma_device {
        spinlock_t phy_lock; /* protect alloc/free phy channels */
 };
 
-#define tx_to_mmp_pdma_desc(tx) container_of(tx, struct mmp_pdma_desc_sw, async_tx)
-#define to_mmp_pdma_desc(lh) container_of(lh, struct mmp_pdma_desc_sw, node)
-#define to_mmp_pdma_chan(dchan) container_of(dchan, struct mmp_pdma_chan, chan)
-#define to_mmp_pdma_dev(dmadev) container_of(dmadev, struct mmp_pdma_device, device)
+#define tx_to_mmp_pdma_desc(tx)                                        \
+       container_of(tx, struct mmp_pdma_desc_sw, async_tx)
+#define to_mmp_pdma_desc(lh)                                   \
+       container_of(lh, struct mmp_pdma_desc_sw, node)
+#define to_mmp_pdma_chan(dchan)                                        \
+       container_of(dchan, struct mmp_pdma_chan, chan)
+#define to_mmp_pdma_dev(dmadev)                                        \
+       container_of(dmadev, struct mmp_pdma_device, device)
 
 static void set_desc(struct mmp_pdma_phy *phy, dma_addr_t addr)
 {
@@ -162,19 +166,18 @@ static void enable_chan(struct mmp_pdma_phy *phy)
        writel(dalgn, phy->base + DALGN);
 
        reg = (phy->idx << 2) + DCSR;
-       writel(readl(phy->base + reg) | DCSR_RUN,
-                                       phy->base + reg);
+       writel(readl(phy->base + reg) | DCSR_RUN, phy->base + reg);
 }
 
 static void disable_chan(struct mmp_pdma_phy *phy)
 {
        u32 reg;
 
-       if (phy) {
-               reg = (phy->idx << 2) + DCSR;
-               writel(readl(phy->base + reg) & ~DCSR_RUN,
-                                               phy->base + reg);
-       }
+       if (!phy)
+               return;
+
+       reg = (phy->idx << 2) + DCSR;
+       writel(readl(phy->base + reg) & ~DCSR_RUN, phy->base + reg);
 }
 
 static int clear_chan_irq(struct mmp_pdma_phy *phy)
@@ -183,26 +186,27 @@ static int clear_chan_irq(struct mmp_pdma_phy *phy)
        u32 dint = readl(phy->base + DINT);
        u32 reg = (phy->idx << 2) + DCSR;
 
-       if (dint & BIT(phy->idx)) {
-               /* clear irq */
-               dcsr = readl(phy->base + reg);
-               writel(dcsr, phy->base + reg);
-               if ((dcsr & DCSR_BUSERR) && (phy->vchan))
-                       dev_warn(phy->vchan->dev, "DCSR_BUSERR\n");
-               return 0;
-       }
-       return -EAGAIN;
+       if (!(dint & BIT(phy->idx)))
+               return -EAGAIN;
+
+       /* clear irq */
+       dcsr = readl(phy->base + reg);
+       writel(dcsr, phy->base + reg);
+       if ((dcsr & DCSR_BUSERR) && (phy->vchan))
+               dev_warn(phy->vchan->dev, "DCSR_BUSERR\n");
+
+       return 0;
 }
 
 static irqreturn_t mmp_pdma_chan_handler(int irq, void *dev_id)
 {
        struct mmp_pdma_phy *phy = dev_id;
 
-       if (clear_chan_irq(phy) == 0) {
-               tasklet_schedule(&phy->vchan->tasklet);
-               return IRQ_HANDLED;
-       } else
+       if (clear_chan_irq(phy) != 0)
                return IRQ_NONE;
+
+       tasklet_schedule(&phy->vchan->tasklet);
+       return IRQ_HANDLED;
 }
 
 static irqreturn_t mmp_pdma_int_handler(int irq, void *dev_id)
@@ -224,8 +228,8 @@ static irqreturn_t mmp_pdma_int_handler(int irq, void *dev_id)
 
        if (irq_num)
                return IRQ_HANDLED;
-       else
-               return IRQ_NONE;
+
+       return IRQ_NONE;
 }
 
 /* lookup free phy channel as descending priority */
@@ -245,9 +249,9 @@ static struct mmp_pdma_phy *lookup_phy(struct mmp_pdma_chan *pchan)
         */
 
        spin_lock_irqsave(&pdev->phy_lock, flags);
-       for (prio = 0; prio <= (((pdev->dma_channels - 1) & 0xf) >> 2); prio++) {
+       for (prio = 0; prio <= ((pdev->dma_channels - 1) & 0xf) >> 2; prio++) {
                for (i = 0; i < pdev->dma_channels; i++) {
-                       if (prio != ((i & 0xf) >> 2))
+                       if (prio != (i & 0xf) >> 2)
                                continue;
                        phy = &pdev->phy[i];
                        if (!phy->vchan) {
@@ -389,14 +393,16 @@ static int mmp_pdma_alloc_chan_resources(struct dma_chan *dchan)
        if (chan->desc_pool)
                return 1;
 
-       chan->desc_pool =
-               dma_pool_create(dev_name(&dchan->dev->device), chan->dev,
-                                 sizeof(struct mmp_pdma_desc_sw),
-                                 __alignof__(struct mmp_pdma_desc_sw), 0);
+       chan->desc_pool = dma_pool_create(dev_name(&dchan->dev->device),
+                                         chan->dev,
+                                         sizeof(struct mmp_pdma_desc_sw),
+                                         __alignof__(struct mmp_pdma_desc_sw),
+                                         0);
        if (!chan->desc_pool) {
                dev_err(chan->dev, "unable to allocate descriptor pool\n");
                return -ENOMEM;
        }
+
        mmp_pdma_free_phy(chan);
        chan->idle = true;
        chan->dev_addr = 0;
@@ -404,7 +410,7 @@ static int mmp_pdma_alloc_chan_resources(struct dma_chan *dchan)
 }
 
 static void mmp_pdma_free_desc_list(struct mmp_pdma_chan *chan,
-                                 struct list_head *list)
+                                   struct list_head *list)
 {
        struct mmp_pdma_desc_sw *desc, *_desc;
 
@@ -434,8 +440,8 @@ static void mmp_pdma_free_chan_resources(struct dma_chan *dchan)
 
 static struct dma_async_tx_descriptor *
 mmp_pdma_prep_memcpy(struct dma_chan *dchan,
-       dma_addr_t dma_dst, dma_addr_t dma_src,
-       size_t len, unsigned long flags)
+                    dma_addr_t dma_dst, dma_addr_t dma_src,
+                    size_t len, unsigned long flags)
 {
        struct mmp_pdma_chan *chan;
        struct mmp_pdma_desc_sw *first = NULL, *prev = NULL, *new;
@@ -515,8 +521,8 @@ fail:
 
 static struct dma_async_tx_descriptor *
 mmp_pdma_prep_slave_sg(struct dma_chan *dchan, struct scatterlist *sgl,
-                        unsigned int sg_len, enum dma_transfer_direction dir,
-                        unsigned long flags, void *context)
+                      unsigned int sg_len, enum dma_transfer_direction dir,
+                      unsigned long flags, void *context)
 {
        struct mmp_pdma_chan *chan = to_mmp_pdma_chan(dchan);
        struct mmp_pdma_desc_sw *first = NULL, *prev = NULL, *new = NULL;
@@ -591,10 +597,11 @@ fail:
        return NULL;
 }
 
-static struct dma_async_tx_descriptor *mmp_pdma_prep_dma_cyclic(
-       struct dma_chan *dchan, dma_addr_t buf_addr, size_t len,
-       size_t period_len, enum dma_transfer_direction direction,
-       unsigned long flags, void *context)
+static struct dma_async_tx_descriptor *
+mmp_pdma_prep_dma_cyclic(struct dma_chan *dchan,
+                        dma_addr_t buf_addr, size_t len, size_t period_len,
+                        enum dma_transfer_direction direction,
+                        unsigned long flags, void *context)
 {
        struct mmp_pdma_chan *chan;
        struct mmp_pdma_desc_sw *first = NULL, *prev = NULL, *new;
@@ -636,8 +643,8 @@ static struct dma_async_tx_descriptor *mmp_pdma_prep_dma_cyclic(
                        goto fail;
                }
 
-               new->desc.dcmd = chan->dcmd | DCMD_ENDIRQEN |
-                                       (DCMD_LENGTH & period_len);
+               new->desc.dcmd = (chan->dcmd | DCMD_ENDIRQEN |
+                                 (DCMD_LENGTH & period_len));
                new->desc.dsadr = dma_src;
                new->desc.dtadr = dma_dst;
 
@@ -677,12 +684,11 @@ fail:
 }
 
 static int mmp_pdma_control(struct dma_chan *dchan, enum dma_ctrl_cmd cmd,
-               unsigned long arg)
+                           unsigned long arg)
 {
        struct mmp_pdma_chan *chan = to_mmp_pdma_chan(dchan);
        struct dma_slave_config *cfg = (void *)arg;
        unsigned long flags;
-       int ret = 0;
        u32 maxburst = 0, addr = 0;
        enum dma_slave_buswidth width = DMA_SLAVE_BUSWIDTH_UNDEFINED;
 
@@ -739,11 +745,12 @@ static int mmp_pdma_control(struct dma_chan *dchan, enum dma_ctrl_cmd cmd,
                return -ENOSYS;
        }
 
-       return ret;
+       return 0;
 }
 
 static enum dma_status mmp_pdma_tx_status(struct dma_chan *dchan,
-                       dma_cookie_t cookie, struct dma_tx_state *txstate)
+                                         dma_cookie_t cookie,
+                                         struct dma_tx_state *txstate)
 {
        return dma_cookie_status(dchan, cookie, txstate);
 }
@@ -845,15 +852,14 @@ static int mmp_pdma_remove(struct platform_device *op)
        return 0;
 }
 
-static int mmp_pdma_chan_init(struct mmp_pdma_device *pdev,
-                                                       int idx, int irq)
+static int mmp_pdma_chan_init(struct mmp_pdma_device *pdev, int idx, int irq)
 {
        struct mmp_pdma_phy *phy  = &pdev->phy[idx];
        struct mmp_pdma_chan *chan;
        int ret;
 
-       chan = devm_kzalloc(pdev->dev,
-                       sizeof(struct mmp_pdma_chan), GFP_KERNEL);
+       chan = devm_kzalloc(pdev->dev, sizeof(struct mmp_pdma_chan),
+                           GFP_KERNEL);
        if (chan == NULL)
                return -ENOMEM;
 
@@ -861,8 +867,8 @@ static int mmp_pdma_chan_init(struct mmp_pdma_device *pdev,
        phy->base = pdev->base;
 
        if (irq) {
-               ret = devm_request_irq(pdev->dev, irq,
-                       mmp_pdma_chan_handler, 0, "pdma", phy);
+               ret = devm_request_irq(pdev->dev, irq, mmp_pdma_chan_handler, 0,
+                                      "pdma", phy);
                if (ret) {
                        dev_err(pdev->dev, "channel request irq fail!\n");
                        return ret;
@@ -877,8 +883,7 @@ static int mmp_pdma_chan_init(struct mmp_pdma_device *pdev,
        INIT_LIST_HEAD(&chan->chain_running);
 
        /* register virt channel to dma engine */
-       list_add_tail(&chan->chan.device_node,
-                       &pdev->device.channels);
+       list_add_tail(&chan->chan.device_node, &pdev->device.channels);
 
        return 0;
 }
@@ -893,33 +898,17 @@ static struct dma_chan *mmp_pdma_dma_xlate(struct of_phandle_args *dma_spec,
                                           struct of_dma *ofdma)
 {
        struct mmp_pdma_device *d = ofdma->of_dma_data;
-       struct dma_chan *chan, *candidate;
-
-retry:
-       candidate = NULL;
+       struct dma_chan *chan;
+       struct mmp_pdma_chan *c;
 
-       /* walk the list of channels registered with the current instance and
-        * find one that is currently unused */
-       list_for_each_entry(chan, &d->device.channels, device_node)
-               if (chan->client_count == 0) {
-                       candidate = chan;
-                       break;
-               }
-
-       if (!candidate)
+       chan = dma_get_any_slave_channel(&d->device);
+       if (!chan)
                return NULL;
 
-       /* dma_get_slave_channel will return NULL if we lost a race between
-        * the lookup and the reservation */
-       chan = dma_get_slave_channel(candidate);
+       c = to_mmp_pdma_chan(chan);
+       c->drcmr = dma_spec->args[0];
 
-       if (chan) {
-               struct mmp_pdma_chan *c = to_mmp_pdma_chan(chan);
-               c->drcmr = dma_spec->args[0];
-               return chan;
-       }
-
-       goto retry;
+       return chan;
 }
 
 static int mmp_pdma_probe(struct platform_device *op)
@@ -934,6 +923,7 @@ static int mmp_pdma_probe(struct platform_device *op)
        pdev = devm_kzalloc(&op->dev, sizeof(*pdev), GFP_KERNEL);
        if (!pdev)
                return -ENOMEM;
+
        pdev->dev = &op->dev;
 
        spin_lock_init(&pdev->phy_lock);
@@ -945,8 +935,8 @@ static int mmp_pdma_probe(struct platform_device *op)
 
        of_id = of_match_device(mmp_pdma_dt_ids, pdev->dev);
        if (of_id)
-               of_property_read_u32(pdev->dev->of_node,
-                               "#dma-channels", &dma_channels);
+               of_property_read_u32(pdev->dev->of_node, "#dma-channels",
+                                    &dma_channels);
        else if (pdata && pdata->dma_channels)
                dma_channels = pdata->dma_channels;
        else
@@ -958,8 +948,9 @@ static int mmp_pdma_probe(struct platform_device *op)
                        irq_num++;
        }
 
-       pdev->phy = devm_kzalloc(pdev->dev,
-               dma_channels * sizeof(struct mmp_pdma_chan), GFP_KERNEL);
+       pdev->phy = devm_kcalloc(pdev->dev,
+                                dma_channels, sizeof(struct mmp_pdma_chan),
+                                GFP_KERNEL);
        if (pdev->phy == NULL)
                return -ENOMEM;
 
@@ -968,8 +959,8 @@ static int mmp_pdma_probe(struct platform_device *op)
        if (irq_num != dma_channels) {
                /* all chan share one irq, demux inside */
                irq = platform_get_irq(op, 0);
-               ret = devm_request_irq(pdev->dev, irq,
-                       mmp_pdma_int_handler, 0, "pdma", pdev);
+               ret = devm_request_irq(pdev->dev, irq, mmp_pdma_int_handler, 0,
+                                      "pdma", pdev);
                if (ret)
                        return ret;
        }
@@ -1017,6 +1008,7 @@ static int mmp_pdma_probe(struct platform_device *op)
                }
        }
 
+       platform_set_drvdata(op, pdev);
        dev_info(pdev->device.dev, "initialized %d channels\n", dma_channels);
        return 0;
 }
@@ -1044,7 +1036,7 @@ bool mmp_pdma_filter_fn(struct dma_chan *chan, void *param)
        if (chan->device->dev->driver != &mmp_pdma_driver.driver)
                return false;
 
-       c->drcmr = *(unsigned int *) param;
+       c->drcmr = *(unsigned int *)param;
 
        return true;
 }
@@ -1052,6 +1044,6 @@ EXPORT_SYMBOL_GPL(mmp_pdma_filter_fn);
 
 module_platform_driver(mmp_pdma_driver);
 
-MODULE_DESCRIPTION("MARVELL MMP Periphera DMA Driver");
+MODULE_DESCRIPTION("MARVELL MMP Peripheral DMA Driver");
 MODULE_AUTHOR("Marvell International Ltd.");
 MODULE_LICENSE("GPL v2");
index 3ddacc14a7366611ffb089d21c70fb4ba3c896c5..d4b730ce03691abb6a90dc1bc7cf952f0e23a5fe 100644 (file)
@@ -121,7 +121,7 @@ struct mmp_tdma_chan {
        int                             idx;
        enum mmp_tdma_type              type;
        int                             irq;
-       unsigned long                   reg_base;
+       void __iomem                    *reg_base;
 
        size_t                          buf_len;
        size_t                          period_len;
@@ -182,7 +182,7 @@ static void mmp_tdma_pause_chan(struct mmp_tdma_chan *tdmac)
 
 static int mmp_tdma_config_chan(struct mmp_tdma_chan *tdmac)
 {
-       unsigned int tdcr;
+       unsigned int tdcr = 0;
 
        mmp_tdma_disable_chan(tdmac);
 
@@ -526,7 +526,7 @@ static int mmp_tdma_chan_init(struct mmp_tdma_device *tdev,
        tdmac->chan.device = &tdev->device;
        tdmac->idx         = idx;
        tdmac->type        = type;
-       tdmac->reg_base    = (unsigned long)tdev->base + idx * 4;
+       tdmac->reg_base    = tdev->base + idx * 4;
        tdmac->status = DMA_COMPLETE;
        tdev->tdmac[tdmac->idx] = tdmac;
        tasklet_init(&tdmac->tasklet, dma_do_tasklet, (unsigned long)tdmac);
index 7807f0ef4e209c25ad90db9d32f7bc13955391cf..23bcc9158cbc39a195f72b679854cc3d360659cc 100644 (file)
@@ -54,12 +54,6 @@ static void mv_desc_init(struct mv_xor_desc_slot *desc, unsigned long flags)
        hw_desc->desc_command = (1 << 31);
 }
 
-static u32 mv_desc_get_dest_addr(struct mv_xor_desc_slot *desc)
-{
-       struct mv_xor_desc *hw_desc = desc->hw_desc;
-       return hw_desc->phy_dest_addr;
-}
-
 static void mv_desc_set_byte_count(struct mv_xor_desc_slot *desc,
                                   u32 byte_count)
 {
index 0b88dd3d05f4880f41561f455f79c5eb9ca0a885..e8fe9dc455f4d8989e6d75618fecdd7ce351647f 100644 (file)
@@ -143,7 +143,7 @@ static int of_dma_match_channel(struct device_node *np, const char *name,
  * @np:                device node to get DMA request from
  * @name:      name of desired channel
  *
- * Returns pointer to appropriate dma channel on success or NULL on error.
+ * Returns pointer to appropriate DMA channel on success or an error pointer.
  */
 struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
                                              const char *name)
@@ -152,17 +152,18 @@ struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
        struct of_dma           *ofdma;
        struct dma_chan         *chan;
        int                     count, i;
+       int                     ret_no_channel = -ENODEV;
 
        if (!np || !name) {
                pr_err("%s: not enough information provided\n", __func__);
-               return NULL;
+               return ERR_PTR(-ENODEV);
        }
 
        count = of_property_count_strings(np, "dma-names");
        if (count < 0) {
                pr_err("%s: dma-names property of node '%s' missing or empty\n",
                        __func__, np->full_name);
-               return NULL;
+               return ERR_PTR(-ENODEV);
        }
 
        for (i = 0; i < count; i++) {
@@ -172,10 +173,12 @@ struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
                mutex_lock(&of_dma_lock);
                ofdma = of_dma_find_controller(&dma_spec);
 
-               if (ofdma)
+               if (ofdma) {
                        chan = ofdma->of_dma_xlate(&dma_spec, ofdma);
-               else
+               } else {
+                       ret_no_channel = -EPROBE_DEFER;
                        chan = NULL;
+               }
 
                mutex_unlock(&of_dma_lock);
 
@@ -185,7 +188,7 @@ struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
                        return chan;
        }
 
-       return NULL;
+       return ERR_PTR(ret_no_channel);
 }
 
 /**
index cdf0483b8f2dfb8f746b786fd6bf84b0d5f6657b..7adaf3abffba91d4f72656513c6ad5b235508c40 100644 (file)
@@ -578,6 +578,9 @@ struct dma_pl330_dmac {
        /* DMA-Engine Device */
        struct dma_device ddma;
 
+       /* Holds info about sg limitations */
+       struct device_dma_parameters dma_parms;
+
        /* Pool of descriptors available for the DMAC's channels */
        struct list_head desc_pool;
        /* To protect desc_pool manipulation */
@@ -3023,6 +3026,9 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
                        "unable to register DMA to the generic DT DMA helpers\n");
                }
        }
+
+       adev->dev.dma_parms = &pdmac->dma_parms;
+
        /*
         * This is the limit for transfers with a buswidth of 1, larger
         * buswidths will have larger limits.
index 8da48c6b2a38ccd76f3e127d53e4be5ab7be425c..8bba298535b0984e241793403af6920399d7366d 100644 (file)
@@ -532,29 +532,6 @@ static void ppc440spe_desc_init_memcpy(struct ppc440spe_adma_desc_slot *desc,
        hw_desc->opc = DMA_CDB_OPC_MV_SG1_SG2;
 }
 
-/**
- * ppc440spe_desc_init_memset - initialize the descriptor for MEMSET operation
- */
-static void ppc440spe_desc_init_memset(struct ppc440spe_adma_desc_slot *desc,
-                                       int value, unsigned long flags)
-{
-       struct dma_cdb *hw_desc = desc->hw_desc;
-
-       memset(desc->hw_desc, 0, sizeof(struct dma_cdb));
-       desc->hw_next = NULL;
-       desc->src_cnt = 1;
-       desc->dst_cnt = 1;
-
-       if (flags & DMA_PREP_INTERRUPT)
-               set_bit(PPC440SPE_DESC_INT, &desc->flags);
-       else
-               clear_bit(PPC440SPE_DESC_INT, &desc->flags);
-
-       hw_desc->sg1u = hw_desc->sg1l = cpu_to_le32((u32)value);
-       hw_desc->sg3u = hw_desc->sg3l = cpu_to_le32((u32)value);
-       hw_desc->opc = DMA_CDB_OPC_DFILL128;
-}
-
 /**
  * ppc440spe_desc_set_src_addr - set source address into the descriptor
  */
@@ -1504,8 +1481,6 @@ static dma_cookie_t ppc440spe_adma_run_tx_complete_actions(
                struct ppc440spe_adma_chan *chan,
                dma_cookie_t cookie)
 {
-       int i;
-
        BUG_ON(desc->async_tx.cookie < 0);
        if (desc->async_tx.cookie > 0) {
                cookie = desc->async_tx.cookie;
@@ -3898,7 +3873,7 @@ static void ppc440spe_adma_init_capabilities(struct ppc440spe_adma_device *adev)
                        ppc440spe_adma_prep_dma_interrupt;
        }
        pr_info("%s: AMCC(R) PPC440SP(E) ADMA Engine: "
-         "( %s%s%s%s%s%s%s)\n",
+         "( %s%s%s%s%s%s)\n",
          dev_name(adev->dev),
          dma_has_cap(DMA_PQ, adev->common.cap_mask) ? "pq " : "",
          dma_has_cap(DMA_PQ_VAL, adev->common.cap_mask) ? "pq_val " : "",
index 4cb12797863678be86af66017ec2cffb54f5dd16..4eddedb6eb7dd3deb68550c1b8065e8b9d882278 100644 (file)
@@ -628,42 +628,13 @@ retry:
        s3cchan->state = S3C24XX_DMA_CHAN_IDLE;
 }
 
-static void s3c24xx_dma_unmap_buffers(struct s3c24xx_txd *txd)
-{
-       struct device *dev = txd->vd.tx.chan->device->dev;
-       struct s3c24xx_sg *dsg;
-
-       if (!(txd->vd.tx.flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
-               if (txd->vd.tx.flags & DMA_COMPL_SRC_UNMAP_SINGLE)
-                       list_for_each_entry(dsg, &txd->dsg_list, node)
-                               dma_unmap_single(dev, dsg->src_addr, dsg->len,
-                                               DMA_TO_DEVICE);
-               else {
-                       list_for_each_entry(dsg, &txd->dsg_list, node)
-                               dma_unmap_page(dev, dsg->src_addr, dsg->len,
-                                               DMA_TO_DEVICE);
-               }
-       }
-
-       if (!(txd->vd.tx.flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
-               if (txd->vd.tx.flags & DMA_COMPL_DEST_UNMAP_SINGLE)
-                       list_for_each_entry(dsg, &txd->dsg_list, node)
-                               dma_unmap_single(dev, dsg->dst_addr, dsg->len,
-                                               DMA_FROM_DEVICE);
-               else
-                       list_for_each_entry(dsg, &txd->dsg_list, node)
-                               dma_unmap_page(dev, dsg->dst_addr, dsg->len,
-                                               DMA_FROM_DEVICE);
-       }
-}
-
 static void s3c24xx_dma_desc_free(struct virt_dma_desc *vd)
 {
        struct s3c24xx_txd *txd = to_s3c24xx_txd(&vd->tx);
        struct s3c24xx_dma_chan *s3cchan = to_s3c24xx_dma_chan(vd->tx.chan);
 
        if (!s3cchan->slave)
-               s3c24xx_dma_unmap_buffers(txd);
+               dma_descriptor_unmap(&vd->tx);
 
        s3c24xx_dma_free_txd(txd);
 }
@@ -795,7 +766,7 @@ static enum dma_status s3c24xx_dma_tx_status(struct dma_chan *chan,
 
        spin_lock_irqsave(&s3cchan->vc.lock, flags);
        ret = dma_cookie_status(chan, cookie, txstate);
-       if (ret == DMA_SUCCESS) {
+       if (ret == DMA_COMPLETE) {
                spin_unlock_irqrestore(&s3cchan->vc.lock, flags);
                return ret;
        }
index ebad84591a6e22bd1f28866c3f0b1946eba3dff0..3083d901a414f000a54e0337e02973a4586399bf 100644 (file)
@@ -60,6 +60,7 @@
 #define HPB_DMAE_DSTPR_DMSTP   BIT(0)
 
 /* DMA status register (DSTSR) bits */
+#define HPB_DMAE_DSTSR_DQSTS   BIT(2)
 #define HPB_DMAE_DSTSR_DMSTS   BIT(0)
 
 /* DMA common registers */
@@ -286,6 +287,9 @@ static void hpb_dmae_halt(struct shdma_chan *schan)
 
        ch_reg_write(chan, HPB_DMAE_DCMDR_DQEND, HPB_DMAE_DCMDR);
        ch_reg_write(chan, HPB_DMAE_DSTPR_DMSTP, HPB_DMAE_DSTPR);
+
+       chan->plane_idx = 0;
+       chan->first_desc = true;
 }
 
 static const struct hpb_dmae_slave_config *
@@ -385,7 +389,10 @@ static bool hpb_dmae_channel_busy(struct shdma_chan *schan)
        struct hpb_dmae_chan *chan = to_chan(schan);
        u32 dstsr = ch_reg_read(chan, HPB_DMAE_DSTSR);
 
-       return (dstsr & HPB_DMAE_DSTSR_DMSTS) == HPB_DMAE_DSTSR_DMSTS;
+       if (chan->xfer_mode == XFER_DOUBLE)
+               return dstsr & HPB_DMAE_DSTSR_DQSTS;
+       else
+               return dstsr & HPB_DMAE_DSTSR_DMSTS;
 }
 
 static int
@@ -510,6 +517,8 @@ static int hpb_dmae_chan_probe(struct hpb_dmae_device *hpbdev, int id)
        }
 
        schan = &new_hpb_chan->shdma_chan;
+       schan->max_xfer_len = HPB_DMA_TCR_MAX;
+
        shdma_chan_probe(sdev, schan, id);
 
        if (pdev->id >= 0)
index b8c031b7de4e045d22cfa0e7d495380bc94ed75f..00a2de957b234da060fe5e03592b171f50fa53d1 100644 (file)
@@ -2409,6 +2409,7 @@ static void d40_set_prio_realtime(struct d40_chan *d40c)
 #define D40_DT_FLAGS_DIR(flags)        ((flags >> 1) & 0x1)
 #define D40_DT_FLAGS_BIG_ENDIAN(flags) ((flags >> 2) & 0x1)
 #define D40_DT_FLAGS_FIXED_CHAN(flags) ((flags >> 3) & 0x1)
+#define D40_DT_FLAGS_HIGH_PRIO(flags)  ((flags >> 4) & 0x1)
 
 static struct dma_chan *d40_xlate(struct of_phandle_args *dma_spec,
                                  struct of_dma *ofdma)
@@ -2446,6 +2447,9 @@ static struct dma_chan *d40_xlate(struct of_phandle_args *dma_spec,
                cfg.use_fixed_channel = true;
        }
 
+       if (D40_DT_FLAGS_HIGH_PRIO(flags))
+               cfg.high_priority = true;
+
        return dma_request_channel(cap, stedma40_filter, &cfg);
 }
 
index bae6c29f5502ab951f7926bdf621977703bc96b1..17686caf64d5c4beedd0d189dd4487a57acb1254 100644 (file)
@@ -406,7 +406,6 @@ txx9dmac_descriptor_complete(struct txx9dmac_chan *dc,
        dma_async_tx_callback callback;
        void *param;
        struct dma_async_tx_descriptor *txd = &desc->txd;
-       struct txx9dmac_slave *ds = dc->chan.private;
 
        dev_vdbg(chan2dev(&dc->chan), "descriptor %u %p complete\n",
                 txd->cookie, desc);
index 3c55ec856e39c714e7b474f081c01180b9aa9e2d..a287cece0593c327c53e8961b70a0dde8b1af2ce 100644 (file)
@@ -1082,7 +1082,7 @@ static void arizona_micd_set_level(struct arizona *arizona, int index,
 static int arizona_extcon_probe(struct platform_device *pdev)
 {
        struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
-       struct arizona_pdata *pdata;
+       struct arizona_pdata *pdata = &arizona->pdata;
        struct arizona_extcon_info *info;
        unsigned int val;
        int jack_irq_fall, jack_irq_rise;
@@ -1091,8 +1091,6 @@ static int arizona_extcon_probe(struct platform_device *pdev)
        if (!arizona->dapm || !arizona->dapm->card)
                return -EPROBE_DEFER;
 
-       pdata = dev_get_platdata(arizona->dev);
-
        info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
        if (!info) {
                dev_err(&pdev->dev, "Failed to allocate memory\n");
index 15443d3b6be18049ddddbb7ec035eb05ce7dc409..76322330cbd7a10b427ff5d011b83abbd0abb0e8 100644 (file)
@@ -792,6 +792,8 @@ void extcon_dev_unregister(struct extcon_dev *edev)
                return;
        }
 
+       device_unregister(&edev->dev);
+
        if (edev->mutually_exclusive && edev->max_supported) {
                for (index = 0; edev->mutually_exclusive[index];
                                index++)
@@ -812,7 +814,6 @@ void extcon_dev_unregister(struct extcon_dev *edev)
        if (switch_class)
                class_compat_remove_link(switch_class, &edev->dev, NULL);
 #endif
-       device_unregister(&edev->dev);
        put_device(&edev->dev);
 }
 EXPORT_SYMBOL_GPL(extcon_dev_unregister);
index 281029daf98c7ea291886d46ecf05378bfa98718..b0bb056458a363b0ee457beea13a8b926a63d483 100644 (file)
@@ -1623,6 +1623,7 @@ static struct scsi_host_template scsi_driver_template = {
        .cmd_per_lun            = 1,
        .can_queue              = 1,
        .sdev_attrs             = sbp2_scsi_sysfs_attrs,
+       .no_write_same          = 1,
 };
 
 MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>");
index 5002d50e37817314d1fe3e449ad991ade1969f6b..743fd426f21bf29299b850833d0137348a2bca64 100644 (file)
@@ -18,14 +18,12 @@ module_param_named(pstore_disable, efivars_pstore_disable, bool, 0644);
 
 static int efi_pstore_open(struct pstore_info *psi)
 {
-       efivar_entry_iter_begin();
        psi->data = NULL;
        return 0;
 }
 
 static int efi_pstore_close(struct pstore_info *psi)
 {
-       efivar_entry_iter_end();
        psi->data = NULL;
        return 0;
 }
@@ -39,6 +37,12 @@ struct pstore_read_data {
        char **buf;
 };
 
+static inline u64 generic_id(unsigned long timestamp,
+                            unsigned int part, int count)
+{
+       return (timestamp * 100 + part) * 1000 + count;
+}
+
 static int efi_pstore_read_func(struct efivar_entry *entry, void *data)
 {
        efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
@@ -57,7 +61,7 @@ static int efi_pstore_read_func(struct efivar_entry *entry, void *data)
 
        if (sscanf(name, "dump-type%u-%u-%d-%lu-%c",
                   cb_data->type, &part, &cnt, &time, &data_type) == 5) {
-               *cb_data->id = part;
+               *cb_data->id = generic_id(time, part, cnt);
                *cb_data->count = cnt;
                cb_data->timespec->tv_sec = time;
                cb_data->timespec->tv_nsec = 0;
@@ -67,7 +71,7 @@ static int efi_pstore_read_func(struct efivar_entry *entry, void *data)
                        *cb_data->compressed = false;
        } else if (sscanf(name, "dump-type%u-%u-%d-%lu",
                   cb_data->type, &part, &cnt, &time) == 4) {
-               *cb_data->id = part;
+               *cb_data->id = generic_id(time, part, cnt);
                *cb_data->count = cnt;
                cb_data->timespec->tv_sec = time;
                cb_data->timespec->tv_nsec = 0;
@@ -79,7 +83,7 @@ static int efi_pstore_read_func(struct efivar_entry *entry, void *data)
                 * which doesn't support holding
                 * multiple logs, remains.
                 */
-               *cb_data->id = part;
+               *cb_data->id = generic_id(time, part, 0);
                *cb_data->count = 0;
                cb_data->timespec->tv_sec = time;
                cb_data->timespec->tv_nsec = 0;
@@ -91,19 +95,125 @@ static int efi_pstore_read_func(struct efivar_entry *entry, void *data)
        __efivar_entry_get(entry, &entry->var.Attributes,
                           &entry->var.DataSize, entry->var.Data);
        size = entry->var.DataSize;
+       memcpy(*cb_data->buf, entry->var.Data,
+              (size_t)min_t(unsigned long, EFIVARS_DATA_SIZE_MAX, size));
 
-       *cb_data->buf = kmemdup(entry->var.Data, size, GFP_KERNEL);
-       if (*cb_data->buf == NULL)
-               return -ENOMEM;
        return size;
 }
 
+/**
+ * efi_pstore_scan_sysfs_enter
+ * @entry: scanning entry
+ * @next: next entry
+ * @head: list head
+ */
+static void efi_pstore_scan_sysfs_enter(struct efivar_entry *pos,
+                                       struct efivar_entry *next,
+                                       struct list_head *head)
+{
+       pos->scanning = true;
+       if (&next->list != head)
+               next->scanning = true;
+}
+
+/**
+ * __efi_pstore_scan_sysfs_exit
+ * @entry: deleting entry
+ * @turn_off_scanning: Check if a scanning flag should be turned off
+ */
+static inline void __efi_pstore_scan_sysfs_exit(struct efivar_entry *entry,
+                                               bool turn_off_scanning)
+{
+       if (entry->deleting) {
+               list_del(&entry->list);
+               efivar_entry_iter_end();
+               efivar_unregister(entry);
+               efivar_entry_iter_begin();
+       } else if (turn_off_scanning)
+               entry->scanning = false;
+}
+
+/**
+ * efi_pstore_scan_sysfs_exit
+ * @pos: scanning entry
+ * @next: next entry
+ * @head: list head
+ * @stop: a flag checking if scanning will stop
+ */
+static void efi_pstore_scan_sysfs_exit(struct efivar_entry *pos,
+                                      struct efivar_entry *next,
+                                      struct list_head *head, bool stop)
+{
+       __efi_pstore_scan_sysfs_exit(pos, true);
+       if (stop)
+               __efi_pstore_scan_sysfs_exit(next, &next->list != head);
+}
+
+/**
+ * efi_pstore_sysfs_entry_iter
+ *
+ * @data: function-specific data to pass to callback
+ * @pos: entry to begin iterating from
+ *
+ * You MUST call efivar_enter_iter_begin() before this function, and
+ * efivar_entry_iter_end() afterwards.
+ *
+ * It is possible to begin iteration from an arbitrary entry within
+ * the list by passing @pos. @pos is updated on return to point to
+ * the next entry of the last one passed to efi_pstore_read_func().
+ * To begin iterating from the beginning of the list @pos must be %NULL.
+ */
+static int efi_pstore_sysfs_entry_iter(void *data, struct efivar_entry **pos)
+{
+       struct efivar_entry *entry, *n;
+       struct list_head *head = &efivar_sysfs_list;
+       int size = 0;
+
+       if (!*pos) {
+               list_for_each_entry_safe(entry, n, head, list) {
+                       efi_pstore_scan_sysfs_enter(entry, n, head);
+
+                       size = efi_pstore_read_func(entry, data);
+                       efi_pstore_scan_sysfs_exit(entry, n, head, size < 0);
+                       if (size)
+                               break;
+               }
+               *pos = n;
+               return size;
+       }
+
+       list_for_each_entry_safe_from((*pos), n, head, list) {
+               efi_pstore_scan_sysfs_enter((*pos), n, head);
+
+               size = efi_pstore_read_func((*pos), data);
+               efi_pstore_scan_sysfs_exit((*pos), n, head, size < 0);
+               if (size)
+                       break;
+       }
+       *pos = n;
+       return size;
+}
+
+/**
+ * efi_pstore_read
+ *
+ * This function returns a size of NVRAM entry logged via efi_pstore_write().
+ * The meaning and behavior of efi_pstore/pstore are as below.
+ *
+ * size > 0: Got data of an entry logged via efi_pstore_write() successfully,
+ *           and pstore filesystem will continue reading subsequent entries.
+ * size == 0: Entry was not logged via efi_pstore_write(),
+ *            and efi_pstore driver will continue reading subsequent entries.
+ * size < 0: Failed to get data of entry logging via efi_pstore_write(),
+ *           and pstore will stop reading entry.
+ */
 static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
                               int *count, struct timespec *timespec,
                               char **buf, bool *compressed,
                               struct pstore_info *psi)
 {
        struct pstore_read_data data;
+       ssize_t size;
 
        data.id = id;
        data.type = type;
@@ -112,8 +222,17 @@ static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
        data.compressed = compressed;
        data.buf = buf;
 
-       return __efivar_entry_iter(efi_pstore_read_func, &efivar_sysfs_list, &data,
-                                  (struct efivar_entry **)&psi->data);
+       *data.buf = kzalloc(EFIVARS_DATA_SIZE_MAX, GFP_KERNEL);
+       if (!*data.buf)
+               return -ENOMEM;
+
+       efivar_entry_iter_begin();
+       size = efi_pstore_sysfs_entry_iter(&data,
+                                          (struct efivar_entry **)&psi->data);
+       efivar_entry_iter_end();
+       if (size <= 0)
+               kfree(*data.buf);
+       return size;
 }
 
 static int efi_pstore_write(enum pstore_type_id type,
@@ -184,9 +303,17 @@ static int efi_pstore_erase_func(struct efivar_entry *entry, void *data)
                        return 0;
        }
 
+       if (entry->scanning) {
+               /*
+                * Skip deletion because this entry will be deleted
+                * after scanning is completed.
+                */
+               entry->deleting = true;
+       } else
+               list_del(&entry->list);
+
        /* found */
        __efivar_entry_delete(entry);
-       list_del(&entry->list);
 
        return 1;
 }
@@ -199,14 +326,16 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count,
        char name[DUMP_NAME_LEN];
        efi_char16_t efi_name[DUMP_NAME_LEN];
        int found, i;
+       unsigned int part;
 
-       sprintf(name, "dump-type%u-%u-%d-%lu", type, (unsigned int)id, count,
-               time.tv_sec);
+       do_div(id, 1000);
+       part = do_div(id, 100);
+       sprintf(name, "dump-type%u-%u-%d-%lu", type, part, count, time.tv_sec);
 
        for (i = 0; i < DUMP_NAME_LEN; i++)
                efi_name[i] = name[i];
 
-       edata.id = id;
+       edata.id = part;
        edata.type = type;
        edata.count = count;
        edata.time = time;
@@ -214,10 +343,12 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count,
 
        efivar_entry_iter_begin();
        found = __efivar_entry_iter(efi_pstore_erase_func, &efivar_sysfs_list, &edata, &entry);
-       efivar_entry_iter_end();
 
-       if (found)
+       if (found && !entry->scanning) {
+               efivar_entry_iter_end();
                efivar_unregister(entry);
+       } else
+               efivar_entry_iter_end();
 
        return 0;
 }
index 933eb027d527d53aa8fb275b84c5d9b6e2ce3602..3dc24823919749ebb110f62b9ca5696cdaf67511 100644 (file)
@@ -383,12 +383,16 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,
        else if (__efivar_entry_delete(entry))
                err = -EIO;
 
-       efivar_entry_iter_end();
-
-       if (err)
+       if (err) {
+               efivar_entry_iter_end();
                return err;
+       }
 
-       efivar_unregister(entry);
+       if (!entry->scanning) {
+               efivar_entry_iter_end();
+               efivar_unregister(entry);
+       } else
+               efivar_entry_iter_end();
 
        /* It's dead Jim.... */
        return count;
index 391c67b182d9b282681890cd04b98c0183023abc..b22659cccca42ebf85e3b54e52249b581b786409 100644 (file)
@@ -683,8 +683,16 @@ struct efivar_entry *efivar_entry_find(efi_char16_t *name, efi_guid_t guid,
        if (!found)
                return NULL;
 
-       if (remove)
-               list_del(&entry->list);
+       if (remove) {
+               if (entry->scanning) {
+                       /*
+                        * The entry will be deleted
+                        * after scanning is completed.
+                        */
+                       entry->deleting = true;
+               } else
+                       list_del(&entry->list);
+       }
 
        return entry;
 }
index 0f0444475bf065e9bc90e9d72ad26fac284ec9f9..7ef68e65918f6900ff424de7db880167a1c32650 100644 (file)
@@ -381,6 +381,14 @@ config GPIO_ARIZONA
        help
          Support for GPIOs on Wolfson Arizona class devices.
 
+config GPIO_LP3943
+       tristate "TI/National Semiconductor LP3943 GPIO expander"
+       depends on MFD_LP3943
+       help
+         GPIO driver for LP3943 MFD.
+         LP3943 can be used as a GPIO expander which provides up to 16 GPIOs.
+         Open drain outputs are required for this usage.
+
 config GPIO_MAX7300
        tristate "Maxim MAX7300 GPIO expander"
        depends on I2C
index 7971e36b8b1200d354254fb877a0b772a6d28361..95927b61c201526e70a6bfd439d8b7a5691944b5 100644 (file)
@@ -35,6 +35,7 @@ obj-$(CONFIG_GPIO_JANZ_TTL)   += gpio-janz-ttl.o
 obj-$(CONFIG_GPIO_KEMPLD)      += gpio-kempld.o
 obj-$(CONFIG_ARCH_KS8695)      += gpio-ks8695.o
 obj-$(CONFIG_GPIO_INTEL_MID)   += gpio-intel-mid.o
+obj-$(CONFIG_GPIO_LP3943)      += gpio-lp3943.o
 obj-$(CONFIG_ARCH_LPC32XX)     += gpio-lpc32xx.o
 obj-$(CONFIG_GPIO_LYNXPOINT)   += gpio-lynxpoint.o
 obj-$(CONFIG_GPIO_MAX730X)     += gpio-max730x.o
index 8847adf392b7ecf823f9f603314c76001367203f..84be70157ad6b6e9809bd007c422e223c359d429 100644 (file)
@@ -327,7 +327,7 @@ static int gpio_to_irq_unbanked(struct gpio_chip *chip, unsigned offset)
         * NOTE:  we assume for now that only irqs in the first gpio_chip
         * can provide direct-mapped IRQs to AINTC (up to 32 GPIOs).
         */
-       if (offset < d->irq_base)
+       if (offset < d->gpio_unbanked)
                return d->gpio_irq + offset;
        else
                return -ENODEV;
@@ -419,6 +419,8 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
 
                /* pass "bank 0" GPIO IRQs to AINTC */
                chips[0].chip.to_irq = gpio_to_irq_unbanked;
+               chips[0].gpio_irq = bank_irq;
+               chips[0].gpio_unbanked = pdata->gpio_unbanked;
                binten = BIT(0);
 
                /* AINTC handles mask/unmask; GPIO handles triggering */
diff --git a/drivers/gpio/gpio-lp3943.c b/drivers/gpio/gpio-lp3943.c
new file mode 100644 (file)
index 0000000..7b8db88
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ * TI/National Semiconductor LP3943 GPIO driver
+ *
+ * Copyright 2013 Texas Instruments
+ *
+ * Author: Milo Kim <milo.kim@ti.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.
+ */
+
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/mfd/lp3943.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+enum lp3943_gpios {
+       LP3943_GPIO1,
+       LP3943_GPIO2,
+       LP3943_GPIO3,
+       LP3943_GPIO4,
+       LP3943_GPIO5,
+       LP3943_GPIO6,
+       LP3943_GPIO7,
+       LP3943_GPIO8,
+       LP3943_GPIO9,
+       LP3943_GPIO10,
+       LP3943_GPIO11,
+       LP3943_GPIO12,
+       LP3943_GPIO13,
+       LP3943_GPIO14,
+       LP3943_GPIO15,
+       LP3943_GPIO16,
+       LP3943_MAX_GPIO,
+};
+
+struct lp3943_gpio {
+       struct gpio_chip chip;
+       struct lp3943 *lp3943;
+       u16 input_mask;         /* 1 = GPIO is input direction, 0 = output */
+};
+
+static inline struct lp3943_gpio *to_lp3943_gpio(struct gpio_chip *_chip)
+{
+       return container_of(_chip, struct lp3943_gpio, chip);
+}
+
+static int lp3943_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+       struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip);
+       struct lp3943 *lp3943 = lp3943_gpio->lp3943;
+
+       /* Return an error if the pin is already assigned */
+       if (test_and_set_bit(offset, &lp3943->pin_used))
+               return -EBUSY;
+
+       return 0;
+}
+
+static void lp3943_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+       struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip);
+       struct lp3943 *lp3943 = lp3943_gpio->lp3943;
+
+       clear_bit(offset, &lp3943->pin_used);
+}
+
+static int lp3943_gpio_set_mode(struct lp3943_gpio *lp3943_gpio, u8 offset,
+                               u8 val)
+{
+       struct lp3943 *lp3943 = lp3943_gpio->lp3943;
+       const struct lp3943_reg_cfg *mux = lp3943->mux_cfg;
+
+       return lp3943_update_bits(lp3943, mux[offset].reg, mux[offset].mask,
+                                 val << mux[offset].shift);
+}
+
+static int lp3943_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+       struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip);
+
+       lp3943_gpio->input_mask |= BIT(offset);
+
+       return lp3943_gpio_set_mode(lp3943_gpio, offset, LP3943_GPIO_IN);
+}
+
+static int lp3943_get_gpio_in_status(struct lp3943_gpio *lp3943_gpio,
+                                    struct gpio_chip *chip, unsigned offset)
+{
+       u8 addr, read;
+       int err;
+
+       switch (offset) {
+       case LP3943_GPIO1 ... LP3943_GPIO8:
+               addr = LP3943_REG_GPIO_A;
+               break;
+       case LP3943_GPIO9 ... LP3943_GPIO16:
+               addr = LP3943_REG_GPIO_B;
+               offset = offset - 8;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       err = lp3943_read_byte(lp3943_gpio->lp3943, addr, &read);
+       if (err)
+               return err;
+
+       return !!(read & BIT(offset));
+}
+
+static int lp3943_get_gpio_out_status(struct lp3943_gpio *lp3943_gpio,
+                                     struct gpio_chip *chip, unsigned offset)
+{
+       struct lp3943 *lp3943 = lp3943_gpio->lp3943;
+       const struct lp3943_reg_cfg *mux = lp3943->mux_cfg;
+       u8 read;
+       int err;
+
+       err = lp3943_read_byte(lp3943, mux[offset].reg, &read);
+       if (err)
+               return err;
+
+       read = (read & mux[offset].mask) >> mux[offset].shift;
+
+       if (read == LP3943_GPIO_OUT_HIGH)
+               return 1;
+       else if (read == LP3943_GPIO_OUT_LOW)
+               return 0;
+       else
+               return -EINVAL;
+}
+
+static int lp3943_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+       struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip);
+
+       /*
+        * Limitation:
+        *   LP3943 doesn't have the GPIO direction register. It provides
+        *   only input and output status registers.
+        *   So, direction info is required to handle the 'get' operation.
+        *   This variable is updated whenever the direction is changed and
+        *   it is used here.
+        */
+
+       if (lp3943_gpio->input_mask & BIT(offset))
+               return lp3943_get_gpio_in_status(lp3943_gpio, chip, offset);
+       else
+               return lp3943_get_gpio_out_status(lp3943_gpio, chip, offset);
+}
+
+static void lp3943_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+       struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip);
+       u8 data;
+
+       if (value)
+               data = LP3943_GPIO_OUT_HIGH;
+       else
+               data = LP3943_GPIO_OUT_LOW;
+
+       lp3943_gpio_set_mode(lp3943_gpio, offset, data);
+}
+
+static int lp3943_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+                                       int value)
+{
+       struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip);
+
+       lp3943_gpio_set(chip, offset, value);
+       lp3943_gpio->input_mask &= ~BIT(offset);
+
+       return 0;
+}
+
+static const struct gpio_chip lp3943_gpio_chip = {
+       .label                  = "lp3943",
+       .owner                  = THIS_MODULE,
+       .request                = lp3943_gpio_request,
+       .free                   = lp3943_gpio_free,
+       .direction_input        = lp3943_gpio_direction_input,
+       .get                    = lp3943_gpio_get,
+       .direction_output       = lp3943_gpio_direction_output,
+       .set                    = lp3943_gpio_set,
+       .base                   = -1,
+       .ngpio                  = LP3943_MAX_GPIO,
+       .can_sleep              = 1,
+};
+
+static int lp3943_gpio_probe(struct platform_device *pdev)
+{
+       struct lp3943 *lp3943 = dev_get_drvdata(pdev->dev.parent);
+       struct lp3943_gpio *lp3943_gpio;
+
+       lp3943_gpio = devm_kzalloc(&pdev->dev, sizeof(*lp3943_gpio),
+                               GFP_KERNEL);
+       if (!lp3943_gpio)
+               return -ENOMEM;
+
+       lp3943_gpio->lp3943 = lp3943;
+       lp3943_gpio->chip = lp3943_gpio_chip;
+       lp3943_gpio->chip.dev = &pdev->dev;
+
+       platform_set_drvdata(pdev, lp3943_gpio);
+
+       return gpiochip_add(&lp3943_gpio->chip);
+}
+
+static int lp3943_gpio_remove(struct platform_device *pdev)
+{
+       struct lp3943_gpio *lp3943_gpio = platform_get_drvdata(pdev);
+
+       return gpiochip_remove(&lp3943_gpio->chip);
+}
+
+static const struct of_device_id lp3943_gpio_of_match[] = {
+       { .compatible = "ti,lp3943-gpio", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, lp3943_gpio_of_match);
+
+static struct platform_driver lp3943_gpio_driver = {
+       .probe = lp3943_gpio_probe,
+       .remove = lp3943_gpio_remove,
+       .driver = {
+               .name = "lp3943-gpio",
+               .owner = THIS_MODULE,
+               .of_match_table = of_match_ptr(lp3943_gpio_of_match),
+       },
+};
+module_platform_driver(lp3943_gpio_driver);
+
+MODULE_DESCRIPTION("LP3943 GPIO driver");
+MODULE_ALIAS("platform:lp3943-gpio");
+MODULE_AUTHOR("Milo Kim");
+MODULE_LICENSE("GPL");
index 914e859e3eda38724642a8bdf60ea8bb7d4adcd6..d7d6d72eba33e89306168a16f16f487e445bb183 100644 (file)
@@ -70,10 +70,14 @@ static int mpc8572_gpio_get(struct gpio_chip *gc, unsigned int gpio)
        u32 val;
        struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
        struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
+       u32 out_mask, out_shadow;
 
-       val = in_be32(mm->regs + GPIO_DAT) & ~in_be32(mm->regs + GPIO_DIR);
+       out_mask = in_be32(mm->regs + GPIO_DIR);
 
-       return (val | mpc8xxx_gc->data) & mpc8xxx_gpio2mask(gpio);
+       val = in_be32(mm->regs + GPIO_DAT) & ~out_mask;
+       out_shadow = mpc8xxx_gc->data & out_mask;
+
+       return (val | out_shadow) & mpc8xxx_gpio2mask(gpio);
 }
 
 static int mpc8xxx_gpio_get(struct gpio_chip *gc, unsigned int gpio)
index ac53a95936626800143d1ad30320329f0f3ec050..85f772c0b26a619ec9c563f77f35c22fb8975e7f 100644 (file)
@@ -2368,7 +2368,7 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id,
                                continue;
                        }
 
-                       if (chip->ngpio >= p->chip_hwnum) {
+                       if (chip->ngpio <= p->chip_hwnum) {
                                dev_warn(dev, "GPIO chip %s has %d GPIOs\n",
                                         chip->label, chip->ngpio);
                                continue;
@@ -2418,7 +2418,7 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
                                               const char *con_id,
                                               unsigned int idx)
 {
-       struct gpio_desc *desc;
+       struct gpio_desc *desc = NULL;
        int status;
        enum gpio_lookup_flags flags = 0;
 
@@ -2431,13 +2431,23 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
        } else if (IS_ENABLED(CONFIG_ACPI) && dev && ACPI_HANDLE(dev)) {
                dev_dbg(dev, "using ACPI for GPIO lookup\n");
                desc = acpi_find_gpio(dev, con_id, idx, &flags);
-       } else {
+       }
+
+       /*
+        * Either we are not using DT or ACPI, or their lookup did not return
+        * a result. In that case, use platform lookup as a fallback.
+        */
+       if (!desc || IS_ERR(desc)) {
+               struct gpio_desc *pdesc;
                dev_dbg(dev, "using lookup tables for GPIO lookup");
-               desc = gpiod_find(dev, con_id, idx, &flags);
+               pdesc = gpiod_find(dev, con_id, idx, &flags);
+               /* If used as fallback, do not replace the previous error */
+               if (!IS_ERR(pdesc) || !desc)
+                       desc = pdesc;
        }
 
        if (IS_ERR(desc)) {
-               dev_warn(dev, "lookup for GPIO %s failed\n", con_id);
+               dev_dbg(dev, "lookup for GPIO %s failed\n", con_id);
                return desc;
        }
 
index fb7cf0e796f668328e7a923dbcada92ba8c2f1c7..0a1e4a5f4234dce320788330e97e8888016338ba 100644 (file)
@@ -2674,7 +2674,7 @@ static int add_3d_struct_modes(struct drm_connector *connector, u16 structure,
        int modes = 0;
        u8 cea_mode;
 
-       if (video_db == NULL || video_index > video_len)
+       if (video_db == NULL || video_index >= video_len)
                return 0;
 
        /* CEA modes are numbered 1..127 */
@@ -2701,7 +2701,7 @@ static int add_3d_struct_modes(struct drm_connector *connector, u16 structure,
        if (structure & (1 << 8)) {
                newmode = drm_mode_duplicate(dev, &edid_cea_modes[cea_mode]);
                if (newmode) {
-                       newmode->flags = DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF;
+                       newmode->flags |= DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF;
                        drm_mode_probed_add(connector, newmode);
                        modes++;
                }
index ebc01503d50ec1f2a9034bb81fa4724f12555f16..6f3400f3978a7544cf9138c4e2cd0d7dc41a7f85 100644 (file)
@@ -36,9 +36,9 @@ enum exynos_crtc_mode {
  * @pipe: a crtc index created at load() with a new crtc object creation
  *     and the crtc object would be set to private->crtc array
  *     to get a crtc object corresponding to this pipe from private->crtc
- *     array when irq interrupt occured. the reason of using this pipe is that
+ *     array when irq interrupt occurred. the reason of using this pipe is that
  *     drm framework doesn't support multiple irq yet.
- *     we can refer to the crtc to current hardware interrupt occured through
+ *     we can refer to the crtc to current hardware interrupt occurred through
  *     this pipe value.
  * @dpms: store the crtc dpms value
  * @mode: store the crtc mode value
index b676006a95a0118951f8e12d04f8a6fff0c49fb0..22b8f5eced80f3407b0fa9fc365c1d9e349d7e54 100644 (file)
@@ -172,29 +172,38 @@ static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
 
 static void exynos_drm_preclose(struct drm_device *dev,
                                        struct drm_file *file)
+{
+       exynos_drm_subdrv_close(dev, file);
+}
+
+static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file)
 {
        struct exynos_drm_private *private = dev->dev_private;
-       struct drm_pending_vblank_event *e, *t;
+       struct drm_pending_vblank_event *v, *vt;
+       struct drm_pending_event *e, *et;
        unsigned long flags;
 
-       /* release events of current file */
+       if (!file->driver_priv)
+               return;
+
+       /* Release all events not unhandled by page flip handler. */
        spin_lock_irqsave(&dev->event_lock, flags);
-       list_for_each_entry_safe(e, t, &private->pageflip_event_list,
+       list_for_each_entry_safe(v, vt, &private->pageflip_event_list,
                        base.link) {
-               if (e->base.file_priv == file) {
-                       list_del(&e->base.link);
-                       e->base.destroy(&e->base);
+               if (v->base.file_priv == file) {
+                       list_del(&v->base.link);
+                       drm_vblank_put(dev, v->pipe);
+                       v->base.destroy(&v->base);
                }
        }
-       spin_unlock_irqrestore(&dev->event_lock, flags);
 
-       exynos_drm_subdrv_close(dev, file);
-}
+       /* Release all events handled by page flip handler but not freed. */
+       list_for_each_entry_safe(e, et, &file->event_list, link) {
+               list_del(&e->link);
+               e->destroy(e);
+       }
+       spin_unlock_irqrestore(&dev->event_lock, flags);
 
-static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file)
-{
-       if (!file->driver_priv)
-               return;
 
        kfree(file->driver_priv);
        file->driver_priv = NULL;
index 23da72b5eae98b0bae1e400ea28d74ed5ee7e472..a61878bf5dcd091cf31ed64a8374d230b580dc1e 100644 (file)
@@ -31,7 +31,7 @@
 #include "exynos_drm_iommu.h"
 
 /*
- * FIMD is stand for Fully Interactive Mobile Display and
+ * FIMD stands for Fully Interactive Mobile Display and
  * as a display controller, it transfers contents drawn on memory
  * to a LCD Panel through Display Interfaces such as RGB or
  * CPU Interface.
index 7bccedca487aebde1483ff08d65898e8d360c1c3..380aec28840b7e5ec4245e71207f0586f05efe75 100644 (file)
@@ -1126,7 +1126,7 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
         * G2D interrupt event once current command list execution is
         * finished.
         * Otherwise only ACF bit should be set to INTEN register so
-        * that one interrupt is occured after all command lists
+        * that one interrupt is occurred after all command lists
         * have been completed.
         */
        if (node->event) {
index 1ade191d84f4d6514fd16871cb54cbdc3208d925..be59d50d8b16c836fbd1a5c88ed2bea87a7b769f 100644 (file)
@@ -652,7 +652,7 @@ int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
        int ret;
 
        /*
-        * alocate memory to be used for framebuffer.
+        * allocate memory to be used for framebuffer.
         * - this callback would be called by user application
         *      with DRM_IOCTL_MODE_CREATE_DUMB command.
         */
index 702ec3abe85cc88eb74aa2e7dc99b5224c175dcf..b8c818ba2ff450e104fe545106a544ed92341632 100644 (file)
@@ -60,7 +60,7 @@ struct exynos_drm_gem_buf {
  * @vma: a pointer to vm_area.
  * @flags: indicate memory type to allocated buffer and cache attruibute.
  *
- * P.S. this object would be transfered to user as kms_bo.handle so
+ * P.S. this object would be transferred to user as kms_bo.handle so
  *     user can access the buffer through kms_bo.handle.
  */
 struct exynos_drm_gem_obj {
index 824e0705c8d333734f1713f996e9c48d225b307f..d519a4e5fe4022bd9101ede7a1e0edd2a4883dba 100644 (file)
@@ -335,7 +335,7 @@ int exynos_drm_ipp_get_property(struct drm_device *drm_dev, void *data,
        } else {
                /*
                 * Getting ippdrv capability by ipp_id.
-                * some deivce not supported wb, output interface.
+                * some device not supported wb, output interface.
                 * so, user application detect correct ipp driver
                 * using this ioctl.
                 */
index 4cadbea7dbde9d71b2011ae012b0e4c9b0b11ce3..ab1634befc05fd11e7766f1b537ae0f039af91bc 100644 (file)
@@ -48,7 +48,7 @@ struct drm_exynos_ipp_cmd_work {
 /*
  * A structure of command node.
  *
- * @priv: IPP private infomation.
+ * @priv: IPP private information.
  * @list: list head to command queue information.
  * @event_list: list head of event.
  * @mem_list: list head to source,destination memory queue information.
@@ -92,7 +92,7 @@ struct drm_exynos_ipp_buf_info {
 };
 
 /*
- * A structure of wb setting infomation.
+ * A structure of wb setting information.
  *
  * @enable: enable flag for wb.
  * @refresh: HZ of the refresh rate.
index 6199d0b5b958fb2610e83810e117ea89c5057e6e..73ed59eff139a88948c7766dcc0c999398f59254 100644 (file)
@@ -1,8 +1,10 @@
 config DRM_I915
        tristate "Intel 8xx/9xx/G3x/G4x/HD Graphics"
        depends on DRM
-       depends on AGP
-       depends on AGP_INTEL
+       depends on X86 && PCI
+       depends on (AGP || AGP=n)
+       select INTEL_GTT
+       select AGP_INTEL if AGP
        # we need shmfs for the swappable backing store, and in particular
        # the shmem_readpage() which depends upon tmpfs
        select SHMEM
@@ -35,15 +37,14 @@ config DRM_I915
 config DRM_I915_KMS
        bool "Enable modesetting on intel by default"
        depends on DRM_I915
+       default y
        help
-         Choose this option if you want kernel modesetting enabled by default,
-         and you have a new enough userspace to support this. Running old
-         userspaces with this enabled will cause pain.  Note that this causes
-         the driver to bind to PCI devices, which precludes loading things
-         like intelfb.
+         Choose this option if you want kernel modesetting enabled by default.
+
+         If in doubt, say "Y".
 
 config DRM_I915_FBDEV
-       bool "Enable legacy fbdev support for the modesettting intel driver"
+       bool "Enable legacy fbdev support for the modesetting intel driver"
        depends on DRM_I915
        select DRM_KMS_FB_HELPER
        select FB_CFB_FILLRECT
@@ -55,9 +56,12 @@ config DRM_I915_FBDEV
          support. Note that this support also provide the linux console
          support on top of the intel modesetting driver.
 
+         If in doubt, say "Y".
+
 config DRM_I915_PRELIMINARY_HW_SUPPORT
        bool "Enable preliminary support for prerelease Intel hardware by default"
        depends on DRM_I915
+       default n
        help
          Choose this option if you have prerelease Intel hardware and want the
          i915 driver to support it by default.  You can enable such support at
@@ -65,3 +69,15 @@ config DRM_I915_PRELIMINARY_HW_SUPPORT
          option changes the default for that module option.
 
          If in doubt, say "N".
+
+config DRM_I915_UMS
+       bool "Enable userspace modesetting on Intel hardware (DEPRECATED)"
+       depends on DRM_I915
+       default n
+       help
+         Choose this option if you still need userspace modesetting.
+
+         Userspace modesetting is deprecated for quite some time now, so
+         enable this only if you have ancient versions of the DDX drivers.
+
+         If in doubt, say "N".
index c4a255be697921caade4bf3dd064217e82230763..954acb2c7021d8eb9a90fe1e49ea5bc806f1f344 100644 (file)
@@ -87,49 +87,6 @@ struct ns2501_priv {
  * when switching the resolution.
  */
 
-static void enable_dvo(struct intel_dvo_device *dvo)
-{
-       struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
-       struct i2c_adapter *adapter = dvo->i2c_bus;
-       struct intel_gmbus *bus = container_of(adapter,
-                                              struct intel_gmbus,
-                                              adapter);
-       struct drm_i915_private *dev_priv = bus->dev_priv;
-
-       DRM_DEBUG_KMS("%s: Trying to re-enable the DVO\n", __FUNCTION__);
-
-       ns->dvoc = I915_READ(DVO_C);
-       ns->pll_a = I915_READ(_DPLL_A);
-       ns->srcdim = I915_READ(DVOC_SRCDIM);
-       ns->fw_blc = I915_READ(FW_BLC);
-
-       I915_WRITE(DVOC, 0x10004084);
-       I915_WRITE(_DPLL_A, 0xd0820000);
-       I915_WRITE(DVOC_SRCDIM, 0x400300);      // 1024x768
-       I915_WRITE(FW_BLC, 0x1080304);
-
-       I915_WRITE(DVOC, 0x90004084);
-}
-
-/*
- * Restore the I915 registers modified by the above
- * trigger function.
- */
-static void restore_dvo(struct intel_dvo_device *dvo)
-{
-       struct i2c_adapter *adapter = dvo->i2c_bus;
-       struct intel_gmbus *bus = container_of(adapter,
-                                              struct intel_gmbus,
-                                              adapter);
-       struct drm_i915_private *dev_priv = bus->dev_priv;
-       struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
-
-       I915_WRITE(DVOC, ns->dvoc);
-       I915_WRITE(_DPLL_A, ns->pll_a);
-       I915_WRITE(DVOC_SRCDIM, ns->srcdim);
-       I915_WRITE(FW_BLC, ns->fw_blc);
-}
-
 /*
 ** Read a register from the ns2501.
 ** Returns true if successful, false otherwise.
@@ -300,7 +257,7 @@ static void ns2501_mode_set(struct intel_dvo_device *dvo,
                            struct drm_display_mode *adjusted_mode)
 {
        bool ok;
-       bool restore = false;
+       int retries = 10;
        struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
 
        DRM_DEBUG_KMS
@@ -476,20 +433,7 @@ static void ns2501_mode_set(struct intel_dvo_device *dvo,
                        ns->reg_8_shadow |= NS2501_8_BPAS;
                }
                ok &= ns2501_writeb(dvo, NS2501_REG8, ns->reg_8_shadow);
-
-               if (!ok) {
-                       if (restore)
-                               restore_dvo(dvo);
-                       enable_dvo(dvo);
-                       restore = true;
-               }
-       } while (!ok);
-       /*
-        * Restore the old i915 registers before
-        * forcing the ns2501 on.
-        */
-       if (restore)
-               restore_dvo(dvo);
+       } while (!ok && retries--);
 }
 
 /* set the NS2501 power state */
@@ -510,7 +454,7 @@ static bool ns2501_get_hw_state(struct intel_dvo_device *dvo)
 static void ns2501_dpms(struct intel_dvo_device *dvo, bool enable)
 {
        bool ok;
-       bool restore = false;
+       int retries = 10;
        struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
        unsigned char ch;
 
@@ -537,16 +481,7 @@ static void ns2501_dpms(struct intel_dvo_device *dvo, bool enable)
                        ok &=
                            ns2501_writeb(dvo, 0x35,
                                          enable ? 0xff : 0x00);
-                       if (!ok) {
-                               if (restore)
-                                       restore_dvo(dvo);
-                               enable_dvo(dvo);
-                               restore = true;
-                       }
-               } while (!ok);
-
-               if (restore)
-                       restore_dvo(dvo);
+               } while (!ok && retries--);
        }
 }
 
index 6ed45a984230c6db3bb8cc4b8fbdc2eec9a661d1..6badc1596cebbbf6877fc9ea8a0f810d887adca9 100644 (file)
@@ -564,10 +564,12 @@ static int i915_gem_seqno_info(struct seq_file *m, void *data)
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
 
        for_each_ring(ring, dev_priv, i)
                i915_ring_seqno_info(m, ring);
 
+       intel_runtime_pm_put(dev_priv);
        mutex_unlock(&dev->struct_mutex);
 
        return 0;
@@ -585,6 +587,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
 
        if (INTEL_INFO(dev)->gen >= 8) {
                int i;
@@ -711,6 +714,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
                }
                i915_ring_seqno_info(m, ring);
        }
+       intel_runtime_pm_put(dev_priv);
        mutex_unlock(&dev->struct_mutex);
 
        return 0;
@@ -904,9 +908,11 @@ static int i915_rstdby_delays(struct seq_file *m, void *unused)
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
 
        crstanddelay = I915_READ16(CRSTANDVID);
 
+       intel_runtime_pm_put(dev_priv);
        mutex_unlock(&dev->struct_mutex);
 
        seq_printf(m, "w/ctx: %d, w/o ctx: %d\n", (crstanddelay >> 8) & 0x3f, (crstanddelay & 0x3f));
@@ -919,7 +925,9 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
        struct drm_info_node *node = (struct drm_info_node *) m->private;
        struct drm_device *dev = node->minor->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
-       int ret;
+       int ret = 0;
+
+       intel_runtime_pm_get(dev_priv);
 
        flush_delayed_work(&dev_priv->rps.delayed_resume_work);
 
@@ -945,9 +953,9 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
                /* RPSTAT1 is in the GT power well */
                ret = mutex_lock_interruptible(&dev->struct_mutex);
                if (ret)
-                       return ret;
+                       goto out;
 
-               gen6_gt_force_wake_get(dev_priv);
+               gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
 
                reqf = I915_READ(GEN6_RPNSWREQ);
                reqf &= ~GEN6_TURBO_DISABLE;
@@ -970,7 +978,7 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
                        cagf = (rpstat & GEN6_CAGF_MASK) >> GEN6_CAGF_SHIFT;
                cagf *= GT_FREQUENCY_MULTIPLIER;
 
-               gen6_gt_force_wake_put(dev_priv);
+               gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
                mutex_unlock(&dev->struct_mutex);
 
                seq_printf(m, "GT_PERF_STATUS: 0x%08x\n", gt_perf_status);
@@ -1018,23 +1026,24 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
                seq_printf(m, "PUNIT_REG_GPU_FREQ_STS: 0x%08x\n", freq_sts);
                seq_printf(m, "DDR freq: %d MHz\n", dev_priv->mem_freq);
 
-               val = vlv_punit_read(dev_priv, PUNIT_FUSE_BUS1);
+               val = valleyview_rps_max_freq(dev_priv);
                seq_printf(m, "max GPU freq: %d MHz\n",
-                          vlv_gpu_freq(dev_priv->mem_freq, val));
+                          vlv_gpu_freq(dev_priv, val));
 
-               val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_LFM);
+               val = valleyview_rps_min_freq(dev_priv);
                seq_printf(m, "min GPU freq: %d MHz\n",
-                          vlv_gpu_freq(dev_priv->mem_freq, val));
+                          vlv_gpu_freq(dev_priv, val));
 
                seq_printf(m, "current GPU freq: %d MHz\n",
-                          vlv_gpu_freq(dev_priv->mem_freq,
-                                       (freq_sts >> 8) & 0xff));
+                          vlv_gpu_freq(dev_priv, (freq_sts >> 8) & 0xff));
                mutex_unlock(&dev_priv->rps.hw_lock);
        } else {
                seq_puts(m, "no P-state info available\n");
        }
 
-       return 0;
+out:
+       intel_runtime_pm_put(dev_priv);
+       return ret;
 }
 
 static int i915_delayfreq_table(struct seq_file *m, void *unused)
@@ -1048,6 +1057,7 @@ static int i915_delayfreq_table(struct seq_file *m, void *unused)
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
 
        for (i = 0; i < 16; i++) {
                delayfreq = I915_READ(PXVFREQ_BASE + i * 4);
@@ -1055,6 +1065,8 @@ static int i915_delayfreq_table(struct seq_file *m, void *unused)
                           (delayfreq & PXVFREQ_PX_MASK) >> PXVFREQ_PX_SHIFT);
        }
 
+       intel_runtime_pm_put(dev_priv);
+
        mutex_unlock(&dev->struct_mutex);
 
        return 0;
@@ -1076,12 +1088,14 @@ static int i915_inttoext_table(struct seq_file *m, void *unused)
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
 
        for (i = 1; i <= 32; i++) {
                inttoext = I915_READ(INTTOEXT_BASE_ILK + i * 4);
                seq_printf(m, "INTTOEXT%02d: 0x%08x\n", i, inttoext);
        }
 
+       intel_runtime_pm_put(dev_priv);
        mutex_unlock(&dev->struct_mutex);
 
        return 0;
@@ -1099,11 +1113,13 @@ static int ironlake_drpc_info(struct seq_file *m)
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
 
        rgvmodectl = I915_READ(MEMMODECTL);
        rstdbyctl = I915_READ(RSTDBYCTL);
        crstandvid = I915_READ16(CRSTANDVID);
 
+       intel_runtime_pm_put(dev_priv);
        mutex_unlock(&dev->struct_mutex);
 
        seq_printf(m, "HD boost: %s\n", (rgvmodectl & MEMMODE_BOOST_EN) ?
@@ -1167,6 +1183,7 @@ static int gen6_drpc_info(struct seq_file *m)
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
 
        spin_lock_irq(&dev_priv->uncore.lock);
        forcewake_count = dev_priv->uncore.forcewake_count;
@@ -1192,6 +1209,8 @@ static int gen6_drpc_info(struct seq_file *m)
        sandybridge_pcode_read(dev_priv, GEN6_PCODE_READ_RC6VIDS, &rc6vids);
        mutex_unlock(&dev_priv->rps.hw_lock);
 
+       intel_runtime_pm_put(dev_priv);
+
        seq_printf(m, "Video Turbo Mode: %s\n",
                   yesno(rpmodectl1 & GEN6_RP_MEDIA_TURBO));
        seq_printf(m, "HW control enabled: %s\n",
@@ -1406,6 +1425,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
        ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
 
        seq_puts(m, "GPU freq (MHz)\tEffective CPU freq (MHz)\tEffective Ring freq (MHz)\n");
 
@@ -1422,6 +1442,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
                           ((ia_freq >> 8) & 0xff) * 100);
        }
 
+       intel_runtime_pm_put(dev_priv);
        mutex_unlock(&dev_priv->rps.hw_lock);
 
        return 0;
@@ -1437,8 +1458,10 @@ static int i915_gfxec(struct seq_file *m, void *unused)
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
 
        seq_printf(m, "GFXEC: %ld\n", (unsigned long)I915_READ(0x112f4));
+       intel_runtime_pm_put(dev_priv);
 
        mutex_unlock(&dev->struct_mutex);
 
@@ -1565,13 +1588,21 @@ static int i915_gen6_forcewake_count_info(struct seq_file *m, void *data)
        struct drm_info_node *node = (struct drm_info_node *) m->private;
        struct drm_device *dev = node->minor->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       unsigned forcewake_count;
+       unsigned forcewake_count = 0, fw_rendercount = 0, fw_mediacount = 0;
 
        spin_lock_irq(&dev_priv->uncore.lock);
-       forcewake_count = dev_priv->uncore.forcewake_count;
+       if (IS_VALLEYVIEW(dev)) {
+               fw_rendercount = dev_priv->uncore.fw_rendercount;
+               fw_mediacount = dev_priv->uncore.fw_mediacount;
+       } else
+               forcewake_count = dev_priv->uncore.forcewake_count;
        spin_unlock_irq(&dev_priv->uncore.lock);
 
-       seq_printf(m, "forcewake count = %u\n", forcewake_count);
+       if (IS_VALLEYVIEW(dev)) {
+               seq_printf(m, "fw_rendercount = %u\n", fw_rendercount);
+               seq_printf(m, "fw_mediacount = %u\n", fw_mediacount);
+       } else
+               seq_printf(m, "forcewake count = %u\n", forcewake_count);
 
        return 0;
 }
@@ -1610,6 +1641,7 @@ static int i915_swizzle_info(struct seq_file *m, void *data)
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
 
        seq_printf(m, "bit6 swizzle for X-tiling = %s\n",
                   swizzle_string(dev_priv->mm.bit_6_swizzle_x));
@@ -1641,6 +1673,7 @@ static int i915_swizzle_info(struct seq_file *m, void *data)
                seq_printf(m, "DISP_ARB_CTL = 0x%08x\n",
                           I915_READ(DISP_ARB_CTL));
        }
+       intel_runtime_pm_put(dev_priv);
        mutex_unlock(&dev->struct_mutex);
 
        return 0;
@@ -1701,16 +1734,19 @@ static int i915_ppgtt_info(struct seq_file *m, void *data)
 {
        struct drm_info_node *node = (struct drm_info_node *) m->private;
        struct drm_device *dev = node->minor->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
 
        int ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
 
        if (INTEL_INFO(dev)->gen >= 8)
                gen8_ppgtt_info(m, dev);
        else if (INTEL_INFO(dev)->gen >= 6)
                gen6_ppgtt_info(m, dev);
 
+       intel_runtime_pm_put(dev_priv);
        mutex_unlock(&dev->struct_mutex);
 
        return 0;
@@ -1735,28 +1771,28 @@ 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, PIPE_A, _DPIO_DIV_A));
-       seq_printf(m, "DPIO_DIV_B: 0x%08x\n",
-                  vlv_dpio_read(dev_priv, PIPE_A, _DPIO_DIV_B));
+       seq_printf(m, "DPIO PLL DW3 CH0 : 0x%08x\n",
+                  vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW3(0)));
+       seq_printf(m, "DPIO PLL DW3 CH1: 0x%08x\n",
+                  vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW3(1)));
 
-       seq_printf(m, "DPIO_REFSFR_A: 0x%08x\n",
-                  vlv_dpio_read(dev_priv, PIPE_A, _DPIO_REFSFR_A));
-       seq_printf(m, "DPIO_REFSFR_B: 0x%08x\n",
-                  vlv_dpio_read(dev_priv, PIPE_A, _DPIO_REFSFR_B));
+       seq_printf(m, "DPIO PLL DW5 CH0: 0x%08x\n",
+                  vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW5(0)));
+       seq_printf(m, "DPIO PLL DW5 CH1: 0x%08x\n",
+                  vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW5(1)));
 
-       seq_printf(m, "DPIO_CORE_CLK_A: 0x%08x\n",
-                  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, PIPE_A, _DPIO_CORE_CLK_B));
+       seq_printf(m, "DPIO PLL DW7 CH0: 0x%08x\n",
+                  vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW7(0)));
+       seq_printf(m, "DPIO PLL DW7 CH1: 0x%08x\n",
+                  vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW7(1)));
 
-       seq_printf(m, "DPIO_LPF_COEFF_A: 0x%08x\n",
-                  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, PIPE_A, _DPIO_LPF_COEFF_B));
+       seq_printf(m, "DPIO PLL DW10 CH0: 0x%08x\n",
+                  vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW10(0)));
+       seq_printf(m, "DPIO PLL DW10 CH1: 0x%08x\n",
+                  vlv_dpio_read(dev_priv, PIPE_A, VLV_PLL_DW10(1)));
 
        seq_printf(m, "DPIO_FASTCLK_DISABLE: 0x%08x\n",
-                  vlv_dpio_read(dev_priv, PIPE_A, DPIO_FASTCLK_DISABLE));
+                  vlv_dpio_read(dev_priv, PIPE_A, VLV_CMN_DW0));
 
        mutex_unlock(&dev_priv->dpio_lock);
 
@@ -1784,6 +1820,8 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
        u32 psrperf = 0;
        bool enabled = false;
 
+       intel_runtime_pm_get(dev_priv);
+
        seq_printf(m, "Sink_Support: %s\n", yesno(dev_priv->psr.sink_support));
        seq_printf(m, "Source_OK: %s\n", yesno(dev_priv->psr.source_ok));
 
@@ -1796,6 +1834,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
                        EDP_PSR_PERF_CNT_MASK;
        seq_printf(m, "Performance_Counter: %u\n", psrperf);
 
+       intel_runtime_pm_put(dev_priv);
        return 0;
 }
 
@@ -1845,6 +1884,76 @@ static int i915_pc8_status(struct seq_file *m, void *unused)
        return 0;
 }
 
+static const char *power_domain_str(enum intel_display_power_domain domain)
+{
+       switch (domain) {
+       case POWER_DOMAIN_PIPE_A:
+               return "PIPE_A";
+       case POWER_DOMAIN_PIPE_B:
+               return "PIPE_B";
+       case POWER_DOMAIN_PIPE_C:
+               return "PIPE_C";
+       case POWER_DOMAIN_PIPE_A_PANEL_FITTER:
+               return "PIPE_A_PANEL_FITTER";
+       case POWER_DOMAIN_PIPE_B_PANEL_FITTER:
+               return "PIPE_B_PANEL_FITTER";
+       case POWER_DOMAIN_PIPE_C_PANEL_FITTER:
+               return "PIPE_C_PANEL_FITTER";
+       case POWER_DOMAIN_TRANSCODER_A:
+               return "TRANSCODER_A";
+       case POWER_DOMAIN_TRANSCODER_B:
+               return "TRANSCODER_B";
+       case POWER_DOMAIN_TRANSCODER_C:
+               return "TRANSCODER_C";
+       case POWER_DOMAIN_TRANSCODER_EDP:
+               return "TRANSCODER_EDP";
+       case POWER_DOMAIN_VGA:
+               return "VGA";
+       case POWER_DOMAIN_AUDIO:
+               return "AUDIO";
+       case POWER_DOMAIN_INIT:
+               return "INIT";
+       default:
+               WARN_ON(1);
+               return "?";
+       }
+}
+
+static int i915_power_domain_info(struct seq_file *m, void *unused)
+{
+       struct drm_info_node *node = (struct drm_info_node *) m->private;
+       struct drm_device *dev = node->minor->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct i915_power_domains *power_domains = &dev_priv->power_domains;
+       int i;
+
+       mutex_lock(&power_domains->lock);
+
+       seq_printf(m, "%-25s %s\n", "Power well/domain", "Use count");
+       for (i = 0; i < power_domains->power_well_count; i++) {
+               struct i915_power_well *power_well;
+               enum intel_display_power_domain power_domain;
+
+               power_well = &power_domains->power_wells[i];
+               seq_printf(m, "%-25s %d\n", power_well->name,
+                          power_well->count);
+
+               for (power_domain = 0; power_domain < POWER_DOMAIN_NUM;
+                    power_domain++) {
+                       if (!(BIT(power_domain) & power_well->domains))
+                               continue;
+
+                       seq_printf(m, "  %-23s %d\n",
+                                power_domain_str(power_domain),
+                                power_domains->domain_use_count[power_domain]);
+               }
+       }
+
+       mutex_unlock(&power_domains->lock);
+
+       return 0;
+}
+
 struct pipe_crc_info {
        const char *name;
        struct drm_device *dev;
@@ -1857,6 +1966,9 @@ static int i915_pipe_crc_open(struct inode *inode, struct file *filep)
        struct drm_i915_private *dev_priv = info->dev->dev_private;
        struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[info->pipe];
 
+       if (info->pipe >= INTEL_INFO(info->dev)->num_pipes)
+               return -ENODEV;
+
        spin_lock_irq(&pipe_crc->lock);
 
        if (pipe_crc->opened) {
@@ -2347,7 +2459,7 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe];
-       u32 val;
+       u32 val = 0; /* shut up gcc */
        int ret;
 
        if (pipe_crc->source == source)
@@ -2742,7 +2854,7 @@ i915_drop_caches_set(void *data, u64 val)
        struct i915_vma *vma, *x;
        int ret;
 
-       DRM_DEBUG_DRIVER("Dropping caches: 0x%08llx\n", val);
+       DRM_DEBUG("Dropping caches: 0x%08llx\n", val);
 
        /* No need to check and wait for gpu resets, only libdrm auto-restarts
         * on ioctls on -EAGAIN. */
@@ -2810,8 +2922,7 @@ i915_max_freq_get(void *data, u64 *val)
                return ret;
 
        if (IS_VALLEYVIEW(dev))
-               *val = vlv_gpu_freq(dev_priv->mem_freq,
-                                   dev_priv->rps.max_delay);
+               *val = vlv_gpu_freq(dev_priv, dev_priv->rps.max_delay);
        else
                *val = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER;
        mutex_unlock(&dev_priv->rps.hw_lock);
@@ -2841,9 +2952,9 @@ i915_max_freq_set(void *data, u64 val)
         * Turbo will still be enabled, but won't go above the set value.
         */
        if (IS_VALLEYVIEW(dev)) {
-               val = vlv_freq_opcode(dev_priv->mem_freq, val);
+               val = vlv_freq_opcode(dev_priv, val);
                dev_priv->rps.max_delay = val;
-               gen6_set_rps(dev, val);
+               valleyview_set_rps(dev, val);
        } else {
                do_div(val, GT_FREQUENCY_MULTIPLIER);
                dev_priv->rps.max_delay = val;
@@ -2876,8 +2987,7 @@ i915_min_freq_get(void *data, u64 *val)
                return ret;
 
        if (IS_VALLEYVIEW(dev))
-               *val = vlv_gpu_freq(dev_priv->mem_freq,
-                                   dev_priv->rps.min_delay);
+               *val = vlv_gpu_freq(dev_priv, dev_priv->rps.min_delay);
        else
                *val = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER;
        mutex_unlock(&dev_priv->rps.hw_lock);
@@ -2907,7 +3017,7 @@ i915_min_freq_set(void *data, u64 val)
         * Turbo will still be enabled, but won't go below the set value.
         */
        if (IS_VALLEYVIEW(dev)) {
-               val = vlv_freq_opcode(dev_priv->mem_freq, val);
+               val = vlv_freq_opcode(dev_priv, val);
                dev_priv->rps.min_delay = val;
                valleyview_set_rps(dev, val);
        } else {
@@ -2938,8 +3048,11 @@ i915_cache_sharing_get(void *data, u64 *val)
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
 
        snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
+
+       intel_runtime_pm_put(dev_priv);
        mutex_unlock(&dev_priv->dev->struct_mutex);
 
        *val = (snpcr & GEN6_MBC_SNPCR_MASK) >> GEN6_MBC_SNPCR_SHIFT;
@@ -2960,6 +3073,7 @@ i915_cache_sharing_set(void *data, u64 val)
        if (val > 3)
                return -EINVAL;
 
+       intel_runtime_pm_get(dev_priv);
        DRM_DEBUG_DRIVER("Manually setting uncore sharing to %llu\n", val);
 
        /* Update the cache sharing policy here as well */
@@ -2968,6 +3082,7 @@ i915_cache_sharing_set(void *data, u64 val)
        snpcr |= (val << GEN6_MBC_SNPCR_SHIFT);
        I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr);
 
+       intel_runtime_pm_put(dev_priv);
        return 0;
 }
 
@@ -2983,7 +3098,8 @@ static int i915_forcewake_open(struct inode *inode, struct file *file)
        if (INTEL_INFO(dev)->gen < 6)
                return 0;
 
-       gen6_gt_force_wake_get(dev_priv);
+       intel_runtime_pm_get(dev_priv);
+       gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
 
        return 0;
 }
@@ -2996,7 +3112,8 @@ static int i915_forcewake_release(struct inode *inode, struct file *file)
        if (INTEL_INFO(dev)->gen < 6)
                return 0;
 
-       gen6_gt_force_wake_put(dev_priv);
+       gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
+       intel_runtime_pm_put(dev_priv);
 
        return 0;
 }
@@ -3079,6 +3196,7 @@ static const struct drm_info_list i915_debugfs_list[] = {
        {"i915_edp_psr_status", i915_edp_psr_status, 0},
        {"i915_energy_uJ", i915_energy_uJ, 0},
        {"i915_pc8_status", i915_pc8_status, 0},
+       {"i915_power_domain_info", i915_power_domain_info, 0},
 };
 #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
 
@@ -3102,10 +3220,10 @@ static const struct i915_debugfs_files {
 void intel_display_crc_init(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       int i;
+       enum pipe pipe;
 
-       for (i = 0; i < INTEL_INFO(dev)->num_pipes; i++) {
-               struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[i];
+       for_each_pipe(pipe) {
+               struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe];
 
                pipe_crc->opened = false;
                spin_lock_init(&pipe_crc->lock);
index 0cab2d045135b66d0462c88d390e43eff3df7b20..bfbf9fc3eb53dbf844d1bb513cfda2d60ef14262 100644 (file)
@@ -42,6 +42,8 @@
 #include <linux/vga_switcheroo.h>
 #include <linux/slab.h>
 #include <acpi/video.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
 
 #define LP_RING(d) (&((struct drm_i915_private *)(d))->ring[RCS])
 
@@ -83,6 +85,14 @@ void i915_update_dri1_breadcrumb(struct drm_device *dev)
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct drm_i915_master_private *master_priv;
 
+       /*
+        * The dri breadcrumb update races against the drm master disappearing.
+        * Instead of trying to fix this (this is by far not the only ums issue)
+        * just don't do the update in kms mode.
+        */
+       if (drm_core_check_feature(dev, DRIVER_MODESET))
+               return;
+
        if (dev->primary->master) {
                master_priv = dev->primary->master->driver_priv;
                if (master_priv->sarea_priv)
@@ -1486,20 +1496,13 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 
        spin_lock_init(&dev_priv->irq_lock);
        spin_lock_init(&dev_priv->gpu_error.lock);
-       spin_lock_init(&dev_priv->backlight.lock);
+       spin_lock_init(&dev_priv->backlight_lock);
        spin_lock_init(&dev_priv->uncore.lock);
        spin_lock_init(&dev_priv->mm.object_stat_lock);
        mutex_init(&dev_priv->dpio_lock);
-       mutex_init(&dev_priv->rps.hw_lock);
        mutex_init(&dev_priv->modeset_restore_lock);
 
-       mutex_init(&dev_priv->pc8.lock);
-       dev_priv->pc8.requirements_met = false;
-       dev_priv->pc8.gpu_idle = false;
-       dev_priv->pc8.irqs_disabled = false;
-       dev_priv->pc8.enabled = false;
-       dev_priv->pc8.disable_count = 2; /* requirements_met + gpu_idle */
-       INIT_DELAYED_WORK(&dev_priv->pc8.enable_work, hsw_enable_pc8_work);
+       intel_pm_setup(dev);
 
        intel_display_crc_init(dev);
 
@@ -1603,7 +1606,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        }
 
        intel_irq_init(dev);
-       intel_pm_init(dev);
        intel_uncore_sanitize(dev);
 
        /* Try to make sure MCHBAR is enabled before poking at it */
@@ -1639,8 +1641,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
                        goto out_gem_unload;
        }
 
-       if (HAS_POWER_WELL(dev))
-               intel_power_domains_init(dev);
+       intel_power_domains_init(dev);
 
        if (drm_core_check_feature(dev, DRIVER_MODESET)) {
                ret = i915_load_modeset_init(dev);
@@ -1664,11 +1665,12 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        if (IS_GEN5(dev))
                intel_gpu_ips_init(dev_priv);
 
+       intel_init_runtime_pm(dev_priv);
+
        return 0;
 
 out_power_well:
-       if (HAS_POWER_WELL(dev))
-               intel_power_domains_remove(dev);
+       intel_power_domains_remove(dev);
        drm_vblank_cleanup(dev);
 out_gem_unload:
        if (dev_priv->mm.inactive_shrinker.scan_objects)
@@ -1704,25 +1706,27 @@ int i915_driver_unload(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        int ret;
 
+       ret = i915_gem_suspend(dev);
+       if (ret) {
+               DRM_ERROR("failed to idle hardware: %d\n", ret);
+               return ret;
+       }
+
+       intel_fini_runtime_pm(dev_priv);
+
        intel_gpu_ips_teardown();
 
-       if (HAS_POWER_WELL(dev)) {
-               /* The i915.ko module is still not prepared to be loaded when
-                * the power well is not enabled, so just enable it in case
-                * we're going to unload/reload. */
-               intel_display_set_init_power(dev, true);
-               intel_power_domains_remove(dev);
-       }
+       /* The i915.ko module is still not prepared to be loaded when
+        * the power well is not enabled, so just enable it in case
+        * we're going to unload/reload. */
+       intel_display_set_init_power(dev, true);
+       intel_power_domains_remove(dev);
 
        i915_teardown_sysfs(dev);
 
        if (dev_priv->mm.inactive_shrinker.scan_objects)
                unregister_shrinker(&dev_priv->mm.inactive_shrinker);
 
-       ret = i915_gem_suspend(dev);
-       if (ret)
-               DRM_ERROR("failed to idle hardware: %d\n", ret);
-
        io_mapping_free(dev_priv->gtt.mappable);
        arch_phys_wc_del(dev_priv->gtt.mtrr);
 
@@ -1777,7 +1781,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);
 
        drm_vblank_cleanup(dev);
 
@@ -1848,8 +1851,10 @@ void i915_driver_lastclose(struct drm_device * dev)
 
 void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
 {
+       mutex_lock(&dev->struct_mutex);
        i915_gem_context_close(dev, file_priv);
        i915_gem_release(dev, file_priv);
+       mutex_unlock(&dev->struct_mutex);
 }
 
 void i915_driver_postclose(struct drm_device *dev, struct drm_file *file)
@@ -1908,6 +1913,7 @@ const struct drm_ioctl_desc i915_ioctls[] = {
        DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_CREATE, i915_gem_context_create_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_DESTROY, i915_gem_context_destroy_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(I915_REG_READ, i915_reg_read_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(I915_GET_RESET_STATS, i915_get_reset_stats_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
 };
 
 int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
index 989be12cdd6e962e625b8376734f101ace947d1c..a13b8ed3f8390372961a8635ed59d6ed862d7a03 100644 (file)
@@ -114,7 +114,7 @@ MODULE_PARM_DESC(enable_hangcheck,
                "(default: true)");
 
 int i915_enable_ppgtt __read_mostly = -1;
-module_param_named(i915_enable_ppgtt, i915_enable_ppgtt, int, 0600);
+module_param_named(i915_enable_ppgtt, i915_enable_ppgtt, int, 0400);
 MODULE_PARM_DESC(i915_enable_ppgtt,
                "Enable PPGTT (default: true)");
 
@@ -155,7 +155,6 @@ MODULE_PARM_DESC(prefault_disable,
                "Disable page prefaulting for pread/pwrite/reloc (default:false). For developers only.");
 
 static struct drm_driver driver;
-extern int intel_agp_enabled;
 
 static const struct intel_device_info intel_i830_info = {
        .gen = 2, .is_mobile = 1, .cursor_needs_physical = 1, .num_pipes = 2,
@@ -265,6 +264,7 @@ static const struct intel_device_info intel_ironlake_m_info = {
 static const struct intel_device_info intel_sandybridge_d_info = {
        .gen = 6, .num_pipes = 2,
        .need_gfx_hws = 1, .has_hotplug = 1,
+       .has_fbc = 1,
        .ring_mask = RENDER_RING | BSD_RING | BLT_RING,
        .has_llc = 1,
 };
@@ -280,6 +280,7 @@ static const struct intel_device_info intel_sandybridge_m_info = {
 #define GEN7_FEATURES  \
        .gen = 7, .num_pipes = 3, \
        .need_gfx_hws = 1, .has_hotplug = 1, \
+       .has_fbc = 1, \
        .ring_mask = RENDER_RING | BSD_RING | BLT_RING, \
        .has_llc = 1
 
@@ -292,7 +293,6 @@ static const struct intel_device_info intel_ivybridge_m_info = {
        GEN7_FEATURES,
        .is_ivybridge = 1,
        .is_mobile = 1,
-       .has_fbc = 1,
 };
 
 static const struct intel_device_info intel_ivybridge_q_info = {
@@ -307,6 +307,7 @@ static const struct intel_device_info intel_valleyview_m_info = {
        .num_pipes = 2,
        .is_valleyview = 1,
        .display_mmio_offset = VLV_DISPLAY_BASE,
+       .has_fbc = 0, /* legal, last one wins */
        .has_llc = 0, /* legal, last one wins */
 };
 
@@ -315,6 +316,7 @@ static const struct intel_device_info intel_valleyview_d_info = {
        .num_pipes = 2,
        .is_valleyview = 1,
        .display_mmio_offset = VLV_DISPLAY_BASE,
+       .has_fbc = 0, /* legal, last one wins */
        .has_llc = 0, /* legal, last one wins */
 };
 
@@ -332,7 +334,6 @@ static const struct intel_device_info intel_haswell_m_info = {
        .is_mobile = 1,
        .has_ddi = 1,
        .has_fpga_dbg = 1,
-       .has_fbc = 1,
        .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
 };
 
@@ -501,6 +502,8 @@ static int i915_drm_freeze(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_crtc *crtc;
 
+       intel_runtime_pm_get(dev_priv);
+
        /* ignore lid events during suspend */
        mutex_lock(&dev_priv->modeset_restore_lock);
        dev_priv->modeset_restore = MODESET_SUSPENDED;
@@ -534,8 +537,10 @@ static int i915_drm_freeze(struct drm_device *dev)
                 * Disable CRTCs directly since we want to preserve sw state
                 * for _thaw.
                 */
+               mutex_lock(&dev->mode_config.mutex);
                list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
                        dev_priv->display.crtc_disable(crtc);
+               mutex_unlock(&dev->mode_config.mutex);
 
                intel_modeset_suspend_hw(dev);
        }
@@ -649,6 +654,7 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
                intel_modeset_init_hw(dev);
 
                drm_modeset_lock_all(dev);
+               drm_mode_config_reset(dev);
                intel_modeset_setup_hw_state(dev, true);
                drm_modeset_unlock_all(dev);
 
@@ -685,6 +691,8 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
        mutex_lock(&dev_priv->modeset_restore_lock);
        dev_priv->modeset_restore = MODESET_DONE;
        mutex_unlock(&dev_priv->modeset_restore_lock);
+
+       intel_runtime_pm_put(dev_priv);
        return error;
 }
 
@@ -759,14 +767,14 @@ int i915_reset(struct drm_device *dev)
                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");
+                       DRM_INFO("Reset not implemented, but ignoring "
+                                "error for simulated gpu hangs\n");
                        ret = 0;
                }
        }
 
        if (ret) {
-               DRM_ERROR("Failed to reset chip.\n");
+               DRM_ERROR("Failed to reset chip: %i\n", ret);
                mutex_unlock(&dev->struct_mutex);
                return ret;
        }
@@ -787,12 +795,9 @@ int i915_reset(struct drm_device *dev)
         */
        if (drm_core_check_feature(dev, DRIVER_MODESET) ||
                        !dev_priv->ums.mm_suspended) {
-               bool hw_contexts_disabled = dev_priv->hw_contexts_disabled;
                dev_priv->ums.mm_suspended = 0;
 
                ret = i915_gem_init_hw(dev);
-               if (!hw_contexts_disabled && dev_priv->hw_contexts_disabled)
-                       DRM_ERROR("HW contexts didn't survive reset\n");
                mutex_unlock(&dev->struct_mutex);
                if (ret) {
                        DRM_ERROR("Failed hw init on reset %d\n", ret);
@@ -828,17 +833,7 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (PCI_FUNC(pdev->devfn))
                return -ENODEV;
 
-       /* We've managed to ship a kms-enabled ddx that shipped with an XvMC
-        * implementation for gen3 (and only gen3) that used legacy drm maps
-        * (gasp!) to share buffers between X and the client. Hence we need to
-        * keep around the fake agp stuff for gen3, even when kms is enabled. */
-       if (intel_info->gen != 3) {
-               driver.driver_features &=
-                       ~(DRIVER_USE_AGP | DRIVER_REQUIRE_AGP);
-       } else if (!intel_agp_enabled) {
-               DRM_ERROR("drm/i915 can't work without intel_agp module!\n");
-               return -ENODEV;
-       }
+       driver.driver_features &= ~(DRIVER_USE_AGP | DRIVER_REQUIRE_AGP);
 
        return drm_get_pci_dev(pdev, ent, &driver);
 }
@@ -912,6 +907,38 @@ static int i915_pm_poweroff(struct device *dev)
        return i915_drm_freeze(drm_dev);
 }
 
+static int i915_runtime_suspend(struct device *device)
+{
+       struct pci_dev *pdev = to_pci_dev(device);
+       struct drm_device *dev = pci_get_drvdata(pdev);
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       WARN_ON(!HAS_RUNTIME_PM(dev));
+
+       DRM_DEBUG_KMS("Suspending device\n");
+
+       dev_priv->pm.suspended = true;
+       intel_opregion_notify_adapter(dev, PCI_D3cold);
+
+       return 0;
+}
+
+static int i915_runtime_resume(struct device *device)
+{
+       struct pci_dev *pdev = to_pci_dev(device);
+       struct drm_device *dev = pci_get_drvdata(pdev);
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       WARN_ON(!HAS_RUNTIME_PM(dev));
+
+       DRM_DEBUG_KMS("Resuming device\n");
+
+       intel_opregion_notify_adapter(dev, PCI_D0);
+       dev_priv->pm.suspended = false;
+
+       return 0;
+}
+
 static const struct dev_pm_ops i915_pm_ops = {
        .suspend = i915_pm_suspend,
        .resume = i915_pm_resume,
@@ -919,6 +946,8 @@ static const struct dev_pm_ops i915_pm_ops = {
        .thaw = i915_pm_thaw,
        .poweroff = i915_pm_poweroff,
        .restore = i915_pm_resume,
+       .runtime_suspend = i915_runtime_suspend,
+       .runtime_resume = i915_runtime_resume,
 };
 
 static const struct vm_operations_struct i915_gem_vm_ops = {
@@ -1021,14 +1050,24 @@ static int __init i915_init(void)
                driver.driver_features &= ~DRIVER_MODESET;
 #endif
 
-       if (!(driver.driver_features & DRIVER_MODESET))
+       if (!(driver.driver_features & DRIVER_MODESET)) {
                driver.get_vblank_timestamp = NULL;
+#ifndef CONFIG_DRM_I915_UMS
+               /* Silently fail loading to not upset userspace. */
+               return 0;
+#endif
+       }
 
        return drm_pci_init(&driver, &i915_pci_driver);
 }
 
 static void __exit i915_exit(void)
 {
+#ifndef CONFIG_DRM_I915_UMS
+       if (!(driver.driver_features & DRIVER_MODESET))
+               return; /* Never loaded a driver. */
+#endif
+
        drm_pci_exit(&driver, &i915_pci_driver);
 }
 
index ccdbecca070d2340919d5499f80824ddb84db4ac..46072b98a28470ac7c0dbd4f2b3a534a52be9e27 100644 (file)
@@ -89,6 +89,18 @@ enum port {
 };
 #define port_name(p) ((p) + 'A')
 
+#define I915_NUM_PHYS_VLV 1
+
+enum dpio_channel {
+       DPIO_CH0,
+       DPIO_CH1
+};
+
+enum dpio_phy {
+       DPIO_PHY0,
+       DPIO_PHY1
+};
+
 enum intel_display_power_domain {
        POWER_DOMAIN_PIPE_A,
        POWER_DOMAIN_PIPE_B,
@@ -101,6 +113,7 @@ enum intel_display_power_domain {
        POWER_DOMAIN_TRANSCODER_C,
        POWER_DOMAIN_TRANSCODER_EDP,
        POWER_DOMAIN_VGA,
+       POWER_DOMAIN_AUDIO,
        POWER_DOMAIN_INIT,
 
        POWER_DOMAIN_NUM,
@@ -310,7 +323,7 @@ struct drm_i915_error_state {
        u32 instps[I915_NUM_RINGS];
        u32 extra_instdone[I915_NUM_INSTDONE_REG];
        u32 seqno[I915_NUM_RINGS];
-       u64 bbaddr;
+       u64 bbaddr[I915_NUM_RINGS];
        u32 fault_reg[I915_NUM_RINGS];
        u32 done_reg;
        u32 faddr[I915_NUM_RINGS];
@@ -351,6 +364,7 @@ struct drm_i915_error_state {
        enum intel_ring_hangcheck_action hangcheck_action[I915_NUM_RINGS];
 };
 
+struct intel_connector;
 struct intel_crtc_config;
 struct intel_crtc;
 struct intel_limit;
@@ -413,11 +427,20 @@ struct drm_i915_display_funcs {
        /* render clock increase/decrease */
        /* display clock increase/decrease */
        /* pll clock increase/decrease */
+
+       int (*setup_backlight)(struct intel_connector *connector);
+       uint32_t (*get_backlight)(struct intel_connector *connector);
+       void (*set_backlight)(struct intel_connector *connector,
+                             uint32_t level);
+       void (*disable_backlight)(struct intel_connector *connector);
+       void (*enable_backlight)(struct intel_connector *connector);
 };
 
 struct intel_uncore_funcs {
-       void (*force_wake_get)(struct drm_i915_private *dev_priv);
-       void (*force_wake_put)(struct drm_i915_private *dev_priv);
+       void (*force_wake_get)(struct drm_i915_private *dev_priv,
+                                                       int fw_engine);
+       void (*force_wake_put)(struct drm_i915_private *dev_priv,
+                                                       int fw_engine);
 
        uint8_t  (*mmio_readb)(struct drm_i915_private *dev_priv, off_t offset, bool trace);
        uint16_t (*mmio_readw)(struct drm_i915_private *dev_priv, off_t offset, bool trace);
@@ -442,6 +465,9 @@ struct intel_uncore {
        unsigned fifo_count;
        unsigned forcewake_count;
 
+       unsigned fw_rendercount;
+       unsigned fw_mediacount;
+
        struct delayed_work force_wake_work;
 };
 
@@ -708,7 +734,6 @@ enum intel_sbi_destination {
 #define QUIRK_PIPEA_FORCE (1<<0)
 #define QUIRK_LVDS_SSC_DISABLE (1<<1)
 #define QUIRK_INVERT_BRIGHTNESS (1<<2)
-#define QUIRK_NO_PCH_PWM_ENABLE (1<<3)
 
 struct intel_fbdev;
 struct intel_fbc_work;
@@ -761,8 +786,6 @@ struct i915_suspend_saved_registers {
        u32 saveBLC_PWM_CTL;
        u32 saveBLC_PWM_CTL2;
        u32 saveBLC_HIST_CTL_B;
-       u32 saveBLC_PWM_CTL_B;
-       u32 saveBLC_PWM_CTL2_B;
        u32 saveBLC_CPU_PWM_CTL;
        u32 saveBLC_CPU_PWM_CTL2;
        u32 saveFPB0;
@@ -932,21 +955,29 @@ struct intel_ilk_power_mgmt {
 
 /* Power well structure for haswell */
 struct i915_power_well {
+       const char *name;
+       bool always_on;
        /* power well enable/disable usage count */
        int count;
+       unsigned long domains;
+       void *data;
+       void (*set)(struct drm_device *dev, struct i915_power_well *power_well,
+                   bool enable);
+       bool (*is_enabled)(struct drm_device *dev,
+                          struct i915_power_well *power_well);
 };
 
-#define I915_MAX_POWER_WELLS 1
-
 struct i915_power_domains {
        /*
         * Power wells needed for initialization at driver init and suspend
         * time are on. They are kept on until after the first modeset.
         */
        bool init_power_on;
+       int power_well_count;
 
        struct mutex lock;
-       struct i915_power_well power_wells[I915_MAX_POWER_WELLS];
+       int domain_use_count[POWER_DOMAIN_NUM];
+       struct i915_power_well *power_wells;
 };
 
 struct i915_dri1_state {
@@ -1077,34 +1108,30 @@ struct i915_gpu_error {
        unsigned long missed_irq_rings;
 
        /**
-        * State variable and reset counter controlling the reset flow
+        * State variable controlling the reset flow and count
+        *
+        * This is a counter which gets incremented when reset is triggered,
+        * and again when reset has been handled. So odd values (lowest bit set)
+        * means that reset is in progress and even values that
+        * (reset_counter >> 1):th reset was successfully completed.
+        *
+        * If reset is not completed succesfully, the I915_WEDGE bit is
+        * set meaning that hardware is terminally sour and there is no
+        * recovery. All waiters on the reset_queue will be woken when
+        * that happens.
         *
-        * Upper bits are for the reset counter.  This counter is used by the
-        * wait_seqno code to race-free noticed that a reset event happened and
-        * that it needs to restart the entire ioctl (since most likely the
-        * seqno it waited for won't ever signal anytime soon).
+        * This counter is used by the wait_seqno code to notice that reset
+        * event happened and it needs to restart the entire ioctl (since most
+        * likely the seqno it waited for won't ever signal anytime soon).
         *
         * This is important for lock-free wait paths, where no contended lock
         * naturally enforces the correct ordering between the bail-out of the
         * waiter and the gpu reset work code.
-        *
-        * Lowest bit controls the reset state machine: Set means a reset is in
-        * progress. This state will (presuming we don't have any bugs) decay
-        * into either unset (successful reset) or the special WEDGED value (hw
-        * terminally sour). All waiters on the reset_queue will be woken when
-        * that happens.
         */
        atomic_t reset_counter;
 
-       /**
-        * Special values/flags for reset_counter
-        *
-        * Note that the code relies on
-        *      I915_WEDGED & I915_RESET_IN_PROGRESS_FLAG
-        * being true.
-        */
 #define I915_RESET_IN_PROGRESS_FLAG    1
-#define I915_WEDGED                    0xffffffff
+#define I915_WEDGED                    (1 << 31)
 
        /**
         * Waitqueue to signal when the reset has completed. Used by clients
@@ -1262,6 +1289,10 @@ struct i915_package_c8 {
        } regsave;
 };
 
+struct i915_runtime_pm {
+       bool suspended;
+};
+
 enum intel_pipe_crc_source {
        INTEL_PIPE_CRC_SOURCE_NONE,
        INTEL_PIPE_CRC_SOURCE_PLANE1,
@@ -1368,13 +1399,8 @@ typedef struct drm_i915_private {
        struct intel_overlay *overlay;
        unsigned int sprite_scaling_enabled;
 
-       /* backlight */
-       struct {
-               int level;
-               bool enabled;
-               spinlock_t lock; /* bl registers and the above bl fields */
-               struct backlight_device *device;
-       } backlight;
+       /* backlight registers and fields in struct intel_panel */
+       spinlock_t backlight_lock;
 
        /* LVDS info */
        bool no_aux_handshake;
@@ -1426,6 +1452,7 @@ typedef struct drm_i915_private {
        int num_shared_dpll;
        struct intel_shared_dpll shared_dplls[I915_NUM_PLLS];
        struct intel_ddi_plls ddi_plls;
+       int dpio_phy_iosf_port[I915_NUM_PHYS_VLV];
 
        /* Reclocking support */
        bool render_reclock_avail;
@@ -1470,7 +1497,6 @@ typedef struct drm_i915_private {
        struct drm_property *broadcast_rgb_property;
        struct drm_property *force_audio_property;
 
-       bool hw_contexts_disabled;
        uint32_t hw_context_size;
        struct list_head context_list;
 
@@ -1497,6 +1523,8 @@ typedef struct drm_i915_private {
 
        struct i915_package_c8 pc8;
 
+       struct i915_runtime_pm pm;
+
        /* Old dri1 support infrastructure, beware the dragons ya fools entering
         * here! */
        struct i915_dri1_state dri1;
@@ -1755,8 +1783,13 @@ struct drm_i915_file_private {
 #define IS_MOBILE(dev)         (INTEL_INFO(dev)->is_mobile)
 #define IS_HSW_EARLY_SDV(dev)  (IS_HASWELL(dev) && \
                                 ((dev)->pdev->device & 0xFF00) == 0x0C00)
-#define IS_ULT(dev)            (IS_HASWELL(dev) && \
+#define IS_BDW_ULT(dev)                (IS_BROADWELL(dev) && \
+                                (((dev)->pdev->device & 0xf) == 0x2  || \
+                                ((dev)->pdev->device & 0xf) == 0x6 || \
+                                ((dev)->pdev->device & 0xf) == 0xe))
+#define IS_HSW_ULT(dev)                (IS_HASWELL(dev) && \
                                 ((dev)->pdev->device & 0xFF00) == 0x0A00)
+#define IS_ULT(dev)            (IS_HSW_ULT(dev) || IS_BDW_ULT(dev))
 #define IS_HSW_GT3(dev)                (IS_HASWELL(dev) && \
                                 ((dev)->pdev->device & 0x00F0) == 0x0020)
 #define IS_PRELIMINARY_HW(intel_info) ((intel_info)->is_preliminary)
@@ -1813,10 +1846,10 @@ struct drm_i915_file_private {
 #define HAS_IPS(dev)           (IS_ULT(dev) || IS_BROADWELL(dev))
 
 #define HAS_DDI(dev)           (INTEL_INFO(dev)->has_ddi)
-#define HAS_POWER_WELL(dev)    (IS_HASWELL(dev) || IS_BROADWELL(dev))
 #define HAS_FPGA_DBG_UNCLAIMED(dev)    (INTEL_INFO(dev)->has_fpga_dbg)
 #define HAS_PSR(dev)           (IS_HASWELL(dev) || IS_BROADWELL(dev))
 #define HAS_PC8(dev)           (IS_HASWELL(dev)) /* XXX HSW:ULX */
+#define HAS_RUNTIME_PM(dev)    false
 
 #define INTEL_PCH_DEVICE_ID_MASK               0xff00
 #define INTEL_PCH_IBX_DEVICE_ID_TYPE           0x3b00
@@ -1901,14 +1934,11 @@ void i915_queue_hangcheck(struct drm_device *dev);
 void i915_handle_error(struct drm_device *dev, bool wedged);
 
 extern void intel_irq_init(struct drm_device *dev);
-extern void intel_pm_init(struct drm_device *dev);
 extern void intel_hpd_init(struct drm_device *dev);
-extern void intel_pm_init(struct drm_device *dev);
 
 extern void intel_uncore_sanitize(struct drm_device *dev);
 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);
 
@@ -2060,12 +2090,17 @@ int __must_check i915_gem_check_wedge(struct i915_gpu_error *error,
 static inline bool i915_reset_in_progress(struct i915_gpu_error *error)
 {
        return unlikely(atomic_read(&error->reset_counter)
-                       & I915_RESET_IN_PROGRESS_FLAG);
+                       & (I915_RESET_IN_PROGRESS_FLAG | I915_WEDGED));
 }
 
 static inline bool i915_terminally_wedged(struct i915_gpu_error *error)
 {
-       return atomic_read(&error->reset_counter) == I915_WEDGED;
+       return atomic_read(&error->reset_counter) & I915_WEDGED;
+}
+
+static inline u32 i915_reset_count(struct i915_gpu_error *error)
+{
+       return ((atomic_read(&error->reset_counter) & ~I915_WEDGED) + 1) / 2;
 }
 
 void i915_gem_reset(struct drm_device *dev);
@@ -2177,7 +2212,7 @@ i915_gem_obj_ggtt_pin(struct drm_i915_gem_object *obj,
 }
 
 /* i915_gem_context.c */
-void i915_gem_context_init(struct drm_device *dev);
+int __must_check i915_gem_context_init(struct drm_device *dev);
 void i915_gem_context_fini(struct drm_device *dev);
 void i915_gem_context_close(struct drm_device *dev, struct drm_file *file);
 int i915_switch_context(struct intel_ring_buffer *ring,
@@ -2395,6 +2430,8 @@ extern int intel_enable_rc6(const struct drm_device *dev);
 extern bool i915_semaphore_is_enabled(struct drm_device *dev);
 int i915_reg_read_ioctl(struct drm_device *dev, void *data,
                        struct drm_file *file);
+int i915_get_reset_stats_ioctl(struct drm_device *dev, void *data,
+                              struct drm_file *file);
 
 /* overlay */
 extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev);
@@ -2410,8 +2447,8 @@ extern void intel_display_print_error_state(struct drm_i915_error_state_buf *e,
  * must be set to prevent GT core from power down and stale values being
  * returned.
  */
-void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv);
-void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv);
+void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine);
+void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine);
 
 int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u8 mbox, u32 *val);
 int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val);
@@ -2426,6 +2463,8 @@ 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_bunit_read(struct drm_i915_private *dev_priv, u32 reg);
+void vlv_bunit_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);
@@ -2434,9 +2473,30 @@ 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,
                     enum intel_sbi_destination destination);
+u32 vlv_flisdsi_read(struct drm_i915_private *dev_priv, u32 reg);
+void vlv_flisdsi_write(struct drm_i915_private *dev_priv, u32 reg, u32 val);
+
+int vlv_gpu_freq(struct drm_i915_private *dev_priv, int val);
+int vlv_freq_opcode(struct drm_i915_private *dev_priv, int val);
+
+void vlv_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine);
+void vlv_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine);
+
+#define FORCEWAKE_VLV_RENDER_RANGE_OFFSET(reg) \
+       (((reg) >= 0x2000 && (reg) < 0x4000) ||\
+       ((reg) >= 0x5000 && (reg) < 0x8000) ||\
+       ((reg) >= 0xB000 && (reg) < 0x12000) ||\
+       ((reg) >= 0x2E000 && (reg) < 0x30000))
+
+#define FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(reg)\
+       (((reg) >= 0x12000 && (reg) < 0x14000) ||\
+       ((reg) >= 0x22000 && (reg) < 0x24000) ||\
+       ((reg) >= 0x30000 && (reg) < 0x40000))
+
+#define FORCEWAKE_RENDER       (1 << 0)
+#define FORCEWAKE_MEDIA                (1 << 1)
+#define FORCEWAKE_ALL          (FORCEWAKE_RENDER | FORCEWAKE_MEDIA)
 
-int vlv_gpu_freq(int ddr_freq, int val);
-int vlv_freq_opcode(int ddr_freq, int val);
 
 #define I915_READ8(reg)                dev_priv->uncore.funcs.mmio_readb(dev_priv, (reg), true)
 #define I915_WRITE8(reg, val)  dev_priv->uncore.funcs.mmio_writeb(dev_priv, (reg), (val), true)
index 12bbd5eac70db7a22a291dfc5c2e01624803c816..4ecfbf7da23e3588c5abf8cdb1a3f84f716f8aa7 100644 (file)
@@ -1380,6 +1380,8 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
        int ret = 0;
        bool write = !!(vmf->flags & FAULT_FLAG_WRITE);
 
+       intel_runtime_pm_get(dev_priv);
+
        /* We don't use vmf->pgoff since that has the fake offset */
        page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >>
                PAGE_SHIFT;
@@ -1427,8 +1429,10 @@ out:
                /* If this -EIO is due to a gpu hang, give the reset code a
                 * chance to clean up the mess. Otherwise return the proper
                 * SIGBUS. */
-               if (i915_terminally_wedged(&dev_priv->gpu_error))
-                       return VM_FAULT_SIGBUS;
+               if (i915_terminally_wedged(&dev_priv->gpu_error)) {
+                       ret = VM_FAULT_SIGBUS;
+                       break;
+               }
        case -EAGAIN:
                /*
                 * EAGAIN means the gpu is hung and we'll wait for the error
@@ -1443,15 +1447,22 @@ out:
                 * EBUSY is ok: this just means that another thread
                 * already did the job.
                 */
-               return VM_FAULT_NOPAGE;
+               ret = VM_FAULT_NOPAGE;
+               break;
        case -ENOMEM:
-               return VM_FAULT_OOM;
+               ret = VM_FAULT_OOM;
+               break;
        case -ENOSPC:
-               return VM_FAULT_SIGBUS;
+               ret = VM_FAULT_SIGBUS;
+               break;
        default:
                WARN_ONCE(ret, "unhandled error in i915_gem_fault: %i\n", ret);
-               return VM_FAULT_SIGBUS;
+               ret = VM_FAULT_SIGBUS;
+               break;
        }
+
+       intel_runtime_pm_put(dev_priv);
+       return ret;
 }
 
 /**
@@ -2746,7 +2757,6 @@ int i915_vma_unbind(struct i915_vma *vma)
                obj->has_aliasing_ppgtt_mapping = 0;
        }
        i915_gem_gtt_finish_object(obj);
-       i915_gem_object_unpin_pages(obj);
 
        list_del(&vma->mm_list);
        /* Avoid an unnecessary call to unbind on rebind. */
@@ -2754,7 +2764,6 @@ int i915_vma_unbind(struct i915_vma *vma)
                obj->map_and_fenceable = true;
 
        drm_mm_remove_node(&vma->node);
-
        i915_gem_vma_destroy(vma);
 
        /* Since the unbound list is global, only move to that list if
@@ -2762,6 +2771,12 @@ int i915_vma_unbind(struct i915_vma *vma)
        if (list_empty(&obj->vma_list))
                list_move_tail(&obj->global_list, &dev_priv->mm.unbound_list);
 
+       /* And finally now the object is completely decoupled from this vma,
+        * we can drop its hold on the backing storage and allow it to be
+        * reaped by the shrinker.
+        */
+       i915_gem_object_unpin_pages(obj);
+
        return 0;
 }
 
@@ -4165,6 +4180,8 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct i915_vma *vma, *next;
 
+       intel_runtime_pm_get(dev_priv);
+
        trace_i915_gem_object_destroy(obj);
 
        if (obj->phys_obj)
@@ -4209,6 +4226,8 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
 
        kfree(obj->bit_17);
        i915_gem_object_free(obj);
+
+       intel_runtime_pm_put(dev_priv);
 }
 
 struct i915_vma *i915_gem_obj_to_vma(struct drm_i915_gem_object *obj,
@@ -4442,10 +4461,9 @@ 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 (IS_HASWELL(dev))
+               I915_WRITE(MI_PREDICATE_RESULT_2, IS_HSW_GT3(dev) ?
+                          LOWER_SLICE_ENABLED : LOWER_SLICE_DISABLED);
 
        if (HAS_PCH_NOP(dev)) {
                u32 temp = I915_READ(GEN7_MSG_CTL);
@@ -4466,7 +4484,13 @@ i915_gem_init_hw(struct drm_device *dev)
         * XXX: There was some w/a described somewhere suggesting loading
         * contexts before PPGTT.
         */
-       i915_gem_context_init(dev);
+       ret = i915_gem_context_init(dev);
+       if (ret) {
+               i915_gem_cleanup_ringbuffer(dev);
+               DRM_ERROR("Context initialization failed %d\n", ret);
+               return ret;
+       }
+
        if (dev_priv->mm.aliasing_ppgtt) {
                ret = dev_priv->mm.aliasing_ppgtt->enable(dev);
                if (ret) {
index 72a3df32292f79d88d1ba17dc8d620a24ad435ca..e08acaba540269736777a7f7758a88d97f2aa4b6 100644 (file)
@@ -247,36 +247,34 @@ err_destroy:
        return ret;
 }
 
-void i915_gem_context_init(struct drm_device *dev)
+int i915_gem_context_init(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
+       int ret;
 
-       if (!HAS_HW_CONTEXTS(dev)) {
-               dev_priv->hw_contexts_disabled = true;
-               DRM_DEBUG_DRIVER("Disabling HW Contexts; old hardware\n");
-               return;
-       }
+       if (!HAS_HW_CONTEXTS(dev))
+               return 0;
 
        /* If called from reset, or thaw... we've been here already */
-       if (dev_priv->hw_contexts_disabled ||
-           dev_priv->ring[RCS].default_context)
-               return;
+       if (dev_priv->ring[RCS].default_context)
+               return 0;
 
        dev_priv->hw_context_size = round_up(get_context_size(dev), 4096);
 
        if (dev_priv->hw_context_size > (1<<20)) {
-               dev_priv->hw_contexts_disabled = true;
                DRM_DEBUG_DRIVER("Disabling HW Contexts; invalid size\n");
-               return;
+               return -E2BIG;
        }
 
-       if (create_default_context(dev_priv)) {
-               dev_priv->hw_contexts_disabled = true;
-               DRM_DEBUG_DRIVER("Disabling HW Contexts; create failed\n");
-               return;
+       ret = create_default_context(dev_priv);
+       if (ret) {
+               DRM_DEBUG_DRIVER("Disabling HW Contexts; create failed %d\n",
+                                ret);
+               return ret;
        }
 
        DRM_DEBUG_DRIVER("HW context support initialized\n");
+       return 0;
 }
 
 void i915_gem_context_fini(struct drm_device *dev)
@@ -284,7 +282,7 @@ void i915_gem_context_fini(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct i915_hw_context *dctx = dev_priv->ring[RCS].default_context;
 
-       if (dev_priv->hw_contexts_disabled)
+       if (!HAS_HW_CONTEXTS(dev))
                return;
 
        /* The only known way to stop the gpu from accessing the hw context is
@@ -327,16 +325,16 @@ i915_gem_context_get_hang_stats(struct drm_device *dev,
                                struct drm_file *file,
                                u32 id)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_i915_file_private *file_priv = file->driver_priv;
        struct i915_hw_context *ctx;
 
        if (id == DEFAULT_CONTEXT_ID)
                return &file_priv->hang_stats;
 
-       ctx = NULL;
-       if (!dev_priv->hw_contexts_disabled)
-               ctx = i915_gem_context_get(file->driver_priv, id);
+       if (!HAS_HW_CONTEXTS(dev))
+               return ERR_PTR(-ENOENT);
+
+       ctx = i915_gem_context_get(file->driver_priv, id);
        if (ctx == NULL)
                return ERR_PTR(-ENOENT);
 
@@ -347,10 +345,8 @@ void i915_gem_context_close(struct drm_device *dev, struct drm_file *file)
 {
        struct drm_i915_file_private *file_priv = file->driver_priv;
 
-       mutex_lock(&dev->struct_mutex);
        idr_for_each(&file_priv->context_idr, context_idr_cleanup, NULL);
        idr_destroy(&file_priv->context_idr);
-       mutex_unlock(&dev->struct_mutex);
 }
 
 static struct i915_hw_context *
@@ -423,11 +419,21 @@ static int do_switch(struct i915_hw_context *to)
        if (ret)
                return ret;
 
-       /* Clear this page out of any CPU caches for coherent swap-in/out. Note
+       /*
+        * Pin can switch back to the default context if we end up calling into
+        * evict_everything - as a last ditch gtt defrag effort that also
+        * switches to the default context. Hence we need to reload from here.
+        */
+       from = ring->last_context;
+
+       /*
+        * Clear this page out of any CPU caches for coherent swap-in/out. Note
         * that thanks to write = false in this call and us not setting any gpu
         * write domains when putting a context object onto the active list
         * (when switching away from it), this won't block.
-        * XXX: We need a real interface to do this instead of trickery. */
+        *
+        * XXX: We need a real interface to do this instead of trickery.
+        */
        ret = i915_gem_object_set_to_gtt_domain(to->obj, false);
        if (ret) {
                i915_gem_object_unpin(to->obj);
@@ -494,8 +500,6 @@ static int do_switch(struct i915_hw_context *to)
  * @ring: ring for which we'll execute the context switch
  * @file_priv: file_priv associated with the context, may be NULL
  * @id: context id number
- * @seqno: sequence number by which the new context will be switched to
- * @flags:
  *
  * The context life cycle is simple. The context refcount is incremented and
  * decremented by 1 and create and destroy. If the context is in use by the GPU,
@@ -509,7 +513,7 @@ int i915_switch_context(struct intel_ring_buffer *ring,
        struct drm_i915_private *dev_priv = ring->dev->dev_private;
        struct i915_hw_context *to;
 
-       if (dev_priv->hw_contexts_disabled)
+       if (!HAS_HW_CONTEXTS(ring->dev))
                return 0;
 
        WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
@@ -534,7 +538,6 @@ int i915_switch_context(struct intel_ring_buffer *ring,
 int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
                                  struct drm_file *file)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_i915_gem_context_create *args = data;
        struct drm_i915_file_private *file_priv = file->driver_priv;
        struct i915_hw_context *ctx;
@@ -543,7 +546,7 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
        if (!(dev->driver->driver_features & DRIVER_GEM))
                return -ENODEV;
 
-       if (dev_priv->hw_contexts_disabled)
+       if (!HAS_HW_CONTEXTS(dev))
                return -ENODEV;
 
        ret = i915_mutex_lock_interruptible(dev);
index 7d5752fda5f18b7850beeed588a6f1b3a85cd79a..9bb533e0d76234cdc14ec6d9da31a310114080a5 100644 (file)
@@ -125,13 +125,15 @@ static void *i915_gem_dmabuf_vmap(struct dma_buf *dma_buf)
 
        ret = i915_gem_object_get_pages(obj);
        if (ret)
-               goto error;
+               goto err;
+
+       i915_gem_object_pin_pages(obj);
 
        ret = -ENOMEM;
 
        pages = drm_malloc_ab(obj->base.size >> PAGE_SHIFT, sizeof(*pages));
        if (pages == NULL)
-               goto error;
+               goto err_unpin;
 
        i = 0;
        for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0)
@@ -141,15 +143,16 @@ static void *i915_gem_dmabuf_vmap(struct dma_buf *dma_buf)
        drm_free_large(pages);
 
        if (!obj->dma_buf_vmapping)
-               goto error;
+               goto err_unpin;
 
        obj->vmapping_count = 1;
-       i915_gem_object_pin_pages(obj);
 out_unlock:
        mutex_unlock(&dev->struct_mutex);
        return obj->dma_buf_vmapping;
 
-error:
+err_unpin:
+       i915_gem_object_unpin_pages(obj);
+err:
        mutex_unlock(&dev->struct_mutex);
        return ERR_PTR(ret);
 }
index b7376533633d2cd74eeae8442a49588cf1af1cdc..8f3adc7d0dc823bd5e7848f013bda20d1d133cbc 100644 (file)
@@ -88,6 +88,7 @@ i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm,
        } else
                drm_mm_init_scan(&vm->mm, min_size, alignment, cache_level);
 
+search_again:
        /* First see if there is a large enough contiguous idle region... */
        list_for_each_entry(vma, &vm->inactive_list, mm_list) {
                if (mark_free(vma, &unwind_list))
@@ -115,10 +116,17 @@ none:
                list_del_init(&vma->exec_list);
        }
 
-       /* We expect the caller to unpin, evict all and try again, or give up.
-        * So calling i915_gem_evict_vm() is unnecessary.
+       /* Can we unpin some objects such as idle hw contents,
+        * or pending flips?
         */
-       return -ENOSPC;
+       ret = nonblocking ? -ENOSPC : i915_gpu_idle(dev);
+       if (ret)
+               return ret;
+
+       /* Only idle the GPU and repeat the search once */
+       i915_gem_retire_requests(dev);
+       nonblocking = true;
+       goto search_again;
 
 found:
        /* drm_mm doesn't allow any other other operations while
index 885d595e0e02255e30fbff181247b70df1af5363..8d795626a25e2de40bf70f872c4495fb72ebb732 100644 (file)
@@ -33,6 +33,9 @@
 #include "intel_drv.h"
 #include <linux/dma_remapping.h>
 
+#define  __EXEC_OBJECT_HAS_PIN (1<<31)
+#define  __EXEC_OBJECT_HAS_FENCE (1<<30)
+
 struct eb_vmas {
        struct list_head vmas;
        int and;
@@ -43,7 +46,7 @@ struct eb_vmas {
 };
 
 static struct eb_vmas *
-eb_create(struct drm_i915_gem_execbuffer2 *args, struct i915_address_space *vm)
+eb_create(struct drm_i915_gem_execbuffer2 *args)
 {
        struct eb_vmas *eb = NULL;
 
@@ -90,7 +93,7 @@ eb_lookup_vmas(struct eb_vmas *eb,
 {
        struct drm_i915_gem_object *obj;
        struct list_head objects;
-       int i, ret = 0;
+       int i, ret;
 
        INIT_LIST_HEAD(&objects);
        spin_lock(&file->table_lock);
@@ -103,7 +106,7 @@ eb_lookup_vmas(struct eb_vmas *eb,
                        DRM_DEBUG("Invalid object handle %d at index %d\n",
                                   exec[i].handle, i);
                        ret = -ENOENT;
-                       goto out;
+                       goto err;
                }
 
                if (!list_empty(&obj->obj_exec_link)) {
@@ -111,7 +114,7 @@ eb_lookup_vmas(struct eb_vmas *eb,
                        DRM_DEBUG("Object %p [handle %d, index %d] appears more than once in object list\n",
                                   obj, exec[i].handle, i);
                        ret = -EINVAL;
-                       goto out;
+                       goto err;
                }
 
                drm_gem_object_reference(&obj->base);
@@ -120,9 +123,13 @@ eb_lookup_vmas(struct eb_vmas *eb,
        spin_unlock(&file->table_lock);
 
        i = 0;
-       list_for_each_entry(obj, &objects, obj_exec_link) {
+       while (!list_empty(&objects)) {
                struct i915_vma *vma;
 
+               obj = list_first_entry(&objects,
+                                      struct drm_i915_gem_object,
+                                      obj_exec_link);
+
                /*
                 * NOTE: We can leak any vmas created here when something fails
                 * later on. But that's no issue since vma_unbind can deal with
@@ -135,10 +142,12 @@ eb_lookup_vmas(struct eb_vmas *eb,
                if (IS_ERR(vma)) {
                        DRM_DEBUG("Failed to lookup VMA\n");
                        ret = PTR_ERR(vma);
-                       goto out;
+                       goto err;
                }
 
+               /* Transfer ownership from the objects list to the vmas list. */
                list_add_tail(&vma->exec_list, &eb->vmas);
+               list_del_init(&obj->obj_exec_link);
 
                vma->exec_entry = &exec[i];
                if (eb->and < 0) {
@@ -152,16 +161,22 @@ eb_lookup_vmas(struct eb_vmas *eb,
                ++i;
        }
 
+       return 0;
+
 
-out:
+err:
        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);
+               drm_gem_object_unreference(&obj->base);
        }
+       /*
+        * Objects already transfered to the vmas list will be unreferenced by
+        * eb_destroy.
+        */
+
        return ret;
 }
 
@@ -187,7 +202,28 @@ static struct i915_vma *eb_get_vma(struct eb_vmas *eb, unsigned long handle)
        }
 }
 
-static void eb_destroy(struct eb_vmas *eb) {
+static void
+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 (!drm_mm_node_allocated(&vma->node))
+               return;
+
+       entry = vma->exec_entry;
+
+       if (entry->flags & __EXEC_OBJECT_HAS_FENCE)
+               i915_gem_object_unpin_fence(obj);
+
+       if (entry->flags & __EXEC_OBJECT_HAS_PIN)
+               i915_gem_object_unpin(obj);
+
+       entry->flags &= ~(__EXEC_OBJECT_HAS_FENCE | __EXEC_OBJECT_HAS_PIN);
+}
+
+static void eb_destroy(struct eb_vmas *eb)
+{
        while (!list_empty(&eb->vmas)) {
                struct i915_vma *vma;
 
@@ -195,6 +231,7 @@ static void eb_destroy(struct eb_vmas *eb) {
                                       struct i915_vma,
                                       exec_list);
                list_del_init(&vma->exec_list);
+               i915_gem_execbuffer_unreserve_vma(vma);
                drm_gem_object_unreference(&vma->obj->base);
        }
        kfree(eb);
@@ -307,7 +344,7 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
        target_i915_obj = target_vma->obj;
        target_obj = &target_vma->obj->base;
 
-       target_offset = i915_gem_obj_ggtt_offset(target_i915_obj);
+       target_offset = target_vma->node.start;
 
        /* Sandybridge PPGTT errata: We need a global gtt mapping for MI and
         * pipe_control writes because the gpu doesn't properly redirect them
@@ -454,8 +491,7 @@ i915_gem_execbuffer_relocate_vma_slow(struct i915_vma *vma,
 }
 
 static int
-i915_gem_execbuffer_relocate(struct eb_vmas *eb,
-                            struct i915_address_space *vm)
+i915_gem_execbuffer_relocate(struct eb_vmas *eb)
 {
        struct i915_vma *vma;
        int ret = 0;
@@ -478,9 +514,6 @@ i915_gem_execbuffer_relocate(struct eb_vmas *eb,
        return ret;
 }
 
-#define  __EXEC_OBJECT_HAS_PIN (1<<31)
-#define  __EXEC_OBJECT_HAS_FENCE (1<<30)
-
 static int
 need_reloc_mappable(struct i915_vma *vma)
 {
@@ -552,26 +585,6 @@ i915_gem_execbuffer_reserve_vma(struct i915_vma *vma,
        return 0;
 }
 
-static void
-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 (!drm_mm_node_allocated(&vma->node))
-               return;
-
-       entry = vma->exec_entry;
-
-       if (entry->flags & __EXEC_OBJECT_HAS_FENCE)
-               i915_gem_object_unpin_fence(obj);
-
-       if (entry->flags & __EXEC_OBJECT_HAS_PIN)
-               i915_gem_object_unpin(obj);
-
-       entry->flags &= ~(__EXEC_OBJECT_HAS_FENCE | __EXEC_OBJECT_HAS_PIN);
-}
-
 static int
 i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
                            struct list_head *vmas,
@@ -670,13 +683,14 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
                                goto err;
                }
 
-err:           /* Decrement pin count for bound objects */
-               list_for_each_entry(vma, vmas, exec_list)
-                       i915_gem_execbuffer_unreserve_vma(vma);
-
+err:
                if (ret != -ENOSPC || retry++)
                        return ret;
 
+               /* Decrement pin count for bound objects */
+               list_for_each_entry(vma, vmas, exec_list)
+                       i915_gem_execbuffer_unreserve_vma(vma);
+
                ret = i915_gem_evict_vm(vm, true);
                if (ret)
                        return ret;
@@ -708,6 +722,7 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
        while (!list_empty(&eb->vmas)) {
                vma = list_first_entry(&eb->vmas, struct i915_vma, exec_list);
                list_del_init(&vma->exec_list);
+               i915_gem_execbuffer_unreserve_vma(vma);
                drm_gem_object_unreference(&vma->obj->base);
        }
 
@@ -885,6 +900,24 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec,
        return 0;
 }
 
+static int
+i915_gem_validate_context(struct drm_device *dev, struct drm_file *file,
+                         const u32 ctx_id)
+{
+       struct i915_ctx_hang_stats *hs;
+
+       hs = i915_gem_context_get_hang_stats(dev, file, ctx_id);
+       if (IS_ERR(hs))
+               return PTR_ERR(hs);
+
+       if (hs->banned) {
+               DRM_DEBUG("Context %u tried to submit while banned\n", ctx_id);
+               return -EIO;
+       }
+
+       return 0;
+}
+
 static void
 i915_gem_execbuffer_move_to_active(struct list_head *vmas,
                                   struct intel_ring_buffer *ring)
@@ -964,8 +997,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
        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);
+       const u32 ctx_id = i915_execbuffer2_get_context_id(*args);
        u32 exec_start, exec_len;
        u32 mask, flags;
        int ret, mode, i;
@@ -1092,6 +1124,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
                }
        }
 
+       intel_runtime_pm_get(dev_priv);
+
        ret = i915_mutex_lock_interruptible(dev);
        if (ret)
                goto pre_mutex_err;
@@ -1102,7 +1136,13 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
                goto pre_mutex_err;
        }
 
-       eb = eb_create(args, vm);
+       ret = i915_gem_validate_context(dev, file, ctx_id);
+       if (ret) {
+               mutex_unlock(&dev->struct_mutex);
+               goto pre_mutex_err;
+       }
+
+       eb = eb_create(args);
        if (eb == NULL) {
                mutex_unlock(&dev->struct_mutex);
                ret = -ENOMEM;
@@ -1125,7 +1165,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 
        /* The objects are in their final locations, apply the relocations. */
        if (need_relocs)
-               ret = i915_gem_execbuffer_relocate(eb, vm);
+               ret = i915_gem_execbuffer_relocate(eb);
        if (ret) {
                if (ret == -EFAULT) {
                        ret = i915_gem_execbuffer_relocate_slow(dev, args, file, ring,
@@ -1154,17 +1194,6 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
        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;
@@ -1226,6 +1255,10 @@ err:
 
 pre_mutex_err:
        kfree(cliprects);
+
+       /* intel_gpu_busy should also get a ref, so it will free when the device
+        * is really idle. */
+       intel_runtime_pm_put(dev_priv);
        return ret;
 }
 
index 3620a1b0a73cbcea019cbd5503250410e51f2807..a54eaabb3a3e9a5e25e6f15437e000768709b38d 100644 (file)
@@ -57,7 +57,9 @@ typedef gen8_gtt_pte_t gen8_ppgtt_pde_t;
 #define HSW_WB_LLC_AGE3                        HSW_CACHEABILITY_CONTROL(0x2)
 #define HSW_WB_LLC_AGE0                        HSW_CACHEABILITY_CONTROL(0x3)
 #define HSW_WB_ELLC_LLC_AGE0           HSW_CACHEABILITY_CONTROL(0xb)
+#define HSW_WB_ELLC_LLC_AGE3           HSW_CACHEABILITY_CONTROL(0x8)
 #define HSW_WT_ELLC_LLC_AGE0           HSW_CACHEABILITY_CONTROL(0x6)
+#define HSW_WT_ELLC_LLC_AGE3           HSW_CACHEABILITY_CONTROL(0x7)
 
 #define GEN8_PTES_PER_PAGE             (PAGE_SIZE / sizeof(gen8_gtt_pte_t))
 #define GEN8_PDES_PER_PAGE             (PAGE_SIZE / sizeof(gen8_ppgtt_pde_t))
@@ -185,10 +187,10 @@ static gen6_gtt_pte_t iris_pte_encode(dma_addr_t addr,
        case I915_CACHE_NONE:
                break;
        case I915_CACHE_WT:
-               pte |= HSW_WT_ELLC_LLC_AGE0;
+               pte |= HSW_WT_ELLC_LLC_AGE3;
                break;
        default:
-               pte |= HSW_WB_ELLC_LLC_AGE0;
+               pte |= HSW_WB_ELLC_LLC_AGE3;
                break;
        }
 
@@ -238,10 +240,16 @@ static int gen8_ppgtt_enable(struct drm_device *dev)
                for_each_ring(ring, dev_priv, j) {
                        ret = gen8_write_pdp(ring, i, addr);
                        if (ret)
-                               return ret;
+                               goto err_out;
                }
        }
        return 0;
+
+err_out:
+       for_each_ring(ring, dev_priv, j)
+               I915_WRITE(RING_MODE_GEN7(ring),
+                          _MASKED_BIT_DISABLE(GFX_PPGTT_ENABLE));
+       return ret;
 }
 
 static void gen8_ppgtt_clear_range(struct i915_address_space *vm,
@@ -316,6 +324,8 @@ static void gen8_ppgtt_cleanup(struct i915_address_space *vm)
                container_of(vm, struct i915_hw_ppgtt, base);
        int i, j;
 
+       drm_mm_takedown(&vm->mm);
+
        for (i = 0; i < ppgtt->num_pd_pages ; i++) {
                if (ppgtt->pd_dma_addr[i]) {
                        pci_unmap_page(ppgtt->base.dev->pdev,
@@ -335,8 +345,8 @@ static void gen8_ppgtt_cleanup(struct i915_address_space *vm)
                kfree(ppgtt->gen8_pt_dma_addr[i]);
        }
 
-       __free_pages(ppgtt->gen8_pt_pages, ppgtt->num_pt_pages << PAGE_SHIFT);
-       __free_pages(ppgtt->pd_pages, ppgtt->num_pd_pages << PAGE_SHIFT);
+       __free_pages(ppgtt->gen8_pt_pages, get_order(ppgtt->num_pt_pages << PAGE_SHIFT));
+       __free_pages(ppgtt->pd_pages, get_order(ppgtt->num_pd_pages << PAGE_SHIFT));
 }
 
 /**
@@ -379,6 +389,8 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt, uint64_t size)
        ppgtt->base.clear_range = gen8_ppgtt_clear_range;
        ppgtt->base.insert_entries = gen8_ppgtt_insert_entries;
        ppgtt->base.cleanup = gen8_ppgtt_cleanup;
+       ppgtt->base.start = 0;
+       ppgtt->base.total = ppgtt->num_pt_pages * GEN8_PTES_PER_PAGE * PAGE_SIZE;
 
        BUG_ON(ppgtt->num_pd_pages > GEN8_LEGACY_PDPS);
 
@@ -630,6 +642,8 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
        ppgtt->base.insert_entries = gen6_ppgtt_insert_entries;
        ppgtt->base.cleanup = gen6_ppgtt_cleanup;
        ppgtt->base.scratch = dev_priv->gtt.base.scratch;
+       ppgtt->base.start = 0;
+       ppgtt->base.total = GEN6_PPGTT_PD_ENTRIES * I915_PPGTT_PT_ENTRIES * PAGE_SIZE;
        ppgtt->pt_pages = kcalloc(ppgtt->num_pd_entries, sizeof(struct page *),
                                  GFP_KERNEL);
        if (!ppgtt->pt_pages)
@@ -1124,7 +1138,6 @@ void i915_gem_setup_global_gtt(struct drm_device *dev,
                if (ret)
                        DRM_DEBUG_KMS("Reservation failed\n");
                obj->has_global_gtt_mapping = 1;
-               list_add(&vma->vma_link, &obj->vma_list);
        }
 
        dev_priv->gtt.base.start = start;
@@ -1239,6 +1252,11 @@ static inline unsigned int gen8_get_total_gtt_size(u16 bdw_gmch_ctl)
        bdw_gmch_ctl &= BDW_GMCH_GGMS_MASK;
        if (bdw_gmch_ctl)
                bdw_gmch_ctl = 1 << bdw_gmch_ctl;
+       if (bdw_gmch_ctl > 4) {
+               WARN_ON(!i915_preliminary_hw_support);
+               return 4<<20;
+       }
+
        return bdw_gmch_ctl << 20;
 }
 
@@ -1395,6 +1413,8 @@ static void gen6_gmch_remove(struct i915_address_space *vm)
 {
 
        struct i915_gtt *gtt = container_of(vm, struct i915_gtt, base);
+
+       drm_mm_takedown(&vm->mm);
        iounmap(gtt->gsm);
        teardown_scratch_page(vm->dev);
 }
index 79dcb8f896c6f34363e6bd62e90f1773bfcf8f0a..a707cca692e442f37f9b1db1b91e14bce388a109 100644 (file)
@@ -247,12 +247,11 @@ static void i915_ring_error_state(struct drm_i915_error_state_buf *m,
        err_printf(m, "  IPEIR: 0x%08x\n", error->ipeir[ring]);
        err_printf(m, "  IPEHR: 0x%08x\n", error->ipehr[ring]);
        err_printf(m, "  INSTDONE: 0x%08x\n", error->instdone[ring]);
-       if (ring == RCS && INTEL_INFO(dev)->gen >= 4)
-               err_printf(m, "  BBADDR: 0x%08llx\n", error->bbaddr);
-       if (INTEL_INFO(dev)->gen >= 4)
+       if (INTEL_INFO(dev)->gen >= 4) {
+               err_printf(m, "  BBADDR: 0x%08llx\n", error->bbaddr[ring]);
                err_printf(m, "  BB_STATE: 0x%08x\n", error->bbstate[ring]);
-       if (INTEL_INFO(dev)->gen >= 4)
                err_printf(m, "  INSTPS: 0x%08x\n", error->instps[ring]);
+       }
        err_printf(m, "  INSTPM: 0x%08x\n", error->instpm[ring]);
        err_printf(m, "  FADDR: 0x%08x\n", error->faddr[ring]);
        if (INTEL_INFO(dev)->gen >= 6) {
@@ -725,8 +724,9 @@ static void i915_record_ring_state(struct drm_device *dev,
                error->ipehr[ring->id] = I915_READ(RING_IPEHR(ring->mmio_base));
                error->instdone[ring->id] = I915_READ(RING_INSTDONE(ring->mmio_base));
                error->instps[ring->id] = I915_READ(RING_INSTPS(ring->mmio_base));
-               if (ring->id == RCS)
-                       error->bbaddr = I915_READ64(BB_ADDR);
+               error->bbaddr[ring->id] = I915_READ(RING_BBADDR(ring->mmio_base));
+               if (INTEL_INFO(dev)->gen >= 8)
+                       error->bbaddr[ring->id] |= (u64) I915_READ(RING_BBADDR_UDW(ring->mmio_base)) << 32;
                error->bbstate[ring->id] = I915_READ(RING_BBSTATE(ring->mmio_base));
        } else {
                error->faddr[ring->id] = I915_READ(DMA_FADD_I8XX);
index 5d1dedc02f159c8b7a21d23a940df9c5bf0c2bd2..1d44c793bdf47cafc7d73cbf5a78b1ed2bd80314 100644 (file)
@@ -600,7 +600,7 @@ static u32 i915_get_vblank_counter(struct drm_device *dev, int pipe)
         * Cook up a vblank counter by also checking the pixel
         * counter against vblank start.
         */
-       return ((high1 << 8) | low) + (pixel >= vbl_start);
+       return (((high1 << 8) | low) + (pixel >= vbl_start)) & 0xffffff;
 }
 
 static u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe)
@@ -1015,10 +1015,8 @@ static void gen6_pm_rps_work(struct work_struct *work)
        /* sysfs frequency interfaces may have snuck in while servicing the
         * interrupt
         */
-       if (new_delay < (int)dev_priv->rps.min_delay)
-               new_delay = dev_priv->rps.min_delay;
-       if (new_delay > (int)dev_priv->rps.max_delay)
-               new_delay = dev_priv->rps.max_delay;
+       new_delay = clamp_t(int, new_delay,
+                           dev_priv->rps.min_delay, dev_priv->rps.max_delay);
        dev_priv->rps.last_adj = new_delay - dev_priv->rps.cur_delay;
 
        if (IS_VALLEYVIEW(dev_priv->dev))
@@ -1474,6 +1472,9 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
 
                        intel_hpd_irq_handler(dev, hotplug_trigger, hpd_status_i915);
 
+                       if (hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X)
+                               dp_aux_irq_handler(dev);
+
                        I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
                        I915_READ(PORT_HOTPLUG_STAT);
                }
@@ -1993,7 +1994,7 @@ static void i915_error_work_func(struct work_struct *work)
                        kobject_uevent_env(&dev->primary->kdev->kobj,
                                           KOBJ_CHANGE, reset_done_event);
                } else {
-                       atomic_set(&error->reset_counter, I915_WEDGED);
+                       atomic_set_mask(I915_WEDGED, &error->reset_counter);
                }
 
                /*
@@ -3138,10 +3139,10 @@ static int i8xx_irq_postinstall(struct drm_device *dev)
  * Returns true when a page flip has completed.
  */
 static bool i8xx_handle_vblank(struct drm_device *dev,
-                              int pipe, u16 iir)
+                              int plane, int pipe, u32 iir)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
-       u16 flip_pending = DISPLAY_PLANE_FLIP_PENDING(pipe);
+       u16 flip_pending = DISPLAY_PLANE_FLIP_PENDING(plane);
 
        if (!drm_handle_vblank(dev, pipe))
                return false;
@@ -3149,7 +3150,7 @@ static bool i8xx_handle_vblank(struct drm_device *dev,
        if ((iir & flip_pending) == 0)
                return false;
 
-       intel_prepare_page_flip(dev, pipe);
+       intel_prepare_page_flip(dev, plane);
 
        /* We detect FlipDone by looking for the change in PendingFlip from '1'
         * to '0' on the following vblank, i.e. IIR has the Pendingflip
@@ -3218,9 +3219,13 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg)
                        notify_ring(dev, &dev_priv->ring[RCS]);
 
                for_each_pipe(pipe) {
+                       int plane = pipe;
+                       if (IS_MOBILE(dev))
+                               plane = !plane;
+
                        if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS &&
-                           i8xx_handle_vblank(dev, pipe, iir))
-                               flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(pipe);
+                           i8xx_handle_vblank(dev, plane, pipe, iir))
+                               flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(plane);
 
                        if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
                                i9xx_pipe_crc_irq_handler(dev, pipe);
@@ -3655,6 +3660,10 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
                        intel_hpd_irq_handler(dev, hotplug_trigger,
                                              IS_G4X(dev) ? hpd_status_gen4 : hpd_status_i915);
 
+                       if (IS_G4X(dev) &&
+                           (hotplug_status & DP_AUX_CHANNEL_MASK_INT_STATUS_G4X))
+                               dp_aux_irq_handler(dev);
+
                        I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
                        I915_READ(PORT_HOTPLUG_STAT);
                }
@@ -3891,8 +3900,8 @@ void hsw_pc8_disable_interrupts(struct drm_device *dev)
        dev_priv->pc8.regsave.gtier = I915_READ(GTIER);
        dev_priv->pc8.regsave.gen6_pmimr = I915_READ(GEN6_PMIMR);
 
-       ironlake_disable_display_irq(dev_priv, ~DE_PCH_EVENT_IVB);
-       ibx_disable_display_interrupt(dev_priv, ~SDE_HOTPLUG_MASK_CPT);
+       ironlake_disable_display_irq(dev_priv, 0xffffffff);
+       ibx_disable_display_interrupt(dev_priv, 0xffffffff);
        ilk_disable_gt_irq(dev_priv, 0xffffffff);
        snb_disable_pm_irq(dev_priv, 0xffffffff);
 
@@ -3906,34 +3915,26 @@ void hsw_pc8_restore_interrupts(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        unsigned long irqflags;
-       uint32_t val, expected;
+       uint32_t val;
 
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
 
        val = I915_READ(DEIMR);
-       expected = ~DE_PCH_EVENT_IVB;
-       WARN(val != expected, "DEIMR is 0x%08x, not 0x%08x\n", val, expected);
+       WARN(val != 0xffffffff, "DEIMR is 0x%08x\n", val);
 
-       val = I915_READ(SDEIMR) & ~SDE_HOTPLUG_MASK_CPT;
-       expected = ~SDE_HOTPLUG_MASK_CPT;
-       WARN(val != expected, "SDEIMR non-HPD bits are 0x%08x, not 0x%08x\n",
-            val, expected);
+       val = I915_READ(SDEIMR);
+       WARN(val != 0xffffffff, "SDEIMR is 0x%08x\n", val);
 
        val = I915_READ(GTIMR);
-       expected = 0xffffffff;
-       WARN(val != expected, "GTIMR is 0x%08x, not 0x%08x\n", val, expected);
+       WARN(val != 0xffffffff, "GTIMR is 0x%08x\n", val);
 
        val = I915_READ(GEN6_PMIMR);
-       expected = 0xffffffff;
-       WARN(val != expected, "GEN6_PMIMR is 0x%08x, not 0x%08x\n", val,
-            expected);
+       WARN(val != 0xffffffff, "GEN6_PMIMR is 0x%08x\n", val);
 
        dev_priv->pc8.irqs_disabled = false;
 
        ironlake_enable_display_irq(dev_priv, ~dev_priv->pc8.regsave.deimr);
-       ibx_enable_display_interrupt(dev_priv,
-                                    ~dev_priv->pc8.regsave.sdeimr &
-                                    ~SDE_HOTPLUG_MASK_CPT);
+       ibx_enable_display_interrupt(dev_priv, ~dev_priv->pc8.regsave.sdeimr);
        ilk_enable_gt_irq(dev_priv, ~dev_priv->pc8.regsave.gtimr);
        snb_enable_pm_irq(dev_priv, ~dev_priv->pc8.regsave.gen6_pmimr);
        I915_WRITE(GTIER, dev_priv->pc8.regsave.gtier);
index f9eafb6ed523a2d0f8fbd2ff981705c644733790..e8cc27cd949413dd8778a2ebc06dedd62ce42b4a 100644 (file)
  */
 #define MI_LOAD_REGISTER_IMM(x)        MI_INSTR(0x22, 2*x-1)
 #define MI_STORE_REGISTER_MEM(x) MI_INSTR(0x24, 2*x-1)
+#define  MI_SRM_LRM_GLOBAL_GTT         (1<<22)
 #define MI_FLUSH_DW            MI_INSTR(0x26, 1) /* for GEN6 */
 #define   MI_FLUSH_DW_STORE_INDEX      (1<<21)
 #define   MI_INVALIDATE_TLB            (1<<18)
 #define   IOSF_BYTE_ENABLES_SHIFT              4
 #define   IOSF_BAR_SHIFT                       1
 #define   IOSF_SB_BUSY                         (1<<0)
+#define   IOSF_PORT_BUNIT                      0x3
 #define   IOSF_PORT_PUNIT                      0x4
 #define   IOSF_PORT_NC                         0x11
 #define   IOSF_PORT_DPIO                       0x12
 #define   IOSF_PORT_CCK                                0x14
 #define   IOSF_PORT_CCU                                0xA9
 #define   IOSF_PORT_GPS_CORE                   0x48
+#define   IOSF_PORT_FLISDSI                    0x1B
 #define VLV_IOSF_DATA                          (VLV_DISPLAY_BASE + 0x2104)
 #define VLV_IOSF_ADDR                          (VLV_DISPLAY_BASE + 0x2108)
 
+/* See configdb bunit SB addr map */
+#define BUNIT_REG_BISOC                                0x11
+
 #define PUNIT_OPCODE_REG_READ                  6
 #define PUNIT_OPCODE_REG_WRITE                 7
 
+#define PUNIT_REG_DSPFREQ                      0x36
+#define   DSPFREQSTAT_SHIFT                    30
+#define   DSPFREQSTAT_MASK                     (0x3 << DSPFREQSTAT_SHIFT)
+#define   DSPFREQGUAR_SHIFT                    14
+#define   DSPFREQGUAR_MASK                     (0x3 << DSPFREQGUAR_SHIFT)
 #define PUNIT_REG_PWRGT_CTRL                   0x60
 #define PUNIT_REG_PWRGT_STATUS                 0x61
 #define          PUNIT_CLK_GATE                        1
 #define  DSI_PLL_N1_DIV_MASK                   (3 << 16)
 #define  DSI_PLL_M1_DIV_SHIFT                  0
 #define  DSI_PLL_M1_DIV_MASK                   (0x1ff << 0)
+#define CCK_DISPLAY_CLOCK_CONTROL              0x6b
 
 /*
  * DPIO - a special bus for various display related registers to hide behind
 #define  DPIO_SFR_BYPASS               (1<<1)
 #define  DPIO_CMNRST                   (1<<0)
 
-#define _DPIO_TX3_SWING_CTL4_A         0x690
-#define _DPIO_TX3_SWING_CTL4_B         0x2a90
-#define DPIO_TX3_SWING_CTL4(pipe) _PIPE(pipe, _DPIO_TX3_SWING_CTL4_A, \
-                                       _DPIO_TX3_SWING_CTL4_B)
+#define DPIO_PHY(pipe)                 ((pipe) >> 1)
+#define DPIO_PHY_IOSF_PORT(phy)                (dev_priv->dpio_phy_iosf_port[phy])
 
 /*
  * Per pipe/PLL DPIO regs
  */
-#define _DPIO_DIV_A                    0x800c
+#define _VLV_PLL_DW3_CH0               0x800c
 #define   DPIO_POST_DIV_SHIFT          (28) /* 3 bits */
 #define   DPIO_POST_DIV_DAC            0
 #define   DPIO_POST_DIV_HDMIDP         1 /* DAC 225-400M rate */
 #define   DPIO_ENABLE_CALIBRATION      (1<<11)
 #define   DPIO_M1DIV_SHIFT             (8) /* 3 bits */
 #define   DPIO_M2DIV_MASK              0xff
-#define _DPIO_DIV_B                    0x802c
-#define DPIO_DIV(pipe) _PIPE(pipe, _DPIO_DIV_A, _DPIO_DIV_B)
+#define _VLV_PLL_DW3_CH1               0x802c
+#define VLV_PLL_DW3(ch) _PIPE(ch, _VLV_PLL_DW3_CH0, _VLV_PLL_DW3_CH1)
 
-#define _DPIO_REFSFR_A                 0x8014
+#define _VLV_PLL_DW5_CH0               0x8014
 #define   DPIO_REFSEL_OVERRIDE         27
 #define   DPIO_PLL_MODESEL_SHIFT       24 /* 3 bits */
 #define   DPIO_BIAS_CURRENT_CTL_SHIFT  21 /* 3 bits, always 0x7 */
 #define   DPIO_PLL_REFCLK_SEL_MASK     3
 #define   DPIO_DRIVER_CTL_SHIFT                12 /* always set to 0x8 */
 #define   DPIO_CLK_BIAS_CTL_SHIFT      8 /* always set to 0x5 */
-#define _DPIO_REFSFR_B                 0x8034
-#define DPIO_REFSFR(pipe) _PIPE(pipe, _DPIO_REFSFR_A, _DPIO_REFSFR_B)
+#define _VLV_PLL_DW5_CH1               0x8034
+#define VLV_PLL_DW5(ch) _PIPE(ch, _VLV_PLL_DW5_CH0, _VLV_PLL_DW5_CH1)
 
-#define _DPIO_CORE_CLK_A               0x801c
-#define _DPIO_CORE_CLK_B               0x803c
-#define DPIO_CORE_CLK(pipe) _PIPE(pipe, _DPIO_CORE_CLK_A, _DPIO_CORE_CLK_B)
+#define _VLV_PLL_DW7_CH0               0x801c
+#define _VLV_PLL_DW7_CH1               0x803c
+#define VLV_PLL_DW7(ch) _PIPE(ch, _VLV_PLL_DW7_CH0, _VLV_PLL_DW7_CH1)
 
-#define _DPIO_IREF_CTL_A               0x8040
-#define _DPIO_IREF_CTL_B               0x8060
-#define DPIO_IREF_CTL(pipe) _PIPE(pipe, _DPIO_IREF_CTL_A, _DPIO_IREF_CTL_B)
+#define _VLV_PLL_DW8_CH0               0x8040
+#define _VLV_PLL_DW8_CH1               0x8060
+#define VLV_PLL_DW8(ch) _PIPE(ch, _VLV_PLL_DW8_CH0, _VLV_PLL_DW8_CH1)
 
-#define DPIO_IREF_BCAST                        0xc044
-#define _DPIO_IREF_A                   0x8044
-#define _DPIO_IREF_B                   0x8064
-#define DPIO_IREF(pipe) _PIPE(pipe, _DPIO_IREF_A, _DPIO_IREF_B)
+#define VLV_PLL_DW9_BCAST              0xc044
+#define _VLV_PLL_DW9_CH0               0x8044
+#define _VLV_PLL_DW9_CH1               0x8064
+#define VLV_PLL_DW9(ch) _PIPE(ch, _VLV_PLL_DW9_CH0, _VLV_PLL_DW9_CH1)
 
-#define _DPIO_PLL_CML_A                        0x804c
-#define _DPIO_PLL_CML_B                        0x806c
-#define DPIO_PLL_CML(pipe) _PIPE(pipe, _DPIO_PLL_CML_A, _DPIO_PLL_CML_B)
+#define _VLV_PLL_DW10_CH0              0x8048
+#define _VLV_PLL_DW10_CH1              0x8068
+#define VLV_PLL_DW10(ch) _PIPE(ch, _VLV_PLL_DW10_CH0, _VLV_PLL_DW10_CH1)
 
-#define _DPIO_LPF_COEFF_A              0x8048
-#define _DPIO_LPF_COEFF_B              0x8068
-#define DPIO_LPF_COEFF(pipe) _PIPE(pipe, _DPIO_LPF_COEFF_A, _DPIO_LPF_COEFF_B)
+#define _VLV_PLL_DW11_CH0              0x804c
+#define _VLV_PLL_DW11_CH1              0x806c
+#define VLV_PLL_DW11(ch) _PIPE(ch, _VLV_PLL_DW11_CH0, _VLV_PLL_DW11_CH1)
 
-#define DPIO_CALIBRATION               0x80ac
+/* Spec for ref block start counts at DW10 */
+#define VLV_REF_DW13                   0x80ac
 
-#define DPIO_FASTCLK_DISABLE           0x8100
+#define VLV_CMN_DW0                    0x8100
 
 /*
  * Per DDI channel DPIO regs
  */
 
-#define _DPIO_PCS_TX_0                 0x8200
-#define _DPIO_PCS_TX_1                 0x8400
+#define _VLV_PCS_DW0_CH0               0x8200
+#define _VLV_PCS_DW0_CH1               0x8400
 #define   DPIO_PCS_TX_LANE2_RESET      (1<<16)
 #define   DPIO_PCS_TX_LANE1_RESET      (1<<7)
-#define DPIO_PCS_TX(port) _PORT(port, _DPIO_PCS_TX_0, _DPIO_PCS_TX_1)
+#define VLV_PCS_DW0(ch) _PORT(ch, _VLV_PCS_DW0_CH0, _VLV_PCS_DW0_CH1)
 
-#define _DPIO_PCS_CLK_0                        0x8204
-#define _DPIO_PCS_CLK_1                        0x8404
+#define _VLV_PCS_DW1_CH0               0x8204
+#define _VLV_PCS_DW1_CH1               0x8404
 #define   DPIO_PCS_CLK_CRI_RXEB_EIOS_EN        (1<<22)
 #define   DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN (1<<21)
 #define   DPIO_PCS_CLK_DATAWIDTH_SHIFT (6)
 #define   DPIO_PCS_CLK_SOFT_RESET      (1<<5)
-#define DPIO_PCS_CLK(port) _PORT(port, _DPIO_PCS_CLK_0, _DPIO_PCS_CLK_1)
-
-#define _DPIO_PCS_CTL_OVR1_A           0x8224
-#define _DPIO_PCS_CTL_OVR1_B           0x8424
-#define DPIO_PCS_CTL_OVER1(port) _PORT(port, _DPIO_PCS_CTL_OVR1_A, \
-                                      _DPIO_PCS_CTL_OVR1_B)
-
-#define _DPIO_PCS_STAGGER0_A           0x822c
-#define _DPIO_PCS_STAGGER0_B           0x842c
-#define DPIO_PCS_STAGGER0(port) _PORT(port, _DPIO_PCS_STAGGER0_A, \
-                                     _DPIO_PCS_STAGGER0_B)
-
-#define _DPIO_PCS_STAGGER1_A           0x8230
-#define _DPIO_PCS_STAGGER1_B           0x8430
-#define DPIO_PCS_STAGGER1(port) _PORT(port, _DPIO_PCS_STAGGER1_A, \
-                                     _DPIO_PCS_STAGGER1_B)
-
-#define _DPIO_PCS_CLOCKBUF0_A          0x8238
-#define _DPIO_PCS_CLOCKBUF0_B          0x8438
-#define DPIO_PCS_CLOCKBUF0(port) _PORT(port, _DPIO_PCS_CLOCKBUF0_A, \
-                                      _DPIO_PCS_CLOCKBUF0_B)
-
-#define _DPIO_PCS_CLOCKBUF8_A          0x825c
-#define _DPIO_PCS_CLOCKBUF8_B          0x845c
-#define DPIO_PCS_CLOCKBUF8(port) _PORT(port, _DPIO_PCS_CLOCKBUF8_A, \
-                                      _DPIO_PCS_CLOCKBUF8_B)
-
-#define _DPIO_TX_SWING_CTL2_A          0x8288
-#define _DPIO_TX_SWING_CTL2_B          0x8488
-#define DPIO_TX_SWING_CTL2(port) _PORT(port, _DPIO_TX_SWING_CTL2_A, \
-                                      _DPIO_TX_SWING_CTL2_B)
-
-#define _DPIO_TX_SWING_CTL3_A          0x828c
-#define _DPIO_TX_SWING_CTL3_B          0x848c
-#define DPIO_TX_SWING_CTL3(port) _PORT(port, _DPIO_TX_SWING_CTL3_A, \
-                                      _DPIO_TX_SWING_CTL3_B)
-
-#define _DPIO_TX_SWING_CTL4_A          0x8290
-#define _DPIO_TX_SWING_CTL4_B          0x8490
-#define DPIO_TX_SWING_CTL4(port) _PORT(port, _DPIO_TX_SWING_CTL4_A, \
-                                      _DPIO_TX_SWING_CTL4_B)
-
-#define _DPIO_TX_OCALINIT_0            0x8294
-#define _DPIO_TX_OCALINIT_1            0x8494
+#define VLV_PCS_DW1(ch) _PORT(ch, _VLV_PCS_DW1_CH0, _VLV_PCS_DW1_CH1)
+
+#define _VLV_PCS_DW8_CH0               0x8220
+#define _VLV_PCS_DW8_CH1               0x8420
+#define VLV_PCS_DW8(ch) _PORT(ch, _VLV_PCS_DW8_CH0, _VLV_PCS_DW8_CH1)
+
+#define _VLV_PCS01_DW8_CH0             0x0220
+#define _VLV_PCS23_DW8_CH0             0x0420
+#define _VLV_PCS01_DW8_CH1             0x2620
+#define _VLV_PCS23_DW8_CH1             0x2820
+#define VLV_PCS01_DW8(port) _PORT(port, _VLV_PCS01_DW8_CH0, _VLV_PCS01_DW8_CH1)
+#define VLV_PCS23_DW8(port) _PORT(port, _VLV_PCS23_DW8_CH0, _VLV_PCS23_DW8_CH1)
+
+#define _VLV_PCS_DW9_CH0               0x8224
+#define _VLV_PCS_DW9_CH1               0x8424
+#define        VLV_PCS_DW9(ch) _PORT(ch, _VLV_PCS_DW9_CH0, _VLV_PCS_DW9_CH1)
+
+#define _VLV_PCS_DW11_CH0              0x822c
+#define _VLV_PCS_DW11_CH1              0x842c
+#define VLV_PCS_DW11(ch) _PORT(ch, _VLV_PCS_DW11_CH0, _VLV_PCS_DW11_CH1)
+
+#define _VLV_PCS_DW12_CH0              0x8230
+#define _VLV_PCS_DW12_CH1              0x8430
+#define VLV_PCS_DW12(ch) _PORT(ch, _VLV_PCS_DW12_CH0, _VLV_PCS_DW12_CH1)
+
+#define _VLV_PCS_DW14_CH0              0x8238
+#define _VLV_PCS_DW14_CH1              0x8438
+#define        VLV_PCS_DW14(ch) _PORT(ch, _VLV_PCS_DW14_CH0, _VLV_PCS_DW14_CH1)
+
+#define _VLV_PCS_DW23_CH0              0x825c
+#define _VLV_PCS_DW23_CH1              0x845c
+#define VLV_PCS_DW23(ch) _PORT(ch, _VLV_PCS_DW23_CH0, _VLV_PCS_DW23_CH1)
+
+#define _VLV_TX_DW2_CH0                        0x8288
+#define _VLV_TX_DW2_CH1                        0x8488
+#define VLV_TX_DW2(ch) _PORT(ch, _VLV_TX_DW2_CH0, _VLV_TX_DW2_CH1)
+
+#define _VLV_TX_DW3_CH0                        0x828c
+#define _VLV_TX_DW3_CH1                        0x848c
+#define VLV_TX_DW3(ch) _PORT(ch, _VLV_TX_DW3_CH0, _VLV_TX_DW3_CH1)
+
+#define _VLV_TX_DW4_CH0                        0x8290
+#define _VLV_TX_DW4_CH1                        0x8490
+#define VLV_TX_DW4(ch) _PORT(ch, _VLV_TX_DW4_CH0, _VLV_TX_DW4_CH1)
+
+#define _VLV_TX3_DW4_CH0               0x690
+#define _VLV_TX3_DW4_CH1               0x2a90
+#define VLV_TX3_DW4(ch) _PORT(ch, _VLV_TX3_DW4_CH0, _VLV_TX3_DW4_CH1)
+
+#define _VLV_TX_DW5_CH0                        0x8294
+#define _VLV_TX_DW5_CH1                        0x8494
 #define   DPIO_TX_OCALINIT_EN          (1<<31)
-#define DPIO_TX_OCALINIT(port) _PORT(port, _DPIO_TX_OCALINIT_0, \
-                                    _DPIO_TX_OCALINIT_1)
-
-#define _DPIO_TX_CTL_0                 0x82ac
-#define _DPIO_TX_CTL_1                 0x84ac
-#define DPIO_TX_CTL(port) _PORT(port, _DPIO_TX_CTL_0, _DPIO_TX_CTL_1)
-
-#define _DPIO_TX_LANE_0                        0x82b8
-#define _DPIO_TX_LANE_1                        0x84b8
-#define DPIO_TX_LANE(port) _PORT(port, _DPIO_TX_LANE_0, _DPIO_TX_LANE_1)
-
-#define _DPIO_DATA_CHANNEL1            0x8220
-#define _DPIO_DATA_CHANNEL2            0x8420
-#define DPIO_DATA_CHANNEL(port) _PORT(port, _DPIO_DATA_CHANNEL1, _DPIO_DATA_CHANNEL2)
-
-#define _DPIO_PORT0_PCS0               0x0220
-#define _DPIO_PORT0_PCS1               0x0420
-#define _DPIO_PORT1_PCS2               0x2620
-#define _DPIO_PORT1_PCS3               0x2820
-#define DPIO_DATA_LANE_A(port) _PORT(port, _DPIO_PORT0_PCS0, _DPIO_PORT1_PCS2)
-#define DPIO_DATA_LANE_B(port) _PORT(port, _DPIO_PORT0_PCS1, _DPIO_PORT1_PCS3)
-#define DPIO_DATA_CHANNEL1              0x8220
-#define DPIO_DATA_CHANNEL2              0x8420
+#define VLV_TX_DW5(ch) _PORT(ch, _VLV_TX_DW5_CH0, _VLV_TX_DW5_CH1)
+
+#define _VLV_TX_DW11_CH0               0x82ac
+#define _VLV_TX_DW11_CH1               0x84ac
+#define VLV_TX_DW11(ch) _PORT(ch, _VLV_TX_DW11_CH0, _VLV_TX_DW11_CH1)
+
+#define _VLV_TX_DW14_CH0               0x82b8
+#define _VLV_TX_DW14_CH1               0x84b8
+#define VLV_TX_DW14(ch) _PORT(ch, _VLV_TX_DW14_CH0, _VLV_TX_DW14_CH1)
 
 /*
  * Fence registers
 #define HWSTAM         0x02098
 #define DMA_FADD_I8XX  0x020d0
 #define RING_BBSTATE(base)     ((base)+0x110)
+#define RING_BBADDR(base)      ((base)+0x140)
+#define RING_BBADDR_UDW(base)  ((base)+0x168) /* gen8+ */
 
 #define ERROR_GEN6     0x040a0
 #define GEN7_ERR_INT   0x44040
 #define   CM0_COLOR_EVICT_DISABLE (1<<3)
 #define   CM0_DEPTH_WRITE_DISABLE (1<<1)
 #define   CM0_RC_OP_FLUSH_DISABLE (1<<0)
-#define BB_ADDR                0x02140 /* 8 bytes */
 #define GFX_FLSH_CNTL  0x02170 /* 915+ only */
 #define GFX_FLSH_CNTL_GEN6     0x101008
 #define   GFX_FLSH_CNTL_EN     (1<<0)
 #define   FBC_CTL_UNCOMPRESSIBLE (1<<14)
 #define   FBC_CTL_C3_IDLE      (1<<13)
 #define   FBC_CTL_STRIDE_SHIFT (5)
-#define   FBC_CTL_FENCENO      (1<<0)
+#define   FBC_CTL_FENCENO_SHIFT        (0)
 #define FBC_COMMAND            0x0320c
 #define   FBC_CMD_COMPRESS     (1<<0)
 #define FBC_STATUS             0x03210
 #define   FBC_STAT_COMPRESSING (1<<31)
 #define   FBC_STAT_COMPRESSED  (1<<30)
 #define   FBC_STAT_MODIFIED    (1<<29)
-#define   FBC_STAT_CURRENT_LINE        (1<<0)
+#define   FBC_STAT_CURRENT_LINE_SHIFT  (0)
 #define FBC_CONTROL2           0x03214
 #define   FBC_CTL_FENCE_DBL    (0<<4)
 #define   FBC_CTL_IDLE_IMM     (0<<2)
 #define   CRT_HOTPLUG_MONITOR_COLOR            (3 << 8)
 #define   CRT_HOTPLUG_MONITOR_MONO             (2 << 8)
 #define   CRT_HOTPLUG_MONITOR_NONE             (0 << 8)
+#define   DP_AUX_CHANNEL_D_INT_STATUS_G4X      (1 << 6)
+#define   DP_AUX_CHANNEL_C_INT_STATUS_G4X      (1 << 5)
+#define   DP_AUX_CHANNEL_B_INT_STATUS_G4X      (1 << 4)
+#define   DP_AUX_CHANNEL_MASK_INT_STATUS_G4X   (1 << 4)
 /* SDVO is different across gen3/4 */
 #define   SDVOC_HOTPLUG_INT_STATUS_G4X         (1 << 3)
 #define   SDVOB_HOTPLUG_INT_STATUS_G4X         (1 << 2)
 
 #define _SPACNTR               (VLV_DISPLAY_BASE + 0x72180)
 #define   SP_ENABLE                    (1<<31)
-#define   SP_GEAMMA_ENABLE             (1<<30)
+#define   SP_GAMMA_ENABLE              (1<<30)
 #define   SP_PIXFORMAT_MASK            (0xf<<26)
 #define   SP_FORMAT_YUV422             (0<<26)
 #define   SP_FORMAT_BGR565             (5<<26)
 #define    FORCEWAKE_MT_ENABLE                 (1<<5)
 
 #define  GTFIFODBG                             0x120000
-#define    GT_FIFO_CPU_ERROR_MASK              7
+#define    GT_FIFO_SBDROPERR                   (1<<6)
+#define    GT_FIFO_BLOBDROPERR                 (1<<5)
+#define    GT_FIFO_SB_READ_ABORTERR            (1<<4)
+#define    GT_FIFO_DROPERR                     (1<<3)
 #define    GT_FIFO_OVFERR                      (1<<2)
 #define    GT_FIFO_IAWRERR                     (1<<1)
 #define    GT_FIFO_IARDERR                     (1<<0)
 
-#define  GT_FIFO_FREE_ENTRIES                  0x120008
+#define  GTFIFOCTL                             0x120008
+#define    GT_FIFO_FREE_ENTRIES_MASK           0x7f
 #define    GT_FIFO_NUM_RESERVED_ENTRIES                20
 
 #define  HSW_IDICR                             0x9008
 #define   GEN6_RC_CTL_RC6_ENABLE               (1<<18)
 #define   GEN6_RC_CTL_RC1e_ENABLE              (1<<20)
 #define   GEN6_RC_CTL_RC7_ENABLE               (1<<22)
+#define   VLV_RC_CTL_CTX_RST_PARALLEL          (1<<24)
 #define   GEN7_RC_CTL_TO_MODE                  (1<<28)
 #define   GEN6_RC_CTL_EI_MODE(x)               ((x)<<27)
 #define   GEN6_RC_CTL_HW_ENABLE                        (1<<31)
index 98790c7cccb1ab0902662e4cc541de9966f2058c..6b8fef7fb3bb94f3aa442c867452637e9dd0919f 100644 (file)
@@ -192,7 +192,6 @@ static void i915_restore_vga(struct drm_device *dev)
 static void i915_save_display(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       unsigned long flags;
 
        /* Display arbitration control */
        if (INTEL_INFO(dev)->gen <= 4)
@@ -203,46 +202,27 @@ static void i915_save_display(struct drm_device *dev)
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                i915_save_display_reg(dev);
 
-       spin_lock_irqsave(&dev_priv->backlight.lock, flags);
-
        /* LVDS state */
        if (HAS_PCH_SPLIT(dev)) {
                dev_priv->regfile.savePP_CONTROL = I915_READ(PCH_PP_CONTROL);
-               dev_priv->regfile.saveBLC_PWM_CTL = I915_READ(BLC_PWM_PCH_CTL1);
-               dev_priv->regfile.saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_PCH_CTL2);
-               dev_priv->regfile.saveBLC_CPU_PWM_CTL = I915_READ(BLC_PWM_CPU_CTL);
-               dev_priv->regfile.saveBLC_CPU_PWM_CTL2 = I915_READ(BLC_PWM_CPU_CTL2);
                if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
                        dev_priv->regfile.saveLVDS = I915_READ(PCH_LVDS);
        } else if (IS_VALLEYVIEW(dev)) {
                dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL);
                dev_priv->regfile.savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS);
 
-               dev_priv->regfile.saveBLC_PWM_CTL =
-                       I915_READ(VLV_BLC_PWM_CTL(PIPE_A));
                dev_priv->regfile.saveBLC_HIST_CTL =
                        I915_READ(VLV_BLC_HIST_CTL(PIPE_A));
-               dev_priv->regfile.saveBLC_PWM_CTL2 =
-                       I915_READ(VLV_BLC_PWM_CTL2(PIPE_A));
-               dev_priv->regfile.saveBLC_PWM_CTL_B =
-                       I915_READ(VLV_BLC_PWM_CTL(PIPE_B));
                dev_priv->regfile.saveBLC_HIST_CTL_B =
                        I915_READ(VLV_BLC_HIST_CTL(PIPE_B));
-               dev_priv->regfile.saveBLC_PWM_CTL2_B =
-                       I915_READ(VLV_BLC_PWM_CTL2(PIPE_B));
        } else {
                dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL);
                dev_priv->regfile.savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS);
-               dev_priv->regfile.saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
                dev_priv->regfile.saveBLC_HIST_CTL = I915_READ(BLC_HIST_CTL);
-               if (INTEL_INFO(dev)->gen >= 4)
-                       dev_priv->regfile.saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2);
                if (IS_MOBILE(dev) && !IS_I830(dev))
                        dev_priv->regfile.saveLVDS = I915_READ(LVDS);
        }
 
-       spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
-
        if (!IS_I830(dev) && !IS_845G(dev) && !HAS_PCH_SPLIT(dev))
                dev_priv->regfile.savePFIT_CONTROL = I915_READ(PFIT_CONTROL);
 
@@ -278,7 +258,6 @@ static void i915_restore_display(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 mask = 0xffffffff;
-       unsigned long flags;
 
        /* Display arbitration */
        if (INTEL_INFO(dev)->gen <= 4)
@@ -287,12 +266,6 @@ static void i915_restore_display(struct drm_device *dev)
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                i915_restore_display_reg(dev);
 
-       spin_lock_irqsave(&dev_priv->backlight.lock, flags);
-
-       /* LVDS state */
-       if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev))
-               I915_WRITE(BLC_PWM_CTL2, dev_priv->regfile.saveBLC_PWM_CTL2);
-
        if (drm_core_check_feature(dev, DRIVER_MODESET))
                mask = ~LVDS_PORT_EN;
 
@@ -305,13 +278,6 @@ static void i915_restore_display(struct drm_device *dev)
                I915_WRITE(PFIT_CONTROL, dev_priv->regfile.savePFIT_CONTROL);
 
        if (HAS_PCH_SPLIT(dev)) {
-               I915_WRITE(BLC_PWM_PCH_CTL1, dev_priv->regfile.saveBLC_PWM_CTL);
-               I915_WRITE(BLC_PWM_PCH_CTL2, dev_priv->regfile.saveBLC_PWM_CTL2);
-               /* NOTE: BLC_PWM_CPU_CTL must be written after BLC_PWM_CPU_CTL2;
-                * otherwise we get blank eDP screen after S3 on some machines
-                */
-               I915_WRITE(BLC_PWM_CPU_CTL2, dev_priv->regfile.saveBLC_CPU_PWM_CTL2);
-               I915_WRITE(BLC_PWM_CPU_CTL, dev_priv->regfile.saveBLC_CPU_PWM_CTL);
                I915_WRITE(PCH_PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS);
                I915_WRITE(PCH_PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS);
                I915_WRITE(PCH_PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR);
@@ -319,21 +285,12 @@ static void i915_restore_display(struct drm_device *dev)
                I915_WRITE(RSTDBYCTL,
                           dev_priv->regfile.saveMCHBAR_RENDER_STANDBY);
        } else if (IS_VALLEYVIEW(dev)) {
-               I915_WRITE(VLV_BLC_PWM_CTL(PIPE_A),
-                          dev_priv->regfile.saveBLC_PWM_CTL);
                I915_WRITE(VLV_BLC_HIST_CTL(PIPE_A),
                           dev_priv->regfile.saveBLC_HIST_CTL);
-               I915_WRITE(VLV_BLC_PWM_CTL2(PIPE_A),
-                          dev_priv->regfile.saveBLC_PWM_CTL2);
-               I915_WRITE(VLV_BLC_PWM_CTL(PIPE_B),
-                          dev_priv->regfile.saveBLC_PWM_CTL);
                I915_WRITE(VLV_BLC_HIST_CTL(PIPE_B),
                           dev_priv->regfile.saveBLC_HIST_CTL);
-               I915_WRITE(VLV_BLC_PWM_CTL2(PIPE_B),
-                          dev_priv->regfile.saveBLC_PWM_CTL2);
        } else {
                I915_WRITE(PFIT_PGM_RATIOS, dev_priv->regfile.savePFIT_PGM_RATIOS);
-               I915_WRITE(BLC_PWM_CTL, dev_priv->regfile.saveBLC_PWM_CTL);
                I915_WRITE(BLC_HIST_CTL, dev_priv->regfile.saveBLC_HIST_CTL);
                I915_WRITE(PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS);
                I915_WRITE(PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS);
@@ -341,8 +298,6 @@ static void i915_restore_display(struct drm_device *dev)
                I915_WRITE(PP_CONTROL, dev_priv->regfile.savePP_CONTROL);
        }
 
-       spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
-
        /* only restore FBC info on the platform that supports FBC*/
        intel_disable_fbc(dev);
        if (I915_HAS_FBC(dev)) {
index cef38fd320a7c5c53c687ca5b67b0d1d3192d615..33bcae314bf86ea5f7a2deafb80625d0382634af 100644 (file)
@@ -40,10 +40,13 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg)
        struct drm_i915_private *dev_priv = dev->dev_private;
        u64 raw_time; /* 32b value may overflow during fixed point math */
        u64 units = 128ULL, div = 100000ULL, bias = 100ULL;
+       u32 ret;
 
        if (!intel_enable_rc6(dev))
                return 0;
 
+       intel_runtime_pm_get(dev_priv);
+
        /* On VLV, residency time is in CZ units rather than 1.28us */
        if (IS_VALLEYVIEW(dev)) {
                u32 clkctl2;
@@ -52,7 +55,8 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg)
                        CLK_CTL2_CZCOUNT_30NS_SHIFT;
                if (!clkctl2) {
                        WARN(!clkctl2, "bogus CZ count value");
-                       return 0;
+                       ret = 0;
+                       goto out;
                }
                units = DIV_ROUND_UP_ULL(30ULL * bias, (u64)clkctl2);
                if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH)
@@ -62,7 +66,11 @@ static u32 calc_residency(struct drm_device *dev, const u32 reg)
        }
 
        raw_time = I915_READ(reg) * units;
-       return DIV_ROUND_UP_ULL(raw_time, div);
+       ret = DIV_ROUND_UP_ULL(raw_time, div);
+
+out:
+       intel_runtime_pm_put(dev_priv);
+       return ret;
 }
 
 static ssize_t
@@ -183,13 +191,13 @@ i915_l3_write(struct file *filp, struct kobject *kobj,
        int slice = (int)(uintptr_t)attr->private;
        int ret;
 
+       if (!HAS_HW_CONTEXTS(drm_dev))
+               return -ENXIO;
+
        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;
@@ -259,7 +267,7 @@ static ssize_t gt_cur_freq_mhz_show(struct device *kdev,
        if (IS_VALLEYVIEW(dev_priv->dev)) {
                u32 freq;
                freq = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
-               ret = vlv_gpu_freq(dev_priv->mem_freq, (freq >> 8) & 0xff);
+               ret = vlv_gpu_freq(dev_priv, (freq >> 8) & 0xff);
        } else {
                ret = dev_priv->rps.cur_delay * GT_FREQUENCY_MULTIPLIER;
        }
@@ -276,8 +284,7 @@ static ssize_t vlv_rpe_freq_mhz_show(struct device *kdev,
        struct drm_i915_private *dev_priv = dev->dev_private;
 
        return snprintf(buf, PAGE_SIZE, "%d\n",
-                       vlv_gpu_freq(dev_priv->mem_freq,
-                                    dev_priv->rps.rpe_delay));
+                       vlv_gpu_freq(dev_priv, dev_priv->rps.rpe_delay));
 }
 
 static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf)
@@ -291,7 +298,7 @@ static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute
 
        mutex_lock(&dev_priv->rps.hw_lock);
        if (IS_VALLEYVIEW(dev_priv->dev))
-               ret = vlv_gpu_freq(dev_priv->mem_freq, dev_priv->rps.max_delay);
+               ret = vlv_gpu_freq(dev_priv, dev_priv->rps.max_delay);
        else
                ret = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER;
        mutex_unlock(&dev_priv->rps.hw_lock);
@@ -318,7 +325,7 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
        mutex_lock(&dev_priv->rps.hw_lock);
 
        if (IS_VALLEYVIEW(dev_priv->dev)) {
-               val = vlv_freq_opcode(dev_priv->mem_freq, val);
+               val = vlv_freq_opcode(dev_priv, val);
 
                hw_max = valleyview_rps_max_freq(dev_priv);
                hw_min = valleyview_rps_min_freq(dev_priv);
@@ -342,15 +349,15 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
                DRM_DEBUG("User requested overclocking to %d\n",
                          val * GT_FREQUENCY_MULTIPLIER);
 
+       dev_priv->rps.max_delay = val;
+
        if (dev_priv->rps.cur_delay > val) {
-               if (IS_VALLEYVIEW(dev_priv->dev))
-                       valleyview_set_rps(dev_priv->dev, val);
+               if (IS_VALLEYVIEW(dev))
+                       valleyview_set_rps(dev, val);
                else
-                       gen6_set_rps(dev_priv->dev, val);
+                       gen6_set_rps(dev, val);
        }
 
-       dev_priv->rps.max_delay = val;
-
        mutex_unlock(&dev_priv->rps.hw_lock);
 
        return count;
@@ -367,7 +374,7 @@ static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute
 
        mutex_lock(&dev_priv->rps.hw_lock);
        if (IS_VALLEYVIEW(dev_priv->dev))
-               ret = vlv_gpu_freq(dev_priv->mem_freq, dev_priv->rps.min_delay);
+               ret = vlv_gpu_freq(dev_priv, dev_priv->rps.min_delay);
        else
                ret = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER;
        mutex_unlock(&dev_priv->rps.hw_lock);
@@ -394,7 +401,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
        mutex_lock(&dev_priv->rps.hw_lock);
 
        if (IS_VALLEYVIEW(dev)) {
-               val = vlv_freq_opcode(dev_priv->mem_freq, val);
+               val = vlv_freq_opcode(dev_priv, val);
 
                hw_max = valleyview_rps_max_freq(dev_priv);
                hw_min = valleyview_rps_min_freq(dev_priv);
@@ -411,15 +418,15 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
                return -EINVAL;
        }
 
+       dev_priv->rps.min_delay = val;
+
        if (dev_priv->rps.cur_delay < val) {
                if (IS_VALLEYVIEW(dev))
                        valleyview_set_rps(dev, val);
                else
-                       gen6_set_rps(dev_priv->dev, val);
+                       gen6_set_rps(dev, val);
        }
 
-       dev_priv->rps.min_delay = val;
-
        mutex_unlock(&dev_priv->rps.hw_lock);
 
        return count;
@@ -449,7 +456,9 @@ static ssize_t gt_rp_mhz_show(struct device *kdev, struct device_attribute *attr
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
+       intel_runtime_pm_get(dev_priv);
        rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
+       intel_runtime_pm_put(dev_priv);
        mutex_unlock(&dev->struct_mutex);
 
        if (attr == &dev_attr_gt_RP0_freq_mhz) {
index 967da4772c449a2be05d16bce648fff9bd19a63e..caa18e855815eaf04a39ecb6eedcc572cf4d6290 100644 (file)
@@ -270,6 +270,18 @@ void i915_save_display_reg(struct drm_device *dev)
        }
        /* FIXME: regfile.save TV & SDVO state */
 
+       /* Backlight */
+       if (HAS_PCH_SPLIT(dev)) {
+               dev_priv->regfile.saveBLC_PWM_CTL = I915_READ(BLC_PWM_PCH_CTL1);
+               dev_priv->regfile.saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_PCH_CTL2);
+               dev_priv->regfile.saveBLC_CPU_PWM_CTL = I915_READ(BLC_PWM_CPU_CTL);
+               dev_priv->regfile.saveBLC_CPU_PWM_CTL2 = I915_READ(BLC_PWM_CPU_CTL2);
+       } else {
+               dev_priv->regfile.saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
+               if (INTEL_INFO(dev)->gen >= 4)
+                       dev_priv->regfile.saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2);
+       }
+
        return;
 }
 
@@ -280,6 +292,21 @@ void i915_restore_display_reg(struct drm_device *dev)
        int dpll_b_reg, fpb0_reg, fpb1_reg;
        int i;
 
+       /* Backlight */
+       if (HAS_PCH_SPLIT(dev)) {
+               I915_WRITE(BLC_PWM_PCH_CTL1, dev_priv->regfile.saveBLC_PWM_CTL);
+               I915_WRITE(BLC_PWM_PCH_CTL2, dev_priv->regfile.saveBLC_PWM_CTL2);
+               /* NOTE: BLC_PWM_CPU_CTL must be written after BLC_PWM_CPU_CTL2;
+                * otherwise we get blank eDP screen after S3 on some machines
+                */
+               I915_WRITE(BLC_PWM_CPU_CTL2, dev_priv->regfile.saveBLC_CPU_PWM_CTL2);
+               I915_WRITE(BLC_PWM_CPU_CTL, dev_priv->regfile.saveBLC_CPU_PWM_CTL);
+       } else {
+               if (INTEL_INFO(dev)->gen >= 4)
+                       I915_WRITE(BLC_PWM_CTL2, dev_priv->regfile.saveBLC_PWM_CTL2);
+               I915_WRITE(BLC_PWM_CTL, dev_priv->regfile.saveBLC_PWM_CTL);
+       }
+
        /* Display port ratios (must be done before clock is set) */
        if (SUPPORTS_INTEGRATED_DP(dev)) {
                I915_WRITE(_PIPEA_DATA_M_G4X, dev_priv->regfile.savePIPEA_GMCH_DATA_M);
index dfff0907f70e53643093c3f6aa8d9258ab8dc5d5..5325b25ccbb4b1b72af10f627f5c7fa82e092d89 100644 (file)
@@ -6,8 +6,6 @@
 #include <linux/pci.h>
 #include <linux/acpi.h>
 #include <linux/vga_switcheroo.h>
-#include <acpi/acpi_drivers.h>
-
 #include <drm/drmP.h>
 #include "i915_drv.h"
 
index e4fba39631a5ae2cd5901f85c73738406ef7cdc9..f88e5079a3f585efdbace1fd2878030e94cfcfaa 100644 (file)
@@ -327,12 +327,12 @@ static int intel_bios_ssc_frequency(struct drm_device *dev,
 {
        switch (INTEL_INFO(dev)->gen) {
        case 2:
-               return alternate ? 66 : 48;
+               return alternate ? 66667 : 48000;
        case 3:
        case 4:
-               return alternate ? 100 : 96;
+               return alternate ? 100000 : 96000;
        default:
-               return alternate ? 100 : 120;
+               return alternate ? 100000 : 120000;
        }
 }
 
@@ -796,7 +796,7 @@ init_vbt_defaults(struct drm_i915_private *dev_priv)
         */
        dev_priv->vbt.lvds_ssc_freq = intel_bios_ssc_frequency(dev,
                        !HAS_PCH_SPLIT(dev));
-       DRM_DEBUG_KMS("Set default to SSC at %dMHz\n", dev_priv->vbt.lvds_ssc_freq);
+       DRM_DEBUG_KMS("Set default to SSC at %d kHz\n", dev_priv->vbt.lvds_ssc_freq);
 
        for (port = PORT_A; port < I915_MAX_PORTS; port++) {
                struct ddi_vbt_port_info *info =
index f580a2b0ddd30f5d4338c7ab61414b6fe8bc62fc..81ed58cb7b31305acc86bd79eaec58225250b520 100644 (file)
@@ -39,7 +39,7 @@ struct vbt_header {
        u8 reserved0;
        u32 bdb_offset;                 /**< from beginning of VBT */
        u32 aim_offset[4];              /**< from beginning of VBT */
-} __attribute__((packed));
+} __packed;
 
 struct bdb_header {
        u8 signature[16];               /**< Always 'BIOS_DATA_BLOCK' */
@@ -65,7 +65,7 @@ struct vbios_data {
        u8 rsvd4; /* popup memory size */
        u8 resize_pci_bios;
        u8 rsvd5; /* is crt already on ddc2 */
-} __attribute__((packed));
+} __packed;
 
 /*
  * There are several types of BIOS data blocks (BDBs), each block has
@@ -142,7 +142,7 @@ struct bdb_general_features {
        u8 dp_ssc_enb:1;        /* PCH attached eDP supports SSC */
        u8 dp_ssc_freq:1;       /* SSC freq for PCH attached eDP */
        u8 rsvd11:3; /* finish byte */
-} __attribute__((packed));
+} __packed;
 
 /* pre-915 */
 #define GPIO_PIN_DVI_LVDS      0x03 /* "DVI/LVDS DDC GPIO pins" */
@@ -225,7 +225,7 @@ struct old_child_dev_config {
        u8  dvo2_wiring;
        u16 extended_type;
        u8  dvo_function;
-} __attribute__((packed));
+} __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,
@@ -238,7 +238,7 @@ struct common_child_dev_config {
        u8 not_common2[2];
        u8 ddc_pin;
        u16 edid_ptr;
-} __attribute__((packed));
+} __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. */
@@ -279,7 +279,7 @@ struct bdb_general_definitions {
         *           sizeof(child_device_config);
         */
        union child_device_config devices[0];
-} __attribute__((packed));
+} __packed;
 
 struct bdb_lvds_options {
        u8 panel_type;
@@ -293,7 +293,7 @@ struct bdb_lvds_options {
        u8 lvds_edid:1;
        u8 rsvd2:1;
        u8 rsvd4;
-} __attribute__((packed));
+} __packed;
 
 /* LFP pointer table contains entries to the struct below */
 struct bdb_lvds_lfp_data_ptr {
@@ -303,12 +303,12 @@ struct bdb_lvds_lfp_data_ptr {
        u8 dvo_table_size;
        u16 panel_pnp_id_offset;
        u8 pnp_table_size;
-} __attribute__((packed));
+} __packed;
 
 struct bdb_lvds_lfp_data_ptrs {
        u8 lvds_entries; /* followed by one or more lvds_data_ptr structs */
        struct bdb_lvds_lfp_data_ptr ptr[16];
-} __attribute__((packed));
+} __packed;
 
 /* LFP data has 3 blocks per entry */
 struct lvds_fp_timing {
@@ -325,7 +325,7 @@ struct lvds_fp_timing {
        u32 pfit_reg;
        u32 pfit_reg_val;
        u16 terminator;
-} __attribute__((packed));
+} __packed;
 
 struct lvds_dvo_timing {
        u16 clock;              /**< In 10khz */
@@ -353,7 +353,7 @@ struct lvds_dvo_timing {
        u8 vsync_positive:1;
        u8 hsync_positive:1;
        u8 rsvd2:1;
-} __attribute__((packed));
+} __packed;
 
 struct lvds_pnp_id {
        u16 mfg_name;
@@ -361,17 +361,17 @@ struct lvds_pnp_id {
        u32 serial;
        u8 mfg_week;
        u8 mfg_year;
-} __attribute__((packed));
+} __packed;
 
 struct bdb_lvds_lfp_data_entry {
        struct lvds_fp_timing fp_timing;
        struct lvds_dvo_timing dvo_timing;
        struct lvds_pnp_id pnp_id;
-} __attribute__((packed));
+} __packed;
 
 struct bdb_lvds_lfp_data {
        struct bdb_lvds_lfp_data_entry data[16];
-} __attribute__((packed));
+} __packed;
 
 struct aimdb_header {
        char signature[16];
@@ -379,12 +379,12 @@ struct aimdb_header {
        u16 aimdb_version;
        u16 aimdb_header_size;
        u16 aimdb_size;
-} __attribute__((packed));
+} __packed;
 
 struct aimdb_block {
        u8 aimdb_id;
        u16 aimdb_size;
-} __attribute__((packed));
+} __packed;
 
 struct vch_panel_data {
        u16 fp_timing_offset;
@@ -395,12 +395,12 @@ struct vch_panel_data {
        u8 text_fitting_size;
        u16 graphics_fitting_offset;
        u8 graphics_fitting_size;
-} __attribute__((packed));
+} __packed;
 
 struct vch_bdb_22 {
        struct aimdb_block aimdb_block;
        struct vch_panel_data panels[16];
-} __attribute__((packed));
+} __packed;
 
 struct bdb_sdvo_lvds_options {
        u8 panel_backlight;
@@ -416,7 +416,7 @@ struct bdb_sdvo_lvds_options {
        u8 panel_misc_bits_2;
        u8 panel_misc_bits_3;
        u8 panel_misc_bits_4;
-} __attribute__((packed));
+} __packed;
 
 
 #define BDB_DRIVER_FEATURE_NO_LVDS             0
@@ -462,7 +462,7 @@ struct bdb_driver_features {
 
        u8 hdmi_termination;
        u8 custom_vbt_version;
-} __attribute__((packed));
+} __packed;
 
 #define EDP_18BPP      0
 #define EDP_24BPP      1
@@ -487,14 +487,14 @@ struct edp_power_seq {
        u16 t9;
        u16 t10;
        u16 t11_t12;
-} __attribute__ ((packed));
+} __packed;
 
 struct edp_link_params {
        u8 rate:4;
        u8 lanes:4;
        u8 preemphasis:4;
        u8 vswing:4;
-} __attribute__ ((packed));
+} __packed;
 
 struct bdb_edp {
        struct edp_power_seq power_seqs[16];
@@ -505,7 +505,7 @@ struct bdb_edp {
        /* ith bit indicates enabled/disabled for (i+1)th panel */
        u16 edp_s3d_feature;
        u16 edp_t3_optimization;
-} __attribute__ ((packed));
+} __packed;
 
 void intel_setup_bios(struct drm_device *dev);
 int intel_parse_bios(struct drm_device *dev);
@@ -733,6 +733,6 @@ struct bdb_mipi {
        u32 hl_switch_cnt;
        u32 lp_byte_clk;
        u32 clk_lane_switch_cnt;
-} __attribute__((packed));
+} __packed;
 
 #endif /* _I830_BIOS_H_ */
index b5b1b9b23adf1b24559e7ffdce658ba37e6bbbab..e2e39e65f10954b8076b3ed01b565f0cb173bb0d 100644 (file)
@@ -222,8 +222,9 @@ static void intel_crt_dpms(struct drm_connector *connector, int mode)
        intel_modeset_check_state(connector->dev);
 }
 
-static int intel_crt_mode_valid(struct drm_connector *connector,
-                               struct drm_display_mode *mode)
+static enum drm_mode_status
+intel_crt_mode_valid(struct drm_connector *connector,
+                    struct drm_display_mode *mode)
 {
        struct drm_device *dev = connector->dev;
 
index 330077bcd0bddb22ecf056766dd88cd7ed70bfaf..3a14d993059de7276905caf541e16b61e03860e1 100644 (file)
@@ -73,7 +73,7 @@ static const u32 hsw_ddi_translations_hdmi[] = {
 };
 
 static const u32 bdw_ddi_translations_edp[] = {
-       0x00FFFFFF, 0x00000012,         /* DP parameters */
+       0x00FFFFFF, 0x00000012,         /* eDP parameters */
        0x00EBAFFF, 0x00020011,
        0x00C71FFF, 0x0006000F,
        0x00FFFFFF, 0x00020011,
@@ -173,7 +173,7 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port)
                ddi_translations = ddi_translations_dp;
                break;
        case PORT_D:
-               if (intel_dpd_is_edp(dev))
+               if (intel_dp_is_edp(dev, PORT_D))
                        ddi_translations = ddi_translations_edp;
                else
                        ddi_translations = ddi_translations_dp;
@@ -713,8 +713,6 @@ bool intel_ddi_pll_mode_set(struct drm_crtc *crtc)
        uint32_t reg, val;
        int clock = intel_crtc->config.port_clock;
 
-       /* TODO: reuse PLLs when possible (compare values) */
-
        intel_ddi_put_crtc_pll(crtc);
 
        if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
@@ -742,31 +740,40 @@ bool intel_ddi_pll_mode_set(struct drm_crtc *crtc)
        } else if (type == INTEL_OUTPUT_HDMI) {
                unsigned p, n2, r2;
 
-               if (plls->wrpll1_refcount == 0) {
+               intel_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p);
+
+               val = WRPLL_PLL_ENABLE | WRPLL_PLL_SELECT_LCPLL_2700 |
+                     WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) |
+                     WRPLL_DIVIDER_POST(p);
+
+               if (val == I915_READ(WRPLL_CTL1)) {
+                       DRM_DEBUG_KMS("Reusing WRPLL 1 on pipe %c\n",
+                                     pipe_name(pipe));
+                       reg = WRPLL_CTL1;
+               } else if (val == I915_READ(WRPLL_CTL2)) {
+                       DRM_DEBUG_KMS("Reusing WRPLL 2 on pipe %c\n",
+                                     pipe_name(pipe));
+                       reg = WRPLL_CTL2;
+               } else if (plls->wrpll1_refcount == 0) {
                        DRM_DEBUG_KMS("Using WRPLL 1 on pipe %c\n",
                                      pipe_name(pipe));
-                       plls->wrpll1_refcount++;
                        reg = WRPLL_CTL1;
-                       intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL1;
                } else if (plls->wrpll2_refcount == 0) {
                        DRM_DEBUG_KMS("Using WRPLL 2 on pipe %c\n",
                                      pipe_name(pipe));
-                       plls->wrpll2_refcount++;
                        reg = WRPLL_CTL2;
-                       intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL2;
                } else {
                        DRM_ERROR("No WRPLLs available!\n");
                        return false;
                }
 
-               WARN(I915_READ(reg) & WRPLL_PLL_ENABLE,
-                    "WRPLL already enabled\n");
-
-               intel_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p);
-
-               val = WRPLL_PLL_ENABLE | WRPLL_PLL_SELECT_LCPLL_2700 |
-                     WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) |
-                     WRPLL_DIVIDER_POST(p);
+               if (reg == WRPLL_CTL1) {
+                       plls->wrpll1_refcount++;
+                       intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL1;
+               } else {
+                       plls->wrpll2_refcount++;
+                       intel_crtc->ddi_pll_sel = PORT_CLK_SEL_WRPLL2;
+               }
 
        } else if (type == INTEL_OUTPUT_ANALOG) {
                if (plls->spll_refcount == 0) {
@@ -1115,9 +1122,7 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
 
        if (type == INTEL_OUTPUT_EDP) {
                struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-               ironlake_edp_panel_vdd_on(intel_dp);
                ironlake_edp_panel_on(intel_dp);
-               ironlake_edp_panel_vdd_off(intel_dp, true);
        }
 
        WARN_ON(intel_crtc->ddi_pll_sel == PORT_CLK_SEL_NONE);
@@ -1125,7 +1130,6 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
 
        if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
                struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-
                intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
                intel_dp_start_link_train(intel_dp);
                intel_dp_complete_link_train(intel_dp);
@@ -1158,9 +1162,10 @@ static void intel_ddi_post_disable(struct intel_encoder *intel_encoder)
        if (wait)
                intel_wait_ddi_buf_idle(dev_priv, port);
 
-       if (type == INTEL_OUTPUT_EDP) {
+       if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
                struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
                ironlake_edp_panel_vdd_on(intel_dp);
+               intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
                ironlake_edp_panel_off(intel_dp);
        }
 
index 7ec8b488bb1d30b6b950a23eecc833b574ab4db0..5c4c3ca5eadea1f13a47bbfa1e31148378733822 100644 (file)
@@ -90,8 +90,8 @@ intel_fdi_link_freq(struct drm_device *dev)
 
 static const intel_limit_t intel_limits_i8xx_dac = {
        .dot = { .min = 25000, .max = 350000 },
-       .vco = { .min = 930000, .max = 1400000 },
-       .n = { .min = 3, .max = 16 },
+       .vco = { .min = 908000, .max = 1512000 },
+       .n = { .min = 2, .max = 16 },
        .m = { .min = 96, .max = 140 },
        .m1 = { .min = 18, .max = 26 },
        .m2 = { .min = 6, .max = 16 },
@@ -103,8 +103,8 @@ static const intel_limit_t intel_limits_i8xx_dac = {
 
 static const intel_limit_t intel_limits_i8xx_dvo = {
        .dot = { .min = 25000, .max = 350000 },
-       .vco = { .min = 930000, .max = 1400000 },
-       .n = { .min = 3, .max = 16 },
+       .vco = { .min = 908000, .max = 1512000 },
+       .n = { .min = 2, .max = 16 },
        .m = { .min = 96, .max = 140 },
        .m1 = { .min = 18, .max = 26 },
        .m2 = { .min = 6, .max = 16 },
@@ -116,8 +116,8 @@ static const intel_limit_t intel_limits_i8xx_dvo = {
 
 static const intel_limit_t intel_limits_i8xx_lvds = {
        .dot = { .min = 25000, .max = 350000 },
-       .vco = { .min = 930000, .max = 1400000 },
-       .n = { .min = 3, .max = 16 },
+       .vco = { .min = 908000, .max = 1512000 },
+       .n = { .min = 2, .max = 16 },
        .m = { .min = 96, .max = 140 },
        .m1 = { .min = 18, .max = 26 },
        .m2 = { .min = 6, .max = 16 },
@@ -329,6 +329,8 @@ static void vlv_clock(int refclk, intel_clock_t *clock)
 {
        clock->m = clock->m1 * clock->m2;
        clock->p = clock->p1 * clock->p2;
+       if (WARN_ON(clock->n == 0 || clock->p == 0))
+               return;
        clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n);
        clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
 }
@@ -430,6 +432,8 @@ static void pineview_clock(int refclk, intel_clock_t *clock)
 {
        clock->m = clock->m2 + 2;
        clock->p = clock->p1 * clock->p2;
+       if (WARN_ON(clock->n == 0 || clock->p == 0))
+               return;
        clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n);
        clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
 }
@@ -443,6 +447,8 @@ static void i9xx_clock(int refclk, intel_clock_t *clock)
 {
        clock->m = i9xx_dpll_compute_m(clock);
        clock->p = clock->p1 * clock->p2;
+       if (WARN_ON(clock->n + 2 == 0 || clock->p == 0))
+               return;
        clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n + 2);
        clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
 }
@@ -748,10 +754,10 @@ enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv,
        return intel_crtc->config.cpu_transcoder;
 }
 
-static void ironlake_wait_for_vblank(struct drm_device *dev, int pipe)
+static void g4x_wait_for_vblank(struct drm_device *dev, int pipe)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 frame, frame_reg = PIPEFRAME(pipe);
+       u32 frame, frame_reg = PIPE_FRMCOUNT_GM45(pipe);
 
        frame = I915_READ(frame_reg);
 
@@ -772,8 +778,8 @@ void intel_wait_for_vblank(struct drm_device *dev, int pipe)
        struct drm_i915_private *dev_priv = dev->dev_private;
        int pipestat_reg = PIPESTAT(pipe);
 
-       if (INTEL_INFO(dev)->gen >= 5) {
-               ironlake_wait_for_vblank(dev, pipe);
+       if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) {
+               g4x_wait_for_vblank(dev, pipe);
                return;
        }
 
@@ -1361,6 +1367,11 @@ static void intel_init_dpio(struct drm_device *dev)
        if (!IS_VALLEYVIEW(dev))
                return;
 
+       /* Enable the CRI clock source so we can get at the display */
+       I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) |
+                  DPLL_INTEGRATED_CRI_CLK_VLV);
+
+       DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO;
        /*
         * From VLV2A0_DP_eDP_DPIO_driver_vbios_notes_10.docx -
         *  6.  De-assert cmn_reset/side_reset. Same as VLV X0.
@@ -1494,18 +1505,25 @@ static void vlv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
        POSTING_READ(DPLL(pipe));
 }
 
-void vlv_wait_port_ready(struct drm_i915_private *dev_priv, int port)
+void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
+               struct intel_digital_port *dport)
 {
        u32 port_mask;
 
-       if (!port)
+       switch (dport->port) {
+       case PORT_B:
                port_mask = DPLL_PORTB_READY_MASK;
-       else
+               break;
+       case PORT_C:
                port_mask = DPLL_PORTC_READY_MASK;
+               break;
+       default:
+               BUG();
+       }
 
        if (wait_for((I915_READ(DPLL(0)) & port_mask) == 0, 1000))
                WARN(1, "timed out waiting for port %c ready: 0x%08x\n",
-                    'B' + port, I915_READ(DPLL(0)));
+                    port_name(dport->port), I915_READ(DPLL(0)));
 }
 
 /**
@@ -2233,7 +2251,12 @@ void intel_display_handle_reset(struct drm_device *dev)
                struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
                mutex_lock(&crtc->mutex);
-               if (intel_crtc->active)
+               /*
+                * FIXME: Once we have proper support for primary planes (and
+                * disabling them without disabling the entire crtc) allow again
+                * a NULL crtc->fb.
+                */
+               if (intel_crtc->active && crtc->fb)
                        dev_priv->display.update_plane(crtc, crtc->fb,
                                                       crtc->x, crtc->y);
                mutex_unlock(&crtc->mutex);
@@ -3910,6 +3933,174 @@ static void i9xx_pfit_enable(struct intel_crtc *crtc)
        I915_WRITE(BCLRPAT(crtc->pipe), 0);
 }
 
+int valleyview_get_vco(struct drm_i915_private *dev_priv)
+{
+       int hpll_freq, vco_freq[] = { 800, 1600, 2000, 2400 };
+
+       /* Obtain SKU information */
+       mutex_lock(&dev_priv->dpio_lock);
+       hpll_freq = vlv_cck_read(dev_priv, CCK_FUSE_REG) &
+               CCK_FUSE_HPLL_FREQ_MASK;
+       mutex_unlock(&dev_priv->dpio_lock);
+
+       return vco_freq[hpll_freq];
+}
+
+/* Adjust CDclk dividers to allow high res or save power if possible */
+static void valleyview_set_cdclk(struct drm_device *dev, int cdclk)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 val, cmd;
+
+       if (cdclk >= 320) /* jump to highest voltage for 400MHz too */
+               cmd = 2;
+       else if (cdclk == 266)
+               cmd = 1;
+       else
+               cmd = 0;
+
+       mutex_lock(&dev_priv->rps.hw_lock);
+       val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ);
+       val &= ~DSPFREQGUAR_MASK;
+       val |= (cmd << DSPFREQGUAR_SHIFT);
+       vlv_punit_write(dev_priv, PUNIT_REG_DSPFREQ, val);
+       if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) &
+                     DSPFREQSTAT_MASK) == (cmd << DSPFREQSTAT_SHIFT),
+                    50)) {
+               DRM_ERROR("timed out waiting for CDclk change\n");
+       }
+       mutex_unlock(&dev_priv->rps.hw_lock);
+
+       if (cdclk == 400) {
+               u32 divider, vco;
+
+               vco = valleyview_get_vco(dev_priv);
+               divider = ((vco << 1) / cdclk) - 1;
+
+               mutex_lock(&dev_priv->dpio_lock);
+               /* adjust cdclk divider */
+               val = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL);
+               val &= ~0xf;
+               val |= divider;
+               vlv_cck_write(dev_priv, CCK_DISPLAY_CLOCK_CONTROL, val);
+               mutex_unlock(&dev_priv->dpio_lock);
+       }
+
+       mutex_lock(&dev_priv->dpio_lock);
+       /* adjust self-refresh exit latency value */
+       val = vlv_bunit_read(dev_priv, BUNIT_REG_BISOC);
+       val &= ~0x7f;
+
+       /*
+        * For high bandwidth configs, we set a higher latency in the bunit
+        * so that the core display fetch happens in time to avoid underruns.
+        */
+       if (cdclk == 400)
+               val |= 4500 / 250; /* 4.5 usec */
+       else
+               val |= 3000 / 250; /* 3.0 usec */
+       vlv_bunit_write(dev_priv, BUNIT_REG_BISOC, val);
+       mutex_unlock(&dev_priv->dpio_lock);
+
+       /* Since we changed the CDclk, we need to update the GMBUSFREQ too */
+       intel_i2c_reset(dev);
+}
+
+static int valleyview_cur_cdclk(struct drm_i915_private *dev_priv)
+{
+       int cur_cdclk, vco;
+       int divider;
+
+       vco = valleyview_get_vco(dev_priv);
+
+       mutex_lock(&dev_priv->dpio_lock);
+       divider = vlv_cck_read(dev_priv, CCK_DISPLAY_CLOCK_CONTROL);
+       mutex_unlock(&dev_priv->dpio_lock);
+
+       divider &= 0xf;
+
+       cur_cdclk = (vco << 1) / (divider + 1);
+
+       return cur_cdclk;
+}
+
+static int valleyview_calc_cdclk(struct drm_i915_private *dev_priv,
+                                int max_pixclk)
+{
+       int cur_cdclk;
+
+       cur_cdclk = valleyview_cur_cdclk(dev_priv);
+
+       /*
+        * Really only a few cases to deal with, as only 4 CDclks are supported:
+        *   200MHz
+        *   267MHz
+        *   320MHz
+        *   400MHz
+        * So we check to see whether we're above 90% of the lower bin and
+        * adjust if needed.
+        */
+       if (max_pixclk > 288000) {
+               return 400;
+       } else if (max_pixclk > 240000) {
+               return 320;
+       } else
+               return 266;
+       /* Looks like the 200MHz CDclk freq doesn't work on some configs */
+}
+
+static int intel_mode_max_pixclk(struct drm_i915_private *dev_priv,
+                                unsigned modeset_pipes,
+                                struct intel_crtc_config *pipe_config)
+{
+       struct drm_device *dev = dev_priv->dev;
+       struct intel_crtc *intel_crtc;
+       int max_pixclk = 0;
+
+       list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
+                           base.head) {
+               if (modeset_pipes & (1 << intel_crtc->pipe))
+                       max_pixclk = max(max_pixclk,
+                                        pipe_config->adjusted_mode.crtc_clock);
+               else if (intel_crtc->base.enabled)
+                       max_pixclk = max(max_pixclk,
+                                        intel_crtc->config.adjusted_mode.crtc_clock);
+       }
+
+       return max_pixclk;
+}
+
+static void valleyview_modeset_global_pipes(struct drm_device *dev,
+                                           unsigned *prepare_pipes,
+                                           unsigned modeset_pipes,
+                                           struct intel_crtc_config *pipe_config)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc;
+       int max_pixclk = intel_mode_max_pixclk(dev_priv, modeset_pipes,
+                                              pipe_config);
+       int cur_cdclk = valleyview_cur_cdclk(dev_priv);
+
+       if (valleyview_calc_cdclk(dev_priv, max_pixclk) == cur_cdclk)
+               return;
+
+       list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
+                           base.head)
+               if (intel_crtc->base.enabled)
+                       *prepare_pipes |= (1 << intel_crtc->pipe);
+}
+
+static void valleyview_modeset_global_resources(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int max_pixclk = intel_mode_max_pixclk(dev_priv, 0, NULL);
+       int cur_cdclk = valleyview_cur_cdclk(dev_priv);
+       int req_cdclk = valleyview_calc_cdclk(dev_priv, max_pixclk);
+
+       if (req_cdclk != cur_cdclk)
+               valleyview_set_cdclk(dev, req_cdclk);
+}
+
 static void valleyview_crtc_enable(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
@@ -4570,9 +4761,8 @@ static int i9xx_get_refclk(struct drm_crtc *crtc, int num_connectors)
                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;
-               DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n",
-                             refclk / 1000);
+               refclk = dev_priv->vbt.lvds_ssc_freq;
+               DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", refclk);
        } else if (!IS_GEN2(dev)) {
                refclk = 96000;
        } else {
@@ -4634,24 +4824,24 @@ static void vlv_pllb_recal_opamp(struct drm_i915_private *dev_priv, enum pipe
         * 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, pipe, DPIO_IREF(1));
+       reg_val = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW9(1));
        reg_val &= 0xffffff00;
        reg_val |= 0x00000030;
-       vlv_dpio_write(dev_priv, pipe, DPIO_IREF(1), reg_val);
+       vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW9(1), reg_val);
 
-       reg_val = vlv_dpio_read(dev_priv, pipe, DPIO_CALIBRATION);
+       reg_val = vlv_dpio_read(dev_priv, pipe, VLV_REF_DW13);
        reg_val &= 0x8cffffff;
        reg_val = 0x8c000000;
-       vlv_dpio_write(dev_priv, pipe, DPIO_CALIBRATION, reg_val);
+       vlv_dpio_write(dev_priv, pipe, VLV_REF_DW13, reg_val);
 
-       reg_val = vlv_dpio_read(dev_priv, pipe, DPIO_IREF(1));
+       reg_val = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW9(1));
        reg_val &= 0xffffff00;
-       vlv_dpio_write(dev_priv, pipe, DPIO_IREF(1), reg_val);
+       vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW9(1), reg_val);
 
-       reg_val = vlv_dpio_read(dev_priv, pipe, DPIO_CALIBRATION);
+       reg_val = vlv_dpio_read(dev_priv, pipe, VLV_REF_DW13);
        reg_val &= 0x00ffffff;
        reg_val |= 0xb0000000;
-       vlv_dpio_write(dev_priv, pipe, DPIO_CALIBRATION, reg_val);
+       vlv_dpio_write(dev_priv, pipe, VLV_REF_DW13, reg_val);
 }
 
 static void intel_pch_transcoder_set_m_n(struct intel_crtc *crtc,
@@ -4720,15 +4910,15 @@ static void vlv_update_pll(struct intel_crtc *crtc)
                vlv_pllb_recal_opamp(dev_priv, pipe);
 
        /* Set up Tx target for periodic Rcomp update */
-       vlv_dpio_write(dev_priv, pipe, DPIO_IREF_BCAST, 0x0100000f);
+       vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW9_BCAST, 0x0100000f);
 
        /* Disable target IRef on PLL */
-       reg_val = vlv_dpio_read(dev_priv, pipe, DPIO_IREF_CTL(pipe));
+       reg_val = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW8(pipe));
        reg_val &= 0x00ffffff;
-       vlv_dpio_write(dev_priv, pipe, DPIO_IREF_CTL(pipe), reg_val);
+       vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW8(pipe), reg_val);
 
        /* Disable fast lock */
-       vlv_dpio_write(dev_priv, pipe, DPIO_FASTCLK_DISABLE, 0x610);
+       vlv_dpio_write(dev_priv, pipe, VLV_CMN_DW0, 0x610);
 
        /* Set idtafcrecal before PLL is enabled */
        mdiv = ((bestm1 << DPIO_M1DIV_SHIFT) | (bestm2 & DPIO_M2DIV_MASK));
@@ -4742,48 +4932,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, pipe, DPIO_DIV(pipe), mdiv);
+       vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW3(pipe), mdiv);
 
        mdiv |= DPIO_ENABLE_CALIBRATION;
-       vlv_dpio_write(dev_priv, pipe, DPIO_DIV(pipe), mdiv);
+       vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW3(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, pipe, DPIO_LPF_COEFF(pipe),
+               vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW10(pipe),
                                 0x009f0003);
        else
-               vlv_dpio_write(dev_priv, pipe, DPIO_LPF_COEFF(pipe),
+               vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW10(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, pipe, DPIO_REFSFR(pipe),
+                       vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe),
                                         0x0df40000);
                else
-                       vlv_dpio_write(dev_priv, pipe, DPIO_REFSFR(pipe),
+                       vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe),
                                         0x0df70000);
        } else { /* HDMI or VGA */
                /* Use bend source */
                if (!pipe)
-                       vlv_dpio_write(dev_priv, pipe, DPIO_REFSFR(pipe),
+                       vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe),
                                         0x0df70000);
                else
-                       vlv_dpio_write(dev_priv, pipe, DPIO_REFSFR(pipe),
+                       vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe),
                                         0x0df40000);
        }
 
-       coreclk = vlv_dpio_read(dev_priv, pipe, DPIO_CORE_CLK(pipe));
+       coreclk = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW7(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, pipe, DPIO_CORE_CLK(pipe), coreclk);
+       vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW7(pipe), coreclk);
 
-       vlv_dpio_write(dev_priv, pipe, DPIO_PLL_CML(pipe), 0x87871000);
+       vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW11(pipe), 0x87871000);
 
        /* Enable DPIO clock input */
        dpll = DPLL_EXT_BUFFER_ENABLE_VLV | DPLL_REFA_CLK_ENABLE_VLV |
@@ -5261,7 +5451,7 @@ static void vlv_crtc_clock_get(struct intel_crtc *crtc,
        int refclk = 100000;
 
        mutex_lock(&dev_priv->dpio_lock);
-       mdiv = vlv_dpio_read(dev_priv, pipe, DPIO_DIV(pipe));
+       mdiv = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW3(pipe));
        mutex_unlock(&dev_priv->dpio_lock);
 
        clock.m1 = (mdiv >> DPIO_M1DIV_SHIFT) & 7;
@@ -5718,9 +5908,9 @@ static int ironlake_get_refclk(struct drm_crtc *crtc)
        }
 
        if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
-               DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n",
+               DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n",
                              dev_priv->vbt.lvds_ssc_freq);
-               return dev_priv->vbt.lvds_ssc_freq * 1000;
+               return dev_priv->vbt.lvds_ssc_freq;
        }
 
        return 120000;
@@ -5815,7 +6005,7 @@ static void intel_set_pipe_csc(struct drm_crtc *crtc)
                uint16_t postoff = 0;
 
                if (intel_crtc->config.limited_color_range)
-                       postoff = (16 * (1 << 13) / 255) & 0x1fff;
+                       postoff = (16 * (1 << 12) / 255) & 0x1fff;
 
                I915_WRITE(PIPE_CSC_POSTOFF_HI(pipe), postoff);
                I915_WRITE(PIPE_CSC_POSTOFF_ME(pipe), postoff);
@@ -5982,7 +6172,7 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc,
        factor = 21;
        if (is_lvds) {
                if ((intel_panel_use_ssc(dev_priv) &&
-                    dev_priv->vbt.lvds_ssc_freq == 100) ||
+                    dev_priv->vbt.lvds_ssc_freq == 100000) ||
                    (HAS_PCH_IBX(dev) && intel_is_dual_link_lvds(dev)))
                        factor = 25;
        } else if (intel_crtc->config.sdvo_tv_clock)
@@ -6303,7 +6493,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
        uint32_t val;
 
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head)
-               WARN(crtc->base.enabled, "CRTC for pipe %c enabled\n",
+               WARN(crtc->active, "CRTC for pipe %c enabled\n",
                     pipe_name(crtc->pipe));
 
        WARN(I915_READ(HSW_PWR_WELL_DRIVER), "Power well on\n");
@@ -6323,7 +6513,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
 
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
        val = I915_READ(DEIMR);
-       WARN((val & ~DE_PCH_EVENT_IVB) != val,
+       WARN((val | DE_PCH_EVENT_IVB) != 0xffffffff,
             "Unexpected DEIMR bits enabled: 0x%x\n", val);
        val = I915_READ(SDEIMR);
        WARN((val | SDE_HOTPLUG_MASK_CPT) != 0xffffffff,
@@ -6402,7 +6592,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
 
        /* Make sure we're not on PC8 state before disabling PC8, otherwise
         * we'll hang the machine! */
-       dev_priv->uncore.funcs.force_wake_get(dev_priv);
+       gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
 
        if (val & LCPLL_POWER_DOWN_ALLOW) {
                val &= ~LCPLL_POWER_DOWN_ALLOW;
@@ -6436,7 +6626,7 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
                        DRM_ERROR("Switching back to LCPLL failed\n");
        }
 
-       dev_priv->uncore.funcs.force_wake_put(dev_priv);
+       gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
 }
 
 void hsw_enable_pc8_work(struct work_struct *__work)
@@ -6447,6 +6637,8 @@ void hsw_enable_pc8_work(struct work_struct *__work)
        struct drm_device *dev = dev_priv->dev;
        uint32_t val;
 
+       WARN_ON(!HAS_PC8(dev));
+
        if (dev_priv->pc8.enabled)
                return;
 
@@ -6463,6 +6655,8 @@ void hsw_enable_pc8_work(struct work_struct *__work)
        lpt_disable_clkout_dp(dev);
        hsw_pc8_disable_interrupts(dev);
        hsw_disable_lcpll(dev_priv, true, true);
+
+       intel_runtime_pm_put(dev_priv);
 }
 
 static void __hsw_enable_package_c8(struct drm_i915_private *dev_priv)
@@ -6492,12 +6686,16 @@ static void __hsw_disable_package_c8(struct drm_i915_private *dev_priv)
        if (dev_priv->pc8.disable_count != 1)
                return;
 
+       WARN_ON(!HAS_PC8(dev));
+
        cancel_delayed_work_sync(&dev_priv->pc8.enable_work);
        if (!dev_priv->pc8.enabled)
                return;
 
        DRM_DEBUG_KMS("Disabling package C8+\n");
 
+       intel_runtime_pm_get(dev_priv);
+
        hsw_restore_lcpll(dev_priv);
        hsw_pc8_restore_interrupts(dev);
        lpt_init_pch_refclk(dev);
@@ -7689,7 +7887,7 @@ static int i9xx_pll_refclk(struct drm_device *dev,
        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;
+               return dev_priv->vbt.lvds_ssc_freq;
        else if (HAS_PCH_SPLIT(dev))
                return 120000;
        else if (!IS_GEN2(dev))
@@ -7752,12 +7950,17 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
                else
                        i9xx_clock(refclk, &clock);
        } else {
-               bool is_lvds = (pipe == 1) && (I915_READ(LVDS) & LVDS_PORT_EN);
+               u32 lvds = I915_READ(LVDS);
+               bool is_lvds = (pipe == 1) && (lvds & LVDS_PORT_EN);
 
                if (is_lvds) {
                        clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >>
                                       DPLL_FPA01_P1_POST_DIV_SHIFT);
-                       clock.p2 = 14;
+
+                       if (lvds & LVDS_CLKB_POWER_UP)
+                               clock.p2 = 7;
+                       else
+                               clock.p2 = 14;
                } else {
                        if (dpll & PLL_P1_DIVIDE_BY_TWO)
                                clock.p1 = 2;
@@ -8354,7 +8557,8 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
                intel_ring_emit(ring, ~(DERRMR_PIPEA_PRI_FLIP_DONE |
                                        DERRMR_PIPEB_PRI_FLIP_DONE |
                                        DERRMR_PIPEC_PRI_FLIP_DONE));
-               intel_ring_emit(ring, MI_STORE_REGISTER_MEM(1));
+               intel_ring_emit(ring, MI_STORE_REGISTER_MEM(1) |
+                               MI_SRM_LRM_GLOBAL_GTT);
                intel_ring_emit(ring, DERRMR);
                intel_ring_emit(ring, ring->scratch.gtt_offset + 256);
        }
@@ -9134,7 +9338,7 @@ intel_pipe_config_compare(struct drm_device *dev,
        if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5)
                PIPE_CONF_CHECK_I(pipe_bpp);
 
-       if (!IS_HASWELL(dev)) {
+       if (!HAS_DDI(dev)) {
                PIPE_CONF_CHECK_CLOCK_FUZZY(adjusted_mode.crtc_clock);
                PIPE_CONF_CHECK_CLOCK_FUZZY(port_clock);
        }
@@ -9401,6 +9605,21 @@ static int __intel_set_mode(struct drm_crtc *crtc,
                                       "[modeset]");
        }
 
+       /*
+        * See if the config requires any additional preparation, e.g.
+        * to adjust global state with pipes off.  We need to do this
+        * here so we can get the modeset_pipe updated config for the new
+        * mode set on this crtc.  For other crtcs we need to use the
+        * adjusted_mode bits in the crtc directly.
+        */
+       if (IS_VALLEYVIEW(dev)) {
+               valleyview_modeset_global_pipes(dev, &prepare_pipes,
+                                               modeset_pipes, pipe_config);
+
+               /* may have added more to prepare_pipes than we should */
+               prepare_pipes &= ~disable_pipes;
+       }
+
        for_each_intel_crtc_masked(dev, disable_pipes, intel_crtc)
                intel_crtc_disable(&intel_crtc->base);
 
@@ -9925,10 +10144,13 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
                intel_crtc->lut_b[i] = i;
        }
 
-       /* Swap pipes & planes for FBC on pre-965 */
+       /*
+        * On gen2/3 only plane A can do fbc, but the panel fitter and lvds port
+        * is hooked to plane B. Hence we want plane A feeding pipe B.
+        */
        intel_crtc->pipe = pipe;
        intel_crtc->plane = pipe;
-       if (IS_MOBILE(dev) && IS_GEN3(dev)) {
+       if (IS_MOBILE(dev) && INTEL_INFO(dev)->gen < 4) {
                DRM_DEBUG_KMS("swapping pipes & planes for FBC\n");
                intel_crtc->plane = !pipe;
        }
@@ -10049,7 +10271,7 @@ static void intel_setup_outputs(struct drm_device *dev)
                        intel_ddi_init(dev, PORT_D);
        } else if (HAS_PCH_SPLIT(dev)) {
                int found;
-               dpd_is_edp = intel_dpd_is_edp(dev);
+               dpd_is_edp = intel_dp_is_edp(dev, PORT_D);
 
                if (has_edp_a(dev))
                        intel_dp_init(dev, DP_A, PORT_A);
@@ -10086,8 +10308,7 @@ static void intel_setup_outputs(struct drm_device *dev)
                        intel_hdmi_init(dev, VLV_DISPLAY_BASE + GEN4_HDMIC,
                                        PORT_C);
                        if (I915_READ(VLV_DISPLAY_BASE + DP_C) & DP_DETECTED)
-                               intel_dp_init(dev, VLV_DISPLAY_BASE + DP_C,
-                                             PORT_C);
+                               intel_dp_init(dev, VLV_DISPLAY_BASE + DP_C, PORT_C);
                }
 
                intel_dsi_init(dev);
@@ -10412,8 +10633,11 @@ static void intel_init_display(struct drm_device *dev)
                }
        } else if (IS_G4X(dev)) {
                dev_priv->display.write_eld = g4x_write_eld;
-       } else if (IS_VALLEYVIEW(dev))
+       } else if (IS_VALLEYVIEW(dev)) {
+               dev_priv->display.modeset_global_resources =
+                       valleyview_modeset_global_resources;
                dev_priv->display.write_eld = ironlake_write_eld;
+       }
 
        /* Default just returns -ENODEV to indicate unsupported */
        dev_priv->display.queue_flip = intel_default_queue_flip;
@@ -10440,6 +10664,8 @@ static void intel_init_display(struct drm_device *dev)
                dev_priv->display.queue_flip = intel_gen7_queue_flip;
                break;
        }
+
+       intel_panel_init_backlight_funcs(dev);
 }
 
 /*
@@ -10476,17 +10702,6 @@ static void quirk_invert_brightness(struct drm_device *dev)
        DRM_INFO("applying inverted panel brightness quirk\n");
 }
 
-/*
- * Some machines (Dell XPS13) suffer broken backlight controls if
- * BLM_PCH_PWM_ENABLE is set.
- */
-static void quirk_no_pcm_pwm_enable(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       dev_priv->quirks |= QUIRK_NO_PCH_PWM_ENABLE;
-       DRM_INFO("applying no-PCH_PWM_ENABLE quirk\n");
-}
-
 struct intel_quirk {
        int device;
        int subsystem_vendor;
@@ -10546,11 +10761,6 @@ static struct intel_quirk intel_quirks[] = {
         * 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 },
-       /* Dell XPS13 HD and XPS13 FHD Ivy Bridge */
-       { 0x0166, 0x1028, 0x058b, quirk_no_pcm_pwm_enable },
 };
 
 static void intel_init_quirks(struct drm_device *dev)
@@ -10594,17 +10804,10 @@ static void i915_disable_vga(struct drm_device *dev)
 
 void intel_modeset_init_hw(struct drm_device *dev)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
        intel_prepare_ddi(dev);
 
        intel_init_clock_gating(dev);
 
-       /* Enable the CRI clock source so we can get at the display */
-       if (IS_VALLEYVIEW(dev))
-               I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) |
-                          DPLL_INTEGRATED_CRI_CLK_VLV);
-
        intel_init_dpio(dev);
 
        mutex_lock(&dev->struct_mutex);
@@ -10870,7 +11073,7 @@ void i915_redisable_vga(struct drm_device *dev)
         * level, just check if the power well is enabled instead of trying to
         * follow the "don't touch the power well if we don't need it" policy
         * the rest of the driver uses. */
-       if (HAS_POWER_WELL(dev) &&
+       if ((IS_HASWELL(dev) || IS_BROADWELL(dev)) &&
            (I915_READ(HSW_PWR_WELL_DRIVER) & HSW_PWR_WELL_STATE_ENABLED) == 0)
                return;
 
@@ -11036,8 +11239,6 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
        }
 
        intel_modeset_check_state(dev);
-
-       drm_mode_config_reset(dev);
 }
 
 void intel_modeset_gem_init(struct drm_device *dev)
@@ -11046,7 +11247,10 @@ void intel_modeset_gem_init(struct drm_device *dev)
 
        intel_setup_overlay(dev);
 
+       drm_modeset_lock_all(dev);
+       drm_mode_config_reset(dev);
        intel_modeset_setup_hw_state(dev, false);
+       drm_modeset_unlock_all(dev);
 }
 
 void intel_modeset_cleanup(struct drm_device *dev)
@@ -11091,12 +11295,11 @@ void intel_modeset_cleanup(struct drm_device *dev)
        /* flush any delayed tasks or pending work */
        flush_scheduled_work();
 
-       /* destroy backlight, if any, before the connectors */
-       intel_panel_destroy_backlight(dev);
-
-       /* destroy the sysfs files before encoders/connectors */
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head)
+       /* destroy the backlight and sysfs files before encoders/connectors */
+       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+               intel_panel_destroy_backlight(connector);
                drm_sysfs_connector_remove(connector);
+       }
 
        drm_mode_config_cleanup(dev);
 
@@ -11150,6 +11353,7 @@ struct intel_display_error_state {
        } cursor[I915_MAX_PIPES];
 
        struct intel_pipe_error_state {
+               bool power_domain_on;
                u32 source;
        } pipe[I915_MAX_PIPES];
 
@@ -11164,6 +11368,7 @@ struct intel_display_error_state {
        } plane[I915_MAX_PIPES];
 
        struct intel_transcoder_error_state {
+               bool power_domain_on;
                enum transcoder cpu_transcoder;
 
                u32 conf;
@@ -11197,11 +11402,13 @@ intel_display_capture_error_state(struct drm_device *dev)
        if (error == NULL)
                return NULL;
 
-       if (HAS_POWER_WELL(dev))
+       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
                error->power_well_driver = I915_READ(HSW_PWR_WELL_DRIVER);
 
        for_each_pipe(i) {
-               if (!intel_display_power_enabled(dev, POWER_DOMAIN_PIPE(i)))
+               error->pipe[i].power_domain_on =
+                       intel_display_power_enabled_sw(dev, POWER_DOMAIN_PIPE(i));
+               if (!error->pipe[i].power_domain_on)
                        continue;
 
                if (INTEL_INFO(dev)->gen <= 6 || IS_VALLEYVIEW(dev)) {
@@ -11237,8 +11444,9 @@ intel_display_capture_error_state(struct drm_device *dev)
        for (i = 0; i < error->num_transcoders; i++) {
                enum transcoder cpu_transcoder = transcoders[i];
 
-               if (!intel_display_power_enabled(dev,
-                               POWER_DOMAIN_TRANSCODER(cpu_transcoder)))
+               error->transcoder[i].power_domain_on =
+                       intel_display_power_enabled_sw(dev, POWER_DOMAIN_PIPE(i));
+               if (!error->transcoder[i].power_domain_on)
                        continue;
 
                error->transcoder[i].cpu_transcoder = cpu_transcoder;
@@ -11268,11 +11476,13 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m,
                return;
 
        err_printf(m, "Num Pipes: %d\n", INTEL_INFO(dev)->num_pipes);
-       if (HAS_POWER_WELL(dev))
+       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
                err_printf(m, "PWR_WELL_CTL2: %08x\n",
                           error->power_well_driver);
        for_each_pipe(i) {
                err_printf(m, "Pipe [%d]:\n", i);
+               err_printf(m, "  Power: %s\n",
+                          error->pipe[i].power_domain_on ? "on" : "off");
                err_printf(m, "  SRC: %08x\n", error->pipe[i].source);
 
                err_printf(m, "Plane [%d]:\n", i);
@@ -11298,6 +11508,8 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m,
        for (i = 0; i < error->num_transcoders; i++) {
                err_printf(m, "CPU transcoder: %c\n",
                           transcoder_name(error->transcoder[i].cpu_transcoder));
+               err_printf(m, "  Power: %s\n",
+                          error->transcoder[i].power_domain_on ? "on" : "off");
                err_printf(m, "  CONF: %08x\n", error->transcoder[i].conf);
                err_printf(m, "  HTOTAL: %08x\n", error->transcoder[i].htotal);
                err_printf(m, "  HBLANK: %08x\n", error->transcoder[i].hblank);
index 0b2e842fef0151070b09af535d54fdcee2215602..88ad417f1ea344b901e3a5e4de0b190e3ecb34cb 100644 (file)
@@ -142,7 +142,7 @@ intel_dp_max_data_rate(int max_link_clock, int max_lanes)
        return (max_link_clock * max_lanes * 8) / 10;
 }
 
-static int
+static enum drm_mode_status
 intel_dp_mode_valid(struct drm_connector *connector,
                    struct drm_display_mode *mode)
 {
@@ -404,7 +404,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
        int i, ret, recv_bytes;
        uint32_t status;
        int try, precharge, clock = 0;
-       bool has_aux_irq = INTEL_INFO(dev)->gen >= 5 && !IS_VALLEYVIEW(dev);
+       bool has_aux_irq = true;
        uint32_t timeout;
 
        /* dp aux is extremely sensitive to irq latency, hence request the
@@ -1037,6 +1037,8 @@ static void ironlake_wait_panel_status(struct intel_dp *intel_dp,
                                I915_READ(pp_stat_reg),
                                I915_READ(pp_ctrl_reg));
        }
+
+       DRM_DEBUG_KMS("Wait complete\n");
 }
 
 static void ironlake_wait_panel_on(struct intel_dp *intel_dp)
@@ -1092,6 +1094,8 @@ void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)
        if (ironlake_edp_have_panel_vdd(intel_dp))
                return;
 
+       intel_runtime_pm_get(dev_priv);
+
        DRM_DEBUG_KMS("Turning eDP VDD on\n");
 
        if (!ironlake_edp_have_panel_power(intel_dp))
@@ -1140,7 +1144,11 @@ static void ironlake_panel_vdd_off_sync(struct intel_dp *intel_dp)
                /* Make sure sequencer is idle before allowing subsequent activity */
                DRM_DEBUG_KMS("PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
                I915_READ(pp_stat_reg), I915_READ(pp_ctrl_reg));
-               msleep(intel_dp->panel_power_down_delay);
+
+               if ((pp & POWER_TARGET_ON) == 0)
+                       msleep(intel_dp->panel_power_cycle_delay);
+
+               intel_runtime_pm_put(dev_priv);
        }
 }
 
@@ -1233,21 +1241,20 @@ void ironlake_edp_panel_off(struct intel_dp *intel_dp)
 
        DRM_DEBUG_KMS("Turn eDP power off\n");
 
-       WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n");
-
        pp = ironlake_get_pp_control(intel_dp);
        /* We need to switch off panel power _and_ force vdd, for otherwise some
         * panels get very unhappy and cease to work. */
-       pp &= ~(POWER_TARGET_ON | EDP_FORCE_VDD | PANEL_POWER_RESET | EDP_BLC_ENABLE);
+       pp &= ~(POWER_TARGET_ON | PANEL_POWER_RESET | EDP_BLC_ENABLE);
 
        pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
 
        I915_WRITE(pp_ctrl_reg, pp);
        POSTING_READ(pp_ctrl_reg);
 
-       intel_dp->want_panel_vdd = false;
-
        ironlake_wait_panel_off(intel_dp);
+
+       /* We got a reference when we enabled the VDD. */
+       intel_runtime_pm_put(dev_priv);
 }
 
 void ironlake_edp_backlight_on(struct intel_dp *intel_dp)
@@ -1772,7 +1779,6 @@ static void intel_disable_dp(struct intel_encoder *encoder)
 
        /* Make sure the panel is off before trying to change the mode. But also
         * ensure that we have vdd while we switch off the panel. */
-       ironlake_edp_panel_vdd_on(intel_dp);
        ironlake_edp_backlight_off(intel_dp);
        intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
        ironlake_edp_panel_off(intel_dp);
@@ -1845,23 +1851,23 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder)
        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);
+       enum dpio_channel 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, pipe, DPIO_DATA_LANE_A(port));
+       val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW8(port));
        val = 0;
        if (pipe)
                val |= (1<<21);
        else
                val &= ~(1<<21);
        val |= 0x001000c4;
-       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);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW8(port), val);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW14(port), 0x00760018);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW23(port), 0x00400888);
 
        mutex_unlock(&dev_priv->dpio_lock);
 
@@ -1872,7 +1878,7 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder)
 
        intel_enable_dp(encoder);
 
-       vlv_wait_port_ready(dev_priv, port);
+       vlv_wait_port_ready(dev_priv, dport);
 }
 
 static void vlv_dp_pre_pll_enable(struct intel_encoder *encoder)
@@ -1882,24 +1888,24 @@ static void vlv_dp_pre_pll_enable(struct intel_encoder *encoder)
        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);
+       enum dpio_channel port = vlv_dport_to_channel(dport);
        int pipe = intel_crtc->pipe;
 
        /* Program Tx lane resets to default */
        mutex_lock(&dev_priv->dpio_lock);
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_TX(port),
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port),
                         DPIO_PCS_TX_LANE2_RESET |
                         DPIO_PCS_TX_LANE1_RESET);
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLK(port),
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW1(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, 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, pipe, VLV_PCS_DW12(port), 0x00750f00);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW11(port), 0x00001500);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW14(port), 0x40400000);
        mutex_unlock(&dev_priv->dpio_lock);
 }
 
@@ -1941,18 +1947,6 @@ intel_dp_get_link_status(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_
                                              DP_LINK_STATUS_SIZE);
 }
 
-#if 0
-static char    *voltage_names[] = {
-       "0.4V", "0.6V", "0.8V", "1.2V"
-};
-static char    *pre_emph_names[] = {
-       "0dB", "3.5dB", "6dB", "9.5dB"
-};
-static char    *link_train_names[] = {
-       "pattern 1", "pattern 2", "idle", "off"
-};
-#endif
-
 /*
  * These are source-specific values; current Intel hardware supports
  * a maximum voltage of 800mV and a maximum pre-emphasis of 6dB
@@ -2050,7 +2044,7 @@ static uint32_t intel_vlv_signal_levels(struct intel_dp *intel_dp)
        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);
+       enum dpio_channel port = vlv_dport_to_channel(dport);
        int pipe = intel_crtc->pipe;
 
        switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) {
@@ -2127,14 +2121,14 @@ static uint32_t intel_vlv_signal_levels(struct intel_dp *intel_dp)
        }
 
        mutex_lock(&dev_priv->dpio_lock);
-       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),
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), 0x00000000);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW4(port), demph_reg_value);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW2(port),
                         uniqtranscale_reg_value);
-       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);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW3(port), 0x0C782040);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW11(port), 0x00030000);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW9(port), preemph_reg_value);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), 0x80000000);
        mutex_unlock(&dev_priv->dpio_lock);
 
        return 0;
@@ -3082,9 +3076,12 @@ intel_dp_detect(struct drm_connector *connector, bool force)
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
        struct intel_encoder *intel_encoder = &intel_dig_port->base;
        struct drm_device *dev = connector->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        enum drm_connector_status status;
        struct edid *edid = NULL;
 
+       intel_runtime_pm_get(dev_priv);
+
        DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
                      connector->base.id, drm_get_connector_name(connector));
 
@@ -3096,7 +3093,7 @@ intel_dp_detect(struct drm_connector *connector, bool force)
                status = g4x_dp_detect(intel_dp);
 
        if (status != connector_status_connected)
-               return status;
+               goto out;
 
        intel_dp_probe_oui(intel_dp);
 
@@ -3112,7 +3109,11 @@ intel_dp_detect(struct drm_connector *connector, bool force)
 
        if (intel_encoder->type != INTEL_OUTPUT_EDP)
                intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
-       return connector_status_connected;
+       status = connector_status_connected;
+
+out:
+       intel_runtime_pm_put(dev_priv);
+       return status;
 }
 
 static int intel_dp_get_modes(struct drm_connector *connector)
@@ -3326,11 +3327,19 @@ intel_trans_dp_port_sel(struct drm_crtc *crtc)
 }
 
 /* check the VBT to see whether the eDP is on DP-D port */
-bool intel_dpd_is_edp(struct drm_device *dev)
+bool intel_dp_is_edp(struct drm_device *dev, enum port port)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        union child_device_config *p_child;
        int i;
+       static const short port_mapping[] = {
+               [PORT_B] = PORT_IDPB,
+               [PORT_C] = PORT_IDPC,
+               [PORT_D] = PORT_IDPD,
+       };
+
+       if (port == PORT_A)
+               return true;
 
        if (!dev_priv->vbt.child_dev_num)
                return false;
@@ -3338,7 +3347,7 @@ 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->common.dvo_port == PORT_IDPD &&
+               if (p_child->common.dvo_port == port_mapping[port] &&
                    (p_child->common.device_type & DEVICE_TYPE_eDP_BITS) ==
                    (DEVICE_TYPE_eDP & DEVICE_TYPE_eDP_BITS))
                        return true;
@@ -3616,26 +3625,10 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
        intel_dp->DP = I915_READ(intel_dp->output_reg);
        intel_dp->attached_connector = intel_connector;
 
-       type = DRM_MODE_CONNECTOR_DisplayPort;
-       /*
-        * FIXME : We need to initialize built-in panels before external panels.
-        * For X0, DP_C is fixed as eDP. Revisit this as part of VLV eDP cleanup
-        */
-       switch (port) {
-       case PORT_A:
+       if (intel_dp_is_edp(dev, port))
                type = DRM_MODE_CONNECTOR_eDP;
-               break;
-       case PORT_C:
-               if (IS_VALLEYVIEW(dev))
-                       type = DRM_MODE_CONNECTOR_eDP;
-               break;
-       case PORT_D:
-               if (HAS_PCH_SPLIT(dev) && intel_dpd_is_edp(dev))
-                       type = DRM_MODE_CONNECTOR_eDP;
-               break;
-       default:        /* silence GCC warning */
-               break;
-       }
+       else
+               type = DRM_MODE_CONNECTOR_DisplayPort;
 
        /*
         * For eDP we always set the encoder type to INTEL_OUTPUT_EDP, but
index 1e49aa8f5377395c8803d5a55765199bd38af037..3f074c8f17d286280979d25c8931a49a6fec7abe 100644 (file)
@@ -155,7 +155,19 @@ struct intel_encoder {
 
 struct intel_panel {
        struct drm_display_mode *fixed_mode;
+       struct drm_display_mode *downclock_mode;
        int fitting_mode;
+
+       /* backlight */
+       struct {
+               bool present;
+               u32 level;
+               u32 max;
+               bool enabled;
+               bool combination_mode;  /* gen 2/4 only */
+               bool active_low_pwm;
+               struct backlight_device *device;
+       } backlight;
 };
 
 struct intel_connector {
@@ -443,7 +455,7 @@ struct intel_hdmi {
        bool rgb_quant_range_selectable;
        void (*write_infoframe)(struct drm_encoder *encoder,
                                enum hdmi_infoframe_type type,
-                               const uint8_t *frame, ssize_t len);
+                               const void *frame, ssize_t len);
        void (*set_infoframes)(struct drm_encoder *encoder,
                               struct drm_display_mode *adjusted_mode);
 };
@@ -490,9 +502,9 @@ vlv_dport_to_channel(struct intel_digital_port *dport)
 {
        switch (dport->port) {
        case PORT_B:
-               return 0;
+               return DPIO_CH0;
        case PORT_C:
-               return 1;
+               return DPIO_CH1;
        default:
                BUG();
        }
@@ -638,7 +650,8 @@ enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv,
 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);
+void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
+                        struct intel_digital_port *dport);
 bool intel_get_load_detect_pipe(struct drm_connector *connector,
                                struct drm_display_mode *mode,
                                struct intel_load_detect_pipe *old);
@@ -694,7 +707,7 @@ void i915_disable_vga_mem(struct drm_device *dev);
 void hsw_enable_ips(struct intel_crtc *crtc);
 void hsw_disable_ips(struct intel_crtc *crtc);
 void intel_display_set_init_power(struct drm_device *dev, bool enable);
-
+int valleyview_get_vco(struct drm_i915_private *dev_priv);
 
 /* intel_dp.c */
 void intel_dp_init(struct drm_device *dev, int output_reg, enum port port);
@@ -708,7 +721,7 @@ 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);
+bool intel_dp_is_edp(struct drm_device *dev, enum port port);
 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);
@@ -808,9 +821,13 @@ void intel_panel_set_backlight(struct intel_connector *connector, u32 level,
 int intel_panel_setup_backlight(struct drm_connector *connector);
 void intel_panel_enable_backlight(struct intel_connector *connector);
 void intel_panel_disable_backlight(struct intel_connector *connector);
-void intel_panel_destroy_backlight(struct drm_device *dev);
+void intel_panel_destroy_backlight(struct drm_connector *connector);
+void intel_panel_init_backlight_funcs(struct drm_device *dev);
 enum drm_connector_status intel_panel_detect(struct drm_device *dev);
-
+extern struct drm_display_mode *intel_find_panel_downclock(
+                               struct drm_device *dev,
+                               struct drm_display_mode *fixed_mode,
+                               struct drm_connector *connector);
 
 /* intel_pm.c */
 void intel_init_clock_gating(struct drm_device *dev);
@@ -821,6 +838,7 @@ void intel_update_sprite_watermarks(struct drm_plane *plane,
                                    uint32_t sprite_width, int pixel_size,
                                    bool enabled, bool scaled);
 void intel_init_pm(struct drm_device *dev);
+void intel_pm_setup(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);
@@ -829,6 +847,8 @@ int intel_power_domains_init(struct drm_device *dev);
 void intel_power_domains_remove(struct drm_device *dev);
 bool intel_display_power_enabled(struct drm_device *dev,
                                 enum intel_display_power_domain domain);
+bool intel_display_power_enabled_sw(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,
@@ -843,6 +863,10 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv);
 void gen6_rps_boost(struct drm_i915_private *dev_priv);
 void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv);
 void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv);
+void intel_runtime_pm_get(struct drm_i915_private *dev_priv);
+void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
+void intel_init_runtime_pm(struct drm_i915_private *dev_priv);
+void intel_fini_runtime_pm(struct drm_i915_private *dev_priv);
 void ilk_wm_get_hw_state(struct drm_device *dev);
 
 
index d257b093ca68757874925999fae766a727755212..fabbf0d895cf2a5e133d804d5e8e05f0f26f79ad 100644 (file)
 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)
+static void band_gap_reset(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);
+       vlv_flisdsi_write(dev_priv, 0x08, 0x0001);
+       vlv_flisdsi_write(dev_priv, 0x0F, 0x0005);
+       vlv_flisdsi_write(dev_priv, 0x0F, 0x0025);
+       udelay(150);
+       vlv_flisdsi_write(dev_priv, 0x0F, 0x0000);
+       vlv_flisdsi_write(dev_priv, 0x08, 0x0000);
 
        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)
@@ -132,14 +101,47 @@ static void intel_dsi_pre_pll_enable(struct intel_encoder *encoder)
        vlv_enable_dsi_pll(encoder);
 }
 
+static void intel_dsi_device_ready(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);
+       int pipe = intel_crtc->pipe;
+       u32 val;
+
+       DRM_DEBUG_KMS("\n");
+
+       val = I915_READ(MIPI_PORT_CTRL(pipe));
+       I915_WRITE(MIPI_PORT_CTRL(pipe), val | LP_OUTPUT_HOLD);
+       usleep_range(1000, 1500);
+       I915_WRITE(MIPI_DEVICE_READY(pipe), DEVICE_READY | ULPS_STATE_EXIT);
+       usleep_range(2000, 2500);
+       I915_WRITE(MIPI_DEVICE_READY(pipe), DEVICE_READY);
+       usleep_range(2000, 2500);
+       I915_WRITE(MIPI_DEVICE_READY(pipe), 0x00);
+       usleep_range(2000, 2500);
+       I915_WRITE(MIPI_DEVICE_READY(pipe), DEVICE_READY);
+       usleep_range(2000, 2500);
+}
 static void intel_dsi_pre_enable(struct intel_encoder *encoder)
 {
+       struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
+
        DRM_DEBUG_KMS("\n");
+
+       if (intel_dsi->dev.dev_ops->panel_reset)
+               intel_dsi->dev.dev_ops->panel_reset(&intel_dsi->dev);
+
+       /* put device in ready state */
+       intel_dsi_device_ready(encoder);
+
+       if (intel_dsi->dev.dev_ops->send_otp_cmds)
+               intel_dsi->dev.dev_ops->send_otp_cmds(&intel_dsi->dev);
 }
 
 static void intel_dsi_enable(struct intel_encoder *encoder)
 {
-       struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+       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);
        struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
        int pipe = intel_crtc->pipe;
@@ -147,41 +149,28 @@ static void intel_dsi_enable(struct intel_encoder *encoder)
 
        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)) {
+       else {
                msleep(20); /* XXX */
                dpi_send_cmd(intel_dsi, TURN_ON);
                msleep(100);
 
                /* assert ip_tg_enable signal */
-               temp = I915_READ(MIPI_PORT_CTRL(pipe));
+               temp = I915_READ(MIPI_PORT_CTRL(pipe)) & ~LANE_CONFIGURATION_MASK;
+               temp = temp | intel_dsi->port_bits;
                I915_WRITE(MIPI_PORT_CTRL(pipe), temp | DPI_ENABLE);
                POSTING_READ(MIPI_PORT_CTRL(pipe));
        }
 
-       intel_dsi->dev.dev_ops->enable(&intel_dsi->dev);
+       if (intel_dsi->dev.dev_ops->enable)
+               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 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);
        struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
        int pipe = intel_crtc->pipe;
@@ -189,8 +178,6 @@ static void intel_dsi_disable(struct intel_encoder *encoder)
 
        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);
@@ -203,20 +190,54 @@ static void intel_dsi_disable(struct intel_encoder *encoder)
                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);
-       }
+       /* if disable packets are sent before sending shutdown packet then in
+        * some next enable sequence send turn on packet error is observed */
+       if (intel_dsi->dev.dev_ops->disable)
+               intel_dsi->dev.dev_ops->disable(&intel_dsi->dev);
 }
 
-static void intel_dsi_post_disable(struct intel_encoder *encoder)
+static void intel_dsi_clear_device_ready(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);
+       int pipe = intel_crtc->pipe;
+       u32 val;
+
        DRM_DEBUG_KMS("\n");
 
+       I915_WRITE(MIPI_DEVICE_READY(pipe), ULPS_STATE_ENTER);
+       usleep_range(2000, 2500);
+
+       I915_WRITE(MIPI_DEVICE_READY(pipe), ULPS_STATE_EXIT);
+       usleep_range(2000, 2500);
+
+       I915_WRITE(MIPI_DEVICE_READY(pipe), ULPS_STATE_ENTER);
+       usleep_range(2000, 2500);
+
+       val = I915_READ(MIPI_PORT_CTRL(pipe));
+       I915_WRITE(MIPI_PORT_CTRL(pipe), val & ~LP_OUTPUT_HOLD);
+       usleep_range(1000, 1500);
+
+       if (wait_for(((I915_READ(MIPI_PORT_CTRL(pipe)) & AFE_LATCHOUT)
+                                       == 0x00000), 30))
+               DRM_ERROR("DSI LP not going Low\n");
+
+       I915_WRITE(MIPI_DEVICE_READY(pipe), 0x00);
+       usleep_range(2000, 2500);
+
        vlv_disable_dsi_pll(encoder);
 }
+static void intel_dsi_post_disable(struct intel_encoder *encoder)
+{
+       struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
+
+       DRM_DEBUG_KMS("\n");
+
+       intel_dsi_clear_device_ready(encoder);
+
+       if (intel_dsi->dev.dev_ops->disable_panel_power)
+               intel_dsi->dev.dev_ops->disable_panel_power(&intel_dsi->dev);
+}
 
 static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
                                   enum pipe *pipe)
@@ -251,8 +272,9 @@ static void intel_dsi_get_config(struct intel_encoder *encoder,
        /* XXX: read flags, set to adjusted_mode */
 }
 
-static int intel_dsi_mode_valid(struct drm_connector *connector,
-                               struct drm_display_mode *mode)
+static enum drm_mode_status
+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;
@@ -352,11 +374,8 @@ static void intel_dsi_mode_set(struct intel_encoder *intel_encoder)
 
        DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe));
 
-       /* Update the DSI PLL */
-       vlv_enable_dsi_pll(intel_encoder);
-
        /* XXX: Location of the call */
-       band_gap_wa(dev_priv);
+       band_gap_reset(dev_priv);
 
        /* escape clock divider, 20MHz, shared for A and C. device ready must be
         * off when doing this! txclkesc? */
@@ -373,11 +392,7 @@ static void intel_dsi_mode_set(struct intel_encoder *intel_encoder)
        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_DPHY_PARAM(pipe), intel_dsi->dphy_reg);
 
        I915_WRITE(MIPI_DPI_RESOLUTION(pipe),
                   adjusted_mode->vdisplay << VERTICAL_ADDRESS_SHIFT |
@@ -425,9 +440,9 @@ static void intel_dsi_mode_set(struct intel_encoder *intel_encoder)
                                       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 */
+       I915_WRITE(MIPI_LP_RX_TIMEOUT(pipe), intel_dsi->lp_rx_timeout);
+       I915_WRITE(MIPI_TURN_AROUND_TIMEOUT(pipe), intel_dsi->turn_arnd_val);
+       I915_WRITE(MIPI_DEVICE_RESET_TIMER(pipe), intel_dsi->rst_timer_val);
 
        /* dphy stuff */
 
@@ -442,29 +457,31 @@ static void intel_dsi_mode_set(struct intel_encoder *intel_encoder)
         *
         * XXX: write MIPI_STOP_STATE_STALL?
         */
-       I915_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT(pipe), 0x46);
+       I915_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT(pipe),
+                                               intel_dsi->hs_to_lp_count);
 
        /* 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);
+       I915_WRITE(MIPI_LP_BYTECLK(pipe), intel_dsi->lp_byte_clk);
 
        /* 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_DBI_BW_CTRL(pipe), intel_dsi->bw_timer);
 
        I915_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT(pipe),
-                  0xa << LP_HS_SSW_CNT_SHIFT |
-                  0x14 << HS_LP_PWR_SW_CNT_SHIFT);
+                  intel_dsi->clk_lp_to_hs_count << LP_HS_SSW_CNT_SHIFT |
+                  intel_dsi->clk_hs_to_lp_count << HS_LP_PWR_SW_CNT_SHIFT);
 
        if (is_vid_mode(intel_dsi))
                I915_WRITE(MIPI_VIDEO_MODE_FORMAT(pipe),
-                          intel_dsi->video_mode_format);
+                               intel_dsi->video_frmt_cfg_bits |
+                               intel_dsi->video_mode_format);
 }
 
 static enum drm_connector_status
index c7765f33d5245fa2ff1fd03fe2bb12339a716473..b4a27cec882f76d7cab17400d8adf438532b4c9d 100644 (file)
@@ -39,6 +39,13 @@ struct intel_dsi_device {
 struct intel_dsi_dev_ops {
        bool (*init)(struct intel_dsi_device *dsi);
 
+       void (*panel_reset)(struct intel_dsi_device *dsi);
+
+       void (*disable_panel_power)(struct intel_dsi_device *dsi);
+
+       /* one time programmable commands if needed */
+       void (*send_otp_cmds)(struct intel_dsi_device *dsi);
+
        /* This callback must be able to assume DSI commands can be sent */
        void (*enable)(struct intel_dsi_device *dsi);
 
@@ -89,6 +96,20 @@ struct intel_dsi {
 
        /* eot for MIPI_EOT_DISABLE register */
        u32 eot_disable;
+
+       u32 port_bits;
+       u32 bw_timer;
+       u32 dphy_reg;
+       u32 video_frmt_cfg_bits;
+       u16 lp_byte_clk;
+
+       /* timeouts in byte clocks */
+       u16 lp_rx_timeout;
+       u16 turn_arnd_val;
+       u16 rst_timer_val;
+       u16 hs_to_lp_count;
+       u16 clk_lp_to_hs_count;
+       u16 clk_hs_to_lp_count;
 };
 
 static inline struct intel_dsi *enc_to_intel_dsi(struct drm_encoder *encoder)
index 44279b2ade888a7821d75da44ab523ab8f1f318a..ba79ec19da3b8ce8d4379df2545c1ea54c3a8f3e 100644 (file)
@@ -50,6 +50,8 @@ static const u32 lfsr_converts[] = {
        71, 35                                                  /* 91 - 92 */
 };
 
+#ifdef DSI_CLK_FROM_RR
+
 static u32 dsi_rr_formula(const struct drm_display_mode *mode,
                          int pixel_format, int video_mode_format,
                          int lane_count, bool eotp)
@@ -121,7 +123,7 @@ static u32 dsi_rr_formula(const struct drm_display_mode *mode,
 
        /* 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);
+       dsi_clk = dsi_bit_clock_hz / 1000;
 
        if (eotp && video_mode_format == VIDEO_MODE_BURST)
                dsi_clk *= 2;
@@ -129,64 +131,37 @@ static u32 dsi_rr_formula(const struct drm_display_mode *mode,
        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*/
-};
+#else
 
-static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp)
+/* Get DSI clock from pixel clock */
+static u32 dsi_clk_from_pclk(const struct drm_display_mode *mode,
+                         int pixel_format, int lane_count)
 {
-       unsigned int i;
-       u8 m;
-       u8 n;
-       u8 p;
-       u32 m_seed;
-
-       if (dsi_clk < 300 || dsi_clk > 1000)
-               return -ECHRNG;
+       u32 dsi_clk_khz;
+       u32 bpp;
 
-       for (i = 0; i <= ARRAY_SIZE(dsi_clk_tbl); i++) {
-               if (dsi_clk_tbl[i].freq > dsi_clk)
-                       break;
+       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;
        }
 
-       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;
+       /* DSI data rate = pixel clock * bits per pixel / lane count
+          pixel clock is converted from KHz to Hz */
+       dsi_clk_khz = DIV_ROUND_CLOSEST(mode->clock * bpp, lane_count);
 
-       return 0;
+       return dsi_clk_khz;
 }
 
-#else
+#endif
 
 static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp)
 {
@@ -194,36 +169,47 @@ static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp)
        u32 ref_clk;
        u32 error;
        u32 tmp_error;
-       u32 target_dsi_clk;
-       u32 calc_dsi_clk;
+       int target_dsi_clk;
+       int calc_dsi_clk;
        u32 calc_m;
        u32 calc_p;
        u32 m_seed;
 
-       if (dsi_clk < 300 || dsi_clk > 1150) {
+       /* dsi_clk is expected in KHZ */
+       if (dsi_clk < 300000 || dsi_clk > 1150000) {
                DRM_ERROR("DSI CLK Out of Range\n");
                return -ECHRNG;
        }
 
        ref_clk = 25000;
-       target_dsi_clk = dsi_clk * 1000;
+       target_dsi_clk = dsi_clk;
        error = 0xFFFFFFFF;
+       tmp_error = 0xFFFFFFFF;
        calc_m = 0;
        calc_p = 0;
 
        for (m = 62; m <= 92; m++) {
                for (p = 2; p <= 6; p++) {
-
+                       /* Find the optimal m and p divisors
+                       with minimal error +/- the required clock */
                        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;
-                               }
+                       if (calc_dsi_clk == target_dsi_clk) {
+                               calc_m = m;
+                               calc_p = p;
+                               error = 0;
+                               break;
+                       } else
+                               tmp_error = abs(target_dsi_clk - calc_dsi_clk);
+
+                       if (tmp_error < error) {
+                               error = tmp_error;
+                               calc_m = m;
+                               calc_p = p;
                        }
                }
+
+               if (error == 0)
+                       break;
        }
 
        m_seed = lfsr_converts[calc_m - 62];
@@ -235,8 +221,6 @@ static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp)
        return 0;
 }
 
-#endif
-
 /*
  * XXX: The muxing and gating is hard coded for now. Need to add support for
  * sharing PLLs with two DSI outputs.
@@ -251,9 +235,8 @@ static void vlv_configure_dsi_pll(struct intel_encoder *encoder)
        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);
+       dsi_clk = dsi_clk_from_pclk(mode, intel_dsi->pixel_format,
+                                               intel_dsi->lane_count);
 
        ret = dsi_calc_mnp(dsi_clk, &dsi_mnp);
        if (ret) {
index 3c77365468562ab026910a1e111fb932b288f242..eeff998e52efdea93534ffb680582503f9f2a56c 100644 (file)
@@ -234,8 +234,9 @@ static void intel_dvo_dpms(struct drm_connector *connector, int mode)
        intel_modeset_check_state(connector->dev);
 }
 
-static int intel_dvo_mode_valid(struct drm_connector *connector,
-                               struct drm_display_mode *mode)
+static enum drm_mode_status
+intel_dvo_mode_valid(struct drm_connector *connector,
+                    struct drm_display_mode *mode)
 {
        struct intel_dvo *intel_dvo = intel_attached_dvo(connector);
 
index 895fcb4fbd9446bfbfafc90f95948d9a4bea5c55..284c3eb066f6ffff76de5b7cb0108617126679f2 100644 (file)
@@ -57,18 +57,14 @@ static struct fb_ops intelfb_ops = {
        .fb_debug_leave = drm_fb_helper_debug_leave,
 };
 
-static int intelfb_create(struct drm_fb_helper *helper,
-                         struct drm_fb_helper_surface_size *sizes)
+static int intelfb_alloc(struct drm_fb_helper *helper,
+                        struct drm_fb_helper_surface_size *sizes)
 {
        struct intel_fbdev *ifbdev =
                container_of(helper, struct intel_fbdev, helper);
        struct drm_device *dev = helper->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct fb_info *info;
-       struct drm_framebuffer *fb;
        struct drm_mode_fb_cmd2 mode_cmd = {};
        struct drm_i915_gem_object *obj;
-       struct device *device = &dev->pdev->dev;
        int size, ret;
 
        /* we don't do packed 24bpp */
@@ -94,8 +90,6 @@ static int intelfb_create(struct drm_fb_helper *helper,
                goto out;
        }
 
-       mutex_lock(&dev->struct_mutex);
-
        /* Flush everything out, we'll be doing GTT only from now on */
        ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
        if (ret) {
@@ -103,7 +97,50 @@ static int intelfb_create(struct drm_fb_helper *helper,
                goto out_unref;
        }
 
-       info = framebuffer_alloc(0, device);
+       ret = intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, obj);
+       if (ret)
+               goto out_unpin;
+
+       return 0;
+
+out_unpin:
+       i915_gem_object_unpin(obj);
+out_unref:
+       drm_gem_object_unreference(&obj->base);
+out:
+       return ret;
+}
+
+static int intelfb_create(struct drm_fb_helper *helper,
+                         struct drm_fb_helper_surface_size *sizes)
+{
+       struct intel_fbdev *ifbdev =
+               container_of(helper, struct intel_fbdev, helper);
+       struct intel_framebuffer *intel_fb = &ifbdev->ifb;
+       struct drm_device *dev = helper->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct fb_info *info;
+       struct drm_framebuffer *fb;
+       struct drm_i915_gem_object *obj;
+       int size, ret;
+
+       mutex_lock(&dev->struct_mutex);
+
+       if (!intel_fb->obj) {
+               DRM_DEBUG_KMS("no BIOS fb, allocating a new one\n");
+               ret = intelfb_alloc(helper, sizes);
+               if (ret)
+                       goto out_unlock;
+       } else {
+               DRM_DEBUG_KMS("re-using BIOS fb\n");
+               sizes->fb_width = intel_fb->base.width;
+               sizes->fb_height = intel_fb->base.height;
+       }
+
+       obj = intel_fb->obj;
+       size = obj->base.size;
+
+       info = framebuffer_alloc(0, &dev->pdev->dev);
        if (!info) {
                ret = -ENOMEM;
                goto out_unpin;
@@ -111,10 +148,6 @@ static int intelfb_create(struct drm_fb_helper *helper,
 
        info->par = helper;
 
-       ret = intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, obj);
-       if (ret)
-               goto out_unpin;
-
        fb = &ifbdev->ifb.base;
 
        ifbdev->helper.fb = fb;
@@ -170,17 +203,15 @@ static int intelfb_create(struct drm_fb_helper *helper,
                      fb->width, fb->height,
                      i915_gem_obj_ggtt_offset(obj), obj);
 
-
        mutex_unlock(&dev->struct_mutex);
        vga_switcheroo_client_fb_set(dev->pdev, info);
        return 0;
 
 out_unpin:
        i915_gem_object_unpin(obj);
-out_unref:
        drm_gem_object_unreference(&obj->base);
+out_unlock:
        mutex_unlock(&dev->struct_mutex);
-out:
        return ret;
 }
 
index 03f9ca70530c03f441ae037b16cf0c5e80b908ab..6db0d9d17f47e7b5ce5c43a7aa7795de71ea6346 100644 (file)
@@ -130,9 +130,9 @@ static u32 hsw_infoframe_data_reg(enum hdmi_infoframe_type type,
 
 static void g4x_write_infoframe(struct drm_encoder *encoder,
                                enum hdmi_infoframe_type type,
-                               const uint8_t *frame, ssize_t len)
+                               const void *frame, ssize_t len)
 {
-       uint32_t *data = (uint32_t *)frame;
+       const uint32_t *data = frame;
        struct drm_device *dev = encoder->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 val = I915_READ(VIDEO_DIP_CTL);
@@ -167,9 +167,9 @@ static void g4x_write_infoframe(struct drm_encoder *encoder,
 
 static void ibx_write_infoframe(struct drm_encoder *encoder,
                                enum hdmi_infoframe_type type,
-                               const uint8_t *frame, ssize_t len)
+                               const void *frame, ssize_t len)
 {
-       uint32_t *data = (uint32_t *)frame;
+       const uint32_t *data = frame;
        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);
@@ -205,9 +205,9 @@ static void ibx_write_infoframe(struct drm_encoder *encoder,
 
 static void cpt_write_infoframe(struct drm_encoder *encoder,
                                enum hdmi_infoframe_type type,
-                               const uint8_t *frame, ssize_t len)
+                               const void *frame, ssize_t len)
 {
-       uint32_t *data = (uint32_t *)frame;
+       const uint32_t *data = frame;
        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);
@@ -246,9 +246,9 @@ static void cpt_write_infoframe(struct drm_encoder *encoder,
 
 static void vlv_write_infoframe(struct drm_encoder *encoder,
                                enum hdmi_infoframe_type type,
-                               const uint8_t *frame, ssize_t len)
+                               const void *frame, ssize_t len)
 {
-       uint32_t *data = (uint32_t *)frame;
+       const uint32_t *data = frame;
        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);
@@ -284,9 +284,9 @@ static void vlv_write_infoframe(struct drm_encoder *encoder,
 
 static void hsw_write_infoframe(struct drm_encoder *encoder,
                                enum hdmi_infoframe_type type,
-                               const uint8_t *frame, ssize_t len)
+                               const void *frame, ssize_t len)
 {
-       uint32_t *data = (uint32_t *)frame;
+       const uint32_t *data = frame;
        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);
@@ -853,8 +853,9 @@ static int hdmi_portclock_limit(struct intel_hdmi *hdmi)
                return 225000;
 }
 
-static int intel_hdmi_mode_valid(struct drm_connector *connector,
-                                struct drm_display_mode *mode)
+static enum drm_mode_status
+intel_hdmi_mode_valid(struct drm_connector *connector,
+                     struct drm_display_mode *mode)
 {
        if (mode->clock > hdmi_portclock_limit(intel_attached_hdmi(connector)))
                return MODE_CLOCK_HIGH;
@@ -1081,7 +1082,7 @@ static void vlv_hdmi_pre_enable(struct intel_encoder *encoder)
        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);
+       enum dpio_channel port = vlv_dport_to_channel(dport);
        int pipe = intel_crtc->pipe;
        u32 val;
 
@@ -1090,41 +1091,33 @@ static void vlv_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, pipe, DPIO_DATA_LANE_A(port));
+       val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW8(port));
        val = 0;
        if (pipe)
                val |= (1<<21);
        else
                val &= ~(1<<21);
        val |= 0x001000c4;
-       vlv_dpio_write(dev_priv, pipe, DPIO_DATA_CHANNEL(port), val);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW8(port), val);
 
        /* HDMI 1.0V-2dB */
-       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, pipe, DPIO_TX_SWING_CTL2(port),
-                        0x5578b83a);
-       vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL3(port),
-                        0x0c782040);
-       vlv_dpio_write(dev_priv, pipe, DPIO_TX3_SWING_CTL4(port),
-                        0x2b247878);
-       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, pipe, DPIO_TX_OCALINIT(port),
-                        DPIO_TX_OCALINIT_EN);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), 0);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW4(port), 0x2b245f5f);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW2(port), 0x5578b83a);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW3(port), 0x0c782040);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX3_DW4(port), 0x2b247878);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW11(port), 0x00030000);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW9(port), 0x00002000);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), DPIO_TX_OCALINIT_EN);
 
        /* Program lane clock */
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLOCKBUF0(port),
-                        0x00760018);
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLOCKBUF8(port),
-                        0x00400888);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW14(port), 0x00760018);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW23(port), 0x00400888);
        mutex_unlock(&dev_priv->dpio_lock);
 
        intel_enable_hdmi(encoder);
 
-       vlv_wait_port_ready(dev_priv, port);
+       vlv_wait_port_ready(dev_priv, dport);
 }
 
 static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
@@ -1134,7 +1127,7 @@ static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
        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);
+       enum dpio_channel port = vlv_dport_to_channel(dport);
        int pipe = intel_crtc->pipe;
 
        if (!IS_VALLEYVIEW(dev))
@@ -1142,24 +1135,22 @@ static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
 
        /* Program Tx lane resets to default */
        mutex_lock(&dev_priv->dpio_lock);
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_TX(port),
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port),
                         DPIO_PCS_TX_LANE2_RESET |
                         DPIO_PCS_TX_LANE1_RESET);
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLK(port),
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW1(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, 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, pipe, DPIO_PCS_CTL_OVER1(port),
-                        0x00002000);
-       vlv_dpio_write(dev_priv, pipe, DPIO_TX_OCALINIT(port),
-                        DPIO_TX_OCALINIT_EN);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW12(port), 0x00750f00);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW11(port), 0x00001500);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW14(port), 0x40400000);
+
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW9(port), 0x00002000);
+       vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), DPIO_TX_OCALINIT_EN);
        mutex_unlock(&dev_priv->dpio_lock);
 }
 
@@ -1169,13 +1160,13 @@ static void vlv_hdmi_post_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);
-       int port = vlv_dport_to_channel(dport);
+       enum dpio_channel 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, pipe, DPIO_PCS_TX(port), 0x00000000);
-       vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLK(port), 0x00e00060);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port), 0x00000000);
+       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW1(port), 0x00e00060);
        mutex_unlock(&dev_priv->dpio_lock);
 }
 
index 2ca17b14b6c1c91710601dfcb34c661b45707347..b1dc33f478991755ec114fe66fbad7bc40fec4c0 100644 (file)
@@ -82,20 +82,11 @@ static int get_disp_clk_div(struct drm_i915_private *dev_priv,
 
 static void gmbus_set_freq(struct drm_i915_private *dev_priv)
 {
-       int vco_freq[] = { 800, 1600, 2000, 2400 };
-       int gmbus_freq = 0, cdclk_div, hpll_freq;
+       int vco, gmbus_freq = 0, cdclk_div;
 
        BUG_ON(!IS_VALLEYVIEW(dev_priv->dev));
 
-       /* Skip setting the gmbus freq if BIOS has already programmed it */
-       if (I915_READ(GMBUSFREQ_VLV) != 0xA0)
-               return;
-
-       /* Obtain SKU information */
-       mutex_lock(&dev_priv->dpio_lock);
-       hpll_freq =
-               vlv_cck_read(dev_priv, CCK_FUSE_REG) & CCK_FUSE_HPLL_FREQ_MASK;
-       mutex_unlock(&dev_priv->dpio_lock);
+       vco = valleyview_get_vco(dev_priv);
 
        /* Get the CDCLK divide ratio */
        cdclk_div = get_disp_clk_div(dev_priv, CDCLK);
@@ -106,7 +97,7 @@ static void gmbus_set_freq(struct drm_i915_private *dev_priv)
         * in fact 1MHz is the correct frequency.
         */
        if (cdclk_div)
-               gmbus_freq = (vco_freq[hpll_freq] << 1) / cdclk_div;
+               gmbus_freq = (vco << 1) / cdclk_div;
 
        if (WARN_ON(gmbus_freq == 0))
                return;
index c3b4da7895ed1c82b185b78ca06d00053cff2402..8bcb93a2a9f6b1d09780c3154f6c656895451e8e 100644 (file)
@@ -256,8 +256,9 @@ static void intel_disable_lvds(struct intel_encoder *encoder)
        POSTING_READ(lvds_encoder->reg);
 }
 
-static int intel_lvds_mode_valid(struct drm_connector *connector,
-                                struct drm_display_mode *mode)
+static enum drm_mode_status
+intel_lvds_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;
@@ -446,9 +447,19 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
        if (dev_priv->modeset_restore == MODESET_DONE)
                goto exit;
 
-       drm_modeset_lock_all(dev);
-       intel_modeset_setup_hw_state(dev, true);
-       drm_modeset_unlock_all(dev);
+       /*
+        * Some old platform's BIOS love to wreak havoc while the lid is closed.
+        * We try to detect this here and undo any damage. The split for PCH
+        * platforms is rather conservative and a bit arbitrary expect that on
+        * those platforms VGA disabling requires actual legacy VGA I/O access,
+        * and as part of the cleanup in the hw state restore we also redisable
+        * the vga plane.
+        */
+       if (!HAS_PCH_SPLIT(dev)) {
+               drm_modeset_lock_all(dev);
+               intel_modeset_setup_hw_state(dev, true);
+               drm_modeset_unlock_all(dev);
+       }
 
        dev_priv->modeset_restore = MODESET_DONE;
 
@@ -744,57 +755,6 @@ static const struct dmi_system_id intel_no_lvds[] = {
        { }     /* terminating entry */
 };
 
-/**
- * intel_find_lvds_downclock - find the reduced downclock for LVDS in EDID
- * @dev: drm device
- * @connector: LVDS connector
- *
- * Find the reduced downclock for LVDS in EDID.
- */
-static void intel_find_lvds_downclock(struct drm_device *dev,
-                                     struct drm_display_mode *fixed_mode,
-                                     struct drm_connector *connector)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_display_mode *scan;
-       int temp_downclock;
-
-       temp_downclock = fixed_mode->clock;
-       list_for_each_entry(scan, &connector->probed_modes, head) {
-               /*
-                * If one mode has the same resolution with the fixed_panel
-                * mode while they have the different refresh rate, it means
-                * that the reduced downclock is found for the LVDS. In such
-                * case we can set the different FPx0/1 to dynamically select
-                * between low and high frequency.
-                */
-               if (scan->hdisplay == fixed_mode->hdisplay &&
-                   scan->hsync_start == fixed_mode->hsync_start &&
-                   scan->hsync_end == fixed_mode->hsync_end &&
-                   scan->htotal == fixed_mode->htotal &&
-                   scan->vdisplay == fixed_mode->vdisplay &&
-                   scan->vsync_start == fixed_mode->vsync_start &&
-                   scan->vsync_end == fixed_mode->vsync_end &&
-                   scan->vtotal == fixed_mode->vtotal) {
-                       if (scan->clock < temp_downclock) {
-                               /*
-                                * The downclock is already found. But we
-                                * expect to find the lower downclock.
-                                */
-                               temp_downclock = scan->clock;
-                       }
-               }
-       }
-       if (temp_downclock < fixed_mode->clock && i915_lvds_downclock) {
-               /* We found the downclock for LVDS. */
-               dev_priv->lvds_downclock_avail = 1;
-               dev_priv->lvds_downclock = temp_downclock;
-               DRM_DEBUG_KMS("LVDS downclock is found in EDID. "
-                             "Normal clock %dKhz, downclock %dKhz\n",
-                             fixed_mode->clock, temp_downclock);
-       }
-}
-
 /*
  * Enumerate the child dev array parsed from VBT to check whether
  * the LVDS is present.
@@ -1072,8 +1032,22 @@ void intel_lvds_init(struct drm_device *dev)
 
                        fixed_mode = drm_mode_duplicate(dev, scan);
                        if (fixed_mode) {
-                               intel_find_lvds_downclock(dev, fixed_mode,
-                                                         connector);
+                               intel_connector->panel.downclock_mode =
+                                       intel_find_panel_downclock(dev,
+                                       fixed_mode, connector);
+                               if (intel_connector->panel.downclock_mode !=
+                                       NULL && i915_lvds_downclock) {
+                                       /* We found the downclock for LVDS. */
+                                       dev_priv->lvds_downclock_avail = true;
+                                       dev_priv->lvds_downclock =
+                                               intel_connector->panel.
+                                               downclock_mode->clock;
+                                       DRM_DEBUG_KMS("LVDS downclock is found"
+                                       " in EDID. Normal clock %dKhz, "
+                                       "downclock %dKhz\n",
+                                       fixed_mode->clock,
+                                       dev_priv->lvds_downclock);
+                               }
                                goto out;
                        }
                }
index 6d69a9bad86545c6a8cfc8e8ff86480d462c2132..3da259e280bad48696d0bbc905a2835c258d1b38 100644 (file)
@@ -64,7 +64,7 @@ struct opregion_header {
        u8 driver_ver[16];
        u32 mboxes;
        u8 reserved[164];
-} __attribute__((packed));
+} __packed;
 
 /* OpRegion mailbox #1: public ACPI methods */
 struct opregion_acpi {
@@ -86,7 +86,7 @@ struct opregion_acpi {
        u32 cnot;       /* current OS notification */
        u32 nrdy;       /* driver status */
        u8 rsvd2[60];
-} __attribute__((packed));
+} __packed;
 
 /* OpRegion mailbox #2: SWSCI */
 struct opregion_swsci {
@@ -94,7 +94,7 @@ struct opregion_swsci {
        u32 parm;       /* command parameters */
        u32 dslp;       /* driver sleep time-out */
        u8 rsvd[244];
-} __attribute__((packed));
+} __packed;
 
 /* OpRegion mailbox #3: ASLE */
 struct opregion_asle {
@@ -115,7 +115,7 @@ struct opregion_asle {
        u32 srot;       /* supported rotation angles */
        u32 iuer;       /* IUER events */
        u8 rsvd[86];
-} __attribute__((packed));
+} __packed;
 
 /* Driver readiness indicator */
 #define ASLE_ARDY_READY                (1 << 0)
@@ -396,13 +396,10 @@ int intel_opregion_notify_adapter(struct drm_device *dev, pci_power_t state)
 static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_encoder *encoder;
        struct drm_connector *connector;
-       struct intel_connector *intel_connector = NULL;
-       struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[0];
+       struct intel_connector *intel_connector;
+       struct intel_panel *panel;
        struct opregion_asle __iomem *asle = dev_priv->opregion.asle;
-       u32 ret = 0;
-       bool found = false;
 
        DRM_DEBUG_DRIVER("bclp = 0x%08x\n", bclp);
 
@@ -414,38 +411,24 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
                return ASLC_BACKLIGHT_FAILED;
 
        mutex_lock(&dev->mode_config.mutex);
+
        /*
-        * Could match the OpRegion connector here instead, but we'd also need
-        * to verify the connector could handle a backlight call.
+        * Update backlight on all connectors that support backlight (usually
+        * only one).
         */
-       list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
-               if (encoder->crtc == crtc) {
-                       found = true;
-                       break;
-               }
-
-       if (!found) {
-               ret = ASLC_BACKLIGHT_FAILED;
-               goto out;
-       }
-
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head)
-               if (connector->encoder == encoder)
-                       intel_connector = to_intel_connector(connector);
-
-       if (!intel_connector) {
-               ret = ASLC_BACKLIGHT_FAILED;
-               goto out;
-       }
-
        DRM_DEBUG_KMS("updating opregion backlight %d/255\n", bclp);
-       intel_panel_set_backlight(intel_connector, bclp, 255);
+       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+               intel_connector = to_intel_connector(connector);
+               panel = &intel_connector->panel;
+               if (panel->backlight.present)
+                       intel_panel_set_backlight(intel_connector, bclp, 255);
+       }
        iowrite32(DIV_ROUND_UP(bclp * 100, 255) | ASLE_CBLV_VALID, &asle->cblv);
 
-out:
        mutex_unlock(&dev->mode_config.mutex);
 
-       return ret;
+
+       return 0;
 }
 
 static u32 asle_set_als_illum(struct drm_device *dev, u32 alsi)
index f161ac02c4f6e613efbfc7f763cbb3566dc75248..20ebc3e83d39fa073d80ad46386884635dd1dce3 100644 (file)
@@ -325,203 +325,170 @@ out:
        pipe_config->gmch_pfit.lvds_border_bits = border;
 }
 
-static int is_backlight_combination_mode(struct drm_device *dev)
+static int i915_panel_invert_brightness;
+MODULE_PARM_DESC(invert_brightness, "Invert backlight brightness "
+       "(-1 force normal, 0 machine defaults, 1 force inversion), please "
+       "report PCI device ID, subsystem vendor and subsystem device ID "
+       "to dri-devel@lists.freedesktop.org, if your machine needs it. "
+       "It will then be included in an upcoming module version.");
+module_param_named(invert_brightness, i915_panel_invert_brightness, int, 0600);
+static u32 intel_panel_compute_brightness(struct intel_connector *connector,
+                                         u32 val)
 {
+       struct drm_device *dev = connector->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
 
-       if (IS_GEN4(dev))
-               return I915_READ(BLC_PWM_CTL2) & BLM_COMBINATION_MODE;
+       WARN_ON(panel->backlight.max == 0);
 
-       if (IS_GEN2(dev))
-               return I915_READ(BLC_PWM_CTL) & BLM_LEGACY_MODE;
+       if (i915_panel_invert_brightness < 0)
+               return val;
 
-       return 0;
+       if (i915_panel_invert_brightness > 0 ||
+           dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) {
+               return panel->backlight.max - val;
+       }
+
+       return val;
 }
 
-/* XXX: query mode clock or hardware clock and program max PWM appropriately
- * when it's 0.
- */
-static u32 i915_read_blc_pwm_ctl(struct drm_device *dev, enum pipe pipe)
+static u32 bdw_get_backlight(struct intel_connector *connector)
 {
+       struct drm_device *dev = connector->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 val;
 
-       WARN_ON_SMP(!spin_is_locked(&dev_priv->backlight.lock));
-
-       /* Restore the CTL value if it lost, e.g. GPU reset */
-
-       if (HAS_PCH_SPLIT(dev_priv->dev)) {
-               val = I915_READ(BLC_PWM_PCH_CTL2);
-               if (dev_priv->regfile.saveBLC_PWM_CTL2 == 0) {
-                       dev_priv->regfile.saveBLC_PWM_CTL2 = val;
-               } else if (val == 0) {
-                       val = dev_priv->regfile.saveBLC_PWM_CTL2;
-                       I915_WRITE(BLC_PWM_PCH_CTL2, val);
-               }
-       } else if (IS_VALLEYVIEW(dev)) {
-               val = I915_READ(VLV_BLC_PWM_CTL(pipe));
-               if (dev_priv->regfile.saveBLC_PWM_CTL == 0) {
-                       dev_priv->regfile.saveBLC_PWM_CTL = val;
-                       dev_priv->regfile.saveBLC_PWM_CTL2 =
-                               I915_READ(VLV_BLC_PWM_CTL2(pipe));
-               } else if (val == 0) {
-                       val = dev_priv->regfile.saveBLC_PWM_CTL;
-                       I915_WRITE(VLV_BLC_PWM_CTL(pipe), val);
-                       I915_WRITE(VLV_BLC_PWM_CTL2(pipe),
-                                  dev_priv->regfile.saveBLC_PWM_CTL2);
-               }
+       return I915_READ(BLC_PWM_PCH_CTL2) & BACKLIGHT_DUTY_CYCLE_MASK;
+}
 
-               if (!val)
-                       val = 0x0f42ffff;
-       } else {
-               val = I915_READ(BLC_PWM_CTL);
-               if (dev_priv->regfile.saveBLC_PWM_CTL == 0) {
-                       dev_priv->regfile.saveBLC_PWM_CTL = val;
-                       if (INTEL_INFO(dev)->gen >= 4)
-                               dev_priv->regfile.saveBLC_PWM_CTL2 =
-                                       I915_READ(BLC_PWM_CTL2);
-               } else if (val == 0) {
-                       val = dev_priv->regfile.saveBLC_PWM_CTL;
-                       I915_WRITE(BLC_PWM_CTL, val);
-                       if (INTEL_INFO(dev)->gen >= 4)
-                               I915_WRITE(BLC_PWM_CTL2,
-                                          dev_priv->regfile.saveBLC_PWM_CTL2);
-               }
-       }
+static u32 pch_get_backlight(struct intel_connector *connector)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
 
-       return val;
+       return I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
 }
 
-static u32 intel_panel_get_max_backlight(struct drm_device *dev,
-                                        enum pipe pipe)
+static u32 i9xx_get_backlight(struct intel_connector *connector)
 {
-       u32 max;
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
+       u32 val;
 
-       max = i915_read_blc_pwm_ctl(dev, pipe);
+       val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
+       if (INTEL_INFO(dev)->gen < 4)
+               val >>= 1;
 
-       if (HAS_PCH_SPLIT(dev)) {
-               max >>= 16;
-       } else {
-               if (INTEL_INFO(dev)->gen < 4)
-                       max >>= 17;
-               else
-                       max >>= 16;
+       if (panel->backlight.combination_mode) {
+               u8 lbpc;
 
-               if (is_backlight_combination_mode(dev))
-                       max *= 0xff;
+               pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc);
+               val *= lbpc;
        }
 
-       DRM_DEBUG_DRIVER("max backlight PWM = %d\n", max);
-
-       return max;
+       return val;
 }
 
-static int i915_panel_invert_brightness;
-MODULE_PARM_DESC(invert_brightness, "Invert backlight brightness "
-       "(-1 force normal, 0 machine defaults, 1 force inversion), please "
-       "report PCI device ID, subsystem vendor and subsystem device ID "
-       "to dri-devel@lists.freedesktop.org, if your machine needs it. "
-       "It will then be included in an upcoming module version.");
-module_param_named(invert_brightness, i915_panel_invert_brightness, int, 0600);
-static u32 intel_panel_compute_brightness(struct drm_device *dev,
-                                         enum pipe pipe, u32 val)
+static u32 _vlv_get_backlight(struct drm_device *dev, enum pipe pipe)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       if (i915_panel_invert_brightness < 0)
-               return val;
+       return I915_READ(VLV_BLC_PWM_CTL(pipe)) & BACKLIGHT_DUTY_CYCLE_MASK;
+}
 
-       if (i915_panel_invert_brightness > 0 ||
-           dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) {
-               u32 max = intel_panel_get_max_backlight(dev, pipe);
-               if (max)
-                       return max - val;
-       }
+static u32 vlv_get_backlight(struct intel_connector *connector)
+{
+       struct drm_device *dev = connector->base.dev;
+       enum pipe pipe = intel_get_pipe_from_connector(connector);
 
-       return val;
+       return _vlv_get_backlight(dev, pipe);
 }
 
-static u32 intel_panel_get_backlight(struct drm_device *dev,
-                                    enum pipe pipe)
+static u32 intel_panel_get_backlight(struct intel_connector *connector)
 {
+       struct drm_device *dev = connector->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 val;
        unsigned long flags;
-       int reg;
-
-       spin_lock_irqsave(&dev_priv->backlight.lock, flags);
-
-       if (HAS_PCH_SPLIT(dev)) {
-               val = I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
-       } else {
-               if (IS_VALLEYVIEW(dev))
-                       reg = VLV_BLC_PWM_CTL(pipe);
-               else
-                       reg = BLC_PWM_CTL;
-
-               val = I915_READ(reg) & BACKLIGHT_DUTY_CYCLE_MASK;
-               if (INTEL_INFO(dev)->gen < 4)
-                       val >>= 1;
-
-               if (is_backlight_combination_mode(dev)) {
-                       u8 lbpc;
 
-                       pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc);
-                       val *= lbpc;
-               }
-       }
+       spin_lock_irqsave(&dev_priv->backlight_lock, flags);
 
-       val = intel_panel_compute_brightness(dev, pipe, val);
+       val = dev_priv->display.get_backlight(connector);
+       val = intel_panel_compute_brightness(connector, val);
 
-       spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
+       spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
 
        DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val);
        return val;
 }
 
-static void intel_pch_panel_set_backlight(struct drm_device *dev, u32 level)
+static void bdw_set_backlight(struct intel_connector *connector, u32 level)
 {
+       struct drm_device *dev = connector->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 val = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
-       I915_WRITE(BLC_PWM_CPU_CTL, val | level);
+       u32 val = I915_READ(BLC_PWM_PCH_CTL2) & ~BACKLIGHT_DUTY_CYCLE_MASK;
+       I915_WRITE(BLC_PWM_PCH_CTL2, val | level);
 }
 
-static void intel_panel_actually_set_backlight(struct drm_device *dev,
-                                              enum pipe pipe, u32 level)
+static void pch_set_backlight(struct intel_connector *connector, u32 level)
 {
+       struct drm_device *dev = connector->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 tmp;
-       int reg;
 
-       DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level);
-       level = intel_panel_compute_brightness(dev, pipe, level);
+       tmp = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
+       I915_WRITE(BLC_PWM_CPU_CTL, tmp | level);
+}
+
+static void i9xx_set_backlight(struct intel_connector *connector, u32 level)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
+       u32 tmp, mask;
 
-       if (HAS_PCH_SPLIT(dev))
-               return intel_pch_panel_set_backlight(dev, level);
+       WARN_ON(panel->backlight.max == 0);
 
-       if (is_backlight_combination_mode(dev)) {
-               u32 max = intel_panel_get_max_backlight(dev, pipe);
+       if (panel->backlight.combination_mode) {
                u8 lbpc;
 
-               /* we're screwed, but keep behaviour backwards compatible */
-               if (!max)
-                       max = 1;
-
-               lbpc = level * 0xfe / max + 1;
+               lbpc = level * 0xfe / panel->backlight.max + 1;
                level /= lbpc;
                pci_write_config_byte(dev->pdev, PCI_LBPC, lbpc);
        }
 
-       if (IS_VALLEYVIEW(dev))
-               reg = VLV_BLC_PWM_CTL(pipe);
-       else
-               reg = BLC_PWM_CTL;
-
-       tmp = I915_READ(reg);
-       if (INTEL_INFO(dev)->gen < 4)
+       if (IS_GEN4(dev)) {
+               mask = BACKLIGHT_DUTY_CYCLE_MASK;
+       } else {
                level <<= 1;
-       tmp &= ~BACKLIGHT_DUTY_CYCLE_MASK;
-       I915_WRITE(reg, tmp | level);
+               mask = BACKLIGHT_DUTY_CYCLE_MASK_PNV;
+       }
+
+       tmp = I915_READ(BLC_PWM_CTL) & ~mask;
+       I915_WRITE(BLC_PWM_CTL, tmp | level);
+}
+
+static void vlv_set_backlight(struct intel_connector *connector, u32 level)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       enum pipe pipe = intel_get_pipe_from_connector(connector);
+       u32 tmp;
+
+       tmp = I915_READ(VLV_BLC_PWM_CTL(pipe)) & ~BACKLIGHT_DUTY_CYCLE_MASK;
+       I915_WRITE(VLV_BLC_PWM_CTL(pipe), tmp | level);
+}
+
+static void
+intel_panel_actually_set_backlight(struct intel_connector *connector, u32 level)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level);
+
+       level = intel_panel_compute_brightness(connector, level);
+       dev_priv->display.set_backlight(connector, level);
 }
 
 /* set backlight brightness to level in range [0..max] */
@@ -530,6 +497,7 @@ void intel_panel_set_backlight(struct intel_connector *connector, u32 level,
 {
        struct drm_device *dev = connector->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
        enum pipe pipe = intel_get_pipe_from_connector(connector);
        u32 freq;
        unsigned long flags;
@@ -537,34 +505,77 @@ void intel_panel_set_backlight(struct intel_connector *connector, u32 level,
        if (pipe == INVALID_PIPE)
                return;
 
-       spin_lock_irqsave(&dev_priv->backlight.lock, flags);
+       spin_lock_irqsave(&dev_priv->backlight_lock, flags);
 
-       freq = intel_panel_get_max_backlight(dev, pipe);
-       if (!freq) {
-               /* we are screwed, bail out */
-               goto out;
-       }
+       WARN_ON(panel->backlight.max == 0);
 
-       /* scale to hardware, but be careful to not overflow */
+       /* scale to hardware max, but be careful to not overflow */
+       freq = panel->backlight.max;
        if (freq < max)
                level = level * freq / max;
        else
                level = freq / max * level;
 
-       dev_priv->backlight.level = level;
-       if (dev_priv->backlight.device)
-               dev_priv->backlight.device->props.brightness = level;
+       panel->backlight.level = level;
+       if (panel->backlight.device)
+               panel->backlight.device->props.brightness = level;
 
-       if (dev_priv->backlight.enabled)
-               intel_panel_actually_set_backlight(dev, pipe, level);
-out:
-       spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
+       if (panel->backlight.enabled)
+               intel_panel_actually_set_backlight(connector, level);
+
+       spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
+}
+
+static void pch_disable_backlight(struct intel_connector *connector)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 tmp;
+
+       intel_panel_actually_set_backlight(connector, 0);
+
+       tmp = I915_READ(BLC_PWM_CPU_CTL2);
+       I915_WRITE(BLC_PWM_CPU_CTL2, tmp & ~BLM_PWM_ENABLE);
+
+       tmp = I915_READ(BLC_PWM_PCH_CTL1);
+       I915_WRITE(BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE);
+}
+
+static void i9xx_disable_backlight(struct intel_connector *connector)
+{
+       intel_panel_actually_set_backlight(connector, 0);
+}
+
+static void i965_disable_backlight(struct intel_connector *connector)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 tmp;
+
+       intel_panel_actually_set_backlight(connector, 0);
+
+       tmp = I915_READ(BLC_PWM_CTL2);
+       I915_WRITE(BLC_PWM_CTL2, tmp & ~BLM_PWM_ENABLE);
+}
+
+static void vlv_disable_backlight(struct intel_connector *connector)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       enum pipe pipe = intel_get_pipe_from_connector(connector);
+       u32 tmp;
+
+       intel_panel_actually_set_backlight(connector, 0);
+
+       tmp = I915_READ(VLV_BLC_PWM_CTL2(pipe));
+       I915_WRITE(VLV_BLC_PWM_CTL2(pipe), tmp & ~BLM_PWM_ENABLE);
 }
 
 void intel_panel_disable_backlight(struct intel_connector *connector)
 {
        struct drm_device *dev = connector->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
        enum pipe pipe = intel_get_pipe_from_connector(connector);
        unsigned long flags;
 
@@ -582,141 +593,215 @@ void intel_panel_disable_backlight(struct intel_connector *connector)
                return;
        }
 
-       spin_lock_irqsave(&dev_priv->backlight.lock, flags);
+       spin_lock_irqsave(&dev_priv->backlight_lock, flags);
 
-       dev_priv->backlight.enabled = false;
-       intel_panel_actually_set_backlight(dev, pipe, 0);
+       panel->backlight.enabled = false;
+       dev_priv->display.disable_backlight(connector);
 
-       if (INTEL_INFO(dev)->gen >= 4) {
-               uint32_t reg, tmp;
+       spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
+}
 
-               if (HAS_PCH_SPLIT(dev))
-                       reg = BLC_PWM_CPU_CTL2;
-               else if (IS_VALLEYVIEW(dev))
-                       reg = VLV_BLC_PWM_CTL2(pipe);
-               else
-                       reg = BLC_PWM_CTL2;
+static void bdw_enable_backlight(struct intel_connector *connector)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
+       u32 pch_ctl1, pch_ctl2;
+
+       pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
+       if (pch_ctl1 & BLM_PCH_PWM_ENABLE) {
+               DRM_DEBUG_KMS("pch backlight already enabled\n");
+               pch_ctl1 &= ~BLM_PCH_PWM_ENABLE;
+               I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
+       }
 
-               I915_WRITE(reg, I915_READ(reg) & ~BLM_PWM_ENABLE);
+       pch_ctl2 = panel->backlight.max << 16;
+       I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2);
 
-               if (HAS_PCH_SPLIT(dev)) {
-                       tmp = I915_READ(BLC_PWM_PCH_CTL1);
-                       tmp &= ~BLM_PCH_PWM_ENABLE;
-                       I915_WRITE(BLC_PWM_PCH_CTL1, tmp);
-               }
-       }
+       pch_ctl1 = 0;
+       if (panel->backlight.active_low_pwm)
+               pch_ctl1 |= BLM_PCH_POLARITY;
+
+       /* BDW always uses the pch pwm controls. */
+       pch_ctl1 |= BLM_PCH_OVERRIDE_ENABLE;
+
+       I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
+       POSTING_READ(BLC_PWM_PCH_CTL1);
+       I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE);
 
-       spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
+       /* This won't stick until the above enable. */
+       intel_panel_actually_set_backlight(connector, panel->backlight.level);
 }
 
-void intel_panel_enable_backlight(struct intel_connector *connector)
+static void pch_enable_backlight(struct intel_connector *connector)
 {
        struct drm_device *dev = connector->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
        enum pipe pipe = intel_get_pipe_from_connector(connector);
        enum transcoder cpu_transcoder =
                intel_pipe_to_cpu_transcoder(dev_priv, pipe);
-       unsigned long flags;
+       u32 cpu_ctl2, pch_ctl1, pch_ctl2;
 
-       if (pipe == INVALID_PIPE)
-               return;
+       cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2);
+       if (cpu_ctl2 & BLM_PWM_ENABLE) {
+               WARN(1, "cpu backlight already enabled\n");
+               cpu_ctl2 &= ~BLM_PWM_ENABLE;
+               I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2);
+       }
 
-       DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe));
+       pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
+       if (pch_ctl1 & BLM_PCH_PWM_ENABLE) {
+               DRM_DEBUG_KMS("pch backlight already enabled\n");
+               pch_ctl1 &= ~BLM_PCH_PWM_ENABLE;
+               I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
+       }
+
+       if (cpu_transcoder == TRANSCODER_EDP)
+               cpu_ctl2 = BLM_TRANSCODER_EDP;
+       else
+               cpu_ctl2 = BLM_PIPE(cpu_transcoder);
+       I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2);
+       POSTING_READ(BLC_PWM_CPU_CTL2);
+       I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2 | BLM_PWM_ENABLE);
+
+       /* This won't stick until the above enable. */
+       intel_panel_actually_set_backlight(connector, panel->backlight.level);
 
-       spin_lock_irqsave(&dev_priv->backlight.lock, flags);
+       pch_ctl2 = panel->backlight.max << 16;
+       I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2);
 
-       if (dev_priv->backlight.level == 0) {
-               dev_priv->backlight.level = intel_panel_get_max_backlight(dev,
-                                                                         pipe);
-               if (dev_priv->backlight.device)
-                       dev_priv->backlight.device->props.brightness =
-                               dev_priv->backlight.level;
+       pch_ctl1 = 0;
+       if (panel->backlight.active_low_pwm)
+               pch_ctl1 |= BLM_PCH_POLARITY;
+
+       I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
+       POSTING_READ(BLC_PWM_PCH_CTL1);
+       I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE);
+}
+
+static void i9xx_enable_backlight(struct intel_connector *connector)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
+       u32 ctl, freq;
+
+       ctl = I915_READ(BLC_PWM_CTL);
+       if (ctl & BACKLIGHT_DUTY_CYCLE_MASK_PNV) {
+               WARN(1, "backlight already enabled\n");
+               I915_WRITE(BLC_PWM_CTL, 0);
        }
 
-       if (INTEL_INFO(dev)->gen >= 4) {
-               uint32_t reg, tmp;
+       freq = panel->backlight.max;
+       if (panel->backlight.combination_mode)
+               freq /= 0xff;
 
-               if (HAS_PCH_SPLIT(dev))
-                       reg = BLC_PWM_CPU_CTL2;
-               else if (IS_VALLEYVIEW(dev))
-                       reg = VLV_BLC_PWM_CTL2(pipe);
-               else
-                       reg = BLC_PWM_CTL2;
+       ctl = freq << 17;
+       if (IS_GEN2(dev) && panel->backlight.combination_mode)
+               ctl |= BLM_LEGACY_MODE;
+       if (IS_PINEVIEW(dev) && panel->backlight.active_low_pwm)
+               ctl |= BLM_POLARITY_PNV;
 
-               tmp = I915_READ(reg);
+       I915_WRITE(BLC_PWM_CTL, ctl);
+       POSTING_READ(BLC_PWM_CTL);
 
-               /* Note that this can also get called through dpms changes. And
-                * we don't track the backlight dpms state, hence check whether
-                * we have to do anything first. */
-               if (tmp & BLM_PWM_ENABLE)
-                       goto set_level;
+       /* XXX: combine this into above write? */
+       intel_panel_actually_set_backlight(connector, panel->backlight.level);
+}
 
-               if (INTEL_INFO(dev)->num_pipes == 3)
-                       tmp &= ~BLM_PIPE_SELECT_IVB;
-               else
-                       tmp &= ~BLM_PIPE_SELECT;
+static void i965_enable_backlight(struct intel_connector *connector)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
+       enum pipe pipe = intel_get_pipe_from_connector(connector);
+       u32 ctl, ctl2, freq;
 
-               if (cpu_transcoder == TRANSCODER_EDP)
-                       tmp |= BLM_TRANSCODER_EDP;
-               else
-                       tmp |= BLM_PIPE(cpu_transcoder);
-               tmp &= ~BLM_PWM_ENABLE;
-
-               I915_WRITE(reg, tmp);
-               POSTING_READ(reg);
-               I915_WRITE(reg, tmp | BLM_PWM_ENABLE);
-
-               if (HAS_PCH_SPLIT(dev) &&
-                   !(dev_priv->quirks & QUIRK_NO_PCH_PWM_ENABLE)) {
-                       tmp = I915_READ(BLC_PWM_PCH_CTL1);
-                       tmp |= BLM_PCH_PWM_ENABLE;
-                       tmp &= ~BLM_PCH_OVERRIDE_ENABLE;
-                       I915_WRITE(BLC_PWM_PCH_CTL1, tmp);
-               }
+       ctl2 = I915_READ(BLC_PWM_CTL2);
+       if (ctl2 & BLM_PWM_ENABLE) {
+               WARN(1, "backlight already enabled\n");
+               ctl2 &= ~BLM_PWM_ENABLE;
+               I915_WRITE(BLC_PWM_CTL2, ctl2);
        }
 
-set_level:
-       /* Call below after setting BLC_PWM_CPU_CTL2 and BLC_PWM_PCH_CTL1.
-        * BLC_PWM_CPU_CTL may be cleared to zero automatically when these
-        * registers are set.
-        */
-       dev_priv->backlight.enabled = true;
-       intel_panel_actually_set_backlight(dev, pipe,
-                                          dev_priv->backlight.level);
+       freq = panel->backlight.max;
+       if (panel->backlight.combination_mode)
+               freq /= 0xff;
+
+       ctl = freq << 16;
+       I915_WRITE(BLC_PWM_CTL, ctl);
 
-       spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
+       /* XXX: combine this into above write? */
+       intel_panel_actually_set_backlight(connector, panel->backlight.level);
+
+       ctl2 = BLM_PIPE(pipe);
+       if (panel->backlight.combination_mode)
+               ctl2 |= BLM_COMBINATION_MODE;
+       if (panel->backlight.active_low_pwm)
+               ctl2 |= BLM_POLARITY_I965;
+       I915_WRITE(BLC_PWM_CTL2, ctl2);
+       POSTING_READ(BLC_PWM_CTL2);
+       I915_WRITE(BLC_PWM_CTL2, ctl2 | BLM_PWM_ENABLE);
 }
 
-/* FIXME: use VBT vals to init PWM_CTL and PWM_CTL2 correctly */
-static void intel_panel_init_backlight_regs(struct drm_device *dev)
+static void vlv_enable_backlight(struct intel_connector *connector)
 {
+       struct drm_device *dev = connector->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
+       enum pipe pipe = intel_get_pipe_from_connector(connector);
+       u32 ctl, ctl2;
 
-       if (IS_VALLEYVIEW(dev)) {
-               enum pipe pipe;
+       ctl2 = I915_READ(VLV_BLC_PWM_CTL2(pipe));
+       if (ctl2 & BLM_PWM_ENABLE) {
+               WARN(1, "backlight already enabled\n");
+               ctl2 &= ~BLM_PWM_ENABLE;
+               I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2);
+       }
 
-               for_each_pipe(pipe) {
-                       u32 cur_val = I915_READ(VLV_BLC_PWM_CTL(pipe));
+       ctl = panel->backlight.max << 16;
+       I915_WRITE(VLV_BLC_PWM_CTL(pipe), ctl);
 
-                       /* Skip if the modulation freq is already set */
-                       if (cur_val & ~BACKLIGHT_DUTY_CYCLE_MASK)
-                               continue;
+       /* XXX: combine this into above write? */
+       intel_panel_actually_set_backlight(connector, panel->backlight.level);
 
-                       cur_val &= BACKLIGHT_DUTY_CYCLE_MASK;
-                       I915_WRITE(VLV_BLC_PWM_CTL(pipe), (0xf42 << 16) |
-                                  cur_val);
-               }
-       }
+       ctl2 = 0;
+       if (panel->backlight.active_low_pwm)
+               ctl2 |= BLM_POLARITY_I965;
+       I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2);
+       POSTING_READ(VLV_BLC_PWM_CTL2(pipe));
+       I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2 | BLM_PWM_ENABLE);
 }
 
-static void intel_panel_init_backlight(struct drm_device *dev)
+void intel_panel_enable_backlight(struct intel_connector *connector)
 {
+       struct drm_device *dev = connector->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
+       enum pipe pipe = intel_get_pipe_from_connector(connector);
+       unsigned long flags;
+
+       if (pipe == INVALID_PIPE)
+               return;
+
+       DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe));
+
+       spin_lock_irqsave(&dev_priv->backlight_lock, flags);
+
+       WARN_ON(panel->backlight.max == 0);
 
-       intel_panel_init_backlight_regs(dev);
+       if (panel->backlight.level == 0) {
+               panel->backlight.level = panel->backlight.max;
+               if (panel->backlight.device)
+                       panel->backlight.device->props.brightness =
+                               panel->backlight.level;
+       }
+
+       dev_priv->display.enable_backlight(connector);
+       panel->backlight.enabled = true;
 
-       dev_priv->backlight.level = intel_panel_get_backlight(dev, 0);
-       dev_priv->backlight.enabled = dev_priv->backlight.level != 0;
+       spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
 }
 
 enum drm_connector_status
@@ -742,7 +827,7 @@ intel_panel_detect(struct drm_device *dev)
 }
 
 #if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE)
-static int intel_panel_update_status(struct backlight_device *bd)
+static int intel_backlight_device_update_status(struct backlight_device *bd)
 {
        struct intel_connector *connector = bl_get_data(bd);
        struct drm_device *dev = connector->base.dev;
@@ -756,85 +841,362 @@ static int intel_panel_update_status(struct backlight_device *bd)
        return 0;
 }
 
-static int intel_panel_get_brightness(struct backlight_device *bd)
+static int intel_backlight_device_get_brightness(struct backlight_device *bd)
 {
        struct intel_connector *connector = bl_get_data(bd);
        struct drm_device *dev = connector->base.dev;
-       enum pipe pipe;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int ret;
 
+       intel_runtime_pm_get(dev_priv);
        mutex_lock(&dev->mode_config.mutex);
-       pipe = intel_get_pipe_from_connector(connector);
+       ret = intel_panel_get_backlight(connector);
        mutex_unlock(&dev->mode_config.mutex);
-       if (pipe == INVALID_PIPE)
-               return 0;
+       intel_runtime_pm_put(dev_priv);
 
-       return intel_panel_get_backlight(connector->base.dev, pipe);
+       return ret;
 }
 
-static const struct backlight_ops intel_panel_bl_ops = {
-       .update_status = intel_panel_update_status,
-       .get_brightness = intel_panel_get_brightness,
+static const struct backlight_ops intel_backlight_device_ops = {
+       .update_status = intel_backlight_device_update_status,
+       .get_brightness = intel_backlight_device_get_brightness,
 };
 
-int intel_panel_setup_backlight(struct drm_connector *connector)
+static int intel_backlight_device_register(struct intel_connector *connector)
 {
-       struct drm_device *dev = connector->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
        struct backlight_properties props;
-       unsigned long flags;
-
-       intel_panel_init_backlight(dev);
 
-       if (WARN_ON(dev_priv->backlight.device))
+       if (WARN_ON(panel->backlight.device))
                return -ENODEV;
 
+       BUG_ON(panel->backlight.max == 0);
+
        memset(&props, 0, sizeof(props));
        props.type = BACKLIGHT_RAW;
-       props.brightness = dev_priv->backlight.level;
-
-       spin_lock_irqsave(&dev_priv->backlight.lock, flags);
-       props.max_brightness = intel_panel_get_max_backlight(dev, 0);
-       spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
+       props.brightness = panel->backlight.level;
+       props.max_brightness = panel->backlight.max;
 
-       if (props.max_brightness == 0) {
-               DRM_DEBUG_DRIVER("Failed to get maximum backlight value\n");
-               return -ENODEV;
-       }
-       dev_priv->backlight.device =
+       /*
+        * Note: using the same name independent of the connector prevents
+        * registration of multiple backlight devices in the driver.
+        */
+       panel->backlight.device =
                backlight_device_register("intel_backlight",
-                                         connector->kdev,
-                                         to_intel_connector(connector),
-                                         &intel_panel_bl_ops, &props);
+                                         connector->base.kdev,
+                                         connector,
+                                         &intel_backlight_device_ops, &props);
 
-       if (IS_ERR(dev_priv->backlight.device)) {
+       if (IS_ERR(panel->backlight.device)) {
                DRM_ERROR("Failed to register backlight: %ld\n",
-                         PTR_ERR(dev_priv->backlight.device));
-               dev_priv->backlight.device = NULL;
+                         PTR_ERR(panel->backlight.device));
+               panel->backlight.device = NULL;
                return -ENODEV;
        }
        return 0;
 }
 
-void intel_panel_destroy_backlight(struct drm_device *dev)
+static void intel_backlight_device_unregister(struct intel_connector *connector)
+{
+       struct intel_panel *panel = &connector->panel;
+
+       if (panel->backlight.device) {
+               backlight_device_unregister(panel->backlight.device);
+               panel->backlight.device = NULL;
+       }
+}
+#else /* CONFIG_BACKLIGHT_CLASS_DEVICE */
+static int intel_backlight_device_register(struct intel_connector *connector)
+{
+       return 0;
+}
+static void intel_backlight_device_unregister(struct intel_connector *connector)
+{
+}
+#endif /* CONFIG_BACKLIGHT_CLASS_DEVICE */
+
+/*
+ * Note: The setup hooks can't assume pipe is set!
+ *
+ * XXX: Query mode clock or hardware clock and program PWM modulation frequency
+ * appropriately when it's 0. Use VBT and/or sane defaults.
+ */
+static int bdw_setup_backlight(struct intel_connector *connector)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
+       u32 pch_ctl1, pch_ctl2, val;
+
+       pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
+       panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY;
+
+       pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2);
+       panel->backlight.max = pch_ctl2 >> 16;
+       if (!panel->backlight.max)
+               return -ENODEV;
+
+       val = bdw_get_backlight(connector);
+       panel->backlight.level = intel_panel_compute_brightness(connector, val);
+
+       panel->backlight.enabled = (pch_ctl1 & BLM_PCH_PWM_ENABLE) &&
+               panel->backlight.level != 0;
+
+       return 0;
+}
+
+static int pch_setup_backlight(struct intel_connector *connector)
 {
+       struct drm_device *dev = connector->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       if (dev_priv->backlight.device) {
-               backlight_device_unregister(dev_priv->backlight.device);
-               dev_priv->backlight.device = NULL;
+       struct intel_panel *panel = &connector->panel;
+       u32 cpu_ctl2, pch_ctl1, pch_ctl2, val;
+
+       pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
+       panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY;
+
+       pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2);
+       panel->backlight.max = pch_ctl2 >> 16;
+       if (!panel->backlight.max)
+               return -ENODEV;
+
+       val = pch_get_backlight(connector);
+       panel->backlight.level = intel_panel_compute_brightness(connector, val);
+
+       cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2);
+       panel->backlight.enabled = (cpu_ctl2 & BLM_PWM_ENABLE) &&
+               (pch_ctl1 & BLM_PCH_PWM_ENABLE) && panel->backlight.level != 0;
+
+       return 0;
+}
+
+static int i9xx_setup_backlight(struct intel_connector *connector)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
+       u32 ctl, val;
+
+       ctl = I915_READ(BLC_PWM_CTL);
+
+       if (IS_GEN2(dev))
+               panel->backlight.combination_mode = ctl & BLM_LEGACY_MODE;
+
+       if (IS_PINEVIEW(dev))
+               panel->backlight.active_low_pwm = ctl & BLM_POLARITY_PNV;
+
+       panel->backlight.max = ctl >> 17;
+       if (panel->backlight.combination_mode)
+               panel->backlight.max *= 0xff;
+
+       if (!panel->backlight.max)
+               return -ENODEV;
+
+       val = i9xx_get_backlight(connector);
+       panel->backlight.level = intel_panel_compute_brightness(connector, val);
+
+       panel->backlight.enabled = panel->backlight.level != 0;
+
+       return 0;
+}
+
+static int i965_setup_backlight(struct intel_connector *connector)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
+       u32 ctl, ctl2, val;
+
+       ctl2 = I915_READ(BLC_PWM_CTL2);
+       panel->backlight.combination_mode = ctl2 & BLM_COMBINATION_MODE;
+       panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965;
+
+       ctl = I915_READ(BLC_PWM_CTL);
+       panel->backlight.max = ctl >> 16;
+       if (panel->backlight.combination_mode)
+               panel->backlight.max *= 0xff;
+
+       if (!panel->backlight.max)
+               return -ENODEV;
+
+       val = i9xx_get_backlight(connector);
+       panel->backlight.level = intel_panel_compute_brightness(connector, val);
+
+       panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) &&
+               panel->backlight.level != 0;
+
+       return 0;
+}
+
+static int vlv_setup_backlight(struct intel_connector *connector)
+{
+       struct drm_device *dev = connector->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_panel *panel = &connector->panel;
+       enum pipe pipe;
+       u32 ctl, ctl2, val;
+
+       for_each_pipe(pipe) {
+               u32 cur_val = I915_READ(VLV_BLC_PWM_CTL(pipe));
+
+               /* Skip if the modulation freq is already set */
+               if (cur_val & ~BACKLIGHT_DUTY_CYCLE_MASK)
+                       continue;
+
+               cur_val &= BACKLIGHT_DUTY_CYCLE_MASK;
+               I915_WRITE(VLV_BLC_PWM_CTL(pipe), (0xf42 << 16) |
+                          cur_val);
        }
+
+       ctl2 = I915_READ(VLV_BLC_PWM_CTL2(PIPE_A));
+       panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965;
+
+       ctl = I915_READ(VLV_BLC_PWM_CTL(PIPE_A));
+       panel->backlight.max = ctl >> 16;
+       if (!panel->backlight.max)
+               return -ENODEV;
+
+       val = _vlv_get_backlight(dev, PIPE_A);
+       panel->backlight.level = intel_panel_compute_brightness(connector, val);
+
+       panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) &&
+               panel->backlight.level != 0;
+
+       return 0;
 }
-#else
+
 int intel_panel_setup_backlight(struct drm_connector *connector)
 {
-       intel_panel_init_backlight(connector->dev);
+       struct drm_device *dev = connector->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_connector *intel_connector = to_intel_connector(connector);
+       struct intel_panel *panel = &intel_connector->panel;
+       unsigned long flags;
+       int ret;
+
+       /* set level and max in panel struct */
+       spin_lock_irqsave(&dev_priv->backlight_lock, flags);
+       ret = dev_priv->display.setup_backlight(intel_connector);
+       spin_unlock_irqrestore(&dev_priv->backlight_lock, flags);
+
+       if (ret) {
+               DRM_DEBUG_KMS("failed to setup backlight for connector %s\n",
+                             drm_get_connector_name(connector));
+               return ret;
+       }
+
+       intel_backlight_device_register(intel_connector);
+
+       panel->backlight.present = true;
+
+       DRM_DEBUG_KMS("backlight initialized, %s, brightness %u/%u, "
+                     "sysfs interface %sregistered\n",
+                     panel->backlight.enabled ? "enabled" : "disabled",
+                     panel->backlight.level, panel->backlight.max,
+                     panel->backlight.device ? "" : "not ");
+
        return 0;
 }
 
-void intel_panel_destroy_backlight(struct drm_device *dev)
+void intel_panel_destroy_backlight(struct drm_connector *connector)
 {
-       return;
+       struct intel_connector *intel_connector = to_intel_connector(connector);
+       struct intel_panel *panel = &intel_connector->panel;
+
+       panel->backlight.present = false;
+       intel_backlight_device_unregister(intel_connector);
+}
+
+/**
+ * intel_find_panel_downclock - find the reduced downclock for LVDS in EDID
+ * @dev: drm device
+ * @fixed_mode : panel native mode
+ * @connector: LVDS/eDP connector
+ *
+ * Return downclock_avail
+ * Find the reduced downclock for LVDS/eDP in EDID.
+ */
+struct drm_display_mode *
+intel_find_panel_downclock(struct drm_device *dev,
+                       struct drm_display_mode *fixed_mode,
+                       struct drm_connector *connector)
+{
+       struct drm_display_mode *scan, *tmp_mode;
+       int temp_downclock;
+
+       temp_downclock = fixed_mode->clock;
+       tmp_mode = NULL;
+
+       list_for_each_entry(scan, &connector->probed_modes, head) {
+               /*
+                * If one mode has the same resolution with the fixed_panel
+                * mode while they have the different refresh rate, it means
+                * that the reduced downclock is found. In such
+                * case we can set the different FPx0/1 to dynamically select
+                * between low and high frequency.
+                */
+               if (scan->hdisplay == fixed_mode->hdisplay &&
+                   scan->hsync_start == fixed_mode->hsync_start &&
+                   scan->hsync_end == fixed_mode->hsync_end &&
+                   scan->htotal == fixed_mode->htotal &&
+                   scan->vdisplay == fixed_mode->vdisplay &&
+                   scan->vsync_start == fixed_mode->vsync_start &&
+                   scan->vsync_end == fixed_mode->vsync_end &&
+                   scan->vtotal == fixed_mode->vtotal) {
+                       if (scan->clock < temp_downclock) {
+                               /*
+                                * The downclock is already found. But we
+                                * expect to find the lower downclock.
+                                */
+                               temp_downclock = scan->clock;
+                               tmp_mode = scan;
+                       }
+               }
+       }
+
+       if (temp_downclock < fixed_mode->clock)
+               return drm_mode_duplicate(dev, tmp_mode);
+       else
+               return NULL;
+}
+
+/* Set up chip specific backlight functions */
+void intel_panel_init_backlight_funcs(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (IS_BROADWELL(dev)) {
+               dev_priv->display.setup_backlight = bdw_setup_backlight;
+               dev_priv->display.enable_backlight = bdw_enable_backlight;
+               dev_priv->display.disable_backlight = pch_disable_backlight;
+               dev_priv->display.set_backlight = bdw_set_backlight;
+               dev_priv->display.get_backlight = bdw_get_backlight;
+       } else if (HAS_PCH_SPLIT(dev)) {
+               dev_priv->display.setup_backlight = pch_setup_backlight;
+               dev_priv->display.enable_backlight = pch_enable_backlight;
+               dev_priv->display.disable_backlight = pch_disable_backlight;
+               dev_priv->display.set_backlight = pch_set_backlight;
+               dev_priv->display.get_backlight = pch_get_backlight;
+       } else if (IS_VALLEYVIEW(dev)) {
+               dev_priv->display.setup_backlight = vlv_setup_backlight;
+               dev_priv->display.enable_backlight = vlv_enable_backlight;
+               dev_priv->display.disable_backlight = vlv_disable_backlight;
+               dev_priv->display.set_backlight = vlv_set_backlight;
+               dev_priv->display.get_backlight = vlv_get_backlight;
+       } else if (IS_GEN4(dev)) {
+               dev_priv->display.setup_backlight = i965_setup_backlight;
+               dev_priv->display.enable_backlight = i965_enable_backlight;
+               dev_priv->display.disable_backlight = i965_disable_backlight;
+               dev_priv->display.set_backlight = i9xx_set_backlight;
+               dev_priv->display.get_backlight = i9xx_get_backlight;
+       } else {
+               dev_priv->display.setup_backlight = i9xx_setup_backlight;
+               dev_priv->display.enable_backlight = i9xx_enable_backlight;
+               dev_priv->display.disable_backlight = i9xx_disable_backlight;
+               dev_priv->display.set_backlight = i9xx_set_backlight;
+               dev_priv->display.get_backlight = i9xx_get_backlight;
+       }
 }
-#endif
 
 int intel_panel_init(struct intel_panel *panel,
                     struct drm_display_mode *fixed_mode)
@@ -851,4 +1213,8 @@ void intel_panel_fini(struct intel_panel *panel)
 
        if (panel->fixed_mode)
                drm_mode_destroy(intel_connector->base.dev, panel->fixed_mode);
+
+       if (panel->downclock_mode)
+               drm_mode_destroy(intel_connector->base.dev,
+                               panel->downclock_mode);
 }
index caf2ee4e5441426527234453dbb43ed4c4c7273f..c01d08d8e76f7bb9b833800d4237fd733781eedf 100644 (file)
@@ -31,6 +31,7 @@
 #include "../../../platform/x86/intel_ips.h"
 #include <linux/module.h>
 #include <drm/i915_powerwell.h>
+#include <linux/pm_runtime.h>
 
 /**
  * RC6 is a special power stage which allows the GPU to enter an very
@@ -191,7 +192,11 @@ static void sandybridge_blit_fbc_update(struct drm_device *dev)
        u32 blt_ecoskpd;
 
        /* Make sure blitter notifies FBC of writes */
-       gen6_gt_force_wake_get(dev_priv);
+
+       /* Blitter is part of Media powerwell on VLV. No impact of
+        * his param in other platforms for now */
+       gen6_gt_force_wake_get(dev_priv, FORCEWAKE_MEDIA);
+
        blt_ecoskpd = I915_READ(GEN6_BLITTER_ECOSKPD);
        blt_ecoskpd |= GEN6_BLITTER_FBC_NOTIFY <<
                GEN6_BLITTER_LOCK_SHIFT;
@@ -202,7 +207,8 @@ static void sandybridge_blit_fbc_update(struct drm_device *dev)
                         GEN6_BLITTER_LOCK_SHIFT);
        I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd);
        POSTING_READ(GEN6_BLITTER_ECOSKPD);
-       gen6_gt_force_wake_put(dev_priv);
+
+       gen6_gt_force_wake_put(dev_priv, FORCEWAKE_MEDIA);
 }
 
 static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
@@ -222,7 +228,9 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
        dpfc_ctl |= (plane | DPFC_CTL_LIMIT_1X);
        /* Set persistent mode for front-buffer rendering, ala X. */
        dpfc_ctl |= DPFC_CTL_PERSISTENT_MODE;
-       dpfc_ctl |= (DPFC_CTL_FENCE_EN | obj->fence_reg);
+       dpfc_ctl |= DPFC_CTL_FENCE_EN;
+       if (IS_GEN5(dev))
+               dpfc_ctl |= obj->fence_reg;
        I915_WRITE(ILK_DPFC_CHICKEN, DPFC_HT_MODIFY);
 
        I915_WRITE(ILK_DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN |
@@ -295,7 +303,7 @@ static void gen7_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
 
        sandybridge_blit_fbc_update(dev);
 
-       DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane);
+       DRM_DEBUG_KMS("enabled fbc on plane %c\n", plane_name(intel_crtc->plane));
 }
 
 bool intel_fbc_enabled(struct drm_device *dev)
@@ -530,10 +538,10 @@ void intel_update_fbc(struct drm_device *dev)
                        DRM_DEBUG_KMS("mode too large for compression, disabling\n");
                goto out_disable;
        }
-       if ((IS_I915GM(dev) || IS_I945GM(dev) || IS_HASWELL(dev)) &&
-           intel_crtc->plane != 0) {
+       if ((INTEL_INFO(dev)->gen < 4 || IS_HASWELL(dev)) &&
+           intel_crtc->plane != PLANE_A) {
                if (set_no_fbc_reason(dev_priv, FBC_BAD_PLANE))
-                       DRM_DEBUG_KMS("plane not 0, disabling compression\n");
+                       DRM_DEBUG_KMS("plane not A, disabling compression\n");
                goto out_disable;
        }
 
@@ -1180,7 +1188,7 @@ static bool g4x_compute_wm0(struct drm_device *dev,
 
        adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode;
        clock = adjusted_mode->crtc_clock;
-       htotal = adjusted_mode->htotal;
+       htotal = adjusted_mode->crtc_htotal;
        hdisplay = to_intel_crtc(crtc)->config.pipe_src_w;
        pixel_size = crtc->fb->bits_per_pixel / 8;
 
@@ -1267,7 +1275,7 @@ static bool g4x_compute_srwm(struct drm_device *dev,
        crtc = intel_get_crtc_for_plane(dev, plane);
        adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode;
        clock = adjusted_mode->crtc_clock;
-       htotal = adjusted_mode->htotal;
+       htotal = adjusted_mode->crtc_htotal;
        hdisplay = to_intel_crtc(crtc)->config.pipe_src_w;
        pixel_size = crtc->fb->bits_per_pixel / 8;
 
@@ -1498,7 +1506,7 @@ static void i965_update_wm(struct drm_crtc *unused_crtc)
                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 htotal = adjusted_mode->crtc_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;
@@ -1624,7 +1632,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
                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 htotal = adjusted_mode->crtc_htotal;
                int hdisplay = to_intel_crtc(enabled)->config.pipe_src_w;
                int pixel_size = enabled->fb->bits_per_pixel / 8;
                unsigned long line_time_us;
@@ -1776,7 +1784,7 @@ static bool ironlake_compute_srwm(struct drm_device *dev, int level, int plane,
        crtc = intel_get_crtc_for_plane(dev, plane);
        adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode;
        clock = adjusted_mode->crtc_clock;
-       htotal = adjusted_mode->htotal;
+       htotal = adjusted_mode->crtc_htotal;
        hdisplay = to_intel_crtc(crtc)->config.pipe_src_w;
        pixel_size = crtc->fb->bits_per_pixel / 8;
 
@@ -2469,8 +2477,9 @@ hsw_compute_linetime_wm(struct drm_device *dev, struct drm_crtc *crtc)
        /* The WM are computed with base on how long it takes to fill a single
         * row at the given clock rate, multiplied by 8.
         * */
-       linetime = DIV_ROUND_CLOSEST(mode->htotal * 1000 * 8, mode->clock);
-       ips_linetime = DIV_ROUND_CLOSEST(mode->htotal * 1000 * 8,
+       linetime = DIV_ROUND_CLOSEST(mode->crtc_htotal * 1000 * 8,
+                                    mode->crtc_clock);
+       ips_linetime = DIV_ROUND_CLOSEST(mode->crtc_htotal * 1000 * 8,
                                         intel_ddi_get_cdclk_freq(dev_priv));
 
        return PIPE_WM_LINETIME_IPS_LINETIME(ips_linetime) |
@@ -3429,26 +3438,19 @@ static void ironlake_disable_drps(struct drm_device *dev)
  * ourselves, instead of doing a rmw cycle (which might result in us clearing
  * all limits and the gpu stuck at whatever frequency it is at atm).
  */
-static u32 gen6_rps_limits(struct drm_i915_private *dev_priv, u8 *val)
+static u32 gen6_rps_limits(struct drm_i915_private *dev_priv, u8 val)
 {
        u32 limits;
 
-       limits = 0;
-
-       if (*val >= dev_priv->rps.max_delay)
-               *val = dev_priv->rps.max_delay;
-       limits |= dev_priv->rps.max_delay << 24;
-
        /* Only set the down limit when we've reached the lowest level to avoid
         * getting more interrupts, otherwise leave this clear. This prevents a
         * race in the hw when coming out of rc6: There's a tiny window where
         * the hw runs at the minimal clock before selecting the desired
         * frequency, if the down threshold expires in that window we will not
         * receive a down interrupt. */
-       if (*val <= dev_priv->rps.min_delay) {
-               *val = dev_priv->rps.min_delay;
+       limits = dev_priv->rps.max_delay << 24;
+       if (val <= dev_priv->rps.min_delay)
                limits |= dev_priv->rps.min_delay << 16;
-       }
 
        return limits;
 }
@@ -3548,7 +3550,6 @@ static void gen6_set_rps_thresholds(struct drm_i915_private *dev_priv, u8 val)
 void gen6_set_rps(struct drm_device *dev, u8 val)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 limits = gen6_rps_limits(dev_priv, &val);
 
        WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
        WARN_ON(val > dev_priv->rps.max_delay);
@@ -3571,7 +3572,8 @@ void gen6_set_rps(struct drm_device *dev, u8 val)
        /* Make sure we continue to get interrupts
         * until we hit the minimum or maximum frequencies.
         */
-       I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, limits);
+       I915_WRITE(GEN6_RP_INTERRUPT_LIMITS,
+                  gen6_rps_limits(dev_priv, val));
 
        POSTING_READ(GEN6_RPNSWREQ);
 
@@ -3606,48 +3608,18 @@ void gen6_rps_boost(struct drm_i915_private *dev_priv)
        mutex_unlock(&dev_priv->rps.hw_lock);
 }
 
-/*
- * Wait until the previous freq change has completed,
- * or the timeout elapsed, and then update our notion
- * of the current GPU frequency.
- */
-static void vlv_update_rps_cur_delay(struct drm_i915_private *dev_priv)
-{
-       u32 pval;
-
-       WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
-
-       if (wait_for(((pval = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS)) & GENFREQSTATUS) == 0, 10))
-               DRM_DEBUG_DRIVER("timed out waiting for Punit\n");
-
-       pval >>= 8;
-
-       if (pval != dev_priv->rps.cur_delay)
-               DRM_DEBUG_DRIVER("Punit overrode GPU freq: %d MHz (%u) requested, but got %d Mhz (%u)\n",
-                                vlv_gpu_freq(dev_priv->mem_freq, dev_priv->rps.cur_delay),
-                                dev_priv->rps.cur_delay,
-                                vlv_gpu_freq(dev_priv->mem_freq, pval), pval);
-
-       dev_priv->rps.cur_delay = pval;
-}
-
 void valleyview_set_rps(struct drm_device *dev, u8 val)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       gen6_rps_limits(dev_priv, &val);
-
        WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
        WARN_ON(val > dev_priv->rps.max_delay);
        WARN_ON(val < dev_priv->rps.min_delay);
 
-       vlv_update_rps_cur_delay(dev_priv);
-
        DRM_DEBUG_DRIVER("GPU freq request from %d MHz (%u) to %d MHz (%u)\n",
-                        vlv_gpu_freq(dev_priv->mem_freq,
-                                     dev_priv->rps.cur_delay),
+                        vlv_gpu_freq(dev_priv, dev_priv->rps.cur_delay),
                         dev_priv->rps.cur_delay,
-                        vlv_gpu_freq(dev_priv->mem_freq, val), val);
+                        vlv_gpu_freq(dev_priv, val), val);
 
        if (val == dev_priv->rps.cur_delay)
                return;
@@ -3656,7 +3628,7 @@ void valleyview_set_rps(struct drm_device *dev, u8 val)
 
        dev_priv->rps.cur_delay = val;
 
-       trace_intel_gpu_freq_change(vlv_gpu_freq(dev_priv->mem_freq, val));
+       trace_intel_gpu_freq_change(vlv_gpu_freq(dev_priv, val));
 }
 
 static void gen6_disable_rps_interrupts(struct drm_device *dev)
@@ -3774,7 +3746,7 @@ static void gen8_enable_rps(struct drm_device *dev)
 
        /* 1c & 1d: Get forcewake during program sequence. Although the driver
         * hasn't enabled a state yet where we need forcewake, BIOS may have.*/
-       gen6_gt_force_wake_get(dev_priv);
+       gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
 
        /* 2a: Disable RC states. */
        I915_WRITE(GEN6_RC_CONTROL, 0);
@@ -3831,7 +3803,7 @@ static void gen8_enable_rps(struct drm_device *dev)
 
        gen6_enable_rps_interrupts(dev);
 
-       gen6_gt_force_wake_put(dev_priv);
+       gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
 }
 
 static void gen6_enable_rps(struct drm_device *dev)
@@ -3861,7 +3833,7 @@ static void gen6_enable_rps(struct drm_device *dev)
                I915_WRITE(GTFIFODBG, gtfifodbg);
        }
 
-       gen6_gt_force_wake_get(dev_priv);
+       gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
 
        rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
        gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
@@ -3953,7 +3925,7 @@ static void gen6_enable_rps(struct drm_device *dev)
                        DRM_ERROR("Couldn't fix incorrect rc6 voltage\n");
        }
 
-       gen6_gt_force_wake_put(dev_priv);
+       gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
 }
 
 void gen6_update_ring_freq(struct drm_device *dev)
@@ -4115,7 +4087,8 @@ static void valleyview_enable_rps(struct drm_device *dev)
 
        valleyview_setup_pctx(dev);
 
-       gen6_gt_force_wake_get(dev_priv);
+       /* If VLV, Forcewake all wells, else re-direct to regular path */
+       gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
 
        I915_WRITE(GEN6_RP_UP_THRESHOLD, 59400);
        I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 245000);
@@ -4139,7 +4112,7 @@ static void valleyview_enable_rps(struct drm_device *dev)
        for_each_ring(ring, dev_priv, i)
                I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
 
-       I915_WRITE(GEN6_RC6_THRESHOLD, 0xc350);
+       I915_WRITE(GEN6_RC6_THRESHOLD, 0x557);
 
        /* allows RC6 residency counter to work */
        I915_WRITE(VLV_COUNTER_CONTROL,
@@ -4147,65 +4120,47 @@ static void valleyview_enable_rps(struct drm_device *dev)
                                      VLV_MEDIA_RC6_COUNT_EN |
                                      VLV_RENDER_RC6_COUNT_EN));
        if (intel_enable_rc6(dev) & INTEL_RC6_ENABLE)
-               rc6_mode = GEN7_RC_CTL_TO_MODE;
+               rc6_mode = GEN7_RC_CTL_TO_MODE | VLV_RC_CTL_CTX_RST_PARALLEL;
 
        intel_print_rc6_info(dev, rc6_mode);
 
        I915_WRITE(GEN6_RC_CONTROL, rc6_mode);
 
        val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
-       switch ((val >> 6) & 3) {
-       case 0:
-       case 1:
-               dev_priv->mem_freq = 800;
-               break;
-       case 2:
-               dev_priv->mem_freq = 1066;
-               break;
-       case 3:
-               dev_priv->mem_freq = 1333;
-               break;
-       }
-       DRM_DEBUG_DRIVER("DDR speed: %d MHz", dev_priv->mem_freq);
 
        DRM_DEBUG_DRIVER("GPLL enabled? %s\n", val & 0x10 ? "yes" : "no");
        DRM_DEBUG_DRIVER("GPU status: 0x%08x\n", val);
 
        dev_priv->rps.cur_delay = (val >> 8) & 0xff;
        DRM_DEBUG_DRIVER("current GPU freq: %d MHz (%u)\n",
-                        vlv_gpu_freq(dev_priv->mem_freq,
-                                     dev_priv->rps.cur_delay),
+                        vlv_gpu_freq(dev_priv, dev_priv->rps.cur_delay),
                         dev_priv->rps.cur_delay);
 
        dev_priv->rps.max_delay = valleyview_rps_max_freq(dev_priv);
        dev_priv->rps.hw_max = dev_priv->rps.max_delay;
        DRM_DEBUG_DRIVER("max GPU freq: %d MHz (%u)\n",
-                        vlv_gpu_freq(dev_priv->mem_freq,
-                                     dev_priv->rps.max_delay),
+                        vlv_gpu_freq(dev_priv, dev_priv->rps.max_delay),
                         dev_priv->rps.max_delay);
 
        dev_priv->rps.rpe_delay = valleyview_rps_rpe_freq(dev_priv);
        DRM_DEBUG_DRIVER("RPe GPU freq: %d MHz (%u)\n",
-                        vlv_gpu_freq(dev_priv->mem_freq,
-                                     dev_priv->rps.rpe_delay),
+                        vlv_gpu_freq(dev_priv, dev_priv->rps.rpe_delay),
                         dev_priv->rps.rpe_delay);
 
        dev_priv->rps.min_delay = valleyview_rps_min_freq(dev_priv);
        DRM_DEBUG_DRIVER("min GPU freq: %d MHz (%u)\n",
-                        vlv_gpu_freq(dev_priv->mem_freq,
-                                     dev_priv->rps.min_delay),
+                        vlv_gpu_freq(dev_priv, dev_priv->rps.min_delay),
                         dev_priv->rps.min_delay);
 
        DRM_DEBUG_DRIVER("setting GPU freq to %d MHz (%u)\n",
-                        vlv_gpu_freq(dev_priv->mem_freq,
-                                     dev_priv->rps.rpe_delay),
+                        vlv_gpu_freq(dev_priv, dev_priv->rps.rpe_delay),
                         dev_priv->rps.rpe_delay);
 
        valleyview_set_rps(dev_priv->dev, dev_priv->rps.rpe_delay);
 
        gen6_enable_rps_interrupts(dev);
 
-       gen6_gt_force_wake_put(dev_priv);
+       gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
 }
 
 void ironlake_teardown_rc6(struct drm_device *dev)
@@ -5462,6 +5417,26 @@ static void ivybridge_init_clock_gating(struct drm_device *dev)
 static void valleyview_init_clock_gating(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 val;
+
+       mutex_lock(&dev_priv->rps.hw_lock);
+       val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
+       mutex_unlock(&dev_priv->rps.hw_lock);
+       switch ((val >> 6) & 3) {
+       case 0:
+               dev_priv->mem_freq = 800;
+               break;
+       case 1:
+               dev_priv->mem_freq = 1066;
+               break;
+       case 2:
+               dev_priv->mem_freq = 1333;
+               break;
+       case 3:
+               dev_priv->mem_freq = 1333;
+               break;
+       }
+       DRM_DEBUG_DRIVER("DDR speed: %d MHz", dev_priv->mem_freq);
 
        I915_WRITE(DSPCLK_GATE_D, VRHUNIT_CLOCK_GATE_DISABLE);
 
@@ -5641,51 +5616,82 @@ void intel_suspend_hw(struct drm_device *dev)
                lpt_suspend_hw(dev);
 }
 
-static bool is_always_on_power_domain(struct drm_device *dev,
-                                     enum intel_display_power_domain domain)
-{
-       unsigned long always_on_domains;
-
-       BUG_ON(BIT(domain) & ~POWER_DOMAIN_MASK);
+#define for_each_power_well(i, power_well, domain_mask, power_domains) \
+       for (i = 0;                                                     \
+            i < (power_domains)->power_well_count &&                   \
+                ((power_well) = &(power_domains)->power_wells[i]);     \
+            i++)                                                       \
+               if ((power_well)->domains & (domain_mask))
 
-       if (IS_BROADWELL(dev)) {
-               always_on_domains = BDW_ALWAYS_ON_POWER_DOMAINS;
-       } else if (IS_HASWELL(dev)) {
-               always_on_domains = HSW_ALWAYS_ON_POWER_DOMAINS;
-       } else {
-               WARN_ON(1);
-               return true;
-       }
-
-       return BIT(domain) & always_on_domains;
-}
+#define for_each_power_well_rev(i, power_well, domain_mask, power_domains) \
+       for (i = (power_domains)->power_well_count - 1;                  \
+            i >= 0 && ((power_well) = &(power_domains)->power_wells[i]);\
+            i--)                                                        \
+               if ((power_well)->domains & (domain_mask))
 
 /**
  * We should only use the power well if we explicitly asked the hardware to
  * enable it, so check if it's enabled and also check if we've requested it to
  * be enabled.
  */
+static bool hsw_power_well_enabled(struct drm_device *dev,
+                                  struct i915_power_well *power_well)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       return I915_READ(HSW_PWR_WELL_DRIVER) ==
+                    (HSW_PWR_WELL_ENABLE_REQUEST | HSW_PWR_WELL_STATE_ENABLED);
+}
+
+bool intel_display_power_enabled_sw(struct drm_device *dev,
+                                   enum intel_display_power_domain domain)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct i915_power_domains *power_domains;
+
+       power_domains = &dev_priv->power_domains;
+
+       return power_domains->domain_use_count[domain];
+}
+
 bool intel_display_power_enabled(struct drm_device *dev,
                                 enum intel_display_power_domain domain)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
+       struct i915_power_domains *power_domains;
+       struct i915_power_well *power_well;
+       bool is_enabled;
+       int i;
+
+       power_domains = &dev_priv->power_domains;
 
-       if (!HAS_POWER_WELL(dev))
-               return true;
+       is_enabled = true;
 
-       if (is_always_on_power_domain(dev, domain))
-               return true;
+       mutex_lock(&power_domains->lock);
+       for_each_power_well_rev(i, power_well, BIT(domain), power_domains) {
+               if (power_well->always_on)
+                       continue;
 
-       return I915_READ(HSW_PWR_WELL_DRIVER) ==
-                    (HSW_PWR_WELL_ENABLE_REQUEST | HSW_PWR_WELL_STATE_ENABLED);
+               if (!power_well->is_enabled(dev, power_well)) {
+                       is_enabled = false;
+                       break;
+               }
+       }
+       mutex_unlock(&power_domains->lock);
+
+       return is_enabled;
 }
 
-static void __intel_set_power_well(struct drm_device *dev, bool enable)
+static void hsw_set_power_well(struct drm_device *dev,
+                              struct i915_power_well *power_well, bool enable)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        bool is_enabled, enable_requested;
+       unsigned long irqflags;
        uint32_t tmp;
 
+       WARN_ON(dev_priv->pc8.enabled);
+
        tmp = I915_READ(HSW_PWR_WELL_DRIVER);
        is_enabled = tmp & HSW_PWR_WELL_STATE_ENABLED;
        enable_requested = tmp & HSW_PWR_WELL_ENABLE_REQUEST;
@@ -5701,9 +5707,24 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable)
                                      HSW_PWR_WELL_STATE_ENABLED), 20))
                                DRM_ERROR("Timeout enabling power well\n");
                }
+
+               if (IS_BROADWELL(dev)) {
+                       spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+                       I915_WRITE(GEN8_DE_PIPE_IMR(PIPE_B),
+                                  dev_priv->de_irq_mask[PIPE_B]);
+                       I915_WRITE(GEN8_DE_PIPE_IER(PIPE_B),
+                                  ~dev_priv->de_irq_mask[PIPE_B] |
+                                  GEN8_PIPE_VBLANK);
+                       I915_WRITE(GEN8_DE_PIPE_IMR(PIPE_C),
+                                  dev_priv->de_irq_mask[PIPE_C]);
+                       I915_WRITE(GEN8_DE_PIPE_IER(PIPE_C),
+                                  ~dev_priv->de_irq_mask[PIPE_C] |
+                                  GEN8_PIPE_VBLANK);
+                       POSTING_READ(GEN8_DE_PIPE_IER(PIPE_C));
+                       spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+               }
        } else {
                if (enable_requested) {
-                       unsigned long irqflags;
                        enum pipe p;
 
                        I915_WRITE(HSW_PWR_WELL_DRIVER, 0);
@@ -5730,16 +5751,26 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable)
 static void __intel_power_well_get(struct drm_device *dev,
                                   struct i915_power_well *power_well)
 {
-       if (!power_well->count++)
-               __intel_set_power_well(dev, true);
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (!power_well->count++ && power_well->set) {
+               hsw_disable_package_c8(dev_priv);
+               power_well->set(dev, power_well, true);
+       }
 }
 
 static void __intel_power_well_put(struct drm_device *dev,
                                   struct i915_power_well *power_well)
 {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
        WARN_ON(!power_well->count);
-       if (!--power_well->count && i915_disable_power_well)
-               __intel_set_power_well(dev, false);
+
+       if (!--power_well->count && power_well->set &&
+           i915_disable_power_well) {
+               power_well->set(dev, power_well, false);
+               hsw_enable_package_c8(dev_priv);
+       }
 }
 
 void intel_display_power_get(struct drm_device *dev,
@@ -5747,17 +5778,18 @@ void intel_display_power_get(struct drm_device *dev,
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct i915_power_domains *power_domains;
-
-       if (!HAS_POWER_WELL(dev))
-               return;
-
-       if (is_always_on_power_domain(dev, domain))
-               return;
+       struct i915_power_well *power_well;
+       int i;
 
        power_domains = &dev_priv->power_domains;
 
        mutex_lock(&power_domains->lock);
-       __intel_power_well_get(dev, &power_domains->power_wells[0]);
+
+       for_each_power_well(i, power_well, BIT(domain), power_domains)
+               __intel_power_well_get(dev, power_well);
+
+       power_domains->domain_use_count[domain]++;
+
        mutex_unlock(&power_domains->lock);
 }
 
@@ -5766,17 +5798,19 @@ void intel_display_power_put(struct drm_device *dev,
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct i915_power_domains *power_domains;
-
-       if (!HAS_POWER_WELL(dev))
-               return;
-
-       if (is_always_on_power_domain(dev, domain))
-               return;
+       struct i915_power_well *power_well;
+       int i;
 
        power_domains = &dev_priv->power_domains;
 
        mutex_lock(&power_domains->lock);
-       __intel_power_well_put(dev, &power_domains->power_wells[0]);
+
+       WARN_ON(!power_domains->domain_use_count[domain]);
+       power_domains->domain_use_count[domain]--;
+
+       for_each_power_well_rev(i, power_well, BIT(domain), power_domains)
+               __intel_power_well_put(dev, power_well);
+
        mutex_unlock(&power_domains->lock);
 }
 
@@ -5792,10 +5826,7 @@ void i915_request_power_well(void)
 
        dev_priv = container_of(hsw_pwr, struct drm_i915_private,
                                power_domains);
-
-       mutex_lock(&hsw_pwr->lock);
-       __intel_power_well_get(dev_priv->dev, &hsw_pwr->power_wells[0]);
-       mutex_unlock(&hsw_pwr->lock);
+       intel_display_power_get(dev_priv->dev, POWER_DOMAIN_AUDIO);
 }
 EXPORT_SYMBOL_GPL(i915_request_power_well);
 
@@ -5809,24 +5840,71 @@ void i915_release_power_well(void)
 
        dev_priv = container_of(hsw_pwr, struct drm_i915_private,
                                power_domains);
-
-       mutex_lock(&hsw_pwr->lock);
-       __intel_power_well_put(dev_priv->dev, &hsw_pwr->power_wells[0]);
-       mutex_unlock(&hsw_pwr->lock);
+       intel_display_power_put(dev_priv->dev, POWER_DOMAIN_AUDIO);
 }
 EXPORT_SYMBOL_GPL(i915_release_power_well);
 
+static struct i915_power_well i9xx_always_on_power_well[] = {
+       {
+               .name = "always-on",
+               .always_on = 1,
+               .domains = POWER_DOMAIN_MASK,
+       },
+};
+
+static struct i915_power_well hsw_power_wells[] = {
+       {
+               .name = "always-on",
+               .always_on = 1,
+               .domains = HSW_ALWAYS_ON_POWER_DOMAINS,
+       },
+       {
+               .name = "display",
+               .domains = POWER_DOMAIN_MASK & ~HSW_ALWAYS_ON_POWER_DOMAINS,
+               .is_enabled = hsw_power_well_enabled,
+               .set = hsw_set_power_well,
+       },
+};
+
+static struct i915_power_well bdw_power_wells[] = {
+       {
+               .name = "always-on",
+               .always_on = 1,
+               .domains = BDW_ALWAYS_ON_POWER_DOMAINS,
+       },
+       {
+               .name = "display",
+               .domains = POWER_DOMAIN_MASK & ~BDW_ALWAYS_ON_POWER_DOMAINS,
+               .is_enabled = hsw_power_well_enabled,
+               .set = hsw_set_power_well,
+       },
+};
+
+#define set_power_wells(power_domains, __power_wells) ({               \
+       (power_domains)->power_wells = (__power_wells);                 \
+       (power_domains)->power_well_count = ARRAY_SIZE(__power_wells);  \
+})
+
 int intel_power_domains_init(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct i915_power_domains *power_domains = &dev_priv->power_domains;
-       struct i915_power_well *power_well;
 
        mutex_init(&power_domains->lock);
-       hsw_pwr = power_domains;
 
-       power_well = &power_domains->power_wells[0];
-       power_well->count = 0;
+       /*
+        * The enabling order will be from lower to higher indexed wells,
+        * the disabling order is reversed.
+        */
+       if (IS_HASWELL(dev)) {
+               set_power_wells(power_domains, hsw_power_wells);
+               hsw_pwr = power_domains;
+       } else if (IS_BROADWELL(dev)) {
+               set_power_wells(power_domains, bdw_power_wells);
+               hsw_pwr = power_domains;
+       } else {
+               set_power_wells(power_domains, i9xx_always_on_power_well);
+       }
 
        return 0;
 }
@@ -5841,15 +5919,13 @@ static void intel_power_domains_resume(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct i915_power_domains *power_domains = &dev_priv->power_domains;
        struct i915_power_well *power_well;
-
-       if (!HAS_POWER_WELL(dev))
-               return;
+       int i;
 
        mutex_lock(&power_domains->lock);
-
-       power_well = &power_domains->power_wells[0];
-       __intel_set_power_well(dev, power_well->count > 0);
-
+       for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) {
+               if (power_well->set)
+                       power_well->set(dev, power_well, power_well->count > 0);
+       }
        mutex_unlock(&power_domains->lock);
 }
 
@@ -5863,13 +5939,13 @@ void intel_power_domains_init_hw(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       if (!HAS_POWER_WELL(dev))
-               return;
-
        /* For now, we need the power well to be always enabled. */
        intel_display_set_init_power(dev, true);
        intel_power_domains_resume(dev);
 
+       if (!(IS_HASWELL(dev) || IS_BROADWELL(dev)))
+               return;
+
        /* We're taking over the BIOS, so clear any requests made by it since
         * the driver is in charge now. */
        if (I915_READ(HSW_PWR_WELL_BIOS) & HSW_PWR_WELL_ENABLE_REQUEST)
@@ -5887,31 +5963,83 @@ void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv)
        hsw_enable_package_c8(dev_priv);
 }
 
+void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
+{
+       struct drm_device *dev = dev_priv->dev;
+       struct device *device = &dev->pdev->dev;
+
+       if (!HAS_RUNTIME_PM(dev))
+               return;
+
+       pm_runtime_get_sync(device);
+       WARN(dev_priv->pm.suspended, "Device still suspended.\n");
+}
+
+void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
+{
+       struct drm_device *dev = dev_priv->dev;
+       struct device *device = &dev->pdev->dev;
+
+       if (!HAS_RUNTIME_PM(dev))
+               return;
+
+       pm_runtime_mark_last_busy(device);
+       pm_runtime_put_autosuspend(device);
+}
+
+void intel_init_runtime_pm(struct drm_i915_private *dev_priv)
+{
+       struct drm_device *dev = dev_priv->dev;
+       struct device *device = &dev->pdev->dev;
+
+       dev_priv->pm.suspended = false;
+
+       if (!HAS_RUNTIME_PM(dev))
+               return;
+
+       pm_runtime_set_active(device);
+
+       pm_runtime_set_autosuspend_delay(device, 10000); /* 10s */
+       pm_runtime_mark_last_busy(device);
+       pm_runtime_use_autosuspend(device);
+}
+
+void intel_fini_runtime_pm(struct drm_i915_private *dev_priv)
+{
+       struct drm_device *dev = dev_priv->dev;
+       struct device *device = &dev->pdev->dev;
+
+       if (!HAS_RUNTIME_PM(dev))
+               return;
+
+       /* Make sure we're not suspended first. */
+       pm_runtime_get_sync(device);
+       pm_runtime_disable(device);
+}
+
 /* Set up chip specific power management-related functions */
 void intel_init_pm(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
        if (I915_HAS_FBC(dev)) {
-               if (HAS_PCH_SPLIT(dev)) {
+               if (INTEL_INFO(dev)->gen >= 7) {
                        dev_priv->display.fbc_enabled = ironlake_fbc_enabled;
-                       if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
-                               dev_priv->display.enable_fbc =
-                                       gen7_enable_fbc;
-                       else
-                               dev_priv->display.enable_fbc =
-                                       ironlake_enable_fbc;
+                       dev_priv->display.enable_fbc = gen7_enable_fbc;
+                       dev_priv->display.disable_fbc = ironlake_disable_fbc;
+               } else if (INTEL_INFO(dev)->gen >= 5) {
+                       dev_priv->display.fbc_enabled = ironlake_fbc_enabled;
+                       dev_priv->display.enable_fbc = ironlake_enable_fbc;
                        dev_priv->display.disable_fbc = ironlake_disable_fbc;
                } else if (IS_GM45(dev)) {
                        dev_priv->display.fbc_enabled = g4x_fbc_enabled;
                        dev_priv->display.enable_fbc = g4x_enable_fbc;
                        dev_priv->display.disable_fbc = g4x_disable_fbc;
-               } else if (IS_CRESTLINE(dev)) {
+               } else {
                        dev_priv->display.fbc_enabled = i8xx_fbc_enabled;
                        dev_priv->display.enable_fbc = i8xx_enable_fbc;
                        dev_priv->display.disable_fbc = i8xx_disable_fbc;
                }
-               /* 855GM needs testing */
        }
 
        /* For cxsr */
@@ -6074,65 +6202,63 @@ int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val)
        return 0;
 }
 
-int vlv_gpu_freq(int ddr_freq, int val)
+int vlv_gpu_freq(struct drm_i915_private *dev_priv, int val)
 {
-       int mult, base;
+       int div;
 
-       switch (ddr_freq) {
+       /* 4 x czclk */
+       switch (dev_priv->mem_freq) {
        case 800:
-               mult = 20;
-               base = 120;
+               div = 10;
                break;
        case 1066:
-               mult = 22;
-               base = 133;
+               div = 12;
                break;
        case 1333:
-               mult = 21;
-               base = 125;
+               div = 16;
                break;
        default:
                return -1;
        }
 
-       return ((val - 0xbd) * mult) + base;
+       return DIV_ROUND_CLOSEST(dev_priv->mem_freq * (val + 6 - 0xbd), 4 * div);
 }
 
-int vlv_freq_opcode(int ddr_freq, int val)
+int vlv_freq_opcode(struct drm_i915_private *dev_priv, int val)
 {
-       int mult, base;
+       int mul;
 
-       switch (ddr_freq) {
+       /* 4 x czclk */
+       switch (dev_priv->mem_freq) {
        case 800:
-               mult = 20;
-               base = 120;
+               mul = 10;
                break;
        case 1066:
-               mult = 22;
-               base = 133;
+               mul = 12;
                break;
        case 1333:
-               mult = 21;
-               base = 125;
+               mul = 16;
                break;
        default:
                return -1;
        }
 
-       val /= mult;
-       val -= base / mult;
-       val += 0xbd;
-
-       if (val > 0xea)
-               val = 0xea;
-
-       return val;
+       return DIV_ROUND_CLOSEST(4 * mul * val, dev_priv->mem_freq) + 0xbd - 6;
 }
 
-void intel_pm_init(struct drm_device *dev)
+void intel_pm_setup(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
+       mutex_init(&dev_priv->rps.hw_lock);
+
+       mutex_init(&dev_priv->pc8.lock);
+       dev_priv->pc8.requirements_met = false;
+       dev_priv->pc8.gpu_idle = false;
+       dev_priv->pc8.irqs_disabled = false;
+       dev_priv->pc8.enabled = false;
+       dev_priv->pc8.disable_count = 2; /* requirements_met + gpu_idle */
+       INIT_DELAYED_WORK(&dev_priv->pc8.enable_work, hsw_enable_pc8_work);
        INIT_DELAYED_WORK(&dev_priv->rps.delayed_resume_work,
                          intel_gen6_powersave_work);
 }
index b620337e6d672c164448090016a27d1b713a2a24..e05a0216cd9b19755a34f711051b8b9c35459b8a 100644 (file)
@@ -285,14 +285,16 @@ static int gen7_ring_fbc_flush(struct intel_ring_buffer *ring, u32 value)
        if (!ring->fbc_dirty)
                return 0;
 
-       ret = intel_ring_begin(ring, 4);
+       ret = intel_ring_begin(ring, 6);
        if (ret)
                return ret;
-       intel_ring_emit(ring, MI_NOOP);
        /* WaFbcNukeOn3DBlt:ivb/hsw */
        intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
        intel_ring_emit(ring, MSG_FBC_REND_STATE);
        intel_ring_emit(ring, value);
+       intel_ring_emit(ring, MI_STORE_REGISTER_MEM(1) | MI_SRM_LRM_GLOBAL_GTT);
+       intel_ring_emit(ring, MSG_FBC_REND_STATE);
+       intel_ring_emit(ring, ring->scratch.gtt_offset + 256);
        intel_ring_advance(ring);
 
        ring->fbc_dirty = false;
@@ -354,7 +356,7 @@ gen7_render_ring_flush(struct intel_ring_buffer *ring,
        intel_ring_emit(ring, 0);
        intel_ring_advance(ring);
 
-       if (flush_domains)
+       if (!invalidate_domains && flush_domains)
                return gen7_ring_fbc_flush(ring, FBC_REND_NUKE);
 
        return 0;
@@ -436,7 +438,7 @@ static int init_ring_common(struct intel_ring_buffer *ring)
        int ret = 0;
        u32 head;
 
-       gen6_gt_force_wake_get(dev_priv);
+       gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
 
        if (I915_NEED_GFX_HWS(dev))
                intel_ring_setup_status_page(ring);
@@ -509,7 +511,7 @@ static int init_ring_common(struct intel_ring_buffer *ring)
        memset(&ring->hangcheck, 0, sizeof(ring->hangcheck));
 
 out:
-       gen6_gt_force_wake_put(dev_priv);
+       gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);
 
        return ret;
 }
@@ -965,6 +967,7 @@ void intel_ring_setup_status_page(struct intel_ring_buffer *ring)
        } else if (IS_GEN6(ring->dev)) {
                mmio = RING_HWS_PGA_GEN6(ring->mmio_base);
        } else {
+               /* XXX: gen8 returns to sanity */
                mmio = RING_HWS_PGA(ring->mmio_base);
        }
 
@@ -1029,11 +1032,6 @@ gen6_ring_get_irq(struct intel_ring_buffer *ring)
        if (!dev->irq_enabled)
               return false;
 
-       /* It looks like we need to prevent the gt from suspending while waiting
-        * for an notifiy irq, otherwise irqs seem to get lost on at least the
-        * blt/bsd rings on ivb. */
-       gen6_gt_force_wake_get(dev_priv);
-
        spin_lock_irqsave(&dev_priv->irq_lock, flags);
        if (ring->irq_refcount++ == 0) {
                if (HAS_L3_DPF(dev) && ring->id == RCS)
@@ -1065,8 +1063,6 @@ gen6_ring_put_irq(struct intel_ring_buffer *ring)
                ilk_disable_gt_irq(dev_priv, ring->irq_enable_mask);
        }
        spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
-
-       gen6_gt_force_wake_put(dev_priv);
 }
 
 static bool
@@ -1837,7 +1833,7 @@ static int gen6_ring_flush(struct intel_ring_buffer *ring,
        }
        intel_ring_advance(ring);
 
-       if (IS_GEN7(dev) && flush)
+       if (IS_GEN7(dev) && !invalidate && flush)
                return gen7_ring_fbc_flush(ring, FBC_REND_CACHE_CLEAN);
 
        return 0;
index a583e8f718a7f0f4b87b4fe724336c73ad1a8198..95bdfb3c431c8467b105c616f6d5f9567505804f 100644 (file)
@@ -413,23 +413,34 @@ static const struct _sdvo_cmd_name {
 static void intel_sdvo_debug_write(struct intel_sdvo *intel_sdvo, u8 cmd,
                                   const void *args, int args_len)
 {
-       int i;
+       int i, pos = 0;
+#define BUF_LEN 256
+       char buffer[BUF_LEN];
+
+#define BUF_PRINT(args...) \
+       pos += snprintf(buffer + pos, max_t(int, BUF_LEN - pos, 0), args)
+
 
-       DRM_DEBUG_KMS("%s: W: %02X ",
-                               SDVO_NAME(intel_sdvo), cmd);
-       for (i = 0; i < args_len; i++)
-               DRM_LOG_KMS("%02X ", ((u8 *)args)[i]);
-       for (; i < 8; i++)
-               DRM_LOG_KMS("   ");
+       for (i = 0; i < args_len; i++) {
+               BUF_PRINT("%02X ", ((u8 *)args)[i]);
+       }
+       for (; i < 8; i++) {
+               BUF_PRINT("   ");
+       }
        for (i = 0; i < ARRAY_SIZE(sdvo_cmd_names); i++) {
                if (cmd == sdvo_cmd_names[i].cmd) {
-                       DRM_LOG_KMS("(%s)", sdvo_cmd_names[i].name);
+                       BUF_PRINT("(%s)", sdvo_cmd_names[i].name);
                        break;
                }
        }
-       if (i == ARRAY_SIZE(sdvo_cmd_names))
-               DRM_LOG_KMS("(%02X)", cmd);
-       DRM_LOG_KMS("\n");
+       if (i == ARRAY_SIZE(sdvo_cmd_names)) {
+               BUF_PRINT("(%02X)", cmd);
+       }
+       BUG_ON(pos >= BUF_LEN - 1);
+#undef BUF_PRINT
+#undef BUF_LEN
+
+       DRM_DEBUG_KMS("%s: W: %02X %s\n", SDVO_NAME(intel_sdvo), cmd, buffer);
 }
 
 static const char *cmd_status_names[] = {
@@ -512,9 +523,10 @@ static bool intel_sdvo_read_response(struct intel_sdvo *intel_sdvo,
 {
        u8 retry = 15; /* 5 quick checks, followed by 10 long checks */
        u8 status;
-       int i;
+       int i, pos = 0;
+#define BUF_LEN 256
+       char buffer[BUF_LEN];
 
-       DRM_DEBUG_KMS("%s: R: ", SDVO_NAME(intel_sdvo));
 
        /*
         * The documentation states that all commands will be
@@ -551,10 +563,13 @@ static bool intel_sdvo_read_response(struct intel_sdvo *intel_sdvo,
                        goto log_fail;
        }
 
+#define BUF_PRINT(args...) \
+       pos += snprintf(buffer + pos, max_t(int, BUF_LEN - pos, 0), args)
+
        if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP)
-               DRM_LOG_KMS("(%s)", cmd_status_names[status]);
+               BUF_PRINT("(%s)", cmd_status_names[status]);
        else
-               DRM_LOG_KMS("(??? %d)", status);
+               BUF_PRINT("(??? %d)", status);
 
        if (status != SDVO_CMD_STATUS_SUCCESS)
                goto log_fail;
@@ -565,13 +580,17 @@ static bool intel_sdvo_read_response(struct intel_sdvo *intel_sdvo,
                                          SDVO_I2C_RETURN_0 + i,
                                          &((u8 *)response)[i]))
                        goto log_fail;
-               DRM_LOG_KMS(" %02X", ((u8 *)response)[i]);
+               BUF_PRINT(" %02X", ((u8 *)response)[i]);
        }
-       DRM_LOG_KMS("\n");
+       BUG_ON(pos >= BUF_LEN - 1);
+#undef BUF_PRINT
+#undef BUF_LEN
+
+       DRM_DEBUG_KMS("%s: R: %s\n", SDVO_NAME(intel_sdvo), buffer);
        return true;
 
 log_fail:
-       DRM_LOG_KMS("... failed\n");
+       DRM_DEBUG_KMS("%s: R: ... failed\n", SDVO_NAME(intel_sdvo));
        return false;
 }
 
@@ -933,7 +952,7 @@ static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo)
 
 static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo,
                                       unsigned if_index, uint8_t tx_rate,
-                                      uint8_t *data, unsigned length)
+                                      const uint8_t *data, unsigned length)
 {
        uint8_t set_buf_index[2] = { if_index, 0 };
        uint8_t hbuf_size, tmp[8];
@@ -1517,8 +1536,9 @@ static void intel_sdvo_dpms(struct drm_connector *connector, int mode)
        intel_modeset_check_state(connector->dev);
 }
 
-static int intel_sdvo_mode_valid(struct drm_connector *connector,
-                                struct drm_display_mode *mode)
+static enum drm_mode_status
+intel_sdvo_mode_valid(struct drm_connector *connector,
+                     struct drm_display_mode *mode)
 {
        struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector);
 
index 770bdd6ecd9fb96b46365bbadd97ba3011c0ef96..2e2d4eb4a00d190b24c03c1998b4e9f0cd9f06c5 100644 (file)
@@ -59,7 +59,7 @@ struct intel_sdvo_caps {
        unsigned int stall_support:1;
        unsigned int pad:1;
        u16 output_flags;
-} __attribute__((packed));
+} __packed;
 
 /* Note: SDVO detailed timing flags match EDID misc flags. */
 #define DTD_FLAG_HSYNC_POSITIVE (1 << 1)
@@ -94,12 +94,12 @@ struct intel_sdvo_dtd {
                u8 v_sync_off_high;
                u8 reserved;
        } part2;
-} __attribute__((packed));
+} __packed;
 
 struct intel_sdvo_pixel_clock_range {
        u16 min;        /**< pixel clock, in 10kHz units */
        u16 max;        /**< pixel clock, in 10kHz units */
-} __attribute__((packed));
+} __packed;
 
 struct intel_sdvo_preferred_input_timing_args {
        u16 clock;
@@ -108,7 +108,7 @@ struct intel_sdvo_preferred_input_timing_args {
        u8      interlace:1;
        u8      scaled:1;
        u8      pad:6;
-} __attribute__((packed));
+} __packed;
 
 /* I2C registers for SDVO */
 #define SDVO_I2C_ARG_0                         0x07
@@ -162,7 +162,7 @@ struct intel_sdvo_get_trained_inputs_response {
        unsigned int input0_trained:1;
        unsigned int input1_trained:1;
        unsigned int pad:6;
-} __attribute__((packed));
+} __packed;
 
 /** Returns a struct intel_sdvo_output_flags of active outputs. */
 #define SDVO_CMD_GET_ACTIVE_OUTPUTS                    0x04
@@ -219,7 +219,7 @@ struct intel_sdvo_get_interrupt_event_source_response {
        unsigned int ambient_light_interrupt:1;
        unsigned int hdmi_audio_encrypt_change:1;
        unsigned int pad:6;
-} __attribute__((packed));
+} __packed;
 
 /**
  * Selects which input is affected by future input commands.
@@ -232,7 +232,7 @@ struct intel_sdvo_get_interrupt_event_source_response {
 struct intel_sdvo_set_target_input_args {
        unsigned int target_1:1;
        unsigned int pad:7;
-} __attribute__((packed));
+} __packed;
 
 /**
  * Takes a struct intel_sdvo_output_flags of which outputs are targeted by
@@ -370,7 +370,7 @@ struct intel_sdvo_tv_format {
        unsigned int hdtv_std_eia_7702a_480i_60:1;
        unsigned int hdtv_std_eia_7702a_480p_60:1;
        unsigned int pad:3;
-} __attribute__((packed));
+} __packed;
 
 #define SDVO_CMD_GET_TV_FORMAT                         0x28
 
@@ -401,7 +401,7 @@ struct intel_sdvo_sdtv_resolution_request {
        unsigned int secam_l:1;
        unsigned int secam_60:1;
        unsigned int pad:5;
-} __attribute__((packed));
+} __packed;
 
 struct intel_sdvo_sdtv_resolution_reply {
        unsigned int res_320x200:1;
@@ -426,7 +426,7 @@ struct intel_sdvo_sdtv_resolution_reply {
        unsigned int res_1024x768:1;
        unsigned int res_1280x1024:1;
        unsigned int pad:5;
-} __attribute__((packed));
+} __packed;
 
 /* Get supported resolution with squire pixel aspect ratio that can be
    scaled for the requested HDTV format */
@@ -463,7 +463,7 @@ struct intel_sdvo_hdtv_resolution_request {
        unsigned int hdtv_std_eia_7702a_480i_60:1;
        unsigned int hdtv_std_eia_7702a_480p_60:1;
        unsigned int pad:6;
-} __attribute__((packed));
+} __packed;
 
 struct intel_sdvo_hdtv_resolution_reply {
        unsigned int res_640x480:1;
@@ -517,7 +517,7 @@ struct intel_sdvo_hdtv_resolution_reply {
 
        unsigned int res_1280x768:1;
        unsigned int pad5:7;
-} __attribute__((packed));
+} __packed;
 
 /* Get supported power state returns info for encoder and monitor, rely on
    last SetTargetInput and SetTargetOutput calls */
@@ -557,13 +557,13 @@ struct sdvo_panel_power_sequencing {
 
        unsigned int t4_high:2;
        unsigned int pad:6;
-} __attribute__((packed));
+} __packed;
 
 #define SDVO_CMD_GET_MAX_BACKLIGHT_LEVEL               0x30
 struct sdvo_max_backlight_reply {
        u8 max_value;
        u8 default_value;
-} __attribute__((packed));
+} __packed;
 
 #define SDVO_CMD_GET_BACKLIGHT_LEVEL                   0x31
 #define SDVO_CMD_SET_BACKLIGHT_LEVEL                   0x32
@@ -573,14 +573,14 @@ struct sdvo_get_ambient_light_reply {
        u16 trip_low;
        u16 trip_high;
        u16 value;
-} __attribute__((packed));
+} __packed;
 #define SDVO_CMD_SET_AMBIENT_LIGHT                     0x34
 struct sdvo_set_ambient_light_reply {
        u16 trip_low;
        u16 trip_high;
        unsigned int enable:1;
        unsigned int pad:7;
-} __attribute__((packed));
+} __packed;
 
 /* Set display power state */
 #define SDVO_CMD_SET_DISPLAY_POWER_STATE               0x7d
@@ -608,7 +608,7 @@ struct intel_sdvo_enhancements_reply {
        unsigned int dither:1;
        unsigned int tv_chroma_filter:1;
        unsigned int tv_luma_filter:1;
-} __attribute__((packed));
+} __packed;
 
 /* Picture enhancement limits below are dependent on the current TV format,
  * and thus need to be queried and set after it.
@@ -630,7 +630,7 @@ struct intel_sdvo_enhancements_reply {
 struct intel_sdvo_enhancement_limits_reply {
        u16 max_value;
        u16 default_value;
-} __attribute__((packed));
+} __packed;
 
 #define SDVO_CMD_GET_LVDS_PANEL_INFORMATION            0x7f
 #define SDVO_CMD_SET_LVDS_PANEL_INFORMATION            0x80
@@ -671,7 +671,7 @@ struct intel_sdvo_enhancement_limits_reply {
 #define SDVO_CMD_SET_TV_LUMA_FILTER                    0x79
 struct intel_sdvo_enhancements_arg {
        u16 value;
-} __attribute__((packed));
+} __packed;
 
 #define SDVO_CMD_GET_DOT_CRAWL                         0x70
 #define SDVO_CMD_SET_DOT_CRAWL                         0x71
@@ -727,4 +727,4 @@ struct intel_sdvo_enhancements_arg {
 struct intel_sdvo_encode {
        u8 dvi_rev;
        u8 hdmi_rev;
-} __attribute__ ((packed));
+} __packed;
index 9944d8135e87f88215d5d07d54a5fd87fcf4dc60..0954f132726ea0ae15593364ef976168fc2c909f 100644 (file)
@@ -90,6 +90,22 @@ void vlv_punit_write(struct drm_i915_private *dev_priv, u8 addr, u32 val)
        mutex_unlock(&dev_priv->dpio_lock);
 }
 
+u32 vlv_bunit_read(struct drm_i915_private *dev_priv, u32 reg)
+{
+       u32 val = 0;
+
+       vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_BUNIT,
+                       PUNIT_OPCODE_REG_READ, reg, &val);
+
+       return val;
+}
+
+void vlv_bunit_write(struct drm_i915_private *dev_priv, u32 reg, u32 val)
+{
+       vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_BUNIT,
+                       PUNIT_OPCODE_REG_WRITE, reg, &val);
+}
+
 u32 vlv_nc_read(struct drm_i915_private *dev_priv, u8 addr)
 {
        u32 val = 0;
@@ -160,27 +176,18 @@ void vlv_gps_core_write(struct drm_i915_private *dev_priv, u32 reg, u32 val)
                        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),
+       vlv_sideband_rw(dev_priv, DPIO_DEVFN, DPIO_PHY_IOSF_PORT(DPIO_PHY(pipe)),
                        DPIO_OPCODE_REG_READ, reg, &val);
        return 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, vlv_get_phy_port(pipe),
+       vlv_sideband_rw(dev_priv, DPIO_DEVFN, DPIO_PHY_IOSF_PORT(DPIO_PHY(pipe)),
                        DPIO_OPCODE_REG_WRITE, reg, &val);
 }
 
@@ -242,3 +249,17 @@ void intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value,
                return;
        }
 }
+
+u32 vlv_flisdsi_read(struct drm_i915_private *dev_priv, u32 reg)
+{
+       u32 val = 0;
+       vlv_sideband_rw(dev_priv, DPIO_DEVFN, IOSF_PORT_FLISDSI,
+                                       DPIO_OPCODE_REG_READ, reg, &val);
+       return val;
+}
+
+void vlv_flisdsi_write(struct drm_i915_private *dev_priv, u32 reg, u32 val)
+{
+       vlv_sideband_rw(dev_priv, DPIO_DEVFN, IOSF_PORT_FLISDSI,
+                                       DPIO_OPCODE_REG_WRITE, reg, &val);
+}
index b9fabf826f7de71f224bd9b808780f81ba1c9027..90a3f6db8288752343d1215fca58c0d831a35e28 100644 (file)
@@ -104,6 +104,12 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
                break;
        }
 
+       /*
+        * Enable gamma to match primary/cursor plane behaviour.
+        * FIXME should be user controllable via propertiesa.
+        */
+       sprctl |= SP_GAMMA_ENABLE;
+
        if (obj->tiling_mode != I915_TILING_NONE)
                sprctl |= SP_TILED;
 
@@ -257,6 +263,12 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
                BUG();
        }
 
+       /*
+        * Enable gamma to match primary/cursor plane behaviour.
+        * FIXME should be user controllable via propertiesa.
+        */
+       sprctl |= SPRITE_GAMMA_ENABLE;
+
        if (obj->tiling_mode != I915_TILING_NONE)
                sprctl |= SPRITE_TILED;
 
@@ -453,6 +465,12 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
                BUG();
        }
 
+       /*
+        * Enable gamma to match primary/cursor plane behaviour.
+        * FIXME should be user controllable via propertiesa.
+        */
+       dvscntr |= DVS_GAMMA_ENABLE;
+
        if (obj->tiling_mode != I915_TILING_NONE)
                dvscntr |= DVS_TILED;
 
index 0b02078a0b848c4127385b1d3b5d3ab6be755c80..8102af9a178dc45ad8370c1d061c5815d927c34c 100644 (file)
@@ -64,7 +64,8 @@ static void __gen6_gt_force_wake_reset(struct drm_i915_private *dev_priv)
        __raw_posting_read(dev_priv, ECOBUS);
 }
 
-static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
+static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv,
+                                                       int fw_engine)
 {
        if (wait_for_atomic((__raw_i915_read32(dev_priv, FORCEWAKE_ACK) & 1) == 0,
                            FORCEWAKE_ACK_TIMEOUT_MS))
@@ -89,7 +90,8 @@ static void __gen6_gt_force_wake_mt_reset(struct drm_i915_private *dev_priv)
        __raw_posting_read(dev_priv, ECOBUS);
 }
 
-static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
+static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv,
+                                                       int fw_engine)
 {
        u32 forcewake_ack;
 
@@ -121,12 +123,12 @@ static void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv)
        u32 gtfifodbg;
 
        gtfifodbg = __raw_i915_read32(dev_priv, GTFIFODBG);
-       if (WARN(gtfifodbg & GT_FIFO_CPU_ERROR_MASK,
-            "MMIO read or write has been dropped %x\n", gtfifodbg))
-               __raw_i915_write32(dev_priv, GTFIFODBG, GT_FIFO_CPU_ERROR_MASK);
+       if (WARN(gtfifodbg, "GT wake FIFO error 0x%x\n", gtfifodbg))
+               __raw_i915_write32(dev_priv, GTFIFODBG, gtfifodbg);
 }
 
-static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
+static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv,
+                                                       int fw_engine)
 {
        __raw_i915_write32(dev_priv, FORCEWAKE, 0);
        /* something from same cacheline, but !FORCEWAKE */
@@ -134,7 +136,8 @@ static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
        gen6_gt_check_fifodbg(dev_priv);
 }
 
-static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv)
+static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv,
+                                                       int fw_engine)
 {
        __raw_i915_write32(dev_priv, FORCEWAKE_MT,
                           _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
@@ -147,12 +150,19 @@ static int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
 {
        int ret = 0;
 
+       /* On VLV, FIFO will be shared by both SW and HW.
+        * So, we need to read the FREE_ENTRIES everytime */
+       if (IS_VALLEYVIEW(dev_priv->dev))
+               dev_priv->uncore.fifo_count =
+                       __raw_i915_read32(dev_priv, GTFIFOCTL) &
+                                               GT_FIFO_FREE_ENTRIES_MASK;
+
        if (dev_priv->uncore.fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES) {
                int loop = 500;
-               u32 fifo = __raw_i915_read32(dev_priv, GT_FIFO_FREE_ENTRIES);
+               u32 fifo = __raw_i915_read32(dev_priv, GTFIFOCTL) & GT_FIFO_FREE_ENTRIES_MASK;
                while (fifo <= GT_FIFO_NUM_RESERVED_ENTRIES && loop--) {
                        udelay(10);
-                       fifo = __raw_i915_read32(dev_priv, GT_FIFO_FREE_ENTRIES);
+                       fifo = __raw_i915_read32(dev_priv, GTFIFOCTL) & GT_FIFO_FREE_ENTRIES_MASK;
                }
                if (WARN_ON(loop < 0 && fifo <= GT_FIFO_NUM_RESERVED_ENTRIES))
                        ++ret;
@@ -171,38 +181,112 @@ static void vlv_force_wake_reset(struct drm_i915_private *dev_priv)
        __raw_posting_read(dev_priv, FORCEWAKE_ACK_VLV);
 }
 
-static void vlv_force_wake_get(struct drm_i915_private *dev_priv)
+static void __vlv_force_wake_get(struct drm_i915_private *dev_priv,
+                                               int fw_engine)
 {
-       if (wait_for_atomic((__raw_i915_read32(dev_priv, FORCEWAKE_ACK_VLV) & FORCEWAKE_KERNEL) == 0,
-                           FORCEWAKE_ACK_TIMEOUT_MS))
-               DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n");
+       /* Check for Render Engine */
+       if (FORCEWAKE_RENDER & fw_engine) {
+               if (wait_for_atomic((__raw_i915_read32(dev_priv,
+                                               FORCEWAKE_ACK_VLV) &
+                                               FORCEWAKE_KERNEL) == 0,
+                                       FORCEWAKE_ACK_TIMEOUT_MS))
+                       DRM_ERROR("Timed out: Render forcewake old ack to clear.\n");
 
-       __raw_i915_write32(dev_priv, FORCEWAKE_VLV,
-                          _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL));
-       __raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_VLV,
-                          _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL));
+               __raw_i915_write32(dev_priv, FORCEWAKE_VLV,
+                                  _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL));
 
-       if (wait_for_atomic((__raw_i915_read32(dev_priv, FORCEWAKE_ACK_VLV) & FORCEWAKE_KERNEL),
-                           FORCEWAKE_ACK_TIMEOUT_MS))
-               DRM_ERROR("Timed out waiting for GT to ack forcewake request.\n");
+               if (wait_for_atomic((__raw_i915_read32(dev_priv,
+                                               FORCEWAKE_ACK_VLV) &
+                                               FORCEWAKE_KERNEL),
+                                       FORCEWAKE_ACK_TIMEOUT_MS))
+                       DRM_ERROR("Timed out: waiting for Render to ack.\n");
+       }
 
-       if (wait_for_atomic((__raw_i915_read32(dev_priv, FORCEWAKE_ACK_MEDIA_VLV) &
-                            FORCEWAKE_KERNEL),
-                           FORCEWAKE_ACK_TIMEOUT_MS))
-               DRM_ERROR("Timed out waiting for media to ack forcewake request.\n");
+       /* Check for Media Engine */
+       if (FORCEWAKE_MEDIA & fw_engine) {
+               if (wait_for_atomic((__raw_i915_read32(dev_priv,
+                                               FORCEWAKE_ACK_MEDIA_VLV) &
+                                               FORCEWAKE_KERNEL) == 0,
+                                       FORCEWAKE_ACK_TIMEOUT_MS))
+                       DRM_ERROR("Timed out: Media forcewake old ack to clear.\n");
+
+               __raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_VLV,
+                                  _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL));
+
+               if (wait_for_atomic((__raw_i915_read32(dev_priv,
+                                               FORCEWAKE_ACK_MEDIA_VLV) &
+                                               FORCEWAKE_KERNEL),
+                                       FORCEWAKE_ACK_TIMEOUT_MS))
+                       DRM_ERROR("Timed out: waiting for media to ack.\n");
+       }
 
        /* WaRsForcewakeWaitTC0:vlv */
        __gen6_gt_wait_for_thread_c0(dev_priv);
+
 }
 
-static void vlv_force_wake_put(struct drm_i915_private *dev_priv)
+static void __vlv_force_wake_put(struct drm_i915_private *dev_priv,
+                                       int fw_engine)
 {
-       __raw_i915_write32(dev_priv, FORCEWAKE_VLV,
-                          _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
-       __raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_VLV,
-                          _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
+
+       /* Check for Render Engine */
+       if (FORCEWAKE_RENDER & fw_engine)
+               __raw_i915_write32(dev_priv, FORCEWAKE_VLV,
+                                       _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
+
+
+       /* Check for Media Engine */
+       if (FORCEWAKE_MEDIA & fw_engine)
+               __raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_VLV,
+                               _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
+
        /* The below doubles as a POSTING_READ */
        gen6_gt_check_fifodbg(dev_priv);
+
+}
+
+void vlv_force_wake_get(struct drm_i915_private *dev_priv,
+                                               int fw_engine)
+{
+       unsigned long irqflags;
+
+       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
+       if (FORCEWAKE_RENDER & fw_engine) {
+               if (dev_priv->uncore.fw_rendercount++ == 0)
+                       dev_priv->uncore.funcs.force_wake_get(dev_priv,
+                                                       FORCEWAKE_RENDER);
+       }
+       if (FORCEWAKE_MEDIA & fw_engine) {
+               if (dev_priv->uncore.fw_mediacount++ == 0)
+                       dev_priv->uncore.funcs.force_wake_get(dev_priv,
+                                                       FORCEWAKE_MEDIA);
+       }
+
+       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
+}
+
+void vlv_force_wake_put(struct drm_i915_private *dev_priv,
+                                               int fw_engine)
+{
+       unsigned long irqflags;
+
+       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
+
+       if (FORCEWAKE_RENDER & fw_engine) {
+               WARN_ON(dev_priv->uncore.fw_rendercount == 0);
+               if (--dev_priv->uncore.fw_rendercount == 0)
+                       dev_priv->uncore.funcs.force_wake_put(dev_priv,
+                                                       FORCEWAKE_RENDER);
+       }
+
+       if (FORCEWAKE_MEDIA & fw_engine) {
+               WARN_ON(dev_priv->uncore.fw_mediacount == 0);
+               if (--dev_priv->uncore.fw_mediacount == 0)
+                       dev_priv->uncore.funcs.force_wake_put(dev_priv,
+                                                       FORCEWAKE_MEDIA);
+       }
+
+       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
 static void gen6_force_wake_work(struct work_struct *work)
@@ -213,7 +297,7 @@ static void gen6_force_wake_work(struct work_struct *work)
 
        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
        if (--dev_priv->uncore.forcewake_count == 0)
-               dev_priv->uncore.funcs.force_wake_put(dev_priv);
+               dev_priv->uncore.funcs.force_wake_put(dev_priv, FORCEWAKE_ALL);
        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
@@ -256,8 +340,6 @@ void intel_uncore_sanitize(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 reg_val;
 
-       intel_uncore_forcewake_reset(dev);
-
        /* BIOS often leaves RC6 enabled, but disable it for hw init */
        intel_disable_gt_powersave(dev);
 
@@ -281,29 +363,40 @@ void intel_uncore_sanitize(struct drm_device *dev)
  * be called at the beginning of the sequence followed by a call to
  * gen6_gt_force_wake_put() at the end of the sequence.
  */
-void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
+void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine)
 {
        unsigned long irqflags;
 
        if (!dev_priv->uncore.funcs.force_wake_get)
                return;
 
+       intel_runtime_pm_get(dev_priv);
+
+       /* Redirect to VLV specific routine */
+       if (IS_VALLEYVIEW(dev_priv->dev))
+               return vlv_force_wake_get(dev_priv, fw_engine);
+
        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
        if (dev_priv->uncore.forcewake_count++ == 0)
-               dev_priv->uncore.funcs.force_wake_get(dev_priv);
+               dev_priv->uncore.funcs.force_wake_get(dev_priv, FORCEWAKE_ALL);
        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
 /*
  * see gen6_gt_force_wake_get()
  */
-void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
+void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine)
 {
        unsigned long irqflags;
 
        if (!dev_priv->uncore.funcs.force_wake_put)
                return;
 
+       /* Redirect to VLV specific routine */
+       if (IS_VALLEYVIEW(dev_priv->dev))
+               return vlv_force_wake_put(dev_priv, fw_engine);
+
+
        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
        if (--dev_priv->uncore.forcewake_count == 0) {
                dev_priv->uncore.forcewake_count++;
@@ -312,6 +405,8 @@ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
                                 1);
        }
        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
+
+       intel_runtime_pm_put(dev_priv);
 }
 
 /* We give fast paths for the really cool registers */
@@ -346,6 +441,13 @@ hsw_unclaimed_reg_check(struct drm_i915_private *dev_priv, u32 reg)
        }
 }
 
+static void
+assert_device_not_suspended(struct drm_i915_private *dev_priv)
+{
+       WARN(HAS_RUNTIME_PM(dev_priv->dev) && dev_priv->pm.suspended,
+            "Device suspended\n");
+}
+
 #define REG_READ_HEADER(x) \
        unsigned long irqflags; \
        u##x val = 0; \
@@ -379,16 +481,51 @@ gen6_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
        REG_READ_HEADER(x); \
        if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
                if (dev_priv->uncore.forcewake_count == 0) \
-                       dev_priv->uncore.funcs.force_wake_get(dev_priv); \
+                       dev_priv->uncore.funcs.force_wake_get(dev_priv, \
+                                                       FORCEWAKE_ALL); \
                val = __raw_i915_read##x(dev_priv, reg); \
                if (dev_priv->uncore.forcewake_count == 0) \
-                       dev_priv->uncore.funcs.force_wake_put(dev_priv); \
+                       dev_priv->uncore.funcs.force_wake_put(dev_priv, \
+                                                       FORCEWAKE_ALL); \
        } else { \
                val = __raw_i915_read##x(dev_priv, reg); \
        } \
        REG_READ_FOOTER; \
 }
 
+#define __vlv_read(x) \
+static u##x \
+vlv_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
+       unsigned fwengine = 0; \
+       unsigned *fwcount; \
+       REG_READ_HEADER(x); \
+       if (FORCEWAKE_VLV_RENDER_RANGE_OFFSET(reg)) {   \
+               fwengine = FORCEWAKE_RENDER;            \
+               fwcount = &dev_priv->uncore.fw_rendercount;    \
+       }                                               \
+       else if (FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(reg)) {       \
+               fwengine = FORCEWAKE_MEDIA;             \
+               fwcount = &dev_priv->uncore.fw_mediacount;     \
+       }  \
+       if (fwengine != 0) {            \
+               if ((*fwcount)++ == 0) \
+                       (dev_priv)->uncore.funcs.force_wake_get(dev_priv, \
+                                                               fwengine); \
+               val = __raw_i915_read##x(dev_priv, reg); \
+               if (--(*fwcount) == 0) \
+                       (dev_priv)->uncore.funcs.force_wake_put(dev_priv, \
+                                                       fwengine); \
+       } else { \
+               val = __raw_i915_read##x(dev_priv, reg); \
+       } \
+       REG_READ_FOOTER; \
+}
+
+
+__vlv_read(8)
+__vlv_read(16)
+__vlv_read(32)
+__vlv_read(64)
 __gen6_read(8)
 __gen6_read(16)
 __gen6_read(32)
@@ -402,6 +539,7 @@ __gen4_read(16)
 __gen4_read(32)
 __gen4_read(64)
 
+#undef __vlv_read
 #undef __gen6_read
 #undef __gen5_read
 #undef __gen4_read
@@ -413,12 +551,15 @@ __gen4_read(64)
        trace_i915_reg_rw(true, reg, val, sizeof(val), trace); \
        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags)
 
+#define REG_WRITE_FOOTER \
+       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags)
+
 #define __gen4_write(x) \
 static void \
 gen4_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \
        REG_WRITE_HEADER; \
        __raw_i915_write##x(dev_priv, reg, val); \
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \
+       REG_WRITE_FOOTER; \
 }
 
 #define __gen5_write(x) \
@@ -427,7 +568,7 @@ gen5_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace
        REG_WRITE_HEADER; \
        ilk_dummy_write(dev_priv); \
        __raw_i915_write##x(dev_priv, reg, val); \
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \
+       REG_WRITE_FOOTER; \
 }
 
 #define __gen6_write(x) \
@@ -438,11 +579,12 @@ gen6_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace
        if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
                __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
        } \
+       assert_device_not_suspended(dev_priv); \
        __raw_i915_write##x(dev_priv, reg, val); \
        if (unlikely(__fifo_ret)) { \
                gen6_gt_check_fifodbg(dev_priv); \
        } \
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \
+       REG_WRITE_FOOTER; \
 }
 
 #define __hsw_write(x) \
@@ -453,13 +595,14 @@ hsw_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace)
        if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
                __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
        } \
+       assert_device_not_suspended(dev_priv); \
        hsw_unclaimed_reg_clear(dev_priv, reg); \
        __raw_i915_write##x(dev_priv, reg, val); \
        if (unlikely(__fifo_ret)) { \
                gen6_gt_check_fifodbg(dev_priv); \
        } \
        hsw_unclaimed_reg_check(dev_priv, reg); \
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \
+       REG_WRITE_FOOTER; \
 }
 
 static const u32 gen8_shadowed_regs[] = {
@@ -489,13 +632,15 @@ gen8_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace
        bool __needs_put = !is_gen8_shadowed(dev_priv, reg); \
        REG_WRITE_HEADER; \
        if (__needs_put) { \
-               dev_priv->uncore.funcs.force_wake_get(dev_priv); \
+               dev_priv->uncore.funcs.force_wake_get(dev_priv, \
+                                                       FORCEWAKE_ALL); \
        } \
        __raw_i915_write##x(dev_priv, reg, val); \
        if (__needs_put) { \
-               dev_priv->uncore.funcs.force_wake_put(dev_priv); \
+               dev_priv->uncore.funcs.force_wake_put(dev_priv, \
+                                                       FORCEWAKE_ALL); \
        } \
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); \
+       REG_WRITE_FOOTER; \
 }
 
 __gen8_write(8)
@@ -524,6 +669,7 @@ __gen4_write(64)
 #undef __gen6_write
 #undef __gen5_write
 #undef __gen4_write
+#undef REG_WRITE_FOOTER
 #undef REG_WRITE_HEADER
 
 void intel_uncore_init(struct drm_device *dev)
@@ -534,8 +680,8 @@ void intel_uncore_init(struct drm_device *dev)
                          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;
+               dev_priv->uncore.funcs.force_wake_get = __vlv_force_wake_get;
+               dev_priv->uncore.funcs.force_wake_put = __vlv_force_wake_put;
        } else if (IS_HASWELL(dev) || IS_GEN8(dev)) {
                dev_priv->uncore.funcs.force_wake_get = __gen6_gt_force_wake_mt_get;
                dev_priv->uncore.funcs.force_wake_put = __gen6_gt_force_wake_mt_put;
@@ -552,9 +698,9 @@ void intel_uncore_init(struct drm_device *dev)
                 * forcewake being disabled.
                 */
                mutex_lock(&dev->struct_mutex);
-               __gen6_gt_force_wake_mt_get(dev_priv);
+               __gen6_gt_force_wake_mt_get(dev_priv, FORCEWAKE_ALL);
                ecobus = __raw_i915_read32(dev_priv, ECOBUS);
-               __gen6_gt_force_wake_mt_put(dev_priv);
+               __gen6_gt_force_wake_mt_put(dev_priv, FORCEWAKE_ALL);
                mutex_unlock(&dev->struct_mutex);
 
                if (ecobus & FORCEWAKE_MT_ENABLE) {
@@ -601,10 +747,18 @@ void intel_uncore_init(struct drm_device *dev)
                        dev_priv->uncore.funcs.mmio_writel  = gen6_write32;
                        dev_priv->uncore.funcs.mmio_writeq  = gen6_write64;
                }
-               dev_priv->uncore.funcs.mmio_readb  = gen6_read8;
-               dev_priv->uncore.funcs.mmio_readw  = gen6_read16;
-               dev_priv->uncore.funcs.mmio_readl  = gen6_read32;
-               dev_priv->uncore.funcs.mmio_readq  = gen6_read64;
+
+               if (IS_VALLEYVIEW(dev)) {
+                       dev_priv->uncore.funcs.mmio_readb  = vlv_read8;
+                       dev_priv->uncore.funcs.mmio_readw  = vlv_read16;
+                       dev_priv->uncore.funcs.mmio_readl  = vlv_read32;
+                       dev_priv->uncore.funcs.mmio_readq  = vlv_read64;
+               } else {
+                       dev_priv->uncore.funcs.mmio_readb  = gen6_read8;
+                       dev_priv->uncore.funcs.mmio_readw  = gen6_read16;
+                       dev_priv->uncore.funcs.mmio_readl  = gen6_read32;
+                       dev_priv->uncore.funcs.mmio_readq  = gen6_read64;
+               }
                break;
        case 5:
                dev_priv->uncore.funcs.mmio_writeb  = gen5_write8;
@@ -687,6 +841,43 @@ int i915_reg_read_ioctl(struct drm_device *dev,
        return 0;
 }
 
+int i915_get_reset_stats_ioctl(struct drm_device *dev,
+                              void *data, struct drm_file *file)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_i915_reset_stats *args = data;
+       struct i915_ctx_hang_stats *hs;
+       int ret;
+
+       if (args->flags || args->pad)
+               return -EINVAL;
+
+       if (args->ctx_id == DEFAULT_CONTEXT_ID && !capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       ret = mutex_lock_interruptible(&dev->struct_mutex);
+       if (ret)
+               return ret;
+
+       hs = i915_gem_context_get_hang_stats(dev, file, args->ctx_id);
+       if (IS_ERR(hs)) {
+               mutex_unlock(&dev->struct_mutex);
+               return PTR_ERR(hs);
+       }
+
+       if (capable(CAP_SYS_ADMIN))
+               args->reset_count = i915_reset_count(&dev_priv->gpu_error);
+       else
+               args->reset_count = 0;
+
+       args->batch_active = hs->batch_active;
+       args->batch_pending = hs->batch_pending;
+
+       mutex_unlock(&dev->struct_mutex);
+
+       return 0;
+}
+
 static int i965_reset_complete(struct drm_device *dev)
 {
        u8 gdrst;
@@ -770,12 +961,12 @@ static int gen6_do_reset(struct drm_device *dev)
 
        /* If reset with a user forcewake, try to restore, otherwise turn it off */
        if (dev_priv->uncore.forcewake_count)
-               dev_priv->uncore.funcs.force_wake_get(dev_priv);
+               dev_priv->uncore.funcs.force_wake_get(dev_priv, FORCEWAKE_ALL);
        else
-               dev_priv->uncore.funcs.force_wake_put(dev_priv);
+               dev_priv->uncore.funcs.force_wake_put(dev_priv, FORCEWAKE_ALL);
 
        /* Restore fifo count */
-       dev_priv->uncore.fifo_count = __raw_i915_read32(dev_priv, GT_FIFO_FREE_ENTRIES);
+       dev_priv->uncore.fifo_count = __raw_i915_read32(dev_priv, GTFIFOCTL) & GT_FIFO_FREE_ENTRIES_MASK;
 
        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
        return ret;
@@ -784,6 +975,7 @@ static int gen6_do_reset(struct drm_device *dev)
 int intel_gpu_reset(struct drm_device *dev)
 {
        switch (INTEL_INFO(dev)->gen) {
+       case 8:
        case 7:
        case 6: return gen6_do_reset(dev);
        case 5: return ironlake_do_reset(dev);
@@ -792,15 +984,6 @@ int intel_gpu_reset(struct drm_device *dev)
        }
 }
 
-void intel_uncore_clear_errors(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       /* XXX needs spinlock around caller's grouping */
-       if (HAS_FPGA_DBG_UNCLAIMED(dev))
-               __raw_i915_write32(dev_priv, FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
-}
-
 void intel_uncore_check_errors(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
index edcf801613e66ea5c34665eafe1147d39cda62db..b3fa1ba191b7115be412894936c3633bf9221188 100644 (file)
@@ -59,6 +59,7 @@ nouveau-y += core/subdev/clock/nv40.o
 nouveau-y += core/subdev/clock/nv50.o
 nouveau-y += core/subdev/clock/nv84.o
 nouveau-y += core/subdev/clock/nva3.o
+nouveau-y += core/subdev/clock/nvaa.o
 nouveau-y += core/subdev/clock/nvc0.o
 nouveau-y += core/subdev/clock/nve0.o
 nouveau-y += core/subdev/clock/pllnv04.o
index db139827047cf4a6b103a2d98cc7fe5c208721db..db3fc7be856a733d07f8431a182326e3f20b4182 100644 (file)
@@ -283,7 +283,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nvaa_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
@@ -311,7 +311,7 @@ nv50_identify(struct nouveau_device *device)
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
                device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass;
                device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass;
-               device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nvaa_clock_oclass;
                device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;
                device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
                device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
index 5f555788121c9ff8c63a7e66da794011b67f237e..e6352bd5b4ff53c066b587bf51595b8ca54ac3af 100644 (file)
@@ -33,6 +33,7 @@
 #include <engine/dmaobj.h>
 #include <engine/fifo.h>
 
+#include "nv04.h"
 #include "nv50.h"
 
 /*******************************************************************************
@@ -460,6 +461,8 @@ nv50_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        nv_subdev(priv)->intr = nv04_fifo_intr;
        nv_engine(priv)->cclass = &nv50_fifo_cclass;
        nv_engine(priv)->sclass = nv50_fifo_sclass;
+       priv->base.pause = nv04_fifo_pause;
+       priv->base.start = nv04_fifo_start;
        return 0;
 }
 
index 0908dc834c84c48ac34f91afde1984ed593531bd..fe0f41e65d9b9c6ab6abfa5b1d5f7b3031fe5557 100644 (file)
@@ -35,6 +35,7 @@
 #include <engine/dmaobj.h>
 #include <engine/fifo.h>
 
+#include "nv04.h"
 #include "nv50.h"
 
 /*******************************************************************************
@@ -432,6 +433,8 @@ nv84_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        nv_subdev(priv)->intr = nv04_fifo_intr;
        nv_engine(priv)->cclass = &nv84_fifo_cclass;
        nv_engine(priv)->sclass = nv84_fifo_sclass;
+       priv->base.pause = nv04_fifo_pause;
+       priv->base.start = nv04_fifo_start;
        return 0;
 }
 
index b574dd4bb8285e65ccdbcf23db7b6f139e1cb73c..5ce686ee729ea5d937164d55892a9aebd2312b77 100644 (file)
@@ -176,7 +176,7 @@ nv50_software_context_ctor(struct nouveau_object *parent,
        if (ret)
                return ret;
 
-       chan->vblank.nr_event = pdisp->vblank->index_nr;
+       chan->vblank.nr_event = pdisp ? pdisp->vblank->index_nr : 0;
        chan->vblank.event = kzalloc(chan->vblank.nr_event *
                                     sizeof(*chan->vblank.event), GFP_KERNEL);
        if (!chan->vblank.event)
index e2675bc0edba5f9baefc5d514750d151a2ce23a7..8f4ced75444a95478887b4be5791fc99dd3499dc 100644 (file)
@@ -14,6 +14,9 @@ enum nv_clk_src {
        nv_clk_src_hclk,
        nv_clk_src_hclkm3,
        nv_clk_src_hclkm3d2,
+       nv_clk_src_hclkm2d3, /* NVAA */
+       nv_clk_src_hclkm4, /* NVAA */
+       nv_clk_src_cclk, /* NVAA */
 
        nv_clk_src_host,
 
@@ -127,6 +130,7 @@ extern struct nouveau_oclass nv04_clock_oclass;
 extern struct nouveau_oclass nv40_clock_oclass;
 extern struct nouveau_oclass *nv50_clock_oclass;
 extern struct nouveau_oclass *nv84_clock_oclass;
+extern struct nouveau_oclass *nvaa_clock_oclass;
 extern struct nouveau_oclass nva3_clock_oclass;
 extern struct nouveau_oclass nvc0_clock_oclass;
 extern struct nouveau_oclass nve0_clock_oclass;
index da50c1b129283923f841eef8c4192df09131f935..30c1f3a4158e3de87fd2bfb24592b9ea685b2d88 100644 (file)
@@ -69,6 +69,11 @@ nv04_clock_pll_prog(struct nouveau_clock *clk, u32 reg1,
        return 0;
 }
 
+static struct nouveau_clocks
+nv04_domain[] = {
+       { nv_clk_src_max }
+};
+
 static int
 nv04_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                struct nouveau_oclass *oclass, void *data, u32 size,
@@ -77,7 +82,7 @@ nv04_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nv04_clock_priv *priv;
        int ret;
 
-       ret = nouveau_clock_create(parent, engine, oclass, NULL, &priv);
+       ret = nouveau_clock_create(parent, engine, oclass, nv04_domain, &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c
new file mode 100644 (file)
index 0000000..7a723b4
--- /dev/null
@@ -0,0 +1,445 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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: Ben Skeggs
+ */
+
+#include <engine/fifo.h>
+#include <subdev/bios.h>
+#include <subdev/bios/pll.h>
+#include <subdev/timer.h>
+#include <subdev/clock.h>
+
+#include "pll.h"
+
+struct nvaa_clock_priv {
+       struct nouveau_clock base;
+       enum nv_clk_src csrc, ssrc, vsrc;
+       u32 cctrl, sctrl;
+       u32 ccoef, scoef;
+       u32 cpost, spost;
+       u32 vdiv;
+};
+
+static u32
+read_div(struct nouveau_clock *clk)
+{
+       return nv_rd32(clk, 0x004600);
+}
+
+static u32
+read_pll(struct nouveau_clock *clk, u32 base)
+{
+       u32 ctrl = nv_rd32(clk, base + 0);
+       u32 coef = nv_rd32(clk, base + 4);
+       u32 ref = clk->read(clk, nv_clk_src_href);
+       u32 post_div = 0;
+       u32 clock = 0;
+       int N1, M1;
+
+       switch (base){
+       case 0x4020:
+               post_div = 1 << ((nv_rd32(clk, 0x4070) & 0x000f0000) >> 16);
+               break;
+       case 0x4028:
+               post_div = (nv_rd32(clk, 0x4040) & 0x000f0000) >> 16;
+               break;
+       default:
+               break;
+       }
+
+       N1 = (coef & 0x0000ff00) >> 8;
+       M1 = (coef & 0x000000ff);
+       if ((ctrl & 0x80000000) && M1) {
+               clock = ref * N1 / M1;
+               clock = clock / post_div;
+       }
+
+       return clock;
+}
+
+static int
+nvaa_clock_read(struct nouveau_clock *clk, enum nv_clk_src src)
+{
+       struct nvaa_clock_priv *priv = (void *)clk;
+       u32 mast = nv_rd32(clk, 0x00c054);
+       u32 P = 0;
+
+       switch (src) {
+       case nv_clk_src_crystal:
+               return nv_device(priv)->crystal;
+       case nv_clk_src_href:
+               return 100000; /* PCIE reference clock */
+       case nv_clk_src_hclkm4:
+               return clk->read(clk, nv_clk_src_href) * 4;
+       case nv_clk_src_hclkm2d3:
+               return clk->read(clk, nv_clk_src_href) * 2 / 3;
+       case nv_clk_src_host:
+               switch (mast & 0x000c0000) {
+               case 0x00000000: return clk->read(clk, nv_clk_src_hclkm2d3);
+               case 0x00040000: break;
+               case 0x00080000: return clk->read(clk, nv_clk_src_hclkm4);
+               case 0x000c0000: return clk->read(clk, nv_clk_src_cclk);
+               }
+               break;
+       case nv_clk_src_core:
+               P = (nv_rd32(clk, 0x004028) & 0x00070000) >> 16;
+
+               switch (mast & 0x00000003) {
+               case 0x00000000: return clk->read(clk, nv_clk_src_crystal) >> P;
+               case 0x00000001: return 0;
+               case 0x00000002: return clk->read(clk, nv_clk_src_hclkm4) >> P;
+               case 0x00000003: return read_pll(clk, 0x004028) >> P;
+               }
+               break;
+       case nv_clk_src_cclk:
+               if ((mast & 0x03000000) != 0x03000000)
+                       return clk->read(clk, nv_clk_src_core);
+
+               if ((mast & 0x00000200) == 0x00000000)
+                       return clk->read(clk, nv_clk_src_core);
+
+               switch (mast & 0x00000c00) {
+               case 0x00000000: return clk->read(clk, nv_clk_src_href);
+               case 0x00000400: return clk->read(clk, nv_clk_src_hclkm4);
+               case 0x00000800: return clk->read(clk, nv_clk_src_hclkm2d3);
+               default: return 0;
+               }
+       case nv_clk_src_shader:
+               P = (nv_rd32(clk, 0x004020) & 0x00070000) >> 16;
+               switch (mast & 0x00000030) {
+               case 0x00000000:
+                       if (mast & 0x00000040)
+                               return clk->read(clk, nv_clk_src_href) >> P;
+                       return clk->read(clk, nv_clk_src_crystal) >> P;
+               case 0x00000010: break;
+               case 0x00000020: return read_pll(clk, 0x004028) >> P;
+               case 0x00000030: return read_pll(clk, 0x004020) >> P;
+               }
+               break;
+       case nv_clk_src_mem:
+               return 0;
+               break;
+       case nv_clk_src_vdec:
+               P = (read_div(clk) & 0x00000700) >> 8;
+
+               switch (mast & 0x00400000) {
+               case 0x00400000:
+                       return clk->read(clk, nv_clk_src_core) >> P;
+                       break;
+               default:
+                       return 500000 >> P;
+                       break;
+               }
+               break;
+       default:
+               break;
+       }
+
+       nv_debug(priv, "unknown clock source %d 0x%08x\n", src, mast);
+       return 0;
+}
+
+static u32
+calc_pll(struct nvaa_clock_priv *priv, u32 reg,
+        u32 clock, int *N, int *M, int *P)
+{
+       struct nouveau_bios *bios = nouveau_bios(priv);
+       struct nvbios_pll pll;
+       struct nouveau_clock *clk = &priv->base;
+       int ret;
+
+       ret = nvbios_pll_parse(bios, reg, &pll);
+       if (ret)
+               return 0;
+
+       pll.vco2.max_freq = 0;
+       pll.refclk = clk->read(clk, nv_clk_src_href);
+       if (!pll.refclk)
+               return 0;
+
+       return nv04_pll_calc(nv_subdev(priv), &pll, clock, N, M, NULL, NULL, P);
+}
+
+static inline u32
+calc_P(u32 src, u32 target, int *div)
+{
+       u32 clk0 = src, clk1 = src;
+       for (*div = 0; *div <= 7; (*div)++) {
+               if (clk0 <= target) {
+                       clk1 = clk0 << (*div ? 1 : 0);
+                       break;
+               }
+               clk0 >>= 1;
+       }
+
+       if (target - clk0 <= clk1 - target)
+               return clk0;
+       (*div)--;
+       return clk1;
+}
+
+static int
+nvaa_clock_calc(struct nouveau_clock *clk, struct nouveau_cstate *cstate)
+{
+       struct nvaa_clock_priv *priv = (void *)clk;
+       const int shader = cstate->domain[nv_clk_src_shader];
+       const int core = cstate->domain[nv_clk_src_core];
+       const int vdec = cstate->domain[nv_clk_src_vdec];
+       u32 out = 0, clock = 0;
+       int N, M, P1, P2 = 0;
+       int divs = 0;
+
+       /* cclk: find suitable source, disable PLL if we can */
+       if (core < clk->read(clk, nv_clk_src_hclkm4))
+               out = calc_P(clk->read(clk, nv_clk_src_hclkm4), core, &divs);
+
+       /* Calculate clock * 2, so shader clock can use it too */
+       clock = calc_pll(priv, 0x4028, (core << 1), &N, &M, &P1);
+
+       if (abs(core - out) <=
+           abs(core - (clock >> 1))) {
+               priv->csrc = nv_clk_src_hclkm4;
+               priv->cctrl = divs << 16;
+       } else {
+               /* NVCTRL is actually used _after_ NVPOST, and after what we
+                * call NVPLL. To make matters worse, NVPOST is an integer
+                * divider instead of a right-shift number. */
+               if(P1 > 2) {
+                       P2 = P1 - 2;
+                       P1 = 2;
+               }
+
+               priv->csrc = nv_clk_src_core;
+               priv->ccoef = (N << 8) | M;
+
+               priv->cctrl = (P2 + 1) << 16;
+               priv->cpost = (1 << P1) << 16;
+       }
+
+       /* sclk: nvpll + divisor, href or spll */
+       out = 0;
+       if (shader == clk->read(clk, nv_clk_src_href)) {
+               priv->ssrc = nv_clk_src_href;
+       } else {
+               clock = calc_pll(priv, 0x4020, shader, &N, &M, &P1);
+               if (priv->csrc == nv_clk_src_core) {
+                       out = calc_P((core << 1), shader, &divs);
+               }
+
+               if (abs(shader - out) <=
+                   abs(shader - clock) &&
+                  (divs + P2) <= 7) {
+                       priv->ssrc = nv_clk_src_core;
+                       priv->sctrl = (divs + P2) << 16;
+               } else {
+                       priv->ssrc = nv_clk_src_shader;
+                       priv->scoef = (N << 8) | M;
+                       priv->sctrl = P1 << 16;
+               }
+       }
+
+       /* vclk */
+       out = calc_P(core, vdec, &divs);
+       clock = calc_P(500000, vdec, &P1);
+       if(abs(vdec - out) <=
+          abs(vdec - clock)) {
+               priv->vsrc = nv_clk_src_cclk;
+               priv->vdiv = divs << 16;
+       } else {
+               priv->vsrc = nv_clk_src_vdec;
+               priv->vdiv = P1 << 16;
+       }
+
+       /* Print strategy! */
+       nv_debug(priv, "nvpll: %08x %08x %08x\n",
+                       priv->ccoef, priv->cpost, priv->cctrl);
+       nv_debug(priv, " spll: %08x %08x %08x\n",
+                       priv->scoef, priv->spost, priv->sctrl);
+       nv_debug(priv, " vdiv: %08x\n", priv->vdiv);
+       if (priv->csrc == nv_clk_src_hclkm4)
+               nv_debug(priv, "core: hrefm4\n");
+       else
+               nv_debug(priv, "core: nvpll\n");
+
+       if (priv->ssrc == nv_clk_src_hclkm4)
+               nv_debug(priv, "shader: hrefm4\n");
+       else if (priv->ssrc == nv_clk_src_core)
+               nv_debug(priv, "shader: nvpll\n");
+       else
+               nv_debug(priv, "shader: spll\n");
+
+       if (priv->vsrc == nv_clk_src_hclkm4)
+               nv_debug(priv, "vdec: 500MHz\n");
+       else
+               nv_debug(priv, "vdec: core\n");
+
+       return 0;
+}
+
+static int
+nvaa_clock_prog(struct nouveau_clock *clk)
+{
+       struct nvaa_clock_priv *priv = (void *)clk;
+       struct nouveau_fifo *pfifo = nouveau_fifo(clk);
+       unsigned long flags;
+       u32 pllmask = 0, mast, ptherm_gate;
+       int ret = -EBUSY;
+
+       /* halt and idle execution engines */
+       ptherm_gate = nv_mask(clk, 0x020060, 0x00070000, 0x00000000);
+       nv_mask(clk, 0x002504, 0x00000001, 0x00000001);
+       /* Wait until the interrupt handler is finished */
+       if (!nv_wait(clk, 0x000100, 0xffffffff, 0x00000000))
+               goto resume;
+
+       if (pfifo)
+               pfifo->pause(pfifo, &flags);
+
+       if (!nv_wait(clk, 0x002504, 0x00000010, 0x00000010))
+               goto resume;
+       if (!nv_wait(clk, 0x00251c, 0x0000003f, 0x0000003f))
+               goto resume;
+
+       /* First switch to safe clocks: href */
+       mast = nv_mask(clk, 0xc054, 0x03400e70, 0x03400640);
+       mast &= ~0x00400e73;
+       mast |= 0x03000000;
+
+       switch (priv->csrc) {
+       case nv_clk_src_hclkm4:
+               nv_mask(clk, 0x4028, 0x00070000, priv->cctrl);
+               mast |= 0x00000002;
+               break;
+       case nv_clk_src_core:
+               nv_wr32(clk, 0x402c, priv->ccoef);
+               nv_wr32(clk, 0x4028, 0x80000000 | priv->cctrl);
+               nv_wr32(clk, 0x4040, priv->cpost);
+               pllmask |= (0x3 << 8);
+               mast |= 0x00000003;
+               break;
+       default:
+               nv_warn(priv,"Reclocking failed: unknown core clock\n");
+               goto resume;
+       }
+
+       switch (priv->ssrc) {
+       case nv_clk_src_href:
+               nv_mask(clk, 0x4020, 0x00070000, 0x00000000);
+               /* mast |= 0x00000000; */
+               break;
+       case nv_clk_src_core:
+               nv_mask(clk, 0x4020, 0x00070000, priv->sctrl);
+               mast |= 0x00000020;
+               break;
+       case nv_clk_src_shader:
+               nv_wr32(clk, 0x4024, priv->scoef);
+               nv_wr32(clk, 0x4020, 0x80000000 | priv->sctrl);
+               nv_wr32(clk, 0x4070, priv->spost);
+               pllmask |= (0x3 << 12);
+               mast |= 0x00000030;
+               break;
+       default:
+               nv_warn(priv,"Reclocking failed: unknown sclk clock\n");
+               goto resume;
+       }
+
+       if (!nv_wait(clk, 0x004080, pllmask, pllmask)) {
+               nv_warn(priv,"Reclocking failed: unstable PLLs\n");
+               goto resume;
+       }
+
+       switch (priv->vsrc) {
+       case nv_clk_src_cclk:
+               mast |= 0x00400000;
+       default:
+               nv_wr32(clk, 0x4600, priv->vdiv);
+       }
+
+       nv_wr32(clk, 0xc054, mast);
+       ret = 0;
+
+resume:
+       if (pfifo)
+               pfifo->start(pfifo, &flags);
+
+       nv_mask(clk, 0x002504, 0x00000001, 0x00000000);
+       nv_wr32(clk, 0x020060, ptherm_gate);
+
+       /* Disable some PLLs and dividers when unused */
+       if (priv->csrc != nv_clk_src_core) {
+               nv_wr32(clk, 0x4040, 0x00000000);
+               nv_mask(clk, 0x4028, 0x80000000, 0x00000000);
+       }
+
+       if (priv->ssrc != nv_clk_src_shader) {
+               nv_wr32(clk, 0x4070, 0x00000000);
+               nv_mask(clk, 0x4020, 0x80000000, 0x00000000);
+       }
+
+       return ret;
+}
+
+static void
+nvaa_clock_tidy(struct nouveau_clock *clk)
+{
+}
+
+static struct nouveau_clocks
+nvaa_domains[] = {
+       { nv_clk_src_crystal, 0xff },
+       { nv_clk_src_href   , 0xff },
+       { nv_clk_src_core   , 0xff, 0, "core", 1000 },
+       { nv_clk_src_shader , 0xff, 0, "shader", 1000 },
+       { nv_clk_src_vdec   , 0xff, 0, "vdec", 1000 },
+       { nv_clk_src_max }
+};
+
+static int
+nvaa_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+               struct nouveau_oclass *oclass, void *data, u32 size,
+               struct nouveau_object **pobject)
+{
+       struct nvaa_clock_priv *priv;
+       int ret;
+
+       ret = nouveau_clock_create(parent, engine, oclass, nvaa_domains, &priv);
+       *pobject = nv_object(priv);
+       if (ret)
+               return ret;
+
+       priv->base.read = nvaa_clock_read;
+       priv->base.calc = nvaa_clock_calc;
+       priv->base.prog = nvaa_clock_prog;
+       priv->base.tidy = nvaa_clock_tidy;
+       return 0;
+}
+
+struct nouveau_oclass *
+nvaa_clock_oclass = &(struct nouveau_oclass) {
+       .handle = NV_SUBDEV(CLOCK, 0xaa),
+       .ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nvaa_clock_ctor,
+               .dtor = _nouveau_clock_dtor,
+               .init = _nouveau_clock_init,
+               .fini = _nouveau_clock_fini,
+       },
+};
index 3618ac6b6316416797a36e474bf613a12cf032ab..32e7064b819b6df4f9e5847beba7a826eaaed726 100644 (file)
@@ -58,8 +58,8 @@ struct nouveau_plane {
 };
 
 static uint32_t formats[] = {
-       DRM_FORMAT_NV12,
        DRM_FORMAT_UYVY,
+       DRM_FORMAT_NV12,
 };
 
 /* Sine can be approximated with
@@ -99,13 +99,28 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
        struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
        struct nouveau_bo *cur = nv_plane->cur;
        bool flip = nv_plane->flip;
-       int format = ALIGN(src_w * 4, 0x100);
        int soff = NV_PCRTC0_SIZE * nv_crtc->index;
        int soff2 = NV_PCRTC0_SIZE * !nv_crtc->index;
-       int ret;
+       int format, ret;
+
+       /* Source parameters given in 16.16 fixed point, ignore fractional. */
+       src_x >>= 16;
+       src_y >>= 16;
+       src_w >>= 16;
+       src_h >>= 16;
+
+       format = ALIGN(src_w * 4, 0x100);
 
        if (format > 0xffff)
-               return -EINVAL;
+               return -ERANGE;
+
+       if (dev->chipset >= 0x30) {
+               if (crtc_w < (src_w >> 1) || crtc_h < (src_h >> 1))
+                       return -ERANGE;
+       } else {
+               if (crtc_w < (src_w >> 3) || crtc_h < (src_h >> 3))
+                       return -ERANGE;
+       }
 
        ret = nouveau_bo_pin(nv_fb->nvbo, TTM_PL_FLAG_VRAM);
        if (ret)
@@ -113,12 +128,6 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 
        nv_plane->cur = nv_fb->nvbo;
 
-       /* Source parameters given in 16.16 fixed point, ignore fractional. */
-       src_x = src_x >> 16;
-       src_y = src_y >> 16;
-       src_w = src_w >> 16;
-       src_h = src_h >> 16;
-
        nv_mask(dev, NV_PCRTC_ENGINE_CTRL + soff, NV_CRTC_FSEL_OVERLAY, NV_CRTC_FSEL_OVERLAY);
        nv_mask(dev, NV_PCRTC_ENGINE_CTRL + soff2, NV_CRTC_FSEL_OVERLAY, 0);
 
@@ -245,14 +254,25 @@ nv10_overlay_init(struct drm_device *device)
 {
        struct nouveau_device *dev = nouveau_dev(device);
        struct nouveau_plane *plane = kzalloc(sizeof(struct nouveau_plane), GFP_KERNEL);
+       int num_formats = ARRAY_SIZE(formats);
        int ret;
 
        if (!plane)
                return;
 
+       switch (dev->chipset) {
+       case 0x10:
+       case 0x11:
+       case 0x15:
+       case 0x1a:
+       case 0x20:
+               num_formats = 1;
+               break;
+       }
+
        ret = drm_plane_init(device, &plane->base, 3 /* both crtc's */,
                             &nv10_plane_funcs,
-                            formats, ARRAY_SIZE(formats), false);
+                            formats, num_formats, false);
        if (ret)
                goto err;
 
index 95c740454049ad1b4a4cf23c2bc63d7038c7a362..1f0b6d238cfaa01a4527e4b02ee0caf8229aa269 100644 (file)
@@ -1,15 +1,10 @@
 #include <linux/pci.h>
 #include <linux/acpi.h>
 #include <linux/slab.h>
-#include <acpi/acpi_drivers.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/video.h>
-#include <acpi/acpi.h>
 #include <linux/mxm-wmi.h>
-
 #include <linux/vga_switcheroo.h>
-
 #include <drm/drm_edid.h>
+#include <acpi/video.h>
 
 #include "nouveau_drm.h"
 #include "nouveau_acpi.h"
index 7809d92183c4236c9f1f937ea6cde6a39e780063..29c3efdfc7dd714e00ae03525d0b9528fce841cd 100644 (file)
@@ -608,6 +608,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
        fence = nouveau_fence_ref(new_bo->bo.sync_obj);
        spin_unlock(&new_bo->bo.bdev->fence_lock);
        ret = nouveau_fence_sync(fence, chan);
+       nouveau_fence_unref(&fence);
        if (ret)
                return ret;
 
@@ -701,7 +702,7 @@ nouveau_finish_page_flip(struct nouveau_channel *chan,
 
        s = list_first_entry(&fctx->flip, struct nouveau_page_flip_state, head);
        if (s->event)
-               drm_send_vblank_event(dev, -1, s->event);
+               drm_send_vblank_event(dev, s->crtc, s->event);
 
        list_del(&s->head);
        if (ps)
index f8e66c08b11a292545a29e327966d3d4256e5f09..4e384a2f99c3627ea0fc6e31f5f0e34ac95e71e8 100644 (file)
@@ -1265,7 +1265,7 @@ nv50_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,
                    uint32_t start, uint32_t size)
 {
        struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
-       u32 end = max(start + size, (u32)256);
+       u32 end = min_t(u32, start + size, 256);
        u32 i;
 
        for (i = start; i < end; i++) {
index 0652ee0a20989db0b69f816d45e17f9354e5ca8a..f685035dbe39a7d7ad48e63a9b4ca2ea717701fe 100644 (file)
@@ -44,7 +44,7 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan,
        PROCESS_I2C_CHANNEL_TRANSACTION_PS_ALLOCATION args;
        int index = GetIndexIntoMasterTable(COMMAND, ProcessI2cChannelTransaction);
        unsigned char *base;
-       u16 out;
+       u16 out = cpu_to_le16(0);
 
        memset(&args, 0, sizeof(args));
 
@@ -55,11 +55,14 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan,
                        DRM_ERROR("hw i2c: tried to write too many bytes (%d vs 3)\n", num);
                        return -EINVAL;
                }
-               args.ucRegIndex = buf[0];
-               if (num > 1) {
+               if (buf == NULL)
+                       args.ucRegIndex = 0;
+               else
+                       args.ucRegIndex = buf[0];
+               if (num)
                        num--;
+               if (num)
                        memcpy(&out, &buf[1], num);
-               }
                args.lpI2CDataOut = cpu_to_le16(out);
        } else {
                if (num > ATOM_MAX_HW_I2C_READ) {
@@ -96,14 +99,14 @@ int radeon_atom_hw_i2c_xfer(struct i2c_adapter *i2c_adap,
        struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap);
        struct i2c_msg *p;
        int i, remaining, current_count, buffer_offset, max_bytes, ret;
-       u8 buf = 0, flags;
+       u8 flags;
 
        /* check for bus probe */
        p = &msgs[0];
        if ((num == 1) && (p->len == 0)) {
                ret = radeon_process_i2c_ch(i2c,
                                            p->addr, HW_I2C_WRITE,
-                                           &buf, 1);
+                                           NULL, 0);
                if (ret)
                        return ret;
                else
index 009f46e0ce72db47534d2b7667bcd0119607d91b..de86493cbc44af60a8079028e8e509f8cee81c7e 100644 (file)
@@ -93,11 +93,13 @@ void dce6_afmt_select_pin(struct drm_encoder *encoder)
        struct radeon_device *rdev = encoder->dev->dev_private;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-       u32 offset = dig->afmt->offset;
+       u32 offset;
 
-       if (!dig->afmt->pin)
+       if (!dig || !dig->afmt || !dig->afmt->pin)
                return;
 
+       offset = dig->afmt->offset;
+
        WREG32(AFMT_AUDIO_SRC_CONTROL + offset,
               AFMT_AUDIO_SRC_SELECT(dig->afmt->pin->id));
 }
@@ -112,7 +114,7 @@ void dce6_afmt_write_latency_fields(struct drm_encoder *encoder,
        struct radeon_connector *radeon_connector = NULL;
        u32 tmp = 0, offset;
 
-       if (!dig->afmt->pin)
+       if (!dig || !dig->afmt || !dig->afmt->pin)
                return;
 
        offset = dig->afmt->pin->offset;
@@ -156,7 +158,7 @@ void dce6_afmt_write_speaker_allocation(struct drm_encoder *encoder)
        u8 *sadb;
        int sad_count;
 
-       if (!dig->afmt->pin)
+       if (!dig || !dig->afmt || !dig->afmt->pin)
                return;
 
        offset = dig->afmt->pin->offset;
@@ -217,7 +219,7 @@ void dce6_afmt_write_sad_regs(struct drm_encoder *encoder)
                { AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13, HDMI_AUDIO_CODING_TYPE_WMA_PRO },
        };
 
-       if (!dig->afmt->pin)
+       if (!dig || !dig->afmt || !dig->afmt->pin)
                return;
 
        offset = dig->afmt->pin->offset;
index cdc003085a76b802eddba1d1ba1a9df5e739dc26..49c4d48f54d616b49b7af261d8fa2d71586ab8fd 100644 (file)
@@ -785,8 +785,8 @@ static void ni_apply_state_adjust_rules(struct radeon_device *rdev,
        struct ni_ps *ps = ni_get_ps(rps);
        struct radeon_clock_and_voltage_limits *max_limits;
        bool disable_mclk_switching;
-       u32 mclk, sclk;
-       u16 vddc, vddci;
+       u32 mclk;
+       u16 vddci;
        u32 max_sclk_vddc, max_mclk_vddci, max_mclk_vddc;
        int i;
 
@@ -839,24 +839,14 @@ static void ni_apply_state_adjust_rules(struct radeon_device *rdev,
 
        /* XXX validate the min clocks required for display */
 
+       /* adjust low state */
        if (disable_mclk_switching) {
-               mclk  = ps->performance_levels[ps->performance_level_count - 1].mclk;
-               sclk = ps->performance_levels[0].sclk;
-               vddc = ps->performance_levels[0].vddc;
-               vddci = ps->performance_levels[ps->performance_level_count - 1].vddci;
-       } else {
-               sclk = ps->performance_levels[0].sclk;
-               mclk = ps->performance_levels[0].mclk;
-               vddc = ps->performance_levels[0].vddc;
-               vddci = ps->performance_levels[0].vddci;
+               ps->performance_levels[0].mclk =
+                       ps->performance_levels[ps->performance_level_count - 1].mclk;
+               ps->performance_levels[0].vddci =
+                       ps->performance_levels[ps->performance_level_count - 1].vddci;
        }
 
-       /* adjusted low state */
-       ps->performance_levels[0].sclk = sclk;
-       ps->performance_levels[0].mclk = mclk;
-       ps->performance_levels[0].vddc = vddc;
-       ps->performance_levels[0].vddci = vddci;
-
        btc_skip_blacklist_clocks(rdev, max_limits->sclk, max_limits->mclk,
                                  &ps->performance_levels[0].sclk,
                                  &ps->performance_levels[0].mclk);
@@ -868,11 +858,15 @@ static void ni_apply_state_adjust_rules(struct radeon_device *rdev,
                        ps->performance_levels[i].vddc = ps->performance_levels[i - 1].vddc;
        }
 
+       /* adjust remaining states */
        if (disable_mclk_switching) {
                mclk = ps->performance_levels[0].mclk;
+               vddci = ps->performance_levels[0].vddci;
                for (i = 1; i < ps->performance_level_count; i++) {
                        if (mclk < ps->performance_levels[i].mclk)
                                mclk = ps->performance_levels[i].mclk;
+                       if (vddci < ps->performance_levels[i].vddci)
+                               vddci = ps->performance_levels[i].vddci;
                }
                for (i = 0; i < ps->performance_level_count; i++) {
                        ps->performance_levels[i].mclk = mclk;
index 4b89262f3f0e37242de23b7b6ea2fc555d141da3..b7d3ecba43e34d3b559ee072800101532150c631 100644 (file)
@@ -304,9 +304,9 @@ void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
                        WREG32(DCCG_AUDIO_DTO1_MODULE, dto_modulo);
                        WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */
                }
-       } else if (ASIC_IS_DCE3(rdev)) {
+       } else {
                /* according to the reg specs, this should DCE3.2 only, but in
-                * practice it seems to cover DCE3.0/3.1 as well.
+                * practice it seems to cover DCE2.0/3.0/3.1 as well.
                 */
                if (dig->dig_encoder == 0) {
                        WREG32(DCCG_AUDIO_DTO0_PHASE, base_rate * 100);
@@ -317,10 +317,6 @@ void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
                        WREG32(DCCG_AUDIO_DTO1_MODULE, clock * 100);
                        WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */
                }
-       } else {
-               /* according to the reg specs, this should be DCE2.0 and DCE3.0/3.1 */
-               WREG32(AUDIO_DTO, AUDIO_DTO_PHASE(base_rate / 10) |
-                      AUDIO_DTO_MODULE(clock / 10));
        }
 }
 
index ecf2a3960c0786ca02fc3aef84afab61e0e6303f..b1f990d0eaa101d1bce56fabfc4b286ff01de7e9 100644 (file)
@@ -2710,10 +2710,10 @@ void radeon_vm_fence(struct radeon_device *rdev,
                     struct radeon_vm *vm,
                     struct radeon_fence *fence);
 uint64_t radeon_vm_map_gart(struct radeon_device *rdev, uint64_t addr);
-int radeon_vm_bo_update_pte(struct radeon_device *rdev,
-                           struct radeon_vm *vm,
-                           struct radeon_bo *bo,
-                           struct ttm_mem_reg *mem);
+int radeon_vm_bo_update(struct radeon_device *rdev,
+                       struct radeon_vm *vm,
+                       struct radeon_bo *bo,
+                       struct ttm_mem_reg *mem);
 void radeon_vm_bo_invalidate(struct radeon_device *rdev,
                             struct radeon_bo *bo);
 struct radeon_bo_va *radeon_vm_bo_find(struct radeon_vm *vm,
index 98a9074b306b640644f576e928d4e28701495bb4..77e9d07c55b6701cbdb0a55bcbc9b68954e5c0d7 100644 (file)
 #include <linux/acpi.h>
 #include <linux/slab.h>
 #include <linux/power_supply.h>
-#include <acpi/acpi_drivers.h>
-#include <acpi/acpi_bus.h>
+#include <linux/vga_switcheroo.h>
 #include <acpi/video.h>
-
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
 #include "radeon.h"
 #include "radeon_acpi.h"
 #include "atom.h"
 
-#include <linux/vga_switcheroo.h>
-
 #define ACPI_AC_CLASS           "ac_adapter"
 
 extern void radeon_pm_acpi_event_handler(struct radeon_device *rdev);
index f79ee184ffd5849f4d0e0ec1b87b0d94d0f1f131..5c39bf7c3d88668bad65ef9667de82a0a145f196 100644 (file)
@@ -2918,7 +2918,7 @@ int radeon_atom_get_memory_pll_dividers(struct radeon_device *rdev,
                        mpll_param->dll_speed = args.ucDllSpeed;
                        mpll_param->bwcntl = args.ucBWCntl;
                        mpll_param->vco_mode =
-                               (args.ucPllCntlFlag & MPLL_CNTL_FLAG_VCO_MODE_MASK) ? 1 : 0;
+                               (args.ucPllCntlFlag & MPLL_CNTL_FLAG_VCO_MODE_MASK);
                        mpll_param->yclk_sel =
                                (args.ucPllCntlFlag & MPLL_CNTL_FLAG_BYPASS_DQ_PLL) ? 1 : 0;
                        mpll_param->qdr =
index f41594b2eeac775794f3d2b2d050a06e387d9025..0b366169d64de55c52e4c2d9c26d1c3b9db19b2d 100644 (file)
@@ -360,13 +360,13 @@ static int radeon_bo_vm_update_pte(struct radeon_cs_parser *parser,
        struct radeon_bo *bo;
        int r;
 
-       r = radeon_vm_bo_update_pte(rdev, vm, rdev->ring_tmp_bo.bo, &rdev->ring_tmp_bo.bo->tbo.mem);
+       r = radeon_vm_bo_update(rdev, vm, rdev->ring_tmp_bo.bo, &rdev->ring_tmp_bo.bo->tbo.mem);
        if (r) {
                return r;
        }
        list_for_each_entry(lobj, &parser->validated, tv.head) {
                bo = lobj->bo;
-               r = radeon_vm_bo_update_pte(parser->rdev, vm, bo, &bo->tbo.mem);
+               r = radeon_vm_bo_update(parser->rdev, vm, bo, &bo->tbo.mem);
                if (r) {
                        return r;
                }
index 543dcfae7e6f5f9a01797a9bb90455be5fef88c5..00e0d449021c343015540ea3baf1028b85a10090 100644 (file)
  * 1.31- Add support for num Z pipes from GET_PARAM
  * 1.32- fixes for rv740 setup
  * 1.33- Add r6xx/r7xx const buffer support
+ * 1.34- fix evergreen/cayman GS register
  */
 #define DRIVER_MAJOR           1
-#define DRIVER_MINOR           33
+#define DRIVER_MINOR           34
 #define DRIVER_PATCHLEVEL      0
 
 long radeon_drm_ioctl(struct file *filp,
index 3044e504f4ec9a8a4cbf6ef18bbd009fe7672c01..96e440061bdbf5b65a6213047f62bbeb89aea77f 100644 (file)
@@ -29,6 +29,7 @@
 #include <drm/radeon_drm.h>
 #include "radeon.h"
 #include "radeon_reg.h"
+#include "radeon_trace.h"
 
 /*
  * GART
@@ -737,6 +738,7 @@ struct radeon_fence *radeon_vm_grab_id(struct radeon_device *rdev,
        for (i = 0; i < 2; ++i) {
                if (choices[i]) {
                        vm->id = choices[i];
+                       trace_radeon_vm_grab_id(vm->id, ring);
                        return rdev->vm_manager.active[choices[i]];
                }
        }
@@ -1116,7 +1118,7 @@ static void radeon_vm_update_ptes(struct radeon_device *rdev,
 }
 
 /**
- * radeon_vm_bo_update_pte - map a bo into the vm page table
+ * radeon_vm_bo_update - map a bo into the vm page table
  *
  * @rdev: radeon_device pointer
  * @vm: requested vm
@@ -1128,10 +1130,10 @@ static void radeon_vm_update_ptes(struct radeon_device *rdev,
  *
  * Object have to be reserved & global and local mutex must be locked!
  */
-int radeon_vm_bo_update_pte(struct radeon_device *rdev,
-                           struct radeon_vm *vm,
-                           struct radeon_bo *bo,
-                           struct ttm_mem_reg *mem)
+int radeon_vm_bo_update(struct radeon_device *rdev,
+                       struct radeon_vm *vm,
+                       struct radeon_bo *bo,
+                       struct ttm_mem_reg *mem)
 {
        struct radeon_ib ib;
        struct radeon_bo_va *bo_va;
@@ -1176,6 +1178,8 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev,
                bo_va->valid = false;
        }
 
+       trace_radeon_vm_bo_update(bo_va);
+
        nptes = radeon_bo_ngpu_pages(bo);
 
        /* assume two extra pdes in case the mapping overlaps the borders */
@@ -1257,7 +1261,7 @@ int radeon_vm_bo_rmv(struct radeon_device *rdev,
        mutex_lock(&rdev->vm_manager.lock);
        mutex_lock(&bo_va->vm->mutex);
        if (bo_va->soffset) {
-               r = radeon_vm_bo_update_pte(rdev, bo_va->vm, bo_va->bo, NULL);
+               r = radeon_vm_bo_update(rdev, bo_va->vm, bo_va->bo, NULL);
        }
        mutex_unlock(&rdev->vm_manager.lock);
        list_del(&bo_va->vm_list);
index d1385ccc672c4976aff90d9150fb221f98c29441..dc75bb603ea5f1921795c01be6d78438d5b8d98d 100644 (file)
@@ -537,8 +537,7 @@ static ssize_t radeon_hwmon_show_temp(struct device *dev,
                                      struct device_attribute *attr,
                                      char *buf)
 {
-       struct drm_device *ddev = dev_get_drvdata(dev);
-       struct radeon_device *rdev = ddev->dev_private;
+       struct radeon_device *rdev = dev_get_drvdata(dev);
        int temp;
 
        if (rdev->asic->pm.get_temperature)
@@ -566,23 +565,14 @@ static ssize_t radeon_hwmon_show_temp_thresh(struct device *dev,
        return snprintf(buf, PAGE_SIZE, "%d\n", temp);
 }
 
-static ssize_t radeon_hwmon_show_name(struct device *dev,
-                                     struct device_attribute *attr,
-                                     char *buf)
-{
-       return sprintf(buf, "radeon\n");
-}
-
 static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, radeon_hwmon_show_temp, NULL, 0);
 static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, radeon_hwmon_show_temp_thresh, NULL, 0);
 static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, radeon_hwmon_show_temp_thresh, NULL, 1);
-static SENSOR_DEVICE_ATTR(name, S_IRUGO, radeon_hwmon_show_name, NULL, 0);
 
 static struct attribute *hwmon_attributes[] = {
        &sensor_dev_attr_temp1_input.dev_attr.attr,
        &sensor_dev_attr_temp1_crit.dev_attr.attr,
        &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,
-       &sensor_dev_attr_name.dev_attr.attr,
        NULL
 };
 
@@ -607,11 +597,15 @@ static const struct attribute_group hwmon_attrgroup = {
        .is_visible = hwmon_attributes_visible,
 };
 
+static const struct attribute_group *hwmon_groups[] = {
+       &hwmon_attrgroup,
+       NULL
+};
+
 static int radeon_hwmon_init(struct radeon_device *rdev)
 {
        int err = 0;
-
-       rdev->pm.int_hwmon_dev = NULL;
+       struct device *hwmon_dev;
 
        switch (rdev->pm.int_thermal_type) {
        case THERMAL_TYPE_RV6XX:
@@ -624,20 +618,13 @@ static int radeon_hwmon_init(struct radeon_device *rdev)
        case THERMAL_TYPE_KV:
                if (rdev->asic->pm.get_temperature == NULL)
                        return err;
-               rdev->pm.int_hwmon_dev = hwmon_device_register(rdev->dev);
-               if (IS_ERR(rdev->pm.int_hwmon_dev)) {
-                       err = PTR_ERR(rdev->pm.int_hwmon_dev);
+               hwmon_dev = hwmon_device_register_with_groups(rdev->dev,
+                                                             "radeon", rdev,
+                                                             hwmon_groups);
+               if (IS_ERR(hwmon_dev)) {
+                       err = PTR_ERR(hwmon_dev);
                        dev_err(rdev->dev,
                                "Unable to register hwmon device: %d\n", err);
-                       break;
-               }
-               dev_set_drvdata(rdev->pm.int_hwmon_dev, rdev->ddev);
-               err = sysfs_create_group(&rdev->pm.int_hwmon_dev->kobj,
-                                        &hwmon_attrgroup);
-               if (err) {
-                       dev_err(rdev->dev,
-                               "Unable to create hwmon sysfs file: %d\n", err);
-                       hwmon_device_unregister(rdev->dev);
                }
                break;
        default:
@@ -647,14 +634,6 @@ static int radeon_hwmon_init(struct radeon_device *rdev)
        return err;
 }
 
-static void radeon_hwmon_fini(struct radeon_device *rdev)
-{
-       if (rdev->pm.int_hwmon_dev) {
-               sysfs_remove_group(&rdev->pm.int_hwmon_dev->kobj, &hwmon_attrgroup);
-               hwmon_device_unregister(rdev->pm.int_hwmon_dev);
-       }
-}
-
 static void radeon_dpm_thermal_work_handler(struct work_struct *work)
 {
        struct radeon_device *rdev =
@@ -1337,8 +1316,6 @@ static void radeon_pm_fini_old(struct radeon_device *rdev)
 
        if (rdev->pm.power_state)
                kfree(rdev->pm.power_state);
-
-       radeon_hwmon_fini(rdev);
 }
 
 static void radeon_pm_fini_dpm(struct radeon_device *rdev)
@@ -1358,8 +1335,6 @@ static void radeon_pm_fini_dpm(struct radeon_device *rdev)
 
        if (rdev->pm.power_state)
                kfree(rdev->pm.power_state);
-
-       radeon_hwmon_fini(rdev);
 }
 
 void radeon_pm_fini(struct radeon_device *rdev)
index 9f0e18172b6e8074bf865e93902d67f1584141bd..0473257d407886e175f77347078b2de54c61cfc3 100644 (file)
@@ -47,6 +47,39 @@ TRACE_EVENT(radeon_cs,
                      __entry->fences)
 );
 
+TRACE_EVENT(radeon_vm_grab_id,
+           TP_PROTO(unsigned vmid, int ring),
+           TP_ARGS(vmid, ring),
+           TP_STRUCT__entry(
+                            __field(u32, vmid)
+                            __field(u32, ring)
+                            ),
+
+           TP_fast_assign(
+                          __entry->vmid = vmid;
+                          __entry->ring = ring;
+                          ),
+           TP_printk("vmid=%u, ring=%u", __entry->vmid, __entry->ring)
+);
+
+TRACE_EVENT(radeon_vm_bo_update,
+           TP_PROTO(struct radeon_bo_va *bo_va),
+           TP_ARGS(bo_va),
+           TP_STRUCT__entry(
+                            __field(u64, soffset)
+                            __field(u64, eoffset)
+                            __field(u32, flags)
+                            ),
+
+           TP_fast_assign(
+                          __entry->soffset = bo_va->soffset;
+                          __entry->eoffset = bo_va->eoffset;
+                          __entry->flags = bo_va->flags;
+                          ),
+           TP_printk("soffs=%010llx, eoffs=%010llx, flags=%08x",
+                     __entry->soffset, __entry->eoffset, __entry->flags)
+);
+
 TRACE_EVENT(radeon_vm_set_page,
            TP_PROTO(uint64_t pe, uint64_t addr, unsigned count,
                     uint32_t incr, uint32_t flags),
index a072fa8c46b04a00a9c78886b20a29615f7ad86c..d46b58d078aad94eaca7050eb3deb9c1375583a7 100644 (file)
@@ -21,7 +21,7 @@ cayman 0x9400
 0x000089AC VGT_COMPUTE_THREAD_GOURP_SIZE
 0x000089B0 VGT_HS_OFFCHIP_PARAM
 0x00008A14 PA_CL_ENHANCE
-0x00008A60 PA_SC_LINE_STIPPLE_VALUE
+0x00008A60 PA_SU_LINE_STIPPLE_VALUE
 0x00008B10 PA_SC_LINE_STIPPLE_STATE
 0x00008BF0 PA_SC_ENHANCE
 0x00008D8C SQ_DYN_GPR_CNTL_PS_FLUSH_REQ
@@ -532,7 +532,7 @@ cayman 0x9400
 0x00028B84 PA_SU_POLY_OFFSET_FRONT_OFFSET
 0x00028B88 PA_SU_POLY_OFFSET_BACK_SCALE
 0x00028B8C PA_SU_POLY_OFFSET_BACK_OFFSET
-0x00028B74 VGT_GS_INSTANCE_CNT
+0x00028B90 VGT_GS_INSTANCE_CNT
 0x00028BD4 PA_SC_CENTROID_PRIORITY_0
 0x00028BD8 PA_SC_CENTROID_PRIORITY_1
 0x00028BDC PA_SC_LINE_CNTL
index b912a37689bf818a0fccd576f6436f71e4e936ff..57745c8761c863714abe07ba2ff73324980ea18e 100644 (file)
@@ -22,7 +22,7 @@ evergreen 0x9400
 0x000089A4 VGT_COMPUTE_START_Z
 0x000089AC VGT_COMPUTE_THREAD_GOURP_SIZE
 0x00008A14 PA_CL_ENHANCE
-0x00008A60 PA_SC_LINE_STIPPLE_VALUE
+0x00008A60 PA_SU_LINE_STIPPLE_VALUE
 0x00008B10 PA_SC_LINE_STIPPLE_STATE
 0x00008BF0 PA_SC_ENHANCE
 0x00008D8C SQ_DYN_GPR_CNTL_PS_FLUSH_REQ
@@ -545,7 +545,7 @@ evergreen 0x9400
 0x00028B84 PA_SU_POLY_OFFSET_FRONT_OFFSET
 0x00028B88 PA_SU_POLY_OFFSET_BACK_SCALE
 0x00028B8C PA_SU_POLY_OFFSET_BACK_OFFSET
-0x00028B74 VGT_GS_INSTANCE_CNT
+0x00028B90 VGT_GS_INSTANCE_CNT
 0x00028C00 PA_SC_LINE_CNTL
 0x00028C08 PA_SU_VTX_CNTL
 0x00028C0C PA_CL_GB_VERT_CLIP_ADJ
index 6a64ccaa0695643add9ee7e6b3f383202d35a988..a36736dab5e0694cd5a7b78d6dbb013b484cb8f6 100644 (file)
@@ -3882,8 +3882,15 @@ static int si_mc_init(struct radeon_device *rdev)
        rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0);
        rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0);
        /* size in MB on si */
-       rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL;
-       rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL;
+       tmp = RREG32(CONFIG_MEMSIZE);
+       /* some boards may have garbage in the upper 16 bits */
+       if (tmp & 0xffff0000) {
+               DRM_INFO("Probable bad vram size: 0x%08x\n", tmp);
+               if (tmp & 0xffff)
+                       tmp &= 0xffff;
+       }
+       rdev->mc.mc_vram_size = tmp * 1024ULL * 1024ULL;
+       rdev->mc.real_vram_size = rdev->mc.mc_vram_size;
        rdev->mc.visible_vram_size = rdev->mc.aper_size;
        si_vram_gtt_location(rdev, &rdev->mc);
        radeon_update_bandwidth_info(rdev);
index 28e178137718090f317c8884da071458900cce65..07eba596d458d22b63bc9f0a731d6ca3befae036 100644 (file)
@@ -135,11 +135,11 @@ int tegra_drm_submit(struct tegra_drm_context *context,
        unsigned int num_relocs = args->num_relocs;
        unsigned int num_waitchks = args->num_waitchks;
        struct drm_tegra_cmdbuf __user *cmdbufs =
-               (void * __user)(uintptr_t)args->cmdbufs;
+               (void __user *)(uintptr_t)args->cmdbufs;
        struct drm_tegra_reloc __user *relocs =
-               (void * __user)(uintptr_t)args->relocs;
+               (void __user *)(uintptr_t)args->relocs;
        struct drm_tegra_waitchk __user *waitchks =
-               (void * __user)(uintptr_t)args->waitchks;
+               (void __user *)(uintptr_t)args->waitchks;
        struct drm_tegra_syncpt syncpt;
        struct host1x_job *job;
        int err;
@@ -163,9 +163,10 @@ int tegra_drm_submit(struct tegra_drm_context *context,
                struct drm_tegra_cmdbuf cmdbuf;
                struct host1x_bo *bo;
 
-               err = copy_from_user(&cmdbuf, cmdbufs, sizeof(cmdbuf));
-               if (err)
+               if (copy_from_user(&cmdbuf, cmdbufs, sizeof(cmdbuf))) {
+                       err = -EFAULT;
                        goto fail;
+               }
 
                bo = host1x_bo_lookup(drm, file, cmdbuf.handle);
                if (!bo) {
@@ -178,10 +179,11 @@ int tegra_drm_submit(struct tegra_drm_context *context,
                cmdbufs++;
        }
 
-       err = copy_from_user(job->relocarray, relocs,
-                            sizeof(*relocs) * num_relocs);
-       if (err)
+       if (copy_from_user(job->relocarray, relocs,
+                          sizeof(*relocs) * num_relocs)) {
+               err = -EFAULT;
                goto fail;
+       }
 
        while (num_relocs--) {
                struct host1x_reloc *reloc = &job->relocarray[num_relocs];
@@ -199,15 +201,17 @@ int tegra_drm_submit(struct tegra_drm_context *context,
                }
        }
 
-       err = copy_from_user(job->waitchk, waitchks,
-                            sizeof(*waitchks) * num_waitchks);
-       if (err)
+       if (copy_from_user(job->waitchk, waitchks,
+                          sizeof(*waitchks) * num_waitchks)) {
+               err = -EFAULT;
                goto fail;
+       }
 
-       err = copy_from_user(&syncpt, (void * __user)(uintptr_t)args->syncpts,
-                            sizeof(syncpt));
-       if (err)
+       if (copy_from_user(&syncpt, (void __user *)(uintptr_t)args->syncpts,
+                          sizeof(syncpt))) {
+               err = -EFAULT;
                goto fail;
+       }
 
        job->is_addr_reg = context->client->ops->is_addr_reg;
        job->syncpt_incrs = syncpt.incrs;
@@ -573,7 +577,7 @@ static void tegra_debugfs_cleanup(struct drm_minor *minor)
 }
 #endif
 
-struct drm_driver tegra_drm_driver = {
+static struct drm_driver tegra_drm_driver = {
        .driver_features = DRIVER_MODESET | DRIVER_GEM,
        .load = tegra_drm_load,
        .unload = tegra_drm_unload,
index fdfe259ed7f8e5e403f984d533b54a3257128aef..7da0b923131f05ca5f67fb8113f2fd9754023a15 100644 (file)
@@ -116,7 +116,7 @@ host1x_client_to_dc(struct host1x_client *client)
 
 static inline struct tegra_dc *to_tegra_dc(struct drm_crtc *crtc)
 {
-       return container_of(crtc, struct tegra_dc, base);
+       return crtc ? container_of(crtc, struct tegra_dc, base) : NULL;
 }
 
 static inline void tegra_dc_writel(struct tegra_dc *dc, unsigned long value,
index 490f7719e317ed80319f4961a69d3e349d1ad333..a3835e7de1842b84145e52c40ef15ed21e183323 100644 (file)
@@ -247,7 +247,7 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper,
                 info->var.yoffset * fb->pitches[0];
 
        drm->mode_config.fb_base = (resource_size_t)bo->paddr;
-       info->screen_base = bo->vaddr + offset;
+       info->screen_base = (void __iomem *)bo->vaddr + offset;
        info->screen_size = size;
        info->fix.smem_start = (unsigned long)(bo->paddr + offset);
        info->fix.smem_len = size;
index ba47ca4fb880cc239a9b5c454b3b6c5b5adcddc8..3b29018913a5f2bb9da1a2ae2f57ddc89280bbe8 100644 (file)
@@ -14,6 +14,8 @@
 
 struct tegra_rgb {
        struct tegra_output output;
+       struct tegra_dc *dc;
+
        struct clk *clk_parent;
        struct clk *clk;
 };
@@ -84,18 +86,18 @@ static void tegra_dc_write_regs(struct tegra_dc *dc,
 
 static int tegra_output_rgb_enable(struct tegra_output *output)
 {
-       struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
+       struct tegra_rgb *rgb = to_rgb(output);
 
-       tegra_dc_write_regs(dc, rgb_enable, ARRAY_SIZE(rgb_enable));
+       tegra_dc_write_regs(rgb->dc, rgb_enable, ARRAY_SIZE(rgb_enable));
 
        return 0;
 }
 
 static int tegra_output_rgb_disable(struct tegra_output *output)
 {
-       struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
+       struct tegra_rgb *rgb = to_rgb(output);
 
-       tegra_dc_write_regs(dc, rgb_disable, ARRAY_SIZE(rgb_disable));
+       tegra_dc_write_regs(rgb->dc, rgb_disable, ARRAY_SIZE(rgb_disable));
 
        return 0;
 }
@@ -146,6 +148,7 @@ int tegra_dc_rgb_probe(struct tegra_dc *dc)
 
        rgb->output.dev = dc->dev;
        rgb->output.of_node = np;
+       rgb->dc = dc;
 
        err = tegra_output_probe(&rgb->output);
        if (err < 0)
index 24ffbe990736e3e0751609e78d113d08c952b69f..8d67b943ac05ce2d1dd44597d00a1e5a07fd9bdb 100644 (file)
@@ -125,6 +125,12 @@ static int udl_gem_get_pages(struct udl_gem_object *obj, gfp_t gfpmask)
 
 static void udl_gem_put_pages(struct udl_gem_object *obj)
 {
+       if (obj->base.import_attach) {
+               drm_free_large(obj->pages);
+               obj->pages = NULL;
+               return;
+       }
+
        drm_gem_put_pages(&obj->base, obj->pages, false, false);
        obj->pages = NULL;
 }
index 7776e6f0aef650d475e39640b3d781b42f8d7036..0489c61524826f2e2b673628783393639f0c591e 100644 (file)
@@ -150,6 +150,8 @@ struct vmw_ttm_tt {
        bool mapped;
 };
 
+const size_t vmw_tt_size = sizeof(struct vmw_ttm_tt);
+
 /**
  * Helper functions to advance a struct vmw_piter iterator.
  *
index db85985c7086f04648b6a4bb89b83f352c393ec2..20890ad8408bb5ef377c4ff54c80397c3105efaf 100644 (file)
@@ -615,6 +615,7 @@ extern int vmw_mmap(struct file *filp, struct vm_area_struct *vma);
  * TTM buffer object driver - vmwgfx_buffer.c
  */
 
+extern const size_t vmw_tt_size;
 extern struct ttm_placement vmw_vram_placement;
 extern struct ttm_placement vmw_vram_ne_placement;
 extern struct ttm_placement vmw_vram_sys_placement;
index ecb3d867b4260d9c9ada27438fb252dac1fc77e9..03f1c203863193621d9941af3051169ea2f79afb 100644 (file)
@@ -75,6 +75,7 @@ void vmw_display_unit_cleanup(struct vmw_display_unit *du)
                vmw_surface_unreference(&du->cursor_surface);
        if (du->cursor_dmabuf)
                vmw_dmabuf_unreference(&du->cursor_dmabuf);
+       drm_sysfs_connector_remove(&du->connector);
        drm_crtc_cleanup(&du->crtc);
        drm_encoder_cleanup(&du->encoder);
        drm_connector_cleanup(&du->connector);
index 79f7e8e605296902bb4355b78e2e78d1792f89fa..a055a26819c2b6b7963d6d245576e17b8d9a7500 100644 (file)
@@ -260,6 +260,7 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
                connector->encoder = NULL;
                encoder->crtc = NULL;
                crtc->fb = NULL;
+               crtc->enabled = false;
 
                vmw_ldu_del_active(dev_priv, ldu);
 
@@ -285,6 +286,7 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
        crtc->x = set->x;
        crtc->y = set->y;
        crtc->mode = *mode;
+       crtc->enabled = true;
 
        vmw_ldu_add_active(dev_priv, ldu, vfb);
 
@@ -369,6 +371,8 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
        encoder->possible_crtcs = (1 << unit);
        encoder->possible_clones = 0;
 
+       (void) drm_sysfs_connector_add(connector);
+
        drm_crtc_init(dev, crtc, &vmw_legacy_crtc_funcs);
 
        drm_mode_crtc_set_gamma_size(crtc, 256);
index efe2b74c5eb17f1f86b12048be5884c9aabf50b2..9b5ea2ac7ddff21562aa7ef52a2f96872c623116 100644 (file)
@@ -352,6 +352,38 @@ int vmw_user_lookup_handle(struct vmw_private *dev_priv,
 /**
  * Buffer management.
  */
+
+/**
+ * vmw_dmabuf_acc_size - Calculate the pinned memory usage of buffers
+ *
+ * @dev_priv: Pointer to a struct vmw_private identifying the device.
+ * @size: The requested buffer size.
+ * @user: Whether this is an ordinary dma buffer or a user dma buffer.
+ */
+static size_t vmw_dmabuf_acc_size(struct vmw_private *dev_priv, size_t size,
+                                 bool user)
+{
+       static size_t struct_size, user_struct_size;
+       size_t num_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
+       size_t page_array_size = ttm_round_pot(num_pages * sizeof(void *));
+
+       if (unlikely(struct_size == 0)) {
+               size_t backend_size = ttm_round_pot(vmw_tt_size);
+
+               struct_size = backend_size +
+                       ttm_round_pot(sizeof(struct vmw_dma_buffer));
+               user_struct_size = backend_size +
+                       ttm_round_pot(sizeof(struct vmw_user_dma_buffer));
+       }
+
+       if (dev_priv->map_mode == vmw_dma_alloc_coherent)
+               page_array_size +=
+                       ttm_round_pot(num_pages * sizeof(dma_addr_t));
+
+       return ((user) ? user_struct_size : struct_size) +
+               page_array_size;
+}
+
 void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo)
 {
        struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo);
@@ -359,6 +391,13 @@ void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo)
        kfree(vmw_bo);
 }
 
+static void vmw_user_dmabuf_destroy(struct ttm_buffer_object *bo)
+{
+       struct vmw_user_dma_buffer *vmw_user_bo = vmw_user_dma_buffer(bo);
+
+       ttm_prime_object_kfree(vmw_user_bo, prime);
+}
+
 int vmw_dmabuf_init(struct vmw_private *dev_priv,
                    struct vmw_dma_buffer *vmw_bo,
                    size_t size, struct ttm_placement *placement,
@@ -368,28 +407,23 @@ int vmw_dmabuf_init(struct vmw_private *dev_priv,
        struct ttm_bo_device *bdev = &dev_priv->bdev;
        size_t acc_size;
        int ret;
+       bool user = (bo_free == &vmw_user_dmabuf_destroy);
 
-       BUG_ON(!bo_free);
+       BUG_ON(!bo_free && (!user && (bo_free != vmw_dmabuf_bo_free)));
 
-       acc_size = ttm_bo_acc_size(bdev, size, sizeof(struct vmw_dma_buffer));
+       acc_size = vmw_dmabuf_acc_size(dev_priv, size, user);
        memset(vmw_bo, 0, sizeof(*vmw_bo));
 
        INIT_LIST_HEAD(&vmw_bo->res_list);
 
        ret = ttm_bo_init(bdev, &vmw_bo->base, size,
-                         ttm_bo_type_device, placement,
+                         (user) ? ttm_bo_type_device :
+                         ttm_bo_type_kernel, placement,
                          0, interruptible,
                          NULL, acc_size, NULL, bo_free);
        return ret;
 }
 
-static void vmw_user_dmabuf_destroy(struct ttm_buffer_object *bo)
-{
-       struct vmw_user_dma_buffer *vmw_user_bo = vmw_user_dma_buffer(bo);
-
-       ttm_prime_object_kfree(vmw_user_bo, prime);
-}
-
 static void vmw_user_dmabuf_release(struct ttm_base_object **p_base)
 {
        struct vmw_user_dma_buffer *vmw_user_bo;
@@ -781,54 +815,55 @@ err_ref:
 }
 
 
+/**
+ * vmw_dumb_create - Create a dumb kms buffer
+ *
+ * @file_priv: Pointer to a struct drm_file identifying the caller.
+ * @dev: Pointer to the drm device.
+ * @args: Pointer to a struct drm_mode_create_dumb structure
+ *
+ * This is a driver callback for the core drm create_dumb functionality.
+ * Note that this is very similar to the vmw_dmabuf_alloc ioctl, except
+ * that the arguments have a different format.
+ */
 int vmw_dumb_create(struct drm_file *file_priv,
                    struct drm_device *dev,
                    struct drm_mode_create_dumb *args)
 {
        struct vmw_private *dev_priv = vmw_priv(dev);
        struct vmw_master *vmaster = vmw_master(file_priv->master);
-       struct vmw_user_dma_buffer *vmw_user_bo;
-       struct ttm_buffer_object *tmp;
+       struct vmw_dma_buffer *dma_buf;
        int ret;
 
        args->pitch = args->width * ((args->bpp + 7) / 8);
        args->size = args->pitch * args->height;
 
-       vmw_user_bo = kzalloc(sizeof(*vmw_user_bo), GFP_KERNEL);
-       if (vmw_user_bo == NULL)
-               return -ENOMEM;
-
        ret = ttm_read_lock(&vmaster->lock, true);
-       if (ret != 0) {
-               kfree(vmw_user_bo);
+       if (unlikely(ret != 0))
                return ret;
-       }
 
-       ret = vmw_dmabuf_init(dev_priv, &vmw_user_bo->dma, args->size,
-                             &vmw_vram_sys_placement, true,
-                             &vmw_user_dmabuf_destroy);
-       if (ret != 0)
-               goto out_no_dmabuf;
-
-       tmp = ttm_bo_reference(&vmw_user_bo->dma.base);
-       ret = ttm_prime_object_init(vmw_fpriv(file_priv)->tfile,
-                                   args->size,
-                                   &vmw_user_bo->prime,
-                                   false,
-                                   ttm_buffer_type,
-                                   &vmw_user_dmabuf_release, NULL);
+       ret = vmw_user_dmabuf_alloc(dev_priv, vmw_fpriv(file_priv)->tfile,
+                                   args->size, false, &args->handle,
+                                   &dma_buf);
        if (unlikely(ret != 0))
-               goto out_no_base_object;
-
-       args->handle = vmw_user_bo->prime.base.hash.key;
+               goto out_no_dmabuf;
 
-out_no_base_object:
-       ttm_bo_unref(&tmp);
+       vmw_dmabuf_unreference(&dma_buf);
 out_no_dmabuf:
        ttm_read_unlock(&vmaster->lock);
        return ret;
 }
 
+/**
+ * vmw_dumb_map_offset - Return the address space offset of a dumb buffer
+ *
+ * @file_priv: Pointer to a struct drm_file identifying the caller.
+ * @dev: Pointer to the drm device.
+ * @handle: Handle identifying the dumb buffer.
+ * @offset: The address space offset returned.
+ *
+ * This is a driver callback for the core drm dumb_map_offset functionality.
+ */
 int vmw_dumb_map_offset(struct drm_file *file_priv,
                        struct drm_device *dev, uint32_t handle,
                        uint64_t *offset)
@@ -846,6 +881,15 @@ int vmw_dumb_map_offset(struct drm_file *file_priv,
        return 0;
 }
 
+/**
+ * vmw_dumb_destroy - Destroy a dumb boffer
+ *
+ * @file_priv: Pointer to a struct drm_file identifying the caller.
+ * @dev: Pointer to the drm device.
+ * @handle: Handle identifying the dumb buffer.
+ *
+ * This is a driver callback for the core drm dumb_destroy functionality.
+ */
 int vmw_dumb_destroy(struct drm_file *file_priv,
                     struct drm_device *dev,
                     uint32_t handle)
index 26387c3d5a21f01c51d844c228f26a6232b84453..22406c8651ead6caa629ce6ae2de963bdd0a35d7 100644 (file)
@@ -310,6 +310,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
                crtc->fb = NULL;
                crtc->x = 0;
                crtc->y = 0;
+               crtc->enabled = false;
 
                vmw_sou_del_active(dev_priv, sou);
 
@@ -370,6 +371,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
                crtc->fb = NULL;
                crtc->x = 0;
                crtc->y = 0;
+               crtc->enabled = false;
 
                return ret;
        }
@@ -382,6 +384,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
        crtc->fb = fb;
        crtc->x = set->x;
        crtc->y = set->y;
+       crtc->enabled = true;
 
        return 0;
 }
@@ -464,6 +467,8 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
        encoder->possible_crtcs = (1 << unit);
        encoder->possible_clones = 0;
 
+       (void) drm_sysfs_connector_add(connector);
+
        drm_crtc_init(dev, crtc, &vmw_screen_object_crtc_funcs);
 
        drm_mode_crtc_set_gamma_size(crtc, 256);
index 509383f8be034ec3512c95b1c2100818bad5d71e..6a929591aa73801df1126433bc514980e80d1465 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/of.h>
 #include <linux/slab.h>
 
+#include "bus.h"
 #include "dev.h"
 
 static DEFINE_MUTEX(clients_lock);
@@ -257,7 +258,7 @@ static int host1x_unregister_client(struct host1x *host1x,
        return -ENODEV;
 }
 
-struct bus_type host1x_bus_type = {
+static struct bus_type host1x_bus_type = {
        .name = "host1x",
 };
 
@@ -301,7 +302,7 @@ static int host1x_device_add(struct host1x *host1x,
        device->dev.coherent_dma_mask = host1x->dev->coherent_dma_mask;
        device->dev.dma_mask = &device->dev.coherent_dma_mask;
        device->dev.release = host1x_device_release;
-       dev_set_name(&device->dev, driver->name);
+       dev_set_name(&device->dev, "%s", driver->name);
        device->dev.bus = &host1x_bus_type;
        device->dev.parent = host1x->dev;
 
index 37e2a63241a9d6150b1554896fde15ac0294c157..6b09b71940c2d5df0251ec2b3cd417ec2eb93e2d 100644 (file)
@@ -54,8 +54,8 @@ static void cdma_timeout_cpu_incr(struct host1x_cdma *cdma, u32 getptr,
                u32 *p = (u32 *)((u32)pb->mapped + getptr);
                *(p++) = HOST1X_OPCODE_NOP;
                *(p++) = HOST1X_OPCODE_NOP;
-               dev_dbg(host1x->dev, "%s: NOP at 0x%x\n", __func__,
-                       pb->phys + getptr);
+               dev_dbg(host1x->dev, "%s: NOP at %#llx\n", __func__,
+                       (u64)pb->phys + getptr);
                getptr = (getptr + 8) & (pb->size_bytes - 1);
        }
        wmb();
index 640c75ca5a8bbc465dcc9f1350d4f5efdd928d5d..f72c873eff819f831202a742cf02ec70e94753f2 100644 (file)
@@ -163,8 +163,8 @@ static void show_channel_gathers(struct output *o, struct host1x_cdma *cdma)
                                continue;
                        }
 
-                       host1x_debug_output(o, "    GATHER at %08x+%04x, %d words\n",
-                                           g->base, g->offset, g->words);
+                       host1x_debug_output(o, "    GATHER at %#llx+%04x, %d words\n",
+                                           (u64)g->base, g->offset, g->words);
 
                        show_gather(o, g->base + g->offset, g->words, cdma,
                                    g->base, mapped);
index 34e2d39d4ce814cb312de6eee14dae43179cb5c3..f7220011a00b7cde8c16754743517ca17301366a 100644 (file)
@@ -344,6 +344,7 @@ config HID_LOGITECH
 
 config HID_LOGITECH_DJ
        tristate "Logitech Unifying receivers full support"
+       depends on HIDRAW
        depends on HID_LOGITECH
        ---help---
        Say Y if you want support for Logitech Unifying receivers and devices.
index 253fe23ef7fe5332ea03f96449f312a69a6b80c0..4c251e1c332a453b22a62af20e6c3f2054962397 100644 (file)
@@ -1823,8 +1823,8 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_SIS2_TOUCH, USB_DEVICE_ID_SIS9200_TOUCH) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_SIS2_TOUCH, USB_DEVICE_ID_SIS817_TOUCH) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS9200_TOUCH) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS817_TOUCH) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER) },
index f9304cb37154982da4de6774894c213bf412163f..f9ca7abe460196ff2dfb5636edd91e2ca0ce9f11 100644 (file)
 #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD  0xc20a
 #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD       0xc211
 #define USB_DEVICE_ID_LOGITECH_EXTREME_3D      0xc215
+#define USB_DEVICE_ID_LOGITECH_DUAL_ACTION     0xc216
 #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2      0xc218
 #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2    0xc219
 #define USB_DEVICE_ID_LOGITECH_WINGMAN_F3D     0xc283
 #define USB_VENDOR_ID_SIGMATEL         0x066F
 #define USB_DEVICE_ID_SIGMATEL_STMP3780        0x3780
 
-#define USB_VENDOR_ID_SIS2_TOUCH       0x0457
+#define USB_VENDOR_ID_SIS_TOUCH                0x0457
 #define USB_DEVICE_ID_SIS9200_TOUCH    0x9200
 #define USB_DEVICE_ID_SIS817_TOUCH     0x0817
+#define USB_DEVICE_ID_SIS_TS           0x1013
 
 #define USB_VENDOR_ID_SKYCABLE                 0x1223
 #define        USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER       0x3F07
 #define USB_DEVICE_ID_SYNAPTICS_DPAD   0x0013
 #define USB_DEVICE_ID_SYNAPTICS_LTS1   0x0af8
 #define USB_DEVICE_ID_SYNAPTICS_LTS2   0x1d10
+#define USB_DEVICE_ID_SYNAPTICS_HD     0x0ac3
+#define USB_DEVICE_ID_SYNAPTICS_QUAD_HD        0x1ac3
 
 #define USB_VENDOR_ID_THINGM           0x27b8
 #define USB_DEVICE_ID_BLINK1           0x01ed
 #define USB_VENDOR_ID_PRIMAX   0x0461
 #define USB_DEVICE_ID_PRIMAX_KEYBOARD  0x4e05
 
-#define USB_VENDOR_ID_SIS      0x0457
-#define USB_DEVICE_ID_SIS_TS   0x1013
 
 #endif
index 06eb45fa6331fee64152754a5ab9bb2275e3a61c..9fe9d4ac3114bb224f942678de76191fbe846edc 100644 (file)
@@ -758,6 +758,8 @@ static const struct hid_device_id lg_devices[] = {
 
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D),
                .driver_data = LG_NOGET },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DUAL_ACTION),
+               .driver_data = LG_NOGET },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL),
                .driver_data = LG_NOGET | LG_FF4 },
 
index d83b1e8b505b512769d8c5955eb8a0b8ca4e5b23..a2d8adf39d7af73ad6416966cecf8ef523715b5d 100644 (file)
@@ -1301,10 +1301,10 @@ static const struct hid_device_id mt_devices[] = {
 
        /* SiS panels */
        { .driver_data = MT_CLS_DEFAULT,
-               HID_USB_DEVICE(USB_VENDOR_ID_SIS2_TOUCH,
+               HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH,
                USB_DEVICE_ID_SIS9200_TOUCH) },
        { .driver_data = MT_CLS_DEFAULT,
-               HID_USB_DEVICE(USB_VENDOR_ID_SIS2_TOUCH,
+               HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH,
                USB_DEVICE_ID_SIS817_TOUCH) },
 
        /* Stantum panels */
index a184e1921c11190ffce1033e5b7d4f512d55f798..d87f7cb4bee5af2b6c9d08dc02630c08f0f69cfb 100644 (file)
@@ -112,13 +112,15 @@ static int sensor_hub_get_physical_device_count(
 
 static void sensor_hub_fill_attr_info(
                struct hid_sensor_hub_attribute_info *info,
-               s32 index, s32 report_id, s32 units, s32 unit_expo, s32 size)
+               s32 index, s32 report_id, struct hid_field *field)
 {
        info->index = index;
        info->report_id = report_id;
-       info->units = units;
-       info->unit_expo = unit_expo;
-       info->size = size/8;
+       info->units = field->unit;
+       info->unit_expo = field->unit_exponent;
+       info->size = (field->report_size * field->report_count)/8;
+       info->logical_minimum = field->logical_minimum;
+       info->logical_maximum = field->logical_maximum;
 }
 
 static struct hid_sensor_hub_callbacks *sensor_hub_get_callback(
@@ -325,9 +327,7 @@ int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev,
                        if (field->physical == usage_id &&
                                field->logical == attr_usage_id) {
                                sensor_hub_fill_attr_info(info, i, report->id,
-                                       field->unit, field->unit_exponent,
-                                       field->report_size *
-                                                       field->report_count);
+                                                         field);
                                ret = 0;
                        } else {
                                for (j = 0; j < field->maxusage; ++j) {
@@ -336,11 +336,7 @@ int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev,
                                        field->usage[j].collection_index ==
                                        collection_index) {
                                                sensor_hub_fill_attr_info(info,
-                                                       i, report->id,
-                                                       field->unit,
-                                                       field->unit_exponent,
-                                                       field->report_size *
-                                                       field->report_count);
+                                                         i, report->id, field);
                                                ret = 0;
                                                break;
                                        }
index 098af2f84b8c653dca9542d78de33c5c5777fe8b..b60bc38903db39f885c4a1d7a680790540edef47 100644 (file)
 
 #include "hid-ids.h"
 
-#define VAIO_RDESC_CONSTANT     (1 << 0)
-#define SIXAXIS_CONTROLLER_USB  (1 << 1)
-#define SIXAXIS_CONTROLLER_BT   (1 << 2)
-#define BUZZ_CONTROLLER         (1 << 3)
-#define PS3REMOTE              (1 << 4)
+#define VAIO_RDESC_CONSTANT     BIT(0)
+#define SIXAXIS_CONTROLLER_USB  BIT(1)
+#define SIXAXIS_CONTROLLER_BT   BIT(2)
+#define BUZZ_CONTROLLER         BIT(3)
+#define PS3REMOTE              BIT(4)
+
+#define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER_USB | BUZZ_CONTROLLER)
 
 static const u8 sixaxis_rdesc_fixup[] = {
        0x95, 0x13, 0x09, 0x01, 0x81, 0x02, 0x95, 0x0C,
@@ -223,21 +225,17 @@ static const unsigned int buzz_keymap[] = {
 };
 
 struct sony_sc {
+       struct hid_device *hdev;
+       struct led_classdev *leds[4];
        unsigned long quirks;
+       struct work_struct state_worker;
 
 #ifdef CONFIG_SONY_FF
-       struct work_struct rumble_worker;
-       struct hid_device *hdev;
        __u8 left;
        __u8 right;
 #endif
 
-       void *extra;
-};
-
-struct buzz_extra {
-       int led_state;
-       struct led_classdev *leds[4];
+       __u8 led_state;
 };
 
 static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc,
@@ -466,58 +464,66 @@ static void buzz_set_leds(struct hid_device *hdev, int leds)
        hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
 }
 
-static void buzz_led_set_brightness(struct led_classdev *led,
+static void sony_set_leds(struct hid_device *hdev, __u8 leds)
+{
+       struct sony_sc *drv_data = hid_get_drvdata(hdev);
+
+       if (drv_data->quirks & BUZZ_CONTROLLER) {
+               buzz_set_leds(hdev, leds);
+       } else if (drv_data->quirks & SIXAXIS_CONTROLLER_USB) {
+               drv_data->led_state = leds;
+               schedule_work(&drv_data->state_worker);
+       }
+}
+
+static void sony_led_set_brightness(struct led_classdev *led,
                                    enum led_brightness value)
 {
        struct device *dev = led->dev->parent;
        struct hid_device *hdev = container_of(dev, struct hid_device, dev);
        struct sony_sc *drv_data;
-       struct buzz_extra *buzz;
 
        int n;
 
        drv_data = hid_get_drvdata(hdev);
-       if (!drv_data || !drv_data->extra) {
+       if (!drv_data) {
                hid_err(hdev, "No device data\n");
                return;
        }
-       buzz = drv_data->extra;
 
        for (n = 0; n < 4; n++) {
-               if (led == buzz->leds[n]) {
-                       int on = !! (buzz->led_state & (1 << n));
+               if (led == drv_data->leds[n]) {
+                       int on = !!(drv_data->led_state & (1 << n));
                        if (value == LED_OFF && on) {
-                               buzz->led_state &= ~(1 << n);
-                               buzz_set_leds(hdev, buzz->led_state);
+                               drv_data->led_state &= ~(1 << n);
+                               sony_set_leds(hdev, drv_data->led_state);
                        } else if (value != LED_OFF && !on) {
-                               buzz->led_state |= (1 << n);
-                               buzz_set_leds(hdev, buzz->led_state);
+                               drv_data->led_state |= (1 << n);
+                               sony_set_leds(hdev, drv_data->led_state);
                        }
                        break;
                }
        }
 }
 
-static enum led_brightness buzz_led_get_brightness(struct led_classdev *led)
+static enum led_brightness sony_led_get_brightness(struct led_classdev *led)
 {
        struct device *dev = led->dev->parent;
        struct hid_device *hdev = container_of(dev, struct hid_device, dev);
        struct sony_sc *drv_data;
-       struct buzz_extra *buzz;
 
        int n;
        int on = 0;
 
        drv_data = hid_get_drvdata(hdev);
-       if (!drv_data || !drv_data->extra) {
+       if (!drv_data) {
                hid_err(hdev, "No device data\n");
                return LED_OFF;
        }
-       buzz = drv_data->extra;
 
        for (n = 0; n < 4; n++) {
-               if (led == buzz->leds[n]) {
-                       on = !! (buzz->led_state & (1 << n));
+               if (led == drv_data->leds[n]) {
+                       on = !!(drv_data->led_state & (1 << n));
                        break;
                }
        }
@@ -525,35 +531,55 @@ static enum led_brightness buzz_led_get_brightness(struct led_classdev *led)
        return on ? LED_FULL : LED_OFF;
 }
 
-static int buzz_init(struct hid_device *hdev)
+static void sony_leds_remove(struct hid_device *hdev)
+{
+       struct sony_sc *drv_data;
+       struct led_classdev *led;
+       int n;
+
+       drv_data = hid_get_drvdata(hdev);
+       BUG_ON(!(drv_data->quirks & SONY_LED_SUPPORT));
+
+       for (n = 0; n < 4; n++) {
+               led = drv_data->leds[n];
+               drv_data->leds[n] = NULL;
+               if (!led)
+                       continue;
+               led_classdev_unregister(led);
+               kfree(led);
+       }
+}
+
+static int sony_leds_init(struct hid_device *hdev)
 {
        struct sony_sc *drv_data;
-       struct buzz_extra *buzz;
        int n, ret = 0;
        struct led_classdev *led;
        size_t name_sz;
        char *name;
+       size_t name_len;
+       const char *name_fmt;
 
        drv_data = hid_get_drvdata(hdev);
-       BUG_ON(!(drv_data->quirks & BUZZ_CONTROLLER));
-
-       /* Validate expected report characteristics. */
-       if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 7))
-               return -ENODEV;
-
-       buzz = kzalloc(sizeof(*buzz), GFP_KERNEL);
-       if (!buzz) {
-               hid_err(hdev, "Insufficient memory, cannot allocate driver data\n");
-               return -ENOMEM;
+       BUG_ON(!(drv_data->quirks & SONY_LED_SUPPORT));
+
+       if (drv_data->quirks & BUZZ_CONTROLLER) {
+               name_len = strlen("::buzz#");
+               name_fmt = "%s::buzz%d";
+               /* Validate expected report characteristics. */
+               if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 7))
+                       return -ENODEV;
+       } else {
+               name_len = strlen("::sony#");
+               name_fmt = "%s::sony%d";
        }
-       drv_data->extra = buzz;
 
        /* Clear LEDs as we have no way of reading their initial state. This is
         * only relevant if the driver is loaded after somebody actively set the
         * LEDs to on */
-       buzz_set_leds(hdev, 0x00);
+       sony_set_leds(hdev, 0x00);
 
-       name_sz = strlen(dev_name(&hdev->dev)) + strlen("::buzz#") + 1;
+       name_sz = strlen(dev_name(&hdev->dev)) + name_len + 1;
 
        for (n = 0; n < 4; n++) {
                led = kzalloc(sizeof(struct led_classdev) + name_sz, GFP_KERNEL);
@@ -563,12 +589,12 @@ static int buzz_init(struct hid_device *hdev)
                }
 
                name = (void *)(&led[1]);
-               snprintf(name, name_sz, "%s::buzz%d", dev_name(&hdev->dev), n + 1);
+               snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev), n + 1);
                led->name = name;
                led->brightness = 0;
                led->max_brightness = 1;
-               led->brightness_get = buzz_led_get_brightness;
-               led->brightness_set = buzz_led_set_brightness;
+               led->brightness_get = sony_led_get_brightness;
+               led->brightness_set = sony_led_set_brightness;
 
                if (led_classdev_register(&hdev->dev, led)) {
                        hid_err(hdev, "Failed to register LED %d\n", n);
@@ -576,59 +602,24 @@ static int buzz_init(struct hid_device *hdev)
                        goto error_leds;
                }
 
-               buzz->leds[n] = led;
+               drv_data->leds[n] = led;
        }
 
        return ret;
 
 error_leds:
-       for (n = 0; n < 4; n++) {
-               led = buzz->leds[n];
-               buzz->leds[n] = NULL;
-               if (!led)
-                       continue;
-               led_classdev_unregister(led);
-               kfree(led);
-       }
+       sony_leds_remove(hdev);
 
-       kfree(drv_data->extra);
-       drv_data->extra = NULL;
        return ret;
 }
 
-static void buzz_remove(struct hid_device *hdev)
-{
-       struct sony_sc *drv_data;
-       struct buzz_extra *buzz;
-       struct led_classdev *led;
-       int n;
-
-       drv_data = hid_get_drvdata(hdev);
-       BUG_ON(!(drv_data->quirks & BUZZ_CONTROLLER));
-
-       buzz = drv_data->extra;
-
-       for (n = 0; n < 4; n++) {
-               led = buzz->leds[n];
-               buzz->leds[n] = NULL;
-               if (!led)
-                       continue;
-               led_classdev_unregister(led);
-               kfree(led);
-       }
-
-       kfree(drv_data->extra);
-       drv_data->extra = NULL;
-}
-
-#ifdef CONFIG_SONY_FF
-static void sony_rumble_worker(struct work_struct *work)
+static void sony_state_worker(struct work_struct *work)
 {
-       struct sony_sc *sc = container_of(work, struct sony_sc, rumble_worker);
+       struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);
        unsigned char buf[] = {
                0x01,
                0x00, 0xff, 0x00, 0xff, 0x00,
-               0x00, 0x00, 0x00, 0x00, 0x03,
+               0x00, 0x00, 0x00, 0x00, 0x00,
                0xff, 0x27, 0x10, 0x00, 0x32,
                0xff, 0x27, 0x10, 0x00, 0x32,
                0xff, 0x27, 0x10, 0x00, 0x32,
@@ -636,13 +627,18 @@ static void sony_rumble_worker(struct work_struct *work)
                0x00, 0x00, 0x00, 0x00, 0x00
        };
 
+#ifdef CONFIG_SONY_FF
        buf[3] = sc->right;
        buf[5] = sc->left;
+#endif
+
+       buf[10] |= (sc->led_state & 0xf) << 1;
 
        sc->hdev->hid_output_raw_report(sc->hdev, buf, sizeof(buf),
                                        HID_OUTPUT_REPORT);
 }
 
+#ifdef CONFIG_SONY_FF
 static int sony_play_effect(struct input_dev *dev, void *data,
                            struct ff_effect *effect)
 {
@@ -655,7 +651,7 @@ static int sony_play_effect(struct input_dev *dev, void *data,
        sc->left = effect->u.rumble.strong_magnitude / 256;
        sc->right = effect->u.rumble.weak_magnitude ? 1 : 0;
 
-       schedule_work(&sc->rumble_worker);
+       schedule_work(&sc->state_worker);
        return 0;
 }
 
@@ -664,10 +660,6 @@ static int sony_init_ff(struct hid_device *hdev)
        struct hid_input *hidinput = list_entry(hdev->inputs.next,
                                                struct hid_input, list);
        struct input_dev *input_dev = hidinput->input;
-       struct sony_sc *sc = hid_get_drvdata(hdev);
-
-       sc->hdev = hdev;
-       INIT_WORK(&sc->rumble_worker, sony_rumble_worker);
 
        input_set_capability(input_dev, EV_FF, FF_RUMBLE);
        return input_ff_create_memless(input_dev, NULL, sony_play_effect);
@@ -677,7 +669,7 @@ static void sony_destroy_ff(struct hid_device *hdev)
 {
        struct sony_sc *sc = hid_get_drvdata(hdev);
 
-       cancel_work_sync(&sc->rumble_worker);
+       cancel_work_sync(&sc->state_worker);
 }
 
 #else
@@ -706,6 +698,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
 
        sc->quirks = quirks;
        hid_set_drvdata(hdev, sc);
+       sc->hdev = hdev;
 
        ret = hid_parse(hdev);
        if (ret) {
@@ -729,23 +722,30 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
        if (sc->quirks & SIXAXIS_CONTROLLER_USB) {
                hdev->hid_output_raw_report = sixaxis_usb_output_raw_report;
                ret = sixaxis_set_operational_usb(hdev);
+               INIT_WORK(&sc->state_worker, sony_state_worker);
        }
        else if (sc->quirks & SIXAXIS_CONTROLLER_BT)
                ret = sixaxis_set_operational_bt(hdev);
-       else if (sc->quirks & BUZZ_CONTROLLER)
-               ret = buzz_init(hdev);
        else
                ret = 0;
 
        if (ret < 0)
                goto err_stop;
 
+       if (sc->quirks & SONY_LED_SUPPORT) {
+               ret = sony_leds_init(hdev);
+               if (ret < 0)
+                       goto err_stop;
+       }
+
        ret = sony_init_ff(hdev);
        if (ret < 0)
                goto err_stop;
 
        return 0;
 err_stop:
+       if (sc->quirks & SONY_LED_SUPPORT)
+               sony_leds_remove(hdev);
        hid_hw_stop(hdev);
        return ret;
 }
@@ -754,8 +754,8 @@ static void sony_remove(struct hid_device *hdev)
 {
        struct sony_sc *sc = hid_get_drvdata(hdev);
 
-       if (sc->quirks & BUZZ_CONTROLLER)
-               buzz_remove(hdev);
+       if (sc->quirks & SONY_LED_SUPPORT)
+               sony_leds_remove(hdev);
 
        sony_destroy_ff(hdev);
 
index 5f7e55f4b7f052e29f754f78cabe8dd6a4593fb4..e914f27554913ab08c903be673a5c641731058b6 100644 (file)
@@ -1061,6 +1061,7 @@ static int i2c_hid_suspend(struct device *dev)
 {
        struct i2c_client *client = to_i2c_client(dev);
 
+       disable_irq(client->irq);
        if (device_may_wakeup(&client->dev))
                enable_irq_wake(client->irq);
 
@@ -1075,6 +1076,7 @@ static int i2c_hid_resume(struct device *dev)
        int ret;
        struct i2c_client *client = to_i2c_client(dev);
 
+       enable_irq(client->irq);
        ret = i2c_hid_hwreset(client);
        if (ret)
                return ret;
index 0db9a67278ba21d3d574b3f209311d5f54fecbac..b3c7684e87062b162d30bd4f021a42904102c821 100644 (file)
@@ -84,8 +84,9 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_REALTEK, USB_DEVICE_ID_REALTEK_READER, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_SIGMATEL, USB_DEVICE_ID_SIGMATEL_STMP3780, HID_QUIRK_NOGET },
-       { USB_VENDOR_ID_SIS2_TOUCH, USB_DEVICE_ID_SIS9200_TOUCH, HID_QUIRK_NOGET },
-       { USB_VENDOR_ID_SIS2_TOUCH, USB_DEVICE_ID_SIS817_TOUCH, HID_QUIRK_NOGET },
+       { USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS9200_TOUCH, HID_QUIRK_NOGET },
+       { USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS817_TOUCH, HID_QUIRK_NOGET },
+       { USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS_TS, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_1, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_2, HID_QUIRK_NOGET },
@@ -114,7 +115,8 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_DUOSENSE, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS1, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS2, HID_QUIRK_NO_INIT_REPORTS },
-       { USB_VENDOR_ID_SIS, USB_DEVICE_ID_SIS_TS, HID_QUIRK_NO_INIT_REPORTS },
+       { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_HD, HID_QUIRK_NO_INIT_REPORTS },
+       { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_QUAD_HD, HID_QUIRK_NO_INIT_REPORTS },
 
        { 0, 0 }
 };
index 796086980f4a622dfe2857eec1d00ff33cdff787..9a332e683db77d170f2f1b281e813db02896df4a 100644 (file)
@@ -146,7 +146,7 @@ static void usb_kbd_irq(struct urb *urb)
                                input_report_key(kbd->dev, usb_kbd_keycode[kbd->new[i]], 1);
                        else
                                hid_info(urb->dev,
-                                        "Unknown key (scancode %#x) released.\n",
+                                        "Unknown key (scancode %#x) pressed.\n",
                                         kbd->new[i]);
                }
        }
index 48aad4faea068e88cbe61976aa3444d9c8a80a58..077bb1bdac34ef4ed87c65c7bf0d204fd42001b4 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/sysctl.h>
 #include <linux/slab.h>
 #include <linux/acpi.h>
-#include <acpi/acpi_bus.h>
 #include <linux/completion.h>
 #include <linux/hyperv.h>
 #include <linux/kernel_stat.h>
@@ -39,7 +38,6 @@
 #include <asm/mshyperv.h>
 #include "hyperv_vmbus.h"
 
-
 static struct acpi_device  *hv_acpi_dev;
 
 static struct tasklet_struct msg_dpc;
index 52d548f1dc1ddbccceedab0c7f2bf9e1d53766f2..f6ca3b21aebd989bcdadeb749e4250134dfbe16e 100644 (file)
@@ -573,8 +573,8 @@ config SENSORS_IT87
        help
          If you say yes here you get support for ITE IT8705F, IT8712F,
          IT8716F, IT8718F, IT8720F, IT8721F, IT8726F, IT8728F, IT8758E,
-         IT8771E, IT8772E, IT8782F, and IT8783E/F sensor chips, and the
-         SiS950 clone.
+         IT8771E, IT8772E, IT8782F, IT8783E/F and IT8603E sensor chips,
+         and the SiS950 clone.
 
          This driver can also be built as a module.  If so, the module
          will be called it87.
index 6a34f7f48eb9172272a25d4467bf1a190f7dc1e3..579bdf93be433b54a23fa8827badd7ace8dbb762 100644 (file)
@@ -30,8 +30,7 @@
 #include <linux/sched.h>
 #include <linux/time.h>
 #include <linux/err.h>
-#include <acpi/acpi_drivers.h>
-#include <acpi/acpi_bus.h>
+#include <linux/acpi.h>
 
 #define ACPI_POWER_METER_NAME          "power_meter"
 ACPI_MODULE_NAME(ACPI_POWER_METER_NAME);
index dafc63c6932dfa47001a0269fc283984c16c321e..ae208f61219804cbac02bc850582c1ad7cfc5f84 100644 (file)
 #include <linux/dmi.h>
 #include <linux/jiffies.h>
 #include <linux/err.h>
-
-#include <acpi/acpi.h>
-#include <acpi/acpi_drivers.h>
-#include <acpi/acpi_bus.h>
-
+#include <linux/acpi.h>
 
 #define ATK_HID "ATK0110"
 
index 78be66176840d1c6abdf29dd632d7a107f6ad2d3..310ce193bbd0faf07d57f0686d5f7ba8dfbe42f0 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/cpu.h>
 #include <linux/smp.h>
 #include <linux/moduleparam.h>
+#include <linux/pci.h>
 #include <asm/msr.h>
 #include <asm/processor.h>
 #include <asm/cpu_device_id.h>
@@ -190,6 +191,18 @@ static ssize_t show_temp(struct device *dev,
        return tdata->valid ? sprintf(buf, "%d\n", tdata->temp) : -EAGAIN;
 }
 
+struct tjmax_pci {
+       unsigned int device;
+       int tjmax;
+};
+
+static const struct tjmax_pci tjmax_pci_table[] __cpuinitconst = {
+       { 0x0708, 110000 },     /* CE41x0 (Sodaville ) */
+       { 0x0c72, 102000 },     /* Atom S1240 (Centerton) */
+       { 0x0c73, 95000 },      /* Atom S1220 (Centerton) */
+       { 0x0c75, 95000 },      /* Atom S1260 (Centerton) */
+};
+
 struct tjmax {
        char const *id;
        int tjmax;
@@ -198,9 +211,6 @@ struct tjmax {
 static const struct tjmax tjmax_table[] = {
        { "CPU  230", 100000 },         /* Model 0x1c, stepping 2       */
        { "CPU  330", 125000 },         /* Model 0x1c, stepping 2       */
-       { "CPU CE4110", 110000 },       /* Model 0x1c, stepping 10 Sodaville */
-       { "CPU CE4150", 110000 },       /* Model 0x1c, stepping 10      */
-       { "CPU CE4170", 110000 },       /* Model 0x1c, stepping 10      */
 };
 
 struct tjmax_model {
@@ -222,8 +232,11 @@ static const struct tjmax_model tjmax_model_table[] = {
                                 * is undetectable by software
                                 */
        { 0x27, ANY, 90000 },   /* Atom Medfield (Z2460) */
-       { 0x35, ANY, 90000 },   /* Atom Clover Trail/Cloverview (Z2760) */
-       { 0x36, ANY, 100000 },  /* Atom Cedar Trail/Cedarview (N2xxx, D2xxx) */
+       { 0x35, ANY, 90000 },   /* Atom Clover Trail/Cloverview (Z27x0) */
+       { 0x36, ANY, 100000 },  /* Atom Cedar Trail/Cedarview (N2xxx, D2xxx)
+                                * Also matches S12x0 (stepping 9), covered by
+                                * PCI table
+                                */
 };
 
 static int adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
@@ -236,8 +249,20 @@ static int adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
        int err;
        u32 eax, edx;
        int i;
+       struct pci_dev *host_bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0));
+
+       /*
+        * Explicit tjmax table entries override heuristics.
+        * First try PCI host bridge IDs, followed by model ID strings
+        * and model/stepping information.
+        */
+       if (host_bridge && host_bridge->vendor == PCI_VENDOR_ID_INTEL) {
+               for (i = 0; i < ARRAY_SIZE(tjmax_pci_table); i++) {
+                       if (host_bridge->device == tjmax_pci_table[i].device)
+                               return tjmax_pci_table[i].tjmax;
+               }
+       }
 
-       /* explicit tjmax table entries override heuristics */
        for (i = 0; i < ARRAY_SIZE(tjmax_table); i++) {
                if (strstr(c->x86_model_id, tjmax_table[i].id))
                        return tjmax_table[i].tjmax;
@@ -343,12 +368,12 @@ static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
                if (cpu_has_tjmax(c))
                        dev_warn(dev, "Unable to read TjMax from CPU %u\n", id);
        } else {
-               val = (eax >> 16) & 0xff;
+               val = (eax >> 16) & 0x7f;
                /*
                 * If the TjMax is not plausible, an assumption
                 * will be used
                 */
-               if (val) {
+               if (val >= 85) {
                        dev_dbg(dev, "TjMax is %d degrees C\n", val);
                        return val * 1000;
                }
index dff841085bafc9bb170c81309c3f75c8a0d92f4b..6040121a405a2c124cf1e9ef5fbbd357f60f6075 100644 (file)
@@ -249,7 +249,7 @@ static void fam15h_power_remove(struct pci_dev *pdev)
        sysfs_remove_group(&dev->kobj, &fam15h_power_attr_group);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(fam15h_power_id_table) = {
+static const struct pci_device_id fam15h_power_id_table[] = {
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) },
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_NB_F4) },
        {}
index 2dc37c7c6947cfa6dd5fde0e72ff5701f7162dd0..7d68a08baaa83eb42366e17c29b4ff88bda68152 100644 (file)
@@ -43,6 +43,7 @@
  * @last_update: time of last update (jiffies)
  * @temperature: cached temperature measurement value
  * @humidity: cached humidity measurement value
+ * @write_length: length for I2C measurement request
  */
 struct hih6130 {
        struct device *hwmon_dev;
@@ -51,6 +52,7 @@ struct hih6130 {
        unsigned long last_update;
        int temperature;
        int humidity;
+       size_t write_length;
 };
 
 /**
@@ -121,8 +123,15 @@ static int hih6130_update_measurements(struct i2c_client *client)
         */
        if (time_after(jiffies, hih6130->last_update + HZ) || !hih6130->valid) {
 
-               /* write to slave address, no data, to request a measurement */
-               ret = i2c_master_send(client, tmp, 0);
+               /*
+                * Write to slave address to request a measurement.
+                * According with the datasheet it should be with no data, but
+                * for systems with I2C bus drivers that do not allow zero
+                * length packets we write one dummy byte to allow sensor
+                * measurements on them.
+                */
+               tmp[0] = 0;
+               ret = i2c_master_send(client, tmp, hih6130->write_length);
                if (ret < 0)
                        goto out;
 
@@ -252,6 +261,9 @@ static int hih6130_probe(struct i2c_client *client,
                goto fail_remove_sysfs;
        }
 
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_QUICK))
+               hih6130->write_length = 1;
+
        return 0;
 
 fail_remove_sysfs:
index 29ffa27c60b89b60bf84db948cf56a890772599e..d50dc3a763a53effdd01563f1b567b213d41b8c3 100644 (file)
@@ -10,7 +10,8 @@
  *  This driver supports only the Environment Controller in the IT8705F and
  *  similar parts.  The other devices are supported by different drivers.
  *
- *  Supports: IT8705F  Super I/O chip w/LPC interface
+ *  Supports: IT8603E  Super I/O chip w/LPC interface
+ *            IT8705F  Super I/O chip w/LPC interface
  *            IT8712F  Super I/O chip w/LPC interface
  *            IT8716F  Super I/O chip w/LPC interface
  *            IT8718F  Super I/O chip w/LPC interface
@@ -64,7 +65,7 @@
 #define DRVNAME "it87"
 
 enum chips { it87, it8712, it8716, it8718, it8720, it8721, it8728, it8771,
-            it8772, it8782, it8783 };
+            it8772, it8782, it8783, it8603 };
 
 static unsigned short force_id;
 module_param(force_id, ushort, 0);
@@ -146,6 +147,7 @@ static inline void superio_exit(void)
 #define IT8772E_DEVID 0x8772
 #define IT8782F_DEVID 0x8782
 #define IT8783E_DEVID 0x8783
+#define IT8306E_DEVID 0x8603
 #define IT87_ACT_REG  0x30
 #define IT87_BASE_REG 0x60
 
@@ -315,6 +317,12 @@ static const struct it87_devices it87_devices[] = {
                  | FEAT_TEMP_OLD_PECI,
                .old_peci_mask = 0x4,
        },
+       [it8603] = {
+               .name = "it8603",
+               .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
+                 | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI,
+               .peci_mask = 0x07,
+       },
 };
 
 #define has_16bit_fans(data)   ((data)->features & FEAT_16BIT_FANS)
@@ -361,7 +369,7 @@ struct it87_data {
        unsigned long last_updated;     /* In jiffies */
 
        u16 in_scaled;          /* Internal voltage sensors are scaled */
-       u8 in[9][3];            /* [nr][0]=in, [1]=min, [2]=max */
+       u8 in[10][3];           /* [nr][0]=in, [1]=min, [2]=max */
        u8 has_fan;             /* Bitfield, fans enabled */
        u16 fan[5][2];          /* Register values, [nr][0]=fan, [1]=min */
        u8 has_temp;            /* Bitfield, temp sensors enabled */
@@ -578,6 +586,7 @@ static SENSOR_DEVICE_ATTR_2(in7_max, S_IRUGO | S_IWUSR, show_in, set_in,
                            7, 2);
 
 static SENSOR_DEVICE_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 8, 0);
+static SENSOR_DEVICE_ATTR_2(in9_input, S_IRUGO, show_in, NULL, 9, 0);
 
 /* 3 temperatures */
 static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
@@ -734,7 +743,7 @@ static int pwm_mode(const struct it87_data *data, int nr)
 {
        int ctrl = data->fan_main_ctrl & (1 << nr);
 
-       if (ctrl == 0)                                  /* Full speed */
+       if (ctrl == 0 && data->type != it8603)          /* Full speed */
                return 0;
        if (data->pwm_ctrl[nr] & 0x80)                  /* Automatic mode */
                return 2;
@@ -929,6 +938,10 @@ static ssize_t set_pwm_enable(struct device *dev,
                        return -EINVAL;
        }
 
+       /* IT8603E does not have on/off mode */
+       if (val == 0 && data->type == it8603)
+               return -EINVAL;
+
        mutex_lock(&data->update_lock);
 
        if (val == 0) {
@@ -948,10 +961,13 @@ static ssize_t set_pwm_enable(struct device *dev,
                else                                    /* Automatic mode */
                        data->pwm_ctrl[nr] = 0x80 | data->pwm_temp_map[nr];
                it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]);
-               /* set SmartGuardian mode */
-               data->fan_main_ctrl |= (1 << nr);
-               it87_write_value(data, IT87_REG_FAN_MAIN_CTRL,
-                                data->fan_main_ctrl);
+
+               if (data->type != it8603) {
+                       /* set SmartGuardian mode */
+                       data->fan_main_ctrl |= (1 << nr);
+                       it87_write_value(data, IT87_REG_FAN_MAIN_CTRL,
+                                        data->fan_main_ctrl);
+               }
        }
 
        mutex_unlock(&data->update_lock);
@@ -1415,6 +1431,8 @@ static ssize_t show_label(struct device *dev, struct device_attribute *attr,
 static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_label, NULL, 0);
 static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_label, NULL, 1);
 static SENSOR_DEVICE_ATTR(in8_label, S_IRUGO, show_label, NULL, 2);
+/* special AVCC3 IT8306E in9 */
+static SENSOR_DEVICE_ATTR(in9_label, S_IRUGO, show_label, NULL, 0);
 
 static ssize_t show_name(struct device *dev, struct device_attribute
                         *devattr, char *buf)
@@ -1424,7 +1442,7 @@ static ssize_t show_name(struct device *dev, struct device_attribute
 }
 static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 
-static struct attribute *it87_attributes_in[9][5] = {
+static struct attribute *it87_attributes_in[10][5] = {
 {
        &sensor_dev_attr_in0_input.dev_attr.attr,
        &sensor_dev_attr_in0_min.dev_attr.attr,
@@ -1476,9 +1494,12 @@ static struct attribute *it87_attributes_in[9][5] = {
 }, {
        &sensor_dev_attr_in8_input.dev_attr.attr,
        NULL
+}, {
+       &sensor_dev_attr_in9_input.dev_attr.attr,
+       NULL
 } };
 
-static const struct attribute_group it87_group_in[9] = {
+static const struct attribute_group it87_group_in[10] = {
        { .attrs = it87_attributes_in[0] },
        { .attrs = it87_attributes_in[1] },
        { .attrs = it87_attributes_in[2] },
@@ -1488,6 +1509,7 @@ static const struct attribute_group it87_group_in[9] = {
        { .attrs = it87_attributes_in[6] },
        { .attrs = it87_attributes_in[7] },
        { .attrs = it87_attributes_in[8] },
+       { .attrs = it87_attributes_in[9] },
 };
 
 static struct attribute *it87_attributes_temp[3][6] = {
@@ -1546,7 +1568,8 @@ static struct attribute *it87_attributes_in_beep[] = {
        &sensor_dev_attr_in5_beep.dev_attr.attr,
        &sensor_dev_attr_in6_beep.dev_attr.attr,
        &sensor_dev_attr_in7_beep.dev_attr.attr,
-       NULL
+       NULL,
+       NULL,
 };
 
 static struct attribute *it87_attributes_temp_beep[] = {
@@ -1685,6 +1708,7 @@ static struct attribute *it87_attributes_label[] = {
        &sensor_dev_attr_in3_label.dev_attr.attr,
        &sensor_dev_attr_in7_label.dev_attr.attr,
        &sensor_dev_attr_in8_label.dev_attr.attr,
+       &sensor_dev_attr_in9_label.dev_attr.attr,
        NULL
 };
 
@@ -1742,6 +1766,9 @@ static int __init it87_find(unsigned short *address,
        case IT8783E_DEVID:
                sio_data->type = it8783;
                break;
+       case IT8306E_DEVID:
+               sio_data->type = it8603;
+               break;
        case 0xffff:    /* No device at all */
                goto exit;
        default:
@@ -1763,11 +1790,16 @@ static int __init it87_find(unsigned short *address,
 
        err = 0;
        sio_data->revision = superio_inb(DEVREV) & 0x0f;
-       pr_info("Found IT%04xF chip at 0x%x, revision %d\n",
-               chip_type, *address, sio_data->revision);
+       pr_info("Found IT%04x%c chip at 0x%x, revision %d\n", chip_type,
+               chip_type == 0x8771 || chip_type == 0x8772 ||
+               chip_type == 0x8603 ? 'E' : 'F', *address,
+               sio_data->revision);
 
        /* in8 (Vbat) is always internal */
        sio_data->internal = (1 << 2);
+       /* Only the IT8603E has in9 */
+       if (sio_data->type != it8603)
+               sio_data->skip_in |= (1 << 9);
 
        /* Read GPIO config and VID value from LDN 7 (GPIO) */
        if (sio_data->type == it87) {
@@ -1844,7 +1876,38 @@ static int __init it87_find(unsigned short *address,
                        sio_data->internal |= (1 << 1);
 
                sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
+       } else if (sio_data->type == it8603) {
+               int reg27, reg29;
+
+               sio_data->skip_vid = 1; /* No VID */
+               superio_select(GPIO);
 
+               reg27 = superio_inb(IT87_SIO_GPIO3_REG);
+
+               /* Check if fan3 is there or not */
+               if (reg27 & (1 << 6))
+                       sio_data->skip_pwm |= (1 << 2);
+               if (reg27 & (1 << 7))
+                       sio_data->skip_fan |= (1 << 2);
+
+               /* Check if fan2 is there or not */
+               reg29 = superio_inb(IT87_SIO_GPIO5_REG);
+               if (reg29 & (1 << 1))
+                       sio_data->skip_pwm |= (1 << 1);
+               if (reg29 & (1 << 2))
+                       sio_data->skip_fan |= (1 << 1);
+
+               sio_data->skip_in |= (1 << 5); /* No VIN5 */
+               sio_data->skip_in |= (1 << 6); /* No VIN6 */
+
+               /* no fan4 */
+               sio_data->skip_pwm |= (1 << 3);
+               sio_data->skip_fan |= (1 << 3);
+
+               sio_data->internal |= (1 << 1); /* in7 is VSB */
+               sio_data->internal |= (1 << 3); /* in9 is AVCC */
+
+               sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
        } else {
                int reg;
                bool uart6;
@@ -1966,7 +2029,7 @@ static void it87_remove_files(struct device *dev)
        int i;
 
        sysfs_remove_group(&dev->kobj, &it87_group);
-       for (i = 0; i < 9; i++) {
+       for (i = 0; i < 10; i++) {
                if (sio_data->skip_in & (1 << i))
                        continue;
                sysfs_remove_group(&dev->kobj, &it87_group_in[i]);
@@ -2080,6 +2143,8 @@ static int it87_probe(struct platform_device *pdev)
                        data->in_scaled |= (1 << 7);    /* in7 is VSB */
                if (sio_data->internal & (1 << 2))
                        data->in_scaled |= (1 << 8);    /* in8 is Vbat */
+               if (sio_data->internal & (1 << 3))
+                       data->in_scaled |= (1 << 9);    /* in9 is AVCC */
        } else if (sio_data->type == it8782 || sio_data->type == it8783) {
                if (sio_data->internal & (1 << 0))
                        data->in_scaled |= (1 << 3);    /* in3 is VCC5V */
@@ -2102,7 +2167,7 @@ static int it87_probe(struct platform_device *pdev)
        if (err)
                return err;
 
-       for (i = 0; i < 9; i++) {
+       for (i = 0; i < 10; i++) {
                if (sio_data->skip_in & (1 << i))
                        continue;
                err = sysfs_create_group(&dev->kobj, &it87_group_in[i]);
@@ -2202,7 +2267,7 @@ static int it87_probe(struct platform_device *pdev)
        }
 
        /* Export labels for internal sensors */
-       for (i = 0; i < 3; i++) {
+       for (i = 0; i < 4; i++) {
                if (!(sio_data->internal & (1 << i)))
                        continue;
                err = sysfs_create_file(&dev->kobj,
@@ -2383,8 +2448,9 @@ static void it87_init_device(struct platform_device *pdev)
        }
        data->has_fan = (data->fan_main_ctrl >> 4) & 0x07;
 
-       /* Set tachometers to 16-bit mode if needed */
-       if (has_16bit_fans(data)) {
+       /* Set tachometers to 16-bit mode if needed, IT8603E (and IT8728F?)
+        * has it by default */
+       if (has_16bit_fans(data) && data->type != it8603) {
                tmp = it87_read_value(data, IT87_REG_FAN_16BIT);
                if (~tmp & 0x07 & data->has_fan) {
                        dev_dbg(&pdev->dev,
@@ -2464,6 +2530,8 @@ static struct it87_data *it87_update_device(struct device *dev)
                }
                /* in8 (battery) has no limit registers */
                data->in[8][0] = it87_read_value(data, IT87_REG_VIN(8));
+               if (data->type == it8603)
+                       data->in[9][0] = it87_read_value(data, 0x2f);
 
                for (i = 0; i < 5; i++) {
                        /* Skip disabled fans */
index d65f3fd895ddda22d23164f1a0c94c870b77e2ce..e375e9fabba9fa164ea5d4bc6c2c3ea2a7e12d35 100644 (file)
@@ -204,7 +204,7 @@ static void k10temp_remove(struct pci_dev *pdev)
                           &sensor_dev_attr_temp1_crit_hyst.dev_attr);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(k10temp_id_table) = {
+static const struct pci_device_id k10temp_id_table[] = {
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) },
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_11H_NB_MISC) },
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CNB17H_F3) },
index 5b50e9e4f96bb2ebf7e6630c846d591afca36248..734d55d48cc88fcf1cb3ededba02cb6cb80961ae 100644 (file)
@@ -135,7 +135,7 @@ static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 1, 0);
 static SENSOR_DEVICE_ATTR_2(temp4_input, S_IRUGO, show_temp, NULL, 1, 1);
 static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 
-static DEFINE_PCI_DEVICE_TABLE(k8temp_ids) = {
+static const struct pci_device_id k8temp_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) },
        { 0 },
 };
index 6cf6bff790033756a70d1d57ebe9f8f1096899f8..a2f3b4a365e4bbafa17385df4fdca298a7ece0e5 100644 (file)
@@ -94,6 +94,8 @@ static inline u8 FAN_TO_REG(long rpm, int div)
 {
        if (rpm <= 0)
                return 255;
+       if (rpm > 1350000)
+               return 1;
        return clamp_val((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
 }
 
index 4c4c1421bf28f66462d8d0bf5f2ee70947005ac0..8b8f3aa49726873b89267ebe45f4e145eab2c7bb 100644 (file)
@@ -1610,12 +1610,14 @@ static int lm90_probe(struct i2c_client *client,
                                                "lm90", client);
                if (err < 0) {
                        dev_err(dev, "cannot request IRQ %d\n", client->irq);
-                       goto exit_remove_files;
+                       goto exit_unregister;
                }
        }
 
        return 0;
 
+exit_unregister:
+       hwmon_device_unregister(data->hwmon_dev);
 exit_remove_files:
        lm90_remove_files(client, data);
 exit_restore:
index 1404e6319deb3cf918c1874f1be8b09b85902d65..e74bd7e620e8140a44a3917ef701ff22223b8a62 100644 (file)
@@ -141,6 +141,8 @@ static inline u8 FAN_TO_REG(long rpm, int div)
 {
        if (rpm <= 0)
                return 255;
+       if (rpm > 1350000)
+               return 1;
        return clamp_val((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
 }
 
@@ -752,7 +754,7 @@ static struct sis5595_data *sis5595_update_device(struct device *dev)
        return data;
 }
 
-static DEFINE_PCI_DEVICE_TABLE(sis5595_pci_ids) = {
+static const struct pci_device_id sis5595_pci_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) },
        { 0, }
 };
index c9dcce8c3dc34fa7ec8e7eeb0c8ee6812dc159ce..babd732b4e184303d071149e98ae4651b71403e4 100644 (file)
@@ -824,7 +824,7 @@ static struct via686a_data *via686a_update_device(struct device *dev)
        return data;
 }
 
-static DEFINE_PCI_DEVICE_TABLE(via686a_pci_ids) = {
+static const struct pci_device_id via686a_pci_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4) },
        { }
 };
index 0e7017841f7dacb9b1341e4313f4acaf009349a6..b3babe3326fb2d41b68ce3712f8dd00871c33508 100644 (file)
@@ -145,7 +145,7 @@ static const u8 regtempmin[] = { 0x3a, 0x3e, 0x2c, 0x2e, 0x30, 0x32 };
  */
 static inline u8 FAN_TO_REG(long rpm, int div)
 {
-       if (rpm == 0)
+       if (rpm <= 0 || rpm > 1310720)
                return 0;
        return clamp_val(1310720 / (rpm * div), 1, 255);
 }
@@ -766,7 +766,7 @@ static struct platform_driver vt8231_driver = {
        .remove = vt8231_remove,
 };
 
-static DEFINE_PCI_DEVICE_TABLE(vt8231_pci_ids) = {
+static const struct pci_device_id vt8231_pci_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4) },
        { 0, }
 };
index edb06cda5a689a4be87046b138051f5b4b42e3ca..6ed76ceb92709078497571ad4cb6f8740d3490bb 100644 (file)
@@ -481,9 +481,11 @@ store_pwm(struct device *dev, struct device_attribute *attr,
        if (err)
                return err;
        val = clamp_val(val, 0, 255);
+       val = DIV_ROUND_CLOSEST(val, 0x11);
 
        mutex_lock(&data->update_lock);
-       data->pwm[nr] = val;
+       data->pwm[nr] = val * 0x11;
+       val |= w83l786ng_read_value(client, W83L786NG_REG_PWM[nr]) & 0xf0;
        w83l786ng_write_value(client, W83L786NG_REG_PWM[nr], val);
        mutex_unlock(&data->update_lock);
        return count;
@@ -510,7 +512,7 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr,
        mutex_lock(&data->update_lock);
        reg = w83l786ng_read_value(client, W83L786NG_REG_FAN_CFG);
        data->pwm_enable[nr] = val;
-       reg &= ~(0x02 << W83L786NG_PWM_ENABLE_SHIFT[nr]);
+       reg &= ~(0x03 << W83L786NG_PWM_ENABLE_SHIFT[nr]);
        reg |= (val - 1) << W83L786NG_PWM_ENABLE_SHIFT[nr];
        w83l786ng_write_value(client, W83L786NG_REG_FAN_CFG, reg);
        mutex_unlock(&data->update_lock);
@@ -776,9 +778,10 @@ static struct w83l786ng_data *w83l786ng_update_device(struct device *dev)
                            ((pwmcfg >> W83L786NG_PWM_MODE_SHIFT[i]) & 1)
                            ? 0 : 1;
                        data->pwm_enable[i] =
-                           ((pwmcfg >> W83L786NG_PWM_ENABLE_SHIFT[i]) & 2) + 1;
-                       data->pwm[i] = w83l786ng_read_value(client,
-                           W83L786NG_REG_PWM[i]);
+                           ((pwmcfg >> W83L786NG_PWM_ENABLE_SHIFT[i]) & 3) + 1;
+                       data->pwm[i] =
+                           (w83l786ng_read_value(client, W83L786NG_REG_PWM[i])
+                            & 0x0f) * 0x11;
                }
 
 
index b1d38590ac0196f1da49d4d67e411b3741175b9f..46eaf58d881b4e31032327e7c248979d693d9c11 100644 (file)
@@ -198,7 +198,7 @@ fail_base2:
                                continue;
                        }
                }         
-               buddha_board = ZTWO_VADDR(board);
+               buddha_board = (unsigned long)ZTWO_VADDR(board);
                
                /* write to BUDDHA_IRQ_MR to enable the board IRQ */
                /* X-Surf doesn't have this.  IRQs are always on */
index d9e1f7ccfe6f086df549160a88ca191e52fca32f..b6940992a6ff95c699eddb8c7e2fb484a2f16ed3 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <acpi/acpi.h>
 #include <linux/ide.h>
 #include <linux/pci.h>
 #include <linux/dmi.h>
@@ -98,6 +97,17 @@ bool ide_port_acpi(ide_hwif_t *hwif)
        return ide_noacpi == 0 && hwif->acpidata;
 }
 
+static acpi_handle acpi_get_child(acpi_handle handle, u64 addr)
+{
+       struct acpi_device *adev;
+
+       if (!handle || acpi_bus_get_device(handle, &adev))
+               return NULL;
+
+       adev = acpi_find_child_device(adev, addr, false);
+       return adev ? adev->handle : NULL;
+}
+
 /**
  * ide_get_dev_handle - finds acpi_handle and PCI device.function
  * @dev: device to locate
index cbd4e9abc47e8f47f512915d224f916166921110..92d1206482a62ca57128690e49735dea2f00aaa3 100644 (file)
@@ -329,7 +329,7 @@ static struct cpuidle_state atom_cstates[] __initdata = {
        {
                .enter = NULL }
 };
-static struct cpuidle_state avn_cstates[CPUIDLE_STATE_MAX] = {
+static struct cpuidle_state avn_cstates[] __initdata = {
        {
                .name = "C1-AVN",
                .desc = "MWAIT 0x00",
@@ -340,7 +340,7 @@ static struct cpuidle_state avn_cstates[CPUIDLE_STATE_MAX] = {
        {
                .name = "C6-AVN",
                .desc = "MWAIT 0x51",
-               .flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+               .flags = MWAIT2flg(0x51) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
                .exit_latency = 15,
                .target_residency = 45,
                .enter = &intel_idle },
index 1178121b55b032989257e3167c6724815458ec26..39188b72cd3b2865a763e5a0b3c4715ad3d93570 100644 (file)
@@ -25,13 +25,4 @@ config HID_SENSOR_IIO_TRIGGER
          If this driver is compiled as a module, it will be named
          hid-sensor-trigger.
 
-config HID_SENSOR_ENUM_BASE_QUIRKS
-       bool "ENUM base quirks for HID Sensor IIO drivers"
-       depends on HID_SENSOR_IIO_COMMON
-       help
-         Say yes here to build support for sensor hub FW using
-         enumeration, which is using 1 as base instead of 0.
-         Since logical minimum is still set 0 instead of 1,
-         there is no easy way to differentiate.
-
 endmenu
index bbd6426c9726d8f4e0bf36f1e138901c19ff99e8..7dcf83998e6f7fc58de8c5c3a894207abcd06bab 100644 (file)
@@ -33,24 +33,34 @@ static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig,
 {
        struct hid_sensor_common *st = iio_trigger_get_drvdata(trig);
        int state_val;
+       int report_val;
 
        if (state) {
                if (sensor_hub_device_open(st->hsdev))
                        return -EIO;
-       } else
+               state_val =
+               HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM;
+               report_val =
+               HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM;
+
+       } else {
                sensor_hub_device_close(st->hsdev);
+               state_val =
+               HID_USAGE_SENSOR_PROP_POWER_STATE_D4_POWER_OFF_ENUM;
+               report_val =
+               HID_USAGE_SENSOR_PROP_REPORTING_STATE_NO_EVENTS_ENUM;
+       }
 
-       state_val = state ? 1 : 0;
-       if (IS_ENABLED(CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS))
-               ++state_val;
        st->data_ready = state;
+       state_val += st->power_state.logical_minimum;
+       report_val += st->report_state.logical_minimum;
        sensor_hub_set_feature(st->hsdev, st->power_state.report_id,
                                        st->power_state.index,
                                        (s32)state_val);
 
        sensor_hub_set_feature(st->hsdev, st->report_state.report_id,
                                        st->report_state.index,
-                                       (s32)state_val);
+                                       (s32)report_val);
 
        return 0;
 }
index b0d65df3ede2050d4c9944e819b45917ef945c87..a022f27c6690d56ba9c70caaa3953919b15c492e 100644 (file)
@@ -43,6 +43,7 @@ config GP2AP020A00F
        depends on I2C
        select IIO_BUFFER
        select IIO_TRIGGERED_BUFFER
+       select IRQ_WORK
        help
          Say Y here if you have a Sharp GP2AP020A00F proximity/ALS combo-chip
          hooked to an I2C bus.
index 5ceda710f516bc4721e14961a504fa7e2c3054a9..10219ee92191bce2c7e8828f8b61dc5c419d0c35 100644 (file)
@@ -53,6 +53,7 @@ source "drivers/infiniband/hw/mlx4/Kconfig"
 source "drivers/infiniband/hw/mlx5/Kconfig"
 source "drivers/infiniband/hw/nes/Kconfig"
 source "drivers/infiniband/hw/ocrdma/Kconfig"
+source "drivers/infiniband/hw/usnic/Kconfig"
 
 source "drivers/infiniband/ulp/ipoib/Kconfig"
 
index 1fe69888515f32cdd5f20f20b9a1d9d5f79876b6..bf508b5550c452f32997a888badb4c885900cec9 100644 (file)
@@ -10,6 +10,7 @@ obj-$(CONFIG_MLX4_INFINIBAND)         += hw/mlx4/
 obj-$(CONFIG_MLX5_INFINIBAND)          += hw/mlx5/
 obj-$(CONFIG_INFINIBAND_NES)           += hw/nes/
 obj-$(CONFIG_INFINIBAND_OCRDMA)                += hw/ocrdma/
+obj-$(CONFIG_INFINIBAND_USNIC)         += hw/usnic/
 obj-$(CONFIG_INFINIBAND_IPOIB)         += ulp/ipoib/
 obj-$(CONFIG_INFINIBAND_SRP)           += ulp/srp/
 obj-$(CONFIG_INFINIBAND_SRPT)          += ulp/srpt/
diff --git a/drivers/infiniband/hw/usnic/Kconfig b/drivers/infiniband/hw/usnic/Kconfig
new file mode 100644 (file)
index 0000000..0f14b6d
--- /dev/null
@@ -0,0 +1,11 @@
+config INFINIBAND_USNIC
+       tristate "Verbs support for Cisco VIC"
+       depends on NETDEVICES && ETHERNET && PCI
+       select ENIC
+       select NET_VENDOR_CISCO
+       select PCI_IOV
+       select IOMMU_SUPPORT
+       select INFINIBAND_USER_ACCESS
+       ---help---
+         This is a low-level driver for Cisco's Virtual Interface
+         Cards (VICs), including the VIC 1240 and 1280 cards.
diff --git a/drivers/infiniband/hw/usnic/Makefile b/drivers/infiniband/hw/usnic/Makefile
new file mode 100644 (file)
index 0000000..99fb2db
--- /dev/null
@@ -0,0 +1,15 @@
+ccflags-y := -Idrivers/net/ethernet/cisco/enic
+
+obj-$(CONFIG_INFINIBAND_USNIC)+= usnic_verbs.o
+
+usnic_verbs-y=\
+usnic_fwd.o \
+usnic_transport.o \
+usnic_uiom.o \
+usnic_uiom_interval_tree.o \
+usnic_vnic.o \
+usnic_ib_main.o \
+usnic_ib_qp_grp.o \
+usnic_ib_sysfs.o \
+usnic_ib_verbs.o \
+usnic_debugfs.o \
diff --git a/drivers/infiniband/hw/usnic/usnic.h b/drivers/infiniband/hw/usnic/usnic.h
new file mode 100644 (file)
index 0000000..d741c76
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may 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.
+ *
+ * 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 USNIC_H_
+#define USNIC_H_
+
+#define DRV_NAME       "usnic_verbs"
+
+#define PCI_DEVICE_ID_CISCO_VIC_USPACE_NIC     0x00cf  /* User space NIC */
+
+#define DRV_VERSION    "1.0.2"
+#define DRV_RELDATE    "September 09, 2013"
+
+#endif /* USNIC_H_ */
diff --git a/drivers/infiniband/hw/usnic/usnic_abi.h b/drivers/infiniband/hw/usnic/usnic_abi.h
new file mode 100644 (file)
index 0000000..2beabf7
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may 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.
+ *
+ * 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 USNIC_ABI_H
+#define USNIC_ABI_H
+
+/* ABI between userspace and kernel */
+#define USNIC_UVERBS_ABI_VERSION       2
+
+#define USNIC_QP_GRP_MAX_WQS           8
+#define USNIC_QP_GRP_MAX_RQS           8
+#define USNIC_QP_GRP_MAX_CQS           16
+
+enum usnic_transport_type {
+       USNIC_TRANSPORT_UNKNOWN         = 0,
+       USNIC_TRANSPORT_ROCE_CUSTOM     = 1,
+       USNIC_TRANSPORT_MAX             = 2,
+};
+
+/*TODO: Future - usnic_modify_qp needs to pass in generic filters */
+struct usnic_ib_create_qp_resp {
+       u32                             vfid;
+       u32                             qp_grp_id;
+       u64                             bar_bus_addr;
+       u32                             bar_len;
+/*
+ * WQ, RQ, CQ are explicity specified bc exposing a generic resources inteface
+ * expands the scope of ABI to many files.
+ */
+       u32                             wq_cnt;
+       u32                             rq_cnt;
+       u32                             cq_cnt;
+       u32                             wq_idx[USNIC_QP_GRP_MAX_WQS];
+       u32                             rq_idx[USNIC_QP_GRP_MAX_RQS];
+       u32                             cq_idx[USNIC_QP_GRP_MAX_CQS];
+       u32                             transport;
+       u64                             reserved;
+};
+
+#endif /* USNIC_ABI_H */
diff --git a/drivers/infiniband/hw/usnic/usnic_common_pkt_hdr.h b/drivers/infiniband/hw/usnic/usnic_common_pkt_hdr.h
new file mode 100644 (file)
index 0000000..3935672
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may 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.
+ *
+ * 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 USNIC_CMN_PKT_HDR_H
+#define USNIC_CMN_PKT_HDR_H
+
+#define USNIC_ROCE_ETHERTYPE           (0x8915)
+#define USNIC_ROCE_GRH_VER              (8)
+#define USNIC_PROTO_VER                 (1)
+#define USNIC_ROCE_GRH_VER_SHIFT        (4)
+
+#endif /* USNIC_COMMON_PKT_HDR_H */
diff --git a/drivers/infiniband/hw/usnic/usnic_common_util.h b/drivers/infiniband/hw/usnic/usnic_common_util.h
new file mode 100644 (file)
index 0000000..128550a
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may 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.
+ *
+ * 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 USNIC_CMN_UTIL_H
+#define USNIC_CMN_UTIL_H
+
+static inline void
+usnic_mac_to_gid(const char *const mac, char *raw_gid)
+{
+       raw_gid[0] = 0xfe;
+       raw_gid[1] = 0x80;
+       memset(&raw_gid[2], 0, 6);
+       raw_gid[8] = mac[0]^2;
+       raw_gid[9] = mac[1];
+       raw_gid[10] = mac[2];
+       raw_gid[11] = 0xff;
+       raw_gid[12] = 0xfe;
+       raw_gid[13] = mac[3];
+       raw_gid[14] = mac[4];
+       raw_gid[15] = mac[5];
+}
+
+static inline void
+usnic_write_gid_if_id_from_mac(char *mac, char *raw_gid)
+{
+       raw_gid[8] = mac[0]^2;
+       raw_gid[9] = mac[1];
+       raw_gid[10] = mac[2];
+       raw_gid[11] = 0xff;
+       raw_gid[12] = 0xfe;
+       raw_gid[13] = mac[3];
+       raw_gid[14] = mac[4];
+       raw_gid[15] = mac[5];
+}
+
+#endif /* USNIC_COMMON_UTIL_H */
diff --git a/drivers/infiniband/hw/usnic/usnic_debugfs.c b/drivers/infiniband/hw/usnic/usnic_debugfs.c
new file mode 100644 (file)
index 0000000..91386df
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may 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.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/debugfs.h>
+#include <linux/module.h>
+
+#include "usnic.h"
+#include "usnic_log.h"
+#include "usnic_debugfs.h"
+
+static struct dentry *debugfs_root;
+
+static ssize_t usnic_debugfs_buildinfo_read(struct file *f, char __user *data,
+                                               size_t count, loff_t *ppos)
+{
+       char buf[500];
+       int res;
+
+       if (*ppos > 0)
+               return 0;
+
+       res = scnprintf(buf, sizeof(buf),
+                       "version:       %s\n"
+                       "build date:    %s\n",
+                       DRV_VERSION, DRV_RELDATE);
+
+       return simple_read_from_buffer(data, count, ppos, buf, res);
+}
+
+static const struct file_operations usnic_debugfs_buildinfo_ops = {
+       .owner = THIS_MODULE,
+       .open = simple_open,
+       .read = usnic_debugfs_buildinfo_read
+};
+
+void usnic_debugfs_init(void)
+{
+       debugfs_root = debugfs_create_dir(DRV_NAME, NULL);
+       if (IS_ERR(debugfs_root)) {
+               usnic_err("Failed to create debugfs root dir, check if debugfs is enabled in kernel configuration\n");
+               debugfs_root = NULL;
+               return;
+       }
+
+       debugfs_create_file("build-info", S_IRUGO, debugfs_root,
+                               NULL, &usnic_debugfs_buildinfo_ops);
+}
+
+void usnic_debugfs_exit(void)
+{
+       if (!debugfs_root)
+               return;
+
+       debugfs_remove_recursive(debugfs_root);
+       debugfs_root = NULL;
+}
diff --git a/drivers/infiniband/hw/usnic/usnic_debugfs.h b/drivers/infiniband/hw/usnic/usnic_debugfs.h
new file mode 100644 (file)
index 0000000..914a330
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may 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.
+ *
+ * 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 USNIC_DEBUGFS_H_
+#define USNIC_DEBUGFS_H_
+
+void usnic_debugfs_init(void);
+
+void usnic_debugfs_exit(void);
+
+#endif /*!USNIC_DEBUGFS_H_ */
diff --git a/drivers/infiniband/hw/usnic/usnic_fwd.c b/drivers/infiniband/hw/usnic/usnic_fwd.c
new file mode 100644 (file)
index 0000000..b5719fc
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may 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.
+ *
+ * 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.
+ *
+ */
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+
+#include "enic_api.h"
+#include "usnic_common_pkt_hdr.h"
+#include "usnic_fwd.h"
+#include "usnic_log.h"
+
+struct usnic_fwd_dev *usnic_fwd_dev_alloc(struct pci_dev *pdev)
+{
+       struct usnic_fwd_dev *ufdev;
+
+       ufdev = kzalloc(sizeof(*ufdev), GFP_KERNEL);
+       if (!ufdev)
+               return NULL;
+
+       ufdev->pdev = pdev;
+       ufdev->netdev = pci_get_drvdata(pdev);
+       spin_lock_init(&ufdev->lock);
+
+       return ufdev;
+}
+
+void usnic_fwd_dev_free(struct usnic_fwd_dev *ufdev)
+{
+       kfree(ufdev);
+}
+
+static int usnic_fwd_devcmd(struct usnic_fwd_dev *ufdev, int vnic_idx,
+                               enum vnic_devcmd_cmd cmd, u64 *a0, u64 *a1)
+{
+       int status;
+       struct net_device *netdev = ufdev->netdev;
+
+       spin_lock(&ufdev->lock);
+       status = enic_api_devcmd_proxy_by_index(netdev,
+                       vnic_idx,
+                       cmd,
+                       a0, a1,
+                       1000);
+       spin_unlock(&ufdev->lock);
+       if (status) {
+               if (status == ERR_EINVAL && cmd == CMD_DEL_FILTER) {
+                       usnic_dbg("Dev %s vnic idx %u cmd %u already deleted",
+                                       netdev_name(netdev), vnic_idx, cmd);
+               } else {
+                       usnic_err("Dev %s vnic idx %u cmd %u failed with status %d\n",
+                                       netdev_name(netdev), vnic_idx, cmd,
+                                       status);
+               }
+       } else {
+               usnic_dbg("Dev %s vnic idx %u cmd %u success",
+                               netdev_name(netdev), vnic_idx,
+                               cmd);
+       }
+
+       return status;
+}
+
+int usnic_fwd_add_usnic_filter(struct usnic_fwd_dev *ufdev, int vnic_idx,
+                               int rq_idx, struct usnic_fwd_filter *fwd_filter,
+                               struct usnic_fwd_filter_hndl **filter_hndl)
+{
+       struct filter_tlv *tlv, *tlv_va;
+       struct filter *filter;
+       struct filter_action *action;
+       struct pci_dev *pdev;
+       struct usnic_fwd_filter_hndl *usnic_filter_hndl;
+       int status;
+       u64 a0, a1;
+       u64 tlv_size;
+       dma_addr_t tlv_pa;
+
+       pdev = ufdev->pdev;
+       tlv_size = (2*sizeof(struct filter_tlv) +
+               sizeof(struct filter) +
+               sizeof(struct filter_action));
+       tlv = pci_alloc_consistent(pdev, tlv_size, &tlv_pa);
+       if (!tlv) {
+               usnic_err("Failed to allocate memory\n");
+               return -ENOMEM;
+       }
+
+       usnic_filter_hndl = kzalloc(sizeof(*usnic_filter_hndl), GFP_KERNEL);
+       if (!usnic_filter_hndl) {
+               usnic_err("Failed to allocate memory for hndl\n");
+               pci_free_consistent(pdev, tlv_size, tlv, tlv_pa);
+               return -ENOMEM;
+       }
+
+       tlv_va = tlv;
+       a0 = tlv_pa;
+       a1 = tlv_size;
+       memset(tlv, 0, tlv_size);
+       tlv->type = CLSF_TLV_FILTER;
+       tlv->length = sizeof(struct filter);
+       filter = (struct filter *)&tlv->val;
+       filter->type = FILTER_USNIC_ID;
+       filter->u.usnic.ethtype = USNIC_ROCE_ETHERTYPE;
+       filter->u.usnic.flags = FILTER_FIELD_USNIC_ETHTYPE |
+                                       FILTER_FIELD_USNIC_ID |
+                                       FILTER_FIELD_USNIC_PROTO;
+       filter->u.usnic.proto_version = (USNIC_ROCE_GRH_VER <<
+                                               USNIC_ROCE_GRH_VER_SHIFT)
+                                                       | USNIC_PROTO_VER;
+       filter->u.usnic.usnic_id = fwd_filter->port_num;
+       tlv = (struct filter_tlv *)((char *)tlv + sizeof(struct filter_tlv) +
+                       sizeof(struct filter));
+       tlv->type = CLSF_TLV_ACTION;
+       tlv->length = sizeof(struct filter_action);
+       action = (struct filter_action *)&tlv->val;
+       action->type = FILTER_ACTION_RQ_STEERING;
+       action->u.rq_idx = rq_idx;
+
+       status = usnic_fwd_devcmd(ufdev, vnic_idx, CMD_ADD_FILTER, &a0, &a1);
+       pci_free_consistent(pdev, tlv_size, tlv_va, tlv_pa);
+       if (status) {
+               usnic_err("VF %s Filter add failed with status:%d",
+                               pci_name(pdev),
+                               status);
+               kfree(usnic_filter_hndl);
+               return status;
+       } else {
+               usnic_dbg("VF %s FILTER ID:%u",
+                               pci_name(pdev),
+                               (u32)a0);
+       }
+
+       usnic_filter_hndl->type = FILTER_USNIC_ID;
+       usnic_filter_hndl->id = (u32)a0;
+       usnic_filter_hndl->vnic_idx = vnic_idx;
+       usnic_filter_hndl->ufdev = ufdev;
+       usnic_filter_hndl->filter = fwd_filter;
+       *filter_hndl = usnic_filter_hndl;
+
+       return status;
+}
+
+int usnic_fwd_del_filter(struct usnic_fwd_filter_hndl *filter_hndl)
+{
+       int status;
+       u64 a0, a1;
+       struct net_device *netdev;
+
+       netdev = filter_hndl->ufdev->netdev;
+       a0 = filter_hndl->id;
+
+       status = usnic_fwd_devcmd(filter_hndl->ufdev, filter_hndl->vnic_idx,
+                                       CMD_DEL_FILTER, &a0, &a1);
+       if (status) {
+               if (status == ERR_EINVAL) {
+                       usnic_dbg("Filter %u already deleted for VF Idx %u pf: %s status: %d",
+                                       filter_hndl->id, filter_hndl->vnic_idx,
+                                       netdev_name(netdev), status);
+                       status = 0;
+                       kfree(filter_hndl);
+               } else {
+                       usnic_err("PF %s VF Idx %u Filter: %u FILTER DELETE failed with status %d",
+                                       netdev_name(netdev),
+                                       filter_hndl->vnic_idx, filter_hndl->id,
+                                       status);
+               }
+       } else {
+               usnic_dbg("PF %s VF Idx %u Filter: %u FILTER DELETED",
+                               netdev_name(netdev), filter_hndl->vnic_idx,
+                               filter_hndl->id);
+               kfree(filter_hndl);
+       }
+
+       return status;
+}
+
+int usnic_fwd_enable_rq(struct usnic_fwd_dev *ufdev, int vnic_idx, int rq_idx)
+{
+       int status;
+       struct net_device *pf_netdev;
+       u64 a0, a1;
+
+       pf_netdev = ufdev->netdev;
+       a0 = rq_idx;
+       a1 = CMD_QP_RQWQ;
+
+       status = usnic_fwd_devcmd(ufdev, vnic_idx, CMD_QP_ENABLE, &a0, &a1);
+
+       if (status) {
+               usnic_err("PF %s VNIC Index %u RQ Index: %u ENABLE Failed with status %d",
+                               netdev_name(pf_netdev),
+                               vnic_idx,
+                               rq_idx,
+                               status);
+       } else {
+               usnic_dbg("PF %s VNIC Index %u RQ Index: %u ENABLED",
+                               netdev_name(pf_netdev),
+                               vnic_idx, rq_idx);
+       }
+
+       return status;
+}
+
+int usnic_fwd_disable_rq(struct usnic_fwd_dev *ufdev, int vnic_idx, int rq_idx)
+{
+       int status;
+       u64 a0, a1;
+       struct net_device *pf_netdev;
+
+       pf_netdev = ufdev->netdev;
+       a0 = rq_idx;
+       a1 = CMD_QP_RQWQ;
+
+       status = usnic_fwd_devcmd(ufdev, vnic_idx, CMD_QP_DISABLE, &a0, &a1);
+
+       if (status) {
+               usnic_err("PF %s VNIC Index %u RQ Index: %u DISABLE Failed with status %d",
+                               netdev_name(pf_netdev),
+                               vnic_idx,
+                               rq_idx,
+                               status);
+       } else {
+               usnic_dbg("PF %s VNIC Index %u RQ Index: %u DISABLED",
+                               netdev_name(pf_netdev),
+                               vnic_idx,
+                               rq_idx);
+       }
+
+       return status;
+}
diff --git a/drivers/infiniband/hw/usnic/usnic_fwd.h b/drivers/infiniband/hw/usnic/usnic_fwd.h
new file mode 100644 (file)
index 0000000..6973901
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may 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.
+ *
+ * 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 USNIC_FWD_H_
+#define USNIC_FWD_H_
+
+#include <linux/if.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+
+#include "usnic_abi.h"
+#include "vnic_devcmd.h"
+
+struct usnic_fwd_dev {
+       struct pci_dev                  *pdev;
+       struct net_device               *netdev;
+       spinlock_t                      lock;
+};
+
+struct usnic_fwd_filter {
+       enum usnic_transport_type       transport;
+       u16                             port_num;
+};
+
+struct usnic_fwd_filter_hndl {
+       enum filter_type                type;
+       u32                             id;
+       u32                             vnic_idx;
+       struct usnic_fwd_dev            *ufdev;
+       struct list_head                link;
+       struct usnic_fwd_filter         *filter;
+};
+
+struct usnic_fwd_dev *usnic_fwd_dev_alloc(struct pci_dev *pdev);
+void usnic_fwd_dev_free(struct usnic_fwd_dev *ufdev);
+int usnic_fwd_add_usnic_filter(struct usnic_fwd_dev *ufdev, int vnic_idx,
+                               int rq_idx, struct usnic_fwd_filter *filter,
+                               struct usnic_fwd_filter_hndl **filter_hndl);
+int usnic_fwd_del_filter(struct usnic_fwd_filter_hndl *filter_hndl);
+int usnic_fwd_enable_rq(struct usnic_fwd_dev *ufdev, int vnic_idx, int rq_idx);
+int usnic_fwd_disable_rq(struct usnic_fwd_dev *ufdev, int vnic_idx, int rq_idx);
+
+#endif /* !USNIC_FWD_H_ */
diff --git a/drivers/infiniband/hw/usnic/usnic_ib.h b/drivers/infiniband/hw/usnic/usnic_ib.h
new file mode 100644 (file)
index 0000000..3511c85
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may 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.
+ *
+ * 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 USNIC_IB_H_
+#define USNIC_IB_H_
+
+#include <linux/iommu.h>
+#include <linux/netdevice.h>
+#include <linux/version.h>
+
+#include <rdma/ib_verbs.h>
+
+
+#include "usnic.h"
+#include "usnic_abi.h"
+#include "usnic_vnic.h"
+
+#define USNIC_IB_PORT_CNT              1
+#define USNIC_IB_NUM_COMP_VECTORS      1
+
+extern unsigned int usnic_ib_share_vf;
+
+struct usnic_ib_ucontext {
+       struct ib_ucontext              ibucontext;
+       /* Protected by usnic_ib_dev->usdev_lock */
+       struct list_head                qp_grp_list;
+       struct list_head                link;
+};
+
+struct usnic_ib_pd {
+       struct ib_pd                    ibpd;
+       struct usnic_uiom_pd            *umem_pd;
+};
+
+struct usnic_ib_mr {
+       struct ib_mr                    ibmr;
+       struct usnic_uiom_reg           *umem;
+};
+
+struct usnic_ib_dev {
+       struct ib_device                ib_dev;
+       struct pci_dev                  *pdev;
+       struct net_device               *netdev;
+       struct usnic_fwd_dev            *ufdev;
+       bool                            link_up;
+       struct list_head                ib_dev_link;
+       struct list_head                vf_dev_list;
+       struct list_head                ctx_list;
+       struct mutex                    usdev_lock;
+       char                            mac[ETH_ALEN];
+       unsigned int                    mtu;
+
+       /* provisioning information */
+       struct kref                     vf_cnt;
+       unsigned int                    vf_res_cnt[USNIC_VNIC_RES_TYPE_MAX];
+
+       /* sysfs vars for QPN reporting */
+       struct kobject *qpn_kobj;
+};
+
+struct usnic_ib_vf {
+       struct usnic_ib_dev             *pf;
+       spinlock_t                      lock;
+       struct usnic_vnic               *vnic;
+       unsigned int                    qp_grp_ref_cnt;
+       struct usnic_ib_pd              *pd;
+       struct list_head                link;
+};
+
+static inline
+struct usnic_ib_dev *to_usdev(struct ib_device *ibdev)
+{
+       return container_of(ibdev, struct usnic_ib_dev, ib_dev);
+}
+
+static inline
+struct usnic_ib_ucontext *to_ucontext(struct ib_ucontext *ibucontext)
+{
+       return container_of(ibucontext, struct usnic_ib_ucontext, ibucontext);
+}
+
+static inline
+struct usnic_ib_pd *to_upd(struct ib_pd *ibpd)
+{
+       return container_of(ibpd, struct usnic_ib_pd, ibpd);
+}
+
+static inline
+struct usnic_ib_ucontext *to_uucontext(struct ib_ucontext *ibucontext)
+{
+       return container_of(ibucontext, struct usnic_ib_ucontext, ibucontext);
+}
+
+static inline
+struct usnic_ib_mr *to_umr(struct ib_mr *ibmr)
+{
+       return container_of(ibmr, struct usnic_ib_mr, ibmr);
+}
+void usnic_ib_log_vf(struct usnic_ib_vf *vf);
+#endif /* USNIC_IB_H_ */
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_main.c b/drivers/infiniband/hw/usnic/usnic_ib_main.c
new file mode 100644 (file)
index 0000000..2bbfa09
--- /dev/null
@@ -0,0 +1,598 @@
+/*
+ * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may 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.
+ *
+ * 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: Upinder Malhi <umalhi@cisco.com>
+ * Author: Anant Deepak <anadeepa@cisco.com>
+ * Author: Cesare Cantu' <cantuc@cisco.com>
+ * Author: Jeff Squyres <jsquyres@cisco.com>
+ * Author: Kiran Thirumalai <kithirum@cisco.com>
+ * Author: Xuyang Wang <xuywang@cisco.com>
+ * Author: Reese Faucette <rfaucett@cisco.com>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+
+#include <rdma/ib_user_verbs.h>
+#include <rdma/ib_addr.h>
+
+#include "usnic_abi.h"
+#include "usnic_common_util.h"
+#include "usnic_ib.h"
+#include "usnic_ib_qp_grp.h"
+#include "usnic_log.h"
+#include "usnic_fwd.h"
+#include "usnic_debugfs.h"
+#include "usnic_ib_verbs.h"
+#include "usnic_transport.h"
+#include "usnic_uiom.h"
+#include "usnic_ib_sysfs.h"
+
+unsigned int usnic_log_lvl = USNIC_LOG_LVL_ERR;
+unsigned int usnic_ib_share_vf = 1;
+
+static const char usnic_version[] =
+       DRV_NAME ": Cisco VIC (USNIC) Verbs Driver v"
+       DRV_VERSION " (" DRV_RELDATE ")\n";
+
+static DEFINE_MUTEX(usnic_ib_ibdev_list_lock);
+static LIST_HEAD(usnic_ib_ibdev_list);
+
+/* Callback dump funcs */
+static int usnic_ib_dump_vf_hdr(void *obj, char *buf, int buf_sz)
+{
+       struct usnic_ib_vf *vf = obj;
+       return scnprintf(buf, buf_sz, "PF: %s ", vf->pf->ib_dev.name);
+}
+/* End callback dump funcs */
+
+static void usnic_ib_dump_vf(struct usnic_ib_vf *vf, char *buf, int buf_sz)
+{
+       usnic_vnic_dump(vf->vnic, buf, buf_sz, vf,
+                       usnic_ib_dump_vf_hdr,
+                       usnic_ib_qp_grp_dump_hdr, usnic_ib_qp_grp_dump_rows);
+}
+
+void usnic_ib_log_vf(struct usnic_ib_vf *vf)
+{
+       char buf[1024];
+       usnic_ib_dump_vf(vf, buf, sizeof(buf));
+       usnic_dbg(buf);
+}
+
+/* Start of netdev section */
+static inline const char *usnic_ib_netdev_event_to_string(unsigned long event)
+{
+       const char *event2str[] = {"NETDEV_NONE", "NETDEV_UP", "NETDEV_DOWN",
+               "NETDEV_REBOOT", "NETDEV_CHANGE",
+               "NETDEV_REGISTER", "NETDEV_UNREGISTER", "NETDEV_CHANGEMTU",
+               "NETDEV_CHANGEADDR", "NETDEV_GOING_DOWN", "NETDEV_FEAT_CHANGE",
+               "NETDEV_BONDING_FAILOVER", "NETDEV_PRE_UP",
+               "NETDEV_PRE_TYPE_CHANGE", "NETDEV_POST_TYPE_CHANGE",
+               "NETDEV_POST_INT", "NETDEV_UNREGISTER_FINAL", "NETDEV_RELEASE",
+               "NETDEV_NOTIFY_PEERS", "NETDEV_JOIN"
+       };
+
+       if (event >= ARRAY_SIZE(event2str))
+               return "UNKNOWN_NETDEV_EVENT";
+       else
+               return event2str[event];
+}
+
+static void usnic_ib_qp_grp_modify_active_to_err(struct usnic_ib_dev *us_ibdev)
+{
+       struct usnic_ib_ucontext *ctx;
+       struct usnic_ib_qp_grp *qp_grp;
+       enum ib_qp_state cur_state;
+       int status;
+
+       BUG_ON(!mutex_is_locked(&us_ibdev->usdev_lock));
+
+       list_for_each_entry(ctx, &us_ibdev->ctx_list, link) {
+               list_for_each_entry(qp_grp, &ctx->qp_grp_list, link) {
+                       cur_state = qp_grp->state;
+                       if (cur_state == IB_QPS_INIT ||
+                               cur_state == IB_QPS_RTR ||
+                               cur_state == IB_QPS_RTS) {
+                               status = usnic_ib_qp_grp_modify(qp_grp,
+                                                               IB_QPS_ERR,
+                                                               NULL);
+                               if (!status) {
+                                       usnic_err("Failed to transistion qp grp %u from %s to %s\n",
+                                               qp_grp->grp_id,
+                                               usnic_ib_qp_grp_state_to_string
+                                               (cur_state),
+                                               usnic_ib_qp_grp_state_to_string
+                                               (IB_QPS_ERR));
+                               }
+                       }
+               }
+       }
+}
+
+static void usnic_ib_handle_usdev_event(struct usnic_ib_dev *us_ibdev,
+                                       unsigned long event)
+{
+       struct net_device *netdev;
+       struct ib_event ib_event;
+
+       memset(&ib_event, 0, sizeof(ib_event));
+
+       mutex_lock(&us_ibdev->usdev_lock);
+       netdev = us_ibdev->netdev;
+       switch (event) {
+       case NETDEV_REBOOT:
+               usnic_info("PF Reset on %s\n", us_ibdev->ib_dev.name);
+               usnic_ib_qp_grp_modify_active_to_err(us_ibdev);
+               ib_event.event = IB_EVENT_PORT_ERR;
+               ib_event.device = &us_ibdev->ib_dev;
+               ib_event.element.port_num = 1;
+               ib_dispatch_event(&ib_event);
+               break;
+       case NETDEV_UP:
+               if (!us_ibdev->link_up) {
+                       us_ibdev->link_up = true;
+                       usnic_info("Link UP on %s\n", us_ibdev->ib_dev.name);
+                       ib_event.event = IB_EVENT_PORT_ACTIVE;
+                       ib_event.device = &us_ibdev->ib_dev;
+                       ib_event.element.port_num = 1;
+                       ib_dispatch_event(&ib_event);
+               } else {
+                       usnic_dbg("Ignorning Link UP on %s\n",
+                                       us_ibdev->ib_dev.name);
+               }
+               break;
+       case NETDEV_DOWN:
+               if (us_ibdev->link_up) {
+                       us_ibdev->link_up = false;
+                       usnic_info("Link DOWN on %s\n", us_ibdev->ib_dev.name);
+                       usnic_ib_qp_grp_modify_active_to_err(us_ibdev);
+                       ib_event.event = IB_EVENT_PORT_ERR;
+                       ib_event.device = &us_ibdev->ib_dev;
+                       ib_event.element.port_num = 1;
+                       ib_dispatch_event(&ib_event);
+               } else {
+                       usnic_dbg("Ignorning Link DOWN on %s\n",
+                                       us_ibdev->ib_dev.name);
+               }
+               break;
+       case NETDEV_CHANGEADDR:
+               if (!memcmp(us_ibdev->mac, netdev->dev_addr,
+                               sizeof(us_ibdev->mac))) {
+                       usnic_dbg("Ignorning addr change on %s\n",
+                                       us_ibdev->ib_dev.name);
+               } else {
+                       usnic_info(" %s old mac: %pM new mac: %pM\n",
+                                       us_ibdev->ib_dev.name,
+                                       us_ibdev->mac,
+                                       netdev->dev_addr);
+                       memcpy(us_ibdev->mac, netdev->dev_addr,
+                               sizeof(us_ibdev->mac));
+                       usnic_ib_qp_grp_modify_active_to_err(us_ibdev);
+                       ib_event.event = IB_EVENT_GID_CHANGE;
+                       ib_event.device = &us_ibdev->ib_dev;
+                       ib_event.element.port_num = 1;
+                       ib_dispatch_event(&ib_event);
+               }
+
+               break;
+       case NETDEV_CHANGEMTU:
+               if (us_ibdev->mtu != netdev->mtu) {
+                       usnic_info("MTU Change on %s old: %u new: %u\n",
+                                       us_ibdev->ib_dev.name,
+                                       us_ibdev->mtu, netdev->mtu);
+                       us_ibdev->mtu = netdev->mtu;
+                       usnic_ib_qp_grp_modify_active_to_err(us_ibdev);
+               } else {
+                       usnic_dbg("Ignoring MTU change on %s\n",
+                                       us_ibdev->ib_dev.name);
+               }
+               break;
+       default:
+               usnic_dbg("Ignorning event %s on %s",
+                               usnic_ib_netdev_event_to_string(event),
+                               us_ibdev->ib_dev.name);
+       }
+       mutex_unlock(&us_ibdev->usdev_lock);
+}
+
+static int usnic_ib_netdevice_event(struct notifier_block *notifier,
+                                       unsigned long event, void *ptr)
+{
+       struct usnic_ib_dev *us_ibdev;
+
+       struct net_device *netdev = ptr;
+
+       mutex_lock(&usnic_ib_ibdev_list_lock);
+       list_for_each_entry(us_ibdev, &usnic_ib_ibdev_list, ib_dev_link) {
+               if (us_ibdev->netdev == netdev) {
+                       usnic_ib_handle_usdev_event(us_ibdev, event);
+                       break;
+               }
+       }
+       mutex_unlock(&usnic_ib_ibdev_list_lock);
+
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block usnic_ib_netdevice_notifier = {
+       .notifier_call = usnic_ib_netdevice_event
+};
+/* End of netdev section */
+
+/* Start of PF discovery section */
+static void *usnic_ib_device_add(struct pci_dev *dev)
+{
+       struct usnic_ib_dev *us_ibdev;
+       union ib_gid gid;
+
+       usnic_dbg("\n");
+
+       us_ibdev = (struct usnic_ib_dev *)ib_alloc_device(sizeof(*us_ibdev));
+       if (IS_ERR_OR_NULL(us_ibdev)) {
+               usnic_err("Device %s context alloc failed\n",
+                               netdev_name(pci_get_drvdata(dev)));
+               return ERR_PTR(us_ibdev ? PTR_ERR(us_ibdev) : -EFAULT);
+       }
+
+       us_ibdev->ufdev = usnic_fwd_dev_alloc(dev);
+       if (IS_ERR_OR_NULL(us_ibdev->ufdev)) {
+               usnic_err("Failed to alloc ufdev for %s with err %ld\n",
+                               pci_name(dev), PTR_ERR(us_ibdev->ufdev));
+               goto err_dealloc;
+       }
+
+       mutex_init(&us_ibdev->usdev_lock);
+       INIT_LIST_HEAD(&us_ibdev->vf_dev_list);
+       INIT_LIST_HEAD(&us_ibdev->ctx_list);
+
+       us_ibdev->pdev = dev;
+       us_ibdev->netdev = pci_get_drvdata(dev);
+       us_ibdev->ib_dev.owner = THIS_MODULE;
+       us_ibdev->ib_dev.node_type = RDMA_NODE_USNIC;
+       us_ibdev->ib_dev.phys_port_cnt = USNIC_IB_PORT_CNT;
+       us_ibdev->ib_dev.num_comp_vectors = USNIC_IB_NUM_COMP_VECTORS;
+       us_ibdev->ib_dev.dma_device = &dev->dev;
+       us_ibdev->ib_dev.uverbs_abi_ver = USNIC_UVERBS_ABI_VERSION;
+       strlcpy(us_ibdev->ib_dev.name, "usnic_%d", IB_DEVICE_NAME_MAX);
+
+       us_ibdev->ib_dev.uverbs_cmd_mask =
+               (1ull << IB_USER_VERBS_CMD_GET_CONTEXT) |
+               (1ull << IB_USER_VERBS_CMD_QUERY_DEVICE) |
+               (1ull << IB_USER_VERBS_CMD_QUERY_PORT) |
+               (1ull << IB_USER_VERBS_CMD_ALLOC_PD) |
+               (1ull << IB_USER_VERBS_CMD_DEALLOC_PD) |
+               (1ull << IB_USER_VERBS_CMD_REG_MR) |
+               (1ull << IB_USER_VERBS_CMD_DEREG_MR) |
+               (1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) |
+               (1ull << IB_USER_VERBS_CMD_CREATE_CQ) |
+               (1ull << IB_USER_VERBS_CMD_DESTROY_CQ) |
+               (1ull << IB_USER_VERBS_CMD_CREATE_QP) |
+               (1ull << IB_USER_VERBS_CMD_MODIFY_QP) |
+               (1ull << IB_USER_VERBS_CMD_QUERY_QP) |
+               (1ull << IB_USER_VERBS_CMD_DESTROY_QP) |
+               (1ull << IB_USER_VERBS_CMD_ATTACH_MCAST) |
+               (1ull << IB_USER_VERBS_CMD_DETACH_MCAST) |
+               (1ull << IB_USER_VERBS_CMD_OPEN_QP);
+
+       us_ibdev->ib_dev.query_device = usnic_ib_query_device;
+       us_ibdev->ib_dev.query_port = usnic_ib_query_port;
+       us_ibdev->ib_dev.query_pkey = usnic_ib_query_pkey;
+       us_ibdev->ib_dev.query_gid = usnic_ib_query_gid;
+       us_ibdev->ib_dev.get_link_layer = usnic_ib_port_link_layer;
+       us_ibdev->ib_dev.alloc_pd = usnic_ib_alloc_pd;
+       us_ibdev->ib_dev.dealloc_pd = usnic_ib_dealloc_pd;
+       us_ibdev->ib_dev.create_qp = usnic_ib_create_qp;
+       us_ibdev->ib_dev.modify_qp = usnic_ib_modify_qp;
+       us_ibdev->ib_dev.query_qp = usnic_ib_query_qp;
+       us_ibdev->ib_dev.destroy_qp = usnic_ib_destroy_qp;
+       us_ibdev->ib_dev.create_cq = usnic_ib_create_cq;
+       us_ibdev->ib_dev.destroy_cq = usnic_ib_destroy_cq;
+       us_ibdev->ib_dev.reg_user_mr = usnic_ib_reg_mr;
+       us_ibdev->ib_dev.dereg_mr = usnic_ib_dereg_mr;
+       us_ibdev->ib_dev.alloc_ucontext = usnic_ib_alloc_ucontext;
+       us_ibdev->ib_dev.dealloc_ucontext = usnic_ib_dealloc_ucontext;
+       us_ibdev->ib_dev.mmap = usnic_ib_mmap;
+       us_ibdev->ib_dev.create_ah = usnic_ib_create_ah;
+       us_ibdev->ib_dev.destroy_ah = usnic_ib_destroy_ah;
+       us_ibdev->ib_dev.post_send = usnic_ib_post_send;
+       us_ibdev->ib_dev.post_recv = usnic_ib_post_recv;
+       us_ibdev->ib_dev.poll_cq = usnic_ib_poll_cq;
+       us_ibdev->ib_dev.req_notify_cq = usnic_ib_req_notify_cq;
+       us_ibdev->ib_dev.get_dma_mr = usnic_ib_get_dma_mr;
+
+
+       if (ib_register_device(&us_ibdev->ib_dev, NULL))
+               goto err_fwd_dealloc;
+
+       us_ibdev->link_up = netif_carrier_ok(us_ibdev->netdev);
+       us_ibdev->mtu = us_ibdev->netdev->mtu;
+       memcpy(&us_ibdev->mac, us_ibdev->netdev->dev_addr,
+               sizeof(us_ibdev->mac));
+       usnic_mac_to_gid(us_ibdev->netdev->perm_addr, &gid.raw[0]);
+       memcpy(&us_ibdev->ib_dev.node_guid, &gid.global.interface_id,
+               sizeof(gid.global.interface_id));
+       kref_init(&us_ibdev->vf_cnt);
+
+       usnic_info("Added ibdev: %s netdev: %s with mac %pM Link: %u MTU: %u\n",
+                       us_ibdev->ib_dev.name, netdev_name(us_ibdev->netdev),
+                       us_ibdev->mac, us_ibdev->link_up, us_ibdev->mtu);
+       return us_ibdev;
+
+err_fwd_dealloc:
+       usnic_fwd_dev_free(us_ibdev->ufdev);
+err_dealloc:
+       usnic_err("failed -- deallocing device\n");
+       ib_dealloc_device(&us_ibdev->ib_dev);
+       return NULL;
+}
+
+static void usnic_ib_device_remove(struct usnic_ib_dev *us_ibdev)
+{
+       usnic_info("Unregistering %s\n", us_ibdev->ib_dev.name);
+       usnic_ib_sysfs_unregister_usdev(us_ibdev);
+       usnic_fwd_dev_free(us_ibdev->ufdev);
+       ib_unregister_device(&us_ibdev->ib_dev);
+       ib_dealloc_device(&us_ibdev->ib_dev);
+}
+
+static void usnic_ib_undiscover_pf(struct kref *kref)
+{
+       struct usnic_ib_dev *us_ibdev, *tmp;
+       struct pci_dev *dev;
+       bool found = false;
+
+       dev = container_of(kref, struct usnic_ib_dev, vf_cnt)->pdev;
+       mutex_lock(&usnic_ib_ibdev_list_lock);
+       list_for_each_entry_safe(us_ibdev, tmp,
+                               &usnic_ib_ibdev_list, ib_dev_link) {
+               if (us_ibdev->pdev == dev) {
+                       list_del(&us_ibdev->ib_dev_link);
+                       usnic_ib_device_remove(us_ibdev);
+                       found = true;
+                       break;
+               }
+       }
+
+       if (!found)
+               WARN("Failed to remove PF %s\n", pci_name(dev));
+
+       mutex_unlock(&usnic_ib_ibdev_list_lock);
+}
+
+static struct usnic_ib_dev *usnic_ib_discover_pf(struct usnic_vnic *vnic)
+{
+       struct usnic_ib_dev *us_ibdev;
+       struct pci_dev *parent_pci, *vf_pci;
+       int err;
+
+       vf_pci = usnic_vnic_get_pdev(vnic);
+       parent_pci = pci_physfn(vf_pci);
+
+       BUG_ON(!parent_pci);
+
+       mutex_lock(&usnic_ib_ibdev_list_lock);
+       list_for_each_entry(us_ibdev, &usnic_ib_ibdev_list, ib_dev_link) {
+               if (us_ibdev->pdev == parent_pci) {
+                       kref_get(&us_ibdev->vf_cnt);
+                       goto out;
+               }
+       }
+
+       us_ibdev = usnic_ib_device_add(parent_pci);
+       if (IS_ERR_OR_NULL(us_ibdev)) {
+               us_ibdev = ERR_PTR(-EINVAL);
+               goto out;
+       }
+
+       err = usnic_ib_sysfs_register_usdev(us_ibdev);
+       if (err) {
+               usnic_ib_device_remove(us_ibdev);
+               goto out;
+       }
+
+       list_add(&us_ibdev->ib_dev_link, &usnic_ib_ibdev_list);
+out:
+       mutex_unlock(&usnic_ib_ibdev_list_lock);
+       return us_ibdev;
+}
+/* End of PF discovery section */
+
+/* Start of PCI section */
+
+static DEFINE_PCI_DEVICE_TABLE(usnic_ib_pci_ids) = {
+       {PCI_DEVICE(PCI_VENDOR_ID_CISCO, PCI_DEVICE_ID_CISCO_VIC_USPACE_NIC)},
+       {0,}
+};
+
+int usnic_ib_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+       int err;
+       struct usnic_ib_dev *pf;
+       struct usnic_ib_vf *vf;
+       enum usnic_vnic_res_type res_type;
+
+       vf = kzalloc(sizeof(*vf), GFP_KERNEL);
+       if (!vf)
+               return -ENOMEM;
+
+       err = pci_enable_device(pdev);
+       if (err) {
+               usnic_err("Failed to enable %s with err %d\n",
+                               pci_name(pdev), err);
+               goto out_clean_vf;
+       }
+
+       err = pci_request_regions(pdev, DRV_NAME);
+       if (err) {
+               usnic_err("Failed to request region for %s with err %d\n",
+                               pci_name(pdev), err);
+               goto out_disable_device;
+       }
+
+       pci_set_master(pdev);
+       pci_set_drvdata(pdev, vf);
+
+       vf->vnic = usnic_vnic_alloc(pdev);
+       if (IS_ERR_OR_NULL(vf->vnic)) {
+               err = (vf->vnic ? PTR_ERR(vf->vnic) : -ENOMEM);
+               usnic_err("Failed to alloc vnic for %s with err %d\n",
+                               pci_name(pdev), err);
+               goto out_release_regions;
+       }
+
+       pf = usnic_ib_discover_pf(vf->vnic);
+       if (!pf) {
+               usnic_err("Failed to discover pf of vnic %s with err%d\n",
+                               pci_name(pdev), err);
+               goto out_clean_vnic;
+       }
+
+       vf->pf = pf;
+       spin_lock_init(&vf->lock);
+       mutex_lock(&pf->usdev_lock);
+       list_add_tail(&vf->link, &pf->vf_dev_list);
+       /*
+        * Save max settings (will be same for each VF, easier to re-write than
+        * to say "if (!set) { set_values(); set=1; }
+        */
+       for (res_type = USNIC_VNIC_RES_TYPE_EOL+1;
+                       res_type < USNIC_VNIC_RES_TYPE_MAX;
+                       res_type++) {
+               pf->vf_res_cnt[res_type] = usnic_vnic_res_cnt(vf->vnic,
+                                                               res_type);
+       }
+
+       mutex_unlock(&pf->usdev_lock);
+
+       usnic_info("Registering usnic VF %s into PF %s\n", pci_name(pdev),
+                       pf->ib_dev.name);
+       usnic_ib_log_vf(vf);
+       return 0;
+
+out_clean_vnic:
+       usnic_vnic_free(vf->vnic);
+out_release_regions:
+       pci_set_drvdata(pdev, NULL);
+       pci_clear_master(pdev);
+       pci_release_regions(pdev);
+out_disable_device:
+       pci_disable_device(pdev);
+out_clean_vf:
+       kfree(vf);
+       return err;
+}
+
+static void usnic_ib_pci_remove(struct pci_dev *pdev)
+{
+       struct usnic_ib_vf *vf = pci_get_drvdata(pdev);
+       struct usnic_ib_dev *pf = vf->pf;
+
+       mutex_lock(&pf->usdev_lock);
+       list_del(&vf->link);
+       mutex_unlock(&pf->usdev_lock);
+
+       kref_put(&pf->vf_cnt, usnic_ib_undiscover_pf);
+       usnic_vnic_free(vf->vnic);
+       pci_set_drvdata(pdev, NULL);
+       pci_clear_master(pdev);
+       pci_release_regions(pdev);
+       pci_disable_device(pdev);
+       kfree(vf);
+
+       usnic_info("Removed VF %s\n", pci_name(pdev));
+}
+
+/* PCI driver entry points */
+static struct pci_driver usnic_ib_pci_driver = {
+       .name = DRV_NAME,
+       .id_table = usnic_ib_pci_ids,
+       .probe = usnic_ib_pci_probe,
+       .remove = usnic_ib_pci_remove,
+};
+/* End of PCI section */
+
+/* Start of module section */
+static int __init usnic_ib_init(void)
+{
+       int err;
+
+       printk_once(KERN_INFO "%s", usnic_version);
+
+       err = usnic_uiom_init(DRV_NAME);
+       if (err) {
+               usnic_err("Unable to initalize umem with err %d\n", err);
+               return err;
+       }
+
+       if (pci_register_driver(&usnic_ib_pci_driver)) {
+               usnic_err("Unable to register with PCI\n");
+               goto out_umem_fini;
+       }
+
+       err = register_netdevice_notifier(&usnic_ib_netdevice_notifier);
+       if (err) {
+               usnic_err("Failed to register netdev notifier\n");
+               goto out_pci_unreg;
+       }
+
+       err = usnic_transport_init();
+       if (err) {
+               usnic_err("Failed to initialize transport\n");
+               goto out_unreg_netdev_notifier;
+       }
+
+       usnic_debugfs_init();
+
+       return 0;
+
+out_unreg_netdev_notifier:
+       unregister_netdevice_notifier(&usnic_ib_netdevice_notifier);
+out_pci_unreg:
+       pci_unregister_driver(&usnic_ib_pci_driver);
+out_umem_fini:
+       usnic_uiom_fini();
+
+       return err;
+}
+
+static void __exit usnic_ib_destroy(void)
+{
+       usnic_dbg("\n");
+       usnic_debugfs_exit();
+       unregister_netdevice_notifier(&usnic_ib_netdevice_notifier);
+       pci_unregister_driver(&usnic_ib_pci_driver);
+       usnic_uiom_fini();
+}
+
+MODULE_DESCRIPTION("Cisco VIC (usNIC) Verbs Driver");
+MODULE_AUTHOR("Upinder Malhi <umalhi@cisco.com>");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_VERSION(DRV_VERSION);
+module_param(usnic_log_lvl, uint, S_IRUGO | S_IWUSR);
+module_param(usnic_ib_share_vf, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(usnic_log_lvl, " Off=0, Err=1, Info=2, Debug=3");
+MODULE_PARM_DESC(usnic_ib_share_vf, "Off=0, On=1 VF sharing amongst QPs");
+MODULE_DEVICE_TABLE(pci, usnic_ib_pci_ids);
+
+module_init(usnic_ib_init);
+module_exit(usnic_ib_destroy);
+/* End of module section */
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c
new file mode 100644 (file)
index 0000000..24da928
--- /dev/null
@@ -0,0 +1,541 @@
+/*
+ * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may 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.
+ *
+ * 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.
+ *
+ */
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+
+#include "usnic_log.h"
+#include "usnic_vnic.h"
+#include "usnic_fwd.h"
+#include "usnic_uiom.h"
+#include "usnic_ib_qp_grp.h"
+#include "usnic_ib_sysfs.h"
+#include "usnic_transport.h"
+
+const char *usnic_ib_qp_grp_state_to_string(enum ib_qp_state state)
+{
+       switch (state) {
+       case IB_QPS_RESET:
+               return "Rst";
+       case IB_QPS_INIT:
+               return "Init";
+       case IB_QPS_RTR:
+               return "RTR";
+       case IB_QPS_RTS:
+               return "RTS";
+       case IB_QPS_SQD:
+               return "SQD";
+       case IB_QPS_SQE:
+               return "SQE";
+       case IB_QPS_ERR:
+               return "ERR";
+       default:
+               return "UNKOWN STATE";
+
+       }
+}
+
+int usnic_ib_qp_grp_dump_hdr(char *buf, int buf_sz)
+{
+       return scnprintf(buf, buf_sz, "|QPN\t|State\t|PID\t|VF Idx\t|Fil ID");
+}
+
+int usnic_ib_qp_grp_dump_rows(void *obj, char *buf, int buf_sz)
+{
+       struct usnic_ib_qp_grp *qp_grp = obj;
+       struct usnic_fwd_filter_hndl *default_filter_hndl;
+       if (obj) {
+               default_filter_hndl = list_first_entry(&qp_grp->filter_hndls,
+                                       struct usnic_fwd_filter_hndl, link);
+               return scnprintf(buf, buf_sz, "|%d\t|%s\t|%d\t|%hu\t|%d",
+                                       qp_grp->ibqp.qp_num,
+                                       usnic_ib_qp_grp_state_to_string(
+                                                       qp_grp->state),
+                                       qp_grp->owner_pid,
+                                       usnic_vnic_get_index(qp_grp->vf->vnic),
+                                       default_filter_hndl->id);
+       } else {
+               return scnprintf(buf, buf_sz, "|N/A\t|N/A\t|N/A\t|N/A\t|N/A");
+       }
+}
+
+static int add_fwd_filter(struct usnic_ib_qp_grp *qp_grp,
+                               struct usnic_fwd_filter *fwd_filter)
+{
+       struct usnic_fwd_filter_hndl *filter_hndl;
+       int status;
+       struct usnic_vnic_res_chunk *chunk;
+       int rq_idx;
+
+       BUG_ON(!spin_is_locked(&qp_grp->lock));
+
+       chunk = usnic_ib_qp_grp_get_chunk(qp_grp, USNIC_VNIC_RES_TYPE_RQ);
+       if (IS_ERR_OR_NULL(chunk) || chunk->cnt < 1) {
+               usnic_err("Failed to get RQ info for qp_grp %u\n",
+                               qp_grp->grp_id);
+               return -EFAULT;
+       }
+
+       rq_idx = chunk->res[0]->vnic_idx;
+
+       switch (qp_grp->transport) {
+       case USNIC_TRANSPORT_ROCE_CUSTOM:
+               status = usnic_fwd_add_usnic_filter(qp_grp->ufdev,
+                                       usnic_vnic_get_index(qp_grp->vf->vnic),
+                                       rq_idx,
+                                       fwd_filter,
+                                       &filter_hndl);
+               break;
+       default:
+               usnic_err("Unable to install filter for qp_grp %u for transport %d",
+                               qp_grp->grp_id, qp_grp->transport);
+               status = -EINVAL;
+       }
+
+       if (status)
+               return status;
+
+       list_add_tail(&filter_hndl->link, &qp_grp->filter_hndls);
+       return 0;
+}
+
+static int del_all_filters(struct usnic_ib_qp_grp *qp_grp)
+{
+       int err, status;
+       struct usnic_fwd_filter_hndl *filter_hndl, *tmp;
+
+       BUG_ON(!spin_is_locked(&qp_grp->lock));
+
+       status = 0;
+
+       list_for_each_entry_safe(filter_hndl, tmp,
+                                       &qp_grp->filter_hndls, link) {
+               list_del(&filter_hndl->link);
+               err = usnic_fwd_del_filter(filter_hndl);
+               if (err) {
+                       usnic_err("Failed to delete filter %u of qp_grp %d\n",
+                                       filter_hndl->id, qp_grp->grp_id);
+               }
+               status |= err;
+       }
+
+       return status;
+}
+
+static int enable_qp_grp(struct usnic_ib_qp_grp *qp_grp)
+{
+
+       int status;
+       int i, vnic_idx;
+       struct usnic_vnic_res_chunk *res_chunk;
+       struct usnic_vnic_res *res;
+
+       BUG_ON(!spin_is_locked(&qp_grp->lock));
+
+       vnic_idx = usnic_vnic_get_index(qp_grp->vf->vnic);
+
+       res_chunk = usnic_ib_qp_grp_get_chunk(qp_grp, USNIC_VNIC_RES_TYPE_RQ);
+       if (IS_ERR_OR_NULL(res_chunk)) {
+               usnic_err("Unable to get %s with err %ld\n",
+                       usnic_vnic_res_type_to_str(USNIC_VNIC_RES_TYPE_RQ),
+                       PTR_ERR(res_chunk));
+               return res_chunk ? PTR_ERR(res_chunk) : -ENOMEM;
+       }
+
+       for (i = 0; i < res_chunk->cnt; i++) {
+               res = res_chunk->res[i];
+               status = usnic_fwd_enable_rq(qp_grp->ufdev, vnic_idx,
+                                               res->vnic_idx);
+               if (status) {
+                       usnic_err("Failed to enable rq %d of %s:%d\n with err %d\n",
+                                       res->vnic_idx,
+                                       netdev_name(qp_grp->ufdev->netdev),
+                                       vnic_idx, status);
+                       goto out_err;
+               }
+       }
+
+       return 0;
+
+out_err:
+       for (i--; i >= 0; i--) {
+               res = res_chunk->res[i];
+               usnic_fwd_disable_rq(qp_grp->ufdev, vnic_idx,
+                                       res->vnic_idx);
+       }
+
+       return status;
+}
+
+static int disable_qp_grp(struct usnic_ib_qp_grp *qp_grp)
+{
+       int i, vnic_idx;
+       struct usnic_vnic_res_chunk *res_chunk;
+       struct usnic_vnic_res *res;
+       int status = 0;
+
+       BUG_ON(!spin_is_locked(&qp_grp->lock));
+       vnic_idx = usnic_vnic_get_index(qp_grp->vf->vnic);
+
+       res_chunk = usnic_ib_qp_grp_get_chunk(qp_grp, USNIC_VNIC_RES_TYPE_RQ);
+       if (IS_ERR_OR_NULL(res_chunk)) {
+               usnic_err("Unable to get %s with err %ld\n",
+                       usnic_vnic_res_type_to_str(USNIC_VNIC_RES_TYPE_RQ),
+                       PTR_ERR(res_chunk));
+               return res_chunk ? PTR_ERR(res_chunk) : -ENOMEM;
+       }
+
+       for (i = 0; i < res_chunk->cnt; i++) {
+               res = res_chunk->res[i];
+               status = usnic_fwd_disable_rq(qp_grp->ufdev, vnic_idx,
+                                               res->vnic_idx);
+               if (status) {
+                       usnic_err("Failed to disable rq %d of %s:%d\n with err %d\n",
+                                       res->vnic_idx,
+                                       netdev_name(qp_grp->ufdev->netdev),
+                                       vnic_idx, status);
+               }
+       }
+
+       return status;
+
+}
+
+int usnic_ib_qp_grp_modify(struct usnic_ib_qp_grp *qp_grp,
+                               enum ib_qp_state new_state,
+                               struct usnic_fwd_filter *fwd_filter)
+{
+       int status = 0;
+       int vnic_idx;
+       struct ib_event ib_event;
+       enum ib_qp_state old_state;
+
+       old_state = qp_grp->state;
+       vnic_idx = usnic_vnic_get_index(qp_grp->vf->vnic);
+
+       spin_lock(&qp_grp->lock);
+       switch (new_state) {
+       case IB_QPS_RESET:
+               switch (old_state) {
+               case IB_QPS_RESET:
+                       /* NO-OP */
+                       break;
+               case IB_QPS_INIT:
+                       status = del_all_filters(qp_grp);
+                       break;
+               case IB_QPS_RTR:
+               case IB_QPS_RTS:
+               case IB_QPS_ERR:
+                       status = disable_qp_grp(qp_grp);
+                       status &= del_all_filters(qp_grp);
+                       break;
+               default:
+                       status = -EINVAL;
+               }
+               break;
+       case IB_QPS_INIT:
+               switch (old_state) {
+               case IB_QPS_RESET:
+                       status = add_fwd_filter(qp_grp, fwd_filter);
+                       break;
+               case IB_QPS_INIT:
+                       status = add_fwd_filter(qp_grp, fwd_filter);
+                       break;
+               case IB_QPS_RTR:
+                       status = disable_qp_grp(qp_grp);
+                       break;
+               case IB_QPS_RTS:
+                       status = disable_qp_grp(qp_grp);
+                       break;
+               default:
+                       status = -EINVAL;
+               }
+               break;
+       case IB_QPS_RTR:
+               switch (old_state) {
+               case IB_QPS_INIT:
+                       status = enable_qp_grp(qp_grp);
+                       break;
+               default:
+                       status = -EINVAL;
+               }
+               break;
+       case IB_QPS_RTS:
+               switch (old_state) {
+               case IB_QPS_RTR:
+                       /* NO-OP FOR NOW */
+                       break;
+               default:
+                       status = -EINVAL;
+               }
+               break;
+       case IB_QPS_ERR:
+               ib_event.device = &qp_grp->vf->pf->ib_dev;
+               ib_event.element.qp = &qp_grp->ibqp;
+               ib_event.event = IB_EVENT_QP_FATAL;
+
+               switch (old_state) {
+               case IB_QPS_RESET:
+                       qp_grp->ibqp.event_handler(&ib_event,
+                                       qp_grp->ibqp.qp_context);
+                       break;
+               case IB_QPS_INIT:
+                       status = del_all_filters(qp_grp);
+                       qp_grp->ibqp.event_handler(&ib_event,
+                                       qp_grp->ibqp.qp_context);
+                       break;
+               case IB_QPS_RTR:
+               case IB_QPS_RTS:
+                       status = disable_qp_grp(qp_grp);
+                       status &= del_all_filters(qp_grp);
+                       qp_grp->ibqp.event_handler(&ib_event,
+                                       qp_grp->ibqp.qp_context);
+                       break;
+               default:
+                       status = -EINVAL;
+               }
+               break;
+       default:
+               status = -EINVAL;
+       }
+       spin_unlock(&qp_grp->lock);
+
+       if (!status) {
+               qp_grp->state = new_state;
+               usnic_info("Transistioned %u from %s to %s",
+               qp_grp->grp_id,
+               usnic_ib_qp_grp_state_to_string(old_state),
+               usnic_ib_qp_grp_state_to_string(new_state));
+       } else {
+               usnic_err("Failed to transistion %u from %s to %s",
+               qp_grp->grp_id,
+               usnic_ib_qp_grp_state_to_string(old_state),
+               usnic_ib_qp_grp_state_to_string(new_state));
+       }
+
+       return status;
+}
+
+struct usnic_vnic_res_chunk**
+alloc_res_chunk_list(struct usnic_vnic *vnic, const struct usnic_vnic_res_spec
+                       const *res_spec, void *owner_obj)
+{
+       enum usnic_vnic_res_type res_type;
+       struct usnic_vnic_res_chunk **res_chunk_list;
+       int err, i, res_cnt, res_lst_sz;
+
+       for (res_lst_sz = 0;
+               res_spec->resources[res_lst_sz].type != USNIC_VNIC_RES_TYPE_EOL;
+               res_lst_sz++) {
+               /* Do Nothing */
+       }
+
+       res_chunk_list = kzalloc(sizeof(*res_chunk_list)*(res_lst_sz+1),
+                                       GFP_KERNEL);
+       if (!res_chunk_list)
+               return ERR_PTR(-ENOMEM);
+
+       for (i = 0; res_spec->resources[i].type != USNIC_VNIC_RES_TYPE_EOL;
+               i++) {
+               res_type = res_spec->resources[i].type;
+               res_cnt = res_spec->resources[i].cnt;
+
+               res_chunk_list[i] = usnic_vnic_get_resources(vnic, res_type,
+                                       res_cnt, owner_obj);
+               if (IS_ERR_OR_NULL(res_chunk_list[i])) {
+                       err = (res_chunk_list[i] ?
+                                       PTR_ERR(res_chunk_list[i]) : -ENOMEM);
+                       usnic_err("Failed to get %s from %s with err %d\n",
+                               usnic_vnic_res_type_to_str(res_type),
+                               usnic_vnic_pci_name(vnic),
+                               err);
+                       goto out_free_res;
+               }
+       }
+
+       return res_chunk_list;
+
+out_free_res:
+       for (i--; i > 0; i--)
+               usnic_vnic_put_resources(res_chunk_list[i]);
+       kfree(res_chunk_list);
+       return ERR_PTR(err);
+}
+
+void free_qp_grp_res(struct usnic_vnic_res_chunk **res_chunk_list)
+{
+       int i;
+       for (i = 0; res_chunk_list[i]; i++)
+               usnic_vnic_put_resources(res_chunk_list[i]);
+       kfree(res_chunk_list);
+}
+
+static int qp_grp_and_vf_bind(struct usnic_ib_vf *vf,
+                               struct usnic_ib_pd *pd,
+                               struct usnic_ib_qp_grp *qp_grp)
+{
+       int err;
+       struct pci_dev *pdev;
+
+       BUG_ON(!spin_is_locked(&vf->lock));
+
+       pdev = usnic_vnic_get_pdev(vf->vnic);
+       if (vf->qp_grp_ref_cnt++ == 0) {
+               vf->pd = pd;
+               err = usnic_uiom_attach_dev_to_pd(pd->umem_pd, &pdev->dev);
+               if (err) {
+                       usnic_err("Failed to attach %s to domain\n",
+                                       pci_name(pdev));
+                       return err;
+               }
+       }
+
+       WARN_ON(vf->pd != pd);
+       qp_grp->vf = vf;
+
+       return 0;
+}
+
+static void qp_grp_and_vf_unbind(struct usnic_ib_qp_grp *qp_grp)
+{
+       struct pci_dev *pdev;
+       struct usnic_ib_pd *pd;
+
+       BUG_ON(!spin_is_locked(&qp_grp->vf->lock));
+
+       pd = qp_grp->vf->pd;
+       pdev = usnic_vnic_get_pdev(qp_grp->vf->vnic);
+       if (--qp_grp->vf->qp_grp_ref_cnt == 0) {
+               qp_grp->vf->pd = NULL;
+               usnic_uiom_detach_dev_from_pd(pd->umem_pd, &pdev->dev);
+       }
+       qp_grp->vf = NULL;
+}
+
+static void log_spec(const struct usnic_vnic_res_spec
+                                       const *res_spec)
+{
+       char buf[1024];
+       usnic_vnic_spec_dump(buf, sizeof(buf), res_spec);
+       usnic_dbg(buf);
+}
+
+struct usnic_ib_qp_grp *usnic_ib_qp_grp_create(struct usnic_fwd_dev *ufdev,
+                               struct usnic_ib_vf *vf,
+                               struct usnic_ib_pd *pd,
+                               const struct usnic_vnic_res_spec
+                               const *res_spec,
+                               enum usnic_transport_type transport)
+{
+       struct usnic_ib_qp_grp *qp_grp;
+       u16 port_num;
+       int err;
+
+       BUG_ON(!spin_is_locked(&vf->lock));
+
+       err = usnic_vnic_res_spec_satisfied(&min_transport_spec[transport],
+                                               res_spec);
+       if (err) {
+               usnic_err("Spec does not meet miniumum req for transport %d\n",
+                               transport);
+               log_spec(res_spec);
+               return ERR_PTR(err);
+       }
+
+       port_num = usnic_transport_rsrv_port(transport, 0);
+       if (!port_num) {
+               usnic_err("Unable to allocate port for %s\n",
+                               netdev_name(ufdev->netdev));
+               return ERR_PTR(-EINVAL);
+       }
+
+       qp_grp = kzalloc(sizeof(*qp_grp), GFP_KERNEL);
+       if (!qp_grp) {
+               usnic_err("Unable to alloc qp_grp - Out of memory\n");
+               return NULL;
+       }
+
+       qp_grp->res_chunk_list = alloc_res_chunk_list(vf->vnic, res_spec,
+                                                       qp_grp);
+       if (IS_ERR_OR_NULL(qp_grp->res_chunk_list)) {
+               err = qp_grp->res_chunk_list ?
+                               PTR_ERR(qp_grp->res_chunk_list) : -ENOMEM;
+               usnic_err("Unable to alloc res for %d with err %d\n",
+                               qp_grp->grp_id, err);
+               goto out_free_port;
+       }
+
+       INIT_LIST_HEAD(&qp_grp->filter_hndls);
+       spin_lock_init(&qp_grp->lock);
+       qp_grp->ufdev = ufdev;
+       qp_grp->transport = transport;
+       qp_grp->filters[DFLT_FILTER_IDX].transport = transport;
+       qp_grp->filters[DFLT_FILTER_IDX].port_num = port_num;
+       qp_grp->state = IB_QPS_RESET;
+       qp_grp->owner_pid = current->pid;
+
+       /* qp_num is same as default filter port_num */
+       qp_grp->ibqp.qp_num = qp_grp->filters[DFLT_FILTER_IDX].port_num;
+       qp_grp->grp_id = qp_grp->ibqp.qp_num;
+
+       err = qp_grp_and_vf_bind(vf, pd, qp_grp);
+       if (err)
+               goto out_free_port;
+
+       usnic_ib_sysfs_qpn_add(qp_grp);
+
+       return qp_grp;
+
+out_free_port:
+       kfree(qp_grp);
+       usnic_transport_unrsrv_port(transport, port_num);
+
+       return ERR_PTR(err);
+}
+
+void usnic_ib_qp_grp_destroy(struct usnic_ib_qp_grp *qp_grp)
+{
+       u16 default_port_num;
+       enum usnic_transport_type transport;
+
+       WARN_ON(qp_grp->state != IB_QPS_RESET);
+       BUG_ON(!spin_is_locked(&qp_grp->vf->lock));
+
+       transport = qp_grp->filters[DFLT_FILTER_IDX].transport;
+       default_port_num = qp_grp->filters[DFLT_FILTER_IDX].port_num;
+
+       usnic_ib_sysfs_qpn_remove(qp_grp);
+       qp_grp_and_vf_unbind(qp_grp);
+       free_qp_grp_res(qp_grp->res_chunk_list);
+       kfree(qp_grp);
+       usnic_transport_unrsrv_port(transport, default_port_num);
+}
+
+struct usnic_vnic_res_chunk*
+usnic_ib_qp_grp_get_chunk(struct usnic_ib_qp_grp *qp_grp,
+                               enum usnic_vnic_res_type res_type)
+{
+       int i;
+
+       for (i = 0; qp_grp->res_chunk_list[i]; i++) {
+               if (qp_grp->res_chunk_list[i]->type == res_type)
+                       return qp_grp->res_chunk_list[i];
+       }
+
+       return ERR_PTR(-EINVAL);
+}
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h
new file mode 100644 (file)
index 0000000..37423f8
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may 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.
+ *
+ * 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 USNIC_IB_QP_GRP_H_
+#define USNIC_IB_QP_GRP_H_
+
+#include <rdma/ib_verbs.h>
+
+#include "usnic_ib.h"
+#include "usnic_abi.h"
+#include "usnic_fwd.h"
+#include "usnic_vnic.h"
+
+#define MAX_QP_GRP_FILTERS     10
+#define DFLT_FILTER_IDX                0
+
+/*
+ * The qp group struct represents all the hw resources needed to present a ib_qp
+ */
+struct usnic_ib_qp_grp {
+       struct ib_qp                            ibqp;
+       enum ib_qp_state                        state;
+       int                                     grp_id;
+
+       struct usnic_fwd_dev                    *ufdev;
+       short unsigned                          filter_cnt;
+       struct usnic_fwd_filter                 filters[MAX_QP_GRP_FILTERS];
+       struct list_head                        filter_hndls;
+       enum usnic_transport_type               transport;
+       struct usnic_ib_ucontext                *ctx;
+
+       struct usnic_vnic_res_chunk             **res_chunk_list;
+
+       pid_t                                   owner_pid;
+       struct usnic_ib_vf                      *vf;
+       struct list_head                        link;
+
+       spinlock_t                              lock;
+
+       struct kobject                          kobj;
+};
+
+static const struct
+usnic_vnic_res_spec min_transport_spec[USNIC_TRANSPORT_MAX] = {
+       { /*USNIC_TRANSPORT_UNKNOWN*/
+               .resources = {
+                       {.type = USNIC_VNIC_RES_TYPE_EOL,       .cnt = 0,},
+               },
+       },
+       { /*USNIC_TRANSPORT_ROCE_CUSTOM*/
+               .resources = {
+                       {.type = USNIC_VNIC_RES_TYPE_WQ,        .cnt = 1,},
+                       {.type = USNIC_VNIC_RES_TYPE_RQ,        .cnt = 1,},
+                       {.type = USNIC_VNIC_RES_TYPE_CQ,        .cnt = 1,},
+                       {.type = USNIC_VNIC_RES_TYPE_EOL,       .cnt = 0,},
+               },
+       },
+};
+
+const char *usnic_ib_qp_grp_state_to_string(enum ib_qp_state state);
+int usnic_ib_qp_grp_dump_hdr(char *buf, int buf_sz);
+int usnic_ib_qp_grp_dump_rows(void *obj, char *buf, int buf_sz);
+struct usnic_ib_qp_grp *usnic_ib_qp_grp_create(struct usnic_fwd_dev *ufdev,
+                                               struct usnic_ib_vf *vf,
+                                               struct usnic_ib_pd *pd,
+                                               const struct usnic_vnic_res_spec
+                                               const *res_spec,
+                                               enum usnic_transport_type
+                                                       transport);
+void usnic_ib_qp_grp_destroy(struct usnic_ib_qp_grp *qp_grp);
+int usnic_ib_qp_grp_modify(struct usnic_ib_qp_grp *qp_grp,
+                               enum ib_qp_state new_state,
+                               struct usnic_fwd_filter *fwd_filter);
+struct usnic_vnic_res_chunk
+*usnic_ib_qp_grp_get_chunk(struct usnic_ib_qp_grp *qp_grp,
+                               enum usnic_vnic_res_type type);
+static inline
+struct usnic_ib_qp_grp *to_uqp_grp(struct ib_qp *ibqp)
+{
+       return container_of(ibqp, struct usnic_ib_qp_grp, ibqp);
+}
+#endif /* USNIC_IB_QP_GRP_H_ */
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c b/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c
new file mode 100644 (file)
index 0000000..e7925e4
--- /dev/null
@@ -0,0 +1,351 @@
+/*
+ * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may 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.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+
+#include <rdma/ib_user_verbs.h>
+#include <rdma/ib_addr.h>
+
+#include "usnic_common_util.h"
+#include "usnic_ib.h"
+#include "usnic_ib_qp_grp.h"
+#include "usnic_vnic.h"
+#include "usnic_ib_verbs.h"
+#include "usnic_log.h"
+
+#define UPDATE_PTR_LEFT(N, P, L)                       \
+do {                                                   \
+       L -= (N);                                       \
+       P += (N);                                       \
+} while (0)
+
+static ssize_t usnic_ib_show_fw_ver(struct device *device,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct usnic_ib_dev *us_ibdev =
+               container_of(device, struct usnic_ib_dev, ib_dev.dev);
+       struct ethtool_drvinfo info;
+
+       mutex_lock(&us_ibdev->usdev_lock);
+       us_ibdev->netdev->ethtool_ops->get_drvinfo(us_ibdev->netdev, &info);
+       mutex_unlock(&us_ibdev->usdev_lock);
+
+       return scnprintf(buf, PAGE_SIZE, "%s\n", info.fw_version);
+}
+
+static ssize_t usnic_ib_show_board(struct device *device,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct usnic_ib_dev *us_ibdev =
+               container_of(device, struct usnic_ib_dev, ib_dev.dev);
+       unsigned short subsystem_device_id;
+
+       mutex_lock(&us_ibdev->usdev_lock);
+       subsystem_device_id = us_ibdev->pdev->subsystem_device;
+       mutex_unlock(&us_ibdev->usdev_lock);
+
+       return scnprintf(buf, PAGE_SIZE, "%hu\n", subsystem_device_id);
+}
+
+/*
+ * Report the configuration for this PF
+ */
+static ssize_t
+usnic_ib_show_config(struct device *device, struct device_attribute *attr,
+                       char *buf)
+{
+       struct usnic_ib_dev *us_ibdev;
+       char *ptr;
+       unsigned left;
+       unsigned n;
+       enum usnic_vnic_res_type res_type;
+
+       us_ibdev = container_of(device, struct usnic_ib_dev, ib_dev.dev);
+
+       /* Buffer space limit is 1 page */
+       ptr = buf;
+       left = PAGE_SIZE;
+
+       mutex_lock(&us_ibdev->usdev_lock);
+       if (atomic_read(&us_ibdev->vf_cnt.refcount) > 0) {
+               char *busname;
+
+               /*
+                * bus name seems to come with annoying prefix.
+                * Remove it if it is predictable
+                */
+               busname = us_ibdev->pdev->bus->name;
+               if (strncmp(busname, "PCI Bus ", 8) == 0)
+                       busname += 8;
+
+               n = scnprintf(ptr, left,
+                       "%s: %s:%d.%d, %s, %pM, %u VFs\n Per VF:",
+                       us_ibdev->ib_dev.name,
+                       busname,
+                       PCI_SLOT(us_ibdev->pdev->devfn),
+                       PCI_FUNC(us_ibdev->pdev->devfn),
+                       netdev_name(us_ibdev->netdev),
+                       us_ibdev->mac,
+                       atomic_read(&us_ibdev->vf_cnt.refcount));
+               UPDATE_PTR_LEFT(n, ptr, left);
+
+               for (res_type = USNIC_VNIC_RES_TYPE_EOL;
+                               res_type < USNIC_VNIC_RES_TYPE_MAX;
+                               res_type++) {
+                       if (us_ibdev->vf_res_cnt[res_type] == 0)
+                               continue;
+                       n = scnprintf(ptr, left, " %d %s%s",
+                               us_ibdev->vf_res_cnt[res_type],
+                               usnic_vnic_res_type_to_str(res_type),
+                               (res_type < (USNIC_VNIC_RES_TYPE_MAX - 1)) ?
+                                "," : "");
+                       UPDATE_PTR_LEFT(n, ptr, left);
+               }
+               n = scnprintf(ptr, left, "\n");
+               UPDATE_PTR_LEFT(n, ptr, left);
+       } else {
+               n = scnprintf(ptr, left, "%s: no VFs\n",
+                               us_ibdev->ib_dev.name);
+               UPDATE_PTR_LEFT(n, ptr, left);
+       }
+       mutex_unlock(&us_ibdev->usdev_lock);
+
+       return ptr - buf;
+}
+
+static ssize_t
+usnic_ib_show_iface(struct device *device, struct device_attribute *attr,
+                       char *buf)
+{
+       struct usnic_ib_dev *us_ibdev;
+
+       us_ibdev = container_of(device, struct usnic_ib_dev, ib_dev.dev);
+
+       return scnprintf(buf, PAGE_SIZE, "%s\n",
+                       netdev_name(us_ibdev->netdev));
+}
+
+static ssize_t
+usnic_ib_show_max_vf(struct device *device, struct device_attribute *attr,
+                       char *buf)
+{
+       struct usnic_ib_dev *us_ibdev;
+
+       us_ibdev = container_of(device, struct usnic_ib_dev, ib_dev.dev);
+
+       return scnprintf(buf, PAGE_SIZE, "%u\n",
+                       atomic_read(&us_ibdev->vf_cnt.refcount));
+}
+
+static ssize_t
+usnic_ib_show_qp_per_vf(struct device *device, struct device_attribute *attr,
+                       char *buf)
+{
+       struct usnic_ib_dev *us_ibdev;
+       int qp_per_vf;
+
+       us_ibdev = container_of(device, struct usnic_ib_dev, ib_dev.dev);
+       qp_per_vf = max(us_ibdev->vf_res_cnt[USNIC_VNIC_RES_TYPE_WQ],
+                       us_ibdev->vf_res_cnt[USNIC_VNIC_RES_TYPE_RQ]);
+
+       return scnprintf(buf, PAGE_SIZE,
+                               "%d\n", qp_per_vf);
+}
+
+static ssize_t
+usnic_ib_show_cq_per_vf(struct device *device, struct device_attribute *attr,
+                       char *buf)
+{
+       struct usnic_ib_dev *us_ibdev;
+
+       us_ibdev = container_of(device, struct usnic_ib_dev, ib_dev.dev);
+
+       return scnprintf(buf, PAGE_SIZE, "%d\n",
+                       us_ibdev->vf_res_cnt[USNIC_VNIC_RES_TYPE_CQ]);
+}
+
+static DEVICE_ATTR(fw_ver, S_IRUGO, usnic_ib_show_fw_ver, NULL);
+static DEVICE_ATTR(board_id, S_IRUGO, usnic_ib_show_board, NULL);
+static DEVICE_ATTR(config, S_IRUGO, usnic_ib_show_config, NULL);
+static DEVICE_ATTR(iface, S_IRUGO, usnic_ib_show_iface, NULL);
+static DEVICE_ATTR(max_vf, S_IRUGO, usnic_ib_show_max_vf, NULL);
+static DEVICE_ATTR(qp_per_vf, S_IRUGO, usnic_ib_show_qp_per_vf, NULL);
+static DEVICE_ATTR(cq_per_vf, S_IRUGO, usnic_ib_show_cq_per_vf, NULL);
+
+static struct device_attribute *usnic_class_attributes[] = {
+       &dev_attr_fw_ver,
+       &dev_attr_board_id,
+       &dev_attr_config,
+       &dev_attr_iface,
+       &dev_attr_max_vf,
+       &dev_attr_qp_per_vf,
+       &dev_attr_cq_per_vf,
+};
+
+struct qpn_attribute {
+       struct attribute attr;
+       ssize_t (*show)(struct usnic_ib_qp_grp *, char *buf);
+};
+
+/*
+ * Definitions for supporting QPN entries in sysfs
+ */
+static ssize_t
+usnic_ib_qpn_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
+{
+       struct usnic_ib_qp_grp *qp_grp;
+       struct qpn_attribute *qpn_attr;
+
+       qp_grp = container_of(kobj, struct usnic_ib_qp_grp, kobj);
+       qpn_attr = container_of(attr, struct qpn_attribute, attr);
+
+       return qpn_attr->show(qp_grp, buf);
+}
+
+static const struct sysfs_ops usnic_ib_qpn_sysfs_ops = {
+       .show = usnic_ib_qpn_attr_show
+};
+
+#define QPN_ATTR_RO(NAME) \
+struct qpn_attribute qpn_attr_##NAME = __ATTR_RO(NAME)
+
+static ssize_t context_show(struct usnic_ib_qp_grp *qp_grp, char *buf)
+{
+       return scnprintf(buf, PAGE_SIZE, "0x%p\n", qp_grp->ctx);
+}
+
+static ssize_t summary_show(struct usnic_ib_qp_grp *qp_grp, char *buf)
+{
+       int i, j, n;
+       int left;
+       char *ptr;
+       struct usnic_vnic_res_chunk *res_chunk;
+       struct usnic_fwd_filter_hndl *default_filter_hndl;
+       struct usnic_vnic_res *vnic_res;
+
+       left = PAGE_SIZE;
+       ptr = buf;
+       default_filter_hndl = list_first_entry(&qp_grp->filter_hndls,
+                                       struct usnic_fwd_filter_hndl, link);
+
+       n = scnprintf(ptr, left,
+                       "QPN: %d State: (%s) PID: %u VF Idx: %hu Filter ID: 0x%x ",
+                       qp_grp->ibqp.qp_num,
+                       usnic_ib_qp_grp_state_to_string(qp_grp->state),
+                       qp_grp->owner_pid,
+                       usnic_vnic_get_index(qp_grp->vf->vnic),
+                       default_filter_hndl->id);
+       UPDATE_PTR_LEFT(n, ptr, left);
+
+       for (i = 0; qp_grp->res_chunk_list[i]; i++) {
+               res_chunk = qp_grp->res_chunk_list[i];
+               for (j = 0; j < res_chunk->cnt; j++) {
+                       vnic_res = res_chunk->res[j];
+                       n = scnprintf(ptr, left, "%s[%d] ",
+                               usnic_vnic_res_type_to_str(vnic_res->type),
+                               vnic_res->vnic_idx);
+                       UPDATE_PTR_LEFT(n, ptr, left);
+               }
+       }
+
+       n = scnprintf(ptr, left, "\n");
+       UPDATE_PTR_LEFT(n, ptr, left);
+
+       return ptr - buf;
+}
+
+static QPN_ATTR_RO(context);
+static QPN_ATTR_RO(summary);
+
+static struct attribute *usnic_ib_qpn_default_attrs[] = {
+       &qpn_attr_context.attr,
+       &qpn_attr_summary.attr,
+       NULL
+};
+
+struct kobj_type usnic_ib_qpn_type = {
+       .sysfs_ops = &usnic_ib_qpn_sysfs_ops,
+       .default_attrs = usnic_ib_qpn_default_attrs
+};
+
+int usnic_ib_sysfs_register_usdev(struct usnic_ib_dev *us_ibdev)
+{
+       int i;
+       int err;
+       for (i = 0; i < ARRAY_SIZE(usnic_class_attributes); ++i) {
+               err = device_create_file(&us_ibdev->ib_dev.dev,
+                                               usnic_class_attributes[i]);
+               if (err) {
+                       usnic_err("Failed to create device file %d for %s eith err %d",
+                               i, us_ibdev->ib_dev.name, err);
+                       return -EINVAL;
+               }
+       }
+
+       /* create kernel object for looking at individual QPs */
+       kobject_get(&us_ibdev->ib_dev.dev.kobj);
+       us_ibdev->qpn_kobj = kobject_create_and_add("qpn",
+                       &us_ibdev->ib_dev.dev.kobj);
+       if (us_ibdev->qpn_kobj == NULL) {
+               kobject_put(&us_ibdev->ib_dev.dev.kobj);
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+void usnic_ib_sysfs_unregister_usdev(struct usnic_ib_dev *us_ibdev)
+{
+       int i;
+       for (i = 0; i < ARRAY_SIZE(usnic_class_attributes); ++i) {
+               device_remove_file(&us_ibdev->ib_dev.dev,
+                                       usnic_class_attributes[i]);
+       }
+
+       kobject_put(us_ibdev->qpn_kobj);
+}
+
+void usnic_ib_sysfs_qpn_add(struct usnic_ib_qp_grp *qp_grp)
+{
+       struct usnic_ib_dev *us_ibdev;
+       int err;
+
+       us_ibdev = qp_grp->vf->pf;
+
+       err = kobject_init_and_add(&qp_grp->kobj, &usnic_ib_qpn_type,
+                       kobject_get(us_ibdev->qpn_kobj),
+                       "%d", qp_grp->grp_id);
+       if (err) {
+               kobject_put(us_ibdev->qpn_kobj);
+               return;
+       }
+}
+
+void usnic_ib_sysfs_qpn_remove(struct usnic_ib_qp_grp *qp_grp)
+{
+       struct usnic_ib_dev *us_ibdev;
+
+       us_ibdev = qp_grp->vf->pf;
+
+       kobject_put(&qp_grp->kobj);
+       kobject_put(us_ibdev->qpn_kobj);
+}
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_sysfs.h b/drivers/infiniband/hw/usnic/usnic_ib_sysfs.h
new file mode 100644 (file)
index 0000000..0d09b49
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may 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.
+ *
+ * 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 USNIC_IB_SYSFS_H_
+#define USNIC_IB_SYSFS_H_
+
+#include "usnic_ib.h"
+
+int usnic_ib_sysfs_register_usdev(struct usnic_ib_dev *us_ibdev);
+void usnic_ib_sysfs_unregister_usdev(struct usnic_ib_dev *us_ibdev);
+void usnic_ib_sysfs_qpn_add(struct usnic_ib_qp_grp *qp_grp);
+void usnic_ib_sysfs_qpn_remove(struct usnic_ib_qp_grp *qp_grp);
+
+#endif /* !USNIC_IB_SYSFS_H_ */
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_verbs.c b/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
new file mode 100644 (file)
index 0000000..d305e4e
--- /dev/null
@@ -0,0 +1,734 @@
+/*
+ * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may 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.
+ *
+ * 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.
+ *
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+
+#include <rdma/ib_user_verbs.h>
+#include <rdma/ib_addr.h>
+
+#include "usnic_abi.h"
+#include "usnic_ib.h"
+#include "usnic_common_util.h"
+#include "usnic_ib_qp_grp.h"
+#include "usnic_fwd.h"
+#include "usnic_log.h"
+#include "usnic_uiom.h"
+#include "usnic_transport.h"
+
+#define USNIC_DEFAULT_TRANSPORT USNIC_TRANSPORT_ROCE_CUSTOM
+
+static void usnic_ib_fw_string_to_u64(char *fw_ver_str, u64 *fw_ver)
+{
+       *fw_ver = (u64) *fw_ver_str;
+}
+
+static int usnic_ib_fill_create_qp_resp(struct usnic_ib_qp_grp *qp_grp,
+                                       struct ib_udata *udata)
+{
+       struct usnic_ib_dev *us_ibdev;
+       struct usnic_ib_create_qp_resp resp;
+       struct pci_dev *pdev;
+       struct vnic_dev_bar *bar;
+       struct usnic_vnic_res_chunk *chunk;
+       int i, err;
+
+       us_ibdev = qp_grp->vf->pf;
+       pdev = usnic_vnic_get_pdev(qp_grp->vf->vnic);
+       if (!pdev) {
+               usnic_err("Failed to get pdev of qp_grp %d\n",
+                               qp_grp->grp_id);
+               return -EFAULT;
+       }
+
+       bar = usnic_vnic_get_bar(qp_grp->vf->vnic, 0);
+       if (!bar) {
+               usnic_err("Failed to get bar0 of qp_grp %d vf %s",
+                               qp_grp->grp_id, pci_name(pdev));
+               return -EFAULT;
+       }
+
+       resp.vfid = usnic_vnic_get_index(qp_grp->vf->vnic);
+       resp.bar_bus_addr = bar->bus_addr;
+       resp.bar_len = bar->len;
+       resp.transport = qp_grp->transport;
+
+       chunk = usnic_ib_qp_grp_get_chunk(qp_grp, USNIC_VNIC_RES_TYPE_RQ);
+       if (IS_ERR_OR_NULL(chunk)) {
+               usnic_err("Failed to get chunk %s for qp_grp %d with err %ld\n",
+                       usnic_vnic_res_type_to_str(USNIC_VNIC_RES_TYPE_RQ),
+                       qp_grp->grp_id,
+                       PTR_ERR(chunk));
+               return chunk ? PTR_ERR(chunk) : -ENOMEM;
+       }
+
+       WARN_ON(chunk->type != USNIC_VNIC_RES_TYPE_RQ);
+       resp.rq_cnt = chunk->cnt;
+       for (i = 0; i < chunk->cnt; i++)
+               resp.rq_idx[i] = chunk->res[i]->vnic_idx;
+
+       chunk = usnic_ib_qp_grp_get_chunk(qp_grp, USNIC_VNIC_RES_TYPE_WQ);
+       if (IS_ERR_OR_NULL(chunk)) {
+               usnic_err("Failed to get chunk %s for qp_grp %d with err %ld\n",
+                       usnic_vnic_res_type_to_str(USNIC_VNIC_RES_TYPE_WQ),
+                       qp_grp->grp_id,
+                       PTR_ERR(chunk));
+               return chunk ? PTR_ERR(chunk) : -ENOMEM;
+       }
+
+       WARN_ON(chunk->type != USNIC_VNIC_RES_TYPE_WQ);
+       resp.wq_cnt = chunk->cnt;
+       for (i = 0; i < chunk->cnt; i++)
+               resp.wq_idx[i] = chunk->res[i]->vnic_idx;
+
+       chunk = usnic_ib_qp_grp_get_chunk(qp_grp, USNIC_VNIC_RES_TYPE_CQ);
+       if (IS_ERR_OR_NULL(chunk)) {
+               usnic_err("Failed to get chunk %s for qp_grp %d with err %ld\n",
+                       usnic_vnic_res_type_to_str(USNIC_VNIC_RES_TYPE_CQ),
+                       qp_grp->grp_id,
+                       PTR_ERR(chunk));
+               return chunk ? PTR_ERR(chunk) : -ENOMEM;
+       }
+
+       WARN_ON(chunk->type != USNIC_VNIC_RES_TYPE_CQ);
+       resp.cq_cnt = chunk->cnt;
+       for (i = 0; i < chunk->cnt; i++)
+               resp.cq_idx[i] = chunk->res[i]->vnic_idx;
+
+       err = ib_copy_to_udata(udata, &resp, sizeof(resp));
+       if (err) {
+               usnic_err("Failed to copy udata for %s", us_ibdev->ib_dev.name);
+               return err;
+       }
+
+       return 0;
+}
+
+static struct usnic_ib_qp_grp*
+find_free_vf_and_create_qp_grp(struct usnic_ib_dev *us_ibdev,
+                               struct usnic_ib_pd *pd,
+                               enum usnic_transport_type transport,
+                               struct usnic_vnic_res_spec *res_spec)
+{
+       struct usnic_ib_vf *vf;
+       struct usnic_vnic *vnic;
+       struct usnic_ib_qp_grp *qp_grp;
+       struct device *dev, **dev_list;
+       int i, found = 0;
+
+       BUG_ON(!mutex_is_locked(&us_ibdev->usdev_lock));
+
+       if (list_empty(&us_ibdev->vf_dev_list)) {
+               usnic_info("No vfs to allocate\n");
+               return NULL;
+       }
+
+       if (!us_ibdev->link_up) {
+               usnic_info("Cannot allocate qp b/c PF link is down\n");
+               return NULL;
+       }
+
+       if (usnic_ib_share_vf) {
+               /* Try to find resouces on a used vf which is in pd */
+               dev_list = usnic_uiom_get_dev_list(pd->umem_pd);
+               for (i = 0; dev_list[i]; i++) {
+                       dev = dev_list[i];
+                       vf = pci_get_drvdata(to_pci_dev(dev));
+                       spin_lock(&vf->lock);
+                       vnic = vf->vnic;
+                       if (!usnic_vnic_check_room(vnic, res_spec)) {
+                               usnic_dbg("Found used vnic %s from %s\n",
+                                               us_ibdev->ib_dev.name,
+                                               pci_name(usnic_vnic_get_pdev(
+                                                                       vnic)));
+                               found = 1;
+                               break;
+                       }
+                       spin_unlock(&vf->lock);
+
+               }
+               usnic_uiom_free_dev_list(dev_list);
+       }
+
+       if (!found) {
+               /* Try to find resources on an unused vf */
+               list_for_each_entry(vf, &us_ibdev->vf_dev_list, link) {
+                       spin_lock(&vf->lock);
+                       vnic = vf->vnic;
+                       if (vf->qp_grp_ref_cnt == 0 &&
+                               usnic_vnic_check_room(vnic, res_spec) == 0) {
+                               found = 1;
+                               break;
+                       }
+                       spin_unlock(&vf->lock);
+               }
+       }
+
+       if (!found) {
+               usnic_info("No free qp grp found on %s\n",
+                               us_ibdev->ib_dev.name);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       qp_grp = usnic_ib_qp_grp_create(us_ibdev->ufdev, vf, pd, res_spec,
+                                               transport);
+       spin_unlock(&vf->lock);
+       if (IS_ERR_OR_NULL(qp_grp)) {
+               usnic_err("Failed to allocate qp_grp\n");
+               return ERR_PTR(qp_grp ? PTR_ERR(qp_grp) : -ENOMEM);
+       }
+
+       return qp_grp;
+}
+
+static void qp_grp_destroy(struct usnic_ib_qp_grp *qp_grp)
+{
+       struct usnic_ib_vf *vf = qp_grp->vf;
+
+       WARN_ON(qp_grp->state != IB_QPS_RESET);
+
+       spin_lock(&vf->lock);
+       usnic_ib_qp_grp_destroy(qp_grp);
+       spin_unlock(&vf->lock);
+}
+
+static void eth_speed_to_ib_speed(int speed, u8 *active_speed,
+                                       u8 *active_width)
+{
+       if (speed <= 10000) {
+               *active_width = IB_WIDTH_1X;
+               *active_speed = IB_SPEED_FDR10;
+       } else if (speed <= 20000) {
+               *active_width = IB_WIDTH_4X;
+               *active_speed = IB_SPEED_DDR;
+       } else if (speed <= 30000) {
+               *active_width = IB_WIDTH_4X;
+               *active_speed = IB_SPEED_QDR;
+       } else if (speed <= 40000) {
+               *active_width = IB_WIDTH_4X;
+               *active_speed = IB_SPEED_FDR10;
+       } else {
+               *active_width = IB_WIDTH_4X;
+               *active_speed = IB_SPEED_EDR;
+       }
+}
+
+/* Start of ib callback functions */
+
+enum rdma_link_layer usnic_ib_port_link_layer(struct ib_device *device,
+                                               u8 port_num)
+{
+       return IB_LINK_LAYER_ETHERNET;
+}
+
+int usnic_ib_query_device(struct ib_device *ibdev,
+                               struct ib_device_attr *props)
+{
+       struct usnic_ib_dev *us_ibdev = to_usdev(ibdev);
+       union ib_gid gid;
+       struct ethtool_drvinfo info;
+       struct ethtool_cmd cmd;
+       int qp_per_vf;
+
+       usnic_dbg("\n");
+       mutex_lock(&us_ibdev->usdev_lock);
+       us_ibdev->netdev->ethtool_ops->get_drvinfo(us_ibdev->netdev, &info);
+       us_ibdev->netdev->ethtool_ops->get_settings(us_ibdev->netdev, &cmd);
+       memset(props, 0, sizeof(*props));
+       usnic_mac_to_gid(us_ibdev->mac, &gid.raw[0]);
+       memcpy(&props->sys_image_guid, &gid.global.interface_id,
+               sizeof(gid.global.interface_id));
+       usnic_ib_fw_string_to_u64(&info.fw_version[0], &props->fw_ver);
+       props->max_mr_size = USNIC_UIOM_MAX_MR_SIZE;
+       props->page_size_cap = USNIC_UIOM_PAGE_SIZE;
+       props->vendor_id = PCI_VENDOR_ID_CISCO;
+       props->vendor_part_id = PCI_DEVICE_ID_CISCO_VIC_USPACE_NIC;
+       props->hw_ver = us_ibdev->pdev->subsystem_device;
+       qp_per_vf = max(us_ibdev->vf_res_cnt[USNIC_VNIC_RES_TYPE_WQ],
+                       us_ibdev->vf_res_cnt[USNIC_VNIC_RES_TYPE_RQ]);
+       props->max_qp = qp_per_vf *
+               atomic_read(&us_ibdev->vf_cnt.refcount);
+       props->device_cap_flags = IB_DEVICE_PORT_ACTIVE_EVENT |
+               IB_DEVICE_SYS_IMAGE_GUID | IB_DEVICE_BLOCK_MULTICAST_LOOPBACK;
+       props->max_cq = us_ibdev->vf_res_cnt[USNIC_VNIC_RES_TYPE_CQ] *
+               atomic_read(&us_ibdev->vf_cnt.refcount);
+       props->max_pd = USNIC_UIOM_MAX_PD_CNT;
+       props->max_mr = USNIC_UIOM_MAX_MR_CNT;
+       props->local_ca_ack_delay = 0;
+       props->max_pkeys = 0;
+       props->atomic_cap = IB_ATOMIC_NONE;
+       props->masked_atomic_cap = props->atomic_cap;
+       props->max_qp_rd_atom = 0;
+       props->max_qp_init_rd_atom = 0;
+       props->max_res_rd_atom = 0;
+       props->max_srq = 0;
+       props->max_srq_wr = 0;
+       props->max_srq_sge = 0;
+       props->max_fast_reg_page_list_len = 0;
+       props->max_mcast_grp = 0;
+       props->max_mcast_qp_attach = 0;
+       props->max_total_mcast_qp_attach = 0;
+       props->max_map_per_fmr = 0;
+       /* Owned by Userspace
+        * max_qp_wr, max_sge, max_sge_rd, max_cqe */
+       mutex_unlock(&us_ibdev->usdev_lock);
+
+       return 0;
+}
+
+int usnic_ib_query_port(struct ib_device *ibdev, u8 port,
+                               struct ib_port_attr *props)
+{
+       struct usnic_ib_dev *us_ibdev = to_usdev(ibdev);
+       struct ethtool_cmd cmd;
+
+       usnic_dbg("\n");
+
+       mutex_lock(&us_ibdev->usdev_lock);
+       us_ibdev->netdev->ethtool_ops->get_settings(us_ibdev->netdev, &cmd);
+       memset(props, 0, sizeof(*props));
+
+       props->lid = 0;
+       props->lmc = 1;
+       props->sm_lid = 0;
+       props->sm_sl = 0;
+
+       if (us_ibdev->link_up) {
+               props->state = IB_PORT_ACTIVE;
+               props->phys_state = 5;
+       } else {
+               props->state = IB_PORT_DOWN;
+               props->phys_state = 3;
+       }
+
+       props->port_cap_flags = 0;
+       props->gid_tbl_len = 1;
+       props->pkey_tbl_len = 1;
+       props->bad_pkey_cntr = 0;
+       props->qkey_viol_cntr = 0;
+       eth_speed_to_ib_speed(cmd.speed, &props->active_speed,
+                               &props->active_width);
+       props->max_mtu = IB_MTU_4096;
+       props->active_mtu = iboe_get_mtu(us_ibdev->mtu);
+       /* Userspace will adjust for hdrs */
+       props->max_msg_sz = us_ibdev->mtu;
+       props->max_vl_num = 1;
+       mutex_unlock(&us_ibdev->usdev_lock);
+
+       return 0;
+}
+
+int usnic_ib_query_qp(struct ib_qp *qp, struct ib_qp_attr *qp_attr,
+                               int qp_attr_mask,
+                               struct ib_qp_init_attr *qp_init_attr)
+{
+       struct usnic_ib_qp_grp *qp_grp;
+       struct usnic_ib_vf *vf;
+       int err;
+
+       usnic_dbg("\n");
+
+       memset(qp_attr, 0, sizeof(*qp_attr));
+       memset(qp_init_attr, 0, sizeof(*qp_init_attr));
+
+       qp_grp = to_uqp_grp(qp);
+       vf = qp_grp->vf;
+       mutex_lock(&vf->pf->usdev_lock);
+       usnic_dbg("\n");
+       qp_attr->qp_state = qp_grp->state;
+       qp_attr->cur_qp_state = qp_grp->state;
+
+       switch (qp_grp->ibqp.qp_type) {
+       case IB_QPT_UD:
+               qp_attr->qkey = 0;
+               break;
+       default:
+               usnic_err("Unexpected qp_type %d\n", qp_grp->ibqp.qp_type);
+               err = -EINVAL;
+               goto err_out;
+       }
+
+       mutex_unlock(&vf->pf->usdev_lock);
+       return 0;
+
+err_out:
+       mutex_unlock(&vf->pf->usdev_lock);
+       return err;
+}
+
+int usnic_ib_query_gid(struct ib_device *ibdev, u8 port, int index,
+                               union ib_gid *gid)
+{
+
+       struct usnic_ib_dev *us_ibdev = to_usdev(ibdev);
+       usnic_dbg("\n");
+
+       if (index > 1)
+               return -EINVAL;
+
+       mutex_lock(&us_ibdev->usdev_lock);
+       memset(&(gid->raw[0]), 0, sizeof(gid->raw));
+       usnic_mac_to_gid(us_ibdev->mac, &gid->raw[0]);
+       mutex_unlock(&us_ibdev->usdev_lock);
+
+       return 0;
+}
+
+int usnic_ib_query_pkey(struct ib_device *ibdev, u8 port, u16 index,
+                               u16 *pkey)
+{
+       if (index > 1)
+               return -EINVAL;
+
+       *pkey = 0xffff;
+       return 0;
+}
+
+struct ib_pd *usnic_ib_alloc_pd(struct ib_device *ibdev,
+                                       struct ib_ucontext *context,
+                                       struct ib_udata *udata)
+{
+       struct usnic_ib_pd *pd;
+       void *umem_pd;
+
+       usnic_dbg("\n");
+
+       pd = kzalloc(sizeof(*pd), GFP_KERNEL);
+       if (!pd)
+               return ERR_PTR(-ENOMEM);
+
+       umem_pd = pd->umem_pd = usnic_uiom_alloc_pd();
+       if (IS_ERR_OR_NULL(umem_pd)) {
+               kfree(pd);
+               return ERR_PTR(umem_pd ? PTR_ERR(umem_pd) : -ENOMEM);
+       }
+
+       usnic_info("domain 0x%p allocated for context 0x%p and device %s\n",
+                       pd, context, ibdev->name);
+       return &pd->ibpd;
+}
+
+int usnic_ib_dealloc_pd(struct ib_pd *pd)
+{
+       usnic_info("freeing domain 0x%p\n", pd);
+
+       usnic_uiom_dealloc_pd((to_upd(pd))->umem_pd);
+       kfree(pd);
+       return 0;
+}
+
+struct ib_qp *usnic_ib_create_qp(struct ib_pd *pd,
+                                       struct ib_qp_init_attr *init_attr,
+                                       struct ib_udata *udata)
+{
+       int err;
+       struct usnic_ib_dev *us_ibdev;
+       struct usnic_ib_qp_grp *qp_grp;
+       struct usnic_ib_ucontext *ucontext;
+       int cq_cnt;
+       struct usnic_vnic_res_spec res_spec;
+
+       usnic_dbg("\n");
+
+       ucontext = to_uucontext(pd->uobject->context);
+       us_ibdev = to_usdev(pd->device);
+
+       if (init_attr->qp_type != IB_QPT_UD) {
+               usnic_err("%s asked to make a non-UD QP: %d\n",
+                               us_ibdev->ib_dev.name, init_attr->qp_type);
+               return ERR_PTR(-EINVAL);
+       }
+
+       mutex_lock(&us_ibdev->usdev_lock);
+       cq_cnt = (init_attr->send_cq == init_attr->recv_cq) ? 1 : 2,
+       res_spec = min_transport_spec[USNIC_DEFAULT_TRANSPORT];
+       usnic_vnic_res_spec_update(&res_spec, USNIC_VNIC_RES_TYPE_CQ, cq_cnt);
+       qp_grp = find_free_vf_and_create_qp_grp(us_ibdev, to_upd(pd),
+                                               USNIC_DEFAULT_TRANSPORT,
+                                               &res_spec);
+       if (IS_ERR_OR_NULL(qp_grp)) {
+               err = (qp_grp ? PTR_ERR(qp_grp) : -ENOMEM);
+               goto out_release_mutex;
+       }
+
+       err = usnic_ib_fill_create_qp_resp(qp_grp, udata);
+       if (err) {
+               err = -EBUSY;
+               goto out_release_qp_grp;
+       }
+
+       qp_grp->ctx = ucontext;
+       list_add_tail(&qp_grp->link, &ucontext->qp_grp_list);
+       usnic_ib_log_vf(qp_grp->vf);
+       mutex_unlock(&us_ibdev->usdev_lock);
+       return &qp_grp->ibqp;
+
+out_release_qp_grp:
+       qp_grp_destroy(qp_grp);
+out_release_mutex:
+       mutex_unlock(&us_ibdev->usdev_lock);
+       return ERR_PTR(err);
+}
+
+int usnic_ib_destroy_qp(struct ib_qp *qp)
+{
+       struct usnic_ib_qp_grp *qp_grp;
+       struct usnic_ib_vf *vf;
+
+       usnic_dbg("\n");
+
+       qp_grp = to_uqp_grp(qp);
+       vf = qp_grp->vf;
+       mutex_lock(&vf->pf->usdev_lock);
+       if (usnic_ib_qp_grp_modify(qp_grp, IB_QPS_RESET, NULL)) {
+               usnic_err("Failed to move qp grp %u to reset\n",
+                               qp_grp->grp_id);
+       }
+
+       list_del(&qp_grp->link);
+       qp_grp_destroy(qp_grp);
+       mutex_unlock(&vf->pf->usdev_lock);
+
+       return 0;
+}
+
+int usnic_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+                               int attr_mask, struct ib_udata *udata)
+{
+       struct usnic_ib_qp_grp *qp_grp;
+       int status;
+       usnic_dbg("\n");
+
+       qp_grp = to_uqp_grp(ibqp);
+
+       /* TODO: Future Support All States */
+       mutex_lock(&qp_grp->vf->pf->usdev_lock);
+       if ((attr_mask & IB_QP_STATE) && attr->qp_state == IB_QPS_INIT) {
+               status = usnic_ib_qp_grp_modify(qp_grp, IB_QPS_INIT,
+                                       &qp_grp->filters[DFLT_FILTER_IDX]);
+       } else if ((attr_mask & IB_QP_STATE) && attr->qp_state == IB_QPS_RTR) {
+               status = usnic_ib_qp_grp_modify(qp_grp, IB_QPS_RTR, NULL);
+       } else if ((attr_mask & IB_QP_STATE) && attr->qp_state == IB_QPS_RTS) {
+               status = usnic_ib_qp_grp_modify(qp_grp, IB_QPS_RTS, NULL);
+       } else {
+               usnic_err("Unexpected combination mask: %u state: %u\n",
+                               attr_mask & IB_QP_STATE, attr->qp_state);
+               status = -EINVAL;
+       }
+
+       mutex_unlock(&qp_grp->vf->pf->usdev_lock);
+       return status;
+}
+
+struct ib_cq *usnic_ib_create_cq(struct ib_device *ibdev, int entries,
+                                       int vector, struct ib_ucontext *context,
+                                       struct ib_udata *udata)
+{
+       struct ib_cq *cq;
+
+       usnic_dbg("\n");
+       cq = kzalloc(sizeof(*cq), GFP_KERNEL);
+       if (!cq)
+               return ERR_PTR(-EBUSY);
+
+       return cq;
+}
+
+int usnic_ib_destroy_cq(struct ib_cq *cq)
+{
+       usnic_dbg("\n");
+       kfree(cq);
+       return 0;
+}
+
+struct ib_mr *usnic_ib_reg_mr(struct ib_pd *pd, u64 start, u64 length,
+                                       u64 virt_addr, int access_flags,
+                                       struct ib_udata *udata)
+{
+       struct usnic_ib_mr *mr;
+       int err;
+
+       usnic_dbg("start 0x%llx va 0x%llx length 0x%llx\n", start,
+                       virt_addr, length);
+
+       mr = kzalloc(sizeof(*mr), GFP_KERNEL);
+       if (IS_ERR_OR_NULL(mr))
+               return ERR_PTR(mr ? PTR_ERR(mr) : -ENOMEM);
+
+       mr->umem = usnic_uiom_reg_get(to_upd(pd)->umem_pd, start, length,
+                                       access_flags, 0);
+       if (IS_ERR_OR_NULL(mr->umem)) {
+               err = PTR_ERR(mr->umem);
+               goto err_free;
+       }
+
+       mr->ibmr.lkey = mr->ibmr.rkey = 0;
+       return &mr->ibmr;
+
+err_free:
+       kfree(mr);
+       return ERR_PTR(err);
+}
+
+int usnic_ib_dereg_mr(struct ib_mr *ibmr)
+{
+       struct usnic_ib_mr *mr = to_umr(ibmr);
+
+       usnic_dbg("va 0x%lx length 0x%lx\n", mr->umem->va, mr->umem->length);
+
+       usnic_uiom_reg_release(mr->umem, ibmr->pd->uobject->context->closing);
+       kfree(mr);
+       return 0;
+}
+
+struct ib_ucontext *usnic_ib_alloc_ucontext(struct ib_device *ibdev,
+                                                       struct ib_udata *udata)
+{
+       struct usnic_ib_ucontext *context;
+       struct usnic_ib_dev *us_ibdev = to_usdev(ibdev);
+       usnic_dbg("\n");
+
+       context = kmalloc(sizeof(*context), GFP_KERNEL);
+       if (!context)
+               return ERR_PTR(-ENOMEM);
+
+       INIT_LIST_HEAD(&context->qp_grp_list);
+       mutex_lock(&us_ibdev->usdev_lock);
+       list_add_tail(&context->link, &us_ibdev->ctx_list);
+       mutex_unlock(&us_ibdev->usdev_lock);
+
+       return &context->ibucontext;
+}
+
+int usnic_ib_dealloc_ucontext(struct ib_ucontext *ibcontext)
+{
+       struct usnic_ib_ucontext *context = to_uucontext(ibcontext);
+       struct usnic_ib_dev *us_ibdev = to_usdev(ibcontext->device);
+       usnic_dbg("\n");
+
+       mutex_lock(&us_ibdev->usdev_lock);
+       BUG_ON(!list_empty(&context->qp_grp_list));
+       list_del(&context->link);
+       mutex_unlock(&us_ibdev->usdev_lock);
+       kfree(context);
+       return 0;
+}
+
+int usnic_ib_mmap(struct ib_ucontext *context,
+                               struct vm_area_struct *vma)
+{
+       struct usnic_ib_ucontext *uctx = to_ucontext(context);
+       struct usnic_ib_dev *us_ibdev;
+       struct usnic_ib_qp_grp *qp_grp;
+       struct usnic_ib_vf *vf;
+       struct vnic_dev_bar *bar;
+       dma_addr_t bus_addr;
+       unsigned int len;
+       unsigned int vfid;
+
+       usnic_dbg("\n");
+
+       us_ibdev = to_usdev(context->device);
+       vma->vm_flags |= VM_IO;
+       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+       vfid = vma->vm_pgoff;
+       usnic_dbg("Page Offset %lu PAGE_SHIFT %u VFID %u\n",
+                       vma->vm_pgoff, PAGE_SHIFT, vfid);
+
+       mutex_lock(&us_ibdev->usdev_lock);
+       list_for_each_entry(qp_grp, &uctx->qp_grp_list, link) {
+               vf = qp_grp->vf;
+               if (usnic_vnic_get_index(vf->vnic) == vfid) {
+                       bar = usnic_vnic_get_bar(vf->vnic, 0);
+                       if ((vma->vm_end - vma->vm_start) != bar->len) {
+                               usnic_err("Bar0 Len %lu - Request map %lu\n",
+                                               bar->len,
+                                               vma->vm_end - vma->vm_start);
+                               mutex_unlock(&us_ibdev->usdev_lock);
+                               return -EINVAL;
+                       }
+                       bus_addr = bar->bus_addr;
+                       len = bar->len;
+                       usnic_dbg("bus: 0x%llx vaddr: %p size: %ld\n",
+                                       bus_addr, bar->vaddr, bar->len);
+                       mutex_unlock(&us_ibdev->usdev_lock);
+
+                       return remap_pfn_range(vma,
+                                               vma->vm_start,
+                                               bus_addr >> PAGE_SHIFT,
+                                               len, vma->vm_page_prot);
+               }
+       }
+
+       mutex_unlock(&us_ibdev->usdev_lock);
+       usnic_err("No VF %u found\n", vfid);
+       return -EINVAL;
+}
+
+/* In ib callbacks section -  Start of stub funcs */
+struct ib_ah *usnic_ib_create_ah(struct ib_pd *pd,
+                                       struct ib_ah_attr *ah_attr)
+{
+       usnic_dbg("\n");
+       return ERR_PTR(-EPERM);
+}
+
+int usnic_ib_destroy_ah(struct ib_ah *ah)
+{
+       usnic_dbg("\n");
+       return -EINVAL;
+}
+
+int usnic_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+                               struct ib_send_wr **bad_wr)
+{
+       usnic_dbg("\n");
+       return -EINVAL;
+}
+
+int usnic_ib_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
+                               struct ib_recv_wr **bad_wr)
+{
+       usnic_dbg("\n");
+       return -EINVAL;
+}
+
+int usnic_ib_poll_cq(struct ib_cq *ibcq, int num_entries,
+                               struct ib_wc *wc)
+{
+       usnic_dbg("\n");
+       return -EINVAL;
+}
+
+int usnic_ib_req_notify_cq(struct ib_cq *cq,
+                                       enum ib_cq_notify_flags flags)
+{
+       usnic_dbg("\n");
+       return -EINVAL;
+}
+
+struct ib_mr *usnic_ib_get_dma_mr(struct ib_pd *pd, int acc)
+{
+       usnic_dbg("\n");
+       return ERR_PTR(-ENOMEM);
+}
+
+
+/* In ib callbacks section - End of stub funcs */
+/* End of ib callbacks section */
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_verbs.h b/drivers/infiniband/hw/usnic/usnic_ib_verbs.h
new file mode 100644 (file)
index 0000000..bb864f5
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may 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.
+ *
+ * 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 USNIC_IB_VERBS_H_
+#define USNIC_IB_VERBS_H_
+
+#include "usnic_ib.h"
+
+enum rdma_link_layer usnic_ib_port_link_layer(struct ib_device *device,
+                                               u8 port_num);
+int usnic_ib_query_device(struct ib_device *ibdev,
+                               struct ib_device_attr *props);
+int usnic_ib_query_port(struct ib_device *ibdev, u8 port,
+                               struct ib_port_attr *props);
+int usnic_ib_query_qp(struct ib_qp *qp, struct ib_qp_attr *qp_attr,
+                               int qp_attr_mask,
+                               struct ib_qp_init_attr *qp_init_attr);
+int usnic_ib_query_gid(struct ib_device *ibdev, u8 port, int index,
+                               union ib_gid *gid);
+int usnic_ib_query_pkey(struct ib_device *ibdev, u8 port, u16 index,
+                               u16 *pkey);
+struct ib_pd *usnic_ib_alloc_pd(struct ib_device *ibdev,
+                               struct ib_ucontext *context,
+                               struct ib_udata *udata);
+int usnic_ib_dealloc_pd(struct ib_pd *pd);
+struct ib_qp *usnic_ib_create_qp(struct ib_pd *pd,
+                                       struct ib_qp_init_attr *init_attr,
+                                       struct ib_udata *udata);
+int usnic_ib_destroy_qp(struct ib_qp *qp);
+int usnic_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+                               int attr_mask, struct ib_udata *udata);
+struct ib_cq *usnic_ib_create_cq(struct ib_device *ibdev, int entries,
+                                       int vector, struct ib_ucontext *context,
+                                       struct ib_udata *udata);
+int usnic_ib_destroy_cq(struct ib_cq *cq);
+struct ib_mr *usnic_ib_reg_mr(struct ib_pd *pd, u64 start, u64 length,
+                               u64 virt_addr, int access_flags,
+                               struct ib_udata *udata);
+int usnic_ib_dereg_mr(struct ib_mr *ibmr);
+struct ib_ucontext *usnic_ib_alloc_ucontext(struct ib_device *ibdev,
+                                               struct ib_udata *udata);
+int usnic_ib_dealloc_ucontext(struct ib_ucontext *ibcontext);
+int usnic_ib_mmap(struct ib_ucontext *context,
+                       struct vm_area_struct *vma);
+struct ib_ah *usnic_ib_create_ah(struct ib_pd *pd,
+                                       struct ib_ah_attr *ah_attr);
+int usnic_ib_destroy_ah(struct ib_ah *ah);
+int usnic_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+                       struct ib_send_wr **bad_wr);
+int usnic_ib_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
+                       struct ib_recv_wr **bad_wr);
+int usnic_ib_poll_cq(struct ib_cq *ibcq, int num_entries,
+                       struct ib_wc *wc);
+int usnic_ib_req_notify_cq(struct ib_cq *cq,
+                               enum ib_cq_notify_flags flags);
+struct ib_mr *usnic_ib_get_dma_mr(struct ib_pd *pd, int acc);
+#endif /* !USNIC_IB_VERBS_H */
diff --git a/drivers/infiniband/hw/usnic/usnic_log.h b/drivers/infiniband/hw/usnic/usnic_log.h
new file mode 100644 (file)
index 0000000..75777a6
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may 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.
+ *
+ * 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 USNIC_LOG_H_
+#define USNIC_LOG_H_
+
+#include "usnic.h"
+
+extern unsigned int usnic_log_lvl;
+
+#define USNIC_LOG_LVL_NONE             (0)
+#define USNIC_LOG_LVL_ERR              (1)
+#define USNIC_LOG_LVL_INFO             (2)
+#define USNIC_LOG_LVL_DBG              (3)
+
+#define usnic_printk(lvl, args...) \
+       do { \
+               printk(lvl "%s:%s:%d: ", DRV_NAME, __func__, \
+                               __LINE__); \
+               printk(args); \
+       } while (0)
+
+#define usnic_dbg(args...) \
+       do { \
+               if (unlikely(usnic_log_lvl >= USNIC_LOG_LVL_DBG)) { \
+                       usnic_printk(KERN_INFO, args); \
+       } \
+} while (0)
+
+#define usnic_info(args...) \
+do { \
+       if (usnic_log_lvl >= USNIC_LOG_LVL_INFO) { \
+                       usnic_printk(KERN_INFO, args); \
+       } \
+} while (0)
+
+#define usnic_err(args...) \
+       do { \
+               if (usnic_log_lvl >= USNIC_LOG_LVL_ERR) { \
+                       usnic_printk(KERN_ERR, args); \
+               } \
+       } while (0)
+#endif /* !USNIC_LOG_H_ */
diff --git a/drivers/infiniband/hw/usnic/usnic_transport.c b/drivers/infiniband/hw/usnic/usnic_transport.c
new file mode 100644 (file)
index 0000000..6f3d245
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may 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.
+ *
+ * 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.
+ *
+ */
+#include <linux/bitmap.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "usnic_transport.h"
+#include "usnic_log.h"
+
+/* ROCE */
+static unsigned long *roce_bitmap;
+static u16 roce_next_port = 1;
+#define ROCE_BITMAP_SZ ((1 << (8 /*CHAR_BIT*/ * sizeof(u16)))/8 /*CHAR BIT*/)
+DEFINE_SPINLOCK(roce_bitmap_lock);
+
+static const char *transport_to_str(enum usnic_transport_type type)
+{
+       switch (type) {
+       case USNIC_TRANSPORT_UNKNOWN:
+               return "Unknown";
+       case USNIC_TRANSPORT_ROCE_CUSTOM:
+               return "roce custom";
+       case USNIC_TRANSPORT_MAX:
+               return "Max?";
+       default:
+               return "Not known";
+       }
+}
+
+/*
+ * reserve a port number.  if "0" specified, we will try to pick one
+ * starting at roce_next_port.  roce_next_port will take on the values
+ * 1..4096
+ */
+u16 usnic_transport_rsrv_port(enum usnic_transport_type type, u16 port_num)
+{
+       if (type == USNIC_TRANSPORT_ROCE_CUSTOM) {
+               spin_lock(&roce_bitmap_lock);
+               if (!port_num) {
+                       port_num = bitmap_find_next_zero_area(roce_bitmap,
+                                               ROCE_BITMAP_SZ,
+                                               roce_next_port /* start */,
+                                               1 /* nr */,
+                                               0 /* align */);
+                       roce_next_port = (port_num & 4095) + 1;
+               } else if (test_bit(port_num, roce_bitmap)) {
+                       usnic_err("Failed to allocate port for %s\n",
+                                       transport_to_str(type));
+                       spin_unlock(&roce_bitmap_lock);
+                       goto out_fail;
+               }
+               bitmap_set(roce_bitmap, port_num, 1);
+               spin_unlock(&roce_bitmap_lock);
+       } else {
+               usnic_err("Failed to allocate port - transport %s unsupported\n",
+                               transport_to_str(type));
+               goto out_fail;
+       }
+
+       usnic_dbg("Allocating port %hu for %s\n", port_num,
+                       transport_to_str(type));
+       return port_num;
+
+out_fail:
+       return 0;
+}
+
+void usnic_transport_unrsrv_port(enum usnic_transport_type type, u16 port_num)
+{
+       if (type == USNIC_TRANSPORT_ROCE_CUSTOM) {
+               spin_lock(&roce_bitmap_lock);
+               if (!port_num) {
+                       usnic_err("Unreserved unvalid port num 0 for %s\n",
+                                       transport_to_str(type));
+                       goto out_roce_custom;
+               }
+
+               if (!test_bit(port_num, roce_bitmap)) {
+                       usnic_err("Unreserving invalid %hu for %s\n",
+                                       port_num,
+                                       transport_to_str(type));
+                       goto out_roce_custom;
+               }
+               bitmap_clear(roce_bitmap, port_num, 1);
+               usnic_dbg("Freeing port %hu for %s\n", port_num,
+                               transport_to_str(type));
+out_roce_custom:
+               spin_unlock(&roce_bitmap_lock);
+       } else {
+               usnic_err("Freeing invalid port %hu for %d\n", port_num, type);
+       }
+}
+
+int usnic_transport_init()
+{
+       roce_bitmap = kzalloc(ROCE_BITMAP_SZ, GFP_KERNEL);
+       if (!roce_bitmap) {
+               usnic_err("Failed to allocate bit map");
+               return -ENOMEM;
+       }
+
+       /* Do not ever allocate bit 0, hence set it here */
+       bitmap_set(roce_bitmap, 0, 1);
+       return 0;
+}
+
+void usnic_transport_fini(void)
+{
+       kfree(roce_bitmap);
+}
diff --git a/drivers/infiniband/hw/usnic/usnic_transport.h b/drivers/infiniband/hw/usnic/usnic_transport.h
new file mode 100644 (file)
index 0000000..e4c924e
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may 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.
+ *
+ * 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 USNIC_TRANSPORT_H_
+#define USNIC_TRANSPORT_H_
+
+#include "usnic_abi.h"
+
+u16 usnic_transport_rsrv_port(enum usnic_transport_type type, u16 port_num);
+void usnic_transport_unrsrv_port(enum usnic_transport_type type, u16 port_num);
+int usnic_transport_init(void);
+#endif /* !USNIC_TRANSPORT_H */
diff --git a/drivers/infiniband/hw/usnic/usnic_uiom.c b/drivers/infiniband/hw/usnic/usnic_uiom.c
new file mode 100644 (file)
index 0000000..c44acbc
--- /dev/null
@@ -0,0 +1,599 @@
+/*
+ * Copyright (c) 2005 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2013 Cisco Systems.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * 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.
+ */
+
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/sched.h>
+#include <linux/hugetlb.h>
+#include <linux/dma-attrs.h>
+#include <linux/iommu.h>
+#include <linux/workqueue.h>
+#include <linux/list.h>
+#include <linux/pci.h>
+
+#include "usnic_log.h"
+#include "usnic_uiom.h"
+#include "usnic_uiom_interval_tree.h"
+
+struct workqueue_struct *usnic_uiom_wq;
+
+#define USNIC_UIOM_PAGE_CHUNK                                          \
+       ((PAGE_SIZE - offsetof(struct usnic_uiom_chunk, page_list))     /\
+       ((void *) &((struct usnic_uiom_chunk *) 0)->page_list[1] -      \
+       (void *) &((struct usnic_uiom_chunk *) 0)->page_list[0]))
+
+static void usnic_uiom_reg_account(struct work_struct *work)
+{
+       struct usnic_uiom_reg *umem = container_of(work,
+                                               struct usnic_uiom_reg, work);
+
+       down_write(&umem->mm->mmap_sem);
+       umem->mm->locked_vm -= umem->diff;
+       up_write(&umem->mm->mmap_sem);
+       mmput(umem->mm);
+       kfree(umem);
+}
+
+static int usnic_uiom_dma_fault(struct iommu_domain *domain,
+                               struct device *dev,
+                               unsigned long iova, int flags,
+                               void *token)
+{
+       usnic_err("Device %s iommu fault domain 0x%pK va 0x%lx flags 0x%x\n",
+               dev_name(dev),
+               domain, iova, flags);
+       return -ENOSYS;
+}
+
+static void usnic_uiom_put_pages(struct list_head *chunk_list, int dirty)
+{
+       struct usnic_uiom_chunk *chunk, *tmp;
+       struct page *page;
+       int i;
+
+       list_for_each_entry_safe(chunk, tmp, chunk_list, list) {
+               for (i = 0; i < chunk->nents; i++) {
+                       page = sg_page(&chunk->page_list[i]);
+                       if (dirty)
+                               set_page_dirty_lock(page);
+                       put_page(page);
+                       usnic_dbg("pa: 0x%llx\n",
+                                       sg_phys(&chunk->page_list[i]));
+               }
+               kfree(chunk);
+       }
+}
+
+static int usnic_uiom_get_pages(unsigned long addr, size_t size, int writable,
+                               int dmasync, struct list_head *chunk_list)
+{
+       struct page **page_list;
+       struct usnic_uiom_chunk *chunk;
+       unsigned long locked;
+       unsigned long lock_limit;
+       unsigned long cur_base;
+       unsigned long npages;
+       int ret;
+       int off;
+       int i;
+       int flags;
+       DEFINE_DMA_ATTRS(attrs);
+
+       if (dmasync)
+               dma_set_attr(DMA_ATTR_WRITE_BARRIER, &attrs);
+
+       if (!can_do_mlock())
+               return -EPERM;
+
+       INIT_LIST_HEAD(chunk_list);
+
+       page_list = (struct page **) __get_free_page(GFP_KERNEL);
+       if (!page_list)
+               return -ENOMEM;
+
+       npages = PAGE_ALIGN(size + (addr & ~PAGE_MASK)) >> PAGE_SHIFT;
+
+       down_write(&current->mm->mmap_sem);
+
+       locked = npages + current->mm->locked_vm;
+       lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
+
+       if ((locked > lock_limit) && !capable(CAP_IPC_LOCK)) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       flags = IOMMU_READ | IOMMU_CACHE;
+       flags |= (writable) ? IOMMU_WRITE : 0;
+       cur_base = addr & PAGE_MASK;
+       ret = 0;
+
+       while (npages) {
+               ret = get_user_pages(current, current->mm, cur_base,
+                                       min_t(unsigned long, npages,
+                                       PAGE_SIZE / sizeof(struct page *)),
+                                       1, !writable, page_list, NULL);
+
+               if (ret < 0)
+                       goto out;
+
+               npages -= ret;
+               off = 0;
+
+               while (ret) {
+                       chunk = kmalloc(sizeof(*chunk) +
+                                       sizeof(struct scatterlist) *
+                                       min_t(int, ret, USNIC_UIOM_PAGE_CHUNK),
+                                       GFP_KERNEL);
+                       if (!chunk) {
+                               ret = -ENOMEM;
+                               goto out;
+                       }
+
+                       chunk->nents = min_t(int, ret, USNIC_UIOM_PAGE_CHUNK);
+                       sg_init_table(chunk->page_list, chunk->nents);
+                       for (i = 0; i < chunk->nents; ++i) {
+                               sg_set_page(&chunk->page_list[i],
+                                                       page_list[i + off],
+                                                       PAGE_SIZE, 0);
+                               usnic_dbg("va: 0x%lx pa: 0x%llx\n",
+                                               cur_base + i*PAGE_SIZE,
+                                               sg_phys(&chunk->page_list[i]));
+                       }
+                       cur_base += chunk->nents * PAGE_SIZE;
+                       ret -= chunk->nents;
+                       off += chunk->nents;
+                       list_add_tail(&chunk->list, chunk_list);
+               }
+
+               ret = 0;
+       }
+
+out:
+       if (ret < 0)
+               usnic_uiom_put_pages(chunk_list, 0);
+       else
+               current->mm->locked_vm = locked;
+
+       up_write(&current->mm->mmap_sem);
+       free_page((unsigned long) page_list);
+       return ret;
+}
+
+static void usnic_uiom_unmap_sorted_intervals(struct list_head *intervals,
+                                               struct usnic_uiom_pd *pd)
+{
+       struct usnic_uiom_interval_node *interval, *tmp;
+       long unsigned va, size;
+
+       list_for_each_entry_safe(interval, tmp, intervals, link) {
+               va = interval->start << PAGE_SHIFT;
+               size = ((interval->last - interval->start) + 1) << PAGE_SHIFT;
+               while (size > 0) {
+                       /* Workaround for RH 970401 */
+                       usnic_dbg("va 0x%lx size 0x%lx", va, PAGE_SIZE);
+                       iommu_unmap(pd->domain, va, PAGE_SIZE);
+                       va += PAGE_SIZE;
+                       size -= PAGE_SIZE;
+               }
+       }
+}
+
+static void __usnic_uiom_reg_release(struct usnic_uiom_pd *pd,
+                                       struct usnic_uiom_reg *uiomr,
+                                       int dirty)
+{
+       int npages;
+       unsigned long vpn_start, vpn_last;
+       struct usnic_uiom_interval_node *interval, *tmp;
+       int writable = 0;
+       LIST_HEAD(rm_intervals);
+
+       npages = PAGE_ALIGN(uiomr->length + uiomr->offset) >> PAGE_SHIFT;
+       vpn_start = (uiomr->va & PAGE_MASK) >> PAGE_SHIFT;
+       vpn_last = vpn_start + npages - 1;
+
+       spin_lock(&pd->lock);
+       usnic_uiom_remove_interval(&pd->rb_root, vpn_start,
+                                       vpn_last, &rm_intervals);
+       usnic_uiom_unmap_sorted_intervals(&rm_intervals, pd);
+
+       list_for_each_entry_safe(interval, tmp, &rm_intervals, link) {
+               if (interval->flags & IOMMU_WRITE)
+                       writable = 1;
+               list_del(&interval->link);
+               kfree(interval);
+       }
+
+       usnic_uiom_put_pages(&uiomr->chunk_list, dirty & writable);
+       spin_unlock(&pd->lock);
+}
+
+static int usnic_uiom_map_sorted_intervals(struct list_head *intervals,
+                                               struct usnic_uiom_reg *uiomr)
+{
+       int i, err;
+       size_t size;
+       struct usnic_uiom_chunk *chunk;
+       struct usnic_uiom_interval_node *interval_node;
+       long int pa, pa_start, pa_end;
+       long int va_start = -EINVAL;
+       struct usnic_uiom_pd *pd = uiomr->pd;
+       long int va = uiomr->va & PAGE_MASK;
+       int flags = IOMMU_READ | IOMMU_CACHE;
+
+       flags |= (uiomr->writable) ? IOMMU_WRITE : 0;
+       chunk = list_first_entry(&uiomr->chunk_list, struct usnic_uiom_chunk,
+                                                                       list);
+       list_for_each_entry(interval_node, intervals, link) {
+iter_chunk:
+               for (i = 0; i < chunk->nents; i++, va += PAGE_SIZE) {
+                       pa = sg_phys(&chunk->page_list[i]);
+                       if ((va >> PAGE_SHIFT) < interval_node->start)
+                               continue;
+
+                       if ((va >> PAGE_SHIFT) == interval_node->start) {
+                               /* First page of the interval */
+                               va_start = va;
+                               pa_start = pa;
+                               pa_end = pa;
+                       }
+
+                       BUG_ON(va_start == -EINVAL);
+
+                       if ((pa_end + PAGE_SIZE != pa) &&
+                                       (pa != pa_start)) {
+                               /* PAs are not contiguous */
+                               size = pa_end - pa_start + PAGE_SIZE;
+                               usnic_dbg("va 0x%lx pa 0x%lx size 0x%lx flags 0x%x",
+                                       va_start, pa_start, size, flags);
+                               err = iommu_map(pd->domain, va_start, pa_start,
+                                                       size, flags);
+                               if (err) {
+                                       usnic_err("Failed to map va 0x%lx pa 0x%lx size 0x%zx with err %d\n",
+                                               va_start, pa_start, size, err);
+                                       goto err_out;
+                               }
+                               va_start = va;
+                               pa_start = pa;
+                               pa_end = pa;
+                       }
+
+                       if ((va >> PAGE_SHIFT) == interval_node->last) {
+                               /* Last page of the interval */
+                               size = pa - pa_start + PAGE_SIZE;
+                               usnic_dbg("va 0x%lx pa 0x%lx size 0x%lx flags 0x%x\n",
+                                       va_start, pa_start, size, flags);
+                               err = iommu_map(pd->domain, va_start, pa_start,
+                                               size, flags);
+                               if (err) {
+                                       usnic_err("Failed to map va 0x%lx pa 0x%lx size 0x%zx with err %d\n",
+                                               va_start, pa_start, size, err);
+                                       goto err_out;
+                               }
+                               break;
+                       }
+
+                       if (pa != pa_start)
+                               pa_end += PAGE_SIZE;
+               }
+
+               if (i == chunk->nents) {
+                       /*
+                        * Hit last entry of the chunk,
+                        * hence advance to next chunk
+                        */
+                       chunk = list_first_entry(&chunk->list,
+                                                       struct usnic_uiom_chunk,
+                                                       list);
+                       goto iter_chunk;
+               }
+       }
+
+       return 0;
+
+err_out:
+       usnic_uiom_unmap_sorted_intervals(intervals, pd);
+       return err;
+}
+
+struct usnic_uiom_reg *usnic_uiom_reg_get(struct usnic_uiom_pd *pd,
+                                               unsigned long addr, size_t size,
+                                               int writable, int dmasync)
+{
+       struct usnic_uiom_reg *uiomr;
+       unsigned long va_base, vpn_start, vpn_last;
+       unsigned long npages;
+       int offset, err;
+       LIST_HEAD(sorted_diff_intervals);
+
+       /*
+        * Intel IOMMU map throws an error if a translation entry is
+        * changed from read to write.  This module may not unmap
+        * and then remap the entry after fixing the permission
+        * b/c this open up a small windows where hw DMA may page fault
+        * Hence, make all entries to be writable.
+        */
+       writable = 1;
+
+       va_base = addr & PAGE_MASK;
+       offset = addr & ~PAGE_MASK;
+       npages = PAGE_ALIGN(size + offset) >> PAGE_SHIFT;
+       vpn_start = (addr & PAGE_MASK) >> PAGE_SHIFT;
+       vpn_last = vpn_start + npages - 1;
+
+       uiomr = kmalloc(sizeof(*uiomr), GFP_KERNEL);
+       if (!uiomr)
+               return ERR_PTR(-ENOMEM);
+
+       uiomr->va = va_base;
+       uiomr->offset = offset;
+       uiomr->length = size;
+       uiomr->writable = writable;
+       uiomr->pd = pd;
+
+       err = usnic_uiom_get_pages(addr, size, writable, dmasync,
+                                       &uiomr->chunk_list);
+       if (err) {
+               usnic_err("Failed get_pages vpn [0x%lx,0x%lx] err %d\n",
+                               vpn_start, vpn_last, err);
+               goto out_free_uiomr;
+       }
+
+       spin_lock(&pd->lock);
+       err = usnic_uiom_get_intervals_diff(vpn_start, vpn_last,
+                                               (writable) ? IOMMU_WRITE : 0,
+                                               IOMMU_WRITE,
+                                               &pd->rb_root,
+                                               &sorted_diff_intervals);
+       if (err) {
+               usnic_err("Failed disjoint interval vpn [0x%lx,0x%lx] err %d\n",
+                                               vpn_start, vpn_last, err);
+               goto out_put_pages;
+       }
+
+       err = usnic_uiom_map_sorted_intervals(&sorted_diff_intervals, uiomr);
+       if (err) {
+               usnic_err("Failed map interval vpn [0x%lx,0x%lx] err %d\n",
+                                               vpn_start, vpn_last, err);
+               goto out_put_intervals;
+
+       }
+
+       err = usnic_uiom_insert_interval(&pd->rb_root, vpn_start, vpn_last,
+                                       (writable) ? IOMMU_WRITE : 0);
+       if (err) {
+               usnic_err("Failed insert interval vpn [0x%lx,0x%lx] err %d\n",
+                                               vpn_start, vpn_last, err);
+               goto out_unmap_intervals;
+       }
+
+       usnic_uiom_put_interval_set(&sorted_diff_intervals);
+       spin_unlock(&pd->lock);
+
+       return uiomr;
+
+out_unmap_intervals:
+       usnic_uiom_unmap_sorted_intervals(&sorted_diff_intervals, pd);
+out_put_intervals:
+       usnic_uiom_put_interval_set(&sorted_diff_intervals);
+out_put_pages:
+       usnic_uiom_put_pages(&uiomr->chunk_list, 0);
+       spin_unlock(&pd->lock);
+out_free_uiomr:
+       kfree(uiomr);
+       return ERR_PTR(err);
+}
+
+void usnic_uiom_reg_release(struct usnic_uiom_reg *uiomr, int closing)
+{
+       struct mm_struct *mm;
+       unsigned long diff;
+
+       __usnic_uiom_reg_release(uiomr->pd, uiomr, 1);
+
+       mm = get_task_mm(current);
+       if (!mm) {
+               kfree(uiomr);
+               return;
+       }
+
+       diff = PAGE_ALIGN(uiomr->length + uiomr->offset) >> PAGE_SHIFT;
+
+       /*
+        * We may be called with the mm's mmap_sem already held.  This
+        * can happen when a userspace munmap() is the call that drops
+        * the last reference to our file and calls our release
+        * method.  If there are memory regions to destroy, we'll end
+        * up here and not be able to take the mmap_sem.  In that case
+        * we defer the vm_locked accounting to the system workqueue.
+        */
+       if (closing) {
+               if (!down_write_trylock(&mm->mmap_sem)) {
+                       INIT_WORK(&uiomr->work, usnic_uiom_reg_account);
+                       uiomr->mm = mm;
+                       uiomr->diff = diff;
+
+                       queue_work(usnic_uiom_wq, &uiomr->work);
+                       return;
+               }
+       } else
+               down_write(&mm->mmap_sem);
+
+       current->mm->locked_vm -= diff;
+       up_write(&mm->mmap_sem);
+       mmput(mm);
+       kfree(uiomr);
+}
+
+struct usnic_uiom_pd *usnic_uiom_alloc_pd(void)
+{
+       struct usnic_uiom_pd *pd;
+       void *domain;
+
+       pd = kzalloc(sizeof(*pd), GFP_KERNEL);
+       if (!pd)
+               return ERR_PTR(-ENOMEM);
+
+       pd->domain = domain = iommu_domain_alloc(&pci_bus_type);
+       if (IS_ERR_OR_NULL(domain)) {
+               usnic_err("Failed to allocate IOMMU domain with err %ld\n",
+                               PTR_ERR(pd->domain));
+               kfree(pd);
+               return ERR_PTR(domain ? PTR_ERR(domain) : -ENOMEM);
+       }
+
+       iommu_set_fault_handler(pd->domain, usnic_uiom_dma_fault, NULL);
+
+       spin_lock_init(&pd->lock);
+       INIT_LIST_HEAD(&pd->devs);
+
+       return pd;
+}
+
+void usnic_uiom_dealloc_pd(struct usnic_uiom_pd *pd)
+{
+       iommu_domain_free(pd->domain);
+       kfree(pd);
+}
+
+int usnic_uiom_attach_dev_to_pd(struct usnic_uiom_pd *pd, struct device *dev)
+{
+       struct usnic_uiom_dev *uiom_dev;
+       int err;
+
+       uiom_dev = kzalloc(sizeof(*uiom_dev), GFP_KERNEL);
+       if (!uiom_dev)
+               return -ENOMEM;
+       uiom_dev->dev = dev;
+
+       err = iommu_attach_device(pd->domain, dev);
+       if (err)
+               goto out_free_dev;
+
+       if (!iommu_domain_has_cap(pd->domain, IOMMU_CAP_CACHE_COHERENCY)) {
+               usnic_err("IOMMU of %s does not support cache coherency\n",
+                               dev_name(dev));
+               err = -EINVAL;
+               goto out_detach_device;
+       }
+
+       spin_lock(&pd->lock);
+       list_add_tail(&uiom_dev->link, &pd->devs);
+       pd->dev_cnt++;
+       spin_unlock(&pd->lock);
+
+       return 0;
+
+out_detach_device:
+       iommu_detach_device(pd->domain, dev);
+out_free_dev:
+       kfree(uiom_dev);
+       return err;
+}
+
+void usnic_uiom_detach_dev_from_pd(struct usnic_uiom_pd *pd, struct device *dev)
+{
+       struct usnic_uiom_dev *uiom_dev;
+       int found = 0;
+
+       spin_lock(&pd->lock);
+       list_for_each_entry(uiom_dev, &pd->devs, link) {
+               if (uiom_dev->dev == dev) {
+                       found = 1;
+                       break;
+               }
+       }
+
+       if (!found) {
+               usnic_err("Unable to free dev %s - not found\n",
+                               dev_name(dev));
+               spin_unlock(&pd->lock);
+               return;
+       }
+
+       list_del(&uiom_dev->link);
+       pd->dev_cnt--;
+       spin_unlock(&pd->lock);
+
+       return iommu_detach_device(pd->domain, dev);
+}
+
+struct device **usnic_uiom_get_dev_list(struct usnic_uiom_pd *pd)
+{
+       struct usnic_uiom_dev *uiom_dev;
+       struct device **devs;
+       int i = 0;
+
+       spin_lock(&pd->lock);
+       devs = kzalloc(sizeof(*devs)*(pd->dev_cnt + 1), GFP_KERNEL);
+       if (!devs) {
+               devs = ERR_PTR(-ENOMEM);
+               goto out;
+       }
+
+       list_for_each_entry(uiom_dev, &pd->devs, link) {
+               devs[i++] = uiom_dev->dev;
+       }
+out:
+       spin_unlock(&pd->lock);
+       return devs;
+}
+
+void usnic_uiom_free_dev_list(struct device **devs)
+{
+       kfree(devs);
+}
+
+int usnic_uiom_init(char *drv_name)
+{
+       if (!iommu_present(&pci_bus_type)) {
+               usnic_err("IOMMU required but not present or enabled.  USNIC QPs will not function w/o enabling IOMMU\n");
+               return -EPERM;
+       }
+
+       usnic_uiom_wq = create_workqueue(drv_name);
+       if (!usnic_uiom_wq) {
+               usnic_err("Unable to alloc wq for drv %s\n", drv_name);
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+void usnic_uiom_fini(void)
+{
+       flush_workqueue(usnic_uiom_wq);
+       destroy_workqueue(usnic_uiom_wq);
+}
diff --git a/drivers/infiniband/hw/usnic/usnic_uiom.h b/drivers/infiniband/hw/usnic/usnic_uiom.h
new file mode 100644 (file)
index 0000000..7044099
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may 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.
+ *
+ * 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 USNIC_UIOM_H_
+#define USNIC_UIOM_H_
+
+#include <linux/list.h>
+#include <linux/scatterlist.h>
+
+#include "usnic_uiom_interval_tree.h"
+
+#define USNIC_UIOM_READ                        (1)
+#define USNIC_UIOM_WRITE               (2)
+
+#define USNIC_UIOM_MAX_PD_CNT          (1000)
+#define USNIC_UIOM_MAX_MR_CNT          (1000000)
+#define USNIC_UIOM_MAX_MR_SIZE         (~0UL)
+#define USNIC_UIOM_PAGE_SIZE           (PAGE_SIZE)
+
+struct usnic_uiom_dev {
+       struct device                   *dev;
+       struct list_head                link;
+};
+
+struct usnic_uiom_pd {
+       struct iommu_domain             *domain;
+       spinlock_t                      lock;
+       struct rb_root                  rb_root;
+       struct list_head                devs;
+       int                             dev_cnt;
+};
+
+struct usnic_uiom_reg {
+       struct usnic_uiom_pd            *pd;
+       unsigned long                   va;
+       size_t                          length;
+       int                             offset;
+       int                             page_size;
+       int                             writable;
+       struct list_head                chunk_list;
+       struct work_struct              work;
+       struct mm_struct                *mm;
+       unsigned long                   diff;
+};
+
+struct usnic_uiom_chunk {
+       struct list_head                list;
+       int                             nents;
+       struct scatterlist              page_list[0];
+};
+
+struct usnic_uiom_pd *usnic_uiom_alloc_pd(void);
+void usnic_uiom_dealloc_pd(struct usnic_uiom_pd *pd);
+int usnic_uiom_attach_dev_to_pd(struct usnic_uiom_pd *pd, struct device *dev);
+void usnic_uiom_detach_dev_from_pd(struct usnic_uiom_pd *pd,
+                                       struct device *dev);
+struct device **usnic_uiom_get_dev_list(struct usnic_uiom_pd *pd);
+void usnic_uiom_free_dev_list(struct device **devs);
+struct usnic_uiom_reg *usnic_uiom_reg_get(struct usnic_uiom_pd *pd,
+                                               unsigned long addr, size_t size,
+                                               int access, int dmasync);
+void usnic_uiom_reg_release(struct usnic_uiom_reg *uiomr, int closing);
+int usnic_uiom_init(char *drv_name);
+void usnic_uiom_fini(void);
+#endif /* USNIC_UIOM_H_ */
diff --git a/drivers/infiniband/hw/usnic/usnic_uiom_interval_tree.c b/drivers/infiniband/hw/usnic/usnic_uiom_interval_tree.c
new file mode 100644 (file)
index 0000000..b6e3a6b
--- /dev/null
@@ -0,0 +1,237 @@
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/list_sort.h>
+#include <linux/version.h>
+
+#include <linux/interval_tree_generic.h>
+#include "usnic_uiom_interval_tree.h"
+
+#define START(node) ((node)->start)
+#define LAST(node) ((node)->last)
+
+#define MAKE_NODE(node, start, end, ref_cnt, flags, err, err_out)      \
+               do {                                                    \
+                       node = usnic_uiom_interval_node_alloc(start,    \
+                                       end, ref_cnt, flags);           \
+                               if (!node) {                            \
+                                       err = -ENOMEM;                  \
+                                       goto err_out;                   \
+                               }                                       \
+               } while (0)
+
+#define MARK_FOR_ADD(node, list) (list_add_tail(&node->link, list))
+
+#define MAKE_NODE_AND_APPEND(node, start, end, ref_cnt, flags, err,    \
+                               err_out, list)                          \
+                               do {                                    \
+                                       MAKE_NODE(node, start, end,     \
+                                               ref_cnt, flags, err,    \
+                                               err_out);               \
+                                       MARK_FOR_ADD(node, list);       \
+                               } while (0)
+
+#define FLAGS_EQUAL(flags1, flags2, mask)                              \
+                       (((flags1) & (mask)) == ((flags2) & (mask)))
+
+static struct usnic_uiom_interval_node*
+usnic_uiom_interval_node_alloc(long int start, long int last, int ref_cnt,
+                               int flags)
+{
+       struct usnic_uiom_interval_node *interval = kzalloc(sizeof(*interval),
+                                                               GFP_KERNEL);
+       if (!interval)
+               return NULL;
+
+       interval->start = start;
+       interval->last = last;
+       interval->flags = flags;
+       interval->ref_cnt = ref_cnt;
+
+       return interval;
+}
+
+static int interval_cmp(void *priv, struct list_head *a, struct list_head *b)
+{
+       struct usnic_uiom_interval_node *node_a, *node_b;
+
+       node_a = list_entry(a, struct usnic_uiom_interval_node, link);
+       node_b = list_entry(b, struct usnic_uiom_interval_node, link);
+
+       /* long to int */
+       if (node_a->start < node_b->start)
+               return -1;
+       else if (node_a->start > node_b->start)
+               return 1;
+
+       return 0;
+}
+
+static void
+find_intervals_intersection_sorted(struct rb_root *root, unsigned long start,
+                                       unsigned long last,
+                                       struct list_head *list)
+{
+       struct usnic_uiom_interval_node *node;
+
+       INIT_LIST_HEAD(list);
+
+       for (node = usnic_uiom_interval_tree_iter_first(root, start, last);
+               node;
+               node = usnic_uiom_interval_tree_iter_next(node, start, last))
+               list_add_tail(&node->link, list);
+
+       list_sort(NULL, list, interval_cmp);
+}
+
+int usnic_uiom_get_intervals_diff(unsigned long start, unsigned long last,
+                                       int flags, int flag_mask,
+                                       struct rb_root *root,
+                                       struct list_head *diff_set)
+{
+       struct usnic_uiom_interval_node *interval, *tmp;
+       int err = 0;
+       long int pivot = start;
+       LIST_HEAD(intersection_set);
+
+       INIT_LIST_HEAD(diff_set);
+
+       find_intervals_intersection_sorted(root, start, last,
+                                               &intersection_set);
+
+       list_for_each_entry(interval, &intersection_set, link) {
+               if (pivot < interval->start) {
+                       MAKE_NODE_AND_APPEND(tmp, pivot, interval->start - 1,
+                                               1, flags, err, err_out,
+                                               diff_set);
+                       pivot = interval->start;
+               }
+
+               /*
+                * Invariant: Set [start, pivot] is either in diff_set or root,
+                * but not in both.
+                */
+
+               if (pivot > interval->last) {
+                       continue;
+               } else if (pivot <= interval->last &&
+                               FLAGS_EQUAL(interval->flags, flags,
+                               flag_mask)) {
+                       pivot = interval->last + 1;
+               }
+       }
+
+       if (pivot <= last)
+               MAKE_NODE_AND_APPEND(tmp, pivot, last, 1, flags, err, err_out,
+                                       diff_set);
+
+       return 0;
+
+err_out:
+       list_for_each_entry_safe(interval, tmp, diff_set, link) {
+               list_del(&interval->link);
+               kfree(interval);
+       }
+
+       return err;
+}
+
+void usnic_uiom_put_interval_set(struct list_head *intervals)
+{
+       struct usnic_uiom_interval_node *interval, *tmp;
+       list_for_each_entry_safe(interval, tmp, intervals, link)
+               kfree(interval);
+}
+
+int usnic_uiom_insert_interval(struct rb_root *root, unsigned long start,
+                               unsigned long last, int flags)
+{
+       struct usnic_uiom_interval_node *interval, *tmp;
+       unsigned long istart, ilast;
+       int iref_cnt, iflags;
+       unsigned long lpivot = start;
+       int err = 0;
+       LIST_HEAD(to_add);
+       LIST_HEAD(intersection_set);
+
+       find_intervals_intersection_sorted(root, start, last,
+                                               &intersection_set);
+
+       list_for_each_entry(interval, &intersection_set, link) {
+               /*
+                * Invariant - lpivot is the left edge of next interval to be
+                * inserted
+                */
+               istart = interval->start;
+               ilast = interval->last;
+               iref_cnt = interval->ref_cnt;
+               iflags = interval->flags;
+
+               if (istart < lpivot) {
+                       MAKE_NODE_AND_APPEND(tmp, istart, lpivot - 1, iref_cnt,
+                                               iflags, err, err_out, &to_add);
+               } else if (istart > lpivot) {
+                       MAKE_NODE_AND_APPEND(tmp, lpivot, istart - 1, 1, flags,
+                                               err, err_out, &to_add);
+                       lpivot = istart;
+               } else {
+                       lpivot = istart;
+               }
+
+               if (ilast > last) {
+                       MAKE_NODE_AND_APPEND(tmp, lpivot, last, iref_cnt + 1,
+                                               iflags | flags, err, err_out,
+                                               &to_add);
+                       MAKE_NODE_AND_APPEND(tmp, last + 1, ilast, iref_cnt,
+                                               iflags, err, err_out, &to_add);
+               } else {
+                       MAKE_NODE_AND_APPEND(tmp, lpivot, ilast, iref_cnt + 1,
+                                               iflags | flags, err, err_out,
+                                               &to_add);
+               }
+
+               lpivot = ilast + 1;
+       }
+
+       if (lpivot <= last)
+               MAKE_NODE_AND_APPEND(tmp, lpivot, last, 1, flags, err, err_out,
+                                       &to_add);
+
+       list_for_each_entry_safe(interval, tmp, &intersection_set, link) {
+               usnic_uiom_interval_tree_remove(interval, root);
+               kfree(interval);
+       }
+
+       list_for_each_entry(interval, &to_add, link)
+               usnic_uiom_interval_tree_insert(interval, root);
+
+       return 0;
+
+err_out:
+       list_for_each_entry_safe(interval, tmp, &to_add, link)
+               kfree(interval);
+
+       return err;
+}
+
+void usnic_uiom_remove_interval(struct rb_root *root, unsigned long start,
+                               unsigned long last, struct list_head *removed)
+{
+       struct usnic_uiom_interval_node *interval;
+
+       for (interval = usnic_uiom_interval_tree_iter_first(root, start, last);
+                       interval;
+                       interval = usnic_uiom_interval_tree_iter_next(interval,
+                                                                       start,
+                                                                       last)) {
+               if (--interval->ref_cnt == 0)
+                       list_add_tail(&interval->link, removed);
+       }
+
+       list_for_each_entry(interval, removed, link)
+               usnic_uiom_interval_tree_remove(interval, root);
+}
+
+INTERVAL_TREE_DEFINE(struct usnic_uiom_interval_node, rb,
+                       unsigned long, __subtree_last,
+                       START, LAST, , usnic_uiom_interval_tree)
diff --git a/drivers/infiniband/hw/usnic/usnic_uiom_interval_tree.h b/drivers/infiniband/hw/usnic/usnic_uiom_interval_tree.h
new file mode 100644 (file)
index 0000000..030ba6e
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may 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.
+ *
+ * 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 USNIC_UIOM_INTERVAL_TREE_H_
+#define USNIC_UIOM_INTERVAL_TREE_H_
+
+#include <linux/version.h>
+#include <linux/rbtree.h>
+
+struct usnic_uiom_interval_node {
+       struct rb_node                  rb;
+       struct list_head                link;
+       unsigned long                   start;
+       unsigned long                   last;
+       unsigned long                   __subtree_last;
+       unsigned int                    ref_cnt;
+       int                             flags;
+};
+
+extern void
+usnic_uiom_interval_tree_insert(struct usnic_uiom_interval_node *node,
+                                       struct rb_root *root);
+extern void
+usnic_uiom_interval_tree_remove(struct usnic_uiom_interval_node *node,
+                                       struct rb_root *root);
+extern struct usnic_uiom_interval_node *
+usnic_uiom_interval_tree_iter_first(struct rb_root *root,
+                                       unsigned long start,
+                                       unsigned long last);
+extern struct usnic_uiom_interval_node *
+usnic_uiom_interval_tree_iter_next(struct usnic_uiom_interval_node *node,
+                       unsigned long start, unsigned long last);
+/*
+ * Inserts {start...last} into {root}.  If there are overlaps,
+ * nodes will be broken up and merged
+ */
+int usnic_uiom_insert_interval(struct rb_root *root,
+                               unsigned long start, unsigned long last,
+                               int flags);
+/*
+ * Removed {start...last} from {root}.  The nodes removed are returned in
+ * 'removed.' The caller is responsibile for freeing memory of nodes in
+ * 'removed.'
+ */
+void usnic_uiom_remove_interval(struct rb_root *root,
+                               unsigned long start, unsigned long last,
+                               struct list_head *removed);
+/*
+ * Returns {start...last} - {root} (relative complement of {start...last} in
+ * {root}) in diff_set sorted ascendingly
+ */
+int usnic_uiom_get_intervals_diff(unsigned long start,
+                                       unsigned long last, int flags,
+                                       int flag_mask,
+                                       struct rb_root *root,
+                                       struct list_head *diff_set);
+/* Call this to free diff_set returned by usnic_uiom_get_intervals_diff */
+void usnic_uiom_put_interval_set(struct list_head *intervals);
+#endif /* USNIC_UIOM_INTERVAL_TREE_H_ */
diff --git a/drivers/infiniband/hw/usnic/usnic_vnic.c b/drivers/infiniband/hw/usnic/usnic_vnic.c
new file mode 100644 (file)
index 0000000..11c2449
--- /dev/null
@@ -0,0 +1,473 @@
+/*
+ * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may 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.
+ *
+ * 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.
+ *
+ */
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#include "usnic_ib.h"
+#include "vnic_resource.h"
+#include "usnic_log.h"
+#include "usnic_vnic.h"
+
+struct usnic_vnic {
+       struct vnic_dev                 *vdev;
+       struct vnic_dev_bar             bar[PCI_NUM_RESOURCES];
+       struct usnic_vnic_res_chunk     chunks[USNIC_VNIC_RES_TYPE_MAX];
+       spinlock_t                      res_lock;
+};
+
+static enum vnic_res_type _to_vnic_res_type(enum usnic_vnic_res_type res_type)
+{
+#define DEFINE_USNIC_VNIC_RES_AT(usnic_vnic_res_t, vnic_res_type, desc, val) \
+               vnic_res_type,
+#define DEFINE_USNIC_VNIC_RES(usnic_vnic_res_t, vnic_res_type, desc) \
+               vnic_res_type,
+       static enum vnic_res_type usnic_vnic_type_2_vnic_type[] = {
+                                               USNIC_VNIC_RES_TYPES};
+#undef DEFINE_USNIC_VNIC_RES
+#undef DEFINE_USNIC_VNIC_RES_AT
+
+       if (res_type >= USNIC_VNIC_RES_TYPE_MAX)
+               return RES_TYPE_MAX;
+
+       return usnic_vnic_type_2_vnic_type[res_type];
+}
+
+const char *usnic_vnic_res_type_to_str(enum usnic_vnic_res_type res_type)
+{
+#define DEFINE_USNIC_VNIC_RES_AT(usnic_vnic_res_t, vnic_res_type, desc, val) \
+               desc,
+#define DEFINE_USNIC_VNIC_RES(usnic_vnic_res_t, vnic_res_type, desc) \
+               desc,
+       static const char * const usnic_vnic_res_type_desc[] = {
+                                               USNIC_VNIC_RES_TYPES};
+#undef DEFINE_USNIC_VNIC_RES
+#undef DEFINE_USNIC_VNIC_RES_AT
+
+       if (res_type >= USNIC_VNIC_RES_TYPE_MAX)
+               return "unknown";
+
+       return usnic_vnic_res_type_desc[res_type];
+
+}
+
+const char *usnic_vnic_pci_name(struct usnic_vnic *vnic)
+{
+       return pci_name(usnic_vnic_get_pdev(vnic));
+}
+
+int usnic_vnic_dump(struct usnic_vnic *vnic, char *buf,
+                       int buf_sz,
+                       void *hdr_obj,
+                       int (*printtitle)(void *, char*, int),
+                       int (*printcols)(char *, int),
+                       int (*printrow)(void *, char *, int))
+{
+       struct usnic_vnic_res_chunk *chunk;
+       struct usnic_vnic_res *res;
+       struct vnic_dev_bar *bar0;
+       int i, j, offset;
+
+       offset = 0;
+       bar0 = usnic_vnic_get_bar(vnic, 0);
+       offset += scnprintf(buf + offset, buf_sz - offset,
+                       "VF:%hu BAR0 bus_addr=0x%llx vaddr=0x%p size=%ld ",
+                       usnic_vnic_get_index(vnic),
+                       bar0->bus_addr,
+                       bar0->vaddr, bar0->len);
+       if (printtitle)
+               offset += printtitle(hdr_obj, buf + offset, buf_sz - offset);
+       offset += scnprintf(buf + offset, buf_sz - offset, "\n");
+       offset += scnprintf(buf + offset, buf_sz - offset,
+                       "|RES\t|CTRL_PIN\t\t|IN_USE\t");
+       if (printcols)
+               offset += printcols(buf + offset, buf_sz - offset);
+       offset += scnprintf(buf + offset, buf_sz - offset, "\n");
+
+       spin_lock(&vnic->res_lock);
+       for (i = 0; i < ARRAY_SIZE(vnic->chunks); i++) {
+               chunk = &vnic->chunks[i];
+               if (chunk->cnt == 0)
+                       continue;
+               for (j = 0; j < chunk->cnt; j++) {
+                       res = chunk->res[j];
+                       offset += scnprintf(buf + offset, buf_sz - offset,
+                                       "|%s[%u]\t|0x%p\t|%u\t",
+                                       usnic_vnic_res_type_to_str(res->type),
+                                       res->vnic_idx, res->ctrl, !!res->owner);
+                       if (printrow) {
+                               offset += printrow(res->owner, buf + offset,
+                                                       buf_sz - offset);
+                       }
+                       offset += scnprintf(buf + offset, buf_sz - offset,
+                                               "\n");
+               }
+       }
+       spin_unlock(&vnic->res_lock);
+       return offset;
+}
+
+void usnic_vnic_res_spec_update(struct usnic_vnic_res_spec *spec,
+                               enum usnic_vnic_res_type trgt_type,
+                               u16 cnt)
+{
+       int i;
+
+       for (i = 0; i < USNIC_VNIC_RES_TYPE_MAX; i++) {
+               if (spec->resources[i].type == trgt_type) {
+                       spec->resources[i].cnt = cnt;
+                       return;
+               }
+       }
+
+       WARN_ON(1);
+}
+
+int usnic_vnic_res_spec_satisfied(const struct usnic_vnic_res_spec
+                                       const *min_spec,
+                                       const struct usnic_vnic_res_spec
+                                       const *res_spec)
+{
+       int found, i, j;
+
+       for (i = 0; i < USNIC_VNIC_RES_TYPE_MAX; i++) {
+               found = 0;
+
+               for (j = 0; j < USNIC_VNIC_RES_TYPE_MAX; j++) {
+                       if (res_spec->resources[i].type !=
+                               min_spec->resources[i].type)
+                               continue;
+                       found = 1;
+                       if (min_spec->resources[i].cnt >
+                                       res_spec->resources[i].cnt)
+                               return -EINVAL;
+                       break;
+               }
+
+               if (!found)
+                       return -EINVAL;
+       }
+       return 0;
+}
+
+int usnic_vnic_spec_dump(char *buf, int buf_sz, const struct usnic_vnic_res_spec
+                                               const *res_spec)
+{
+       enum usnic_vnic_res_type res_type;
+       int res_cnt;
+       int i;
+       int offset = 0;
+
+       for (i = 0; i < USNIC_VNIC_RES_TYPE_MAX; i++) {
+               res_type = res_spec->resources[i].type;
+               res_cnt = res_spec->resources[i].cnt;
+               offset += scnprintf(buf + offset, buf_sz - offset,
+                               "Res: %s Cnt: %d ",
+                               usnic_vnic_res_type_to_str(res_type),
+                               res_cnt);
+       }
+
+       offset += scnprintf(buf + offset, buf_sz - offset,
+                               "\n");
+       return offset;
+}
+
+int usnic_vnic_check_room(struct usnic_vnic *vnic,
+                       const struct usnic_vnic_res_spec const *res_spec)
+{
+       int i;
+       enum usnic_vnic_res_type res_type;
+       int res_cnt;
+
+       for (i = 0; i < USNIC_VNIC_RES_TYPE_MAX; i++) {
+               res_type = res_spec->resources[i].type;
+               res_cnt = res_spec->resources[i].cnt;
+
+               if (res_type == USNIC_VNIC_RES_TYPE_EOL)
+                       break;
+
+               if (res_cnt > usnic_vnic_res_free_cnt(vnic, res_type))
+                       return -EBUSY;
+       }
+
+       return 0;
+}
+
+int usnic_vnic_res_cnt(struct usnic_vnic *vnic,
+                               enum usnic_vnic_res_type type)
+{
+       return vnic->chunks[type].cnt;
+}
+
+int usnic_vnic_res_free_cnt(struct usnic_vnic *vnic,
+                               enum usnic_vnic_res_type type)
+{
+       return vnic->chunks[type].free_cnt;
+}
+
+struct usnic_vnic_res_chunk *
+usnic_vnic_get_resources(struct usnic_vnic *vnic, enum usnic_vnic_res_type type,
+                               int cnt, void *owner)
+{
+       struct usnic_vnic_res_chunk *src, *ret;
+       struct usnic_vnic_res *res;
+       int i;
+
+       if (usnic_vnic_res_free_cnt(vnic, type) < cnt || cnt < 1 || !owner)
+               return ERR_PTR(-EINVAL);
+
+       ret = kzalloc(sizeof(*ret), GFP_KERNEL);
+       if (!ret) {
+               usnic_err("Failed to allocate chunk for %s - Out of memory\n",
+                               usnic_vnic_pci_name(vnic));
+               return ERR_PTR(-ENOMEM);
+       }
+
+       ret->res = kzalloc(sizeof(*(ret->res))*cnt, GFP_KERNEL);
+       if (!ret->res) {
+               usnic_err("Failed to allocate resources for %s. Out of memory\n",
+                               usnic_vnic_pci_name(vnic));
+               kfree(ret);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       spin_lock(&vnic->res_lock);
+       src = &vnic->chunks[type];
+       for (i = 0; i < src->cnt && ret->cnt < cnt; i++) {
+               res = src->res[i];
+               if (!res->owner) {
+                       src->free_cnt--;
+                       res->owner = owner;
+                       ret->res[ret->cnt++] = res;
+               }
+       }
+
+       spin_unlock(&vnic->res_lock);
+       ret->type = type;
+       ret->vnic = vnic;
+       WARN_ON(ret->cnt != cnt);
+
+       return ret;
+}
+
+void usnic_vnic_put_resources(struct usnic_vnic_res_chunk *chunk)
+{
+
+       struct usnic_vnic_res *res;
+       int i;
+       struct usnic_vnic *vnic = chunk->vnic;
+
+       spin_lock(&vnic->res_lock);
+       while ((i = --chunk->cnt) >= 0) {
+               res = chunk->res[i];
+               chunk->res[i] = NULL;
+               res->owner = NULL;
+               vnic->chunks[res->type].free_cnt++;
+       }
+       spin_unlock(&vnic->res_lock);
+
+       kfree(chunk->res);
+       kfree(chunk);
+}
+
+u16 usnic_vnic_get_index(struct usnic_vnic *vnic)
+{
+       return usnic_vnic_get_pdev(vnic)->devfn - 1;
+}
+
+static int usnic_vnic_alloc_res_chunk(struct usnic_vnic *vnic,
+                                       enum usnic_vnic_res_type type,
+                                       struct usnic_vnic_res_chunk *chunk)
+{
+       int cnt, err, i;
+       struct usnic_vnic_res *res;
+
+       cnt = vnic_dev_get_res_count(vnic->vdev, _to_vnic_res_type(type));
+       if (cnt < 1)
+               return -EINVAL;
+
+       chunk->cnt = chunk->free_cnt = cnt;
+       chunk->res = kzalloc(sizeof(*(chunk->res))*cnt, GFP_KERNEL);
+       if (!chunk->res)
+               return -ENOMEM;
+
+       for (i = 0; i < cnt; i++) {
+               res = kzalloc(sizeof(*res), GFP_KERNEL);
+               if (!res) {
+                       err = -ENOMEM;
+                       goto fail;
+               }
+               res->type = type;
+               res->vnic_idx = i;
+               res->vnic = vnic;
+               res->ctrl = vnic_dev_get_res(vnic->vdev,
+                                               _to_vnic_res_type(type), i);
+               chunk->res[i] = res;
+       }
+
+       chunk->vnic = vnic;
+       return 0;
+fail:
+       for (i--; i >= 0; i--)
+               kfree(chunk->res[i]);
+       kfree(chunk->res);
+       return err;
+}
+
+static void usnic_vnic_free_res_chunk(struct usnic_vnic_res_chunk *chunk)
+{
+       int i;
+       for (i = 0; i < chunk->cnt; i++)
+               kfree(chunk->res[i]);
+       kfree(chunk->res);
+}
+
+static int usnic_vnic_discover_resources(struct pci_dev *pdev,
+                                               struct usnic_vnic *vnic)
+{
+       enum usnic_vnic_res_type res_type;
+       int i;
+       int err = 0;
+
+       for (i = 0; i < ARRAY_SIZE(vnic->bar); i++) {
+               if (!(pci_resource_flags(pdev, i) & IORESOURCE_MEM))
+                       continue;
+               vnic->bar[i].len = pci_resource_len(pdev, i);
+               vnic->bar[i].vaddr = pci_iomap(pdev, i, vnic->bar[i].len);
+               if (!vnic->bar[i].vaddr) {
+                       usnic_err("Cannot memory-map BAR %d, aborting\n",
+                                       i);
+                       err = -ENODEV;
+                       goto out_clean_bar;
+               }
+               vnic->bar[i].bus_addr = pci_resource_start(pdev, i);
+       }
+
+       vnic->vdev = vnic_dev_register(NULL, pdev, pdev, vnic->bar,
+                       ARRAY_SIZE(vnic->bar));
+       if (!vnic->vdev) {
+               usnic_err("Failed to register device %s\n",
+                               pci_name(pdev));
+               err = -EINVAL;
+               goto out_clean_bar;
+       }
+
+       for (res_type = USNIC_VNIC_RES_TYPE_EOL + 1;
+                       res_type < USNIC_VNIC_RES_TYPE_MAX; res_type++) {
+               err = usnic_vnic_alloc_res_chunk(vnic, res_type,
+                                               &vnic->chunks[res_type]);
+               if (err) {
+                       usnic_err("Failed to alloc res %s with err %d\n",
+                                       usnic_vnic_res_type_to_str(res_type),
+                                       err);
+                       goto out_clean_chunks;
+               }
+       }
+
+       return 0;
+
+out_clean_chunks:
+       for (res_type--; res_type > USNIC_VNIC_RES_TYPE_EOL; res_type--)
+               usnic_vnic_free_res_chunk(&vnic->chunks[res_type]);
+       vnic_dev_unregister(vnic->vdev);
+out_clean_bar:
+       for (i = 0; i < ARRAY_SIZE(vnic->bar); i++) {
+               if (!(pci_resource_flags(pdev, i) & IORESOURCE_MEM))
+                       continue;
+               if (!vnic->bar[i].vaddr)
+                       break;
+
+               iounmap(vnic->bar[i].vaddr);
+       }
+
+       return err;
+}
+
+struct pci_dev *usnic_vnic_get_pdev(struct usnic_vnic *vnic)
+{
+       return vnic_dev_get_pdev(vnic->vdev);
+}
+
+struct vnic_dev_bar *usnic_vnic_get_bar(struct usnic_vnic *vnic,
+                               int bar_num)
+{
+       return (bar_num < ARRAY_SIZE(vnic->bar)) ? &vnic->bar[bar_num] : NULL;
+}
+
+static void usnic_vnic_release_resources(struct usnic_vnic *vnic)
+{
+       int i;
+       struct pci_dev *pdev;
+       enum usnic_vnic_res_type res_type;
+
+       pdev = usnic_vnic_get_pdev(vnic);
+
+       for (res_type = USNIC_VNIC_RES_TYPE_EOL + 1;
+                       res_type < USNIC_VNIC_RES_TYPE_MAX; res_type++)
+               usnic_vnic_free_res_chunk(&vnic->chunks[res_type]);
+
+       vnic_dev_unregister(vnic->vdev);
+
+       for (i = 0; i < ARRAY_SIZE(vnic->bar); i++) {
+               if (!(pci_resource_flags(pdev, i) & IORESOURCE_MEM))
+                       continue;
+               iounmap(vnic->bar[i].vaddr);
+       }
+}
+
+struct usnic_vnic *usnic_vnic_alloc(struct pci_dev *pdev)
+{
+       struct usnic_vnic *vnic;
+       int err = 0;
+
+       if (!pci_is_enabled(pdev)) {
+               usnic_err("PCI dev %s is disabled\n", pci_name(pdev));
+               return ERR_PTR(-EINVAL);
+       }
+
+       vnic = kzalloc(sizeof(*vnic), GFP_KERNEL);
+       if (!vnic) {
+               usnic_err("Failed to alloc vnic for %s - out of memory\n",
+                               pci_name(pdev));
+               return ERR_PTR(-ENOMEM);
+       }
+
+       spin_lock_init(&vnic->res_lock);
+
+       err = usnic_vnic_discover_resources(pdev, vnic);
+       if (err) {
+               usnic_err("Failed to discover %s resources with err %d\n",
+                               pci_name(pdev), err);
+               goto out_free_vnic;
+       }
+
+       usnic_dbg("Allocated vnic for %s\n", usnic_vnic_pci_name(vnic));
+
+       return vnic;
+
+out_free_vnic:
+       kfree(vnic);
+
+       return ERR_PTR(err);
+}
+
+void usnic_vnic_free(struct usnic_vnic *vnic)
+{
+       usnic_vnic_release_resources(vnic);
+       kfree(vnic);
+}
diff --git a/drivers/infiniband/hw/usnic/usnic_vnic.h b/drivers/infiniband/hw/usnic/usnic_vnic.h
new file mode 100644 (file)
index 0000000..0a69a5d
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may 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.
+ *
+ * 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 USNIC_VNIC_H_
+#define USNIC_VNIC_H_
+
+#include <linux/pci.h>
+
+#include "vnic_dev.h"
+
+/*                      =USNIC_VNIC_RES_TYPE= =VNIC_RES=   =DESC= */
+#define USNIC_VNIC_RES_TYPES \
+       DEFINE_USNIC_VNIC_RES_AT(EOL, RES_TYPE_EOL, "EOL", 0) \
+       DEFINE_USNIC_VNIC_RES(WQ, RES_TYPE_WQ, "WQ") \
+       DEFINE_USNIC_VNIC_RES(RQ, RES_TYPE_RQ, "RQ") \
+       DEFINE_USNIC_VNIC_RES(CQ, RES_TYPE_CQ, "CQ") \
+       DEFINE_USNIC_VNIC_RES(INTR, RES_TYPE_INTR_CTRL, "INT") \
+       DEFINE_USNIC_VNIC_RES(MAX, RES_TYPE_MAX, "MAX")\
+
+#define DEFINE_USNIC_VNIC_RES_AT(usnic_vnic_res_t, vnic_res_type, desc, val) \
+       USNIC_VNIC_RES_TYPE_##usnic_vnic_res_t = val,
+#define DEFINE_USNIC_VNIC_RES(usnic_vnic_res_t, vnic_res_type, desc) \
+       USNIC_VNIC_RES_TYPE_##usnic_vnic_res_t,
+enum usnic_vnic_res_type {
+       USNIC_VNIC_RES_TYPES
+};
+#undef DEFINE_USNIC_VNIC_RES
+#undef DEFINE_USNIC_VNIC_RES_AT
+
+struct usnic_vnic_res {
+       enum usnic_vnic_res_type        type;
+       unsigned int                    vnic_idx;
+       struct usnic_vnic               *vnic;
+       void __iomem                    *ctrl;
+       void                            *owner;
+};
+
+struct usnic_vnic_res_chunk {
+       enum usnic_vnic_res_type        type;
+       int                             cnt;
+       int                             free_cnt;
+       struct usnic_vnic_res           **res;
+       struct usnic_vnic               *vnic;
+};
+
+struct usnic_vnic_res_desc {
+       enum usnic_vnic_res_type        type;
+       uint16_t                        cnt;
+};
+
+struct usnic_vnic_res_spec {
+       struct usnic_vnic_res_desc resources[USNIC_VNIC_RES_TYPE_MAX];
+};
+
+const char *usnic_vnic_res_type_to_str(enum usnic_vnic_res_type res_type);
+const char *usnic_vnic_pci_name(struct usnic_vnic *vnic);
+int usnic_vnic_dump(struct usnic_vnic *vnic, char *buf, int buf_sz,
+                       void *hdr_obj,
+                       int (*printtitle)(void *, char*, int),
+                       int (*printcols)(char *, int),
+                       int (*printrow)(void *, char *, int));
+void usnic_vnic_res_spec_update(struct usnic_vnic_res_spec *spec,
+                               enum usnic_vnic_res_type trgt_type,
+                               u16 cnt);
+int usnic_vnic_res_spec_satisfied(const struct usnic_vnic_res_spec
+                                       const *min_spec,
+                                       const struct usnic_vnic_res_spec
+                                       const *res_spec);
+int usnic_vnic_spec_dump(char *buf, int buf_sz, const struct usnic_vnic_res_spec
+                                               const *res_spec);
+int usnic_vnic_check_room(struct usnic_vnic *vnic,
+                       const struct usnic_vnic_res_spec const *res_spec);
+int usnic_vnic_res_cnt(struct usnic_vnic *vnic,
+                               enum usnic_vnic_res_type type);
+int usnic_vnic_res_free_cnt(struct usnic_vnic *vnic,
+                               enum usnic_vnic_res_type type);
+struct usnic_vnic_res_chunk *
+usnic_vnic_get_resources(struct usnic_vnic *vnic,
+                               enum usnic_vnic_res_type type,
+                               int cnt,
+                               void *owner);
+void usnic_vnic_put_resources(struct usnic_vnic_res_chunk *chunk);
+struct pci_dev *usnic_vnic_get_pdev(struct usnic_vnic *vnic);
+struct vnic_dev_bar *usnic_vnic_get_bar(struct usnic_vnic *vnic,
+                               int bar_num);
+struct usnic_vnic *usnic_vnic_alloc(struct pci_dev *pdev);
+void usnic_vnic_free(struct usnic_vnic *vnic);
+u16 usnic_vnic_get_index(struct usnic_vnic *vnic);
+
+#endif /*!USNIC_VNIC_H_*/
index bb174c1a9886eb8a1592f347e71e20bdb6fd90b6..a673c9f3a0b97d939f24c76d88d42596ea097257 100644 (file)
@@ -525,7 +525,7 @@ config KEYBOARD_SUNKBD
 
 config KEYBOARD_SH_KEYSC
        tristate "SuperH KEYSC keypad support"
-       depends on SUPERH || ARM || COMPILE_TEST
+       depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST
        help
          Say Y here if you want to use a keypad attached to the KEYSC block
          on SuperH processors such as sh7722 and sh7343.
index ef26b17fb159d411111d5c479c4b6d753846a61a..0dc1151d02fbf05a152116336cf9e4628bd6f0ec 100644 (file)
@@ -71,7 +71,7 @@ static int adp5520_keys_notifier(struct notifier_block *nb,
 
 static int adp5520_keys_probe(struct platform_device *pdev)
 {
-       struct adp5520_keys_platform_data *pdata = pdev->dev.platform_data;
+       struct adp5520_keys_platform_data *pdata = dev_get_platdata(&pdev->dev);
        struct input_dev *input;
        struct adp5520_keys *dev;
        int ret, i;
index dbd2047f1641f0751340eade88c408f31201f318..a8f5f92165654e4f536875b352f189ddb1ee100d 100644 (file)
@@ -173,7 +173,7 @@ static int adp5588_build_gpiomap(struct adp5588_kpad *kpad,
 static int adp5588_gpio_add(struct adp5588_kpad *kpad)
 {
        struct device *dev = &kpad->client->dev;
-       const struct adp5588_kpad_platform_data *pdata = dev->platform_data;
+       const struct adp5588_kpad_platform_data *pdata = dev_get_platdata(dev);
        const struct adp5588_gpio_platform_data *gpio_data = pdata->gpio_data;
        int i, error;
 
@@ -227,7 +227,7 @@ static int adp5588_gpio_add(struct adp5588_kpad *kpad)
 static void adp5588_gpio_remove(struct adp5588_kpad *kpad)
 {
        struct device *dev = &kpad->client->dev;
-       const struct adp5588_kpad_platform_data *pdata = dev->platform_data;
+       const struct adp5588_kpad_platform_data *pdata = dev_get_platdata(dev);
        const struct adp5588_gpio_platform_data *gpio_data = pdata->gpio_data;
        int error;
 
@@ -321,7 +321,8 @@ static irqreturn_t adp5588_irq(int irq, void *handle)
 
 static int adp5588_setup(struct i2c_client *client)
 {
-       const struct adp5588_kpad_platform_data *pdata = client->dev.platform_data;
+       const struct adp5588_kpad_platform_data *pdata =
+                       dev_get_platdata(&client->dev);
        const struct adp5588_gpio_platform_data *gpio_data = pdata->gpio_data;
        int i, ret;
        unsigned char evt_mode1 = 0, evt_mode2 = 0, evt_mode3 = 0;
@@ -424,7 +425,8 @@ static int adp5588_probe(struct i2c_client *client,
                         const struct i2c_device_id *id)
 {
        struct adp5588_kpad *kpad;
-       const struct adp5588_kpad_platform_data *pdata = client->dev.platform_data;
+       const struct adp5588_kpad_platform_data *pdata =
+                       dev_get_platdata(&client->dev);
        struct input_dev *input;
        unsigned int revid;
        int ret, i;
@@ -536,7 +538,8 @@ static int adp5588_probe(struct i2c_client *client,
                __set_bit(EV_REP, input->evbit);
 
        for (i = 0; i < input->keycodemax; i++)
-               __set_bit(kpad->keycode[i] & KEY_MAX, input->keybit);
+               if (kpad->keycode[i] <= KEY_MAX)
+                       __set_bit(kpad->keycode[i], input->keybit);
        __clear_bit(KEY_RESERVED, input->keybit);
 
        if (kpad->gpimapsize)
index 67d12b3427c9ee9bcb5da69d276a6bc814467586..ff7725a00776dd4e8d17b6f07ef75b02ce533c96 100644 (file)
@@ -499,7 +499,7 @@ static int adp5589_build_gpiomap(struct adp5589_kpad *kpad,
 static int adp5589_gpio_add(struct adp5589_kpad *kpad)
 {
        struct device *dev = &kpad->client->dev;
-       const struct adp5589_kpad_platform_data *pdata = dev->platform_data;
+       const struct adp5589_kpad_platform_data *pdata = dev_get_platdata(dev);
        const struct adp5589_gpio_platform_data *gpio_data = pdata->gpio_data;
        int i, error;
 
@@ -553,7 +553,7 @@ static int adp5589_gpio_add(struct adp5589_kpad *kpad)
 static void adp5589_gpio_remove(struct adp5589_kpad *kpad)
 {
        struct device *dev = &kpad->client->dev;
-       const struct adp5589_kpad_platform_data *pdata = dev->platform_data;
+       const struct adp5589_kpad_platform_data *pdata = dev_get_platdata(dev);
        const struct adp5589_gpio_platform_data *gpio_data = pdata->gpio_data;
        int error;
 
@@ -658,7 +658,7 @@ static int adp5589_setup(struct adp5589_kpad *kpad)
 {
        struct i2c_client *client = kpad->client;
        const struct adp5589_kpad_platform_data *pdata =
-               client->dev.platform_data;
+               dev_get_platdata(&client->dev);
        u8 (*reg) (u8) = kpad->var->reg;
        unsigned char evt_mode1 = 0, evt_mode2 = 0, evt_mode3 = 0;
        unsigned char pull_mask = 0;
@@ -864,7 +864,7 @@ static int adp5589_probe(struct i2c_client *client,
 {
        struct adp5589_kpad *kpad;
        const struct adp5589_kpad_platform_data *pdata =
-               client->dev.platform_data;
+               dev_get_platdata(&client->dev);
        struct input_dev *input;
        unsigned int revid;
        int ret, i;
@@ -992,7 +992,8 @@ static int adp5589_probe(struct i2c_client *client,
                __set_bit(EV_REP, input->evbit);
 
        for (i = 0; i < input->keycodemax; i++)
-               __set_bit(kpad->keycode[i] & KEY_MAX, input->keybit);
+               if (kpad->keycode[i] <= KEY_MAX)
+                       __set_bit(kpad->keycode[i], input->keybit);
        __clear_bit(KEY_RESERVED, input->keybit);
 
        if (kpad->gpimapsize)
index fc88fb48d70d6740ef96f8fdbe9afc32760218c5..16223f4599d425704c9ddf3ad613e9ab03790ae9 100644 (file)
@@ -180,7 +180,7 @@ static irqreturn_t bfin_kpad_isr(int irq, void *dev_id)
 static int bfin_kpad_probe(struct platform_device *pdev)
 {
        struct bf54x_kpad *bf54x_kpad;
-       struct bfin_kpad_platform_data *pdata = pdev->dev.platform_data;
+       struct bfin_kpad_platform_data *pdata = dev_get_platdata(&pdev->dev);
        struct input_dev *input;
        int i, error;
 
@@ -289,7 +289,8 @@ static int bfin_kpad_probe(struct platform_device *pdev)
                __set_bit(EV_REP, input->evbit);
 
        for (i = 0; i < input->keycodemax; i++)
-               __set_bit(bf54x_kpad->keycode[i] & KEY_MAX, input->keybit);
+               if (bf54x_kpad->keycode[i] <= KEY_MAX)
+                       __set_bit(bf54x_kpad->keycode[i], input->keybit);
        __clear_bit(KEY_RESERVED, input->keybit);
 
        error = input_register_device(input);
@@ -332,7 +333,7 @@ out:
 
 static int bfin_kpad_remove(struct platform_device *pdev)
 {
-       struct bfin_kpad_platform_data *pdata = pdev->dev.platform_data;
+       struct bfin_kpad_platform_data *pdata = dev_get_platdata(&pdev->dev);
        struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev);
 
        del_timer_sync(&bf54x_kpad->timer);
index d15977a8361ea5b007fa19e3a653600252a99cbd..1559dc1cf9516c50527e6bddad12f18db74bc0c5 100644 (file)
@@ -172,7 +172,7 @@ static int __init davinci_ks_probe(struct platform_device *pdev)
        struct input_dev *key_dev;
        struct resource *res, *mem;
        struct device *dev = &pdev->dev;
-       struct davinci_ks_platform_data *pdata = pdev->dev.platform_data;
+       struct davinci_ks_platform_data *pdata = dev_get_platdata(&pdev->dev);
        int error, i;
 
        if (pdata->device_enable) {
index 47206bdba4113a54db431d581a62b84da93b28ed..e59876212b8c47b42f69973ee7f3f93fdc905694 100644 (file)
@@ -244,7 +244,7 @@ static int ep93xx_keypad_probe(struct platform_device *pdev)
        if (!keypad)
                return -ENOMEM;
 
-       keypad->pdata = pdev->dev.platform_data;
+       keypad->pdata = dev_get_platdata(&pdev->dev);
        if (!keypad->pdata) {
                err = -EINVAL;
                goto failed_free;
index 328cfc1eed95dac7d8452547a389909d0320e35a..34bb3589526808ab30491ea9ef18dc4218f4ace2 100644 (file)
@@ -425,7 +425,8 @@ MODULE_DEVICE_TABLE(of, imx_keypad_of_match);
 
 static int imx_keypad_probe(struct platform_device *pdev)
 {
-       const struct matrix_keymap_data *keymap_data = pdev->dev.platform_data;
+       const struct matrix_keymap_data *keymap_data =
+                       dev_get_platdata(&pdev->dev);
        struct imx_keypad *keypad;
        struct input_dev *input_dev;
        struct resource *res;
index 0de23f41b2d316364b8a0f50b8b1b72ca5c9555b..0b42118cbf8f53709debac3415b9d28b5e355a77 100644 (file)
@@ -627,7 +627,7 @@ static DEVICE_ATTR(disable_kp, 0644, lm8323_show_disable, lm8323_set_disable);
 static int lm8323_probe(struct i2c_client *client,
                                  const struct i2c_device_id *id)
 {
-       struct lm8323_platform_data *pdata = client->dev.platform_data;
+       struct lm8323_platform_data *pdata = dev_get_platdata(&client->dev);
        struct input_dev *idev;
        struct lm8323_chip *lm;
        int pwm;
index 5a8ca35dc9af97898d9fa8f0a7988309edeb57a6..9081cbef11ea126d4c46097416dce9cff21aa799 100644 (file)
@@ -131,7 +131,8 @@ static irqreturn_t lm8333_irq_thread(int irq, void *data)
 static int lm8333_probe(struct i2c_client *client,
                                  const struct i2c_device_id *id)
 {
-       const struct lm8333_platform_data *pdata = client->dev.platform_data;
+       const struct lm8333_platform_data *pdata =
+                       dev_get_platdata(&client->dev);
        struct lm8333 *lm8333;
        struct input_dev *input;
        int err, active_time;
index bc2cdaf563fd76da86c9318f0159a9d7a492590f..430b54539720055c78c8e2832e70a03b1ed0a555 100644 (file)
@@ -182,7 +182,8 @@ static void max7359_initialize(struct i2c_client *client)
 static int max7359_probe(struct i2c_client *client,
                                        const struct i2c_device_id *id)
 {
-       const struct matrix_keymap_data *keymap_data = client->dev.platform_data;
+       const struct matrix_keymap_data *keymap_data =
+                       dev_get_platdata(&client->dev);
        struct max7359_keypad *keypad;
        struct input_dev *input_dev;
        int ret;
index 7c236f9c6a519f1baf7f36f44599dd96fc82820c..5ec77523e0401e3238dddcf80ccc297962712cf0 100644 (file)
@@ -108,7 +108,7 @@ static int mcs_touchkey_probe(struct i2c_client *client,
        int error;
        int i;
 
-       pdata = client->dev.platform_data;
+       pdata = dev_get_platdata(&client->dev);
        if (!pdata) {
                dev_err(&client->dev, "no platform data defined\n");
                return -EINVAL;
index f7f3e9a9fd3f5c4b63234fd63b750f10b327afb0..98b8467aa6c94021d261062b3ab4b3c5c29ff43e 100644 (file)
@@ -188,7 +188,8 @@ err_i2c_write:
 static int mpr_touchkey_probe(struct i2c_client *client,
                              const struct i2c_device_id *id)
 {
-       const struct mpr121_platform_data *pdata = client->dev.platform_data;
+       const struct mpr121_platform_data *pdata =
+                       dev_get_platdata(&client->dev);
        struct mpr121_touchkey *mpr121;
        struct input_dev *input_dev;
        int error;
index c7d505cce72f7b36e3658ae5cdea16a0cc96ffba..63332e2f86288f75827e95342f7043b47b09e472 100644 (file)
@@ -222,7 +222,8 @@ static irqreturn_t ske_keypad_irq(int irq, void *dev_id)
 
 static int __init ske_keypad_probe(struct platform_device *pdev)
 {
-       const struct ske_keypad_platform_data *plat = pdev->dev.platform_data;
+       const struct ske_keypad_platform_data *plat =
+                       dev_get_platdata(&pdev->dev);
        struct ske_keypad *keypad;
        struct input_dev *input;
        struct resource *res;
index d0d5226d9cd4981398997d60db6b01949bc0030a..e80bb97433566df07a89b4562993271228108b77 100644 (file)
@@ -248,7 +248,7 @@ static int omap_kp_probe(struct platform_device *pdev)
 {
        struct omap_kp *omap_kp;
        struct input_dev *input_dev;
-       struct omap_kp_platform_data *pdata =  pdev->dev.platform_data;
+       struct omap_kp_platform_data *pdata = dev_get_platdata(&pdev->dev);
        int i, col_idx, row_idx, ret;
        unsigned int row_shift, keycodemax;
 
index 248cdcf952965c616b4de79fca4dfe87f79e38b3..367b03ab92a259d8143b09aa430ff229cc97e8df 100644 (file)
@@ -84,7 +84,8 @@ static void pxa930_rotary_close(struct input_dev *dev)
 
 static int pxa930_rotary_probe(struct platform_device *pdev)
 {
-       struct pxa930_rotary_platform_data *pdata = pdev->dev.platform_data;
+       struct pxa930_rotary_platform_data *pdata =
+                       dev_get_platdata(&pdev->dev);
        struct pxa930_rotary *r;
        struct input_dev *input_dev;
        struct resource *res;
index ac43a486c77536c6267aa33f766b104d698784d7..a7357adeaf242e2ae3f10115f76a17cf1fa05d0e 100644 (file)
@@ -244,8 +244,8 @@ static void samsung_keypad_close(struct input_dev *input_dev)
 }
 
 #ifdef CONFIG_OF
-static struct samsung_keypad_platdata *samsung_keypad_parse_dt(
-                               struct device *dev)
+static struct samsung_keypad_platdata *
+samsung_keypad_parse_dt(struct device *dev)
 {
        struct samsung_keypad_platdata *pdata;
        struct matrix_keymap_data *keymap_data;
@@ -253,17 +253,22 @@ static struct samsung_keypad_platdata *samsung_keypad_parse_dt(
        struct device_node *np = dev->of_node, *key_np;
        unsigned int key_count;
 
+       if (!np) {
+               dev_err(dev, "missing device tree data\n");
+               return ERR_PTR(-EINVAL);
+       }
+
        pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
        if (!pdata) {
                dev_err(dev, "could not allocate memory for platform data\n");
-               return NULL;
+               return ERR_PTR(-ENOMEM);
        }
 
        of_property_read_u32(np, "samsung,keypad-num-rows", &num_rows);
        of_property_read_u32(np, "samsung,keypad-num-columns", &num_cols);
        if (!num_rows || !num_cols) {
                dev_err(dev, "number of keypad rows/columns not specified\n");
-               return NULL;
+               return ERR_PTR(-EINVAL);
        }
        pdata->rows = num_rows;
        pdata->cols = num_cols;
@@ -271,7 +276,7 @@ static struct samsung_keypad_platdata *samsung_keypad_parse_dt(
        keymap_data = devm_kzalloc(dev, sizeof(*keymap_data), GFP_KERNEL);
        if (!keymap_data) {
                dev_err(dev, "could not allocate memory for keymap data\n");
-               return NULL;
+               return ERR_PTR(-ENOMEM);
        }
        pdata->keymap_data = keymap_data;
 
@@ -280,7 +285,7 @@ static struct samsung_keypad_platdata *samsung_keypad_parse_dt(
        keymap = devm_kzalloc(dev, sizeof(uint32_t) * key_count, GFP_KERNEL);
        if (!keymap) {
                dev_err(dev, "could not allocate memory for keymap\n");
-               return NULL;
+               return ERR_PTR(-ENOMEM);
        }
        keymap_data->keymap = keymap;
 
@@ -294,16 +299,19 @@ static struct samsung_keypad_platdata *samsung_keypad_parse_dt(
 
        if (of_get_property(np, "linux,input-no-autorepeat", NULL))
                pdata->no_autorepeat = true;
+
        if (of_get_property(np, "linux,input-wakeup", NULL))
                pdata->wakeup = true;
 
        return pdata;
 }
 #else
-static
-struct samsung_keypad_platdata *samsung_keypad_parse_dt(struct device *dev)
+static struct samsung_keypad_platdata *
+samsung_keypad_parse_dt(struct device *dev)
 {
-       return NULL;
+       dev_err(dev, "no platform data defined\n");
+
+       return ERR_PTR(-EINVAL);
 }
 #endif
 
@@ -318,13 +326,11 @@ static int samsung_keypad_probe(struct platform_device *pdev)
        unsigned int keymap_size;
        int error;
 
-       if (pdev->dev.of_node)
-               pdata = samsung_keypad_parse_dt(&pdev->dev);
-       else
-               pdata = pdev->dev.platform_data;
+       pdata = dev_get_platdata(&pdev->dev);
        if (!pdata) {
-               dev_err(&pdev->dev, "no platform data defined\n");
-               return -EINVAL;
+               pdata = samsung_keypad_parse_dt(&pdev->dev);
+               if (IS_ERR(pdata))
+                       return PTR_ERR(pdata);
        }
 
        keymap_data = pdata->keymap_data;
index fe0e498d24794e557c5c63f67059103dd105fcca..d65a98b1d7dde3f4c675f2d4b6b0df1e21d887bb 100644 (file)
@@ -171,7 +171,7 @@ static int sh_keysc_probe(struct platform_device *pdev)
        int i;
        int irq, error;
 
-       if (!pdev->dev.platform_data) {
+       if (!dev_get_platdata(&pdev->dev)) {
                dev_err(&pdev->dev, "no platform data defined\n");
                error = -EINVAL;
                goto err0;
@@ -198,7 +198,7 @@ static int sh_keysc_probe(struct platform_device *pdev)
        }
 
        platform_set_drvdata(pdev, priv);
-       memcpy(&priv->pdata, pdev->dev.platform_data, sizeof(priv->pdata));
+       memcpy(&priv->pdata, dev_get_platdata(&pdev->dev), sizeof(priv->pdata));
        pdata = &priv->pdata;
 
        priv->iomem_base = ioremap_nocache(res->start, resource_size(res));
index bfc832c35a7cf811aaf121ec59cca5e1f161a442..dc983ab6c0ad566d6b5d126eed9c5551525d62d4 100644 (file)
@@ -213,7 +213,7 @@ static int tca6416_keypad_probe(struct i2c_client *client,
                return -ENODEV;
        }
 
-       pdata = client->dev.platform_data;
+       pdata = dev_get_platdata(&client->dev);
        if (!pdata) {
                dev_dbg(&client->dev, "no platform data\n");
                return -EINVAL;
index 8bd24d52bf1bedd0438e0737350c640b6e3b38b8..086511c2121b821b701fe12ba9ec3763f8470e3b 100644 (file)
@@ -162,7 +162,7 @@ static int keypad_probe(struct platform_device *pdev)
        int error = 0, sz, row_shift;
        u32 rev = 0;
 
-       pdata = pdev->dev.platform_data;
+       pdata = dev_get_platdata(&pdev->dev);
        if (!pdata) {
                dev_err(dev, "cannot find device data\n");
                return -EINVAL;
index d2d178c84ea7584467badbfc2a79ba35afbdb726..8bc2879b4c876627c9e81db0f3c94120c4453130 100644 (file)
@@ -330,7 +330,7 @@ static int twl4030_kp_program(struct twl4030_keypad *kp)
  */
 static int twl4030_kp_probe(struct platform_device *pdev)
 {
-       struct twl4030_keypad_data *pdata = pdev->dev.platform_data;
+       struct twl4030_keypad_data *pdata = dev_get_platdata(&pdev->dev);
        const struct matrix_keymap_data *keymap_data;
        struct twl4030_keypad *kp;
        struct input_dev *input;
index 7b039162a3f833485239274e613aad5cd6ad8710..e03614f20d3b10d5e8cbad86a9a4d9afc75639af 100644 (file)
@@ -121,7 +121,7 @@ static void w90p910_keypad_close(struct input_dev *dev)
 static int w90p910_keypad_probe(struct platform_device *pdev)
 {
        const struct w90p910_keypad_platform_data *pdata =
-                                               pdev->dev.platform_data;
+                                               dev_get_platdata(&pdev->dev);
        const struct matrix_keymap_data *keymap_data;
        struct w90p910_keypad *keypad;
        struct input_dev *input_dev;
index 5f4967d01bc36a621655f64eea7e2c1408ef43b7..4ffc39732513fcd0a20a28d611c2b077ccd0e6bb 100644 (file)
@@ -222,6 +222,15 @@ config INPUT_GP2A
          To compile this driver as a module, choose M here: the
          module will be called gp2ap002a00f.
 
+config INPUT_GPIO_BEEPER
+       tristate "Generic GPIO Beeper support"
+       depends on OF_GPIO
+       help
+         Say Y here if you have a beeper connected to a GPIO pin.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gpio-beeper.
+
 config INPUT_GPIO_TILT_POLLED
        tristate "Polled GPIO tilt switch"
        depends on GPIOLIB
index 0ebfb6dbf0f7788afd75b7a88bd171ff90b567b6..cda71fc52fb3a6bd026bd5edf878f03834996b88 100644 (file)
@@ -27,6 +27,7 @@ obj-$(CONFIG_INPUT_DA9052_ONKEY)      += da9052_onkey.o
 obj-$(CONFIG_INPUT_DA9055_ONKEY)       += da9055_onkey.o
 obj-$(CONFIG_INPUT_DM355EVM)           += dm355evm_keys.o
 obj-$(CONFIG_INPUT_GP2A)               += gp2ap002a00f.o
+obj-$(CONFIG_INPUT_GPIO_BEEPER)                += gpio-beeper.o
 obj-$(CONFIG_INPUT_GPIO_TILT_POLLED)   += gpio_tilt_polled.o
 obj-$(CONFIG_HP_SDC_RTC)               += hp_sdc_rtc.o
 obj-$(CONFIG_INPUT_IMS_PCU)            += ims-pcu.o
index 2e5d5e1de64787f17c2349e1a3c575144411518f..6deecdd3d11bae34af377bcf648d51b689cc054e 100644 (file)
@@ -969,7 +969,7 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
        int error;
        struct input_dev *input[MAX_DEVICE_NUM];
 
-       struct ad714x_platform_data *plat_data = dev->platform_data;
+       struct ad714x_platform_data *plat_data = dev_get_platdata(dev);
        struct ad714x_chip *ad714x;
        void *drv_mem;
        unsigned long irqflags;
@@ -986,7 +986,7 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
                goto err_out;
        }
 
-       if (dev->platform_data == NULL) {
+       if (dev_get_platdata(dev) == NULL) {
                dev_err(dev, "platform data for ad714x doesn't exist\n");
                error = -EINVAL;
                goto err_out;
index 0735de3a6468f85cad2c08a1dc601d5a67a67a23..86c9ec48804f75400eded459f287d190cde03ce6 100644 (file)
 
 /* ORIENT ADXL346 only */
 #define ADXL346_2D_VALID               (1 << 6)
-#define ADXL346_2D_ORIENT(x)           (((x) & 0x3) >> 4)
+#define ADXL346_2D_ORIENT(x)           (((x) & 0x30) >> 4)
 #define ADXL346_3D_VALID               (1 << 3)
 #define ADXL346_3D_ORIENT(x)           ((x) & 0x7)
 #define ADXL346_2D_PORTRAIT_POS                0       /* +X */
@@ -714,7 +714,7 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq,
 
        ac->fifo_delay = fifo_delay_default;
 
-       pdata = dev->platform_data;
+       pdata = dev_get_platdata(dev);
        if (!pdata) {
                dev_dbg(dev,
                        "No platform data: Using default initialization\n");
index 5d4402365a5207258dbd9b4b7d68f18489fa1598..d781b5e520655f074071fb6fc6f9a6e9390086bd 100644 (file)
@@ -28,8 +28,8 @@
 #include <linux/init.h>
 #include <linux/input.h>
 #include <linux/types.h>
+#include <linux/acpi.h>
 #include <asm/uaccess.h>
-#include <acpi/acpi_drivers.h>
 
 #define ACPI_ATLAS_NAME                "Atlas ACPI"
 #define ACPI_ATLAS_CLASS       "Atlas"
index cd139cb17e326dd6a740db877a2b85ef18344963..7703447d1fd9292dab4219f5236f9d97f7330f52 100644 (file)
@@ -92,7 +92,7 @@ static irqreturn_t bfin_rotary_isr(int irq, void *dev_id)
 
 static int bfin_rotary_probe(struct platform_device *pdev)
 {
-       struct bfin_rotary_platform_data *pdata = pdev->dev.platform_data;
+       struct bfin_rotary_platform_data *pdata = dev_get_platdata(&pdev->dev);
        struct bfin_rot *rotary;
        struct input_dev *input;
        int error;
index 865c2f9d25b9ff9cb55f63505852d89c06cf9687..52d3a9b28f0b80a253eb04584016b767c90c22cc 100644 (file)
@@ -526,7 +526,8 @@ static int bma150_register_polled_device(struct bma150_data *bma150)
 static int bma150_probe(struct i2c_client *client,
                                  const struct i2c_device_id *id)
 {
-       const struct bma150_platform_data *pdata = client->dev.platform_data;
+       const struct bma150_platform_data *pdata =
+                       dev_get_platdata(&client->dev);
        const struct bma150_cfg *cfg;
        struct bma150_data *bma150;
        int chip_id;
index df9b756594f80e54cd688faa51e7975c2bf5ff48..c7d00748277b1d34d7eaf98930ec14b8b16ce621 100644 (file)
@@ -284,7 +284,7 @@ EXPORT_SYMBOL(cma3000_resume);
 struct cma3000_accl_data *cma3000_init(struct device *dev, int irq,
                                       const struct cma3000_bus_ops *bops)
 {
-       const struct cma3000_platform_data *pdata = dev->platform_data;
+       const struct cma3000_platform_data *pdata = dev_get_platdata(dev);
        struct cma3000_accl_data *data;
        struct input_dev *input_dev;
        int rev;
index fe30bd0fe4bdc8fb6fda70d758ad23597f0aaf25..de21e317da32b6155142c76fc346acfbac14d7d7 100644 (file)
@@ -125,7 +125,7 @@ static int gp2a_initialize(struct gp2a_data *dt)
 static int gp2a_probe(struct i2c_client *client,
                                const struct i2c_device_id *id)
 {
-       const struct gp2a_platform_data *pdata = client->dev.platform_data;
+       const struct gp2a_platform_data *pdata = dev_get_platdata(&client->dev);
        struct gp2a_data *dt;
        int error;
 
diff --git a/drivers/input/misc/gpio-beeper.c b/drivers/input/misc/gpio-beeper.c
new file mode 100644 (file)
index 0000000..b757435
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Generic GPIO beeper driver
+ *
+ * Copyright (C) 2013 Alexander Shiyan <shc_work@mail.ru>
+ *
+ * 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/input.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+
+#define BEEPER_MODNAME         "gpio-beeper"
+
+struct gpio_beeper {
+       struct work_struct      work;
+       int                     gpio;
+       bool                    active_low;
+       bool                    beeping;
+};
+
+static void gpio_beeper_toggle(struct gpio_beeper *beep, bool on)
+{
+       gpio_set_value_cansleep(beep->gpio, on ^ beep->active_low);
+}
+
+static void gpio_beeper_work(struct work_struct *work)
+{
+       struct gpio_beeper *beep = container_of(work, struct gpio_beeper, work);
+
+       gpio_beeper_toggle(beep, beep->beeping);
+}
+
+static int gpio_beeper_event(struct input_dev *dev, unsigned int type,
+                            unsigned int code, int value)
+{
+       struct gpio_beeper *beep = input_get_drvdata(dev);
+
+       if (type != EV_SND || code != SND_BELL)
+               return -ENOTSUPP;
+
+       if (value < 0)
+               return -EINVAL;
+
+       beep->beeping = value;
+       /* Schedule work to actually turn the beeper on or off */
+       schedule_work(&beep->work);
+
+       return 0;
+}
+
+static void gpio_beeper_close(struct input_dev *input)
+{
+       struct gpio_beeper *beep = input_get_drvdata(input);
+
+       cancel_work_sync(&beep->work);
+       gpio_beeper_toggle(beep, false);
+}
+
+static int gpio_beeper_probe(struct platform_device *pdev)
+{
+       struct gpio_beeper *beep;
+       enum of_gpio_flags flags;
+       struct input_dev *input;
+       unsigned long gflags;
+       int err;
+
+       beep = devm_kzalloc(&pdev->dev, sizeof(*beep), GFP_KERNEL);
+       if (!beep)
+               return -ENOMEM;
+
+       beep->gpio = of_get_gpio_flags(pdev->dev.of_node, 0, &flags);
+       if (!gpio_is_valid(beep->gpio))
+               return beep->gpio;
+
+       input = devm_input_allocate_device(&pdev->dev);
+       if (!input)
+               return -ENOMEM;
+
+       INIT_WORK(&beep->work, gpio_beeper_work);
+
+       input->name             = pdev->name;
+       input->id.bustype       = BUS_HOST;
+       input->id.vendor        = 0x0001;
+       input->id.product       = 0x0001;
+       input->id.version       = 0x0100;
+       input->close            = gpio_beeper_close;
+       input->event            = gpio_beeper_event;
+
+       input_set_capability(input, EV_SND, SND_BELL);
+
+       beep->active_low = flags & OF_GPIO_ACTIVE_LOW;
+       gflags = beep->active_low ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
+
+       err = devm_gpio_request_one(&pdev->dev, beep->gpio, gflags, pdev->name);
+       if (err)
+               return err;
+
+       input_set_drvdata(input, beep);
+
+       return input_register_device(input);
+}
+
+static struct of_device_id gpio_beeper_of_match[] = {
+       { .compatible = BEEPER_MODNAME, },
+       { }
+};
+MODULE_DEVICE_TABLE(of, gpio_beeper_of_match);
+
+static struct platform_driver gpio_beeper_platform_driver = {
+       .driver = {
+               .name           = BEEPER_MODNAME,
+               .owner          = THIS_MODULE,
+               .of_match_table = gpio_beeper_of_match,
+       },
+       .probe  = gpio_beeper_probe,
+};
+module_platform_driver(gpio_beeper_platform_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>");
+MODULE_DESCRIPTION("Generic GPIO beeper driver");
index 714c68369134be4939b166421c0dcd5fbd38eeb8..38b3c11a8ae911405bc2711de658aecd373774ed 100644 (file)
@@ -98,7 +98,8 @@ static void gpio_tilt_polled_close(struct input_polled_dev *dev)
 
 static int gpio_tilt_polled_probe(struct platform_device *pdev)
 {
-       const struct gpio_tilt_platform_data *pdata = pdev->dev.platform_data;
+       const struct gpio_tilt_platform_data *pdata =
+                       dev_get_platdata(&pdev->dev);
        struct device *dev = &pdev->dev;
        struct gpio_tilt_polled_dev *tdev;
        struct input_polled_dev *poll_dev;
index a993b67a8a5b34a956272f2007c26d1c1da85022..d708478bc5b5d463299d2d1dc52eae01bba47cc8 100644 (file)
@@ -509,7 +509,8 @@ out:
 static int kxtj9_probe(struct i2c_client *client,
                                 const struct i2c_device_id *id)
 {
-       const struct kxtj9_platform_data *pdata = client->dev.platform_data;
+       const struct kxtj9_platform_data *pdata =
+                       dev_get_platdata(&client->dev);
        struct kxtj9_data *tj9;
        int err;
 
index e37392976fdd5f3f252ca5f2af2a2477fc8265b7..0deca5a3c87fe1adacdce8259a052738486749cb 100644 (file)
@@ -113,9 +113,12 @@ static int pcf8574_kp_probe(struct i2c_client *client, const struct i2c_device_i
        idev->keycodemax = ARRAY_SIZE(lp->btncode);
 
        for (i = 0; i < ARRAY_SIZE(pcf8574_kp_btncode); i++) {
-               lp->btncode[i] = pcf8574_kp_btncode[i];
-               __set_bit(lp->btncode[i] & KEY_MAX, idev->keybit);
+               if (lp->btncode[i] <= KEY_MAX) {
+                       lp->btncode[i] = pcf8574_kp_btncode[i];
+                       __set_bit(lp->btncode[i], idev->keybit);
+               }
        }
+       __clear_bit(KEY_RESERVED, idev->keybit);
 
        sprintf(lp->name, DRV_NAME);
        sprintf(lp->phys, "kp_data/input0");
index 940566e7be1322751689027166653845173d6004..8ef288e7c971e40ee687f5e358461c0b6402a784 100644 (file)
@@ -68,7 +68,7 @@ static int pwm_beeper_event(struct input_dev *input,
 
 static int pwm_beeper_probe(struct platform_device *pdev)
 {
-       unsigned long pwm_id = (unsigned long)pdev->dev.platform_data;
+       unsigned long pwm_id = (unsigned long)dev_get_platdata(&pdev->dev);
        struct pwm_beeper *beeper;
        int error;
 
index b9a05fda03e402c2d8e382626a890d6099604231..fb3b63b2f85c3615619452ef9ee2e6f0528d8245 100644 (file)
@@ -52,15 +52,15 @@ static irqreturn_t powerbutton_irq(int irq, void *_pwr)
        return IRQ_HANDLED;
 }
 
-static int __init twl4030_pwrbutton_probe(struct platform_device *pdev)
+static int twl4030_pwrbutton_probe(struct platform_device *pdev)
 {
        struct input_dev *pwr;
        int irq = platform_get_irq(pdev, 0);
        int err;
 
-       pwr = input_allocate_device();
+       pwr = devm_input_allocate_device(&pdev->dev);
        if (!pwr) {
-               dev_dbg(&pdev->dev, "Can't allocate power button\n");
+               dev_err(&pdev->dev, "Can't allocate power button\n");
                return -ENOMEM;
        }
 
@@ -70,52 +70,42 @@ static int __init twl4030_pwrbutton_probe(struct platform_device *pdev)
        pwr->phys = "twl4030_pwrbutton/input0";
        pwr->dev.parent = &pdev->dev;
 
-       err = request_threaded_irq(irq, NULL, powerbutton_irq,
+       err = devm_request_threaded_irq(&pwr->dev, irq, NULL, powerbutton_irq,
                        IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
                        "twl4030_pwrbutton", pwr);
        if (err < 0) {
-               dev_dbg(&pdev->dev, "Can't get IRQ for pwrbutton: %d\n", err);
-               goto free_input_dev;
+               dev_err(&pdev->dev, "Can't get IRQ for pwrbutton: %d\n", err);
+               return err;
        }
 
        err = input_register_device(pwr);
        if (err) {
-               dev_dbg(&pdev->dev, "Can't register power button: %d\n", err);
-               goto free_irq;
+               dev_err(&pdev->dev, "Can't register power button: %d\n", err);
+               return err;
        }
 
        platform_set_drvdata(pdev, pwr);
 
        return 0;
-
-free_irq:
-       free_irq(irq, pwr);
-free_input_dev:
-       input_free_device(pwr);
-       return err;
 }
 
-static int __exit twl4030_pwrbutton_remove(struct platform_device *pdev)
-{
-       struct input_dev *pwr = platform_get_drvdata(pdev);
-       int irq = platform_get_irq(pdev, 0);
-
-       free_irq(irq, pwr);
-       input_unregister_device(pwr);
-
-       return 0;
-}
+#ifdef CONFIG_OF
+static const struct of_device_id twl4030_pwrbutton_dt_match_table[] = {
+       { .compatible = "ti,twl4030-pwrbutton" },
+       {},
+};
+MODULE_DEVICE_TABLE(of, twl4030_pwrbutton_dt_match_table);
+#endif
 
 static struct platform_driver twl4030_pwrbutton_driver = {
-       .remove         = __exit_p(twl4030_pwrbutton_remove),
+       .probe          = twl4030_pwrbutton_probe,
        .driver         = {
                .name   = "twl4030_pwrbutton",
                .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(twl4030_pwrbutton_dt_match_table),
        },
 };
-
-module_platform_driver_probe(twl4030_pwrbutton_driver,
-                       twl4030_pwrbutton_probe);
+module_platform_driver(twl4030_pwrbutton_driver);
 
 MODULE_ALIAS("platform:twl4030_pwrbutton");
 MODULE_DESCRIPTION("Triton2 Power Button");
index 68a5f33152a8cd8914d39245257735d0e5ecae38..d993775a7c3908513698208b499bc51494ea2094 100644 (file)
@@ -193,7 +193,7 @@ static bool twl4030_vibra_check_coexist(struct twl4030_vibra_data *pdata,
 
 static int twl4030_vibra_probe(struct platform_device *pdev)
 {
-       struct twl4030_vibra_data *pdata = pdev->dev.platform_data;
+       struct twl4030_vibra_data *pdata = dev_get_platdata(&pdev->dev);
        struct device_node *twl4030_core_node = pdev->dev.parent->of_node;
        struct vibra_info *info;
        int ret;
index ca7a26f1dce81c37c6cd8524f8c4698effbfd739..5cf62e315218386817972a74aafcca22dc572113 100644 (file)
@@ -70,6 +70,25 @@ static const struct alps_nibble_commands alps_v4_nibble_commands[] = {
        { PSMOUSE_CMD_SETSCALE11,       0x00 }, /* f */
 };
 
+static const struct alps_nibble_commands alps_v6_nibble_commands[] = {
+       { PSMOUSE_CMD_ENABLE,           0x00 }, /* 0 */
+       { PSMOUSE_CMD_SETRATE,          0x0a }, /* 1 */
+       { PSMOUSE_CMD_SETRATE,          0x14 }, /* 2 */
+       { PSMOUSE_CMD_SETRATE,          0x28 }, /* 3 */
+       { PSMOUSE_CMD_SETRATE,          0x3c }, /* 4 */
+       { PSMOUSE_CMD_SETRATE,          0x50 }, /* 5 */
+       { PSMOUSE_CMD_SETRATE,          0x64 }, /* 6 */
+       { PSMOUSE_CMD_SETRATE,          0xc8 }, /* 7 */
+       { PSMOUSE_CMD_GETID,            0x00 }, /* 8 */
+       { PSMOUSE_CMD_GETINFO,          0x00 }, /* 9 */
+       { PSMOUSE_CMD_SETRES,           0x00 }, /* a */
+       { PSMOUSE_CMD_SETRES,           0x01 }, /* b */
+       { PSMOUSE_CMD_SETRES,           0x02 }, /* c */
+       { PSMOUSE_CMD_SETRES,           0x03 }, /* d */
+       { PSMOUSE_CMD_SETSCALE21,       0x00 }, /* e */
+       { PSMOUSE_CMD_SETSCALE11,       0x00 }, /* f */
+};
+
 
 #define ALPS_DUALPOINT         0x02    /* touchpad has trackstick */
 #define ALPS_PASS              0x04    /* device has a pass-through port */
@@ -103,6 +122,7 @@ static const struct alps_model_info alps_model_data[] = {
        /* Dell Latitude E5500, E6400, E6500, Precision M4400 */
        { { 0x62, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf,
                ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED },
+       { { 0x73, 0x00, 0x14 }, 0x00, ALPS_PROTO_V6, 0xff, 0xff, ALPS_DUALPOINT },              /* Dell XT2 */
        { { 0x73, 0x02, 0x50 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS },           /* Dell Vostro 1400 */
        { { 0x52, 0x01, 0x14 }, 0x00, ALPS_PROTO_V2, 0xff, 0xff,
                ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED },                            /* Toshiba Tecra A11-11L */
@@ -645,6 +665,76 @@ static void alps_process_packet_v3(struct psmouse *psmouse)
        alps_process_touchpad_packet_v3(psmouse);
 }
 
+static void alps_process_packet_v6(struct psmouse *psmouse)
+{
+       struct alps_data *priv = psmouse->private;
+       unsigned char *packet = psmouse->packet;
+       struct input_dev *dev = psmouse->dev;
+       struct input_dev *dev2 = priv->dev2;
+       int x, y, z, left, right, middle;
+
+       /*
+        * We can use Byte5 to distinguish if the packet is from Touchpad
+        * or Trackpoint.
+        * Touchpad:    0 - 0x7E
+        * Trackpoint:  0x7F
+        */
+       if (packet[5] == 0x7F) {
+               /* It should be a DualPoint when received Trackpoint packet */
+               if (!(priv->flags & ALPS_DUALPOINT))
+                       return;
+
+               /* Trackpoint packet */
+               x = packet[1] | ((packet[3] & 0x20) << 2);
+               y = packet[2] | ((packet[3] & 0x40) << 1);
+               z = packet[4];
+               left = packet[3] & 0x01;
+               right = packet[3] & 0x02;
+               middle = packet[3] & 0x04;
+
+               /* To prevent the cursor jump when finger lifted */
+               if (x == 0x7F && y == 0x7F && z == 0x7F)
+                       x = y = z = 0;
+
+               /* Divide 4 since trackpoint's speed is too fast */
+               input_report_rel(dev2, REL_X, (char)x / 4);
+               input_report_rel(dev2, REL_Y, -((char)y / 4));
+
+               input_report_key(dev2, BTN_LEFT, left);
+               input_report_key(dev2, BTN_RIGHT, right);
+               input_report_key(dev2, BTN_MIDDLE, middle);
+
+               input_sync(dev2);
+               return;
+       }
+
+       /* Touchpad packet */
+       x = packet[1] | ((packet[3] & 0x78) << 4);
+       y = packet[2] | ((packet[4] & 0x78) << 4);
+       z = packet[5];
+       left = packet[3] & 0x01;
+       right = packet[3] & 0x02;
+
+       if (z > 30)
+               input_report_key(dev, BTN_TOUCH, 1);
+       if (z < 25)
+               input_report_key(dev, BTN_TOUCH, 0);
+
+       if (z > 0) {
+               input_report_abs(dev, ABS_X, x);
+               input_report_abs(dev, ABS_Y, y);
+       }
+
+       input_report_abs(dev, ABS_PRESSURE, z);
+       input_report_key(dev, BTN_TOOL_FINGER, z > 0);
+
+       /* v6 touchpad does not have middle button */
+       input_report_key(dev, BTN_LEFT, left);
+       input_report_key(dev, BTN_RIGHT, right);
+
+       input_sync(dev);
+}
+
 static void alps_process_packet_v4(struct psmouse *psmouse)
 {
        struct alps_data *priv = psmouse->private;
@@ -897,7 +987,7 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
        }
 
        /* Bytes 2 - pktsize should have 0 in the highest bit */
-       if (priv->proto_version != ALPS_PROTO_V5 &&
+       if ((priv->proto_version < ALPS_PROTO_V5) &&
            psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize &&
            (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) {
                psmouse_dbg(psmouse, "refusing packet[%i] = %x\n",
@@ -1085,6 +1175,80 @@ static int alps_absolute_mode_v1_v2(struct psmouse *psmouse)
        return ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETPOLL);
 }
 
+static int alps_monitor_mode_send_word(struct psmouse *psmouse, u16 word)
+{
+       int i, nibble;
+
+       /*
+        * b0-b11 are valid bits, send sequence is inverse.
+        * e.g. when word = 0x0123, nibble send sequence is 3, 2, 1
+        */
+       for (i = 0; i <= 8; i += 4) {
+               nibble = (word >> i) & 0xf;
+               if (alps_command_mode_send_nibble(psmouse, nibble))
+                       return -1;
+       }
+
+       return 0;
+}
+
+static int alps_monitor_mode_write_reg(struct psmouse *psmouse,
+                                      u16 addr, u16 value)
+{
+       struct ps2dev *ps2dev = &psmouse->ps2dev;
+
+       /* 0x0A0 is the command to write the word */
+       if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE) ||
+           alps_monitor_mode_send_word(psmouse, 0x0A0) ||
+           alps_monitor_mode_send_word(psmouse, addr) ||
+           alps_monitor_mode_send_word(psmouse, value) ||
+           ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE))
+               return -1;
+
+       return 0;
+}
+
+static int alps_monitor_mode(struct psmouse *psmouse, bool enable)
+{
+       struct ps2dev *ps2dev = &psmouse->ps2dev;
+
+       if (enable) {
+               /* EC E9 F5 F5 E7 E6 E7 E9 to enter monitor mode */
+               if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) ||
+                   ps2_command(ps2dev, NULL, PSMOUSE_CMD_GETINFO) ||
+                   ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
+                   ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
+                   ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) ||
+                   ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
+                   ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) ||
+                   ps2_command(ps2dev, NULL, PSMOUSE_CMD_GETINFO))
+                       return -1;
+       } else {
+               /* EC to exit monitor mode */
+               if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP))
+                       return -1;
+       }
+
+       return 0;
+}
+
+static int alps_absolute_mode_v6(struct psmouse *psmouse)
+{
+       u16 reg_val = 0x181;
+       int ret = -1;
+
+       /* enter monitor mode, to write the register */
+       if (alps_monitor_mode(psmouse, true))
+               return -1;
+
+       ret = alps_monitor_mode_write_reg(psmouse, 0x000, reg_val);
+
+       if (alps_monitor_mode(psmouse, false))
+               ret = -1;
+
+       return ret;
+}
+
 static int alps_get_status(struct psmouse *psmouse, char *param)
 {
        /* Get status: 0xF5 0xF5 0xF5 0xE9 */
@@ -1189,6 +1353,32 @@ static int alps_hw_init_v1_v2(struct psmouse *psmouse)
        return 0;
 }
 
+static int alps_hw_init_v6(struct psmouse *psmouse)
+{
+       unsigned char param[2] = {0xC8, 0x14};
+
+       /* Enter passthrough mode to let trackpoint enter 6byte raw mode */
+       if (alps_passthrough_mode_v2(psmouse, true))
+               return -1;
+
+       if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
+           ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
+           ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
+           ps2_command(&psmouse->ps2dev, &param[0], PSMOUSE_CMD_SETRATE) ||
+           ps2_command(&psmouse->ps2dev, &param[1], PSMOUSE_CMD_SETRATE))
+               return -1;
+
+       if (alps_passthrough_mode_v2(psmouse, false))
+               return -1;
+
+       if (alps_absolute_mode_v6(psmouse)) {
+               psmouse_err(psmouse, "Failed to enable absolute mode\n");
+               return -1;
+       }
+
+       return 0;
+}
+
 /*
  * Enable or disable passthrough mode to the trackstick.
  */
@@ -1553,6 +1743,8 @@ static void alps_set_defaults(struct alps_data *priv)
                priv->hw_init = alps_hw_init_v1_v2;
                priv->process_packet = alps_process_packet_v1_v2;
                priv->set_abs_params = alps_set_abs_params_st;
+               priv->x_max = 1023;
+               priv->y_max = 767;
                break;
        case ALPS_PROTO_V3:
                priv->hw_init = alps_hw_init_v3;
@@ -1584,6 +1776,14 @@ static void alps_set_defaults(struct alps_data *priv)
                priv->x_bits = 23;
                priv->y_bits = 12;
                break;
+       case ALPS_PROTO_V6:
+               priv->hw_init = alps_hw_init_v6;
+               priv->process_packet = alps_process_packet_v6;
+               priv->set_abs_params = alps_set_abs_params_st;
+               priv->nibble_commands = alps_v6_nibble_commands;
+               priv->x_max = 2047;
+               priv->y_max = 1535;
+               break;
        }
 }
 
@@ -1705,8 +1905,8 @@ static void alps_disconnect(struct psmouse *psmouse)
 static void alps_set_abs_params_st(struct alps_data *priv,
                                   struct input_dev *dev1)
 {
-       input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0);
-       input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0);
+       input_set_abs_params(dev1, ABS_X, 0, priv->x_max, 0, 0);
+       input_set_abs_params(dev1, ABS_Y, 0, priv->y_max, 0, 0);
 }
 
 static void alps_set_abs_params_mt(struct alps_data *priv,
index eee59853b9ce0c21bc755c206430911e15789964..704f0f9243076190213b1c1876ef833348e61c99 100644 (file)
@@ -17,6 +17,7 @@
 #define ALPS_PROTO_V3  3
 #define ALPS_PROTO_V4  4
 #define ALPS_PROTO_V5  5
+#define ALPS_PROTO_V6  6
 
 /**
  * struct alps_model_info - touchpad ID table
index 8551dcaf24dbadc854a7f6a6664128598c99a067..597e9b8fc18db99c5bf1f33b3a274c632b2ba24b 100644 (file)
@@ -1313,6 +1313,7 @@ static int elantech_set_properties(struct elantech_data *etd)
                        break;
                case 6:
                case 7:
+               case 8:
                        etd->hw_version = 4;
                        break;
                default:
index 6b44413f54e357cd9201af5dc011bed845e1377d..6810a4626a2a5cb390a7c0c96e3a48127140aeed 100644 (file)
@@ -48,7 +48,7 @@ static void gpio_mouse_scan(struct input_polled_dev *dev)
 
 static int gpio_mouse_probe(struct platform_device *pdev)
 {
-       struct gpio_mouse_platform_data *pdata = pdev->dev.platform_data;
+       struct gpio_mouse_platform_data *pdata = dev_get_platdata(&pdev->dev);
        struct input_polled_dev *input_poll;
        struct input_dev *input;
        int pin, i;
index 0ecb9e7945eb0df7d8eb83031fbd39ed2f18355c..d20d2ae5f1ee695e324e67b9d74272f52829dba1 100644 (file)
@@ -166,7 +166,7 @@ static int pxa930_trkball_probe(struct platform_device *pdev)
        if (!trkball)
                return -ENOMEM;
 
-       trkball->pdata = pdev->dev.platform_data;
+       trkball->pdata = dev_get_platdata(&pdev->dev);
        if (!trkball->pdata) {
                dev_err(&pdev->dev, "no platform data defined\n");
                error = -EINVAL;
index 4e2fd44865e1cad4819db1a7f959912a76adaabf..b7c206db0df86fd34053f644b07e8b92abf2c4c0 100644 (file)
@@ -167,8 +167,6 @@ static int amba_kmi_remove(struct amba_device *dev)
 {
        struct amba_kmi_port *kmi = amba_get_drvdata(dev);
 
-       amba_set_drvdata(dev, NULL);
-
        serio_unregister_port(kmi->io);
        clk_put(kmi->clk);
        iounmap(kmi->base);
index 76f83836fd5a557b513eb8d3e91b2e964bfa5507..13062f667e82650467495702b35b038cff616130 100644 (file)
@@ -181,7 +181,6 @@ static void pcips2_remove(struct pci_dev *dev)
        struct pcips2_data *ps2if = pci_get_drvdata(dev);
 
        serio_unregister_port(ps2if->io);
-       pci_set_drvdata(dev, NULL);
        kfree(ps2if);
        pci_release_regions(dev);
        pci_disable_device(dev);
index 98707fb2cb5d672b6b5bcdc8b787bb37c90c9989..8f4c4ab04bc2d8c61d5fda2a65696806e61ad6f2 100644 (file)
@@ -455,16 +455,26 @@ static DEVICE_ATTR_RO(type);
 static DEVICE_ATTR_RO(proto);
 static DEVICE_ATTR_RO(id);
 static DEVICE_ATTR_RO(extra);
-static DEVICE_ATTR_RO(modalias);
-static DEVICE_ATTR_WO(drvctl);
-static DEVICE_ATTR(description, S_IRUGO, serio_show_description, NULL);
-static DEVICE_ATTR(bind_mode, S_IWUSR | S_IRUGO, serio_show_bind_mode, serio_set_bind_mode);
 
 static struct attribute *serio_device_id_attrs[] = {
        &dev_attr_type.attr,
        &dev_attr_proto.attr,
        &dev_attr_id.attr,
        &dev_attr_extra.attr,
+       NULL
+};
+
+static struct attribute_group serio_id_attr_group = {
+       .name   = "id",
+       .attrs  = serio_device_id_attrs,
+};
+
+static DEVICE_ATTR_RO(modalias);
+static DEVICE_ATTR_WO(drvctl);
+static DEVICE_ATTR(description, S_IRUGO, serio_show_description, NULL);
+static DEVICE_ATTR(bind_mode, S_IWUSR | S_IRUGO, serio_show_bind_mode, serio_set_bind_mode);
+
+static struct attribute *serio_device_attrs[] = {
        &dev_attr_modalias.attr,
        &dev_attr_description.attr,
        &dev_attr_drvctl.attr,
@@ -472,13 +482,13 @@ static struct attribute *serio_device_id_attrs[] = {
        NULL
 };
 
-static struct attribute_group serio_id_attr_group = {
-       .name   = "id",
-       .attrs  = serio_device_id_attrs,
+static struct attribute_group serio_device_attr_group = {
+       .attrs  = serio_device_attrs,
 };
 
 static const struct attribute_group *serio_device_attr_groups[] = {
        &serio_id_attr_group,
+       &serio_device_attr_group,
        NULL
 };
 
index 867e7c33ac55072b19f2ff339705c4e90f6b428d..8318826d976eabdc55a5cd1c13269d720901edcf 100644 (file)
@@ -304,7 +304,7 @@ static int wacom_parse_hid(struct usb_interface *intf,
        struct usb_device *dev = interface_to_usbdev(intf);
        char limit = 0;
        /* result has to be defined as int for some devices */
-       int result = 0;
+       int result = 0, touch_max = 0;
        int i = 0, usage = WCM_UNDEFINED, finger = 0, pen = 0;
        unsigned char *report;
 
@@ -351,7 +351,8 @@ static int wacom_parse_hid(struct usb_interface *intf,
                                if (usage == WCM_DESKTOP) {
                                        if (finger) {
                                                features->device_type = BTN_TOOL_FINGER;
-
+                                               /* touch device at least supports one touch point */
+                                               touch_max = 1;
                                                switch (features->type) {
                                                case TABLETPC2FG:
                                                        features->pktlen = WACOM_PKGLEN_TPC2FG;
@@ -504,6 +505,8 @@ static int wacom_parse_hid(struct usb_interface *intf,
        }
 
  out:
+       if (!features->touch_max && touch_max)
+               features->touch_max = touch_max;
        result = 0;
        kfree(report);
        return result;
@@ -1199,7 +1202,8 @@ static void wacom_wireless_work(struct work_struct *work)
                        goto fail;
 
                /* Touch interface */
-               if (wacom_wac1->features.touch_max) {
+               if (wacom_wac1->features.touch_max ||
+                   wacom_wac1->features.type == INTUOSHT) {
                        wacom_wac2->features =
                                *((struct wacom_features *)id->driver_info);
                        wacom_wac2->features.pktlen = WACOM_PKGLEN_BBTOUCH3;
@@ -1322,7 +1326,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 <= INTUOSPL) {
+       if (features->type >= INTUOS5S && features->type <= INTUOSHT) {
                if (endpoint->wMaxPacketSize == WACOM_PKGLEN_BBTOUCH3) {
                        features->device_type = BTN_TOOL_FINGER;
                        features->pktlen = WACOM_PKGLEN_BBTOUCH3;
@@ -1392,7 +1396,6 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
                        goto fail5;
                }
        }
-
        return 0;
 
  fail5: wacom_destroy_leds(wacom);
index 782c2535f1d81a26db96716ac406405b2b03a78b..7655088f78e0efc4bab45fa62cfc442230b460c1 100644 (file)
@@ -1151,8 +1151,8 @@ static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data)
                int width, height;
 
                if (features->type >= INTUOSPS && features->type <= INTUOSPL) {
-                       width  = data[5];
-                       height = data[6];
+                       width  = data[5] * 100;
+                       height = data[6] * 100;
                } else {
                        /*
                         * "a" is a scaled-down area which we assume is
@@ -1176,10 +1176,16 @@ static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data)
 static void wacom_bpt3_button_msg(struct wacom_wac *wacom, unsigned char *data)
 {
        struct input_dev *input = wacom->input;
+       struct wacom_features *features = &wacom->features;
 
-       input_report_key(input, BTN_LEFT, (data[1] & 0x08) != 0);
+       if (features->type == INTUOSHT) {
+               input_report_key(input, BTN_LEFT, (data[1] & 0x02) != 0);
+               input_report_key(input, BTN_BACK, (data[1] & 0x08) != 0);
+       } else {
+               input_report_key(input, BTN_BACK, (data[1] & 0x02) != 0);
+               input_report_key(input, BTN_LEFT, (data[1] & 0x08) != 0);
+       }
        input_report_key(input, BTN_FORWARD, (data[1] & 0x04) != 0);
-       input_report_key(input, BTN_BACK, (data[1] & 0x02) != 0);
        input_report_key(input, BTN_RIGHT, (data[1] & 0x01) != 0);
 }
 
@@ -1217,7 +1223,7 @@ static int wacom_bpt_pen(struct wacom_wac *wacom)
        unsigned char *data = wacom->data;
        int prox = 0, x = 0, y = 0, p = 0, d = 0, pen = 0, btn1 = 0, btn2 = 0;
 
-       if (data[0] != 0x02)
+       if (data[0] != WACOM_REPORT_PENABLED)
            return 0;
 
        prox = (data[1] & 0x20) == 0x20;
@@ -1297,7 +1303,7 @@ static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len)
        unsigned char *data = wacom->data;
        int connected;
 
-       if (len != WACOM_PKGLEN_WIRELESS || data[0] != 0x80)
+       if (len != WACOM_PKGLEN_WIRELESS || data[0] != WACOM_REPORT_WL)
                return 0;
 
        connected = data[1] & 0x01;
@@ -1391,6 +1397,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
                break;
 
        case BAMBOO_PT:
+       case INTUOSHT:
                sync = wacom_bpt_irq(wacom_wac, len);
                break;
 
@@ -1459,7 +1466,7 @@ void wacom_setup_device_quirks(struct wacom_features *features)
 
        /* these device have multiple inputs */
        if (features->type >= WIRELESS ||
-           (features->type >= INTUOS5S && features->type <= INTUOSPL) ||
+           (features->type >= INTUOS5S && features->type <= INTUOSHT) ||
            (features->oVid && features->oPid))
                features->quirks |= WACOM_QUIRK_MULTI_INPUT;
 
@@ -1771,33 +1778,43 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
                __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
                break;
 
+       case INTUOSHT:
        case BAMBOO_PT:
                __clear_bit(ABS_MISC, input_dev->absbit);
 
-               __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
-
                if (features->device_type == BTN_TOOL_FINGER) {
-                       unsigned int flags = INPUT_MT_POINTER;
 
                        __set_bit(BTN_LEFT, input_dev->keybit);
                        __set_bit(BTN_FORWARD, input_dev->keybit);
                        __set_bit(BTN_BACK, input_dev->keybit);
                        __set_bit(BTN_RIGHT, input_dev->keybit);
 
-                       if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) {
-                               input_set_abs_params(input_dev,
+                       if (features->touch_max) {
+                               /* touch interface */
+                               unsigned int flags = INPUT_MT_POINTER;
+
+                               __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
+                               if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) {
+                                       input_set_abs_params(input_dev,
                                                     ABS_MT_TOUCH_MAJOR,
                                                     0, features->x_max, 0, 0);
-                               input_set_abs_params(input_dev,
+                                       input_set_abs_params(input_dev,
                                                     ABS_MT_TOUCH_MINOR,
                                                     0, features->y_max, 0, 0);
+                               } else {
+                                       __set_bit(BTN_TOOL_FINGER, input_dev->keybit);
+                                       __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
+                                       flags = 0;
+                               }
+                               input_mt_init_slots(input_dev, features->touch_max, flags);
                        } else {
-                               __set_bit(BTN_TOOL_FINGER, input_dev->keybit);
-                               __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
-                               flags = 0;
+                               /* buttons/keys only interface */
+                               __clear_bit(ABS_X, input_dev->absbit);
+                               __clear_bit(ABS_Y, input_dev->absbit);
+                               __clear_bit(BTN_TOUCH, input_dev->keybit);
                        }
-                       input_mt_init_slots(input_dev, features->touch_max, flags);
                } else if (features->device_type == BTN_TOOL_PEN) {
+                       __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
                        __set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
                        __set_bit(BTN_TOOL_PEN, input_dev->keybit);
                        __set_bit(BTN_STYLUS, input_dev->keybit);
@@ -2200,6 +2217,17 @@ static const struct wacom_features wacom_features_0x300 =
 static const struct wacom_features wacom_features_0x301 =
        { "Wacom Bamboo One M",    WACOM_PKGLEN_BBPEN,    21648, 13530, 1023,
          31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x302 =
+       { "Wacom Intuos PT S",     WACOM_PKGLEN_BBPEN,    15200,  9500, 1023,
+         31, INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
+         .touch_max = 16 };
+static const struct wacom_features wacom_features_0x303 =
+       { "Wacom Intuos PT M",     WACOM_PKGLEN_BBPEN,    21600, 13500, 1023,
+         31, INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
+         .touch_max = 16 };
+static const struct wacom_features wacom_features_0x30E =
+       { "Wacom Intuos S",        WACOM_PKGLEN_BBPEN,    15200,  9500, 1023,
+         31, INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x6004 =
        { "ISD-V4",               WACOM_PKGLEN_GRAPHIRE,  12800,  8000,  255,
          0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
@@ -2337,6 +2365,9 @@ const struct usb_device_id wacom_ids[] = {
        { USB_DEVICE_WACOM(0x10F) },
        { USB_DEVICE_WACOM(0x300) },
        { USB_DEVICE_WACOM(0x301) },
+       { USB_DEVICE_DETAILED(0x302, USB_CLASS_HID, 0, 0) },
+       { USB_DEVICE_DETAILED(0x303, USB_CLASS_HID, 0, 0) },
+       { USB_DEVICE_DETAILED(0x30E, USB_CLASS_HID, 0, 0) },
        { USB_DEVICE_WACOM(0x304) },
        { USB_DEVICE_DETAILED(0x314, USB_CLASS_HID, 0, 0) },
        { USB_DEVICE_DETAILED(0x315, USB_CLASS_HID, 0, 0) },
index fd23a3790605070a41ec37f19eff051b0e89be5a..854cceb6d6deec48ba8da9432e57c6a83bd69043 100644 (file)
@@ -54,6 +54,7 @@
 #define WACOM_REPORT_TPCST             16
 #define WACOM_REPORT_TPC1FGE           18
 #define WACOM_REPORT_24HDT             1
+#define WACOM_REPORT_WL                        128
 
 /* device quirks */
 #define WACOM_QUIRK_MULTI_INPUT                0x0001
@@ -81,6 +82,7 @@ enum {
        INTUOSPS,
        INTUOSPM,
        INTUOSPL,
+       INTUOSHT,
        WACOM_21UX2,
        WACOM_22HD,
        DTK,
index f7de14a268bfc577b5dbc62abcccb3294de33f85..544e20c551f8360c4f355677af03bb638d034887 100644 (file)
@@ -172,7 +172,7 @@ static int pm860x_touch_dt_init(struct platform_device *pdev,
 static int pm860x_touch_probe(struct platform_device *pdev)
 {
        struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
-       struct pm860x_touch_pdata *pdata = pdev->dev.platform_data;
+       struct pm860x_touch_pdata *pdata = dev_get_platdata(&pdev->dev);
        struct pm860x_touch *touch;
        struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
                                 : chip->companion;
index 69834dd3c313b95dcab54dcd23d51a6730727868..b9f9bcb22683d2252d50fffef464de317fbd3be6 100644 (file)
@@ -686,7 +686,7 @@ static int ad7877_probe(struct spi_device *spi)
 {
        struct ad7877                   *ts;
        struct input_dev                *input_dev;
-       struct ad7877_platform_data     *pdata = spi->dev.platform_data;
+       struct ad7877_platform_data     *pdata = dev_get_platdata(&spi->dev);
        int                             err;
        u16                             verify;
 
index facd3057b62dcb4aa634c41a674197ad1c5871e2..a0364d8ae6c650b5e47f77b91b0085dc5534f824 100644 (file)
@@ -470,7 +470,7 @@ static int ad7879_gpio_add(struct ad7879 *ts,
 
 static void ad7879_gpio_remove(struct ad7879 *ts)
 {
-       const struct ad7879_platform_data *pdata = ts->dev->platform_data;
+       const struct ad7879_platform_data *pdata = dev_get_platdata(ts->dev);
        int ret;
 
        if (pdata->gpio_export) {
@@ -495,7 +495,7 @@ static inline void ad7879_gpio_remove(struct ad7879 *ts)
 struct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned int irq,
                            const struct ad7879_bus_ops *bops)
 {
-       struct ad7879_platform_data *pdata = dev->platform_data;
+       struct ad7879_platform_data *pdata = dev_get_platdata(dev);
        struct ad7879 *ts;
        struct input_dev *input_dev;
        int err;
index ea195360747ef7a27119f84dfce26dc4a9d12d3a..569578638233b6b49bd638916cfc5eb1ea55c13e 100644 (file)
@@ -101,7 +101,7 @@ struct ads7846 {
        struct spi_device       *spi;
        struct regulator        *reg;
 
-#if defined(CONFIG_HWMON) || defined(CONFIG_HWMON_MODULE)
+#if IS_ENABLED(CONFIG_HWMON)
        struct attribute_group  *attr_group;
        struct device           *hwmon;
 #endif
@@ -421,7 +421,7 @@ static int ads7845_read12_ser(struct device *dev, unsigned command)
        return status;
 }
 
-#if defined(CONFIG_HWMON) || defined(CONFIG_HWMON_MODULE)
+#if IS_ENABLED(CONFIG_HWMON)
 
 #define SHOW(name, var, adjust) static ssize_t \
 name ## _show(struct device *dev, struct device_attribute *attr, char *buf) \
index 59aa24002c7bff9e1f8629787c7c0ce9eea36886..37ea05741d209a00c0648748ede58ecde5e82448 100644 (file)
@@ -1130,7 +1130,7 @@ static void mxt_input_close(struct input_dev *dev)
 static int mxt_probe(struct i2c_client *client,
                const struct i2c_device_id *id)
 {
-       const struct mxt_platform_data *pdata = client->dev.platform_data;
+       const struct mxt_platform_data *pdata = dev_get_platdata(&client->dev);
        struct mxt_data *data;
        struct input_dev *input_dev;
        int error;
index bddabc5950778a793f04cdf6cbb9d3fe24bebcd1..f7d1ea5849ba46d4c977cc0d6e763ba4d6658f2a 100644 (file)
@@ -182,7 +182,7 @@ static int atmel_tsadcc_probe(struct platform_device *pdev)
        struct atmel_tsadcc     *ts_dev;
        struct input_dev        *input_dev;
        struct resource         *res;
-       struct at91_tsadcc_data *pdata = pdev->dev.platform_data;
+       struct at91_tsadcc_data *pdata = dev_get_platdata(&pdev->dev);
        int             err;
        unsigned int    prsc;
        unsigned int    reg;
index 8c651985a5c44929f083c99e881be5431bca9cad..5bf1aeeea8258e445b2a772befefcc75c160e103 100644 (file)
@@ -178,7 +178,7 @@ static irqreturn_t cy8ctmg110_irq_thread(int irq, void *dev_id)
 static int cy8ctmg110_probe(struct i2c_client *client,
                                        const struct i2c_device_id *id)
 {
-       const struct cy8ctmg110_pdata *pdata = client->dev.platform_data;
+       const struct cy8ctmg110_pdata *pdata = dev_get_platdata(&client->dev);
        struct cy8ctmg110 *ts;
        struct input_dev *input_dev;
        int err;
index 4204841cdc49743054f284cd4fcae8b7131255e8..eee656f77a2e3daa28a98727dbba5278026febc3 100644 (file)
@@ -534,7 +534,7 @@ static void cyttsp_close(struct input_dev *dev)
 struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops,
                            struct device *dev, int irq, size_t xfer_buf_size)
 {
-       const struct cyttsp_platform_data *pdata = dev->platform_data;
+       const struct cyttsp_platform_data *pdata = dev_get_platdata(dev);
        struct cyttsp *ts;
        struct input_dev *input_dev;
        int error;
@@ -553,7 +553,7 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops,
 
        ts->dev = dev;
        ts->input = input_dev;
-       ts->pdata = dev->platform_data;
+       ts->pdata = dev_get_platdata(dev);
        ts->bus_ops = bus_ops;
        ts->irq = irq;
 
index 34ad84105e6ee1a18718fe06b23ca379a6a0346f..ea0f7645220f09fc71bcbc8099de69a156ee9f88 100644 (file)
@@ -299,7 +299,7 @@ static void da9034_touch_close(struct input_dev *dev)
 
 static int da9034_touch_probe(struct platform_device *pdev)
 {
-       struct da9034_touch_pdata *pdata = pdev->dev.platform_data;
+       struct da9034_touch_pdata *pdata = dev_get_platdata(&pdev->dev);
        struct da9034_touch *touch;
        struct input_dev *input_dev;
        int ret;
index 83fa1b15a97f4f6a7ea5a78b6ab044485a08f957..af0d68b703b702528a59d6b81cc90bf043e44f75 100644 (file)
@@ -705,7 +705,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
                                         const struct i2c_device_id *id)
 {
        const struct edt_ft5x06_platform_data *pdata =
-                                               client->dev.platform_data;
+                                               dev_get_platdata(&client->dev);
        struct edt_ft5x06_ts_data *tsdata;
        struct input_dev *input;
        int error;
index 1ce3d29ffca5a11e2411936cce7999c089d68764..b1884ddd7a84fa74f41c7c7bae333dfce495914a 100644 (file)
@@ -157,7 +157,7 @@ static void eeti_ts_close(struct input_dev *dev)
 static int eeti_ts_probe(struct i2c_client *client,
                                   const struct i2c_device_id *idp)
 {
-       struct eeti_ts_platform_data *pdata = client->dev.platform_data;
+       struct eeti_ts_platform_data *pdata = dev_get_platdata(&client->dev);
        struct eeti_ts_priv *priv;
        struct input_dev *input;
        unsigned int irq_flags;
index 1418bdda61bbdde36df38a88eb434be57e3db6ab..2a50891398185545bf7e63fa1c82ad13072c0130 100644 (file)
@@ -184,7 +184,7 @@ static int ili210x_i2c_probe(struct i2c_client *client,
                                       const struct i2c_device_id *id)
 {
        struct device *dev = &client->dev;
-       const struct ili210x_platform_data *pdata = dev->platform_data;
+       const struct ili210x_platform_data *pdata = dev_get_platdata(dev);
        struct ili210x *priv;
        struct input_dev *input;
        struct panel_info panel;
index f9f4e0c56eda9fec33439bcd8a54913f3953e462..58486f135a4c3d5a675c09ef5263055295f69bf2 100644 (file)
@@ -194,7 +194,7 @@ static int mcs5000_ts_probe(struct i2c_client *client,
        struct input_dev *input_dev;
        int ret;
 
-       if (!client->dev.platform_data)
+       if (!dev_get_platdata(&client->dev))
                return -EINVAL;
 
        data = kzalloc(sizeof(struct mcs5000_ts_data), GFP_KERNEL);
@@ -207,7 +207,7 @@ static int mcs5000_ts_probe(struct i2c_client *client,
 
        data->client = client;
        data->input_dev = input_dev;
-       data->platform_data = client->dev.platform_data;
+       data->platform_data = dev_get_platdata(&client->dev);
 
        input_dev->name = "MELPAS MCS-5000 Touchscreen";
        input_dev->id.bustype = BUS_I2C;
index 6cc6b36663ffb188ff97b20714d0d4de39dbb833..02392d2061d6a01f304216ecfed1dc84b9de60a3 100644 (file)
@@ -128,7 +128,8 @@ static SIMPLE_DEV_PM_OPS(pixcir_dev_pm_ops,
 static int pixcir_i2c_ts_probe(struct i2c_client *client,
                                         const struct i2c_device_id *id)
 {
-       const struct pixcir_ts_platform_data *pdata = client->dev.platform_data;
+       const struct pixcir_ts_platform_data *pdata =
+                       dev_get_platdata(&client->dev);
        struct pixcir_i2c_ts_data *tsdata;
        struct input_dev *input;
        int error;
index b061af2c83768f2b0a7159c1707a78a6da55bc71..d32bd9e6d21540265c0d9a4d21299f8a6d7b35ec 100644 (file)
@@ -251,7 +251,7 @@ static int s3c2410ts_probe(struct platform_device *pdev)
 
        ts.dev = dev;
 
-       info = pdev->dev.platform_data;
+       info = dev_get_platdata(&pdev->dev);
        if (!info) {
                dev_err(dev, "no platform data, cannot attach\n");
                return -EINVAL;
@@ -392,7 +392,7 @@ static int s3c2410ts_suspend(struct device *dev)
 static int s3c2410ts_resume(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
-       struct s3c2410_ts_mach_info *info = pdev->dev.platform_data;
+       struct s3c2410_ts_mach_info *info = dev_get_platdata(&pdev->dev);
 
        clk_enable(ts.clock);
        enable_irq(ts.irq_tc);
index 2f03b2f289dd365fe3053338d09d049b7d724244..5c342b3139e8989ed737a91180cb6b3fa0f58f9c 100644 (file)
@@ -154,7 +154,7 @@ static int st1232_ts_probe(struct i2c_client *client,
                                        const struct i2c_device_id *id)
 {
        struct st1232_ts_data *ts;
-       struct st1232_pdata *pdata = client->dev.platform_data;
+       struct st1232_pdata *pdata = dev_get_platdata(&client->dev);
        struct input_dev *input_dev;
        int error;
 
index cfd1b7e8c0014306f09d021756e158ffc67ec728..f1cb05148b46826c7075e238f24e530a6a32720c 100644 (file)
@@ -251,7 +251,7 @@ static void sur40_poll(struct input_polled_dev *polldev)
        struct sur40_state *sur40 = polldev->private;
        struct input_dev *input = polldev->input;
        int result, bulk_read, need_blobs, packet_blobs, i;
-       u32 packet_id;
+       u32 uninitialized_var(packet_id);
 
        struct sur40_header *header = &sur40->bulk_in_buffer->header;
        struct sur40_blob *inblob = &sur40->bulk_in_buffer->blobs[0];
@@ -286,7 +286,7 @@ static void sur40_poll(struct input_polled_dev *polldev)
                if (need_blobs == -1) {
                        need_blobs = le16_to_cpu(header->count);
                        dev_dbg(sur40->dev, "need %d blobs\n", need_blobs);
-                       packet_id = header->packet_id;
+                       packet_id = le32_to_cpu(header->packet_id);
                }
 
                /*
index 811353353917d2b5f0440b8c5a5f5a704cd6c1e9..550adcbbfc2321b3110bf6a62d2c87805c6cabec 100644 (file)
@@ -571,7 +571,7 @@ static void tsc2005_setup_spi_xfer(struct tsc2005 *ts)
 
 static int tsc2005_probe(struct spi_device *spi)
 {
-       const struct tsc2005_platform_data *pdata = spi->dev.platform_data;
+       const struct tsc2005_platform_data *pdata = dev_get_platdata(&spi->dev);
        struct tsc2005 *ts;
        struct input_dev *input_dev;
        unsigned int max_x, max_y, max_p;
index 0b67ba476b4cdc204e6dc98aec29d006b217a4bc..1bf9906b5a3fc189276c39d065a2cc58b36ddbd3 100644 (file)
@@ -26,6 +26,9 @@
 #include <linux/interrupt.h>
 #include <linux/i2c.h>
 #include <linux/i2c/tsc2007.h>
+#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
 
 #define TSC2007_MEASURE_TEMP0          (0x0 << 4)
 #define TSC2007_MEASURE_AUX            (0x2 << 4)
@@ -72,15 +75,18 @@ struct tsc2007 {
        u16                     model;
        u16                     x_plate_ohms;
        u16                     max_rt;
-       unsigned long           poll_delay;
        unsigned long           poll_period;
+       int                     fuzzx;
+       int                     fuzzy;
+       int                     fuzzz;
 
+       unsigned                gpio;
        int                     irq;
 
        wait_queue_head_t       wait;
        bool                    stopped;
 
-       int                     (*get_pendown_state)(void);
+       int                     (*get_pendown_state)(struct device *);
        void                    (*clear_penirq)(void);
 };
 
@@ -161,7 +167,7 @@ static bool tsc2007_is_pen_down(struct tsc2007 *ts)
        if (!ts->get_pendown_state)
                return true;
 
-       return ts->get_pendown_state();
+       return ts->get_pendown_state(&ts->client->dev);
 }
 
 static irqreturn_t tsc2007_soft_irq(int irq, void *handle)
@@ -178,7 +184,7 @@ static irqreturn_t tsc2007_soft_irq(int irq, void *handle)
 
                rt = tsc2007_calculate_pressure(ts, &tc);
 
-               if (rt == 0 && !ts->get_pendown_state) {
+               if (!rt && !ts->get_pendown_state) {
                        /*
                         * If pressure reported is 0 and we don't have
                         * callback to check pendown state, we have to
@@ -228,7 +234,7 @@ static irqreturn_t tsc2007_hard_irq(int irq, void *handle)
 {
        struct tsc2007 *ts = handle;
 
-       if (!ts->get_pendown_state || likely(ts->get_pendown_state()))
+       if (tsc2007_is_pen_down(ts))
                return IRQ_WAKE_THREAD;
 
        if (ts->clear_penirq)
@@ -273,49 +279,134 @@ static void tsc2007_close(struct input_dev *input_dev)
        tsc2007_stop(ts);
 }
 
-static int tsc2007_probe(struct i2c_client *client,
-                                  const struct i2c_device_id *id)
+#ifdef CONFIG_OF
+static int tsc2007_get_pendown_state_gpio(struct device *dev)
 {
-       struct tsc2007 *ts;
-       struct tsc2007_platform_data *pdata = client->dev.platform_data;
-       struct input_dev *input_dev;
-       int err;
+       struct i2c_client *client = to_i2c_client(dev);
+       struct tsc2007 *ts = i2c_get_clientdata(client);
+
+       return !gpio_get_value(ts->gpio);
+}
+
+static int tsc2007_probe_dt(struct i2c_client *client, struct tsc2007 *ts)
+{
+       struct device_node *np = client->dev.of_node;
+       u32 val32;
+       u64 val64;
 
-       if (!pdata) {
-               dev_err(&client->dev, "platform data is required!\n");
+       if (!np) {
+               dev_err(&client->dev, "missing device tree data\n");
                return -EINVAL;
        }
 
-       if (!i2c_check_functionality(client->adapter,
-                                    I2C_FUNC_SMBUS_READ_WORD_DATA))
-               return -EIO;
+       if (!of_property_read_u32(np, "ti,max-rt", &val32))
+               ts->max_rt = val32;
+       else
+               ts->max_rt = MAX_12BIT;
+
+       if (!of_property_read_u32(np, "ti,fuzzx", &val32))
+               ts->fuzzx = val32;
+
+       if (!of_property_read_u32(np, "ti,fuzzy", &val32))
+               ts->fuzzy = val32;
+
+       if (!of_property_read_u32(np, "ti,fuzzz", &val32))
+               ts->fuzzz = val32;
+
+       if (!of_property_read_u64(np, "ti,poll-period", &val64))
+               ts->poll_period = val64;
+       else
+               ts->poll_period = 1;
 
-       ts = kzalloc(sizeof(struct tsc2007), GFP_KERNEL);
-       input_dev = input_allocate_device();
-       if (!ts || !input_dev) {
-               err = -ENOMEM;
-               goto err_free_mem;
+       if (!of_property_read_u32(np, "ti,x-plate-ohms", &val32)) {
+               ts->x_plate_ohms = val32;
+       } else {
+               dev_err(&client->dev, "missing ti,x-plate-ohms devicetree property.");
+               return -EINVAL;
        }
 
-       ts->client = client;
-       ts->irq = client->irq;
-       ts->input = input_dev;
-       init_waitqueue_head(&ts->wait);
+       ts->gpio = of_get_gpio(np, 0);
+       if (gpio_is_valid(ts->gpio))
+               ts->get_pendown_state = tsc2007_get_pendown_state_gpio;
+       else
+               dev_warn(&client->dev,
+                        "GPIO not specified in DT (of_get_gpio returned %d)\n",
+                        ts->gpio);
+
+       return 0;
+}
+#else
+static int tsc2007_probe_dt(struct i2c_client *client, struct tsc2007 *ts)
+{
+       dev_err(&client->dev, "platform data is required!\n");
+       return -EINVAL;
+}
+#endif
 
+static int tsc2007_probe_pdev(struct i2c_client *client, struct tsc2007 *ts,
+                             const struct tsc2007_platform_data *pdata,
+                             const struct i2c_device_id *id)
+{
        ts->model             = pdata->model;
        ts->x_plate_ohms      = pdata->x_plate_ohms;
        ts->max_rt            = pdata->max_rt ? : MAX_12BIT;
-       ts->poll_delay        = pdata->poll_delay ? : 1;
        ts->poll_period       = pdata->poll_period ? : 1;
        ts->get_pendown_state = pdata->get_pendown_state;
        ts->clear_penirq      = pdata->clear_penirq;
+       ts->fuzzx             = pdata->fuzzx;
+       ts->fuzzy             = pdata->fuzzy;
+       ts->fuzzz             = pdata->fuzzz;
 
        if (pdata->x_plate_ohms == 0) {
                dev_err(&client->dev, "x_plate_ohms is not set up in platform data");
-               err = -EINVAL;
-               goto err_free_mem;
+               return -EINVAL;
        }
 
+       return 0;
+}
+
+static void tsc2007_call_exit_platform_hw(void *data)
+{
+       struct device *dev = data;
+       const struct tsc2007_platform_data *pdata = dev_get_platdata(dev);
+
+       pdata->exit_platform_hw();
+}
+
+static int tsc2007_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
+{
+       const struct tsc2007_platform_data *pdata = dev_get_platdata(&client->dev);
+       struct tsc2007 *ts;
+       struct input_dev *input_dev;
+       int err;
+
+       if (!i2c_check_functionality(client->adapter,
+                                    I2C_FUNC_SMBUS_READ_WORD_DATA))
+               return -EIO;
+
+       ts = devm_kzalloc(&client->dev, sizeof(struct tsc2007), GFP_KERNEL);
+       if (!ts)
+               return -ENOMEM;
+
+       if (pdata)
+               err = tsc2007_probe_pdev(client, ts, pdata, id);
+       else
+               err = tsc2007_probe_dt(client, ts);
+       if (err)
+               return err;
+
+       input_dev = devm_input_allocate_device(&client->dev);
+       if (!input_dev)
+               return -ENOMEM;
+
+       i2c_set_clientdata(client, ts);
+
+       ts->client = client;
+       ts->irq = client->irq;
+       ts->input = input_dev;
+       init_waitqueue_head(&ts->wait);
+
        snprintf(ts->phys, sizeof(ts->phys),
                 "%s/input0", dev_name(&client->dev));
 
@@ -331,53 +422,46 @@ static int tsc2007_probe(struct i2c_client *client,
        input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
        input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
 
-       input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, pdata->fuzzx, 0);
-       input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, pdata->fuzzy, 0);
+       input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, ts->fuzzx, 0);
+       input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, ts->fuzzy, 0);
        input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT,
-                       pdata->fuzzz, 0);
+                            ts->fuzzz, 0);
+
+       if (pdata) {
+               if (pdata->exit_platform_hw) {
+                       err = devm_add_action(&client->dev,
+                                             tsc2007_call_exit_platform_hw,
+                                             &client->dev);
+                       if (err) {
+                               dev_err(&client->dev,
+                                       "Failed to register exit_platform_hw action, %d\n",
+                                       err);
+                               return err;
+                       }
+               }
 
-       if (pdata->init_platform_hw)
-               pdata->init_platform_hw();
+               if (pdata->init_platform_hw)
+                       pdata->init_platform_hw();
+       }
 
-       err = request_threaded_irq(ts->irq, tsc2007_hard_irq, tsc2007_soft_irq,
-                                  IRQF_ONESHOT, client->dev.driver->name, ts);
-       if (err < 0) {
-               dev_err(&client->dev, "irq %d busy?\n", ts->irq);
-               goto err_free_mem;
+       err = devm_request_threaded_irq(&client->dev, ts->irq,
+                                       tsc2007_hard_irq, tsc2007_soft_irq,
+                                       IRQF_ONESHOT,
+                                       client->dev.driver->name, ts);
+       if (err) {
+               dev_err(&client->dev, "Failed to request irq %d: %d\n",
+                       ts->irq, err);
+               return err;
        }
 
        tsc2007_stop(ts);
 
        err = input_register_device(input_dev);
-       if (err)
-               goto err_free_irq;
-
-       i2c_set_clientdata(client, ts);
-
-       return 0;
-
- err_free_irq:
-       free_irq(ts->irq, ts);
-       if (pdata->exit_platform_hw)
-               pdata->exit_platform_hw();
- err_free_mem:
-       input_free_device(input_dev);
-       kfree(ts);
-       return err;
-}
-
-static int tsc2007_remove(struct i2c_client *client)
-{
-       struct tsc2007  *ts = i2c_get_clientdata(client);
-       struct tsc2007_platform_data *pdata = client->dev.platform_data;
-
-       free_irq(ts->irq, ts);
-
-       if (pdata->exit_platform_hw)
-               pdata->exit_platform_hw();
-
-       input_unregister_device(ts->input);
-       kfree(ts);
+       if (err) {
+               dev_err(&client->dev,
+                       "Failed to register input device: %d\n", err);
+               return err;
+       }
 
        return 0;
 }
@@ -389,14 +473,22 @@ static const struct i2c_device_id tsc2007_idtable[] = {
 
 MODULE_DEVICE_TABLE(i2c, tsc2007_idtable);
 
+#ifdef CONFIG_OF
+static const struct of_device_id tsc2007_of_match[] = {
+       { .compatible = "ti,tsc2007" },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, tsc2007_of_match);
+#endif
+
 static struct i2c_driver tsc2007_driver = {
        .driver = {
                .owner  = THIS_MODULE,
-               .name   = "tsc2007"
+               .name   = "tsc2007",
+               .of_match_table = of_match_ptr(tsc2007_of_match),
        },
        .id_table       = tsc2007_idtable,
        .probe          = tsc2007_probe,
-       .remove         = tsc2007_remove,
 };
 
 module_i2c_driver(tsc2007_driver);
index 1271f97b40791bd983b6342bb3e2459bba9deef4..5b3ca807d179043fbda308a123ce2e82943113e6 100644 (file)
@@ -320,7 +320,7 @@ static int ucb1400_ts_detect_irq(struct ucb1400_ts *ucb,
 
 static int ucb1400_ts_probe(struct platform_device *pdev)
 {
-       struct ucb1400_ts *ucb = pdev->dev.platform_data;
+       struct ucb1400_ts *ucb = dev_get_platdata(&pdev->dev);
        int error, x_res, y_res;
        u16 fcsr;
 
@@ -399,7 +399,7 @@ err:
 
 static int ucb1400_ts_remove(struct platform_device *pdev)
 {
-       struct ucb1400_ts *ucb = pdev->dev.platform_data;
+       struct ucb1400_ts *ucb = dev_get_platdata(&pdev->dev);
 
        free_irq(ucb->irq, ucb);
        input_unregister_device(ucb->ts_idev);
@@ -410,7 +410,7 @@ static int ucb1400_ts_remove(struct platform_device *pdev)
 #ifdef CONFIG_PM_SLEEP
 static int ucb1400_ts_suspend(struct device *dev)
 {
-       struct ucb1400_ts *ucb = dev->platform_data;
+       struct ucb1400_ts *ucb = dev_get_platdata(dev);
        struct input_dev *idev = ucb->ts_idev;
 
        mutex_lock(&idev->mutex);
@@ -424,7 +424,7 @@ static int ucb1400_ts_suspend(struct device *dev)
 
 static int ucb1400_ts_resume(struct device *dev)
 {
-       struct ucb1400_ts *ucb = dev->platform_data;
+       struct ucb1400_ts *ucb = dev_get_platdata(dev);
        struct input_dev *idev = ucb->ts_idev;
 
        mutex_lock(&idev->mutex);
index ae4b6b9036292c23387fafb1124247fc377c3f72..5f87bed054674b487e724d3588806235b5b5f738 100644 (file)
@@ -106,6 +106,7 @@ struct usbtouch_device_info {
 struct usbtouch_usb {
        unsigned char *data;
        dma_addr_t data_dma;
+       int data_size;
        unsigned char *buffer;
        int buf_len;
        struct urb *irq;
@@ -1521,7 +1522,7 @@ static int usbtouch_reset_resume(struct usb_interface *intf)
 static void usbtouch_free_buffers(struct usb_device *udev,
                                  struct usbtouch_usb *usbtouch)
 {
-       usb_free_coherent(udev, usbtouch->type->rept_size,
+       usb_free_coherent(udev, usbtouch->data_size,
                          usbtouch->data, usbtouch->data_dma);
        kfree(usbtouch->buffer);
 }
@@ -1566,7 +1567,20 @@ static int usbtouch_probe(struct usb_interface *intf,
        if (!type->process_pkt)
                type->process_pkt = usbtouch_process_pkt;
 
-       usbtouch->data = usb_alloc_coherent(udev, type->rept_size,
+       usbtouch->data_size = type->rept_size;
+       if (type->get_pkt_len) {
+               /*
+                * When dealing with variable-length packets we should
+                * not request more than wMaxPacketSize bytes at once
+                * as we do not know if there is more data coming or
+                * we filled exactly wMaxPacketSize bytes and there is
+                * nothing else.
+                */
+               usbtouch->data_size = min(usbtouch->data_size,
+                                         usb_endpoint_maxp(endpoint));
+       }
+
+       usbtouch->data = usb_alloc_coherent(udev, usbtouch->data_size,
                                            GFP_KERNEL, &usbtouch->data_dma);
        if (!usbtouch->data)
                goto out_free;
@@ -1626,12 +1640,12 @@ static int usbtouch_probe(struct usb_interface *intf,
        if (usb_endpoint_type(endpoint) == USB_ENDPOINT_XFER_INT)
                usb_fill_int_urb(usbtouch->irq, udev,
                         usb_rcvintpipe(udev, endpoint->bEndpointAddress),
-                        usbtouch->data, type->rept_size,
+                        usbtouch->data, usbtouch->data_size,
                         usbtouch_irq, usbtouch, endpoint->bInterval);
        else
                usb_fill_bulk_urb(usbtouch->irq, udev,
                         usb_rcvbulkpipe(udev, endpoint->bEndpointAddress),
-                        usbtouch->data, type->rept_size,
+                        usbtouch->data, usbtouch->data_size,
                         usbtouch_irq, usbtouch);
 
        usbtouch->irq->dev = udev;
index 7e45c9f6e6b7426d69c90f82f3c8eb2c54a7a15f..d0ef91fc87d1cc67838056a77b5539fe10eef4ed 100644 (file)
@@ -584,7 +584,7 @@ static void wm97xx_ts_input_close(struct input_dev *idev)
 static int wm97xx_probe(struct device *dev)
 {
        struct wm97xx *wm;
-       struct wm97xx_pdata *pdata = dev->platform_data;
+       struct wm97xx_pdata *pdata = dev_get_platdata(dev);
        int ret = 0, id = 0;
 
        wm = kzalloc(sizeof(struct wm97xx), GFP_KERNEL);
index 8f798be6e398d98ccacc5ba85f3f5b76c4096683..28b4bea7c1094d79a483ee5256c21a91d3829396 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/msi.h>
 #include <linux/amd-iommu.h>
 #include <linux/export.h>
-#include <acpi/acpi.h>
 #include <asm/pci-direct.h>
 #include <asm/iommu.h>
 #include <asm/gart.h>
index 1abfb5684ab7ebcb7c735e10c71625439490ca09..e46a88700b6824c735967118281c9f7feb6e41b0 100644 (file)
@@ -392,7 +392,7 @@ struct arm_smmu_domain {
        struct arm_smmu_cfg             root_cfg;
        phys_addr_t                     output_mask;
 
-       spinlock_t                      lock;
+       struct mutex                    lock;
 };
 
 static DEFINE_SPINLOCK(arm_smmu_devices_lock);
@@ -900,7 +900,7 @@ static int arm_smmu_domain_init(struct iommu_domain *domain)
                goto out_free_domain;
        smmu_domain->root_cfg.pgd = pgd;
 
-       spin_lock_init(&smmu_domain->lock);
+       mutex_init(&smmu_domain->lock);
        domain->priv = smmu_domain;
        return 0;
 
@@ -1137,7 +1137,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
         * Sanity check the domain. We don't currently support domains
         * that cross between different SMMU chains.
         */
-       spin_lock(&smmu_domain->lock);
+       mutex_lock(&smmu_domain->lock);
        if (!smmu_domain->leaf_smmu) {
                /* Now that we have a master, we can finalise the domain */
                ret = arm_smmu_init_domain_context(domain, dev);
@@ -1152,7 +1152,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
                        dev_name(device_smmu->dev));
                goto err_unlock;
        }
-       spin_unlock(&smmu_domain->lock);
+       mutex_unlock(&smmu_domain->lock);
 
        /* Looks ok, so add the device to the domain */
        master = find_smmu_master(smmu_domain->leaf_smmu, dev->of_node);
@@ -1162,7 +1162,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
        return arm_smmu_domain_add_master(smmu_domain, master);
 
 err_unlock:
-       spin_unlock(&smmu_domain->lock);
+       mutex_unlock(&smmu_domain->lock);
        return ret;
 }
 
@@ -1394,7 +1394,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain,
        if (paddr & ~output_mask)
                return -ERANGE;
 
-       spin_lock(&smmu_domain->lock);
+       mutex_lock(&smmu_domain->lock);
        pgd += pgd_index(iova);
        end = iova + size;
        do {
@@ -1410,7 +1410,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain,
        } while (pgd++, iova != end);
 
 out_unlock:
-       spin_unlock(&smmu_domain->lock);
+       mutex_unlock(&smmu_domain->lock);
 
        /* Ensure new page tables are visible to the hardware walker */
        if (smmu->features & ARM_SMMU_FEAT_COHERENT_WALK)
@@ -1423,9 +1423,8 @@ static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova,
                        phys_addr_t paddr, size_t size, int flags)
 {
        struct arm_smmu_domain *smmu_domain = domain->priv;
-       struct arm_smmu_device *smmu = smmu_domain->leaf_smmu;
 
-       if (!smmu_domain || !smmu)
+       if (!smmu_domain)
                return -ENODEV;
 
        /* Check for silent address truncation up the SMMU chain. */
@@ -1449,44 +1448,34 @@ static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova,
 static phys_addr_t arm_smmu_iova_to_phys(struct iommu_domain *domain,
                                         dma_addr_t iova)
 {
-       pgd_t *pgd;
-       pud_t *pud;
-       pmd_t *pmd;
-       pte_t *pte;
+       pgd_t *pgdp, pgd;
+       pud_t pud;
+       pmd_t pmd;
+       pte_t pte;
        struct arm_smmu_domain *smmu_domain = domain->priv;
        struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg;
-       struct arm_smmu_device *smmu = root_cfg->smmu;
 
-       spin_lock(&smmu_domain->lock);
-       pgd = root_cfg->pgd;
-       if (!pgd)
-               goto err_unlock;
+       pgdp = root_cfg->pgd;
+       if (!pgdp)
+               return 0;
 
-       pgd += pgd_index(iova);
-       if (pgd_none_or_clear_bad(pgd))
-               goto err_unlock;
+       pgd = *(pgdp + pgd_index(iova));
+       if (pgd_none(pgd))
+               return 0;
 
-       pud = pud_offset(pgd, iova);
-       if (pud_none_or_clear_bad(pud))
-               goto err_unlock;
+       pud = *pud_offset(&pgd, iova);
+       if (pud_none(pud))
+               return 0;
 
-       pmd = pmd_offset(pud, iova);
-       if (pmd_none_or_clear_bad(pmd))
-               goto err_unlock;
+       pmd = *pmd_offset(&pud, iova);
+       if (pmd_none(pmd))
+               return 0;
 
-       pte = pmd_page_vaddr(*pmd) + pte_index(iova);
+       pte = *(pmd_page_vaddr(pmd) + pte_index(iova));
        if (pte_none(pte))
-               goto err_unlock;
-
-       spin_unlock(&smmu_domain->lock);
-       return __pfn_to_phys(pte_pfn(*pte)) | (iova & ~PAGE_MASK);
+               return 0;
 
-err_unlock:
-       spin_unlock(&smmu_domain->lock);
-       dev_warn(smmu->dev,
-                "invalid (corrupt?) page tables detected for iova 0x%llx\n",
-                (unsigned long long)iova);
-       return -EINVAL;
+       return __pfn_to_phys(pte_pfn(pte)) | (iova & ~PAGE_MASK);
 }
 
 static int arm_smmu_domain_has_cap(struct iommu_domain *domain,
@@ -1863,6 +1852,7 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
                dev_err(dev,
                        "found only %d context interrupt(s) but %d required\n",
                        smmu->num_context_irqs, smmu->num_context_banks);
+               err = -ENODEV;
                goto out_put_parent;
        }
 
index bab10b1002fbf04bae1fe8e2b36cbb6f280dea51..0cb7528b30a134416b4343b08a458f80dcb6aecf 100644 (file)
@@ -6,11 +6,11 @@
 #include <linux/hpet.h>
 #include <linux/pci.h>
 #include <linux/irq.h>
+#include <linux/intel-iommu.h>
+#include <linux/acpi.h>
 #include <asm/io_apic.h>
 #include <asm/smp.h>
 #include <asm/cpu.h>
-#include <linux/intel-iommu.h>
-#include <acpi/acpi.h>
 #include <asm/irq_remapping.h>
 #include <asm/pci-direct.h>
 #include <asm/msidef.h>
index 3792a1aa52b88d3439cdc66195230cc1b20f0f2a..07bc79c340125be220f7b667b9cb8e16db36d4ab 100644 (file)
@@ -61,3 +61,7 @@ config VERSATILE_FPGA_IRQ_NR
        int
        default 4
        depends on VERSATILE_FPGA_IRQ
+
+config XTENSA_MX
+       bool
+       select IRQ_DOMAIN
index c60b9010b152cf4980336eac485daa8bceec9412..679e2d102a296e84a60acdc9d24a3cbcffe7d5d5 100644 (file)
@@ -1,6 +1,7 @@
 obj-$(CONFIG_IRQCHIP)                  += irqchip.o
 
 obj-$(CONFIG_ARCH_BCM2835)             += irq-bcm2835.o
+obj-$(CONFIG_ARCH_DOVE)                        += irq-dove.o
 obj-$(CONFIG_ARCH_EXYNOS)              += exynos-combiner.o
 obj-$(CONFIG_ARCH_MMP)                 += irq-mmp.o
 obj-$(CONFIG_ARCH_MVEBU)               += irq-armada-370-xp.o
@@ -22,3 +23,5 @@ obj-$(CONFIG_RENESAS_IRQC)            += irq-renesas-irqc.o
 obj-$(CONFIG_VERSATILE_FPGA_IRQ)       += irq-versatile-fpga.o
 obj-$(CONFIG_ARCH_VT8500)              += irq-vt8500.o
 obj-$(CONFIG_TB10X_IRQC)               += irq-tb10x.o
+obj-$(CONFIG_XTENSA)                   += irq-xtensa-pic.o
+obj-$(CONFIG_XTENSA_MX)                        += irq-xtensa-mx.o
index 868ed40cb6bf070ba5b6b5a4156cda73f54fa9fa..40e6440348ff5d9ace76ff17510bbf40ae648415 100644 (file)
@@ -171,8 +171,7 @@ static struct irq_domain_ops combiner_irq_domain_ops = {
 
 static void __init combiner_init(void __iomem *combiner_base,
                                 struct device_node *np,
-                                unsigned int max_nr,
-                                int irq_base)
+                                unsigned int max_nr)
 {
        int i, irq;
        unsigned int nr_irq;
@@ -186,7 +185,7 @@ static void __init combiner_init(void __iomem *combiner_base,
                return;
        }
 
-       combiner_irq_domain = irq_domain_add_simple(np, nr_irq, irq_base,
+       combiner_irq_domain = irq_domain_add_linear(np, nr_irq,
                                &combiner_irq_domain_ops, combiner_data);
        if (WARN_ON(!combiner_irq_domain)) {
                pr_warning("%s: irq domain init failed\n", __func__);
@@ -207,7 +206,6 @@ static int __init combiner_of_init(struct device_node *np,
 {
        void __iomem *combiner_base;
        unsigned int max_nr = 20;
-       int irq_base = -1;
 
        combiner_base = of_iomap(np, 0);
        if (!combiner_base) {
@@ -221,14 +219,7 @@ static int __init combiner_of_init(struct device_node *np,
                        __func__, max_nr);
        }
 
-       /* 
-        * FIXME: This is a hardwired COMBINER_IRQ(0,0). Once all devices
-        * get their IRQ from DT, remove this in order to get dynamic
-        * allocation.
-        */
-       irq_base = 160;
-
-       combiner_init(combiner_base, np, max_nr, irq_base);
+       combiner_init(combiner_base, np, max_nr);
 
        return 0;
 }
diff --git a/drivers/irqchip/irq-dove.c b/drivers/irqchip/irq-dove.c
new file mode 100644 (file)
index 0000000..788acd8
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Marvell Dove SoCs PMU IRQ chip driver.
+ *
+ * Andrew Lunn <andrew@lunn.ch>
+ *
+ * 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.
+ */
+
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <asm/exception.h>
+#include <asm/mach/irq.h>
+
+#include "irqchip.h"
+
+#define DOVE_PMU_IRQ_CAUSE     0x00
+#define DOVE_PMU_IRQ_MASK      0x04
+
+static void dove_pmu_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+       struct irq_domain *d = irq_get_handler_data(irq);
+       struct irq_chip_generic *gc = irq_get_domain_generic_chip(d, 0);
+       u32 stat = readl_relaxed(gc->reg_base + DOVE_PMU_IRQ_CAUSE) &
+                  gc->mask_cache;
+
+       while (stat) {
+               u32 hwirq = ffs(stat) - 1;
+
+               generic_handle_irq(irq_find_mapping(d, gc->irq_base + hwirq));
+               stat &= ~(1 << hwirq);
+       }
+}
+
+static void pmu_irq_ack(struct irq_data *d)
+{
+       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+       struct irq_chip_type *ct = irq_data_get_chip_type(d);
+       u32 mask = ~d->mask;
+
+       /*
+        * The PMU mask register is not RW0C: it is RW.  This means that
+        * the bits take whatever value is written to them; if you write
+        * a '1', you will set the interrupt.
+        *
+        * Unfortunately this means there is NO race free way to clear
+        * these interrupts.
+        *
+        * So, let's structure the code so that the window is as small as
+        * possible.
+        */
+       irq_gc_lock(gc);
+       mask &= irq_reg_readl(gc->reg_base +  ct->regs.ack);
+       irq_reg_writel(mask, gc->reg_base +  ct->regs.ack);
+       irq_gc_unlock(gc);
+}
+
+static int __init dove_pmu_irq_init(struct device_node *np,
+                                   struct device_node *parent)
+{
+       unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
+       struct resource r;
+       struct irq_domain *domain;
+       struct irq_chip_generic *gc;
+       int ret, irq, nrirqs = 7;
+
+       domain = irq_domain_add_linear(np, nrirqs,
+                                      &irq_generic_chip_ops, NULL);
+       if (!domain) {
+               pr_err("%s: unable to add irq domain\n", np->name);
+               return -ENOMEM;
+       }
+
+       ret = irq_alloc_domain_generic_chips(domain, nrirqs, 1, np->name,
+                            handle_level_irq, clr, 0, IRQ_GC_INIT_MASK_CACHE);
+       if (ret) {
+               pr_err("%s: unable to alloc irq domain gc\n", np->name);
+               return ret;
+       }
+
+       ret = of_address_to_resource(np, 0, &r);
+       if (ret) {
+               pr_err("%s: unable to get resource\n", np->name);
+               return ret;
+       }
+
+       if (!request_mem_region(r.start, resource_size(&r), np->name)) {
+               pr_err("%s: unable to request mem region\n", np->name);
+               return -ENOMEM;
+       }
+
+       /* Map the parent interrupt for the chained handler */
+       irq = irq_of_parse_and_map(np, 0);
+       if (irq <= 0) {
+               pr_err("%s: unable to parse irq\n", np->name);
+               return -EINVAL;
+       }
+
+       gc = irq_get_domain_generic_chip(domain, 0);
+       gc->reg_base = ioremap(r.start, resource_size(&r));
+       if (!gc->reg_base) {
+               pr_err("%s: unable to map resource\n", np->name);
+               return -ENOMEM;
+       }
+
+       gc->chip_types[0].regs.ack = DOVE_PMU_IRQ_CAUSE;
+       gc->chip_types[0].regs.mask = DOVE_PMU_IRQ_MASK;
+       gc->chip_types[0].chip.irq_ack = pmu_irq_ack;
+       gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit;
+       gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit;
+
+       /* mask and clear all interrupts */
+       writel(0, gc->reg_base + DOVE_PMU_IRQ_MASK);
+       writel(0, gc->reg_base + DOVE_PMU_IRQ_CAUSE);
+
+       irq_set_handler_data(irq, domain);
+       irq_set_chained_handler(irq, dove_pmu_irq_handler);
+
+       return 0;
+}
+IRQCHIP_DECLARE(dove_pmu_intc,
+               "marvell,dove-pmu-intc", dove_pmu_irq_init);
index 9031171c141b52c5e9175fdbf6eec9bd0c4224b3..341c6016812de0e17fbd4c1601708723409351c5 100644 (file)
@@ -957,12 +957,13 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
        if (WARN_ON(!gic->domain))
                return;
 
+       if (gic_nr == 0) {
 #ifdef CONFIG_SMP
-       set_smp_cross_call(gic_raise_softirq);
-       register_cpu_notifier(&gic_cpu_notifier);
+               set_smp_cross_call(gic_raise_softirq);
+               register_cpu_notifier(&gic_cpu_notifier);
 #endif
-
-       set_handle_irq(gic_handle_irq);
+               set_handle_irq(gic_handle_irq);
+       }
 
        gic_chip.flags |= gic_arch_extn.flags;
        gic_dist_init(gic);
index 82cec63a90112e184c96a2e21e612df977adf7b7..3ee78f02e5d7d940d531aa6ab03c8dc681c9cb3c 100644 (file)
@@ -149,8 +149,9 @@ static void intc_irqpin_read_modify_write(struct intc_irqpin_priv *p,
 static void intc_irqpin_mask_unmask_prio(struct intc_irqpin_priv *p,
                                         int irq, int do_mask)
 {
-       int bitfield_width = 4; /* PRIO assumed to have fixed bitfield width */
-       int shift = (7 - irq) * bitfield_width; /* PRIO assumed to be 32-bit */
+       /* The PRIO register is assumed to be 32-bit with fixed 4-bit fields. */
+       int bitfield_width = 4;
+       int shift = 32 - (irq + 1) * bitfield_width;
 
        intc_irqpin_read_modify_write(p, INTC_IRQPIN_REG_PRIO,
                                      shift, bitfield_width,
@@ -159,8 +160,9 @@ static void intc_irqpin_mask_unmask_prio(struct intc_irqpin_priv *p,
 
 static int intc_irqpin_set_sense(struct intc_irqpin_priv *p, int irq, int value)
 {
+       /* The SENSE register is assumed to be 32-bit. */
        int bitfield_width = p->config.sense_bitfield_width;
-       int shift = (7 - irq) * bitfield_width; /* SENSE assumed to be 32-bit */
+       int shift = 32 - (irq + 1) * bitfield_width;
 
        dev_dbg(&p->pdev->dev, "sense irq = %d, mode = %d\n", irq, value);
 
diff --git a/drivers/irqchip/irq-xtensa-mx.c b/drivers/irqchip/irq-xtensa-mx.c
new file mode 100644 (file)
index 0000000..f693f1b
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * Xtensa MX interrupt distributor
+ *
+ * Copyright (C) 2002 - 2013 Tensilica, Inc.
+ *
+ * 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/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+
+#include <asm/mxregs.h>
+
+#include "irqchip.h"
+
+#define HW_IRQ_IPI_COUNT 2
+#define HW_IRQ_MX_BASE 2
+#define HW_IRQ_EXTERN_BASE 3
+
+static DEFINE_PER_CPU(unsigned int, cached_irq_mask);
+
+static int xtensa_mx_irq_map(struct irq_domain *d, unsigned int irq,
+               irq_hw_number_t hw)
+{
+       if (hw < HW_IRQ_IPI_COUNT) {
+               struct irq_chip *irq_chip = d->host_data;
+               irq_set_chip_and_handler_name(irq, irq_chip,
+                               handle_percpu_irq, "ipi");
+               irq_set_status_flags(irq, IRQ_LEVEL);
+               return 0;
+       }
+       return xtensa_irq_map(d, irq, hw);
+}
+
+/*
+ * Device Tree IRQ specifier translation function which works with one or
+ * two cell bindings. First cell value maps directly to the hwirq number.
+ * Second cell if present specifies whether hwirq number is external (1) or
+ * internal (0).
+ */
+static int xtensa_mx_irq_domain_xlate(struct irq_domain *d,
+               struct device_node *ctrlr,
+               const u32 *intspec, unsigned int intsize,
+               unsigned long *out_hwirq, unsigned int *out_type)
+{
+       return xtensa_irq_domain_xlate(intspec, intsize,
+                       intspec[0], intspec[0] + HW_IRQ_EXTERN_BASE,
+                       out_hwirq, out_type);
+}
+
+static const struct irq_domain_ops xtensa_mx_irq_domain_ops = {
+       .xlate = xtensa_mx_irq_domain_xlate,
+       .map = xtensa_mx_irq_map,
+};
+
+void secondary_init_irq(void)
+{
+       __this_cpu_write(cached_irq_mask,
+                       XCHAL_INTTYPE_MASK_EXTERN_EDGE |
+                       XCHAL_INTTYPE_MASK_EXTERN_LEVEL);
+       set_sr(XCHAL_INTTYPE_MASK_EXTERN_EDGE |
+                       XCHAL_INTTYPE_MASK_EXTERN_LEVEL, intenable);
+}
+
+static void xtensa_mx_irq_mask(struct irq_data *d)
+{
+       unsigned int mask = 1u << d->hwirq;
+
+       if (mask & (XCHAL_INTTYPE_MASK_EXTERN_EDGE |
+                               XCHAL_INTTYPE_MASK_EXTERN_LEVEL)) {
+               set_er(1u << (xtensa_get_ext_irq_no(d->hwirq) -
+                                       HW_IRQ_MX_BASE), MIENG);
+       } else {
+               mask = __this_cpu_read(cached_irq_mask) & ~mask;
+               __this_cpu_write(cached_irq_mask, mask);
+               set_sr(mask, intenable);
+       }
+}
+
+static void xtensa_mx_irq_unmask(struct irq_data *d)
+{
+       unsigned int mask = 1u << d->hwirq;
+
+       if (mask & (XCHAL_INTTYPE_MASK_EXTERN_EDGE |
+                               XCHAL_INTTYPE_MASK_EXTERN_LEVEL)) {
+               set_er(1u << (xtensa_get_ext_irq_no(d->hwirq) -
+                                       HW_IRQ_MX_BASE), MIENGSET);
+       } else {
+               mask |= __this_cpu_read(cached_irq_mask);
+               __this_cpu_write(cached_irq_mask, mask);
+               set_sr(mask, intenable);
+       }
+}
+
+static void xtensa_mx_irq_enable(struct irq_data *d)
+{
+       variant_irq_enable(d->hwirq);
+       xtensa_mx_irq_unmask(d);
+}
+
+static void xtensa_mx_irq_disable(struct irq_data *d)
+{
+       xtensa_mx_irq_mask(d);
+       variant_irq_disable(d->hwirq);
+}
+
+static void xtensa_mx_irq_ack(struct irq_data *d)
+{
+       set_sr(1 << d->hwirq, intclear);
+}
+
+static int xtensa_mx_irq_retrigger(struct irq_data *d)
+{
+       set_sr(1 << d->hwirq, intset);
+       return 1;
+}
+
+static int xtensa_mx_irq_set_affinity(struct irq_data *d,
+               const struct cpumask *dest, bool force)
+{
+       unsigned mask = 1u << cpumask_any(dest);
+
+       set_er(mask, MIROUT(d->hwirq - HW_IRQ_MX_BASE));
+       return 0;
+
+}
+
+static struct irq_chip xtensa_mx_irq_chip = {
+       .name           = "xtensa-mx",
+       .irq_enable     = xtensa_mx_irq_enable,
+       .irq_disable    = xtensa_mx_irq_disable,
+       .irq_mask       = xtensa_mx_irq_mask,
+       .irq_unmask     = xtensa_mx_irq_unmask,
+       .irq_ack        = xtensa_mx_irq_ack,
+       .irq_retrigger  = xtensa_mx_irq_retrigger,
+       .irq_set_affinity = xtensa_mx_irq_set_affinity,
+};
+
+int __init xtensa_mx_init_legacy(struct device_node *interrupt_parent)
+{
+       struct irq_domain *root_domain =
+               irq_domain_add_legacy(NULL, NR_IRQS, 0, 0,
+                               &xtensa_mx_irq_domain_ops,
+                               &xtensa_mx_irq_chip);
+       irq_set_default_host(root_domain);
+       secondary_init_irq();
+       return 0;
+}
+
+static int __init xtensa_mx_init(struct device_node *np,
+               struct device_node *interrupt_parent)
+{
+       struct irq_domain *root_domain =
+               irq_domain_add_linear(np, NR_IRQS, &xtensa_mx_irq_domain_ops,
+                               &xtensa_mx_irq_chip);
+       irq_set_default_host(root_domain);
+       secondary_init_irq();
+       return 0;
+}
+IRQCHIP_DECLARE(xtensa_mx_irq_chip, "cdns,xtensa-mx", xtensa_mx_init);
diff --git a/drivers/irqchip/irq-xtensa-pic.c b/drivers/irqchip/irq-xtensa-pic.c
new file mode 100644 (file)
index 0000000..7d71126
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Xtensa built-in interrupt controller
+ *
+ * Copyright (C) 2002 - 2013 Tensilica, Inc.
+ * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
+ *
+ * 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.
+ *
+ * Chris Zankel <chris@zankel.net>
+ * Kevin Chea
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+
+#include "irqchip.h"
+
+unsigned int cached_irq_mask;
+
+/*
+ * Device Tree IRQ specifier translation function which works with one or
+ * two cell bindings. First cell value maps directly to the hwirq number.
+ * Second cell if present specifies whether hwirq number is external (1) or
+ * internal (0).
+ */
+static int xtensa_pic_irq_domain_xlate(struct irq_domain *d,
+               struct device_node *ctrlr,
+               const u32 *intspec, unsigned int intsize,
+               unsigned long *out_hwirq, unsigned int *out_type)
+{
+       return xtensa_irq_domain_xlate(intspec, intsize,
+                       intspec[0], intspec[0],
+                       out_hwirq, out_type);
+}
+
+static const struct irq_domain_ops xtensa_irq_domain_ops = {
+       .xlate = xtensa_pic_irq_domain_xlate,
+       .map = xtensa_irq_map,
+};
+
+static void xtensa_irq_mask(struct irq_data *d)
+{
+       cached_irq_mask &= ~(1 << d->hwirq);
+       set_sr(cached_irq_mask, intenable);
+}
+
+static void xtensa_irq_unmask(struct irq_data *d)
+{
+       cached_irq_mask |= 1 << d->hwirq;
+       set_sr(cached_irq_mask, intenable);
+}
+
+static void xtensa_irq_enable(struct irq_data *d)
+{
+       variant_irq_enable(d->hwirq);
+       xtensa_irq_unmask(d);
+}
+
+static void xtensa_irq_disable(struct irq_data *d)
+{
+       xtensa_irq_mask(d);
+       variant_irq_disable(d->hwirq);
+}
+
+static void xtensa_irq_ack(struct irq_data *d)
+{
+       set_sr(1 << d->hwirq, intclear);
+}
+
+static int xtensa_irq_retrigger(struct irq_data *d)
+{
+       set_sr(1 << d->hwirq, intset);
+       return 1;
+}
+
+static struct irq_chip xtensa_irq_chip = {
+       .name           = "xtensa",
+       .irq_enable     = xtensa_irq_enable,
+       .irq_disable    = xtensa_irq_disable,
+       .irq_mask       = xtensa_irq_mask,
+       .irq_unmask     = xtensa_irq_unmask,
+       .irq_ack        = xtensa_irq_ack,
+       .irq_retrigger  = xtensa_irq_retrigger,
+};
+
+int __init xtensa_pic_init_legacy(struct device_node *interrupt_parent)
+{
+       struct irq_domain *root_domain =
+               irq_domain_add_legacy(NULL, NR_IRQS, 0, 0,
+                               &xtensa_irq_domain_ops, &xtensa_irq_chip);
+       irq_set_default_host(root_domain);
+       return 0;
+}
+
+static int __init xtensa_pic_init(struct device_node *np,
+               struct device_node *interrupt_parent)
+{
+       struct irq_domain *root_domain =
+               irq_domain_add_linear(np, NR_IRQS, &xtensa_irq_domain_ops,
+                               &xtensa_irq_chip);
+       irq_set_default_host(root_domain);
+       return 0;
+}
+IRQCHIP_DECLARE(xtensa_irq_chip, "cdns,xtensa-pic", xtensa_pic_init);
index 1747a02a019a1bcb7ed1ac1d37c02babd2a8c99e..c0730d5c734d6ad805d2a589573da4dfbe53bb48 100644 (file)
@@ -17,7 +17,7 @@ config MISDN_DSP
 
          This module may be used for special applications that require
          cross connecting of bchannels, conferencing, dtmf decoding,
-         echo cancelation, tone generation, and Blowfish encryption and
+         echo cancellation, tone generation, and Blowfish encryption and
          decryption. It may use hardware features if available.
 
          E.g. it is required for PBX4Linux. Go to http://isdn.eversberg.eu
index 2848171b8576f3475c63b0669c5a9788d11e6069..b31d8e99c41992c77610fe5ca1694211035ea592 100644 (file)
@@ -82,22 +82,12 @@ static inline size_t sizeof_pwm_leds_priv(int num_leds)
                      (sizeof(struct led_pwm_data) * num_leds);
 }
 
-static struct led_pwm_priv *led_pwm_create_of(struct platform_device *pdev)
+static int led_pwm_create_of(struct platform_device *pdev,
+                            struct led_pwm_priv *priv)
 {
        struct device_node *node = pdev->dev.of_node;
        struct device_node *child;
-       struct led_pwm_priv *priv;
-       int count, ret;
-
-       /* count LEDs in this device, so we know how much to allocate */
-       count = of_get_child_count(node);
-       if (!count)
-               return NULL;
-
-       priv = devm_kzalloc(&pdev->dev, sizeof_pwm_leds_priv(count),
-                           GFP_KERNEL);
-       if (!priv)
-               return NULL;
+       int ret;
 
        for_each_child_of_node(node, child) {
                struct led_pwm_data *led_dat = &priv->leds[priv->num_leds];
@@ -109,6 +99,7 @@ static struct led_pwm_priv *led_pwm_create_of(struct platform_device *pdev)
                if (IS_ERR(led_dat->pwm)) {
                        dev_err(&pdev->dev, "unable to request PWM for %s\n",
                                led_dat->cdev.name);
+                       ret = PTR_ERR(led_dat->pwm);
                        goto err;
                }
                /* Get the period from PWM core when n*/
@@ -137,28 +128,36 @@ static struct led_pwm_priv *led_pwm_create_of(struct platform_device *pdev)
                priv->num_leds++;
        }
 
-       return priv;
+       return 0;
 err:
        while (priv->num_leds--)
                led_classdev_unregister(&priv->leds[priv->num_leds].cdev);
 
-       return NULL;
+       return ret;
 }
 
 static int led_pwm_probe(struct platform_device *pdev)
 {
        struct led_pwm_platform_data *pdata = dev_get_platdata(&pdev->dev);
        struct led_pwm_priv *priv;
-       int i, ret = 0;
+       int count, i;
+       int ret = 0;
+
+       if (pdata)
+               count = pdata->num_leds;
+       else
+               count = of_get_child_count(pdev->dev.of_node);
+
+       if (!count)
+               return -EINVAL;
 
-       if (pdata && pdata->num_leds) {
-               priv = devm_kzalloc(&pdev->dev,
-                                   sizeof_pwm_leds_priv(pdata->num_leds),
-                                   GFP_KERNEL);
-               if (!priv)
-                       return -ENOMEM;
+       priv = devm_kzalloc(&pdev->dev, sizeof_pwm_leds_priv(count),
+                           GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
 
-               for (i = 0; i < pdata->num_leds; i++) {
+       if (pdata) {
+               for (i = 0; i < count; i++) {
                        struct led_pwm *cur_led = &pdata->leds[i];
                        struct led_pwm_data *led_dat = &priv->leds[i];
 
@@ -188,11 +187,11 @@ static int led_pwm_probe(struct platform_device *pdev)
                        if (ret < 0)
                                goto err;
                }
-               priv->num_leds = pdata->num_leds;
+               priv->num_leds = count;
        } else {
-               priv = led_pwm_create_of(pdev);
-               if (!priv)
-                       return -ENODEV;
+               ret = led_pwm_create_of(pdev, priv);
+               if (ret)
+                       return ret;
        }
 
        platform_set_drvdata(pdev, priv);
index d26a312f117aefbfa41dc8bbff377c5b53db345c..3067d56b11a6b6af70ac980ec42d1e8846dd87ca 100644 (file)
@@ -32,7 +32,7 @@ config ADB_MACII
 
 config ADB_MACIISI
        bool "Include Mac IIsi ADB driver"
-       depends on ADB && MAC
+       depends on ADB && MAC && BROKEN
        help
          Say Y here if want your kernel to support Macintosh systems that use
          the Mac IIsi style ADB.  This includes the IIsi, IIvi, IIvx, Classic
index 9ef32b3df91f060b0b85d399d207faad7c072384..590214ba736c1778181f3a75cccd1aed0d2f71f9 100644 (file)
@@ -133,7 +133,7 @@ static int wf_lm75_probe(struct i2c_client *client,
        lm->inited = 0;
        lm->ds1775 = ds1775;
        lm->i2c = client;
-       lm->sens.name = (char *)name; /* XXX fix constness in structure */
+       lm->sens.name = name;
        lm->sens.ops = &wf_lm75_ops;
        i2c_set_clientdata(client, lm);
 
index 945a25b2f31ea78b82a746d6beff6407341e5db4..87e439b10318de19bcafe544350c0268d444702a 100644 (file)
@@ -95,7 +95,7 @@ static int wf_max6690_probe(struct i2c_client *client,
        }
 
        max->i2c = client;
-       max->sens.name = (char *)name; /* XXX fix constness in structure */
+       max->sens.name = name;
        max->sens.ops = &wf_max6690_ops;
        i2c_set_clientdata(client, max);
 
index 4beb55a0ff30dc9da10c340270e9cbd1c0e1c0b0..964353c5329d4d997ca16aae8c4bfdf72b7b816e 100644 (file)
@@ -279,7 +279,6 @@ struct bcache_device {
        unsigned long           sectors_dirty_last;
        long                    sectors_dirty_derivative;
 
-       mempool_t               *unaligned_bvec;
        struct bio_set          *bio_split;
 
        unsigned                data_csum:1;
@@ -902,7 +901,6 @@ void bch_bbio_endio(struct cache_set *, struct bio *, int, const char *);
 void bch_bbio_free(struct bio *, struct cache_set *);
 struct bio *bch_bbio_alloc(struct cache_set *);
 
-struct bio *bch_bio_split(struct bio *, int, gfp_t, struct bio_set *);
 void bch_generic_make_request(struct bio *, struct bio_split_pool *);
 void __bch_submit_bbio(struct bio *, struct cache_set *);
 void bch_submit_bbio(struct bio *, struct cache_set *, struct bkey *, unsigned);
index 5e2765aadce174e9b7cffd479667a2c48bcf500f..b62f3792537454c13cd7ba7c881428a54e8cbfa4 100644 (file)
@@ -299,7 +299,7 @@ void bch_btree_node_read(struct btree *b)
 
        bio = bch_bbio_alloc(b->c);
        bio->bi_rw      = REQ_META|READ_SYNC;
-       bio->bi_size    = KEY_SIZE(&b->key) << 9;
+       bio->bi_iter.bi_size = KEY_SIZE(&b->key) << 9;
        bio->bi_end_io  = btree_node_read_endio;
        bio->bi_private = &cl;
 
@@ -362,7 +362,7 @@ static void btree_node_write_done(struct closure *cl)
        struct bio_vec *bv;
        int n;
 
-       __bio_for_each_segment(bv, b->bio, n, 0)
+       bio_for_each_segment_all(bv, b->bio, n)
                __free_page(bv->bv_page);
 
        __btree_node_write_done(cl);
@@ -395,7 +395,7 @@ static void do_btree_node_write(struct btree *b)
        b->bio->bi_end_io       = btree_node_write_endio;
        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);
+       b->bio->bi_iter.bi_size = set_blocks(i, b->c) * block_bytes(b->c);
        bch_bio_map(b->bio, i);
 
        /*
@@ -421,7 +421,7 @@ static void do_btree_node_write(struct btree *b)
                struct bio_vec *bv;
                void *base = (void *) ((unsigned long) i & ~(PAGE_SIZE - 1));
 
-               bio_for_each_segment(bv, b->bio, j)
+               bio_for_each_segment_all(bv, b->bio, j)
                        memcpy(page_address(bv->bv_page),
                               base + j * PAGE_SIZE, PAGE_SIZE);
 
index 264fcfbd629016aa1ab890cce56de2699c49be70..03cb4d114e1624997d114a3ac4a131d80d3d90fb 100644 (file)
@@ -173,7 +173,8 @@ void bch_data_verify(struct cached_dev *dc, struct bio *bio)
 {
        char name[BDEVNAME_SIZE];
        struct bio *check;
-       struct bio_vec *bv;
+       struct bio_vec bv, *bv2;
+       struct bvec_iter iter;
        int i;
 
        check = bio_clone(bio, GFP_NOIO);
@@ -185,23 +186,23 @@ void bch_data_verify(struct cached_dev *dc, struct bio *bio)
 
        submit_bio_wait(READ_SYNC, check);
 
-       bio_for_each_segment(bv, bio, i) {
-               void *p1 = kmap_atomic(bv->bv_page);
-               void *p2 = page_address(check->bi_io_vec[i].bv_page);
+       bio_for_each_segment(bv, bio, iter) {
+               void *p1 = kmap_atomic(bv.bv_page);
+               void *p2 = page_address(check->bi_io_vec[iter.bi_idx].bv_page);
 
-               cache_set_err_on(memcmp(p1 + bv->bv_offset,
-                                       p2 + bv->bv_offset,
-                                       bv->bv_len),
+               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);
+                                (uint64_t) bio->bi_iter.bi_sector);
 
                kunmap_atomic(p1);
        }
 
-       bio_for_each_segment_all(bv, check, i)
-               __free_page(bv->bv_page);
+       bio_for_each_segment_all(bv2, check, i)
+               __free_page(bv2->bv_page);
 out_put:
        bio_put(check);
 }
index 9056632995b1b8a2de9de607c60cd693704c9c65..fa028fa82df41bf509e15d140f9b3b943c5a8c2d 100644 (file)
 
 #include <linux/blkdev.h>
 
-static void bch_bi_idx_hack_endio(struct bio *bio, int error)
-{
-       struct bio *p = bio->bi_private;
-
-       bio_endio(p, error);
-       bio_put(bio);
-}
-
-static void bch_generic_make_request_hack(struct bio *bio)
-{
-       if (bio->bi_idx) {
-               struct bio *clone = bio_alloc(GFP_NOIO, bio_segments(bio));
-
-               memcpy(clone->bi_io_vec,
-                      bio_iovec(bio),
-                      bio_segments(bio) * sizeof(struct bio_vec));
-
-               clone->bi_sector        = bio->bi_sector;
-               clone->bi_bdev          = bio->bi_bdev;
-               clone->bi_rw            = bio->bi_rw;
-               clone->bi_vcnt          = bio_segments(bio);
-               clone->bi_size          = bio->bi_size;
-
-               clone->bi_private       = bio;
-               clone->bi_end_io        = bch_bi_idx_hack_endio;
-
-               bio = clone;
-       }
-
-       /*
-        * Hack, since drivers that clone bios clone up to bi_max_vecs, but our
-        * bios might have had more than that (before we split them per device
-        * limitations).
-        *
-        * To be taken out once immutable bvec stuff is in.
-        */
-       bio->bi_max_vecs = bio->bi_vcnt;
-
-       generic_make_request(bio);
-}
-
-/**
- * bch_bio_split - split a bio
- * @bio:       bio to split
- * @sectors:   number of sectors to split from the front of @bio
- * @gfp:       gfp mask
- * @bs:                bio set to allocate from
- *
- * Allocates and returns a new bio which represents @sectors from the start of
- * @bio, and updates @bio to represent the remaining sectors.
- *
- * If bio_sectors(@bio) was less than or equal to @sectors, returns @bio
- * unchanged.
- *
- * The newly allocated bio will point to @bio's bi_io_vec, if the split was on a
- * bvec boundry; it is the caller's responsibility to ensure that @bio is not
- * freed before the split.
- */
-struct bio *bch_bio_split(struct bio *bio, int sectors,
-                         gfp_t gfp, struct bio_set *bs)
-{
-       unsigned idx = bio->bi_idx, vcnt = 0, nbytes = sectors << 9;
-       struct bio_vec *bv;
-       struct bio *ret = NULL;
-
-       BUG_ON(sectors <= 0);
-
-       if (sectors >= bio_sectors(bio))
-               return bio;
-
-       if (bio->bi_rw & REQ_DISCARD) {
-               ret = bio_alloc_bioset(gfp, 1, bs);
-               if (!ret)
-                       return NULL;
-               idx = 0;
-               goto out;
-       }
-
-       bio_for_each_segment(bv, bio, idx) {
-               vcnt = idx - bio->bi_idx;
-
-               if (!nbytes) {
-                       ret = bio_alloc_bioset(gfp, vcnt, bs);
-                       if (!ret)
-                               return NULL;
-
-                       memcpy(ret->bi_io_vec, bio_iovec(bio),
-                              sizeof(struct bio_vec) * vcnt);
-
-                       break;
-               } else if (nbytes < bv->bv_len) {
-                       ret = bio_alloc_bioset(gfp, ++vcnt, bs);
-                       if (!ret)
-                               return NULL;
-
-                       memcpy(ret->bi_io_vec, bio_iovec(bio),
-                              sizeof(struct bio_vec) * vcnt);
-
-                       ret->bi_io_vec[vcnt - 1].bv_len = nbytes;
-                       bv->bv_offset   += nbytes;
-                       bv->bv_len      -= nbytes;
-                       break;
-               }
-
-               nbytes -= bv->bv_len;
-       }
-out:
-       ret->bi_bdev    = bio->bi_bdev;
-       ret->bi_sector  = bio->bi_sector;
-       ret->bi_size    = sectors << 9;
-       ret->bi_rw      = bio->bi_rw;
-       ret->bi_vcnt    = vcnt;
-       ret->bi_max_vecs = vcnt;
-
-       bio->bi_sector  += sectors;
-       bio->bi_size    -= sectors << 9;
-       bio->bi_idx      = idx;
-
-       if (bio_integrity(bio)) {
-               if (bio_integrity_clone(ret, bio, gfp)) {
-                       bio_put(ret);
-                       return NULL;
-               }
-
-               bio_integrity_trim(ret, 0, bio_sectors(ret));
-               bio_integrity_trim(bio, bio_sectors(ret), bio_sectors(bio));
-       }
-
-       return ret;
-}
-
 static unsigned bch_bio_max_sectors(struct bio *bio)
 {
-       unsigned ret = bio_sectors(bio);
        struct request_queue *q = bdev_get_queue(bio->bi_bdev);
-       unsigned max_segments = min_t(unsigned, BIO_MAX_PAGES,
-                                     queue_max_segments(q));
+       struct bio_vec bv;
+       struct bvec_iter iter;
+       unsigned ret = 0, seg = 0;
 
        if (bio->bi_rw & REQ_DISCARD)
-               return min(ret, q->limits.max_discard_sectors);
-
-       if (bio_segments(bio) > max_segments ||
-           q->merge_bvec_fn) {
-               struct bio_vec *bv;
-               int i, seg = 0;
-
-               ret = 0;
-
-               bio_for_each_segment(bv, bio, i) {
-                       struct bvec_merge_data bvm = {
-                               .bi_bdev        = bio->bi_bdev,
-                               .bi_sector      = bio->bi_sector,
-                               .bi_size        = ret << 9,
-                               .bi_rw          = bio->bi_rw,
-                       };
-
-                       if (seg == max_segments)
-                               break;
+               return min(bio_sectors(bio), q->limits.max_discard_sectors);
+
+       bio_for_each_segment(bv, bio, iter) {
+               struct bvec_merge_data bvm = {
+                       .bi_bdev        = bio->bi_bdev,
+                       .bi_sector      = bio->bi_iter.bi_sector,
+                       .bi_size        = ret << 9,
+                       .bi_rw          = bio->bi_rw,
+               };
+
+               if (seg == min_t(unsigned, BIO_MAX_PAGES,
+                                queue_max_segments(q)))
+                       break;
 
-                       if (q->merge_bvec_fn &&
-                           q->merge_bvec_fn(q, &bvm, bv) < (int) bv->bv_len)
-                               break;
+               if (q->merge_bvec_fn &&
+                   q->merge_bvec_fn(q, &bvm, &bv) < (int) bv.bv_len)
+                       break;
 
-                       seg++;
-                       ret += bv->bv_len >> 9;
-               }
+               seg++;
+               ret += bv.bv_len >> 9;
        }
 
        ret = min(ret, queue_max_sectors(q));
 
        WARN_ON(!ret);
-       ret = max_t(int, ret, bio_iovec(bio)->bv_len >> 9);
+       ret = max_t(int, ret, bio_iovec(bio).bv_len >> 9);
 
        return ret;
 }
@@ -193,7 +55,7 @@ static void bch_bio_submit_split_done(struct closure *cl)
 
        s->bio->bi_end_io = s->bi_end_io;
        s->bio->bi_private = s->bi_private;
-       bio_endio(s->bio, 0);
+       bio_endio_nodec(s->bio, 0);
 
        closure_debug_destroy(&s->cl);
        mempool_free(s, s->p->bio_split_hook);
@@ -232,19 +94,19 @@ void bch_generic_make_request(struct bio *bio, struct bio_split_pool *p)
        bio_get(bio);
 
        do {
-               n = bch_bio_split(bio, bch_bio_max_sectors(bio),
-                                 GFP_NOIO, s->p->bio_split);
+               n = bio_next_split(bio, bch_bio_max_sectors(bio),
+                                  GFP_NOIO, s->p->bio_split);
 
                n->bi_end_io    = bch_bio_submit_split_endio;
                n->bi_private   = &s->cl;
 
                closure_get(&s->cl);
-               bch_generic_make_request_hack(n);
+               generic_make_request(n);
        } while (n != bio);
 
        continue_at(&s->cl, bch_bio_submit_split_done, NULL);
 submit:
-       bch_generic_make_request_hack(bio);
+       generic_make_request(bio);
 }
 
 /* Bios with headers */
@@ -272,8 +134,8 @@ void __bch_submit_bbio(struct bio *bio, struct cache_set *c)
 {
        struct bbio *b = container_of(bio, struct bbio, bio);
 
-       bio->bi_sector  = PTR_OFFSET(&b->key, 0);
-       bio->bi_bdev    = PTR_CACHE(c, &b->key, 0)->bdev;
+       bio->bi_iter.bi_sector  = PTR_OFFSET(&b->key, 0);
+       bio->bi_bdev            = PTR_CACHE(c, &b->key, 0)->bdev;
 
        b->submit_time_us = local_clock_us();
        closure_bio_submit(bio, bio->bi_private, PTR_CACHE(c, &b->key, 0));
index ecdaa671bd50457bf38d1cf9f896ffd1c8352546..7eafdf09a0ae11cb1c4108926e4d1c51ac90c9f4 100644 (file)
@@ -51,10 +51,10 @@ reread:             left = ca->sb.bucket_size - offset;
                len = min_t(unsigned, left, PAGE_SECTORS * 8);
 
                bio_reset(bio);
-               bio->bi_sector  = bucket + offset;
+               bio->bi_iter.bi_sector  = bucket + offset;
                bio->bi_bdev    = ca->bdev;
                bio->bi_rw      = READ;
-               bio->bi_size    = len << 9;
+               bio->bi_iter.bi_size    = len << 9;
 
                bio->bi_end_io  = journal_read_endio;
                bio->bi_private = &cl;
@@ -437,13 +437,13 @@ static void do_journal_discard(struct cache *ca)
                atomic_set(&ja->discard_in_flight, DISCARD_IN_FLIGHT);
 
                bio_init(bio);
-               bio->bi_sector          = bucket_to_sector(ca->set,
+               bio->bi_iter.bi_sector  = bucket_to_sector(ca->set,
                                                ca->sb.d[ja->discard_idx]);
                bio->bi_bdev            = ca->bdev;
                bio->bi_rw              = REQ_WRITE|REQ_DISCARD;
                bio->bi_max_vecs        = 1;
                bio->bi_io_vec          = bio->bi_inline_vecs;
-               bio->bi_size            = bucket_bytes(ca);
+               bio->bi_iter.bi_size    = bucket_bytes(ca);
                bio->bi_end_io          = journal_discard_endio;
 
                closure_get(&ca->set->cl);
@@ -608,10 +608,10 @@ static void journal_write_unlocked(struct closure *cl)
                atomic_long_add(sectors, &ca->meta_sectors_written);
 
                bio_reset(bio);
-               bio->bi_sector  = PTR_OFFSET(k, i);
+               bio->bi_iter.bi_sector  = PTR_OFFSET(k, i);
                bio->bi_bdev    = ca->bdev;
                bio->bi_rw      = REQ_WRITE|REQ_SYNC|REQ_META|REQ_FLUSH|REQ_FUA;
-               bio->bi_size    = sectors << 9;
+               bio->bi_iter.bi_size = sectors << 9;
 
                bio->bi_end_io  = journal_write_endio;
                bio->bi_private = w;
index 7c1275e66025b691ec8ee4896448d46e28a2c5d9..581f95df8265579e94a9546d84644be8deb335c2 100644 (file)
@@ -82,7 +82,7 @@ static void moving_init(struct moving_io *io)
        bio_get(bio);
        bio_set_prio(bio, IOPRIO_PRIO_VALUE(IOPRIO_CLASS_IDLE, 0));
 
-       bio->bi_size            = KEY_SIZE(&io->w->key) << 9;
+       bio->bi_iter.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->cl;
@@ -98,7 +98,7 @@ static void write_moving(struct closure *cl)
        if (!op->error) {
                moving_init(io);
 
-               io->bio.bio.bi_sector = KEY_START(&io->w->key);
+               io->bio.bio.bi_iter.bi_sector = KEY_START(&io->w->key);
                op->write_prio          = 1;
                op->bio                 = &io->bio.bio;
 
index fbcc851ed5a5a74b09d763c455d132dee68e7eb3..5878cdb3952948d78e029f4ed0a343d7a7807cab 100644 (file)
@@ -198,14 +198,14 @@ static bool verify(struct cached_dev *dc, struct bio *bio)
 
 static void bio_csum(struct bio *bio, struct bkey *k)
 {
-       struct bio_vec *bv;
+       struct bio_vec bv;
+       struct bvec_iter iter;
        uint64_t csum = 0;
-       int i;
 
-       bio_for_each_segment(bv, bio, i) {
-               void *d = kmap(bv->bv_page) + bv->bv_offset;
-               csum = bch_crc64_update(csum, d, bv->bv_len);
-               kunmap(bv->bv_page);
+       bio_for_each_segment(bv, bio, iter) {
+               void *d = kmap(bv.bv_page) + bv.bv_offset;
+               csum = bch_crc64_update(csum, d, bv.bv_len);
+               kunmap(bv.bv_page);
        }
 
        k->ptr[KEY_PTRS(k)] = csum & (~0ULL >> 1);
@@ -261,7 +261,7 @@ static void bch_data_invalidate(struct closure *cl)
        struct bio *bio = op->bio;
 
        pr_debug("invalidating %i sectors from %llu",
-                bio_sectors(bio), (uint64_t) bio->bi_sector);
+                bio_sectors(bio), (uint64_t) bio->bi_iter.bi_sector);
 
        while (bio_sectors(bio)) {
                unsigned sectors = min(bio_sectors(bio),
@@ -270,11 +270,11 @@ static void bch_data_invalidate(struct closure *cl)
                if (bch_keylist_realloc(&op->insert_keys, 0, op->c))
                        goto out;
 
-               bio->bi_sector  += sectors;
-               bio->bi_size    -= sectors << 9;
+               bio->bi_iter.bi_sector  += sectors;
+               bio->bi_iter.bi_size    -= sectors << 9;
 
                bch_keylist_add(&op->insert_keys,
-                               &KEY(op->inode, bio->bi_sector, sectors));
+                               &KEY(op->inode, bio->bi_iter.bi_sector, sectors));
        }
 
        op->insert_data_done = true;
@@ -364,14 +364,14 @@ static void bch_data_insert_start(struct closure *cl)
                k = op->insert_keys.top;
                bkey_init(k);
                SET_KEY_INODE(k, op->inode);
-               SET_KEY_OFFSET(k, bio->bi_sector);
+               SET_KEY_OFFSET(k, bio->bi_iter.bi_sector);
 
                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 = bio_next_split(bio, KEY_SIZE(k), GFP_NOIO, split);
 
                n->bi_end_io    = bch_data_insert_endio;
                n->bi_private   = cl;
@@ -522,7 +522,7 @@ static bool check_should_bypass(struct cached_dev *dc, struct bio *bio)
             (bio->bi_rw & REQ_WRITE)))
                goto skip;
 
-       if (bio->bi_sector & (c->sb.block_size - 1) ||
+       if (bio->bi_iter.bi_sector & (c->sb.block_size - 1) ||
            bio_sectors(bio) & (c->sb.block_size - 1)) {
                pr_debug("skipping unaligned io");
                goto skip;
@@ -546,8 +546,8 @@ static bool check_should_bypass(struct cached_dev *dc, struct bio *bio)
 
        spin_lock(&dc->io_lock);
 
-       hlist_for_each_entry(i, iohash(dc, bio->bi_sector), hash)
-               if (i->last == bio->bi_sector &&
+       hlist_for_each_entry(i, iohash(dc, bio->bi_iter.bi_sector), hash)
+               if (i->last == bio->bi_iter.bi_sector &&
                    time_before(jiffies, i->jiffies))
                        goto found;
 
@@ -556,8 +556,8 @@ static bool check_should_bypass(struct cached_dev *dc, struct bio *bio)
        add_sequential(task);
        i->sequential = 0;
 found:
-       if (i->sequential + bio->bi_size > i->sequential)
-               i->sequential   += bio->bi_size;
+       if (i->sequential + bio->bi_iter.bi_size > i->sequential)
+               i->sequential   += bio->bi_iter.bi_size;
 
        i->last                  = bio_end_sector(bio);
        i->jiffies               = jiffies + msecs_to_jiffies(5000);
@@ -606,7 +606,6 @@ struct search {
        unsigned                insert_bio_sectors;
 
        unsigned                recoverable:1;
-       unsigned                unaligned_bvec:1;
        unsigned                write:1;
        unsigned                read_dirty_data:1;
 
@@ -650,15 +649,15 @@ static int cache_lookup_fn(struct btree_op *op, struct btree *b, struct bkey *k)
        struct bkey *bio_key;
        unsigned ptr;
 
-       if (bkey_cmp(k, &KEY(s->iop.inode, bio->bi_sector, 0)) <= 0)
+       if (bkey_cmp(k, &KEY(s->iop.inode, bio->bi_iter.bi_sector, 0)) <= 0)
                return MAP_CONTINUE;
 
        if (KEY_INODE(k) != s->iop.inode ||
-           KEY_START(k) > bio->bi_sector) {
+           KEY_START(k) > bio->bi_iter.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)
+                               KEY_START(k) - bio->bi_iter.bi_sector)
                        : INT_MAX;
 
                int ret = s->d->cache_miss(b, s, bio, sectors);
@@ -680,14 +679,14 @@ static int cache_lookup_fn(struct btree_op *op, struct btree *b, struct bkey *k)
        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);
+       n = bio_next_split(bio, min_t(uint64_t, INT_MAX,
+                                     KEY_OFFSET(k) - bio->bi_iter.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_front(&KEY(s->iop.inode, n->bi_iter.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;
@@ -714,7 +713,7 @@ static void cache_lookup(struct closure *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),
+                                    &KEY(s->iop.inode, bio->bi_iter.bi_sector, 0),
                                     cache_lookup_fn, MAP_END_KEY);
        if (ret == -EAGAIN)
                continue_at(cl, cache_lookup, bcache_wq);
@@ -759,10 +758,12 @@ static void bio_complete(struct search *s)
 static void do_bio_hook(struct search *s)
 {
        struct bio *bio = &s->bio.bio;
-       memcpy(bio, s->orig_bio, sizeof(struct bio));
 
+       bio_init(bio);
+       __bio_clone_fast(bio, s->orig_bio);
        bio->bi_end_io          = request_endio;
        bio->bi_private         = &s->cl;
+
        atomic_set(&bio->bi_cnt, 3);
 }
 
@@ -774,9 +775,6 @@ static void search_free(struct closure *cl)
        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);
-
        closure_debug_destroy(cl);
        mempool_free(s, s->d->c->search);
 }
@@ -784,7 +782,6 @@ static void search_free(struct closure *cl)
 static struct search *search_alloc(struct bio *bio, struct bcache_device *d)
 {
        struct search *s;
-       struct bio_vec *bv;
 
        s = mempool_alloc(d->c->search, GFP_NOIO);
        memset(s, 0, offsetof(struct search, iop.insert_keys));
@@ -803,15 +800,6 @@ static struct search *search_alloc(struct bio *bio, struct bcache_device *d)
        s->start_time           = jiffies;
        do_bio_hook(s);
 
-       if (bio->bi_size != bio_segments(bio) * PAGE_SIZE) {
-               bv = mempool_alloc(d->unaligned_bvec, GFP_NOIO);
-               memcpy(bv, bio_iovec(bio),
-                      sizeof(struct bio_vec) * bio_segments(bio));
-
-               s->bio.bio.bi_io_vec    = bv;
-               s->unaligned_bvec       = 1;
-       }
-
        return s;
 }
 
@@ -850,26 +838,13 @@ 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;
 
        if (s->recoverable) {
                /* Retry from the backing device: */
                trace_bcache_read_retry(s->orig_bio);
 
                s->iop.error = 0;
-               bv = s->bio.bio.bi_io_vec;
                do_bio_hook(s);
-               s->bio.bio.bi_io_vec = bv;
-
-               if (!s->unaligned_bvec)
-                       bio_for_each_segment(bv, s->orig_bio, i)
-                               bv->bv_offset = 0, bv->bv_len = PAGE_SIZE;
-               else
-                       memcpy(s->bio.bio.bi_io_vec,
-                              bio_iovec(s->orig_bio),
-                              sizeof(struct bio_vec) *
-                              bio_segments(s->orig_bio));
 
                /* XXX: invalidate cache */
 
@@ -894,9 +869,9 @@ static void cached_dev_read_done(struct closure *cl)
 
        if (s->iop.bio) {
                bio_reset(s->iop.bio);
-               s->iop.bio->bi_sector = s->cache_miss->bi_sector;
+               s->iop.bio->bi_iter.bi_sector = s->cache_miss->bi_iter.bi_sector;
                s->iop.bio->bi_bdev = s->cache_miss->bi_bdev;
-               s->iop.bio->bi_size = s->insert_bio_sectors << 9;
+               s->iop.bio->bi_iter.bi_size = s->insert_bio_sectors << 9;
                bch_bio_map(s->iop.bio, NULL);
 
                bio_copy_data(s->cache_miss, s->iop.bio);
@@ -905,8 +880,7 @@ static void cached_dev_read_done(struct closure *cl)
                s->cache_miss = NULL;
        }
 
-       if (verify(dc, &s->bio.bio) && s->recoverable &&
-           !s->unaligned_bvec && !s->read_dirty_data)
+       if (verify(dc, &s->bio.bio) && s->recoverable && !s->read_dirty_data)
                bch_data_verify(dc, s->orig_bio);
 
        bio_complete(s);
@@ -946,7 +920,7 @@ static int cached_dev_cache_miss(struct btree *b, struct search *s,
        struct bio *miss, *cache_bio;
 
        if (s->cache_miss || s->iop.bypass) {
-               miss = bch_bio_split(bio, sectors, GFP_NOIO, s->d->bio_split);
+               miss = bio_next_split(bio, sectors, GFP_NOIO, s->d->bio_split);
                ret = miss == bio ? MAP_DONE : MAP_CONTINUE;
                goto out_submit;
        }
@@ -960,7 +934,7 @@ static int cached_dev_cache_miss(struct btree *b, struct search *s,
        s->insert_bio_sectors = min(sectors, bio_sectors(bio) + reada);
 
        s->iop.replace_key = KEY(s->iop.inode,
-                                bio->bi_sector + s->insert_bio_sectors,
+                                bio->bi_iter.bi_sector + s->insert_bio_sectors,
                                 s->insert_bio_sectors);
 
        ret = bch_btree_insert_check_key(b, &s->op, &s->iop.replace_key);
@@ -969,7 +943,7 @@ static int cached_dev_cache_miss(struct btree *b, struct search *s,
 
        s->iop.replace = true;
 
-       miss = bch_bio_split(bio, sectors, GFP_NOIO, s->d->bio_split);
+       miss = bio_next_split(bio, sectors, GFP_NOIO, s->d->bio_split);
 
        /* btree_search_recurse()'s btree iterator is no good anymore */
        ret = miss == bio ? MAP_DONE : -EINTR;
@@ -980,9 +954,9 @@ static int cached_dev_cache_miss(struct btree *b, struct search *s,
        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_iter.bi_sector    = miss->bi_iter.bi_sector;
+       cache_bio->bi_bdev              = miss->bi_bdev;
+       cache_bio->bi_iter.bi_size      = s->insert_bio_sectors << 9;
 
        cache_bio->bi_end_io    = request_endio;
        cache_bio->bi_private   = &s->cl;
@@ -1032,7 +1006,7 @@ 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 = KEY(dc->disk.id, bio->bi_sector, 0);
+       struct bkey start = KEY(dc->disk.id, bio->bi_iter.bi_sector, 0);
        struct bkey end = KEY(dc->disk.id, bio_end_sector(bio), 0);
 
        bch_keybuf_check_overlapping(&s->iop.c->moving_gc_keys, &start, &end);
@@ -1088,8 +1062,7 @@ static void cached_dev_write(struct cached_dev *dc, struct search *s)
                        closure_bio_submit(flush, cl, s->d);
                }
        } else {
-               s->iop.bio = bio_clone_bioset(bio, GFP_NOIO,
-                                             dc->disk.bio_split);
+               s->iop.bio = bio_clone_fast(bio, GFP_NOIO, dc->disk.bio_split);
 
                closure_bio_submit(bio, cl, s->d);
        }
@@ -1127,13 +1100,13 @@ static void cached_dev_make_request(struct request_queue *q, struct bio *bio)
        part_stat_unlock();
 
        bio->bi_bdev = dc->bdev;
-       bio->bi_sector += dc->sb.data_offset;
+       bio->bi_iter.bi_sector += dc->sb.data_offset;
 
        if (cached_dev_get(dc)) {
                s = search_alloc(bio, d);
                trace_bcache_request_start(s->d, bio);
 
-               if (!bio->bi_size) {
+               if (!bio->bi_iter.bi_size) {
                        /*
                         * can't call bch_journal_meta from under
                         * generic_make_request
@@ -1205,24 +1178,24 @@ void bch_cached_dev_request_init(struct cached_dev *dc)
 static int flash_dev_cache_miss(struct btree *b, struct search *s,
                                struct bio *bio, unsigned sectors)
 {
-       struct bio_vec *bv;
-       int i;
+       struct bio_vec bv;
+       struct bvec_iter iter;
 
        /* Zero fill bio */
 
-       bio_for_each_segment(bv, bio, i) {
-               unsigned j = min(bv->bv_len >> 9, sectors);
+       bio_for_each_segment(bv, bio, iter) {
+               unsigned j = min(bv.bv_len >> 9, sectors);
 
-               void *p = kmap(bv->bv_page);
-               memset(p + bv->bv_offset, 0, j << 9);
-               kunmap(bv->bv_page);
+               void *p = kmap(bv.bv_page);
+               memset(p + bv.bv_offset, 0, j << 9);
+               kunmap(bv.bv_page);
 
                sectors -= j;
        }
 
-       bio_advance(bio, min(sectors << 9, bio->bi_size));
+       bio_advance(bio, min(sectors << 9, bio->bi_iter.bi_size));
 
-       if (!bio->bi_size)
+       if (!bio->bi_iter.bi_size)
                return MAP_DONE;
 
        return MAP_CONTINUE;
@@ -1256,7 +1229,7 @@ static void flash_dev_make_request(struct request_queue *q, struct bio *bio)
 
        trace_bcache_request_start(s->d, bio);
 
-       if (!bio->bi_size) {
+       if (!bio->bi_iter.bi_size) {
                /*
                 * can't call bch_journal_meta from under
                 * generic_make_request
@@ -1266,7 +1239,7 @@ static void flash_dev_make_request(struct request_queue *q, struct bio *bio)
                                      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->bi_iter.bi_sector, 0),
                                        &KEY(d->id, bio_end_sector(bio), 0));
 
                s->iop.bypass           = (bio->bi_rw & REQ_DISCARD) != 0;
index dec15cd2d797eaaa7fa0585abf8867c9f70a4cef..60fb6044b9535fcb1864b12af36b479014ad641b 100644 (file)
@@ -233,9 +233,9 @@ static void __write_super(struct cache_sb *sb, struct bio *bio)
        struct cache_sb *out = page_address(bio->bi_io_vec[0].bv_page);
        unsigned i;
 
-       bio->bi_sector  = SB_SECTOR;
-       bio->bi_rw      = REQ_SYNC|REQ_META;
-       bio->bi_size    = SB_SIZE;
+       bio->bi_iter.bi_sector  = SB_SECTOR;
+       bio->bi_rw              = REQ_SYNC|REQ_META;
+       bio->bi_iter.bi_size    = SB_SIZE;
        bch_bio_map(bio, NULL);
 
        out->offset             = cpu_to_le64(sb->offset);
@@ -347,7 +347,7 @@ static void uuid_io(struct cache_set *c, unsigned long rw,
                struct bio *bio = bch_bbio_alloc(c);
 
                bio->bi_rw      = REQ_SYNC|REQ_META|rw;
-               bio->bi_size    = KEY_SIZE(k) << 9;
+               bio->bi_iter.bi_size = KEY_SIZE(k) << 9;
 
                bio->bi_end_io  = uuid_endio;
                bio->bi_private = cl;
@@ -503,10 +503,10 @@ static void prio_io(struct cache *ca, uint64_t bucket, unsigned long rw)
 
        closure_init_stack(cl);
 
-       bio->bi_sector  = bucket * ca->sb.bucket_size;
-       bio->bi_bdev    = ca->bdev;
-       bio->bi_rw      = REQ_SYNC|REQ_META|rw;
-       bio->bi_size    = bucket_bytes(ca);
+       bio->bi_iter.bi_sector  = bucket * ca->sb.bucket_size;
+       bio->bi_bdev            = ca->bdev;
+       bio->bi_rw              = REQ_SYNC|REQ_META|rw;
+       bio->bi_iter.bi_size    = bucket_bytes(ca);
 
        bio->bi_end_io  = prio_endio;
        bio->bi_private = ca;
@@ -739,8 +739,6 @@ static void bcache_device_free(struct bcache_device *d)
        }
 
        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))
@@ -793,8 +791,6 @@ static int bcache_device_init(struct bcache_device *d, unsigned block_size,
                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))) {
                ida_simple_remove(&bcache_minor, minor);
index 462214eeacbedbd9548e725be2e625723cda0d7e..c57621e49dc002c7b94b7bf34f2a1aa06a3f1b46 100644 (file)
@@ -218,10 +218,10 @@ uint64_t bch_next_delay(struct bch_ratelimit *d, uint64_t done)
 
 void bch_bio_map(struct bio *bio, void *base)
 {
-       size_t size = bio->bi_size;
+       size_t size = bio->bi_iter.bi_size;
        struct bio_vec *bv = bio->bi_io_vec;
 
-       BUG_ON(!bio->bi_size);
+       BUG_ON(!bio->bi_iter.bi_size);
        BUG_ON(bio->bi_vcnt);
 
        bv->bv_offset = base ? ((unsigned long) base) % PAGE_SIZE : 0;
index 99053b1251bea1049c627580f3614d1c18f89b60..04657e93f4fd55e0985797c5813bffd893ca65bc 100644 (file)
@@ -113,7 +113,7 @@ static void dirty_init(struct keybuf_key *w)
        if (!io->dc->writeback_percent)
                bio_set_prio(bio, IOPRIO_PRIO_VALUE(IOPRIO_CLASS_IDLE, 0));
 
-       bio->bi_size            = KEY_SIZE(&w->key) << 9;
+       bio->bi_iter.bi_size    = KEY_SIZE(&w->key) << 9;
        bio->bi_max_vecs        = DIV_ROUND_UP(KEY_SIZE(&w->key), PAGE_SECTORS);
        bio->bi_private         = w;
        bio->bi_io_vec          = bio->bi_inline_vecs;
@@ -186,7 +186,7 @@ static void write_dirty(struct closure *cl)
 
        dirty_init(w);
        io->bio.bi_rw           = WRITE;
-       io->bio.bi_sector       = KEY_START(&w->key);
+       io->bio.bi_iter.bi_sector = KEY_START(&w->key);
        io->bio.bi_bdev         = io->dc->bdev;
        io->bio.bi_end_io       = dirty_endio;
 
@@ -255,7 +255,7 @@ static void read_dirty(struct cached_dev *dc)
                io->dc          = dc;
 
                dirty_init(w);
-               io->bio.bi_sector       = PTR_OFFSET(&w->key, 0);
+               io->bio.bi_iter.bi_sector = PTR_OFFSET(&w->key, 0);
                io->bio.bi_bdev         = PTR_CACHE(dc->disk.c,
                                                    &w->key, 0)->bdev;
                io->bio.bi_rw           = READ;
index c9ddcf4614b9300701c9867033c82bc13cadf472..e2f8598937ac41ff5c7577bc5e65aeb39de95386 100644 (file)
@@ -50,7 +50,7 @@ static inline bool should_writeback(struct cached_dev *dc, struct bio *bio,
                return false;
 
        if (dc->partial_stripes_expensive &&
-           bcache_dev_stripe_dirty(dc, bio->bi_sector,
+           bcache_dev_stripe_dirty(dc, bio->bi_iter.bi_sector,
                                    bio_sectors(bio)))
                return true;
 
index 3a8cfa2645c72f6539170f2ab2d3242bb4a6fa58..dd3646111561512f50728aa915b8a279be1c26ac 100644 (file)
  * original bio state.
  */
 
-struct dm_bio_vec_details {
-#if PAGE_SIZE < 65536
-       __u16 bv_len;
-       __u16 bv_offset;
-#else
-       unsigned bv_len;
-       unsigned bv_offset;
-#endif
-};
-
 struct dm_bio_details {
-       sector_t bi_sector;
        struct block_device *bi_bdev;
-       unsigned int bi_size;
-       unsigned short bi_idx;
        unsigned long bi_flags;
-       struct dm_bio_vec_details bi_io_vec[BIO_MAX_PAGES];
+       struct bvec_iter bi_iter;
 };
 
 static inline void dm_bio_record(struct dm_bio_details *bd, struct bio *bio)
 {
-       unsigned i;
-
-       bd->bi_sector = bio->bi_sector;
        bd->bi_bdev = bio->bi_bdev;
-       bd->bi_size = bio->bi_size;
-       bd->bi_idx = bio->bi_idx;
        bd->bi_flags = bio->bi_flags;
-
-       for (i = 0; i < bio->bi_vcnt; i++) {
-               bd->bi_io_vec[i].bv_len = bio->bi_io_vec[i].bv_len;
-               bd->bi_io_vec[i].bv_offset = bio->bi_io_vec[i].bv_offset;
-       }
+       bd->bi_iter = bio->bi_iter;
 }
 
 static inline void dm_bio_restore(struct dm_bio_details *bd, struct bio *bio)
 {
-       unsigned i;
-
-       bio->bi_sector = bd->bi_sector;
        bio->bi_bdev = bd->bi_bdev;
-       bio->bi_size = bd->bi_size;
-       bio->bi_idx = bd->bi_idx;
        bio->bi_flags = bd->bi_flags;
-
-       for (i = 0; i < bio->bi_vcnt; i++) {
-               bio->bi_io_vec[i].bv_len = bd->bi_io_vec[i].bv_len;
-               bio->bi_io_vec[i].bv_offset = bd->bi_io_vec[i].bv_offset;
-       }
+       bio->bi_iter = bd->bi_iter;
 }
 
 #endif
index 173cbb20d10498b21440ada78b27f241b47af2cc..a1b58a65d8ed849ecef2217e1b93f2a5d3e42ba1 100644 (file)
@@ -538,7 +538,7 @@ static void use_inline_bio(struct dm_buffer *b, int rw, sector_t block,
        bio_init(&b->bio);
        b->bio.bi_io_vec = b->bio_vec;
        b->bio.bi_max_vecs = DM_BUFIO_INLINE_VECS;
-       b->bio.bi_sector = block << b->c->sectors_per_block_bits;
+       b->bio.bi_iter.bi_sector = block << b->c->sectors_per_block_bits;
        b->bio.bi_bdev = b->c->bdev;
        b->bio.bi_end_io = end_io;
 
@@ -1717,6 +1717,11 @@ static int __init dm_bufio_init(void)
 {
        __u64 mem;
 
+       dm_bufio_allocated_kmem_cache = 0;
+       dm_bufio_allocated_get_free_pages = 0;
+       dm_bufio_allocated_vmalloc = 0;
+       dm_bufio_current_allocated = 0;
+
        memset(&dm_bufio_caches, 0, sizeof dm_bufio_caches);
        memset(&dm_bufio_cache_names, 0, sizeof dm_bufio_cache_names);
 
index 416b7b752a6e0018d4a11800606a8be6b8890e22..d13a16865d03ddc4ec418618d3d8fbdb4909ddc8 100644 (file)
@@ -72,7 +72,7 @@ static enum io_pattern iot_pattern(struct io_tracker *t)
 
 static void iot_update_stats(struct io_tracker *t, struct bio *bio)
 {
-       if (bio->bi_sector == from_oblock(t->last_end_oblock) + 1)
+       if (bio->bi_iter.bi_sector == from_oblock(t->last_end_oblock) + 1)
                t->nr_seq_samples++;
        else {
                /*
@@ -87,7 +87,7 @@ static void iot_update_stats(struct io_tracker *t, struct bio *bio)
                t->nr_rand_samples++;
        }
 
-       t->last_end_oblock = to_oblock(bio->bi_sector + bio_sectors(bio) - 1);
+       t->last_end_oblock = to_oblock(bio_end_sector(bio) - 1);
 }
 
 static void iot_check_for_pattern_switch(struct io_tracker *t)
@@ -730,15 +730,18 @@ static int pre_cache_entry_found(struct mq_policy *mq, struct entry *e,
        int r = 0;
        bool updated = updated_this_tick(mq, e);
 
-       requeue_and_update_tick(mq, e);
-
        if ((!discarded_oblock && updated) ||
-           !should_promote(mq, e, discarded_oblock, data_dir))
+           !should_promote(mq, e, discarded_oblock, data_dir)) {
+               requeue_and_update_tick(mq, e);
                result->op = POLICY_MISS;
-       else if (!can_migrate)
+
+       } else if (!can_migrate)
                r = -EWOULDBLOCK;
-       else
+
+       else {
+               requeue_and_update_tick(mq, e);
                r = pre_cache_to_cache(mq, e, result);
+       }
 
        return r;
 }
index 9efcf1059b99e3ae2e6e712eb150c0954646d5d8..99f91628a33aa6b6969d2b87b61a861e85d16de6 100644 (file)
@@ -85,6 +85,12 @@ static void dm_unhook_bio(struct dm_hook_info *h, struct bio *bio)
 {
        bio->bi_end_io = h->bi_end_io;
        bio->bi_private = h->bi_private;
+
+       /*
+        * Must bump bi_remaining to allow bio to complete with
+        * restored bi_end_io.
+        */
+       atomic_inc(&bio->bi_remaining);
 }
 
 /*----------------------------------------------------------------*/
@@ -664,15 +670,17 @@ static void remap_to_origin(struct cache *cache, struct bio *bio)
 static void remap_to_cache(struct cache *cache, struct bio *bio,
                           dm_cblock_t cblock)
 {
-       sector_t bi_sector = bio->bi_sector;
+       sector_t bi_sector = bio->bi_iter.bi_sector;
 
        bio->bi_bdev = cache->cache_dev->bdev;
        if (!block_size_is_power_of_two(cache))
-               bio->bi_sector = (from_cblock(cblock) * cache->sectors_per_block) +
-                               sector_div(bi_sector, cache->sectors_per_block);
+               bio->bi_iter.bi_sector =
+                       (from_cblock(cblock) * cache->sectors_per_block) +
+                       sector_div(bi_sector, cache->sectors_per_block);
        else
-               bio->bi_sector = (from_cblock(cblock) << cache->sectors_per_block_shift) |
-                               (bi_sector & (cache->sectors_per_block - 1));
+               bio->bi_iter.bi_sector =
+                       (from_cblock(cblock) << cache->sectors_per_block_shift) |
+                       (bi_sector & (cache->sectors_per_block - 1));
 }
 
 static void check_if_tick_bio_needed(struct cache *cache, struct bio *bio)
@@ -712,7 +720,7 @@ static void remap_to_cache_dirty(struct cache *cache, struct bio *bio,
 
 static dm_oblock_t get_bio_block(struct cache *cache, struct bio *bio)
 {
-       sector_t block_nr = bio->bi_sector;
+       sector_t block_nr = bio->bi_iter.bi_sector;
 
        if (!block_size_is_power_of_two(cache))
                (void) sector_div(block_nr, cache->sectors_per_block);
@@ -1027,7 +1035,7 @@ static void issue_overwrite(struct dm_cache_migration *mg, struct bio *bio)
 static bool bio_writes_complete_block(struct cache *cache, struct bio *bio)
 {
        return (bio_data_dir(bio) == WRITE) &&
-               (bio->bi_size == (cache->sectors_per_block << SECTOR_SHIFT));
+               (bio->bi_iter.bi_size == (cache->sectors_per_block << SECTOR_SHIFT));
 }
 
 static void avoid_copy(struct dm_cache_migration *mg)
@@ -1252,7 +1260,7 @@ static void process_flush_bio(struct cache *cache, struct bio *bio)
        size_t pb_data_size = get_per_bio_data_size(cache);
        struct per_bio_data *pb = get_per_bio_data(bio, pb_data_size);
 
-       BUG_ON(bio->bi_size);
+       BUG_ON(bio->bi_iter.bi_size);
        if (!pb->req_nr)
                remap_to_origin(cache, bio);
        else
@@ -1275,9 +1283,9 @@ static void process_flush_bio(struct cache *cache, struct bio *bio)
  */
 static void process_discard_bio(struct cache *cache, struct bio *bio)
 {
-       dm_block_t start_block = dm_sector_div_up(bio->bi_sector,
+       dm_block_t start_block = dm_sector_div_up(bio->bi_iter.bi_sector,
                                                  cache->discard_block_size);
-       dm_block_t end_block = bio->bi_sector + bio_sectors(bio);
+       dm_block_t end_block = bio_end_sector(bio);
        dm_block_t b;
 
        end_block = block_div(end_block, cache->discard_block_size);
@@ -2755,7 +2763,7 @@ static int resize_cache_dev(struct cache *cache, dm_cblock_t new_size)
 {
        int r;
 
-       r = dm_cache_resize(cache->cmd, cache->cache_size);
+       r = dm_cache_resize(cache->cmd, new_size);
        if (r) {
                DMERR("could not resize cache metadata");
                return r;
index 81b0fa66045204604a979fdc929e723f6c914a5c..784695d22fde1acaaf11acd78c7263438c04648e 100644 (file)
@@ -39,10 +39,8 @@ struct convert_context {
        struct completion restart;
        struct bio *bio_in;
        struct bio *bio_out;
-       unsigned int offset_in;
-       unsigned int offset_out;
-       unsigned int idx_in;
-       unsigned int idx_out;
+       struct bvec_iter iter_in;
+       struct bvec_iter iter_out;
        sector_t cc_sector;
        atomic_t cc_pending;
 };
@@ -826,10 +824,10 @@ static void crypt_convert_init(struct crypt_config *cc,
 {
        ctx->bio_in = bio_in;
        ctx->bio_out = bio_out;
-       ctx->offset_in = 0;
-       ctx->offset_out = 0;
-       ctx->idx_in = bio_in ? bio_in->bi_idx : 0;
-       ctx->idx_out = bio_out ? bio_out->bi_idx : 0;
+       if (bio_in)
+               ctx->iter_in = bio_in->bi_iter;
+       if (bio_out)
+               ctx->iter_out = bio_out->bi_iter;
        ctx->cc_sector = sector + cc->iv_offset;
        init_completion(&ctx->restart);
 }
@@ -857,8 +855,8 @@ static int crypt_convert_block(struct crypt_config *cc,
                               struct convert_context *ctx,
                               struct ablkcipher_request *req)
 {
-       struct bio_vec *bv_in = bio_iovec_idx(ctx->bio_in, ctx->idx_in);
-       struct bio_vec *bv_out = bio_iovec_idx(ctx->bio_out, ctx->idx_out);
+       struct bio_vec bv_in = bio_iter_iovec(ctx->bio_in, ctx->iter_in);
+       struct bio_vec bv_out = bio_iter_iovec(ctx->bio_out, ctx->iter_out);
        struct dm_crypt_request *dmreq;
        u8 *iv;
        int r;
@@ -869,24 +867,15 @@ static int crypt_convert_block(struct crypt_config *cc,
        dmreq->iv_sector = ctx->cc_sector;
        dmreq->ctx = ctx;
        sg_init_table(&dmreq->sg_in, 1);
-       sg_set_page(&dmreq->sg_in, bv_in->bv_page, 1 << SECTOR_SHIFT,
-                   bv_in->bv_offset + ctx->offset_in);
+       sg_set_page(&dmreq->sg_in, bv_in.bv_page, 1 << SECTOR_SHIFT,
+                   bv_in.bv_offset);
 
        sg_init_table(&dmreq->sg_out, 1);
-       sg_set_page(&dmreq->sg_out, bv_out->bv_page, 1 << SECTOR_SHIFT,
-                   bv_out->bv_offset + ctx->offset_out);
+       sg_set_page(&dmreq->sg_out, bv_out.bv_page, 1 << SECTOR_SHIFT,
+                   bv_out.bv_offset);
 
-       ctx->offset_in += 1 << SECTOR_SHIFT;
-       if (ctx->offset_in >= bv_in->bv_len) {
-               ctx->offset_in = 0;
-               ctx->idx_in++;
-       }
-
-       ctx->offset_out += 1 << SECTOR_SHIFT;
-       if (ctx->offset_out >= bv_out->bv_len) {
-               ctx->offset_out = 0;
-               ctx->idx_out++;
-       }
+       bio_advance_iter(ctx->bio_in, &ctx->iter_in, 1 << SECTOR_SHIFT);
+       bio_advance_iter(ctx->bio_out, &ctx->iter_out, 1 << SECTOR_SHIFT);
 
        if (cc->iv_gen_ops) {
                r = cc->iv_gen_ops->generator(cc, iv, dmreq);
@@ -937,8 +926,7 @@ static int crypt_convert(struct crypt_config *cc,
 
        atomic_set(&ctx->cc_pending, 1);
 
-       while(ctx->idx_in < ctx->bio_in->bi_vcnt &&
-             ctx->idx_out < ctx->bio_out->bi_vcnt) {
+       while (ctx->iter_in.bi_size && ctx->iter_out.bi_size) {
 
                crypt_alloc_req(cc, ctx);
 
@@ -1021,7 +1009,7 @@ static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned size,
                size -= len;
        }
 
-       if (!clone->bi_size) {
+       if (!clone->bi_iter.bi_size) {
                bio_put(clone);
                return NULL;
        }
@@ -1161,7 +1149,7 @@ static int kcryptd_io_read(struct dm_crypt_io *io, gfp_t gfp)
        crypt_inc_pending(io);
 
        clone_init(io, clone);
-       clone->bi_sector = cc->start + io->sector;
+       clone->bi_iter.bi_sector = cc->start + io->sector;
 
        generic_make_request(clone);
        return 0;
@@ -1207,9 +1195,9 @@ static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io, int async)
        }
 
        /* crypt_convert should have filled the clone bio */
-       BUG_ON(io->ctx.idx_out < clone->bi_vcnt);
+       BUG_ON(io->ctx.iter_out.bi_size);
 
-       clone->bi_sector = cc->start + io->sector;
+       clone->bi_iter.bi_sector = cc->start + io->sector;
 
        if (async)
                kcryptd_queue_io(io);
@@ -1224,7 +1212,7 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io)
        struct dm_crypt_io *new_io;
        int crypt_finished;
        unsigned out_of_pages = 0;
-       unsigned remaining = io->base_bio->bi_size;
+       unsigned remaining = io->base_bio->bi_iter.bi_size;
        sector_t sector = io->sector;
        int r;
 
@@ -1246,9 +1234,9 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io)
                }
 
                io->ctx.bio_out = clone;
-               io->ctx.idx_out = 0;
+               io->ctx.iter_out = clone->bi_iter;
 
-               remaining -= clone->bi_size;
+               remaining -= clone->bi_iter.bi_size;
                sector += bio_sectors(clone);
 
                crypt_inc_pending(io);
@@ -1290,8 +1278,7 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io)
                        crypt_inc_pending(new_io);
                        crypt_convert_init(cc, &new_io->ctx, NULL,
                                           io->base_bio, sector);
-                       new_io->ctx.idx_in = io->ctx.idx_in;
-                       new_io->ctx.offset_in = io->ctx.offset_in;
+                       new_io->ctx.iter_in = io->ctx.iter_in;
 
                        /*
                         * Fragments after the first use the base_io
@@ -1869,11 +1856,12 @@ static int crypt_map(struct dm_target *ti, struct bio *bio)
        if (unlikely(bio->bi_rw & (REQ_FLUSH | REQ_DISCARD))) {
                bio->bi_bdev = cc->dev->bdev;
                if (bio_sectors(bio))
-                       bio->bi_sector = cc->start + dm_target_offset(ti, bio->bi_sector);
+                       bio->bi_iter.bi_sector = cc->start +
+                               dm_target_offset(ti, bio->bi_iter.bi_sector);
                return DM_MAPIO_REMAPPED;
        }
 
-       io = crypt_io_alloc(cc, bio, dm_target_offset(ti, bio->bi_sector));
+       io = crypt_io_alloc(cc, bio, dm_target_offset(ti, bio->bi_iter.bi_sector));
 
        if (bio_data_dir(io->base_bio) == READ) {
                if (kcryptd_io_read(io, GFP_NOWAIT))
index 496d5f3646a5df623e6c0a9b22d35ad003c610bc..fc8482a65dd27d0083e1c0f226c619c4cc3142f8 100644 (file)
@@ -20,6 +20,7 @@
 struct delay_c {
        struct timer_list delay_timer;
        struct mutex timer_lock;
+       struct workqueue_struct *kdelayd_wq;
        struct work_struct flush_expired_bios;
        struct list_head delayed_bios;
        atomic_t may_delay;
@@ -45,14 +46,13 @@ struct dm_delay_info {
 
 static DEFINE_MUTEX(delayed_bios_lock);
 
-static struct workqueue_struct *kdelayd_wq;
 static struct kmem_cache *delayed_cache;
 
 static void handle_delayed_timer(unsigned long data)
 {
        struct delay_c *dc = (struct delay_c *)data;
 
-       queue_work(kdelayd_wq, &dc->flush_expired_bios);
+       queue_work(dc->kdelayd_wq, &dc->flush_expired_bios);
 }
 
 static void queue_timeout(struct delay_c *dc, unsigned long expires)
@@ -191,6 +191,12 @@ out:
                goto bad_dev_write;
        }
 
+       dc->kdelayd_wq = alloc_workqueue("kdelayd", WQ_MEM_RECLAIM, 0);
+       if (!dc->kdelayd_wq) {
+               DMERR("Couldn't start kdelayd");
+               goto bad_queue;
+       }
+
        setup_timer(&dc->delay_timer, handle_delayed_timer, (unsigned long)dc);
 
        INIT_WORK(&dc->flush_expired_bios, flush_expired_bios);
@@ -203,6 +209,8 @@ out:
        ti->private = dc;
        return 0;
 
+bad_queue:
+       mempool_destroy(dc->delayed_pool);
 bad_dev_write:
        if (dc->dev_write)
                dm_put_device(ti, dc->dev_write);
@@ -217,7 +225,7 @@ static void delay_dtr(struct dm_target *ti)
 {
        struct delay_c *dc = ti->private;
 
-       flush_workqueue(kdelayd_wq);
+       destroy_workqueue(dc->kdelayd_wq);
 
        dm_put_device(ti, dc->dev_read);
 
@@ -281,14 +289,15 @@ static int delay_map(struct dm_target *ti, struct bio *bio)
        if ((bio_data_dir(bio) == WRITE) && (dc->dev_write)) {
                bio->bi_bdev = dc->dev_write->bdev;
                if (bio_sectors(bio))
-                       bio->bi_sector = dc->start_write +
-                                        dm_target_offset(ti, bio->bi_sector);
+                       bio->bi_iter.bi_sector = dc->start_write +
+                               dm_target_offset(ti, bio->bi_iter.bi_sector);
 
                return delay_bio(dc, dc->write_delay, bio);
        }
 
        bio->bi_bdev = dc->dev_read->bdev;
-       bio->bi_sector = dc->start_read + dm_target_offset(ti, bio->bi_sector);
+       bio->bi_iter.bi_sector = dc->start_read +
+               dm_target_offset(ti, bio->bi_iter.bi_sector);
 
        return delay_bio(dc, dc->read_delay, bio);
 }
@@ -350,12 +359,6 @@ static int __init dm_delay_init(void)
 {
        int r = -ENOMEM;
 
-       kdelayd_wq = alloc_workqueue("kdelayd", WQ_MEM_RECLAIM, 0);
-       if (!kdelayd_wq) {
-               DMERR("Couldn't start kdelayd");
-               goto bad_queue;
-       }
-
        delayed_cache = KMEM_CACHE(dm_delay_info, 0);
        if (!delayed_cache) {
                DMERR("Couldn't create delayed bio cache.");
@@ -373,8 +376,6 @@ static int __init dm_delay_init(void)
 bad_register:
        kmem_cache_destroy(delayed_cache);
 bad_memcache:
-       destroy_workqueue(kdelayd_wq);
-bad_queue:
        return r;
 }
 
@@ -382,7 +383,6 @@ static void __exit dm_delay_exit(void)
 {
        dm_unregister_target(&delay_target);
        kmem_cache_destroy(delayed_cache);
-       destroy_workqueue(kdelayd_wq);
 }
 
 /* Module hooks */
index c80a0ec5f1269b40be7da133c68c6e789c5e5329..b257e46876d357f831bf1c751010d5b16fa125b8 100644 (file)
@@ -248,7 +248,8 @@ static void flakey_map_bio(struct dm_target *ti, struct bio *bio)
 
        bio->bi_bdev = fc->dev->bdev;
        if (bio_sectors(bio))
-               bio->bi_sector = flakey_map_sector(ti, bio->bi_sector);
+               bio->bi_iter.bi_sector =
+                       flakey_map_sector(ti, bio->bi_iter.bi_sector);
 }
 
 static void corrupt_bio_data(struct bio *bio, struct flakey_c *fc)
@@ -265,8 +266,8 @@ static void corrupt_bio_data(struct bio *bio, struct flakey_c *fc)
                DMDEBUG("Corrupting data bio=%p by writing %u to byte %u "
                        "(rw=%c bi_rw=%lu bi_sector=%llu cur_bytes=%u)\n",
                        bio, fc->corrupt_bio_value, fc->corrupt_bio_byte,
-                       (bio_data_dir(bio) == WRITE) ? 'w' : 'r',
-                       bio->bi_rw, (unsigned long long)bio->bi_sector, bio_bytes);
+                       (bio_data_dir(bio) == WRITE) ? 'w' : 'r', bio->bi_rw,
+                       (unsigned long long)bio->bi_iter.bi_sector, bio_bytes);
        }
 }
 
index 2a20986a2fec9701cd25e443c990f2b7a8479f9f..b2b8a10e842784de5454e2639474f1a208b4b3f1 100644 (file)
@@ -201,26 +201,29 @@ static void list_dp_init(struct dpages *dp, struct page_list *pl, unsigned offse
 /*
  * Functions for getting the pages from a bvec.
  */
-static void bvec_get_page(struct dpages *dp,
+static void bio_get_page(struct dpages *dp,
                  struct page **p, unsigned long *len, unsigned *offset)
 {
-       struct bio_vec *bvec = (struct bio_vec *) dp->context_ptr;
-       *p = bvec->bv_page;
-       *len = bvec->bv_len;
-       *offset = bvec->bv_offset;
+       struct bio *bio = dp->context_ptr;
+       struct bio_vec bvec = bio_iovec(bio);
+       *p = bvec.bv_page;
+       *len = bvec.bv_len;
+       *offset = bvec.bv_offset;
 }
 
-static void bvec_next_page(struct dpages *dp)
+static void bio_next_page(struct dpages *dp)
 {
-       struct bio_vec *bvec = (struct bio_vec *) dp->context_ptr;
-       dp->context_ptr = bvec + 1;
+       struct bio *bio = dp->context_ptr;
+       struct bio_vec bvec = bio_iovec(bio);
+
+       bio_advance(bio, bvec.bv_len);
 }
 
-static void bvec_dp_init(struct dpages *dp, struct bio_vec *bvec)
+static void bio_dp_init(struct dpages *dp, struct bio *bio)
 {
-       dp->get_page = bvec_get_page;
-       dp->next_page = bvec_next_page;
-       dp->context_ptr = bvec;
+       dp->get_page = bio_get_page;
+       dp->next_page = bio_next_page;
+       dp->context_ptr = bio;
 }
 
 /*
@@ -304,14 +307,14 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where,
                                          dm_sector_div_up(remaining, (PAGE_SIZE >> SECTOR_SHIFT)));
 
                bio = bio_alloc_bioset(GFP_NOIO, num_bvecs, io->client->bios);
-               bio->bi_sector = where->sector + (where->count - remaining);
+               bio->bi_iter.bi_sector = where->sector + (where->count - remaining);
                bio->bi_bdev = where->bdev;
                bio->bi_end_io = endio;
                store_io_and_region_in_bio(bio, io, region);
 
                if (rw & REQ_DISCARD) {
                        num_sectors = min_t(sector_t, q->limits.max_discard_sectors, remaining);
-                       bio->bi_size = num_sectors << SECTOR_SHIFT;
+                       bio->bi_iter.bi_size = num_sectors << SECTOR_SHIFT;
                        remaining -= num_sectors;
                } else if (rw & REQ_WRITE_SAME) {
                        /*
@@ -320,7 +323,7 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where,
                        dp->get_page(dp, &page, &len, &offset);
                        bio_add_page(bio, page, logical_block_size, offset);
                        num_sectors = min_t(sector_t, q->limits.max_write_same_sectors, remaining);
-                       bio->bi_size = num_sectors << SECTOR_SHIFT;
+                       bio->bi_iter.bi_size = num_sectors << SECTOR_SHIFT;
 
                        offset = 0;
                        remaining -= num_sectors;
@@ -457,8 +460,8 @@ static int dp_init(struct dm_io_request *io_req, struct dpages *dp,
                list_dp_init(dp, io_req->mem.ptr.pl, io_req->mem.offset);
                break;
 
-       case DM_IO_BVEC:
-               bvec_dp_init(dp, io_req->mem.ptr.bvec);
+       case DM_IO_BIO:
+               bio_dp_init(dp, io_req->mem.ptr.bio);
                break;
 
        case DM_IO_VMA:
index 4f99d267340cdb48c3a7b64edcdd4ed9a7fd48ea..53e848c1093936560a9554c9fdacbec2f6dae5bd 100644 (file)
@@ -85,7 +85,8 @@ static void linear_map_bio(struct dm_target *ti, struct bio *bio)
 
        bio->bi_bdev = lc->dev->bdev;
        if (bio_sectors(bio))
-               bio->bi_sector = linear_map_sector(ti, bio->bi_sector);
+               bio->bi_iter.bi_sector =
+                       linear_map_sector(ti, bio->bi_iter.bi_sector);
 }
 
 static int linear_map(struct dm_target *ti, struct bio *bio)
index 9584443c56148608d159ceab1d436fd6bacfda3b..f284e0bfb25fca869855f390f2d8d7a5519a0864 100644 (file)
@@ -432,7 +432,7 @@ static int mirror_available(struct mirror_set *ms, struct bio *bio)
        region_t region = dm_rh_bio_to_region(ms->rh, bio);
 
        if (log->type->in_sync(log, region, 0))
-               return choose_mirror(ms,  bio->bi_sector) ? 1 : 0;
+               return choose_mirror(ms,  bio->bi_iter.bi_sector) ? 1 : 0;
 
        return 0;
 }
@@ -442,15 +442,15 @@ static int mirror_available(struct mirror_set *ms, struct bio *bio)
  */
 static sector_t map_sector(struct mirror *m, struct bio *bio)
 {
-       if (unlikely(!bio->bi_size))
+       if (unlikely(!bio->bi_iter.bi_size))
                return 0;
-       return m->offset + dm_target_offset(m->ms->ti, bio->bi_sector);
+       return m->offset + dm_target_offset(m->ms->ti, bio->bi_iter.bi_sector);
 }
 
 static void map_bio(struct mirror *m, struct bio *bio)
 {
        bio->bi_bdev = m->dev->bdev;
-       bio->bi_sector = map_sector(m, bio);
+       bio->bi_iter.bi_sector = map_sector(m, bio);
 }
 
 static void map_region(struct dm_io_region *io, struct mirror *m,
@@ -526,8 +526,8 @@ static void read_async_bio(struct mirror *m, struct bio *bio)
        struct dm_io_region io;
        struct dm_io_request io_req = {
                .bi_rw = READ,
-               .mem.type = DM_IO_BVEC,
-               .mem.ptr.bvec = bio->bi_io_vec + bio->bi_idx,
+               .mem.type = DM_IO_BIO,
+               .mem.ptr.bio = bio,
                .notify.fn = read_callback,
                .notify.context = bio,
                .client = m->ms->io_client,
@@ -559,7 +559,7 @@ static void do_reads(struct mirror_set *ms, struct bio_list *reads)
                 * We can only read balance if the region is in sync.
                 */
                if (likely(region_in_sync(ms, region, 1)))
-                       m = choose_mirror(ms, bio->bi_sector);
+                       m = choose_mirror(ms, bio->bi_iter.bi_sector);
                else if (m && atomic_read(&m->error_count))
                        m = NULL;
 
@@ -629,8 +629,8 @@ static void do_write(struct mirror_set *ms, struct bio *bio)
        struct mirror *m;
        struct dm_io_request io_req = {
                .bi_rw = WRITE | (bio->bi_rw & WRITE_FLUSH_FUA),
-               .mem.type = DM_IO_BVEC,
-               .mem.ptr.bvec = bio->bi_io_vec + bio->bi_idx,
+               .mem.type = DM_IO_BIO,
+               .mem.ptr.bio = bio,
                .notify.fn = write_callback,
                .notify.context = bio,
                .client = ms->io_client,
@@ -1181,7 +1181,7 @@ static int mirror_map(struct dm_target *ti, struct bio *bio)
         * The region is in-sync and we can perform reads directly.
         * Store enough information so we can retry if it fails.
         */
-       m = choose_mirror(ms, bio->bi_sector);
+       m = choose_mirror(ms, bio->bi_iter.bi_sector);
        if (unlikely(!m))
                return -EIO;
 
index 69732e03eb3490d636a0183bd22303742ab65c65..b929fd5f4984bb67fbb62474e24e5af425758770 100644 (file)
@@ -126,7 +126,8 @@ EXPORT_SYMBOL_GPL(dm_rh_region_to_sector);
 
 region_t dm_rh_bio_to_region(struct dm_region_hash *rh, struct bio *bio)
 {
-       return dm_rh_sector_to_region(rh, bio->bi_sector - rh->target_begin);
+       return dm_rh_sector_to_region(rh, bio->bi_iter.bi_sector -
+                                     rh->target_begin);
 }
 EXPORT_SYMBOL_GPL(dm_rh_bio_to_region);
 
index aec57d76db5d616c8e692fa95cee58a8f62a0573..01b6a11813f29e5ab32e3af144714ab28dc26089 100644 (file)
@@ -66,6 +66,18 @@ struct dm_snapshot {
 
        atomic_t pending_exceptions_count;
 
+       /* Protected by "lock" */
+       sector_t exception_start_sequence;
+
+       /* Protected by kcopyd single-threaded callback */
+       sector_t exception_complete_sequence;
+
+       /*
+        * A list of pending exceptions that completed out of order.
+        * Protected by kcopyd single-threaded callback.
+        */
+       struct list_head out_of_order_list;
+
        mempool_t *pending_pool;
 
        struct dm_exception_table pending;
@@ -173,6 +185,14 @@ struct dm_snap_pending_exception {
         */
        int started;
 
+       /* There was copying error. */
+       int copy_error;
+
+       /* A sequence number, it is used for in-order completion. */
+       sector_t exception_sequence;
+
+       struct list_head out_of_order_entry;
+
        /*
         * For writing a complete chunk, bypassing the copy.
         */
@@ -1094,6 +1114,9 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        s->valid = 1;
        s->active = 0;
        atomic_set(&s->pending_exceptions_count, 0);
+       s->exception_start_sequence = 0;
+       s->exception_complete_sequence = 0;
+       INIT_LIST_HEAD(&s->out_of_order_list);
        init_rwsem(&s->lock);
        INIT_LIST_HEAD(&s->list);
        spin_lock_init(&s->pe_lock);
@@ -1415,6 +1438,7 @@ out:
        if (full_bio) {
                full_bio->bi_end_io = pe->full_bio_end_io;
                full_bio->bi_private = pe->full_bio_private;
+               atomic_inc(&full_bio->bi_remaining);
        }
        free_pending_exception(pe);
 
@@ -1443,6 +1467,19 @@ static void commit_callback(void *context, int success)
        pending_complete(pe, success);
 }
 
+static void complete_exception(struct dm_snap_pending_exception *pe)
+{
+       struct dm_snapshot *s = pe->snap;
+
+       if (unlikely(pe->copy_error))
+               pending_complete(pe, 0);
+
+       else
+               /* Update the metadata if we are persistent */
+               s->store->type->commit_exception(s->store, &pe->e,
+                                                commit_callback, pe);
+}
+
 /*
  * Called when the copy I/O has finished.  kcopyd actually runs
  * this code so don't block.
@@ -1452,13 +1489,32 @@ static void copy_callback(int read_err, unsigned long write_err, void *context)
        struct dm_snap_pending_exception *pe = context;
        struct dm_snapshot *s = pe->snap;
 
-       if (read_err || write_err)
-               pending_complete(pe, 0);
+       pe->copy_error = read_err || write_err;
 
-       else
-               /* Update the metadata if we are persistent */
-               s->store->type->commit_exception(s->store, &pe->e,
-                                                commit_callback, pe);
+       if (pe->exception_sequence == s->exception_complete_sequence) {
+               s->exception_complete_sequence++;
+               complete_exception(pe);
+
+               while (!list_empty(&s->out_of_order_list)) {
+                       pe = list_entry(s->out_of_order_list.next,
+                                       struct dm_snap_pending_exception, out_of_order_entry);
+                       if (pe->exception_sequence != s->exception_complete_sequence)
+                               break;
+                       s->exception_complete_sequence++;
+                       list_del(&pe->out_of_order_entry);
+                       complete_exception(pe);
+               }
+       } else {
+               struct list_head *lh;
+               struct dm_snap_pending_exception *pe2;
+
+               list_for_each_prev(lh, &s->out_of_order_list) {
+                       pe2 = list_entry(lh, struct dm_snap_pending_exception, out_of_order_entry);
+                       if (pe2->exception_sequence < pe->exception_sequence)
+                               break;
+               }
+               list_add(&pe->out_of_order_entry, lh);
+       }
 }
 
 /*
@@ -1553,6 +1609,8 @@ __find_pending_exception(struct dm_snapshot *s,
                return NULL;
        }
 
+       pe->exception_sequence = s->exception_start_sequence++;
+
        dm_insert_exception(&s->pending, &pe->e);
 
        return pe;
@@ -1562,11 +1620,10 @@ static void remap_exception(struct dm_snapshot *s, struct dm_exception *e,
                            struct bio *bio, chunk_t chunk)
 {
        bio->bi_bdev = s->cow->bdev;
-       bio->bi_sector = chunk_to_sector(s->store,
-                                        dm_chunk_number(e->new_chunk) +
-                                        (chunk - e->old_chunk)) +
-                                        (bio->bi_sector &
-                                         s->store->chunk_mask);
+       bio->bi_iter.bi_sector =
+               chunk_to_sector(s->store, dm_chunk_number(e->new_chunk) +
+                               (chunk - e->old_chunk)) +
+               (bio->bi_iter.bi_sector & s->store->chunk_mask);
 }
 
 static int snapshot_map(struct dm_target *ti, struct bio *bio)
@@ -1584,7 +1641,7 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio)
                return DM_MAPIO_REMAPPED;
        }
 
-       chunk = sector_to_chunk(s->store, bio->bi_sector);
+       chunk = sector_to_chunk(s->store, bio->bi_iter.bi_sector);
 
        /* Full snapshots are not usable */
        /* To get here the table must be live so s->active is always set. */
@@ -1645,7 +1702,8 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio)
                r = DM_MAPIO_SUBMITTED;
 
                if (!pe->started &&
-                   bio->bi_size == (s->store->chunk_size << SECTOR_SHIFT)) {
+                   bio->bi_iter.bi_size ==
+                   (s->store->chunk_size << SECTOR_SHIFT)) {
                        pe->started = 1;
                        up_write(&s->lock);
                        start_full_bio(pe, bio);
@@ -1701,7 +1759,7 @@ static int snapshot_merge_map(struct dm_target *ti, struct bio *bio)
                return DM_MAPIO_REMAPPED;
        }
 
-       chunk = sector_to_chunk(s->store, bio->bi_sector);
+       chunk = sector_to_chunk(s->store, bio->bi_iter.bi_sector);
 
        down_write(&s->lock);
 
@@ -2038,7 +2096,7 @@ static int do_origin(struct dm_dev *origin, struct bio *bio)
        down_read(&_origins_lock);
        o = __lookup_origin(origin->bdev);
        if (o)
-               r = __origin_write(&o->snapshots, bio->bi_sector, bio);
+               r = __origin_write(&o->snapshots, bio->bi_iter.bi_sector, bio);
        up_read(&_origins_lock);
 
        return r;
@@ -2192,7 +2250,7 @@ static struct target_type origin_target = {
 
 static struct target_type snapshot_target = {
        .name    = "snapshot",
-       .version = {1, 11, 1},
+       .version = {1, 12, 0},
        .module  = THIS_MODULE,
        .ctr     = snapshot_ctr,
        .dtr     = snapshot_dtr,
index 3d404c1371ed2d7e6f4fa052fd4379fbc89ec388..28a90122a5a89272f5873ed0911d2de19125c15b 100644 (file)
@@ -964,6 +964,7 @@ int dm_stats_message(struct mapped_device *md, unsigned argc, char **argv,
 
 int __init dm_statistics_init(void)
 {
+       shared_memory_amount = 0;
        dm_stat_need_rcu_barrier = 0;
        return 0;
 }
index 73c1712dad96d09f2760416852dd0cacd22cbd33..d1600d2aa2e2e6983643ef0ef864195f858d4f9d 100644 (file)
@@ -259,13 +259,15 @@ static int stripe_map_range(struct stripe_c *sc, struct bio *bio,
 {
        sector_t begin, end;
 
-       stripe_map_range_sector(sc, bio->bi_sector, target_stripe, &begin);
+       stripe_map_range_sector(sc, bio->bi_iter.bi_sector,
+                               target_stripe, &begin);
        stripe_map_range_sector(sc, bio_end_sector(bio),
                                target_stripe, &end);
        if (begin < end) {
                bio->bi_bdev = sc->stripe[target_stripe].dev->bdev;
-               bio->bi_sector = begin + sc->stripe[target_stripe].physical_start;
-               bio->bi_size = to_bytes(end - begin);
+               bio->bi_iter.bi_sector = begin +
+                       sc->stripe[target_stripe].physical_start;
+               bio->bi_iter.bi_size = to_bytes(end - begin);
                return DM_MAPIO_REMAPPED;
        } else {
                /* The range doesn't map to the target stripe */
@@ -293,9 +295,10 @@ static int stripe_map(struct dm_target *ti, struct bio *bio)
                return stripe_map_range(sc, bio, target_bio_nr);
        }
 
-       stripe_map_sector(sc, bio->bi_sector, &stripe, &bio->bi_sector);
+       stripe_map_sector(sc, bio->bi_iter.bi_sector,
+                         &stripe, &bio->bi_iter.bi_sector);
 
-       bio->bi_sector += sc->stripe[stripe].physical_start;
+       bio->bi_iter.bi_sector += sc->stripe[stripe].physical_start;
        bio->bi_bdev = sc->stripe[stripe].dev->bdev;
 
        return DM_MAPIO_REMAPPED;
index ff9ac4be47210839369e233d1d1dfc161cbfb852..09a688b3d48ca1445e136544321a54b112b280e1 100644 (file)
@@ -311,11 +311,11 @@ error:
 static int switch_map(struct dm_target *ti, struct bio *bio)
 {
        struct switch_ctx *sctx = ti->private;
-       sector_t offset = dm_target_offset(ti, bio->bi_sector);
+       sector_t offset = dm_target_offset(ti, bio->bi_iter.bi_sector);
        unsigned path_nr = switch_get_path_nr(sctx, offset);
 
        bio->bi_bdev = sctx->path_list[path_nr].dmdev->bdev;
-       bio->bi_sector = sctx->path_list[path_nr].start + offset;
+       bio->bi_iter.bi_sector = sctx->path_list[path_nr].start + offset;
 
        return DM_MAPIO_REMAPPED;
 }
index 465f08ca62b1e355f8fd776fac4a6159d79a1a2e..3ba6a3859ce3c4957439ff3afdc4a5133bc2900b 100644 (file)
@@ -200,6 +200,11 @@ int dm_table_create(struct dm_table **result, fmode_t mode,
 
        num_targets = dm_round_up(num_targets, KEYS_PER_NODE);
 
+       if (!num_targets) {
+               kfree(t);
+               return -ENOMEM;
+       }
+
        if (alloc_targets(t, num_targets)) {
                kfree(t);
                return -ENOMEM;
index 60bce435f4fa1443c2994bd483e70ea096c7aa92..8a30ad54bd46aabc72f4ac1800890b5bd8041e11 100644 (file)
@@ -1697,6 +1697,14 @@ void dm_pool_metadata_read_only(struct dm_pool_metadata *pmd)
        up_write(&pmd->root_lock);
 }
 
+void dm_pool_metadata_read_write(struct dm_pool_metadata *pmd)
+{
+       down_write(&pmd->root_lock);
+       pmd->read_only = false;
+       dm_bm_set_read_write(pmd->bm);
+       up_write(&pmd->root_lock);
+}
+
 int dm_pool_register_metadata_threshold(struct dm_pool_metadata *pmd,
                                        dm_block_t threshold,
                                        dm_sm_threshold_fn fn,
index 845ebbe589a9e0a00505bab0150df48331233928..7bcc0e1d62386768d540c41da8e0a25bf7fe9e78 100644 (file)
@@ -193,6 +193,7 @@ int dm_pool_resize_metadata_dev(struct dm_pool_metadata *pmd, dm_block_t new_siz
  * that nothing is changing.
  */
 void dm_pool_metadata_read_only(struct dm_pool_metadata *pmd);
+void dm_pool_metadata_read_write(struct dm_pool_metadata *pmd);
 
 int dm_pool_register_metadata_threshold(struct dm_pool_metadata *pmd,
                                        dm_block_t threshold,
index 2c0cf511ec2385fa5a558b5d2e1e1ed0c874c9f6..357eb272dbd9d3337bf5d1a13db443261eb2b24b 100644 (file)
@@ -413,7 +413,7 @@ static bool block_size_is_power_of_two(struct pool *pool)
 static dm_block_t get_bio_block(struct thin_c *tc, struct bio *bio)
 {
        struct pool *pool = tc->pool;
-       sector_t block_nr = bio->bi_sector;
+       sector_t block_nr = bio->bi_iter.bi_sector;
 
        if (block_size_is_power_of_two(pool))
                block_nr >>= pool->sectors_per_block_shift;
@@ -426,14 +426,15 @@ static dm_block_t get_bio_block(struct thin_c *tc, struct bio *bio)
 static void remap(struct thin_c *tc, struct bio *bio, dm_block_t block)
 {
        struct pool *pool = tc->pool;
-       sector_t bi_sector = bio->bi_sector;
+       sector_t bi_sector = bio->bi_iter.bi_sector;
 
        bio->bi_bdev = tc->pool_dev->bdev;
        if (block_size_is_power_of_two(pool))
-               bio->bi_sector = (block << pool->sectors_per_block_shift) |
-                               (bi_sector & (pool->sectors_per_block - 1));
+               bio->bi_iter.bi_sector =
+                       (block << pool->sectors_per_block_shift) |
+                       (bi_sector & (pool->sectors_per_block - 1));
        else
-               bio->bi_sector = (block * pool->sectors_per_block) +
+               bio->bi_iter.bi_sector = (block * pool->sectors_per_block) +
                                 sector_div(bi_sector, pool->sectors_per_block);
 }
 
@@ -610,8 +611,10 @@ static void cell_defer_no_holder(struct thin_c *tc, struct dm_bio_prison_cell *c
 
 static void process_prepared_mapping_fail(struct dm_thin_new_mapping *m)
 {
-       if (m->bio)
+       if (m->bio) {
                m->bio->bi_end_io = m->saved_bi_end_io;
+               atomic_inc(&m->bio->bi_remaining);
+       }
        cell_error(m->tc->pool, m->cell);
        list_del(&m->list);
        mempool_free(m, m->tc->pool->mapping_pool);
@@ -625,8 +628,10 @@ static void process_prepared_mapping(struct dm_thin_new_mapping *m)
        int r;
 
        bio = m->bio;
-       if (bio)
+       if (bio) {
                bio->bi_end_io = m->saved_bi_end_io;
+               atomic_inc(&bio->bi_remaining);
+       }
 
        if (m->err) {
                cell_error(pool, m->cell);
@@ -640,7 +645,9 @@ static void process_prepared_mapping(struct dm_thin_new_mapping *m)
         */
        r = dm_thin_insert_block(tc->td, m->virt_block, m->data_block);
        if (r) {
-               DMERR_LIMIT("dm_thin_insert_block() failed");
+               DMERR_LIMIT("%s: dm_thin_insert_block() failed: error = %d",
+                           dm_device_name(pool->pool_md), r);
+               set_pool_mode(pool, PM_READ_ONLY);
                cell_error(pool, m->cell);
                goto out;
        }
@@ -721,7 +728,8 @@ static void process_prepared(struct pool *pool, struct list_head *head,
  */
 static int io_overlaps_block(struct pool *pool, struct bio *bio)
 {
-       return bio->bi_size == (pool->sectors_per_block << SECTOR_SHIFT);
+       return bio->bi_iter.bi_size ==
+               (pool->sectors_per_block << SECTOR_SHIFT);
 }
 
 static int io_overwrites_block(struct pool *pool, struct bio *bio)
@@ -881,32 +889,23 @@ static void schedule_zero(struct thin_c *tc, dm_block_t virt_block,
        }
 }
 
-static int commit(struct pool *pool)
-{
-       int r;
-
-       r = dm_pool_commit_metadata(pool->pmd);
-       if (r)
-               DMERR_LIMIT("%s: commit failed: error = %d",
-                           dm_device_name(pool->pool_md), r);
-
-       return r;
-}
-
 /*
  * A non-zero return indicates read_only or fail_io mode.
  * Many callers don't care about the return value.
  */
-static int commit_or_fallback(struct pool *pool)
+static int commit(struct pool *pool)
 {
        int r;
 
        if (get_pool_mode(pool) != PM_WRITE)
                return -EINVAL;
 
-       r = commit(pool);
-       if (r)
+       r = dm_pool_commit_metadata(pool->pmd);
+       if (r) {
+               DMERR_LIMIT("%s: dm_pool_commit_metadata failed: error = %d",
+                           dm_device_name(pool->pool_md), r);
                set_pool_mode(pool, PM_READ_ONLY);
+       }
 
        return r;
 }
@@ -943,7 +942,9 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result)
                 * Try to commit to see if that will free up some
                 * more space.
                 */
-               (void) commit_or_fallback(pool);
+               r = commit(pool);
+               if (r)
+                       return r;
 
                r = dm_pool_get_free_block_count(pool->pmd, &free_blocks);
                if (r)
@@ -957,7 +958,7 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result)
                 * table reload).
                 */
                if (!free_blocks) {
-                       DMWARN("%s: no free space available.",
+                       DMWARN("%s: no free data space available.",
                               dm_device_name(pool->pool_md));
                        spin_lock_irqsave(&pool->lock, flags);
                        pool->no_free_space = 1;
@@ -967,8 +968,16 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result)
        }
 
        r = dm_pool_alloc_data_block(pool->pmd, result);
-       if (r)
+       if (r) {
+               if (r == -ENOSPC &&
+                   !dm_pool_get_free_metadata_block_count(pool->pmd, &free_blocks) &&
+                   !free_blocks) {
+                       DMWARN("%s: no free metadata space available.",
+                              dm_device_name(pool->pool_md));
+                       set_pool_mode(pool, PM_READ_ONLY);
+               }
                return r;
+       }
 
        return 0;
 }
@@ -1130,7 +1139,7 @@ static void process_shared_bio(struct thin_c *tc, struct bio *bio,
        if (bio_detain(pool, &key, bio, &cell))
                return;
 
-       if (bio_data_dir(bio) == WRITE && bio->bi_size)
+       if (bio_data_dir(bio) == WRITE && bio->bi_iter.bi_size)
                break_sharing(tc, bio, block, &key, lookup_result, cell);
        else {
                struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook));
@@ -1153,7 +1162,7 @@ static void provision_block(struct thin_c *tc, struct bio *bio, dm_block_t block
        /*
         * Remap empty bios (flushes) immediately, without provisioning.
         */
-       if (!bio->bi_size) {
+       if (!bio->bi_iter.bi_size) {
                inc_all_io_entry(pool, bio);
                cell_defer_no_holder(tc, cell);
 
@@ -1253,7 +1262,7 @@ static void process_bio_read_only(struct thin_c *tc, struct bio *bio)
        r = dm_thin_find_block(tc->td, block, 1, &lookup_result);
        switch (r) {
        case 0:
-               if (lookup_result.shared && (rw == WRITE) && bio->bi_size)
+               if (lookup_result.shared && (rw == WRITE) && bio->bi_iter.bi_size)
                        bio_io_error(bio);
                else {
                        inc_all_io_entry(tc->pool, bio);
@@ -1349,7 +1358,7 @@ static void process_deferred_bios(struct pool *pool)
        if (bio_list_empty(&bios) && !need_commit_due_to_time(pool))
                return;
 
-       if (commit_or_fallback(pool)) {
+       if (commit(pool)) {
                while ((bio = bio_list_pop(&bios)))
                        bio_io_error(bio);
                return;
@@ -1397,6 +1406,7 @@ static void set_pool_mode(struct pool *pool, enum pool_mode mode)
        case PM_FAIL:
                DMERR("%s: switching pool to failure mode",
                      dm_device_name(pool->pool_md));
+               dm_pool_metadata_read_only(pool->pmd);
                pool->process_bio = process_bio_fail;
                pool->process_discard = process_bio_fail;
                pool->process_prepared_mapping = process_prepared_mapping_fail;
@@ -1421,6 +1431,7 @@ static void set_pool_mode(struct pool *pool, enum pool_mode mode)
                break;
 
        case PM_WRITE:
+               dm_pool_metadata_read_write(pool->pmd);
                pool->process_bio = process_bio;
                pool->process_discard = process_discard;
                pool->process_prepared_mapping = process_prepared_mapping;
@@ -1637,12 +1648,19 @@ static int bind_control_target(struct pool *pool, struct dm_target *ti)
        struct pool_c *pt = ti->private;
 
        /*
-        * We want to make sure that degraded pools are never upgraded.
+        * We want to make sure that a pool in PM_FAIL mode is never upgraded.
         */
        enum pool_mode old_mode = pool->pf.mode;
        enum pool_mode new_mode = pt->adjusted_pf.mode;
 
-       if (old_mode > new_mode)
+       /*
+        * If we were in PM_FAIL mode, rollback of metadata failed.  We're
+        * not going to recover without a thin_repair.  So we never let the
+        * pool move out of the old mode.  On the other hand a PM_READ_ONLY
+        * may have been due to a lack of metadata or data space, and may
+        * now work (ie. if the underlying devices have been resized).
+        */
+       if (old_mode == PM_FAIL)
                new_mode = old_mode;
 
        pool->ti = ti;
@@ -2266,7 +2284,7 @@ static int pool_preresume(struct dm_target *ti)
                return r;
 
        if (need_commit1 || need_commit2)
-               (void) commit_or_fallback(pool);
+               (void) commit(pool);
 
        return 0;
 }
@@ -2293,7 +2311,7 @@ static void pool_postsuspend(struct dm_target *ti)
 
        cancel_delayed_work(&pool->waker);
        flush_workqueue(pool->wq);
-       (void) commit_or_fallback(pool);
+       (void) commit(pool);
 }
 
 static int check_arg_count(unsigned argc, unsigned args_required)
@@ -2427,7 +2445,7 @@ static int process_reserve_metadata_snap_mesg(unsigned argc, char **argv, struct
        if (r)
                return r;
 
-       (void) commit_or_fallback(pool);
+       (void) commit(pool);
 
        r = dm_pool_reserve_metadata_snap(pool->pmd);
        if (r)
@@ -2489,7 +2507,7 @@ static int pool_message(struct dm_target *ti, unsigned argc, char **argv)
                DMWARN("Unrecognised thin pool target message received: %s", argv[0]);
 
        if (!r)
-               (void) commit_or_fallback(pool);
+               (void) commit(pool);
 
        return r;
 }
@@ -2544,7 +2562,7 @@ static void pool_status(struct dm_target *ti, status_type_t type,
 
                /* Commit to ensure statistics aren't out-of-date */
                if (!(status_flags & DM_STATUS_NOFLUSH_FLAG) && !dm_suspended(ti))
-                       (void) commit_or_fallback(pool);
+                       (void) commit(pool);
 
                r = dm_pool_get_metadata_transaction_id(pool->pmd, &transaction_id);
                if (r) {
@@ -2867,7 +2885,7 @@ out_unlock:
 
 static int thin_map(struct dm_target *ti, struct bio *bio)
 {
-       bio->bi_sector = dm_target_offset(ti, bio->bi_sector);
+       bio->bi_iter.bi_sector = dm_target_offset(ti, bio->bi_iter.bi_sector);
 
        return thin_bio_map(ti, bio);
 }
index 4b7941db3aff33223481464f24a162d101ab7698..796007a5e0e1a4b6e83b0871c1fca1ef8c0c461f 100644 (file)
@@ -73,15 +73,10 @@ struct dm_verity_io {
        sector_t block;
        unsigned n_blocks;
 
-       /* saved bio vector */
-       struct bio_vec *io_vec;
-       unsigned io_vec_size;
+       struct bvec_iter iter;
 
        struct work_struct work;
 
-       /* A space for short vectors; longer vectors are allocated separately. */
-       struct bio_vec io_vec_inline[DM_VERITY_IO_VEC_INLINE];
-
        /*
         * Three variably-size fields follow this struct:
         *
@@ -284,9 +279,10 @@ release_ret_r:
 static int verity_verify_io(struct dm_verity_io *io)
 {
        struct dm_verity *v = io->v;
+       struct bio *bio = dm_bio_from_per_bio_data(io,
+                                                  v->ti->per_bio_data_size);
        unsigned b;
        int i;
-       unsigned vector = 0, offset = 0;
 
        for (b = 0; b < io->n_blocks; b++) {
                struct shash_desc *desc;
@@ -336,31 +332,22 @@ test_block_hash:
                }
 
                todo = 1 << v->data_dev_block_bits;
-               do {
-                       struct bio_vec *bv;
+               while (io->iter.bi_size) {
                        u8 *page;
-                       unsigned len;
-
-                       BUG_ON(vector >= io->io_vec_size);
-                       bv = &io->io_vec[vector];
-                       page = kmap_atomic(bv->bv_page);
-                       len = bv->bv_len - offset;
-                       if (likely(len >= todo))
-                               len = todo;
-                       r = crypto_shash_update(desc,
-                                       page + bv->bv_offset + offset, len);
+                       struct bio_vec bv = bio_iter_iovec(bio, io->iter);
+
+                       page = kmap_atomic(bv.bv_page);
+                       r = crypto_shash_update(desc, page + bv.bv_offset,
+                                               bv.bv_len);
                        kunmap_atomic(page);
+
                        if (r < 0) {
                                DMERR("crypto_shash_update failed: %d", r);
                                return r;
                        }
-                       offset += len;
-                       if (likely(offset == bv->bv_len)) {
-                               offset = 0;
-                               vector++;
-                       }
-                       todo -= len;
-               } while (todo);
+
+                       bio_advance_iter(bio, &io->iter, bv.bv_len);
+               }
 
                if (!v->version) {
                        r = crypto_shash_update(desc, v->salt, v->salt_size);
@@ -383,8 +370,6 @@ test_block_hash:
                        return -EIO;
                }
        }
-       BUG_ON(vector != io->io_vec_size);
-       BUG_ON(offset);
 
        return 0;
 }
@@ -400,10 +385,7 @@ static void verity_finish_io(struct dm_verity_io *io, int error)
        bio->bi_end_io = io->orig_bi_end_io;
        bio->bi_private = io->orig_bi_private;
 
-       if (io->io_vec != io->io_vec_inline)
-               mempool_free(io->io_vec, v->vec_mempool);
-
-       bio_endio(bio, error);
+       bio_endio_nodec(bio, error);
 }
 
 static void verity_work(struct work_struct *w)
@@ -493,9 +475,9 @@ static int verity_map(struct dm_target *ti, struct bio *bio)
        struct dm_verity_io *io;
 
        bio->bi_bdev = v->data_dev->bdev;
-       bio->bi_sector = verity_map_sector(v, bio->bi_sector);
+       bio->bi_iter.bi_sector = verity_map_sector(v, bio->bi_iter.bi_sector);
 
-       if (((unsigned)bio->bi_sector | bio_sectors(bio)) &
+       if (((unsigned)bio->bi_iter.bi_sector | bio_sectors(bio)) &
            ((1 << (v->data_dev_block_bits - SECTOR_SHIFT)) - 1)) {
                DMERR_LIMIT("unaligned io");
                return -EIO;
@@ -514,18 +496,12 @@ static int verity_map(struct dm_target *ti, struct bio *bio)
        io->v = v;
        io->orig_bi_end_io = bio->bi_end_io;
        io->orig_bi_private = bio->bi_private;
-       io->block = bio->bi_sector >> (v->data_dev_block_bits - SECTOR_SHIFT);
-       io->n_blocks = bio->bi_size >> v->data_dev_block_bits;
+       io->block = bio->bi_iter.bi_sector >> (v->data_dev_block_bits - SECTOR_SHIFT);
+       io->n_blocks = bio->bi_iter.bi_size >> v->data_dev_block_bits;
 
        bio->bi_end_io = verity_end_io;
        bio->bi_private = io;
-       io->io_vec_size = bio_segments(bio);
-       if (io->io_vec_size < DM_VERITY_IO_VEC_INLINE)
-               io->io_vec = io->io_vec_inline;
-       else
-               io->io_vec = mempool_alloc(v->vec_mempool, GFP_NOIO);
-       memcpy(io->io_vec, bio_iovec(bio),
-              io->io_vec_size * sizeof(struct bio_vec));
+       io->iter = bio->bi_iter;
 
        verity_submit_prefetch(v, io);
 
index 0704c523a76b98e41413599aa2707e0f16eeb25a..44a2fa6814ce97cbd05d3e3e34c65672c6dbbebe 100644 (file)
@@ -575,7 +575,7 @@ static void start_io_acct(struct dm_io *io)
                atomic_inc_return(&md->pending[rw]));
 
        if (unlikely(dm_stats_used(&md->stats)))
-               dm_stats_account_io(&md->stats, bio->bi_rw, bio->bi_sector,
+               dm_stats_account_io(&md->stats, bio->bi_rw, bio->bi_iter.bi_sector,
                                    bio_sectors(bio), false, 0, &io->stats_aux);
 }
 
@@ -593,7 +593,7 @@ static void end_io_acct(struct dm_io *io)
        part_stat_unlock();
 
        if (unlikely(dm_stats_used(&md->stats)))
-               dm_stats_account_io(&md->stats, bio->bi_rw, bio->bi_sector,
+               dm_stats_account_io(&md->stats, bio->bi_rw, bio->bi_iter.bi_sector,
                                    bio_sectors(bio), true, duration, &io->stats_aux);
 
        /*
@@ -742,7 +742,7 @@ static void dec_pending(struct dm_io *io, int error)
                if (io_error == DM_ENDIO_REQUEUE)
                        return;
 
-               if ((bio->bi_rw & REQ_FLUSH) && bio->bi_size) {
+               if ((bio->bi_rw & REQ_FLUSH) && bio->bi_iter.bi_size) {
                        /*
                         * Preflush done for flush with data, reissue
                         * without REQ_FLUSH.
@@ -797,7 +797,7 @@ static void end_clone_bio(struct bio *clone, int error)
        struct dm_rq_clone_bio_info *info = clone->bi_private;
        struct dm_rq_target_io *tio = info->tio;
        struct bio *bio = info->orig;
-       unsigned int nr_bytes = info->orig->bi_size;
+       unsigned int nr_bytes = info->orig->bi_iter.bi_size;
 
        bio_put(clone);
 
@@ -1128,7 +1128,7 @@ static void __map_bio(struct dm_target_io *tio)
         * this io.
         */
        atomic_inc(&tio->io->io_count);
-       sector = clone->bi_sector;
+       sector = clone->bi_iter.bi_sector;
        r = ti->type->map(ti, clone);
        if (r == DM_MAPIO_REMAPPED) {
                /* the bio has been remapped so dispatch it */
@@ -1155,76 +1155,32 @@ struct clone_info {
        struct dm_io *io;
        sector_t sector;
        sector_t sector_count;
-       unsigned short idx;
 };
 
 static void bio_setup_sector(struct bio *bio, sector_t sector, sector_t len)
 {
-       bio->bi_sector = sector;
-       bio->bi_size = to_bytes(len);
-}
-
-static void bio_setup_bv(struct bio *bio, unsigned short idx, unsigned short bv_count)
-{
-       bio->bi_idx = idx;
-       bio->bi_vcnt = idx + bv_count;
-       bio->bi_flags &= ~(1 << BIO_SEG_VALID);
-}
-
-static void clone_bio_integrity(struct bio *bio, struct bio *clone,
-                               unsigned short idx, unsigned len, unsigned offset,
-                               unsigned trim)
-{
-       if (!bio_integrity(bio))
-               return;
-
-       bio_integrity_clone(clone, bio, GFP_NOIO);
-
-       if (trim)
-               bio_integrity_trim(clone, bio_sector_offset(bio, idx, offset), len);
-}
-
-/*
- * Creates a little bio that just does part of a bvec.
- */
-static void clone_split_bio(struct dm_target_io *tio, struct bio *bio,
-                           sector_t sector, unsigned short idx,
-                           unsigned offset, unsigned len)
-{
-       struct bio *clone = &tio->clone;
-       struct bio_vec *bv = bio->bi_io_vec + idx;
-
-       *clone->bi_io_vec = *bv;
-
-       bio_setup_sector(clone, sector, len);
-
-       clone->bi_bdev = bio->bi_bdev;
-       clone->bi_rw = bio->bi_rw;
-       clone->bi_vcnt = 1;
-       clone->bi_io_vec->bv_offset = offset;
-       clone->bi_io_vec->bv_len = clone->bi_size;
-       clone->bi_flags |= 1 << BIO_CLONED;
-
-       clone_bio_integrity(bio, clone, idx, len, offset, 1);
+       bio->bi_iter.bi_sector = sector;
+       bio->bi_iter.bi_size = to_bytes(len);
 }
 
 /*
  * Creates a bio that consists of range of complete bvecs.
  */
 static void clone_bio(struct dm_target_io *tio, struct bio *bio,
-                     sector_t sector, unsigned short idx,
-                     unsigned short bv_count, unsigned len)
+                     sector_t sector, unsigned len)
 {
        struct bio *clone = &tio->clone;
-       unsigned trim = 0;
 
-       __bio_clone(clone, bio);
-       bio_setup_sector(clone, sector, len);
-       bio_setup_bv(clone, idx, bv_count);
+       __bio_clone_fast(clone, bio);
+
+       if (bio_integrity(bio))
+               bio_integrity_clone(clone, bio, GFP_NOIO);
+
+       bio_advance(clone, to_bytes(sector - clone->bi_iter.bi_sector));
+       clone->bi_iter.bi_size = to_bytes(len);
 
-       if (idx != bio->bi_idx || clone->bi_size < bio->bi_size)
-               trim = 1;
-       clone_bio_integrity(bio, clone, idx, len, 0, trim);
+       if (bio_integrity(bio))
+               bio_integrity_trim(clone, 0, len);
 }
 
 static struct dm_target_io *alloc_tio(struct clone_info *ci,
@@ -1257,7 +1213,7 @@ static void __clone_and_map_simple_bio(struct clone_info *ci,
         * ci->bio->bi_max_vecs is BIO_INLINE_VECS anyway, for both flush
         * and discard, so no need for concern about wasted bvec allocations.
         */
-        __bio_clone(clone, ci->bio);
+        __bio_clone_fast(clone, ci->bio);
        if (len)
                bio_setup_sector(clone, ci->sector, len);
 
@@ -1286,10 +1242,7 @@ static int __send_empty_flush(struct clone_info *ci)
 }
 
 static void __clone_and_map_data_bio(struct clone_info *ci, struct dm_target *ti,
-                                    sector_t sector, int nr_iovecs,
-                                    unsigned short idx, unsigned short bv_count,
-                                    unsigned offset, unsigned len,
-                                    unsigned split_bvec)
+                                    sector_t sector, unsigned len)
 {
        struct bio *bio = ci->bio;
        struct dm_target_io *tio;
@@ -1303,11 +1256,8 @@ static void __clone_and_map_data_bio(struct clone_info *ci, struct dm_target *ti
                num_target_bios = ti->num_write_bios(ti, bio);
 
        for (target_bio_nr = 0; target_bio_nr < num_target_bios; target_bio_nr++) {
-               tio = alloc_tio(ci, ti, nr_iovecs, target_bio_nr);
-               if (split_bvec)
-                       clone_split_bio(tio, bio, sector, idx, offset, len);
-               else
-                       clone_bio(tio, bio, sector, idx, bv_count, len);
+               tio = alloc_tio(ci, ti, 0, target_bio_nr);
+               clone_bio(tio, bio, sector, len);
                __map_bio(tio);
        }
 }
@@ -1378,60 +1328,6 @@ static int __send_write_same(struct clone_info *ci)
        return __send_changing_extent_only(ci, get_num_write_same_bios, NULL);
 }
 
-/*
- * Find maximum number of sectors / bvecs we can process with a single bio.
- */
-static sector_t __len_within_target(struct clone_info *ci, sector_t max, int *idx)
-{
-       struct bio *bio = ci->bio;
-       sector_t bv_len, total_len = 0;
-
-       for (*idx = ci->idx; max && (*idx < bio->bi_vcnt); (*idx)++) {
-               bv_len = to_sector(bio->bi_io_vec[*idx].bv_len);
-
-               if (bv_len > max)
-                       break;
-
-               max -= bv_len;
-               total_len += bv_len;
-       }
-
-       return total_len;
-}
-
-static int __split_bvec_across_targets(struct clone_info *ci,
-                                      struct dm_target *ti, sector_t max)
-{
-       struct bio *bio = ci->bio;
-       struct bio_vec *bv = bio->bi_io_vec + ci->idx;
-       sector_t remaining = to_sector(bv->bv_len);
-       unsigned offset = 0;
-       sector_t len;
-
-       do {
-               if (offset) {
-                       ti = dm_table_find_target(ci->map, ci->sector);
-                       if (!dm_target_is_valid(ti))
-                               return -EIO;
-
-                       max = max_io_len(ci->sector, ti);
-               }
-
-               len = min(remaining, max);
-
-               __clone_and_map_data_bio(ci, ti, ci->sector, 1, ci->idx, 0,
-                                        bv->bv_offset + offset, len, 1);
-
-               ci->sector += len;
-               ci->sector_count -= len;
-               offset += to_bytes(len);
-       } while (remaining -= len);
-
-       ci->idx++;
-
-       return 0;
-}
-
 /*
  * Select the correct strategy for processing a non-flush bio.
  */
@@ -1439,8 +1335,7 @@ static int __split_and_process_non_flush(struct clone_info *ci)
 {
        struct bio *bio = ci->bio;
        struct dm_target *ti;
-       sector_t len, max;
-       int idx;
+       unsigned len;
 
        if (unlikely(bio->bi_rw & REQ_DISCARD))
                return __send_discard(ci);
@@ -1451,41 +1346,14 @@ static int __split_and_process_non_flush(struct clone_info *ci)
        if (!dm_target_is_valid(ti))
                return -EIO;
 
-       max = max_io_len(ci->sector, ti);
-
-       /*
-        * Optimise for the simple case where we can do all of
-        * the remaining io with a single clone.
-        */
-       if (ci->sector_count <= max) {
-               __clone_and_map_data_bio(ci, ti, ci->sector, bio->bi_max_vecs,
-                                        ci->idx, bio->bi_vcnt - ci->idx, 0,
-                                        ci->sector_count, 0);
-               ci->sector_count = 0;
-               return 0;
-       }
-
-       /*
-        * There are some bvecs that don't span targets.
-        * Do as many of these as possible.
-        */
-       if (to_sector(bio->bi_io_vec[ci->idx].bv_len) <= max) {
-               len = __len_within_target(ci, max, &idx);
-
-               __clone_and_map_data_bio(ci, ti, ci->sector, bio->bi_max_vecs,
-                                        ci->idx, idx - ci->idx, 0, len, 0);
+       len = min_t(sector_t, max_io_len(ci->sector, ti), ci->sector_count);
 
-               ci->sector += len;
-               ci->sector_count -= len;
-               ci->idx = idx;
+       __clone_and_map_data_bio(ci, ti, ci->sector, len);
 
-               return 0;
-       }
+       ci->sector += len;
+       ci->sector_count -= len;
 
-       /*
-        * Handle a bvec that must be split between two or more targets.
-        */
-       return __split_bvec_across_targets(ci, ti, max);
+       return 0;
 }
 
 /*
@@ -1510,8 +1378,7 @@ static void __split_and_process_bio(struct mapped_device *md,
        ci.io->bio = bio;
        ci.io->md = md;
        spin_lock_init(&ci.io->endio_lock);
-       ci.sector = bio->bi_sector;
-       ci.idx = bio->bi_idx;
+       ci.sector = bio->bi_iter.bi_sector;
 
        start_io_acct(ci.io);
 
index 3193aefe982b7b42badf4eba4adc36f89439d70c..e8b4574956c73e500cd634fa0acafad4fad0b93d 100644 (file)
@@ -74,8 +74,8 @@ static void faulty_fail(struct bio *bio, int error)
 {
        struct bio *b = bio->bi_private;
 
-       b->bi_size = bio->bi_size;
-       b->bi_sector = bio->bi_sector;
+       b->bi_iter.bi_size = bio->bi_iter.bi_size;
+       b->bi_iter.bi_sector = bio->bi_iter.bi_sector;
 
        bio_put(bio);
 
@@ -185,26 +185,31 @@ static void make_request(struct mddev *mddev, struct bio *bio)
                        return;
                }
 
-               if (check_sector(conf, bio->bi_sector, bio_end_sector(bio), WRITE))
+               if (check_sector(conf, bio->bi_iter.bi_sector,
+                                bio_end_sector(bio), WRITE))
                        failit = 1;
                if (check_mode(conf, WritePersistent)) {
-                       add_sector(conf, bio->bi_sector, WritePersistent);
+                       add_sector(conf, bio->bi_iter.bi_sector,
+                                  WritePersistent);
                        failit = 1;
                }
                if (check_mode(conf, WriteTransient))
                        failit = 1;
        } else {
                /* read request */
-               if (check_sector(conf, bio->bi_sector, bio_end_sector(bio), READ))
+               if (check_sector(conf, bio->bi_iter.bi_sector,
+                                bio_end_sector(bio), READ))
                        failit = 1;
                if (check_mode(conf, ReadTransient))
                        failit = 1;
                if (check_mode(conf, ReadPersistent)) {
-                       add_sector(conf, bio->bi_sector, ReadPersistent);
+                       add_sector(conf, bio->bi_iter.bi_sector,
+                                  ReadPersistent);
                        failit = 1;
                }
                if (check_mode(conf, ReadFixable)) {
-                       add_sector(conf, bio->bi_sector, ReadFixable);
+                       add_sector(conf, bio->bi_iter.bi_sector,
+                                  ReadFixable);
                        failit = 1;
                }
        }
index f03fabd2b37bacf34a231a0bb034a6d8f2826e68..56f534b4a2d27036b1f820f8bf4bfed56a9b2002 100644 (file)
@@ -288,65 +288,65 @@ static int linear_stop (struct mddev *mddev)
 
 static void linear_make_request(struct mddev *mddev, struct bio *bio)
 {
+       char b[BDEVNAME_SIZE];
        struct dev_info *tmp_dev;
-       sector_t start_sector;
+       struct bio *split;
+       sector_t start_sector, end_sector, data_offset;
 
        if (unlikely(bio->bi_rw & REQ_FLUSH)) {
                md_flush_request(mddev, bio);
                return;
        }
 
-       rcu_read_lock();
-       tmp_dev = which_dev(mddev, bio->bi_sector);
-       start_sector = tmp_dev->end_sector - tmp_dev->rdev->sectors;
-
-
-       if (unlikely(bio->bi_sector >= (tmp_dev->end_sector)
-                    || (bio->bi_sector < start_sector))) {
-               char b[BDEVNAME_SIZE];
-
-               printk(KERN_ERR
-                      "md/linear:%s: make_request: Sector %llu out of bounds on "
-                      "dev %s: %llu sectors, offset %llu\n",
-                      mdname(mddev),
-                      (unsigned long long)bio->bi_sector,
-                      bdevname(tmp_dev->rdev->bdev, b),
-                      (unsigned long long)tmp_dev->rdev->sectors,
-                      (unsigned long long)start_sector);
-               rcu_read_unlock();
-               bio_io_error(bio);
-               return;
-       }
-       if (unlikely(bio_end_sector(bio) > tmp_dev->end_sector)) {
-               /* This bio crosses a device boundary, so we have to
-                * split it.
-                */
-               struct bio_pair *bp;
-               sector_t end_sector = tmp_dev->end_sector;
+       do {
+               rcu_read_lock();
 
-               rcu_read_unlock();
-
-               bp = bio_split(bio, end_sector - bio->bi_sector);
+               tmp_dev = which_dev(mddev, bio->bi_iter.bi_sector);
+               start_sector = tmp_dev->end_sector - tmp_dev->rdev->sectors;
+               end_sector = tmp_dev->end_sector;
+               data_offset = tmp_dev->rdev->data_offset;
+               bio->bi_bdev = tmp_dev->rdev->bdev;
 
-               linear_make_request(mddev, &bp->bio1);
-               linear_make_request(mddev, &bp->bio2);
-               bio_pair_release(bp);
-               return;
-       }
-                   
-       bio->bi_bdev = tmp_dev->rdev->bdev;
-       bio->bi_sector = bio->bi_sector - start_sector
-               + tmp_dev->rdev->data_offset;
-       rcu_read_unlock();
+               rcu_read_unlock();
 
-       if (unlikely((bio->bi_rw & REQ_DISCARD) &&
-                    !blk_queue_discard(bdev_get_queue(bio->bi_bdev)))) {
-               /* Just ignore it */
-               bio_endio(bio, 0);
-               return;
-       }
+               if (unlikely(bio->bi_iter.bi_sector >= end_sector ||
+                            bio->bi_iter.bi_sector < start_sector))
+                       goto out_of_bounds;
+
+               if (unlikely(bio_end_sector(bio) > end_sector)) {
+                       /* This bio crosses a device boundary, so we have to
+                        * split it.
+                        */
+                       split = bio_split(bio, end_sector -
+                                         bio->bi_iter.bi_sector,
+                                         GFP_NOIO, fs_bio_set);
+                       bio_chain(split, bio);
+               } else {
+                       split = bio;
+               }
 
-       generic_make_request(bio);
+               split->bi_iter.bi_sector = split->bi_iter.bi_sector -
+                       start_sector + data_offset;
+
+               if (unlikely((split->bi_rw & REQ_DISCARD) &&
+                        !blk_queue_discard(bdev_get_queue(split->bi_bdev)))) {
+                       /* Just ignore it */
+                       bio_endio(split, 0);
+               } else
+                       generic_make_request(split);
+       } while (split != bio);
+       return;
+
+out_of_bounds:
+       printk(KERN_ERR
+              "md/linear:%s: make_request: Sector %llu out of bounds on "
+              "dev %s: %llu sectors, offset %llu\n",
+              mdname(mddev),
+              (unsigned long long)bio->bi_iter.bi_sector,
+              bdevname(tmp_dev->rdev->bdev, b),
+              (unsigned long long)tmp_dev->rdev->sectors,
+              (unsigned long long)start_sector);
+       bio_io_error(bio);
 }
 
 static void linear_status (struct seq_file *seq, struct mddev *mddev)
index e60cebf3f519841d81726f1aee6ef97df6e8da6b..16d84e091e2d199222f3c58203a07f3b696249c9 100644 (file)
@@ -393,7 +393,7 @@ static void md_submit_flush_data(struct work_struct *ws)
        struct mddev *mddev = container_of(ws, struct mddev, flush_work);
        struct bio *bio = mddev->flush_bio;
 
-       if (bio->bi_size == 0)
+       if (bio->bi_iter.bi_size == 0)
                /* an empty barrier - all done */
                bio_endio(bio, 0);
        else {
@@ -754,7 +754,7 @@ void md_super_write(struct mddev *mddev, struct md_rdev *rdev,
        struct bio *bio = bio_alloc_mddev(GFP_NOIO, 1, mddev);
 
        bio->bi_bdev = rdev->meta_bdev ? rdev->meta_bdev : rdev->bdev;
-       bio->bi_sector = sector;
+       bio->bi_iter.bi_sector = sector;
        bio_add_page(bio, page, size, 0);
        bio->bi_private = rdev;
        bio->bi_end_io = super_written;
@@ -776,36 +776,24 @@ void md_super_wait(struct mddev *mddev)
        finish_wait(&mddev->sb_wait, &wq);
 }
 
-static void bi_complete(struct bio *bio, int error)
-{
-       complete((struct completion*)bio->bi_private);
-}
-
 int sync_page_io(struct md_rdev *rdev, sector_t sector, int size,
                 struct page *page, int rw, bool metadata_op)
 {
        struct bio *bio = bio_alloc_mddev(GFP_NOIO, 1, rdev->mddev);
-       struct completion event;
        int ret;
 
-       rw |= REQ_SYNC;
-
        bio->bi_bdev = (metadata_op && rdev->meta_bdev) ?
                rdev->meta_bdev : rdev->bdev;
        if (metadata_op)
-               bio->bi_sector = sector + rdev->sb_start;
+               bio->bi_iter.bi_sector = sector + rdev->sb_start;
        else if (rdev->mddev->reshape_position != MaxSector &&
                 (rdev->mddev->reshape_backwards ==
                  (sector >= rdev->mddev->reshape_position)))
-               bio->bi_sector = sector + rdev->new_data_offset;
+               bio->bi_iter.bi_sector = sector + rdev->new_data_offset;
        else
-               bio->bi_sector = sector + rdev->data_offset;
+               bio->bi_iter.bi_sector = sector + rdev->data_offset;
        bio_add_page(bio, page, size, 0);
-       init_completion(&event);
-       bio->bi_private = &event;
-       bio->bi_end_io = bi_complete;
-       submit_bio(rw, bio);
-       wait_for_completion(&event);
+       submit_bio_wait(rw, bio);
 
        ret = test_bit(BIO_UPTODATE, &bio->bi_flags);
        bio_put(bio);
index 1642eae75a3335d1282a4bf53751802e1aeb52db..849ad39f547b9c1fbb8d993e118261a33b242134 100644 (file)
@@ -100,7 +100,7 @@ static void multipath_end_request(struct bio *bio, int error)
                md_error (mp_bh->mddev, rdev);
                printk(KERN_ERR "multipath: %s: rescheduling sector %llu\n", 
                       bdevname(rdev->bdev,b), 
-                      (unsigned long long)bio->bi_sector);
+                      (unsigned long long)bio->bi_iter.bi_sector);
                multipath_reschedule_retry(mp_bh);
        } else
                multipath_end_bh_io(mp_bh, error);
@@ -132,7 +132,7 @@ static void multipath_make_request(struct mddev *mddev, struct bio * bio)
        multipath = conf->multipaths + mp_bh->path;
 
        mp_bh->bio = *bio;
-       mp_bh->bio.bi_sector += multipath->rdev->data_offset;
+       mp_bh->bio.bi_iter.bi_sector += multipath->rdev->data_offset;
        mp_bh->bio.bi_bdev = multipath->rdev->bdev;
        mp_bh->bio.bi_rw |= REQ_FAILFAST_TRANSPORT;
        mp_bh->bio.bi_end_io = multipath_end_request;
@@ -355,21 +355,22 @@ static void multipathd(struct md_thread *thread)
                spin_unlock_irqrestore(&conf->device_lock, flags);
 
                bio = &mp_bh->bio;
-               bio->bi_sector = mp_bh->master_bio->bi_sector;
+               bio->bi_iter.bi_sector = mp_bh->master_bio->bi_iter.bi_sector;
                
                if ((mp_bh->path = multipath_map (conf))<0) {
                        printk(KERN_ALERT "multipath: %s: unrecoverable IO read"
                                " error for block %llu\n",
                                bdevname(bio->bi_bdev,b),
-                               (unsigned long long)bio->bi_sector);
+                               (unsigned long long)bio->bi_iter.bi_sector);
                        multipath_end_bh_io(mp_bh, -EIO);
                } else {
                        printk(KERN_ERR "multipath: %s: redirecting sector %llu"
                                " to another IO path\n",
                                bdevname(bio->bi_bdev,b),
-                               (unsigned long long)bio->bi_sector);
+                               (unsigned long long)bio->bi_iter.bi_sector);
                        *bio = *(mp_bh->master_bio);
-                       bio->bi_sector += conf->multipaths[mp_bh->path].rdev->data_offset;
+                       bio->bi_iter.bi_sector +=
+                               conf->multipaths[mp_bh->path].rdev->data_offset;
                        bio->bi_bdev = conf->multipaths[mp_bh->path].rdev->bdev;
                        bio->bi_rw |= REQ_FAILFAST_TRANSPORT;
                        bio->bi_end_io = multipath_end_request;
index a7e8bf2963886dfa349a03644cf33ff1ded748c5..064a3c271baa8843657dca3c374ed89061565ad4 100644 (file)
@@ -626,6 +626,12 @@ void dm_bm_set_read_only(struct dm_block_manager *bm)
 }
 EXPORT_SYMBOL_GPL(dm_bm_set_read_only);
 
+void dm_bm_set_read_write(struct dm_block_manager *bm)
+{
+       bm->read_only = false;
+}
+EXPORT_SYMBOL_GPL(dm_bm_set_read_write);
+
 u32 dm_bm_checksum(const void *data, size_t len, u32 init_xor)
 {
        return crc32c(~(u32) 0, data, len) ^ init_xor;
index 9a82083a66b6a86833bccc1d2b6d4d43c9de6500..13cd58e1fe69ffb4ed477b10ee6bbbe6d58d9926 100644 (file)
@@ -108,9 +108,9 @@ int dm_bm_unlock(struct dm_block *b);
 int dm_bm_flush_and_unlock(struct dm_block_manager *bm,
                           struct dm_block *superblock);
 
- /*
 * Request data be prefetched into the cache.
 */
+/*
* Request data is prefetched into the cache.
+ */
 void dm_bm_prefetch(struct dm_block_manager *bm, dm_block_t b);
 
 /*
@@ -125,6 +125,7 @@ void dm_bm_prefetch(struct dm_block_manager *bm, dm_block_t b);
  * be returned if you do.
  */
 void dm_bm_set_read_only(struct dm_block_manager *bm);
+void dm_bm_set_read_write(struct dm_block_manager *bm);
 
 u32 dm_bm_checksum(const void *data, size_t len, u32 init_xor);
 
index 1c959684caef7512fafd3c1a5505c29c798a9c11..58fc1eef7499e1923ef00095502c1e1b49f50ffb 100644 (file)
@@ -384,12 +384,16 @@ static int sm_metadata_new_block(struct dm_space_map *sm, dm_block_t *b)
        struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
 
        int r = sm_metadata_new_block_(sm, b);
-       if (r)
+       if (r) {
                DMERR("unable to allocate new metadata block");
+               return r;
+       }
 
        r = sm_metadata_get_nr_free(sm, &count);
-       if (r)
+       if (r) {
                DMERR("couldn't get free block count");
+               return r;
+       }
 
        check_threshold(&smm->threshold, count);
 
index c4d420b7d2f43d0804e1c1a94d88ca63484b5ec3..407a99e46f6993a770c21fdfff1972b7f64063b6 100644 (file)
@@ -501,10 +501,11 @@ static inline int is_io_in_chunk_boundary(struct mddev *mddev,
                        unsigned int chunk_sects, struct bio *bio)
 {
        if (likely(is_power_of_2(chunk_sects))) {
-               return chunk_sects >= ((bio->bi_sector & (chunk_sects-1))
+               return chunk_sects >=
+                       ((bio->bi_iter.bi_sector & (chunk_sects-1))
                                        + bio_sectors(bio));
        } else{
-               sector_t sector = bio->bi_sector;
+               sector_t sector = bio->bi_iter.bi_sector;
                return chunk_sects >= (sector_div(sector, chunk_sects)
                                                + bio_sectors(bio));
        }
@@ -512,64 +513,44 @@ static inline int is_io_in_chunk_boundary(struct mddev *mddev,
 
 static void raid0_make_request(struct mddev *mddev, struct bio *bio)
 {
-       unsigned int chunk_sects;
-       sector_t sector_offset;
        struct strip_zone *zone;
        struct md_rdev *tmp_dev;
+       struct bio *split;
 
        if (unlikely(bio->bi_rw & REQ_FLUSH)) {
                md_flush_request(mddev, bio);
                return;
        }
 
-       chunk_sects = mddev->chunk_sectors;
-       if (unlikely(!is_io_in_chunk_boundary(mddev, chunk_sects, bio))) {
-               sector_t sector = bio->bi_sector;
-               struct bio_pair *bp;
-               /* Sanity check -- queue functions should prevent this happening */
-               if (bio_segments(bio) > 1)
-                       goto bad_map;
-               /* This is a one page bio that upper layers
-                * refuse to split for us, so we need to split it.
-                */
-               if (likely(is_power_of_2(chunk_sects)))
-                       bp = bio_split(bio, chunk_sects - (sector &
-                                                          (chunk_sects-1)));
-               else
-                       bp = bio_split(bio, chunk_sects -
-                                      sector_div(sector, chunk_sects));
-               raid0_make_request(mddev, &bp->bio1);
-               raid0_make_request(mddev, &bp->bio2);
-               bio_pair_release(bp);
-               return;
-       }
+       do {
+               sector_t sector = bio->bi_iter.bi_sector;
+               unsigned chunk_sects = mddev->chunk_sectors;
 
-       sector_offset = bio->bi_sector;
-       zone = find_zone(mddev->private, &sector_offset);
-       tmp_dev = map_sector(mddev, zone, bio->bi_sector,
-                            &sector_offset);
-       bio->bi_bdev = tmp_dev->bdev;
-       bio->bi_sector = sector_offset + zone->dev_start +
-               tmp_dev->data_offset;
-
-       if (unlikely((bio->bi_rw & REQ_DISCARD) &&
-                    !blk_queue_discard(bdev_get_queue(bio->bi_bdev)))) {
-               /* Just ignore it */
-               bio_endio(bio, 0);
-               return;
-       }
+               unsigned sectors = chunk_sects -
+                       (likely(is_power_of_2(chunk_sects))
+                        ? (sector & (chunk_sects-1))
+                        : sector_div(sector, chunk_sects));
 
-       generic_make_request(bio);
-       return;
-
-bad_map:
-       printk("md/raid0:%s: make_request bug: can't convert block across chunks"
-              " or bigger than %dk %llu %d\n",
-              mdname(mddev), chunk_sects / 2,
-              (unsigned long long)bio->bi_sector, bio_sectors(bio) / 2);
+               if (sectors < bio_sectors(bio)) {
+                       split = bio_split(bio, sectors, GFP_NOIO, fs_bio_set);
+                       bio_chain(split, bio);
+               } else {
+                       split = bio;
+               }
 
-       bio_io_error(bio);
-       return;
+               zone = find_zone(mddev->private, &sector);
+               tmp_dev = map_sector(mddev, zone, sector, &sector);
+               split->bi_bdev = tmp_dev->bdev;
+               split->bi_iter.bi_sector = sector + zone->dev_start +
+                       tmp_dev->data_offset;
+
+               if (unlikely((split->bi_rw & REQ_DISCARD) &&
+                        !blk_queue_discard(bdev_get_queue(split->bi_bdev)))) {
+                       /* Just ignore it */
+                       bio_endio(split, 0);
+               } else
+                       generic_make_request(split);
+       } while (split != bio);
 }
 
 static void raid0_status(struct seq_file *seq, struct mddev *mddev)
index 1e5a540995e932852df5ff484a96bfcc8636a432..db3b9d7314f1835def74642faaff39af892d1d8c 100644 (file)
@@ -229,7 +229,7 @@ static void call_bio_endio(struct r1bio *r1_bio)
        int done;
        struct r1conf *conf = r1_bio->mddev->private;
        sector_t start_next_window = r1_bio->start_next_window;
-       sector_t bi_sector = bio->bi_sector;
+       sector_t bi_sector = bio->bi_iter.bi_sector;
 
        if (bio->bi_phys_segments) {
                unsigned long flags;
@@ -265,9 +265,8 @@ static void raid_end_bio_io(struct r1bio *r1_bio)
        if (!test_and_set_bit(R1BIO_Returned, &r1_bio->state)) {
                pr_debug("raid1: sync end %s on sectors %llu-%llu\n",
                         (bio_data_dir(bio) == WRITE) ? "write" : "read",
-                        (unsigned long long) bio->bi_sector,
-                        (unsigned long long) bio->bi_sector +
-                        bio_sectors(bio) - 1);
+                        (unsigned long long) bio->bi_iter.bi_sector,
+                        (unsigned long long) bio_end_sector(bio) - 1);
 
                call_bio_endio(r1_bio);
        }
@@ -466,9 +465,8 @@ static void raid1_end_write_request(struct bio *bio, int error)
                                struct bio *mbio = r1_bio->master_bio;
                                pr_debug("raid1: behind end write sectors"
                                         " %llu-%llu\n",
-                                        (unsigned long long) mbio->bi_sector,
-                                        (unsigned long long) mbio->bi_sector +
-                                        bio_sectors(mbio) - 1);
+                                        (unsigned long long) mbio->bi_iter.bi_sector,
+                                        (unsigned long long) bio_end_sector(mbio) - 1);
                                call_bio_endio(r1_bio);
                        }
                }
@@ -875,7 +873,7 @@ static bool need_to_wait_for_sync(struct r1conf *conf, struct bio *bio)
                else if ((conf->next_resync - RESYNC_WINDOW_SECTORS
                                >= bio_end_sector(bio)) ||
                         (conf->next_resync + NEXT_NORMALIO_DISTANCE
-                               <= bio->bi_sector))
+                               <= bio->bi_iter.bi_sector))
                        wait = false;
                else
                        wait = true;
@@ -913,19 +911,19 @@ static sector_t wait_barrier(struct r1conf *conf, struct bio *bio)
 
        if (bio && bio_data_dir(bio) == WRITE) {
                if (conf->next_resync + NEXT_NORMALIO_DISTANCE
-                   <= bio->bi_sector) {
+                   <= bio->bi_iter.bi_sector) {
                        if (conf->start_next_window == MaxSector)
                                conf->start_next_window =
                                        conf->next_resync +
                                        NEXT_NORMALIO_DISTANCE;
 
                        if ((conf->start_next_window + NEXT_NORMALIO_DISTANCE)
-                           <= bio->bi_sector)
+                           <= bio->bi_iter.bi_sector)
                                conf->next_window_requests++;
                        else
                                conf->current_window_requests++;
                }
-               if (bio->bi_sector >= conf->start_next_window)
+               if (bio->bi_iter.bi_sector >= conf->start_next_window)
                        sector = conf->start_next_window;
        }
 
@@ -1028,7 +1026,8 @@ do_sync_io:
                if (bvecs[i].bv_page)
                        put_page(bvecs[i].bv_page);
        kfree(bvecs);
-       pr_debug("%dB behind alloc failed, doing sync I/O\n", bio->bi_size);
+       pr_debug("%dB behind alloc failed, doing sync I/O\n",
+                bio->bi_iter.bi_size);
 }
 
 struct raid1_plug_cb {
@@ -1108,7 +1107,7 @@ static void make_request(struct mddev *mddev, struct bio * bio)
 
        if (bio_data_dir(bio) == WRITE &&
            bio_end_sector(bio) > mddev->suspend_lo &&
-           bio->bi_sector < mddev->suspend_hi) {
+           bio->bi_iter.bi_sector < mddev->suspend_hi) {
                /* As the suspend_* range is controlled by
                 * userspace, we want an interruptible
                 * wait.
@@ -1119,7 +1118,7 @@ static void make_request(struct mddev *mddev, struct bio * bio)
                        prepare_to_wait(&conf->wait_barrier,
                                        &w, TASK_INTERRUPTIBLE);
                        if (bio_end_sector(bio) <= mddev->suspend_lo ||
-                           bio->bi_sector >= mddev->suspend_hi)
+                           bio->bi_iter.bi_sector >= mddev->suspend_hi)
                                break;
                        schedule();
                }
@@ -1141,7 +1140,7 @@ static void make_request(struct mddev *mddev, struct bio * bio)
        r1_bio->sectors = bio_sectors(bio);
        r1_bio->state = 0;
        r1_bio->mddev = mddev;
-       r1_bio->sector = bio->bi_sector;
+       r1_bio->sector = bio->bi_iter.bi_sector;
 
        /* We might need to issue multiple reads to different
         * devices if there are bad blocks around, so we keep
@@ -1181,12 +1180,13 @@ read_again:
                r1_bio->read_disk = rdisk;
 
                read_bio = bio_clone_mddev(bio, GFP_NOIO, mddev);
-               bio_trim(read_bio, r1_bio->sector - bio->bi_sector,
+               bio_trim(read_bio, r1_bio->sector - bio->bi_iter.bi_sector,
                         max_sectors);
 
                r1_bio->bios[rdisk] = read_bio;
 
-               read_bio->bi_sector = r1_bio->sector + mirror->rdev->data_offset;
+               read_bio->bi_iter.bi_sector = r1_bio->sector +
+                       mirror->rdev->data_offset;
                read_bio->bi_bdev = mirror->rdev->bdev;
                read_bio->bi_end_io = raid1_end_read_request;
                read_bio->bi_rw = READ | do_sync;
@@ -1198,7 +1198,7 @@ read_again:
                         */
 
                        sectors_handled = (r1_bio->sector + max_sectors
-                                          - bio->bi_sector);
+                                          - bio->bi_iter.bi_sector);
                        r1_bio->sectors = max_sectors;
                        spin_lock_irq(&conf->device_lock);
                        if (bio->bi_phys_segments == 0)
@@ -1219,7 +1219,8 @@ read_again:
                        r1_bio->sectors = bio_sectors(bio) - sectors_handled;
                        r1_bio->state = 0;
                        r1_bio->mddev = mddev;
-                       r1_bio->sector = bio->bi_sector + sectors_handled;
+                       r1_bio->sector = bio->bi_iter.bi_sector +
+                               sectors_handled;
                        goto read_again;
                } else
                        generic_make_request(read_bio);
@@ -1322,7 +1323,7 @@ read_again:
                        if (r1_bio->bios[j])
                                rdev_dec_pending(conf->mirrors[j].rdev, mddev);
                r1_bio->state = 0;
-               allow_barrier(conf, start_next_window, bio->bi_sector);
+               allow_barrier(conf, start_next_window, bio->bi_iter.bi_sector);
                md_wait_for_blocked_rdev(blocked_rdev, mddev);
                start_next_window = wait_barrier(conf, bio);
                /*
@@ -1349,7 +1350,7 @@ read_again:
                        bio->bi_phys_segments++;
                spin_unlock_irq(&conf->device_lock);
        }
-       sectors_handled = r1_bio->sector + max_sectors - bio->bi_sector;
+       sectors_handled = r1_bio->sector + max_sectors - bio->bi_iter.bi_sector;
 
        atomic_set(&r1_bio->remaining, 1);
        atomic_set(&r1_bio->behind_remaining, 0);
@@ -1361,7 +1362,7 @@ read_again:
                        continue;
 
                mbio = bio_clone_mddev(bio, GFP_NOIO, mddev);
-               bio_trim(mbio, r1_bio->sector - bio->bi_sector, max_sectors);
+               bio_trim(mbio, r1_bio->sector - bio->bi_iter.bi_sector, max_sectors);
 
                if (first_clone) {
                        /* do behind I/O ?
@@ -1395,7 +1396,7 @@ read_again:
 
                r1_bio->bios[i] = mbio;
 
-               mbio->bi_sector = (r1_bio->sector +
+               mbio->bi_iter.bi_sector = (r1_bio->sector +
                                   conf->mirrors[i].rdev->data_offset);
                mbio->bi_bdev = conf->mirrors[i].rdev->bdev;
                mbio->bi_end_io = raid1_end_write_request;
@@ -1435,7 +1436,7 @@ read_again:
                r1_bio->sectors = bio_sectors(bio) - sectors_handled;
                r1_bio->state = 0;
                r1_bio->mddev = mddev;
-               r1_bio->sector = bio->bi_sector + sectors_handled;
+               r1_bio->sector = bio->bi_iter.bi_sector + sectors_handled;
                goto retry_write;
        }
 
@@ -1959,14 +1960,14 @@ static int process_checks(struct r1bio *r1_bio)
                /* fixup the bio for reuse */
                bio_reset(b);
                b->bi_vcnt = vcnt;
-               b->bi_size = r1_bio->sectors << 9;
-               b->bi_sector = r1_bio->sector +
+               b->bi_iter.bi_size = r1_bio->sectors << 9;
+               b->bi_iter.bi_sector = r1_bio->sector +
                        conf->mirrors[i].rdev->data_offset;
                b->bi_bdev = conf->mirrors[i].rdev->bdev;
                b->bi_end_io = end_sync_read;
                b->bi_private = r1_bio;
 
-               size = b->bi_size;
+               size = b->bi_iter.bi_size;
                for (j = 0; j < vcnt ; j++) {
                        struct bio_vec *bi;
                        bi = &b->bi_io_vec[j];
@@ -2221,11 +2222,11 @@ static int narrow_write_error(struct r1bio *r1_bio, int i)
                }
 
                wbio->bi_rw = WRITE;
-               wbio->bi_sector = r1_bio->sector;
-               wbio->bi_size = r1_bio->sectors << 9;
+               wbio->bi_iter.bi_sector = r1_bio->sector;
+               wbio->bi_iter.bi_size = r1_bio->sectors << 9;
 
                bio_trim(wbio, sector - r1_bio->sector, sectors);
-               wbio->bi_sector += rdev->data_offset;
+               wbio->bi_iter.bi_sector += rdev->data_offset;
                wbio->bi_bdev = rdev->bdev;
                if (submit_bio_wait(WRITE, wbio) == 0)
                        /* failure! */
@@ -2339,7 +2340,8 @@ read_more:
                }
                r1_bio->read_disk = disk;
                bio = bio_clone_mddev(r1_bio->master_bio, GFP_NOIO, mddev);
-               bio_trim(bio, r1_bio->sector - bio->bi_sector, max_sectors);
+               bio_trim(bio, r1_bio->sector - bio->bi_iter.bi_sector,
+                        max_sectors);
                r1_bio->bios[r1_bio->read_disk] = bio;
                rdev = conf->mirrors[disk].rdev;
                printk_ratelimited(KERN_ERR
@@ -2348,7 +2350,7 @@ read_more:
                                   mdname(mddev),
                                   (unsigned long long)r1_bio->sector,
                                   bdevname(rdev->bdev, b));
-               bio->bi_sector = r1_bio->sector + rdev->data_offset;
+               bio->bi_iter.bi_sector = r1_bio->sector + rdev->data_offset;
                bio->bi_bdev = rdev->bdev;
                bio->bi_end_io = raid1_end_read_request;
                bio->bi_rw = READ | do_sync;
@@ -2357,7 +2359,7 @@ read_more:
                        /* Drat - have to split this up more */
                        struct bio *mbio = r1_bio->master_bio;
                        int sectors_handled = (r1_bio->sector + max_sectors
-                                              - mbio->bi_sector);
+                                              - mbio->bi_iter.bi_sector);
                        r1_bio->sectors = max_sectors;
                        spin_lock_irq(&conf->device_lock);
                        if (mbio->bi_phys_segments == 0)
@@ -2375,7 +2377,8 @@ read_more:
                        r1_bio->state = 0;
                        set_bit(R1BIO_ReadError, &r1_bio->state);
                        r1_bio->mddev = mddev;
-                       r1_bio->sector = mbio->bi_sector + sectors_handled;
+                       r1_bio->sector = mbio->bi_iter.bi_sector +
+                               sectors_handled;
 
                        goto read_more;
                } else
@@ -2599,7 +2602,7 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipp
                }
                if (bio->bi_end_io) {
                        atomic_inc(&rdev->nr_pending);
-                       bio->bi_sector = sector_nr + rdev->data_offset;
+                       bio->bi_iter.bi_sector = sector_nr + rdev->data_offset;
                        bio->bi_bdev = rdev->bdev;
                        bio->bi_private = r1_bio;
                }
@@ -2699,7 +2702,7 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipp
                                                        continue;
                                                /* remove last page from this bio */
                                                bio->bi_vcnt--;
-                                               bio->bi_size -= len;
+                                               bio->bi_iter.bi_size -= len;
                                                bio->bi_flags &= ~(1<< BIO_SEG_VALID);
                                        }
                                        goto bio_full;
index c504e8389e69e3ab9ad717b9f83d0c19c2008d68..6d43d88657aa81982e1f31540878e822ffd44a39 100644 (file)
@@ -1152,14 +1152,12 @@ static void raid10_unplug(struct blk_plug_cb *cb, bool from_schedule)
        kfree(plug);
 }
 
-static void make_request(struct mddev *mddev, struct bio * bio)
+static void __make_request(struct mddev *mddev, struct bio *bio)
 {
        struct r10conf *conf = mddev->private;
        struct r10bio *r10_bio;
        struct bio *read_bio;
        int i;
-       sector_t chunk_mask = (conf->geo.chunk_mask & conf->prev.chunk_mask);
-       int chunk_sects = chunk_mask + 1;
        const int rw = bio_data_dir(bio);
        const unsigned long do_sync = (bio->bi_rw & REQ_SYNC);
        const unsigned long do_fua = (bio->bi_rw & REQ_FUA);
@@ -1174,88 +1172,27 @@ static void make_request(struct mddev *mddev, struct bio * bio)
        int max_sectors;
        int sectors;
 
-       if (unlikely(bio->bi_rw & REQ_FLUSH)) {
-               md_flush_request(mddev, bio);
-               return;
-       }
-
-       /* If this request crosses a chunk boundary, we need to
-        * split it.  This will only happen for 1 PAGE (or less) requests.
-        */
-       if (unlikely((bio->bi_sector & chunk_mask) + bio_sectors(bio)
-                    > chunk_sects
-                    && (conf->geo.near_copies < conf->geo.raid_disks
-                        || conf->prev.near_copies < conf->prev.raid_disks))) {
-               struct bio_pair *bp;
-               /* Sanity check -- queue functions should prevent this happening */
-               if (bio_segments(bio) > 1)
-                       goto bad_map;
-               /* This is a one page bio that upper layers
-                * refuse to split for us, so we need to split it.
-                */
-               bp = bio_split(bio,
-                              chunk_sects - (bio->bi_sector & (chunk_sects - 1)) );
-
-               /* Each of these 'make_request' calls will call 'wait_barrier'.
-                * If the first succeeds but the second blocks due to the resync
-                * thread raising the barrier, we will deadlock because the
-                * IO to the underlying device will be queued in generic_make_request
-                * and will never complete, so will never reduce nr_pending.
-                * So increment nr_waiting here so no new raise_barriers will
-                * succeed, and so the second wait_barrier cannot block.
-                */
-               spin_lock_irq(&conf->resync_lock);
-               conf->nr_waiting++;
-               spin_unlock_irq(&conf->resync_lock);
-
-               make_request(mddev, &bp->bio1);
-               make_request(mddev, &bp->bio2);
-
-               spin_lock_irq(&conf->resync_lock);
-               conf->nr_waiting--;
-               wake_up(&conf->wait_barrier);
-               spin_unlock_irq(&conf->resync_lock);
-
-               bio_pair_release(bp);
-               return;
-       bad_map:
-               printk("md/raid10:%s: make_request bug: can't convert block across chunks"
-                      " or bigger than %dk %llu %d\n", mdname(mddev), chunk_sects/2,
-                      (unsigned long long)bio->bi_sector, bio_sectors(bio) / 2);
-
-               bio_io_error(bio);
-               return;
-       }
-
-       md_write_start(mddev, bio);
-
-       /*
-        * Register the new request and wait if the reconstruction
-        * thread has put up a bar for new requests.
-        * Continue immediately if no resync is active currently.
-        */
-       wait_barrier(conf);
-
        sectors = bio_sectors(bio);
        while (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
-           bio->bi_sector < conf->reshape_progress &&
-           bio->bi_sector + sectors > conf->reshape_progress) {
+           bio->bi_iter.bi_sector < conf->reshape_progress &&
+           bio->bi_iter.bi_sector + sectors > conf->reshape_progress) {
                /* IO spans the reshape position.  Need to wait for
                 * reshape to pass
                 */
                allow_barrier(conf);
                wait_event(conf->wait_barrier,
-                          conf->reshape_progress <= bio->bi_sector ||
-                          conf->reshape_progress >= bio->bi_sector + sectors);
+                          conf->reshape_progress <= bio->bi_iter.bi_sector ||
+                          conf->reshape_progress >= bio->bi_iter.bi_sector +
+                          sectors);
                wait_barrier(conf);
        }
        if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
            bio_data_dir(bio) == WRITE &&
            (mddev->reshape_backwards
-            ? (bio->bi_sector < conf->reshape_safe &&
-               bio->bi_sector + sectors > conf->reshape_progress)
-            : (bio->bi_sector + sectors > conf->reshape_safe &&
-               bio->bi_sector < conf->reshape_progress))) {
+            ? (bio->bi_iter.bi_sector < conf->reshape_safe &&
+               bio->bi_iter.bi_sector + sectors > conf->reshape_progress)
+            : (bio->bi_iter.bi_sector + sectors > conf->reshape_safe &&
+               bio->bi_iter.bi_sector < conf->reshape_progress))) {
                /* Need to update reshape_position in metadata */
                mddev->reshape_position = conf->reshape_progress;
                set_bit(MD_CHANGE_DEVS, &mddev->flags);
@@ -1273,7 +1210,7 @@ static void make_request(struct mddev *mddev, struct bio * bio)
        r10_bio->sectors = sectors;
 
        r10_bio->mddev = mddev;
-       r10_bio->sector = bio->bi_sector;
+       r10_bio->sector = bio->bi_iter.bi_sector;
        r10_bio->state = 0;
 
        /* We might need to issue multiple reads to different
@@ -1302,13 +1239,13 @@ read_again:
                slot = r10_bio->read_slot;
 
                read_bio = bio_clone_mddev(bio, GFP_NOIO, mddev);
-               bio_trim(read_bio, r10_bio->sector - bio->bi_sector,
+               bio_trim(read_bio, r10_bio->sector - bio->bi_iter.bi_sector,
                         max_sectors);
 
                r10_bio->devs[slot].bio = read_bio;
                r10_bio->devs[slot].rdev = rdev;
 
-               read_bio->bi_sector = r10_bio->devs[slot].addr +
+               read_bio->bi_iter.bi_sector = r10_bio->devs[slot].addr +
                        choose_data_offset(r10_bio, rdev);
                read_bio->bi_bdev = rdev->bdev;
                read_bio->bi_end_io = raid10_end_read_request;
@@ -1320,7 +1257,7 @@ read_again:
                         * need another r10_bio.
                         */
                        sectors_handled = (r10_bio->sectors + max_sectors
-                                          - bio->bi_sector);
+                                          - bio->bi_iter.bi_sector);
                        r10_bio->sectors = max_sectors;
                        spin_lock_irq(&conf->device_lock);
                        if (bio->bi_phys_segments == 0)
@@ -1341,7 +1278,8 @@ read_again:
                        r10_bio->sectors = bio_sectors(bio) - sectors_handled;
                        r10_bio->state = 0;
                        r10_bio->mddev = mddev;
-                       r10_bio->sector = bio->bi_sector + sectors_handled;
+                       r10_bio->sector = bio->bi_iter.bi_sector +
+                               sectors_handled;
                        goto read_again;
                } else
                        generic_make_request(read_bio);
@@ -1499,7 +1437,8 @@ retry_write:
                        bio->bi_phys_segments++;
                spin_unlock_irq(&conf->device_lock);
        }
-       sectors_handled = r10_bio->sector + max_sectors - bio->bi_sector;
+       sectors_handled = r10_bio->sector + max_sectors -
+               bio->bi_iter.bi_sector;
 
        atomic_set(&r10_bio->remaining, 1);
        bitmap_startwrite(mddev->bitmap, r10_bio->sector, r10_bio->sectors, 0);
@@ -1510,11 +1449,11 @@ retry_write:
                if (r10_bio->devs[i].bio) {
                        struct md_rdev *rdev = conf->mirrors[d].rdev;
                        mbio = bio_clone_mddev(bio, GFP_NOIO, mddev);
-                       bio_trim(mbio, r10_bio->sector - bio->bi_sector,
+                       bio_trim(mbio, r10_bio->sector - bio->bi_iter.bi_sector,
                                 max_sectors);
                        r10_bio->devs[i].bio = mbio;
 
-                       mbio->bi_sector = (r10_bio->devs[i].addr+
+                       mbio->bi_iter.bi_sector = (r10_bio->devs[i].addr+
                                           choose_data_offset(r10_bio,
                                                              rdev));
                        mbio->bi_bdev = rdev->bdev;
@@ -1553,11 +1492,11 @@ retry_write:
                                rdev = conf->mirrors[d].rdev;
                        }
                        mbio = bio_clone_mddev(bio, GFP_NOIO, mddev);
-                       bio_trim(mbio, r10_bio->sector - bio->bi_sector,
+                       bio_trim(mbio, r10_bio->sector - bio->bi_iter.bi_sector,
                                 max_sectors);
                        r10_bio->devs[i].repl_bio = mbio;
 
-                       mbio->bi_sector = (r10_bio->devs[i].addr +
+                       mbio->bi_iter.bi_sector = (r10_bio->devs[i].addr +
                                           choose_data_offset(
                                                   r10_bio, rdev));
                        mbio->bi_bdev = rdev->bdev;
@@ -1591,11 +1530,57 @@ retry_write:
                r10_bio->sectors = bio_sectors(bio) - sectors_handled;
 
                r10_bio->mddev = mddev;
-               r10_bio->sector = bio->bi_sector + sectors_handled;
+               r10_bio->sector = bio->bi_iter.bi_sector + sectors_handled;
                r10_bio->state = 0;
                goto retry_write;
        }
        one_write_done(r10_bio);
+}
+
+static void make_request(struct mddev *mddev, struct bio *bio)
+{
+       struct r10conf *conf = mddev->private;
+       sector_t chunk_mask = (conf->geo.chunk_mask & conf->prev.chunk_mask);
+       int chunk_sects = chunk_mask + 1;
+
+       struct bio *split;
+
+       if (unlikely(bio->bi_rw & REQ_FLUSH)) {
+               md_flush_request(mddev, bio);
+               return;
+       }
+
+       md_write_start(mddev, bio);
+
+       /*
+        * Register the new request and wait if the reconstruction
+        * thread has put up a bar for new requests.
+        * Continue immediately if no resync is active currently.
+        */
+       wait_barrier(conf);
+
+       do {
+
+               /*
+                * If this request crosses a chunk boundary, we need to split
+                * it.
+                */
+               if (unlikely((bio->bi_iter.bi_sector & chunk_mask) +
+                            bio_sectors(bio) > chunk_sects
+                            && (conf->geo.near_copies < conf->geo.raid_disks
+                                || conf->prev.near_copies <
+                                conf->prev.raid_disks))) {
+                       split = bio_split(bio, chunk_sects -
+                                         (bio->bi_iter.bi_sector &
+                                          (chunk_sects - 1)),
+                                         GFP_NOIO, fs_bio_set);
+                       bio_chain(split, bio);
+               } else {
+                       split = bio;
+               }
+
+               __make_request(mddev, split);
+       } while (split != bio);
 
        /* In case raid10d snuck in to freeze_array */
        wake_up(&conf->wait_barrier);
@@ -2124,10 +2109,10 @@ static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio)
                bio_reset(tbio);
 
                tbio->bi_vcnt = vcnt;
-               tbio->bi_size = r10_bio->sectors << 9;
+               tbio->bi_iter.bi_size = r10_bio->sectors << 9;
                tbio->bi_rw = WRITE;
                tbio->bi_private = r10_bio;
-               tbio->bi_sector = r10_bio->devs[i].addr;
+               tbio->bi_iter.bi_sector = r10_bio->devs[i].addr;
 
                for (j=0; j < vcnt ; j++) {
                        tbio->bi_io_vec[j].bv_offset = 0;
@@ -2144,7 +2129,7 @@ static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio)
                atomic_inc(&r10_bio->remaining);
                md_sync_acct(conf->mirrors[d].rdev->bdev, bio_sectors(tbio));
 
-               tbio->bi_sector += conf->mirrors[d].rdev->data_offset;
+               tbio->bi_iter.bi_sector += conf->mirrors[d].rdev->data_offset;
                tbio->bi_bdev = conf->mirrors[d].rdev->bdev;
                generic_make_request(tbio);
        }
@@ -2614,8 +2599,8 @@ static int narrow_write_error(struct r10bio *r10_bio, int i)
                        sectors = sect_to_write;
                /* Write at 'sector' for 'sectors' */
                wbio = bio_clone_mddev(bio, GFP_NOIO, mddev);
-               bio_trim(wbio, sector - bio->bi_sector, sectors);
-               wbio->bi_sector = (r10_bio->devs[i].addr+
+               bio_trim(wbio, sector - bio->bi_iter.bi_sector, sectors);
+               wbio->bi_iter.bi_sector = (r10_bio->devs[i].addr+
                                   choose_data_offset(r10_bio, rdev) +
                                   (sector - r10_bio->sector));
                wbio->bi_bdev = rdev->bdev;
@@ -2687,10 +2672,10 @@ read_more:
                (unsigned long long)r10_bio->sector);
        bio = bio_clone_mddev(r10_bio->master_bio,
                              GFP_NOIO, mddev);
-       bio_trim(bio, r10_bio->sector - bio->bi_sector, max_sectors);
+       bio_trim(bio, r10_bio->sector - bio->bi_iter.bi_sector, max_sectors);
        r10_bio->devs[slot].bio = bio;
        r10_bio->devs[slot].rdev = rdev;
-       bio->bi_sector = r10_bio->devs[slot].addr
+       bio->bi_iter.bi_sector = r10_bio->devs[slot].addr
                + choose_data_offset(r10_bio, rdev);
        bio->bi_bdev = rdev->bdev;
        bio->bi_rw = READ | do_sync;
@@ -2701,7 +2686,7 @@ read_more:
                struct bio *mbio = r10_bio->master_bio;
                int sectors_handled =
                        r10_bio->sector + max_sectors
-                       - mbio->bi_sector;
+                       - mbio->bi_iter.bi_sector;
                r10_bio->sectors = max_sectors;
                spin_lock_irq(&conf->device_lock);
                if (mbio->bi_phys_segments == 0)
@@ -2719,7 +2704,7 @@ read_more:
                set_bit(R10BIO_ReadError,
                        &r10_bio->state);
                r10_bio->mddev = mddev;
-               r10_bio->sector = mbio->bi_sector
+               r10_bio->sector = mbio->bi_iter.bi_sector
                        + sectors_handled;
 
                goto read_more;
@@ -3157,7 +3142,8 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
                                bio->bi_end_io = end_sync_read;
                                bio->bi_rw = READ;
                                from_addr = r10_bio->devs[j].addr;
-                               bio->bi_sector = from_addr + rdev->data_offset;
+                               bio->bi_iter.bi_sector = from_addr +
+                                       rdev->data_offset;
                                bio->bi_bdev = rdev->bdev;
                                atomic_inc(&rdev->nr_pending);
                                /* and we write to 'i' (if not in_sync) */
@@ -3181,7 +3167,7 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
                                        bio->bi_private = r10_bio;
                                        bio->bi_end_io = end_sync_write;
                                        bio->bi_rw = WRITE;
-                                       bio->bi_sector = to_addr
+                                       bio->bi_iter.bi_sector = to_addr
                                                + rdev->data_offset;
                                        bio->bi_bdev = rdev->bdev;
                                        atomic_inc(&r10_bio->remaining);
@@ -3210,7 +3196,8 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
                                bio->bi_private = r10_bio;
                                bio->bi_end_io = end_sync_write;
                                bio->bi_rw = WRITE;
-                               bio->bi_sector = to_addr + rdev->data_offset;
+                               bio->bi_iter.bi_sector = to_addr +
+                                       rdev->data_offset;
                                bio->bi_bdev = rdev->bdev;
                                atomic_inc(&r10_bio->remaining);
                                break;
@@ -3328,7 +3315,7 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
                        bio->bi_private = r10_bio;
                        bio->bi_end_io = end_sync_read;
                        bio->bi_rw = READ;
-                       bio->bi_sector = sector +
+                       bio->bi_iter.bi_sector = sector +
                                conf->mirrors[d].rdev->data_offset;
                        bio->bi_bdev = conf->mirrors[d].rdev->bdev;
                        count++;
@@ -3350,7 +3337,7 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
                        bio->bi_private = r10_bio;
                        bio->bi_end_io = end_sync_write;
                        bio->bi_rw = WRITE;
-                       bio->bi_sector = sector +
+                       bio->bi_iter.bi_sector = sector +
                                conf->mirrors[d].replacement->data_offset;
                        bio->bi_bdev = conf->mirrors[d].replacement->bdev;
                        count++;
@@ -3397,7 +3384,7 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
                             bio2 = bio2->bi_next) {
                                /* remove last page from this bio */
                                bio2->bi_vcnt--;
-                               bio2->bi_size -= len;
+                               bio2->bi_iter.bi_size -= len;
                                bio2->bi_flags &= ~(1<< BIO_SEG_VALID);
                        }
                        goto bio_full;
@@ -4417,7 +4404,7 @@ read_more:
        read_bio = bio_alloc_mddev(GFP_KERNEL, RESYNC_PAGES, mddev);
 
        read_bio->bi_bdev = rdev->bdev;
-       read_bio->bi_sector = (r10_bio->devs[r10_bio->read_slot].addr
+       read_bio->bi_iter.bi_sector = (r10_bio->devs[r10_bio->read_slot].addr
                               + rdev->data_offset);
        read_bio->bi_private = r10_bio;
        read_bio->bi_end_io = end_sync_read;
@@ -4425,7 +4412,7 @@ read_more:
        read_bio->bi_flags &= ~(BIO_POOL_MASK - 1);
        read_bio->bi_flags |= 1 << BIO_UPTODATE;
        read_bio->bi_vcnt = 0;
-       read_bio->bi_size = 0;
+       read_bio->bi_iter.bi_size = 0;
        r10_bio->master_bio = read_bio;
        r10_bio->read_slot = r10_bio->devs[r10_bio->read_slot].devnum;
 
@@ -4451,7 +4438,8 @@ read_more:
 
                bio_reset(b);
                b->bi_bdev = rdev2->bdev;
-               b->bi_sector = r10_bio->devs[s/2].addr + rdev2->new_data_offset;
+               b->bi_iter.bi_sector = r10_bio->devs[s/2].addr +
+                       rdev2->new_data_offset;
                b->bi_private = r10_bio;
                b->bi_end_io = end_reshape_write;
                b->bi_rw = WRITE;
@@ -4478,7 +4466,7 @@ read_more:
                             bio2 = bio2->bi_next) {
                                /* Remove last page from this bio */
                                bio2->bi_vcnt--;
-                               bio2->bi_size -= len;
+                               bio2->bi_iter.bi_size -= len;
                                bio2->bi_flags &= ~(1<<BIO_SEG_VALID);
                        }
                        goto bio_full;
index cc055da02e2a300706548041dc4d9cf63957978c..eea63372e4d30533b2255159c8b428b2ad90acb3 100644 (file)
@@ -133,7 +133,7 @@ static inline void unlock_all_device_hash_locks_irq(struct r5conf *conf)
 static inline struct bio *r5_next_bio(struct bio *bio, sector_t sector)
 {
        int sectors = bio_sectors(bio);
-       if (bio->bi_sector + sectors < sector + STRIPE_SECTORS)
+       if (bio->bi_iter.bi_sector + sectors < sector + STRIPE_SECTORS)
                return bio->bi_next;
        else
                return NULL;
@@ -225,7 +225,7 @@ static void return_io(struct bio *return_bi)
 
                return_bi = bi->bi_next;
                bi->bi_next = NULL;
-               bi->bi_size = 0;
+               bi->bi_iter.bi_size = 0;
                trace_block_bio_complete(bdev_get_queue(bi->bi_bdev),
                                         bi, 0);
                bio_endio(bi, 0);
@@ -851,10 +851,10 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
                                bi->bi_rw, i);
                        atomic_inc(&sh->count);
                        if (use_new_offset(conf, sh))
-                               bi->bi_sector = (sh->sector
+                               bi->bi_iter.bi_sector = (sh->sector
                                                 + rdev->new_data_offset);
                        else
-                               bi->bi_sector = (sh->sector
+                               bi->bi_iter.bi_sector = (sh->sector
                                                 + rdev->data_offset);
                        if (test_bit(R5_ReadNoMerge, &sh->dev[i].flags))
                                bi->bi_rw |= REQ_NOMERGE;
@@ -862,7 +862,7 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
                        bi->bi_vcnt = 1;
                        bi->bi_io_vec[0].bv_len = STRIPE_SIZE;
                        bi->bi_io_vec[0].bv_offset = 0;
-                       bi->bi_size = STRIPE_SIZE;
+                       bi->bi_iter.bi_size = STRIPE_SIZE;
                        /*
                         * If this is discard request, set bi_vcnt 0. We don't
                         * want to confuse SCSI because SCSI will replace payload
@@ -898,15 +898,15 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
                                rbi->bi_rw, i);
                        atomic_inc(&sh->count);
                        if (use_new_offset(conf, sh))
-                               rbi->bi_sector = (sh->sector
+                               rbi->bi_iter.bi_sector = (sh->sector
                                                  + rrdev->new_data_offset);
                        else
-                               rbi->bi_sector = (sh->sector
+                               rbi->bi_iter.bi_sector = (sh->sector
                                                  + rrdev->data_offset);
                        rbi->bi_vcnt = 1;
                        rbi->bi_io_vec[0].bv_len = STRIPE_SIZE;
                        rbi->bi_io_vec[0].bv_offset = 0;
-                       rbi->bi_size = STRIPE_SIZE;
+                       rbi->bi_iter.bi_size = STRIPE_SIZE;
                        /*
                         * If this is discard request, set bi_vcnt 0. We don't
                         * want to confuse SCSI because SCSI will replace payload
@@ -934,24 +934,24 @@ static struct dma_async_tx_descriptor *
 async_copy_data(int frombio, struct bio *bio, struct page *page,
        sector_t sector, struct dma_async_tx_descriptor *tx)
 {
-       struct bio_vec *bvl;
+       struct bio_vec bvl;
+       struct bvec_iter iter;
        struct page *bio_page;
-       int i;
        int page_offset;
        struct async_submit_ctl submit;
        enum async_tx_flags flags = 0;
 
-       if (bio->bi_sector >= sector)
-               page_offset = (signed)(bio->bi_sector - sector) * 512;
+       if (bio->bi_iter.bi_sector >= sector)
+               page_offset = (signed)(bio->bi_iter.bi_sector - sector) * 512;
        else
-               page_offset = (signed)(sector - bio->bi_sector) * -512;
+               page_offset = (signed)(sector - bio->bi_iter.bi_sector) * -512;
 
        if (frombio)
                flags |= ASYNC_TX_FENCE;
        init_async_submit(&submit, flags, tx, NULL, NULL, NULL);
 
-       bio_for_each_segment(bvl, bio, i) {
-               int len = bvl->bv_len;
+       bio_for_each_segment(bvl, bio, iter) {
+               int len = bvl.bv_len;
                int clen;
                int b_offset = 0;
 
@@ -967,8 +967,8 @@ async_copy_data(int frombio, struct bio *bio, struct page *page,
                        clen = len;
 
                if (clen > 0) {
-                       b_offset += bvl->bv_offset;
-                       bio_page = bvl->bv_page;
+                       b_offset += bvl.bv_offset;
+                       bio_page = bvl.bv_page;
                        if (frombio)
                                tx = async_memcpy(page, bio_page, page_offset,
                                                  b_offset, clen, &submit);
@@ -1011,7 +1011,7 @@ static void ops_complete_biofill(void *stripe_head_ref)
                        BUG_ON(!dev->read);
                        rbi = dev->read;
                        dev->read = NULL;
-                       while (rbi && rbi->bi_sector <
+                       while (rbi && rbi->bi_iter.bi_sector <
                                dev->sector + STRIPE_SECTORS) {
                                rbi2 = r5_next_bio(rbi, dev->sector);
                                if (!raid5_dec_bi_active_stripes(rbi)) {
@@ -1047,7 +1047,7 @@ static void ops_run_biofill(struct stripe_head *sh)
                        dev->read = rbi = dev->toread;
                        dev->toread = NULL;
                        spin_unlock_irq(&sh->stripe_lock);
-                       while (rbi && rbi->bi_sector <
+                       while (rbi && rbi->bi_iter.bi_sector <
                                dev->sector + STRIPE_SECTORS) {
                                tx = async_copy_data(0, rbi, dev->page,
                                        dev->sector, tx);
@@ -1389,7 +1389,7 @@ ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
                        wbi = dev->written = chosen;
                        spin_unlock_irq(&sh->stripe_lock);
 
-                       while (wbi && wbi->bi_sector <
+                       while (wbi && wbi->bi_iter.bi_sector <
                                dev->sector + STRIPE_SECTORS) {
                                if (wbi->bi_rw & REQ_FUA)
                                        set_bit(R5_WantFUA, &dev->flags);
@@ -2613,7 +2613,7 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
        int firstwrite=0;
 
        pr_debug("adding bi b#%llu to stripe s#%llu\n",
-               (unsigned long long)bi->bi_sector,
+               (unsigned long long)bi->bi_iter.bi_sector,
                (unsigned long long)sh->sector);
 
        /*
@@ -2631,12 +2631,12 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
                        firstwrite = 1;
        } else
                bip = &sh->dev[dd_idx].toread;
-       while (*bip && (*bip)->bi_sector < bi->bi_sector) {
-               if (bio_end_sector(*bip) > bi->bi_sector)
+       while (*bip && (*bip)->bi_iter.bi_sector < bi->bi_iter.bi_sector) {
+               if (bio_end_sector(*bip) > bi->bi_iter.bi_sector)
                        goto overlap;
                bip = & (*bip)->bi_next;
        }
-       if (*bip && (*bip)->bi_sector < bio_end_sector(bi))
+       if (*bip && (*bip)->bi_iter.bi_sector < bio_end_sector(bi))
                goto overlap;
 
        BUG_ON(*bip && bi->bi_next && (*bip) != bi->bi_next);
@@ -2650,7 +2650,7 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
                sector_t sector = sh->dev[dd_idx].sector;
                for (bi=sh->dev[dd_idx].towrite;
                     sector < sh->dev[dd_idx].sector + STRIPE_SECTORS &&
-                            bi && bi->bi_sector <= sector;
+                            bi && bi->bi_iter.bi_sector <= sector;
                     bi = r5_next_bio(bi, sh->dev[dd_idx].sector)) {
                        if (bio_end_sector(bi) >= sector)
                                sector = bio_end_sector(bi);
@@ -2660,7 +2660,7 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
        }
 
        pr_debug("added bi b#%llu to stripe s#%llu, disk %d.\n",
-               (unsigned long long)(*bip)->bi_sector,
+               (unsigned long long)(*bip)->bi_iter.bi_sector,
                (unsigned long long)sh->sector, dd_idx);
        spin_unlock_irq(&sh->stripe_lock);
 
@@ -2735,7 +2735,7 @@ handle_failed_stripe(struct r5conf *conf, struct stripe_head *sh,
                if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
                        wake_up(&conf->wait_for_overlap);
 
-               while (bi && bi->bi_sector <
+               while (bi && bi->bi_iter.bi_sector <
                        sh->dev[i].sector + STRIPE_SECTORS) {
                        struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);
                        clear_bit(BIO_UPTODATE, &bi->bi_flags);
@@ -2754,7 +2754,7 @@ handle_failed_stripe(struct r5conf *conf, struct stripe_head *sh,
                bi = sh->dev[i].written;
                sh->dev[i].written = NULL;
                if (bi) bitmap_end = 1;
-               while (bi && bi->bi_sector <
+               while (bi && bi->bi_iter.bi_sector <
                       sh->dev[i].sector + STRIPE_SECTORS) {
                        struct bio *bi2 = r5_next_bio(bi, sh->dev[i].sector);
                        clear_bit(BIO_UPTODATE, &bi->bi_flags);
@@ -2778,7 +2778,7 @@ handle_failed_stripe(struct r5conf *conf, struct stripe_head *sh,
                        spin_unlock_irq(&sh->stripe_lock);
                        if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
                                wake_up(&conf->wait_for_overlap);
-                       while (bi && bi->bi_sector <
+                       while (bi && bi->bi_iter.bi_sector <
                               sh->dev[i].sector + STRIPE_SECTORS) {
                                struct bio *nextbi =
                                        r5_next_bio(bi, sh->dev[i].sector);
@@ -3002,7 +3002,7 @@ static void handle_stripe_clean_event(struct r5conf *conf,
                                        clear_bit(R5_UPTODATE, &dev->flags);
                                wbi = dev->written;
                                dev->written = NULL;
-                               while (wbi && wbi->bi_sector <
+                               while (wbi && wbi->bi_iter.bi_sector <
                                        dev->sector + STRIPE_SECTORS) {
                                        wbi2 = r5_next_bio(wbi, dev->sector);
                                        if (!raid5_dec_bi_active_stripes(wbi)) {
@@ -4094,7 +4094,7 @@ static int raid5_mergeable_bvec(struct request_queue *q,
 
 static int in_chunk_boundary(struct mddev *mddev, struct bio *bio)
 {
-       sector_t sector = bio->bi_sector + get_start_sect(bio->bi_bdev);
+       sector_t sector = bio->bi_iter.bi_sector + get_start_sect(bio->bi_bdev);
        unsigned int chunk_sectors = mddev->chunk_sectors;
        unsigned int bio_sectors = bio_sectors(bio);
 
@@ -4231,9 +4231,9 @@ static int chunk_aligned_read(struct mddev *mddev, struct bio * raid_bio)
        /*
         *      compute position
         */
-       align_bi->bi_sector =  raid5_compute_sector(conf, raid_bio->bi_sector,
-                                                   0,
-                                                   &dd_idx, NULL);
+       align_bi->bi_iter.bi_sector =
+               raid5_compute_sector(conf, raid_bio->bi_iter.bi_sector,
+                                    0, &dd_idx, NULL);
 
        end_sector = bio_end_sector(align_bi);
        rcu_read_lock();
@@ -4258,7 +4258,8 @@ static int chunk_aligned_read(struct mddev *mddev, struct bio * raid_bio)
                align_bi->bi_flags &= ~(1 << BIO_SEG_VALID);
 
                if (!bio_fits_rdev(align_bi) ||
-                   is_badblock(rdev, align_bi->bi_sector, bio_sectors(align_bi),
+                   is_badblock(rdev, align_bi->bi_iter.bi_sector,
+                               bio_sectors(align_bi),
                                &first_bad, &bad_sectors)) {
                        /* too big in some way, or has a known bad block */
                        bio_put(align_bi);
@@ -4267,7 +4268,7 @@ static int chunk_aligned_read(struct mddev *mddev, struct bio * raid_bio)
                }
 
                /* No reshape active, so we can trust rdev->data_offset */
-               align_bi->bi_sector += rdev->data_offset;
+               align_bi->bi_iter.bi_sector += rdev->data_offset;
 
                spin_lock_irq(&conf->device_lock);
                wait_event_lock_irq(conf->wait_for_stripe,
@@ -4279,7 +4280,7 @@ static int chunk_aligned_read(struct mddev *mddev, struct bio * raid_bio)
                if (mddev->gendisk)
                        trace_block_bio_remap(bdev_get_queue(align_bi->bi_bdev),
                                              align_bi, disk_devt(mddev->gendisk),
-                                             raid_bio->bi_sector);
+                                             raid_bio->bi_iter.bi_sector);
                generic_make_request(align_bi);
                return 1;
        } else {
@@ -4462,8 +4463,8 @@ static void make_discard_request(struct mddev *mddev, struct bio *bi)
                /* Skip discard while reshape is happening */
                return;
 
-       logical_sector = bi->bi_sector & ~((sector_t)STRIPE_SECTORS-1);
-       last_sector = bi->bi_sector + (bi->bi_size>>9);
+       logical_sector = bi->bi_iter.bi_sector & ~((sector_t)STRIPE_SECTORS-1);
+       last_sector = bi->bi_iter.bi_sector + (bi->bi_iter.bi_size>>9);
 
        bi->bi_next = NULL;
        bi->bi_phys_segments = 1; /* over-loaded to count active stripes */
@@ -4567,7 +4568,7 @@ static void make_request(struct mddev *mddev, struct bio * bi)
                return;
        }
 
-       logical_sector = bi->bi_sector & ~((sector_t)STRIPE_SECTORS-1);
+       logical_sector = bi->bi_iter.bi_sector & ~((sector_t)STRIPE_SECTORS-1);
        last_sector = bio_end_sector(bi);
        bi->bi_next = NULL;
        bi->bi_phys_segments = 1;       /* over-loaded to count active stripes */
@@ -5051,7 +5052,8 @@ static int  retry_aligned_read(struct r5conf *conf, struct bio *raid_bio)
        int remaining;
        int handled = 0;
 
-       logical_sector = raid_bio->bi_sector & ~((sector_t)STRIPE_SECTORS-1);
+       logical_sector = raid_bio->bi_iter.bi_sector &
+               ~((sector_t)STRIPE_SECTORS-1);
        sector = raid5_compute_sector(conf, logical_sector,
                                      0, &dd_idx, NULL);
        last_sector = bio_end_sector(raid_bio);
index d0799e32336450d967114938fc610b66d4134070..9c9063cd3208909d5840a7c2cc745d1bf124f542 100644 (file)
@@ -955,7 +955,7 @@ struct sms_rx_stats {
        u32 modem_state;                /* from SMSHOSTLIB_DVB_MODEM_STATE_ET */
        s32 SNR;                /* dB */
        u32 ber;                /* Post Viterbi ber [1E-5] */
-       u32 ber_error_count;    /* Number of erronous SYNC bits. */
+       u32 ber_error_count;    /* Number of erroneous SYNC bits. */
        u32 ber_bit_count;      /* Total number of SYNC bits. */
        u32 ts_per;             /* Transport stream PER,
        0xFFFFFFFF indicate N/A */
@@ -981,7 +981,7 @@ struct sms_rx_stats_ex {
        u32 modem_state;                /* from SMSHOSTLIB_DVB_MODEM_STATE_ET */
        s32 SNR;                /* dB */
        u32 ber;                /* Post Viterbi ber [1E-5] */
-       u32 ber_error_count;    /* Number of erronous SYNC bits. */
+       u32 ber_error_count;    /* Number of erroneous SYNC bits. */
        u32 ber_bit_count;      /* Total number of SYNC bits. */
        u32 ts_per;             /* Transport stream PER,
        0xFFFFFFFF indicate N/A */
index 92c413ba0c7971386f052e2f4c4c00876062a31d..ae36d0ae0fb1991ae0ee2e16e392796ca12d271f 100644 (file)
@@ -95,7 +95,7 @@ struct RECEPTION_STATISTICS_PER_SLICES_S {
        u32 is_demod_locked;    /* 0 - not locked, 1 - locked */
 
        u32 ber_bit_count;      /* Total number of SYNC bits. */
-       u32 ber_error_count;    /* Number of erronous SYNC bits. */
+       u32 ber_error_count;    /* Number of erroneous SYNC bits. */
 
        s32 MRC_SNR;            /* dB */
        s32 mrc_in_band_pwr;    /* In band power in dBM */
index 58de4410c5258a7d6009ae47b5becd7e20fa6208..6c7ff0cdcd32ddd44cae9dcf85e98054a7601052 100644 (file)
@@ -435,7 +435,7 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
                dprintk_tscheck("TEI detected. "
                                "PID=0x%x data1=0x%x\n",
                                pid, buf[1]);
-               /* data in this packet cant be trusted - drop it unless
+               /* data in this packet can't be trusted - drop it unless
                 * module option dvb_demux_feed_err_pkts is set */
                if (!dvb_demux_feed_err_pkts)
                        return;
@@ -1032,8 +1032,13 @@ static int dmx_section_feed_release_filter(struct dmx_section_feed *feed,
                return -EINVAL;
        }
 
-       if (feed->is_filtering)
+       if (feed->is_filtering) {
+               /* release dvbdmx->mutex as far as it is
+                  acquired by stop_filtering() itself */
+               mutex_unlock(&dvbdmx->mutex);
                feed->stop_filtering(feed);
+               mutex_lock(&dvbdmx->mutex);
+       }
 
        spin_lock_irq(&dvbdmx->lock);
        f = dvbdmxfeed->filter;
index 30ee59052157815edd50669afe2293ed4e2e8867..65728c25ea05adcd50bd658c96a6c54dd6fb569b 100644 (file)
@@ -170,18 +170,18 @@ static int af9033_rd_reg_mask(struct af9033_state *state, u32 reg, u8 *val,
 static int af9033_wr_reg_val_tab(struct af9033_state *state,
                const struct reg_val *tab, int tab_len)
 {
+#define MAX_TAB_LEN 212
        int ret, i, j;
-       u8 buf[MAX_XFER_SIZE];
+       u8 buf[1 + MAX_TAB_LEN];
+
+       dev_dbg(&state->i2c->dev, "%s: tab_len=%d\n", __func__, tab_len);
 
        if (tab_len > sizeof(buf)) {
-               dev_warn(&state->i2c->dev,
-                        "%s: i2c wr len=%d is too big!\n",
-                        KBUILD_MODNAME, tab_len);
+               dev_warn(&state->i2c->dev, "%s: tab len %d is too big\n",
+                               KBUILD_MODNAME, tab_len);
                return -EINVAL;
        }
 
-       dev_dbg(&state->i2c->dev, "%s: tab_len=%d\n", __func__, tab_len);
-
        for (i = 0, j = 0; i < tab_len; i++) {
                buf[j] = tab[i].val;
 
index 476b422ccf1960bbf2cf71d5973fdd64e8680cdc..68f768a5422d063f69b4e33446364f5af699a7a1 100644 (file)
 
 
 enum cmds {
-       CMD_SET_VCO     = 0x10,
-       CMD_TUNEREQUEST = 0x11,
-       CMD_MPEGCONFIG  = 0x13,
-       CMD_TUNERINIT   = 0x14,
-       CMD_LNBSEND     = 0x21, /* Formerly CMD_SEND_DISEQC */
-       CMD_LNBDCLEVEL  = 0x22,
-       CMD_SET_TONE    = 0x23,
-       CMD_UPDFWVERS   = 0x35,
-       CMD_TUNERSLEEP  = 0x36,
+       CMD_SET_VCOFREQ    = 0x10,
+       CMD_TUNEREQUEST    = 0x11,
+       CMD_GLOBAL_MPEGCFG = 0x13,
+       CMD_MPEGCFG        = 0x14,
+       CMD_TUNERINIT      = 0x15,
+       CMD_GET_SRATE      = 0x18,
+       CMD_SET_GOLDCODE   = 0x19,
+       CMD_GET_AGCACC     = 0x1a,
+       CMD_DEMODINIT      = 0x1b,
+       CMD_GETCTLACC      = 0x1c,
+
+       CMD_LNBCONFIG      = 0x20,
+       CMD_LNBSEND        = 0x21,
+       CMD_LNBDCLEVEL     = 0x22,
+       CMD_LNBPCBCONFIG   = 0x23,
+       CMD_LNBSENDTONEBST = 0x24,
+       CMD_LNBUPDREPLY    = 0x25,
+
+       CMD_SET_GPIOMODE   = 0x30,
+       CMD_SET_GPIOEN     = 0x31,
+       CMD_SET_GPIODIR    = 0x32,
+       CMD_SET_GPIOOUT    = 0x33,
+       CMD_ENABLERSCORR   = 0x34,
+       CMD_FWVERSION      = 0x35,
+       CMD_SET_SLEEPMODE  = 0x36,
+       CMD_BERCTRL        = 0x3c,
+       CMD_EVENTCTRL      = 0x3d,
 };
 
 static LIST_HEAD(hybrid_tuner_instance_list);
@@ -619,8 +637,8 @@ static int cx24117_load_firmware(struct dvb_frontend *fe,
        cx24117_writereg(state, 0xf7, 0x0c);
        cx24117_writereg(state, 0xe0, 0x00);
 
-       /* CMD 1B */
-       cmd.args[0] = 0x1b;
+       /* Init demodulator */
+       cmd.args[0] = CMD_DEMODINIT;
        cmd.args[1] = 0x00;
        cmd.args[2] = 0x01;
        cmd.args[3] = 0x00;
@@ -629,8 +647,8 @@ static int cx24117_load_firmware(struct dvb_frontend *fe,
        if (ret != 0)
                goto error;
 
-       /* CMD 10 */
-       cmd.args[0] = CMD_SET_VCO;
+       /* Set VCO frequency */
+       cmd.args[0] = CMD_SET_VCOFREQ;
        cmd.args[1] = 0x06;
        cmd.args[2] = 0x2b;
        cmd.args[3] = 0xd8;
@@ -648,8 +666,8 @@ static int cx24117_load_firmware(struct dvb_frontend *fe,
        if (ret != 0)
                goto error;
 
-       /* CMD 15 */
-       cmd.args[0] = 0x15;
+       /* Tuner init */
+       cmd.args[0] = CMD_TUNERINIT;
        cmd.args[1] = 0x00;
        cmd.args[2] = 0x01;
        cmd.args[3] = 0x00;
@@ -667,8 +685,8 @@ static int cx24117_load_firmware(struct dvb_frontend *fe,
        if (ret != 0)
                goto error;
 
-       /* CMD 13 */
-       cmd.args[0] = CMD_MPEGCONFIG;
+       /* Global MPEG config */
+       cmd.args[0] = CMD_GLOBAL_MPEGCFG;
        cmd.args[1] = 0x00;
        cmd.args[2] = 0x00;
        cmd.args[3] = 0x00;
@@ -679,9 +697,9 @@ static int cx24117_load_firmware(struct dvb_frontend *fe,
        if (ret != 0)
                goto error;
 
-       /* CMD 14 */
+       /* MPEG config for each demod */
        for (i = 0; i < 2; i++) {
-               cmd.args[0] = CMD_TUNERINIT;
+               cmd.args[0] = CMD_MPEGCFG;
                cmd.args[1] = (u8) i;
                cmd.args[2] = 0x00;
                cmd.args[3] = 0x05;
@@ -699,8 +717,8 @@ static int cx24117_load_firmware(struct dvb_frontend *fe,
        cx24117_writereg(state, 0xcf, 0x00);
        cx24117_writereg(state, 0xe5, 0x04);
 
-       /* Firmware CMD 35: Get firmware version */
-       cmd.args[0] = CMD_UPDFWVERS;
+       /* Get firmware version */
+       cmd.args[0] = CMD_FWVERSION;
        cmd.len = 2;
        for (i = 0; i < 4; i++) {
                cmd.args[1] = i;
@@ -779,8 +797,8 @@ static int cx24117_read_signal_strength(struct dvb_frontend *fe,
        u8 reg = (state->demod == 0) ?
                CX24117_REG_SSTATUS0 : CX24117_REG_SSTATUS1;
 
-       /* Firmware CMD 1A */
-       cmd.args[0] = 0x1a;
+       /* Read AGC accumulator register */
+       cmd.args[0] = CMD_GET_AGCACC;
        cmd.args[1] = (u8) state->demod;
        cmd.len = 2;
        ret = cx24117_cmd_execute(fe, &cmd);
@@ -899,22 +917,15 @@ static int cx24117_set_voltage(struct dvb_frontend *fe,
                voltage == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" :
                "SEC_VOLTAGE_OFF");
 
-       /* CMD 32 */
-       cmd.args[0] = 0x32;
-       cmd.args[1] = reg;
-       cmd.args[2] = reg;
+       /* Prepare a set GPIO logic level CMD */
+       cmd.args[0] = CMD_SET_GPIOOUT;
+       cmd.args[2] = reg; /* mask */
        cmd.len = 3;
-       ret = cx24117_cmd_execute(fe, &cmd);
-       if (ret)
-               return ret;
 
        if ((voltage == SEC_VOLTAGE_13) ||
            (voltage == SEC_VOLTAGE_18)) {
-               /* CMD 33 */
-               cmd.args[0] = 0x33;
+               /* power on LNB */
                cmd.args[1] = reg;
-               cmd.args[2] = reg;
-               cmd.len = 3;
                ret = cx24117_cmd_execute(fe, &cmd);
                if (ret != 0)
                        return ret;
@@ -926,22 +937,22 @@ static int cx24117_set_voltage(struct dvb_frontend *fe,
                /* Wait for voltage/min repeat delay */
                msleep(100);
 
-               /* CMD 22 - CMD_LNBDCLEVEL */
+               /* Set 13V/18V select pin */
                cmd.args[0] = CMD_LNBDCLEVEL;
                cmd.args[1] = state->demod ? 0 : 1;
                cmd.args[2] = (voltage == SEC_VOLTAGE_18 ? 0x01 : 0x00);
                cmd.len = 3;
+               ret = cx24117_cmd_execute(fe, &cmd);
 
                /* Min delay time before DiSEqC send */
                msleep(20);
        } else {
-               cmd.args[0] = 0x33;
+               /* power off LNB */
                cmd.args[1] = 0x00;
-               cmd.args[2] = reg;
-               cmd.len = 3;
+               ret = cx24117_cmd_execute(fe, &cmd);
        }
 
-       return cx24117_cmd_execute(fe, &cmd);
+       return ret;
 }
 
 static int cx24117_set_tone(struct dvb_frontend *fe,
@@ -968,8 +979,7 @@ static int cx24117_set_tone(struct dvb_frontend *fe,
        msleep(20);
 
        /* Set the tone */
-       /* CMD 23 - CMD_SET_TONE */
-       cmd.args[0] = CMD_SET_TONE;
+       cmd.args[0] = CMD_LNBPCBCONFIG;
        cmd.args[1] = (state->demod ? 0 : 1);
        cmd.args[2] = 0x00;
        cmd.args[3] = 0x00;
@@ -1231,8 +1241,8 @@ static int cx24117_initfe(struct dvb_frontend *fe)
 
        mutex_lock(&state->priv->fe_lock);
 
-       /* Firmware CMD 36: Power config */
-       cmd.args[0] = CMD_TUNERSLEEP;
+       /* Set sleep mode off */
+       cmd.args[0] = CMD_SET_SLEEPMODE;
        cmd.args[1] = (state->demod ? 1 : 0);
        cmd.args[2] = 0;
        cmd.len = 3;
@@ -1244,8 +1254,8 @@ static int cx24117_initfe(struct dvb_frontend *fe)
        if (ret != 0)
                goto exit;
 
-       /* CMD 3C */
-       cmd.args[0] = 0x3c;
+       /* Set BER control */
+       cmd.args[0] = CMD_BERCTRL;
        cmd.args[1] = (state->demod ? 1 : 0);
        cmd.args[2] = 0x10;
        cmd.args[3] = 0x10;
@@ -1254,12 +1264,22 @@ static int cx24117_initfe(struct dvb_frontend *fe)
        if (ret != 0)
                goto exit;
 
-       /* CMD 34 */
-       cmd.args[0] = 0x34;
+       /* Set RS correction (enable/disable) */
+       cmd.args[0] = CMD_ENABLERSCORR;
        cmd.args[1] = (state->demod ? 1 : 0);
        cmd.args[2] = CX24117_OCC;
        cmd.len = 3;
        ret = cx24117_cmd_execute_nolock(fe, &cmd);
+       if (ret != 0)
+               goto exit;
+
+       /* Set GPIO direction */
+       /* Set as output - controls LNB power on/off */
+       cmd.args[0] = CMD_SET_GPIODIR;
+       cmd.args[1] = 0x30;
+       cmd.args[2] = 0x30;
+       cmd.len = 3;
+       ret = cx24117_cmd_execute_nolock(fe, &cmd);
 
 exit:
        mutex_unlock(&state->priv->fe_lock);
@@ -1278,8 +1298,8 @@ static int cx24117_sleep(struct dvb_frontend *fe)
        dev_dbg(&state->priv->i2c->dev, "%s() demod%d\n",
                __func__, state->demod);
 
-       /* Firmware CMD 36: Power config */
-       cmd.args[0] = CMD_TUNERSLEEP;
+       /* Set sleep mode on */
+       cmd.args[0] = CMD_SET_SLEEPMODE;
        cmd.args[1] = (state->demod ? 1 : 0);
        cmd.args[2] = 1;
        cmd.len = 3;
@@ -1558,7 +1578,8 @@ static int cx24117_get_frontend(struct dvb_frontend *fe)
 
        u8 buf[0x1f-4];
 
-       cmd.args[0] = 0x1c;
+       /* Read current tune parameters */
+       cmd.args[0] = CMD_GETCTLACC;
        cmd.args[1] = (u8) state->demod;
        cmd.len = 2;
        ret = cx24117_cmd_execute(fe, &cmd);
index 125a44041011ca0ed17f99999a2bffaa5c1999a1..5c6ab4921bf11d2004ed77e9240b2452fbbb3974 100644 (file)
@@ -78,7 +78,7 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe)
 
        num = if_freq / 1000; /* Hz => kHz */
        num *= 0x4000;
-       if_ctl = cxd2820r_div_u64_round_closest(num, 41000);
+       if_ctl = 0x4000 - cxd2820r_div_u64_round_closest(num, 41000);
        buf[0] = (if_ctl >> 8) & 0x3f;
        buf[1] = (if_ctl >> 0) & 0xff;
 
index 90536147bf0458c444a59e176b79ddff09471f4f..6dbbee453ee15adb0c4d6b97196beefe6e7d9523 100644 (file)
@@ -3048,7 +3048,7 @@ static int dib8000_tune(struct dvb_frontend *fe)
                        dib8000_set_diversity_in(state->fe[0], state->diversity_onoff);
 
                        locks = (dib8000_read_word(state, 180) >> 6) & 0x3f; /* P_coff_winlen ? */
-                       /* coff should lock over P_coff_winlen ofdm symbols : give 3 times this lenght to lock */
+                       /* coff should lock over P_coff_winlen ofdm symbols : give 3 times this length to lock */
                        *timeout = dib8000_get_timeout(state, 2 * locks, SYMBOL_DEPENDENT_ON);
                        *tune_state = CT_DEMOD_STEP_5;
                        break;
@@ -3115,7 +3115,7 @@ static int dib8000_tune(struct dvb_frontend *fe)
 
        case CT_DEMOD_STEP_9: /* 39 */
                        if ((state->revision == 0x8090) || ((dib8000_read_word(state, 1291) >> 9) & 0x1)) { /* fe capable of deinterleaving : esram */
-                               /* defines timeout for mpeg lock depending on interleaver lenght of longest layer */
+                               /* defines timeout for mpeg lock depending on interleaver length of longest layer */
                                for (i = 0; i < 3; i++) {
                                        if (c->layer[i].interleaving >= deeper_interleaver) {
                                                dprintk("layer%i: time interleaver = %d ", i, c->layer[i].interleaving);
index d416c15691dadd69b49eda6f26c70892c3a02652..bf29a3f0e6f0ca440990f7b8b61e71e9bd02674a 100644 (file)
@@ -1191,7 +1191,7 @@ static int mpegts_configure_pins(struct drxk_state *state, bool mpeg_enable)
                        goto error;
 
                if (state->m_enable_parallel == true) {
-                       /* paralel -> enable MD1 to MD7 */
+                       /* parallel -> enable MD1 to MD7 */
                        status = write16(state, SIO_PDR_MD1_CFG__A,
                                         sio_pdr_mdx_cfg);
                        if (status < 0)
@@ -1428,7 +1428,7 @@ static int mpegts_stop(struct drxk_state *state)
 
        dprintk(1, "\n");
 
-       /* Gracefull shutdown (byte boundaries) */
+       /* Graceful shutdown (byte boundaries) */
        status = read16(state, FEC_OC_SNC_MODE__A, &fec_oc_snc_mode);
        if (status < 0)
                goto error;
@@ -2021,7 +2021,7 @@ static int mpegts_dto_setup(struct drxk_state *state,
                fec_oc_dto_burst_len = 204;
        }
 
-       /* Check serial or parrallel output */
+       /* Check serial or parallel output */
        fec_oc_reg_ipr_mode &= (~(FEC_OC_IPR_MODE_SERIAL__M));
        if (state->m_enable_parallel == false) {
                /* MPEG data output is serial -> set ipr_mode[0] */
@@ -2908,7 +2908,7 @@ static int adc_synchronization(struct drxk_state *state)
                goto error;
 
        if (count == 1) {
-               /* Try sampling on a diffrent edge */
+               /* Try sampling on a different edge */
                u16 clk_neg = 0;
 
                status = read16(state, IQM_AF_CLKNEG__A, &clk_neg);
@@ -3306,7 +3306,7 @@ static int dvbt_sc_command(struct drxk_state *state,
        if (status < 0)
                goto error;
 
-       /* Retreive results parameters from SC */
+       /* Retrieve results parameters from SC */
        switch (cmd) {
                /* All commands yielding 5 results */
                /* All commands yielding 4 results */
@@ -3849,7 +3849,7 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz,
                break;
        }
 #if 0
-       /* No hierachical channels support in BDA */
+       /* No hierarchical channels support in BDA */
        /* Priority (only for hierarchical channels) */
        switch (channel->priority) {
        case DRX_PRIORITY_LOW:
@@ -4081,7 +4081,7 @@ error:
 /*============================================================================*/
 
 /**
-* \brief Retreive lock status .
+* \brief Retrieve lock status .
 * \param demod    Pointer to demodulator instance.
 * \param lockStat Pointer to lock status structure.
 * \return DRXStatus_t.
@@ -6174,7 +6174,7 @@ static int init_drxk(struct drxk_state *state)
                        goto error;
 
                /* Stamp driver version number in SCU data RAM in BCD code
-                       Done to enable field application engineers to retreive drxdriver version
+                       Done to enable field application engineers to retrieve drxdriver version
                        via I2C from SCU RAM.
                        Not using SCU command interface for SCU register access since no
                        microcode may be present.
@@ -6399,7 +6399,7 @@ static int drxk_set_parameters(struct dvb_frontend *fe)
        fe->ops.tuner_ops.get_if_frequency(fe, &IF);
        start(state, 0, IF);
 
-       /* After set_frontend, stats aren't avaliable */
+       /* After set_frontend, stats aren't available */
        p->strength.stat[0].scale = FE_SCALE_RELATIVE;
        p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
        p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
index 7efb796c472c475bed62f1a0bb783f5b991a5b1e..50e8b63e5169bad938b1fc8b79e0871a619364d3 100644 (file)
@@ -710,6 +710,7 @@ struct dvb_frontend *rtl2830_attach(const struct rtl2830_config *cfg,
                sizeof(priv->tuner_i2c_adapter.name));
        priv->tuner_i2c_adapter.algo = &rtl2830_tuner_i2c_algo;
        priv->tuner_i2c_adapter.algo_data = NULL;
+       priv->tuner_i2c_adapter.dev.parent = &i2c->dev;
        i2c_set_adapdata(&priv->tuner_i2c_adapter, priv);
        if (i2c_add_adapter(&priv->tuner_i2c_adapter) < 0) {
                dev_err(&i2c->dev,
index 4a5b7d211d2f14e3810111a7f6399405e5000935..b253d400e8176a8baa3d1ba6928a1911d74bdb9d 100644 (file)
@@ -52,9 +52,9 @@
 #define ADV7183_VS_FIELD_CTRL_1    0x31 /* Vsync field control 1 */
 #define ADV7183_VS_FIELD_CTRL_2    0x32 /* Vsync field control 2 */
 #define ADV7183_VS_FIELD_CTRL_3    0x33 /* Vsync field control 3 */
-#define ADV7183_HS_POS_CTRL_1      0x34 /* Hsync positon control 1 */
-#define ADV7183_HS_POS_CTRL_2      0x35 /* Hsync positon control 2 */
-#define ADV7183_HS_POS_CTRL_3      0x36 /* Hsync positon control 3 */
+#define ADV7183_HS_POS_CTRL_1      0x34 /* Hsync position control 1 */
+#define ADV7183_HS_POS_CTRL_2      0x35 /* Hsync position control 2 */
+#define ADV7183_HS_POS_CTRL_3      0x36 /* Hsync position control 3 */
 #define ADV7183_POLARITY           0x37 /* Polarity */
 #define ADV7183_NTSC_COMB_CTRL     0x38 /* NTSC comb control */
 #define ADV7183_PAL_COMB_CTRL      0x39 /* PAL comb control */
index fbfdd2fc2a367f5b48c67fc41785395508fc473d..a324106b9f11e985c0637c16578cd3922ee6f58b 100644 (file)
@@ -877,7 +877,7 @@ static void configure_custom_video_timings(struct v4l2_subdev *sd,
                break;
        case ADV7604_MODE_HDMI:
                /* set default prim_mode/vid_std for HDMI
-                  accoring to [REF_03, c. 4.2] */
+                  according to [REF_03, c. 4.2] */
                io_write(sd, 0x00, 0x02); /* video std */
                io_write(sd, 0x01, 0x06); /* prim mode */
                break;
index 22f729d66a9696522e18d42932ae383594cbca5f..b154f36740b49151e2b1e0daeaf307c53032f3e7 100644 (file)
@@ -1013,7 +1013,7 @@ static void configure_custom_video_timings(struct v4l2_subdev *sd,
                break;
        case ADV7842_MODE_HDMI:
                /* set default prim_mode/vid_std for HDMI
-                  accoring to [REF_03, c. 4.2] */
+                  according to [REF_03, c. 4.2] */
                io_write(sd, 0x00, 0x02); /* video std */
                io_write(sd, 0x01, 0x06); /* prim mode */
                break;
index 82bf5679da3064d5a8ffd9da91c3d9e085d8d8bb..99ee456700f4972ef53888d692aa5f4b19930bce 100644 (file)
@@ -394,7 +394,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 
        if (!rc) {
                /*
-                * If platform_data doesn't specify rc_dev, initilize it
+                * If platform_data doesn't specify rc_dev, initialize it
                 * internally
                 */
                rc = rc_allocate_device();
index 3317a9ae3961fcf11dcf4cd97254654af608e1d5..ab5857d66f2d8f58e5a708bdfc01f28746c0e069 100644 (file)
@@ -172,28 +172,28 @@ static int lm3560_flash_brt_ctrl(struct lm3560_flash *flash,
 static int lm3560_get_ctrl(struct v4l2_ctrl *ctrl, enum lm3560_led_id led_no)
 {
        struct lm3560_flash *flash = to_lm3560_flash(ctrl, led_no);
+       int rval = -EINVAL;
 
        mutex_lock(&flash->lock);
 
        if (ctrl->id == V4L2_CID_FLASH_FAULT) {
-               int rval;
                s32 fault = 0;
                unsigned int reg_val;
                rval = regmap_read(flash->regmap, REG_FLAG, &reg_val);
                if (rval < 0)
-                       return rval;
-               if (rval & FAULT_SHORT_CIRCUIT)
+                       goto out;
+               if (reg_val & FAULT_SHORT_CIRCUIT)
                        fault |= V4L2_FLASH_FAULT_SHORT_CIRCUIT;
-               if (rval & FAULT_OVERTEMP)
+               if (reg_val & FAULT_OVERTEMP)
                        fault |= V4L2_FLASH_FAULT_OVER_TEMPERATURE;
-               if (rval & FAULT_TIMEOUT)
+               if (reg_val & FAULT_TIMEOUT)
                        fault |= V4L2_FLASH_FAULT_TIMEOUT;
                ctrl->cur.val = fault;
-               return 0;
        }
 
+out:
        mutex_unlock(&flash->lock);
-       return -EINVAL;
+       return rval;
 }
 
 static int lm3560_set_ctrl(struct v4l2_ctrl *ctrl, enum lm3560_led_id led_no)
index f34429e452abf4e01dfd71d38ceb690d3c5ab021..a60931e66312e1ff3818ff363c0edd920c0d6c04 100644 (file)
@@ -544,7 +544,7 @@ int m5mols_init_controls(struct v4l2_subdev *sd)
        u16 zoom_step;
        int ret;
 
-       /* Determine the firmware dependant control range and step values */
+       /* Determine the firmware dependent control range and step values */
        ret = m5mols_read_u16(sd, AE_MAX_GAIN_MON, &exposure_max);
        if (ret < 0)
                return ret;
index 4734836fe5a410c8cf4249d9c455f5ceaf4b627c..1c2303d18bf49db242c00ac0cab8a474843c6db1 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/i2c.h>
 #include <linux/log2.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/of_gpio.h>
 #include <linux/pm.h>
 #include <linux/regulator/consumer.h>
index 6fec9384d86e4877d5b750a9f9a9ceec53e06bde..e7f555cc827abb4ddc1eba44bb1526e1d32576e4 100644 (file)
@@ -1460,7 +1460,7 @@ static int s5c73m3_oif_registered(struct v4l2_subdev *sd)
        mutex_unlock(&state->lock);
 
        v4l2_dbg(1, s5c73m3_dbg, sd, "%s: Booting %s (%d)\n",
-                __func__, ret ? "failed" : "succeded", ret);
+                __func__, ret ? "failed" : "succeeded", ret);
 
        return ret;
 }
index 9d2c0865224609504ab1a9b9302cb99d53086e85..9dfa516f694471660f9de431c948ae279ed07bb9 100644 (file)
@@ -393,7 +393,7 @@ struct s5c73m3 {
 
        /* External master clock frequency */
        u32 mclk_frequency;
-       /* Video bus type - MIPI-CSI2/paralell */
+       /* Video bus type - MIPI-CSI2/parallel */
        enum v4l2_mbus_type bus_type;
 
        const struct s5c73m3_frame_size *sensor_pix_size[2];
index 637d026345271c154f4af2da7a53bde6adbcae94..afdbcb045ceece64685db171dac9699d8a7dfc49 100644 (file)
@@ -1699,7 +1699,7 @@ static void saa711x_write_platform_data(struct saa711x_state *state,
  * the analog demod.
  * If the tuner is not found, it returns -ENODEV.
  * If auto-detection is disabled and the tuner doesn't match what it was
- *     requred, it returns -EINVAL and fills 'name'.
+ *     required, it returns -EINVAL and fills 'name'.
  * If the chip is found, it returns the chip ID and fills 'name'.
  */
 static int saa711x_detect_chip(struct i2c_client *client,
index ae66d91bf7136c2e494432cea21d8359654f89a6..fbd48f04b5c81a6c76975bac06ae0d856089f90b 100644 (file)
@@ -399,7 +399,6 @@ static void smiapp_update_mbus_formats(struct smiapp_sensor *sensor)
 
        BUG_ON(max(internal_csi_format_idx, csi_format_idx) + pixel_order
               >= ARRAY_SIZE(smiapp_csi_data_formats));
-       BUG_ON(min(internal_csi_format_idx, csi_format_idx) < 0);
 
        dev_dbg(&client->dev, "new pixel order %s\n",
                pixel_order_str[pixel_order]);
index 0a5c5d4fedd6e375b34a1848f3b646a6577bd97d..d2daa6a8f27245b88f69d832b2f2537ab716b0f9 100644 (file)
@@ -642,7 +642,7 @@ static const struct ov5642_datafmt
 static int reg_read(struct i2c_client *client, u16 reg, u8 *val)
 {
        int ret;
-       /* We have 16-bit i2c addresses - care for endianess */
+       /* We have 16-bit i2c addresses - care for endianness */
        unsigned char data[2] = { reg >> 8, reg & 0xff };
 
        ret = i2c_master_send(client, data, 2);
index 42276d93624cada191b30eb7e3ca7ad40fb923fa..ed9ae8875348b6abdd226e3026e4b1d6f117c12f 100644 (file)
@@ -83,7 +83,8 @@ static int ths7303_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 }
 
 /* following function is used to set ths7303 */
-int ths7303_setval(struct v4l2_subdev *sd, enum ths7303_filter_mode mode)
+static int ths7303_setval(struct v4l2_subdev *sd,
+                         enum ths7303_filter_mode mode)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct ths7303_state *state = to_state(sd);
index 3f584a7d0781b9860aad6b6bb9f6ddef4ad2b449..bee7946faa7cc2ba28a690e219cd0c5dcf89ff3b 100644 (file)
@@ -130,12 +130,10 @@ static int wm8775_s_routing(struct v4l2_subdev *sd,
                return -EINVAL;
        }
        state->input = input;
-       if (!v4l2_ctrl_g_ctrl(state->mute))
+       if (v4l2_ctrl_g_ctrl(state->mute))
                return 0;
        if (!v4l2_ctrl_g_ctrl(state->vol))
                return 0;
-       if (!v4l2_ctrl_g_ctrl(state->bal))
-               return 0;
        wm8775_set_audio(sd, 1);
        return 0;
 }
index 2c286c307145b6828a7ac8c3b4bfc4f05ae18735..37c334edc7e8c10d3a6430f64a29b1f16088d929 100644 (file)
@@ -235,6 +235,8 @@ __must_check int media_entity_pipeline_start(struct media_entity *entity,
        media_entity_graph_walk_start(&graph, entity);
 
        while ((entity = media_entity_graph_walk_next(&graph))) {
+               DECLARE_BITMAP(active, entity->num_pads);
+               DECLARE_BITMAP(has_no_links, entity->num_pads);
                unsigned int i;
 
                entity->stream_count++;
@@ -248,21 +250,46 @@ __must_check int media_entity_pipeline_start(struct media_entity *entity,
                if (!entity->ops || !entity->ops->link_validate)
                        continue;
 
+               bitmap_zero(active, entity->num_pads);
+               bitmap_fill(has_no_links, entity->num_pads);
+
                for (i = 0; i < entity->num_links; i++) {
                        struct media_link *link = &entity->links[i];
-
-                       /* Is this pad part of an enabled link? */
-                       if (!(link->flags & MEDIA_LNK_FL_ENABLED))
-                               continue;
-
-                       /* Are we the sink or not? */
-                       if (link->sink->entity != entity)
+                       struct media_pad *pad = link->sink->entity == entity
+                                               ? link->sink : link->source;
+
+                       /* Mark that a pad is connected by a link. */
+                       bitmap_clear(has_no_links, pad->index, 1);
+
+                       /*
+                        * Pads that either do not need to connect or
+                        * are connected through an enabled link are
+                        * fine.
+                        */
+                       if (!(pad->flags & MEDIA_PAD_FL_MUST_CONNECT) ||
+                           link->flags & MEDIA_LNK_FL_ENABLED)
+                               bitmap_set(active, pad->index, 1);
+
+                       /*
+                        * Link validation will only take place for
+                        * sink ends of the link that are enabled.
+                        */
+                       if (link->sink != pad ||
+                           !(link->flags & MEDIA_LNK_FL_ENABLED))
                                continue;
 
                        ret = entity->ops->link_validate(link);
                        if (ret < 0 && ret != -ENOIOCTLCMD)
                                goto error;
                }
+
+               /* Either no links or validated links are fine. */
+               bitmap_or(active, active, has_no_links, entity->num_pads);
+
+               if (!bitmap_full(active, entity->num_pads)) {
+                       ret = -EPIPE;
+                       goto error;
+               }
        }
 
        mutex_unlock(&mdev->graph_mutex);
index a3b1ee9c00d7152405e9ea0e71549f350194692e..92a06fd858652acddff2dd65ce07dee560445df1 100644 (file)
@@ -4182,7 +4182,8 @@ static int bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
        }
        btv->std = V4L2_STD_PAL;
        init_irqreg(btv);
-       v4l2_ctrl_handler_setup(hdl);
+       if (!bttv_tvcards[btv->c.type].no_video)
+               v4l2_ctrl_handler_setup(hdl);
        if (hdl->error) {
                result = hdl->error;
                goto fail2;
index 2767c64df0c87f9c044aca755a63fbfd0c75adf3..57f4688ea55bdf2488eb14dc523d4a4c542a2609 100644 (file)
@@ -262,7 +262,7 @@ struct cx18_options {
 };
 
 /* per-mdl bit flags */
-#define CX18_F_M_NEED_SWAP  0  /* mdl buffer data must be endianess swapped */
+#define CX18_F_M_NEED_SWAP  0  /* mdl buffer data must be endianness swapped */
 
 /* per-stream, s_flags */
 #define CX18_F_S_CLAIMED       3       /* this stream is claimed */
index e3fc2c71808abbd0746cc7d9faabdfc14b9c583f..95666eee7b277026f3c1154a78361212653130b9 100644 (file)
@@ -427,7 +427,7 @@ int mc417_register_read(struct cx23885_dev *dev, u16 address, u32 *value)
        cx_write(MC417_RWD, regval);
 
        /* Transition RD to effect read transaction across bus.
-        * Transtion 0x5000 -> 0x9000 correct (RD/RDY -> WR/RDY)?
+        * Transition 0x5000 -> 0x9000 correct (RD/RDY -> WR/RDY)?
         * Should it be 0x9000 -> 0xF000 (also why is RDY being set, its
         * input only...)
         */
index 8164d74b46a4590af0db79f56bd8c41bacead624..655d6854a8d7fa165502c711bf6c83a017cc16be 100644 (file)
@@ -401,7 +401,7 @@ static int pluto_hw_init(struct pluto *pluto)
        /* set automatic LED control by FPGA */
        pluto_rw(pluto, REG_MISC, MISC_ALED, MISC_ALED);
 
-       /* set data endianess */
+       /* set data endianness */
 #ifdef __LITTLE_ENDIAN
        pluto_rw(pluto, REG_PIDn(0), PID0_END, PID0_END);
 #else
index 57ef5456f1e87e9cc042ec8dc05cdb07192bc15d..1bf06970ca3e8e180cb6a2f20d732c983af820b2 100644 (file)
@@ -1354,9 +1354,11 @@ static int saa7164_initdev(struct pci_dev *pci_dev,
                if (fw_debug) {
                        dev->kthread = kthread_run(saa7164_thread_function, dev,
                                "saa7164 debug");
-                       if (!dev->kthread)
+                       if (IS_ERR(dev->kthread)) {
+                               dev->kthread = NULL;
                                printk(KERN_ERR "%s() Failed to create "
                                        "debug kernel thread\n", __func__);
+                       }
                }
 
        } /* != BOARD_UNKNOWN */
index bd72fb97fea5ab05924c4eeb4f5452534f3c3f46..61f3dbcc259f40f8a0f6f2b4bfa9b52ed6bf24ee 100644 (file)
@@ -1434,7 +1434,7 @@ static void coda_buf_queue(struct vb2_buffer *vb)
        if (q_data->fourcc == V4L2_PIX_FMT_H264 &&
            vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
                /*
-                * For backwards compatiblity, queuing an empty buffer marks
+                * For backwards compatibility, queuing an empty buffer marks
                 * the stream end
                 */
                if (vb2_get_plane_payload(vb, 0) == 0)
index fb27ff7e1e0750e33215b96ee100c9ad569fd9dd..8a712ca91d11bcf46f424778433b3c7c07bbdc78 100644 (file)
@@ -549,7 +549,7 @@ static int fimc_capture_release(struct file *file)
                vc->streaming = false;
        }
 
-       ret = vb2_fop_release(file);
+       ret = _vb2_fop_release(file, NULL);
 
        if (close) {
                clear_bit(ST_CAPT_BUSY, &fimc->state);
index 3d66d88ea3a191911ce72a22a8198602d7640e35..f7915695c9073d37ca10da947c29891b8d0e45d5 100644 (file)
@@ -1039,7 +1039,7 @@ static int fimc_runtime_resume(struct device *dev)
 
        dbg("fimc%d: state: 0x%lx", fimc->id, fimc->state);
 
-       /* Enable clocks and perform basic initalization */
+       /* Enable clocks and perform basic initialization */
        clk_enable(fimc->clock[CLK_GATE]);
        fimc_hw_reset(fimc);
 
index 3d376faec777d1781434cdbf5526301f50b98271..1790fb4e32eabfc8af8084d452e6483827a3852f 100644 (file)
@@ -481,7 +481,6 @@ struct fimc_ctrls {
  * @flags:             additional flags for image conversion
  * @state:             flags to keep track of user configuration
  * @fimc_dev:          the FIMC device this context applies to
- * @m2m_ctx:           memory-to-memory device context
  * @fh:                        v4l2 file handle
  * @ctrls:             v4l2 controls structure
  */
@@ -502,7 +501,6 @@ struct fimc_ctx {
        u32                     flags;
        u32                     state;
        struct fimc_dev         *fimc_dev;
-       struct v4l2_m2m_ctx     *m2m_ctx;
        struct v4l2_fh          fh;
        struct fimc_ctrls       ctrls;
 };
index f758e2694fa3f1eede8b7155fb10094e72e08a04..2628733c4e104f6e7790a74b40f1add7416a2760 100644 (file)
@@ -33,47 +33,23 @@ void fimc_is_hw_set_intgr0_gd0(struct fimc_is *is)
        mcuctl_write(INTGR0_INTGD(0), is, MCUCTL_REG_INTGR0);
 }
 
-int fimc_is_hw_wait_intsr0_intsd0(struct fimc_is *is)
-{
-       unsigned int timeout = 2000;
-       u32 cfg, status;
-
-       cfg = mcuctl_read(is, MCUCTL_REG_INTSR0);
-       status = INTSR0_GET_INTSD(0, cfg);
-
-       while (status) {
-               cfg = mcuctl_read(is, MCUCTL_REG_INTSR0);
-               status = INTSR0_GET_INTSD(0, cfg);
-               if (timeout == 0) {
-                       dev_warn(&is->pdev->dev, "%s timeout\n",
-                                __func__);
-                       return -ETIME;
-               }
-               timeout--;
-               udelay(1);
-       }
-       return 0;
-}
-
 int fimc_is_hw_wait_intmsr0_intmsd0(struct fimc_is *is)
 {
        unsigned int timeout = 2000;
        u32 cfg, status;
 
-       cfg = mcuctl_read(is, MCUCTL_REG_INTMSR0);
-       status = INTMSR0_GET_INTMSD(0, cfg);
-
-       while (status) {
+       do {
                cfg = mcuctl_read(is, MCUCTL_REG_INTMSR0);
                status = INTMSR0_GET_INTMSD(0, cfg);
-               if (timeout == 0) {
+
+               if (--timeout == 0) {
                        dev_warn(&is->pdev->dev, "%s timeout\n",
                                 __func__);
-                       return -ETIME;
+                       return -ETIMEDOUT;
                }
-               timeout--;
                udelay(1);
-       }
+       } while (status != 0);
+
        return 0;
 }
 
index 5fa2fda46742687e97e7aad2f14a508e6889ecfe..1d9d4ffc6ad59ca8d24fbd0bef0005ece14d1354 100644 (file)
@@ -145,7 +145,6 @@ void fimc_is_fw_clear_irq2(struct fimc_is *is);
 int fimc_is_hw_get_params(struct fimc_is *is, unsigned int num);
 
 void fimc_is_hw_set_intgr0_gd0(struct fimc_is *is);
-int fimc_is_hw_wait_intsr0_intsd0(struct fimc_is *is);
 int fimc_is_hw_wait_intmsr0_intmsd0(struct fimc_is *is);
 void fimc_is_hw_set_sensor_num(struct fimc_is *is);
 void fimc_is_hw_stream_on(struct fimc_is *is);
index 72a343e3b5e85e62393f8950c3d0e096d09b8909..d0dc7ee0445272eb9d3111b88a33460626f49a6a 100644 (file)
@@ -133,7 +133,7 @@ void flite_hw_set_source_format(struct fimc_lite *dev, struct flite_frame *f)
        int i = ARRAY_SIZE(src_pixfmt_map);
        u32 cfg;
 
-       while (--i >= 0) {
+       while (--i) {
                if (src_pixfmt_map[i][0] == pixelcode)
                        break;
        }
@@ -240,7 +240,7 @@ static void flite_hw_set_out_order(struct fimc_lite *dev, struct flite_frame *f)
        u32 cfg = readl(dev->regs + FLITE_REG_CIODMAFMT);
        int i = ARRAY_SIZE(pixcode);
 
-       while (--i >= 0)
+       while (--i)
                if (pixcode[i][0] == f->fmt->mbus_code)
                        break;
        cfg &= ~FLITE_REG_CIODMAFMT_YCBCR_ORDER_MASK;
index e5798f70d149287a1df8e080c9e0ed766d0a73de..d3b32b6f795d3fbea560407c2b90320a9b620897 100644 (file)
@@ -546,7 +546,7 @@ static int fimc_lite_release(struct file *file)
                mutex_unlock(&entity->parent->graph_mutex);
        }
 
-       vb2_fop_release(file);
+       _vb2_fop_release(file, NULL);
        pm_runtime_put(&fimc->pdev->dev);
        clear_bit(ST_FLITE_SUSPENDED, &fimc->state);
 
index 8d33b68c76bac7d9e278785a8c914dddce602197..9da95bd148200d5a4406aa6f80a09bf1364d7c65 100644 (file)
@@ -44,17 +44,17 @@ void fimc_m2m_job_finish(struct fimc_ctx *ctx, int vb_state)
 {
        struct vb2_buffer *src_vb, *dst_vb;
 
-       if (!ctx || !ctx->m2m_ctx)
+       if (!ctx || !ctx->fh.m2m_ctx)
                return;
 
-       src_vb = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
-       dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
+       src_vb = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+       dst_vb = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
 
        if (src_vb && dst_vb) {
                v4l2_m2m_buf_done(src_vb, vb_state);
                v4l2_m2m_buf_done(dst_vb, vb_state);
                v4l2_m2m_job_finish(ctx->fimc_dev->m2m.m2m_dev,
-                                   ctx->m2m_ctx);
+                                   ctx->fh.m2m_ctx);
        }
 }
 
@@ -123,12 +123,12 @@ static void fimc_device_run(void *priv)
                fimc_prepare_dma_offset(ctx, df);
        }
 
-       src_vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
+       src_vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
        ret = fimc_prepare_addr(ctx, src_vb, sf, &sf->paddr);
        if (ret)
                goto dma_unlock;
 
-       dst_vb = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+       dst_vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
        ret = fimc_prepare_addr(ctx, dst_vb, df, &df->paddr);
        if (ret)
                goto dma_unlock;
@@ -219,31 +219,15 @@ static int fimc_buf_prepare(struct vb2_buffer *vb)
 static void fimc_buf_queue(struct vb2_buffer *vb)
 {
        struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-
-       dbg("ctx: %p, ctx->state: 0x%x", ctx, ctx->state);
-
-       if (ctx->m2m_ctx)
-               v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
-}
-
-static void fimc_lock(struct vb2_queue *vq)
-{
-       struct fimc_ctx *ctx = vb2_get_drv_priv(vq);
-       mutex_lock(&ctx->fimc_dev->lock);
-}
-
-static void fimc_unlock(struct vb2_queue *vq)
-{
-       struct fimc_ctx *ctx = vb2_get_drv_priv(vq);
-       mutex_unlock(&ctx->fimc_dev->lock);
+       v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb);
 }
 
 static struct vb2_ops fimc_qops = {
        .queue_setup     = fimc_queue_setup,
        .buf_prepare     = fimc_buf_prepare,
        .buf_queue       = fimc_buf_queue,
-       .wait_prepare    = fimc_unlock,
-       .wait_finish     = fimc_lock,
+       .wait_prepare    = vb2_ops_wait_prepare,
+       .wait_finish     = vb2_ops_wait_finish,
        .stop_streaming  = stop_streaming,
        .start_streaming = start_streaming,
 };
@@ -385,7 +369,7 @@ static int fimc_m2m_s_fmt_mplane(struct file *file, void *fh,
        if (ret)
                return ret;
 
-       vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
+       vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
 
        if (vb2_is_busy(vq)) {
                v4l2_err(&fimc->m2m.vfd, "queue (%d) busy\n", f->type);
@@ -410,56 +394,6 @@ static int fimc_m2m_s_fmt_mplane(struct file *file, void *fh,
        return 0;
 }
 
-static int fimc_m2m_reqbufs(struct file *file, void *fh,
-                           struct v4l2_requestbuffers *reqbufs)
-{
-       struct fimc_ctx *ctx = fh_to_ctx(fh);
-       return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs);
-}
-
-static int fimc_m2m_querybuf(struct file *file, void *fh,
-                            struct v4l2_buffer *buf)
-{
-       struct fimc_ctx *ctx = fh_to_ctx(fh);
-       return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf);
-}
-
-static int fimc_m2m_qbuf(struct file *file, void *fh,
-                        struct v4l2_buffer *buf)
-{
-       struct fimc_ctx *ctx = fh_to_ctx(fh);
-       return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
-}
-
-static int fimc_m2m_dqbuf(struct file *file, void *fh,
-                         struct v4l2_buffer *buf)
-{
-       struct fimc_ctx *ctx = fh_to_ctx(fh);
-       return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
-}
-
-static int fimc_m2m_expbuf(struct file *file, void *fh,
-                           struct v4l2_exportbuffer *eb)
-{
-       struct fimc_ctx *ctx = fh_to_ctx(fh);
-       return v4l2_m2m_expbuf(file, ctx->m2m_ctx, eb);
-}
-
-
-static int fimc_m2m_streamon(struct file *file, void *fh,
-                            enum v4l2_buf_type type)
-{
-       struct fimc_ctx *ctx = fh_to_ctx(fh);
-       return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
-}
-
-static int fimc_m2m_streamoff(struct file *file, void *fh,
-                           enum v4l2_buf_type type)
-{
-       struct fimc_ctx *ctx = fh_to_ctx(fh);
-       return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
-}
-
 static int fimc_m2m_cropcap(struct file *file, void *fh,
                            struct v4l2_cropcap *cr)
 {
@@ -598,13 +532,13 @@ static const struct v4l2_ioctl_ops fimc_m2m_ioctl_ops = {
        .vidioc_try_fmt_vid_out_mplane  = fimc_m2m_try_fmt_mplane,
        .vidioc_s_fmt_vid_cap_mplane    = fimc_m2m_s_fmt_mplane,
        .vidioc_s_fmt_vid_out_mplane    = fimc_m2m_s_fmt_mplane,
-       .vidioc_reqbufs                 = fimc_m2m_reqbufs,
-       .vidioc_querybuf                = fimc_m2m_querybuf,
-       .vidioc_qbuf                    = fimc_m2m_qbuf,
-       .vidioc_dqbuf                   = fimc_m2m_dqbuf,
-       .vidioc_expbuf                  = fimc_m2m_expbuf,
-       .vidioc_streamon                = fimc_m2m_streamon,
-       .vidioc_streamoff               = fimc_m2m_streamoff,
+       .vidioc_reqbufs                 = v4l2_m2m_ioctl_reqbufs,
+       .vidioc_querybuf                = v4l2_m2m_ioctl_querybuf,
+       .vidioc_qbuf                    = v4l2_m2m_ioctl_qbuf,
+       .vidioc_dqbuf                   = v4l2_m2m_ioctl_dqbuf,
+       .vidioc_expbuf                  = v4l2_m2m_ioctl_expbuf,
+       .vidioc_streamon                = v4l2_m2m_ioctl_streamon,
+       .vidioc_streamoff               = v4l2_m2m_ioctl_streamoff,
        .vidioc_g_crop                  = fimc_m2m_g_crop,
        .vidioc_s_crop                  = fimc_m2m_s_crop,
        .vidioc_cropcap                 = fimc_m2m_cropcap
@@ -624,6 +558,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,
        src_vq->mem_ops = &vb2_dma_contig_memops;
        src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
        src_vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+       src_vq->lock = &ctx->fimc_dev->lock;
 
        ret = vb2_queue_init(src_vq);
        if (ret)
@@ -636,6 +571,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,
        dst_vq->mem_ops = &vb2_dma_contig_memops;
        dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
        dst_vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+       dst_vq->lock = &ctx->fimc_dev->lock;
 
        return vb2_queue_init(dst_vq);
 }
@@ -708,9 +644,9 @@ static int fimc_m2m_open(struct file *file)
        ctx->out_path = FIMC_IO_DMA;
        ctx->scaler.enabled = 1;
 
-       ctx->m2m_ctx = v4l2_m2m_ctx_init(fimc->m2m.m2m_dev, ctx, queue_init);
-       if (IS_ERR(ctx->m2m_ctx)) {
-               ret = PTR_ERR(ctx->m2m_ctx);
+       ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(fimc->m2m.m2m_dev, ctx, queue_init);
+       if (IS_ERR(ctx->fh.m2m_ctx)) {
+               ret = PTR_ERR(ctx->fh.m2m_ctx);
                goto error_c;
        }
 
@@ -725,7 +661,7 @@ static int fimc_m2m_open(struct file *file)
        return 0;
 
 error_m2m_ctx:
-       v4l2_m2m_ctx_release(ctx->m2m_ctx);
+       v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
 error_c:
        fimc_ctrls_delete(ctx);
 error_fh:
@@ -747,7 +683,7 @@ static int fimc_m2m_release(struct file *file)
 
        mutex_lock(&fimc->lock);
 
-       v4l2_m2m_ctx_release(ctx->m2m_ctx);
+       v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
        fimc_ctrls_delete(ctx);
        v4l2_fh_del(&ctx->fh);
        v4l2_fh_exit(&ctx->fh);
@@ -760,45 +696,13 @@ static int fimc_m2m_release(struct file *file)
        return 0;
 }
 
-static unsigned int fimc_m2m_poll(struct file *file,
-                                 struct poll_table_struct *wait)
-{
-       struct fimc_ctx *ctx = fh_to_ctx(file->private_data);
-       struct fimc_dev *fimc = ctx->fimc_dev;
-       int ret;
-
-       if (mutex_lock_interruptible(&fimc->lock))
-               return -ERESTARTSYS;
-
-       ret = v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
-       mutex_unlock(&fimc->lock);
-
-       return ret;
-}
-
-
-static int fimc_m2m_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       struct fimc_ctx *ctx = fh_to_ctx(file->private_data);
-       struct fimc_dev *fimc = ctx->fimc_dev;
-       int ret;
-
-       if (mutex_lock_interruptible(&fimc->lock))
-               return -ERESTARTSYS;
-
-       ret = v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
-       mutex_unlock(&fimc->lock);
-
-       return ret;
-}
-
 static const struct v4l2_file_operations fimc_m2m_fops = {
        .owner          = THIS_MODULE,
        .open           = fimc_m2m_open,
        .release        = fimc_m2m_release,
-       .poll           = fimc_m2m_poll,
+       .poll           = v4l2_m2m_fop_poll,
        .unlocked_ioctl = video_ioctl2,
-       .mmap           = fimc_m2m_mmap,
+       .mmap           = v4l2_m2m_fop_mmap,
 };
 
 static struct v4l2_m2m_ops m2m_ops = {
index 7a4ee4c0449deea95dc86e82a85af8412a1d5aad..c1bce170df6fbce44d519a498bf6d19694389306 100644 (file)
@@ -759,7 +759,7 @@ static int fimc_md_register_platform_entity(struct fimc_md *fmd,
                goto dev_unlock;
 
        drvdata = dev_get_drvdata(dev);
-       /* Some subdev didn't probe succesfully id drvdata is NULL */
+       /* Some subdev didn't probe successfully id drvdata is NULL */
        if (drvdata) {
                switch (plat_entity) {
                case IDX_FIMC:
index 9fc2af6a04466b402c6f931097e28dbdec2ad29c..31dfc501524797b943cb8d750a7fcd05b39d5d5c 100644 (file)
@@ -91,7 +91,7 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)");
 #define S5PCSIS_INTSRC_ODD_BEFORE      (1 << 29)
 #define S5PCSIS_INTSRC_ODD_AFTER       (1 << 28)
 #define S5PCSIS_INTSRC_ODD             (0x3 << 28)
-#define S5PCSIS_INTSRC_NON_IMAGE_DATA  (0xff << 28)
+#define S5PCSIS_INTSRC_NON_IMAGE_DATA  (0xf << 28)
 #define S5PCSIS_INTSRC_FRAME_START     (1 << 27)
 #define S5PCSIS_INTSRC_FRAME_END       (1 << 26)
 #define S5PCSIS_INTSRC_ERR_SOT_HS      (0xf << 12)
index 6a232239ee8c71f8c04d3c42c002af2c789fd9a8..dbf0ce38a8e7db1566d5ddde361f51d570fca03d 100644 (file)
@@ -1580,7 +1580,7 @@ static int viu_of_probe(struct platform_device *op)
        }
 
        /* enable VIU clock */
-       clk = devm_clk_get(&op->dev, "viu_clk");
+       clk = devm_clk_get(&op->dev, "ipg");
        if (IS_ERR(clk)) {
                dev_err(&op->dev, "failed to lookup the clock!\n");
                ret = PTR_ERR(clk);
index 3458fa0e2fd537916270fd9fbb0908d2b1610821..054507f16734de8c04c67fbda15d9afff60d6f11 100644 (file)
@@ -142,12 +142,6 @@ static int mmpcam_power_up(struct mcam_camera *mcam)
        struct mmp_camera *cam = mcam_to_cam(mcam);
        struct mmp_camera_platform_data *pdata;
 
-       if (mcam->bus_type == V4L2_MBUS_CSI2) {
-               cam->mipi_clk = devm_clk_get(mcam->dev, "mipi");
-               if ((IS_ERR(cam->mipi_clk) && mcam->dphy[2] == 0))
-                       return PTR_ERR(cam->mipi_clk);
-       }
-
 /*
  * Turn on power and clocks to the controller.
  */
@@ -186,12 +180,6 @@ static void mmpcam_power_down(struct mcam_camera *mcam)
        gpio_set_value(pdata->sensor_power_gpio, 0);
        gpio_set_value(pdata->sensor_reset_gpio, 0);
 
-       if (mcam->bus_type == V4L2_MBUS_CSI2 && !IS_ERR(cam->mipi_clk)) {
-               if (cam->mipi_clk)
-                       devm_clk_put(mcam->dev, cam->mipi_clk);
-               cam->mipi_clk = NULL;
-       }
-
        mcam_clk_disable(mcam);
 }
 
@@ -292,8 +280,9 @@ void mmpcam_calc_dphy(struct mcam_camera *mcam)
                return;
 
        /* get the escape clk, this is hard coded */
+       clk_prepare_enable(cam->mipi_clk);
        tx_clk_esc = (clk_get_rate(cam->mipi_clk) / 1000000) / 12;
-
+       clk_disable_unprepare(cam->mipi_clk);
        /*
         * dphy[2] - CSI2_DPHY6:
         * bit 0 ~ bit 7: CK Term Enable
@@ -325,19 +314,6 @@ static irqreturn_t mmpcam_irq(int irq, void *data)
        return IRQ_RETVAL(handled);
 }
 
-static void mcam_deinit_clk(struct mcam_camera *mcam)
-{
-       unsigned int i;
-
-       for (i = 0; i < NR_MCAM_CLK; i++) {
-               if (!IS_ERR(mcam->clk[i])) {
-                       if (mcam->clk[i])
-                               devm_clk_put(mcam->dev, mcam->clk[i]);
-               }
-               mcam->clk[i] = NULL;
-       }
-}
-
 static void mcam_init_clk(struct mcam_camera *mcam)
 {
        unsigned int i;
@@ -371,7 +347,6 @@ static int mmpcam_probe(struct platform_device *pdev)
        if (cam == NULL)
                return -ENOMEM;
        cam->pdev = pdev;
-       cam->mipi_clk = NULL;
        INIT_LIST_HEAD(&cam->devlist);
 
        mcam = &cam->mcam;
@@ -387,6 +362,11 @@ static int mmpcam_probe(struct platform_device *pdev)
        mcam->mclk_div = pdata->mclk_div;
        mcam->bus_type = pdata->bus_type;
        mcam->dphy = pdata->dphy;
+       if (mcam->bus_type == V4L2_MBUS_CSI2) {
+               cam->mipi_clk = devm_clk_get(mcam->dev, "mipi");
+               if ((IS_ERR(cam->mipi_clk) && mcam->dphy[2] == 0))
+                       return PTR_ERR(cam->mipi_clk);
+       }
        mcam->mipi_enabled = false;
        mcam->lane = pdata->lane;
        mcam->chip_id = MCAM_ARMADA610;
@@ -444,7 +424,7 @@ static int mmpcam_probe(struct platform_device *pdev)
         */
        ret = mmpcam_power_up(mcam);
        if (ret)
-               goto out_deinit_clk;
+               return ret;
        ret = mccic_register(mcam);
        if (ret)
                goto out_power_down;
@@ -469,8 +449,6 @@ out_unregister:
        mccic_shutdown(mcam);
 out_power_down:
        mmpcam_power_down(mcam);
-out_deinit_clk:
-       mcam_deinit_clk(mcam);
        return ret;
 }
 
@@ -478,18 +456,10 @@ out_deinit_clk:
 static int mmpcam_remove(struct mmp_camera *cam)
 {
        struct mcam_camera *mcam = &cam->mcam;
-       struct mmp_camera_platform_data *pdata;
 
        mmpcam_remove_device(cam);
        mccic_shutdown(mcam);
        mmpcam_power_down(mcam);
-       pdata = cam->pdev->dev.platform_data;
-       gpio_free(pdata->sensor_reset_gpio);
-       gpio_free(pdata->sensor_power_gpio);
-       mcam_deinit_clk(mcam);
-       iounmap(cam->power_regs);
-       iounmap(mcam->regs);
-       kfree(cam);
        return 0;
 }
 
index 8df5975b700a01c8f433fb902e1d10e2983de5aa..08e24379b7949af3a71f67123dd8749ce831c7aa 100644 (file)
@@ -177,8 +177,6 @@ struct m2mtest_ctx {
 
        enum v4l2_colorspace    colorspace;
 
-       struct v4l2_m2m_ctx     *m2m_ctx;
-
        /* Source and destination queue data */
        struct m2mtest_q_data   q_data[2];
 };
@@ -342,8 +340,8 @@ static int job_ready(void *priv)
 {
        struct m2mtest_ctx *ctx = priv;
 
-       if (v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) < ctx->translen
-           || v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) < ctx->translen) {
+       if (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) < ctx->translen
+           || v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx) < ctx->translen) {
                dprintk(ctx->dev, "Not enough buffers available\n");
                return 0;
        }
@@ -359,21 +357,6 @@ static void job_abort(void *priv)
        ctx->aborting = 1;
 }
 
-static void m2mtest_lock(void *priv)
-{
-       struct m2mtest_ctx *ctx = priv;
-       struct m2mtest_dev *dev = ctx->dev;
-       mutex_lock(&dev->dev_mutex);
-}
-
-static void m2mtest_unlock(void *priv)
-{
-       struct m2mtest_ctx *ctx = priv;
-       struct m2mtest_dev *dev = ctx->dev;
-       mutex_unlock(&dev->dev_mutex);
-}
-
-
 /* device_run() - prepares and starts the device
  *
  * This simulates all the immediate preparations required before starting
@@ -386,8 +369,8 @@ static void device_run(void *priv)
        struct m2mtest_dev *dev = ctx->dev;
        struct vb2_buffer *src_buf, *dst_buf;
 
-       src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
-       dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+       src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+       dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
 
        device_process(ctx, src_buf, dst_buf);
 
@@ -409,8 +392,8 @@ static void device_isr(unsigned long priv)
                return;
        }
 
-       src_vb = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx);
-       dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx);
+       src_vb = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
+       dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
 
        curr_ctx->num_processed++;
 
@@ -423,7 +406,7 @@ static void device_isr(unsigned long priv)
            || curr_ctx->aborting) {
                dprintk(curr_ctx->dev, "Finishing transaction\n");
                curr_ctx->num_processed = 0;
-               v4l2_m2m_job_finish(m2mtest_dev->m2m_dev, curr_ctx->m2m_ctx);
+               v4l2_m2m_job_finish(m2mtest_dev->m2m_dev, curr_ctx->fh.m2m_ctx);
        } else {
                device_run(curr_ctx);
        }
@@ -491,7 +474,7 @@ static int vidioc_g_fmt(struct m2mtest_ctx *ctx, struct v4l2_format *f)
        struct vb2_queue *vq;
        struct m2mtest_q_data *q_data;
 
-       vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
+       vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
        if (!vq)
                return -EINVAL;
 
@@ -594,7 +577,7 @@ static int vidioc_s_fmt(struct m2mtest_ctx *ctx, struct v4l2_format *f)
        struct m2mtest_q_data *q_data;
        struct vb2_queue *vq;
 
-       vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
+       vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
        if (!vq)
                return -EINVAL;
 
@@ -648,52 +631,6 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
        return ret;
 }
 
-static int vidioc_reqbufs(struct file *file, void *priv,
-                         struct v4l2_requestbuffers *reqbufs)
-{
-       struct m2mtest_ctx *ctx = file2ctx(file);
-
-       return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs);
-}
-
-static int vidioc_querybuf(struct file *file, void *priv,
-                          struct v4l2_buffer *buf)
-{
-       struct m2mtest_ctx *ctx = file2ctx(file);
-
-       return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf);
-}
-
-static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
-{
-       struct m2mtest_ctx *ctx = file2ctx(file);
-
-       return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
-}
-
-static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
-{
-       struct m2mtest_ctx *ctx = file2ctx(file);
-
-       return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
-}
-
-static int vidioc_streamon(struct file *file, void *priv,
-                          enum v4l2_buf_type type)
-{
-       struct m2mtest_ctx *ctx = file2ctx(file);
-
-       return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
-}
-
-static int vidioc_streamoff(struct file *file, void *priv,
-                           enum v4l2_buf_type type)
-{
-       struct m2mtest_ctx *ctx = file2ctx(file);
-
-       return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
-}
-
 static int m2mtest_s_ctrl(struct v4l2_ctrl *ctrl)
 {
        struct m2mtest_ctx *ctx =
@@ -748,14 +685,14 @@ static const struct v4l2_ioctl_ops m2mtest_ioctl_ops = {
        .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out,
        .vidioc_s_fmt_vid_out   = vidioc_s_fmt_vid_out,
 
-       .vidioc_reqbufs         = vidioc_reqbufs,
-       .vidioc_querybuf        = vidioc_querybuf,
+       .vidioc_reqbufs         = v4l2_m2m_ioctl_reqbufs,
+       .vidioc_querybuf        = v4l2_m2m_ioctl_querybuf,
+       .vidioc_qbuf            = v4l2_m2m_ioctl_qbuf,
+       .vidioc_dqbuf           = v4l2_m2m_ioctl_dqbuf,
 
-       .vidioc_qbuf            = vidioc_qbuf,
-       .vidioc_dqbuf           = vidioc_dqbuf,
+       .vidioc_streamon        = v4l2_m2m_ioctl_streamon,
+       .vidioc_streamoff       = v4l2_m2m_ioctl_streamoff,
 
-       .vidioc_streamon        = vidioc_streamon,
-       .vidioc_streamoff       = vidioc_streamoff,
        .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
        .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
 };
@@ -818,27 +755,15 @@ static int m2mtest_buf_prepare(struct vb2_buffer *vb)
 static void m2mtest_buf_queue(struct vb2_buffer *vb)
 {
        struct m2mtest_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-       v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
-}
-
-static void m2mtest_wait_prepare(struct vb2_queue *q)
-{
-       struct m2mtest_ctx *ctx = vb2_get_drv_priv(q);
-       m2mtest_unlock(ctx);
-}
-
-static void m2mtest_wait_finish(struct vb2_queue *q)
-{
-       struct m2mtest_ctx *ctx = vb2_get_drv_priv(q);
-       m2mtest_lock(ctx);
+       v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb);
 }
 
 static struct vb2_ops m2mtest_qops = {
        .queue_setup     = m2mtest_queue_setup,
        .buf_prepare     = m2mtest_buf_prepare,
        .buf_queue       = m2mtest_buf_queue,
-       .wait_prepare    = m2mtest_wait_prepare,
-       .wait_finish     = m2mtest_wait_finish,
+       .wait_prepare    = vb2_ops_wait_prepare,
+       .wait_finish     = vb2_ops_wait_finish,
 };
 
 static int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
@@ -853,6 +778,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *ds
        src_vq->ops = &m2mtest_qops;
        src_vq->mem_ops = &vb2_vmalloc_memops;
        src_vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+       src_vq->lock = &ctx->dev->dev_mutex;
 
        ret = vb2_queue_init(src_vq);
        if (ret)
@@ -865,6 +791,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *ds
        dst_vq->ops = &m2mtest_qops;
        dst_vq->mem_ops = &vb2_vmalloc_memops;
        dst_vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+       dst_vq->lock = &ctx->dev->dev_mutex;
 
        return vb2_queue_init(dst_vq);
 }
@@ -936,10 +863,10 @@ static int m2mtest_open(struct file *file)
        ctx->q_data[V4L2_M2M_DST] = ctx->q_data[V4L2_M2M_SRC];
        ctx->colorspace = V4L2_COLORSPACE_REC709;
 
-       ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init);
+       ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init);
 
-       if (IS_ERR(ctx->m2m_ctx)) {
-               rc = PTR_ERR(ctx->m2m_ctx);
+       if (IS_ERR(ctx->fh.m2m_ctx)) {
+               rc = PTR_ERR(ctx->fh.m2m_ctx);
 
                v4l2_ctrl_handler_free(hdl);
                kfree(ctx);
@@ -949,7 +876,8 @@ static int m2mtest_open(struct file *file)
        v4l2_fh_add(&ctx->fh);
        atomic_inc(&dev->num_inst);
 
-       dprintk(dev, "Created instance %p, m2m_ctx: %p\n", ctx, ctx->m2m_ctx);
+       dprintk(dev, "Created instance: %p, m2m_ctx: %p\n",
+               ctx, ctx->fh.m2m_ctx);
 
 open_unlock:
        mutex_unlock(&dev->dev_mutex);
@@ -967,7 +895,7 @@ static int m2mtest_release(struct file *file)
        v4l2_fh_exit(&ctx->fh);
        v4l2_ctrl_handler_free(&ctx->hdl);
        mutex_lock(&dev->dev_mutex);
-       v4l2_m2m_ctx_release(ctx->m2m_ctx);
+       v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
        mutex_unlock(&dev->dev_mutex);
        kfree(ctx);
 
@@ -976,34 +904,13 @@ static int m2mtest_release(struct file *file)
        return 0;
 }
 
-static unsigned int m2mtest_poll(struct file *file,
-                                struct poll_table_struct *wait)
-{
-       struct m2mtest_ctx *ctx = file2ctx(file);
-
-       return v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
-}
-
-static int m2mtest_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       struct m2mtest_dev *dev = video_drvdata(file);
-       struct m2mtest_ctx *ctx = file2ctx(file);
-       int res;
-
-       if (mutex_lock_interruptible(&dev->dev_mutex))
-               return -ERESTARTSYS;
-       res = v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
-       mutex_unlock(&dev->dev_mutex);
-       return res;
-}
-
 static const struct v4l2_file_operations m2mtest_fops = {
        .owner          = THIS_MODULE,
        .open           = m2mtest_open,
        .release        = m2mtest_release,
-       .poll           = m2mtest_poll,
+       .poll           = v4l2_m2m_fop_poll,
        .unlocked_ioctl = video_ioctl2,
-       .mmap           = m2mtest_mmap,
+       .mmap           = v4l2_m2m_fop_mmap,
 };
 
 static struct video_device m2mtest_videodev = {
@@ -1019,8 +926,6 @@ static struct v4l2_m2m_ops m2m_ops = {
        .device_run     = device_run,
        .job_ready      = job_ready,
        .job_abort      = job_abort,
-       .lock           = m2mtest_lock,
-       .unlock         = m2mtest_unlock,
 };
 
 static int m2mtest_probe(struct platform_device *pdev)
@@ -1133,4 +1038,3 @@ static int __init m2mtest_init(void)
 
 module_init(m2mtest_init);
 module_exit(m2mtest_exit);
-
index 1c3608039663e281d23541f17aedcbce044c87fb..561bce8ffb1b57c87dd1b45bbae6cbf7c2b479c1 100644 (file)
@@ -1673,7 +1673,7 @@ void omap3isp_print_status(struct isp_device *isp)
  * ISP clocks get disabled in suspend(). Similarly, the clocks are reenabled in
  * resume(), and the the pipelines are restarted in complete().
  *
- * TODO: PM dependencies between the ISP and sensors are not modeled explicitly
+ * TODO: PM dependencies between the ISP and sensors are not modelled explicitly
  * yet.
  */
 static int isp_pm_prepare(struct device *dev)
index 907a205da5a55d977fe39e40c7b612315578e996..561c991529e6f723510baf9744bfc34d94822e52 100644 (file)
@@ -2484,7 +2484,8 @@ static int ccdc_init_entities(struct isp_ccdc_device *ccdc)
        v4l2_set_subdevdata(sd, ccdc);
        sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
 
-       pads[CCDC_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+       pads[CCDC_PAD_SINK].flags = MEDIA_PAD_FL_SINK
+                                   | MEDIA_PAD_FL_MUST_CONNECT;
        pads[CCDC_PAD_SOURCE_VP].flags = MEDIA_PAD_FL_SOURCE;
        pads[CCDC_PAD_SOURCE_OF].flags = MEDIA_PAD_FL_SOURCE;
 
index e71651429ddad36523943d4f61c0ca89caaa5bb9..e84fe0543e4719424c3224895ed7b5a218ea8904 100644 (file)
@@ -1076,7 +1076,8 @@ static int ccp2_init_entities(struct isp_ccp2_device *ccp2)
        v4l2_set_subdevdata(sd, ccp2);
        sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
 
-       pads[CCP2_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+       pads[CCP2_PAD_SINK].flags = MEDIA_PAD_FL_SINK
+                                   | MEDIA_PAD_FL_MUST_CONNECT;
        pads[CCP2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
 
        me->ops = &ccp2_media_ops;
index 6db245d84bbbe5f8e27bc9fb1555e2bdf0f20d0d..620560828a48cc9d395bfba0ddbb2c7f017ed84b 100644 (file)
@@ -1245,7 +1245,8 @@ static int csi2_init_entities(struct isp_csi2_device *csi2)
        sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
 
        pads[CSI2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
-       pads[CSI2_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+       pads[CSI2_PAD_SINK].flags = MEDIA_PAD_FL_SINK
+                                   | MEDIA_PAD_FL_MUST_CONNECT;
 
        me->ops = &csi2_media_ops;
        ret = media_entity_init(me, CSI2_PADS_NUM, pads, 0);
index cd8831aebdebdfe80d74bf599dcef02f3db7bbaa..1c776c1186f1b9ff4a4ddbb79b6cb48c88e196f4 100644 (file)
@@ -2283,7 +2283,8 @@ static int preview_init_entities(struct isp_prev_device *prev)
        v4l2_ctrl_handler_setup(&prev->ctrls);
        sd->ctrl_handler = &prev->ctrls;
 
-       pads[PREV_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+       pads[PREV_PAD_SINK].flags = MEDIA_PAD_FL_SINK
+                                   | MEDIA_PAD_FL_MUST_CONNECT;
        pads[PREV_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
 
        me->ops = &preview_media_ops;
index d11fb261d53070a131b4a3fbbd6cd2195bb3f574..0d36b8bc9f9806b1360d0a7482f2fe446fc70e4e 100644 (file)
@@ -1532,6 +1532,20 @@ static int resizer_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        return 0;
 }
 
+static int resizer_link_validate(struct v4l2_subdev *sd,
+                                struct media_link *link,
+                                struct v4l2_subdev_format *source_fmt,
+                                struct v4l2_subdev_format *sink_fmt)
+{
+       struct isp_res_device *res = v4l2_get_subdevdata(sd);
+       struct isp_pipeline *pipe = to_isp_pipeline(&sd->entity);
+
+       omap3isp_resizer_max_rate(res, &pipe->max_rate);
+
+       return v4l2_subdev_link_validate_default(sd, link,
+                                                source_fmt, sink_fmt);
+}
+
 /*
  * resizer_init_formats - Initialize formats on all pads
  * @sd: ISP resizer V4L2 subdevice
@@ -1570,6 +1584,7 @@ static const struct v4l2_subdev_pad_ops resizer_v4l2_pad_ops = {
        .set_fmt = resizer_set_format,
        .get_selection = resizer_get_selection,
        .set_selection = resizer_set_selection,
+       .link_validate = resizer_link_validate,
 };
 
 /* subdev operations */
@@ -1701,7 +1716,8 @@ static int resizer_init_entities(struct isp_res_device *res)
        v4l2_set_subdevdata(sd, res);
        sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
 
-       pads[RESZ_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+       pads[RESZ_PAD_SINK].flags = MEDIA_PAD_FL_SINK
+                                   | MEDIA_PAD_FL_MUST_CONNECT;
        pads[RESZ_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
 
        me->ops = &resizer_media_ops;
index 61e17f9bd8b92148457a45e973aefdb0487dbcec..a75407c3a726217981d40193b89919332a7919bf 100644 (file)
@@ -1067,7 +1067,7 @@ static int isp_stat_init_entities(struct ispstat *stat, const char *name,
        subdev->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
        v4l2_set_subdevdata(subdev, stat);
 
-       stat->pad.flags = MEDIA_PAD_FL_SINK;
+       stat->pad.flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT;
        me->ops = NULL;
 
        return media_entity_init(me, 1, &stat->pad, 0);
index a908d006f5277c2abe9adebcbb757ea699495fbf..3953aec7c5c5954efbf6a3aedddc110bd6105a13 100644 (file)
@@ -278,55 +278,6 @@ static int isp_video_get_graph_data(struct isp_video *video,
        return 0;
 }
 
-/*
- * Validate a pipeline by checking both ends of all links for format
- * discrepancies.
- *
- * Compute the minimum time per frame value as the maximum of time per frame
- * limits reported by every block in the pipeline.
- *
- * Return 0 if all formats match, or -EPIPE if at least one link is found with
- * different formats on its two ends or if the pipeline doesn't start with a
- * video source (either a subdev with no input pad, or a non-subdev entity).
- */
-static int isp_video_validate_pipeline(struct isp_pipeline *pipe)
-{
-       struct isp_device *isp = pipe->output->isp;
-       struct media_pad *pad;
-       struct v4l2_subdev *subdev;
-
-       subdev = isp_video_remote_subdev(pipe->output, NULL);
-       if (subdev == NULL)
-               return -EPIPE;
-
-       while (1) {
-               /* Retrieve the sink format */
-               pad = &subdev->entity.pads[0];
-               if (!(pad->flags & MEDIA_PAD_FL_SINK))
-                       break;
-
-               /* Update the maximum frame rate */
-               if (subdev == &isp->isp_res.subdev)
-                       omap3isp_resizer_max_rate(&isp->isp_res,
-                                                 &pipe->max_rate);
-
-               /* Retrieve the source format. Return an error if no source
-                * entity can be found, and stop checking the pipeline if the
-                * source entity isn't a subdev.
-                */
-               pad = media_entity_remote_pad(pad);
-               if (pad == NULL)
-                       return -EPIPE;
-
-               if (media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
-                       break;
-
-               subdev = media_entity_to_v4l2_subdev(pad->entity);
-       }
-
-       return 0;
-}
-
 static int
 __isp_video_get_format(struct isp_video *video, struct v4l2_format *format)
 {
@@ -339,14 +290,11 @@ __isp_video_get_format(struct isp_video *video, struct v4l2_format *format)
        if (subdev == NULL)
                return -EINVAL;
 
-       mutex_lock(&video->mutex);
-
        fmt.pad = pad;
        fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
-       ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
-       if (ret == -ENOIOCTLCMD)
-               ret = -EINVAL;
 
+       mutex_lock(&video->mutex);
+       ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
        mutex_unlock(&video->mutex);
 
        if (ret)
@@ -1054,11 +1002,6 @@ isp_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
        if (ret < 0)
                goto err_check_format;
 
-       /* Validate the pipeline and update its state. */
-       ret = isp_video_validate_pipeline(pipe);
-       if (ret < 0)
-               goto err_check_format;
-
        pipe->error = false;
 
        spin_lock_irqsave(&pipe->lock, flags);
@@ -1335,11 +1278,13 @@ int omap3isp_video_init(struct isp_video *video, const char *name)
        switch (video->type) {
        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
                direction = "output";
-               video->pad.flags = MEDIA_PAD_FL_SINK;
+               video->pad.flags = MEDIA_PAD_FL_SINK
+                                  | MEDIA_PAD_FL_MUST_CONNECT;
                break;
        case V4L2_BUF_TYPE_VIDEO_OUTPUT:
                direction = "input";
-               video->pad.flags = MEDIA_PAD_FL_SOURCE;
+               video->pad.flags = MEDIA_PAD_FL_SOURCE
+                                  | MEDIA_PAD_FL_MUST_CONNECT;
                video->video.vfl_dir = VFL_DIR_TX;
                break;
 
index 0b2948376aee9d3715c67d97346d6e775d48ab48..0fcf7d75e841b550d24df8faa9d247ce846d2044 100644 (file)
@@ -136,10 +136,9 @@ static int g2d_buf_prepare(struct vb2_buffer *vb)
 static void g2d_buf_queue(struct vb2_buffer *vb)
 {
        struct g2d_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-       v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
+       v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb);
 }
 
-
 static struct vb2_ops g2d_qops = {
        .queue_setup    = g2d_queue_setup,
        .buf_prepare    = g2d_buf_prepare,
@@ -159,6 +158,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,
        src_vq->mem_ops = &vb2_dma_contig_memops;
        src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
        src_vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+       src_vq->lock = &ctx->dev->mutex;
 
        ret = vb2_queue_init(src_vq);
        if (ret)
@@ -171,6 +171,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,
        dst_vq->mem_ops = &vb2_dma_contig_memops;
        dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
        dst_vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+       dst_vq->lock = &ctx->dev->mutex;
 
        return vb2_queue_init(dst_vq);
 }
@@ -253,9 +254,9 @@ static int g2d_open(struct file *file)
                kfree(ctx);
                return -ERESTARTSYS;
        }
-       ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init);
-       if (IS_ERR(ctx->m2m_ctx)) {
-               ret = PTR_ERR(ctx->m2m_ctx);
+       ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init);
+       if (IS_ERR(ctx->fh.m2m_ctx)) {
+               ret = PTR_ERR(ctx->fh.m2m_ctx);
                mutex_unlock(&dev->mutex);
                kfree(ctx);
                return ret;
@@ -324,7 +325,7 @@ static int vidioc_g_fmt(struct file *file, void *prv, struct v4l2_format *f)
        struct vb2_queue *vq;
        struct g2d_frame *frm;
 
-       vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
+       vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
        if (!vq)
                return -EINVAL;
        frm = get_frame(ctx, f->type);
@@ -384,7 +385,7 @@ static int vidioc_s_fmt(struct file *file, void *prv, struct v4l2_format *f)
        ret = vidioc_try_fmt(file, prv, f);
        if (ret)
                return ret;
-       vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
+       vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
        if (vb2_is_busy(vq)) {
                v4l2_err(&dev->v4l2_dev, "queue (%d) bust\n", f->type);
                return -EBUSY;
@@ -410,72 +411,6 @@ static int vidioc_s_fmt(struct file *file, void *prv, struct v4l2_format *f)
        return 0;
 }
 
-static unsigned int g2d_poll(struct file *file, struct poll_table_struct *wait)
-{
-       struct g2d_ctx *ctx = fh2ctx(file->private_data);
-       struct g2d_dev *dev = ctx->dev;
-       unsigned int res;
-
-       mutex_lock(&dev->mutex);
-       res = v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
-       mutex_unlock(&dev->mutex);
-       return res;
-}
-
-static int g2d_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       struct g2d_ctx *ctx = fh2ctx(file->private_data);
-       struct g2d_dev *dev = ctx->dev;
-       int ret;
-
-       if (mutex_lock_interruptible(&dev->mutex))
-               return -ERESTARTSYS;
-       ret = v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
-       mutex_unlock(&dev->mutex);
-       return ret;
-}
-
-static int vidioc_reqbufs(struct file *file, void *priv,
-                       struct v4l2_requestbuffers *reqbufs)
-{
-       struct g2d_ctx *ctx = priv;
-       return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs);
-}
-
-static int vidioc_querybuf(struct file *file, void *priv,
-                       struct v4l2_buffer *buf)
-{
-       struct g2d_ctx *ctx = priv;
-       return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf);
-}
-
-static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
-{
-       struct g2d_ctx *ctx = priv;
-       return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
-}
-
-static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
-{
-       struct g2d_ctx *ctx = priv;
-       return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
-}
-
-
-static int vidioc_streamon(struct file *file, void *priv,
-                                       enum v4l2_buf_type type)
-{
-       struct g2d_ctx *ctx = priv;
-       return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
-}
-
-static int vidioc_streamoff(struct file *file, void *priv,
-                                       enum v4l2_buf_type type)
-{
-       struct g2d_ctx *ctx = priv;
-       return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
-}
-
 static int vidioc_cropcap(struct file *file, void *priv,
                                        struct v4l2_cropcap *cr)
 {
@@ -551,20 +486,6 @@ static int vidioc_s_crop(struct file *file, void *prv, const struct v4l2_crop *c
        return 0;
 }
 
-static void g2d_lock(void *prv)
-{
-       struct g2d_ctx *ctx = prv;
-       struct g2d_dev *dev = ctx->dev;
-       mutex_lock(&dev->mutex);
-}
-
-static void g2d_unlock(void *prv)
-{
-       struct g2d_ctx *ctx = prv;
-       struct g2d_dev *dev = ctx->dev;
-       mutex_unlock(&dev->mutex);
-}
-
 static void job_abort(void *prv)
 {
        struct g2d_ctx *ctx = prv;
@@ -589,8 +510,8 @@ static void device_run(void *prv)
 
        dev->curr = ctx;
 
-       src = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
-       dst = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+       src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+       dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
 
        clk_enable(dev->gate);
        g2d_reset(dev);
@@ -631,8 +552,8 @@ static irqreturn_t g2d_isr(int irq, void *prv)
 
        BUG_ON(ctx == NULL);
 
-       src = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
-       dst = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
+       src = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+       dst = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
 
        BUG_ON(src == NULL);
        BUG_ON(dst == NULL);
@@ -642,7 +563,7 @@ static irqreturn_t g2d_isr(int irq, void *prv)
 
        v4l2_m2m_buf_done(src, VB2_BUF_STATE_DONE);
        v4l2_m2m_buf_done(dst, VB2_BUF_STATE_DONE);
-       v4l2_m2m_job_finish(dev->m2m_dev, ctx->m2m_ctx);
+       v4l2_m2m_job_finish(dev->m2m_dev, ctx->fh.m2m_ctx);
 
        dev->curr = NULL;
        wake_up(&dev->irq_queue);
@@ -653,9 +574,9 @@ static const struct v4l2_file_operations g2d_fops = {
        .owner          = THIS_MODULE,
        .open           = g2d_open,
        .release        = g2d_release,
-       .poll           = g2d_poll,
+       .poll           = v4l2_m2m_fop_poll,
        .unlocked_ioctl = video_ioctl2,
-       .mmap           = g2d_mmap,
+       .mmap           = v4l2_m2m_fop_mmap,
 };
 
 static const struct v4l2_ioctl_ops g2d_ioctl_ops = {
@@ -671,14 +592,13 @@ static const struct v4l2_ioctl_ops g2d_ioctl_ops = {
        .vidioc_try_fmt_vid_out         = vidioc_try_fmt,
        .vidioc_s_fmt_vid_out           = vidioc_s_fmt,
 
-       .vidioc_reqbufs                 = vidioc_reqbufs,
-       .vidioc_querybuf                = vidioc_querybuf,
-
-       .vidioc_qbuf                    = vidioc_qbuf,
-       .vidioc_dqbuf                   = vidioc_dqbuf,
+       .vidioc_reqbufs                 = v4l2_m2m_ioctl_reqbufs,
+       .vidioc_querybuf                = v4l2_m2m_ioctl_querybuf,
+       .vidioc_qbuf                    = v4l2_m2m_ioctl_qbuf,
+       .vidioc_dqbuf                   = v4l2_m2m_ioctl_dqbuf,
 
-       .vidioc_streamon                = vidioc_streamon,
-       .vidioc_streamoff               = vidioc_streamoff,
+       .vidioc_streamon                = v4l2_m2m_ioctl_streamon,
+       .vidioc_streamoff               = v4l2_m2m_ioctl_streamoff,
 
        .vidioc_g_crop                  = vidioc_g_crop,
        .vidioc_s_crop                  = vidioc_s_crop,
@@ -697,8 +617,6 @@ static struct video_device g2d_videodev = {
 static struct v4l2_m2m_ops g2d_m2m_ops = {
        .device_run     = device_run,
        .job_abort      = job_abort,
-       .lock           = g2d_lock,
-       .unlock         = g2d_unlock,
 };
 
 static const struct of_device_id exynos_g2d_match[];
index 300ca05ba40438f944f2651d2feccd58279eb1c1..b0e52ab7ecdb806b102a51497c2f29303fd5772e 100644 (file)
@@ -57,7 +57,6 @@ struct g2d_frame {
 struct g2d_ctx {
        struct v4l2_fh fh;
        struct g2d_dev          *dev;
-       struct v4l2_m2m_ctx     *m2m_ctx;
        struct g2d_frame        in;
        struct g2d_frame        out;
        struct v4l2_ctrl        *ctrl_hflip;
index 9b88a46010072fbe3b4aeefa46bbc8ee0f04ea7e..c818cbe6dd5d8f0ff688e866caf4603d87f70c0d 100644 (file)
@@ -316,9 +316,9 @@ static int s5p_jpeg_open(struct file *file)
        if (ret < 0)
                goto error;
 
-       ctx->m2m_ctx = v4l2_m2m_ctx_init(jpeg->m2m_dev, ctx, queue_init);
-       if (IS_ERR(ctx->m2m_ctx)) {
-               ret = PTR_ERR(ctx->m2m_ctx);
+       ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(jpeg->m2m_dev, ctx, queue_init);
+       if (IS_ERR(ctx->fh.m2m_ctx)) {
+               ret = PTR_ERR(ctx->fh.m2m_ctx);
                goto error;
        }
 
@@ -342,7 +342,7 @@ static int s5p_jpeg_release(struct file *file)
        struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data);
 
        mutex_lock(&jpeg->lock);
-       v4l2_m2m_ctx_release(ctx->m2m_ctx);
+       v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
        mutex_unlock(&jpeg->lock);
        v4l2_ctrl_handler_free(&ctx->ctrl_handler);
        v4l2_fh_del(&ctx->fh);
@@ -352,39 +352,13 @@ static int s5p_jpeg_release(struct file *file)
        return 0;
 }
 
-static unsigned int s5p_jpeg_poll(struct file *file,
-                                struct poll_table_struct *wait)
-{
-       struct s5p_jpeg *jpeg = video_drvdata(file);
-       struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data);
-       unsigned int res;
-
-       mutex_lock(&jpeg->lock);
-       res = v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
-       mutex_unlock(&jpeg->lock);
-       return res;
-}
-
-static int s5p_jpeg_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       struct s5p_jpeg *jpeg = video_drvdata(file);
-       struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data);
-       int ret;
-
-       if (mutex_lock_interruptible(&jpeg->lock))
-               return -ERESTARTSYS;
-       ret = v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
-       mutex_unlock(&jpeg->lock);
-       return ret;
-}
-
 static const struct v4l2_file_operations s5p_jpeg_fops = {
        .owner          = THIS_MODULE,
        .open           = s5p_jpeg_open,
        .release        = s5p_jpeg_release,
-       .poll           = s5p_jpeg_poll,
+       .poll           = v4l2_m2m_fop_poll,
        .unlocked_ioctl = video_ioctl2,
-       .mmap           = s5p_jpeg_mmap,
+       .mmap           = v4l2_m2m_fop_mmap,
 };
 
 /*
@@ -589,7 +563,7 @@ static int s5p_jpeg_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
        struct v4l2_pix_format *pix = &f->fmt.pix;
        struct s5p_jpeg_ctx *ct = fh_to_ctx(priv);
 
-       vq = v4l2_m2m_get_vq(ct->m2m_ctx, f->type);
+       vq = v4l2_m2m_get_vq(ct->fh.m2m_ctx, f->type);
        if (!vq)
                return -EINVAL;
 
@@ -745,7 +719,7 @@ static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f)
        struct s5p_jpeg_q_data *q_data = NULL;
        struct v4l2_pix_format *pix = &f->fmt.pix;
 
-       vq = v4l2_m2m_get_vq(ct->m2m_ctx, f->type);
+       vq = v4l2_m2m_get_vq(ct->fh.m2m_ctx, f->type);
        if (!vq)
                return -EINVAL;
 
@@ -792,53 +766,6 @@ static int s5p_jpeg_s_fmt_vid_out(struct file *file, void *priv,
        return s5p_jpeg_s_fmt(fh_to_ctx(priv), f);
 }
 
-static int s5p_jpeg_reqbufs(struct file *file, void *priv,
-                         struct v4l2_requestbuffers *reqbufs)
-{
-       struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
-
-       return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs);
-}
-
-static int s5p_jpeg_querybuf(struct file *file, void *priv,
-                          struct v4l2_buffer *buf)
-{
-       struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
-
-       return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf);
-}
-
-static int s5p_jpeg_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
-{
-       struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
-
-       return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
-}
-
-static int s5p_jpeg_dqbuf(struct file *file, void *priv,
-                         struct v4l2_buffer *buf)
-{
-       struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
-
-       return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
-}
-
-static int s5p_jpeg_streamon(struct file *file, void *priv,
-                          enum v4l2_buf_type type)
-{
-       struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
-
-       return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
-}
-
-static int s5p_jpeg_streamoff(struct file *file, void *priv,
-                           enum v4l2_buf_type type)
-{
-       struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
-
-       return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
-}
-
 static int s5p_jpeg_g_selection(struct file *file, void *priv,
                         struct v4l2_selection *s)
 {
@@ -972,14 +899,13 @@ static const struct v4l2_ioctl_ops s5p_jpeg_ioctl_ops = {
        .vidioc_s_fmt_vid_cap           = s5p_jpeg_s_fmt_vid_cap,
        .vidioc_s_fmt_vid_out           = s5p_jpeg_s_fmt_vid_out,
 
-       .vidioc_reqbufs                 = s5p_jpeg_reqbufs,
-       .vidioc_querybuf                = s5p_jpeg_querybuf,
+       .vidioc_reqbufs                 = v4l2_m2m_ioctl_reqbufs,
+       .vidioc_querybuf                = v4l2_m2m_ioctl_querybuf,
+       .vidioc_qbuf                    = v4l2_m2m_ioctl_qbuf,
+       .vidioc_dqbuf                   = v4l2_m2m_ioctl_dqbuf,
 
-       .vidioc_qbuf                    = s5p_jpeg_qbuf,
-       .vidioc_dqbuf                   = s5p_jpeg_dqbuf,
-
-       .vidioc_streamon                = s5p_jpeg_streamon,
-       .vidioc_streamoff               = s5p_jpeg_streamoff,
+       .vidioc_streamon                = v4l2_m2m_ioctl_streamon,
+       .vidioc_streamoff               = v4l2_m2m_ioctl_streamoff,
 
        .vidioc_g_selection             = s5p_jpeg_g_selection,
 };
@@ -997,8 +923,8 @@ static void s5p_jpeg_device_run(void *priv)
        struct vb2_buffer *src_buf, *dst_buf;
        unsigned long src_addr, dst_addr;
 
-       src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
-       dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+       src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+       dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
        src_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
        dst_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
 
@@ -1170,22 +1096,8 @@ static void s5p_jpeg_buf_queue(struct vb2_buffer *vb)
                                      );
                q_data->size = q_data->w * q_data->h * q_data->fmt->depth >> 3;
        }
-       if (ctx->m2m_ctx)
-               v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
-}
-
-static void s5p_jpeg_wait_prepare(struct vb2_queue *vq)
-{
-       struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vq);
-
-       mutex_unlock(&ctx->jpeg->lock);
-}
-
-static void s5p_jpeg_wait_finish(struct vb2_queue *vq)
-{
-       struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vq);
 
-       mutex_lock(&ctx->jpeg->lock);
+       v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb);
 }
 
 static int s5p_jpeg_start_streaming(struct vb2_queue *q, unsigned int count)
@@ -1211,8 +1123,8 @@ static struct vb2_ops s5p_jpeg_qops = {
        .queue_setup            = s5p_jpeg_queue_setup,
        .buf_prepare            = s5p_jpeg_buf_prepare,
        .buf_queue              = s5p_jpeg_buf_queue,
-       .wait_prepare           = s5p_jpeg_wait_prepare,
-       .wait_finish            = s5p_jpeg_wait_finish,
+       .wait_prepare           = vb2_ops_wait_prepare,
+       .wait_finish            = vb2_ops_wait_finish,
        .start_streaming        = s5p_jpeg_start_streaming,
        .stop_streaming         = s5p_jpeg_stop_streaming,
 };
@@ -1230,6 +1142,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,
        src_vq->ops = &s5p_jpeg_qops;
        src_vq->mem_ops = &vb2_dma_contig_memops;
        src_vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+       src_vq->lock = &ctx->jpeg->lock;
 
        ret = vb2_queue_init(src_vq);
        if (ret)
@@ -1242,6 +1155,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,
        dst_vq->ops = &s5p_jpeg_qops;
        dst_vq->mem_ops = &vb2_dma_contig_memops;
        dst_vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+       dst_vq->lock = &ctx->jpeg->lock;
 
        return vb2_queue_init(dst_vq);
 }
@@ -1267,8 +1181,8 @@ static irqreturn_t s5p_jpeg_irq(int irq, void *dev_id)
 
        curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
 
-       src_buf = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx);
-       dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx);
+       src_buf = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
+       dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
 
        if (curr_ctx->mode == S5P_JPEG_ENCODE)
                enc_jpeg_too_large = jpeg_enc_stream_stat(jpeg->regs);
@@ -1296,7 +1210,7 @@ static irqreturn_t s5p_jpeg_irq(int irq, void *dev_id)
        if (curr_ctx->mode == S5P_JPEG_ENCODE)
                vb2_set_plane_payload(dst_buf, 0, payload_size);
        v4l2_m2m_buf_done(dst_buf, state);
-       v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->m2m_ctx);
+       v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx);
 
        curr_ctx->subsampling = jpeg_get_subsampling_mode(jpeg->regs);
        spin_unlock(&jpeg->slock);
index 8a4013e3aee7717afb9275f36c92f83fde479b30..4a4776b7e1d42e3404b793245248d4f3cd9a1ace 100644 (file)
@@ -115,7 +115,6 @@ struct s5p_jpeg_q_data {
  * @jpeg:              JPEG IP device for this context
  * @mode:              compression (encode) operation or decompression (decode)
  * @compr_quality:     destination image quality in compression (encode) mode
- * @m2m_ctx:           mem2mem device context
  * @out_q:             source (output) queue information
  * @cap_fmt:           destination (capture) queue queue information
  * @hdr_parsed:                set if header has been parsed during decompression
@@ -127,7 +126,6 @@ struct s5p_jpeg_ctx {
        unsigned short          compr_quality;
        unsigned short          restart_interval;
        unsigned short          subsampling;
-       struct v4l2_m2m_ctx     *m2m_ctx;
        struct s5p_jpeg_q_data  out_q;
        struct s5p_jpeg_q_data  cap_q;
        struct v4l2_fh          fh;
index 9319e93599ae5731241b58535583bc1a04b77e73..6ccc3f8c122add705d7338d0656ac744331823fb 100644 (file)
 #define S5P_FIMV_R2H_CMD_EDFU_INIT_RET         16
 #define S5P_FIMV_R2H_CMD_ERR_RET               32
 
-/* Dummy definition for MFCv6 compatibilty */
+/* Dummy definition for MFCv6 compatibility */
 #define S5P_FIMV_CODEC_H264_MVC_DEC            -1
 #define S5P_FIMV_R2H_CMD_FIELD_DONE_RET                -1
 #define S5P_FIMV_MFC_RESET                     -1
index 5f2c4ad6c2cb3427835ed2f40ec9ba5432ae3221..e46067a5785307ac7a1381bd8a8babd8e4ec4fc2 100644 (file)
@@ -239,7 +239,7 @@ static void s5p_mfc_handle_frame_copy_time(struct s5p_mfc_ctx *ctx)
        frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_dec_frame_type, dev);
 
        /* Copy timestamp / timecode from decoded src to dst and set
-          appropraite flags */
+          appropriate flags */
        src_buf = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
        list_for_each_entry(dst_buf, &ctx->dst_queue, list) {
                if (vb2_dma_contig_plane_dma_addr(dst_buf->b, 0) == dec_y_addr) {
@@ -428,7 +428,7 @@ static void s5p_mfc_handle_error(struct s5p_mfc_dev *dev,
                case MFCINST_FINISHING:
                case MFCINST_FINISHED:
                case MFCINST_RUNNING:
-                       /* It is higly probable that an error occured
+                       /* It is highly probable that an error occurred
                         * while decoding a frame */
                        clear_work_bit(ctx);
                        ctx->state = MFCINST_ERROR;
@@ -611,7 +611,7 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv)
        mfc_debug(1, "Int reason: %d (err: %08x)\n", reason, err);
        switch (reason) {
        case S5P_MFC_R2H_CMD_ERR_RET:
-               /* An error has occured */
+               /* An error has occurred */
                if (ctx->state == MFCINST_RUNNING &&
                        s5p_mfc_hw_call(dev->mfc_ops, err_dec, err) >=
                                dev->warn_start)
@@ -840,7 +840,7 @@ static int s5p_mfc_open(struct file *file)
        mutex_unlock(&dev->mfc_mutex);
        mfc_debug_leave();
        return ret;
-       /* Deinit when failure occured */
+       /* Deinit when failure occurred */
 err_queue_init:
        if (dev->num_inst == 1)
                s5p_mfc_deinit_hw(dev);
@@ -881,14 +881,14 @@ static int s5p_mfc_release(struct file *file)
        /* Mark context as idle */
        clear_work_bit_irqsave(ctx);
        /* If instance was initialised then
-        * return instance and free reosurces */
+        * return instance and free resources */
        if (ctx->inst_no != MFC_NO_INSTANCE_SET) {
                mfc_debug(2, "Has to free instance\n");
                ctx->state = MFCINST_RETURN_INST;
                set_work_bit_irqsave(ctx);
                s5p_mfc_clean_ctx_int_flags(ctx);
                s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
-               /* Wait until instance is returned or timeout occured */
+               /* Wait until instance is returned or timeout occurred */
                if (s5p_mfc_wait_for_done_ctx
                    (ctx, S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET, 0)) {
                        s5p_mfc_clock_off();
index 7cab6849fb5b73d9463c591b4b24eaffcae48bae..2475a3c9a0a62ab27330a347865530466d209e0d 100644 (file)
@@ -69,7 +69,7 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev)
 
        } else {
                /* In this case bank2 can point to the same address as bank1.
-                * Firmware will always occupy the beggining of this area so it is
+                * Firmware will always occupy the beginning of this area so it is
                 * impossible having a video frame buffer with zero address. */
                dev->bank2 = dev->bank1;
        }
index 04e6490a45befbae453d55ef0a86be0bb32497d2..fb2acc53112a47201be7ec785057cdb491eabffc 100644 (file)
@@ -65,7 +65,7 @@ struct mxr_format {
        int num_subframes;
        /** specifies to which subframe belong given plane */
        int plane2subframe[MXR_MAX_PLANES];
-       /** internal code, driver dependant */
+       /** internal code, driver dependent */
        unsigned long cookie;
 };
 
index 51805a5e2beb742d1f3372090085c3a3f0097d86..bc08b5f28e447795b4c7d61526666ca551194e26 100644 (file)
@@ -347,19 +347,41 @@ static int mxr_runtime_resume(struct device *dev)
 {
        struct mxr_device *mdev = to_mdev(dev);
        struct mxr_resources *res = &mdev->res;
+       int ret;
 
        mxr_dbg(mdev, "resume - start\n");
        mutex_lock(&mdev->mutex);
        /* turn clocks on */
-       clk_enable(res->mixer);
-       clk_enable(res->vp);
-       clk_enable(res->sclk_mixer);
+       ret = clk_prepare_enable(res->mixer);
+       if (ret < 0) {
+               dev_err(mdev->dev, "clk_prepare_enable(mixer) failed\n");
+               goto fail;
+       }
+       ret = clk_prepare_enable(res->vp);
+       if (ret < 0) {
+               dev_err(mdev->dev, "clk_prepare_enable(vp) failed\n");
+               goto fail_mixer;
+       }
+       ret = clk_prepare_enable(res->sclk_mixer);
+       if (ret < 0) {
+               dev_err(mdev->dev, "clk_prepare_enable(sclk_mixer) failed\n");
+               goto fail_vp;
+       }
        /* apply default configuration */
        mxr_reg_reset(mdev);
        mxr_dbg(mdev, "resume - finished\n");
 
        mutex_unlock(&mdev->mutex);
        return 0;
+
+fail_vp:
+       clk_disable_unprepare(res->vp);
+fail_mixer:
+       clk_disable_unprepare(res->mixer);
+fail:
+       mutex_unlock(&mdev->mutex);
+       dev_err(mdev->dev, "resume failed\n");
+       return ret;
 }
 
 static int mxr_runtime_suspend(struct device *dev)
@@ -369,9 +391,9 @@ static int mxr_runtime_suspend(struct device *dev)
        mxr_dbg(mdev, "suspend - start\n");
        mutex_lock(&mdev->mutex);
        /* turn clocks off */
-       clk_disable(res->sclk_mixer);
-       clk_disable(res->vp);
-       clk_disable(res->mixer);
+       clk_disable_unprepare(res->sclk_mixer);
+       clk_disable_unprepare(res->vp);
+       clk_disable_unprepare(res->mixer);
        mutex_unlock(&mdev->mutex);
        mxr_dbg(mdev, "suspend - finished\n");
        return 0;
index 641b1f071e06a2b74796f030ddfdcdc80644179b..81b97db111d8506a1c28df84a86ce4181f6ddccb 100644 (file)
@@ -528,7 +528,7 @@ static int mxr_s_dv_timings(struct file *file, void *fh,
        mutex_lock(&mdev->mutex);
 
        /* timings change cannot be done while there is an entity
-        * dependant on output configuration
+        * dependent on output configuration
         */
        if (mdev->n_output > 0) {
                mutex_unlock(&mdev->mutex);
@@ -585,7 +585,7 @@ static int mxr_s_std(struct file *file, void *fh, v4l2_std_id norm)
        mutex_lock(&mdev->mutex);
 
        /* standard change cannot be done while there is an entity
-        * dependant on output configuration
+        * dependent on output configuration
         */
        if (mdev->n_output > 0) {
                mutex_unlock(&mdev->mutex);
index 0afa90f0f6abfdfd8aee75981c147608b9c1262e..5a7c3796f22e349de4edf608bd5eb8ffee62d0dd 100644 (file)
@@ -55,6 +55,8 @@ struct sdo_device {
        struct clk *dacphy;
        /** clock for control of VPLL */
        struct clk *fout_vpll;
+       /** vpll rate before sdo stream was on */
+       unsigned long vpll_rate;
        /** regulator for SDO IP power */
        struct regulator *vdac;
        /** regulator for SDO plug detection */
@@ -193,17 +195,33 @@ static int sdo_s_power(struct v4l2_subdev *sd, int on)
 
 static int sdo_streamon(struct sdo_device *sdev)
 {
+       int ret;
+
        /* set proper clock for Timing Generator */
-       clk_set_rate(sdev->fout_vpll, 54000000);
+       sdev->vpll_rate = clk_get_rate(sdev->fout_vpll);
+       ret = clk_set_rate(sdev->fout_vpll, 54000000);
+       if (ret < 0) {
+               dev_err(sdev->dev, "Failed to set vpll rate\n");
+               return ret;
+       }
        dev_info(sdev->dev, "fout_vpll.rate = %lu\n",
        clk_get_rate(sdev->fout_vpll));
        /* enable clock in SDO */
        sdo_write_mask(sdev, SDO_CLKCON, ~0, SDO_TVOUT_CLOCK_ON);
-       clk_enable(sdev->dacphy);
+       ret = clk_prepare_enable(sdev->dacphy);
+       if (ret < 0) {
+               dev_err(sdev->dev, "clk_prepare_enable(dacphy) failed\n");
+               goto fail;
+       }
        /* enable DAC */
        sdo_write_mask(sdev, SDO_DAC, ~0, SDO_POWER_ON_DAC);
        sdo_reg_debug(sdev);
        return 0;
+
+fail:
+       sdo_write_mask(sdev, SDO_CLKCON, 0, SDO_TVOUT_CLOCK_ON);
+       clk_set_rate(sdev->fout_vpll, sdev->vpll_rate);
+       return ret;
 }
 
 static int sdo_streamoff(struct sdo_device *sdev)
@@ -211,7 +229,7 @@ static int sdo_streamoff(struct sdo_device *sdev)
        int tries;
 
        sdo_write_mask(sdev, SDO_DAC, 0, SDO_POWER_ON_DAC);
-       clk_disable(sdev->dacphy);
+       clk_disable_unprepare(sdev->dacphy);
        sdo_write_mask(sdev, SDO_CLKCON, 0, SDO_TVOUT_CLOCK_ON);
        for (tries = 100; tries; --tries) {
                if (sdo_read(sdev, SDO_CLKCON) & SDO_TVOUT_CLOCK_READY)
@@ -220,6 +238,7 @@ static int sdo_streamoff(struct sdo_device *sdev)
        }
        if (tries == 0)
                dev_err(sdev->dev, "failed to stop streaming\n");
+       clk_set_rate(sdev->fout_vpll, sdev->vpll_rate);
        return tries ? 0 : -EIO;
 }
 
@@ -254,7 +273,7 @@ static int sdo_runtime_suspend(struct device *dev)
        dev_info(dev, "suspend\n");
        regulator_disable(sdev->vdet);
        regulator_disable(sdev->vdac);
-       clk_disable(sdev->sclk_dac);
+       clk_disable_unprepare(sdev->sclk_dac);
        return 0;
 }
 
@@ -266,7 +285,7 @@ static int sdo_runtime_resume(struct device *dev)
 
        dev_info(dev, "resume\n");
 
-       ret = clk_enable(sdev->sclk_dac);
+       ret = clk_prepare_enable(sdev->sclk_dac);
        if (ret < 0)
                return ret;
 
@@ -299,7 +318,7 @@ static int sdo_runtime_resume(struct device *dev)
 vdac_r_dis:
        regulator_disable(sdev->vdac);
 dac_clk_dis:
-       clk_disable(sdev->sclk_dac);
+       clk_disable_unprepare(sdev->sclk_dac);
        return ret;
 }
 
@@ -405,7 +424,11 @@ static int sdo_probe(struct platform_device *pdev)
        }
 
        /* enable gate for dac clock, because mixer uses it */
-       clk_enable(sdev->dac);
+       ret = clk_prepare_enable(sdev->dac);
+       if (ret < 0) {
+               dev_err(dev, "clk_prepare_enable(dac) failed\n");
+               goto fail_fout_vpll;
+       }
 
        /* configure power management */
        pm_runtime_enable(dev);
@@ -444,7 +467,7 @@ static int sdo_remove(struct platform_device *pdev)
        struct sdo_device *sdev = sd_to_sdev(sd);
 
        pm_runtime_disable(&pdev->dev);
-       clk_disable(sdev->dac);
+       clk_disable_unprepare(sdev->dac);
        clk_put(sdev->fout_vpll);
        clk_put(sdev->dacphy);
        clk_put(sdev->dac);
index 6769193c7c7bbeef27f723e98760f73ece8d0219..74ce8b6b79fa91c80644e0646996397befd325cc 100644 (file)
@@ -1495,7 +1495,7 @@ static int omap1_cam_set_bus_param(struct soc_camera_device *icd)
        if (ctrlclock & LCLK_EN)
                CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock);
 
-       /* select bus endianess */
+       /* select bus endianness */
        xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
        fmt = xlate->host_fmt;
 
index 1d3f1196519669cca0509c1972bdb320d2d35ad1..2d4e73b45c5e3b05d7e4615f6f6fd0d46bd56656 100644 (file)
@@ -1108,7 +1108,7 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
        return 0;
 }
 
-/* timeperframe is arbitrary and continous */
+/* timeperframe is arbitrary and continuous */
 static int vidioc_enum_frameintervals(struct file *file, void *priv,
                                             struct v4l2_frmivalenum *fival)
 {
@@ -1125,7 +1125,7 @@ static int vidioc_enum_frameintervals(struct file *file, void *priv,
 
        fival->type = V4L2_FRMIVAL_TYPE_CONTINUOUS;
 
-       /* fill in stepwise (step=1.0 is requred by V4L2 spec) */
+       /* fill in stepwise (step=1.0 is required by V4L2 spec) */
        fival->stepwise.min  = tpf_min;
        fival->stepwise.max  = tpf_max;
        fival->stepwise.step = (struct v4l2_fract) {1, 1};
index 1c9e771aa15c7bb40b5a8a1de25d66b2b108c528..d16bf0f41e247bd69e3af1ebdc31e0309861e0fd 100644 (file)
@@ -323,7 +323,7 @@ static void vsp1_clocks_disable(struct vsp1_device *vsp1)
  * Increment the VSP1 reference count and initialize the device if the first
  * reference is taken.
  *
- * Return a pointer to the VSP1 device or NULL if an error occured.
+ * Return a pointer to the VSP1 device or NULL if an error occurred.
  */
 struct vsp1_device *vsp1_device_get(struct vsp1_device *vsp1)
 {
index 714c53ef6c11b19d48304405f363f750b26547d2..4b0ac07af662c2bca05c6534ecb52bfc15730c74 100644 (file)
@@ -1026,8 +1026,10 @@ int vsp1_video_init(struct vsp1_video *video, struct vsp1_entity *rwpf)
 
        /* ... and the buffers queue... */
        video->alloc_ctx = vb2_dma_contig_init_ctx(video->vsp1->dev);
-       if (IS_ERR(video->alloc_ctx))
+       if (IS_ERR(video->alloc_ctx)) {
+               ret = PTR_ERR(video->alloc_ctx);
                goto error;
+       }
 
        video->queue.type = video->type;
        video->queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
index 3db8a8cfe1a87f4eb80e9c22950bbcac93b7daed..050b3bb96fecc13a15f05d3f294147200954e8dd 100644 (file)
@@ -271,8 +271,7 @@ static void shark_unregister_leds(struct shark_device *shark)
        cancel_work_sync(&shark->led_work);
 }
 
-#ifdef CONFIG_PM
-static void shark_resume_leds(struct shark_device *shark)
+static inline void shark_resume_leds(struct shark_device *shark)
 {
        if (test_bit(BLUE_IS_PULSE, &shark->brightness_new))
                set_bit(BLUE_PULSE_LED, &shark->brightness_new);
@@ -281,7 +280,6 @@ static void shark_resume_leds(struct shark_device *shark)
        set_bit(RED_LED, &shark->brightness_new);
        schedule_work(&shark->led_work);
 }
-#endif
 #else
 static int shark_register_leds(struct shark_device *shark, struct device *dev)
 {
index d86d90dab8bf880666a05ca0463aa83fc62f77de..8654e0dc5c95376aa7140498e10af342b955d15a 100644 (file)
@@ -237,8 +237,7 @@ static void shark_unregister_leds(struct shark_device *shark)
        cancel_work_sync(&shark->led_work);
 }
 
-#ifdef CONFIG_PM
-static void shark_resume_leds(struct shark_device *shark)
+static inline void shark_resume_leds(struct shark_device *shark)
 {
        int i;
 
@@ -247,7 +246,6 @@ static void shark_resume_leds(struct shark_device *shark)
 
        schedule_work(&shark->led_work);
 }
-#endif
 #else
 static int shark_register_leds(struct shark_device *shark, struct device *dev)
 {
index 9c9084cb99f7dd1fde0800f0325c58584edd9e19..2fd9009f86633e74b4752472f5db2829daf6d9ce 100644 (file)
@@ -268,8 +268,8 @@ struct si476x_radio;
  *
  * @tune_freq: Tune chip to a specific frequency
  * @seek_start: Star station seeking
- * @rsq_status: Get Recieved Signal Quality(RSQ) status
- * @rds_blckcnt: Get recived RDS blocks count
+ * @rsq_status: Get Received Signal Quality(RSQ) status
+ * @rds_blckcnt: Get received RDS blocks count
  * @phase_diversity: Change phase diversity mode of the tuner
  * @phase_div_status: Get phase diversity mode status
  * @acf_status: Get the status of Automatically Controlled
index 036e2f54f4db4b1bc5c6f574e19ccde1960da9b5..3ed1f5669f791b9d3015bb91efd80ba2fa82d0c0 100644 (file)
@@ -356,7 +356,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
                   So we keep it as-is. */
                return -EINVAL;
        }
-       clamp(freq, FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL);
+       freq = clamp(freq, FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL);
        tea5764_power_up(radio);
        tea5764_tune(radio, (freq * 125) / 2);
        return 0;
index 69e3245a58a0cbfcc1d333d390a30aa45e4c70d8..a9319a24c7efe1290efbc5b309bb719584cf7b5f 100644 (file)
@@ -112,7 +112,7 @@ static int tef6862_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequen
        if (f->tuner != 0)
                return -EINVAL;
 
-       clamp(freq, TEF6862_LO_FREQ, TEF6862_HI_FREQ);
+       freq = clamp(freq, TEF6862_LO_FREQ, TEF6862_HI_FREQ);
        pll = 1964 + ((freq - TEF6862_LO_FREQ) * 20) / FREQ_MUL;
        i2cmsg[0] = (MSA_MODE_PRESET << MSA_MODE_SHIFT) | WM_SUB_PLLM;
        i2cmsg[1] = (pll >> 8) & 0xff;
index 72e3fa652481671cff04e2c06a1478d21fb0ffb6..f329485c6629b038ff2aee825edff86c82189328 100644 (file)
@@ -1370,7 +1370,7 @@ static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf)
         * 0x68nnnnB7 to 0x6AnnnnB7, the left mouse button generates
         * 0x688301b7 and the right one 0x688481b7. All other keys generate
         * 0x2nnnnnnn. Position coordinate is encoded in buf[1] and buf[2] with
-        * reversed endianess. Extract direction from buffer, rotate endianess,
+        * reversed endianness. Extract direction from buffer, rotate endianness,
         * adjust sign and feed the values into stabilize(). The resulting codes
         * will be 0x01008000, 0x01007F00, which match the newer devices.
         */
index 094484fac94cdbe52f7832f140f87895e922e631..a5d4f883d053a7b0ebca0543ac82d29d216ec26a 100644 (file)
@@ -118,7 +118,7 @@ static int debug;
 #define RR3_IR_IO_LENGTH_FUZZ  0x04
 /* Timeout for end of signal detection */
 #define RR3_IR_IO_SIG_TIMEOUT  0x05
-/* Minumum value for pause recognition. */
+/* Minimum value for pause recognition. */
 #define RR3_IR_IO_MIN_PAUSE    0x06
 
 /* Clock freq. of EZ-USB chip */
index 2e1a02e360ff0cd7279fed8ca20b80a3ee0b8ad8..20cca405bf452c46195ebbbadb37c8a535e85d0b 100644 (file)
@@ -1195,7 +1195,7 @@ static u32 mt2063_set_dnc_output_enable(struct mt2063_state *state,
  *   DNC Output is selected, the other is always off)
  *
  * @state:     ptr to mt2063_state structure
- * @Mode:      desired reciever delivery system
+ * @Mode:      desired receiver delivery system
  *
  * Note: Register cache must be valid for it to work
  */
@@ -2119,7 +2119,7 @@ static int mt2063_set_analog_params(struct dvb_frontend *fe,
 
 /*
  * As defined on EN 300 429, the DVB-C roll-off factor is 0.15.
- * So, the amount of the needed bandwith is given by:
+ * So, the amount of the needed bandwidth is given by:
  *     Bw = Symbol_rate * (1 + 0.15)
  * As such, the maximum symbol rate supported by 6 MHz is given by:
  *     max_symbol_rate = 6 MHz / 1.15 = 5217391 Bauds
index 74dc46a71f64555c07bb67be9ee09facf822ad41..7e4798783db733cc139e557444f12d4bddb820b5 100644 (file)
 #define V4L2_STD_A2            (V4L2_STD_A2_A    | V4L2_STD_A2_B)
 #define V4L2_STD_NICAM         (V4L2_STD_NICAM_A | V4L2_STD_NICAM_B)
 
-/* To preserve backward compatibilty,
+/* To preserve backward compatibility,
    (std & V4L2_STD_AUDIO) = 0 means that ALL audio stds are supported
  */
 
index e9d017bea377069da087751404e75f86b081c7cd..528cce958a82c4a67c91ea0c52841364db36f7d4 100644 (file)
@@ -1412,8 +1412,8 @@ err_v4l2:
        usb_set_intfdata(interface, NULL);
 err_if:
        usb_put_dev(udev);
-       kfree(dev);
        clear_bit(dev->devno, &cx231xx_devused);
+       kfree(dev);
        return retval;
 }
 
index c8fcd78425bd228ca4374daf94fdbf4ed1c0c17a..8f9b2cea88f009ec316fb1b97cbbfa67984fcda0 100644 (file)
@@ -131,7 +131,7 @@ static int af9035_wr_regs(struct dvb_usb_device *d, u32 reg, u8 *val, int len)
 {
        u8 wbuf[MAX_XFER_SIZE];
        u8 mbox = (reg >> 16) & 0xff;
-       struct usb_req req = { CMD_MEM_WR, mbox, sizeof(wbuf), wbuf, 0, NULL };
+       struct usb_req req = { CMD_MEM_WR, mbox, 6 + len, wbuf, 0, NULL };
 
        if (6 + len > sizeof(wbuf)) {
                dev_warn(&d->udev->dev, "%s: i2c wr: len=%d is too big!\n",
@@ -238,14 +238,15 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap,
                } else {
                        /* I2C */
                        u8 buf[MAX_XFER_SIZE];
-                       struct usb_req req = { CMD_I2C_RD, 0, sizeof(buf),
+                       struct usb_req req = { CMD_I2C_RD, 0, 5 + msg[0].len,
                                        buf, msg[1].len, msg[1].buf };
 
                        if (5 + msg[0].len > sizeof(buf)) {
                                dev_warn(&d->udev->dev,
                                         "%s: i2c xfer: len=%d is too big!\n",
                                         KBUILD_MODNAME, msg[0].len);
-                               return -EOPNOTSUPP;
+                               ret = -EOPNOTSUPP;
+                               goto unlock;
                        }
                        req.mbox |= ((msg[0].addr & 0x80)  >>  3);
                        buf[0] = msg[1].len;
@@ -274,14 +275,15 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap,
                } else {
                        /* I2C */
                        u8 buf[MAX_XFER_SIZE];
-                       struct usb_req req = { CMD_I2C_WR, 0, sizeof(buf), buf,
-                                       0, NULL };
+                       struct usb_req req = { CMD_I2C_WR, 0, 5 + msg[0].len,
+                                       buf, 0, NULL };
 
                        if (5 + msg[0].len > sizeof(buf)) {
                                dev_warn(&d->udev->dev,
                                         "%s: i2c xfer: len=%d is too big!\n",
                                         KBUILD_MODNAME, msg[0].len);
-                               return -EOPNOTSUPP;
+                               ret = -EOPNOTSUPP;
+                               goto unlock;
                        }
                        req.mbox |= ((msg[0].addr & 0x80)  >>  3);
                        buf[0] = msg[0].len;
@@ -319,6 +321,7 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap,
                ret = -EOPNOTSUPP;
        }
 
+unlock:
        mutex_unlock(&d->i2c_mutex);
 
        if (ret < 0)
@@ -1534,6 +1537,8 @@ static const struct usb_device_id af9035_id_table[] = {
        /* XXX: that same ID [0ccd:0099] is used by af9015 driver too */
        { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x0099,
                &af9035_props, "TerraTec Cinergy T Stick Dual RC (rev. 2)", NULL) },
+       { DVB_USB_DEVICE(USB_VID_LEADTEK, 0x6a05,
+               &af9035_props, "Leadtek WinFast DTV Dongle Dual", NULL) },
        { }
 };
 MODULE_DEVICE_TABLE(usb, af9035_id_table);
index 2627553f7de1f90c262f2d234d1d1faa9288f45f..08240e498451a55810e4bd00a75df73d0c1a607e 100644 (file)
@@ -266,7 +266,7 @@ static int mxl111sf_adap_fe_init(struct dvb_frontend *fe)
        struct mxl111sf_adap_state *adap_state = &state->adap_state[fe->id];
        int err;
 
-       /* exit if we didnt initialize the driver yet */
+       /* exit if we didn't initialize the driver yet */
        if (!state->chip_id) {
                mxl_debug("driver not yet initialized, exit.");
                goto fail;
@@ -322,7 +322,7 @@ static int mxl111sf_adap_fe_sleep(struct dvb_frontend *fe)
        struct mxl111sf_adap_state *adap_state = &state->adap_state[fe->id];
        int err;
 
-       /* exit if we didnt initialize the driver yet */
+       /* exit if we didn't initialize the driver yet */
        if (!state->chip_id) {
                mxl_debug("driver not yet initialized, exit.");
                goto fail;
index 40832a1aef6c71c0df2eaf51ffdea327bafe18da..98d24aefb640f80e12d6dd720f872273c71e6276 100644 (file)
@@ -102,7 +102,7 @@ static int technisat_usb2_i2c_access(struct usb_device *udev,
        if (rxlen > 62) {
                err("i2c RX buffer can't exceed 62 bytes (dev 0x%02x)",
                                device_addr);
-               txlen = 62;
+               rxlen = 62;
        }
 
        b[0] = I2C_SPEED_100KHZ_BIT;
index fc5d60efd4abe99f19acbafff7b83879da5ff3ac..dd19c9ff76e0f9a159c6630320814c89e9e83d5a 100644 (file)
@@ -1664,8 +1664,8 @@ static int em28xx_v4l2_close(struct file *filp)
 
        em28xx_videodbg("users=%d\n", dev->users);
 
-       mutex_lock(&dev->lock);
        vb2_fop_release(filp);
+       mutex_lock(&dev->lock);
 
        if (dev->users == 1) {
                /* the device is already disconnect,
index cb1e64ca59c9259b59ca1aaaaea036b6bd2c5fa0..cea8d7f51c3cc9430af956066d87b045b453c062 100644 (file)
@@ -438,7 +438,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
        s32 nToSkip =
                sd->swapRB * (gspca_dev->cam.cam_mode[mode].bytesperline + 1);
 
-       /* Test only against 0202h, so endianess does not matter */
+       /* Test only against 0202h, so endianness does not matter */
        switch (*(s16 *) data) {
        case 0x0202:            /* End of frame, start a new one */
                gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
index cd79c180f67b87e84689a8a162b4962bf5691cde..07529e5a0c5605186b3aa619b6b89d06cf98bc45 100644 (file)
@@ -416,7 +416,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 #if IS_ENABLED(CONFIG_INPUT)
 static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
                        u8 *data,               /* interrupt packet data */
-                       int len)                /* interrput packet length */
+                       int len)                /* interrupt packet length */
 {
        int ret = -EINVAL;
 
index a9150964356329d93ea136e151c0d7f0aebf8590..2fd1c5e31a0f2692a1d59dd88c72cbee74e61054 100644 (file)
@@ -874,7 +874,7 @@ static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
 #if IS_ENABLED(CONFIG_INPUT)
 static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
                        u8 *data,               /* interrupt packet data */
-                       int len)                /* interrput packet length */
+                       int len)                /* interrupt packet length */
 {
        int ret = -EINVAL;
        u8 data0, data1;
index 1fc80af2a18907e57d54eac3f58481ada0f3cda7..48234c9a8b6c3e4b4b927eb654ddb0009aa3d8ba 100644 (file)
@@ -361,6 +361,9 @@ static void stk1135_configure_clock(struct gspca_dev *gspca_dev)
 
        /* set serial interface clock divider (30MHz/0x1f*16+2) = 60240 kHz) */
        reg_w(gspca_dev, STK1135_REG_SICTL + 2, 0x1f);
+
+       /* wait a while for sensor to catch up */
+       udelay(1000);
 }
 
 static void stk1135_camera_disable(struct gspca_dev *gspca_dev)
index 9c0827631b9c105658575ed52e754fd1efa0c740..7f94ec74282e3ea42b0c423130419b038a5e3edd 100644 (file)
@@ -139,7 +139,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
        struct sd *sd = (struct sd *) gspca_dev;
        struct cam *cam = &gspca_dev->cam;
 
-       /* Give the camera some time to settle, otherwise initalization will
+       /* Give the camera some time to settle, otherwise initialization will
           fail on hotplug, and yes it really needs a full second. */
        msleep(1000);
 
index a517d185febed4590bbb5f58306aa4e4a2c4f0f1..46c9f2229a18675c6a1ca39528dab2196937c0c5 100644 (file)
@@ -1027,6 +1027,7 @@ static const struct usb_device_id device_table[] = {
        {USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)},
        {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)},
        {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)},
+       {USB_DEVICE(0x06d6, 0x0041), BS(SPCA504B, 0)},
        {USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)},
        {USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)},
        {USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)},
index 7b95d8e88a20240305a8817b72c3459d80a5adc6..d3e1b6d8bf494f79d449c38c96be5d022ab61043 100644 (file)
@@ -6905,7 +6905,7 @@ static int sd_get_jcomp(struct gspca_dev *gspca_dev,
 #if IS_ENABLED(CONFIG_INPUT)
 static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
                        u8 *data,               /* interrupt packet data */
-                       int len)                /* interrput packet length */
+                       int len)                /* interrupt packet length */
 {
        if (len == 8 && data[4] == 1) {
                input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
index 77bbf788965953bbc67f8fa8b3ab18ccbe5806d8..78c9bc8e7f561744364a6de94f4aeaae382dd077 100644 (file)
@@ -1039,7 +1039,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        /* Set the leds off */
        pwc_set_leds(pdev, 0, 0);
 
-       /* Setup intial videomode */
+       /* Setup initial videomode */
        rc = pwc_set_video_mode(pdev, MAX_WIDTH, MAX_HEIGHT,
                                V4L2_PIX_FMT_YUV420, 30, &compression, 1);
        if (rc)
index 8a505a90d3189a59876a916507ae50b6e11a0ed9..6222a4ab1e00bfff2d58d7816145bdae58fe4059 100644 (file)
 #define USBTV_ISOC_TRANSFERS   16
 #define USBTV_ISOC_PACKETS     8
 
-#define USBTV_WIDTH            720
-#define USBTV_HEIGHT           480
-
 #define USBTV_CHUNK_SIZE       256
 #define USBTV_CHUNK            240
-#define USBTV_CHUNKS           (USBTV_WIDTH * USBTV_HEIGHT \
-                                       / 4 / USBTV_CHUNK)
 
 /* Chunk header. */
 #define USBTV_MAGIC_OK(chunk)  ((be32_to_cpu(chunk[0]) & 0xff000000) \
 #define USBTV_ODD(chunk)       ((be32_to_cpu(chunk[0]) & 0x0000f000) >> 15)
 #define USBTV_CHUNK_NO(chunk)  (be32_to_cpu(chunk[0]) & 0x00000fff)
 
+#define USBTV_TV_STD  (V4L2_STD_525_60 | V4L2_STD_PAL)
+
+/* parameters for supported TV norms */
+struct usbtv_norm_params {
+       v4l2_std_id norm;
+       int cap_width, cap_height;
+};
+
+static struct usbtv_norm_params norm_params[] = {
+       {
+               .norm = V4L2_STD_525_60,
+               .cap_width = 720,
+               .cap_height = 480,
+       },
+       {
+               .norm = V4L2_STD_PAL,
+               .cap_width = 720,
+               .cap_height = 576,
+       }
+};
+
 /* A single videobuf2 frame buffer. */
 struct usbtv_buf {
        struct vb2_buffer vb;
@@ -94,11 +110,38 @@ struct usbtv {
                USBTV_COMPOSITE_INPUT,
                USBTV_SVIDEO_INPUT,
        } input;
+       v4l2_std_id norm;
+       int width, height;
+       int n_chunks;
        int iso_size;
        unsigned int sequence;
        struct urb *isoc_urbs[USBTV_ISOC_TRANSFERS];
 };
 
+static int usbtv_configure_for_norm(struct usbtv *usbtv, v4l2_std_id norm)
+{
+       int i, ret = 0;
+       struct usbtv_norm_params *params = NULL;
+
+       for (i = 0; i < ARRAY_SIZE(norm_params); i++) {
+               if (norm_params[i].norm & norm) {
+                       params = &norm_params[i];
+                       break;
+               }
+       }
+
+       if (params) {
+               usbtv->width = params->cap_width;
+               usbtv->height = params->cap_height;
+               usbtv->n_chunks = usbtv->width * usbtv->height
+                                               / 4 / USBTV_CHUNK;
+               usbtv->norm = params->norm;
+       } else
+               ret = -EINVAL;
+
+       return ret;
+}
+
 static int usbtv_set_regs(struct usbtv *usbtv, const u16 regs[][2], int size)
 {
        int ret;
@@ -158,6 +201,57 @@ static int usbtv_select_input(struct usbtv *usbtv, int input)
        return ret;
 }
 
+static int usbtv_select_norm(struct usbtv *usbtv, v4l2_std_id norm)
+{
+       int ret;
+       static const u16 pal[][2] = {
+               { USBTV_BASE + 0x001a, 0x0068 },
+               { USBTV_BASE + 0x010e, 0x0072 },
+               { USBTV_BASE + 0x010f, 0x00a2 },
+               { USBTV_BASE + 0x0112, 0x00b0 },
+               { USBTV_BASE + 0x0117, 0x0001 },
+               { USBTV_BASE + 0x0118, 0x002c },
+               { USBTV_BASE + 0x012d, 0x0010 },
+               { USBTV_BASE + 0x012f, 0x0020 },
+               { USBTV_BASE + 0x024f, 0x0002 },
+               { USBTV_BASE + 0x0254, 0x0059 },
+               { USBTV_BASE + 0x025a, 0x0016 },
+               { USBTV_BASE + 0x025b, 0x0035 },
+               { USBTV_BASE + 0x0263, 0x0017 },
+               { USBTV_BASE + 0x0266, 0x0016 },
+               { USBTV_BASE + 0x0267, 0x0036 }
+       };
+
+       static const u16 ntsc[][2] = {
+               { USBTV_BASE + 0x001a, 0x0079 },
+               { USBTV_BASE + 0x010e, 0x0068 },
+               { USBTV_BASE + 0x010f, 0x009c },
+               { USBTV_BASE + 0x0112, 0x00f0 },
+               { USBTV_BASE + 0x0117, 0x0000 },
+               { USBTV_BASE + 0x0118, 0x00fc },
+               { USBTV_BASE + 0x012d, 0x0004 },
+               { USBTV_BASE + 0x012f, 0x0008 },
+               { USBTV_BASE + 0x024f, 0x0001 },
+               { USBTV_BASE + 0x0254, 0x005f },
+               { USBTV_BASE + 0x025a, 0x0012 },
+               { USBTV_BASE + 0x025b, 0x0001 },
+               { USBTV_BASE + 0x0263, 0x001c },
+               { USBTV_BASE + 0x0266, 0x0011 },
+               { USBTV_BASE + 0x0267, 0x0005 }
+       };
+
+       ret = usbtv_configure_for_norm(usbtv, norm);
+
+       if (!ret) {
+               if (norm & V4L2_STD_525_60)
+                       ret = usbtv_set_regs(usbtv, ntsc, ARRAY_SIZE(ntsc));
+               else if (norm & V4L2_STD_PAL)
+                       ret = usbtv_set_regs(usbtv, pal, ARRAY_SIZE(pal));
+       }
+
+       return ret;
+}
+
 static int usbtv_setup_capture(struct usbtv *usbtv)
 {
        int ret;
@@ -225,26 +319,11 @@ static int usbtv_setup_capture(struct usbtv *usbtv)
 
                { USBTV_BASE + 0x0284, 0x0088 },
                { USBTV_BASE + 0x0003, 0x0004 },
-               { USBTV_BASE + 0x001a, 0x0079 },
                { USBTV_BASE + 0x0100, 0x00d3 },
-               { USBTV_BASE + 0x010e, 0x0068 },
-               { USBTV_BASE + 0x010f, 0x009c },
-               { USBTV_BASE + 0x0112, 0x00f0 },
                { USBTV_BASE + 0x0115, 0x0015 },
-               { USBTV_BASE + 0x0117, 0x0000 },
-               { USBTV_BASE + 0x0118, 0x00fc },
-               { USBTV_BASE + 0x012d, 0x0004 },
-               { USBTV_BASE + 0x012f, 0x0008 },
                { USBTV_BASE + 0x0220, 0x002e },
                { USBTV_BASE + 0x0225, 0x0008 },
                { USBTV_BASE + 0x024e, 0x0002 },
-               { USBTV_BASE + 0x024f, 0x0001 },
-               { USBTV_BASE + 0x0254, 0x005f },
-               { USBTV_BASE + 0x025a, 0x0012 },
-               { USBTV_BASE + 0x025b, 0x0001 },
-               { USBTV_BASE + 0x0263, 0x001c },
-               { USBTV_BASE + 0x0266, 0x0011 },
-               { USBTV_BASE + 0x0267, 0x0005 },
                { USBTV_BASE + 0x024e, 0x0002 },
                { USBTV_BASE + 0x024f, 0x0002 },
        };
@@ -253,6 +332,10 @@ static int usbtv_setup_capture(struct usbtv *usbtv)
        if (ret)
                return ret;
 
+       ret = usbtv_select_norm(usbtv, usbtv->norm);
+       if (ret)
+               return ret;
+
        ret = usbtv_select_input(usbtv, usbtv->input);
        if (ret)
                return ret;
@@ -296,7 +379,7 @@ static void usbtv_image_chunk(struct usbtv *usbtv, u32 *chunk)
        frame_id = USBTV_FRAME_ID(chunk);
        odd = USBTV_ODD(chunk);
        chunk_no = USBTV_CHUNK_NO(chunk);
-       if (chunk_no >= USBTV_CHUNKS)
+       if (chunk_no >= usbtv->n_chunks)
                return;
 
        /* Beginning of a frame. */
@@ -324,10 +407,10 @@ static void usbtv_image_chunk(struct usbtv *usbtv, u32 *chunk)
        usbtv->chunks_done++;
 
        /* Last chunk in a frame, signalling an end */
-       if (odd && chunk_no == USBTV_CHUNKS-1) {
+       if (odd && chunk_no == usbtv->n_chunks-1) {
                int size = vb2_plane_size(&buf->vb, 0);
                enum vb2_buffer_state state = usbtv->chunks_done ==
-                                               USBTV_CHUNKS ?
+                                               usbtv->n_chunks ?
                                                VB2_BUF_STATE_DONE :
                                                VB2_BUF_STATE_ERROR;
 
@@ -500,6 +583,8 @@ static int usbtv_querycap(struct file *file, void *priv,
 static int usbtv_enum_input(struct file *file, void *priv,
                                        struct v4l2_input *i)
 {
+       struct usbtv *dev = video_drvdata(file);
+
        switch (i->index) {
        case USBTV_COMPOSITE_INPUT:
                strlcpy(i->name, "Composite", sizeof(i->name));
@@ -512,7 +597,7 @@ static int usbtv_enum_input(struct file *file, void *priv,
        }
 
        i->type = V4L2_INPUT_TYPE_CAMERA;
-       i->std = V4L2_STD_525_60;
+       i->std = dev->vdev.tvnorms;
        return 0;
 }
 
@@ -531,23 +616,37 @@ static int usbtv_enum_fmt_vid_cap(struct file *file, void  *priv,
 static int usbtv_fmt_vid_cap(struct file *file, void *priv,
                                        struct v4l2_format *f)
 {
-       f->fmt.pix.width = USBTV_WIDTH;
-       f->fmt.pix.height = USBTV_HEIGHT;
+       struct usbtv *usbtv = video_drvdata(file);
+
+       f->fmt.pix.width = usbtv->width;
+       f->fmt.pix.height = usbtv->height;
        f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
        f->fmt.pix.field = V4L2_FIELD_INTERLACED;
-       f->fmt.pix.bytesperline = USBTV_WIDTH * 2;
+       f->fmt.pix.bytesperline = usbtv->width * 2;
        f->fmt.pix.sizeimage = (f->fmt.pix.bytesperline * f->fmt.pix.height);
        f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-       f->fmt.pix.priv = 0;
+
        return 0;
 }
 
 static int usbtv_g_std(struct file *file, void *priv, v4l2_std_id *norm)
 {
-       *norm = V4L2_STD_525_60;
+       struct usbtv *usbtv = video_drvdata(file);
+       *norm = usbtv->norm;
        return 0;
 }
 
+static int usbtv_s_std(struct file *file, void *priv, v4l2_std_id norm)
+{
+       int ret = -EINVAL;
+       struct usbtv *usbtv = video_drvdata(file);
+
+       if ((norm & V4L2_STD_525_60) || (norm & V4L2_STD_PAL))
+               ret = usbtv_select_norm(usbtv, norm);
+
+       return ret;
+}
+
 static int usbtv_g_input(struct file *file, void *priv, unsigned int *i)
 {
        struct usbtv *usbtv = video_drvdata(file);
@@ -561,13 +660,6 @@ static int usbtv_s_input(struct file *file, void *priv, unsigned int i)
        return usbtv_select_input(usbtv, i);
 }
 
-static int usbtv_s_std(struct file *file, void *priv, v4l2_std_id norm)
-{
-       if (norm & V4L2_STD_525_60)
-               return 0;
-       return -EINVAL;
-}
-
 struct v4l2_ioctl_ops usbtv_ioctl_ops = {
        .vidioc_querycap = usbtv_querycap,
        .vidioc_enum_input = usbtv_enum_input,
@@ -604,10 +696,12 @@ static int usbtv_queue_setup(struct vb2_queue *vq,
        const struct v4l2_format *v4l_fmt, unsigned int *nbuffers,
        unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[])
 {
+       struct usbtv *usbtv = vb2_get_drv_priv(vq);
+
        if (*nbuffers < 2)
                *nbuffers = 2;
        *nplanes = 1;
-       sizes[0] = USBTV_WIDTH * USBTV_HEIGHT / 2 * sizeof(u32);
+       sizes[0] = USBTV_CHUNK * usbtv->n_chunks * 2 * sizeof(u32);
 
        return 0;
 }
@@ -690,7 +784,11 @@ static int usbtv_probe(struct usb_interface *intf,
                return -ENOMEM;
        usbtv->dev = dev;
        usbtv->udev = usb_get_dev(interface_to_usbdev(intf));
+
        usbtv->iso_size = size;
+
+       (void)usbtv_configure_for_norm(usbtv, V4L2_STD_525_60);
+
        spin_lock_init(&usbtv->buflock);
        mutex_init(&usbtv->v4l2_lock);
        mutex_init(&usbtv->vb2q_lock);
@@ -727,7 +825,7 @@ static int usbtv_probe(struct usb_interface *intf,
        usbtv->vdev.release = video_device_release_empty;
        usbtv->vdev.fops = &usbtv_fops;
        usbtv->vdev.ioctl_ops = &usbtv_ioctl_ops;
-       usbtv->vdev.tvnorms = V4L2_STD_525_60;
+       usbtv->vdev.tvnorms = USBTV_TV_STD;
        usbtv->vdev.queue = &usbtv->vb2q;
        usbtv->vdev.lock = &usbtv->v4l2_lock;
        set_bit(V4L2_FL_USE_FH_PRIO, &usbtv->vdev.flags);
index 899cb6d1c4a4a74a68cae01dbea51de5befc821e..898c208889cd2d55dd5a22522a2d06340eb0891d 100644 (file)
@@ -556,7 +556,7 @@ static u16 uvc_video_clock_host_sof(const struct uvc_clock_sample *sample)
  *
  * SOF = ((SOF2 - SOF1) * PTS + SOF1 * STC2 - SOF2 * STC1) / (STC2 - STC1)   (1)
  *
- * to avoid loosing precision in the division. Similarly, the host timestamp is
+ * to avoid losing precision in the division. Similarly, the host timestamp is
  * computed with
  *
  * TS = ((TS2 - TS1) * PTS + TS1 * SOF2 - TS2 * SOF1) / (SOF2 - SOF1)       (2)
index 60dcc0f3b32e7b445352b455d377f5b2b794b4fb..fb46790d0eca795d5e411c54bf7129d96e61d3e9 100644 (file)
@@ -420,7 +420,7 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
                "Advanced Simple",
                "Core",
                "Simple Scalable",
-               "Advanced Coding Efficency",
+               "Advanced Coding Efficiency",
                NULL,
        };
 
index 73035ee0f4def8c7425872dba6c1687419b1303f..178ce96556c6424432a9220295219ccd0dadf4e7 100644 (file)
@@ -558,6 +558,8 @@ unsigned int v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
 
        if (m2m_ctx->m2m_dev->m2m_ops->unlock)
                m2m_ctx->m2m_dev->m2m_ops->unlock(m2m_ctx->priv);
+       else if (m2m_ctx->q_lock)
+               mutex_unlock(m2m_ctx->q_lock);
 
        if (list_empty(&src_q->done_list))
                poll_wait(file, &src_q->done_wq, wait);
@@ -566,6 +568,8 @@ unsigned int v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
 
        if (m2m_ctx->m2m_dev->m2m_ops->lock)
                m2m_ctx->m2m_dev->m2m_ops->lock(m2m_ctx->priv);
+       else if (m2m_ctx->q_lock)
+               mutex_lock(m2m_ctx->q_lock);
 
        spin_lock_irqsave(&src_q->done_lock, flags);
        if (!list_empty(&src_q->done_list))
@@ -693,6 +697,13 @@ struct v4l2_m2m_ctx *v4l2_m2m_ctx_init(struct v4l2_m2m_dev *m2m_dev,
 
        if (ret)
                goto err;
+       /*
+        * If both queues use same mutex assign it as the common buffer
+        * queues lock to the m2m context. This lock is used in the
+        * v4l2_m2m_ioctl_* helpers.
+        */
+       if (out_q_ctx->q.lock == cap_q_ctx->q.lock)
+               m2m_ctx->q_lock = out_q_ctx->q.lock;
 
        return m2m_ctx;
 err:
@@ -740,3 +751,118 @@ void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx, struct vb2_buffer *vb)
 }
 EXPORT_SYMBOL_GPL(v4l2_m2m_buf_queue);
 
+/* Videobuf2 ioctl helpers */
+
+int v4l2_m2m_ioctl_reqbufs(struct file *file, void *priv,
+                               struct v4l2_requestbuffers *rb)
+{
+       struct v4l2_fh *fh = file->private_data;
+
+       return v4l2_m2m_reqbufs(file, fh->m2m_ctx, rb);
+}
+EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_reqbufs);
+
+int v4l2_m2m_ioctl_create_bufs(struct file *file, void *priv,
+                               struct v4l2_create_buffers *create)
+{
+       struct v4l2_fh *fh = file->private_data;
+
+       return v4l2_m2m_create_bufs(file, fh->m2m_ctx, create);
+}
+EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_create_bufs);
+
+int v4l2_m2m_ioctl_querybuf(struct file *file, void *priv,
+                               struct v4l2_buffer *buf)
+{
+       struct v4l2_fh *fh = file->private_data;
+
+       return v4l2_m2m_querybuf(file, fh->m2m_ctx, buf);
+}
+EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_querybuf);
+
+int v4l2_m2m_ioctl_qbuf(struct file *file, void *priv,
+                               struct v4l2_buffer *buf)
+{
+       struct v4l2_fh *fh = file->private_data;
+
+       return v4l2_m2m_qbuf(file, fh->m2m_ctx, buf);
+}
+EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_qbuf);
+
+int v4l2_m2m_ioctl_dqbuf(struct file *file, void *priv,
+                               struct v4l2_buffer *buf)
+{
+       struct v4l2_fh *fh = file->private_data;
+
+       return v4l2_m2m_dqbuf(file, fh->m2m_ctx, buf);
+}
+EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_dqbuf);
+
+int v4l2_m2m_ioctl_expbuf(struct file *file, void *priv,
+                               struct v4l2_exportbuffer *eb)
+{
+       struct v4l2_fh *fh = file->private_data;
+
+       return v4l2_m2m_expbuf(file, fh->m2m_ctx, eb);
+}
+EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_expbuf);
+
+int v4l2_m2m_ioctl_streamon(struct file *file, void *priv,
+                               enum v4l2_buf_type type)
+{
+       struct v4l2_fh *fh = file->private_data;
+
+       return v4l2_m2m_streamon(file, fh->m2m_ctx, type);
+}
+EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_streamon);
+
+int v4l2_m2m_ioctl_streamoff(struct file *file, void *priv,
+                               enum v4l2_buf_type type)
+{
+       struct v4l2_fh *fh = file->private_data;
+
+       return v4l2_m2m_streamoff(file, fh->m2m_ctx, type);
+}
+EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_streamoff);
+
+/*
+ * v4l2_file_operations helpers. It is assumed here same lock is used
+ * for the output and the capture buffer queue.
+ */
+
+int v4l2_m2m_fop_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct v4l2_fh *fh = file->private_data;
+       struct v4l2_m2m_ctx *m2m_ctx = fh->m2m_ctx;
+       int ret;
+
+       if (m2m_ctx->q_lock && mutex_lock_interruptible(m2m_ctx->q_lock))
+               return -ERESTARTSYS;
+
+       ret = v4l2_m2m_mmap(file, m2m_ctx, vma);
+
+       if (m2m_ctx->q_lock)
+               mutex_unlock(m2m_ctx->q_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(v4l2_m2m_fop_mmap);
+
+unsigned int v4l2_m2m_fop_poll(struct file *file, poll_table *wait)
+{
+       struct v4l2_fh *fh = file->private_data;
+       struct v4l2_m2m_ctx *m2m_ctx = fh->m2m_ctx;
+       unsigned int ret;
+
+       if (m2m_ctx->q_lock)
+               mutex_lock(m2m_ctx->q_lock);
+
+       ret = v4l2_m2m_poll(file, m2m_ctx, wait);
+
+       if (m2m_ctx->q_lock)
+               mutex_unlock(m2m_ctx->q_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(v4l2_m2m_fop_poll);
+
index b19b306c8f7f533d3112db441f692e57bd76638d..12df9fda29243217b166074d568574f5abd25607 100644 (file)
@@ -144,6 +144,25 @@ static void __vb2_buf_dmabuf_put(struct vb2_buffer *vb)
                __vb2_plane_dmabuf_put(q, &vb->planes[plane]);
 }
 
+/**
+ * __setup_lengths() - setup initial lengths for every plane in
+ * every buffer on the queue
+ */
+static void __setup_lengths(struct vb2_queue *q, unsigned int n)
+{
+       unsigned int buffer, plane;
+       struct vb2_buffer *vb;
+
+       for (buffer = q->num_buffers; buffer < q->num_buffers + n; ++buffer) {
+               vb = q->bufs[buffer];
+               if (!vb)
+                       continue;
+
+               for (plane = 0; plane < vb->num_planes; ++plane)
+                       vb->v4l2_planes[plane].length = q->plane_sizes[plane];
+       }
+}
+
 /**
  * __setup_offsets() - setup unique offsets ("cookies") for every plane in
  * every buffer on the queue
@@ -169,7 +188,6 @@ static void __setup_offsets(struct vb2_queue *q, unsigned int n)
                        continue;
 
                for (plane = 0; plane < vb->num_planes; ++plane) {
-                       vb->v4l2_planes[plane].length = q->plane_sizes[plane];
                        vb->v4l2_planes[plane].m.mem_offset = off;
 
                        dprintk(3, "Buffer %d, plane %d offset 0x%08lx\n",
@@ -241,6 +259,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
                q->bufs[q->num_buffers + buffer] = vb;
        }
 
+       __setup_lengths(q, buffer);
        if (memory == V4L2_MEMORY_MMAP)
                __setup_offsets(q, buffer);
 
@@ -1116,6 +1135,8 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 
                if (planes[plane].length < planes[plane].data_offset +
                    q->plane_sizes[plane]) {
+                       dprintk(1, "qbuf: invalid dmabuf length for plane %d\n",
+                               plane);
                        ret = -EINVAL;
                        goto err;
                }
@@ -1697,8 +1718,8 @@ int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
        }
 
        if (q->streaming) {
-               dprintk(1, "streamon: already streaming\n");
-               return -EBUSY;
+               dprintk(3, "streamon successful: already streaming\n");
+               return 0;
        }
 
        /*
@@ -1754,8 +1775,8 @@ int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
        }
 
        if (!q->streaming) {
-               dprintk(1, "streamoff: not streaming\n");
-               return -EINVAL;
+               dprintk(3, "streamoff successful: not streaming\n");
+               return 0;
        }
 
        /*
@@ -1824,8 +1845,8 @@ int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
                return -EINVAL;
        }
 
-       if (eb->flags & ~O_CLOEXEC) {
-               dprintk(1, "Queue does support only O_CLOEXEC flag\n");
+       if (eb->flags & ~(O_CLOEXEC | O_ACCMODE)) {
+               dprintk(1, "Queue does support only O_CLOEXEC and access mode flags\n");
                return -EINVAL;
        }
 
@@ -1848,14 +1869,14 @@ int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
 
        vb_plane = &vb->planes[eb->plane];
 
-       dbuf = call_memop(q, get_dmabuf, vb_plane->mem_priv);
+       dbuf = call_memop(q, get_dmabuf, vb_plane->mem_priv, eb->flags & O_ACCMODE);
        if (IS_ERR_OR_NULL(dbuf)) {
                dprintk(1, "Failed to export buffer %d, plane %d\n",
                        eb->index, eb->plane);
                return -EINVAL;
        }
 
-       ret = dma_buf_fd(dbuf, eb->flags);
+       ret = dma_buf_fd(dbuf, eb->flags & ~O_ACCMODE);
        if (ret < 0) {
                dprintk(3, "buffer %d, plane %d failed to export (%d)\n",
                        eb->index, eb->plane, ret);
@@ -2630,16 +2651,29 @@ int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma)
 }
 EXPORT_SYMBOL_GPL(vb2_fop_mmap);
 
-int vb2_fop_release(struct file *file)
+int _vb2_fop_release(struct file *file, struct mutex *lock)
 {
        struct video_device *vdev = video_devdata(file);
 
        if (file->private_data == vdev->queue->owner) {
+               if (lock)
+                       mutex_lock(lock);
                vb2_queue_release(vdev->queue);
                vdev->queue->owner = NULL;
+               if (lock)
+                       mutex_unlock(lock);
        }
        return v4l2_fh_release(file);
 }
+EXPORT_SYMBOL_GPL(_vb2_fop_release);
+
+int vb2_fop_release(struct file *file)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
+
+       return _vb2_fop_release(file, lock);
+}
 EXPORT_SYMBOL_GPL(vb2_fop_release);
 
 ssize_t vb2_fop_write(struct file *file, const char __user *buf,
index 646f08f4f504c05ae37dd95cbc1fe8333705e658..33d3871d1e131dce9a2f1d8392020dce5b8ff799 100644 (file)
@@ -393,7 +393,7 @@ static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf)
        return sgt;
 }
 
-static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv)
+static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv, unsigned long flags)
 {
        struct vb2_dc_buf *buf = buf_priv;
        struct dma_buf *dbuf;
@@ -404,7 +404,7 @@ static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv)
        if (WARN_ON(!buf->sgt_base))
                return NULL;
 
-       dbuf = dma_buf_export(buf, &vb2_dc_dmabuf_ops, buf->size, 0);
+       dbuf = dma_buf_export(buf, &vb2_dc_dmabuf_ops, buf->size, flags);
        if (IS_ERR(dbuf))
                return NULL;
 
index 2f860543912cd1c3f5dd4f286705b2c8b208dc37..c779f210d2c623e9807ad7c41737813ed92d43ea 100644 (file)
@@ -40,6 +40,7 @@ struct vb2_dma_sg_buf {
        unsigned int                    num_pages;
        atomic_t                        refcount;
        struct vb2_vmarea_handler       handler;
+       struct vm_area_struct           *vma;
 };
 
 static void vb2_dma_sg_put(void *buf_priv);
@@ -155,12 +156,18 @@ static void vb2_dma_sg_put(void *buf_priv)
        }
 }
 
+static inline int vma_is_io(struct vm_area_struct *vma)
+{
+       return !!(vma->vm_flags & (VM_IO | VM_PFNMAP));
+}
+
 static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
                                    unsigned long size, int write)
 {
        struct vb2_dma_sg_buf *buf;
        unsigned long first, last;
        int num_pages_from_user;
+       struct vm_area_struct *vma;
 
        buf = kzalloc(sizeof *buf, GFP_KERNEL);
        if (!buf)
@@ -178,9 +185,40 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
        buf->pages = kzalloc(buf->num_pages * sizeof(struct page *),
                             GFP_KERNEL);
        if (!buf->pages)
-               return NULL;
+               goto userptr_fail_alloc_pages;
+
+       vma = find_vma(current->mm, vaddr);
+       if (!vma) {
+               dprintk(1, "no vma for address %lu\n", vaddr);
+               goto userptr_fail_find_vma;
+       }
+
+       if (vma->vm_end < vaddr + size) {
+               dprintk(1, "vma at %lu is too small for %lu bytes\n",
+                       vaddr, size);
+               goto userptr_fail_find_vma;
+       }
+
+       buf->vma = vb2_get_vma(vma);
+       if (!buf->vma) {
+               dprintk(1, "failed to copy vma\n");
+               goto userptr_fail_find_vma;
+       }
+
+       if (vma_is_io(buf->vma)) {
+               for (num_pages_from_user = 0;
+                    num_pages_from_user < buf->num_pages;
+                    ++num_pages_from_user, vaddr += PAGE_SIZE) {
+                       unsigned long pfn;
 
-       num_pages_from_user = get_user_pages(current, current->mm,
+                       if (follow_pfn(buf->vma, vaddr, &pfn)) {
+                               dprintk(1, "no page for address %lu\n", vaddr);
+                               break;
+                       }
+                       buf->pages[num_pages_from_user] = pfn_to_page(pfn);
+               }
+       } else
+               num_pages_from_user = get_user_pages(current, current->mm,
                                             vaddr & PAGE_MASK,
                                             buf->num_pages,
                                             write,
@@ -200,10 +238,14 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
 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->num_pages);
-       while (--num_pages_from_user >= 0)
-               put_page(buf->pages[num_pages_from_user]);
+               buf->num_pages, num_pages_from_user);
+       if (!vma_is_io(buf->vma))
+               while (--num_pages_from_user >= 0)
+                       put_page(buf->pages[num_pages_from_user]);
+       vb2_put_vma(buf->vma);
+userptr_fail_find_vma:
        kfree(buf->pages);
+userptr_fail_alloc_pages:
        kfree(buf);
        return NULL;
 }
@@ -225,9 +267,11 @@ static void vb2_dma_sg_put_userptr(void *buf_priv)
        while (--i >= 0) {
                if (buf->write)
                        set_page_dirty_lock(buf->pages[i]);
-               put_page(buf->pages[i]);
+               if (!vma_is_io(buf->vma))
+                       put_page(buf->pages[i]);
        }
        kfree(buf->pages);
+       vb2_put_vma(buf->vma);
        kfree(buf);
 }
 
index dd239bdbfcb4a0877db2ab49aa3c27a81eec7dd1..00d339c361fc0ecbd0b9b086e8c5756d28983d77 100644 (file)
@@ -2235,10 +2235,10 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
        }
 
        /* do we need to support multiple segments? */
-       if (bio_segments(req->bio) > 1 || bio_segments(rsp->bio) > 1) {
-               printk(MYIOC_s_ERR_FMT "%s: multiple segments req %u %u, rsp %u %u\n",
-                   ioc->name, __func__, bio_segments(req->bio), blk_rq_bytes(req),
-                   bio_segments(rsp->bio), blk_rq_bytes(rsp));
+       if (bio_multiple_segments(req->bio) ||
+           bio_multiple_segments(rsp->bio)) {
+               printk(MYIOC_s_ERR_FMT "%s: multiple segments req %u, rsp %u\n",
+                   ioc->name, __func__, blk_rq_bytes(req), blk_rq_bytes(rsp));
                return -EINVAL;
        }
 
index a65447d65605fe7d7539082322a70cceae9c18c7..7dca1e640970a0dfb7f28ad8909c1f3e4d7d26e4 100644 (file)
@@ -148,7 +148,7 @@ static struct resource onkey_resources[] = {
         },
 };
 
-static struct mfd_cell onkey_devs[] = {
+static const struct mfd_cell onkey_devs[] = {
        {
         .name = "88pm80x-onkey",
         .num_resources = 1,
@@ -157,7 +157,7 @@ static struct mfd_cell onkey_devs[] = {
         },
 };
 
-static struct mfd_cell regulator_devs[] = {
+static const struct mfd_cell regulator_devs[] = {
        {
         .name = "88pm80x-regulator",
         .id = -1,
index 8a5b6ffb5afb6fbedbd8a1364a879890a6ebfba5..64751c2a1ace8fc2f90e59c1a1ca404776aa04d0 100644 (file)
@@ -77,7 +77,7 @@ static struct resource codec_resources[] = {
         },
 };
 
-static struct mfd_cell codec_devs[] = {
+static const struct mfd_cell codec_devs[] = {
        {
         .name = "88pm80x-codec",
         .num_resources = ARRAY_SIZE(codec_resources),
index 62a60caa5d1fe7eb583cb208fef9b96a5b0dd8f0..58ed055c1c08b7e93ecf85b5ae191e86c6ba7549 100644 (file)
@@ -32,7 +32,7 @@ config MFD_AS3722
        select MFD_CORE
        select REGMAP_I2C
        select REGMAP_IRQ
-       depends on I2C && OF
+       depends on I2C=y && OF
        help
          The ams AS3722 is a compact system PMU suitable for mobile phones,
          tablets etc. It has 4 DC/DC step-down regulators, 3 DC/DC step-down
@@ -80,7 +80,7 @@ config MFD_CROS_EC_I2C
 
 config MFD_CROS_EC_SPI
        tristate "ChromeOS Embedded Controller (SPI)"
-       depends on MFD_CROS_EC && SPI
+       depends on MFD_CROS_EC && SPI && OF
 
        ---help---
          If you say Y here, you get support for talking to the ChromeOS EC
@@ -321,6 +321,19 @@ config MFD_88PM860X
          select individual components like voltage regulators, RTC and
          battery-charger under the corresponding menus.
 
+config MFD_MAX14577
+       bool "Maxim Semiconductor MAX14577 MUIC + Charger Support"
+       depends on I2C=y
+       select MFD_CORE
+       select REGMAP_I2C
+       select IRQ_DOMAIN
+       help
+         Say yes here to support for Maxim Semiconductor MAX14577.
+         This is a Micro-USB IC with Charger controls on chip.
+         This driver provides common support for accessing the device;
+         additional drivers must be enabled in order to use the functionality
+         of the device.
+
 config MFD_MAX77686
        bool "Maxim Semiconductor MAX77686 PMIC Support"
        depends on I2C=y
@@ -725,6 +738,17 @@ config MFD_DM355EVM_MSP
          boards.  MSP430 firmware manages resets and power sequencing,
          inputs from buttons and the IR remote, LEDs, an RTC, and more.
 
+config MFD_LP3943
+       tristate "TI/National Semiconductor LP3943 MFD Driver"
+       depends on I2C
+       select MFD_CORE
+       select REGMAP_I2C
+       help
+         Support for the TI/National Semiconductor LP3943.
+         This driver consists of GPIO and PWM drivers.
+         With these functionalities, it can be used for LED string control or
+         general usage such like a GPIO controller and a PWM controller.
+
 config MFD_LP8788
        bool "TI LP8788 Power Management Unit Driver"
        depends on I2C=y
index 8a28dc90fe785033452a1740973f34883abbe0de..5aea5ef0a62f51eff03a14404569c68a7700262f 100644 (file)
@@ -102,6 +102,7 @@ obj-$(CONFIG_PMIC_DA9052)   += da9052-core.o
 obj-$(CONFIG_MFD_DA9052_SPI)   += da9052-spi.o
 obj-$(CONFIG_MFD_DA9052_I2C)   += da9052-i2c.o
 
+obj-$(CONFIG_MFD_LP3943)       += lp3943.o
 obj-$(CONFIG_MFD_LP8788)       += lp8788.o lp8788-irq.o
 
 da9055-objs                    := da9055-core.o da9055-i2c.o
@@ -110,6 +111,7 @@ obj-$(CONFIG_MFD_DA9055)    += da9055.o
 da9063-objs                    := da9063-core.o da9063-irq.o da9063-i2c.o
 obj-$(CONFIG_MFD_DA9063)       += da9063.o
 
+obj-$(CONFIG_MFD_MAX14577)     += max14577.o
 obj-$(CONFIG_MFD_MAX77686)     += max77686.o max77686-irq.o
 obj-$(CONFIG_MFD_MAX77693)     += max77693.o max77693-irq.o
 obj-$(CONFIG_MFD_MAX8907)      += max8907.o
index b6c2cdc76091aa2ff78b8d1d17e3c7b6e6d1dbd0..aaff683cd37d43809bb8da6b1cd5c085f1bf664a 100644 (file)
@@ -491,7 +491,7 @@ static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500,
                if (line == AB8540_INT_GPIO43F || line == AB8540_INT_GPIO44F)
                        line += 1;
 
-               handle_nested_irq(ab8500->irq_base + line);
+               handle_nested_irq(irq_create_mapping(ab8500->domain, line));
        }
 
        return 0;
@@ -1017,7 +1017,7 @@ static struct resource ab8500_temp_resources[] = {
        },
 };
 
-static struct mfd_cell ab8500_bm_devs[] = {
+static const struct mfd_cell ab8500_bm_devs[] = {
        {
                .name = "ab8500-charger",
                .of_compatible = "stericsson,ab8500-charger",
@@ -1052,7 +1052,7 @@ static struct mfd_cell ab8500_bm_devs[] = {
        },
 };
 
-static struct mfd_cell ab8500_devs[] = {
+static const struct mfd_cell ab8500_devs[] = {
 #ifdef CONFIG_DEBUG_FS
        {
                .name = "ab8500-debug",
@@ -1143,7 +1143,7 @@ static struct mfd_cell ab8500_devs[] = {
        },
 };
 
-static struct mfd_cell ab9540_devs[] = {
+static const struct mfd_cell ab9540_devs[] = {
 #ifdef CONFIG_DEBUG_FS
        {
                .name = "ab8500-debug",
@@ -1214,7 +1214,7 @@ static struct mfd_cell ab9540_devs[] = {
 };
 
 /* Device list for ab8505  */
-static struct mfd_cell ab8505_devs[] = {
+static const struct mfd_cell ab8505_devs[] = {
 #ifdef CONFIG_DEBUG_FS
        {
                .name = "ab8500-debug",
@@ -1275,7 +1275,7 @@ static struct mfd_cell ab8505_devs[] = {
        },
 };
 
-static struct mfd_cell ab8540_devs[] = {
+static const struct mfd_cell ab8540_devs[] = {
 #ifdef CONFIG_DEBUG_FS
        {
                .name = "ab8500-debug",
@@ -1339,7 +1339,7 @@ static struct mfd_cell ab8540_devs[] = {
        },
 };
 
-static struct mfd_cell ab8540_cut1_devs[] = {
+static const struct mfd_cell ab8540_cut1_devs[] = {
        {
                .name = "ab8500-rtc",
                .of_compatible = "stericsson,ab8500-rtc",
@@ -1348,7 +1348,7 @@ static struct mfd_cell ab8540_cut1_devs[] = {
        },
 };
 
-static struct mfd_cell ab8540_cut2_devs[] = {
+static const struct mfd_cell ab8540_cut2_devs[] = {
        {
                .name = "ab8540-rtc",
                .of_compatible = "stericsson,ab8540-rtc",
index e33e385af0a29e7930e4277984c640a1cf1db975..d1a22aae2df51cda0936a52dc58e9df66c493f7d 100644 (file)
@@ -1600,7 +1600,6 @@ static int ab8500_interrupts_print(struct seq_file *s, void *p)
 
        for (line = 0; line < num_interrupt_lines; line++) {
                struct irq_desc *desc = irq_to_desc(line + irq_first);
-               struct irqaction *action = desc->action;
 
                seq_printf(s, "%3i:  %6i %4i", line,
                           num_interrupts[line],
@@ -1608,7 +1607,9 @@ static int ab8500_interrupts_print(struct seq_file *s, void *p)
 
                if (desc && desc->name)
                        seq_printf(s, "-%-8s", desc->name);
-               if (action) {
+               if (desc && desc->action) {
+                       struct irqaction *action = desc->action;
+
                        seq_printf(s, "  %s", action->name);
                        while ((action = action->next) != NULL)
                                seq_printf(s, ", %s", action->name);
index 75e180ceecf3fac16f9a432ada482130624dfe01..a45aab9f6bb135e64c0f0a420f75ed2508e17e92 100644 (file)
@@ -565,7 +565,7 @@ static inline int arizona_of_get_core_pdata(struct arizona *arizona)
 }
 #endif
 
-static struct mfd_cell early_devs[] = {
+static const struct mfd_cell early_devs[] = {
        { .name = "arizona-ldo1" },
 };
 
@@ -577,7 +577,7 @@ static const char *wm5102_supplies[] = {
        "SPKVDDR",
 };
 
-static struct mfd_cell wm5102_devs[] = {
+static const struct mfd_cell wm5102_devs[] = {
        { .name = "arizona-micsupp" },
        { .name = "arizona-extcon" },
        { .name = "arizona-gpio" },
@@ -590,7 +590,7 @@ static struct mfd_cell wm5102_devs[] = {
        },
 };
 
-static struct mfd_cell wm5110_devs[] = {
+static const struct mfd_cell wm5110_devs[] = {
        { .name = "arizona-micsupp" },
        { .name = "arizona-extcon" },
        { .name = "arizona-gpio" },
@@ -609,7 +609,7 @@ static const char *wm8997_supplies[] = {
        "SPKVDD",
 };
 
-static struct mfd_cell wm8997_devs[] = {
+static const struct mfd_cell wm8997_devs[] = {
        { .name = "arizona-micsupp" },
        { .name = "arizona-extcon" },
        { .name = "arizona-gpio" },
index f161f2e00df7434ee8970584e76392af68304179..c71ff0af1547e573aacf17c6317e2e02224813f7 100644 (file)
@@ -54,7 +54,7 @@ static const struct resource as3722_adc_resource[] = {
        },
 };
 
-static struct mfd_cell as3722_devs[] = {
+static const struct mfd_cell as3722_devs[] = {
        {
                .name = "as3722-pinctrl",
        },
@@ -74,6 +74,9 @@ static struct mfd_cell as3722_devs[] = {
        {
                .name = "as3722-power-off",
        },
+       {
+               .name = "as3722-wdt",
+       },
 };
 
 static const struct regmap_irq as3722_irqs[] = {
index fa22154c84e49cfb6be58930339ea180b8be77b6..9f6294f2a0708ab6be063d4bfbc0f98ad1062fa5 100644 (file)
@@ -695,7 +695,7 @@ static int ds1wm_disable(struct platform_device *pdev)
        return 0;
 }
 
-static struct mfd_cell asic3_cell_ds1wm = {
+static const struct mfd_cell asic3_cell_ds1wm = {
        .name          = "ds1wm",
        .enable        = ds1wm_enable,
        .disable       = ds1wm_disable,
@@ -797,7 +797,7 @@ static int asic3_mmc_disable(struct platform_device *pdev)
        return 0;
 }
 
-static struct mfd_cell asic3_cell_mmc = {
+static const struct mfd_cell asic3_cell_mmc = {
        .name          = "tmio-mmc",
        .enable        = asic3_mmc_enable,
        .disable       = asic3_mmc_disable,
index 1f36885d674b07741a4f0374089f2cb04ed839e4..783fe2e73e1edd43344d3bb4c3b1fb09daf9cf3d 100644 (file)
@@ -84,7 +84,7 @@ static irqreturn_t ec_irq_thread(int irq, void *data)
        return IRQ_HANDLED;
 }
 
-static struct mfd_cell cros_devs[] = {
+static const struct mfd_cell cros_devs[] = {
        {
                .name = "cros-ec-keyb",
                .id = 1,
index 123044608b63dc5997f9cf921003814f9ac53f84..4f71be99a183713810c5d00e7f4eac480e006a58 100644 (file)
@@ -120,7 +120,7 @@ static int cros_ec_command_xfer(struct cros_ec_device *ec_dev,
        return ret;
 }
 
-static int cros_ec_probe_i2c(struct i2c_client *client,
+static int cros_ec_i2c_probe(struct i2c_client *client,
                             const struct i2c_device_id *dev_id)
 {
        struct device *dev = &client->dev;
@@ -150,7 +150,7 @@ static int cros_ec_probe_i2c(struct i2c_client *client,
        return 0;
 }
 
-static int cros_ec_remove_i2c(struct i2c_client *client)
+static int cros_ec_i2c_remove(struct i2c_client *client)
 {
        struct cros_ec_device *ec_dev = i2c_get_clientdata(client);
 
@@ -190,8 +190,8 @@ static struct i2c_driver cros_ec_driver = {
                .owner  = THIS_MODULE,
                .pm     = &cros_ec_i2c_pm_ops,
        },
-       .probe          = cros_ec_probe_i2c,
-       .remove         = cros_ec_remove_i2c,
+       .probe          = cros_ec_i2c_probe,
+       .remove         = cros_ec_i2c_remove,
        .id_table       = cros_ec_i2c_id,
 };
 
index 367ccb58ecb15a1954cf39e936c46bc5a4bf3498..d64d88a9e247a1bbac7ad3911fca430f936390d5 100644 (file)
 /*
   * Time between raising the SPI chip select (for the end of a
   * transaction) and dropping it again (for the next transaction).
-  * If we go too fast, the EC will miss the transaction. It seems
-  * that 50us is enough with the 16MHz STM32 EC.
+  * If we go too fast, the EC will miss the transaction. We know that we
+  * need at least 70 us with the 16 MHz STM32 EC, so go with 200 us to be
+  * safe.
   */
-#define EC_SPI_RECOVERY_TIME_NS        (50 * 1000)
+#define EC_SPI_RECOVERY_TIME_NS        (200 * 1000)
 
 /**
  * struct cros_ec_spi - information about a SPI-connected EC
@@ -75,7 +76,9 @@ static void debug_packet(struct device *dev, const char *name, u8 *ptr,
 
        dev_dbg(dev, "%s: ", name);
        for (i = 0; i < len; i++)
-               dev_cont(dev, " %02x", ptr[i]);
+               pr_cont(" %02x", ptr[i]);
+
+       pr_cont("\n");
 #endif
 }
 
@@ -281,7 +284,7 @@ static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev,
        return 0;
 }
 
-static int cros_ec_probe_spi(struct spi_device *spi)
+static int cros_ec_spi_probe(struct spi_device *spi)
 {
        struct device *dev = &spi->dev;
        struct cros_ec_device *ec_dev;
@@ -323,7 +326,7 @@ static int cros_ec_probe_spi(struct spi_device *spi)
        return 0;
 }
 
-static int cros_ec_remove_spi(struct spi_device *spi)
+static int cros_ec_spi_remove(struct spi_device *spi)
 {
        struct cros_ec_device *ec_dev;
 
@@ -364,12 +367,12 @@ static struct spi_driver cros_ec_driver_spi = {
                .owner  = THIS_MODULE,
                .pm     = &cros_ec_spi_pm_ops,
        },
-       .probe          = cros_ec_probe_spi,
-       .remove         = cros_ec_remove_spi,
+       .probe          = cros_ec_spi_probe,
+       .remove         = cros_ec_spi_remove,
        .id_table       = cros_ec_spi_id,
 };
 
 module_spi_driver(cros_ec_driver_spi);
 
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("ChromeOS EC multi function device (SPI)");
index 2e4752a9220a92808e98e52a0dc6c50ecccf0068..17c13012686af663ba970f4c423a4262aa602b58 100644 (file)
@@ -172,7 +172,7 @@ static void cs5535_mfd_remove(struct pci_dev *pdev)
        pci_disable_device(pdev);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(cs5535_mfd_pci_tbl) = {
+static const struct pci_device_id cs5535_mfd_pci_tbl[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA) },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) },
        { 0, }
index ea28a33576e45cd3c3df406a09264bd69a5c3298..25838f10b35b2d08c295e18b27ecf4155bb5f4ce 100644 (file)
@@ -427,7 +427,7 @@ int da9052_adc_read_temp(struct da9052 *da9052)
 }
 EXPORT_SYMBOL_GPL(da9052_adc_read_temp);
 
-static struct mfd_cell da9052_subdev_info[] = {
+static const struct mfd_cell da9052_subdev_info[] = {
        {
                .name = "da9052-regulator",
                .id = 1,
index d3670cd3c3c6c0e025c80ec940851ee5599037b1..caf8dcffd0ad403d6b239f9f0c3442ac1651aa2c 100644 (file)
@@ -294,7 +294,7 @@ static struct resource da9055_ld05_6_resource = {
        .flags = IORESOURCE_IRQ,
 };
 
-static struct mfd_cell da9055_devs[] = {
+static const struct mfd_cell da9055_devs[] = {
        {
                .of_compatible = "dialog,da9055-gpio",
                .name = "da9055-gpio",
index c9cf8d988406ff8ed4d01c23d5acd6793e3d06e4..26937cd010714b7c1c9e98877603616390b6e952 100644 (file)
@@ -75,7 +75,7 @@ static struct resource da9063_hwmon_resources[] = {
 };
 
 
-static struct mfd_cell da9063_devs[] = {
+static const struct mfd_cell da9063_devs[] = {
        {
                .name           = DA9063_DRVNAME_REGULATORS,
                .num_resources  = ARRAY_SIZE(da9063_regulators_resources),
index b9ce60c301de026bba38daf276e83773c44379ec..e43e6e821117a01aac56b8e4086fe783056977cd 100644 (file)
@@ -3070,7 +3070,7 @@ static struct db8500_thsens_platform_data db8500_thsens_data = {
        .num_trips = 4,
 };
 
-static struct mfd_cell common_prcmu_devs[] = {
+static const struct mfd_cell common_prcmu_devs[] = {
        {
                .name = "ux500_wdt",
                .platform_data = &db8500_wdt_pdata,
@@ -3079,7 +3079,7 @@ static struct mfd_cell common_prcmu_devs[] = {
        },
 };
 
-static struct mfd_cell db8500_prcmu_devs[] = {
+static const struct mfd_cell db8500_prcmu_devs[] = {
        {
                .name = "db8500-prcmu-regulators",
                .of_compatible = "stericsson,db8500-prcmu-regulator",
index 6bf92a507b9546b911e258037c2dba3ac391851b..e88d4f6fef4cb80b76bdea85498056e6b272874a 100644 (file)
@@ -114,7 +114,7 @@ static struct resource ds1wm_resources[] __initdata = {
        },
 };
 
-static struct mfd_cell ds1wm_cell __initdata = {
+static const struct mfd_cell ds1wm_cell __initconst = {
        .name          = "ds1wm",
        .enable        = ds1wm_enable,
        .disable       = ds1wm_disable,
index 9203d47cdbb1b4106e87ba91e4571cea54c55543..049fd23af54a58f85a51ae564ae2bdc49e3bcdd0 100644 (file)
@@ -178,7 +178,7 @@ static struct mfd_cell msic_devs[] = {
  * These devices appear only after the MSIC driver itself is initialized so
  * we can guarantee that the SCU IPC interface is ready.
  */
-static struct mfd_cell msic_other_devs[] = {
+static const struct mfd_cell msic_other_devs[] = {
        /* Audio codec in the MSIC */
        {
                .id                     = -1,
index fcbb2e9dfd3706af3d6dd0cccfaa6f45693d7328..81b7d88af3135cc7d26bd0e3afb842497b58024c 100644 (file)
@@ -265,7 +265,7 @@ static void cmodio_pci_remove(struct pci_dev *dev)
 #define PCI_VENDOR_ID_JANZ             0x13c3
 
 /* The list of devices that this module will support */
-static DEFINE_PCI_DEVICE_TABLE(cmodio_pci_ids) = {
+static const struct pci_device_id cmodio_pci_ids[] = {
        { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030, PCI_VENDOR_ID_JANZ, 0x0101 },
        { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_JANZ, 0x0100 },
        { 0, }
index 3c0e8cf6916bd0f9cdb040548b7b7919d3f49753..7a51c0d0d4f1f5ec23b323550424cec4ff6386a7 100644 (file)
@@ -181,7 +181,7 @@ static struct resource jz4740_battery_resources[] = {
        },
 };
 
-static struct mfd_cell jz4740_adc_cells[] = {
+static const struct mfd_cell jz4740_adc_cells[] = {
        {
                .id = 0,
                .name = "jz4740-hwmon",
diff --git a/drivers/mfd/lp3943.c b/drivers/mfd/lp3943.c
new file mode 100644 (file)
index 0000000..e322268
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * TI/National Semiconductor LP3943 MFD Core Driver
+ *
+ * Copyright 2013 Texas Instruments
+ *
+ * Author: Milo Kim <milo.kim@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Driver structure:
+ *   LP3943 is an integrated device capable of driving 16 output channels.
+ *   It can be used for a GPIO expander and PWM generators.
+ *
+ *                                   LED control    General usage for a device
+ *                                   ___________   ____________________________
+ *
+ *   LP3943 MFD ---- GPIO expander    leds-gpio        eg) HW enable pin
+ *               |
+ *               --- PWM generator    leds-pwm         eg) PWM input
+ *
+ *   Internal two PWM channels are used for LED dimming effect.
+ *   And each output pin can be used as a GPIO as well.
+ *   The LED functionality can work with GPIOs or PWMs.
+ *   LEDs can be controlled with legacy leds-gpio(static brightness) or
+ *   leds-pwm drivers(dynamic brightness control).
+ *   Alternatively, it can be used for generic GPIO and PWM controller.
+ *   For example, a GPIO is HW enable pin of a device.
+ *   A PWM is input pin of a backlight device.
+ */
+
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/lp3943.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+
+#define LP3943_MAX_REGISTERS           0x09
+
+/* Register configuration for pin MUX */
+static const struct lp3943_reg_cfg lp3943_mux_cfg[] = {
+       /* address, mask, shift */
+       { LP3943_REG_MUX0, 0x03, 0 },
+       { LP3943_REG_MUX0, 0x0C, 2 },
+       { LP3943_REG_MUX0, 0x30, 4 },
+       { LP3943_REG_MUX0, 0xC0, 6 },
+       { LP3943_REG_MUX1, 0x03, 0 },
+       { LP3943_REG_MUX1, 0x0C, 2 },
+       { LP3943_REG_MUX1, 0x30, 4 },
+       { LP3943_REG_MUX1, 0xC0, 6 },
+       { LP3943_REG_MUX2, 0x03, 0 },
+       { LP3943_REG_MUX2, 0x0C, 2 },
+       { LP3943_REG_MUX2, 0x30, 4 },
+       { LP3943_REG_MUX2, 0xC0, 6 },
+       { LP3943_REG_MUX3, 0x03, 0 },
+       { LP3943_REG_MUX3, 0x0C, 2 },
+       { LP3943_REG_MUX3, 0x30, 4 },
+       { LP3943_REG_MUX3, 0xC0, 6 },
+};
+
+static struct mfd_cell lp3943_devs[] = {
+       {
+               .name = "lp3943-pwm",
+               .of_compatible = "ti,lp3943-pwm",
+       },
+       {
+               .name = "lp3943-gpio",
+               .of_compatible = "ti,lp3943-gpio",
+       },
+};
+
+int lp3943_read_byte(struct lp3943 *lp3943, u8 reg, u8 *read)
+{
+       int ret;
+       unsigned int val;
+
+       ret = regmap_read(lp3943->regmap, reg, &val);
+       if (ret < 0)
+               return ret;
+
+       *read = (u8)val;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(lp3943_read_byte);
+
+int lp3943_write_byte(struct lp3943 *lp3943, u8 reg, u8 data)
+{
+       return regmap_write(lp3943->regmap, reg, data);
+}
+EXPORT_SYMBOL_GPL(lp3943_write_byte);
+
+int lp3943_update_bits(struct lp3943 *lp3943, u8 reg, u8 mask, u8 data)
+{
+       return regmap_update_bits(lp3943->regmap, reg, mask, data);
+}
+EXPORT_SYMBOL_GPL(lp3943_update_bits);
+
+static const struct regmap_config lp3943_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .max_register = LP3943_MAX_REGISTERS,
+};
+
+static int lp3943_probe(struct i2c_client *cl, const struct i2c_device_id *id)
+{
+       struct lp3943 *lp3943;
+       struct device *dev = &cl->dev;
+
+       lp3943 = devm_kzalloc(dev, sizeof(*lp3943), GFP_KERNEL);
+       if (!lp3943)
+               return -ENOMEM;
+
+       lp3943->regmap = devm_regmap_init_i2c(cl, &lp3943_regmap_config);
+       if (IS_ERR(lp3943->regmap))
+               return PTR_ERR(lp3943->regmap);
+
+       lp3943->pdata = dev_get_platdata(dev);
+       lp3943->dev = dev;
+       lp3943->mux_cfg = lp3943_mux_cfg;
+       i2c_set_clientdata(cl, lp3943);
+
+       return mfd_add_devices(dev, -1, lp3943_devs, ARRAY_SIZE(lp3943_devs),
+                              NULL, 0, NULL);
+}
+
+static int lp3943_remove(struct i2c_client *cl)
+{
+       struct lp3943 *lp3943 = i2c_get_clientdata(cl);
+
+       mfd_remove_devices(lp3943->dev);
+       return 0;
+}
+
+static const struct i2c_device_id lp3943_ids[] = {
+       { "lp3943", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, lp3943_ids);
+
+#ifdef CONFIG_OF
+static const struct of_device_id lp3943_of_match[] = {
+       { .compatible = "ti,lp3943", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, lp3943_of_match);
+#endif
+
+static struct i2c_driver lp3943_driver = {
+       .probe = lp3943_probe,
+       .remove = lp3943_remove,
+       .driver = {
+               .name = "lp3943",
+               .owner = THIS_MODULE,
+               .of_match_table = of_match_ptr(lp3943_of_match),
+       },
+       .id_table = lp3943_ids,
+};
+
+module_i2c_driver(lp3943_driver);
+
+MODULE_DESCRIPTION("LP3943 MFD Core Driver");
+MODULE_AUTHOR("Milo Kim");
+MODULE_LICENSE("GPL");
index 0f1221911018b6d4fd4e558ff0df4996a4b70a10..a30bc15fe5ba5ac6a5b2a04a23a3a518ae2d2ba5 100644 (file)
@@ -71,7 +71,7 @@ static struct resource rtc_irqs[] = {
        },
 };
 
-static struct mfd_cell lp8788_devs[] = {
+static const struct mfd_cell lp8788_devs[] = {
        /* 4 bucks */
        MFD_DEV_WITH_ID(BUCK, 1),
        MFD_DEV_WITH_ID(BUCK, 2),
index da1c6566d93d2f755878d358a018835bd7cd1454..be93fa261dedb4c808955c1830932f84a48b7524 100644 (file)
@@ -506,7 +506,7 @@ static struct lpc_ich_info lpc_chipset_info[] = {
                .iTCO_version = 2,
        },
        [LPC_WPT_LP] = {
-               .name = "Lynx Point_LP",
+               .name = "Wildcat Point_LP",
                .iTCO_version = 2,
        },
 };
@@ -517,7 +517,7 @@ static struct lpc_ich_info lpc_chipset_info[] = {
  * pci_driver, because the I/O Controller Hub has also other
  * functions that probably will be registered by other drivers.
  */
-static DEFINE_PCI_DEVICE_TABLE(lpc_ich_ids) = {
+static const struct pci_device_id lpc_ich_ids[] = {
        { PCI_VDEVICE(INTEL, 0x2410), LPC_ICH},
        { PCI_VDEVICE(INTEL, 0x2420), LPC_ICH0},
        { PCI_VDEVICE(INTEL, 0x2440), LPC_ICH2},
index fbfbf0b7f97ac1cfad5d8964a7436fa05122a89f..3bb05c03c68ded9f3e6c807a1c3559ec66830a94 100644 (file)
@@ -76,7 +76,7 @@ static struct mfd_cell wdt_sch_cell = {
        .ignore_resource_conflicts = true,
 };
 
-static DEFINE_PCI_DEVICE_TABLE(lpc_sch_ids) = {
+static const struct pci_device_id lpc_sch_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SCH_LPC) },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ITC_LPC) },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CENTERTON_ILB) },
diff --git a/drivers/mfd/max14577.c b/drivers/mfd/max14577.c
new file mode 100644 (file)
index 0000000..a5e1c37
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * max14577.c - mfd core driver for the Maxim 14577
+ *
+ * Copyright (C) 2013 Samsung Electrnoics
+ * Chanwoo Choi <cw00.choi@samsung.com>
+ * Krzysztof Kozlowski <k.kozlowski@samsung.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.
+ *
+ * This driver is based on max8997.c
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/max14577.h>
+#include <linux/mfd/max14577-private.h>
+
+static struct mfd_cell max14577_devs[] = {
+       { .name = "max14577-muic", },
+       {
+               .name = "max14577-regulator",
+               .of_compatible = "maxim,max14577-regulator",
+       },
+       { .name = "max14577-charger", },
+};
+
+static bool max14577_volatile_reg(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case MAX14577_REG_INT1 ... MAX14577_REG_STATUS3:
+               return true;
+       default:
+               break;
+       }
+       return false;
+}
+
+static const struct regmap_config max14577_regmap_config = {
+       .reg_bits       = 8,
+       .val_bits       = 8,
+       .volatile_reg   = max14577_volatile_reg,
+       .max_register   = MAX14577_REG_END,
+};
+
+static const struct regmap_irq max14577_irqs[] = {
+       /* INT1 interrupts */
+       { .reg_offset = 0, .mask = INT1_ADC_MASK, },
+       { .reg_offset = 0, .mask = INT1_ADCLOW_MASK, },
+       { .reg_offset = 0, .mask = INT1_ADCERR_MASK, },
+       /* INT2 interrupts */
+       { .reg_offset = 1, .mask = INT2_CHGTYP_MASK, },
+       { .reg_offset = 1, .mask = INT2_CHGDETRUN_MASK, },
+       { .reg_offset = 1, .mask = INT2_DCDTMR_MASK, },
+       { .reg_offset = 1, .mask = INT2_DBCHG_MASK, },
+       { .reg_offset = 1, .mask = INT2_VBVOLT_MASK, },
+       /* INT3 interrupts */
+       { .reg_offset = 2, .mask = INT3_EOC_MASK, },
+       { .reg_offset = 2, .mask = INT3_CGMBC_MASK, },
+       { .reg_offset = 2, .mask = INT3_OVP_MASK, },
+       { .reg_offset = 2, .mask = INT3_MBCCHGERR_MASK, },
+};
+
+static const struct regmap_irq_chip max14577_irq_chip = {
+       .name                   = "max14577",
+       .status_base            = MAX14577_REG_INT1,
+       .mask_base              = MAX14577_REG_INTMASK1,
+       .mask_invert            = 1,
+       .num_regs               = 3,
+       .irqs                   = max14577_irqs,
+       .num_irqs               = ARRAY_SIZE(max14577_irqs),
+};
+
+static int max14577_i2c_probe(struct i2c_client *i2c,
+                             const struct i2c_device_id *id)
+{
+       struct max14577 *max14577;
+       struct max14577_platform_data *pdata = dev_get_platdata(&i2c->dev);
+       struct device_node *np = i2c->dev.of_node;
+       u8 reg_data;
+       int ret = 0;
+
+       if (np) {
+               pdata = devm_kzalloc(&i2c->dev, sizeof(*pdata), GFP_KERNEL);
+               if (!pdata)
+                       return -ENOMEM;
+               i2c->dev.platform_data = pdata;
+       }
+
+       if (!pdata) {
+               dev_err(&i2c->dev, "No platform data found.\n");
+               return -EINVAL;
+       }
+
+       max14577 = devm_kzalloc(&i2c->dev, sizeof(*max14577), GFP_KERNEL);
+       if (!max14577)
+               return -ENOMEM;
+
+       i2c_set_clientdata(i2c, max14577);
+       max14577->dev = &i2c->dev;
+       max14577->i2c = i2c;
+       max14577->irq = i2c->irq;
+
+       max14577->regmap = devm_regmap_init_i2c(i2c, &max14577_regmap_config);
+       if (IS_ERR(max14577->regmap)) {
+               ret = PTR_ERR(max14577->regmap);
+               dev_err(max14577->dev, "Failed to allocate register map: %d\n",
+                               ret);
+               return ret;
+       }
+
+       ret = max14577_read_reg(max14577->regmap, MAX14577_REG_DEVICEID,
+                       &reg_data);
+       if (ret) {
+               dev_err(max14577->dev, "Device not found on this channel: %d\n",
+                               ret);
+               return ret;
+       }
+       max14577->vendor_id = ((reg_data & DEVID_VENDORID_MASK) >>
+                               DEVID_VENDORID_SHIFT);
+       max14577->device_id = ((reg_data & DEVID_DEVICEID_MASK) >>
+                               DEVID_DEVICEID_SHIFT);
+       dev_info(max14577->dev, "Device ID: 0x%x, vendor: 0x%x\n",
+                       max14577->device_id, max14577->vendor_id);
+
+       ret = regmap_add_irq_chip(max14577->regmap, max14577->irq,
+                                 IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 0,
+                                 &max14577_irq_chip,
+                                 &max14577->irq_data);
+       if (ret != 0) {
+               dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n",
+                               max14577->irq, ret);
+               return ret;
+       }
+
+       ret = mfd_add_devices(max14577->dev, -1, max14577_devs,
+                       ARRAY_SIZE(max14577_devs), NULL, 0,
+                       regmap_irq_get_domain(max14577->irq_data));
+       if (ret < 0)
+               goto err_mfd;
+
+       device_init_wakeup(max14577->dev, 1);
+
+       return 0;
+
+err_mfd:
+       regmap_del_irq_chip(max14577->irq, max14577->irq_data);
+
+       return ret;
+}
+
+static int max14577_i2c_remove(struct i2c_client *i2c)
+{
+       struct max14577 *max14577 = i2c_get_clientdata(i2c);
+
+       mfd_remove_devices(max14577->dev);
+       regmap_del_irq_chip(max14577->irq, max14577->irq_data);
+
+       return 0;
+}
+
+static const struct i2c_device_id max14577_i2c_id[] = {
+       { "max14577", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, max14577_i2c_id);
+
+static int max14577_suspend(struct device *dev)
+{
+       struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+       struct max14577 *max14577 = i2c_get_clientdata(i2c);
+
+       if (device_may_wakeup(dev)) {
+               enable_irq_wake(max14577->irq);
+               /*
+                * MUIC IRQ must be disabled during suspend if this is
+                * a wake up source because it will be handled before
+                * resuming I2C.
+                *
+                * When device is woken up from suspend (e.g. by ADC change),
+                * an interrupt occurs before resuming I2C bus controller.
+                * Interrupt handler tries to read registers but this read
+                * will fail because I2C is still suspended.
+                */
+               disable_irq(max14577->irq);
+       }
+
+       return 0;
+}
+
+static int max14577_resume(struct device *dev)
+{
+       struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+       struct max14577 *max14577 = i2c_get_clientdata(i2c);
+
+       if (device_may_wakeup(dev)) {
+               disable_irq_wake(max14577->irq);
+               enable_irq(max14577->irq);
+       }
+
+       return 0;
+}
+
+static struct of_device_id max14577_dt_match[] = {
+       { .compatible = "maxim,max14577", },
+       {},
+};
+
+static SIMPLE_DEV_PM_OPS(max14577_pm, max14577_suspend, max14577_resume);
+
+static struct i2c_driver max14577_i2c_driver = {
+       .driver = {
+               .name = "max14577",
+               .owner = THIS_MODULE,
+               .pm = &max14577_pm,
+               .of_match_table = of_match_ptr(max14577_dt_match),
+       },
+       .probe = max14577_i2c_probe,
+       .remove = max14577_i2c_remove,
+       .id_table = max14577_i2c_id,
+};
+
+static int __init max14577_i2c_init(void)
+{
+       return i2c_add_driver(&max14577_i2c_driver);
+}
+subsys_initcall(max14577_i2c_init);
+
+static void __exit max14577_i2c_exit(void)
+{
+       i2c_del_driver(&max14577_i2c_driver);
+}
+module_exit(max14577_i2c_exit);
+
+MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>, Krzysztof Kozlowski <k.kozlowski@samsung.com>");
+MODULE_DESCRIPTION("MAXIM 14577 multi-function core driver");
+MODULE_LICENSE("GPL");
index 34520cbe8afbd6e9f0daca77f4bbde41b93697a6..fb0848544b768ab3a0943ddfe984b29cfeca4b53 100644 (file)
@@ -35,7 +35,7 @@
 
 #define I2C_ADDR_RTC   (0x0C >> 1)
 
-static struct mfd_cell max77686_devs[] = {
+static const struct mfd_cell max77686_devs[] = {
        { .name = "max77686-pmic", },
        { .name = "max77686-rtc", },
        { .name = "max77686-clk", },
index 9f92463f4f7ecaca1b005a14e6cd59f7d38deb4a..a0093a839d4b6fcb397f474248ee7962b2952b5d 100644 (file)
@@ -41,7 +41,7 @@
 #define I2C_ADDR_MUIC  (0x4A >> 1)
 #define I2C_ADDR_HAPTIC        (0x90 >> 1)
 
-static struct mfd_cell max77693_devs[] = {
+static const struct mfd_cell max77693_devs[] = {
        { .name = "max77693-pmic", },
        { .name = "max77693-charger", },
        { .name = "max77693-flash", },
index 3bbfedc07f41c8e24d866120b64423374c629fa3..07740314b29d03acc8068dcc56addd989abca5d1 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/regmap.h>
 #include <linux/slab.h>
 
-static struct mfd_cell max8907_cells[] = {
+static const struct mfd_cell max8907_cells[] = {
        { .name = "max8907-regulator", },
        { .name = "max8907-rtc", },
 };
index f0cc40296d8ccc50fab35f0805023bdab6ebc54f..f3faf0c45dddf36d09d4b2d05641145a7ebe13f6 100644 (file)
@@ -45,7 +45,7 @@ static struct resource touch_resources[] = {
        },
 };
 
-static struct mfd_cell touch_devs[] = {
+static const struct mfd_cell touch_devs[] = {
        {
                .name           = "max8925-touch",
                .num_resources  = 1,
@@ -63,7 +63,7 @@ static struct resource power_supply_resources[] = {
        },
 };
 
-static struct mfd_cell power_devs[] = {
+static const struct mfd_cell power_devs[] = {
        {
                .name           = "max8925-power",
                .num_resources  = 1,
@@ -81,7 +81,7 @@ static struct resource rtc_resources[] = {
        },
 };
 
-static struct mfd_cell rtc_devs[] = {
+static const struct mfd_cell rtc_devs[] = {
        {
                .name           = "max8925-rtc",
                .num_resources  = 1,
@@ -104,7 +104,7 @@ static struct resource onkey_resources[] = {
        },
 };
 
-static struct mfd_cell onkey_devs[] = {
+static const struct mfd_cell onkey_devs[] = {
        {
                .name           = "max8925-onkey",
                .num_resources  = 2,
index 791aea3e96ce27622032a0c0fd1bc52ecd69203e..1b80e51c2e73622b11769c6ddec449be50cd9044 100644 (file)
@@ -40,7 +40,7 @@
 #define I2C_ADDR_RTC   (0x0C >> 1)
 #define I2C_ADDR_HAPTIC        (0x90 >> 1)
 
-static struct mfd_cell max8997_devs[] = {
+static const struct mfd_cell max8997_devs[] = {
        { .name = "max8997-pmic", },
        { .name = "max8997-rtc", },
        { .name = "max8997-battery", },
index fe6332dcabee891a27daed80e3ed2525e3b1caa8..f47eaa70eae076f172f4e72977f98dfe26e680da 100644 (file)
@@ -37,7 +37,7 @@
 
 #define RTC_I2C_ADDR           (0x0c >> 1)
 
-static struct mfd_cell max8998_devs[] = {
+static const struct mfd_cell max8998_devs[] = {
        {
                .name = "max8998-pmic",
        }, {
@@ -47,7 +47,7 @@ static struct mfd_cell max8998_devs[] = {
        },
 };
 
-static struct mfd_cell lp3974_devs[] = {
+static const struct mfd_cell lp3974_devs[] = {
        {
                .name = "lp3974-pmic",
        }, {
index dbbf8ee3f592369fdd5aa968148e7aa307246580..b0c7cb04af8538f8a0d1903ac24128cae4fff78e 100644 (file)
@@ -158,9 +158,6 @@ int mc13xxx_reg_read(struct mc13xxx *mc13xxx, unsigned int offset, u32 *val)
 {
        int ret;
 
-       if (offset > MC13XXX_NUMREGS)
-               return -EINVAL;
-
        ret = regmap_read(mc13xxx->regmap, offset, val);
        dev_vdbg(mc13xxx->dev, "[0x%02x] -> 0x%06x\n", offset, *val);
 
@@ -172,7 +169,7 @@ int mc13xxx_reg_write(struct mc13xxx *mc13xxx, unsigned int offset, u32 val)
 {
        dev_vdbg(mc13xxx->dev, "[0x%02x] <- 0x%06x\n", offset, val);
 
-       if (offset > MC13XXX_NUMREGS || val > 0xffffff)
+       if (val >= BIT(24))
                return -EINVAL;
 
        return regmap_write(mc13xxx->regmap, offset, val);
index 5f14ef6693c22abd073b62ea6114dab2b09d76b8..cbcc86d9b6e7f88045c287516ba68fa67c453bb6 100644 (file)
@@ -149,7 +149,6 @@ static int mc13xxx_spi_probe(struct spi_device *spi)
                ret = PTR_ERR(mc13xxx->regmap);
                dev_err(mc13xxx->dev, "Failed to initialize register map: %d\n",
                                ret);
-               spi_set_drvdata(spi, NULL);
                return ret;
        }
 
index 142650fdc0582e1d25f99480e4a2fb13e1e9bd23..90b630ccc8bc65fa7381439cd190274834c50153 100644 (file)
@@ -121,22 +121,22 @@ static u64 usbhs_dmamask = DMA_BIT_MASK(32);
 
 static inline void usbhs_write(void __iomem *base, u32 reg, u32 val)
 {
-       __raw_writel(val, base + reg);
+       writel_relaxed(val, base + reg);
 }
 
 static inline u32 usbhs_read(void __iomem *base, u32 reg)
 {
-       return __raw_readl(base + reg);
+       return readl_relaxed(base + reg);
 }
 
 static inline void usbhs_writeb(void __iomem *base, u8 reg, u8 val)
 {
-       __raw_writeb(val, base + reg);
+       writeb_relaxed(val, base + reg);
 }
 
 static inline u8 usbhs_readb(void __iomem *base, u8 reg)
 {
-       return __raw_readb(base + reg);
+       return readb_relaxed(base + reg);
 }
 
 /*-------------------------------------------------------------------------*/
index 0d946ae14453380e4abca019a09519627309c5b6..ee7468c1cb60e8ebbbeb0499fb7edc8f5958fe06 100644 (file)
@@ -121,22 +121,22 @@ static DEFINE_SPINLOCK(tll_lock); /* serialize access to tll_dev */
 
 static inline void usbtll_write(void __iomem *base, u32 reg, u32 val)
 {
-       __raw_writel(val, base + reg);
+       writel_relaxed(val, base + reg);
 }
 
 static inline u32 usbtll_read(void __iomem *base, u32 reg)
 {
-       return __raw_readl(base + reg);
+       return readl_relaxed(base + reg);
 }
 
 static inline void usbtll_writeb(void __iomem *base, u8 reg, u8 val)
 {
-       __raw_writeb(val, base + reg);
+       writeb_relaxed(val, base + reg);
 }
 
 static inline u8 usbtll_readb(void __iomem *base, u8 reg)
 {
-       return __raw_readb(base + reg);
+       return readb_relaxed(base + reg);
 }
 
 /*-------------------------------------------------------------------------*/
index 6841d6805fd64a6aaab032ce121d4e3c63b36443..41ab5e34d2acb0a150f5ae9af8aab3774cfd01a3 100644 (file)
@@ -245,7 +245,7 @@ static int pcf50633_probe(struct i2c_client *client,
        for (i = 0; i < PCF50633_NUM_REGULATORS; i++) {
                struct platform_device *pdev;
 
-               pdev = platform_device_alloc("pcf50633-regltr", i);
+               pdev = platform_device_alloc("pcf50633-regulator", i);
                if (!pdev) {
                        dev_err(pcf->dev, "Cannot create regulator %d\n", i);
                        continue;
index 346330176afcd81ba9f6a294420db761e60ab908..df276ad9f40bfb32639c78b28ad7f2155e1f749f 100644 (file)
@@ -74,7 +74,7 @@ static struct deepsleep_control_data deepsleep_data[] = {
 #define EXT_PWR_REQ            \
        (RC5T583_EXT_PWRREQ1_CONTROL | RC5T583_EXT_PWRREQ2_CONTROL)
 
-static struct mfd_cell rc5t583_subdevs[] = {
+static const struct mfd_cell rc5t583_subdevs[] = {
        {.name = "rc5t583-gpio",},
        {.name = "rc5t583-regulator",},
        {.name = "rc5t583-rtc",      },
index 21b7bef73507cc969ae49074873f47b64b3ebe99..d346146249a2d387dbb5485c8517b5e662fac72a 100644 (file)
@@ -56,7 +56,7 @@ static struct resource rdc321x_gpio_resources[] = {
        }
 };
 
-static struct mfd_cell rdc321x_sb_cells[] = {
+static const struct mfd_cell rdc321x_sb_cells[] = {
        {
                .name           = "rdc321x-wdt",
                .resources      = rdc321x_wdt_resource,
@@ -96,7 +96,7 @@ static void rdc321x_sb_remove(struct pci_dev *pdev)
        mfd_remove_devices(&pdev->dev);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(rdc321x_sb_table) = {
+static const struct pci_device_id rdc321x_sb_table[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_RDC, PCI_DEVICE_ID_RDC_R6030) },
        {}
 };
index a1830986eeb71006b9c693e0aab1bb5e25d98e81..c8f345f7e9a2b574c69d5c2d47fa3dbcf1390993 100644 (file)
@@ -55,7 +55,7 @@ static struct resource retu_pwrbutton_res[] = {
        },
 };
 
-static struct mfd_cell retu_devs[] = {
+static const struct mfd_cell retu_devs[] = {
        {
                .name           = "retu-wdt"
        },
@@ -94,7 +94,7 @@ static struct resource tahvo_usb_res[] = {
        },
 };
 
-static struct mfd_cell tahvo_devs[] = {
+static const struct mfd_cell tahvo_devs[] = {
        {
                .name           = "tahvo-usb",
                .resources      = tahvo_usb_res,
@@ -122,7 +122,7 @@ static const struct retu_data {
        char                    *chip_name;
        char                    *companion_name;
        struct regmap_irq_chip  *irq_chip;
-       struct mfd_cell         *children;
+       const struct mfd_cell   *children;
        int                     nchildren;
 } retu_data[] = {
        [0] = {
index 52801351864d684e094ec59b60ec797cf4ffcc27..1ee867591ee4de3b6a02081297c9ad22ff12134e 100644 (file)
@@ -49,8 +49,8 @@ static int rtl8411b_is_qfn48(struct rtsx_pcr *pcr)
 
 static void rtl8411_fetch_vendor_settings(struct rtsx_pcr *pcr)
 {
-       u32 reg1;
-       u8 reg3;
+       u32 reg1 = 0;
+       u8 reg3 = 0;
 
        rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg1);
        dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg1);
@@ -71,7 +71,7 @@ static void rtl8411_fetch_vendor_settings(struct rtsx_pcr *pcr)
 
 static void rtl8411b_fetch_vendor_settings(struct rtsx_pcr *pcr)
 {
-       u32 reg;
+       u32 reg = 0;
 
        rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg);
        dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
index 11e20afbdcacb7d31e49798db6d2dfbf0504afd8..c422dca8d90f57c4e256ca4ab77d68422184d53d 100644 (file)
@@ -50,7 +50,7 @@ static struct mfd_cell rtsx_pcr_cells[] = {
        },
 };
 
-static DEFINE_PCI_DEVICE_TABLE(rtsx_pci_ids) = {
+static const struct pci_device_id rtsx_pci_ids[] = {
        { PCI_DEVICE(0x10EC, 0x5209), PCI_CLASS_OTHERS << 16, 0xFF0000 },
        { PCI_DEVICE(0x10EC, 0x5229), PCI_CLASS_OTHERS << 16, 0xFF0000 },
        { PCI_DEVICE(0x10EC, 0x5289), PCI_CLASS_OTHERS << 16, 0xFF0000 },
@@ -1228,8 +1228,14 @@ static void rtsx_pci_remove(struct pci_dev *pcidev)
 
        pcr->remove_pci = true;
 
-       cancel_delayed_work(&pcr->carddet_work);
-       cancel_delayed_work(&pcr->idle_work);
+       /* Disable interrupts at the pcr level */
+       spin_lock_irq(&pcr->lock);
+       rtsx_pci_writel(pcr, RTSX_BIER, 0);
+       pcr->bier = 0;
+       spin_unlock_irq(&pcr->lock);
+
+       cancel_delayed_work_sync(&pcr->carddet_work);
+       cancel_delayed_work_sync(&pcr->idle_work);
 
        mfd_remove_devices(&pcidev->dev);
 
index 34c18fb8c0896b46f49de48b4d5631a5d780a811..87fa1e653cb696e5c179dad82ab32367caf189a0 100644 (file)
@@ -31,7 +31,7 @@
 #include <linux/mfd/samsung/s5m8767.h>
 #include <linux/regmap.h>
 
-static struct mfd_cell s5m8751_devs[] = {
+static const struct mfd_cell s5m8751_devs[] = {
        {
                .name = "s5m8751-pmic",
        }, {
@@ -41,7 +41,7 @@ static struct mfd_cell s5m8751_devs[] = {
        },
 };
 
-static struct mfd_cell s5m8763_devs[] = {
+static const struct mfd_cell s5m8763_devs[] = {
        {
                .name = "s5m8763-pmic",
        }, {
@@ -51,7 +51,7 @@ static struct mfd_cell s5m8763_devs[] = {
        },
 };
 
-static struct mfd_cell s5m8767_devs[] = {
+static const struct mfd_cell s5m8767_devs[] = {
        {
                .name = "s5m8767-pmic",
        }, {
@@ -59,7 +59,7 @@ static struct mfd_cell s5m8767_devs[] = {
        },
 };
 
-static struct mfd_cell s2mps11_devs[] = {
+static const struct mfd_cell s2mps11_devs[] = {
        {
                .name = "s2mps11-pmic",
        }, {
@@ -134,12 +134,12 @@ static bool s5m8763_volatile(struct device *dev, unsigned int reg)
        }
 }
 
-static struct regmap_config sec_regmap_config = {
+static const struct regmap_config sec_regmap_config = {
        .reg_bits = 8,
        .val_bits = 8,
 };
 
-static struct regmap_config s2mps11_regmap_config = {
+static const struct regmap_config s2mps11_regmap_config = {
        .reg_bits = 8,
        .val_bits = 8,
 
@@ -148,7 +148,7 @@ static struct regmap_config s2mps11_regmap_config = {
        .cache_type = REGCACHE_FLAT,
 };
 
-static struct regmap_config s5m8763_regmap_config = {
+static const struct regmap_config s5m8763_regmap_config = {
        .reg_bits = 8,
        .val_bits = 8,
 
@@ -157,7 +157,7 @@ static struct regmap_config s5m8763_regmap_config = {
        .cache_type = REGCACHE_FLAT,
 };
 
-static struct regmap_config s5m8767_regmap_config = {
+static const struct regmap_config s5m8767_regmap_config = {
        .reg_bits = 8,
        .val_bits = 8,
 
@@ -199,7 +199,7 @@ static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata(
 static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata(
                                        struct device *dev)
 {
-       return 0;
+       return NULL;
 }
 #endif
 
@@ -309,6 +309,8 @@ static int sec_pmic_probe(struct i2c_client *i2c,
        if (ret)
                goto err;
 
+       device_init_wakeup(sec_pmic->dev, sec_pmic->wakeup);
+
        return ret;
 
 err:
@@ -327,6 +329,43 @@ static int sec_pmic_remove(struct i2c_client *i2c)
        return 0;
 }
 
+static int sec_pmic_suspend(struct device *dev)
+{
+       struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+       struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c);
+
+       if (device_may_wakeup(dev)) {
+               enable_irq_wake(sec_pmic->irq);
+               /*
+                * PMIC IRQ must be disabled during suspend for RTC alarm
+                * to work properly.
+                * When device is woken up from suspend by RTC Alarm, an
+                * interrupt occurs before resuming I2C bus controller.
+                * The interrupt is handled by regmap_irq_thread which tries
+                * to read RTC registers. This read fails (I2C is still
+                * suspended) and RTC Alarm interrupt is disabled.
+                */
+               disable_irq(sec_pmic->irq);
+       }
+
+       return 0;
+}
+
+static int sec_pmic_resume(struct device *dev)
+{
+       struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+       struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c);
+
+       if (device_may_wakeup(dev)) {
+               disable_irq_wake(sec_pmic->irq);
+               enable_irq(sec_pmic->irq);
+       }
+
+       return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(sec_pmic_pm_ops, sec_pmic_suspend, sec_pmic_resume);
+
 static const struct i2c_device_id sec_pmic_id[] = {
        { "sec_pmic", 0 },
        { }
@@ -337,6 +376,7 @@ static struct i2c_driver sec_pmic_driver = {
        .driver = {
                   .name = "sec_pmic",
                   .owner = THIS_MODULE,
+                  .pm = &sec_pmic_pm_ops,
                   .of_match_table = of_match_ptr(sec_dt_match),
        },
        .probe = sec_pmic_probe,
index 0dd84e99081e9d30539ab96cccc255591a18be82..f3699748f04ec83f07493465e64e439b41c7ca51 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/mfd/samsung/s5m8763.h>
 #include <linux/mfd/samsung/s5m8767.h>
 
-static struct regmap_irq s2mps11_irqs[] = {
+static const struct regmap_irq s2mps11_irqs[] = {
        [S2MPS11_IRQ_PWRONF] = {
                .reg_offset = 0,
                .mask = S2MPS11_IRQ_PWRONF_MASK,
@@ -90,7 +90,7 @@ static struct regmap_irq s2mps11_irqs[] = {
 };
 
 
-static struct regmap_irq s5m8767_irqs[] = {
+static const struct regmap_irq s5m8767_irqs[] = {
        [S5M8767_IRQ_PWRR] = {
                .reg_offset = 0,
                .mask = S5M8767_IRQ_PWRR_MASK,
@@ -161,7 +161,7 @@ static struct regmap_irq s5m8767_irqs[] = {
        },
 };
 
-static struct regmap_irq s5m8763_irqs[] = {
+static const struct regmap_irq s5m8763_irqs[] = {
        [S5M8763_IRQ_DCINF] = {
                .reg_offset = 0,
                .mask = S5M8763_IRQ_DCINF_MASK,
@@ -236,7 +236,7 @@ static struct regmap_irq s5m8763_irqs[] = {
        },
 };
 
-static struct regmap_irq_chip s2mps11_irq_chip = {
+static const struct regmap_irq_chip s2mps11_irq_chip = {
        .name = "s2mps11",
        .irqs = s2mps11_irqs,
        .num_irqs = ARRAY_SIZE(s2mps11_irqs),
@@ -246,7 +246,7 @@ static struct regmap_irq_chip s2mps11_irq_chip = {
        .ack_base = S2MPS11_REG_INT1,
 };
 
-static struct regmap_irq_chip s5m8767_irq_chip = {
+static const struct regmap_irq_chip s5m8767_irq_chip = {
        .name = "s5m8767",
        .irqs = s5m8767_irqs,
        .num_irqs = ARRAY_SIZE(s5m8767_irqs),
@@ -256,7 +256,7 @@ static struct regmap_irq_chip s5m8767_irq_chip = {
        .ack_base = S5M8767_REG_INT1,
 };
 
-static struct regmap_irq_chip s5m8763_irq_chip = {
+static const struct regmap_irq_chip s5m8763_irq_chip = {
        .name = "s5m8763",
        .irqs = s5m8763_irqs,
        .num_irqs = ARRAY_SIZE(s5m8763_irqs),
index c2c8c91c6c7b3188180301e85c6a4ce5ffff0c77..e7dc441a8f8ac057392de6b565fc815fd9ad22f4 100644 (file)
@@ -1710,7 +1710,7 @@ static int sm501_plat_remove(struct platform_device *dev)
        return 0;
 }
 
-static DEFINE_PCI_DEVICE_TABLE(sm501_pci_tbl) = {
+static const struct pci_device_id sm501_pci_tbl[] = {
        { 0x126f, 0x0501, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
        { 0, },
 };
index 65c6fa671acb27a67496b3b9277aa4919942dc89..0d42e40adb98d6edc362d5164a1e65b5de8943bd 100644 (file)
@@ -339,7 +339,7 @@ static int sta2x11_mfd_platform_probe(struct platform_device *dev,
        regmap_config->cache_type = REGCACHE_NONE;
        mfd->regmap[index] = devm_regmap_init_mmio(&dev->dev, mfd->regs[index],
                                                   regmap_config);
-       WARN_ON(!mfd->regmap[index]);
+       WARN_ON(IS_ERR(mfd->regmap[index]));
 
        return 0;
 }
@@ -642,7 +642,7 @@ err_disable:
        return err;
 }
 
-static DEFINE_PCI_DEVICE_TABLE(sta2x11_mfd_tbl) = {
+static const struct pci_device_id sta2x11_mfd_tbl[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_GPIO)},
        {PCI_DEVICE(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_VIC)},
        {0,},
index fff63a41862cf6bbb4acfac38496447a4137ad0a..42ccd05445133444e52be15c4d380de7b4915539 100644 (file)
@@ -297,14 +297,14 @@ static struct resource stmpe_gpio_resources[] = {
        },
 };
 
-static struct mfd_cell stmpe_gpio_cell = {
+static const struct mfd_cell stmpe_gpio_cell = {
        .name           = "stmpe-gpio",
        .of_compatible  = "st,stmpe-gpio",
        .resources      = stmpe_gpio_resources,
        .num_resources  = ARRAY_SIZE(stmpe_gpio_resources),
 };
 
-static struct mfd_cell stmpe_gpio_cell_noirq = {
+static const struct mfd_cell stmpe_gpio_cell_noirq = {
        .name           = "stmpe-gpio",
        .of_compatible  = "st,stmpe-gpio",
        /* gpio cell resources consist of an irq only so no resources here */
@@ -325,7 +325,7 @@ static struct resource stmpe_keypad_resources[] = {
        },
 };
 
-static struct mfd_cell stmpe_keypad_cell = {
+static const struct mfd_cell stmpe_keypad_cell = {
        .name           = "stmpe-keypad",
        .of_compatible  = "st,stmpe-keypad",
        .resources      = stmpe_keypad_resources,
@@ -409,7 +409,7 @@ static struct resource stmpe_ts_resources[] = {
        },
 };
 
-static struct mfd_cell stmpe_ts_cell = {
+static const struct mfd_cell stmpe_ts_cell = {
        .name           = "stmpe-ts",
        .of_compatible  = "st,stmpe-ts",
        .resources      = stmpe_ts_resources,
@@ -1064,7 +1064,7 @@ static int stmpe_chip_init(struct stmpe *stmpe)
        return stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_ICR_LSB], icr);
 }
 
-static int stmpe_add_device(struct stmpe *stmpe, struct mfd_cell *cell)
+static int stmpe_add_device(struct stmpe *stmpe, const struct mfd_cell *cell)
 {
        return mfd_add_devices(stmpe->dev, stmpe->pdata->id, cell, 1,
                               NULL, stmpe->irq_base, stmpe->domain);
index ff2b09ba8797cfc214d36fada42efe1f1b64a807..6639f1b0fef50525a6292a9cce9984dd7c05c836 100644 (file)
@@ -38,7 +38,7 @@ static inline void stmpe_dump_bytes(const char *str, const void *buf,
  *             enable and altfunc callbacks
  */
 struct stmpe_variant_block {
-       struct mfd_cell         *cell;
+       const struct mfd_cell   *cell;
        int                     irq;
        enum stmpe_block        block;
 };
index 87ea51dc6234a243021bce1682a213856c49128b..2cf636c267d9413f77e39d787b6a47496ce1859e 100644 (file)
@@ -155,7 +155,7 @@ static struct resource keypad_resources[] = {
        },
 };
 
-static struct mfd_cell tc3589x_dev_gpio[] = {
+static const struct mfd_cell tc3589x_dev_gpio[] = {
        {
                .name           = "tc3589x-gpio",
                .num_resources  = ARRAY_SIZE(gpio_resources),
@@ -164,7 +164,7 @@ static struct mfd_cell tc3589x_dev_gpio[] = {
        },
 };
 
-static struct mfd_cell tc3589x_dev_keypad[] = {
+static const struct mfd_cell tc3589x_dev_keypad[] = {
        {
                .name           = "tc3589x-keypad",
                .num_resources  = ARRAY_SIZE(keypad_resources),
index acd0f3a41044a5171cc0cfde9d03ad693fa9f48c..591a331d8d83b147fbc10fa23351d61a05aeaf9e 100644 (file)
@@ -126,7 +126,7 @@ static struct tmio_mmc_data tc6387xb_mmc_data = {
 
 /*--------------------------------------------------------------------------*/
 
-static struct mfd_cell tc6387xb_cells[] = {
+static const struct mfd_cell tc6387xb_cells[] = {
        [TC6387XB_CELL_MMC] = {
                .name = "tmio-mmc",
                .enable = tc6387xb_mmc_enable,
index 71e3e0c5bf730c7e8f3423619d9a2e2acc6fa27d..a5424579679cfcd7e0b835964557ea1188c58eaa 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/sched.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/ti_ssp.h>
 
@@ -409,7 +410,6 @@ static int ti_ssp_probe(struct platform_device *pdev)
                cells[id].id            = id;
                cells[id].name          = data->dev_name;
                cells[id].platform_data = data->pdata;
-               cells[id].data_size     = data->pdata_size;
        }
 
        error = mfd_add_devices(dev, 0, cells, 2, NULL, 0, NULL);
index dbb34f94e5e3fce2e0df7f18097930558069af2f..2bc5cfb852042cd5e41e240cb5ce0662ebd0698f 100644 (file)
@@ -374,7 +374,7 @@ static const struct resource timberdale_dma_resources[] = {
        },
 };
 
-static struct mfd_cell timberdale_cells_bar0_cfg0[] = {
+static const struct mfd_cell timberdale_cells_bar0_cfg0[] = {
        {
                .name = "timb-dma",
                .num_resources = ARRAY_SIZE(timberdale_dma_resources),
@@ -431,7 +431,7 @@ static struct mfd_cell timberdale_cells_bar0_cfg0[] = {
        },
 };
 
-static struct mfd_cell timberdale_cells_bar0_cfg1[] = {
+static const struct mfd_cell timberdale_cells_bar0_cfg1[] = {
        {
                .name = "timb-dma",
                .num_resources = ARRAY_SIZE(timberdale_dma_resources),
@@ -498,7 +498,7 @@ static struct mfd_cell timberdale_cells_bar0_cfg1[] = {
        },
 };
 
-static struct mfd_cell timberdale_cells_bar0_cfg2[] = {
+static const struct mfd_cell timberdale_cells_bar0_cfg2[] = {
        {
                .name = "timb-dma",
                .num_resources = ARRAY_SIZE(timberdale_dma_resources),
@@ -548,7 +548,7 @@ static struct mfd_cell timberdale_cells_bar0_cfg2[] = {
        },
 };
 
-static struct mfd_cell timberdale_cells_bar0_cfg3[] = {
+static const struct mfd_cell timberdale_cells_bar0_cfg3[] = {
        {
                .name = "timb-dma",
                .num_resources = ARRAY_SIZE(timberdale_dma_resources),
@@ -619,7 +619,7 @@ static const struct resource timberdale_sdhc_resources[] = {
        },
 };
 
-static struct mfd_cell timberdale_cells_bar1[] = {
+static const struct mfd_cell timberdale_cells_bar1[] = {
        {
                .name = "sdhci",
                .num_resources = ARRAY_SIZE(timberdale_sdhc_resources),
@@ -627,7 +627,7 @@ static struct mfd_cell timberdale_cells_bar1[] = {
        },
 };
 
-static struct mfd_cell timberdale_cells_bar2[] = {
+static const struct mfd_cell timberdale_cells_bar2[] = {
        {
                .name = "sdhci",
                .num_resources = ARRAY_SIZE(timberdale_sdhc_resources),
@@ -851,7 +851,7 @@ static void timb_remove(struct pci_dev *dev)
        kfree(priv);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(timberdale_pci_tbl) = {
+static const struct pci_device_id timberdale_pci_tbl[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_TIMB, PCI_DEVICE_ID_TIMB) },
        { 0 }
 };
index a081b925d10b2debf94e28ea2c5c500081262309..3b27482a174fd14bae949ee284f76f4ac504a6fe 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/mfd/core.h>
 #include <linux/mfd/tps6507x.h>
 
-static struct mfd_cell tps6507x_devs[] = {
+static const struct mfd_cell tps6507x_devs[] = {
        {
                .name = "tps6507x-pmic",
        },
index e6f03a733879b063d670ecc2bd074ea28063ec18..ba1a25d758c12ed61d82aaea82501272fc34081a 100644 (file)
@@ -64,7 +64,7 @@ static struct resource charger_resources[] = {
        }
 };
 
-static struct mfd_cell tps65090s[] = {
+static const struct mfd_cell tps65090s[] = {
        {
                .name = "tps65090-pmic",
        },
index b7be0b29557599ab94c30ba4f16534c88eff030b..6939ae56c2e168d390a504af22767198b222b9f1 100644 (file)
@@ -30,7 +30,7 @@
 #include <linux/mfd/core.h>
 #include <linux/mfd/tps65217.h>
 
-static struct mfd_cell tps65217s[] = {
+static const struct mfd_cell tps65217s[] = {
        {
                .name = "tps65217-pmic",
        },
index ee61fd7c198da714c2dd56ba7be2bfe6da5a068d..bbd54414a75da5f99edbc70375c717c4ecd41267 100644 (file)
@@ -103,7 +103,7 @@ static struct resource tps6586x_rtc_resources[] = {
        },
 };
 
-static struct mfd_cell tps6586x_cell[] = {
+static const struct mfd_cell tps6586x_cell[] = {
        {
                .name = "tps6586x-gpio",
        },
@@ -124,6 +124,7 @@ struct tps6586x {
        struct device           *dev;
        struct i2c_client       *client;
        struct regmap           *regmap;
+       int                     version;
 
        int                     irq;
        struct irq_chip         irq_chip;
@@ -208,6 +209,14 @@ int tps6586x_irq_get_virq(struct device *dev, int irq)
 }
 EXPORT_SYMBOL_GPL(tps6586x_irq_get_virq);
 
+int tps6586x_get_version(struct device *dev)
+{
+       struct tps6586x *tps6586x = dev_get_drvdata(dev);
+
+       return tps6586x->version;
+}
+EXPORT_SYMBOL_GPL(tps6586x_get_version);
+
 static int __remove_subdev(struct device *dev, void *unused)
 {
        platform_device_unregister(to_platform_device(dev));
@@ -472,12 +481,38 @@ static void tps6586x_power_off(void)
        tps6586x_set_bits(tps6586x_dev, TPS6586X_SUPPLYENE, SLEEP_MODE_BIT);
 }
 
+static void tps6586x_print_version(struct i2c_client *client, int version)
+{
+       const char *name;
+
+       switch (version) {
+       case TPS658621A:
+               name = "TPS658621A";
+               break;
+       case TPS658621CD:
+               name = "TPS658621C/D";
+               break;
+       case TPS658623:
+               name = "TPS658623";
+               break;
+       case TPS658643:
+               name = "TPS658643";
+               break;
+       default:
+               name = "TPS6586X";
+               break;
+       }
+
+       dev_info(&client->dev, "Found %s, VERSIONCRC is %02x\n", name, version);
+}
+
 static int tps6586x_i2c_probe(struct i2c_client *client,
                                        const struct i2c_device_id *id)
 {
        struct tps6586x_platform_data *pdata = dev_get_platdata(&client->dev);
        struct tps6586x *tps6586x;
        int ret;
+       int version;
 
        if (!pdata && client->dev.of_node)
                pdata = tps6586x_parse_dt(client);
@@ -487,19 +522,18 @@ static int tps6586x_i2c_probe(struct i2c_client *client,
                return -ENOTSUPP;
        }
 
-       ret = i2c_smbus_read_byte_data(client, TPS6586X_VERSIONCRC);
-       if (ret < 0) {
-               dev_err(&client->dev, "Chip ID read failed: %d\n", ret);
+       version = i2c_smbus_read_byte_data(client, TPS6586X_VERSIONCRC);
+       if (version < 0) {
+               dev_err(&client->dev, "Chip ID read failed: %d\n", version);
                return -EIO;
        }
 
-       dev_info(&client->dev, "VERSIONCRC is %02x\n", ret);
-
        tps6586x = devm_kzalloc(&client->dev, sizeof(*tps6586x), GFP_KERNEL);
-       if (tps6586x == NULL) {
-               dev_err(&client->dev, "memory for tps6586x alloc failed\n");
+       if (!tps6586x)
                return -ENOMEM;
-       }
+
+       tps6586x->version = version;
+       tps6586x_print_version(client, tps6586x->version);
 
        tps6586x->client = client;
        tps6586x->dev = &client->dev;
index c0f608e3ca9e5fc1fc0706666b8fcc4f89778567..1f142d76cbbc6fc03f44ead367c01a9b75f24c86 100644 (file)
@@ -36,7 +36,7 @@ static struct resource rtc_resources[] = {
        }
 };
 
-static struct mfd_cell tps65910s[] = {
+static const struct mfd_cell tps65910s[] = {
        {
                .name = "tps65910-gpio",
        },
index 925a044cbdf61740e3c54e0a481a9774587c652b..27a518e0eec6d04db1310e86f7ed678b4a762065 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/mfd/core.h>
 #include <linux/mfd/tps65912.h>
 
-static struct mfd_cell tps65912s[] = {
+static const struct mfd_cell tps65912s[] = {
        {
                .name = "tps65912-pmic",
        },
index f15ee6d5cfbf96fb97ef6f169528c624b09a2aba..ed6c5b0956e2387f09b213eba64879e2fc656fc7 100644 (file)
@@ -44,7 +44,7 @@ static struct resource tps80031_rtc_resources[] = {
 };
 
 /* TPS80031 sub mfd devices */
-static struct mfd_cell tps80031_cell[] = {
+static const struct mfd_cell tps80031_cell[] = {
        {
                .name = "tps80031-pmic",
        },
index 29473c2c95ae0d92aa75184199486f70bdf5fc53..f0aa4cef9ad0619db9357b1f553c12f7594bf3cd 100644 (file)
@@ -701,62 +701,6 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
                        usb3v1[0].dev_name = dev_name(child);
                }
        }
-       if (IS_ENABLED(CONFIG_TWL6030_USB) && pdata->usb &&
-           twl_class_is_6030()) {
-
-               static struct regulator_consumer_supply usb3v3;
-               int regulator;
-
-               if (IS_ENABLED(CONFIG_REGULATOR_TWL4030)) {
-                       /* this is a template that gets copied */
-                       struct regulator_init_data usb_fixed = {
-                               .constraints.valid_modes_mask =
-                                       REGULATOR_MODE_NORMAL
-                                       | REGULATOR_MODE_STANDBY,
-                               .constraints.valid_ops_mask =
-                                       REGULATOR_CHANGE_MODE
-                                       | REGULATOR_CHANGE_STATUS,
-                       };
-
-                       if (features & TWL6032_SUBCLASS) {
-                               usb3v3.supply = "ldousb";
-                               regulator = TWL6032_REG_LDOUSB;
-                       } else {
-                               usb3v3.supply = "vusb";
-                               regulator = TWL6030_REG_VUSB;
-                       }
-                       child = add_regulator_linked(regulator, &usb_fixed,
-                                                       &usb3v3, 1,
-                                                       features);
-                       if (IS_ERR(child))
-                               return PTR_ERR(child);
-               }
-
-               pdata->usb->features = features;
-
-               child = add_child(TWL_MODULE_USB, "twl6030_usb",
-                       pdata->usb, sizeof(*pdata->usb), true,
-                       /* irq1 = VBUS_PRES, irq0 = USB ID */
-                       irq_base + USBOTG_INTR_OFFSET,
-                       irq_base + USB_PRES_INTR_OFFSET);
-
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-               /* we need to connect regulators to this transceiver */
-               if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && child)
-                       usb3v3.dev_name = dev_name(child);
-       } else if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) &&
-                  twl_class_is_6030()) {
-               if (features & TWL6032_SUBCLASS)
-                       child = add_regulator(TWL6032_REG_LDOUSB,
-                                               pdata->ldousb, features);
-               else
-                       child = add_regulator(TWL6030_REG_VUSB,
-                                               pdata->vusb, features);
-
-                       if (IS_ERR(child))
-                                       return PTR_ERR(child);
-       }
 
        if (IS_ENABLED(CONFIG_TWL4030_WATCHDOG) && twl_class_is_4030()) {
                child = add_child(TWL_MODULE_PM_RECEIVER, "twl4030_wdt", NULL,
@@ -870,148 +814,6 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
                        return PTR_ERR(child);
        }
 
-       /* twl6030 regulators */
-       if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_6030() &&
-                       !(features & TWL6032_SUBCLASS)) {
-               child = add_regulator(TWL6030_REG_VDD1, pdata->vdd1,
-                                       features);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-               child = add_regulator(TWL6030_REG_VDD2, pdata->vdd2,
-                                       features);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-               child = add_regulator(TWL6030_REG_VDD3, pdata->vdd3,
-                                       features);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-               child = add_regulator(TWL6030_REG_V1V8, pdata->v1v8,
-                                       features);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-               child = add_regulator(TWL6030_REG_V2V1, pdata->v2v1,
-                                       features);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-               child = add_regulator(TWL6030_REG_VMMC, pdata->vmmc,
-                                       features);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-               child = add_regulator(TWL6030_REG_VPP, pdata->vpp,
-                                       features);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-               child = add_regulator(TWL6030_REG_VUSIM, pdata->vusim,
-                                       features);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-               child = add_regulator(TWL6030_REG_VCXIO, pdata->vcxio,
-                                       features);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-               child = add_regulator(TWL6030_REG_VDAC, pdata->vdac,
-                                       features);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-               child = add_regulator(TWL6030_REG_VAUX1_6030, pdata->vaux1,
-                                       features);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-               child = add_regulator(TWL6030_REG_VAUX2_6030, pdata->vaux2,
-                                       features);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-               child = add_regulator(TWL6030_REG_VAUX3_6030, pdata->vaux3,
-                                       features);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-               child = add_regulator(TWL6030_REG_CLK32KG, pdata->clk32kg,
-                                       features);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-       }
-
-       /* 6030 and 6025 share this regulator */
-       if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_6030()) {
-               child = add_regulator(TWL6030_REG_VANA, pdata->vana,
-                                       features);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-       }
-
-       /* twl6032 regulators */
-       if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_6030() &&
-                       (features & TWL6032_SUBCLASS)) {
-               child = add_regulator(TWL6032_REG_LDO5, pdata->ldo5,
-                                       features);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-               child = add_regulator(TWL6032_REG_LDO1, pdata->ldo1,
-                                       features);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-               child = add_regulator(TWL6032_REG_LDO7, pdata->ldo7,
-                                       features);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-               child = add_regulator(TWL6032_REG_LDO6, pdata->ldo6,
-                                       features);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-               child = add_regulator(TWL6032_REG_LDOLN, pdata->ldoln,
-                                       features);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-               child = add_regulator(TWL6032_REG_LDO2, pdata->ldo2,
-                                       features);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-               child = add_regulator(TWL6032_REG_LDO4, pdata->ldo4,
-                                       features);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-               child = add_regulator(TWL6032_REG_LDO3, pdata->ldo3,
-                                       features);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-               child = add_regulator(TWL6032_REG_SMPS3, pdata->smps3,
-                                       features);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-               child = add_regulator(TWL6032_REG_SMPS4, pdata->smps4,
-                                       features);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-               child = add_regulator(TWL6032_REG_VIO, pdata->vio6025,
-                                       features);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-       }
-
        if (IS_ENABLED(CONFIG_CHARGER_TWL4030) && pdata->bci &&
                        !(features & (TPS_SUBSET | TWL5031))) {
                child = add_child(TWL_MODULE_MAIN_CHARGE, "twl4030_bci",
@@ -1133,6 +935,11 @@ static int twl_remove(struct i2c_client *client)
        return 0;
 }
 
+static struct of_dev_auxdata twl_auxdata_lookup[] = {
+       OF_DEV_AUXDATA("ti,twl4030-gpio", 0, "twl4030-gpio", NULL),
+       { /* sentinel */ },
+};
+
 /* NOTE: This driver only handles a single twl4030/tps659x0 chip */
 static int
 twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
@@ -1271,10 +1078,14 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
                twl_i2c_write_u8(TWL4030_MODULE_INTBR, temp, REG_GPPUPDCTR1);
        }
 
-       if (node)
-               status = of_platform_populate(node, NULL, NULL, &client->dev);
-       else
+       if (node) {
+               if (pdata)
+                       twl_auxdata_lookup[0].platform_data = pdata->gpio;
+               status = of_platform_populate(node, NULL, twl_auxdata_lookup,
+                                             &client->dev);
+       } else {
                status = add_children(pdata, irq_base, id->driver_data);
+       }
 
 fail:
        if (status < 0)
index af2a6703f34fa89d6a6c68397c91104ab768f6fe..e00f5340ed872089d31998ff39d6bb57842e731a 100644 (file)
@@ -37,7 +37,7 @@ static const struct usb_device_id vprbrd_table[] = {
 
 MODULE_DEVICE_TABLE(usb, vprbrd_table);
 
-static struct mfd_cell vprbrd_devs[] = {
+static const struct mfd_cell vprbrd_devs[] = {
        {
                .name = "viperboard-gpio",
        },
index 757ecc63338c19a7d7d75c85e4a185459fb3d3a0..84f01da4875eb39a064e56b8612138a93afb3fbd 100644 (file)
@@ -60,7 +60,7 @@ static struct resource vx855_gpio_resources[] = {
        },
 };
 
-static struct mfd_cell vx855_cells[] = {
+static const struct mfd_cell vx855_cells[] = {
        {
                .name = "vx855_gpio",
                .num_resources = ARRAY_SIZE(vx855_gpio_resources),
@@ -118,7 +118,7 @@ static void vx855_remove(struct pci_dev *pdev)
        pci_disable_device(pdev);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(vx855_pci_tbl) = {
+static const struct pci_device_id vx855_pci_tbl[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855) },
        { 0, }
 };
index bf8b3b5ad1fe65d03eb067881599c5cbc1418a32..c24eff39184187f2cdd62000f29cce390da01091 100644 (file)
@@ -14,6 +14,7 @@
 
 #include <linux/mfd/arizona/core.h>
 #include <linux/mfd/arizona/registers.h>
+#include <linux/device.h>
 
 #include "arizona.h"
 
@@ -504,7 +505,7 @@ static const struct reg_default wm5110_reg_default[] = {
        { 0x000001AA, 0x0004 },    /* R426   - FLL2 GPIO Clock */
        { 0x00000200, 0x0006 },    /* R512   - Mic Charge Pump 1 */
        { 0x00000210, 0x0184 },    /* R528   - LDO1 Control 1 */
-       { 0x00000213, 0x0344 },    /* R531   - LDO2 Control 1 */
+       { 0x00000213, 0x03E4 },    /* R531   - LDO2 Control 1 */
        { 0x00000218, 0x01A6 },    /* R536   - Mic Bias Ctrl 1 */
        { 0x00000219, 0x01A6 },    /* R537   - Mic Bias Ctrl 2 */
        { 0x0000021A, 0x01A6 },    /* R538   - Mic Bias Ctrl 3 */
@@ -524,6 +525,7 @@ static const struct reg_default wm5110_reg_default[] = {
        { 0x00000300, 0x0000 },    /* R768   - Input Enables */
        { 0x00000308, 0x0000 },    /* R776   - Input Rate */
        { 0x00000309, 0x0022 },    /* R777   - Input Volume Ramp */
+       { 0x0000030C, 0x0002 },    /* R780   - HPF Control */
        { 0x00000310, 0x2080 },    /* R784   - IN1L Control */
        { 0x00000311, 0x0180 },    /* R785   - ADC Digital Volume 1L */
        { 0x00000312, 0x0000 },    /* R786   - DMIC1L Control */
@@ -545,6 +547,7 @@ static const struct reg_default wm5110_reg_default[] = {
        { 0x00000328, 0x2000 },    /* R808   - IN4L Control */
        { 0x00000329, 0x0180 },    /* R809   - ADC Digital Volume 4L */
        { 0x0000032A, 0x0000 },    /* R810   - DMIC4L Control */
+       { 0x0000032C, 0x0000 },    /* R812   - IN4R Control */
        { 0x0000032D, 0x0180 },    /* R813   - ADC Digital Volume 4R */
        { 0x0000032E, 0x0000 },    /* R814   - DMIC4R Control */
        { 0x00000400, 0x0000 },    /* R1024  - Output Enables 1 */
@@ -882,6 +885,38 @@ static const struct reg_default wm5110_reg_default[] = {
        { 0x0000074D, 0x0080 },    /* R1869  - AIF2TX2MIX Input 3 Volume */
        { 0x0000074E, 0x0000 },    /* R1870  - AIF2TX2MIX Input 4 Source */
        { 0x0000074F, 0x0080 },    /* R1871  - AIF2TX2MIX Input 4 Volume */
+       { 0x00000750, 0x0000 },    /* R1872  - AIF2TX3MIX Input 1 Source */
+       { 0x00000751, 0x0080 },    /* R1873  - AIF2TX3MIX Input 1 Volume */
+       { 0x00000752, 0x0000 },    /* R1874  - AIF2TX3MIX Input 2 Source */
+       { 0x00000753, 0x0080 },    /* R1875  - AIF2TX3MIX Input 2 Volume */
+       { 0x00000754, 0x0000 },    /* R1876  - AIF2TX3MIX Input 3 Source */
+       { 0x00000755, 0x0080 },    /* R1877  - AIF2TX3MIX Input 3 Volume */
+       { 0x00000756, 0x0000 },    /* R1878  - AIF2TX3MIX Input 4 Source */
+       { 0x00000757, 0x0080 },    /* R1879  - AIF2TX3MIX Input 4 Volume */
+       { 0x00000758, 0x0000 },    /* R1880  - AIF2TX4MIX Input 1 Source */
+       { 0x00000759, 0x0080 },    /* R1881  - AIF2TX4MIX Input 1 Volume */
+       { 0x0000075A, 0x0000 },    /* R1882  - AIF2TX4MIX Input 2 Source */
+       { 0x0000075B, 0x0080 },    /* R1883  - AIF2TX4MIX Input 2 Volume */
+       { 0x0000075C, 0x0000 },    /* R1884  - AIF2TX4MIX Input 3 Source */
+       { 0x0000075D, 0x0080 },    /* R1885  - AIF2TX4MIX Input 3 Volume */
+       { 0x0000075E, 0x0000 },    /* R1886  - AIF2TX4MIX Input 4 Source */
+       { 0x0000075F, 0x0080 },    /* R1887  - AIF2TX4MIX Input 4 Volume */
+       { 0x00000760, 0x0000 },    /* R1888  - AIF2TX5MIX Input 1 Source */
+       { 0x00000761, 0x0080 },    /* R1889  - AIF2TX5MIX Input 1 Volume */
+       { 0x00000762, 0x0000 },    /* R1890  - AIF2TX5MIX Input 2 Source */
+       { 0x00000763, 0x0080 },    /* R1891  - AIF2TX5MIX Input 2 Volume */
+       { 0x00000764, 0x0000 },    /* R1892  - AIF2TX5MIX Input 3 Source */
+       { 0x00000765, 0x0080 },    /* R1893  - AIF2TX5MIX Input 3 Volume */
+       { 0x00000766, 0x0000 },    /* R1894  - AIF2TX5MIX Input 4 Source */
+       { 0x00000767, 0x0080 },    /* R1895  - AIF2TX5MIX Input 4 Volume */
+       { 0x00000768, 0x0000 },    /* R1896  - AIF2TX6MIX Input 1 Source */
+       { 0x00000769, 0x0080 },    /* R1897  - AIF2TX6MIX Input 1 Volume */
+       { 0x0000076A, 0x0000 },    /* R1898  - AIF2TX6MIX Input 2 Source */
+       { 0x0000076B, 0x0080 },    /* R1899  - AIF2TX6MIX Input 2 Volume */
+       { 0x0000076C, 0x0000 },    /* R1900  - AIF2TX6MIX Input 3 Source */
+       { 0x0000076D, 0x0080 },    /* R1901  - AIF2TX6MIX Input 3 Volume */
+       { 0x0000076E, 0x0000 },    /* R1902  - AIF2TX6MIX Input 4 Source */
+       { 0x0000076F, 0x0080 },    /* R1903  - AIF2TX6MIX Input 4 Volume */
        { 0x00000780, 0x0000 },    /* R1920  - AIF3TX1MIX Input 1 Source */
        { 0x00000781, 0x0080 },    /* R1921  - AIF3TX1MIX Input 1 Volume */
        { 0x00000782, 0x0000 },    /* R1922  - AIF3TX1MIX Input 2 Source */
@@ -1342,6 +1377,64 @@ static const struct reg_default wm5110_reg_default[] = {
        { 0x00001404, 0x0000 },    /* R5124  - DSP4 Status 1 */
 };
 
+static bool wm5110_is_rev_b_adsp_memory(unsigned int reg)
+{
+       if ((reg >= 0x100000 && reg < 0x103000) ||
+           (reg >= 0x180000 && reg < 0x181000) ||
+           (reg >= 0x190000 && reg < 0x192000) ||
+           (reg >= 0x1a8000 && reg < 0x1a9000) ||
+           (reg >= 0x200000 && reg < 0x209000) ||
+           (reg >= 0x280000 && reg < 0x281000) ||
+           (reg >= 0x290000 && reg < 0x29a000) ||
+           (reg >= 0x2a8000 && reg < 0x2aa000) ||
+           (reg >= 0x300000 && reg < 0x30f000) ||
+           (reg >= 0x380000 && reg < 0x382000) ||
+           (reg >= 0x390000 && reg < 0x39e000) ||
+           (reg >= 0x3a8000 && reg < 0x3b6000) ||
+           (reg >= 0x400000 && reg < 0x403000) ||
+           (reg >= 0x480000 && reg < 0x481000) ||
+           (reg >= 0x490000 && reg < 0x492000) ||
+           (reg >= 0x4a8000 && reg < 0x4a9000))
+               return true;
+       else
+               return false;
+}
+
+static bool wm5110_is_rev_d_adsp_memory(unsigned int reg)
+{
+       if ((reg >= 0x100000 && reg < 0x106000) ||
+           (reg >= 0x180000 && reg < 0x182000) ||
+           (reg >= 0x190000 && reg < 0x198000) ||
+           (reg >= 0x1a8000 && reg < 0x1aa000) ||
+           (reg >= 0x200000 && reg < 0x20f000) ||
+           (reg >= 0x280000 && reg < 0x282000) ||
+           (reg >= 0x290000 && reg < 0x29c000) ||
+           (reg >= 0x2a6000 && reg < 0x2b4000) ||
+           (reg >= 0x300000 && reg < 0x30f000) ||
+           (reg >= 0x380000 && reg < 0x382000) ||
+           (reg >= 0x390000 && reg < 0x3a2000) ||
+           (reg >= 0x3a6000 && reg < 0x3b4000) ||
+           (reg >= 0x400000 && reg < 0x406000) ||
+           (reg >= 0x480000 && reg < 0x482000) ||
+           (reg >= 0x490000 && reg < 0x498000) ||
+           (reg >= 0x4a8000 && reg < 0x4aa000))
+               return true;
+       else
+               return false;
+}
+
+static bool wm5110_is_adsp_memory(struct device *dev, unsigned int reg)
+{
+       struct arizona *arizona = dev_get_drvdata(dev);
+
+       switch (arizona->rev) {
+       case 0 ... 2:
+               return wm5110_is_rev_b_adsp_memory(reg);
+       default:
+               return wm5110_is_rev_d_adsp_memory(reg);
+       }
+}
+
 static bool wm5110_readable_register(struct device *dev, unsigned int reg)
 {
        switch (reg) {
@@ -1460,6 +1553,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
        case ARIZONA_INPUT_ENABLES_STATUS:
        case ARIZONA_INPUT_RATE:
        case ARIZONA_INPUT_VOLUME_RAMP:
+       case ARIZONA_HPF_CONTROL:
        case ARIZONA_IN1L_CONTROL:
        case ARIZONA_ADC_DIGITAL_VOLUME_1L:
        case ARIZONA_DMIC1L_CONTROL:
@@ -1481,6 +1575,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
        case ARIZONA_IN4L_CONTROL:
        case ARIZONA_ADC_DIGITAL_VOLUME_4L:
        case ARIZONA_DMIC4L_CONTROL:
+       case ARIZONA_IN4R_CONTROL:
        case ARIZONA_ADC_DIGITAL_VOLUME_4R:
        case ARIZONA_DMIC4R_CONTROL:
        case ARIZONA_OUTPUT_ENABLES_1:
@@ -1820,6 +1915,38 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
        case ARIZONA_AIF2TX2MIX_INPUT_3_VOLUME:
        case ARIZONA_AIF2TX2MIX_INPUT_4_SOURCE:
        case ARIZONA_AIF2TX2MIX_INPUT_4_VOLUME:
+       case ARIZONA_AIF2TX3MIX_INPUT_1_SOURCE:
+       case ARIZONA_AIF2TX3MIX_INPUT_1_VOLUME:
+       case ARIZONA_AIF2TX3MIX_INPUT_2_SOURCE:
+       case ARIZONA_AIF2TX3MIX_INPUT_2_VOLUME:
+       case ARIZONA_AIF2TX3MIX_INPUT_3_SOURCE:
+       case ARIZONA_AIF2TX3MIX_INPUT_3_VOLUME:
+       case ARIZONA_AIF2TX3MIX_INPUT_4_SOURCE:
+       case ARIZONA_AIF2TX3MIX_INPUT_4_VOLUME:
+       case ARIZONA_AIF2TX4MIX_INPUT_1_SOURCE:
+       case ARIZONA_AIF2TX4MIX_INPUT_1_VOLUME:
+       case ARIZONA_AIF2TX4MIX_INPUT_2_SOURCE:
+       case ARIZONA_AIF2TX4MIX_INPUT_2_VOLUME:
+       case ARIZONA_AIF2TX4MIX_INPUT_3_SOURCE:
+       case ARIZONA_AIF2TX4MIX_INPUT_3_VOLUME:
+       case ARIZONA_AIF2TX4MIX_INPUT_4_SOURCE:
+       case ARIZONA_AIF2TX4MIX_INPUT_4_VOLUME:
+       case ARIZONA_AIF2TX5MIX_INPUT_1_SOURCE:
+       case ARIZONA_AIF2TX5MIX_INPUT_1_VOLUME:
+       case ARIZONA_AIF2TX5MIX_INPUT_2_SOURCE:
+       case ARIZONA_AIF2TX5MIX_INPUT_2_VOLUME:
+       case ARIZONA_AIF2TX5MIX_INPUT_3_SOURCE:
+       case ARIZONA_AIF2TX5MIX_INPUT_3_VOLUME:
+       case ARIZONA_AIF2TX5MIX_INPUT_4_SOURCE:
+       case ARIZONA_AIF2TX5MIX_INPUT_4_VOLUME:
+       case ARIZONA_AIF2TX6MIX_INPUT_1_SOURCE:
+       case ARIZONA_AIF2TX6MIX_INPUT_1_VOLUME:
+       case ARIZONA_AIF2TX6MIX_INPUT_2_SOURCE:
+       case ARIZONA_AIF2TX6MIX_INPUT_2_VOLUME:
+       case ARIZONA_AIF2TX6MIX_INPUT_3_SOURCE:
+       case ARIZONA_AIF2TX6MIX_INPUT_3_VOLUME:
+       case ARIZONA_AIF2TX6MIX_INPUT_4_SOURCE:
+       case ARIZONA_AIF2TX6MIX_INPUT_4_VOLUME:
        case ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE:
        case ARIZONA_AIF3TX1MIX_INPUT_1_VOLUME:
        case ARIZONA_AIF3TX1MIX_INPUT_2_SOURCE:
@@ -2331,7 +2458,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
        case ARIZONA_DSP4_SCRATCH_3:
                return true;
        default:
-               return false;
+               return wm5110_is_adsp_memory(dev, reg);
        }
 }
 
@@ -2407,16 +2534,18 @@ static bool wm5110_volatile_register(struct device *dev, unsigned int reg)
        case ARIZONA_DSP4_SCRATCH_3:
                return true;
        default:
-               return false;
+               return wm5110_is_adsp_memory(dev, reg);
        }
 }
 
+#define WM5110_MAX_REGISTER 0x4a9fff
+
 const struct regmap_config wm5110_spi_regmap = {
        .reg_bits = 32,
        .pad_bits = 16,
        .val_bits = 16,
 
-       .max_register = ARIZONA_DSP1_STATUS_2,
+       .max_register = WM5110_MAX_REGISTER,
        .readable_reg = wm5110_readable_register,
        .volatile_reg = wm5110_volatile_register,
 
@@ -2430,7 +2559,7 @@ const struct regmap_config wm5110_i2c_regmap = {
        .reg_bits = 32,
        .val_bits = 16,
 
-       .max_register = ARIZONA_DSP1_STATUS_2,
+       .max_register = WM5110_MAX_REGISTER,
        .readable_reg = wm5110_readable_register,
        .volatile_reg = wm5110_volatile_register,
 
index 5c459f469224a61719d3258e948c0f0f3ecef856..28366a90e1adfbec14b5679244676b1077c9926e 100644 (file)
@@ -1011,7 +1011,7 @@ static struct resource wm831x_wdt_resources[] = {
        },
 };
 
-static struct mfd_cell wm8310_devs[] = {
+static const struct mfd_cell wm8310_devs[] = {
        {
                .name = "wm831x-backup",
        },
@@ -1165,7 +1165,7 @@ static struct mfd_cell wm8310_devs[] = {
        },
 };
 
-static struct mfd_cell wm8311_devs[] = {
+static const struct mfd_cell wm8311_devs[] = {
        {
                .name = "wm831x-backup",
        },
@@ -1295,7 +1295,7 @@ static struct mfd_cell wm8311_devs[] = {
        },
 };
 
-static struct mfd_cell wm8312_devs[] = {
+static const struct mfd_cell wm8312_devs[] = {
        {
                .name = "wm831x-backup",
        },
@@ -1449,7 +1449,7 @@ static struct mfd_cell wm8312_devs[] = {
        },
 };
 
-static struct mfd_cell wm8320_devs[] = {
+static const struct mfd_cell wm8320_devs[] = {
        {
                .name = "wm831x-backup",
        },
@@ -1578,7 +1578,7 @@ static struct mfd_cell wm8320_devs[] = {
        },
 };
 
-static struct mfd_cell touch_devs[] = {
+static const struct mfd_cell touch_devs[] = {
        {
                .name = "wm831x-touch",
                .num_resources = ARRAY_SIZE(wm831x_touch_resources),
@@ -1586,7 +1586,7 @@ static struct mfd_cell touch_devs[] = {
        },
 };
 
-static struct mfd_cell rtc_devs[] = {
+static const struct mfd_cell rtc_devs[] = {
        {
                .name = "wm831x-rtc",
                .num_resources = ARRAY_SIZE(wm831x_rtc_resources),
@@ -1594,7 +1594,7 @@ static struct mfd_cell rtc_devs[] = {
        },
 };
 
-static struct mfd_cell backlight_devs[] = {
+static const struct mfd_cell backlight_devs[] = {
        {
                .name = "wm831x-backlight",
        },
index 2b29caebc9cf77818094a142324fcfc059cac471..a4cbefe5430f340c93a567f603e5f79431136855 100644 (file)
@@ -64,11 +64,13 @@ static int wm831x_i2c_suspend(struct device *dev)
        return wm831x_device_suspend(wm831x);
 }
 
-static void wm831x_i2c_shutdown(struct i2c_client *i2c)
+static int wm831x_i2c_poweroff(struct device *dev)
 {
-       struct wm831x *wm831x = i2c_get_clientdata(i2c);
+       struct wm831x *wm831x = dev_get_drvdata(dev);
 
        wm831x_device_shutdown(wm831x);
+
+       return 0;
 }
 
 static const struct i2c_device_id wm831x_i2c_id[] = {
@@ -85,6 +87,7 @@ MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id);
 
 static const struct dev_pm_ops wm831x_pm_ops = {
        .suspend = wm831x_i2c_suspend,
+       .poweroff = wm831x_i2c_poweroff,
 };
 
 static struct i2c_driver wm831x_i2c_driver = {
@@ -95,7 +98,6 @@ static struct i2c_driver wm831x_i2c_driver = {
        },
        .probe = wm831x_i2c_probe,
        .remove = wm831x_i2c_remove,
-       .shutdown = wm831x_i2c_shutdown,
        .id_table = wm831x_i2c_id,
 };
 
index 07de3cc5a0d91db385a8ef755e8bf89d3817477b..b8a5e3b34ec78448abea9eef2cc79b56871733f6 100644 (file)
@@ -66,16 +66,19 @@ static int wm831x_spi_suspend(struct device *dev)
        return wm831x_device_suspend(wm831x);
 }
 
-static void wm831x_spi_shutdown(struct spi_device *spi)
+static int wm831x_spi_poweroff(struct device *dev)
 {
-       struct wm831x *wm831x = spi_get_drvdata(spi);
+       struct wm831x *wm831x = dev_get_drvdata(dev);
 
        wm831x_device_shutdown(wm831x);
+
+       return 0;
 }
 
 static const struct dev_pm_ops wm831x_spi_pm = {
        .freeze = wm831x_spi_suspend,
        .suspend = wm831x_spi_suspend,
+       .poweroff = wm831x_spi_poweroff,
 };
 
 static const struct spi_device_id wm831x_spi_ids[] = {
@@ -99,7 +102,6 @@ static struct spi_driver wm831x_spi_driver = {
        .id_table       = wm831x_spi_ids,
        .probe          = wm831x_spi_probe,
        .remove         = wm831x_spi_remove,
-       .shutdown       = wm831x_spi_shutdown,
 };
 
 static int __init wm831x_spi_init(void)
index 0308275116672c2b15ab2d91b334c561dadbcf46..ba04f1bc70eb52988ce27b5f4e45195e8b216b82 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "wm8994.h"
 
-static struct mfd_cell wm8994_regulator_devs[] = {
+static const struct mfd_cell wm8994_regulator_devs[] = {
        {
                .name = "wm8994-ldo",
                .id = 1,
@@ -62,7 +62,7 @@ static struct resource wm8994_gpio_resources[] = {
        },
 };
 
-static struct mfd_cell wm8994_devs[] = {
+static const struct mfd_cell wm8994_devs[] = {
        {
                .name = "wm8994-codec",
                .num_resources = ARRAY_SIZE(wm8994_codec_resources),
index 0e8df41aaf144c7a00818bb95959a58060c99efe..2cf2bbc0b927e7d46f381d507dd0729d3bdab23c 100644 (file)
@@ -198,6 +198,13 @@ static void enclosure_remove_links(struct enclosure_component *cdev)
 {
        char name[ENCLOSURE_NAME_SIZE];
 
+       /*
+        * In odd circumstances, like multipath devices, something else may
+        * already have removed the links, so check for this condition first.
+        */
+       if (!cdev->dev->kobj.sd)
+               return;
+
        enclosure_link_name(cdev, name);
        sysfs_remove_link(&cdev->dev->kobj, name);
        sysfs_remove_link(&cdev->cdev.kobj, "device");
index 6c0fde55270d3681c6048c1516b6915c291e4c45..66f411a6e8ea502251ede2b92bca60c59e8843fe 100644 (file)
 #define MEI_DEV_ID_PPT_2      0x1CBA  /* Panther Point */
 #define MEI_DEV_ID_PPT_3      0x1DBA  /* Panther Point */
 
-#define MEI_DEV_ID_LPT        0x8C3A  /* Lynx Point */
+#define MEI_DEV_ID_LPT_H      0x8C3A  /* Lynx Point H */
 #define MEI_DEV_ID_LPT_W      0x8D3A  /* Lynx Point - Wellsburg */
 #define MEI_DEV_ID_LPT_LP     0x9C3A  /* Lynx Point LP */
+#define MEI_DEV_ID_LPT_HR     0x8CBA  /* Lynx Point H Refresh */
+
+#define MEI_DEV_ID_WPT_LP     0x9CBA  /* Wildcat Point LP */
 /*
  * MEI HW Section
  */
index b96205aece0c781d267ef9c2ac198cc154145080..2cab3c0a6805364393e69a5410905874c4103e87 100644 (file)
@@ -76,9 +76,11 @@ static DEFINE_PCI_DEVICE_TABLE(mei_me_pci_tbl) = {
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_1)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_2)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_3)},
-       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT_H)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT_W)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT_LP)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT_HR)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_WPT_LP)},
 
        /* required last entry */
        {0, }
index 8aa42e738acc6dde99a716535f8b27efcd9d0988..653799b96bfae0dd709367fa20a3a74bc296033d 100644 (file)
@@ -154,14 +154,14 @@ 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;
+       int retry;
 
        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--;) {
+       for (retry = 100; retry--;) {
                if (ioread8(&dc->host_ack))
                        break;
                msleep(100);
@@ -187,11 +187,12 @@ static void mic_reset(struct virtio_device *vdev)
 /*
  * The virtio_ring code calls this API when it wants to notify the Host.
  */
-static void mic_notify(struct virtqueue *vq)
+static bool mic_notify(struct virtqueue *vq)
 {
        struct mic_vdev *mvdev = vq->priv;
 
        mic_send_intr(mvdev->mdev, mvdev->c2h_vdev_db);
+       return true;
 }
 
 static void mic_del_vq(struct virtqueue *vq, int n)
@@ -247,17 +248,17 @@ static struct virtqueue *mic_find_vq(struct virtio_device *vdev,
        /* 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 = vring_size(le16_to_cpu(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);
+       va = mic_card_map(mvdev->mdev, le64_to_cpu(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);
+       vq = vring_new_virtqueue(index, le16_to_cpu(config.num),
+                                MIC_VIRTIO_RING_ALIGN, vdev, false,
+                                (void __force *)va, mic_notify, callback,
+                                name);
        if (!vq) {
                err = -ENOMEM;
                goto unmap;
@@ -272,7 +273,8 @@ static struct virtqueue *mic_find_vq(struct virtio_device *vdev,
 
        /* Allocate and reassign used ring now */
        mvdev->used_size[index] = PAGE_ALIGN(sizeof(__u16) * 3 +
-                       sizeof(struct vring_used_elem) * config.num);
+                                            sizeof(struct vring_used_elem) *
+                                            le16_to_cpu(config.num));
        used = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
                                        get_order(mvdev->used_size[index]));
        if (!used) {
@@ -309,7 +311,7 @@ static int mic_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 {
        struct mic_vdev *mvdev = to_micvdev(vdev);
        struct mic_device_ctrl __iomem *dc = mvdev->dc;
-       int i, err, retry = 100;
+       int i, err, retry;
 
        /* We must have this many virtqueues. */
        if (nvqs > ioread8(&mvdev->desc->num_vq))
@@ -331,7 +333,7 @@ static int mic_find_vqs(struct virtio_device *vdev, unsigned nvqs,
         * rings have been re-assigned.
         */
        mic_send_intr(mvdev->mdev, mvdev->c2h_vdev_db);
-       for (i = retry; i--;) {
+       for (retry = 100; retry--;) {
                if (!ioread8(&dc->used_address_updated))
                        break;
                msleep(100);
@@ -519,8 +521,8 @@ static void mic_scan_devices(struct mic_driver *mdrv, bool remove)
        struct device *dev;
        int ret;
 
-       for (i = mic_aligned_size(struct mic_bootparam);
-               i < MIC_DP_SIZE; i += mic_total_desc_size(d)) {
+       for (i = sizeof(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);
                /*
@@ -539,7 +541,8 @@ static void mic_scan_devices(struct mic_driver *mdrv, bool remove)
                        continue;
 
                /* device already exists */
-               dev = device_find_child(mdrv->dev, d, mic_match_desc);
+               dev = device_find_child(mdrv->dev, (void __force *)d,
+                                       mic_match_desc);
                if (dev) {
                        if (remove)
                                iowrite8(MIC_VIRTIO_PARAM_DEV_REMOVE,
index 2c5c22c93ba8e787a1666e74d1b2256c4f894a27..d0407ba53bb7e81b45ecc2b6cfeb6af60ef747b8 100644 (file)
@@ -42,8 +42,8 @@
 
 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)
+       return sizeof(*desc)
+               + ioread8(&desc->num_vq) * sizeof(struct mic_vqconfig)
                + ioread8(&desc->feature_len) * 2
                + ioread8(&desc->config_len);
 }
@@ -67,8 +67,7 @@ mic_vq_configspace(struct mic_device_desc __iomem *desc)
 }
 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);
+       return mic_aligned_desc_size(desc) + sizeof(struct mic_device_ctrl);
 }
 
 int mic_devices_init(struct mic_driver *mdrv);
index 7558d91864380ae849d90a24deee4e31985850eb..b75c6b5cc20fc7a908944291add52a5cada071ff 100644 (file)
@@ -62,7 +62,7 @@ void mic_bootparam_init(struct mic_device *mdev)
 {
        struct mic_bootparam *bootparam = mdev->dp;
 
-       bootparam->magic = MIC_MAGIC;
+       bootparam->magic = cpu_to_le32(MIC_MAGIC);
        bootparam->c2h_shutdown_db = mdev->shutdown_db;
        bootparam->h2c_shutdown_db = -1;
        bootparam->h2c_config_db = -1;
index 5b8494bd1e003ff9cb53d49fa7ffd22798893912..e04bb4fe68235a7de2ac7e5c09c7c027776cb39c 100644 (file)
@@ -41,7 +41,7 @@ static int mic_virtio_copy_to_user(struct mic_vdev *mvdev,
         * 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)) {
+       if (copy_to_user(ubuf, (void __force *)dbuf, len)) {
                err = -EFAULT;
                dev_err(mic_dev(mvdev), "%s %d err %d\n",
                        __func__, __LINE__, err);
@@ -66,7 +66,7 @@ static int mic_virtio_copy_from_user(struct mic_vdev *mvdev,
         * 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)) {
+       if (copy_from_user((void __force *)dbuf, ubuf, len)) {
                err = -EFAULT;
                dev_err(mic_dev(mvdev), "%s %d err %d\n",
                        __func__, __LINE__, err);
@@ -293,7 +293,7 @@ static void mic_virtio_init_post(struct mic_vdev *mvdev)
                        continue;
                }
                mvdev->mvr[i].vrh.vring.used =
-                       mvdev->mdev->aper.va +
+                       (void __force *)mvdev->mdev->aper.va +
                        le64_to_cpu(vqconfig[i].used_address);
        }
 
@@ -378,7 +378,7 @@ int mic_virtio_config_change(struct mic_vdev *mvdev,
                        void __user *argp)
 {
        DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake);
-       int ret = 0, retry = 100, i;
+       int ret = 0, retry, i;
        struct mic_bootparam *bootparam = mvdev->mdev->dp;
        s8 db = bootparam->h2c_config_db;
 
@@ -401,7 +401,7 @@ int mic_virtio_config_change(struct mic_vdev *mvdev,
        mvdev->dc->config_change = MIC_VIRTIO_PARAM_CONFIG_CHANGED;
        mvdev->mdev->ops->send_intr(mvdev->mdev, db);
 
-       for (i = retry; i--;) {
+       for (retry = 100; retry--;) {
                ret = wait_event_timeout(wake,
                        mvdev->dc->guest_ack, msecs_to_jiffies(100));
                if (ret)
@@ -467,7 +467,7 @@ static int mic_copy_dp_entry(struct mic_vdev *mvdev,
        }
 
        /* Find the first free device page entry */
-       for (i = mic_aligned_size(struct mic_bootparam);
+       for (i = sizeof(struct mic_bootparam);
                i < MIC_DP_SIZE - mic_total_desc_size(dd_config);
                i += mic_total_desc_size(devp)) {
                devp = mdev->dp + i;
@@ -525,6 +525,7 @@ int mic_virtio_add_device(struct mic_vdev *mvdev,
        char irqname[10];
        struct mic_bootparam *bootparam = mdev->dp;
        u16 num;
+       dma_addr_t vr_addr;
 
        mutex_lock(&mdev->mic_mutex);
 
@@ -559,17 +560,16 @@ int mic_virtio_add_device(struct mic_vdev *mvdev,
                }
                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)) {
+               vr->info->magic = cpu_to_le32(MIC_MAGIC + mvdev->virtio_id + i);
+               vr_addr = mic_map_single(mdev, vr->va, vr_size);
+               if (mic_map_error(vr_addr)) {
                        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);
+               vqconfig[i].address = cpu_to_le64(vr_addr);
 
                vring_init(&vr->vr, num, vr->va, MIC_VIRTIO_RING_ALIGN);
                ret = vringh_init_kern(&mvr->vrh,
@@ -639,7 +639,7 @@ void mic_virtio_del_device(struct mic_vdev *mvdev)
        struct mic_vdev *tmp_mvdev;
        struct mic_device *mdev = mvdev->mdev;
        DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake);
-       int i, ret, retry = 100;
+       int i, ret, retry;
        struct mic_vqconfig *vqconfig;
        struct mic_bootparam *bootparam = mdev->dp;
        s8 db;
@@ -652,16 +652,16 @@ void mic_virtio_del_device(struct mic_vdev *mvdev)
                "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--;) {
+       for (retry = 100; retry--;) {
                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",
+               "Device id %d config_change %d guest_ack %d retry %d\n",
                mvdev->virtio_id, mvdev->dc->config_change,
-               mvdev->dc->guest_ack);
+               mvdev->dc->guest_ack, retry);
        mvdev->dc->config_change = 0;
        mvdev->dc->guest_ack = 0;
 skip_hot_remove:
index 81e9541b784c3a4d46bbd352c2aa26faf70c2877..0dfa8a81436e80ebd325d1722caa791d5193936e 100644 (file)
@@ -397,8 +397,8 @@ mic_x100_load_ramdisk(struct mic_device *mdev)
         * 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);
+       iowrite32(mdev->bootaddr << 1, &bp->hdr.ramdisk_image);
+       iowrite32(fw->size, &bp->hdr.ramdisk_size);
        release_firmware(fw);
 error:
        return rc;
index 157b570ba343e4648b796e7330e7b75bc052d00a..92d1ba8e8153ab9849ab51037804747cd37df7f1 100644 (file)
@@ -308,7 +308,7 @@ static void sdio_acpi_set_handle(struct sdio_func *func)
        struct mmc_host *host = func->card->host;
        u64 addr = (host->slotno << 16) | func->num;
 
-       acpi_preset_companion(&func->dev, ACPI_HANDLE(host->parent), addr);
+       acpi_preset_companion(&func->dev, ACPI_COMPANION(host->parent), addr);
 }
 #else
 static inline void sdio_acpi_set_handle(struct sdio_func *func) {}
index f32057972dd77fe9a7487f74aa2ab727c2126db6..b931226365317b6b64ed2462c1beeb25b7857d16 100644 (file)
@@ -1683,8 +1683,6 @@ static int mmci_remove(struct amba_device *dev)
 {
        struct mmc_host *mmc = amba_get_drvdata(dev);
 
-       amba_set_drvdata(dev, NULL);
-
        if (mmc) {
                struct mmci_host *host = mmc_priv(mmc);
 
index 0b10a9030f4e2a85029ea4bab3afcdb8102899be..98b6b6ef7e5c9d737a749e9a3ddf631f5d92c1c0 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/delay.h>
 #include <linux/spinlock.h>
 #include <linux/timer.h>
+#include <linux/of.h>
 #include <linux/omap-dma.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/card.h>
 #define OMAP_MMC_CMDTYPE_AC    2
 #define OMAP_MMC_CMDTYPE_ADTC  3
 
-#define OMAP_DMA_MMC_TX                21
-#define OMAP_DMA_MMC_RX                22
-#define OMAP_DMA_MMC2_TX       54
-#define OMAP_DMA_MMC2_RX       55
-
-#define OMAP24XX_DMA_MMC2_TX   47
-#define OMAP24XX_DMA_MMC2_RX   48
-#define OMAP24XX_DMA_MMC1_TX   61
-#define OMAP24XX_DMA_MMC1_RX   62
-
-
 #define DRIVER_NAME "mmci-omap"
 
 /* Specifies how often in millisecs to poll for card status changes
@@ -1330,7 +1320,7 @@ static int mmc_omap_probe(struct platform_device *pdev)
        struct mmc_omap_host *host = NULL;
        struct resource *res;
        dma_cap_mask_t mask;
-       unsigned sig;
+       unsigned sig = 0;
        int i, ret = 0;
        int irq;
 
@@ -1340,7 +1330,7 @@ static int mmc_omap_probe(struct platform_device *pdev)
        }
        if (pdata->nr_slots == 0) {
                dev_err(&pdev->dev, "no slots\n");
-               return -ENXIO;
+               return -EPROBE_DEFER;
        }
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1407,19 +1397,20 @@ static int mmc_omap_probe(struct platform_device *pdev)
        host->dma_tx_burst = -1;
        host->dma_rx_burst = -1;
 
-       if (mmc_omap2())
-               sig = host->id == 0 ? OMAP24XX_DMA_MMC1_TX : OMAP24XX_DMA_MMC2_TX;
-       else
-               sig = host->id == 0 ? OMAP_DMA_MMC_TX : OMAP_DMA_MMC2_TX;
-       host->dma_tx = dma_request_channel(mask, omap_dma_filter_fn, &sig);
+       res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
+       if (res)
+               sig = res->start;
+       host->dma_tx = dma_request_slave_channel_compat(mask,
+                               omap_dma_filter_fn, &sig, &pdev->dev, "tx");
        if (!host->dma_tx)
                dev_warn(host->dev, "unable to obtain TX DMA engine channel %u\n",
                        sig);
-       if (mmc_omap2())
-               sig = host->id == 0 ? OMAP24XX_DMA_MMC1_RX : OMAP24XX_DMA_MMC2_RX;
-       else
-               sig = host->id == 0 ? OMAP_DMA_MMC_RX : OMAP_DMA_MMC2_RX;
-       host->dma_rx = dma_request_channel(mask, omap_dma_filter_fn, &sig);
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
+       if (res)
+               sig = res->start;
+       host->dma_rx = dma_request_slave_channel_compat(mask,
+                               omap_dma_filter_fn, &sig, &pdev->dev, "rx");
        if (!host->dma_rx)
                dev_warn(host->dev, "unable to obtain RX DMA engine channel %u\n",
                        sig);
@@ -1512,12 +1503,20 @@ static int mmc_omap_remove(struct platform_device *pdev)
        return 0;
 }
 
+#if IS_BUILTIN(CONFIG_OF)
+static const struct of_device_id mmc_omap_match[] = {
+       { .compatible = "ti,omap2420-mmc", },
+       { },
+};
+#endif
+
 static struct platform_driver mmc_omap_driver = {
        .probe          = mmc_omap_probe,
        .remove         = mmc_omap_remove,
        .driver         = {
                .name   = DRIVER_NAME,
                .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(mmc_omap_match),
        },
 };
 
index 5a3942bf109cd9ccded20d42fc4ee62b36a3ad8e..96a33e3f7b000394c1480260246585531c88b920 100644 (file)
@@ -264,7 +264,8 @@ static struct mtd_part_parser afs_parser = {
 
 static int __init afs_parser_init(void)
 {
-       return register_mtd_parser(&afs_parser);
+       register_mtd_parser(&afs_parser);
+       return 0;
 }
 
 static void __exit afs_parser_exit(void)
index ddc0a4287a4b89c8124dd3629b9647e3ca800b74..7c9172ad26210e1d25c9506889e0cbb54212dbfe 100644 (file)
@@ -139,7 +139,8 @@ static struct mtd_part_parser ar7_parser = {
 
 static int __init ar7_parser_init(void)
 {
-       return register_mtd_parser(&ar7_parser);
+       register_mtd_parser(&ar7_parser);
+       return 0;
 }
 
 static void __exit ar7_parser_exit(void)
index 7a6384b0962a9de2c92dffb81f1fc45d6d89a490..931746ded98905af7bf0fd75376eeded39b17817 100644 (file)
@@ -243,7 +243,8 @@ static struct mtd_part_parser bcm47xxpart_mtd_parser = {
 
 static int __init bcm47xxpart_init(void)
 {
-       return register_mtd_parser(&bcm47xxpart_mtd_parser);
+       register_mtd_parser(&bcm47xxpart_mtd_parser);
+       return 0;
 }
 
 static void __exit bcm47xxpart_exit(void)
index 5c813907661c3415c979b1176bf937f7c086f2c8..b2443f7031c9afb0bda808a37b6da7e8113d0a61 100644 (file)
@@ -221,7 +221,8 @@ static struct mtd_part_parser bcm63xx_cfe_parser = {
 
 static int __init bcm63xx_cfe_parser_init(void)
 {
-       return register_mtd_parser(&bcm63xx_cfe_parser);
+       register_mtd_parser(&bcm63xx_cfe_parser);
+       return 0;
 }
 
 static void __exit bcm63xx_cfe_parser_exit(void)
index 721caebbc5cc21344a58a710d466205f75f845ef..3e829b37af8d0e0d5c73eff2c03e054ed6516eab 100644 (file)
@@ -395,7 +395,8 @@ static int __init cmdline_parser_init(void)
 {
        if (mtdparts)
                mtdpart_setup(mtdparts);
-       return register_mtd_parser(&cmdline_parser);
+       register_mtd_parser(&cmdline_parser);
+       return 0;
 }
 
 static void __exit cmdline_parser_exit(void)
index 7eda71dbc183b7aa456e60a41f0490c882d94331..7b976e869636ffe5b920032f53df977bdedd050a 100644 (file)
@@ -41,6 +41,7 @@
 #define        OPCODE_WRSR             0x01    /* Write status register 1 byte */
 #define        OPCODE_NORM_READ        0x03    /* Read data bytes (low frequency) */
 #define        OPCODE_FAST_READ        0x0b    /* Read data bytes (high frequency) */
+#define        OPCODE_QUAD_READ        0x6b    /* Read data bytes */
 #define        OPCODE_PP               0x02    /* Page program (up to 256 bytes) */
 #define        OPCODE_BE_4K            0x20    /* Erase 4KiB block */
 #define        OPCODE_BE_4K_PMC        0xd7    /* Erase 4KiB block on PMC chips */
 #define        OPCODE_CHIP_ERASE       0xc7    /* Erase whole flash chip */
 #define        OPCODE_SE               0xd8    /* Sector erase (usually 64KiB) */
 #define        OPCODE_RDID             0x9f    /* Read JEDEC ID */
+#define        OPCODE_RDCR             0x35    /* Read configuration register */
 
 /* 4-byte address opcodes - used on Spansion and some Macronix flashes. */
 #define        OPCODE_NORM_READ_4B     0x13    /* Read data bytes (low frequency) */
 #define        OPCODE_FAST_READ_4B     0x0c    /* Read data bytes (high frequency) */
+#define        OPCODE_QUAD_READ_4B     0x6c    /* Read data bytes */
 #define        OPCODE_PP_4B            0x12    /* Page program (up to 256 bytes) */
 #define        OPCODE_SE_4B            0xdc    /* Sector erase (usually 64KiB) */
 
 #define        SR_BP2                  0x10    /* Block protect 2 */
 #define        SR_SRWD                 0x80    /* SR write protect */
 
+#define SR_QUAD_EN_MX           0x40    /* Macronix Quad I/O */
+
+/* Configuration Register bits. */
+#define CR_QUAD_EN_SPAN                0x2     /* Spansion Quad I/O */
+
 /* Define max times to check status register before we give up. */
 #define        MAX_READY_WAIT_JIFFIES  (40 * HZ)       /* M25P16 specs 40s max chip erase */
 #define        MAX_CMD_SIZE            6
 
 /****************************************************************************/
 
+enum read_type {
+       M25P80_NORMAL = 0,
+       M25P80_FAST,
+       M25P80_QUAD,
+};
+
 struct m25p {
        struct spi_device       *spi;
        struct mutex            lock;
@@ -94,7 +108,7 @@ struct m25p {
        u8                      read_opcode;
        u8                      program_opcode;
        u8                      *command;
-       bool                    fast_read;
+       enum read_type          flash_read;
 };
 
 static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd)
@@ -130,6 +144,26 @@ static int read_sr(struct m25p *flash)
        return val;
 }
 
+/*
+ * Read configuration register, returning its value in the
+ * location. Return the configuration register value.
+ * Returns negative if error occured.
+ */
+static int read_cr(struct m25p *flash)
+{
+       u8 code = OPCODE_RDCR;
+       int ret;
+       u8 val;
+
+       ret = spi_write_then_read(flash->spi, &code, 1, &val, 1);
+       if (ret < 0) {
+               dev_err(&flash->spi->dev, "error %d reading CR\n", ret);
+               return ret;
+       }
+
+       return val;
+}
+
 /*
  * Write status register 1 byte
  * Returns negative if error occurred.
@@ -219,6 +253,93 @@ static int wait_till_ready(struct m25p *flash)
        return 1;
 }
 
+/*
+ * Write status Register and configuration register with 2 bytes
+ * The first byte will be written to the status register, while the
+ * second byte will be written to the configuration register.
+ * Return negative if error occured.
+ */
+static int write_sr_cr(struct m25p *flash, u16 val)
+{
+       flash->command[0] = OPCODE_WRSR;
+       flash->command[1] = val & 0xff;
+       flash->command[2] = (val >> 8);
+
+       return spi_write(flash->spi, flash->command, 3);
+}
+
+static int macronix_quad_enable(struct m25p *flash)
+{
+       int ret, val;
+       u8 cmd[2];
+       cmd[0] = OPCODE_WRSR;
+
+       val = read_sr(flash);
+       cmd[1] = val | SR_QUAD_EN_MX;
+       write_enable(flash);
+
+       spi_write(flash->spi, &cmd, 2);
+
+       if (wait_till_ready(flash))
+               return 1;
+
+       ret = read_sr(flash);
+       if (!(ret > 0 && (ret & SR_QUAD_EN_MX))) {
+               dev_err(&flash->spi->dev, "Macronix Quad bit not set\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int spansion_quad_enable(struct m25p *flash)
+{
+       int ret;
+       int quad_en = CR_QUAD_EN_SPAN << 8;
+
+       write_enable(flash);
+
+       ret = write_sr_cr(flash, quad_en);
+       if (ret < 0) {
+               dev_err(&flash->spi->dev,
+                       "error while writing configuration register\n");
+               return -EINVAL;
+       }
+
+       /* read back and check it */
+       ret = read_cr(flash);
+       if (!(ret > 0 && (ret & CR_QUAD_EN_SPAN))) {
+               dev_err(&flash->spi->dev, "Spansion Quad bit not set\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int set_quad_mode(struct m25p *flash, u32 jedec_id)
+{
+       int status;
+
+       switch (JEDEC_MFR(jedec_id)) {
+       case CFI_MFR_MACRONIX:
+               status = macronix_quad_enable(flash);
+               if (status) {
+                       dev_err(&flash->spi->dev,
+                               "Macronix quad-read not enabled\n");
+                       return -EINVAL;
+               }
+               return status;
+       default:
+               status = spansion_quad_enable(flash);
+               if (status) {
+                       dev_err(&flash->spi->dev,
+                               "Spansion quad-read not enabled\n");
+                       return -EINVAL;
+               }
+               return status;
+       }
+}
+
 /*
  * Erase the whole flash memory
  *
@@ -349,6 +470,25 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
        return 0;
 }
 
+/*
+ * Dummy Cycle calculation for different type of read.
+ * It can be used to support more commands with
+ * different dummy cycle requirements.
+ */
+static inline int m25p80_dummy_cycles_read(struct m25p *flash)
+{
+       switch (flash->flash_read) {
+       case M25P80_FAST:
+       case M25P80_QUAD:
+               return 1;
+       case M25P80_NORMAL:
+               return 0;
+       default:
+               dev_err(&flash->spi->dev, "No valid read type supported\n");
+               return -1;
+       }
+}
+
 /*
  * Read an address range from the flash chip.  The address range
  * may be any size provided it is within the physical boundaries.
@@ -360,6 +500,7 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
        struct spi_transfer t[2];
        struct spi_message m;
        uint8_t opcode;
+       int dummy;
 
        pr_debug("%s: %s from 0x%08x, len %zd\n", dev_name(&flash->spi->dev),
                        __func__, (u32)from, len);
@@ -367,8 +508,14 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
        spi_message_init(&m);
        memset(t, 0, (sizeof t));
 
+       dummy =  m25p80_dummy_cycles_read(flash);
+       if (dummy < 0) {
+               dev_err(&flash->spi->dev, "No valid read command supported\n");
+               return -EINVAL;
+       }
+
        t[0].tx_buf = flash->command;
-       t[0].len = m25p_cmdsz(flash) + (flash->fast_read ? 1 : 0);
+       t[0].len = m25p_cmdsz(flash) + dummy;
        spi_message_add_tail(&t[0], &m);
 
        t[1].rx_buf = buf;
@@ -391,8 +538,7 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
 
        spi_sync(flash->spi, &m);
 
-       *retlen = m.actual_length - m25p_cmdsz(flash) -
-                       (flash->fast_read ? 1 : 0);
+       *retlen = m.actual_length - m25p_cmdsz(flash) - dummy;
 
        mutex_unlock(&flash->lock);
 
@@ -698,6 +844,7 @@ struct flash_info {
 #define        SST_WRITE       0x04            /* use SST byte programming */
 #define        M25P_NO_FR      0x08            /* Can't do fastread */
 #define        SECT_4K_PMC     0x10            /* OPCODE_BE_4K_PMC works uniformly */
+#define        M25P80_QUAD_READ        0x20    /* Flash supports Quad Read */
 };
 
 #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags)     \
@@ -775,7 +922,7 @@ static const struct spi_device_id m25p_ids[] = {
        { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
        { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) },
        { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
-       { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, 0) },
+       { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, M25P80_QUAD_READ) },
 
        /* Micron */
        { "n25q064",     INFO(0x20ba17, 0, 64 * 1024,  128, 0) },
@@ -795,7 +942,7 @@ static const struct spi_device_id m25p_ids[] = {
        { "s25sl032p",  INFO(0x010215, 0x4d00,  64 * 1024,  64, 0) },
        { "s25sl064p",  INFO(0x010216, 0x4d00,  64 * 1024, 128, 0) },
        { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 0) },
-       { "s25fl256s1", INFO(0x010219, 0x4d01,  64 * 1024, 512, 0) },
+       { "s25fl256s1", INFO(0x010219, 0x4d01,  64 * 1024, 512, M25P80_QUAD_READ) },
        { "s25fl512s",  INFO(0x010220, 0x4d00, 256 * 1024, 256, 0) },
        { "s70fl01gs",  INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) },
        { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024,  64, 0) },
@@ -851,6 +998,7 @@ static const struct spi_device_id m25p_ids[] = {
        { "m25pe80", INFO(0x208014,  0, 64 * 1024, 16,       0) },
        { "m25pe16", INFO(0x208015,  0, 64 * 1024, 32, SECT_4K) },
 
+       { "m25px16",    INFO(0x207115,  0, 64 * 1024, 32, SECT_4K) },
        { "m25px32",    INFO(0x207116,  0, 64 * 1024, 64, SECT_4K) },
        { "m25px32-s0", INFO(0x207316,  0, 64 * 1024, 64, SECT_4K) },
        { "m25px32-s1", INFO(0x206316,  0, 64 * 1024, 64, SECT_4K) },
@@ -937,6 +1085,7 @@ static int m25p_probe(struct spi_device *spi)
        unsigned                        i;
        struct mtd_part_parser_data     ppdata;
        struct device_node *np = spi->dev.of_node;
+       int ret;
 
        /* Platform data helps sort out which chip type we have, as
         * well as how this board partitions it.  If we don't have
@@ -1051,22 +1200,44 @@ static int m25p_probe(struct spi_device *spi)
        flash->page_size = info->page_size;
        flash->mtd.writebufsize = flash->page_size;
 
-       if (np)
+       if (np) {
                /* If we were instantiated by DT, use it */
-               flash->fast_read = of_property_read_bool(np, "m25p,fast-read");
-       else
+               if (of_property_read_bool(np, "m25p,fast-read"))
+                       flash->flash_read = M25P80_FAST;
+       } else {
                /* If we weren't instantiated by DT, default to fast-read */
-               flash->fast_read = true;
+               flash->flash_read = M25P80_FAST;
+       }
 
        /* Some devices cannot do fast-read, no matter what DT tells us */
        if (info->flags & M25P_NO_FR)
-               flash->fast_read = false;
+               flash->flash_read = M25P80_NORMAL;
+
+       /* Quad-read mode takes precedence over fast/normal */
+       if (spi->mode & SPI_RX_QUAD && info->flags & M25P80_QUAD_READ) {
+               ret = set_quad_mode(flash, info->jedec_id);
+               if (ret) {
+                       dev_err(&flash->spi->dev, "quad mode not supported\n");
+                       return ret;
+               }
+               flash->flash_read = M25P80_QUAD;
+       }
 
        /* Default commands */
-       if (flash->fast_read)
+       switch (flash->flash_read) {
+       case M25P80_QUAD:
+               flash->read_opcode = OPCODE_QUAD_READ;
+               break;
+       case M25P80_FAST:
                flash->read_opcode = OPCODE_FAST_READ;
-       else
+               break;
+       case M25P80_NORMAL:
                flash->read_opcode = OPCODE_NORM_READ;
+               break;
+       default:
+               dev_err(&flash->spi->dev, "No Read opcode defined\n");
+               return -EINVAL;
+       }
 
        flash->program_opcode = OPCODE_PP;
 
@@ -1077,9 +1248,17 @@ static int m25p_probe(struct spi_device *spi)
                flash->addr_width = 4;
                if (JEDEC_MFR(info->jedec_id) == CFI_MFR_AMD) {
                        /* Dedicated 4-byte command set */
-                       flash->read_opcode = flash->fast_read ?
-                               OPCODE_FAST_READ_4B :
-                               OPCODE_NORM_READ_4B;
+                       switch (flash->flash_read) {
+                       case M25P80_QUAD:
+                               flash->read_opcode = OPCODE_QUAD_READ;
+                               break;
+                       case M25P80_FAST:
+                               flash->read_opcode = OPCODE_FAST_READ_4B;
+                               break;
+                       case M25P80_NORMAL:
+                               flash->read_opcode = OPCODE_NORM_READ_4B;
+                               break;
+                       }
                        flash->program_opcode = OPCODE_PP_4B;
                        /* No small sector erase for 4-byte command set */
                        flash->erase_opcode = OPCODE_SE_4B;
index 182849d39c61acb34c40a79ab6bf04e30162da79..5c8b322ba904b1691bf204efc3f4523106dc8f67 100644 (file)
@@ -205,7 +205,7 @@ static int __init ms02nv_init_one(ulong addr)
        mtd->type = MTD_RAM;
        mtd->flags = MTD_CAP_RAM;
        mtd->size = fixsize;
-       mtd->name = (char *)ms02nv_name;
+       mtd->name = ms02nv_name;
        mtd->owner = THIS_MODULE;
        mtd->_read = ms02nv_read;
        mtd->_write = ms02nv_write;
index 4a47b0266d4e587761a2db5c1cd2e1613fc710bc..624069de4f28c067260fc4fec75c35b713fc5c84 100644 (file)
@@ -669,7 +669,6 @@ static int add_dataflash_otp(struct spi_device *spi, char *name, int nr_pages,
        if (!err)
                return 0;
 
-       spi_set_drvdata(spi, NULL);
        kfree(priv);
        return err;
 }
@@ -899,10 +898,8 @@ static int dataflash_remove(struct spi_device *spi)
        pr_debug("%s: remove\n", dev_name(&spi->dev));
 
        status = mtd_device_unregister(&flash->mtd);
-       if (status == 0) {
-               spi_set_drvdata(spi, NULL);
+       if (status == 0)
                kfree(flash);
-       }
        return status;
 }
 
index d210d131fef255da97e7d277574ac80f01a66341..9aad854fe9121aaa821181bffe64e819ec0e8498 100644 (file)
@@ -61,7 +61,7 @@ static int pxa2xx_flash_probe(struct platform_device *pdev)
        if (!info)
                return -ENOMEM;
 
-       info->map.name = (char *) flash->name;
+       info->map.name = flash->name;
        info->map.bankwidth = flash->width;
        info->map.phys = res->start;
        info->map.size = resource_size(res);
@@ -73,7 +73,7 @@ static int pxa2xx_flash_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
        info->map.cached =
-               ioremap_cached(info->map.phys, info->map.size);
+               ioremap_cache(info->map.phys, info->map.size);
        if (!info->map.cached)
                printk(KERN_WARNING "Failed to ioremap cached %s\n",
                       info->map.name);
index d467f3b11c96c72ded5f3019cc823eb50fc6bd0b..39cc4181f02538a438b8fc427e00e19c1074fde3 100644 (file)
@@ -75,7 +75,7 @@ int uflash_devinit(struct platform_device *op, struct device_node *dp)
 
        up->name = of_get_property(dp, "model", NULL);
        if (up->name && 0 < strlen(up->name))
-               up->map.name = (char *)up->name;
+               up->map.name = up->name;
 
        up->map.phys = op->resource[0].start;
 
index 92311a56939fca8d53e05e178054520f80b3bcec..34c0b16aed5c4e2f7d61a22d3fdeaf2ca066a632 100644 (file)
@@ -313,15 +313,7 @@ static struct attribute *mtd_attrs[] = {
        &dev_attr_bitflip_threshold.attr,
        NULL,
 };
-
-static struct attribute_group mtd_group = {
-       .attrs          = mtd_attrs,
-};
-
-static const struct attribute_group *mtd_groups[] = {
-       &mtd_group,
-       NULL,
-};
+ATTRIBUTE_GROUPS(mtd);
 
 static struct device_type mtd_devtype = {
        .name           = "mtd",
index 6e732c3820c14bf9d07b693a0c1de9bfff0088f0..3c7d6d7623c1cd5557b4dfeb38e80e03fc6e2abc 100644 (file)
@@ -534,7 +534,7 @@ out_register:
        return slave;
 }
 
-int mtd_add_partition(struct mtd_info *master, char *name,
+int mtd_add_partition(struct mtd_info *master, const char *name,
                      long long offset, long long length)
 {
        struct mtd_partition part;
@@ -672,22 +672,19 @@ static struct mtd_part_parser *get_partition_parser(const char *name)
 
 #define put_partition_parser(p) do { module_put((p)->owner); } while (0)
 
-int register_mtd_parser(struct mtd_part_parser *p)
+void register_mtd_parser(struct mtd_part_parser *p)
 {
        spin_lock(&part_parser_lock);
        list_add(&p->list, &part_parsers);
        spin_unlock(&part_parser_lock);
-
-       return 0;
 }
 EXPORT_SYMBOL_GPL(register_mtd_parser);
 
-int deregister_mtd_parser(struct mtd_part_parser *p)
+void deregister_mtd_parser(struct mtd_part_parser *p)
 {
        spin_lock(&part_parser_lock);
        list_del(&p->list);
        spin_unlock(&part_parser_lock);
-       return 0;
 }
 EXPORT_SYMBOL_GPL(deregister_mtd_parser);
 
index 93ae6a6d94f713d6352abd612efd1fed05f43dfd..a7808e6d4c711efb5436323d714f328a89c873c3 100644 (file)
@@ -95,7 +95,7 @@ config MTD_NAND_OMAP2
          platforms.
 
 config MTD_NAND_OMAP_BCH
-       depends on MTD_NAND && MTD_NAND_OMAP2 && ARCH_OMAP3
+       depends on MTD_NAND_OMAP2
        tristate "Support hardware based BCH error correction"
        default n
        select BCH
@@ -326,11 +326,11 @@ config MTD_NAND_ATMEL
          on Atmel AT91 and AVR32 processors.
 
 config MTD_NAND_PXA3xx
-       tristate "Support for NAND flash devices on PXA3xx"
+       tristate "NAND support on PXA3xx and Armada 370/XP"
        depends on PXA3xx || ARCH_MMP || PLAT_ORION
        help
          This enables the driver for the NAND flash device found on
-         PXA3xx processors
+         PXA3xx processors (NFCv1) and also on Armada 370/XP (NFCv2).
 
 config MTD_NAND_SLC_LPC32XX
        tristate "NXP LPC32xx SLC Controller"
@@ -458,7 +458,7 @@ config MTD_NAND_MXC
 
 config MTD_NAND_SH_FLCTL
        tristate "Support for NAND on Renesas SuperH FLCTL"
-       depends on SUPERH || ARCH_SHMOBILE
+       depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST
        help
          Several Renesas SuperH CPU has FLCTL. This option enables support
          for NAND Flash using FLCTL.
index 033f177a6369b2d240b499f33df0b6bd925ed4d2..622dfb7eba66f8df6c1011735be3709d1eaf657b 100644 (file)
@@ -21,7 +21,7 @@
 #define DENALI_NAND_NAME    "denali-nand-pci"
 
 /* List of platforms this NAND controller has be integrated into */
-static DEFINE_PCI_DEVICE_TABLE(denali_pci_ids) = {
+static const struct pci_device_id denali_pci_ids[] = {
        { PCI_VDEVICE(INTEL, 0x0701), INTEL_CE4100 },
        { PCI_VDEVICE(INTEL, 0x0809), INTEL_MRST },
        { /* end: all zeroes */ }
index b68a4959f700af3e2768af69e6dd9afd0f94c8e1..0afafa049ea139672136ef4fd929edc740261c70 100644 (file)
@@ -1440,10 +1440,13 @@ static int __init doc_probe(unsigned long physadr)
        int reg, len, numchips;
        int ret = 0;
 
+       if (!request_mem_region(physadr, DOC_IOREMAP_LEN, NULL))
+               return -EBUSY;
        virtadr = ioremap(physadr, DOC_IOREMAP_LEN);
        if (!virtadr) {
                printk(KERN_ERR "Diskonchip ioremap failed: 0x%x bytes at 0x%lx\n", DOC_IOREMAP_LEN, physadr);
-               return -EIO;
+               ret = -EIO;
+               goto error_ioremap;
        }
 
        /* It's not possible to cleanly detect the DiskOnChip - the
@@ -1629,6 +1632,10 @@ static int __init doc_probe(unsigned long physadr)
        WriteDOC(save_control, virtadr, DOCControl);
  fail:
        iounmap(virtadr);
+
+error_ioremap:
+       release_mem_region(physadr, DOC_IOREMAP_LEN);
+
        return ret;
 }
 
@@ -1645,6 +1652,7 @@ static void release_nanddoc(void)
                nextmtd = doc->nextdoc;
                nand_release(mtd);
                iounmap(doc->virtadr);
+               release_mem_region(doc->physadr, DOC_IOREMAP_LEN);
                kfree(mtd);
        }
 }
index aaced29727fb0437f6a0c142253b04cbc0ca82d0..dd1df605a1d61ec8a43ffb5515ea50ce2f3c9b69 100644 (file)
@@ -20,6 +20,7 @@
  */
 #include <linux/delay.h>
 #include <linux/clk.h>
+#include <linux/slab.h>
 
 #include "gpmi-nand.h"
 #include "gpmi-regs.h"
@@ -207,30 +208,41 @@ void gpmi_dump_info(struct gpmi_nand_data *this)
        u32 reg;
        int i;
 
-       pr_err("Show GPMI registers :\n");
+       dev_err(this->dev, "Show GPMI registers :\n");
        for (i = 0; i <= HW_GPMI_DEBUG / 0x10 + 1; i++) {
                reg = readl(r->gpmi_regs + i * 0x10);
-               pr_err("offset 0x%.3x : 0x%.8x\n", i * 0x10, reg);
+               dev_err(this->dev, "offset 0x%.3x : 0x%.8x\n", i * 0x10, reg);
        }
 
        /* start to print out the BCH info */
-       pr_err("Show BCH registers :\n");
+       dev_err(this->dev, "Show BCH registers :\n");
        for (i = 0; i <= HW_BCH_VERSION / 0x10 + 1; i++) {
                reg = readl(r->bch_regs + i * 0x10);
-               pr_err("offset 0x%.3x : 0x%.8x\n", i * 0x10, reg);
+               dev_err(this->dev, "offset 0x%.3x : 0x%.8x\n", i * 0x10, reg);
        }
-       pr_err("BCH Geometry :\n");
-       pr_err("GF length              : %u\n", geo->gf_len);
-       pr_err("ECC Strength           : %u\n", geo->ecc_strength);
-       pr_err("Page Size in Bytes     : %u\n", geo->page_size);
-       pr_err("Metadata Size in Bytes : %u\n", geo->metadata_size);
-       pr_err("ECC Chunk Size in Bytes: %u\n", geo->ecc_chunk_size);
-       pr_err("ECC Chunk Count        : %u\n", geo->ecc_chunk_count);
-       pr_err("Payload Size in Bytes  : %u\n", geo->payload_size);
-       pr_err("Auxiliary Size in Bytes: %u\n", geo->auxiliary_size);
-       pr_err("Auxiliary Status Offset: %u\n", geo->auxiliary_status_offset);
-       pr_err("Block Mark Byte Offset : %u\n", geo->block_mark_byte_offset);
-       pr_err("Block Mark Bit Offset  : %u\n", geo->block_mark_bit_offset);
+       dev_err(this->dev, "BCH Geometry :\n"
+               "GF length              : %u\n"
+               "ECC Strength           : %u\n"
+               "Page Size in Bytes     : %u\n"
+               "Metadata Size in Bytes : %u\n"
+               "ECC Chunk Size in Bytes: %u\n"
+               "ECC Chunk Count        : %u\n"
+               "Payload Size in Bytes  : %u\n"
+               "Auxiliary Size in Bytes: %u\n"
+               "Auxiliary Status Offset: %u\n"
+               "Block Mark Byte Offset : %u\n"
+               "Block Mark Bit Offset  : %u\n",
+               geo->gf_len,
+               geo->ecc_strength,
+               geo->page_size,
+               geo->metadata_size,
+               geo->ecc_chunk_size,
+               geo->ecc_chunk_count,
+               geo->payload_size,
+               geo->auxiliary_size,
+               geo->auxiliary_status_offset,
+               geo->block_mark_byte_offset,
+               geo->block_mark_bit_offset);
 }
 
 /* Configures the geometry for BCH.  */
@@ -265,8 +277,8 @@ int bch_set_geometry(struct gpmi_nand_data *this)
        * chip, otherwise it will lock up. So we skip resetting BCH on the MX23.
        * On the other hand, the MX28 needs the reset, because one case has been
        * seen where the BCH produced ECC errors constantly after 10000
-       * consecutive reboots. The latter case has not been seen on the MX23 yet,
-       * still we don't know if it could happen there as well.
+       * consecutive reboots. The latter case has not been seen on the MX23
+       * yet, still we don't know if it could happen there as well.
        */
        ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this));
        if (ret)
@@ -353,7 +365,7 @@ static int gpmi_nfc_compute_hardware_timing(struct gpmi_nand_data *this,
        improved_timing_is_available =
                (target.tREA_in_ns  >= 0) &&
                (target.tRLOH_in_ns >= 0) &&
-               (target.tRHOH_in_ns >= 0) ;
+               (target.tRHOH_in_ns >= 0);
 
        /* Inspect the clock. */
        nfc->clock_frequency_in_hz = clk_get_rate(r->clock[0]);
@@ -911,10 +923,14 @@ static int enable_edo_mode(struct gpmi_nand_data *this, int mode)
        struct resources  *r = &this->resources;
        struct nand_chip *nand = &this->nand;
        struct mtd_info  *mtd = &this->mtd;
-       uint8_t feature[ONFI_SUBFEATURE_PARAM_LEN] = {};
+       uint8_t *feature;
        unsigned long rate;
        int ret;
 
+       feature = kzalloc(ONFI_SUBFEATURE_PARAM_LEN, GFP_KERNEL);
+       if (!feature)
+               return -ENOMEM;
+
        nand->select_chip(mtd, 0);
 
        /* [1] send SET FEATURE commond to NAND */
@@ -942,11 +958,13 @@ static int enable_edo_mode(struct gpmi_nand_data *this, int mode)
 
        this->flags |= GPMI_ASYNC_EDO_ENABLED;
        this->timing_mode = mode;
+       kfree(feature);
        dev_info(this->dev, "enable the asynchronous EDO mode %d\n", mode);
        return 0;
 
 err_out:
        nand->select_chip(mtd, -1);
+       kfree(feature);
        dev_err(this->dev, "mode:%d ,failed in set feature.\n", mode);
        return -EINVAL;
 }
@@ -986,7 +1004,7 @@ void gpmi_begin(struct gpmi_nand_data *this)
        /* Enable the clock. */
        ret = gpmi_enable_clk(this);
        if (ret) {
-               pr_err("We failed in enable the clk\n");
+               dev_err(this->dev, "We failed in enable the clk\n");
                goto err_out;
        }
 
@@ -1003,7 +1021,7 @@ void gpmi_begin(struct gpmi_nand_data *this)
        /* [1] Set HW_GPMI_TIMING0 */
        reg = BF_GPMI_TIMING0_ADDRESS_SETUP(hw.address_setup_in_cycles) |
                BF_GPMI_TIMING0_DATA_HOLD(hw.data_hold_in_cycles)         |
-               BF_GPMI_TIMING0_DATA_SETUP(hw.data_setup_in_cycles)       ;
+               BF_GPMI_TIMING0_DATA_SETUP(hw.data_setup_in_cycles);
 
        writel(reg, gpmi_regs + HW_GPMI_TIMING0);
 
@@ -1090,7 +1108,7 @@ int gpmi_is_ready(struct gpmi_nand_data *this, unsigned chip)
                mask = MX28_BF_GPMI_STAT_READY_BUSY(1 << chip);
                reg = readl(r->gpmi_regs + HW_GPMI_STAT);
        } else
-               pr_err("unknow arch.\n");
+               dev_err(this->dev, "unknow arch.\n");
        return reg & mask;
 }
 
@@ -1121,10 +1139,8 @@ int gpmi_send_command(struct gpmi_nand_data *this)
        desc = dmaengine_prep_slave_sg(channel,
                                        (struct scatterlist *)pio,
                                        ARRAY_SIZE(pio), DMA_TRANS_NONE, 0);
-       if (!desc) {
-               pr_err("step 1 error\n");
-               return -1;
-       }
+       if (!desc)
+               return -EINVAL;
 
        /* [2] send out the COMMAND + ADDRESS string stored in @buffer */
        sgl = &this->cmd_sgl;
@@ -1134,11 +1150,8 @@ int gpmi_send_command(struct gpmi_nand_data *this)
        desc = dmaengine_prep_slave_sg(channel,
                                sgl, 1, DMA_MEM_TO_DEV,
                                DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-
-       if (!desc) {
-               pr_err("step 2 error\n");
-               return -1;
-       }
+       if (!desc)
+               return -EINVAL;
 
        /* [3] submit the DMA */
        set_dma_type(this, DMA_FOR_COMMAND);
@@ -1167,20 +1180,17 @@ int gpmi_send_data(struct gpmi_nand_data *this)
        pio[1] = 0;
        desc = dmaengine_prep_slave_sg(channel, (struct scatterlist *)pio,
                                        ARRAY_SIZE(pio), DMA_TRANS_NONE, 0);
-       if (!desc) {
-               pr_err("step 1 error\n");
-               return -1;
-       }
+       if (!desc)
+               return -EINVAL;
 
        /* [2] send DMA request */
        prepare_data_dma(this, DMA_TO_DEVICE);
        desc = dmaengine_prep_slave_sg(channel, &this->data_sgl,
                                        1, DMA_MEM_TO_DEV,
                                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-       if (!desc) {
-               pr_err("step 2 error\n");
-               return -1;
-       }
+       if (!desc)
+               return -EINVAL;
+
        /* [3] submit the DMA */
        set_dma_type(this, DMA_FOR_WRITE_DATA);
        return start_dma_without_bch_irq(this, desc);
@@ -1204,20 +1214,16 @@ int gpmi_read_data(struct gpmi_nand_data *this)
        desc = dmaengine_prep_slave_sg(channel,
                                        (struct scatterlist *)pio,
                                        ARRAY_SIZE(pio), DMA_TRANS_NONE, 0);
-       if (!desc) {
-               pr_err("step 1 error\n");
-               return -1;
-       }
+       if (!desc)
+               return -EINVAL;
 
        /* [2] : send DMA request */
        prepare_data_dma(this, DMA_FROM_DEVICE);
        desc = dmaengine_prep_slave_sg(channel, &this->data_sgl,
                                        1, DMA_DEV_TO_MEM,
                                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-       if (!desc) {
-               pr_err("step 2 error\n");
-               return -1;
-       }
+       if (!desc)
+               return -EINVAL;
 
        /* [3] : submit the DMA */
        set_dma_type(this, DMA_FOR_READ_DATA);
@@ -1262,10 +1268,9 @@ int gpmi_send_page(struct gpmi_nand_data *this,
                                        (struct scatterlist *)pio,
                                        ARRAY_SIZE(pio), DMA_TRANS_NONE,
                                        DMA_CTRL_ACK);
-       if (!desc) {
-               pr_err("step 2 error\n");
-               return -1;
-       }
+       if (!desc)
+               return -EINVAL;
+
        set_dma_type(this, DMA_FOR_WRITE_ECC_PAGE);
        return start_dma_with_bch_irq(this, desc);
 }
@@ -1297,10 +1302,8 @@ int gpmi_read_page(struct gpmi_nand_data *this,
        desc = dmaengine_prep_slave_sg(channel,
                                (struct scatterlist *)pio, 2,
                                DMA_TRANS_NONE, 0);
-       if (!desc) {
-               pr_err("step 1 error\n");
-               return -1;
-       }
+       if (!desc)
+               return -EINVAL;
 
        /* [2] Enable the BCH block and read. */
        command_mode = BV_GPMI_CTRL0_COMMAND_MODE__READ;
@@ -1327,10 +1330,8 @@ int gpmi_read_page(struct gpmi_nand_data *this,
                                        (struct scatterlist *)pio,
                                        ARRAY_SIZE(pio), DMA_TRANS_NONE,
                                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-       if (!desc) {
-               pr_err("step 2 error\n");
-               return -1;
-       }
+       if (!desc)
+               return -EINVAL;
 
        /* [3] Disable the BCH block */
        command_mode = BV_GPMI_CTRL0_COMMAND_MODE__WAIT_FOR_READY;
@@ -1348,10 +1349,8 @@ int gpmi_read_page(struct gpmi_nand_data *this,
                                (struct scatterlist *)pio, 3,
                                DMA_TRANS_NONE,
                                DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-       if (!desc) {
-               pr_err("step 3 error\n");
-               return -1;
-       }
+       if (!desc)
+               return -EINVAL;
 
        /* [4] submit the DMA */
        set_dma_type(this, DMA_FOR_READ_ECC_PAGE);
index dabbc14db5630d8592268012fc067559179aa0f8..e2f58207c779313c1c254d60b2c515b8963421c2 100644 (file)
@@ -18,9 +18,6 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
 #include <linux/clk.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
@@ -352,6 +349,9 @@ static int legacy_set_geometry(struct gpmi_nand_data *this)
 
 int common_nfc_set_geometry(struct gpmi_nand_data *this)
 {
+       if (of_property_read_bool(this->dev->of_node, "fsl,use-minimum-ecc")
+               && set_geometry_by_ecc_info(this))
+               return 0;
        return legacy_set_geometry(this);
 }
 
@@ -382,7 +382,7 @@ void prepare_data_dma(struct gpmi_nand_data *this, enum dma_data_direction dr)
 
                ret = dma_map_sg(this->dev, sgl, 1, dr);
                if (ret == 0)
-                       pr_err("DMA mapping failed.\n");
+                       dev_err(this->dev, "DMA mapping failed.\n");
 
                this->direct_dma_map_ok = false;
        }
@@ -416,7 +416,7 @@ static void dma_irq_callback(void *param)
                break;
 
        default:
-               pr_err("in wrong DMA operation.\n");
+               dev_err(this->dev, "in wrong DMA operation.\n");
        }
 
        complete(dma_c);
@@ -438,7 +438,8 @@ int start_dma_without_bch_irq(struct gpmi_nand_data *this,
        /* Wait for the interrupt from the DMA block. */
        err = wait_for_completion_timeout(dma_c, msecs_to_jiffies(1000));
        if (!err) {
-               pr_err("DMA timeout, last DMA :%d\n", this->last_dma_type);
+               dev_err(this->dev, "DMA timeout, last DMA :%d\n",
+                       this->last_dma_type);
                gpmi_dump_info(this);
                return -ETIMEDOUT;
        }
@@ -467,7 +468,8 @@ int start_dma_with_bch_irq(struct gpmi_nand_data *this,
        /* Wait for the interrupt from the BCH block. */
        err = wait_for_completion_timeout(bch_c, msecs_to_jiffies(1000));
        if (!err) {
-               pr_err("BCH timeout, last DMA :%d\n", this->last_dma_type);
+               dev_err(this->dev, "BCH timeout, last DMA :%d\n",
+                       this->last_dma_type);
                gpmi_dump_info(this);
                return -ETIMEDOUT;
        }
@@ -483,70 +485,38 @@ static int acquire_register_block(struct gpmi_nand_data *this,
        void __iomem *p;
 
        r = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name);
-       if (!r) {
-               pr_err("Can't get resource for %s\n", res_name);
-               return -ENODEV;
-       }
-
-       p = ioremap(r->start, resource_size(r));
-       if (!p) {
-               pr_err("Can't remap %s\n", res_name);
-               return -ENOMEM;
-       }
+       p = devm_ioremap_resource(&pdev->dev, r);
+       if (IS_ERR(p))
+               return PTR_ERR(p);
 
        if (!strcmp(res_name, GPMI_NAND_GPMI_REGS_ADDR_RES_NAME))
                res->gpmi_regs = p;
        else if (!strcmp(res_name, GPMI_NAND_BCH_REGS_ADDR_RES_NAME))
                res->bch_regs = p;
        else
-               pr_err("unknown resource name : %s\n", res_name);
+               dev_err(this->dev, "unknown resource name : %s\n", res_name);
 
        return 0;
 }
 
-static void release_register_block(struct gpmi_nand_data *this)
-{
-       struct resources *res = &this->resources;
-       if (res->gpmi_regs)
-               iounmap(res->gpmi_regs);
-       if (res->bch_regs)
-               iounmap(res->bch_regs);
-       res->gpmi_regs = NULL;
-       res->bch_regs = NULL;
-}
-
 static int acquire_bch_irq(struct gpmi_nand_data *this, irq_handler_t irq_h)
 {
        struct platform_device *pdev = this->pdev;
-       struct resources *res = &this->resources;
        const char *res_name = GPMI_NAND_BCH_INTERRUPT_RES_NAME;
        struct resource *r;
        int err;
 
        r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, res_name);
        if (!r) {
-               pr_err("Can't get resource for %s\n", res_name);
+               dev_err(this->dev, "Can't get resource for %s\n", res_name);
                return -ENODEV;
        }
 
-       err = request_irq(r->start, irq_h, 0, res_name, this);
-       if (err) {
-               pr_err("Can't own %s\n", res_name);
-               return err;
-       }
-
-       res->bch_low_interrupt = r->start;
-       res->bch_high_interrupt = r->end;
-       return 0;
-}
+       err = devm_request_irq(this->dev, r->start, irq_h, 0, res_name, this);
+       if (err)
+               dev_err(this->dev, "error requesting BCH IRQ\n");
 
-static void release_bch_irq(struct gpmi_nand_data *this)
-{
-       struct resources *res = &this->resources;
-       int i = res->bch_low_interrupt;
-
-       for (; i <= res->bch_high_interrupt; i++)
-               free_irq(i, this);
+       return err;
 }
 
 static void release_dma_channels(struct gpmi_nand_data *this)
@@ -567,7 +537,7 @@ static int acquire_dma_channels(struct gpmi_nand_data *this)
        /* request dma channel */
        dma_chan = dma_request_slave_channel(&pdev->dev, "rx-tx");
        if (!dma_chan) {
-               pr_err("Failed to request DMA channel.\n");
+               dev_err(this->dev, "Failed to request DMA channel.\n");
                goto acquire_err;
        }
 
@@ -579,21 +549,6 @@ acquire_err:
        return -EINVAL;
 }
 
-static void gpmi_put_clks(struct gpmi_nand_data *this)
-{
-       struct resources *r = &this->resources;
-       struct clk *clk;
-       int i;
-
-       for (i = 0; i < GPMI_CLK_MAX; i++) {
-               clk = r->clock[i];
-               if (clk) {
-                       clk_put(clk);
-                       r->clock[i] = NULL;
-               }
-       }
-}
-
 static char *extra_clks_for_mx6q[GPMI_CLK_MAX] = {
        "gpmi_apb", "gpmi_bch", "gpmi_bch_apb", "per1_bch",
 };
@@ -606,7 +561,7 @@ static int gpmi_get_clks(struct gpmi_nand_data *this)
        int err, i;
 
        /* The main clock is stored in the first. */
-       r->clock[0] = clk_get(this->dev, "gpmi_io");
+       r->clock[0] = devm_clk_get(this->dev, "gpmi_io");
        if (IS_ERR(r->clock[0])) {
                err = PTR_ERR(r->clock[0]);
                goto err_clock;
@@ -622,7 +577,7 @@ static int gpmi_get_clks(struct gpmi_nand_data *this)
                if (extra_clks[i - 1] == NULL)
                        break;
 
-               clk = clk_get(this->dev, extra_clks[i - 1]);
+               clk = devm_clk_get(this->dev, extra_clks[i - 1]);
                if (IS_ERR(clk)) {
                        err = PTR_ERR(clk);
                        goto err_clock;
@@ -644,7 +599,6 @@ static int gpmi_get_clks(struct gpmi_nand_data *this)
 
 err_clock:
        dev_dbg(this->dev, "failed in finding the clocks.\n");
-       gpmi_put_clks(this);
        return err;
 }
 
@@ -666,7 +620,7 @@ static int acquire_resources(struct gpmi_nand_data *this)
 
        ret = acquire_dma_channels(this);
        if (ret)
-               goto exit_dma_channels;
+               goto exit_regs;
 
        ret = gpmi_get_clks(this);
        if (ret)
@@ -675,18 +629,12 @@ static int acquire_resources(struct gpmi_nand_data *this)
 
 exit_clock:
        release_dma_channels(this);
-exit_dma_channels:
-       release_bch_irq(this);
 exit_regs:
-       release_register_block(this);
        return ret;
 }
 
 static void release_resources(struct gpmi_nand_data *this)
 {
-       gpmi_put_clks(this);
-       release_register_block(this);
-       release_bch_irq(this);
        release_dma_channels(this);
 }
 
@@ -732,8 +680,7 @@ static int read_page_prepare(struct gpmi_nand_data *this,
                                                length, DMA_FROM_DEVICE);
                if (dma_mapping_error(dev, dest_phys)) {
                        if (alt_size < length) {
-                               pr_err("%s, Alternate buffer is too small\n",
-                                       __func__);
+                               dev_err(dev, "Alternate buffer is too small\n");
                                return -ENOMEM;
                        }
                        goto map_failed;
@@ -783,8 +730,7 @@ static int send_page_prepare(struct gpmi_nand_data *this,
                                                DMA_TO_DEVICE);
                if (dma_mapping_error(dev, source_phys)) {
                        if (alt_size < length) {
-                               pr_err("%s, Alternate buffer is too small\n",
-                                       __func__);
+                               dev_err(dev, "Alternate buffer is too small\n");
                                return -ENOMEM;
                        }
                        goto map_failed;
@@ -872,7 +818,6 @@ static int gpmi_alloc_dma_buffer(struct gpmi_nand_data *this)
 
 error_alloc:
        gpmi_free_dma_buffer(this);
-       pr_err("Error allocating DMA buffers!\n");
        return -ENOMEM;
 }
 
@@ -904,7 +849,8 @@ static void gpmi_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl)
 
        ret = gpmi_send_command(this);
        if (ret)
-               pr_err("Chip: %u, Error %d\n", this->current_chip, ret);
+               dev_err(this->dev, "Chip: %u, Error %d\n",
+                       this->current_chip, ret);
 
        this->command_length = 0;
 }
@@ -935,7 +881,7 @@ static void gpmi_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
        struct nand_chip *chip = mtd->priv;
        struct gpmi_nand_data *this = chip->priv;
 
-       pr_debug("len is %d\n", len);
+       dev_dbg(this->dev, "len is %d\n", len);
        this->upper_buf = buf;
        this->upper_len = len;
 
@@ -947,7 +893,7 @@ static void gpmi_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
        struct nand_chip *chip = mtd->priv;
        struct gpmi_nand_data *this = chip->priv;
 
-       pr_debug("len is %d\n", len);
+       dev_dbg(this->dev, "len is %d\n", len);
        this->upper_buf = (uint8_t *)buf;
        this->upper_len = len;
 
@@ -1026,13 +972,13 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
        unsigned int  max_bitflips = 0;
        int           ret;
 
-       pr_debug("page number is : %d\n", page);
+       dev_dbg(this->dev, "page number is : %d\n", page);
        ret = read_page_prepare(this, buf, mtd->writesize,
                                        this->payload_virt, this->payload_phys,
                                        nfc_geo->payload_size,
                                        &payload_virt, &payload_phys);
        if (ret) {
-               pr_err("Inadequate DMA buffer\n");
+               dev_err(this->dev, "Inadequate DMA buffer\n");
                ret = -ENOMEM;
                return ret;
        }
@@ -1046,7 +992,7 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
                        nfc_geo->payload_size,
                        payload_virt, payload_phys);
        if (ret) {
-               pr_err("Error in ECC-based read: %d\n", ret);
+               dev_err(this->dev, "Error in ECC-based read: %d\n", ret);
                return ret;
        }
 
@@ -1102,7 +1048,7 @@ static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
        dma_addr_t auxiliary_phys;
        int        ret;
 
-       pr_debug("ecc write page.\n");
+       dev_dbg(this->dev, "ecc write page.\n");
        if (this->swap_block_mark) {
                /*
                 * If control arrives here, we're doing block mark swapping.
@@ -1132,7 +1078,7 @@ static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
                                nfc_geo->payload_size,
                                &payload_virt, &payload_phys);
                if (ret) {
-                       pr_err("Inadequate payload DMA buffer\n");
+                       dev_err(this->dev, "Inadequate payload DMA buffer\n");
                        return 0;
                }
 
@@ -1142,7 +1088,7 @@ static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
                                nfc_geo->auxiliary_size,
                                &auxiliary_virt, &auxiliary_phys);
                if (ret) {
-                       pr_err("Inadequate auxiliary DMA buffer\n");
+                       dev_err(this->dev, "Inadequate auxiliary DMA buffer\n");
                        goto exit_auxiliary;
                }
        }
@@ -1150,7 +1096,7 @@ static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
        /* Ask the NFC. */
        ret = gpmi_send_page(this, payload_phys, auxiliary_phys);
        if (ret)
-               pr_err("Error in ECC-based write: %d\n", ret);
+               dev_err(this->dev, "Error in ECC-based write: %d\n", ret);
 
        if (!this->swap_block_mark) {
                send_page_end(this, chip->oob_poi, mtd->oobsize,
@@ -1240,7 +1186,7 @@ static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
 {
        struct gpmi_nand_data *this = chip->priv;
 
-       pr_debug("page number is %d\n", page);
+       dev_dbg(this->dev, "page number is %d\n", page);
        /* clear the OOB buffer */
        memset(chip->oob_poi, ~0, mtd->oobsize);
 
@@ -1453,7 +1399,6 @@ static int mx23_write_transcription_stamp(struct gpmi_nand_data *this)
 
        /* Write the NCB fingerprint into the page buffer. */
        memset(buffer, ~0, mtd->writesize);
-       memset(chip->oob_poi, ~0, mtd->oobsize);
        memcpy(buffer + 12, fingerprint, strlen(fingerprint));
 
        /* Loop through the first search area, writing NCB fingerprints. */
@@ -1568,7 +1513,7 @@ static int gpmi_set_geometry(struct gpmi_nand_data *this)
        /* Set up the NFC geometry which is used by BCH. */
        ret = bch_set_geometry(this);
        if (ret) {
-               pr_err("Error setting BCH geometry : %d\n", ret);
+               dev_err(this->dev, "Error setting BCH geometry : %d\n", ret);
                return ret;
        }
 
@@ -1576,20 +1521,7 @@ static int gpmi_set_geometry(struct gpmi_nand_data *this)
        return gpmi_alloc_dma_buffer(this);
 }
 
-static int gpmi_pre_bbt_scan(struct gpmi_nand_data  *this)
-{
-       /* Set up swap_block_mark, must be set before the gpmi_set_geometry() */
-       if (GPMI_IS_MX23(this))
-               this->swap_block_mark = false;
-       else
-               this->swap_block_mark = true;
-
-       /* Set up the medium geometry */
-       return gpmi_set_geometry(this);
-
-}
-
-static void gpmi_nfc_exit(struct gpmi_nand_data *this)
+static void gpmi_nand_exit(struct gpmi_nand_data *this)
 {
        nand_release(&this->mtd);
        gpmi_free_dma_buffer(this);
@@ -1603,8 +1535,11 @@ static int gpmi_init_last(struct gpmi_nand_data *this)
        struct bch_geometry *bch_geo = &this->bch_geometry;
        int ret;
 
-       /* Prepare for the BBT scan. */
-       ret = gpmi_pre_bbt_scan(this);
+       /* Set up swap_block_mark, must be set before the gpmi_set_geometry() */
+       this->swap_block_mark = !GPMI_IS_MX23(this);
+
+       /* Set up the medium geometry */
+       ret = gpmi_set_geometry(this);
        if (ret)
                return ret;
 
@@ -1629,7 +1564,7 @@ static int gpmi_init_last(struct gpmi_nand_data *this)
        return 0;
 }
 
-static int gpmi_nfc_init(struct gpmi_nand_data *this)
+static int gpmi_nand_init(struct gpmi_nand_data *this)
 {
        struct mtd_info  *mtd = &this->mtd;
        struct nand_chip *chip = &this->nand;
@@ -1693,7 +1628,7 @@ static int gpmi_nfc_init(struct gpmi_nand_data *this)
        return 0;
 
 err_out:
-       gpmi_nfc_exit(this);
+       gpmi_nand_exit(this);
        return ret;
 }
 
@@ -1728,15 +1663,13 @@ static int gpmi_nand_probe(struct platform_device *pdev)
        if (of_id) {
                pdev->id_entry = of_id->data;
        } else {
-               pr_err("Failed to find the right device id.\n");
+               dev_err(&pdev->dev, "Failed to find the right device id.\n");
                return -ENODEV;
        }
 
        this = devm_kzalloc(&pdev->dev, sizeof(*this), GFP_KERNEL);
-       if (!this) {
-               pr_err("Failed to allocate per-device memory\n");
+       if (!this)
                return -ENOMEM;
-       }
 
        platform_set_drvdata(pdev, this);
        this->pdev  = pdev;
@@ -1750,7 +1683,7 @@ static int gpmi_nand_probe(struct platform_device *pdev)
        if (ret)
                goto exit_nfc_init;
 
-       ret = gpmi_nfc_init(this);
+       ret = gpmi_nand_init(this);
        if (ret)
                goto exit_nfc_init;
 
@@ -1770,7 +1703,7 @@ static int gpmi_nand_remove(struct platform_device *pdev)
 {
        struct gpmi_nand_data *this = platform_get_drvdata(pdev);
 
-       gpmi_nfc_exit(this);
+       gpmi_nand_exit(this);
        release_resources(this);
        return 0;
 }
index a7685e3a87486b86713fef19da82e9bbad3c6253..4c801fa1872530e681e801d2adaee333d4acffb4 100644 (file)
@@ -26,8 +26,6 @@
 struct resources {
        void __iomem  *gpmi_regs;
        void __iomem  *bch_regs;
-       unsigned int  bch_low_interrupt;
-       unsigned int  bch_high_interrupt;
        unsigned int  dma_low_channel;
        unsigned int  dma_high_channel;
        struct clk    *clock[GPMI_CLK_MAX];
index 439bc389641841dc05f79ab638f7010e4a9cd053..a244aaa4c33db4721b650be4619f4e7acd2fc959 100644 (file)
@@ -731,7 +731,7 @@ static int mpc5121_nfc_probe(struct platform_device *op)
        of_node_put(rootnode);
 
        /* Enable NFC clock */
-       clk = devm_clk_get(dev, "nfc_clk");
+       clk = devm_clk_get(dev, "ipg");
        if (IS_ERR(clk)) {
                dev_err(dev, "Unable to acquire NFC clock!\n");
                retval = PTR_ERR(clk);
@@ -786,7 +786,6 @@ static int mpc5121_nfc_probe(struct platform_device *op)
        /* Detect NAND chips */
        if (nand_scan(mtd, be32_to_cpup(chips_no))) {
                dev_err(dev, "NAND Flash not found !\n");
-               devm_free_irq(dev, prv->irq, mtd);
                retval = -ENXIO;
                goto error;
        }
@@ -811,7 +810,6 @@ static int mpc5121_nfc_probe(struct platform_device *op)
 
        default:
                dev_err(dev, "Unsupported NAND flash!\n");
-               devm_free_irq(dev, prv->irq, mtd);
                retval = -ENXIO;
                goto error;
        }
@@ -822,7 +820,6 @@ static int mpc5121_nfc_probe(struct platform_device *op)
        retval = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0);
        if (retval) {
                dev_err(dev, "Error adding MTD device!\n");
-               devm_free_irq(dev, prv->irq, mtd);
                goto error;
        }
 
@@ -836,11 +833,8 @@ static int mpc5121_nfc_remove(struct platform_device *op)
 {
        struct device *dev = &op->dev;
        struct mtd_info *mtd = dev_get_drvdata(dev);
-       struct nand_chip *chip = mtd->priv;
-       struct mpc5121_nfc_prv *prv = chip->priv;
 
        nand_release(mtd);
-       devm_free_irq(dev, prv->irq, mtd);
        mpc5121_nfc_free(dev, mtd);
 
        return 0;
index 9dfdb06c508b05439cd93a71ce5c30ef8558335e..7a4e032f6c7cb17c0b7514fc7d2b3f8d49198e8d 100644 (file)
@@ -677,7 +677,6 @@ static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
                ecc_stat >>= 4;
        } while (--no_subpages);
 
-       mtd->ecc_stats.corrected += ret;
        pr_debug("%d Symbol Correctable RS-ECC Error\n", ret);
 
        return ret;
@@ -1512,7 +1511,9 @@ static int mxcnd_probe(struct platform_device *pdev)
        if (err)
                return err;
 
-       clk_prepare_enable(host->clk);
+       err = clk_prepare_enable(host->clk);
+       if (err)
+               return err;
        host->clk_act = 1;
 
        /*
index bd39f7b67906f65db526cbd0d1d27bb84ad93277..9b3bb3c519e9f632610f5e03faafa45ae3c648ee 100644 (file)
@@ -29,6 +29,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
@@ -2979,7 +2981,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
                chip->onfi_version = 10;
 
        if (!chip->onfi_version) {
-               pr_info("%s: unsupported ONFI version: %d\n", __func__, val);
+               pr_info("unsupported ONFI version: %d\n", val);
                return 0;
        }
 
@@ -3372,8 +3374,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
                id_data[i] = chip->read_byte(mtd);
 
        if (id_data[0] != *maf_id || id_data[1] != *dev_id) {
-               pr_info("%s: second ID read did not match "
-                       "%02x,%02x against %02x,%02x\n", __func__,
+               pr_info("second ID read did not match %02x,%02x against %02x,%02x\n",
                        *maf_id, *dev_id, id_data[0], id_data[1]);
                return ERR_PTR(-ENODEV);
        }
@@ -3440,10 +3441,10 @@ ident_done:
                 * Check, if buswidth is correct. Hardware drivers should set
                 * chip correct!
                 */
-               pr_info("NAND device: Manufacturer ID:"
-                       " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id,
-                       *dev_id, nand_manuf_ids[maf_idx].name, mtd->name);
-               pr_warn("NAND bus width %d instead %d bit\n",
+               pr_info("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n",
+                       *maf_id, *dev_id);
+               pr_info("%s %s\n", nand_manuf_ids[maf_idx].name, mtd->name);
+               pr_warn("bus width %d instead %d bit\n",
                           (chip->options & NAND_BUSWIDTH_16) ? 16 : 8,
                           busw ? 16 : 8);
                return ERR_PTR(-EINVAL);
@@ -3472,14 +3473,13 @@ ident_done:
        if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
                chip->cmdfunc = nand_command_lp;
 
-       pr_info("NAND device: Manufacturer ID: 0x%02x, Chip ID: 0x%02x (%s %s)\n",
-               *maf_id, *dev_id, nand_manuf_ids[maf_idx].name,
+       pr_info("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n",
+               *maf_id, *dev_id);
+       pr_info("%s %s\n", nand_manuf_ids[maf_idx].name,
                chip->onfi_version ? chip->onfi_params.model : type->name);
-
-       pr_info("NAND device: %dMiB, %s, page size: %d, OOB size: %d\n",
+       pr_info("%dMiB, %s, page size: %d, OOB size: %d\n",
                (int)(chip->chipsize >> 20), nand_is_slc(chip) ? "SLC" : "MLC",
                mtd->writesize, mtd->oobsize);
-
        return type;
 }
 
@@ -3535,7 +3535,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
                chip->select_chip(mtd, -1);
        }
        if (i > 1)
-               pr_info("%d NAND chips detected\n", i);
+               pr_info("%d chips detected\n", i);
 
        /* Store the number of chips and calc total size for mtd */
        chip->numchips = i;
index 4d174366a0f09ec2ebecd99fc8241fc978a05caa..90f871acb0efec737c918532bbdd350ca7969220 100644 (file)
@@ -223,7 +223,7 @@ MODULE_DEVICE_TABLE(of, pasemi_nand_match);
 static struct platform_driver pasemi_nand_driver =
 {
        .driver = {
-               .name = (char*)driver_name,
+               .name = driver_name,
                .owner = THIS_MODULE,
                .of_match_table = pasemi_nand_match,
        },
index 4cabdc9fda9076ceff440af42e028fb1073f9ed7..3d143fec2c0ce4f563060054ca88e41c712c52a5 100644 (file)
@@ -7,6 +7,8 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
+ *
+ * See Documentation/mtd/nand/pxa3xx-nand.txt for more details.
  */
 
 #include <linux/kernel.h>
@@ -24,6 +26,7 @@
 #include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/of_mtd.h>
 
 #if defined(CONFIG_ARCH_PXA) || defined(CONFIG_ARCH_MMP)
 #define ARCH_HAS_DMA
@@ -35,6 +38,7 @@
 
 #include <linux/platform_data/mtd-nand-pxa3xx.h>
 
+#define NAND_DEV_READY_TIMEOUT  50
 #define        CHIP_DELAY_TIMEOUT      (2 * HZ/10)
 #define NAND_STOP_DELAY                (2 * HZ/50)
 #define PAGE_CHUNK_SIZE                (2048)
@@ -54,6 +58,7 @@
 #define NDPCR          (0x18) /* Page Count Register */
 #define NDBDR0         (0x1C) /* Bad Block Register 0 */
 #define NDBDR1         (0x20) /* Bad Block Register 1 */
+#define NDECCCTRL      (0x28) /* ECC control */
 #define NDDB           (0x40) /* Data Buffer */
 #define NDCB0          (0x48) /* Command Buffer0 */
 #define NDCB1          (0x4C) /* Command Buffer1 */
@@ -80,6 +85,9 @@
 #define NDCR_INT_MASK           (0xFFF)
 
 #define NDSR_MASK              (0xfff)
+#define NDSR_ERR_CNT_OFF       (16)
+#define NDSR_ERR_CNT_MASK       (0x1f)
+#define NDSR_ERR_CNT(sr)       ((sr >> NDSR_ERR_CNT_OFF) & NDSR_ERR_CNT_MASK)
 #define NDSR_RDY                (0x1 << 12)
 #define NDSR_FLASH_RDY          (0x1 << 11)
 #define NDSR_CS0_PAGED         (0x1 << 10)
@@ -88,8 +96,8 @@
 #define NDSR_CS1_CMDD          (0x1 << 7)
 #define NDSR_CS0_BBD           (0x1 << 6)
 #define NDSR_CS1_BBD           (0x1 << 5)
-#define NDSR_DBERR             (0x1 << 4)
-#define NDSR_SBERR             (0x1 << 3)
+#define NDSR_UNCORERR          (0x1 << 4)
+#define NDSR_CORERR            (0x1 << 3)
 #define NDSR_WRDREQ            (0x1 << 2)
 #define NDSR_RDDREQ            (0x1 << 1)
 #define NDSR_WRCMDREQ          (0x1)
 #define NDCB0_ST_ROW_EN         (0x1 << 26)
 #define NDCB0_AUTO_RS          (0x1 << 25)
 #define NDCB0_CSEL             (0x1 << 24)
+#define NDCB0_EXT_CMD_TYPE_MASK        (0x7 << 29)
+#define NDCB0_EXT_CMD_TYPE(x)  (((x) << 29) & NDCB0_EXT_CMD_TYPE_MASK)
 #define NDCB0_CMD_TYPE_MASK    (0x7 << 21)
 #define NDCB0_CMD_TYPE(x)      (((x) << 21) & NDCB0_CMD_TYPE_MASK)
 #define NDCB0_NC               (0x1 << 20)
 #define NDCB0_CMD1_MASK                (0xff)
 #define NDCB0_ADDR_CYC_SHIFT   (16)
 
+#define EXT_CMD_TYPE_DISPATCH  6 /* Command dispatch */
+#define EXT_CMD_TYPE_NAKED_RW  5 /* Naked read or Naked write */
+#define EXT_CMD_TYPE_READ      4 /* Read */
+#define EXT_CMD_TYPE_DISP_WR   4 /* Command dispatch with write */
+#define EXT_CMD_TYPE_FINAL     3 /* Final command */
+#define EXT_CMD_TYPE_LAST_RW   1 /* Last naked read/write */
+#define EXT_CMD_TYPE_MONO      0 /* Monolithic read/write */
+
 /* macros for registers read/write */
 #define nand_writel(info, off, val)    \
        __raw_writel((val), (info)->mmio_base + (off))
@@ -120,9 +138,9 @@ enum {
        ERR_NONE        = 0,
        ERR_DMABUSERR   = -1,
        ERR_SENDCMD     = -2,
-       ERR_DBERR       = -3,
+       ERR_UNCORERR    = -3,
        ERR_BBERR       = -4,
-       ERR_SBERR       = -5,
+       ERR_CORERR      = -5,
 };
 
 enum {
@@ -149,7 +167,6 @@ struct pxa3xx_nand_host {
        void                    *info_data;
 
        /* page size of attached chip */
-       unsigned int            page_size;
        int                     use_ecc;
        int                     cs;
 
@@ -167,11 +184,13 @@ struct pxa3xx_nand_info {
        struct clk              *clk;
        void __iomem            *mmio_base;
        unsigned long           mmio_phys;
-       struct completion       cmd_complete;
+       struct completion       cmd_complete, dev_ready;
 
        unsigned int            buf_start;
        unsigned int            buf_count;
        unsigned int            buf_size;
+       unsigned int            data_buff_pos;
+       unsigned int            oob_buff_pos;
 
        /* DMA information */
        int                     drcmr_dat;
@@ -195,13 +214,18 @@ struct pxa3xx_nand_info {
 
        int                     cs;
        int                     use_ecc;        /* use HW ECC ? */
+       int                     ecc_bch;        /* using BCH ECC? */
        int                     use_dma;        /* use DMA ? */
        int                     use_spare;      /* use spare ? */
-       int                     is_ready;
+       int                     need_wait;
 
-       unsigned int            page_size;      /* page size of attached chip */
-       unsigned int            data_size;      /* data size in FIFO */
+       unsigned int            data_size;      /* data to be read from FIFO */
+       unsigned int            chunk_size;     /* split commands chunk size */
        unsigned int            oob_size;
+       unsigned int            spare_size;
+       unsigned int            ecc_size;
+       unsigned int            ecc_err_cnt;
+       unsigned int            max_bitflips;
        int                     retcode;
 
        /* cached register value */
@@ -239,6 +263,54 @@ static struct pxa3xx_nand_flash builtin_flash_types[] = {
 { "256MiB 16-bit", 0xba20,  64, 2048, 16, 16, 2048, &timing[3] },
 };
 
+static u8 bbt_pattern[] = {'M', 'V', 'B', 'b', 't', '0' };
+static u8 bbt_mirror_pattern[] = {'1', 't', 'b', 'B', 'V', 'M' };
+
+static struct nand_bbt_descr bbt_main_descr = {
+       .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+               | NAND_BBT_2BIT | NAND_BBT_VERSION,
+       .offs = 8,
+       .len = 6,
+       .veroffs = 14,
+       .maxblocks = 8,         /* Last 8 blocks in each chip */
+       .pattern = bbt_pattern
+};
+
+static struct nand_bbt_descr bbt_mirror_descr = {
+       .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+               | NAND_BBT_2BIT | NAND_BBT_VERSION,
+       .offs = 8,
+       .len = 6,
+       .veroffs = 14,
+       .maxblocks = 8,         /* Last 8 blocks in each chip */
+       .pattern = bbt_mirror_pattern
+};
+
+static struct nand_ecclayout ecc_layout_4KB_bch4bit = {
+       .eccbytes = 64,
+       .eccpos = {
+               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,
+               96,  97,  98,  99,  100, 101, 102, 103,
+               104, 105, 106, 107, 108, 109, 110, 111,
+               112, 113, 114, 115, 116, 117, 118, 119,
+               120, 121, 122, 123, 124, 125, 126, 127},
+       /* Bootrom looks in bytes 0 & 5 for bad blocks */
+       .oobfree = { {6, 26}, { 64, 32} }
+};
+
+static struct nand_ecclayout ecc_layout_4KB_bch8bit = {
+       .eccbytes = 128,
+       .eccpos = {
+               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},
+       .oobfree = { }
+};
+
 /* Define a default flash type setting serve as flash detecting only */
 #define DEFAULT_FLASH_TYPE (&builtin_flash_types[0])
 
@@ -256,6 +328,29 @@ static struct pxa3xx_nand_flash builtin_flash_types[] = {
 /* convert nano-seconds to nand flash controller clock cycles */
 #define ns2cycle(ns, clk)      (int)((ns) * (clk / 1000000) / 1000)
 
+static struct of_device_id pxa3xx_nand_dt_ids[] = {
+       {
+               .compatible = "marvell,pxa3xx-nand",
+               .data       = (void *)PXA3XX_NAND_VARIANT_PXA,
+       },
+       {
+               .compatible = "marvell,armada370-nand",
+               .data       = (void *)PXA3XX_NAND_VARIANT_ARMADA370,
+       },
+       {}
+};
+MODULE_DEVICE_TABLE(of, pxa3xx_nand_dt_ids);
+
+static enum pxa3xx_nand_variant
+pxa3xx_nand_get_variant(struct platform_device *pdev)
+{
+       const struct of_device_id *of_id =
+                       of_match_device(pxa3xx_nand_dt_ids, &pdev->dev);
+       if (!of_id)
+               return PXA3XX_NAND_VARIANT_PXA;
+       return (enum pxa3xx_nand_variant)of_id->data;
+}
+
 static void pxa3xx_nand_set_timing(struct pxa3xx_nand_host *host,
                                   const struct pxa3xx_nand_timing *t)
 {
@@ -280,25 +375,23 @@ static void pxa3xx_nand_set_timing(struct pxa3xx_nand_host *host,
        nand_writel(info, NDTR1CS0, ndtr1);
 }
 
-static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info)
+/*
+ * Set the data and OOB size, depending on the selected
+ * spare and ECC configuration.
+ * Only applicable to READ0, READOOB and PAGEPROG commands.
+ */
+static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info,
+                               struct mtd_info *mtd)
 {
-       struct pxa3xx_nand_host *host = info->host[info->cs];
        int oob_enable = info->reg_ndcr & NDCR_SPARE_EN;
 
-       info->data_size = host->page_size;
-       if (!oob_enable) {
-               info->oob_size = 0;
+       info->data_size = mtd->writesize;
+       if (!oob_enable)
                return;
-       }
 
-       switch (host->page_size) {
-       case 2048:
-               info->oob_size = (info->use_ecc) ? 40 : 64;
-               break;
-       case 512:
-               info->oob_size = (info->use_ecc) ? 8 : 16;
-               break;
-       }
+       info->oob_size = info->spare_size;
+       if (!info->use_ecc)
+               info->oob_size += info->ecc_size;
 }
 
 /**
@@ -313,10 +406,15 @@ static void pxa3xx_nand_start(struct pxa3xx_nand_info *info)
 
        ndcr = info->reg_ndcr;
 
-       if (info->use_ecc)
+       if (info->use_ecc) {
                ndcr |= NDCR_ECC_EN;
-       else
+               if (info->ecc_bch)
+                       nand_writel(info, NDECCCTRL, 0x1);
+       } else {
                ndcr &= ~NDCR_ECC_EN;
+               if (info->ecc_bch)
+                       nand_writel(info, NDECCCTRL, 0x0);
+       }
 
        if (info->use_dma)
                ndcr |= NDCR_DMA_EN;
@@ -375,26 +473,39 @@ static void disable_int(struct pxa3xx_nand_info *info, uint32_t int_mask)
 
 static void handle_data_pio(struct pxa3xx_nand_info *info)
 {
+       unsigned int do_bytes = min(info->data_size, info->chunk_size);
+
        switch (info->state) {
        case STATE_PIO_WRITING:
-               __raw_writesl(info->mmio_base + NDDB, info->data_buff,
-                               DIV_ROUND_UP(info->data_size, 4));
+               __raw_writesl(info->mmio_base + NDDB,
+                             info->data_buff + info->data_buff_pos,
+                             DIV_ROUND_UP(do_bytes, 4));
+
                if (info->oob_size > 0)
-                       __raw_writesl(info->mmio_base + NDDB, info->oob_buff,
-                                       DIV_ROUND_UP(info->oob_size, 4));
+                       __raw_writesl(info->mmio_base + NDDB,
+                                     info->oob_buff + info->oob_buff_pos,
+                                     DIV_ROUND_UP(info->oob_size, 4));
                break;
        case STATE_PIO_READING:
-               __raw_readsl(info->mmio_base + NDDB, info->data_buff,
-                               DIV_ROUND_UP(info->data_size, 4));
+               __raw_readsl(info->mmio_base + NDDB,
+                            info->data_buff + info->data_buff_pos,
+                            DIV_ROUND_UP(do_bytes, 4));
+
                if (info->oob_size > 0)
-                       __raw_readsl(info->mmio_base + NDDB, info->oob_buff,
-                                       DIV_ROUND_UP(info->oob_size, 4));
+                       __raw_readsl(info->mmio_base + NDDB,
+                                    info->oob_buff + info->oob_buff_pos,
+                                    DIV_ROUND_UP(info->oob_size, 4));
                break;
        default:
                dev_err(&info->pdev->dev, "%s: invalid state %d\n", __func__,
                                info->state);
                BUG();
        }
+
+       /* Update buffer pointers for multi-page read/write */
+       info->data_buff_pos += do_bytes;
+       info->oob_buff_pos += info->oob_size;
+       info->data_size -= do_bytes;
 }
 
 #ifdef ARCH_HAS_DMA
@@ -452,7 +563,7 @@ static void start_data_dma(struct pxa3xx_nand_info *info)
 static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 {
        struct pxa3xx_nand_info *info = devid;
-       unsigned int status, is_completed = 0;
+       unsigned int status, is_completed = 0, is_ready = 0;
        unsigned int ready, cmd_done;
 
        if (info->cs == 0) {
@@ -465,10 +576,25 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 
        status = nand_readl(info, NDSR);
 
-       if (status & NDSR_DBERR)
-               info->retcode = ERR_DBERR;
-       if (status & NDSR_SBERR)
-               info->retcode = ERR_SBERR;
+       if (status & NDSR_UNCORERR)
+               info->retcode = ERR_UNCORERR;
+       if (status & NDSR_CORERR) {
+               info->retcode = ERR_CORERR;
+               if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 &&
+                   info->ecc_bch)
+                       info->ecc_err_cnt = NDSR_ERR_CNT(status);
+               else
+                       info->ecc_err_cnt = 1;
+
+               /*
+                * Each chunk composing a page is corrected independently,
+                * and we need to store maximum number of corrected bitflips
+                * to return it to the MTD layer in ecc.read_page().
+                */
+               info->max_bitflips = max_t(unsigned int,
+                                          info->max_bitflips,
+                                          info->ecc_err_cnt);
+       }
        if (status & (NDSR_RDDREQ | NDSR_WRDREQ)) {
                /* whether use dma to transfer data */
                if (info->use_dma) {
@@ -488,8 +614,8 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
                is_completed = 1;
        }
        if (status & ready) {
-               info->is_ready = 1;
                info->state = STATE_READY;
+               is_ready = 1;
        }
 
        if (status & NDSR_WRCMDREQ) {
@@ -518,6 +644,8 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
        nand_writel(info, NDSR, status);
        if (is_completed)
                complete(&info->cmd_complete);
+       if (is_ready)
+               complete(&info->dev_ready);
 NORMAL_IRQ_EXIT:
        return IRQ_HANDLED;
 }
@@ -530,51 +658,93 @@ static inline int is_buf_blank(uint8_t *buf, size_t len)
        return 1;
 }
 
-static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
-               uint16_t column, int page_addr)
+static void set_command_address(struct pxa3xx_nand_info *info,
+               unsigned int page_size, uint16_t column, int page_addr)
 {
-       int addr_cycle, exec_cmd;
-       struct pxa3xx_nand_host *host;
-       struct mtd_info *mtd;
+       /* small page addr setting */
+       if (page_size < PAGE_CHUNK_SIZE) {
+               info->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
+                               | (column & 0xFF);
 
-       host = info->host[info->cs];
-       mtd = host->mtd;
-       addr_cycle = 0;
-       exec_cmd = 1;
+               info->ndcb2 = 0;
+       } else {
+               info->ndcb1 = ((page_addr & 0xFFFF) << 16)
+                               | (column & 0xFFFF);
+
+               if (page_addr & 0xFF0000)
+                       info->ndcb2 = (page_addr & 0xFF0000) >> 16;
+               else
+                       info->ndcb2 = 0;
+       }
+}
+
+static void prepare_start_command(struct pxa3xx_nand_info *info, int command)
+{
+       struct pxa3xx_nand_host *host = info->host[info->cs];
+       struct mtd_info *mtd = host->mtd;
 
        /* reset data and oob column point to handle data */
        info->buf_start         = 0;
        info->buf_count         = 0;
        info->oob_size          = 0;
+       info->data_buff_pos     = 0;
+       info->oob_buff_pos      = 0;
        info->use_ecc           = 0;
        info->use_spare         = 1;
-       info->is_ready          = 0;
        info->retcode           = ERR_NONE;
-       if (info->cs != 0)
-               info->ndcb0 = NDCB0_CSEL;
-       else
-               info->ndcb0 = 0;
+       info->ecc_err_cnt       = 0;
+       info->ndcb3             = 0;
 
        switch (command) {
        case NAND_CMD_READ0:
        case NAND_CMD_PAGEPROG:
                info->use_ecc = 1;
        case NAND_CMD_READOOB:
-               pxa3xx_set_datasize(info);
+               pxa3xx_set_datasize(info, mtd);
                break;
        case NAND_CMD_PARAM:
                info->use_spare = 0;
                break;
-       case NAND_CMD_SEQIN:
-               exec_cmd = 0;
-               break;
        default:
                info->ndcb1 = 0;
                info->ndcb2 = 0;
-               info->ndcb3 = 0;
                break;
        }
 
+       /*
+        * If we are about to issue a read command, or about to set
+        * the write address, then clean the data buffer.
+        */
+       if (command == NAND_CMD_READ0 ||
+           command == NAND_CMD_READOOB ||
+           command == NAND_CMD_SEQIN) {
+
+               info->buf_count = mtd->writesize + mtd->oobsize;
+               memset(info->data_buff, 0xFF, info->buf_count);
+       }
+
+}
+
+static int prepare_set_command(struct pxa3xx_nand_info *info, int command,
+               int ext_cmd_type, uint16_t column, int page_addr)
+{
+       int addr_cycle, exec_cmd;
+       struct pxa3xx_nand_host *host;
+       struct mtd_info *mtd;
+
+       host = info->host[info->cs];
+       mtd = host->mtd;
+       addr_cycle = 0;
+       exec_cmd = 1;
+
+       if (info->cs != 0)
+               info->ndcb0 = NDCB0_CSEL;
+       else
+               info->ndcb0 = 0;
+
+       if (command == NAND_CMD_SEQIN)
+               exec_cmd = 0;
+
        addr_cycle = NDCB0_ADDR_CYC(host->row_addr_cycles
                                    + host->col_addr_cycles);
 
@@ -589,30 +759,42 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
                if (command == NAND_CMD_READOOB)
                        info->buf_start += mtd->writesize;
 
-               /* Second command setting for large pages */
-               if (host->page_size >= PAGE_CHUNK_SIZE)
+               /*
+                * Multiple page read needs an 'extended command type' field,
+                * which is either naked-read or last-read according to the
+                * state.
+                */
+               if (mtd->writesize == PAGE_CHUNK_SIZE) {
                        info->ndcb0 |= NDCB0_DBC | (NAND_CMD_READSTART << 8);
+               } else if (mtd->writesize > PAGE_CHUNK_SIZE) {
+                       info->ndcb0 |= NDCB0_DBC | (NAND_CMD_READSTART << 8)
+                                       | NDCB0_LEN_OVRD
+                                       | NDCB0_EXT_CMD_TYPE(ext_cmd_type);
+                       info->ndcb3 = info->chunk_size +
+                                     info->oob_size;
+               }
+
+               set_command_address(info, mtd->writesize, column, page_addr);
+               break;
 
        case NAND_CMD_SEQIN:
-               /* small page addr setting */
-               if (unlikely(host->page_size < PAGE_CHUNK_SIZE)) {
-                       info->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
-                                       | (column & 0xFF);
 
-                       info->ndcb2 = 0;
-               } else {
-                       info->ndcb1 = ((page_addr & 0xFFFF) << 16)
-                                       | (column & 0xFFFF);
+               info->buf_start = column;
+               set_command_address(info, mtd->writesize, 0, page_addr);
 
-                       if (page_addr & 0xFF0000)
-                               info->ndcb2 = (page_addr & 0xFF0000) >> 16;
-                       else
-                               info->ndcb2 = 0;
+               /*
+                * Multiple page programming needs to execute the initial
+                * SEQIN command that sets the page address.
+                */
+               if (mtd->writesize > PAGE_CHUNK_SIZE) {
+                       info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
+                               | NDCB0_EXT_CMD_TYPE(ext_cmd_type)
+                               | addr_cycle
+                               | command;
+                       /* No data transfer in this case */
+                       info->data_size = 0;
+                       exec_cmd = 1;
                }
-
-               info->buf_count = mtd->writesize + mtd->oobsize;
-               memset(info->data_buff, 0xFF, info->buf_count);
-
                break;
 
        case NAND_CMD_PAGEPROG:
@@ -622,13 +804,40 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
                        break;
                }
 
-               info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
-                               | NDCB0_AUTO_RS
-                               | NDCB0_ST_ROW_EN
-                               | NDCB0_DBC
-                               | (NAND_CMD_PAGEPROG << 8)
-                               | NAND_CMD_SEQIN
-                               | addr_cycle;
+               /* Second command setting for large pages */
+               if (mtd->writesize > PAGE_CHUNK_SIZE) {
+                       /*
+                        * Multiple page write uses the 'extended command'
+                        * field. This can be used to issue a command dispatch
+                        * or a naked-write depending on the current stage.
+                        */
+                       info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
+                                       | NDCB0_LEN_OVRD
+                                       | NDCB0_EXT_CMD_TYPE(ext_cmd_type);
+                       info->ndcb3 = info->chunk_size +
+                                     info->oob_size;
+
+                       /*
+                        * This is the command dispatch that completes a chunked
+                        * page program operation.
+                        */
+                       if (info->data_size == 0) {
+                               info->ndcb0 = NDCB0_CMD_TYPE(0x1)
+                                       | NDCB0_EXT_CMD_TYPE(ext_cmd_type)
+                                       | command;
+                               info->ndcb1 = 0;
+                               info->ndcb2 = 0;
+                               info->ndcb3 = 0;
+                       }
+               } else {
+                       info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
+                                       | NDCB0_AUTO_RS
+                                       | NDCB0_ST_ROW_EN
+                                       | NDCB0_DBC
+                                       | (NAND_CMD_PAGEPROG << 8)
+                                       | NAND_CMD_SEQIN
+                                       | addr_cycle;
+               }
                break;
 
        case NAND_CMD_PARAM:
@@ -717,10 +926,15 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
                nand_writel(info, NDTR1CS0, info->ndtr1cs0);
        }
 
+       prepare_start_command(info, command);
+
        info->state = STATE_PREPARED;
-       exec_cmd = prepare_command_pool(info, command, column, page_addr);
+       exec_cmd = prepare_set_command(info, command, 0, column, page_addr);
+
        if (exec_cmd) {
                init_completion(&info->cmd_complete);
+               init_completion(&info->dev_ready);
+               info->need_wait = 1;
                pxa3xx_nand_start(info);
 
                ret = wait_for_completion_timeout(&info->cmd_complete,
@@ -734,6 +948,117 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
        info->state = STATE_IDLE;
 }
 
+static void armada370_nand_cmdfunc(struct mtd_info *mtd,
+                                  const unsigned command,
+                                  int column, int page_addr)
+{
+       struct pxa3xx_nand_host *host = mtd->priv;
+       struct pxa3xx_nand_info *info = host->info_data;
+       int ret, exec_cmd, ext_cmd_type;
+
+       /*
+        * if this is a x16 device then convert the input
+        * "byte" address into a "word" address appropriate
+        * for indexing a word-oriented device
+        */
+       if (info->reg_ndcr & NDCR_DWIDTH_M)
+               column /= 2;
+
+       /*
+        * There may be different NAND chip hooked to
+        * different chip select, so check whether
+        * chip select has been changed, if yes, reset the timing
+        */
+       if (info->cs != host->cs) {
+               info->cs = host->cs;
+               nand_writel(info, NDTR0CS0, info->ndtr0cs0);
+               nand_writel(info, NDTR1CS0, info->ndtr1cs0);
+       }
+
+       /* Select the extended command for the first command */
+       switch (command) {
+       case NAND_CMD_READ0:
+       case NAND_CMD_READOOB:
+               ext_cmd_type = EXT_CMD_TYPE_MONO;
+               break;
+       case NAND_CMD_SEQIN:
+               ext_cmd_type = EXT_CMD_TYPE_DISPATCH;
+               break;
+       case NAND_CMD_PAGEPROG:
+               ext_cmd_type = EXT_CMD_TYPE_NAKED_RW;
+               break;
+       default:
+               ext_cmd_type = 0;
+               break;
+       }
+
+       prepare_start_command(info, command);
+
+       /*
+        * Prepare the "is ready" completion before starting a command
+        * transaction sequence. If the command is not executed the
+        * completion will be completed, see below.
+        *
+        * We can do that inside the loop because the command variable
+        * is invariant and thus so is the exec_cmd.
+        */
+       info->need_wait = 1;
+       init_completion(&info->dev_ready);
+       do {
+               info->state = STATE_PREPARED;
+               exec_cmd = prepare_set_command(info, command, ext_cmd_type,
+                                              column, page_addr);
+               if (!exec_cmd) {
+                       info->need_wait = 0;
+                       complete(&info->dev_ready);
+                       break;
+               }
+
+               init_completion(&info->cmd_complete);
+               pxa3xx_nand_start(info);
+
+               ret = wait_for_completion_timeout(&info->cmd_complete,
+                               CHIP_DELAY_TIMEOUT);
+               if (!ret) {
+                       dev_err(&info->pdev->dev, "Wait time out!!!\n");
+                       /* Stop State Machine for next command cycle */
+                       pxa3xx_nand_stop(info);
+                       break;
+               }
+
+               /* Check if the sequence is complete */
+               if (info->data_size == 0 && command != NAND_CMD_PAGEPROG)
+                       break;
+
+               /*
+                * After a splitted program command sequence has issued
+                * the command dispatch, the command sequence is complete.
+                */
+               if (info->data_size == 0 &&
+                   command == NAND_CMD_PAGEPROG &&
+                   ext_cmd_type == EXT_CMD_TYPE_DISPATCH)
+                       break;
+
+               if (command == NAND_CMD_READ0 || command == NAND_CMD_READOOB) {
+                       /* Last read: issue a 'last naked read' */
+                       if (info->data_size == info->chunk_size)
+                               ext_cmd_type = EXT_CMD_TYPE_LAST_RW;
+                       else
+                               ext_cmd_type = EXT_CMD_TYPE_NAKED_RW;
+
+               /*
+                * If a splitted program command has no more data to transfer,
+                * the command dispatch must be issued to complete.
+                */
+               } else if (command == NAND_CMD_PAGEPROG &&
+                          info->data_size == 0) {
+                               ext_cmd_type = EXT_CMD_TYPE_DISPATCH;
+               }
+       } while (1);
+
+       info->state = STATE_IDLE;
+}
+
 static int pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
                struct nand_chip *chip, const uint8_t *buf, int oob_required)
 {
@@ -753,20 +1078,14 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
        chip->read_buf(mtd, buf, mtd->writesize);
        chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
 
-       if (info->retcode == ERR_SBERR) {
-               switch (info->use_ecc) {
-               case 1:
-                       mtd->ecc_stats.corrected++;
-                       break;
-               case 0:
-               default:
-                       break;
-               }
-       } else if (info->retcode == ERR_DBERR) {
+       if (info->retcode == ERR_CORERR && info->use_ecc) {
+               mtd->ecc_stats.corrected += info->ecc_err_cnt;
+
+       } else if (info->retcode == ERR_UNCORERR) {
                /*
                 * for blank page (all 0xff), HW will calculate its ECC as
                 * 0, which is different from the ECC information within
-                * OOB, ignore such double bit errors
+                * OOB, ignore such uncorrectable errors
                 */
                if (is_buf_blank(buf, mtd->writesize))
                        info->retcode = ERR_NONE;
@@ -774,7 +1093,7 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
                        mtd->ecc_stats.failed++;
        }
 
-       return 0;
+       return info->max_bitflips;
 }
 
 static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
@@ -833,21 +1152,27 @@ static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
 {
        struct pxa3xx_nand_host *host = mtd->priv;
        struct pxa3xx_nand_info *info = host->info_data;
+       int ret;
+
+       if (info->need_wait) {
+               ret = wait_for_completion_timeout(&info->dev_ready,
+                               CHIP_DELAY_TIMEOUT);
+               info->need_wait = 0;
+               if (!ret) {
+                       dev_err(&info->pdev->dev, "Ready time out!!!\n");
+                       return NAND_STATUS_FAIL;
+               }
+       }
 
        /* pxa3xx_nand_send_command has waited for command complete */
        if (this->state == FL_WRITING || this->state == FL_ERASING) {
                if (info->retcode == ERR_NONE)
                        return 0;
-               else {
-                       /*
-                        * any error make it return 0x01 which will tell
-                        * the caller the erase and write fail
-                        */
-                       return 0x01;
-               }
+               else
+                       return NAND_STATUS_FAIL;
        }
 
-       return 0;
+       return NAND_STATUS_READY;
 }
 
 static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
@@ -869,7 +1194,6 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
        }
 
        /* calculate flash information */
-       host->page_size = f->page_size;
        host->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
 
        /* calculate addressing information */
@@ -906,13 +1230,15 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
        uint32_t ndcr = nand_readl(info, NDCR);
 
        if (ndcr & NDCR_PAGE_SZ) {
-               host->page_size = 2048;
+               /* Controller's FIFO size */
+               info->chunk_size = 2048;
                host->read_id_bytes = 4;
        } else {
-               host->page_size = 512;
+               info->chunk_size = 512;
                host->read_id_bytes = 2;
        }
 
+       /* Set an initial chunk size */
        info->reg_ndcr = ndcr & ~NDCR_INT_MASK;
        info->ndtr0cs0 = nand_readl(info, NDTR0CS0);
        info->ndtr1cs0 = nand_readl(info, NDTR1CS0);
@@ -988,18 +1314,89 @@ static void pxa3xx_nand_free_buff(struct pxa3xx_nand_info *info)
 static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info)
 {
        struct mtd_info *mtd;
+       struct nand_chip *chip;
        int ret;
+
        mtd = info->host[info->cs]->mtd;
+       chip = mtd->priv;
+
        /* use the common timing to make a try */
        ret = pxa3xx_nand_config_flash(info, &builtin_flash_types[0]);
        if (ret)
                return ret;
 
-       pxa3xx_nand_cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
-       if (info->is_ready)
-               return 0;
+       chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
+       ret = chip->waitfunc(mtd, chip);
+       if (ret & NAND_STATUS_FAIL)
+               return -ENODEV;
 
-       return -ENODEV;
+       return 0;
+}
+
+static int pxa_ecc_init(struct pxa3xx_nand_info *info,
+                       struct nand_ecc_ctrl *ecc,
+                       int strength, int page_size)
+{
+       /*
+        * We don't use strength here as the PXA variant
+        * is used with non-ONFI compliant devices.
+        */
+       if (page_size == 2048) {
+               info->chunk_size = 2048;
+               info->spare_size = 40;
+               info->ecc_size = 24;
+               ecc->mode = NAND_ECC_HW;
+               ecc->size = 512;
+               ecc->strength = 1;
+               return 1;
+
+       } else if (page_size == 512) {
+               info->chunk_size = 512;
+               info->spare_size = 8;
+               info->ecc_size = 8;
+               ecc->mode = NAND_ECC_HW;
+               ecc->size = 512;
+               ecc->strength = 1;
+               return 1;
+       }
+       return 0;
+}
+
+static int armada370_ecc_init(struct pxa3xx_nand_info *info,
+                             struct nand_ecc_ctrl *ecc,
+                             int strength, int ecc_stepsize, int page_size)
+{
+       /*
+        * Required ECC: 4-bit correction per 512 bytes
+        * Select: 16-bit correction per 2048 bytes
+        */
+       if (strength == 4 && ecc_stepsize == 512 && page_size == 4096) {
+               info->ecc_bch = 1;
+               info->chunk_size = 2048;
+               info->spare_size = 32;
+               info->ecc_size = 32;
+               ecc->mode = NAND_ECC_HW;
+               ecc->size = info->chunk_size;
+               ecc->layout = &ecc_layout_4KB_bch4bit;
+               ecc->strength = 16;
+               return 1;
+
+       /*
+        * Required ECC: 8-bit correction per 512 bytes
+        * Select: 16-bit correction per 1024 bytes
+        */
+       } else if (strength == 8 && ecc_stepsize == 512 && page_size == 4096) {
+               info->ecc_bch = 1;
+               info->chunk_size = 1024;
+               info->spare_size = 0;
+               info->ecc_size = 32;
+               ecc->mode = NAND_ECC_HW;
+               ecc->size = info->chunk_size;
+               ecc->layout = &ecc_layout_4KB_bch8bit;
+               ecc->strength = 16;
+               return 1;
+       }
+       return 0;
 }
 
 static int pxa3xx_nand_scan(struct mtd_info *mtd)
@@ -1072,15 +1469,43 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
        pxa3xx_flash_ids[1].name = NULL;
        def = pxa3xx_flash_ids;
 KEEP_CONFIG:
-       chip->ecc.mode = NAND_ECC_HW;
-       chip->ecc.size = host->page_size;
-       chip->ecc.strength = 1;
-
        if (info->reg_ndcr & NDCR_DWIDTH_M)
                chip->options |= NAND_BUSWIDTH_16;
 
+       /* Device detection must be done with ECC disabled */
+       if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370)
+               nand_writel(info, NDECCCTRL, 0x0);
+
        if (nand_scan_ident(mtd, 1, def))
                return -ENODEV;
+
+       if (pdata->flash_bbt) {
+               /*
+                * We'll use a bad block table stored in-flash and don't
+                * allow writing the bad block marker to the flash.
+                */
+               chip->bbt_options |= NAND_BBT_USE_FLASH |
+                                    NAND_BBT_NO_OOB_BBM;
+               chip->bbt_td = &bbt_main_descr;
+               chip->bbt_md = &bbt_mirror_descr;
+       }
+
+       if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370)
+               ret = armada370_ecc_init(info, &chip->ecc,
+                                  chip->ecc_strength_ds,
+                                  chip->ecc_step_ds,
+                                  mtd->writesize);
+       else
+               ret = pxa_ecc_init(info, &chip->ecc,
+                                  chip->ecc_strength_ds,
+                                  mtd->writesize);
+       if (!ret) {
+               dev_err(&info->pdev->dev,
+                       "ECC strength %d at page size %d is not supported\n",
+                       chip->ecc_strength_ds, mtd->writesize);
+               return -ENODEV;
+       }
+
        /* calculate addressing information */
        if (mtd->writesize >= 2048)
                host->col_addr_cycles = 2;
@@ -1121,6 +1546,7 @@ static int alloc_nand_resource(struct platform_device *pdev)
                return -ENOMEM;
 
        info->pdev = pdev;
+       info->variant = pxa3xx_nand_get_variant(pdev);
        for (cs = 0; cs < pdata->num_cs; cs++) {
                mtd = (struct mtd_info *)((unsigned int)&info[1] +
                      (sizeof(*mtd) + sizeof(*host)) * cs);
@@ -1138,11 +1564,16 @@ static int alloc_nand_resource(struct platform_device *pdev)
                chip->controller        = &info->controller;
                chip->waitfunc          = pxa3xx_nand_waitfunc;
                chip->select_chip       = pxa3xx_nand_select_chip;
-               chip->cmdfunc           = pxa3xx_nand_cmdfunc;
                chip->read_word         = pxa3xx_nand_read_word;
                chip->read_byte         = pxa3xx_nand_read_byte;
                chip->read_buf          = pxa3xx_nand_read_buf;
                chip->write_buf         = pxa3xx_nand_write_buf;
+               chip->options           |= NAND_NO_SUBPAGE_WRITE;
+
+               if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370)
+                       chip->cmdfunc = armada370_nand_cmdfunc;
+               else
+                       chip->cmdfunc = pxa3xx_nand_cmdfunc;
        }
 
        spin_lock_init(&chip->controller->lock);
@@ -1254,29 +1685,6 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
        return 0;
 }
 
-static struct of_device_id pxa3xx_nand_dt_ids[] = {
-       {
-               .compatible = "marvell,pxa3xx-nand",
-               .data       = (void *)PXA3XX_NAND_VARIANT_PXA,
-       },
-       {
-               .compatible = "marvell,armada370-nand",
-               .data       = (void *)PXA3XX_NAND_VARIANT_ARMADA370,
-       },
-       {}
-};
-MODULE_DEVICE_TABLE(of, pxa3xx_nand_dt_ids);
-
-static enum pxa3xx_nand_variant
-pxa3xx_nand_get_variant(struct platform_device *pdev)
-{
-       const struct of_device_id *of_id =
-                       of_match_device(pxa3xx_nand_dt_ids, &pdev->dev);
-       if (!of_id)
-               return PXA3XX_NAND_VARIANT_PXA;
-       return (enum pxa3xx_nand_variant)of_id->data;
-}
-
 static int pxa3xx_nand_probe_dt(struct platform_device *pdev)
 {
        struct pxa3xx_nand_platform_data *pdata;
@@ -1296,6 +1704,7 @@ static int pxa3xx_nand_probe_dt(struct platform_device *pdev)
        if (of_get_property(np, "marvell,nand-keep-config", NULL))
                pdata->keep_config = 1;
        of_property_read_u32(np, "num-cs", &pdata->num_cs);
+       pdata->flash_bbt = of_get_nand_on_flash_bbt(np);
 
        pdev->dev.platform_data = pdata;
 
@@ -1333,7 +1742,6 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
        }
 
        info = platform_get_drvdata(pdev);
-       info->variant = pxa3xx_nand_get_variant(pdev);
        probe_success = 0;
        for (cs = 0; cs < pdata->num_cs; cs++) {
                struct mtd_info *mtd = info->host[cs]->mtd;
index a3c84ebbe39227dac06bae3d0f9014849cf48b17..50f1cb93324f2134f132f3e305e61efcaa361f01 100644 (file)
@@ -151,7 +151,7 @@ static void flctl_setup_dma(struct sh_flctl *flctl)
        dma_cap_set(DMA_SLAVE, mask);
 
        flctl->chan_fifo0_tx = dma_request_channel(mask, shdma_chan_filter,
-                                           (void *)pdata->slave_id_fifo0_tx);
+                               (void *)(uintptr_t)pdata->slave_id_fifo0_tx);
        dev_dbg(&pdev->dev, "%s: TX: got channel %p\n", __func__,
                flctl->chan_fifo0_tx);
 
@@ -168,7 +168,7 @@ static void flctl_setup_dma(struct sh_flctl *flctl)
                goto err;
 
        flctl->chan_fifo0_rx = dma_request_channel(mask, shdma_chan_filter,
-                                           (void *)pdata->slave_id_fifo0_rx);
+                               (void *)(uintptr_t)pdata->slave_id_fifo0_rx);
        dev_dbg(&pdev->dev, "%s: RX: got channel %p\n", __func__,
                flctl->chan_fifo0_rx);
 
@@ -1094,38 +1094,32 @@ static int flctl_probe(struct platform_device *pdev)
        struct mtd_info *flctl_mtd;
        struct nand_chip *nand;
        struct sh_flctl_platform_data *pdata;
-       int ret = -ENXIO;
+       int ret;
        int irq;
        struct mtd_part_parser_data ppdata = {};
 
-       flctl = kzalloc(sizeof(struct sh_flctl), GFP_KERNEL);
+       flctl = devm_kzalloc(&pdev->dev, sizeof(struct sh_flctl), GFP_KERNEL);
        if (!flctl) {
                dev_err(&pdev->dev, "failed to allocate driver data\n");
                return -ENOMEM;
        }
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "failed to get I/O memory\n");
-               goto err_iomap;
-       }
-
-       flctl->reg = ioremap(res->start, resource_size(res));
-       if (flctl->reg == NULL) {
-               dev_err(&pdev->dev, "failed to remap I/O memory\n");
-               goto err_iomap;
-       }
+       flctl->reg = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(flctl->reg))
+               return PTR_ERR(flctl->reg);
 
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
                dev_err(&pdev->dev, "failed to get flste irq data\n");
-               goto err_flste;
+               return -ENXIO;
        }
 
-       ret = request_irq(irq, flctl_handle_flste, IRQF_SHARED, "flste", flctl);
+       ret = devm_request_irq(&pdev->dev, irq, flctl_handle_flste, IRQF_SHARED,
+                              "flste", flctl);
        if (ret) {
                dev_err(&pdev->dev, "request interrupt failed.\n");
-               goto err_flste;
+               return ret;
        }
 
        if (pdev->dev.of_node)
@@ -1135,8 +1129,7 @@ static int flctl_probe(struct platform_device *pdev)
 
        if (!pdata) {
                dev_err(&pdev->dev, "no setup data defined\n");
-               ret = -EINVAL;
-               goto err_pdata;
+               return -EINVAL;
        }
 
        platform_set_drvdata(pdev, flctl);
@@ -1190,12 +1183,6 @@ static int flctl_probe(struct platform_device *pdev)
 err_chip:
        flctl_release_dma(flctl);
        pm_runtime_disable(&pdev->dev);
-err_pdata:
-       free_irq(irq, flctl);
-err_flste:
-       iounmap(flctl->reg);
-err_iomap:
-       kfree(flctl);
        return ret;
 }
 
@@ -1206,9 +1193,6 @@ static int flctl_remove(struct platform_device *pdev)
        flctl_release_dma(flctl);
        nand_release(&flctl->mtd);
        pm_runtime_disable(&pdev->dev);
-       free_irq(platform_get_irq(pdev, 0), flctl);
-       iounmap(flctl->reg);
-       kfree(flctl);
 
        return 0;
 }
index d64f8c30945fbcd8e2d09a5b8342e75c081cd343..aa26c32e1bc28943426992eba09fddc207cf104d 100644 (file)
@@ -81,7 +81,7 @@ static int parse_ofpart_partitions(struct mtd_info *master,
                partname = of_get_property(pp, "label", &len);
                if (!partname)
                        partname = of_get_property(pp, "name", &len);
-               (*pparts)[i].name = (char *)partname;
+               (*pparts)[i].name = partname;
 
                if (of_get_property(pp, "read-only", &len))
                        (*pparts)[i].mask_flags |= MTD_WRITEABLE;
@@ -152,7 +152,7 @@ static int parse_ofoldpart_partitions(struct mtd_info *master,
                if (names && (plen > 0)) {
                        int len = strlen(names) + 1;
 
-                       (*pparts)[i].name = (char *)names;
+                       (*pparts)[i].name = names;
                        plen -= len;
                        names += len;
                } else {
@@ -173,18 +173,9 @@ static struct mtd_part_parser ofoldpart_parser = {
 
 static int __init ofpart_parser_init(void)
 {
-       int rc;
-       rc = register_mtd_parser(&ofpart_parser);
-       if (rc)
-               goto out;
-
-       rc = register_mtd_parser(&ofoldpart_parser);
-       if (!rc)
-               return 0;
-
-       deregister_mtd_parser(&ofoldpart_parser);
-out:
-       return rc;
+       register_mtd_parser(&ofpart_parser);
+       register_mtd_parser(&ofoldpart_parser);
+       return 0;
 }
 
 static void __exit ofpart_parser_exit(void)
index 580035c803d693eb38b8f37750a85d57f70cadfa..5da911ebdf495152c68c52af72d0784f0a8ede54 100644 (file)
@@ -300,7 +300,8 @@ MODULE_ALIAS("RedBoot");
 
 static int __init redboot_parser_init(void)
 {
-       return register_mtd_parser(&redboot_parser);
+       register_mtd_parser(&redboot_parser);
+       return 0;
 }
 
 static void __exit redboot_parser_exit(void)
index 70106607c247289b6328c9ff99321d64ffc49c81..e579f9027c47d82bb1e4d577ddd13128324a0075 100644 (file)
@@ -19,7 +19,7 @@
  * or detected.
  */
 
-#if defined(CONFIG_MTD_NAND) || defined(CONFIG_MTD_NAND_MODULE)
+#if IS_ENABLED(CONFIG_MTD_NAND)
 
 struct nand_ecc_test {
        const char *name;
index 02872405d35dc4a53d13473b31d1b517d22610d0..2250b063ab89e09006397f123ae725486f09fed5 100644 (file)
@@ -12,8 +12,7 @@
  * 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.
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * The full GNU General Public License is included in this distribution in the
  * file called LICENSE.
index 4226044efd083645db9229c0f88e507eae6d410b..e09dd4bfafffcf585b8f853f7661e2e416c58602 100644 (file)
@@ -12,8 +12,7 @@
  * 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.
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * The full GNU General Public License is included in this distribution in the
  * file called LICENSE.
index 4dd5ee2a34cc68c4222f4c4115beedaee8b187d2..398e299ee1bded33a57d7eb91318b00b24513658 100644 (file)
@@ -4110,7 +4110,7 @@ static int bond_check_params(struct bond_params *params)
                if (!miimon) {
                        pr_warning("Warning: miimon must be specified, otherwise bonding will not detect link failure, speed and duplex which are essential for 802.3ad operation\n");
                        pr_warning("Forcing miimon to 100msec\n");
-                       miimon = 100;
+                       miimon = BOND_DEFAULT_MIIMON;
                }
        }
 
@@ -4147,7 +4147,7 @@ static int bond_check_params(struct bond_params *params)
                if (!miimon) {
                        pr_warning("Warning: miimon must be specified, otherwise bonding will not detect link failure and link speed which are essential for TLB/ALB load balancing\n");
                        pr_warning("Forcing miimon to 100msec\n");
-                       miimon = 100;
+                       miimon = BOND_DEFAULT_MIIMON;
                }
        }
 
@@ -4199,9 +4199,9 @@ static int bond_check_params(struct bond_params *params)
             (arp_ip_count < BOND_MAX_ARP_TARGETS) && arp_ip_target[i]; i++) {
                /* not complete check, but should be good enough to
                   catch mistakes */
-               __be32 ip = in_aton(arp_ip_target[i]);
-               if (!isdigit(arp_ip_target[i][0]) || ip == 0 ||
-                   ip == htonl(INADDR_BROADCAST)) {
+               __be32 ip;
+               if (!in4_pton(arp_ip_target[i], -1, (u8 *)&ip, -1, NULL) ||
+                   IS_IP_TARGET_UNUSABLE_ADDRESS(ip)) {
                        pr_warning("Warning: bad arp_ip_target module parameter (%s), ARP monitoring will not be performed\n",
                                   arp_ip_target[i]);
                        arp_interval = 0;
index 9a5223c7b4d1a14f9b19354cfba6c4ea3dd933d0..ea6f640782b7456228787fa33ab8882b2bd8aa0b 100644 (file)
@@ -45,10 +45,15 @@ int bond_option_mode_set(struct bonding *bond, int mode)
                return -EPERM;
        }
 
-       if (BOND_MODE_IS_LB(mode) && bond->params.arp_interval) {
-               pr_err("%s: %s mode is incompatible with arp monitoring.\n",
-                      bond->dev->name, bond_mode_tbl[mode].modename);
-               return -EINVAL;
+       if (BOND_NO_USES_ARP(mode) && bond->params.arp_interval) {
+               pr_info("%s: %s mode is incompatible with arp monitoring, start mii monitoring\n",
+                       bond->dev->name, bond_mode_tbl[mode].modename);
+               /* disable arp monitoring */
+               bond->params.arp_interval = 0;
+               /* set miimon to default value */
+               bond->params.miimon = BOND_DEFAULT_MIIMON;
+               pr_info("%s: Setting MII monitoring interval to %d.\n",
+                       bond->dev->name, bond->params.miimon);
        }
 
        /* don't cache arp_validate between modes */
index 0ec2a7e8c8a9588170c97715856e7b5f34cf7c60..e46467683e822e6d5ff6bd49f389220c12a28e16 100644 (file)
@@ -12,8 +12,7 @@
  * 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.
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * The full GNU General Public License is included in this distribution in the
  * file called LICENSE.
@@ -523,9 +522,7 @@ static ssize_t bonding_store_arp_interval(struct device *d,
                ret = -EINVAL;
                goto out;
        }
-       if (bond->params.mode == BOND_MODE_ALB ||
-           bond->params.mode == BOND_MODE_TLB ||
-           bond->params.mode == BOND_MODE_8023AD) {
+       if (BOND_NO_USES_ARP(bond->params.mode)) {
                pr_info("%s: ARP monitoring cannot be used with ALB/TLB/802.3ad. Only MII monitoring is supported on %s.\n",
                        bond->dev->name, bond->dev->name);
                ret = -EINVAL;
@@ -1637,12 +1634,12 @@ static ssize_t bonding_show_packets_per_slave(struct device *d,
                                              char *buf)
 {
        struct bonding *bond = to_bond(d);
-       int packets_per_slave = bond->params.packets_per_slave;
+       unsigned int packets_per_slave = bond->params.packets_per_slave;
 
        if (packets_per_slave > 1)
                packets_per_slave = reciprocal_value(packets_per_slave);
 
-       return sprintf(buf, "%d\n", packets_per_slave);
+       return sprintf(buf, "%u\n", packets_per_slave);
 }
 
 static ssize_t bonding_store_packets_per_slave(struct device *d,
index ca31286aa028158341a5847382b75afb74a6ea2f..a74c92c83eadda206f92ea02d59c75281ffeab71 100644 (file)
@@ -35,6 +35,8 @@
 
 #define BOND_MAX_ARP_TARGETS   16
 
+#define BOND_DEFAULT_MIIMON    100
+
 #define IS_UP(dev)                                        \
              ((((dev)->flags & IFF_UP) == IFF_UP)      && \
               netif_running(dev)                       && \
                 ((mode) == BOND_MODE_TLB)          ||  \
                 ((mode) == BOND_MODE_ALB))
 
+#define BOND_NO_USES_ARP(mode)                         \
+               (((mode) == BOND_MODE_8023AD)   ||      \
+                ((mode) == BOND_MODE_TLB)      ||      \
+                ((mode) == BOND_MODE_ALB))
+
 #define TX_QUEUE_OVERRIDE(mode)                                \
                        (((mode) == BOND_MODE_ACTIVEBACKUP) ||  \
                         ((mode) == BOND_MODE_ROUNDROBIN))
@@ -387,8 +394,8 @@ static inline __be32 bond_confirm_addr(struct net_device *dev, __be32 dst, __be3
        in_dev = __in_dev_get_rcu(dev);
 
        if (in_dev)
-               addr = inet_confirm_addr(in_dev, dst, local, RT_SCOPE_HOST);
-
+               addr = inet_confirm_addr(dev_net(dev), in_dev, dst, local,
+                                        RT_SCOPE_HOST);
        rcu_read_unlock();
        return addr;
 }
index e3fc07cf2f6269e5ccf0ca5dbf42897c191cecd4..77061eebb034f4295258d9b0800fed28865d123a 100644 (file)
@@ -712,22 +712,31 @@ static int c_can_set_mode(struct net_device *dev, enum can_mode mode)
        return 0;
 }
 
-static int c_can_get_berr_counter(const struct net_device *dev,
-                                       struct can_berr_counter *bec)
+static int __c_can_get_berr_counter(const struct net_device *dev,
+                                   struct can_berr_counter *bec)
 {
        unsigned int reg_err_counter;
        struct c_can_priv *priv = netdev_priv(dev);
 
-       c_can_pm_runtime_get_sync(priv);
-
        reg_err_counter = priv->read_reg(priv, C_CAN_ERR_CNT_REG);
        bec->rxerr = (reg_err_counter & ERR_CNT_REC_MASK) >>
                                ERR_CNT_REC_SHIFT;
        bec->txerr = reg_err_counter & ERR_CNT_TEC_MASK;
 
+       return 0;
+}
+
+static int c_can_get_berr_counter(const struct net_device *dev,
+                                 struct can_berr_counter *bec)
+{
+       struct c_can_priv *priv = netdev_priv(dev);
+       int err;
+
+       c_can_pm_runtime_get_sync(priv);
+       err = __c_can_get_berr_counter(dev, bec);
        c_can_pm_runtime_put_sync(priv);
 
-       return 0;
+       return err;
 }
 
 /*
@@ -754,6 +763,7 @@ static void c_can_do_tx(struct net_device *dev)
                if (!(val & (1 << (msg_obj_no - 1)))) {
                        can_get_echo_skb(dev,
                                        msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST);
+                       c_can_object_get(dev, 0, msg_obj_no, IF_COMM_ALL);
                        stats->tx_bytes += priv->read_reg(priv,
                                        C_CAN_IFACE(MSGCTRL_REG, 0))
                                        & IF_MCONT_DLC_MASK;
@@ -872,7 +882,7 @@ static int c_can_handle_state_change(struct net_device *dev,
        if (unlikely(!skb))
                return 0;
 
-       c_can_get_berr_counter(dev, &bec);
+       __c_can_get_berr_counter(dev, &bec);
        reg_err_counter = priv->read_reg(priv, C_CAN_ERR_CNT_REG);
        rx_err_passive = (reg_err_counter & ERR_CNT_RP_MASK) >>
                                ERR_CNT_RP_SHIFT;
index ae08cf129ebbb0bda31f4b74893574b9703253f0..aaed97bee4711d1cb2e8b1eb514fc3e343ad21e0 100644 (file)
@@ -1020,13 +1020,13 @@ static int flexcan_probe(struct platform_device *pdev)
                        dev_err(&pdev->dev, "no ipg clock defined\n");
                        return PTR_ERR(clk_ipg);
                }
-               clock_freq = clk_get_rate(clk_ipg);
 
                clk_per = devm_clk_get(&pdev->dev, "per");
                if (IS_ERR(clk_per)) {
                        dev_err(&pdev->dev, "no per clock defined\n");
                        return PTR_ERR(clk_per);
                }
+               clock_freq = clk_get_rate(clk_per);
        }
 
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
index e59b3a392af62d8cfcb0e9f40ad3b974027c3299..6b0c9958d824b729d74cfbbdb83713a71dd978f3 100644 (file)
@@ -109,135 +109,170 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
 #endif /* CONFIG_PPC_MPC52xx */
 
 #ifdef CONFIG_PPC_MPC512x
-struct mpc512x_clockctl {
-       u32 spmr;               /* System PLL Mode Reg */
-       u32 sccr[2];            /* System Clk Ctrl Reg 1 & 2 */
-       u32 scfr1;              /* System Clk Freq Reg 1 */
-       u32 scfr2;              /* System Clk Freq Reg 2 */
-       u32 reserved;
-       u32 bcr;                /* Bread Crumb Reg */
-       u32 pccr[12];           /* PSC Clk Ctrl Reg 0-11 */
-       u32 spccr;              /* SPDIF Clk Ctrl Reg */
-       u32 cccr;               /* CFM Clk Ctrl Reg */
-       u32 dccr;               /* DIU Clk Cnfg Reg */
-       u32 mccr[4];            /* MSCAN Clk Ctrl Reg 1-3 */
-};
-
-static struct of_device_id mpc512x_clock_ids[] = {
-       { .compatible = "fsl,mpc5121-clock", },
-       {}
-};
-
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
-                                const char *clock_name, int *mscan_clksrc)
+                                const char *clock_source, int *mscan_clksrc)
 {
-       struct mpc512x_clockctl __iomem *clockctl;
-       struct device_node *np_clock;
-       struct clk *sys_clk, *ref_clk;
-       int plen, clockidx, clocksrc = -1;
-       u32 sys_freq, val, clockdiv = 1, freq = 0;
-       const u32 *pval;
-
-       np_clock = of_find_matching_node(NULL, mpc512x_clock_ids);
-       if (!np_clock) {
-               dev_err(&ofdev->dev, "couldn't find clock node\n");
-               return 0;
-       }
-       clockctl = of_iomap(np_clock, 0);
-       if (!clockctl) {
-               dev_err(&ofdev->dev, "couldn't map clock registers\n");
-               goto exit_put;
-       }
+       struct device_node *np;
+       u32 clockdiv;
+       enum {
+               CLK_FROM_AUTO,
+               CLK_FROM_IPS,
+               CLK_FROM_SYS,
+               CLK_FROM_REF,
+       } clk_from;
+       struct clk *clk_in, *clk_can;
+       unsigned long freq_calc;
+       struct mscan_priv *priv;
+       struct clk *clk_ipg;
 
-       /* Determine the MSCAN device index from the peripheral's
-        * physical address. Register address offsets against the
-        * IMMR base are:  0x1300, 0x1380, 0x2300, 0x2380
+       /* the caller passed in the clock source spec that was read from
+        * the device tree, get the optional clock divider as well
         */
-       pval = of_get_property(ofdev->dev.of_node, "reg", &plen);
-       BUG_ON(!pval || plen < sizeof(*pval));
-       clockidx = (*pval & 0x80) ? 1 : 0;
-       if (*pval & 0x2000)
-               clockidx += 2;
+       np = ofdev->dev.of_node;
+       clockdiv = 1;
+       of_property_read_u32(np, "fsl,mscan-clock-divider", &clockdiv);
+       dev_dbg(&ofdev->dev, "device tree specs: clk src[%s] div[%d]\n",
+               clock_source ? clock_source : "<NULL>", clockdiv);
+
+       /* when clock-source is 'ip', the CANCTL1[CLKSRC] bit needs to
+        * get set, and the 'ips' clock is the input to the MSCAN
+        * component
+        *
+        * for clock-source values of 'ref' or 'sys' the CANCTL1[CLKSRC]
+        * bit needs to get cleared, an optional clock-divider may have
+        * been specified (the default value is 1), the appropriate
+        * MSCAN related MCLK is the input to the MSCAN component
+        *
+        * in the absence of a clock-source spec, first an optimal clock
+        * gets determined based on the 'sys' clock, if that fails the
+        * 'ref' clock is used
+        */
+       clk_from = CLK_FROM_AUTO;
+       if (clock_source) {
+               /* interpret the device tree's spec for the clock source */
+               if (!strcmp(clock_source, "ip"))
+                       clk_from = CLK_FROM_IPS;
+               else if (!strcmp(clock_source, "sys"))
+                       clk_from = CLK_FROM_SYS;
+               else if (!strcmp(clock_source, "ref"))
+                       clk_from = CLK_FROM_REF;
+               else
+                       goto err_invalid;
+               dev_dbg(&ofdev->dev, "got a clk source spec[%d]\n", clk_from);
+       }
+       if (clk_from == CLK_FROM_AUTO) {
+               /* no spec so far, try the 'sys' clock; round to the
+                * next MHz and see if we can get a multiple of 16MHz
+                */
+               dev_dbg(&ofdev->dev, "no clk source spec, trying SYS\n");
+               clk_in = devm_clk_get(&ofdev->dev, "sys");
+               if (IS_ERR(clk_in))
+                       goto err_notavail;
+               freq_calc = clk_get_rate(clk_in);
+               freq_calc +=  499999;
+               freq_calc /= 1000000;
+               freq_calc *= 1000000;
+               if ((freq_calc % 16000000) == 0) {
+                       clk_from = CLK_FROM_SYS;
+                       clockdiv = freq_calc / 16000000;
+                       dev_dbg(&ofdev->dev,
+                               "clk fit, sys[%lu] div[%d] freq[%lu]\n",
+                               freq_calc, clockdiv, freq_calc / clockdiv);
+               }
+       }
+       if (clk_from == CLK_FROM_AUTO) {
+               /* no spec so far, use the 'ref' clock */
+               dev_dbg(&ofdev->dev, "no clk source spec, trying REF\n");
+               clk_in = devm_clk_get(&ofdev->dev, "ref");
+               if (IS_ERR(clk_in))
+                       goto err_notavail;
+               clk_from = CLK_FROM_REF;
+               freq_calc = clk_get_rate(clk_in);
+               dev_dbg(&ofdev->dev,
+                       "clk fit, ref[%lu] (no div) freq[%lu]\n",
+                       freq_calc, freq_calc);
+       }
 
-       /*
-        * Clock source and divider selection: 3 different clock sources
-        * can be selected: "ip", "ref" or "sys". For the latter two, a
-        * clock divider can be defined as well. If the clock source is
-        * not specified by the device tree, we first try to find an
-        * optimal CAN source clock based on the system clock. If that
-        * is not posslible, the reference clock will be used.
+       /* select IPS or MCLK as the MSCAN input (returned to the caller),
+        * setup the MCLK mux source and rate if applicable, apply the
+        * optionally specified or derived above divider, and determine
+        * the actual resulting clock rate to return to the caller
         */
-       if (clock_name && !strcmp(clock_name, "ip")) {
+       switch (clk_from) {
+       case CLK_FROM_IPS:
+               clk_can = devm_clk_get(&ofdev->dev, "ips");
+               if (IS_ERR(clk_can))
+                       goto err_notavail;
+               priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
+               priv->clk_can = clk_can;
+               freq_calc = clk_get_rate(clk_can);
                *mscan_clksrc = MSCAN_CLKSRC_IPS;
-               freq = mpc5xxx_get_bus_frequency(ofdev->dev.of_node);
-       } else {
+               dev_dbg(&ofdev->dev, "clk from IPS, clksrc[%d] freq[%lu]\n",
+                       *mscan_clksrc, freq_calc);
+               break;
+       case CLK_FROM_SYS:
+       case CLK_FROM_REF:
+               clk_can = devm_clk_get(&ofdev->dev, "mclk");
+               if (IS_ERR(clk_can))
+                       goto err_notavail;
+               priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
+               priv->clk_can = clk_can;
+               if (clk_from == CLK_FROM_SYS)
+                       clk_in = devm_clk_get(&ofdev->dev, "sys");
+               if (clk_from == CLK_FROM_REF)
+                       clk_in = devm_clk_get(&ofdev->dev, "ref");
+               if (IS_ERR(clk_in))
+                       goto err_notavail;
+               clk_set_parent(clk_can, clk_in);
+               freq_calc = clk_get_rate(clk_in);
+               freq_calc /= clockdiv;
+               clk_set_rate(clk_can, freq_calc);
+               freq_calc = clk_get_rate(clk_can);
                *mscan_clksrc = MSCAN_CLKSRC_BUS;
-
-               pval = of_get_property(ofdev->dev.of_node,
-                                      "fsl,mscan-clock-divider", &plen);
-               if (pval && plen == sizeof(*pval))
-                       clockdiv = *pval;
-               if (!clockdiv)
-                       clockdiv = 1;
-
-               if (!clock_name || !strcmp(clock_name, "sys")) {
-                       sys_clk = devm_clk_get(&ofdev->dev, "sys_clk");
-                       if (IS_ERR(sys_clk)) {
-                               dev_err(&ofdev->dev, "couldn't get sys_clk\n");
-                               goto exit_unmap;
-                       }
-                       /* Get and round up/down sys clock rate */
-                       sys_freq = 1000000 *
-                               ((clk_get_rate(sys_clk) + 499999) / 1000000);
-
-                       if (!clock_name) {
-                               /* A multiple of 16 MHz would be optimal */
-                               if ((sys_freq % 16000000) == 0) {
-                                       clocksrc = 0;
-                                       clockdiv = sys_freq / 16000000;
-                                       freq = sys_freq / clockdiv;
-                               }
-                       } else {
-                               clocksrc = 0;
-                               freq = sys_freq / clockdiv;
-                       }
-               }
-
-               if (clocksrc < 0) {
-                       ref_clk = devm_clk_get(&ofdev->dev, "ref_clk");
-                       if (IS_ERR(ref_clk)) {
-                               dev_err(&ofdev->dev, "couldn't get ref_clk\n");
-                               goto exit_unmap;
-                       }
-                       clocksrc = 1;
-                       freq = clk_get_rate(ref_clk) / clockdiv;
-               }
+               dev_dbg(&ofdev->dev, "clk from MCLK, clksrc[%d] freq[%lu]\n",
+                       *mscan_clksrc, freq_calc);
+               break;
+       default:
+               goto err_invalid;
        }
 
-       /* Disable clock */
-       out_be32(&clockctl->mccr[clockidx], 0x0);
-       if (clocksrc >= 0) {
-               /* Set source and divider */
-               val = (clocksrc << 14) | ((clockdiv - 1) << 17);
-               out_be32(&clockctl->mccr[clockidx], val);
-               /* Enable clock */
-               out_be32(&clockctl->mccr[clockidx], val | 0x10000);
-       }
+       /* the above clk_can item is used for the bitrate, access to
+        * the peripheral's register set needs the clk_ipg item
+        */
+       clk_ipg = devm_clk_get(&ofdev->dev, "ipg");
+       if (IS_ERR(clk_ipg))
+               goto err_notavail_ipg;
+       if (clk_prepare_enable(clk_ipg))
+               goto err_notavail_ipg;
+       priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
+       priv->clk_ipg = clk_ipg;
+
+       /* return the determined clock source rate */
+       return freq_calc;
+
+err_invalid:
+       dev_err(&ofdev->dev, "invalid clock source specification\n");
+       /* clock source rate could not get determined */
+       return 0;
 
-       /* Enable MSCAN clock domain */
-       val = in_be32(&clockctl->sccr[1]);
-       if (!(val & (1 << 25)))
-               out_be32(&clockctl->sccr[1], val | (1 << 25));
+err_notavail:
+       dev_err(&ofdev->dev, "cannot acquire or setup bitrate clock source\n");
+       /* clock source rate could not get determined */
+       return 0;
 
-       dev_dbg(&ofdev->dev, "using '%s' with frequency divider %d\n",
-               *mscan_clksrc == MSCAN_CLKSRC_IPS ? "ips_clk" :
-               clocksrc == 1 ? "ref_clk" : "sys_clk", clockdiv);
+err_notavail_ipg:
+       dev_err(&ofdev->dev, "cannot acquire or setup register clock\n");
+       /* clock source rate could not get determined */
+       return 0;
+}
 
-exit_unmap:
-       iounmap(clockctl);
-exit_put:
-       of_node_put(np_clock);
-       return freq;
+static void mpc512x_can_put_clock(struct platform_device *ofdev)
+{
+       struct mscan_priv *priv;
+
+       priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
+       if (priv->clk_ipg)
+               clk_disable_unprepare(priv->clk_ipg);
 }
 #else /* !CONFIG_PPC_MPC512x */
 static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
@@ -245,6 +280,7 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
 {
        return 0;
 }
+#define mpc512x_can_put_clock NULL
 #endif /* CONFIG_PPC_MPC512x */
 
 static const struct of_device_id mpc5xxx_can_table[];
@@ -386,11 +422,13 @@ static int mpc5xxx_can_resume(struct platform_device *ofdev)
 static const struct mpc5xxx_can_data mpc5200_can_data = {
        .type = MSCAN_TYPE_MPC5200,
        .get_clock = mpc52xx_can_get_clock,
+       /* .put_clock not applicable */
 };
 
 static const struct mpc5xxx_can_data mpc5121_can_data = {
        .type = MSCAN_TYPE_MPC5121,
        .get_clock = mpc512x_can_get_clock,
+       .put_clock = mpc512x_can_put_clock,
 };
 
 static const struct of_device_id mpc5xxx_can_table[] = {
index 7164a999f50ff37e176f9995f21cd04451f17043..f17c3018b7c7ffb3f7d75785c3ddd2218b0f3f79 100644 (file)
@@ -494,20 +494,20 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
        uint8_t isrc, status;
        int n = 0;
 
-       /* Shared interrupts and IRQ off? */
-       if (priv->read_reg(priv, SJA1000_IER) == IRQ_OFF)
-               return IRQ_NONE;
-
        if (priv->pre_irq)
                priv->pre_irq(priv);
 
+       /* Shared interrupts and IRQ off? */
+       if (priv->read_reg(priv, SJA1000_IER) == IRQ_OFF)
+               goto out;
+
        while ((isrc = priv->read_reg(priv, SJA1000_IR)) &&
               (n < SJA1000_MAX_IRQ)) {
-               n++;
+
                status = priv->read_reg(priv, SJA1000_SR);
                /* check for absent controller due to hw unplug */
                if (status == 0xFF && sja1000_is_absent(priv))
-                       return IRQ_NONE;
+                       goto out;
 
                if (isrc & IRQ_WUI)
                        netdev_warn(dev, "wakeup interrupt\n");
@@ -535,7 +535,7 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
                                status = priv->read_reg(priv, SJA1000_SR);
                                /* check for absent controller */
                                if (status == 0xFF && sja1000_is_absent(priv))
-                                       return IRQ_NONE;
+                                       goto out;
                        }
                }
                if (isrc & (IRQ_DOI | IRQ_EI | IRQ_BEI | IRQ_EPI | IRQ_ALI)) {
@@ -543,8 +543,9 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
                        if (sja1000_err(dev, isrc, status))
                                break;
                }
+               n++;
        }
-
+out:
        if (priv->post_irq)
                priv->post_irq(priv);
 
index ad5272b348f07debb61c540a909da8fa0e1593f1..af24c3cf821582c56cefab0b592a3e5d3392f9bd 100644 (file)
@@ -693,7 +693,7 @@ DEFINE_WINDOW_IO(16)
 DEFINE_WINDOW_IO(32)
 
 #ifdef CONFIG_PCI
-#define DEVICE_PCI(dev) (((dev)->bus == &pci_bus_type) ? to_pci_dev((dev)) : NULL)
+#define DEVICE_PCI(dev) ((dev_is_pci(dev)) ? to_pci_dev((dev)) : NULL)
 #else
 #define DEVICE_PCI(dev) NULL
 #endif
index 2923c51bb351c38e2cc7d728056bdcb6f5c25a97..3e2f2c2e7b5848770502fedf05bf34b1e991be48 100644 (file)
@@ -21,12 +21,6 @@ struct e8390_pkt_hdr {
   unsigned short count; /* header + packet length in bytes */
 };
 
-#ifdef notdef
-extern int ei_debug;
-#else
-#define ei_debug 1
-#endif
-
 #ifdef CONFIG_NET_POLL_CONTROLLER
 void ei_poll(struct net_device *dev);
 void eip_poll(struct net_device *dev);
@@ -99,6 +93,7 @@ struct ei_device {
        u32 *reg_offset;                /* Register mapping table */
        spinlock_t page_lock;           /* Page register locks */
        unsigned long priv;             /* Private field to store bus IDs etc. */
+       u32 msg_enable;                 /* debug message level */
 #ifdef AX88796_PLATFORM
        unsigned char rxcr_base;        /* default value for RXCR */
 #endif
index 912ed7a5f33af5da3e3718cb9d2972be2d4c81d8..811fa5d5c6971c0a71f55d12e420fb38691bb9f7 100644 (file)
@@ -116,9 +116,15 @@ static const char version[] =
 
 static int apne_owned; /* signal if card already owned */
 
+static u32 apne_msg_enable;
+module_param_named(msg_enable, apne_msg_enable, uint, (S_IRUSR|S_IRGRP|S_IROTH));
+MODULE_PARM_DESC(msg_enable, "Debug message level (see linux/netdevice.h for bitmap)");
+
 struct net_device * __init apne_probe(int unit)
 {
        struct net_device *dev;
+       struct ei_device *ei_local;
+
 #ifndef MANUAL_CONFIG
        char tuple[8];
 #endif
@@ -133,11 +139,11 @@ struct net_device * __init apne_probe(int unit)
        if ( !(AMIGAHW_PRESENT(PCMCIA)) )
                return ERR_PTR(-ENODEV);
 
-       printk("Looking for PCMCIA ethernet card : ");
+       pr_info("Looking for PCMCIA ethernet card : ");
 
        /* check if a card is inserted */
        if (!(PCMCIA_INSERTED)) {
-               printk("NO PCMCIA card inserted\n");
+               pr_cont("NO PCMCIA card inserted\n");
                return ERR_PTR(-ENODEV);
        }
 
@@ -148,6 +154,8 @@ struct net_device * __init apne_probe(int unit)
                sprintf(dev->name, "eth%d", unit);
                netdev_boot_setup_check(dev);
        }
+       ei_local = netdev_priv(dev);
+       ei_local->msg_enable = apne_msg_enable;
 
        /* disable pcmcia irq for readtuple */
        pcmcia_disable_irq();
@@ -155,14 +163,14 @@ struct net_device * __init apne_probe(int unit)
 #ifndef MANUAL_CONFIG
        if ((pcmcia_copy_tuple(CISTPL_FUNCID, tuple, 8) < 3) ||
                (tuple[2] != CISTPL_FUNCID_NETWORK)) {
-               printk("not an ethernet card\n");
+               pr_cont("not an ethernet card\n");
                /* XXX: shouldn't we re-enable irq here? */
                free_netdev(dev);
                return ERR_PTR(-ENODEV);
        }
 #endif
 
-       printk("ethernet PCMCIA card inserted\n");
+       pr_cont("ethernet PCMCIA card inserted\n");
 
        if (!init_pcmcia()) {
                /* XXX: shouldn't we re-enable irq here? */
@@ -204,11 +212,12 @@ static int __init apne_probe1(struct net_device *dev, int ioaddr)
     int neX000, ctron;
 #endif
     static unsigned version_printed;
+    struct ei_device *ei_local = netdev_priv(dev);
 
-    if (ei_debug  &&  version_printed++ == 0)
-       printk(version);
+    if ((apne_msg_enable & NETIF_MSG_DRV) && (version_printed++ == 0))
+               netdev_info(dev, version);
 
-    printk("PCMCIA NE*000 ethercard probe");
+    netdev_info(dev, "PCMCIA NE*000 ethercard probe");
 
     /* Reset card. Who knows what dain-bramaged state it was left in. */
     {  unsigned long reset_start_time = jiffies;
@@ -217,7 +226,7 @@ static int __init apne_probe1(struct net_device *dev, int ioaddr)
 
        while ((inb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0)
                if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
-                       printk(" not found (no reset ack).\n");
+                       pr_cont(" not found (no reset ack).\n");
                        return -ENODEV;
                }
 
@@ -288,7 +297,7 @@ static int __init apne_probe1(struct net_device *dev, int ioaddr)
        start_page = 0x01;
        stop_page = (wordlength == 2) ? 0x40 : 0x20;
     } else {
-       printk(" not found.\n");
+       pr_cont(" not found.\n");
        return -ENXIO;
 
     }
@@ -320,9 +329,9 @@ static int __init apne_probe1(struct net_device *dev, int ioaddr)
     for (i = 0; i < ETH_ALEN; i++)
        dev->dev_addr[i] = SA_prom[i];
 
-    printk(" %pM\n", dev->dev_addr);
+    pr_cont(" %pM\n", dev->dev_addr);
 
-    printk("%s: %s found.\n", dev->name, name);
+    netdev_info(dev, "%s found.\n", name);
 
     ei_status.name = name;
     ei_status.tx_start_page = start_page;
@@ -352,10 +361,11 @@ static void
 apne_reset_8390(struct net_device *dev)
 {
     unsigned long reset_start_time = jiffies;
+    struct ei_device *ei_local = netdev_priv(dev);
 
     init_pcmcia();
 
-    if (ei_debug > 1) printk("resetting the 8390 t=%ld...", jiffies);
+    netif_dbg(ei_local, hw, dev, "resetting the 8390 t=%ld...\n", jiffies);
 
     outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
 
@@ -365,8 +375,8 @@ apne_reset_8390(struct net_device *dev)
     /* This check _should_not_ be necessary, omit eventually. */
     while ((inb(NE_BASE+NE_EN0_ISR) & ENISR_RESET) == 0)
        if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
-           printk("%s: ne_reset_8390() did not complete.\n", dev->name);
-           break;
+               netdev_err(dev, "ne_reset_8390() did not complete.\n");
+               break;
        }
     outb(ENISR_RESET, NE_BASE + NE_EN0_ISR);   /* Ack intr. */
 }
@@ -386,9 +396,9 @@ apne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_pa
 
     /* This *shouldn't* happen. If it does, it's the last thing you'll see */
     if (ei_status.dmaing) {
-       printk("%s: DMAing conflict in ne_get_8390_hdr "
-          "[DMAstat:%d][irqlock:%d][intr:%d].\n",
-          dev->name, ei_status.dmaing, ei_status.irqlock, dev->irq);
+       netdev_err(dev, "DMAing conflict in ne_get_8390_hdr "
+                  "[DMAstat:%d][irqlock:%d][intr:%d].\n",
+                  ei_status.dmaing, ei_status.irqlock, dev->irq);
        return;
     }
 
@@ -433,9 +443,9 @@ apne_block_input(struct net_device *dev, int count, struct sk_buff *skb, int rin
 
     /* This *shouldn't* happen. If it does, it's the last thing you'll see */
     if (ei_status.dmaing) {
-       printk("%s: DMAing conflict in ne_block_input "
-          "[DMAstat:%d][irqlock:%d][intr:%d].\n",
-          dev->name, ei_status.dmaing, ei_status.irqlock, dev->irq);
+               netdev_err(dev, "DMAing conflict in ne_block_input "
+                          "[DMAstat:%d][irqlock:%d][intr:%d].\n",
+                          ei_status.dmaing, ei_status.irqlock, dev->irq);
        return;
     }
     ei_status.dmaing |= 0x01;
@@ -481,9 +491,9 @@ apne_block_output(struct net_device *dev, int count,
 
     /* This *shouldn't* happen. If it does, it's the last thing you'll see */
     if (ei_status.dmaing) {
-       printk("%s: DMAing conflict in ne_block_output."
-          "[DMAstat:%d][irqlock:%d][intr:%d]\n",
-          dev->name, ei_status.dmaing, ei_status.irqlock, dev->irq);
+               netdev_err(dev, "DMAing conflict in ne_block_output."
+                          "[DMAstat:%d][irqlock:%d][intr:%d]\n",
+                          ei_status.dmaing, ei_status.irqlock, dev->irq);
        return;
     }
     ei_status.dmaing |= 0x01;
@@ -513,7 +523,7 @@ apne_block_output(struct net_device *dev, int count,
 
     while ((inb(NE_BASE + NE_EN0_ISR) & ENISR_RDC) == 0)
        if (time_after(jiffies, dma_start + 2*HZ/100)) {        /* 20ms */
-               printk("%s: timeout waiting for Tx RDC.\n", dev->name);
+               netdev_warn(dev, "timeout waiting for Tx RDC.\n");
                apne_reset_8390(dev);
                NS8390_init(dev,1);
                break;
@@ -536,8 +546,8 @@ static irqreturn_t apne_interrupt(int irq, void *dev_id)
         pcmcia_ack_int(pcmcia_intreq);
         return IRQ_NONE;
     }
-    if (ei_debug > 3)
-        printk("pcmcia intreq = %x\n", pcmcia_intreq);
+    if (apne_msg_enable & NETIF_MSG_INTR)
+       pr_debug("pcmcia intreq = %x\n", pcmcia_intreq);
     pcmcia_disable_irq();                      /* to get rid of the sti() within ei_interrupt */
     ei_interrupt(irq, dev_id);
     pcmcia_ack_int(pcmcia_get_intreq());
index 36fa577970bbae8741254519c0450d497a286d7e..8ed5b34d75530bceb558ca6bece93f302a3a8541 100644 (file)
@@ -78,6 +78,8 @@ static unsigned char version[] = "ax88796.c: Copyright 2005,2007 Simtec Electron
 
 #define AX_GPOC_PPDSET BIT(6)
 
+static u32 ax_msg_enable;
+
 /* device private data */
 
 struct ax_device {
@@ -147,8 +149,7 @@ static void ax_reset_8390(struct net_device *dev)
        unsigned long reset_start_time = jiffies;
        void __iomem *addr = (void __iomem *)dev->base_addr;
 
-       if (ei_debug > 1)
-               netdev_dbg(dev, "resetting the 8390 t=%ld\n", jiffies);
+       netif_dbg(ei_local, hw, dev, "resetting the 8390 t=%ld...\n", jiffies);
 
        ei_outb(ei_inb(addr + NE_RESET), addr + NE_RESET);
 
@@ -496,12 +497,28 @@ static int ax_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
        return phy_ethtool_sset(phy_dev, cmd);
 }
 
+static u32 ax_get_msglevel(struct net_device *dev)
+{
+       struct ei_device *ei_local = netdev_priv(dev);
+
+       return ei_local->msg_enable;
+}
+
+static void ax_set_msglevel(struct net_device *dev, u32 v)
+{
+       struct ei_device *ei_local = netdev_priv(dev);
+
+       ei_local->msg_enable = v;
+}
+
 static const struct ethtool_ops ax_ethtool_ops = {
        .get_drvinfo            = ax_get_drvinfo,
        .get_settings           = ax_get_settings,
        .set_settings           = ax_set_settings,
        .get_link               = ethtool_op_get_link,
        .get_ts_info            = ethtool_op_get_ts_info,
+       .get_msglevel           = ax_get_msglevel,
+       .set_msglevel           = ax_set_msglevel,
 };
 
 #ifdef CONFIG_AX88796_93CX6
@@ -763,6 +780,7 @@ static int ax_init_dev(struct net_device *dev)
        ei_local->block_output = &ax_block_output;
        ei_local->get_8390_hdr = &ax_get_8390_hdr;
        ei_local->priv = 0;
+       ei_local->msg_enable = ax_msg_enable;
 
        dev->netdev_ops = &ax_netdev_ops;
        dev->ethtool_ops = &ax_ethtool_ops;
index d801c1410fb04186316d46c3ae90afef2e3b3149..5698a4c85d8ef43afc68415897098381277717c1 100644 (file)
@@ -105,6 +105,7 @@ static void AX88190_init(struct net_device *dev, int startp);
 static int ax_open(struct net_device *dev);
 static int ax_close(struct net_device *dev);
 static irqreturn_t ax_interrupt(int irq, void *dev_id);
+static u32 axnet_msg_enable;
 
 /*====================================================================*/
 
@@ -152,6 +153,7 @@ static int axnet_probe(struct pcmcia_device *link)
        return -ENOMEM;
 
     ei_local = netdev_priv(dev);
+    ei_local->msg_enable = axnet_msg_enable;
     spin_lock_init(&ei_local->page_lock);
 
     info = PRIV(dev);
@@ -650,11 +652,12 @@ static void block_input(struct net_device *dev, int count,
                        struct sk_buff *skb, int ring_offset)
 {
     unsigned int nic_base = dev->base_addr;
+    struct ei_device *ei_local = netdev_priv(dev);
     int xfer_count = count;
     char *buf = skb->data;
 
-    if ((ei_debug > 4) && (count != 4))
-           pr_debug("%s: [bi=%d]\n", dev->name, count+4);
+    if ((netif_msg_rx_status(ei_local)) && (count != 4))
+       netdev_dbg(dev, "[bi=%d]\n", count+4);
     outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
     outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
     outb_p(E8390_RREAD+E8390_START, nic_base + AXNET_CMD);
@@ -810,11 +813,6 @@ module_pcmcia_driver(axnet_cs_driver);
 #define ei_block_input (ei_local->block_input)
 #define ei_get_8390_hdr (ei_local->get_8390_hdr)
 
-/* use 0 for production, 1 for verification, >2 for debug */
-#ifndef ei_debug
-int ei_debug = 1;
-#endif
-
 /* Index to functions. */
 static void ei_tx_intr(struct net_device *dev);
 static void ei_tx_err(struct net_device *dev);
@@ -925,11 +923,10 @@ static void axnet_tx_timeout(struct net_device *dev)
        isr = inb(e8390_base+EN0_ISR);
        spin_unlock_irqrestore(&ei_local->page_lock, flags);
 
-       netdev_printk(KERN_DEBUG, dev,
-                     "Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n",
-                     (txsr & ENTSR_ABT) ? "excess collisions." :
-                     (isr) ? "lost interrupt?" : "cable problem?",
-                     txsr, isr, tickssofar);
+       netdev_dbg(dev, "Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n",
+                  (txsr & ENTSR_ABT) ? "excess collisions." :
+                  (isr) ? "lost interrupt?" : "cable problem?",
+                  txsr, isr, tickssofar);
 
        if (!isr && !dev->stats.tx_packets) 
        {
@@ -998,29 +995,30 @@ static netdev_tx_t axnet_start_xmit(struct sk_buff *skb,
        {
                output_page = ei_local->tx_start_page;
                ei_local->tx1 = send_length;
-               if (ei_debug  &&  ei_local->tx2 > 0)
-                       netdev_printk(KERN_DEBUG, dev,
-                                     "idle transmitter tx2=%d, lasttx=%d, txing=%d\n",
-                                     ei_local->tx2, ei_local->lasttx,
-                                     ei_local->txing);
+               if ((netif_msg_tx_queued(ei_local)) &&
+                   ei_local->tx2 > 0)
+                       netdev_dbg(dev,
+                                  "idle transmitter tx2=%d, lasttx=%d, txing=%d\n",
+                                  ei_local->tx2, ei_local->lasttx,
+                                  ei_local->txing);
        }
        else if (ei_local->tx2 == 0) 
        {
                output_page = ei_local->tx_start_page + TX_PAGES/2;
                ei_local->tx2 = send_length;
-               if (ei_debug  &&  ei_local->tx1 > 0)
-                       netdev_printk(KERN_DEBUG, dev,
-                                     "idle transmitter, tx1=%d, lasttx=%d, txing=%d\n",
-                                     ei_local->tx1, ei_local->lasttx,
-                                     ei_local->txing);
+               if ((netif_msg_tx_queued(ei_local)) &&
+                   ei_local->tx1 > 0)
+                       netdev_dbg(dev,
+                                  "idle transmitter, tx1=%d, lasttx=%d, txing=%d\n",
+                                  ei_local->tx1, ei_local->lasttx,
+                                  ei_local->txing);
        }
        else
        {       /* We should never get here. */
-               if (ei_debug)
-                       netdev_printk(KERN_DEBUG, dev,
-                                     "No Tx buffers free! tx1=%d tx2=%d last=%d\n",
-                                     ei_local->tx1, ei_local->tx2,
-                                     ei_local->lasttx);
+               netif_dbg(ei_local, tx_err, dev,
+                         "No Tx buffers free! tx1=%d tx2=%d last=%d\n",
+                         ei_local->tx1, ei_local->tx2,
+                         ei_local->lasttx);
                ei_local->irqlock = 0;
                netif_stop_queue(dev);
                outb_p(ENISR_ALL, e8390_base + EN0_IMR);
@@ -1124,10 +1122,9 @@ static irqreturn_t ax_interrupt(int irq, void *dev_id)
                spin_unlock_irqrestore(&ei_local->page_lock, flags);
                return IRQ_NONE;
        }
-    
-       if (ei_debug > 3)
-               netdev_printk(KERN_DEBUG, dev, "interrupt(isr=%#2.2x)\n",
-                             inb_p(e8390_base + EN0_ISR));
+
+       netif_dbg(ei_local, intr, dev, "interrupt(isr=%#2.2x)\n",
+                 inb_p(e8390_base + EN0_ISR));
 
        outb_p(0x00, e8390_base + EN0_ISR);
        ei_local->irqlock = 1;
@@ -1137,9 +1134,8 @@ static irqreturn_t ax_interrupt(int irq, void *dev_id)
               ++nr_serviced < MAX_SERVICE)
        {
                if (!netif_running(dev) || (interrupts == 0xff)) {
-                       if (ei_debug > 1)
-                               netdev_warn(dev,
-                                           "interrupt from stopped card\n");
+                       netif_warn(ei_local, intr, dev,
+                                  "interrupt from stopped card\n");
                        outb_p(interrupts, e8390_base + EN0_ISR);
                        interrupts = 0;
                        break;
@@ -1175,14 +1171,15 @@ static irqreturn_t ax_interrupt(int irq, void *dev_id)
                }
        }
     
-       if (interrupts && ei_debug > 3) 
+       if (interrupts && (netif_msg_intr(ei_local)))
        {
                handled = 1;
                if (nr_serviced >= MAX_SERVICE) 
                {
                        /* 0xFF is valid for a card removal */
-                       if(interrupts!=0xFF)
-                               netdev_warn(dev, "Too much work at interrupt, status %#2.2x\n",
+                       if (interrupts != 0xFF)
+                               netdev_warn(dev,
+                                           "Too much work at interrupt, status %#2.2x\n",
                                            interrupts);
                        outb_p(ENISR_ALL, e8390_base + EN0_ISR); /* Ack. most intrs. */
                } else {
@@ -1221,8 +1218,7 @@ static void ei_tx_err(struct net_device *dev)
        unsigned char tx_was_aborted = txsr & (ENTSR_ABT+ENTSR_FU);
 
 #ifdef VERBOSE_ERROR_DUMP
-       netdev_printk(KERN_DEBUG, dev,
-                     "transmitter error (%#2x):", txsr);
+       netdev_dbg(dev, "transmitter error (%#2x):", txsr);
        if (txsr & ENTSR_ABT)
                pr_cont(" excess-collisions");
        if (txsr & ENTSR_ND)
@@ -1287,9 +1283,9 @@ static void ei_tx_intr(struct net_device *dev)
        else if (ei_local->tx2 < 0) 
        {
                if (ei_local->lasttx != 2  &&  ei_local->lasttx != -2)
-                       netdev_info(dev, "%s: bogus last_tx_buffer %d, tx2=%d\n",
-                                   ei_local->name, ei_local->lasttx,
-                                   ei_local->tx2);
+                       netdev_err(dev, "%s: bogus last_tx_buffer %d, tx2=%d\n",
+                                  ei_local->name, ei_local->lasttx,
+                                  ei_local->tx2);
                ei_local->tx2 = 0;
                if (ei_local->tx1 > 0) 
                {
@@ -1366,9 +1362,11 @@ static void ei_receive(struct net_device *dev)
                   Keep quiet if it looks like a card removal. One problem here
                   is that some clones crash in roughly the same way.
                 */
-               if (ei_debug > 0  &&  this_frame != ei_local->current_page && (this_frame!=0x0 || rxing_page!=0xFF))
-                   netdev_err(dev, "mismatched read page pointers %2x vs %2x\n",
-                              this_frame, ei_local->current_page);
+               if ((netif_msg_rx_err(ei_local)) &&
+                   this_frame != ei_local->current_page &&
+                   (this_frame != 0x0 || rxing_page != 0xFF))
+                       netdev_err(dev, "mismatched read page pointers %2x vs %2x\n",
+                                  this_frame, ei_local->current_page);
                
                if (this_frame == rxing_page)   /* Read all the frames? */
                        break;                          /* Done for now */
@@ -1383,11 +1381,10 @@ static void ei_receive(struct net_device *dev)
                
                if (pkt_len < 60  ||  pkt_len > 1518) 
                {
-                       if (ei_debug)
-                               netdev_printk(KERN_DEBUG, dev,
-                                             "bogus packet size: %d, status=%#2x nxpg=%#2x\n",
-                                             rx_frame.count, rx_frame.status,
-                                             rx_frame.next);
+                       netif_err(ei_local, rx_err, dev,
+                                 "bogus packet size: %d, status=%#2x nxpg=%#2x\n",
+                                 rx_frame.count, rx_frame.status,
+                                 rx_frame.next);
                        dev->stats.rx_errors++;
                        dev->stats.rx_length_errors++;
                }
@@ -1398,10 +1395,9 @@ static void ei_receive(struct net_device *dev)
                        skb = netdev_alloc_skb(dev, pkt_len + 2);
                        if (skb == NULL) 
                        {
-                               if (ei_debug > 1)
-                                       netdev_printk(KERN_DEBUG, dev,
-                                                     "Couldn't allocate a sk_buff of size %d\n",
-                                                     pkt_len);
+                               netif_err(ei_local, rx_err, dev,
+                                         "Couldn't allocate a sk_buff of size %d\n",
+                                         pkt_len);
                                dev->stats.rx_dropped++;
                                break;
                        }
@@ -1420,11 +1416,10 @@ static void ei_receive(struct net_device *dev)
                } 
                else 
                {
-                       if (ei_debug)
-                               netdev_printk(KERN_DEBUG, dev,
-                                             "bogus packet: status=%#2x nxpg=%#2x size=%d\n",
-                                             rx_frame.status, rx_frame.next,
-                                             rx_frame.count);
+                       netif_err(ei_local, rx_err, dev,
+                                 "bogus packet: status=%#2x nxpg=%#2x size=%d\n",
+                                 rx_frame.status, rx_frame.next,
+                                 rx_frame.count);
                        dev->stats.rx_errors++;
                        /* NB: The NIC counts CRC, frame and missed errors. */
                        if (pkt_stat & ENRSR_FO)
@@ -1461,6 +1456,7 @@ static void ei_rx_overrun(struct net_device *dev)
        axnet_dev_t *info = PRIV(dev);
        long e8390_base = dev->base_addr;
        unsigned char was_txing, must_resend = 0;
+       struct ei_device *ei_local = netdev_priv(dev);
     
        /*
         * Record whether a Tx was in progress and then issue the
@@ -1468,9 +1464,8 @@ static void ei_rx_overrun(struct net_device *dev)
         */
        was_txing = inb_p(e8390_base+E8390_CMD) & E8390_TRANS;
        outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
-    
-       if (ei_debug > 1)
-               netdev_printk(KERN_DEBUG, dev, "Receiver overrun\n");
+
+       netif_dbg(ei_local, rx_err, dev, "Receiver overrun\n");
        dev->stats.rx_over_errors++;
     
        /* 
index 78c6fb4b11437e2b187cb9e93a9e44ba71806692..b15e482a7c63c7249ff51e5a2a86755427918fcb 100644 (file)
@@ -56,9 +56,6 @@
 #define ei_inb_p(_p)    readb((void __iomem *)_p)
 #define ei_outb_p(_v,_p) writeb(_v,(void __iomem *)_p)
 
-#define NET_DEBUG  0
-#define DEBUG_INIT 2
-
 #define DRV_NAME       "etherh"
 #define DRV_VERSION    "1.11"
 
@@ -67,7 +64,7 @@ static char version[] __initdata =
 
 #include "lib8390.c"
 
-static unsigned int net_debug = NET_DEBUG;
+static u32 etherh_msg_enable;
 
 struct etherh_priv {
        void __iomem    *ioc_fast;
@@ -317,9 +314,9 @@ etherh_block_output (struct net_device *dev, int count, const unsigned char *buf
        void __iomem *dma_base, *addr;
 
        if (ei_local->dmaing) {
-               printk(KERN_ERR "%s: DMAing conflict in etherh_block_input: "
-                       " DMAstat %d irqlock %d\n", dev->name,
-                       ei_local->dmaing, ei_local->irqlock);
+               netdev_err(dev, "DMAing conflict in etherh_block_input: "
+                          " DMAstat %d irqlock %d\n",
+                          ei_local->dmaing, ei_local->irqlock);
                return;
        }
 
@@ -361,8 +358,7 @@ etherh_block_output (struct net_device *dev, int count, const unsigned char *buf
 
        while ((readb (addr + EN0_ISR) & ENISR_RDC) == 0)
                if (time_after(jiffies, dma_start + 2*HZ/100)) { /* 20ms */
-                       printk(KERN_ERR "%s: timeout waiting for TX RDC\n",
-                               dev->name);
+                       netdev_warn(dev, "timeout waiting for TX RDC\n");
                        etherh_reset (dev);
                        __NS8390_init (dev, 1);
                        break;
@@ -383,9 +379,9 @@ etherh_block_input (struct net_device *dev, int count, struct sk_buff *skb, int
        void __iomem *dma_base, *addr;
 
        if (ei_local->dmaing) {
-               printk(KERN_ERR "%s: DMAing conflict in etherh_block_input: "
-                       " DMAstat %d irqlock %d\n", dev->name,
-                       ei_local->dmaing, ei_local->irqlock);
+               netdev_err(dev, "DMAing conflict in etherh_block_input: "
+                          " DMAstat %d irqlock %d\n",
+                          ei_local->dmaing, ei_local->irqlock);
                return;
        }
 
@@ -423,9 +419,9 @@ etherh_get_header (struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_p
        void __iomem *dma_base, *addr;
 
        if (ei_local->dmaing) {
-               printk(KERN_ERR "%s: DMAing conflict in etherh_get_header: "
-                       " DMAstat %d irqlock %d\n", dev->name,
-                       ei_local->dmaing, ei_local->irqlock);
+               netdev_err(dev, "DMAing conflict in etherh_get_header: "
+                          " DMAstat %d irqlock %d\n",
+                          ei_local->dmaing, ei_local->irqlock);
                return;
        }
 
@@ -513,8 +509,8 @@ static void __init etherh_banner(void)
 {
        static int version_printed;
 
-       if (net_debug && version_printed++ == 0)
-               printk(KERN_INFO "%s", version);
+       if ((etherh_msg_enable & NETIF_MSG_DRV) && (version_printed++ == 0))
+               pr_info("%s", version);
 }
 
 /*
@@ -625,11 +621,27 @@ static int etherh_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
        return 0;
 }
 
+static u32 etherh_get_msglevel(struct net_device *dev)
+{
+       struct ei_device *ei_local = netdev_priv(dev);
+
+       return ei_local->msg_enable;
+}
+
+static void etherh_set_msglevel(struct net_device *dev, u32 v)
+{
+       struct ei_device *ei_local = netdev_priv(dev);
+
+       ei_local->msg_enable = v;
+}
+
 static const struct ethtool_ops etherh_ethtool_ops = {
        .get_settings   = etherh_get_settings,
        .set_settings   = etherh_set_settings,
        .get_drvinfo    = etherh_get_drvinfo,
        .get_ts_info    = ethtool_op_get_ts_info,
+       .get_msglevel   = etherh_get_msglevel,
+       .set_msglevel   = etherh_set_msglevel,
 };
 
 static const struct net_device_ops etherh_netdev_ops = {
@@ -746,6 +758,7 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
        ei_local->block_output  = etherh_block_output;
        ei_local->get_8390_hdr  = etherh_get_header;
        ei_local->interface_num = 0;
+       ei_local->msg_enable = etherh_msg_enable;
 
        etherh_reset(dev);
        __NS8390_init(dev, 0);
@@ -754,8 +767,8 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
        if (ret)
                goto free;
 
-       printk(KERN_INFO "%s: %s in slot %d, %pM\n",
-               dev->name, data->name, ec->slot_no, dev->dev_addr);
+       netdev_info(dev, "%s in slot %d, %pM\n",
+                   data->name, ec->slot_no, dev->dev_addr);
 
        ecard_set_drvdata(ec, dev);
 
index fb3dd4399cf36e24cd4a1fe809333d140c8419f2..0fe19d609c2ecbf0d84881f2f0960916eb4c010c 100644 (file)
@@ -66,6 +66,7 @@ static void hydra_block_input(struct net_device *dev, int count,
 static void hydra_block_output(struct net_device *dev, int count,
                               const unsigned char *buf, int start_page);
 static void hydra_remove_one(struct zorro_dev *z);
+static u32 hydra_msg_enable;
 
 static struct zorro_device_id hydra_zorro_tbl[] = {
     { ZORRO_PROD_HYDRA_SYSTEMS_AMIGANET },
@@ -113,12 +114,13 @@ static const struct net_device_ops hydra_netdev_ops = {
 static int hydra_init(struct zorro_dev *z)
 {
     struct net_device *dev;
-    unsigned long board = ZTWO_VADDR(z->resource.start);
+    unsigned long board = (unsigned long)ZTWO_VADDR(z->resource.start);
     unsigned long ioaddr = board+HYDRA_NIC_BASE;
     const char name[] = "NE2000";
     int start_page, stop_page;
     int j;
     int err;
+    struct ei_device *ei_local;
 
     static u32 hydra_offsets[16] = {
        0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
@@ -137,6 +139,8 @@ static int hydra_init(struct zorro_dev *z)
     start_page = NESM_START_PG;
     stop_page = NESM_STOP_PG;
 
+    ei_local = netdev_priv(dev);
+    ei_local->msg_enable = hydra_msg_enable;
     dev->base_addr = ioaddr;
     dev->irq = IRQ_AMIGA_PORTS;
 
@@ -187,15 +191,16 @@ static int hydra_open(struct net_device *dev)
 
 static int hydra_close(struct net_device *dev)
 {
-    if (ei_debug > 1)
-       printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name);
+    struct ei_device *ei_local = netdev_priv(dev);
+
+    netif_dbg(ei_local, ifdown, dev, "Shutting down ethercard.\n");
     __ei_close(dev);
     return 0;
 }
 
 static void hydra_reset_8390(struct net_device *dev)
 {
-    printk(KERN_INFO "Hydra hw reset not there\n");
+    netdev_info(dev, "Hydra hw reset not there\n");
 }
 
 static void hydra_get_8390_hdr(struct net_device *dev,
index b329f5c0d62b25203db832aa151dda371bcf4a1c..d2cd80444ade7b5e5a6bdfe1f5e5207f8c02d798 100644 (file)
 #define ei_block_input (ei_local->block_input)
 #define ei_get_8390_hdr (ei_local->get_8390_hdr)
 
-/* use 0 for production, 1 for verification, >2 for debug */
-#ifndef ei_debug
-int ei_debug = 1;
-#endif
-
 /* Index to functions. */
 static void ei_tx_intr(struct net_device *dev);
 static void ei_tx_err(struct net_device *dev);
@@ -116,6 +111,11 @@ static void NS8390_trigger_send(struct net_device *dev, unsigned int length,
 static void do_set_multicast_list(struct net_device *dev);
 static void __NS8390_init(struct net_device *dev, int startp);
 
+static unsigned version_printed;
+static u32 msg_enable;
+module_param(msg_enable, uint, (S_IRUSR|S_IRGRP|S_IROTH));
+MODULE_PARM_DESC(msg_enable, "Debug message level (see linux/netdevice.h for bitmap)");
+
 /*
  *     SMP and the 8390 setup.
  *
@@ -345,19 +345,23 @@ static netdev_tx_t __ei_start_xmit(struct sk_buff *skb,
        if (ei_local->tx1 == 0) {
                output_page = ei_local->tx_start_page;
                ei_local->tx1 = send_length;
-               if (ei_debug  &&  ei_local->tx2 > 0)
-                       netdev_dbg(dev, "idle transmitter tx2=%d, lasttx=%d, txing=%d\n",
+               if ((netif_msg_tx_queued(ei_local)) &&
+                   ei_local->tx2 > 0)
+                       netdev_dbg(dev,
+                                  "idle transmitter tx2=%d, lasttx=%d, txing=%d\n",
                                   ei_local->tx2, ei_local->lasttx, ei_local->txing);
        } else if (ei_local->tx2 == 0) {
                output_page = ei_local->tx_start_page + TX_PAGES/2;
                ei_local->tx2 = send_length;
-               if (ei_debug  &&  ei_local->tx1 > 0)
-                       netdev_dbg(dev, "idle transmitter, tx1=%d, lasttx=%d, txing=%d\n",
+               if ((netif_msg_tx_queued(ei_local)) &&
+                   ei_local->tx1 > 0)
+                       netdev_dbg(dev,
+                                  "idle transmitter, tx1=%d, lasttx=%d, txing=%d\n",
                                   ei_local->tx1, ei_local->lasttx, ei_local->txing);
        } else {                        /* We should never get here. */
-               if (ei_debug)
-                       netdev_dbg(dev, "No Tx buffers free! tx1=%d tx2=%d last=%d\n",
-                                  ei_local->tx1, ei_local->tx2, ei_local->lasttx);
+               netif_dbg(ei_local, tx_err, dev,
+                         "No Tx buffers free! tx1=%d tx2=%d last=%d\n",
+                         ei_local->tx1, ei_local->tx2, ei_local->lasttx);
                ei_local->irqlock = 0;
                netif_stop_queue(dev);
                ei_outb_p(ENISR_ALL, e8390_base + EN0_IMR);
@@ -388,7 +392,7 @@ static netdev_tx_t __ei_start_xmit(struct sk_buff *skb,
        } else
                ei_local->txqueue++;
 
-       if (ei_local->tx1  &&  ei_local->tx2)
+       if (ei_local->tx1 && ei_local->tx2)
                netif_stop_queue(dev);
        else
                netif_start_queue(dev);
@@ -445,9 +449,8 @@ static irqreturn_t __ei_interrupt(int irq, void *dev_id)
 
        /* Change to page 0 and read the intr status reg. */
        ei_outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD);
-       if (ei_debug > 3)
-               netdev_dbg(dev, "interrupt(isr=%#2.2x)\n",
-                          ei_inb_p(e8390_base + EN0_ISR));
+       netif_dbg(ei_local, intr, dev, "interrupt(isr=%#2.2x)\n",
+                 ei_inb_p(e8390_base + EN0_ISR));
 
        /* !!Assumption!! -- we stay in page 0.  Don't break this. */
        while ((interrupts = ei_inb_p(e8390_base + EN0_ISR)) != 0 &&
@@ -485,7 +488,7 @@ static irqreturn_t __ei_interrupt(int irq, void *dev_id)
                ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD);
        }
 
-       if (interrupts && ei_debug) {
+       if (interrupts && (netif_msg_intr(ei_local))) {
                ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD);
                if (nr_serviced >= MAX_SERVICE) {
                        /* 0xFF is valid for a card removal */
@@ -676,10 +679,11 @@ static void ei_receive(struct net_device *dev)
                   Keep quiet if it looks like a card removal. One problem here
                   is that some clones crash in roughly the same way.
                 */
-               if (ei_debug > 0 &&
+               if ((netif_msg_rx_status(ei_local)) &&
                    this_frame != ei_local->current_page &&
                    (this_frame != 0x0 || rxing_page != 0xFF))
-                       netdev_err(dev, "mismatched read page pointers %2x vs %2x\n",
+                       netdev_err(dev,
+                                  "mismatched read page pointers %2x vs %2x\n",
                                   this_frame, ei_local->current_page);
 
                if (this_frame == rxing_page)   /* Read all the frames? */
@@ -707,10 +711,10 @@ static void ei_receive(struct net_device *dev)
                }
 
                if (pkt_len < 60  ||  pkt_len > 1518) {
-                       if (ei_debug)
-                               netdev_dbg(dev, "bogus packet size: %d, status=%#2x nxpg=%#2x\n",
-                                          rx_frame.count, rx_frame.status,
-                                          rx_frame.next);
+                       netif_dbg(ei_local, rx_status, dev,
+                                 "bogus packet size: %d, status=%#2x nxpg=%#2x\n",
+                                 rx_frame.count, rx_frame.status,
+                                 rx_frame.next);
                        dev->stats.rx_errors++;
                        dev->stats.rx_length_errors++;
                } else if ((pkt_stat & 0x0F) == ENRSR_RXOK) {
@@ -718,9 +722,9 @@ static void ei_receive(struct net_device *dev)
 
                        skb = netdev_alloc_skb(dev, pkt_len + 2);
                        if (skb == NULL) {
-                               if (ei_debug > 1)
-                                       netdev_dbg(dev, "Couldn't allocate a sk_buff of size %d\n",
-                                                  pkt_len);
+                               netif_err(ei_local, rx_err, dev,
+                                         "Couldn't allocate a sk_buff of size %d\n",
+                                         pkt_len);
                                dev->stats.rx_dropped++;
                                break;
                        } else {
@@ -736,10 +740,10 @@ static void ei_receive(struct net_device *dev)
                                        dev->stats.multicast++;
                        }
                } else {
-                       if (ei_debug)
-                               netdev_dbg(dev, "bogus packet: status=%#2x nxpg=%#2x size=%d\n",
-                                          rx_frame.status, rx_frame.next,
-                                          rx_frame.count);
+                       netif_err(ei_local, rx_err, dev,
+                                 "bogus packet: status=%#2x nxpg=%#2x size=%d\n",
+                                 rx_frame.status, rx_frame.next,
+                                 rx_frame.count);
                        dev->stats.rx_errors++;
                        /* NB: The NIC counts CRC, frame and missed errors. */
                        if (pkt_stat & ENRSR_FO)
@@ -789,8 +793,7 @@ static void ei_rx_overrun(struct net_device *dev)
        was_txing = ei_inb_p(e8390_base+E8390_CMD) & E8390_TRANS;
        ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
 
-       if (ei_debug > 1)
-               netdev_dbg(dev, "Receiver overrun\n");
+       netif_dbg(ei_local, rx_err, dev, "Receiver overrun\n");
        dev->stats.rx_over_errors++;
 
        /*
@@ -965,8 +968,9 @@ static void __ei_set_multicast_list(struct net_device *dev)
 static void ethdev_setup(struct net_device *dev)
 {
        struct ei_device *ei_local = netdev_priv(dev);
-       if (ei_debug > 1)
-               printk(version);
+
+       if ((msg_enable & NETIF_MSG_DRV) && (version_printed++ == 0))
+               pr_info("%s", version);
 
        ether_setup(dev);
 
@@ -1035,9 +1039,10 @@ static void __NS8390_init(struct net_device *dev, int startp)
        ei_outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, e8390_base+E8390_CMD); /* 0x61 */
        for (i = 0; i < 6; i++) {
                ei_outb_p(dev->dev_addr[i], e8390_base + EN1_PHYS_SHIFT(i));
-               if (ei_debug > 1 &&
+               if ((netif_msg_probe(ei_local)) &&
                    ei_inb_p(e8390_base + EN1_PHYS_SHIFT(i)) != dev->dev_addr[i])
-                       netdev_err(dev, "Hw. address read/write mismap %d\n", i);
+                       netdev_err(dev,
+                                  "Hw. address read/write mismap %d\n", i);
        }
 
        ei_outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG);
index 88ccc8b14f0a4b09aa8097a5f8a5dbcbacb128ba..90e825e8abfee9aeb4d743fab9be26ca7dd109ec 100644 (file)
@@ -167,6 +167,7 @@ static void slow_sane_block_output(struct net_device *dev, int count,
                                   const unsigned char *buf, int start_page);
 static void word_memcpy_tocard(unsigned long tp, const void *fp, int count);
 static void word_memcpy_fromcard(void *tp, unsigned long fp, int count);
+static u32 mac8390_msg_enable;
 
 static enum mac8390_type __init mac8390_ident(struct nubus_dev *dev)
 {
@@ -402,6 +403,7 @@ struct net_device * __init mac8390_probe(int unit)
        struct net_device *dev;
        struct nubus_dev *ndev = NULL;
        int err = -ENODEV;
+       struct ei_device *ei_local;
 
        static unsigned int slots;
 
@@ -440,6 +442,10 @@ struct net_device * __init mac8390_probe(int unit)
 
        if (!ndev)
                goto out;
+
+        ei_local = netdev_priv(dev);
+        ei_local->msg_enable = mac8390_msg_enable;
+
        err = register_netdev(dev);
        if (err)
                goto out;
@@ -660,19 +666,22 @@ static int mac8390_close(struct net_device *dev)
 
 static void mac8390_no_reset(struct net_device *dev)
 {
+       struct ei_device *ei_local = netdev_priv(dev);
+
        ei_status.txing = 0;
-       if (ei_debug > 1)
-               pr_info("reset not supported\n");
+       netif_info(ei_local, hw, dev, "reset not supported\n");
 }
 
 static void interlan_reset(struct net_device *dev)
 {
        unsigned char *target = nubus_slot_addr(IRQ2SLOT(dev->irq));
-       if (ei_debug > 1)
-               pr_info("Need to reset the NS8390 t=%lu...", jiffies);
+       struct ei_device *ei_local = netdev_priv(dev);
+
+       netif_info(ei_local, hw, dev, "Need to reset the NS8390 t=%lu...",
+                  jiffies);
        ei_status.txing = 0;
        target[0xC0000] = 0;
-       if (ei_debug > 1)
+       if (netif_msg_hw(ei_local))
                pr_cont("reset complete\n");
 }
 
index 230efd6fa5d5517e4227eb49933be0badc449735..df0ffca91c1ca65806670b5f4a5a1fb644c24f9c 100644 (file)
@@ -39,6 +39,7 @@ static const char version[] =
 
 #define NESM_START_PG  0x40    /* First page of TX buffer */
 #define NESM_STOP_PG   0x80    /* Last page +1 of RX ring */
+static u32 mcf8390_msg_enable;
 
 #ifdef NE2000_ODDOFFSET
 /*
@@ -153,9 +154,9 @@ static void mcf8390_reset_8390(struct net_device *dev)
 {
        unsigned long reset_start_time = jiffies;
        u32 addr = dev->base_addr;
+       struct ei_device *ei_local = netdev_priv(dev);
 
-       if (ei_debug > 1)
-               netdev_dbg(dev, "resetting the 8390 t=%ld...\n", jiffies);
+       netif_dbg(ei_local, hw, dev, "resetting the 8390 t=%ld...\n", jiffies);
 
        ei_outb(ei_inb(addr + NE_RESET), addr + NE_RESET);
 
@@ -288,7 +289,7 @@ static void mcf8390_block_output(struct net_device *dev, int count,
        dma_start = jiffies;
        while ((ei_inb(addr + NE_EN0_ISR) & ENISR_RDC) == 0) {
                if (time_after(jiffies, dma_start + 2 * HZ / 100)) { /* 20ms */
-                       netdev_err(dev, "timeout waiting for Tx RDC\n");
+                       netdev_warn(dev, "timeout waiting for Tx RDC\n");
                        mcf8390_reset_8390(dev);
                        __NS8390_init(dev, 1);
                        break;
@@ -437,6 +438,7 @@ static int mcf8390_probe(struct platform_device *pdev)
        SET_NETDEV_DEV(dev, &pdev->dev);
        platform_set_drvdata(pdev, dev);
        ei_local = netdev_priv(dev);
+       ei_local->msg_enable = mcf8390_msg_enable;
 
        dev->irq = irq->start;
        dev->base_addr = mem->start;
index b2e8405137357f2cef6303c1a9a16d96b1abb23d..58eaa8f34942cac2dfe416e0d6086b7103afb83c 100644 (file)
@@ -71,14 +71,17 @@ static struct platform_device *pdev_ne[MAX_NE_CARDS];
 static int io[MAX_NE_CARDS];
 static int irq[MAX_NE_CARDS];
 static int bad[MAX_NE_CARDS];
+static u32 ne_msg_enable;
 
 #ifdef MODULE
 module_param_array(io, int, NULL, 0);
 module_param_array(irq, int, NULL, 0);
 module_param_array(bad, int, NULL, 0);
+module_param_named(msg_enable, ne_msg_enable, uint, (S_IRUSR|S_IRGRP|S_IROTH));
 MODULE_PARM_DESC(io, "I/O base address(es),required");
 MODULE_PARM_DESC(irq, "IRQ number(s)");
 MODULE_PARM_DESC(bad, "Accept card(s) with bad signatures");
+MODULE_PARM_DESC(msg_enable, "Debug message level (see linux/netdevice.h for bitmap)");
 MODULE_DESCRIPTION("NE1000/NE2000 ISA/PnP Ethernet driver");
 MODULE_LICENSE("GPL");
 #endif /* MODULE */
@@ -214,8 +217,8 @@ static int __init do_ne_probe(struct net_device *dev)
        if (base_addr > 0x1ff) {        /* Check a single specified location. */
                int ret = ne_probe1(dev, base_addr);
                if (ret)
-                       printk(KERN_WARNING "ne.c: No NE*000 card found at "
-                               "i/o = %#lx\n", base_addr);
+                       netdev_warn(dev, "ne.c: No NE*000 card found at "
+                                   "i/o = %#lx\n", base_addr);
                return ret;
        }
        else if (base_addr != 0)        /* Don't probe at all. */
@@ -264,11 +267,14 @@ static int __init ne_probe_isapnp(struct net_device *dev)
                        /* found it */
                        dev->base_addr = pnp_port_start(idev, 0);
                        dev->irq = pnp_irq(idev, 0);
-                       printk(KERN_INFO "ne.c: ISAPnP reports %s at i/o %#lx, irq %d.\n",
-                               (char *) isapnp_clone_list[i].driver_data,
-                               dev->base_addr, dev->irq);
+                       netdev_info(dev,
+                                   "ne.c: ISAPnP reports %s at i/o %#lx, irq %d.\n",
+                                   (char *) isapnp_clone_list[i].driver_data,
+                                   dev->base_addr, dev->irq);
                        if (ne_probe1(dev, dev->base_addr) != 0) {      /* Shouldn't happen. */
-                               printk(KERN_ERR "ne.c: Probe of ISAPnP card at %#lx failed.\n", dev->base_addr);
+                               netdev_err(dev,
+                                          "ne.c: Probe of ISAPnP card at %#lx failed.\n",
+                                          dev->base_addr);
                                pnp_device_detach(idev);
                                return -ENXIO;
                        }
@@ -293,6 +299,7 @@ static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr)
        int neX000, ctron, copam, bad_card;
        int reg0, ret;
        static unsigned version_printed;
+       struct ei_device *ei_local = netdev_priv(dev);
 
        if (!request_region(ioaddr, NE_IO_EXTENT, DRV_NAME))
                return -EBUSY;
@@ -319,10 +326,10 @@ static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr)
                }
        }
 
-       if (ei_debug  &&  version_printed++ == 0)
-               printk(KERN_INFO "%s%s", version1, version2);
+       if ((ne_msg_enable & NETIF_MSG_DRV) && (version_printed++ == 0))
+               netdev_info(dev, "%s%s", version1, version2);
 
-       printk(KERN_INFO "NE*000 ethercard probe at %#3lx:", ioaddr);
+       netdev_info(dev, "NE*000 ethercard probe at %#3lx:", ioaddr);
 
        /* A user with a poor card that fails to ack the reset, or that
           does not have a valid 0x57,0x57 signature can still use this
@@ -343,10 +350,10 @@ static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr)
                while ((inb_p(ioaddr + EN0_ISR) & ENISR_RESET) == 0)
                if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
                        if (bad_card) {
-                               printk(" (warning: no reset ack)");
+                               pr_cont(" (warning: no reset ack)");
                                break;
                        } else {
-                               printk(" not found (no reset ack).\n");
+                               pr_cont(" not found (no reset ack).\n");
                                ret = -ENODEV;
                                goto err_out;
                        }
@@ -454,13 +461,13 @@ static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr)
                }
                if (bad_clone_list[i].name8 == NULL)
                {
-                       printk(" not found (invalid signature %2.2x %2.2x).\n",
+                       pr_cont(" not found (invalid signature %2.2x %2.2x).\n",
                                SA_prom[14], SA_prom[15]);
                        ret = -ENXIO;
                        goto err_out;
                }
 #else
-               printk(" not found.\n");
+               pr_cont(" not found.\n");
                ret = -ENXIO;
                goto err_out;
 #endif
@@ -476,15 +483,15 @@ static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr)
                mdelay(10);             /* wait 10ms for interrupt to propagate */
                outb_p(0x00, ioaddr + EN0_IMR);                 /* Mask it again. */
                dev->irq = probe_irq_off(cookie);
-               if (ei_debug > 2)
-                       printk(" autoirq is %d\n", dev->irq);
+               if (netif_msg_probe(ei_local))
+                       pr_cont(" autoirq is %d", dev->irq);
        } else if (dev->irq == 2)
                /* Fixup for users that don't know that IRQ 2 is really IRQ 9,
                   or don't know which one to set. */
                dev->irq = 9;
 
        if (! dev->irq) {
-               printk(" failed to detect IRQ line.\n");
+               pr_cont(" failed to detect IRQ line.\n");
                ret = -EAGAIN;
                goto err_out;
        }
@@ -493,7 +500,7 @@ static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr)
           share and the board will usually be enabled. */
        ret = request_irq(dev->irq, eip_interrupt, 0, name, dev);
        if (ret) {
-               printk (" unable to get IRQ %d (errno=%d).\n", dev->irq, ret);
+               pr_cont(" unable to get IRQ %d (errno=%d).\n", dev->irq, ret);
                goto err_out;
        }
 
@@ -512,7 +519,7 @@ static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr)
        }
 #endif
 
-       printk("%pM\n", dev->dev_addr);
+       pr_cont("%pM\n", dev->dev_addr);
 
        ei_status.name = name;
        ei_status.tx_start_page = start_page;
@@ -536,11 +543,12 @@ static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr)
        dev->netdev_ops = &eip_netdev_ops;
        NS8390p_init(dev, 0);
 
+       ei_local->msg_enable = ne_msg_enable;
        ret = register_netdev(dev);
        if (ret)
                goto out_irq;
-       printk(KERN_INFO "%s: %s found at %#lx, using IRQ %d.\n",
-              dev->name, name, ioaddr, dev->irq);
+       netdev_info(dev, "%s found at %#lx, using IRQ %d.\n",
+                   name, ioaddr, dev->irq);
        return 0;
 
 out_irq:
@@ -556,9 +564,9 @@ err_out:
 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);
+       netif_dbg(ei_local, hw, dev, "resetting the 8390 t=%ld...\n", 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);
@@ -569,7 +577,7 @@ static void ne_reset_8390(struct net_device *dev)
        /* 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);
+                       netdev_err(dev, "ne_reset_8390() did not complete.\n");
                        break;
                }
        outb_p(ENISR_RESET, NE_BASE + EN0_ISR); /* Ack intr. */
@@ -587,9 +595,9 @@ static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, i
 
        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);
+               netdev_err(dev, "DMAing conflict in ne_get_8390_hdr "
+                          "[DMAstat:%d][irqlock:%d].\n",
+                          ei_status.dmaing, ei_status.irqlock);
                return;
        }
 
@@ -621,6 +629,7 @@ static void ne_block_input(struct net_device *dev, int count, struct sk_buff *sk
 {
 #ifdef NE_SANITY_CHECK
        int xfer_count = count;
+       struct ei_device *ei_local = netdev_priv(dev);
 #endif
        int nic_base = dev->base_addr;
        char *buf = skb->data;
@@ -628,9 +637,9 @@ static void ne_block_input(struct net_device *dev, int count, struct sk_buff *sk
        /* 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);
+               netdev_err(dev, "DMAing conflict in ne_block_input "
+                          "[DMAstat:%d][irqlock:%d].\n",
+                          ei_status.dmaing, ei_status.irqlock);
                return;
        }
        ei_status.dmaing |= 0x01;
@@ -660,7 +669,7 @@ static void ne_block_input(struct net_device *dev, int count, struct sk_buff *sk
           this message you either 1) have a slightly incompatible clone
           or 2) have noise/speed problems with your bus. */
 
-       if (ei_debug > 1)
+       if (netif_msg_rx_status(ei_local))
        {
                /* DMA termination address check... */
                int addr, tries = 20;
@@ -674,9 +683,9 @@ static void ne_block_input(struct net_device *dev, int count, struct sk_buff *sk
                                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);
+                       netdev_warn(dev, "RX transfer address mismatch,"
+                                   "%#4.4x (expected) vs. %#4.4x (actual).\n",
+                                   ring_offset + xfer_count, addr);
        }
 #endif
        outb_p(ENISR_RDC, nic_base + EN0_ISR);  /* Ack intr. */
@@ -690,6 +699,7 @@ static void ne_block_output(struct net_device *dev, int count,
        unsigned long dma_start;
 #ifdef NE_SANITY_CHECK
        int retries = 0;
+       struct ei_device *ei_local = netdev_priv(dev);
 #endif
 
        /* Round the count up for word writes.  Do we need to do this?
@@ -702,9 +712,9 @@ static void ne_block_output(struct net_device *dev, int 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);
+               netdev_err(dev, "DMAing conflict in ne_block_output."
+                          "[DMAstat:%d][irqlock:%d]\n",
+                          ei_status.dmaing, ei_status.irqlock);
                return;
        }
        ei_status.dmaing |= 0x01;
@@ -751,7 +761,7 @@ retry:
        /* This was for the ALPHA version only, but enough people have
           been encountering problems so it is still here. */
 
-       if (ei_debug > 1)
+       if (netif_msg_tx_queued(ei_local))
        {
                /* DMA termination address check... */
                int addr, tries = 20;
@@ -765,9 +775,9 @@ retry:
 
                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);
+                       netdev_warn(dev, "Tx packet transfer address mismatch,"
+                                   "%#4.4x (expected) vs. %#4.4x (actual).\n",
+                                   (start_page << 8) + count, addr);
                        if (retries++ == 0)
                                goto retry;
                }
@@ -776,7 +786,7 @@ retry:
 
        while ((inb_p(nic_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);
+                       netdev_warn(dev, "timeout waiting for Tx RDC.\n");
                        ne_reset_8390(dev);
                        NS8390p_init(dev, 1);
                        break;
@@ -936,8 +946,8 @@ int __init init_module(void)
        retval = platform_driver_probe(&ne_driver, ne_drv_probe);
        if (retval) {
                if (io[0] == 0)
-                       printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\""
-                               " value(s) for ISA cards.\n");
+                       pr_notice("ne.c: You must supply \"io=0xNNN\""
+                              " value(s) for ISA cards.\n");
                ne_loop_rm_unreg(1);
                return retval;
        }
index fc14a85e4d5ffdde31d42c40dac5f6af7e80c946..f395c967262e98e0464ec7a01726a6e3a83d0e56 100644 (file)
@@ -33,8 +33,6 @@
 /* The user-configurable values.
    These may be modified when a driver module is loaded.*/
 
-static int debug = 1;                  /* 1 normal messages, 0 quiet .. 7 verbose. */
-
 #define MAX_UNITS 8                            /* More are supported, limit only on options */
 /* Used to pass the full-duplex flag, etc. */
 static int full_duplex[MAX_UNITS];
@@ -60,6 +58,8 @@ static int options[MAX_UNITS];
 
 #include "8390.h"
 
+static u32 ne2k_msg_enable;
+
 /* These identify the driver base version and may not be removed. */
 static const char version[] =
        KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE
@@ -76,10 +76,10 @@ MODULE_AUTHOR("Donald Becker / Paul Gortmaker");
 MODULE_DESCRIPTION("PCI NE2000 clone driver");
 MODULE_LICENSE("GPL");
 
-module_param(debug, int, 0);
+module_param_named(msg_enable, ne2k_msg_enable, uint, (S_IRUSR|S_IRGRP|S_IROTH));
 module_param_array(options, int, NULL, 0);
 module_param_array(full_duplex, int, NULL, 0);
-MODULE_PARM_DESC(debug, "debug level (1-2)");
+MODULE_PARM_DESC(msg_enable, "Debug message level (see linux/netdevice.h for bitmap)");
 MODULE_PARM_DESC(options, "Bit 5: full duplex");
 MODULE_PARM_DESC(full_duplex, "full duplex setting(s) (1)");
 
@@ -226,6 +226,7 @@ static int ne2k_pci_init_one(struct pci_dev *pdev,
        static unsigned int fnd_cnt;
        long ioaddr;
        int flags = pci_clone_list[chip_idx].flags;
+       struct ei_device *ei_local;
 
 /* when built into the kernel, we only print version if device is found */
 #ifndef MODULE
@@ -280,6 +281,8 @@ static int ne2k_pci_init_one(struct pci_dev *pdev,
                goto err_out_free_res;
        }
        dev->netdev_ops = &ne2k_netdev_ops;
+       ei_local = netdev_priv(dev);
+       ei_local->msg_enable = ne2k_msg_enable;
 
        SET_NETDEV_DEV(dev, &pdev->dev);
 
@@ -379,9 +382,9 @@ static int ne2k_pci_init_one(struct pci_dev *pdev,
        if (i)
                goto err_out_free_netdev;
 
-       printk("%s: %s found at %#lx, IRQ %d, %pM.\n",
-              dev->name, pci_clone_list[chip_idx].name, ioaddr, dev->irq,
-              dev->dev_addr);
+       netdev_info(dev, "%s found at %#lx, IRQ %d, %pM.\n",
+                   pci_clone_list[chip_idx].name, ioaddr, dev->irq,
+                   dev->dev_addr);
 
        return 0;
 
@@ -450,9 +453,10 @@ static int ne2k_pci_close(struct net_device *dev)
 static void ne2k_pci_reset_8390(struct net_device *dev)
 {
        unsigned long reset_start_time = jiffies;
+       struct ei_device *ei_local = netdev_priv(dev);
 
-       if (debug > 1) printk("%s: Resetting the 8390 t=%ld...",
-                                                 dev->name, jiffies);
+       netif_dbg(ei_local, hw, dev, "resetting the 8390 t=%ld...\n",
+                 jiffies);
 
        outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
 
@@ -462,7 +466,7 @@ static void ne2k_pci_reset_8390(struct net_device *dev)
        /* This check _should_not_ be necessary, omit eventually. */
        while ((inb(NE_BASE+EN0_ISR) & ENISR_RESET) == 0)
                if (jiffies - reset_start_time > 2) {
-                       printk("%s: ne2k_pci_reset_8390() did not complete.\n", dev->name);
+                       netdev_err(dev, "ne2k_pci_reset_8390() did not complete.\n");
                        break;
                }
        outb(ENISR_RESET, NE_BASE + EN0_ISR);   /* Ack intr. */
@@ -479,9 +483,9 @@ static void ne2k_pci_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *
 
        /* This *shouldn't* happen. If it does, it's the last thing you'll see */
        if (ei_status.dmaing) {
-               printk("%s: DMAing conflict in ne2k_pci_get_8390_hdr "
+               netdev_err(dev, "DMAing conflict in ne2k_pci_get_8390_hdr "
                           "[DMAstat:%d][irqlock:%d].\n",
-                          dev->name, ei_status.dmaing, ei_status.irqlock);
+                          ei_status.dmaing, ei_status.irqlock);
                return;
        }
 
@@ -517,9 +521,9 @@ static void ne2k_pci_block_input(struct net_device *dev, int count,
 
        /* This *shouldn't* happen. If it does, it's the last thing you'll see */
        if (ei_status.dmaing) {
-               printk("%s: DMAing conflict in ne2k_pci_block_input "
+               netdev_err(dev, "DMAing conflict in ne2k_pci_block_input "
                           "[DMAstat:%d][irqlock:%d].\n",
-                          dev->name, ei_status.dmaing, ei_status.irqlock);
+                          ei_status.dmaing, ei_status.irqlock);
                return;
        }
        ei_status.dmaing |= 0x01;
@@ -572,9 +576,9 @@ static void ne2k_pci_block_output(struct net_device *dev, int count,
 
        /* This *shouldn't* happen. If it does, it's the last thing you'll see */
        if (ei_status.dmaing) {
-               printk("%s: DMAing conflict in ne2k_pci_block_output."
+               netdev_err(dev, "DMAing conflict in ne2k_pci_block_output."
                           "[DMAstat:%d][irqlock:%d]\n",
-                          dev->name, ei_status.dmaing, ei_status.irqlock);
+                          ei_status.dmaing, ei_status.irqlock);
                return;
        }
        ei_status.dmaing |= 0x01;
@@ -619,7 +623,7 @@ static void ne2k_pci_block_output(struct net_device *dev, int count,
 
        while ((inb(nic_base + EN0_ISR) & ENISR_RDC) == 0)
                if (jiffies - dma_start > 2) {                  /* Avoid clock roll-over. */
-                       printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name);
+                       netdev_warn(dev, "timeout waiting for Tx RDC.\n");
                        ne2k_pci_reset_8390(dev);
                        NS8390_init(dev,1);
                        break;
@@ -640,8 +644,24 @@ static void ne2k_pci_get_drvinfo(struct net_device *dev,
        strlcpy(info->bus_info, pci_name(pci_dev), sizeof(info->bus_info));
 }
 
+static u32 ne2k_pci_get_msglevel(struct net_device *dev)
+{
+       struct ei_device *ei_local = netdev_priv(dev);
+
+       return ei_local->msg_enable;
+}
+
+static void ne2k_pci_set_msglevel(struct net_device *dev, u32 v)
+{
+       struct ei_device *ei_local = netdev_priv(dev);
+
+       ei_local->msg_enable = v;
+}
+
 static const struct ethtool_ops ne2k_pci_ethtool_ops = {
        .get_drvinfo            = ne2k_pci_get_drvinfo,
+       .get_msglevel           = ne2k_pci_get_msglevel,
+       .set_msglevel           = ne2k_pci_set_msglevel,
 };
 
 static void ne2k_pci_remove_one(struct pci_dev *pdev)
index 46c5aadaca8efb50f6701e8e9be3aff615dd5846..eea33d667fb0bb50afa28d33fb82cfef417f9791 100644 (file)
@@ -67,7 +67,7 @@
 #define PCNET_RDC_TIMEOUT (2*HZ/100)   /* Max wait in jiffies for Tx RDC */
 
 static const char *if_names[] = { "auto", "10baseT", "10base2"};
-
+static u32 pcnet_msg_enable;
 
 /*====================================================================*/
 
@@ -558,6 +558,7 @@ static int pcnet_config(struct pcmcia_device *link)
     int start_pg, stop_pg, cm_offset;
     int has_shmem = 0;
     hw_info_t *local_hw_info;
+    struct ei_device *ei_local;
 
     dev_dbg(&link->dev, "pcnet_config\n");
 
@@ -607,6 +608,8 @@ static int pcnet_config(struct pcmcia_device *link)
        mii_phy_probe(dev);
 
     SET_NETDEV_DEV(dev, &link->dev);
+    ei_local = netdev_priv(dev);
+    ei_local->msg_enable = pcnet_msg_enable;
 
     if (register_netdev(dev) != 0) {
        pr_notice("register_netdev() failed\n");
@@ -616,7 +619,7 @@ static int pcnet_config(struct pcmcia_device *link)
     if (info->flags & (IS_DL10019|IS_DL10022)) {
        u_char id = inb(dev->base_addr + 0x1a);
        netdev_info(dev, "NE2000 (DL100%d rev %02x): ",
-              (info->flags & IS_DL10022) ? 22 : 19, id);
+                   (info->flags & IS_DL10022) ? 22 : 19, id);
        if (info->pna_phy)
            pr_cont("PNA, ");
     } else {
@@ -1063,9 +1066,9 @@ static void ei_watchdog(u_long arg)
            if (info->phy_id == info->eth_phy) {
                if (p)
                    netdev_info(dev, "autonegotiation complete: "
-                          "%sbaseT-%cD selected\n",
-                          ((p & 0x0180) ? "100" : "10"),
-                          ((p & 0x0140) ? 'F' : 'H'));
+                               "%sbaseT-%cD selected\n",
+                               ((p & 0x0180) ? "100" : "10"),
+                               ((p & 0x0140) ? 'F' : 'H'));
                else
                    netdev_info(dev, "link partner did not autonegotiate\n");
            }
@@ -1081,7 +1084,7 @@ static void ei_watchdog(u_long arg)
            mdio_write(mii_addr, info->phy_id, 0, 0x0400);
            info->phy_id ^= info->pna_phy ^ info->eth_phy;
            netdev_info(dev, "switched to %s transceiver\n",
-                  (info->phy_id == info->eth_phy) ? "ethernet" : "PNA");
+                       (info->phy_id == info->eth_phy) ? "ethernet" : "PNA");
            mdio_write(mii_addr, info->phy_id, 0,
                       (info->phy_id == info->eth_phy) ? 0x1000 : 0);
            info->link_status = 0;
@@ -1128,9 +1131,9 @@ static void dma_get_8390_hdr(struct net_device *dev,
     unsigned int nic_base = dev->base_addr;
 
     if (ei_status.dmaing) {
-       netdev_notice(dev, "DMAing conflict in dma_block_input."
-              "[DMAstat:%1x][irqlock:%1x]\n",
-              ei_status.dmaing, ei_status.irqlock);
+       netdev_err(dev, "DMAing conflict in dma_block_input."
+                  "[DMAstat:%1x][irqlock:%1x]\n",
+                  ei_status.dmaing, ei_status.irqlock);
        return;
     }
 
@@ -1159,13 +1162,14 @@ static void dma_block_input(struct net_device *dev, int count,
     unsigned int nic_base = dev->base_addr;
     int xfer_count = count;
     char *buf = skb->data;
+    struct ei_device *ei_local = netdev_priv(dev);
 
-    if ((ei_debug > 4) && (count != 4))
+    if ((netif_msg_rx_status(ei_local)) && (count != 4))
        netdev_dbg(dev, "[bi=%d]\n", count+4);
     if (ei_status.dmaing) {
-       netdev_notice(dev, "DMAing conflict in dma_block_input."
-              "[DMAstat:%1x][irqlock:%1x]\n",
-              ei_status.dmaing, ei_status.irqlock);
+       netdev_err(dev, "DMAing conflict in dma_block_input."
+                  "[DMAstat:%1x][irqlock:%1x]\n",
+                  ei_status.dmaing, ei_status.irqlock);
        return;
     }
     ei_status.dmaing |= 0x01;
@@ -1183,7 +1187,8 @@ static void dma_block_input(struct net_device *dev, int count,
     /* This was for the ALPHA version only, but enough people have been
        encountering problems that it is still here. */
 #ifdef PCMCIA_DEBUG
-    if (ei_debug > 4) {                /* DMA termination address check... */
+      /* DMA termination address check... */
+    if (netif_msg_rx_status(ei_local)) {
        int addr, tries = 20;
        do {
            /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here
@@ -1196,8 +1201,8 @@ static void dma_block_input(struct net_device *dev, int count,
        } while (--tries > 0);
        if (tries <= 0)
            netdev_notice(dev, "RX transfer address mismatch,"
-                  "%#4.4x (expected) vs. %#4.4x (actual).\n",
-                  ring_offset + xfer_count, addr);
+                         "%#4.4x (expected) vs. %#4.4x (actual).\n",
+                         ring_offset + xfer_count, addr);
     }
 #endif
     outb_p(ENISR_RDC, nic_base + EN0_ISR);     /* Ack intr. */
@@ -1213,12 +1218,12 @@ static void dma_block_output(struct net_device *dev, int count,
     pcnet_dev_t *info = PRIV(dev);
 #ifdef PCMCIA_DEBUG
     int retries = 0;
+    struct ei_device *ei_local = netdev_priv(dev);
 #endif
     u_long dma_start;
 
 #ifdef PCMCIA_DEBUG
-    if (ei_debug > 4)
-       netdev_dbg(dev, "[bo=%d]\n", count);
+    netif_dbg(ei_local, tx_queued, dev, "[bo=%d]\n", count);
 #endif
 
     /* Round the count up for word writes.  Do we need to do this?
@@ -1227,9 +1232,9 @@ static void dma_block_output(struct net_device *dev, int count,
     if (count & 0x01)
        count++;
     if (ei_status.dmaing) {
-       netdev_notice(dev, "DMAing conflict in dma_block_output."
-              "[DMAstat:%1x][irqlock:%1x]\n",
-              ei_status.dmaing, ei_status.irqlock);
+       netdev_err(dev, "DMAing conflict in dma_block_output."
+                  "[DMAstat:%1x][irqlock:%1x]\n",
+                  ei_status.dmaing, ei_status.irqlock);
        return;
     }
     ei_status.dmaing |= 0x01;
@@ -1256,7 +1261,8 @@ static void dma_block_output(struct net_device *dev, int count,
 #ifdef PCMCIA_DEBUG
     /* This was for the ALPHA version only, but enough people have been
        encountering problems that it is still here. */
-    if (ei_debug > 4) {        /* DMA termination address check... */
+    /* DMA termination address check... */
+    if (netif_msg_tx_queued(ei_local)) {
        int addr, tries = 20;
        do {
            int high = inb_p(nic_base + EN0_RSARHI);
@@ -1267,8 +1273,8 @@ static void dma_block_output(struct net_device *dev, int count,
        } while (--tries > 0);
        if (tries <= 0) {
            netdev_notice(dev, "Tx packet transfer address mismatch,"
-                  "%#4.4x (expected) vs. %#4.4x (actual).\n",
-                  (start_page << 8) + count, addr);
+                         "%#4.4x (expected) vs. %#4.4x (actual).\n",
+                         (start_page << 8) + count, addr);
            if (retries++ == 0)
                goto retry;
        }
@@ -1277,10 +1283,10 @@ static void dma_block_output(struct net_device *dev, int count,
 
     while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0)
        if (time_after(jiffies, dma_start + PCNET_RDC_TIMEOUT)) {
-           netdev_notice(dev, "timeout waiting for Tx RDC.\n");
-           pcnet_reset_8390(dev);
-           NS8390_init(dev, 1);
-           break;
+               netdev_warn(dev, "timeout waiting for Tx RDC.\n");
+               pcnet_reset_8390(dev);
+               NS8390_init(dev, 1);
+               break;
        }
 
     outb_p(ENISR_RDC, nic_base + EN0_ISR);     /* Ack intr. */
index b0fbce39661a7154e5d2c6af00ea543acce2d107..139385dcdaa753db90e14c6265fa1d0c117acb15 100644 (file)
@@ -111,6 +111,7 @@ static struct isapnp_device_id ultra_device_ids[] __initdata = {
 MODULE_DEVICE_TABLE(isapnp, ultra_device_ids);
 #endif
 
+static u32 ultra_msg_enable;
 
 #define START_PG               0x00    /* First page of TX buffer */
 
@@ -211,6 +212,7 @@ static int __init ultra_probe1(struct net_device *dev, int ioaddr)
        unsigned char num_pages, irqreg, addr, piomode;
        unsigned char idreg = inb(ioaddr + 7);
        unsigned char reg4 = inb(ioaddr + 4) & 0x7f;
+       struct ei_device *ei_local = netdev_priv(dev);
 
        if (!request_region(ioaddr, ULTRA_IO_EXTENT, DRV_NAME))
                return -EBUSY;
@@ -232,16 +234,16 @@ static int __init ultra_probe1(struct net_device *dev, int ioaddr)
                goto out;
        }
 
-       if (ei_debug  &&  version_printed++ == 0)
-               printk(version);
+       if ((ultra_msg_enable & NETIF_MSG_DRV) && (version_printed++ == 0))
+               netdev_info(dev, version);
 
        model_name = (idreg & 0xF0) == 0x20 ? "SMC Ultra" : "SMC EtherEZ";
 
        for (i = 0; i < 6; i++)
                dev->dev_addr[i] = inb(ioaddr + 8 + i);
 
-       printk("%s: %s at %#3x, %pM", dev->name, model_name,
-              ioaddr, dev->dev_addr);
+       netdev_info(dev, "%s at %#3x, %pM", model_name,
+                   ioaddr, dev->dev_addr);
 
        /* Switch from the station address to the alternate register set and
           read the useful registers there. */
@@ -265,7 +267,7 @@ static int __init ultra_probe1(struct net_device *dev, int ioaddr)
                irq = irqmap[((irqreg & 0x40) >> 4) + ((irqreg & 0x0c) >> 2)];
 
                if (irq == 0) {
-                       printk(", failed to detect IRQ line.\n");
+                       pr_cont(", failed to detect IRQ line.\n");
                        retval =  -EAGAIN;
                        goto out;
                }
@@ -296,7 +298,7 @@ static int __init ultra_probe1(struct net_device *dev, int ioaddr)
 
        ei_status.mem = ioremap(dev->mem_start, (ei_status.stop_page - START_PG)*256);
        if (!ei_status.mem) {
-               printk(", failed to ioremap.\n");
+               pr_cont(", failed to ioremap.\n");
                retval =  -ENOMEM;
                goto out;
        }
@@ -304,14 +306,15 @@ static int __init ultra_probe1(struct net_device *dev, int ioaddr)
        dev->mem_end = dev->mem_start + (ei_status.stop_page - START_PG)*256;
 
        if (piomode) {
-               printk(",%s IRQ %d programmed-I/O mode.\n",
-                          eeprom_irq ? "EEPROM" : "assigned ", dev->irq);
+               pr_cont(", %s IRQ %d programmed-I/O mode.\n",
+                       eeprom_irq ? "EEPROM" : "assigned ", dev->irq);
                ei_status.block_input = &ultra_pio_input;
                ei_status.block_output = &ultra_pio_output;
                ei_status.get_8390_hdr = &ultra_pio_get_hdr;
        } else {
-               printk(",%s IRQ %d memory %#lx-%#lx.\n", eeprom_irq ? "" : "assigned ",
-                          dev->irq, dev->mem_start, dev->mem_end-1);
+               pr_cont(", %s IRQ %d memory %#lx-%#lx.\n",
+                       eeprom_irq ? "" : "assigned ", dev->irq, dev->mem_start,
+                       dev->mem_end-1);
                ei_status.block_input = &ultra_block_input;
                ei_status.block_output = &ultra_block_output;
                ei_status.get_8390_hdr = &ultra_get_8390_hdr;
@@ -320,6 +323,7 @@ static int __init ultra_probe1(struct net_device *dev, int ioaddr)
 
        dev->netdev_ops = &ultra_netdev_ops;
        NS8390_init(dev, 0);
+       ei_local->msg_enable = ultra_msg_enable;
 
        retval = register_netdev(dev);
        if (retval)
@@ -356,12 +360,15 @@ static int __init ultra_probe_isapnp(struct net_device *dev)
                         /* found it */
                        dev->base_addr = pnp_port_start(idev, 0);
                        dev->irq = pnp_irq(idev, 0);
-                        printk(KERN_INFO "smc-ultra.c: ISAPnP reports %s at i/o %#lx, irq %d.\n",
-                                (char *) ultra_device_ids[i].driver_data,
-                                dev->base_addr, dev->irq);
+                       netdev_info(dev,
+                                   "smc-ultra.c: ISAPnP reports %s at i/o %#lx, irq %d.\n",
+                                   (char *) ultra_device_ids[i].driver_data,
+                                   dev->base_addr, dev->irq);
                         if (ultra_probe1(dev, dev->base_addr) != 0) {      /* Shouldn't happen. */
-                                printk(KERN_ERR "smc-ultra.c: Probe of ISAPnP card at %#lx failed.\n", dev->base_addr);
-                                pnp_device_detach(idev);
+                               netdev_err(dev,
+                                          "smc-ultra.c: Probe of ISAPnP card at %#lx failed.\n",
+                                          dev->base_addr);
+                               pnp_device_detach(idev);
                                return -ENXIO;
                         }
                         ei_status.priv = (unsigned long)idev;
@@ -412,9 +419,10 @@ static void
 ultra_reset_8390(struct net_device *dev)
 {
        int cmd_port = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC base addr */
+       struct ei_device *ei_local = netdev_priv(dev);
 
        outb(ULTRA_RESET, cmd_port);
-       if (ei_debug > 1) printk("resetting Ultra, t=%ld...", jiffies);
+       netif_dbg(ei_local, hw, dev, "resetting Ultra, t=%ld...\n", jiffies);
        ei_status.txing = 0;
 
        outb(0x00, cmd_port);   /* Disable shared memory for safety. */
@@ -424,7 +432,7 @@ ultra_reset_8390(struct net_device *dev)
        else
                outb(0x01, cmd_port + 6);               /* Enable interrupts and memory. */
 
-       if (ei_debug > 1) printk("reset done\n");
+       netif_dbg(ei_local, hw, dev, "reset done\n");
 }
 
 /* Grab the 8390 specific header. Similar to the block_input routine, but
@@ -530,11 +538,11 @@ static int
 ultra_close_card(struct net_device *dev)
 {
        int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* CMDREG */
+       struct ei_device *ei_local = netdev_priv(dev);
 
        netif_stop_queue(dev);
 
-       if (ei_debug > 1)
-               printk("%s: Shutting down ethercard.\n", dev->name);
+       netif_dbg(ei_local, ifdown, dev, "Shutting down ethercard.\n");
 
        outb(0x00, ioaddr + 6);         /* Disable interrupts. */
        free_irq(dev->irq, dev);
@@ -556,8 +564,10 @@ static int irq[MAX_ULTRA_CARDS];
 
 module_param_array(io, int, NULL, 0);
 module_param_array(irq, int, NULL, 0);
+module_param_named(msg_enable, ultra_msg_enable, uint, (S_IRUSR|S_IRGRP|S_IROTH));
 MODULE_PARM_DESC(io, "I/O base address(es)");
 MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
+MODULE_PARM_DESC(msg_enable, "Debug message level (see linux/netdevice.h for bitmap)");
 MODULE_DESCRIPTION("SMC Ultra/EtherEZ ISA/PnP Ethernet driver");
 MODULE_LICENSE("GPL");
 
index 8df4c41572306d9f4fad96567964778b7455c23a..aca957d4e12196c9be02a2319a39d4ff232c1c4e 100644 (file)
@@ -69,6 +69,11 @@ static void stnic_block_output (struct net_device *dev, int count,
 
 static void stnic_init (struct net_device *dev);
 
+static u32 stnic_msg_enable;
+
+module_param_named(msg_enable, stnic_msg_enable, uint, (S_IRUSR|S_IRGRP|S_IROTH));
+MODULE_PARM_DESC(msg_enable, "Debug message level (see linux/netdevice.h for bitmap)");
+
 /* SH7750 specific read/write io. */
 static inline void
 STNIC_DELAY (void)
@@ -100,6 +105,7 @@ static int __init stnic_probe(void)
 {
   struct net_device *dev;
   int i, err;
+  struct ei_device *ei_local;
 
   /* If we are not running on a SolutionEngine, give up now */
   if (! MACH_SE)
@@ -125,10 +131,10 @@ static int __init stnic_probe(void)
      share and the board will usually be enabled. */
   err = request_irq (dev->irq, ei_interrupt, 0, DRV_NAME, dev);
   if (err)  {
-      printk (KERN_EMERG " unable to get IRQ %d.\n", dev->irq);
-      free_netdev(dev);
-      return err;
-    }
+       netdev_emerg(dev, " unable to get IRQ %d.\n", dev->irq);
+       free_netdev(dev);
+       return err;
+  }
 
   ei_status.name = dev->name;
   ei_status.word16 = 1;
@@ -147,6 +153,8 @@ static int __init stnic_probe(void)
   ei_status.block_output = &stnic_block_output;
 
   stnic_init (dev);
+  ei_local = netdev_priv(dev);
+  ei_local->msg_enable = stnic_msg_enable;
 
   err = register_netdev(dev);
   if (err) {
@@ -156,7 +164,7 @@ static int __init stnic_probe(void)
   }
   stnic_dev = dev;
 
-  printk (KERN_INFO "NS ST-NIC 83902A\n");
+  netdev_info(dev, "NS ST-NIC 83902A\n");
 
   return 0;
 }
@@ -164,10 +172,11 @@ static int __init stnic_probe(void)
 static void
 stnic_reset (struct net_device *dev)
 {
+  struct ei_device *ei_local = netdev_priv(dev);
+
   *(vhalf *) PA_83902_RST = 0;
   udelay (5);
-  if (ei_debug > 1)
-    printk (KERN_WARNING "8390 reset done (%ld).\n", jiffies);
+  netif_warn(ei_local, hw, dev, "8390 reset done (%ld).\n", jiffies);
   *(vhalf *) PA_83902_RST = ~0;
   udelay (5);
 }
@@ -176,6 +185,8 @@ static void
 stnic_get_hdr (struct net_device *dev, struct e8390_pkt_hdr *hdr,
               int ring_page)
 {
+  struct ei_device *ei_local = netdev_priv(dev);
+
   half buf[2];
 
   STNIC_WRITE (PG0_RSAR0, 0);
@@ -196,8 +207,7 @@ stnic_get_hdr (struct net_device *dev, struct e8390_pkt_hdr *hdr,
   hdr->count = ((buf[1] >> 8) & 0xff) | (buf[1] << 8);
 #endif
 
-  if (ei_debug > 1)
-    printk (KERN_DEBUG "ring %x status %02x next %02x count %04x.\n",
+  netif_dbg(ei_local, probe, dev, "ring %x status %02x next %02x count %04x.\n",
            ring_page, hdr->status, hdr->next, hdr->count);
 
   STNIC_WRITE (STNIC_CR, CR_RDMA | CR_PG0 | CR_STA);
index 03eb3eed49fa42d2485f606710c3347525040c43..dd7d816bde52680b793880ab27e0c00454125a7c 100644 (file)
@@ -60,6 +60,7 @@ static void wd_block_output(struct net_device *dev, int count,
                                                        const unsigned char *buf, int start_page);
 static int wd_close(struct net_device *dev);
 
+static u32 wd_msg_enable;
 
 #define WD_START_PG            0x00    /* First page of TX buffer */
 #define WD03_STOP_PG   0x20    /* Last page +1 of RX ring */
@@ -170,6 +171,7 @@ static int __init wd_probe1(struct net_device *dev, int ioaddr)
        int word16 = 0;                         /* 0 = 8 bit, 1 = 16 bit */
        const char *model_name;
        static unsigned version_printed;
+       struct ei_device *ei_local = netdev_priv(dev);
 
        for (i = 0; i < 8; i++)
                checksum += inb(ioaddr + 8 + i);
@@ -180,19 +182,19 @@ static int __init wd_probe1(struct net_device *dev, int ioaddr)
 
        /* Check for semi-valid mem_start/end values if supplied. */
        if ((dev->mem_start % 0x2000) || (dev->mem_end % 0x2000)) {
-               printk(KERN_WARNING "wd.c: user supplied mem_start or mem_end not on 8kB boundary - ignored.\n");
+               netdev_warn(dev,
+                           "wd.c: user supplied mem_start or mem_end not on 8kB boundary - ignored.\n");
                dev->mem_start = 0;
                dev->mem_end = 0;
        }
 
-       if (ei_debug  &&  version_printed++ == 0)
-               printk(version);
+       if ((wd_msg_enable & NETIF_MSG_DRV) && (version_printed++ == 0))
+               netdev_info(dev, version);
 
        for (i = 0; i < 6; i++)
                dev->dev_addr[i] = inb(ioaddr + 8 + i);
 
-       printk("%s: WD80x3 at %#3x, %pM",
-              dev->name, ioaddr, dev->dev_addr);
+       netdev_info(dev, "WD80x3 at %#3x, %pM", ioaddr, dev->dev_addr);
 
        /* The following PureData probe code was contributed by
           Mike Jagdis <jaggy@purplet.demon.co.uk>. Puredata does software
@@ -244,8 +246,9 @@ static int __init wd_probe1(struct net_device *dev, int ioaddr)
                }
 #ifndef final_version
                if ( !ancient && (inb(ioaddr+1) & 0x01) != (word16 & 0x01))
-                       printk("\nWD80?3: Bus width conflict, %d (probe) != %d (reg report).",
-                                  word16 ? 16 : 8, (inb(ioaddr+1) & 0x01) ? 16 : 8);
+                       pr_cont("\nWD80?3: Bus width conflict, %d (probe) != %d (reg report).",
+                               word16 ? 16 : 8,
+                               (inb(ioaddr+1) & 0x01) ? 16 : 8);
 #endif
        }
 
@@ -259,7 +262,7 @@ static int __init wd_probe1(struct net_device *dev, int ioaddr)
                if (reg0 == 0xff || reg0 == 0) {
                        /* Future plan: this could check a few likely locations first. */
                        dev->mem_start = 0xd0000;
-                       printk(" assigning address %#lx", dev->mem_start);
+                       pr_cont(" assigning address %#lx", dev->mem_start);
                } else {
                        int high_addr_bits = inb(ioaddr+WD_CMDREG5) & 0x1f;
                        /* Some boards don't have the register 5 -- it returns 0xff. */
@@ -297,8 +300,8 @@ static int __init wd_probe1(struct net_device *dev, int ioaddr)
 
                        outb_p(0x00, nic_addr+EN0_IMR); /* Mask all intrs. again. */
 
-                       if (ei_debug > 2)
-                               printk(" autoirq is %d", dev->irq);
+                       if (netif_msg_drv(ei_local))
+                               pr_cont(" autoirq is %d", dev->irq);
                        if (dev->irq < 2)
                                dev->irq = word16 ? 10 : 5;
                } else
@@ -310,7 +313,7 @@ static int __init wd_probe1(struct net_device *dev, int ioaddr)
           share and the board will usually be enabled. */
        i = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev);
        if (i) {
-               printk (" unable to get IRQ %d.\n", dev->irq);
+               pr_cont(" unable to get IRQ %d.\n", dev->irq);
                return i;
        }
 
@@ -338,8 +341,8 @@ static int __init wd_probe1(struct net_device *dev, int ioaddr)
                return -ENOMEM;
        }
 
-       printk(" %s, IRQ %d, shared memory at %#lx-%#lx.\n",
-                  model_name, dev->irq, dev->mem_start, dev->mem_end-1);
+       pr_cont(" %s, IRQ %d, shared memory at %#lx-%#lx.\n",
+               model_name, dev->irq, dev->mem_start, dev->mem_end-1);
 
        ei_status.reset_8390 = wd_reset_8390;
        ei_status.block_input = wd_block_input;
@@ -348,6 +351,7 @@ static int __init wd_probe1(struct net_device *dev, int ioaddr)
 
        dev->netdev_ops = &wd_netdev_ops;
        NS8390_init(dev, 0);
+       ei_local->msg_enable = wd_msg_enable;
 
 #if 1
        /* Enable interrupt generation on softconfig cards -- M.U */
@@ -385,9 +389,11 @@ static void
 wd_reset_8390(struct net_device *dev)
 {
        int wd_cmd_port = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
+       struct ei_device *ei_local = netdev_priv(dev);
 
        outb(WD_RESET, wd_cmd_port);
-       if (ei_debug > 1) printk("resetting the WD80x3 t=%lu...", jiffies);
+       netif_dbg(ei_local, hw, dev, "resetting the WD80x3 t=%lu...\n",
+                 jiffies);
        ei_status.txing = 0;
 
        /* Set up the ASIC registers, just in case something changed them. */
@@ -395,7 +401,7 @@ wd_reset_8390(struct net_device *dev)
        if (ei_status.word16)
                outb(NIC16 | ((dev->mem_start>>19) & 0x1f), wd_cmd_port+WD_CMDREG5);
 
-       if (ei_debug > 1) printk("reset done\n");
+       netif_dbg(ei_local, hw, dev, "reset done\n");
 }
 
 /* Grab the 8390 specific header. Similar to the block_input routine, but
@@ -474,9 +480,9 @@ static int
 wd_close(struct net_device *dev)
 {
        int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
+       struct ei_device *ei_local = netdev_priv(dev);
 
-       if (ei_debug > 1)
-               printk("%s: Shutting down ethercard.\n", dev->name);
+       netif_dbg(ei_local, ifdown, dev, "Shutting down ethercard.\n");
        ei_close(dev);
 
        /* Change from 16-bit to 8-bit shared memory so reboot works. */
@@ -502,10 +508,12 @@ module_param_array(io, int, NULL, 0);
 module_param_array(irq, int, NULL, 0);
 module_param_array(mem, int, NULL, 0);
 module_param_array(mem_end, int, NULL, 0);
+module_param_named(msg_enable, wd_msg_enable, uint, (S_IRUSR|S_IRGRP|S_IROTH));
 MODULE_PARM_DESC(io, "I/O base address(es)");
 MODULE_PARM_DESC(irq, "IRQ number(s) (ignored for PureData boards)");
 MODULE_PARM_DESC(mem, "memory base address(es)(ignored for PureData boards)");
 MODULE_PARM_DESC(mem_end, "memory end address(es)");
+MODULE_PARM_DESC(msg_enable, "Debug message level (see linux/netdevice.h for bitmap)");
 MODULE_DESCRIPTION("ISA Western Digital wd8003/wd8013 ; SMC Elite, Elite16 ethernet driver");
 MODULE_LICENSE("GPL");
 
index 85ec4c2d2645582339eb7ecfa796e9b37fee91ad..8308728fad0511c74f0164488a59e09ef2ea8194 100644 (file)
@@ -44,6 +44,8 @@
 static const char version[] =
        "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
 
+static u32 zorro8390_msg_enable;
+
 #include "lib8390.c"
 
 #define DRV_NAME       "zorro8390"
@@ -86,9 +88,9 @@ static struct card_info {
 static void zorro8390_reset_8390(struct net_device *dev)
 {
        unsigned long reset_start_time = jiffies;
+       struct ei_device *ei_local = netdev_priv(dev);
 
-       if (ei_debug > 1)
-               netdev_dbg(dev, "resetting - t=%ld...\n", jiffies);
+       netif_dbg(ei_local, hw, dev, "resetting - t=%ld...\n", jiffies);
 
        z_writeb(z_readb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
 
@@ -119,8 +121,9 @@ static void zorro8390_get_8390_hdr(struct net_device *dev,
         * If it does, it's the last thing you'll see
         */
        if (ei_status.dmaing) {
-               netdev_err(dev, "%s: DMAing conflict [DMAstat:%d][irqlock:%d]\n",
-                          __func__, ei_status.dmaing, ei_status.irqlock);
+               netdev_warn(dev,
+                           "%s: DMAing conflict [DMAstat:%d][irqlock:%d]\n",
+                           __func__, ei_status.dmaing, ei_status.irqlock);
                return;
        }
 
@@ -230,7 +233,7 @@ static void zorro8390_block_output(struct net_device *dev, int count,
        while ((z_readb(NE_BASE + NE_EN0_ISR) & ENISR_RDC) == 0)
                if (time_after(jiffies, dma_start + 2 * HZ / 100)) {
                                        /* 20ms */
-                       netdev_err(dev, "timeout waiting for Tx RDC\n");
+                       netdev_warn(dev, "timeout waiting for Tx RDC\n");
                        zorro8390_reset_8390(dev);
                        __NS8390_init(dev, 1);
                        break;
@@ -248,8 +251,9 @@ static int zorro8390_open(struct net_device *dev)
 
 static int zorro8390_close(struct net_device *dev)
 {
-       if (ei_debug > 1)
-               netdev_dbg(dev, "Shutting down ethercard\n");
+       struct ei_device *ei_local = netdev_priv(dev);
+
+       netif_dbg(ei_local, ifdown, dev, "Shutting down ethercard\n");
        __ei_close(dev);
        return 0;
 }
@@ -287,12 +291,13 @@ static const struct net_device_ops zorro8390_netdev_ops = {
 };
 
 static int zorro8390_init(struct net_device *dev, unsigned long board,
-                         const char *name, unsigned long ioaddr)
+                         const char *name, void __iomem *ioaddr)
 {
        int i;
        int err;
        unsigned char SA_prom[32];
        int start_page, stop_page;
+       struct ei_device *ei_local = netdev_priv(dev);
        static u32 zorro8390_offsets[16] = {
                0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
                0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
@@ -354,7 +359,7 @@ static int zorro8390_init(struct net_device *dev, unsigned long board,
        start_page = NESM_START_PG;
        stop_page = NESM_STOP_PG;
 
-       dev->base_addr = ioaddr;
+       dev->base_addr = (unsigned long)ioaddr;
        dev->irq = IRQ_AMIGA_PORTS;
 
        /* Install the Interrupt handler */
@@ -383,6 +388,9 @@ static int zorro8390_init(struct net_device *dev, unsigned long board,
 
        dev->netdev_ops = &zorro8390_netdev_ops;
        __NS8390_init(dev, 0);
+
+       ei_local->msg_enable = zorro8390_msg_enable;
+
        err = register_netdev(dev);
        if (err) {
                free_irq(IRQ_AMIGA_PORTS, dev);
index 75fb1d20d6fd8ebff82f34da2b99271c1894fb4a..c0f68dcd1dc125c422d4d1d084b331a01beee2b3 100644 (file)
@@ -667,8 +667,8 @@ static u32 bfin_select_phc_clock(u32 input_clk, unsigned int *shift_result)
        return 1000000000UL / ppn;
 }
 
-static int bfin_mac_hwtstamp_ioctl(struct net_device *netdev,
-               struct ifreq *ifr, int cmd)
+static int bfin_mac_hwtstamp_set(struct net_device *netdev,
+                                struct ifreq *ifr)
 {
        struct hwtstamp_config config;
        struct bfin_mac_local *lp = netdev_priv(netdev);
@@ -824,6 +824,16 @@ static int bfin_mac_hwtstamp_ioctl(struct net_device *netdev,
                -EFAULT : 0;
 }
 
+static int bfin_mac_hwtstamp_get(struct net_device *netdev,
+                                struct ifreq *ifr)
+{
+       struct bfin_mac_local *lp = netdev_priv(netdev);
+
+       return copy_to_user(ifr->ifr_data, &lp->stamp_cfg,
+                           sizeof(lp->stamp_cfg)) ?
+               -EFAULT : 0;
+}
+
 static void bfin_tx_hwtstamp(struct net_device *netdev, struct sk_buff *skb)
 {
        struct bfin_mac_local *lp = netdev_priv(netdev);
@@ -1062,7 +1072,8 @@ static void bfin_phc_release(struct bfin_mac_local *lp)
 #else
 # define bfin_mac_hwtstamp_is_none(cfg) 0
 # define bfin_mac_hwtstamp_init(dev)
-# define bfin_mac_hwtstamp_ioctl(dev, ifr, cmd) (-EOPNOTSUPP)
+# define bfin_mac_hwtstamp_set(dev, ifr) (-EOPNOTSUPP)
+# define bfin_mac_hwtstamp_get(dev, ifr) (-EOPNOTSUPP)
 # define bfin_rx_hwtstamp(dev, skb)
 # define bfin_tx_hwtstamp(dev, skb)
 # define bfin_phc_init(netdev, dev) 0
@@ -1496,7 +1507,9 @@ static int bfin_mac_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
 
        switch (cmd) {
        case SIOCSHWTSTAMP:
-               return bfin_mac_hwtstamp_ioctl(netdev, ifr, cmd);
+               return bfin_mac_hwtstamp_set(netdev, ifr);
+       case SIOCGHWTSTAMP:
+               return bfin_mac_hwtstamp_get(netdev, ifr);
        default:
                if (lp->phydev)
                        return phy_mii_ioctl(lp->phydev, ifr, cmd);
@@ -1544,7 +1557,6 @@ static int bfin_mac_open(struct net_device *dev)
                return ret;
 
        phy_start(lp->phydev);
-       phy_write(lp->phydev, MII_BMCR, BMCR_RESET);
        setup_system_regs(dev);
        setup_mac_addr(dev->dev_addr);
 
index e0669455514458705fc5a321b1a82efb13891c2c..b20cbf0323e0ff4f87e852da3679002757862d39 100644 (file)
@@ -1361,7 +1361,7 @@ static int greth_mdio_init(struct greth_private *greth)
                timeout = jiffies + 6*HZ;
                while (!phy_aneg_done(greth->phy) && time_before(jiffies, timeout)) {
                }
-               genphy_read_status(greth->phy);
+               phy_read_status(greth->phy);
                greth_link_change(greth->netdev);
        }
 
index 50b853a79d7787c73d0ea8d0ac1f1e0853ac2adf..46dfb1378c17cac79064a5f3f809e94a1d75c584 100644 (file)
@@ -717,8 +717,7 @@ static int emac_open(struct net_device *dev)
        if (netif_msg_ifup(db))
                dev_dbg(db->dev, "enabling %s\n", dev->name);
 
-       if (devm_request_irq(db->dev, dev->irq, &emac_interrupt,
-                            0, dev->name, dev))
+       if (request_irq(dev->irq, &emac_interrupt, 0, dev->name, dev))
                return -EAGAIN;
 
        /* Initialize EMAC board */
@@ -774,6 +773,8 @@ static int emac_stop(struct net_device *ndev)
 
        emac_shutdown(ndev);
 
+       free_irq(ndev->irq, ndev);
+
        return 0;
 }
 
index 0866e7627433c1148037b9ade8064351c2819722..56139184b8019c132428654a5af6a4bd4018de14 100644 (file)
@@ -57,6 +57,7 @@
 #include <linux/zorro.h>
 #include <linux/bitops.h>
 
+#include <asm/byteorder.h>
 #include <asm/irq.h>
 #include <asm/amigaints.h>
 #include <asm/amigahw.h>
@@ -678,6 +679,7 @@ static int a2065_init_one(struct zorro_dev *z,
        unsigned long base_addr = board + A2065_LANCE;
        unsigned long mem_start = board + A2065_RAM;
        struct resource *r1, *r2;
+       u32 serial;
        int err;
 
        r1 = request_mem_region(base_addr, sizeof(struct lance_regs),
@@ -702,6 +704,7 @@ static int a2065_init_one(struct zorro_dev *z,
        r1->name = dev->name;
        r2->name = dev->name;
 
+       serial = be32_to_cpu(z->rom.er_SerialNumber);
        dev->dev_addr[0] = 0x00;
        if (z->id != ZORRO_PROD_AMERISTAR_A2065) {      /* Commodore */
                dev->dev_addr[1] = 0x80;
@@ -710,11 +713,11 @@ static int a2065_init_one(struct zorro_dev *z,
                dev->dev_addr[1] = 0x00;
                dev->dev_addr[2] = 0x9f;
        }
-       dev->dev_addr[3] = (z->rom.er_SerialNumber >> 16) & 0xff;
-       dev->dev_addr[4] = (z->rom.er_SerialNumber >> 8) & 0xff;
-       dev->dev_addr[5] = z->rom.er_SerialNumber & 0xff;
-       dev->base_addr = ZTWO_VADDR(base_addr);
-       dev->mem_start = ZTWO_VADDR(mem_start);
+       dev->dev_addr[3] = (serial >> 16) & 0xff;
+       dev->dev_addr[4] = (serial >> 8) & 0xff;
+       dev->dev_addr[5] = serial & 0xff;
+       dev->base_addr = (unsigned long)ZTWO_VADDR(base_addr);
+       dev->mem_start = (unsigned long)ZTWO_VADDR(mem_start);
        dev->mem_end = dev->mem_start + A2065_RAM_SIZE;
 
        priv->ll = (volatile struct lance_regs *)dev->base_addr;
index d042511bdc1365882a3bea08626bfce6bcc714da..d6beba0bc01f475f66aa22da7733e584c99b038b 100644 (file)
@@ -24,9 +24,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
 
 Module Name:
 
index 8baa3527ba746f289ed0aead68fd350be4bb09b0..b1fae36360d23daa1c489afe7cea325ac808b4c7 100644 (file)
@@ -13,9 +13,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
 
 Module Name:
 
index c178eb4c81668ad3a1b033f11c9070b9e63c934d..b08101b31b8bc547ffbfb486f87abc7a18f92686 100644 (file)
@@ -51,6 +51,7 @@
 #include <linux/zorro.h>
 #include <linux/bitops.h>
 
+#include <asm/byteorder.h>
 #include <asm/amigaints.h>
 #include <asm/amigahw.h>
 #include <asm/irq.h>
@@ -718,6 +719,7 @@ static int ariadne_init_one(struct zorro_dev *z,
        struct resource *r1, *r2;
        struct net_device *dev;
        struct ariadne_private *priv;
+       u32 serial;
        int err;
 
        r1 = request_mem_region(base_addr, sizeof(struct Am79C960), "Am79C960");
@@ -741,14 +743,15 @@ static int ariadne_init_one(struct zorro_dev *z,
        r1->name = dev->name;
        r2->name = dev->name;
 
+       serial = be32_to_cpu(z->rom.er_SerialNumber);
        dev->dev_addr[0] = 0x00;
        dev->dev_addr[1] = 0x60;
        dev->dev_addr[2] = 0x30;
-       dev->dev_addr[3] = (z->rom.er_SerialNumber >> 16) & 0xff;
-       dev->dev_addr[4] = (z->rom.er_SerialNumber >> 8) & 0xff;
-       dev->dev_addr[5] = z->rom.er_SerialNumber & 0xff;
-       dev->base_addr = ZTWO_VADDR(base_addr);
-       dev->mem_start = ZTWO_VADDR(mem_start);
+       dev->dev_addr[3] = (serial >> 16) & 0xff;
+       dev->dev_addr[4] = (serial >> 8) & 0xff;
+       dev->dev_addr[5] = serial & 0xff;
+       dev->base_addr = (unsigned long)ZTWO_VADDR(base_addr);
+       dev->mem_start = (unsigned long)ZTWO_VADDR(mem_start);
        dev->mem_end = dev->mem_start + ARIADNE_RAM_SIZE;
 
        dev->netdev_ops = &ariadne_netdev_ops;
index 427c148bb643538c1d2240036a9dd7cad1be9596..2eee5764805d71732d1af1da940f8da58202ae68 100644 (file)
@@ -27,8 +27,7 @@
  *  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.
+ *  with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * ########################################################################
  *
index 4b7f7ad62bb883dd08aae97187eafb25f9a432a8..ca53024f017f26ecd0b3a9c2bb0e90352bbe7c08 100644 (file)
@@ -18,8 +18,7 @@
  *  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.
+ *  with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * ########################################################################
  *
index dc08678bf9a4f1561e9d95c7126fe43eaa0ab6ea..928fac6dd10a90dca66244dba99194c9c9e2924d 100644 (file)
@@ -122,7 +122,6 @@ struct buffer_state {
  * @link:      PHY's last seen link state.
  * @duplex:    PHY's last set duplex mode.
  * @speed:     PHY's last set speed.
- * @max_speed: Maximum supported by current system network data-rate.
  */
 struct arc_emac_priv {
        /* Devices */
@@ -152,7 +151,6 @@ struct arc_emac_priv {
        unsigned int link;
        unsigned int duplex;
        unsigned int speed;
-       unsigned int max_speed;
 };
 
 /**
index b2ffad1304d221ef54e60cd1a82138a4d8344975..eedf2a5fc2be472084a3561b17ab4ecfd7134705 100644 (file)
@@ -381,17 +381,7 @@ static int arc_emac_open(struct net_device *ndev)
        phy_dev->autoneg = AUTONEG_ENABLE;
        phy_dev->speed = 0;
        phy_dev->duplex = 0;
-       phy_dev->advertising = phy_dev->supported;
-
-       if (priv->max_speed > 100) {
-               phy_dev->advertising &= PHY_GBIT_FEATURES;
-       } else if (priv->max_speed <= 100) {
-               phy_dev->advertising &= PHY_BASIC_FEATURES;
-               if (priv->max_speed <= 10) {
-                       phy_dev->advertising &= ~SUPPORTED_100baseT_Half;
-                       phy_dev->advertising &= ~SUPPORTED_100baseT_Full;
-               }
-       }
+       phy_dev->advertising &= phy_dev->supported;
 
        priv->last_rx_bd = 0;
 
@@ -704,14 +694,6 @@ static int arc_emac_probe(struct platform_device *pdev)
        /* Set poll rate so that it polls every 1 ms */
        arc_reg_set(priv, R_POLLRATE, clock_frequency / 1000000);
 
-       /* Get max speed of operation from device tree */
-       if (of_property_read_u32(pdev->dev.of_node, "max-speed",
-                                &priv->max_speed)) {
-               dev_err(&pdev->dev, "failed to retrieve <max-speed> from device tree\n");
-               err = -EINVAL;
-               goto out;
-       }
-
        ndev->irq = irq;
        dev_info(&pdev->dev, "IRQ is %d\n", ndev->irq);
 
index e2aa09ce6af7702d6d8a9063e9841f3c4f50c830..b665a6aa7e14f1c2e27b73c4ee43c1cdb0bb2fa6 100644 (file)
@@ -682,70 +682,6 @@ static int bgmac_phy_write(struct bgmac *bgmac, u8 phyaddr, u8 reg, u16 value)
        return 0;
 }
 
-/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphyforce */
-static void bgmac_phy_force(struct bgmac *bgmac)
-{
-       u16 ctl;
-       u16 mask = ~(BGMAC_PHY_CTL_SPEED | BGMAC_PHY_CTL_SPEED_MSB |
-                    BGMAC_PHY_CTL_ANENAB | BGMAC_PHY_CTL_DUPLEX);
-
-       if (bgmac->phyaddr == BGMAC_PHY_NOREGS)
-               return;
-
-       if (bgmac->autoneg)
-               return;
-
-       ctl = bgmac_phy_read(bgmac, bgmac->phyaddr, BGMAC_PHY_CTL);
-       ctl &= mask;
-       if (bgmac->full_duplex)
-               ctl |= BGMAC_PHY_CTL_DUPLEX;
-       if (bgmac->speed == BGMAC_SPEED_100)
-               ctl |= BGMAC_PHY_CTL_SPEED_100;
-       else if (bgmac->speed == BGMAC_SPEED_1000)
-               ctl |= BGMAC_PHY_CTL_SPEED_1000;
-       bgmac_phy_write(bgmac, bgmac->phyaddr, BGMAC_PHY_CTL, ctl);
-}
-
-/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphyadvertise */
-static void bgmac_phy_advertise(struct bgmac *bgmac)
-{
-       u16 adv;
-
-       if (bgmac->phyaddr == BGMAC_PHY_NOREGS)
-               return;
-
-       if (!bgmac->autoneg)
-               return;
-
-       /* Adv selected 10/100 speeds */
-       adv = bgmac_phy_read(bgmac, bgmac->phyaddr, BGMAC_PHY_ADV);
-       adv &= ~(BGMAC_PHY_ADV_10HALF | BGMAC_PHY_ADV_10FULL |
-                BGMAC_PHY_ADV_100HALF | BGMAC_PHY_ADV_100FULL);
-       if (!bgmac->full_duplex && bgmac->speed & BGMAC_SPEED_10)
-               adv |= BGMAC_PHY_ADV_10HALF;
-       if (!bgmac->full_duplex && bgmac->speed & BGMAC_SPEED_100)
-               adv |= BGMAC_PHY_ADV_100HALF;
-       if (bgmac->full_duplex && bgmac->speed & BGMAC_SPEED_10)
-               adv |= BGMAC_PHY_ADV_10FULL;
-       if (bgmac->full_duplex && bgmac->speed & BGMAC_SPEED_100)
-               adv |= BGMAC_PHY_ADV_100FULL;
-       bgmac_phy_write(bgmac, bgmac->phyaddr, BGMAC_PHY_ADV, adv);
-
-       /* Adv selected 1000 speeds */
-       adv = bgmac_phy_read(bgmac, bgmac->phyaddr, BGMAC_PHY_ADV2);
-       adv &= ~(BGMAC_PHY_ADV2_1000HALF | BGMAC_PHY_ADV2_1000FULL);
-       if (!bgmac->full_duplex && bgmac->speed & BGMAC_SPEED_1000)
-               adv |= BGMAC_PHY_ADV2_1000HALF;
-       if (bgmac->full_duplex && bgmac->speed & BGMAC_SPEED_1000)
-               adv |= BGMAC_PHY_ADV2_1000FULL;
-       bgmac_phy_write(bgmac, bgmac->phyaddr, BGMAC_PHY_ADV2, adv);
-
-       /* Restart */
-       bgmac_phy_write(bgmac, bgmac->phyaddr, BGMAC_PHY_CTL,
-                       bgmac_phy_read(bgmac, bgmac->phyaddr, BGMAC_PHY_CTL) |
-                       BGMAC_PHY_CTL_RESTART);
-}
-
 /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphyinit */
 static void bgmac_phy_init(struct bgmac *bgmac)
 {
@@ -876,19 +812,28 @@ static void bgmac_clear_mib(struct bgmac *bgmac)
 }
 
 /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/gmac_speed */
-static void bgmac_speed(struct bgmac *bgmac, int speed)
+static void bgmac_mac_speed(struct bgmac *bgmac)
 {
        u32 mask = ~(BGMAC_CMDCFG_ES_MASK | BGMAC_CMDCFG_HD);
        u32 set = 0;
 
-       if (speed & BGMAC_SPEED_10)
+       switch (bgmac->mac_speed) {
+       case SPEED_10:
                set |= BGMAC_CMDCFG_ES_10;
-       if (speed & BGMAC_SPEED_100)
+               break;
+       case SPEED_100:
                set |= BGMAC_CMDCFG_ES_100;
-       if (speed & BGMAC_SPEED_1000)
+               break;
+       case SPEED_1000:
                set |= BGMAC_CMDCFG_ES_1000;
-       if (!bgmac->full_duplex)
+               break;
+       default:
+               bgmac_err(bgmac, "Unsupported speed: %d\n", bgmac->mac_speed);
+       }
+
+       if (bgmac->mac_duplex == DUPLEX_HALF)
                set |= BGMAC_CMDCFG_HD;
+
        bgmac_cmdcfg_maskset(bgmac, mask, set, true);
 }
 
@@ -897,10 +842,9 @@ static void bgmac_miiconfig(struct bgmac *bgmac)
        u8 imode = (bgmac_read(bgmac, BGMAC_DEV_STATUS) & BGMAC_DS_MM_MASK) >>
                        BGMAC_DS_MM_SHIFT;
        if (imode == 0 || imode == 1) {
-               if (bgmac->autoneg)
-                       bgmac_speed(bgmac, BGMAC_SPEED_100);
-               else
-                       bgmac_speed(bgmac, bgmac->speed);
+               bgmac->mac_speed = SPEED_100;
+               bgmac->mac_duplex = DUPLEX_FULL;
+               bgmac_mac_speed(bgmac);
        }
 }
 
@@ -933,9 +877,9 @@ static void bgmac_chip_reset(struct bgmac *bgmac)
        }
 
        iost = bcma_aread32(core, BCMA_IOST);
-       if ((ci->id == BCMA_CHIP_ID_BCM5357 && ci->pkg == 10) ||
+       if ((ci->id == BCMA_CHIP_ID_BCM5357 && ci->pkg == BCMA_PKG_ID_BCM47186) ||
            (ci->id == BCMA_CHIP_ID_BCM4749 && ci->pkg == 10) ||
-           (ci->id == BCMA_CHIP_ID_BCM53572 && ci->pkg == 9))
+           (ci->id == BCMA_CHIP_ID_BCM53572 && ci->pkg == BCMA_PKG_ID_BCM47188))
                iost &= ~BGMAC_BCMA_IOST_ATTACHED;
 
        if (iost & BGMAC_BCMA_IOST_ATTACHED) {
@@ -947,12 +891,16 @@ static void bgmac_chip_reset(struct bgmac *bgmac)
        bcma_core_enable(core, flags);
 
        if (core->id.rev > 2) {
-               bgmac_set(bgmac, BCMA_CLKCTLST, 1 << 8);
-               bgmac_wait_value(bgmac->core, BCMA_CLKCTLST, 1 << 24, 1 << 24,
+               bgmac_set(bgmac, BCMA_CLKCTLST,
+                         BGMAC_BCMA_CLKCTLST_MISC_PLL_REQ);
+               bgmac_wait_value(bgmac->core, BCMA_CLKCTLST,
+                                BGMAC_BCMA_CLKCTLST_MISC_PLL_ST,
+                                BGMAC_BCMA_CLKCTLST_MISC_PLL_ST,
                                 1000);
        }
 
-       if (ci->id == BCMA_CHIP_ID_BCM5357 || ci->id == BCMA_CHIP_ID_BCM4749 ||
+       if (ci->id == BCMA_CHIP_ID_BCM5357 ||
+           ci->id == BCMA_CHIP_ID_BCM4749 ||
            ci->id == BCMA_CHIP_ID_BCM53572) {
                struct bcma_drv_cc *cc = &bgmac->core->bus->drv_cc;
                u8 et_swtype = 0;
@@ -967,10 +915,11 @@ static void bgmac_chip_reset(struct bgmac *bgmac)
                        et_swtype &= 0x0f;
                        et_swtype <<= 4;
                        sw_type = et_swtype;
-               } else if (ci->id == BCMA_CHIP_ID_BCM5357 && ci->pkg == 9) {
+               } else if (ci->id == BCMA_CHIP_ID_BCM5357 && ci->pkg == BCMA_PKG_ID_BCM5358) {
                        sw_type = BGMAC_CHIPCTL_1_SW_TYPE_EPHYRMII;
-               } else if ((ci->id != BCMA_CHIP_ID_BCM53572 && ci->pkg == 10) ||
-                          (ci->id == BCMA_CHIP_ID_BCM53572 && ci->pkg == 9)) {
+               } else if ((ci->id == BCMA_CHIP_ID_BCM5357 && ci->pkg == BCMA_PKG_ID_BCM47186) ||
+                          (ci->id == BCMA_CHIP_ID_BCM4749 && ci->pkg == 10) ||
+                          (ci->id == BCMA_CHIP_ID_BCM53572 && ci->pkg == BCMA_PKG_ID_BCM47188)) {
                        sw_type = BGMAC_CHIPCTL_1_IF_TYPE_RGMII |
                                  BGMAC_CHIPCTL_1_SW_TYPE_RGMII;
                }
@@ -1009,6 +958,8 @@ static void bgmac_chip_reset(struct bgmac *bgmac)
                             BGMAC_CMDCFG_CFE |
                             BGMAC_CMDCFG_SR,
                             false);
+       bgmac->mac_speed = SPEED_UNKNOWN;
+       bgmac->mac_duplex = DUPLEX_UNKNOWN;
 
        bgmac_clear_mib(bgmac);
        if (core->id.id == BCMA_CORE_4706_MAC_GBIT)
@@ -1108,13 +1059,6 @@ static void bgmac_chip_init(struct bgmac *bgmac, bool full_init)
 
        bgmac_write(bgmac, BGMAC_RXMAX_LENGTH, 32 + ETHER_MAX_LEN);
 
-       if (!bgmac->autoneg) {
-               bgmac_speed(bgmac, bgmac->speed);
-               bgmac_phy_force(bgmac);
-       } else if (bgmac->speed) { /* if there is anything to adv */
-               bgmac_phy_advertise(bgmac);
-       }
-
        if (full_init) {
                bgmac_dma_init(bgmac);
                if (1) /* FIXME: is there any case we don't want IRQs? */
@@ -1204,6 +1148,8 @@ static int bgmac_open(struct net_device *net_dev)
        }
        napi_enable(&bgmac->napi);
 
+       phy_start(bgmac->phy_dev);
+
        netif_carrier_on(net_dev);
 
 err_out:
@@ -1216,6 +1162,8 @@ static int bgmac_stop(struct net_device *net_dev)
 
        netif_carrier_off(net_dev);
 
+       phy_stop(bgmac->phy_dev);
+
        napi_disable(&bgmac->napi);
        bgmac_chip_intrs_off(bgmac);
        free_irq(bgmac->core->irq, net_dev);
@@ -1294,61 +1242,16 @@ static int bgmac_get_settings(struct net_device *net_dev,
 {
        struct bgmac *bgmac = netdev_priv(net_dev);
 
-       cmd->supported = SUPPORTED_10baseT_Half |
-                        SUPPORTED_10baseT_Full |
-                        SUPPORTED_100baseT_Half |
-                        SUPPORTED_100baseT_Full |
-                        SUPPORTED_1000baseT_Half |
-                        SUPPORTED_1000baseT_Full |
-                        SUPPORTED_Autoneg;
-
-       if (bgmac->autoneg) {
-               WARN_ON(cmd->advertising);
-               if (bgmac->full_duplex) {
-                       if (bgmac->speed & BGMAC_SPEED_10)
-                               cmd->advertising |= ADVERTISED_10baseT_Full;
-                       if (bgmac->speed & BGMAC_SPEED_100)
-                               cmd->advertising |= ADVERTISED_100baseT_Full;
-                       if (bgmac->speed & BGMAC_SPEED_1000)
-                               cmd->advertising |= ADVERTISED_1000baseT_Full;
-               } else {
-                       if (bgmac->speed & BGMAC_SPEED_10)
-                               cmd->advertising |= ADVERTISED_10baseT_Half;
-                       if (bgmac->speed & BGMAC_SPEED_100)
-                               cmd->advertising |= ADVERTISED_100baseT_Half;
-                       if (bgmac->speed & BGMAC_SPEED_1000)
-                               cmd->advertising |= ADVERTISED_1000baseT_Half;
-               }
-       } else {
-               switch (bgmac->speed) {
-               case BGMAC_SPEED_10:
-                       ethtool_cmd_speed_set(cmd, SPEED_10);
-                       break;
-               case BGMAC_SPEED_100:
-                       ethtool_cmd_speed_set(cmd, SPEED_100);
-                       break;
-               case BGMAC_SPEED_1000:
-                       ethtool_cmd_speed_set(cmd, SPEED_1000);
-                       break;
-               }
-       }
-
-       cmd->duplex = bgmac->full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
-
-       cmd->autoneg = bgmac->autoneg;
-
-       return 0;
+       return phy_ethtool_gset(bgmac->phy_dev, cmd);
 }
 
-#if 0
 static int bgmac_set_settings(struct net_device *net_dev,
                              struct ethtool_cmd *cmd)
 {
        struct bgmac *bgmac = netdev_priv(net_dev);
 
-       return -1;
+       return phy_ethtool_sset(bgmac->phy_dev, cmd);
 }
-#endif
 
 static void bgmac_get_drvinfo(struct net_device *net_dev,
                              struct ethtool_drvinfo *info)
@@ -1359,6 +1262,7 @@ static void bgmac_get_drvinfo(struct net_device *net_dev,
 
 static const struct ethtool_ops bgmac_ethtool_ops = {
        .get_settings           = bgmac_get_settings,
+       .set_settings           = bgmac_set_settings,
        .get_drvinfo            = bgmac_get_drvinfo,
 };
 
@@ -1377,9 +1281,35 @@ static int bgmac_mii_write(struct mii_bus *bus, int mii_id, int regnum,
        return bgmac_phy_write(bus->priv, mii_id, regnum, value);
 }
 
+static void bgmac_adjust_link(struct net_device *net_dev)
+{
+       struct bgmac *bgmac = netdev_priv(net_dev);
+       struct phy_device *phy_dev = bgmac->phy_dev;
+       bool update = false;
+
+       if (phy_dev->link) {
+               if (phy_dev->speed != bgmac->mac_speed) {
+                       bgmac->mac_speed = phy_dev->speed;
+                       update = true;
+               }
+
+               if (phy_dev->duplex != bgmac->mac_duplex) {
+                       bgmac->mac_duplex = phy_dev->duplex;
+                       update = true;
+               }
+       }
+
+       if (update) {
+               bgmac_mac_speed(bgmac);
+               phy_print_status(phy_dev);
+       }
+}
+
 static int bgmac_mii_register(struct bgmac *bgmac)
 {
        struct mii_bus *mii_bus;
+       struct phy_device *phy_dev;
+       char bus_id[MII_BUS_ID_SIZE + 3];
        int i, err = 0;
 
        mii_bus = mdiobus_alloc();
@@ -1411,8 +1341,22 @@ static int bgmac_mii_register(struct bgmac *bgmac)
 
        bgmac->mii_bus = mii_bus;
 
+       /* Connect to the PHY */
+       snprintf(bus_id, sizeof(bus_id), PHY_ID_FMT, mii_bus->id,
+                bgmac->phyaddr);
+       phy_dev = phy_connect(bgmac->net_dev, bus_id, &bgmac_adjust_link,
+                             PHY_INTERFACE_MODE_MII);
+       if (IS_ERR(phy_dev)) {
+               bgmac_err(bgmac, "PHY connecton failed\n");
+               err = PTR_ERR(phy_dev);
+               goto err_unregister_bus;
+       }
+       bgmac->phy_dev = phy_dev;
+
        return err;
 
+err_unregister_bus:
+       mdiobus_unregister(mii_bus);
 err_free_irq:
        kfree(mii_bus->irq);
 err_free_bus:
@@ -1467,9 +1411,6 @@ static int bgmac_probe(struct bcma_device *core)
        bcma_set_drvdata(core, bgmac);
 
        /* Defaults */
-       bgmac->autoneg = true;
-       bgmac->full_duplex = true;
-       bgmac->speed = BGMAC_SPEED_10 | BGMAC_SPEED_100 | BGMAC_SPEED_1000;
        memcpy(bgmac->net_dev->dev_addr, mac, ETH_ALEN);
 
        /* On BCM4706 we need common core to access PHY */
index 66c8afbdc8c7fd863337da4795df8df9443ae120..2d44119a764893bbdcf58bed93798f47779ef22d 100644 (file)
 #define  BGMAC_RXQ_CTL_MDP_SHIFT               24
 #define BGMAC_GPIO_SELECT                      0x194
 #define BGMAC_GPIO_OUTPUT_EN                   0x198
-/* For 0x1e0 see BCMA_CLKCTLST */
+
+/* For 0x1e0 see BCMA_CLKCTLST. Below are BGMAC specific bits */
+#define  BGMAC_BCMA_CLKCTLST_MISC_PLL_REQ      0x00000100
+#define  BGMAC_BCMA_CLKCTLST_MISC_PLL_ST       0x01000000
+
 #define BGMAC_HW_WAR                           0x1e4
 #define BGMAC_PWR_CTL                          0x1e8
 #define BGMAC_DMA_BASE0                                0x200           /* Tx and Rx controller */
 #define BGMAC_CHIPCTL_1_SW_TYPE_RGMII          0x000000C0
 #define BGMAC_CHIPCTL_1_RXC_DLL_BYPASS         0x00010000
 
-#define BGMAC_SPEED_10                         0x0001
-#define BGMAC_SPEED_100                                0x0002
-#define BGMAC_SPEED_1000                       0x0004
-
 #define BGMAC_WEIGHT   64
 
 #define ETHER_MAX_LEN   1518
@@ -402,6 +402,7 @@ struct bgmac {
        struct net_device *net_dev;
        struct napi_struct napi;
        struct mii_bus *mii_bus;
+       struct phy_device *phy_dev;
 
        /* DMA */
        struct bgmac_dma_ring tx_ring[BGMAC_MAX_TX_RINGS];
@@ -416,10 +417,9 @@ struct bgmac {
        u32 int_mask;
        u32 int_status;
 
-       /* Speed-related */
-       int speed;
-       bool autoneg;
-       bool full_duplex;
+       /* Current MAC state */
+       int mac_speed;
+       int mac_duplex;
 
        u8 phyaddr;
        bool has_robosw;
index 0216d592d0cee4b080a9d33d7776f632bf639453..2e46c28fc6019a892f7792c6017effe3f7db7063 100644 (file)
@@ -3114,6 +3114,11 @@ int bnx2x_sriov_configure(struct pci_dev *dev, int num_vfs_param)
 {
        struct bnx2x *bp = netdev_priv(pci_get_drvdata(dev));
 
+       if (!IS_SRIOV(bp)) {
+               BNX2X_ERR("failed to configure SR-IOV since vfdb was not allocated. Check dmesg for errors in probe stage\n");
+               return -EINVAL;
+       }
+
        DP(BNX2X_MSG_IOV, "bnx2x_sriov_configure called with %d, BNX2X_NR_VIRTFN(bp) was %d\n",
           num_vfs_param, BNX2X_NR_VIRTFN(bp));
 
index c2777712da991dd72b876eac74fb991c73b12010..31a076d86709f2256c9a1ebe4ab93d0a5e7c9c41 100644 (file)
@@ -13,8 +13,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  *
  * This driver is designed for the Broadcom SiByte SOC built-in
index a9e068423ba0651414cc0c5b23f0eda6937a6c23..a8def93f6b6b7a1cf5b02bfa988a6c701a7797d9 100644 (file)
@@ -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                    134
+#define TG3_MIN_NUM                    135
 #define DRV_MODULE_VERSION     \
        __stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM)
-#define DRV_MODULE_RELDATE     "Sep 16, 2013"
+#define DRV_MODULE_RELDATE     "Nov 14, 2013"
 
 #define RESET_KIND_SHUTDOWN    0
 #define RESET_KIND_INIT                1
@@ -4403,9 +4403,12 @@ static void tg3_phy_copper_begin(struct tg3 *tp)
                        if (tg3_flag(tp, WOL_SPEED_100MB))
                                adv |= ADVERTISED_100baseT_Half |
                                       ADVERTISED_100baseT_Full;
-                       if (tp->phy_flags & TG3_PHYFLG_1G_ON_VAUX_OK)
-                               adv |= ADVERTISED_1000baseT_Half |
-                                      ADVERTISED_1000baseT_Full;
+                       if (tp->phy_flags & TG3_PHYFLG_1G_ON_VAUX_OK) {
+                               if (!(tp->phy_flags &
+                                     TG3_PHYFLG_DISABLE_1G_HD_ADV))
+                                       adv |= ADVERTISED_1000baseT_Half;
+                               adv |= ADVERTISED_1000baseT_Full;
+                       }
 
                        fc = FLOW_CTRL_TX | FLOW_CTRL_RX;
                } else {
@@ -8932,6 +8935,9 @@ static int tg3_chip_reset(struct tg3 *tp)
        void (*write_op)(struct tg3 *, u32, u32);
        int i, err;
 
+       if (!pci_device_is_present(tp->pdev))
+               return -ENODEV;
+
        tg3_nvram_lock(tp);
 
        tg3_ape_lock(tp, TG3_APE_LOCK_GRC);
@@ -9963,6 +9969,7 @@ static int tg3_reset_hw(struct tg3 *tp, bool reset_phy)
        if (tg3_asic_rev(tp) == ASIC_REV_5719)
                val |= BUFMGR_MODE_NO_TX_UNDERRUN;
        if (tg3_asic_rev(tp) == ASIC_REV_5717 ||
+           tg3_asic_rev(tp) == ASIC_REV_5762 ||
            tg3_chip_rev_id(tp) == CHIPREV_ID_5719_A0 ||
            tg3_chip_rev_id(tp) == CHIPREV_ID_5720_A0)
                val |= BUFMGR_MODE_MBLOW_ATTN_ENAB;
@@ -10629,10 +10636,8 @@ static void tg3_sd_scan_scratchpad(struct tg3 *tp, struct tg3_ocir *ocir)
 static ssize_t tg3_show_temp(struct device *dev,
                             struct device_attribute *devattr, char *buf)
 {
-       struct pci_dev *pdev = to_pci_dev(dev);
-       struct net_device *netdev = pci_get_drvdata(pdev);
-       struct tg3 *tp = netdev_priv(netdev);
        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct tg3 *tp = dev_get_drvdata(dev);
        u32 temperature;
 
        spin_lock_bh(&tp->lock);
@@ -10650,29 +10655,25 @@ static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, tg3_show_temp, NULL,
 static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, tg3_show_temp, NULL,
                          TG3_TEMP_MAX_OFFSET);
 
-static struct attribute *tg3_attributes[] = {
+static struct attribute *tg3_attrs[] = {
        &sensor_dev_attr_temp1_input.dev_attr.attr,
        &sensor_dev_attr_temp1_crit.dev_attr.attr,
        &sensor_dev_attr_temp1_max.dev_attr.attr,
        NULL
 };
-
-static const struct attribute_group tg3_group = {
-       .attrs = tg3_attributes,
-};
+ATTRIBUTE_GROUPS(tg3);
 
 static void tg3_hwmon_close(struct tg3 *tp)
 {
        if (tp->hwmon_dev) {
                hwmon_device_unregister(tp->hwmon_dev);
                tp->hwmon_dev = NULL;
-               sysfs_remove_group(&tp->pdev->dev.kobj, &tg3_group);
        }
 }
 
 static void tg3_hwmon_open(struct tg3 *tp)
 {
-       int i, err;
+       int i;
        u32 size = 0;
        struct pci_dev *pdev = tp->pdev;
        struct tg3_ocir ocirs[TG3_SD_NUM_RECS];
@@ -10690,18 +10691,11 @@ static void tg3_hwmon_open(struct tg3 *tp)
        if (!size)
                return;
 
-       /* Register hwmon sysfs hooks */
-       err = sysfs_create_group(&pdev->dev.kobj, &tg3_group);
-       if (err) {
-               dev_err(&pdev->dev, "Cannot create sysfs group, aborting\n");
-               return;
-       }
-
-       tp->hwmon_dev = hwmon_device_register(&pdev->dev);
+       tp->hwmon_dev = hwmon_device_register_with_groups(&pdev->dev, "tg3",
+                                                         tp, tg3_groups);
        if (IS_ERR(tp->hwmon_dev)) {
                tp->hwmon_dev = NULL;
                dev_err(&pdev->dev, "Cannot register hwmon device, aborting\n");
-               sysfs_remove_group(&pdev->dev.kobj, &tg3_group);
        }
 }
 
@@ -10761,6 +10755,7 @@ static void tg3_periodic_fetch_stats(struct tg3 *tp)
 
        TG3_STAT_ADD32(&sp->rxbds_empty, RCVLPC_NO_RCV_BD_CNT);
        if (tg3_asic_rev(tp) != ASIC_REV_5717 &&
+           tg3_asic_rev(tp) != ASIC_REV_5762 &&
            tg3_chip_rev_id(tp) != CHIPREV_ID_5719_A0 &&
            tg3_chip_rev_id(tp) != CHIPREV_ID_5720_A0) {
                TG3_STAT_ADD32(&sp->rx_discards, RCVLPC_IN_DISCARDS_CNT);
@@ -11594,10 +11589,11 @@ static int tg3_close(struct net_device *dev)
        memset(&tp->net_stats_prev, 0, sizeof(tp->net_stats_prev));
        memset(&tp->estats_prev, 0, sizeof(tp->estats_prev));
 
-       tg3_power_down_prepare(tp);
-
-       tg3_carrier_off(tp);
+       if (pci_device_is_present(tp->pdev)) {
+               tg3_power_down_prepare(tp);
 
+               tg3_carrier_off(tp);
+       }
        return 0;
 }
 
@@ -11755,8 +11751,6 @@ static void tg3_get_nstats(struct tg3 *tp, struct rtnl_link_stats64 *stats)
                get_stat64(&hw_stats->rx_frame_too_long_errors) +
                get_stat64(&hw_stats->rx_undersize_packets);
 
-       stats->rx_over_errors = old_stats->rx_over_errors +
-               get_stat64(&hw_stats->rxbds_empty);
        stats->rx_frame_errors = old_stats->rx_frame_errors +
                get_stat64(&hw_stats->rx_align_errors);
        stats->tx_aborted_errors = old_stats->tx_aborted_errors +
@@ -13603,14 +13597,13 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
 
 }
 
-static int tg3_hwtstamp_ioctl(struct net_device *dev,
-                             struct ifreq *ifr, int cmd)
+static int tg3_hwtstamp_set(struct net_device *dev, struct ifreq *ifr)
 {
        struct tg3 *tp = netdev_priv(dev);
        struct hwtstamp_config stmpconf;
 
        if (!tg3_flag(tp, PTP_CAPABLE))
-               return -EINVAL;
+               return -EOPNOTSUPP;
 
        if (copy_from_user(&stmpconf, ifr->ifr_data, sizeof(stmpconf)))
                return -EFAULT;
@@ -13691,6 +13684,67 @@ static int tg3_hwtstamp_ioctl(struct net_device *dev,
                -EFAULT : 0;
 }
 
+static int tg3_hwtstamp_get(struct net_device *dev, struct ifreq *ifr)
+{
+       struct tg3 *tp = netdev_priv(dev);
+       struct hwtstamp_config stmpconf;
+
+       if (!tg3_flag(tp, PTP_CAPABLE))
+               return -EOPNOTSUPP;
+
+       stmpconf.flags = 0;
+       stmpconf.tx_type = (tg3_flag(tp, TX_TSTAMP_EN) ?
+                           HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF);
+
+       switch (tp->rxptpctl) {
+       case 0:
+               stmpconf.rx_filter = HWTSTAMP_FILTER_NONE;
+               break;
+       case TG3_RX_PTP_CTL_RX_PTP_V1_EN | TG3_RX_PTP_CTL_ALL_V1_EVENTS:
+               stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
+               break;
+       case TG3_RX_PTP_CTL_RX_PTP_V1_EN | TG3_RX_PTP_CTL_SYNC_EVNT:
+               stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_SYNC;
+               break;
+       case TG3_RX_PTP_CTL_RX_PTP_V1_EN | TG3_RX_PTP_CTL_DELAY_REQ:
+               stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ;
+               break;
+       case TG3_RX_PTP_CTL_RX_PTP_V2_EN | TG3_RX_PTP_CTL_ALL_V2_EVENTS:
+               stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
+               break;
+       case TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN | TG3_RX_PTP_CTL_ALL_V2_EVENTS:
+               stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
+               break;
+       case TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN | TG3_RX_PTP_CTL_ALL_V2_EVENTS:
+               stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT;
+               break;
+       case TG3_RX_PTP_CTL_RX_PTP_V2_EN | TG3_RX_PTP_CTL_SYNC_EVNT:
+               stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_SYNC;
+               break;
+       case TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN | TG3_RX_PTP_CTL_SYNC_EVNT:
+               stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_SYNC;
+               break;
+       case TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN | TG3_RX_PTP_CTL_SYNC_EVNT:
+               stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_SYNC;
+               break;
+       case TG3_RX_PTP_CTL_RX_PTP_V2_EN | TG3_RX_PTP_CTL_DELAY_REQ:
+               stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_DELAY_REQ;
+               break;
+       case TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN | TG3_RX_PTP_CTL_DELAY_REQ:
+               stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ;
+               break;
+       case TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN | TG3_RX_PTP_CTL_DELAY_REQ:
+               stmpconf.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ;
+               break;
+       default:
+               WARN_ON_ONCE(1);
+               return -ERANGE;
+       }
+
+       return copy_to_user(ifr->ifr_data, &stmpconf, sizeof(stmpconf)) ?
+               -EFAULT : 0;
+}
+
 static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
        struct mii_ioctl_data *data = if_mii(ifr);
@@ -13744,7 +13798,10 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                return err;
 
        case SIOCSHWTSTAMP:
-               return tg3_hwtstamp_ioctl(dev, ifr, cmd);
+               return tg3_hwtstamp_set(dev, ifr);
+
+       case SIOCGHWTSTAMP:
+               return tg3_hwtstamp_get(dev, ifr);
 
        default:
                /* do nothing */
@@ -14865,7 +14922,8 @@ static void tg3_get_eeprom_hw_cfg(struct tg3 *tp)
        tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val);
        if (val == NIC_SRAM_DATA_SIG_MAGIC) {
                u32 nic_cfg, led_cfg;
-               u32 nic_phy_id, ver, cfg2 = 0, cfg4 = 0, eeprom_phy_id;
+               u32 cfg2 = 0, cfg4 = 0, cfg5 = 0;
+               u32 nic_phy_id, ver, eeprom_phy_id;
                int eeprom_phy_serdes = 0;
 
                tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg);
@@ -14882,6 +14940,11 @@ static void tg3_get_eeprom_hw_cfg(struct tg3 *tp)
                if (tg3_asic_rev(tp) == ASIC_REV_5785)
                        tg3_read_mem(tp, NIC_SRAM_DATA_CFG_4, &cfg4);
 
+               if (tg3_asic_rev(tp) == ASIC_REV_5717 ||
+                   tg3_asic_rev(tp) == ASIC_REV_5719 ||
+                   tg3_asic_rev(tp) == ASIC_REV_5720)
+                       tg3_read_mem(tp, NIC_SRAM_DATA_CFG_5, &cfg5);
+
                if ((nic_cfg & NIC_SRAM_DATA_CFG_PHY_TYPE_MASK) ==
                    NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER)
                        eeprom_phy_serdes = 1;
@@ -15034,6 +15097,9 @@ static void tg3_get_eeprom_hw_cfg(struct tg3 *tp)
                        tg3_flag_set(tp, RGMII_EXT_IBND_RX_EN);
                if (cfg4 & NIC_SRAM_RGMII_EXT_IBND_TX_EN)
                        tg3_flag_set(tp, RGMII_EXT_IBND_TX_EN);
+
+               if (cfg5 & NIC_SRAM_DISABLE_1G_HALF_ADV)
+                       tp->phy_flags |= TG3_PHYFLG_DISABLE_1G_HD_ADV;
        }
 done:
        if (tg3_flag(tp, WOL_CAP))
@@ -15129,9 +15195,11 @@ static void tg3_phy_init_link_config(struct tg3 *tp)
 {
        u32 adv = ADVERTISED_Autoneg;
 
-       if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY))
-               adv |= ADVERTISED_1000baseT_Half |
-                      ADVERTISED_1000baseT_Full;
+       if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) {
+               if (!(tp->phy_flags & TG3_PHYFLG_DISABLE_1G_HD_ADV))
+                       adv |= ADVERTISED_1000baseT_Half;
+               adv |= ADVERTISED_1000baseT_Full;
+       }
 
        if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES))
                adv |= ADVERTISED_100baseT_Half |
@@ -16479,6 +16547,7 @@ static int tg3_get_invariants(struct tg3 *tp, const struct pci_device_id *ent)
 
        /* Set these bits to enable statistics workaround. */
        if (tg3_asic_rev(tp) == ASIC_REV_5717 ||
+           tg3_asic_rev(tp) == ASIC_REV_5762 ||
            tg3_chip_rev_id(tp) == CHIPREV_ID_5719_A0 ||
            tg3_chip_rev_id(tp) == CHIPREV_ID_5720_A0) {
                tp->coalesce_mode |= HOSTCC_MODE_ATTN;
@@ -16512,6 +16581,9 @@ static int tg3_get_invariants(struct tg3 *tp, const struct pci_device_id *ent)
        /* Clear this out for sanity. */
        tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0);
 
+       /* Clear TG3PCI_REG_BASE_ADDR to prevent hangs. */
+       tw32(TG3PCI_REG_BASE_ADDR, 0);
+
        pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE,
                              &pci_state_reg);
        if ((pci_state_reg & PCISTATE_CONV_PCI_MODE) == 0 &&
@@ -17739,10 +17811,12 @@ static int tg3_suspend(struct device *device)
        struct pci_dev *pdev = to_pci_dev(device);
        struct net_device *dev = pci_get_drvdata(pdev);
        struct tg3 *tp = netdev_priv(dev);
-       int err;
+       int err = 0;
+
+       rtnl_lock();
 
        if (!netif_running(dev))
-               return 0;
+               goto unlock;
 
        tg3_reset_task_cancel(tp);
        tg3_phy_stop(tp);
@@ -17784,6 +17858,8 @@ out:
                        tg3_phy_start(tp);
        }
 
+unlock:
+       rtnl_unlock();
        return err;
 }
 
@@ -17792,10 +17868,12 @@ static int tg3_resume(struct device *device)
        struct pci_dev *pdev = to_pci_dev(device);
        struct net_device *dev = pci_get_drvdata(pdev);
        struct tg3 *tp = netdev_priv(dev);
-       int err;
+       int err = 0;
+
+       rtnl_lock();
 
        if (!netif_running(dev))
-               return 0;
+               goto unlock;
 
        netif_device_attach(dev);
 
@@ -17819,6 +17897,8 @@ out:
        if (!err)
                tg3_phy_start(tp);
 
+unlock:
+       rtnl_unlock();
        return err;
 }
 #endif /* CONFIG_PM_SLEEP */
index 5c3835aa1e1b0702d602102031a260644129390e..e4da9d7834ce330ca895bbd2391776255f03bd4f 100644 (file)
 
 #define NIC_SRAM_DATA_CFG_2            0x00000d38
 
-#define  NIC_SRAM_DATA_CFG_2_APD_EN     0x00000400
+#define  NIC_SRAM_DATA_CFG_2_APD_EN     0x00004000
 #define  SHASTA_EXT_LED_MODE_MASK       0x00018000
 #define  SHASTA_EXT_LED_LEGACY          0x00000000
 #define  SHASTA_EXT_LED_SHARED          0x00008000
 #define  NIC_SRAM_CPMUSTAT_SIG         0x0000362c
 #define  NIC_SRAM_CPMUSTAT_SIG_MSK     0x0000ffff
 
+#define NIC_SRAM_DATA_CFG_5            0x00000e0c
+#define  NIC_SRAM_DISABLE_1G_HALF_ADV  0x00000002
+
 #define NIC_SRAM_RX_MINI_BUFFER_DESC   0x00001000
 
 #define NIC_SRAM_DMA_DESC_POOL_BASE    0x00002000
@@ -3325,6 +3328,7 @@ struct tg3 {
 #define TG3_PHYFLG_1G_ON_VAUX_OK       0x00080000
 #define TG3_PHYFLG_KEEP_LINK_ON_PWRDN  0x00100000
 #define TG3_PHYFLG_MDIX_STATE          0x00200000
+#define TG3_PHYFLG_DISABLE_1G_HD_ADV   0x00400000
 
        u32                             led_ctrl;
        u32                             phy_otp;
index 248bc37cb41b24680441c057312e9882f905dd1d..3d151bd1635ee3c37374261f510c17e31d2ff19a 100644 (file)
@@ -3262,7 +3262,6 @@ bnad_uninit(struct bnad *bnad)
 
        if (bnad->bar0)
                iounmap(bnad->bar0);
-       pci_set_drvdata(bnad->pcidev, NULL);
 }
 
 /*
index 92578690f6de326dc4c6530bec4d867a384894eb..3190d38e16fbd5d59a8cbc0cca7378a500572402 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/circ_buf.h>
 #include <linux/slab.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/gpio.h>
 #include <linux/interrupt.h>
 #include <linux/netdevice.h>
@@ -203,6 +204,47 @@ static int macb_mdio_reset(struct mii_bus *bus)
        return 0;
 }
 
+/**
+ * macb_set_tx_clk() - Set a clock to a new frequency
+ * @clk                Pointer to the clock to change
+ * @rate       New frequency in Hz
+ * @dev                Pointer to the struct net_device
+ */
+static void macb_set_tx_clk(struct clk *clk, int speed, struct net_device *dev)
+{
+       long ferr, rate, rate_rounded;
+
+       switch (speed) {
+       case SPEED_10:
+               rate = 2500000;
+               break;
+       case SPEED_100:
+               rate = 25000000;
+               break;
+       case SPEED_1000:
+               rate = 125000000;
+               break;
+       default:
+               return;
+       }
+
+       rate_rounded = clk_round_rate(clk, rate);
+       if (rate_rounded < 0)
+               return;
+
+       /* RGMII allows 50 ppm frequency error. Test and warn if this limit
+        * is not satisfied.
+        */
+       ferr = abs(rate_rounded - rate);
+       ferr = DIV_ROUND_UP(ferr, rate / 100000);
+       if (ferr > 5)
+               netdev_warn(dev, "unable to generate target frequency: %ld Hz\n",
+                               rate);
+
+       if (clk_set_rate(clk, rate_rounded))
+               netdev_err(dev, "adjusting tx_clk failed.\n");
+}
+
 static void macb_handle_link_change(struct net_device *dev)
 {
        struct macb *bp = netdev_priv(dev);
@@ -250,6 +292,9 @@ static void macb_handle_link_change(struct net_device *dev)
 
        spin_unlock_irqrestore(&bp->lock, flags);
 
+       if (!IS_ERR(bp->tx_clk))
+               macb_set_tx_clk(bp->tx_clk, phydev->speed, dev);
+
        if (status_change) {
                if (phydev->link) {
                        netif_carrier_on(dev);
@@ -1790,21 +1835,44 @@ static int __init macb_probe(struct platform_device *pdev)
        spin_lock_init(&bp->lock);
        INIT_WORK(&bp->tx_error_task, macb_tx_error_task);
 
-       bp->pclk = clk_get(&pdev->dev, "pclk");
+       bp->pclk = devm_clk_get(&pdev->dev, "pclk");
        if (IS_ERR(bp->pclk)) {
-               dev_err(&pdev->dev, "failed to get macb_clk\n");
+               err = PTR_ERR(bp->pclk);
+               dev_err(&pdev->dev, "failed to get macb_clk (%u)\n", err);
                goto err_out_free_dev;
        }
-       clk_prepare_enable(bp->pclk);
 
-       bp->hclk = clk_get(&pdev->dev, "hclk");
+       bp->hclk = devm_clk_get(&pdev->dev, "hclk");
        if (IS_ERR(bp->hclk)) {
-               dev_err(&pdev->dev, "failed to get hclk\n");
-               goto err_out_put_pclk;
+               err = PTR_ERR(bp->hclk);
+               dev_err(&pdev->dev, "failed to get hclk (%u)\n", err);
+               goto err_out_free_dev;
        }
-       clk_prepare_enable(bp->hclk);
 
-       bp->regs = ioremap(regs->start, resource_size(regs));
+       bp->tx_clk = devm_clk_get(&pdev->dev, "tx_clk");
+
+       err = clk_prepare_enable(bp->pclk);
+       if (err) {
+               dev_err(&pdev->dev, "failed to enable pclk (%u)\n", err);
+               goto err_out_free_dev;
+       }
+
+       err = clk_prepare_enable(bp->hclk);
+       if (err) {
+               dev_err(&pdev->dev, "failed to enable hclk (%u)\n", err);
+               goto err_out_disable_pclk;
+       }
+
+       if (!IS_ERR(bp->tx_clk)) {
+               err = clk_prepare_enable(bp->tx_clk);
+               if (err) {
+                       dev_err(&pdev->dev, "failed to enable tx_clk (%u)\n",
+                                       err);
+                       goto err_out_disable_hclk;
+               }
+       }
+
+       bp->regs = devm_ioremap(&pdev->dev, regs->start, resource_size(regs));
        if (!bp->regs) {
                dev_err(&pdev->dev, "failed to map registers, aborting.\n");
                err = -ENOMEM;
@@ -1812,11 +1880,12 @@ static int __init macb_probe(struct platform_device *pdev)
        }
 
        dev->irq = platform_get_irq(pdev, 0);
-       err = request_irq(dev->irq, macb_interrupt, 0, dev->name, dev);
+       err = devm_request_irq(&pdev->dev, dev->irq, macb_interrupt, 0,
+                       dev->name, dev);
        if (err) {
                dev_err(&pdev->dev, "Unable to request IRQ %d (error %d)\n",
                        dev->irq, err);
-               goto err_out_iounmap;
+               goto err_out_disable_clocks;
        }
 
        dev->netdev_ops = &macb_netdev_ops;
@@ -1879,7 +1948,7 @@ static int __init macb_probe(struct platform_device *pdev)
        err = register_netdev(dev);
        if (err) {
                dev_err(&pdev->dev, "Cannot register net device, aborting.\n");
-               goto err_out_free_irq;
+               goto err_out_disable_clocks;
        }
 
        err = macb_mii_init(bp);
@@ -1902,16 +1971,13 @@ static int __init macb_probe(struct platform_device *pdev)
 
 err_out_unregister_netdev:
        unregister_netdev(dev);
-err_out_free_irq:
-       free_irq(dev->irq, dev);
-err_out_iounmap:
-       iounmap(bp->regs);
 err_out_disable_clocks:
+       if (!IS_ERR(bp->tx_clk))
+               clk_disable_unprepare(bp->tx_clk);
+err_out_disable_hclk:
        clk_disable_unprepare(bp->hclk);
-       clk_put(bp->hclk);
+err_out_disable_pclk:
        clk_disable_unprepare(bp->pclk);
-err_out_put_pclk:
-       clk_put(bp->pclk);
 err_out_free_dev:
        free_netdev(dev);
 err_out:
@@ -1933,12 +1999,10 @@ static int __exit macb_remove(struct platform_device *pdev)
                kfree(bp->mii_bus->irq);
                mdiobus_free(bp->mii_bus);
                unregister_netdev(dev);
-               free_irq(dev->irq, dev);
-               iounmap(bp->regs);
+               if (!IS_ERR(bp->tx_clk))
+                       clk_disable_unprepare(bp->tx_clk);
                clk_disable_unprepare(bp->hclk);
-               clk_put(bp->hclk);
                clk_disable_unprepare(bp->pclk);
-               clk_put(bp->pclk);
                free_netdev(dev);
        }
 
@@ -1946,45 +2010,49 @@ static int __exit macb_remove(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_PM
-static int macb_suspend(struct platform_device *pdev, pm_message_t state)
+static int macb_suspend(struct device *dev)
 {
+       struct platform_device *pdev = to_platform_device(dev);
        struct net_device *netdev = platform_get_drvdata(pdev);
        struct macb *bp = netdev_priv(netdev);
 
        netif_carrier_off(netdev);
        netif_device_detach(netdev);
 
+       if (!IS_ERR(bp->tx_clk))
+               clk_disable_unprepare(bp->tx_clk);
        clk_disable_unprepare(bp->hclk);
        clk_disable_unprepare(bp->pclk);
 
        return 0;
 }
 
-static int macb_resume(struct platform_device *pdev)
+static int macb_resume(struct device *dev)
 {
+       struct platform_device *pdev = to_platform_device(dev);
        struct net_device *netdev = platform_get_drvdata(pdev);
        struct macb *bp = netdev_priv(netdev);
 
        clk_prepare_enable(bp->pclk);
        clk_prepare_enable(bp->hclk);
+       if (!IS_ERR(bp->tx_clk))
+               clk_prepare_enable(bp->tx_clk);
 
        netif_device_attach(netdev);
 
        return 0;
 }
-#else
-#define macb_suspend   NULL
-#define macb_resume    NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(macb_pm_ops, macb_suspend, macb_resume);
+
 static struct platform_driver macb_driver = {
        .remove         = __exit_p(macb_remove),
-       .suspend        = macb_suspend,
-       .resume         = macb_resume,
        .driver         = {
                .name           = "macb",
                .owner  = THIS_MODULE,
                .of_match_table = of_match_ptr(macb_dt_ids),
+               .pm     = &macb_pm_ops,
        },
 };
 
index f4076155bed7aa07eb2b04f133a3cab86f75cb23..51c02442160adb06d0c08bc3c408f65c06b96b65 100644 (file)
@@ -572,6 +572,7 @@ struct macb {
        struct platform_device  *pdev;
        struct clk              *pclk;
        struct clk              *hclk;
+       struct clk              *tx_clk;
        struct net_device       *dev;
        struct napi_struct      napi;
        struct work_struct      tx_error_task;
index 8abb46b39032df4bc13fe3ad4b0f227f9d2411e1..5dd20f7285eb754e8bb6227811019af1451e6ce0 100644 (file)
@@ -11,8 +11,7 @@
  * published by the Free Software Foundation.                                *
  *                                                                           *
  * 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.                 *
+ * with this program; if not, see <http://www.gnu.org/licenses/>.            *
  *                                                                           *
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
index 1f095a9fc73993432d15cb500db7bbb6b9c4695f..a4d2a4c08d3f73130c90ca06b4cff6ccd05069f9 100644 (file)
@@ -11,8 +11,7 @@
  * published by the Free Software Foundation.                                *
  *                                                                           *
  * 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.                 *
+ * with this program; if not, see <http://www.gnu.org/licenses/>.            *
  *                                                                           *
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
index e36d45b78cc7fc45e6e0ff4749967f33eabb151a..5249686afe713798f0e19214791e4868612e3852 100644 (file)
@@ -11,8 +11,7 @@
  * published by the Free Software Foundation.                                *
  *                                                                           *
  * 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.                 *
+ * with this program; if not, see <http://www.gnu.org/licenses/>.            *
  *                                                                           *
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
index 1d021059f097579b9306e458e2c8a5cd92a41948..e5987139a1aeb04ba4aef230d713813545e51a00 100644 (file)
@@ -11,8 +11,7 @@
  * published by the Free Software Foundation.                                *
  *                                                                           *
  * 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.                 *
+ * with this program; if not, see <http://www.gnu.org/licenses/>.            *
  *                                                                           *
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
index eef655c827d967f7dcc07f710caadb8554de577c..81526ad36339ba2bb2aea4dc7b994122510f18f0 100644 (file)
@@ -11,8 +11,7 @@
  * published by the Free Software Foundation.                                *
  *                                                                           *
  * 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.                 *
+ * with this program; if not, see <http://www.gnu.org/licenses/>.            *
  *                                                                           *
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
index 639ff1955739915416f9f1c40898e43c5ec9b80e..3e182eee799e64e482b1823e69b179ecef634262 100644 (file)
@@ -12,8 +12,7 @@
  * published by the Free Software Foundation.                                *
  *                                                                           *
  * 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.                 *
+ * with this program; if not, see <http://www.gnu.org/licenses/>.            *
  *                                                                           *
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
index 5694aad4fbc0a014c478b87cb4049a73446457c7..162de5259df929d6481d83afca3599ce0cebcf16 100644 (file)
@@ -11,8 +11,7 @@
  * published by the Free Software Foundation.                                *
  *                                                                           *
  * 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.                 *
+ * with this program; if not, see <http://www.gnu.org/licenses/>.            *
  *                                                                           *
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
index d42337457cf74bdc62e625a9688d1cb2728cd929..dfa77491a910d79b58c76475abf866d8a722b8d6 100644 (file)
@@ -12,8 +12,7 @@
  * published by the Free Software Foundation.                                *
  *                                                                           *
  * 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.                 *
+ * with this program; if not, see <http://www.gnu.org/licenses/>.            *
  *                                                                           *
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
index f7136b2fd1e5c946f8ee320a087cfbc872982039..d0cf611551a17185cef1e87b2e07b8aed955a588 100644 (file)
@@ -12,8 +12,7 @@
  * published by the Free Software Foundation.                                *
  *                                                                           *
  * 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.                 *
+ * with this program; if not, see <http://www.gnu.org/licenses/>.            *
  *                                                                           *
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
index eb33a31b08a01487dc17465ffbc7a4505030b9e2..ec5e05052d99ea208e8bf27ae28103cf4e73a23d 100644 (file)
@@ -12,8 +12,7 @@
  * published by the Free Software Foundation.                                *
  *                                                                           *
  * 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.                 *
+ * with this program; if not, see <http://www.gnu.org/licenses/>.            *
  *                                                                           *
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
index c80bf4d6d0a65e4a065d7833a10ec63a59dea536..964ce59ee16925607c3ff51f7360c4f1ea0d8d97 100644 (file)
@@ -11,8 +11,7 @@
  * published by the Free Software Foundation.                                *
  *                                                                           *
  * 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.                 *
+ * with this program; if not, see <http://www.gnu.org/licenses/>.            *
  *                                                                           *
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
index 8061fb0ef7edd5b8b9d5bca8d8d6a3e270c5314a..0341537cdd37f50b5824cb9df4d5b0e6f4bf9bda 100644 (file)
@@ -12,8 +12,7 @@
  * published by the Free Software Foundation.                                *
  *                                                                           *
  * 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.                 *
+ * with this program; if not, see <http://www.gnu.org/licenses/>.            *
  *                                                                           *
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
index b9bf16b385f7241c3cffc353e3fbc0feb798eafd..a1ba591b34312cf86e04e74ffa769486ce078024 100644 (file)
@@ -11,8 +11,7 @@
  * published by the Free Software Foundation.                                *
  *                                                                           *
  * 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.                 *
+ * with this program; if not, see <http://www.gnu.org/licenses/>.            *
  *                                                                           *
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
index e0a03a31e7c487489006aa57594d86cfb73e27b0..816719314cc893217693d3bc2756e4d8d5ac3013 100644 (file)
@@ -12,8 +12,7 @@
  * published by the Free Software Foundation.                                *
  *                                                                           *
  * 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.                 *
+ * with this program; if not, see <http://www.gnu.org/licenses/>.            *
  *                                                                           *
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
index d0f87d82566aa46cf1135d5918cfdfd37690cee6..7f79cc7ceb7522d7138be52df848262ce14870b3 100644 (file)
@@ -12,8 +12,7 @@
  * published by the Free Software Foundation.                                *
  *                                                                           *
  * 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.                 *
+ * with this program; if not, see <http://www.gnu.org/licenses/>.            *
  *                                                                           *
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
index ecd2fb3ef69596146a7cf155323e624e397b6834..6c9308850453bf1ecd21173afa1d1cf11681c8c7 100644 (file)
 #include <asm/io.h>
 #include "cxgb4_uld.h"
 
-#define FW_VERSION_MAJOR 1
-#define FW_VERSION_MINOR 4
-#define FW_VERSION_MICRO 0
+#define T4FW_VERSION_MAJOR 0x01
+#define T4FW_VERSION_MINOR 0x06
+#define T4FW_VERSION_MICRO 0x18
+#define T4FW_VERSION_BUILD 0x00
 
-#define FW_VERSION_MAJOR_T5 0
-#define FW_VERSION_MINOR_T5 0
-#define FW_VERSION_MICRO_T5 0
+#define T5FW_VERSION_MAJOR 0x01
+#define T5FW_VERSION_MINOR 0x08
+#define T5FW_VERSION_MICRO 0x1C
+#define T5FW_VERSION_BUILD 0x00
 
 #define CH_WARN(adap, fmt, ...) dev_warn(adap->pdev_dev, fmt, ## __VA_ARGS__)
 
@@ -240,6 +242,26 @@ struct pci_params {
        unsigned char width;
 };
 
+#define CHELSIO_CHIP_CODE(version, revision) (((version) << 4) | (revision))
+#define CHELSIO_CHIP_FPGA          0x100
+#define CHELSIO_CHIP_VERSION(code) (((code) >> 4) & 0xf)
+#define CHELSIO_CHIP_RELEASE(code) ((code) & 0xf)
+
+#define CHELSIO_T4             0x4
+#define CHELSIO_T5             0x5
+
+enum chip_type {
+       T4_A1 = CHELSIO_CHIP_CODE(CHELSIO_T4, 1),
+       T4_A2 = CHELSIO_CHIP_CODE(CHELSIO_T4, 2),
+       T4_FIRST_REV    = T4_A1,
+       T4_LAST_REV     = T4_A2,
+
+       T5_A0 = CHELSIO_CHIP_CODE(CHELSIO_T5, 0),
+       T5_A1 = CHELSIO_CHIP_CODE(CHELSIO_T5, 1),
+       T5_FIRST_REV    = T5_A0,
+       T5_LAST_REV     = T5_A1,
+};
+
 struct adapter_params {
        struct tp_params  tp;
        struct vpd_params vpd;
@@ -259,7 +281,7 @@ struct adapter_params {
 
        unsigned char nports;             /* # of ethernet ports */
        unsigned char portvec;
-       unsigned char rev;                /* chip revision */
+       enum chip_type chip;               /* chip code */
        unsigned char offload;
 
        unsigned char bypass;
@@ -267,6 +289,23 @@ struct adapter_params {
        unsigned int ofldq_wr_cred;
 };
 
+#include "t4fw_api.h"
+
+#define FW_VERSION(chip) ( \
+               FW_HDR_FW_VER_MAJOR_GET(chip##FW_VERSION_MAJOR) | \
+               FW_HDR_FW_VER_MINOR_GET(chip##FW_VERSION_MINOR) | \
+               FW_HDR_FW_VER_MICRO_GET(chip##FW_VERSION_MICRO) | \
+               FW_HDR_FW_VER_BUILD_GET(chip##FW_VERSION_BUILD))
+#define FW_INTFVER(chip, intf) (FW_HDR_INTFVER_##intf)
+
+struct fw_info {
+       u8 chip;
+       char *fs_name;
+       char *fw_mod_name;
+       struct fw_hdr fw_hdr;
+};
+
+
 struct trace_params {
        u32 data[TRACE_LEN / 4];
        u32 mask[TRACE_LEN / 4];
@@ -512,25 +551,6 @@ struct sge {
 
 struct l2t_data;
 
-#define CHELSIO_CHIP_CODE(version, revision) (((version) << 4) | (revision))
-#define CHELSIO_CHIP_VERSION(code) ((code) >> 4)
-#define CHELSIO_CHIP_RELEASE(code) ((code) & 0xf)
-
-#define CHELSIO_T4             0x4
-#define CHELSIO_T5             0x5
-
-enum chip_type {
-       T4_A1 = CHELSIO_CHIP_CODE(CHELSIO_T4, 0),
-       T4_A2 = CHELSIO_CHIP_CODE(CHELSIO_T4, 1),
-       T4_A3 = CHELSIO_CHIP_CODE(CHELSIO_T4, 2),
-       T4_FIRST_REV    = T4_A1,
-       T4_LAST_REV     = T4_A3,
-
-       T5_A1 = CHELSIO_CHIP_CODE(CHELSIO_T5, 0),
-       T5_FIRST_REV    = T5_A1,
-       T5_LAST_REV     = T5_A1,
-};
-
 #ifdef CONFIG_PCI_IOV
 
 /* T4 supports SRIOV on PF0-3 and T5 on PF0-7.  However, the Serial
@@ -715,12 +735,12 @@ enum {
 
 static inline int is_t5(enum chip_type chip)
 {
-       return (chip >= T5_FIRST_REV && chip <= T5_LAST_REV);
+       return CHELSIO_CHIP_VERSION(chip) == CHELSIO_T5;
 }
 
 static inline int is_t4(enum chip_type chip)
 {
-       return (chip >= T4_FIRST_REV && chip <= T4_LAST_REV);
+       return CHELSIO_CHIP_VERSION(chip) == CHELSIO_T4;
 }
 
 static inline u32 t4_read_reg(struct adapter *adap, u32 reg_addr)
@@ -900,7 +920,11 @@ int get_vpd_params(struct adapter *adapter, struct vpd_params *p);
 int t4_load_fw(struct adapter *adapter, const u8 *fw_data, unsigned int size);
 unsigned int t4_flash_cfg_addr(struct adapter *adapter);
 int t4_load_cfg(struct adapter *adapter, const u8 *cfg_data, unsigned int size);
-int t4_check_fw_version(struct adapter *adapter);
+int t4_get_fw_version(struct adapter *adapter, u32 *vers);
+int t4_get_tp_version(struct adapter *adapter, u32 *vers);
+int t4_prep_fw(struct adapter *adap, struct fw_info *fw_info,
+              const u8 *fw_data, unsigned int fw_size,
+              struct fw_hdr *card_fw, enum dev_state state, int *reset);
 int t4_prep_adapter(struct adapter *adapter);
 int t4_port_init(struct adapter *adap, int mbox, int pf, int vf);
 void t4_fatal_err(struct adapter *adapter);
index 8b929eeecd2d37cd3b41e32d57bd1fa50402a230..d6b12e035a7d9f27d84d397dc2921713c7fed46f 100644 (file)
@@ -276,9 +276,9 @@ static DEFINE_PCI_DEVICE_TABLE(cxgb4_pci_tbl) = {
        { 0, }
 };
 
-#define FW_FNAME "cxgb4/t4fw.bin"
+#define FW4_FNAME "cxgb4/t4fw.bin"
 #define FW5_FNAME "cxgb4/t5fw.bin"
-#define FW_CFNAME "cxgb4/t4-config.txt"
+#define FW4_CFNAME "cxgb4/t4-config.txt"
 #define FW5_CFNAME "cxgb4/t5-config.txt"
 
 MODULE_DESCRIPTION(DRV_DESC);
@@ -286,7 +286,7 @@ MODULE_AUTHOR("Chelsio Communications");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_VERSION(DRV_VERSION);
 MODULE_DEVICE_TABLE(pci, cxgb4_pci_tbl);
-MODULE_FIRMWARE(FW_FNAME);
+MODULE_FIRMWARE(FW4_FNAME);
 MODULE_FIRMWARE(FW5_FNAME);
 
 /*
@@ -1070,72 +1070,6 @@ freeout: t4_free_sge_resources(adap);
        return 0;
 }
 
-/*
- * Returns 0 if new FW was successfully loaded, a positive errno if a load was
- * started but failed, and a negative errno if flash load couldn't start.
- */
-static int upgrade_fw(struct adapter *adap)
-{
-       int ret;
-       u32 vers, exp_major;
-       const struct fw_hdr *hdr;
-       const struct firmware *fw;
-       struct device *dev = adap->pdev_dev;
-       char *fw_file_name;
-
-       switch (CHELSIO_CHIP_VERSION(adap->chip)) {
-       case CHELSIO_T4:
-               fw_file_name = FW_FNAME;
-               exp_major = FW_VERSION_MAJOR;
-               break;
-       case CHELSIO_T5:
-               fw_file_name = FW5_FNAME;
-               exp_major = FW_VERSION_MAJOR_T5;
-               break;
-       default:
-               dev_err(dev, "Unsupported chip type, %x\n", adap->chip);
-               return -EINVAL;
-       }
-
-       ret = request_firmware(&fw, fw_file_name, dev);
-       if (ret < 0) {
-               dev_err(dev, "unable to load firmware image %s, error %d\n",
-                       fw_file_name, ret);
-               return ret;
-       }
-
-       hdr = (const struct fw_hdr *)fw->data;
-       vers = ntohl(hdr->fw_ver);
-       if (FW_HDR_FW_VER_MAJOR_GET(vers) != exp_major) {
-               ret = -EINVAL;              /* wrong major version, won't do */
-               goto out;
-       }
-
-       /*
-        * If the flash FW is unusable or we found something newer, load it.
-        */
-       if (FW_HDR_FW_VER_MAJOR_GET(adap->params.fw_vers) != exp_major ||
-           vers > adap->params.fw_vers) {
-               dev_info(dev, "upgrading firmware ...\n");
-               ret = t4_fw_upgrade(adap, adap->mbox, fw->data, fw->size,
-                                   /*force=*/false);
-               if (!ret)
-                       dev_info(dev,
-                                "firmware upgraded to version %pI4 from %s\n",
-                                &hdr->fw_ver, fw_file_name);
-               else
-                       dev_err(dev, "firmware upgrade failed! err=%d\n", -ret);
-       } else {
-               /*
-                * Tell our caller that we didn't upgrade the firmware.
-                */
-               ret = -EINVAL;
-       }
-
-out:   release_firmware(fw);
-       return ret;
-}
-
 /*
  * Allocate a chunk of memory using kmalloc or, if that fails, vmalloc.
  * The allocated memory is cleared.
@@ -1415,7 +1349,7 @@ static int get_sset_count(struct net_device *dev, int sset)
 static int get_regs_len(struct net_device *dev)
 {
        struct adapter *adap = netdev2adap(dev);
-       if (is_t4(adap->chip))
+       if (is_t4(adap->params.chip))
                return T4_REGMAP_SIZE;
        else
                return T5_REGMAP_SIZE;
@@ -1499,7 +1433,7 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats,
        data += sizeof(struct port_stats) / sizeof(u64);
        collect_sge_port_stats(adapter, pi, (struct queue_port_stats *)data);
        data += sizeof(struct queue_port_stats) / sizeof(u64);
-       if (!is_t4(adapter->chip)) {
+       if (!is_t4(adapter->params.chip)) {
                t4_write_reg(adapter, SGE_STAT_CFG, STATSOURCE_T5(7));
                val1 = t4_read_reg(adapter, SGE_STAT_TOTAL);
                val2 = t4_read_reg(adapter, SGE_STAT_MATCH);
@@ -1521,8 +1455,8 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats,
  */
 static inline unsigned int mk_adap_vers(const struct adapter *ap)
 {
-       return CHELSIO_CHIP_VERSION(ap->chip) |
-               (CHELSIO_CHIP_RELEASE(ap->chip) << 10) | (1 << 16);
+       return CHELSIO_CHIP_VERSION(ap->params.chip) |
+               (CHELSIO_CHIP_RELEASE(ap->params.chip) << 10) | (1 << 16);
 }
 
 static void reg_block_dump(struct adapter *ap, void *buf, unsigned int start,
@@ -2189,7 +2123,7 @@ static void get_regs(struct net_device *dev, struct ethtool_regs *regs,
        static const unsigned int *reg_ranges;
        int arr_size = 0, buf_size = 0;
 
-       if (is_t4(ap->chip)) {
+       if (is_t4(ap->params.chip)) {
                reg_ranges = &t4_reg_ranges[0];
                arr_size = ARRAY_SIZE(t4_reg_ranges);
                buf_size = T4_REGMAP_SIZE;
@@ -2967,7 +2901,7 @@ static int setup_debugfs(struct adapter *adap)
                size = t4_read_reg(adap, MA_EDRAM1_BAR);
                add_debugfs_mem(adap, "edc1", MEM_EDC1, EDRAM_SIZE_GET(size));
        }
-       if (is_t4(adap->chip)) {
+       if (is_t4(adap->params.chip)) {
                size = t4_read_reg(adap, MA_EXT_MEMORY_BAR);
                if (i & EXT_MEM_ENABLE)
                        add_debugfs_mem(adap, "mc", MEM_MC,
@@ -3419,7 +3353,7 @@ unsigned int cxgb4_dbfifo_count(const struct net_device *dev, int lpfifo)
 
        v1 = t4_read_reg(adap, A_SGE_DBFIFO_STATUS);
        v2 = t4_read_reg(adap, SGE_DBFIFO_STATUS2);
-       if (is_t4(adap->chip)) {
+       if (is_t4(adap->params.chip)) {
                lp_count = G_LP_COUNT(v1);
                hp_count = G_HP_COUNT(v1);
        } else {
@@ -3588,7 +3522,7 @@ static void drain_db_fifo(struct adapter *adap, int usecs)
        do {
                v1 = t4_read_reg(adap, A_SGE_DBFIFO_STATUS);
                v2 = t4_read_reg(adap, SGE_DBFIFO_STATUS2);
-               if (is_t4(adap->chip)) {
+               if (is_t4(adap->params.chip)) {
                        lp_count = G_LP_COUNT(v1);
                        hp_count = G_HP_COUNT(v1);
                } else {
@@ -3708,7 +3642,7 @@ static void process_db_drop(struct work_struct *work)
 
        adap = container_of(work, struct adapter, db_drop_task);
 
-       if (is_t4(adap->chip)) {
+       if (is_t4(adap->params.chip)) {
                disable_dbs(adap);
                notify_rdma_uld(adap, CXGB4_CONTROL_DB_DROP);
                drain_db_fifo(adap, 1);
@@ -3753,7 +3687,7 @@ static void process_db_drop(struct work_struct *work)
 
 void t4_db_full(struct adapter *adap)
 {
-       if (is_t4(adap->chip)) {
+       if (is_t4(adap->params.chip)) {
                t4_set_reg_field(adap, SGE_INT_ENABLE3,
                                 DBFIFO_HP_INT | DBFIFO_LP_INT, 0);
                queue_work(workq, &adap->db_full_task);
@@ -3762,7 +3696,7 @@ void t4_db_full(struct adapter *adap)
 
 void t4_db_dropped(struct adapter *adap)
 {
-       if (is_t4(adap->chip))
+       if (is_t4(adap->params.chip))
                queue_work(workq, &adap->db_drop_task);
 }
 
@@ -3789,7 +3723,7 @@ static void uld_attach(struct adapter *adap, unsigned int uld)
        lli.nchan = adap->params.nports;
        lli.nports = adap->params.nports;
        lli.wr_cred = adap->params.ofldq_wr_cred;
-       lli.adapter_type = adap->params.rev;
+       lli.adapter_type = adap->params.chip;
        lli.iscsi_iolen = MAXRXDATA_GET(t4_read_reg(adap, TP_PARA_REG2));
        lli.udb_density = 1 << QUEUESPERPAGEPF0_GET(
                        t4_read_reg(adap, SGE_EGRESS_QUEUES_PER_PAGE_PF) >>
@@ -4483,7 +4417,7 @@ static void setup_memwin(struct adapter *adap)
        u32 bar0, mem_win0_base, mem_win1_base, mem_win2_base;
 
        bar0 = pci_resource_start(adap->pdev, 0);  /* truncation intentional */
-       if (is_t4(adap->chip)) {
+       if (is_t4(adap->params.chip)) {
                mem_win0_base = bar0 + MEMWIN0_BASE;
                mem_win1_base = bar0 + MEMWIN1_BASE;
                mem_win2_base = bar0 + MEMWIN2_BASE;
@@ -4668,8 +4602,10 @@ static int adap_init0_config(struct adapter *adapter, int reset)
        const struct firmware *cf;
        unsigned long mtype = 0, maddr = 0;
        u32 finiver, finicsum, cfcsum;
-       int ret, using_flash;
+       int ret;
+       int config_issued = 0;
        char *fw_config_file, fw_config_file_path[256];
+       char *config_name = NULL;
 
        /*
         * Reset device if necessary.
@@ -4686,9 +4622,9 @@ static int adap_init0_config(struct adapter *adapter, int reset)
         * then use that.  Otherwise, use the configuration file stored
         * in the adapter flash ...
         */
-       switch (CHELSIO_CHIP_VERSION(adapter->chip)) {
+       switch (CHELSIO_CHIP_VERSION(adapter->params.chip)) {
        case CHELSIO_T4:
-               fw_config_file = FW_CFNAME;
+               fw_config_file = FW4_CFNAME;
                break;
        case CHELSIO_T5:
                fw_config_file = FW5_CFNAME;
@@ -4702,13 +4638,16 @@ static int adap_init0_config(struct adapter *adapter, int reset)
 
        ret = request_firmware(&cf, fw_config_file, adapter->pdev_dev);
        if (ret < 0) {
-               using_flash = 1;
+               config_name = "On FLASH";
                mtype = FW_MEMTYPE_CF_FLASH;
                maddr = t4_flash_cfg_addr(adapter);
        } else {
                u32 params[7], val[7];
 
-               using_flash = 0;
+               sprintf(fw_config_file_path,
+                       "/lib/firmware/%s", fw_config_file);
+               config_name = fw_config_file_path;
+
                if (cf->size >= FLASH_CFG_MAX_SIZE)
                        ret = -ENOMEM;
                else {
@@ -4776,6 +4715,26 @@ static int adap_init0_config(struct adapter *adapter, int reset)
                      FW_LEN16(caps_cmd));
        ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd, sizeof(caps_cmd),
                         &caps_cmd);
+
+       /* If the CAPS_CONFIG failed with an ENOENT (for a Firmware
+        * Configuration File in FLASH), our last gasp effort is to use the
+        * Firmware Configuration File which is embedded in the firmware.  A
+        * very few early versions of the firmware didn't have one embedded
+        * but we can ignore those.
+        */
+       if (ret == -ENOENT) {
+               memset(&caps_cmd, 0, sizeof(caps_cmd));
+               caps_cmd.op_to_write =
+                       htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
+                                       FW_CMD_REQUEST |
+                                       FW_CMD_READ);
+               caps_cmd.cfvalid_to_len16 = htonl(FW_LEN16(caps_cmd));
+               ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd,
+                               sizeof(caps_cmd), &caps_cmd);
+               config_name = "Firmware Default";
+       }
+
+       config_issued = 1;
        if (ret < 0)
                goto bye;
 
@@ -4816,7 +4775,6 @@ static int adap_init0_config(struct adapter *adapter, int reset)
        if (ret < 0)
                goto bye;
 
-       sprintf(fw_config_file_path, "/lib/firmware/%s", fw_config_file);
        /*
         * Return successfully and note that we're operating with parameters
         * not supplied by the driver, rather than from hard-wired
@@ -4824,11 +4782,8 @@ static int adap_init0_config(struct adapter *adapter, int reset)
         */
        adapter->flags |= USING_SOFT_PARAMS;
        dev_info(adapter->pdev_dev, "Successfully configured using Firmware "\
-                "Configuration File %s, version %#x, computed checksum %#x\n",
-                (using_flash
-                 ? "in device FLASH"
-                 : fw_config_file_path),
-                finiver, cfcsum);
+                "Configuration File \"%s\", version %#x, computed checksum %#x\n",
+                config_name, finiver, cfcsum);
        return 0;
 
        /*
@@ -4837,9 +4792,9 @@ static int adap_init0_config(struct adapter *adapter, int reset)
         * want to issue a warning since this is fairly common.)
         */
 bye:
-       if (ret != -ENOENT)
-               dev_warn(adapter->pdev_dev, "Configuration file error %d\n",
-                        -ret);
+       if (config_issued && ret != -ENOENT)
+               dev_warn(adapter->pdev_dev, "\"%s\" configuration file error %d\n",
+                        config_name, -ret);
        return ret;
 }
 
@@ -5086,6 +5041,47 @@ bye:
        return ret;
 }
 
+static struct fw_info fw_info_array[] = {
+       {
+               .chip = CHELSIO_T4,
+               .fs_name = FW4_CFNAME,
+               .fw_mod_name = FW4_FNAME,
+               .fw_hdr = {
+                       .chip = FW_HDR_CHIP_T4,
+                       .fw_ver = __cpu_to_be32(FW_VERSION(T4)),
+                       .intfver_nic = FW_INTFVER(T4, NIC),
+                       .intfver_vnic = FW_INTFVER(T4, VNIC),
+                       .intfver_ri = FW_INTFVER(T4, RI),
+                       .intfver_iscsi = FW_INTFVER(T4, ISCSI),
+                       .intfver_fcoe = FW_INTFVER(T4, FCOE),
+               },
+       }, {
+               .chip = CHELSIO_T5,
+               .fs_name = FW5_CFNAME,
+               .fw_mod_name = FW5_FNAME,
+               .fw_hdr = {
+                       .chip = FW_HDR_CHIP_T5,
+                       .fw_ver = __cpu_to_be32(FW_VERSION(T5)),
+                       .intfver_nic = FW_INTFVER(T5, NIC),
+                       .intfver_vnic = FW_INTFVER(T5, VNIC),
+                       .intfver_ri = FW_INTFVER(T5, RI),
+                       .intfver_iscsi = FW_INTFVER(T5, ISCSI),
+                       .intfver_fcoe = FW_INTFVER(T5, FCOE),
+               },
+       }
+};
+
+static struct fw_info *find_fw_info(int chip)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(fw_info_array); i++) {
+               if (fw_info_array[i].chip == chip)
+                       return &fw_info_array[i];
+       }
+       return NULL;
+}
+
 /*
  * Phase 0 of initialization: contact FW, obtain config, perform basic init.
  */
@@ -5123,44 +5119,54 @@ static int adap_init0(struct adapter *adap)
         * later reporting and B. to warn if the currently loaded firmware
         * is excessively mismatched relative to the driver.)
         */
-       ret = t4_check_fw_version(adap);
-
-       /* The error code -EFAULT is returned by t4_check_fw_version() if
-        * firmware on adapter < supported firmware. If firmware on adapter
-        * is too old (not supported by driver) and we're the MASTER_PF set
-        * adapter state to DEV_STATE_UNINIT to force firmware upgrade
-        * and reinitialization.
-        */
-       if ((adap->flags & MASTER_PF) && ret == -EFAULT)
-               state = DEV_STATE_UNINIT;
+       t4_get_fw_version(adap, &adap->params.fw_vers);
+       t4_get_tp_version(adap, &adap->params.tp_vers);
        if ((adap->flags & MASTER_PF) && state != DEV_STATE_INIT) {
-               if (ret == -EINVAL || ret == -EFAULT || ret > 0) {
-                       if (upgrade_fw(adap) >= 0) {
-                               /*
-                                * Note that the chip was reset as part of the
-                                * firmware upgrade so we don't reset it again
-                                * below and grab the new firmware version.
-                                */
-                               reset = 0;
-                               ret = t4_check_fw_version(adap);
-                       } else
-                               if (ret == -EFAULT) {
-                                       /*
-                                        * Firmware is old but still might
-                                        * work if we force reinitialization
-                                        * of the adapter. Ignoring FW upgrade
-                                        * failure.
-                                        */
-                                       dev_warn(adap->pdev_dev,
-                                                "Ignoring firmware upgrade "
-                                                "failure, and forcing driver "
-                                                "to reinitialize the "
-                                                "adapter.\n");
-                                       ret = 0;
-                               }
+               struct fw_info *fw_info;
+               struct fw_hdr *card_fw;
+               const struct firmware *fw;
+               const u8 *fw_data = NULL;
+               unsigned int fw_size = 0;
+
+               /* This is the firmware whose headers the driver was compiled
+                * against
+                */
+               fw_info = find_fw_info(CHELSIO_CHIP_VERSION(adap->params.chip));
+               if (fw_info == NULL) {
+                       dev_err(adap->pdev_dev,
+                               "unable to get firmware info for chip %d.\n",
+                               CHELSIO_CHIP_VERSION(adap->params.chip));
+                       return -EINVAL;
                }
+
+               /* allocate memory to read the header of the firmware on the
+                * card
+                */
+               card_fw = t4_alloc_mem(sizeof(*card_fw));
+
+               /* Get FW from from /lib/firmware/ */
+               ret = request_firmware(&fw, fw_info->fw_mod_name,
+                                      adap->pdev_dev);
+               if (ret < 0) {
+                       dev_err(adap->pdev_dev,
+                               "unable to load firmware image %s, error %d\n",
+                               fw_info->fw_mod_name, ret);
+               } else {
+                       fw_data = fw->data;
+                       fw_size = fw->size;
+               }
+
+               /* upgrade FW logic */
+               ret = t4_prep_fw(adap, fw_info, fw_data, fw_size, card_fw,
+                                state, &reset);
+
+               /* Cleaning up */
+               if (fw != NULL)
+                       release_firmware(fw);
+               t4_free_mem(card_fw);
+
                if (ret < 0)
-                       return ret;
+                       goto bye;
        }
 
        /*
@@ -5245,7 +5251,7 @@ static int adap_init0(struct adapter *adap)
                                if (ret == -ENOENT) {
                                        dev_info(adap->pdev_dev,
                                            "No Configuration File present "
-                                           "on adapter.  Using hard-wired "
+                                           "on adapter. Using hard-wired "
                                            "configuration parameters.\n");
                                        ret = adap_init0_no_config(adap, reset);
                                }
@@ -5787,7 +5793,7 @@ static void print_port_info(const struct net_device *dev)
 
        netdev_info(dev, "Chelsio %s rev %d %s %sNIC PCIe x%d%s%s\n",
                    adap->params.vpd.id,
-                   CHELSIO_CHIP_RELEASE(adap->params.rev), buf,
+                   CHELSIO_CHIP_RELEASE(adap->params.chip), buf,
                    is_offload(adap) ? "R" : "", adap->params.pci.width, spd,
                    (adap->flags & USING_MSIX) ? " MSI-X" :
                    (adap->flags & USING_MSI) ? " MSI" : "");
@@ -5910,7 +5916,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (err)
                goto out_unmap_bar0;
 
-       if (!is_t4(adapter->chip)) {
+       if (!is_t4(adapter->params.chip)) {
                s_qpp = QUEUESPERPAGEPF1 * adapter->fn;
                qpp = 1 << QUEUESPERPAGEPF0_GET(t4_read_reg(adapter,
                      SGE_EGRESS_QUEUES_PER_PAGE_PF) >> s_qpp);
@@ -6064,7 +6070,7 @@ sriov:
  out_free_dev:
        free_some_resources(adapter);
  out_unmap_bar:
-       if (!is_t4(adapter->chip))
+       if (!is_t4(adapter->params.chip))
                iounmap(adapter->bar2);
  out_unmap_bar0:
        iounmap(adapter->regs);
@@ -6116,7 +6122,7 @@ static void remove_one(struct pci_dev *pdev)
 
                free_some_resources(adapter);
                iounmap(adapter->regs);
-               if (!is_t4(adapter->chip))
+               if (!is_t4(adapter->params.chip))
                        iounmap(adapter->bar2);
                kfree(adapter);
                pci_disable_pcie_error_reporting(pdev);
index ac311f5f3eb9590d1d9b5fb3bb0a9c3f0fac5ce7..cc380c36e1a8687cd1c7f3b4c3dbf2d0b8c1bf47 100644 (file)
@@ -509,7 +509,7 @@ static inline void ring_fl_db(struct adapter *adap, struct sge_fl *q)
        u32 val;
        if (q->pend_cred >= 8) {
                val = PIDX(q->pend_cred / 8);
-               if (!is_t4(adap->chip))
+               if (!is_t4(adap->params.chip))
                        val |= DBTYPE(1);
                wmb();
                t4_write_reg(adap, MYPF_REG(SGE_PF_KDOORBELL), DBPRIO(1) |
@@ -847,7 +847,7 @@ static inline void ring_tx_db(struct adapter *adap, struct sge_txq *q, int n)
        wmb();            /* write descriptors before telling HW */
        spin_lock(&q->db_lock);
        if (!q->db_disabled) {
-               if (is_t4(adap->chip)) {
+               if (is_t4(adap->params.chip)) {
                        t4_write_reg(adap, MYPF_REG(SGE_PF_KDOORBELL),
                                     QID(q->cntxt_id) | PIDX(n));
                } else {
@@ -1596,7 +1596,7 @@ static noinline int handle_trace_pkt(struct adapter *adap,
                return 0;
        }
 
-       if (is_t4(adap->chip))
+       if (is_t4(adap->params.chip))
                __skb_pull(skb, sizeof(struct cpl_trace_pkt));
        else
                __skb_pull(skb, sizeof(struct cpl_t5_trace_pkt));
@@ -1661,7 +1661,7 @@ int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp,
        const struct cpl_rx_pkt *pkt;
        struct sge_eth_rxq *rxq = container_of(q, struct sge_eth_rxq, rspq);
        struct sge *s = &q->adap->sge;
-       int cpl_trace_pkt = is_t4(q->adap->chip) ?
+       int cpl_trace_pkt = is_t4(q->adap->params.chip) ?
                            CPL_TRACE_PKT : CPL_TRACE_PKT_T5;
 
        if (unlikely(*(u8 *)rsp == cpl_trace_pkt))
@@ -2182,7 +2182,7 @@ err:
 static void init_txq(struct adapter *adap, struct sge_txq *q, unsigned int id)
 {
        q->cntxt_id = id;
-       if (!is_t4(adap->chip)) {
+       if (!is_t4(adap->params.chip)) {
                unsigned int s_qpp;
                unsigned short udb_density;
                unsigned long qpshift;
@@ -2641,7 +2641,7 @@ static int t4_sge_init_hard(struct adapter *adap)
         * Set up to drop DOORBELL writes when the DOORBELL FIFO overflows
         * and generate an interrupt when this occurs so we can recover.
         */
-       if (is_t4(adap->chip)) {
+       if (is_t4(adap->params.chip)) {
                t4_set_reg_field(adap, A_SGE_DBFIFO_STATUS,
                                 V_HP_INT_THRESH(M_HP_INT_THRESH) |
                                 V_LP_INT_THRESH(M_LP_INT_THRESH),
index 4cbb2f9850be554c9ec48afd7479b4fcd9e5ebc2..74a6fce5a15a6914faf74bbf903dcc76ec717775 100644 (file)
@@ -296,7 +296,7 @@ int t4_mc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, u64 *ecc)
        u32 mc_bist_cmd, mc_bist_cmd_addr, mc_bist_cmd_len;
        u32 mc_bist_status_rdata, mc_bist_data_pattern;
 
-       if (is_t4(adap->chip)) {
+       if (is_t4(adap->params.chip)) {
                mc_bist_cmd = MC_BIST_CMD;
                mc_bist_cmd_addr = MC_BIST_CMD_ADDR;
                mc_bist_cmd_len = MC_BIST_CMD_LEN;
@@ -349,7 +349,7 @@ int t4_edc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, u64 *ecc)
        u32 edc_bist_cmd, edc_bist_cmd_addr, edc_bist_cmd_len;
        u32 edc_bist_cmd_data_pattern, edc_bist_status_rdata;
 
-       if (is_t4(adap->chip)) {
+       if (is_t4(adap->params.chip)) {
                edc_bist_cmd = EDC_REG(EDC_BIST_CMD, idx);
                edc_bist_cmd_addr = EDC_REG(EDC_BIST_CMD_ADDR, idx);
                edc_bist_cmd_len = EDC_REG(EDC_BIST_CMD_LEN, idx);
@@ -402,7 +402,7 @@ int t4_edc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, u64 *ecc)
 static int t4_mem_win_rw(struct adapter *adap, u32 addr, __be32 *data, int dir)
 {
        int i;
-       u32 win_pf = is_t4(adap->chip) ? 0 : V_PFNUM(adap->fn);
+       u32 win_pf = is_t4(adap->params.chip) ? 0 : V_PFNUM(adap->fn);
 
        /*
         * Setup offset into PCIE memory window.  Address must be a
@@ -863,104 +863,169 @@ unlock:
 }
 
 /**
- *     get_fw_version - read the firmware version
+ *     t4_get_fw_version - read the firmware version
  *     @adapter: the adapter
  *     @vers: where to place the version
  *
  *     Reads the FW version from flash.
  */
-static int get_fw_version(struct adapter *adapter, u32 *vers)
+int t4_get_fw_version(struct adapter *adapter, u32 *vers)
 {
-       return t4_read_flash(adapter, adapter->params.sf_fw_start +
-                            offsetof(struct fw_hdr, fw_ver), 1, vers, 0);
+       return t4_read_flash(adapter, FLASH_FW_START +
+                            offsetof(struct fw_hdr, fw_ver), 1,
+                            vers, 0);
 }
 
 /**
- *     get_tp_version - read the TP microcode version
+ *     t4_get_tp_version - read the TP microcode version
  *     @adapter: the adapter
  *     @vers: where to place the version
  *
  *     Reads the TP microcode version from flash.
  */
-static int get_tp_version(struct adapter *adapter, u32 *vers)
+int t4_get_tp_version(struct adapter *adapter, u32 *vers)
 {
-       return t4_read_flash(adapter, adapter->params.sf_fw_start +
+       return t4_read_flash(adapter, FLASH_FW_START +
                             offsetof(struct fw_hdr, tp_microcode_ver),
                             1, vers, 0);
 }
 
-/**
- *     t4_check_fw_version - check if the FW is compatible with this driver
- *     @adapter: the adapter
- *
- *     Checks if an adapter's FW is compatible with the driver.  Returns 0
- *     if there's exact match, a negative error if the version could not be
- *     read or there's a major version mismatch, and a positive value if the
- *     expected major version is found but there's a minor version mismatch.
+/* Is the given firmware API compatible with the one the driver was compiled
+ * with?
  */
-int t4_check_fw_version(struct adapter *adapter)
+static int fw_compatible(const struct fw_hdr *hdr1, const struct fw_hdr *hdr2)
 {
-       u32 api_vers[2];
-       int ret, major, minor, micro;
-       int exp_major, exp_minor, exp_micro;
 
-       ret = get_fw_version(adapter, &adapter->params.fw_vers);
-       if (!ret)
-               ret = get_tp_version(adapter, &adapter->params.tp_vers);
-       if (!ret)
-               ret = t4_read_flash(adapter, adapter->params.sf_fw_start +
-                                   offsetof(struct fw_hdr, intfver_nic),
-                                   2, api_vers, 1);
-       if (ret)
-               return ret;
+       /* short circuit if it's the exact same firmware version */
+       if (hdr1->chip == hdr2->chip && hdr1->fw_ver == hdr2->fw_ver)
+               return 1;
 
-       major = FW_HDR_FW_VER_MAJOR_GET(adapter->params.fw_vers);
-       minor = FW_HDR_FW_VER_MINOR_GET(adapter->params.fw_vers);
-       micro = FW_HDR_FW_VER_MICRO_GET(adapter->params.fw_vers);
+#define SAME_INTF(x) (hdr1->intfver_##x == hdr2->intfver_##x)
+       if (hdr1->chip == hdr2->chip && SAME_INTF(nic) && SAME_INTF(vnic) &&
+           SAME_INTF(ri) && SAME_INTF(iscsi) && SAME_INTF(fcoe))
+               return 1;
+#undef SAME_INTF
 
-       switch (CHELSIO_CHIP_VERSION(adapter->chip)) {
-       case CHELSIO_T4:
-               exp_major = FW_VERSION_MAJOR;
-               exp_minor = FW_VERSION_MINOR;
-               exp_micro = FW_VERSION_MICRO;
-               break;
-       case CHELSIO_T5:
-               exp_major = FW_VERSION_MAJOR_T5;
-               exp_minor = FW_VERSION_MINOR_T5;
-               exp_micro = FW_VERSION_MICRO_T5;
-               break;
-       default:
-               dev_err(adapter->pdev_dev, "Unsupported chip type, %x\n",
-                       adapter->chip);
-               return -EINVAL;
-       }
+       return 0;
+}
 
-       memcpy(adapter->params.api_vers, api_vers,
-              sizeof(adapter->params.api_vers));
+/* The firmware in the filesystem is usable, but should it be installed?
+ * This routine explains itself in detail if it indicates the filesystem
+ * firmware should be installed.
+ */
+static int should_install_fs_fw(struct adapter *adap, int card_fw_usable,
+                               int k, int c)
+{
+       const char *reason;
 
-       if (major < exp_major || (major == exp_major && minor < exp_minor) ||
-           (major == exp_major && minor == exp_minor && micro < exp_micro)) {
-               dev_err(adapter->pdev_dev,
-                       "Card has firmware version %u.%u.%u, minimum "
-                       "supported firmware is %u.%u.%u.\n", major, minor,
-                       micro, exp_major, exp_minor, exp_micro);
-               return -EFAULT;
+       if (!card_fw_usable) {
+               reason = "incompatible or unusable";
+               goto install;
        }
 
-       if (major != exp_major) {            /* major mismatch - fail */
-               dev_err(adapter->pdev_dev,
-                       "card FW has major version %u, driver wants %u\n",
-                       major, exp_major);
-               return -EINVAL;
+       if (k > c) {
+               reason = "older than the version supported with this driver";
+               goto install;
        }
 
-       if (minor == exp_minor && micro == exp_micro)
-               return 0;                                   /* perfect match */
+       return 0;
+
+install:
+       dev_err(adap->pdev_dev, "firmware on card (%u.%u.%u.%u) is %s, "
+               "installing firmware %u.%u.%u.%u on card.\n",
+               FW_HDR_FW_VER_MAJOR_GET(c), FW_HDR_FW_VER_MINOR_GET(c),
+               FW_HDR_FW_VER_MICRO_GET(c), FW_HDR_FW_VER_BUILD_GET(c), reason,
+               FW_HDR_FW_VER_MAJOR_GET(k), FW_HDR_FW_VER_MINOR_GET(k),
+               FW_HDR_FW_VER_MICRO_GET(k), FW_HDR_FW_VER_BUILD_GET(k));
 
-       /* Minor/micro version mismatch.  Report it but often it's OK. */
        return 1;
 }
 
+int t4_prep_fw(struct adapter *adap, struct fw_info *fw_info,
+              const u8 *fw_data, unsigned int fw_size,
+              struct fw_hdr *card_fw, enum dev_state state,
+              int *reset)
+{
+       int ret, card_fw_usable, fs_fw_usable;
+       const struct fw_hdr *fs_fw;
+       const struct fw_hdr *drv_fw;
+
+       drv_fw = &fw_info->fw_hdr;
+
+       /* Read the header of the firmware on the card */
+       ret = -t4_read_flash(adap, FLASH_FW_START,
+                           sizeof(*card_fw) / sizeof(uint32_t),
+                           (uint32_t *)card_fw, 1);
+       if (ret == 0) {
+               card_fw_usable = fw_compatible(drv_fw, (const void *)card_fw);
+       } else {
+               dev_err(adap->pdev_dev,
+                       "Unable to read card's firmware header: %d\n", ret);
+               card_fw_usable = 0;
+       }
+
+       if (fw_data != NULL) {
+               fs_fw = (const void *)fw_data;
+               fs_fw_usable = fw_compatible(drv_fw, fs_fw);
+       } else {
+               fs_fw = NULL;
+               fs_fw_usable = 0;
+       }
+
+       if (card_fw_usable && card_fw->fw_ver == drv_fw->fw_ver &&
+           (!fs_fw_usable || fs_fw->fw_ver == drv_fw->fw_ver)) {
+               /* Common case: the firmware on the card is an exact match and
+                * the filesystem one is an exact match too, or the filesystem
+                * one is absent/incompatible.
+                */
+       } else if (fs_fw_usable && state == DEV_STATE_UNINIT &&
+                  should_install_fs_fw(adap, card_fw_usable,
+                                       be32_to_cpu(fs_fw->fw_ver),
+                                       be32_to_cpu(card_fw->fw_ver))) {
+               ret = -t4_fw_upgrade(adap, adap->mbox, fw_data,
+                                    fw_size, 0);
+               if (ret != 0) {
+                       dev_err(adap->pdev_dev,
+                               "failed to install firmware: %d\n", ret);
+                       goto bye;
+               }
+
+               /* Installed successfully, update the cached header too. */
+               memcpy(card_fw, fs_fw, sizeof(*card_fw));
+               card_fw_usable = 1;
+               *reset = 0;     /* already reset as part of load_fw */
+       }
+
+       if (!card_fw_usable) {
+               uint32_t d, c, k;
+
+               d = be32_to_cpu(drv_fw->fw_ver);
+               c = be32_to_cpu(card_fw->fw_ver);
+               k = fs_fw ? be32_to_cpu(fs_fw->fw_ver) : 0;
+
+               dev_err(adap->pdev_dev, "Cannot find a usable firmware: "
+                       "chip state %d, "
+                       "driver compiled with %d.%d.%d.%d, "
+                       "card has %d.%d.%d.%d, filesystem has %d.%d.%d.%d\n",
+                       state,
+                       FW_HDR_FW_VER_MAJOR_GET(d), FW_HDR_FW_VER_MINOR_GET(d),
+                       FW_HDR_FW_VER_MICRO_GET(d), FW_HDR_FW_VER_BUILD_GET(d),
+                       FW_HDR_FW_VER_MAJOR_GET(c), FW_HDR_FW_VER_MINOR_GET(c),
+                       FW_HDR_FW_VER_MICRO_GET(c), FW_HDR_FW_VER_BUILD_GET(c),
+                       FW_HDR_FW_VER_MAJOR_GET(k), FW_HDR_FW_VER_MINOR_GET(k),
+                       FW_HDR_FW_VER_MICRO_GET(k), FW_HDR_FW_VER_BUILD_GET(k));
+               ret = EINVAL;
+               goto bye;
+       }
+
+       /* We're using whatever's on the card and it's known to be good. */
+       adap->params.fw_vers = be32_to_cpu(card_fw->fw_ver);
+       adap->params.tp_vers = be32_to_cpu(card_fw->tp_microcode_ver);
+
+bye:
+       return ret;
+}
+
 /**
  *     t4_flash_erase_sectors - erase a range of flash sectors
  *     @adapter: the adapter
@@ -1368,7 +1433,7 @@ static void pcie_intr_handler(struct adapter *adapter)
                                    PCIE_CORE_UTL_PCI_EXPRESS_PORT_STATUS,
                                    pcie_port_intr_info) +
              t4_handle_intr_status(adapter, PCIE_INT_CAUSE,
-                                   is_t4(adapter->chip) ?
+                                   is_t4(adapter->params.chip) ?
                                    pcie_intr_info : t5_pcie_intr_info);
 
        if (fat)
@@ -1782,7 +1847,7 @@ static void xgmac_intr_handler(struct adapter *adap, int port)
 {
        u32 v, int_cause_reg;
 
-       if (is_t4(adap->chip))
+       if (is_t4(adap->params.chip))
                int_cause_reg = PORT_REG(port, XGMAC_PORT_INT_CAUSE);
        else
                int_cause_reg = T5_PORT_REG(port, MAC_PORT_INT_CAUSE);
@@ -2250,7 +2315,7 @@ void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p)
 
 #define GET_STAT(name) \
        t4_read_reg64(adap, \
-       (is_t4(adap->chip) ? PORT_REG(idx, MPS_PORT_STAT_##name##_L) : \
+       (is_t4(adap->params.chip) ? PORT_REG(idx, MPS_PORT_STAT_##name##_L) : \
        T5_PORT_REG(idx, MPS_PORT_STAT_##name##_L)))
 #define GET_STAT_COM(name) t4_read_reg64(adap, MPS_STAT_##name##_L)
 
@@ -2332,7 +2397,7 @@ void t4_wol_magic_enable(struct adapter *adap, unsigned int port,
 {
        u32 mag_id_reg_l, mag_id_reg_h, port_cfg_reg;
 
-       if (is_t4(adap->chip)) {
+       if (is_t4(adap->params.chip)) {
                mag_id_reg_l = PORT_REG(port, XGMAC_PORT_MAGIC_MACID_LO);
                mag_id_reg_h = PORT_REG(port, XGMAC_PORT_MAGIC_MACID_HI);
                port_cfg_reg = PORT_REG(port, XGMAC_PORT_CFG2);
@@ -2374,7 +2439,7 @@ int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map,
        int i;
        u32 port_cfg_reg;
 
-       if (is_t4(adap->chip))
+       if (is_t4(adap->params.chip))
                port_cfg_reg = PORT_REG(port, XGMAC_PORT_CFG2);
        else
                port_cfg_reg = T5_PORT_REG(port, MAC_PORT_CFG2);
@@ -2387,7 +2452,7 @@ int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map,
                return -EINVAL;
 
 #define EPIO_REG(name) \
-       (is_t4(adap->chip) ? PORT_REG(port, XGMAC_PORT_EPIO_##name) : \
+       (is_t4(adap->params.chip) ? PORT_REG(port, XGMAC_PORT_EPIO_##name) : \
        T5_PORT_REG(port, MAC_PORT_EPIO_##name))
 
        t4_write_reg(adap, EPIO_REG(DATA1), mask0 >> 32);
@@ -2474,7 +2539,7 @@ int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox,
 int t4_mem_win_read_len(struct adapter *adap, u32 addr, __be32 *data, int len)
 {
        int i, off;
-       u32 win_pf = is_t4(adap->chip) ? 0 : V_PFNUM(adap->fn);
+       u32 win_pf = is_t4(adap->params.chip) ? 0 : V_PFNUM(adap->fn);
 
        /* Align on a 2KB boundary.
         */
@@ -3306,7 +3371,7 @@ int t4_alloc_mac_filt(struct adapter *adap, unsigned int mbox,
        int i, ret;
        struct fw_vi_mac_cmd c;
        struct fw_vi_mac_exact *p;
-       unsigned int max_naddr = is_t4(adap->chip) ?
+       unsigned int max_naddr = is_t4(adap->params.chip) ?
                                       NUM_MPS_CLS_SRAM_L_INSTANCES :
                                       NUM_MPS_T5_CLS_SRAM_L_INSTANCES;
 
@@ -3368,7 +3433,7 @@ int t4_change_mac(struct adapter *adap, unsigned int mbox, unsigned int viid,
        int ret, mode;
        struct fw_vi_mac_cmd c;
        struct fw_vi_mac_exact *p = c.u.exact;
-       unsigned int max_mac_addr = is_t4(adap->chip) ?
+       unsigned int max_mac_addr = is_t4(adap->params.chip) ?
                                    NUM_MPS_CLS_SRAM_L_INSTANCES :
                                    NUM_MPS_T5_CLS_SRAM_L_INSTANCES;
 
@@ -3699,13 +3764,14 @@ int t4_prep_adapter(struct adapter *adapter)
 {
        int ret, ver;
        uint16_t device_id;
+       u32 pl_rev;
 
        ret = t4_wait_dev_ready(adapter);
        if (ret < 0)
                return ret;
 
        get_pci_mode(adapter, &adapter->params.pci);
-       adapter->params.rev = t4_read_reg(adapter, PL_REV);
+       pl_rev = G_REV(t4_read_reg(adapter, PL_REV));
 
        ret = get_flash_params(adapter);
        if (ret < 0) {
@@ -3717,14 +3783,13 @@ int t4_prep_adapter(struct adapter *adapter)
         */
        pci_read_config_word(adapter->pdev, PCI_DEVICE_ID, &device_id);
        ver = device_id >> 12;
+       adapter->params.chip = 0;
        switch (ver) {
        case CHELSIO_T4:
-               adapter->chip = CHELSIO_CHIP_CODE(CHELSIO_T4,
-                                                 adapter->params.rev);
+               adapter->params.chip |= CHELSIO_CHIP_CODE(CHELSIO_T4, pl_rev);
                break;
        case CHELSIO_T5:
-               adapter->chip = CHELSIO_CHIP_CODE(CHELSIO_T5,
-                                                 adapter->params.rev);
+               adapter->params.chip |= CHELSIO_CHIP_CODE(CHELSIO_T5, pl_rev);
                break;
        default:
                dev_err(adapter->pdev_dev, "Device %d is not supported\n",
@@ -3732,9 +3797,6 @@ int t4_prep_adapter(struct adapter *adapter)
                return -EINVAL;
        }
 
-       /* Reassign the updated revision field */
-       adapter->params.rev = adapter->chip;
-
        init_cong_ctrl(adapter->params.a_wnd, adapter->params.b_wnd);
 
        /*
index ef146c0ba4814ef5abff64794075b9d5e806c62b..0a8205d69d2c290aae4dbec30245c9dc3e18bd39 100644 (file)
 
 #define PL_REV 0x1943c
 
+#define S_REV    0
+#define M_REV    0xfU
+#define V_REV(x) ((x) << S_REV)
+#define G_REV(x) (((x) >> S_REV) & M_REV)
+
 #define LE_DB_CONFIG 0x19c04
 #define  HASHEN 0x00100000U
 
 #define EDC_STRIDE_T5 (EDC_T51_BASE_ADDR - EDC_T50_BASE_ADDR)
 #define EDC_REG_T5(reg, idx) (reg + EDC_STRIDE_T5 * idx)
 
+#define A_PL_VF_REV 0x4
+#define A_PL_VF_WHOAMI 0x0
+#define A_PL_VF_REVISION 0x8
+
+#define S_CHIPID    4
+#define M_CHIPID    0xfU
+#define V_CHIPID(x) ((x) << S_CHIPID)
+#define G_CHIPID(x) (((x) >> S_CHIPID) & M_CHIPID)
+
 #endif /* __T4_REGS_H */
index 6f77ac487743edfbe899f470805f58cc38d9c61b..74fea74ce0aa25a676045868fa0b48c4a3800860 100644 (file)
@@ -2157,7 +2157,7 @@ struct fw_debug_cmd {
 
 struct fw_hdr {
        u8 ver;
-       u8 reserved1;
+       u8 chip;                        /* terminator chip type */
        __be16  len512;                 /* bin length in units of 512-bytes */
        __be32  fw_ver;                 /* firmware version */
        __be32  tp_microcode_ver;
@@ -2176,6 +2176,11 @@ struct fw_hdr {
        __be32  reserved6[23];
 };
 
+enum fw_hdr_chip {
+       FW_HDR_CHIP_T4,
+       FW_HDR_CHIP_T5
+};
+
 #define FW_HDR_FW_VER_MAJOR_GET(x) (((x) >> 24) & 0xff)
 #define FW_HDR_FW_VER_MINOR_GET(x) (((x) >> 16) & 0xff)
 #define FW_HDR_FW_VER_MICRO_GET(x) (((x) >> 8) & 0xff)
index be5c7ef6ca939654365b6aec6dc108e03e0f74d9..68eaa9c88c7d8a77646bd217e00877a281254a59 100644 (file)
@@ -344,7 +344,6 @@ struct adapter {
        unsigned long registered_device_map;
        unsigned long open_device_map;
        unsigned long flags;
-       enum chip_type chip;
        struct adapter_params params;
 
        /* queue and interrupt resources */
index 5f90ec5f7519a4ac6e7916396cff31446f5c614b..0899c098359446346f7abe1939ac214705fd0acb 100644 (file)
@@ -1064,7 +1064,7 @@ static inline unsigned int mk_adap_vers(const struct adapter *adapter)
        /*
         * Chip version 4, revision 0x3f (cxgb4vf).
         */
-       return CHELSIO_CHIP_VERSION(adapter->chip) | (0x3f << 10);
+       return CHELSIO_CHIP_VERSION(adapter->params.chip) | (0x3f << 10);
 }
 
 /*
@@ -1551,9 +1551,13 @@ static void cxgb4vf_get_regs(struct net_device *dev,
        reg_block_dump(adapter, regbuf,
                       T4VF_MPS_BASE_ADDR + T4VF_MOD_MAP_MPS_FIRST,
                       T4VF_MPS_BASE_ADDR + T4VF_MOD_MAP_MPS_LAST);
+
+       /* T5 adds new registers in the PL Register map.
+        */
        reg_block_dump(adapter, regbuf,
                       T4VF_PL_BASE_ADDR + T4VF_MOD_MAP_PL_FIRST,
-                      T4VF_PL_BASE_ADDR + T4VF_MOD_MAP_PL_LAST);
+                      T4VF_PL_BASE_ADDR + (is_t4(adapter->params.chip)
+                      ? A_PL_VF_WHOAMI : A_PL_VF_REVISION));
        reg_block_dump(adapter, regbuf,
                       T4VF_CIM_BASE_ADDR + T4VF_MOD_MAP_CIM_FIRST,
                       T4VF_CIM_BASE_ADDR + T4VF_MOD_MAP_CIM_LAST);
@@ -2087,6 +2091,7 @@ static int adap_init0(struct adapter *adapter)
        unsigned int ethqsets;
        int err;
        u32 param, val = 0;
+       unsigned int chipid;
 
        /*
         * Wait for the device to become ready before proceeding ...
@@ -2114,12 +2119,14 @@ static int adap_init0(struct adapter *adapter)
                return err;
        }
 
+       adapter->params.chip = 0;
        switch (adapter->pdev->device >> 12) {
        case CHELSIO_T4:
-               adapter->chip = CHELSIO_CHIP_CODE(CHELSIO_T4, 0);
+               adapter->params.chip = CHELSIO_CHIP_CODE(CHELSIO_T4, 0);
                break;
        case CHELSIO_T5:
-               adapter->chip = CHELSIO_CHIP_CODE(CHELSIO_T5, 0);
+               chipid = G_REV(t4_read_reg(adapter, A_PL_VF_REV));
+               adapter->params.chip |= CHELSIO_CHIP_CODE(CHELSIO_T5, chipid);
                break;
        }
 
index 8475c4cda9e4ca72ef8a2b309788620e82fb67d3..0a89963c48ce78148d1abe6cd86151e850c24062 100644 (file)
@@ -537,7 +537,7 @@ static inline void ring_fl_db(struct adapter *adapter, struct sge_fl *fl)
         */
        if (fl->pend_cred >= FL_PER_EQ_UNIT) {
                val = PIDX(fl->pend_cred / FL_PER_EQ_UNIT);
-               if (!is_t4(adapter->chip))
+               if (!is_t4(adapter->params.chip))
                        val |= DBTYPE(1);
                wmb();
                t4_write_reg(adapter, T4VF_SGE_BASE_ADDR + SGE_VF_KDOORBELL,
index 53cbfed21d0b9871fe257ee75836dc2dadbdc185..61362450d05b4f83daeacf9a0c54ebed35e2da4c 100644 (file)
 #include "../cxgb4/t4fw_api.h"
 
 #define CHELSIO_CHIP_CODE(version, revision) (((version) << 4) | (revision))
-#define CHELSIO_CHIP_VERSION(code) ((code) >> 4)
+#define CHELSIO_CHIP_VERSION(code) (((code) >> 4) & 0xf)
 #define CHELSIO_CHIP_RELEASE(code) ((code) & 0xf)
 
+/* All T4 and later chips have their PCI-E Device IDs encoded as 0xVFPP where:
+ *
+ *   V  = "4" for T4; "5" for T5, etc. or
+ *      = "a" for T4 FPGA; "b" for T4 FPGA, etc.
+ *   F  = "0" for PF 0..3; "4".."7" for PF4..7; and "8" for VFs
+ *   PP = adapter product designation
+ */
 #define CHELSIO_T4             0x4
 #define CHELSIO_T5             0x5
 
 enum chip_type {
-       T4_A1 = CHELSIO_CHIP_CODE(CHELSIO_T4, 0),
-       T4_A2 = CHELSIO_CHIP_CODE(CHELSIO_T4, 1),
-       T4_A3 = CHELSIO_CHIP_CODE(CHELSIO_T4, 2),
+       T4_A1 = CHELSIO_CHIP_CODE(CHELSIO_T4, 1),
+       T4_A2 = CHELSIO_CHIP_CODE(CHELSIO_T4, 2),
        T4_FIRST_REV    = T4_A1,
-       T4_LAST_REV     = T4_A3,
+       T4_LAST_REV     = T4_A2,
 
-       T5_A1 = CHELSIO_CHIP_CODE(CHELSIO_T5, 0),
-       T5_FIRST_REV    = T5_A1,
+       T5_A0 = CHELSIO_CHIP_CODE(CHELSIO_T5, 0),
+       T5_A1 = CHELSIO_CHIP_CODE(CHELSIO_T5, 1),
+       T5_FIRST_REV    = T5_A0,
        T5_LAST_REV     = T5_A1,
 };
 
@@ -203,6 +210,7 @@ struct adapter_params {
        struct vpd_params vpd;          /* Vital Product Data */
        struct rss_params rss;          /* Receive Side Scaling */
        struct vf_resources vfres;      /* Virtual Function Resource limits */
+       enum chip_type chip;            /* chip code */
        u8 nports;                      /* # of Ethernet "ports" */
 };
 
@@ -253,7 +261,7 @@ static inline int t4vf_wr_mbox_ns(struct adapter *adapter, const void *cmd,
 
 static inline int is_t4(enum chip_type chip)
 {
-       return (chip >= T4_FIRST_REV && chip <= T4_LAST_REV);
+       return CHELSIO_CHIP_VERSION(chip) == CHELSIO_T4;
 }
 
 int t4vf_wait_dev_ready(struct adapter *);
index 9f96dc3bb11203e0781faa785d12ec31df4f76f3..d958c44341b5cb299d704600494de5be9d15bb72 100644 (file)
@@ -1027,7 +1027,7 @@ int t4vf_alloc_mac_filt(struct adapter *adapter, unsigned int viid, bool free,
        unsigned nfilters = 0;
        unsigned int rem = naddr;
        struct fw_vi_mac_cmd cmd, rpl;
-       unsigned int max_naddr = is_t4(adapter->chip) ?
+       unsigned int max_naddr = is_t4(adapter->params.chip) ?
                                 NUM_MPS_CLS_SRAM_L_INSTANCES :
                                 NUM_MPS_T5_CLS_SRAM_L_INSTANCES;
 
@@ -1121,7 +1121,7 @@ int t4vf_change_mac(struct adapter *adapter, unsigned int viid,
        struct fw_vi_mac_exact *p = &cmd.u.exact[0];
        size_t len16 = DIV_ROUND_UP(offsetof(struct fw_vi_mac_cmd,
                                             u.exact[1]), 16);
-       unsigned int max_naddr = is_t4(adapter->chip) ?
+       unsigned int max_naddr = is_t4(adapter->params.chip) ?
                                 NUM_MPS_CLS_SRAM_L_INSTANCES :
                                 NUM_MPS_T5_CLS_SRAM_L_INSTANCES;
 
index f4825db5d1792419924bab4f9d08e17abbfd6128..5878df619b531ad0b3ea96167f53e8909ff9fd21 100644 (file)
@@ -503,6 +503,7 @@ struct be_adapter {
 };
 
 #define be_physfn(adapter)             (!adapter->virtfn)
+#define be_virtfn(adapter)             (adapter->virtfn)
 #define        sriov_enabled(adapter)          (adapter->num_vfs > 0)
 #define sriov_want(adapter)             (be_physfn(adapter) && \
                                         (num_vfs || pci_num_vf(adapter->pdev)))
index dbcd5262c0167c1ae0dacf7dd578b5c3a2a43ce5..e0e8bc1ef14c47e93336df2c784d1ff14e6b4143 100644 (file)
@@ -1032,6 +1032,13 @@ int be_cmd_cq_create(struct be_adapter *adapter, struct be_queue_info *cq,
        } else {
                req->hdr.version = 2;
                req->page_size = 1; /* 1 for 4K */
+
+               /* coalesce-wm field in this cmd is not relevant to Lancer.
+                * Lancer uses COMMON_MODIFY_CQ to set this field
+                */
+               if (!lancer_chip(adapter))
+                       AMAP_SET_BITS(struct amap_cq_context_v2, coalescwm,
+                                     ctxt, coalesce_wm);
                AMAP_SET_BITS(struct amap_cq_context_v2, nodelay, ctxt,
                                                                no_delay);
                AMAP_SET_BITS(struct amap_cq_context_v2, count, ctxt,
index 3e2162121601e79481428c4d7ca02c3523dc0e33..dc88782185f26f000e4e58cd793f90f6064bbfb6 100644 (file)
@@ -64,6 +64,9 @@
 #define SLIPORT_ERROR_NO_RESOURCE1     0x2
 #define SLIPORT_ERROR_NO_RESOURCE2     0x9
 
+#define SLIPORT_ERROR_FW_RESET1                0x2
+#define SLIPORT_ERROR_FW_RESET2                0x0
+
 /********* Memory BAR register ************/
 #define PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET     0xfc
 /* Host Interrupt Enable, if set interrupts are enabled although "PCI Interrupt
index abde97471636918a6b7e2381634cdc743678d24c..0fde69d5cb6afd610db5f2a57325e5d2e9f5ed94 100644 (file)
@@ -2464,8 +2464,16 @@ void be_detect_error(struct be_adapter *adapter)
         */
        if (sliport_status & SLIPORT_STATUS_ERR_MASK) {
                adapter->hw_error = true;
-               dev_err(&adapter->pdev->dev,
-                       "Error detected in the card\n");
+               /* Do not log error messages if its a FW reset */
+               if (sliport_err1 == SLIPORT_ERROR_FW_RESET1 &&
+                   sliport_err2 == SLIPORT_ERROR_FW_RESET2) {
+                       dev_info(&adapter->pdev->dev,
+                                "Firmware update in progress\n");
+                       return;
+               } else {
+                       dev_err(&adapter->pdev->dev,
+                               "Error detected in the card\n");
+               }
        }
 
        if (sliport_status & SLIPORT_STATUS_ERR_MASK) {
@@ -2658,8 +2666,8 @@ static int be_close(struct net_device *netdev)
 
        be_roce_dev_close(adapter);
 
-       for_all_evt_queues(adapter, eqo, i) {
-               if (adapter->flags & BE_FLAGS_NAPI_ENABLED) {
+       if (adapter->flags & BE_FLAGS_NAPI_ENABLED) {
+               for_all_evt_queues(adapter, eqo, i) {
                        napi_disable(&eqo->napi);
                        be_disable_busy_poll(eqo);
                }
@@ -2932,28 +2940,35 @@ static void be_cancel_worker(struct be_adapter *adapter)
        }
 }
 
-static int be_clear(struct be_adapter *adapter)
+static void be_mac_clear(struct be_adapter *adapter)
 {
        int i;
 
+       if (adapter->pmac_id) {
+               for (i = 0; i < (adapter->uc_macs + 1); i++)
+                       be_cmd_pmac_del(adapter, adapter->if_handle,
+                                       adapter->pmac_id[i], 0);
+               adapter->uc_macs = 0;
+
+               kfree(adapter->pmac_id);
+               adapter->pmac_id = NULL;
+       }
+}
+
+static int be_clear(struct be_adapter *adapter)
+{
        be_cancel_worker(adapter);
 
        if (sriov_enabled(adapter))
                be_vf_clear(adapter);
 
        /* delete the primary mac along with the uc-mac list */
-       for (i = 0; i < (adapter->uc_macs + 1); i++)
-               be_cmd_pmac_del(adapter, adapter->if_handle,
-                               adapter->pmac_id[i], 0);
-       adapter->uc_macs = 0;
+       be_mac_clear(adapter);
 
        be_cmd_if_destroy(adapter, adapter->if_handle,  0);
 
        be_clear_queues(adapter);
 
-       kfree(adapter->pmac_id);
-       adapter->pmac_id = NULL;
-
        be_msix_disable(adapter);
        return 0;
 }
@@ -3253,12 +3268,10 @@ static int be_mac_setup(struct be_adapter *adapter)
                memcpy(mac, adapter->netdev->dev_addr, ETH_ALEN);
        }
 
-       /* On BE3 VFs this cmd may fail due to lack of privilege.
-        * Ignore the failure as in this case pmac_id is fetched
-        * in the IFACE_CREATE cmd.
-        */
-       be_cmd_pmac_add(adapter, mac, adapter->if_handle,
-                       &adapter->pmac_id[0], 0);
+       /* For BE3-R VFs, the PF programs the initial MAC address */
+       if (!(BEx_chip(adapter) && be_virtfn(adapter)))
+               be_cmd_pmac_add(adapter, mac, adapter->if_handle,
+                               &adapter->pmac_id[0], 0);
        return 0;
 }
 
@@ -3814,6 +3827,8 @@ static int lancer_fw_download(struct be_adapter *adapter,
        }
 
        if (change_status == LANCER_FW_RESET_NEEDED) {
+               dev_info(&adapter->pdev->dev,
+                        "Resetting adapter to activate new FW\n");
                status = lancer_physdev_ctrl(adapter,
                                             PHYSDEV_CONTROL_FW_RESET_MASK);
                if (status) {
@@ -4365,13 +4380,13 @@ static int lancer_recover_func(struct be_adapter *adapter)
                        goto err;
        }
 
-       dev_err(dev, "Error recovery successful\n");
+       dev_err(dev, "Adapter recovery successful\n");
        return 0;
 err:
        if (status == -EAGAIN)
                dev_err(dev, "Waiting for resource provisioning\n");
        else
-               dev_err(dev, "Error recovery failed\n");
+               dev_err(dev, "Adapter recovery failed\n");
 
        return status;
 }
@@ -4599,6 +4614,7 @@ static int be_suspend(struct pci_dev *pdev, pm_message_t state)
        if (adapter->wol)
                be_setup_wol(adapter, true);
 
+       be_intr_set(adapter, false);
        cancel_delayed_work_sync(&adapter->func_recovery_work);
 
        netif_device_detach(netdev);
@@ -4634,6 +4650,7 @@ static int be_resume(struct pci_dev *pdev)
        if (status)
                return status;
 
+       be_intr_set(adapter, true);
        /* tell fw we're ready to fire cmds */
        status = be_cmd_fw_init(adapter);
        if (status)
index 0120217a16dd8c7d1dbedbf088957785e741c3de..3b8d6d19ff0595885570713d7f866c732695a0db 100644 (file)
@@ -339,7 +339,8 @@ struct fec_enet_private {
 
 void fec_ptp_init(struct platform_device *pdev);
 void fec_ptp_start_cyclecounter(struct net_device *ndev);
-int fec_ptp_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd);
+int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr);
+int fec_ptp_get(struct net_device *ndev, struct ifreq *ifr);
 
 /****************************************************************************/
 #endif /* FEC_H */
index 4cbebf3d80eb1492d847f1ad8a9888e2a6c17b97..92ef4e5eddf74b57dff2306354cedfb68768387d 100644 (file)
@@ -385,7 +385,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
         * data.
         */
        bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, bufaddr,
-                       FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);
+                       skb->len, DMA_TO_DEVICE);
        if (dma_mapping_error(&fep->pdev->dev, bdp->cbd_bufaddr)) {
                bdp->cbd_bufaddr = 0;
                fep->tx_skbuff[index] = NULL;
@@ -779,11 +779,10 @@ fec_enet_tx(struct net_device *ndev)
                else
                        index = bdp - fep->tx_bd_base;
 
-               dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
-                               FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);
-               bdp->cbd_bufaddr = 0;
-
                skb = fep->tx_skbuff[index];
+               dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, skb->len,
+                               DMA_TO_DEVICE);
+               bdp->cbd_bufaddr = 0;
 
                /* Check for errors. */
                if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC |
@@ -1684,8 +1683,12 @@ static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
        if (!phydev)
                return -ENODEV;
 
-       if (cmd == SIOCSHWTSTAMP && fep->bufdesc_ex)
-               return fec_ptp_ioctl(ndev, rq, cmd);
+       if (fep->bufdesc_ex) {
+               if (cmd == SIOCSHWTSTAMP)
+                       return fec_ptp_set(ndev, rq);
+               if (cmd == SIOCGHWTSTAMP)
+                       return fec_ptp_get(ndev, rq);
+       }
 
        return phy_mii_ioctl(phydev, rq, cmd);
 }
index 5007e4f9fff91705d93e875ad2c15108e915ebb3..3a74ea48fd40c698cfe75c2a1c8f97d7142675c2 100644 (file)
@@ -274,7 +274,7 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp,
  * @ifreq: ioctl data
  * @cmd: particular ioctl requested
  */
-int fec_ptp_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd)
+int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr)
 {
        struct fec_enet_private *fep = netdev_priv(ndev);
 
@@ -321,6 +321,20 @@ int fec_ptp_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd)
            -EFAULT : 0;
 }
 
+int fec_ptp_get(struct net_device *ndev, struct ifreq *ifr)
+{
+       struct fec_enet_private *fep = netdev_priv(ndev);
+       struct hwtstamp_config config;
+
+       config.flags = 0;
+       config.tx_type = fep->hwts_tx_en ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
+       config.rx_filter = (fep->hwts_rx_en ?
+                           HWTSTAMP_FILTER_ALL : HWTSTAMP_FILTER_NONE);
+
+       return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
+               -EFAULT : 0;
+}
+
 /**
  * fec_time_keep - call timecounter_read every second to avoid timer overrun
  *                 because ENET just support 32bit counter, will timeout in 4s
index b14d7904a075e69779e4a2847dee1bedaba791d2..365342d293e82492f396551cdf1dad5af702e817 100644 (file)
@@ -795,8 +795,7 @@ err_grp_init:
        return err;
 }
 
-static int gfar_hwtstamp_ioctl(struct net_device *netdev,
-                              struct ifreq *ifr, int cmd)
+static int gfar_hwtstamp_set(struct net_device *netdev, struct ifreq *ifr)
 {
        struct hwtstamp_config config;
        struct gfar_private *priv = netdev_priv(netdev);
@@ -845,7 +844,20 @@ static int gfar_hwtstamp_ioctl(struct net_device *netdev,
                -EFAULT : 0;
 }
 
-/* Ioctl MII Interface */
+static int gfar_hwtstamp_get(struct net_device *netdev, struct ifreq *ifr)
+{
+       struct hwtstamp_config config;
+       struct gfar_private *priv = netdev_priv(netdev);
+
+       config.flags = 0;
+       config.tx_type = priv->hwts_tx_en ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
+       config.rx_filter = (priv->hwts_rx_en ?
+                           HWTSTAMP_FILTER_ALL : HWTSTAMP_FILTER_NONE);
+
+       return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
+               -EFAULT : 0;
+}
+
 static int gfar_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
        struct gfar_private *priv = netdev_priv(dev);
@@ -854,7 +866,9 @@ static int gfar_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                return -EINVAL;
 
        if (cmd == SIOCSHWTSTAMP)
-               return gfar_hwtstamp_ioctl(dev, rq, cmd);
+               return gfar_hwtstamp_set(dev, rq);
+       if (cmd == SIOCGHWTSTAMP)
+               return gfar_hwtstamp_get(dev, rq);
 
        if (!priv->phydev)
                return -ENODEV;
index 2d1c6bdd36189f9f595ada15599301ce992330a9..7628e0fd84554fd56eca5f4181f2ff31c85eca0d 100644 (file)
@@ -3033,7 +3033,7 @@ static struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
 
        dev->hw_features = NETIF_F_SG | NETIF_F_TSO |
                      NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_CTAG_TX;
-       dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO |
+       dev->features = NETIF_F_SG | NETIF_F_TSO |
                      NETIF_F_HIGHDMA | NETIF_F_IP_CSUM |
                      NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
                      NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_RXCSUM;
index 952d795230a479c79c0684ee0849a05e5e0ff631..cde0fd941f0ce6bbb8364f268a141cc1917d8e41 100644 (file)
@@ -12,8 +12,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * Copyright (C) IBM Corporation, 2003, 2010
  *
index 84066bafe0576f8ac72126c43377a07bcade027b..451ba7949e152a66ee87e661e90722496792dfb8 100644 (file)
@@ -12,8 +12,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * Copyright (C) IBM Corporation, 2003, 2010
  *
index 149ac85b5f9e328d584aaa2a40d899527739edc5..41a2fa2fc67dff1ff1c03f9fc6e09234e4c8897e 100644 (file)
@@ -220,12 +220,12 @@ config IXGBE_DCB
          If unsure, say N.
 
 config IXGBEVF
-       tristate "Intel(R) 82599 Virtual Function Ethernet support"
+       tristate "Intel(R) 10GbE PCI Express Virtual Function Ethernet support"
        depends on PCI_MSI
        ---help---
-         This driver supports Intel(R) 82599 virtual functions.  For more
-         information on how to identify your adapter, go to the Adapter &
-         Driver ID Guide at:
+         This driver supports Intel(R) PCI Express virtual functions for the
+         Intel(R) ixgbe driver.  For more information on how to identify your
+         adapter, go to the Adapter & Driver ID Guide at:
 
          <http://support.intel.com/support/network/sb/CS-008441.htm>
 
index 58c147271a362e68914d55d97b71b327b194e86b..f9313b36c88716068611b44d3c7a6b182d4277e9 100644 (file)
@@ -83,6 +83,11 @@ struct e1000_adapter;
 
 #define E1000_MAX_INTR                 10
 
+/*
+ * Count for polling __E1000_RESET condition every 10-20msec.
+ */
+#define E1000_CHECK_RESET_COUNT        50
+
 /* TX/RX descriptor defines */
 #define E1000_DEFAULT_TXD              256
 #define E1000_MAX_TXD                  256
@@ -312,8 +317,6 @@ struct e1000_adapter {
        struct delayed_work watchdog_task;
        struct delayed_work fifo_stall_task;
        struct delayed_work phy_info_task;
-
-       struct mutex mutex;
 };
 
 enum e1000_state_t {
index e38622825fa7336ae74f64229f3e5619cb668335..46e6544ed1b7f5c1ba9367dd1dfe444d725cd0e3 100644 (file)
@@ -494,13 +494,20 @@ static void e1000_down_and_stop(struct e1000_adapter *adapter)
 {
        set_bit(__E1000_DOWN, &adapter->flags);
 
-       /* Only kill reset task if adapter is not resetting */
-       if (!test_bit(__E1000_RESETTING, &adapter->flags))
-               cancel_work_sync(&adapter->reset_task);
-
        cancel_delayed_work_sync(&adapter->watchdog_task);
+
+       /*
+        * Since the watchdog task can reschedule other tasks, we should cancel
+        * it first, otherwise we can run into the situation when a work is
+        * still running after the adapter has been turned down.
+        */
+
        cancel_delayed_work_sync(&adapter->phy_info_task);
        cancel_delayed_work_sync(&adapter->fifo_stall_task);
+
+       /* Only kill reset task if adapter is not resetting */
+       if (!test_bit(__E1000_RESETTING, &adapter->flags))
+               cancel_work_sync(&adapter->reset_task);
 }
 
 void e1000_down(struct e1000_adapter *adapter)
@@ -544,21 +551,8 @@ void e1000_down(struct e1000_adapter *adapter)
        e1000_clean_all_rx_rings(adapter);
 }
 
-static void e1000_reinit_safe(struct e1000_adapter *adapter)
-{
-       while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
-               msleep(1);
-       mutex_lock(&adapter->mutex);
-       e1000_down(adapter);
-       e1000_up(adapter);
-       mutex_unlock(&adapter->mutex);
-       clear_bit(__E1000_RESETTING, &adapter->flags);
-}
-
 void e1000_reinit_locked(struct e1000_adapter *adapter)
 {
-       /* if rtnl_lock is not held the call path is bogus */
-       ASSERT_RTNL();
        WARN_ON(in_interrupt());
        while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
                msleep(1);
@@ -1316,7 +1310,6 @@ static int e1000_sw_init(struct e1000_adapter *adapter)
        e1000_irq_disable(adapter);
 
        spin_lock_init(&adapter->stats_lock);
-       mutex_init(&adapter->mutex);
 
        set_bit(__E1000_DOWN, &adapter->flags);
 
@@ -1440,6 +1433,10 @@ static int e1000_close(struct net_device *netdev)
 {
        struct e1000_adapter *adapter = netdev_priv(netdev);
        struct e1000_hw *hw = &adapter->hw;
+       int count = E1000_CHECK_RESET_COUNT;
+
+       while (test_bit(__E1000_RESETTING, &adapter->flags) && count--)
+               usleep_range(10000, 20000);
 
        WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags));
        e1000_down(adapter);
@@ -2325,11 +2322,8 @@ static void e1000_update_phy_info_task(struct work_struct *work)
        struct e1000_adapter *adapter = container_of(work,
                                                     struct e1000_adapter,
                                                     phy_info_task.work);
-       if (test_bit(__E1000_DOWN, &adapter->flags))
-               return;
-       mutex_lock(&adapter->mutex);
+
        e1000_phy_get_info(&adapter->hw, &adapter->phy_info);
-       mutex_unlock(&adapter->mutex);
 }
 
 /**
@@ -2345,9 +2339,6 @@ static void e1000_82547_tx_fifo_stall_task(struct work_struct *work)
        struct net_device *netdev = adapter->netdev;
        u32 tctl;
 
-       if (test_bit(__E1000_DOWN, &adapter->flags))
-               return;
-       mutex_lock(&adapter->mutex);
        if (atomic_read(&adapter->tx_fifo_stall)) {
                if ((er32(TDT) == er32(TDH)) &&
                   (er32(TDFT) == er32(TDFH)) &&
@@ -2368,7 +2359,6 @@ static void e1000_82547_tx_fifo_stall_task(struct work_struct *work)
                        schedule_delayed_work(&adapter->fifo_stall_task, 1);
                }
        }
-       mutex_unlock(&adapter->mutex);
 }
 
 bool e1000_has_link(struct e1000_adapter *adapter)
@@ -2422,10 +2412,6 @@ static void e1000_watchdog(struct work_struct *work)
        struct e1000_tx_ring *txdr = adapter->tx_ring;
        u32 link, tctl;
 
-       if (test_bit(__E1000_DOWN, &adapter->flags))
-               return;
-
-       mutex_lock(&adapter->mutex);
        link = e1000_has_link(adapter);
        if ((netif_carrier_ok(netdev)) && link)
                goto link_up;
@@ -2516,7 +2502,7 @@ link_up:
                        adapter->tx_timeout_count++;
                        schedule_work(&adapter->reset_task);
                        /* exit immediately since reset is imminent */
-                       goto unlock;
+                       return;
                }
        }
 
@@ -2544,9 +2530,6 @@ link_up:
        /* Reschedule the task */
        if (!test_bit(__E1000_DOWN, &adapter->flags))
                schedule_delayed_work(&adapter->watchdog_task, 2 * HZ);
-
-unlock:
-       mutex_unlock(&adapter->mutex);
 }
 
 enum latency_range {
@@ -3495,10 +3478,8 @@ static void e1000_reset_task(struct work_struct *work)
        struct e1000_adapter *adapter =
                container_of(work, struct e1000_adapter, reset_task);
 
-       if (test_bit(__E1000_DOWN, &adapter->flags))
-               return;
        e_err(drv, "Reset adapter\n");
-       e1000_reinit_safe(adapter);
+       e1000_reinit_locked(adapter);
 }
 
 /**
@@ -4963,6 +4944,11 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)
        netif_device_detach(netdev);
 
        if (netif_running(netdev)) {
+               int count = E1000_CHECK_RESET_COUNT;
+
+               while (test_bit(__E1000_RESETTING, &adapter->flags) && count--)
+                       usleep_range(10000, 20000);
+
                WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags));
                e1000_down(adapter);
        }
index 8d3945ab7334840684db42ea6eefa9bafc52c061..051d1583e21130dfddac70cb42c16e66a249bda8 100644 (file)
@@ -5790,7 +5790,7 @@ static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
  * specified. Matching the kind of event packet is not supported, with the
  * exception of "all V2 events regardless of level 2 or 4".
  **/
-static int e1000e_hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr)
+static int e1000e_hwtstamp_set(struct net_device *netdev, struct ifreq *ifr)
 {
        struct e1000_adapter *adapter = netdev_priv(netdev);
        struct hwtstamp_config config;
@@ -5825,6 +5825,14 @@ static int e1000e_hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr)
                            sizeof(config)) ? -EFAULT : 0;
 }
 
+static int e1000e_hwtstamp_get(struct net_device *netdev, struct ifreq *ifr)
+{
+       struct e1000_adapter *adapter = netdev_priv(netdev);
+
+       return copy_to_user(ifr->ifr_data, &adapter->hwtstamp_config,
+                           sizeof(adapter->hwtstamp_config)) ? -EFAULT : 0;
+}
+
 static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
 {
        switch (cmd) {
@@ -5833,7 +5841,9 @@ static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
        case SIOCSMIIREG:
                return e1000_mii_ioctl(netdev, ifr, cmd);
        case SIOCSHWTSTAMP:
-               return e1000e_hwtstamp_ioctl(netdev, ifr);
+               return e1000e_hwtstamp_set(netdev, ifr);
+       case SIOCGHWTSTAMP:
+               return e1000e_hwtstamp_get(netdev, ifr);
        default:
                return -EOPNOTSUPP;
        }
index 1ca9834cdfda58411c5a43bd3ec344382500382f..001d7cfc9129c8501ca62a2847fd201c79698276 100644 (file)
@@ -61,6 +61,7 @@
 #define I40E_BASE_VSI_SEID    512
 #define I40E_BASE_VEB_SEID    288
 #define I40E_MAX_VEB          16
+#define I40E_MAX_NPAR_QPS     32
 
 #define I40E_MAX_NUM_DESCRIPTORS      4096
 #define I40E_MAX_REGISTER     0x0038FFFF
 #define I40E_DEFAULT_MSG_ENABLE       4
 
 #define I40E_NVM_VERSION_LO_SHIFT  0
-#define I40E_NVM_VERSION_LO_MASK   (0xf << I40E_NVM_VERSION_LO_SHIFT)
-#define I40E_NVM_VERSION_MID_SHIFT 4
-#define I40E_NVM_VERSION_MID_MASK  (0xff << I40E_NVM_VERSION_MID_SHIFT)
-#define I40E_NVM_VERSION_HI_SHIFT  12
-#define I40E_NVM_VERSION_HI_MASK   (0xf << I40E_NVM_VERSION_HI_SHIFT)
+#define I40E_NVM_VERSION_LO_MASK   (0xff << I40E_NVM_VERSION_LO_SHIFT)
+#define I40E_NVM_VERSION_HI_SHIFT  8
+#define I40E_NVM_VERSION_HI_MASK   (0xff << I40E_NVM_VERSION_HI_SHIFT)
+
+/* The values in here are decimal coded as hex as is the case in the NVM map*/
+#define I40E_CURRENT_NVM_VERSION_HI 0x2
+#define I40E_CURRENT_NVM_VERSION_LO 0x1
+
 
 /* magic for getting defines into strings */
 #define STRINGIFY(foo)  #foo
@@ -127,6 +131,7 @@ enum i40e_state_t {
        __I40E_PF_RESET_REQUESTED,
        __I40E_CORE_RESET_REQUESTED,
        __I40E_GLOBAL_RESET_REQUESTED,
+       __I40E_EMP_RESET_REQUESTED,
        __I40E_FILTER_OVERFLOW_PROMISC,
 };
 
@@ -247,6 +252,7 @@ struct i40e_pf {
        u16 globr_count; /* Global reset count */
        u16 empr_count; /* EMP reset count */
        u16 pfr_count; /* PF reset count */
+       u16 sw_int_count; /* SW interrupt count */
 
        struct mutex switch_mutex;
        u16 lan_vsi;       /* our default LAN VSI */
@@ -270,6 +276,8 @@ struct i40e_pf {
        struct dentry *i40e_dbg_pf;
 #endif /* CONFIG_DEBUG_FS */
 
+       u16 instance; /* A unique number per i40e_pf instance in the system */
+
        /* sr-iov config info */
        struct i40e_vf *vf;
        int num_alloc_vfs;      /* actual number of VFs allocated */
@@ -441,13 +449,11 @@ static inline char *i40e_fw_version_str(struct i40e_hw *hw)
        static char buf[32];
 
        snprintf(buf, sizeof(buf),
-                "f%d.%d a%d.%d n%02d.%02d.%02d e%08x",
+                "f%d.%d a%d.%d n%02x.%02x e%08x",
                 hw->aq.fw_maj_ver, hw->aq.fw_min_ver,
                 hw->aq.api_maj_ver, hw->aq.api_min_ver,
                 (hw->nvm.version & I40E_NVM_VERSION_HI_MASK)
                                                >> I40E_NVM_VERSION_HI_SHIFT,
-                (hw->nvm.version & I40E_NVM_VERSION_MID_MASK)
-                                               >> I40E_NVM_VERSION_MID_SHIFT,
                 (hw->nvm.version & I40E_NVM_VERSION_LO_MASK)
                                                >> I40E_NVM_VERSION_LO_SHIFT,
                 hw->nvm.eetrack);
index cfef7fc32cdd4643382f6d0125589fd1e3de6a95..30f32f3a86bcaef4c8b5cdd74259c2810957eff5 100644 (file)
@@ -43,13 +43,17 @@ static void i40e_adminq_init_regs(struct i40e_hw *hw)
        if (hw->mac.type == I40E_MAC_VF) {
                hw->aq.asq.tail = I40E_VF_ATQT1;
                hw->aq.asq.head = I40E_VF_ATQH1;
+               hw->aq.asq.len  = I40E_VF_ATQLEN1;
                hw->aq.arq.tail = I40E_VF_ARQT1;
                hw->aq.arq.head = I40E_VF_ARQH1;
+               hw->aq.arq.len  = I40E_VF_ARQLEN1;
        } else {
                hw->aq.asq.tail = I40E_PF_ATQT;
                hw->aq.asq.head = I40E_PF_ATQH;
+               hw->aq.asq.len  = I40E_PF_ATQLEN;
                hw->aq.arq.tail = I40E_PF_ARQT;
                hw->aq.arq.head = I40E_PF_ARQH;
+               hw->aq.arq.len  = I40E_PF_ARQLEN;
        }
 }
 
@@ -466,10 +470,9 @@ static i40e_status i40e_shutdown_asq(struct i40e_hw *hw)
                return I40E_ERR_NOT_READY;
 
        /* Stop firmware AdminQ processing */
-       if (hw->mac.type == I40E_MAC_VF)
-               wr32(hw, I40E_VF_ATQLEN1, 0);
-       else
-               wr32(hw, I40E_PF_ATQLEN, 0);
+       wr32(hw, hw->aq.asq.head, 0);
+       wr32(hw, hw->aq.asq.tail, 0);
+       wr32(hw, hw->aq.asq.len, 0);
 
        /* make sure lock is available */
        mutex_lock(&hw->aq.asq_mutex);
@@ -500,10 +503,9 @@ static i40e_status i40e_shutdown_arq(struct i40e_hw *hw)
                return I40E_ERR_NOT_READY;
 
        /* Stop firmware AdminQ processing */
-       if (hw->mac.type == I40E_MAC_VF)
-               wr32(hw, I40E_VF_ARQLEN1, 0);
-       else
-               wr32(hw, I40E_PF_ARQLEN, 0);
+       wr32(hw, hw->aq.arq.head, 0);
+       wr32(hw, hw->aq.arq.tail, 0);
+       wr32(hw, hw->aq.arq.len, 0);
 
        /* make sure lock is available */
        mutex_lock(&hw->aq.arq_mutex);
@@ -533,8 +535,9 @@ static i40e_status i40e_shutdown_arq(struct i40e_hw *hw)
  **/
 i40e_status i40e_init_adminq(struct i40e_hw *hw)
 {
-       u16 eetrack_lo, eetrack_hi;
        i40e_status ret_code;
+       u16 eetrack_lo, eetrack_hi;
+       int retry = 0;
 
        /* verify input for valid configuration */
        if ((hw->aq.num_arq_entries == 0) ||
@@ -562,11 +565,24 @@ i40e_status i40e_init_adminq(struct i40e_hw *hw)
        if (ret_code)
                goto init_adminq_free_asq;
 
-       ret_code = i40e_aq_get_firmware_version(hw,
-                                    &hw->aq.fw_maj_ver, &hw->aq.fw_min_ver,
-                                    &hw->aq.api_maj_ver, &hw->aq.api_min_ver,
-                                    NULL);
-       if (ret_code)
+       /* There are some cases where the firmware may not be quite ready
+        * for AdminQ operations, so we retry the AdminQ setup a few times
+        * if we see timeouts in this first AQ call.
+        */
+       do {
+               ret_code = i40e_aq_get_firmware_version(hw,
+                                                       &hw->aq.fw_maj_ver,
+                                                       &hw->aq.fw_min_ver,
+                                                       &hw->aq.api_maj_ver,
+                                                       &hw->aq.api_min_ver,
+                                                       NULL);
+               if (ret_code != I40E_ERR_ADMIN_QUEUE_TIMEOUT)
+                       break;
+               retry++;
+               msleep(100);
+               i40e_resume_aq(hw);
+       } while (retry < 10);
+       if (ret_code != I40E_SUCCESS)
                goto init_adminq_free_arq;
 
        if (hw->aq.api_maj_ver != I40E_FW_API_VERSION_MAJOR ||
@@ -956,27 +972,13 @@ void i40e_resume_aq(struct i40e_hw *hw)
        hw->aq.asq.next_to_clean = 0;
 
        i40e_config_asq_regs(hw);
-       reg = hw->aq.num_asq_entries;
-
-       if (hw->mac.type == I40E_MAC_VF) {
-               reg |= I40E_VF_ATQLEN_ATQENABLE_MASK;
-               wr32(hw, I40E_VF_ATQLEN1, reg);
-       } else {
-               reg |= I40E_PF_ATQLEN_ATQENABLE_MASK;
-               wr32(hw, I40E_PF_ATQLEN, reg);
-       }
+       reg = hw->aq.num_asq_entries | I40E_PF_ATQLEN_ATQENABLE_MASK;
+       wr32(hw, hw->aq.asq.len, reg);
 
        hw->aq.arq.next_to_use = 0;
        hw->aq.arq.next_to_clean = 0;
 
        i40e_config_arq_regs(hw);
-       reg = hw->aq.num_arq_entries;
-
-       if (hw->mac.type == I40E_MAC_VF) {
-               reg |= I40E_VF_ATQLEN_ATQENABLE_MASK;
-               wr32(hw, I40E_VF_ARQLEN1, reg);
-       } else {
-               reg |= I40E_PF_ATQLEN_ATQENABLE_MASK;
-               wr32(hw, I40E_PF_ARQLEN, reg);
-       }
+       reg = hw->aq.num_arq_entries | I40E_PF_ATQLEN_ATQENABLE_MASK;
+       wr32(hw, hw->aq.arq.len, reg);
 }
index 22e5ed683e4770a5a26a6a44f1eec3c22904619d..f8c2c44e233d4cc14a5386083d6daf961c64bc82 100644 (file)
@@ -56,6 +56,7 @@ struct i40e_adminq_ring {
        /* used for queue tracking */
        u32 head;
        u32 tail;
+       u32 len;
 };
 
 /* ASQ transaction details */
index 1e4ea134975ac43e8288132e6e4b93bacb2f4b7e..e526d40e9cf81ee11ae1dc46645e0560dec8cccb 100644 (file)
@@ -266,6 +266,54 @@ i40e_status i40e_validate_mac_addr(u8 *mac_addr)
        return status;
 }
 
+/**
+ * i40e_get_media_type - Gets media type
+ * @hw: pointer to the hardware structure
+ **/
+static enum i40e_media_type i40e_get_media_type(struct i40e_hw *hw)
+{
+       enum i40e_media_type media;
+
+       switch (hw->phy.link_info.phy_type) {
+       case I40E_PHY_TYPE_10GBASE_SR:
+       case I40E_PHY_TYPE_10GBASE_LR:
+       case I40E_PHY_TYPE_40GBASE_SR4:
+       case I40E_PHY_TYPE_40GBASE_LR4:
+               media = I40E_MEDIA_TYPE_FIBER;
+               break;
+       case I40E_PHY_TYPE_100BASE_TX:
+       case I40E_PHY_TYPE_1000BASE_T:
+       case I40E_PHY_TYPE_10GBASE_T:
+               media = I40E_MEDIA_TYPE_BASET;
+               break;
+       case I40E_PHY_TYPE_10GBASE_CR1_CU:
+       case I40E_PHY_TYPE_40GBASE_CR4_CU:
+       case I40E_PHY_TYPE_10GBASE_CR1:
+       case I40E_PHY_TYPE_40GBASE_CR4:
+       case I40E_PHY_TYPE_10GBASE_SFPP_CU:
+               media = I40E_MEDIA_TYPE_DA;
+               break;
+       case I40E_PHY_TYPE_1000BASE_KX:
+       case I40E_PHY_TYPE_10GBASE_KX4:
+       case I40E_PHY_TYPE_10GBASE_KR:
+       case I40E_PHY_TYPE_40GBASE_KR4:
+               media = I40E_MEDIA_TYPE_BACKPLANE;
+               break;
+       case I40E_PHY_TYPE_SGMII:
+       case I40E_PHY_TYPE_XAUI:
+       case I40E_PHY_TYPE_XFI:
+       case I40E_PHY_TYPE_XLAUI:
+       case I40E_PHY_TYPE_XLPPI:
+       default:
+               media = I40E_MEDIA_TYPE_UNKNOWN;
+               break;
+       }
+
+       return media;
+}
+
+#define I40E_PF_RESET_WAIT_COUNT_A0    200
+#define I40E_PF_RESET_WAIT_COUNT       10
 /**
  * i40e_pf_reset - Reset the PF
  * @hw: pointer to the hardware structure
@@ -275,7 +323,7 @@ i40e_status i40e_validate_mac_addr(u8 *mac_addr)
  **/
 i40e_status i40e_pf_reset(struct i40e_hw *hw)
 {
-       u32 wait_cnt = 0;
+       u32 cnt = 0;
        u32 reg = 0;
        u32 grst_del;
 
@@ -285,7 +333,7 @@ i40e_status i40e_pf_reset(struct i40e_hw *hw)
         */
        grst_del = rd32(hw, I40E_GLGEN_RSTCTL) & I40E_GLGEN_RSTCTL_GRSTDEL_MASK
                        >> I40E_GLGEN_RSTCTL_GRSTDEL_SHIFT;
-       for (wait_cnt = 0; wait_cnt < grst_del + 2; wait_cnt++) {
+       for (cnt = 0; cnt < grst_del + 2; cnt++) {
                reg = rd32(hw, I40E_GLGEN_RSTAT);
                if (!(reg & I40E_GLGEN_RSTAT_DEVSTATE_MASK))
                        break;
@@ -297,16 +345,24 @@ i40e_status i40e_pf_reset(struct i40e_hw *hw)
        }
 
        /* Determine the PF number based on the PCI fn */
-       hw->pf_id = (u8)hw->bus.func;
+       reg = rd32(hw, I40E_GLPCI_CAPSUP);
+       if (reg & I40E_GLPCI_CAPSUP_ARI_EN_MASK)
+               hw->pf_id = (u8)((hw->bus.device << 3) | hw->bus.func);
+       else
+               hw->pf_id = (u8)hw->bus.func;
 
        /* If there was a Global Reset in progress when we got here,
         * we don't need to do the PF Reset
         */
-       if (!wait_cnt) {
+       if (!cnt) {
+               if (hw->revision_id == 0)
+                       cnt = I40E_PF_RESET_WAIT_COUNT_A0;
+               else
+                       cnt = I40E_PF_RESET_WAIT_COUNT;
                reg = rd32(hw, I40E_PFGEN_CTRL);
                wr32(hw, I40E_PFGEN_CTRL,
                     (reg | I40E_PFGEN_CTRL_PFSWR_MASK));
-               for (wait_cnt = 0; wait_cnt < 10; wait_cnt++) {
+               for (; cnt; cnt--) {
                        reg = rd32(hw, I40E_PFGEN_CTRL);
                        if (!(reg & I40E_PFGEN_CTRL_PFSWR_MASK))
                                break;
@@ -335,7 +391,13 @@ void i40e_clear_pxe_mode(struct i40e_hw *hw)
 
        /* Clear single descriptor fetch/write-back mode */
        reg = rd32(hw, I40E_GLLAN_RCTL_0);
-       wr32(hw, I40E_GLLAN_RCTL_0, (reg | I40E_GLLAN_RCTL_0_PXE_MODE_MASK));
+
+       if (hw->revision_id == 0) {
+               /* As a work around clear PXE_MODE instead of setting it */
+               wr32(hw, I40E_GLLAN_RCTL_0, (reg & (~I40E_GLLAN_RCTL_0_PXE_MODE_MASK)));
+       } else {
+               wr32(hw, I40E_GLLAN_RCTL_0, (reg | I40E_GLLAN_RCTL_0_PXE_MODE_MASK));
+       }
 }
 
 /**
@@ -495,10 +557,12 @@ i40e_status i40e_aq_get_link_info(struct i40e_hw *hw,
 
        /* update link status */
        hw_link_info->phy_type = (enum i40e_aq_phy_type)resp->phy_type;
+       hw->phy.media_type = i40e_get_media_type(hw);
        hw_link_info->link_speed = (enum i40e_aq_link_speed)resp->link_speed;
        hw_link_info->link_info = resp->link_info;
        hw_link_info->an_info = resp->an_info;
        hw_link_info->ext_info = resp->ext_info;
+       hw_link_info->loopback = resp->loopback;
 
        if (resp->command_flags & cpu_to_le16(I40E_AQ_LSE_ENABLE))
                hw_link_info->lse_enable = true;
@@ -873,6 +937,7 @@ i40e_get_link_status_exit:
  * @downlink_seid: the VSI SEID
  * @enabled_tc: bitmap of TCs to be enabled
  * @default_port: true for default port VSI, false for control port
+ * @enable_l2_filtering: true to add L2 filter table rules to regular forwarding rules for cloud support
  * @veb_seid: pointer to where to put the resulting VEB SEID
  * @cmd_details: pointer to command details structure or NULL
  *
@@ -881,7 +946,8 @@ i40e_get_link_status_exit:
  **/
 i40e_status i40e_aq_add_veb(struct i40e_hw *hw, u16 uplink_seid,
                                u16 downlink_seid, u8 enabled_tc,
-                               bool default_port, u16 *veb_seid,
+                               bool default_port, bool enable_l2_filtering,
+                               u16 *veb_seid,
                                struct i40e_asq_cmd_details *cmd_details)
 {
        struct i40e_aq_desc desc;
@@ -907,6 +973,10 @@ i40e_status i40e_aq_add_veb(struct i40e_hw *hw, u16 uplink_seid,
                veb_flags |= I40E_AQC_ADD_VEB_PORT_TYPE_DEFAULT;
        else
                veb_flags |= I40E_AQC_ADD_VEB_PORT_TYPE_DATA;
+
+       if (enable_l2_filtering)
+               veb_flags |= I40E_AQC_ADD_VEB_ENABLE_L2_FILTER;
+
        cmd->veb_flags = cpu_to_le16(veb_flags);
 
        status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
index ef4cb1cf31f2d392a4ed4e1ae2e0059919423317..9c675b5f1466cfa0446eec8d65b5419c2276ab5e 100644 (file)
@@ -1472,6 +1472,10 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
                dev_info(&pf->pdev->dev, "forcing GlobR\n");
                i40e_do_reset(pf, (1 << __I40E_GLOBAL_RESET_REQUESTED));
 
+       } else if (strncmp(cmd_buf, "empr", 4) == 0) {
+               dev_info(&pf->pdev->dev, "forcing EMPR\n");
+               i40e_do_reset(pf, (1 << __I40E_EMP_RESET_REQUESTED));
+
        } else if (strncmp(cmd_buf, "read", 4) == 0) {
                u32 address;
                u32 value;
index de255143bde6f94098139e1d40ada768f410632a..dc6c41fade9e2e2f77f38671fcd0a14d7b2fc495 100644 (file)
@@ -68,16 +68,16 @@ static i40e_status i40e_diag_reg_pattern_test(struct i40e_hw *hw,
 
 struct i40e_diag_reg_test_info i40e_reg_list[] = {
        /* offset               mask         elements   stride */
-       {I40E_QTX_CTL(0),       0x0000FFBF,  64, I40E_QTX_CTL(1) - I40E_QTX_CTL(0)},
+       {I40E_QTX_CTL(0),       0x0000FFBF,   4, I40E_QTX_CTL(1) - I40E_QTX_CTL(0)},
        {I40E_PFINT_ITR0(0),    0x00000FFF,   3, I40E_PFINT_ITR0(1) - I40E_PFINT_ITR0(0)},
        {I40E_PFINT_ITRN(0, 0), 0x00000FFF,  64, I40E_PFINT_ITRN(0, 1) - I40E_PFINT_ITRN(0, 0)},
        {I40E_PFINT_ITRN(1, 0), 0x00000FFF,  64, I40E_PFINT_ITRN(1, 1) - I40E_PFINT_ITRN(1, 0)},
        {I40E_PFINT_ITRN(2, 0), 0x00000FFF,  64, I40E_PFINT_ITRN(2, 1) - I40E_PFINT_ITRN(2, 0)},
        {I40E_PFINT_STAT_CTL0,  0x0000000C,   1, 0},
        {I40E_PFINT_LNKLST0,    0x00001FFF,   1, 0},
-       {I40E_PFINT_LNKLSTN(0), 0x000007FF, 511, I40E_PFINT_LNKLSTN(1) - I40E_PFINT_LNKLSTN(0)},
-       {I40E_QINT_TQCTL(0),    0x000000FF, I40E_QINT_TQCTL_MAX_INDEX + 1, I40E_QINT_TQCTL(1) - I40E_QINT_TQCTL(0)},
-       {I40E_QINT_RQCTL(0),    0x000000FF, I40E_QINT_RQCTL_MAX_INDEX + 1, I40E_QINT_RQCTL(1) - I40E_QINT_RQCTL(0)},
+       {I40E_PFINT_LNKLSTN(0), 0x000007FF,  64, I40E_PFINT_LNKLSTN(1) - I40E_PFINT_LNKLSTN(0)},
+       {I40E_QINT_TQCTL(0),    0x000000FF,  64, I40E_QINT_TQCTL(1) - I40E_QINT_TQCTL(0)},
+       {I40E_QINT_RQCTL(0),    0x000000FF,  64, I40E_QINT_RQCTL(1) - I40E_QINT_RQCTL(0)},
        {I40E_PFINT_ICR0_ENA,   0xF7F20000,   1, 0},
        { 0 }
 };
index 3d98277f45268afd00457fa63c758ea225bd077b..d1fc68cd6c942b3e4f84302d71415b2e13132aa0 100644 (file)
 #include "i40e_type.h"
 
 enum i40e_lb_mode {
-       I40E_LB_MODE_NONE 0,
-       I40E_LB_MODE_PHY_LOCAL,
-       I40E_LB_MODE_PHY_REMOTE,
-       I40E_LB_MODE_MAC_LOCAL,
+       I40E_LB_MODE_NONE       = 0x0,
+       I40E_LB_MODE_PHY_LOCAL  = I40E_AQ_LB_PHY_LOCAL,
+       I40E_LB_MODE_PHY_REMOTE = I40E_AQ_LB_PHY_REMOTE,
+       I40E_LB_MODE_MAC_LOCAL  = I40E_AQ_LB_MAC_LOCAL,
 };
 
 struct i40e_diag_reg_test_info {
index 1b86138fa9e19fb0a87510db8d05c5dafd347a61..fd3e379de6da0a211a9626ce2e2e117fd693f249 100644 (file)
@@ -211,6 +211,10 @@ static int i40e_get_settings(struct net_device *netdev,
                ecmd->supported |= SUPPORTED_TP;
                ecmd->advertising |= ADVERTISED_TP;
                ecmd->port = PORT_TP;
+       } else if (hw->phy.media_type == I40E_MEDIA_TYPE_DA) {
+               ecmd->supported |= SUPPORTED_FIBRE;
+               ecmd->advertising |= ADVERTISED_FIBRE;
+               ecmd->port = PORT_DA;
        } else {
                ecmd->supported |= SUPPORTED_FIBRE;
                ecmd->advertising |= ADVERTISED_FIBRE;
@@ -418,15 +422,19 @@ static int i40e_set_ringparam(struct net_device *netdev,
        if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
                return -EINVAL;
 
-       new_tx_count = clamp_t(u32, ring->tx_pending,
-                              I40E_MIN_NUM_DESCRIPTORS,
-                              I40E_MAX_NUM_DESCRIPTORS);
-       new_tx_count = ALIGN(new_tx_count, I40E_REQ_DESCRIPTOR_MULTIPLE);
+       if (ring->tx_pending > I40E_MAX_NUM_DESCRIPTORS ||
+           ring->tx_pending < I40E_MIN_NUM_DESCRIPTORS ||
+           ring->rx_pending > I40E_MAX_NUM_DESCRIPTORS ||
+           ring->rx_pending < I40E_MIN_NUM_DESCRIPTORS) {
+               netdev_info(netdev,
+                           "Descriptors requested (Tx: %d / Rx: %d) out of range [%d-%d]\n",
+                           ring->tx_pending, ring->rx_pending,
+                           I40E_MIN_NUM_DESCRIPTORS, I40E_MAX_NUM_DESCRIPTORS);
+               return -EINVAL;
+       }
 
-       new_rx_count = clamp_t(u32, ring->rx_pending,
-                              I40E_MIN_NUM_DESCRIPTORS,
-                              I40E_MAX_NUM_DESCRIPTORS);
-       new_rx_count = ALIGN(new_rx_count, I40E_REQ_DESCRIPTOR_MULTIPLE);
+       new_tx_count = ALIGN(ring->tx_pending, I40E_REQ_DESCRIPTOR_MULTIPLE);
+       new_rx_count = ALIGN(ring->rx_pending, I40E_REQ_DESCRIPTOR_MULTIPLE);
 
        /* if nothing to do return success */
        if ((new_tx_count == vsi->tx_rings[0]->count) &&
@@ -702,8 +710,12 @@ static int i40e_get_ts_info(struct net_device *dev,
        return ethtool_op_get_ts_info(dev, info);
 }
 
-static int i40e_link_test(struct i40e_pf *pf, u64 *data)
+static int i40e_link_test(struct net_device *netdev, u64 *data)
 {
+       struct i40e_netdev_priv *np = netdev_priv(netdev);
+       struct i40e_pf *pf = np->vsi->back;
+
+       netif_info(pf, hw, netdev, "link test\n");
        if (i40e_get_link_status(&pf->hw))
                *data = 0;
        else
@@ -712,36 +724,52 @@ static int i40e_link_test(struct i40e_pf *pf, u64 *data)
        return *data;
 }
 
-static int i40e_reg_test(struct i40e_pf *pf, u64 *data)
+static int i40e_reg_test(struct net_device *netdev, u64 *data)
 {
-       i40e_status ret;
+       struct i40e_netdev_priv *np = netdev_priv(netdev);
+       struct i40e_pf *pf = np->vsi->back;
 
-       ret = i40e_diag_reg_test(&pf->hw);
-       *data = ret;
+       netif_info(pf, hw, netdev, "register test\n");
+       *data = i40e_diag_reg_test(&pf->hw);
 
-       return ret;
+       i40e_do_reset(pf, (1 << __I40E_PF_RESET_REQUESTED));
+       return *data;
 }
 
-static int i40e_eeprom_test(struct i40e_pf *pf, u64 *data)
+static int i40e_eeprom_test(struct net_device *netdev, u64 *data)
 {
-       i40e_status ret;
+       struct i40e_netdev_priv *np = netdev_priv(netdev);
+       struct i40e_pf *pf = np->vsi->back;
 
-       ret = i40e_diag_eeprom_test(&pf->hw);
-       *data = ret;
+       netif_info(pf, hw, netdev, "eeprom test\n");
+       *data = i40e_diag_eeprom_test(&pf->hw);
 
-       return ret;
+       return *data;
 }
 
-static int i40e_intr_test(struct i40e_pf *pf, u64 *data)
+static int i40e_intr_test(struct net_device *netdev, u64 *data)
 {
-       *data = -ENOSYS;
+       struct i40e_netdev_priv *np = netdev_priv(netdev);
+       struct i40e_pf *pf = np->vsi->back;
+       u16 swc_old = pf->sw_int_count;
+
+       netif_info(pf, hw, netdev, "interrupt test\n");
+       wr32(&pf->hw, I40E_PFINT_DYN_CTL0,
+            (I40E_PFINT_DYN_CTL0_INTENA_MASK |
+             I40E_PFINT_DYN_CTL0_SWINT_TRIG_MASK));
+       usleep_range(1000, 2000);
+       *data = (swc_old == pf->sw_int_count);
 
        return *data;
 }
 
-static int i40e_loopback_test(struct i40e_pf *pf, u64 *data)
+static int i40e_loopback_test(struct net_device *netdev, u64 *data)
 {
-       *data = -ENOSYS;
+       struct i40e_netdev_priv *np = netdev_priv(netdev);
+       struct i40e_pf *pf = np->vsi->back;
+
+       netif_info(pf, hw, netdev, "loopback test not implemented\n");
+       *data = 0;
 
        return *data;
 }
@@ -755,39 +783,31 @@ static void i40e_diag_test(struct net_device *netdev,
        set_bit(__I40E_TESTING, &pf->state);
        if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
                /* Offline tests */
-
-               netdev_info(netdev, "offline testing starting\n");
+               netif_info(pf, drv, netdev, "offline testing starting\n");
 
                /* Link test performed before hardware reset
                 * so autoneg doesn't interfere with test result
                 */
-               netdev_info(netdev, "link test starting\n");
-               if (i40e_link_test(pf, &data[I40E_ETH_TEST_LINK]))
+               if (i40e_link_test(netdev, &data[I40E_ETH_TEST_LINK]))
                        eth_test->flags |= ETH_TEST_FL_FAILED;
 
-               netdev_info(netdev, "register test starting\n");
-               if (i40e_reg_test(pf, &data[I40E_ETH_TEST_REG]))
+               if (i40e_reg_test(netdev, &data[I40E_ETH_TEST_REG]))
                        eth_test->flags |= ETH_TEST_FL_FAILED;
 
-               i40e_do_reset(pf, (1 << __I40E_PF_RESET_REQUESTED));
-               netdev_info(netdev, "eeprom test starting\n");
-               if (i40e_eeprom_test(pf, &data[I40E_ETH_TEST_EEPROM]))
+               if (i40e_eeprom_test(netdev, &data[I40E_ETH_TEST_EEPROM]))
                        eth_test->flags |= ETH_TEST_FL_FAILED;
 
-               i40e_do_reset(pf, (1 << __I40E_PF_RESET_REQUESTED));
-               netdev_info(netdev, "interrupt test starting\n");
-               if (i40e_intr_test(pf, &data[I40E_ETH_TEST_INTR]))
+               if (i40e_intr_test(netdev, &data[I40E_ETH_TEST_INTR]))
                        eth_test->flags |= ETH_TEST_FL_FAILED;
 
-               i40e_do_reset(pf, (1 << __I40E_PF_RESET_REQUESTED));
-               netdev_info(netdev, "loopback test starting\n");
-               if (i40e_loopback_test(pf, &data[I40E_ETH_TEST_LOOPBACK]))
+               if (i40e_loopback_test(netdev, &data[I40E_ETH_TEST_LOOPBACK]))
                        eth_test->flags |= ETH_TEST_FL_FAILED;
 
        } else {
-               netdev_info(netdev, "online test starting\n");
                /* Online tests */
-               if (i40e_link_test(pf, &data[I40E_ETH_TEST_LINK]))
+               netif_info(pf, drv, netdev, "online testing starting\n");
+
+               if (i40e_link_test(netdev, &data[I40E_ETH_TEST_LINK]))
                        eth_test->flags |= ETH_TEST_FL_FAILED;
 
                /* Offline only tests, not run in online; pass by default */
@@ -795,9 +815,10 @@ static void i40e_diag_test(struct net_device *netdev,
                data[I40E_ETH_TEST_EEPROM] = 0;
                data[I40E_ETH_TEST_INTR] = 0;
                data[I40E_ETH_TEST_LOOPBACK] = 0;
-
-               clear_bit(__I40E_TESTING, &pf->state);
        }
+       clear_bit(__I40E_TESTING, &pf->state);
+
+       netif_info(pf, drv, netdev, "testing finished\n");
 }
 
 static void i40e_get_wol(struct net_device *netdev,
index 00ff35006077e57b72dd05644ce8c5a05e8bdf7e..f8afbcb053c539d58ea4034fed2fcd5908846193 100644 (file)
@@ -113,8 +113,8 @@ enum i40e_hmc_lan_object_size {
 #define I40E_HMC_L2OBJ_BASE_ALIGNMENT 512
 #define I40E_HMC_OBJ_SIZE_TXQ         128
 #define I40E_HMC_OBJ_SIZE_RXQ         32
-#define I40E_HMC_OBJ_SIZE_FCOE_CNTX   128
-#define I40E_HMC_OBJ_SIZE_FCOE_FILT   32
+#define I40E_HMC_OBJ_SIZE_FCOE_CNTX   64
+#define I40E_HMC_OBJ_SIZE_FCOE_FILT   64
 
 enum i40e_hmc_lan_rsrc_type {
        I40E_HMC_LAN_FULL  = 0,
index be15938ba2130372192276670e1621c3e470505c..a6291e23fe5f7b7859bf5aa60c749a4149af13ec 100644 (file)
@@ -36,7 +36,7 @@ static const char i40e_driver_string[] =
 
 #define DRV_VERSION_MAJOR 0
 #define DRV_VERSION_MINOR 3
-#define DRV_VERSION_BUILD 11
+#define DRV_VERSION_BUILD 13
 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \
             __stringify(DRV_VERSION_MINOR) "." \
             __stringify(DRV_VERSION_BUILD)    DRV_KERN
@@ -574,10 +574,11 @@ static void i40e_update_veb_stats(struct i40e_veb *veb)
        i40e_stat_update32(hw, I40E_GLSW_TDPC(idx),
                           veb->stat_offsets_loaded,
                           &oes->tx_discards, &es->tx_discards);
-       i40e_stat_update32(hw, I40E_GLSW_RUPP(idx),
-                          veb->stat_offsets_loaded,
-                          &oes->rx_unknown_protocol, &es->rx_unknown_protocol);
-
+       if (hw->revision_id > 0)
+               i40e_stat_update32(hw, I40E_GLSW_RUPP(idx),
+                                  veb->stat_offsets_loaded,
+                                  &oes->rx_unknown_protocol,
+                                  &es->rx_unknown_protocol);
        i40e_stat_update48(hw, I40E_GLSW_GORCH(idx), I40E_GLSW_GORCL(idx),
                           veb->stat_offsets_loaded,
                           &oes->rx_bytes, &es->rx_bytes);
@@ -2240,7 +2241,10 @@ static int i40e_configure_rx_ring(struct i40e_ring *ring)
        rx_ctx.tphwdesc_ena = 1;
        rx_ctx.tphdata_ena = 1;
        rx_ctx.tphhead_ena = 1;
-       rx_ctx.lrxqthresh = 2;
+       if (hw->revision_id == 0)
+               rx_ctx.lrxqthresh = 0;
+       else
+               rx_ctx.lrxqthresh = 2;
        rx_ctx.crcstrip = 1;
        rx_ctx.l2tsel = 1;
        rx_ctx.showiv = 1;
@@ -2752,6 +2756,11 @@ static irqreturn_t i40e_intr(int irq, void *data)
 
        ena_mask = rd32(hw, I40E_PFINT_ICR0_ENA);
 
+       /* if interrupt but no bits showing, must be SWINT */
+       if (((icr0 & ~I40E_PFINT_ICR0_INTEVENT_MASK) == 0) ||
+           (icr0 & I40E_PFINT_ICR0_SWINT_MASK))
+               pf->sw_int_count++;
+
        /* only q0 is used in MSI/Legacy mode, and none are used in MSIX */
        if (icr0 & I40E_PFINT_ICR0_QUEUE_0_MASK) {
 
@@ -2790,11 +2799,11 @@ static irqreturn_t i40e_intr(int irq, void *data)
                val = rd32(hw, I40E_GLGEN_RSTAT);
                val = (val & I40E_GLGEN_RSTAT_RESET_TYPE_MASK)
                       >> I40E_GLGEN_RSTAT_RESET_TYPE_SHIFT;
-               if (val & I40E_RESET_CORER)
+               if (val == I40E_RESET_CORER)
                        pf->corer_count++;
-               else if (val & I40E_RESET_GLOBR)
+               else if (val == I40E_RESET_GLOBR)
                        pf->globr_count++;
-               else if (val & I40E_RESET_EMPR)
+               else if (val == I40E_RESET_EMPR)
                        pf->empr_count++;
        }
 
@@ -3016,6 +3025,9 @@ static int i40e_vsi_control_tx(struct i40e_vsi *vsi, bool enable)
                }
        }
 
+       if (hw->revision_id == 0)
+               mdelay(50);
+
        return 0;
 }
 
@@ -4051,6 +4063,24 @@ void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags)
                wr32(&pf->hw, I40E_GLGEN_RTRIG, val);
                i40e_flush(&pf->hw);
 
+       } else if (reset_flags & (1 << __I40E_EMP_RESET_REQUESTED)) {
+
+               /* Request a Firmware Reset
+                *
+                * Same as Global reset, plus restarting the
+                * embedded firmware engine.
+                */
+               /* enable EMP Reset */
+               val = rd32(&pf->hw, I40E_GLGEN_RSTENA_EMP);
+               val |= I40E_GLGEN_RSTENA_EMP_EMP_RST_ENA_MASK;
+               wr32(&pf->hw, I40E_GLGEN_RSTENA_EMP, val);
+
+               /* force the reset */
+               val = rd32(&pf->hw, I40E_GLGEN_RTRIG);
+               val |= I40E_GLGEN_RTRIG_EMPFWR_MASK;
+               wr32(&pf->hw, I40E_GLGEN_RTRIG, val);
+               i40e_flush(&pf->hw);
+
        } else if (reset_flags & (1 << __I40E_PF_RESET_REQUESTED)) {
 
                /* Request a PF Reset
@@ -4589,6 +4619,13 @@ static int i40e_get_capabilities(struct i40e_pf *pf)
                }
        } while (err);
 
+       if (pf->hw.revision_id == 0 && pf->hw.func_caps.npar_enable) {
+               pf->hw.func_caps.num_msix_vectors += 1;
+               pf->hw.func_caps.num_tx_qp =
+                       min_t(int, pf->hw.func_caps.num_tx_qp,
+                             I40E_MAX_NPAR_QPS);
+       }
+
        if (pf->hw.debug_mask & I40E_DEBUG_USER)
                dev_info(&pf->pdev->dev,
                         "pf=%d, num_vfs=%d, msix_pf=%d, msix_vf=%d, fd_g=%d, fd_b=%d, pf_max_q=%d num_vsi=%d\n",
@@ -4600,6 +4637,15 @@ static int i40e_get_capabilities(struct i40e_pf *pf)
                         pf->hw.func_caps.num_tx_qp,
                         pf->hw.func_caps.num_vsis);
 
+#define DEF_NUM_VSI (1 + (pf->hw.func_caps.fcoe ? 1 : 0) \
+                      + pf->hw.func_caps.num_vfs)
+       if (pf->hw.revision_id == 0 && (DEF_NUM_VSI > pf->hw.func_caps.num_vsis)) {
+               dev_info(&pf->pdev->dev,
+                        "got num_vsis %d, setting num_vsis to %d\n",
+                        pf->hw.func_caps.num_vsis, DEF_NUM_VSI);
+               pf->hw.func_caps.num_vsis = DEF_NUM_VSI;
+       }
+
        return 0;
 }
 
@@ -4670,22 +4716,20 @@ static void i40e_fdir_teardown(struct i40e_pf *pf)
 }
 
 /**
- * i40e_handle_reset_warning - prep for the core to reset
+ * i40e_prep_for_reset - prep for the core to reset
  * @pf: board private structure
  *
- * Close up the VFs and other things in prep for a Core Reset,
- * then get ready to rebuild the world.
- **/
-static void i40e_handle_reset_warning(struct i40e_pf *pf)
+ * Close up the VFs and other things in prep for pf Reset.
+  **/
+static int i40e_prep_for_reset(struct i40e_pf *pf)
 {
-       struct i40e_driver_version dv;
        struct i40e_hw *hw = &pf->hw;
        i40e_status ret;
        u32 v;
 
        clear_bit(__I40E_RESET_INTR_RECEIVED, &pf->state);
        if (test_and_set_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state))
-               return;
+               return 0;
 
        dev_info(&pf->pdev->dev, "Tearing down internal switch for reset\n");
 
@@ -4701,6 +4745,26 @@ static void i40e_handle_reset_warning(struct i40e_pf *pf)
 
        i40e_shutdown_adminq(&pf->hw);
 
+       /* call shutdown HMC */
+       ret = i40e_shutdown_lan_hmc(hw);
+       if (ret) {
+               dev_info(&pf->pdev->dev, "shutdown_lan_hmc failed: %d\n", ret);
+               clear_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state);
+       }
+       return ret;
+}
+
+/**
+ * i40e_reset_and_rebuild - reset and rebuid using a saved config
+ * @pf: board private structure
+ **/
+static void i40e_reset_and_rebuild(struct i40e_pf *pf)
+{
+       struct i40e_driver_version dv;
+       struct i40e_hw *hw = &pf->hw;
+       i40e_status ret;
+       u32 v;
+
        /* Now we wait for GRST to settle out.
         * We don't have to delete the VEBs or VSIs from the hw switch
         * because the reset will make them disappear.
@@ -4728,13 +4792,6 @@ static void i40e_handle_reset_warning(struct i40e_pf *pf)
                goto end_core_reset;
        }
 
-       /* call shutdown HMC */
-       ret = i40e_shutdown_lan_hmc(hw);
-       if (ret) {
-               dev_info(&pf->pdev->dev, "shutdown_lan_hmc failed: %d\n", ret);
-               goto end_core_reset;
-       }
-
        ret = i40e_init_lan_hmc(hw, hw->func_caps.num_tx_qp,
                                hw->func_caps.num_rx_qp,
                                pf->fcoe_hmc_cntx_num, pf->fcoe_hmc_filt_num);
@@ -4827,6 +4884,22 @@ end_core_reset:
        clear_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state);
 }
 
+/**
+ * i40e_handle_reset_warning - prep for the pf to reset, reset and rebuild
+ * @pf: board private structure
+ *
+ * Close up the VFs and other things in prep for a Core Reset,
+ * then get ready to rebuild the world.
+ **/
+static void i40e_handle_reset_warning(struct i40e_pf *pf)
+{
+       i40e_status ret;
+
+       ret = i40e_prep_for_reset(pf);
+       if (!ret)
+               i40e_reset_and_rebuild(pf);
+}
+
 /**
  * i40e_handle_mdd_event
  * @pf: pointer to the pf structure
@@ -5002,6 +5075,39 @@ static int i40e_set_num_rings_in_vsi(struct i40e_vsi *vsi)
        return 0;
 }
 
+/**
+ * i40e_vsi_alloc_arrays - Allocate queue and vector pointer arrays for the vsi
+ * @type: VSI pointer
+ *
+ * On error: returns error code (negative)
+ * On success: returns 0
+ **/
+static int i40e_vsi_alloc_arrays(struct i40e_vsi *vsi)
+{
+       int size;
+       int ret = 0;
+
+       /* allocate memory for both Tx and Rx ring pointers */
+       size = sizeof(struct i40e_ring *) * vsi->alloc_queue_pairs * 2;
+       vsi->tx_rings = kzalloc(size, GFP_KERNEL);
+       if (!vsi->tx_rings)
+               return -ENOMEM;
+       vsi->rx_rings = &vsi->tx_rings[vsi->alloc_queue_pairs];
+
+       /* allocate memory for q_vector pointers */
+       size = sizeof(struct i40e_q_vectors *) * vsi->num_q_vectors;
+       vsi->q_vectors = kzalloc(size, GFP_KERNEL);
+       if (!vsi->q_vectors) {
+               ret = -ENOMEM;
+               goto err_vectors;
+       }
+       return ret;
+
+err_vectors:
+       kfree(vsi->tx_rings);
+       return ret;
+}
+
 /**
  * i40e_vsi_mem_alloc - Allocates the next available struct vsi in the PF
  * @pf: board private structure
@@ -5014,8 +5120,6 @@ static int i40e_vsi_mem_alloc(struct i40e_pf *pf, enum i40e_vsi_type type)
 {
        int ret = -ENODEV;
        struct i40e_vsi *vsi;
-       int sz_vectors;
-       int sz_rings;
        int vsi_idx;
        int i;
 
@@ -5065,22 +5169,9 @@ static int i40e_vsi_mem_alloc(struct i40e_pf *pf, enum i40e_vsi_type type)
        if (ret)
                goto err_rings;
 
-       /* allocate memory for ring pointers */
-       sz_rings = sizeof(struct i40e_ring *) * vsi->alloc_queue_pairs * 2;
-       vsi->tx_rings = kzalloc(sz_rings, GFP_KERNEL);
-       if (!vsi->tx_rings) {
-               ret = -ENOMEM;
+       ret = i40e_vsi_alloc_arrays(vsi);
+       if (ret)
                goto err_rings;
-       }
-       vsi->rx_rings = &vsi->tx_rings[vsi->alloc_queue_pairs];
-
-       /* allocate memory for q_vector pointers */
-       sz_vectors = sizeof(struct i40e_q_vectors *) * vsi->num_q_vectors;
-       vsi->q_vectors = kzalloc(sz_vectors, GFP_KERNEL);
-       if (!vsi->q_vectors) {
-               ret = -ENOMEM;
-               goto err_vectors;
-       }
 
        /* Setup default MSIX irq handler for VSI */
        i40e_vsi_setup_irqhandler(vsi, i40e_msix_clean_rings);
@@ -5089,8 +5180,6 @@ static int i40e_vsi_mem_alloc(struct i40e_pf *pf, enum i40e_vsi_type type)
        ret = vsi_idx;
        goto unlock_pf;
 
-err_vectors:
-       kfree(vsi->tx_rings);
 err_rings:
        pf->next_vsi = i - 1;
        kfree(vsi);
@@ -5099,6 +5188,23 @@ unlock_pf:
        return ret;
 }
 
+/**
+ * i40e_vsi_free_arrays - Free queue and vector pointer arrays for the VSI
+ * @type: VSI pointer
+ *
+ * On error: returns error code (negative)
+ * On success: returns 0
+ **/
+static void i40e_vsi_free_arrays(struct i40e_vsi *vsi)
+{
+       /* free the ring and vector containers */
+       kfree(vsi->q_vectors);
+       vsi->q_vectors = NULL;
+       kfree(vsi->tx_rings);
+       vsi->tx_rings = NULL;
+       vsi->rx_rings = NULL;
+}
+
 /**
  * i40e_vsi_clear - Deallocate the VSI provided
  * @vsi: the VSI being un-configured
@@ -5135,9 +5241,7 @@ static int i40e_vsi_clear(struct i40e_vsi *vsi)
        i40e_put_lump(pf->qp_pile, vsi->base_queue, vsi->idx);
        i40e_put_lump(pf->irq_pile, vsi->base_vector, vsi->idx);
 
-       /* free the ring and vector containers */
-       kfree(vsi->q_vectors);
-       kfree(vsi->tx_rings);
+       i40e_vsi_free_arrays(vsi);
 
        pf->vsi[vsi->idx] = NULL;
        if (vsi->idx < pf->next_vsi)
@@ -5160,7 +5264,7 @@ static s32 i40e_vsi_clear_rings(struct i40e_vsi *vsi)
        int i;
 
        if (vsi->tx_rings[0])
-               for (i = 0; i < vsi->alloc_queue_pairs; i++) {
+               for (i = 0; i < vsi->num_queue_pairs; i++) {
                        kfree_rcu(vsi->tx_rings[i], rcu);
                        vsi->tx_rings[i] = NULL;
                        vsi->rx_rings[i] = NULL;
@@ -5179,10 +5283,11 @@ static int i40e_alloc_rings(struct i40e_vsi *vsi)
        int i;
 
        /* Set basic values in the rings to be used later during open() */
-       for (i = 0; i < vsi->alloc_queue_pairs; i++) {
+       for (i = 0; i < vsi->num_queue_pairs; i++) {
                struct i40e_ring *tx_ring;
                struct i40e_ring *rx_ring;
 
+               /* allocate space for both Tx and Rx in one shot */
                tx_ring = kzalloc(sizeof(struct i40e_ring) * 2, GFP_KERNEL);
                if (!tx_ring)
                        goto err_out;
@@ -5510,15 +5615,34 @@ static int i40e_setup_misc_vector(struct i40e_pf *pf)
  **/
 static int i40e_config_rss(struct i40e_pf *pf)
 {
-       struct i40e_hw *hw = &pf->hw;
-       u32 lut = 0;
-       int i, j;
-       u64 hena;
+       const u64 default_hena =
+                       ((u64)1 << I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) |
+                       ((u64)1 << I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP) |
+                       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_UDP) |
+                       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_SCTP) |
+                       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN) |
+                       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_TCP) |
+                       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_OTHER) |
+                       ((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV4) |
+                       ((u64)1 << I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) |
+                       ((u64)1 << I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP) |
+                       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_UDP) |
+                       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN) |
+                       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP) |
+                       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_SCTP) |
+                       ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_OTHER) |
+                       ((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV6) |
+                       ((u64)1 << I40E_FILTER_PCTYPE_L2_PAYLOAD);
+
        /* Set of random keys generated using kernel random number generator */
        static const u32 seed[I40E_PFQF_HKEY_MAX_INDEX + 1] = {0x41b01687,
                                0x183cfd8c, 0xce880440, 0x580cbc3c, 0x35897377,
                                0x328b25e1, 0x4fa98922, 0xb7d90c14, 0xd5bad70d,
                                0xcd15a2c1, 0xe8580225, 0x4a1e9d11, 0xfe5731be};
+       struct i40e_hw *hw = &pf->hw;
+       u32 lut = 0;
+       int i, j;
+       u64 hena;
 
        /* Fill out hash function seed */
        for (i = 0; i <= I40E_PFQF_HKEY_MAX_INDEX; i++)
@@ -5527,16 +5651,7 @@ static int i40e_config_rss(struct i40e_pf *pf)
        /* By default we enable TCP/UDP with IPv4/IPv6 ptypes */
        hena = (u64)rd32(hw, I40E_PFQF_HENA(0)) |
                ((u64)rd32(hw, I40E_PFQF_HENA(1)) << 32);
-       hena |= ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_UDP) |
-               ((u64)1 << I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) |
-               ((u64)1 << I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP) |
-               ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_TCP) |
-               ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP) |
-               ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_UDP) |
-               ((u64)1 << I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) |
-               ((u64)1 << I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP) |
-               ((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV4)|
-               ((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV6);
+       hena |= default_hena;
        wr32(hw, I40E_PFQF_HENA(0), (u32)hena);
        wr32(hw, I40E_PFQF_HENA(1), (u32)(hena >> 32));
 
@@ -5579,6 +5694,7 @@ static int i40e_sw_init(struct i40e_pf *pf)
 
        pf->msg_enable = netif_msg_init(I40E_DEFAULT_MSG_ENABLE,
                                (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK));
+       pf->hw.debug_mask = pf->msg_enable | I40E_DEBUG_DIAG;
        if (debug != -1 && debug != I40E_DEFAULT_MSG_ENABLE) {
                if (I40E_DEBUG_USER & debug)
                        pf->hw.debug_mask = debug;
@@ -5594,7 +5710,12 @@ static int i40e_sw_init(struct i40e_pf *pf)
                    I40E_FLAG_MQ_ENABLED      |
                    I40E_FLAG_RX_1BUF_ENABLED;
 
+       /* Depending on PF configurations, it is possible that the RSS
+        * maximum might end up larger than the available queues
+        */
        pf->rss_size_max = 0x1 << pf->hw.func_caps.rss_table_entry_width;
+       pf->rss_size_max = min_t(int, pf->rss_size_max,
+                                pf->hw.func_caps.num_tx_qp);
        if (pf->hw.func_caps.rss) {
                pf->flags |= I40E_FLAG_RSS_ENABLED;
                pf->rss_size = min_t(int, pf->rss_size_max,
@@ -5644,6 +5765,9 @@ static int i40e_sw_init(struct i40e_pf *pf)
                pf->num_req_vfs = min_t(int,
                                        pf->hw.func_caps.num_vfs,
                                        I40E_MAX_VF_COUNT);
+               dev_info(&pf->pdev->dev,
+                        "Number of VFs being requested for PF[%d] = %d\n",
+                        pf->hw.pf_id, pf->num_req_vfs);
        }
 #endif /* CONFIG_PCI_IOV */
        pf->eeprom_version = 0xDEAD;
@@ -5737,7 +5861,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
        int etherdev_size;
 
        etherdev_size = sizeof(struct i40e_netdev_priv);
-       netdev = alloc_etherdev_mq(etherdev_size, vsi->alloc_queue_pairs);
+       netdev = alloc_etherdev_mq(etherdev_size, vsi->num_queue_pairs);
        if (!netdev)
                return -ENOMEM;
 
@@ -6501,11 +6625,13 @@ void i40e_veb_release(struct i40e_veb *veb)
 static int i40e_add_veb(struct i40e_veb *veb, struct i40e_vsi *vsi)
 {
        bool is_default = (vsi->idx == vsi->back->lan_vsi);
+       bool is_cloud = false;
        int ret;
 
        /* get a VEB from the hardware */
        ret = i40e_aq_add_veb(&veb->pf->hw, veb->uplink_seid, vsi->seid,
-                             veb->enabled_tc, is_default, &veb->seid, NULL);
+                             veb->enabled_tc, is_default,
+                             is_cloud, &veb->seid, NULL);
        if (ret) {
                dev_info(&veb->pf->pdev->dev,
                         "couldn't add VEB, err %d, aq_err %d\n",
@@ -6816,8 +6942,8 @@ static int i40e_setup_pf_switch(struct i40e_pf *pf)
                 * into the pf, since this newer code pushes the pf queue
                 * info down a level into a VSI
                 */
-               pf->num_rx_queues = vsi->alloc_queue_pairs;
-               pf->num_tx_queues = vsi->alloc_queue_pairs;
+               pf->num_rx_queues = vsi->num_queue_pairs;
+               pf->num_tx_queues = vsi->num_queue_pairs;
        } else {
                /* force a reset of TC and queue layout configurations */
                u8 enabled_tc = pf->vsi[pf->lan_vsi]->tc_config.enabled_tc;
@@ -7050,6 +7176,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        struct i40e_driver_version dv;
        struct i40e_pf *pf;
        struct i40e_hw *hw;
+       static u16 pfs_found;
        int err = 0;
        u32 len;
 
@@ -7115,6 +7242,18 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        hw->subsystem_device_id = pdev->subsystem_device;
        hw->bus.device = PCI_SLOT(pdev->devfn);
        hw->bus.func = PCI_FUNC(pdev->devfn);
+       pf->instance = pfs_found;
+
+       /* do a special CORER for clearing PXE mode once at init */
+       if (hw->revision_id == 0 &&
+           (rd32(hw, I40E_GLLAN_RCTL_0) & I40E_GLLAN_RCTL_0_PXE_MODE_MASK)) {
+               wr32(hw, I40E_GLGEN_RTRIG, I40E_GLGEN_RTRIG_CORER_MASK);
+               i40e_flush(hw);
+               msleep(200);
+               pf->corer_count++;
+
+               i40e_clear_pxe_mode(hw);
+       }
 
        /* Reset here to make sure all is clean and to define PF 'n' */
        err = i40e_pf_reset(hw);
@@ -7141,6 +7280,13 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        err = i40e_init_adminq(hw);
        dev_info(&pdev->dev, "%s\n", i40e_fw_version_str(hw));
+       if (((hw->nvm.version & I40E_NVM_VERSION_HI_MASK)
+                >> I40E_NVM_VERSION_HI_SHIFT) != I40E_CURRENT_NVM_VERSION_HI) {
+               dev_info(&pdev->dev,
+                        "warning: NVM version not supported, supported version: %02x.%02x\n",
+                        I40E_CURRENT_NVM_VERSION_HI,
+                        I40E_CURRENT_NVM_VERSION_LO);
+       }
        if (err) {
                dev_info(&pdev->dev,
                         "init_adminq failed: %d expecting API %02x.%02x\n",
@@ -7247,6 +7393,8 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                i40e_flush(hw);
        }
 
+       pfs_found++;
+
        i40e_dbg_pf_init(pf);
 
        /* tell the firmware that we're starting */
index f75bb9ccc900d623c4e9cb2863574d279fef5529..930f53a2f50c613f3d25ea6a532438c7cda9052f 100644 (file)
@@ -106,7 +106,8 @@ i40e_status i40e_aq_update_vsi_params(struct i40e_hw *hw,
                                struct i40e_asq_cmd_details *cmd_details);
 i40e_status i40e_aq_add_veb(struct i40e_hw *hw, u16 uplink_seid,
                                u16 downlink_seid, u8 enabled_tc,
-                               bool default_port, u16 *pveb_seid,
+                               bool default_port, bool enable_l2_filtering,
+                               u16 *pveb_seid,
                                struct i40e_asq_cmd_details *cmd_details);
 i40e_status i40e_aq_get_veb_parameters(struct i40e_hw *hw,
                                u16 veb_seid, u16 *switch_id, bool *floating,
index 6bd333cde28bc6e0b92a095aca7490669348434d..2394c66870f4f672aae7e223554f6ce2345847fe 100644 (file)
 #ifndef _I40E_REGISTER_H_
 #define _I40E_REGISTER_H_
 
+#define I40E_GL_GP_FUSE(_i) (0x0009400C + ((_i) * 4)) /* _i=0...28 */
+#define I40E_GL_GP_FUSE_MAX_INDEX 28
+#define I40E_GL_GP_FUSE_GL_GP_FUSE_SHIFT 0
+#define I40E_GL_GP_FUSE_GL_GP_FUSE_MASK (0xFFFFFFFF << I40E_GL_GP_FUSE_GL_GP_FUSE_SHIFT)
 #define I40E_GLPCI_PM_MUX_NPQ 0x0009C4F4
 #define I40E_GLPCI_PM_MUX_NPQ_NPQ_NUM_PORT_SEL_SHIFT 0
 #define I40E_GLPCI_PM_MUX_NPQ_NPQ_NUM_PORT_SEL_MASK (0x7 << I40E_GLPCI_PM_MUX_NPQ_NPQ_NUM_PORT_SEL_SHIFT)
 #define I40E_GLPCI_PM_MUX_PFB_PFB_PORT_SEL_MASK (0x1F << I40E_GLPCI_PM_MUX_PFB_PFB_PORT_SEL_SHIFT)
 #define I40E_GLPCI_PM_MUX_PFB_INNER_PORT_SEL_SHIFT 16
 #define I40E_GLPCI_PM_MUX_PFB_INNER_PORT_SEL_MASK (0x7 << I40E_GLPCI_PM_MUX_PFB_INNER_PORT_SEL_SHIFT)
+#define I40E_GLPCI_PQ_MAX_USED_SPC 0x0009C4EC
+#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_12_SHIFT 0
+#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_12_MASK (0xFF << I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_12_SHIFT)
+#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_13_SHIFT 8
+#define I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_13_MASK (0xFF << I40E_GLPCI_PQ_MAX_USED_SPC_GLPCI_PQ_MAX_USED_SPC_13_SHIFT)
 #define I40E_GLPCI_SPARE_BITS_0 0x0009C4F8
 #define I40E_GLPCI_SPARE_BITS_0_SPARE_BITS_SHIFT 0
 #define I40E_GLPCI_SPARE_BITS_0_SPARE_BITS_MASK (0xFFFFFFFF << I40E_GLPCI_SPARE_BITS_0_SPARE_BITS_SHIFT)
 #define I40E_PFPCI_VF_FLUSH_DONE 0x0009C600
 #define I40E_PFPCI_VF_FLUSH_DONE_FLUSH_DONE_SHIFT 0
 #define I40E_PFPCI_VF_FLUSH_DONE_FLUSH_DONE_MASK (0x1 << I40E_PFPCI_VF_FLUSH_DONE_FLUSH_DONE_SHIFT)
+#define I40E_PFPCI_VF_FLUSH_DONE1(_VF) (0x0009C600 + ((_VF) * 4)) /* _i=0...127 */
+#define I40E_PFPCI_VF_FLUSH_DONE1_MAX_INDEX 127
+#define I40E_PFPCI_VF_FLUSH_DONE1_FLUSH_DONE_SHIFT 0
+#define I40E_PFPCI_VF_FLUSH_DONE1_FLUSH_DONE_MASK (0x1 << I40E_PFPCI_VF_FLUSH_DONE1_FLUSH_DONE_SHIFT)
 #define I40E_PFPCI_VM_FLUSH_DONE 0x0009C880
 #define I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_SHIFT 0
 #define I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_MASK (0x1 << I40E_PFPCI_VM_FLUSH_DONE_FLUSH_DONE_SHIFT)
+
 #define I40E_PF_ARQBAH 0x00080180
 #define I40E_PF_ARQBAH_ARQBAH_SHIFT 0
 #define I40E_PF_ARQBAH_ARQBAH_MASK (0xFFFFFFFF << I40E_PF_ARQBAH_ARQBAH_SHIFT)
 #define I40E_GLHMC_PEQ1FLCNT_FPMPEQ1FLCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEQ1FLCNT_FPMPEQ1FLCNT_SHIFT)
 #define I40E_GLHMC_PEQ1FLMAX 0x000C2058
 #define I40E_GLHMC_PEQ1FLMAX_PMPEQ1FLMAX_SHIFT 0
-#define I40E_GLHMC_PEQ1FLMAX_PMPEQ1FLMAX_MASK (0x3FFFFF << I40E_GLHMC_PEQ1FLMAX_PMPEQ1FLMAX_SHIFT)
+#define I40E_GLHMC_PEQ1FLMAX_PMPEQ1FLMAX_MASK (0x3FFFFFF << I40E_GLHMC_PEQ1FLMAX_PMPEQ1FLMAX_SHIFT)
 #define I40E_GLHMC_PEQ1MAX 0x000C2054
 #define I40E_GLHMC_PEQ1MAX_PMPEQ1MAX_SHIFT 0
 #define I40E_GLHMC_PEQ1MAX_PMPEQ1MAX_MASK (0x3FFFFFF << I40E_GLHMC_PEQ1MAX_PMPEQ1MAX_SHIFT)
 #define I40E_GLHMC_PEXFFLCNT_FPMPEXFFLCNT_MASK (0x1FFFFFFF << I40E_GLHMC_PEXFFLCNT_FPMPEXFFLCNT_SHIFT)
 #define I40E_GLHMC_PEXFFLMAX 0x000C204c
 #define I40E_GLHMC_PEXFFLMAX_PMPEXFFLMAX_SHIFT 0
-#define I40E_GLHMC_PEXFFLMAX_PMPEXFFLMAX_MASK (0x3FFFFF << I40E_GLHMC_PEXFFLMAX_PMPEXFFLMAX_SHIFT)
+#define I40E_GLHMC_PEXFFLMAX_PMPEXFFLMAX_MASK (0x1FFFFFF << I40E_GLHMC_PEXFFLMAX_PMPEXFFLMAX_SHIFT)
 #define I40E_GLHMC_PEXFMAX 0x000C2048
 #define I40E_GLHMC_PEXFMAX_PMPEXFMAX_SHIFT 0
 #define I40E_GLHMC_PEXFMAX_PMPEXFMAX_MASK (0x3FFFFFF << I40E_GLHMC_PEXFMAX_PMPEXFMAX_SHIFT)
 #define I40E_VSILAN_QBASE_VSIQTABLE_ENA_SHIFT 11
 #define I40E_VSILAN_QBASE_VSIQTABLE_ENA_MASK (0x1 << I40E_VSILAN_QBASE_VSIQTABLE_ENA_SHIFT)
 #define I40E_VSILAN_QTABLE(_i, _VSI) (0x00200000 + ((_i) * 2048 + (_VSI) * 4))
-#define I40E_VSILAN_QTABLE_MAX_INDEX 15
+#define I40E_VSILAN_QTABLE_MAX_INDEX 7
 #define I40E_VSILAN_QTABLE_QINDEX_0_SHIFT 0
 #define I40E_VSILAN_QTABLE_QINDEX_0_MASK (0x7FF << I40E_VSILAN_QTABLE_QINDEX_0_SHIFT)
 #define I40E_VSILAN_QTABLE_QINDEX_1_SHIFT 16
 #define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE0_SHIFT 14
 #define I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE0_MASK (0x3 << I40E_PRTMAC_PCS_XAUI_SWAP_B_SWAP_RX_LANE0_SHIFT)
 #define I40E_GL_MNG_FWSM 0x000B6134
-#define I40E_GL_MNG_FWSM_FW_MODES_SHIFT 0
-#define I40E_GL_MNG_FWSM_FW_MODES_MASK (0x3FF << I40E_GL_MNG_FWSM_FW_MODES_SHIFT)
-#define I40E_GL_MNG_FWSM_EEP_RELOAD_IND_SHIFT 10
+#define I40E_GL_MNG_FWSM_FW_MODES_SHIFT 1
+#define I40E_GL_MNG_FWSM_FW_MODES_MASK (0x7 << I40E_GL_MNG_FWSM_FW_MODES_SHIFT)
+#define I40E_GL_MNG_FWSM_EEP_RELOAD_IND_SHIFT 6
 #define I40E_GL_MNG_FWSM_EEP_RELOAD_IND_MASK (0x1 << I40E_GL_MNG_FWSM_EEP_RELOAD_IND_SHIFT)
 #define I40E_GL_MNG_FWSM_CRC_ERROR_MODULE_SHIFT 11
 #define I40E_GL_MNG_FWSM_CRC_ERROR_MODULE_MASK (0xF << I40E_GL_MNG_FWSM_CRC_ERROR_MODULE_SHIFT)
 #define I40E_GL_MNG_FWSM_FW_STATUS_VALID_SHIFT 15
 #define I40E_GL_MNG_FWSM_FW_STATUS_VALID_MASK (0x1 << I40E_GL_MNG_FWSM_FW_STATUS_VALID_SHIFT)
+#define I40E_GL_MNG_FWSM_RESET_CNT_SHIFT 16
+#define I40E_GL_MNG_FWSM_RESET_CNT_MASK (0x7 << I40E_GL_MNG_FWSM_RESET_CNT_SHIFT)
 #define I40E_GL_MNG_FWSM_EXT_ERR_IND_SHIFT 19
 #define I40E_GL_MNG_FWSM_EXT_ERR_IND_MASK (0x3F << I40E_GL_MNG_FWSM_EXT_ERR_IND_SHIFT)
+#define I40E_GL_MNG_FWSM_RSVD_SHIFT 25
+#define I40E_GL_MNG_FWSM_RSVD_MASK (0x1 << I40E_GL_MNG_FWSM_RSVD_SHIFT)
 #define I40E_GL_MNG_FWSM_PHY_SERDES0_CONFIG_ERR_SHIFT 26
 #define I40E_GL_MNG_FWSM_PHY_SERDES0_CONFIG_ERR_MASK (0x1 << I40E_GL_MNG_FWSM_PHY_SERDES0_CONFIG_ERR_SHIFT)
 #define I40E_GL_MNG_FWSM_PHY_SERDES1_CONFIG_ERR_SHIFT 27
 #define I40E_GLPCI_PCIERR 0x000BE4FC
 #define I40E_GLPCI_PCIERR_PCIE_ERR_REP_SHIFT 0
 #define I40E_GLPCI_PCIERR_PCIE_ERR_REP_MASK (0xFFFFFFFF << I40E_GLPCI_PCIERR_PCIE_ERR_REP_SHIFT)
+#define I40E_GLPCI_PCITEST2 0x000BE4BC
+#define I40E_GLPCI_PCITEST2_IOV_TEST_MODE_SHIFT 0
+#define I40E_GLPCI_PCITEST2_IOV_TEST_MODE_MASK (0x1 << I40E_GLPCI_PCITEST2_IOV_TEST_MODE_SHIFT)
+#define I40E_GLPCI_PCITEST2_TAG_ALLOC_SHIFT 1
+#define I40E_GLPCI_PCITEST2_TAG_ALLOC_MASK (0x1 << I40E_GLPCI_PCITEST2_TAG_ALLOC_SHIFT)
+
 #define I40E_GLPCI_PKTCT 0x0009C4BC
 #define I40E_GLPCI_PKTCT_PCI_COUNT_BW_PCT_SHIFT 0
 #define I40E_GLPCI_PKTCT_PCI_COUNT_BW_PCT_MASK (0xFFFFFFFF << I40E_GLPCI_PKTCT_PCI_COUNT_BW_PCT_SHIFT)
 #define I40E_PFPE_IPCONFIG0_PEIPID_MASK (0xFFFF << I40E_PFPE_IPCONFIG0_PEIPID_SHIFT)
 #define I40E_PFPE_IPCONFIG0_USEENTIREIDRANGE_SHIFT 16
 #define I40E_PFPE_IPCONFIG0_USEENTIREIDRANGE_MASK (0x1 << I40E_PFPE_IPCONFIG0_USEENTIREIDRANGE_SHIFT)
-#define I40E_PFPE_IPCONFIG0_USEUPPERIDRANGE_SHIFT 17
-#define I40E_PFPE_IPCONFIG0_USEUPPERIDRANGE_MASK (0x1 << I40E_PFPE_IPCONFIG0_USEUPPERIDRANGE_SHIFT)
+
 #define I40E_PFPE_MRTEIDXMASK 0x00008600
 #define I40E_PFPE_MRTEIDXMASK_MRTEIDXMASKBITS_SHIFT 0
 #define I40E_PFPE_MRTEIDXMASK_MRTEIDXMASKBITS_MASK (0x1F << I40E_PFPE_MRTEIDXMASK_MRTEIDXMASKBITS_SHIFT)
 #define I40E_VFPE_IPCONFIG0_PEIPID_MASK (0xFFFF << I40E_VFPE_IPCONFIG0_PEIPID_SHIFT)
 #define I40E_VFPE_IPCONFIG0_USEENTIREIDRANGE_SHIFT 16
 #define I40E_VFPE_IPCONFIG0_USEENTIREIDRANGE_MASK (0x1 << I40E_VFPE_IPCONFIG0_USEENTIREIDRANGE_SHIFT)
-#define I40E_VFPE_IPCONFIG0_USEUPPERIDRANGE_SHIFT 17
-#define I40E_VFPE_IPCONFIG0_USEUPPERIDRANGE_MASK (0x1 << I40E_VFPE_IPCONFIG0_USEUPPERIDRANGE_SHIFT)
 #define I40E_VFPE_MRTEIDXMASK(_VF) (0x00003000 + ((_VF) * 4)) /* _i=0...127 */
 #define I40E_VFPE_MRTEIDXMASK_MAX_INDEX 127
 #define I40E_VFPE_MRTEIDXMASK_MRTEIDXMASKBITS_SHIFT 0
 #define I40E_GLPES_VFUDPTXPKTSLO_MAX_INDEX 31
 #define I40E_GLPES_VFUDPTXPKTSLO_UDPTXPKTSLO_SHIFT 0
 #define I40E_GLPES_VFUDPTXPKTSLO_UDPTXPKTSLO_MASK (0xFFFFFFFF << I40E_GLPES_VFUDPTXPKTSLO_UDPTXPKTSLO_SHIFT)
-#define I40E_GLPM_DMACR 0x000881F4
-#define I40E_GLPM_DMACR_DMACWT_SHIFT 0
-#define I40E_GLPM_DMACR_DMACWT_MASK (0xFFFF << I40E_GLPM_DMACR_DMACWT_SHIFT)
-#define I40E_GLPM_DMACR_EXIT_DC_SHIFT 29
-#define I40E_GLPM_DMACR_EXIT_DC_MASK (0x1 << I40E_GLPM_DMACR_EXIT_DC_SHIFT)
-#define I40E_GLPM_DMACR_LX_COALESCING_INDICATION_SHIFT 30
-#define I40E_GLPM_DMACR_LX_COALESCING_INDICATION_MASK (0x1 << I40E_GLPM_DMACR_LX_COALESCING_INDICATION_SHIFT)
-#define I40E_GLPM_DMACR_DMAC_EN_SHIFT 31
-#define I40E_GLPM_DMACR_DMAC_EN_MASK (0x1 << I40E_GLPM_DMACR_DMAC_EN_SHIFT)
-#define I40E_GLPM_LTRC 0x000BE500
-#define I40E_GLPM_LTRC_SLTRV_SHIFT 0
-#define I40E_GLPM_LTRC_SLTRV_MASK (0x3FF << I40E_GLPM_LTRC_SLTRV_SHIFT)
-#define I40E_GLPM_LTRC_SSCALE_SHIFT 10
-#define I40E_GLPM_LTRC_SSCALE_MASK (0x7 << I40E_GLPM_LTRC_SSCALE_SHIFT)
-#define I40E_GLPM_LTRC_LTRS_REQUIREMENT_SHIFT 15
-#define I40E_GLPM_LTRC_LTRS_REQUIREMENT_MASK (0x1 << I40E_GLPM_LTRC_LTRS_REQUIREMENT_SHIFT)
-#define I40E_GLPM_LTRC_NSLTRV_SHIFT 16
-#define I40E_GLPM_LTRC_NSLTRV_MASK (0x3FF << I40E_GLPM_LTRC_NSLTRV_SHIFT)
-#define I40E_GLPM_LTRC_NSSCALE_SHIFT 26
-#define I40E_GLPM_LTRC_NSSCALE_MASK (0x7 << I40E_GLPM_LTRC_NSSCALE_SHIFT)
-#define I40E_GLPM_LTRC_LTR_SEND_SHIFT 30
-#define I40E_GLPM_LTRC_LTR_SEND_MASK (0x1 << I40E_GLPM_LTRC_LTR_SEND_SHIFT)
-#define I40E_GLPM_LTRC_LTRNS_REQUIREMENT_SHIFT 31
-#define I40E_GLPM_LTRC_LTRNS_REQUIREMENT_MASK (0x1 << I40E_GLPM_LTRC_LTRNS_REQUIREMENT_SHIFT)
 #define I40E_PRTPM_EEE_STAT 0x001E4320
 #define I40E_PRTPM_EEE_STAT_EEE_NEG_SHIFT 29
 #define I40E_PRTPM_EEE_STAT_EEE_NEG_MASK (0x1 << I40E_PRTPM_EEE_STAT_EEE_NEG_SHIFT)
 #define I40E_PRTPM_GC_LCDMP_MASK (0x1 << I40E_PRTPM_GC_LCDMP_SHIFT)
 #define I40E_PRTPM_GC_LPLU_ASSERTED_SHIFT 31
 #define I40E_PRTPM_GC_LPLU_ASSERTED_MASK (0x1 << I40E_PRTPM_GC_LPLU_ASSERTED_SHIFT)
-#define I40E_PRTPM_HPTC 0x000AC800
-#define I40E_PRTPM_HPTC_HIGH_PRI_TC_SHIFT 0
-#define I40E_PRTPM_HPTC_HIGH_PRI_TC_MASK (0xFF << I40E_PRTPM_HPTC_HIGH_PRI_TC_SHIFT)
 #define I40E_PRTPM_RLPIC 0x001E43A0
 #define I40E_PRTPM_RLPIC_ERLPIC_SHIFT 0
 #define I40E_PRTPM_RLPIC_ERLPIC_MASK (0xFFFFFFFF << I40E_PRTPM_RLPIC_ERLPIC_SHIFT)
 #define I40E_GLQF_CTL_HTOEP_FCOE_MASK (0x1 << I40E_GLQF_CTL_HTOEP_FCOE_SHIFT)
 #define I40E_GLQF_CTL_PCNT_ALLOC_SHIFT 3
 #define I40E_GLQF_CTL_PCNT_ALLOC_MASK (0x7 << I40E_GLQF_CTL_PCNT_ALLOC_SHIFT)
-#define I40E_GLQF_CTL_DDPLPEN_SHIFT 7
-#define I40E_GLQF_CTL_DDPLPEN_MASK (0x1 << I40E_GLQF_CTL_DDPLPEN_SHIFT)
+#define I40E_GLQF_CTL_RSVD_SHIFT 7
+#define I40E_GLQF_CTL_RSVD_MASK (0x1 << I40E_GLQF_CTL_RSVD_SHIFT)
 #define I40E_GLQF_CTL_MAXPEBLEN_SHIFT 8
 #define I40E_GLQF_CTL_MAXPEBLEN_MASK (0x7 << I40E_GLQF_CTL_MAXPEBLEN_SHIFT)
 #define I40E_GLQF_CTL_MAXFCBLEN_SHIFT 11
 #define I40E_PRTQF_FLX_PIT(_i) (0x00255200 + ((_i) * 32)) /* _i=0...8 */
 #define I40E_PRTQF_FLX_PIT_MAX_INDEX 8
 #define I40E_PRTQF_FLX_PIT_SOURCE_OFF_SHIFT 0
-#define I40E_PRTQF_FLX_PIT_SOURCE_OFF_MASK (0x3F << I40E_PRTQF_FLX_PIT_SOURCE_OFF_SHIFT)
-#define I40E_PRTQF_FLX_PIT_FSIZE_SHIFT 6
-#define I40E_PRTQF_FLX_PIT_FSIZE_MASK (0xF << I40E_PRTQF_FLX_PIT_FSIZE_SHIFT)
+#define I40E_PRTQF_FLX_PIT_SOURCE_OFF_MASK (0x1F << I40E_PRTQF_FLX_PIT_SOURCE_OFF_SHIFT)
+#define I40E_PRTQF_FLX_PIT_FSIZE_SHIFT 5
+#define I40E_PRTQF_FLX_PIT_FSIZE_MASK (0x1F << I40E_PRTQF_FLX_PIT_FSIZE_SHIFT)
 #define I40E_PRTQF_FLX_PIT_DEST_OFF_SHIFT 10
 #define I40E_PRTQF_FLX_PIT_DEST_OFF_MASK (0x3F << I40E_PRTQF_FLX_PIT_DEST_OFF_SHIFT)
 #define I40E_VFQF_HENA1(_i, _VF) (0x00230800 + ((_i) * 1024 + (_VF) * 4))
 #define I40E_VSIQF_CTL_PEMFRAG_ENA_SHIFT 5
 #define I40E_VSIQF_CTL_PEMFRAG_ENA_MASK (0x1 << I40E_VSIQF_CTL_PEMFRAG_ENA_SHIFT)
 #define I40E_VSIQF_TCREGION(_i, _VSI) (0x00206000 + ((_i) * 2048 + (_VSI) * 4))
-#define I40E_VSIQF_TCREGION_MAX_INDEX 7
+#define I40E_VSIQF_TCREGION_MAX_INDEX 3
 #define I40E_VSIQF_TCREGION_TC_OFFSET_SHIFT 0
 #define I40E_VSIQF_TCREGION_TC_OFFSET_MASK (0x1FF << I40E_VSIQF_TCREGION_TC_OFFSET_SHIFT)
 #define I40E_VSIQF_TCREGION_TC_SIZE_SHIFT 9
 #define I40E_GL_FCOEDDPC_MAX_INDEX 143
 #define I40E_GL_FCOEDDPC_FCOEDDPC_SHIFT 0
 #define I40E_GL_FCOEDDPC_FCOEDDPC_MASK (0xFFFFFFFF << I40E_GL_FCOEDDPC_FCOEDDPC_SHIFT)
-#define I40E_GL_FCOEDDPEC(_i) (0x00314900 + ((_i) * 8)) /* _i=0...143 */
-#define I40E_GL_FCOEDDPEC_MAX_INDEX 143
-#define I40E_GL_FCOEDDPEC_CFOEDDPEC_SHIFT 0
-#define I40E_GL_FCOEDDPEC_CFOEDDPEC_MASK (0xFFFFFFFF << I40E_GL_FCOEDDPEC_CFOEDDPEC_SHIFT)
+/* _i=0...143 */
 #define I40E_GL_FCOEDIFEC(_i) (0x00318480 + ((_i) * 8)) /* _i=0...143 */
 #define I40E_GL_FCOEDIFEC_MAX_INDEX 143
 #define I40E_GL_FCOEDIFEC_FCOEDIFRC_SHIFT 0
 #define I40E_PFPM_APM 0x000B8080
 #define I40E_PFPM_APM_APME_SHIFT 0
 #define I40E_PFPM_APM_APME_MASK (0x1 << I40E_PFPM_APM_APME_SHIFT)
-#define I40E_PFPM_FHFT_DATA(_i, _j) (0x00060000 + ((_i) * 4096 + (_j) * 128))
-#define I40E_PFPM_FHFT_DATA_MAX_INDEX 7
-#define I40E_PFPM_FHFT_DATA_DWORD_SHIFT 0
-#define I40E_PFPM_FHFT_DATA_DWORD_MASK (0xFFFFFFFF << I40E_PFPM_FHFT_DATA_DWORD_SHIFT)
 #define I40E_PFPM_FHFT_LENGTH(_i) (0x0006A000 + ((_i) * 128)) /* _i=0...7 */
 #define I40E_PFPM_FHFT_LENGTH_MAX_INDEX 7
 #define I40E_PFPM_FHFT_LENGTH_LENGTH_SHIFT 0
 #define I40E_PFPM_FHFT_LENGTH_LENGTH_MASK (0xFF << I40E_PFPM_FHFT_LENGTH_LENGTH_SHIFT)
-#define I40E_PFPM_FHFT_MASK(_i, _j) (0x00068000 + ((_i) * 1024 + (_j) * 128))
-#define I40E_PFPM_FHFT_MASK_MAX_INDEX 7
-#define I40E_PFPM_FHFT_MASK_MASK_SHIFT 0
-#define I40E_PFPM_FHFT_MASK_MASK_MASK (0xFFFF << I40E_PFPM_FHFT_MASK_MASK_SHIFT)
-#define I40E_PFPM_PROXYFC 0x00245A80
-#define I40E_PFPM_PROXYFC_PPROXYE_SHIFT 0
-#define I40E_PFPM_PROXYFC_PPROXYE_MASK (0x1 << I40E_PFPM_PROXYFC_PPROXYE_SHIFT)
-#define I40E_PFPM_PROXYFC_EX_SHIFT 1
-#define I40E_PFPM_PROXYFC_EX_MASK (0x1 << I40E_PFPM_PROXYFC_EX_SHIFT)
-#define I40E_PFPM_PROXYFC_ARP_SHIFT 4
-#define I40E_PFPM_PROXYFC_ARP_MASK (0x1 << I40E_PFPM_PROXYFC_ARP_SHIFT)
-#define I40E_PFPM_PROXYFC_ARP_DIRECTED_SHIFT 5
-#define I40E_PFPM_PROXYFC_ARP_DIRECTED_MASK (0x1 << I40E_PFPM_PROXYFC_ARP_DIRECTED_SHIFT)
-#define I40E_PFPM_PROXYFC_NS_SHIFT 9
-#define I40E_PFPM_PROXYFC_NS_MASK (0x1 << I40E_PFPM_PROXYFC_NS_SHIFT)
-#define I40E_PFPM_PROXYFC_NS_DIRECTED_SHIFT 10
-#define I40E_PFPM_PROXYFC_NS_DIRECTED_MASK (0x1 << I40E_PFPM_PROXYFC_NS_DIRECTED_SHIFT)
-#define I40E_PFPM_PROXYFC_MLD_SHIFT 12
-#define I40E_PFPM_PROXYFC_MLD_MASK (0x1 << I40E_PFPM_PROXYFC_MLD_SHIFT)
-#define I40E_PFPM_PROXYS 0x00245B80
-#define I40E_PFPM_PROXYS_EX_SHIFT 1
-#define I40E_PFPM_PROXYS_EX_MASK (0x1 << I40E_PFPM_PROXYS_EX_SHIFT)
-#define I40E_PFPM_PROXYS_ARP_SHIFT 4
-#define I40E_PFPM_PROXYS_ARP_MASK (0x1 << I40E_PFPM_PROXYS_ARP_SHIFT)
-#define I40E_PFPM_PROXYS_ARP_DIRECTED_SHIFT 5
-#define I40E_PFPM_PROXYS_ARP_DIRECTED_MASK (0x1 << I40E_PFPM_PROXYS_ARP_DIRECTED_SHIFT)
-#define I40E_PFPM_PROXYS_NS_SHIFT 9
-#define I40E_PFPM_PROXYS_NS_MASK (0x1 << I40E_PFPM_PROXYS_NS_SHIFT)
-#define I40E_PFPM_PROXYS_NS_DIRECTED_SHIFT 10
-#define I40E_PFPM_PROXYS_NS_DIRECTED_MASK (0x1 << I40E_PFPM_PROXYS_NS_DIRECTED_SHIFT)
-#define I40E_PFPM_PROXYS_MLD_SHIFT 12
-#define I40E_PFPM_PROXYS_MLD_MASK (0x1 << I40E_PFPM_PROXYS_MLD_SHIFT)
 #define I40E_PFPM_WUC 0x0006B200
 #define I40E_PFPM_WUC_EN_APM_D0_SHIFT 5
 #define I40E_PFPM_WUC_EN_APM_D0_MASK (0x1 << I40E_PFPM_WUC_EN_APM_D0_SHIFT)
 #define I40E_VFMSIX_PBA 0x00002000
 #define I40E_VFMSIX_PBA_PENBIT_SHIFT 0
 #define I40E_VFMSIX_PBA_PENBIT_MASK (0xFFFFFFFF << I40E_VFMSIX_PBA_PENBIT_SHIFT)
-#define I40E_VFMSIX_TADD(_i) (0x00000008 + ((_i) * 16)) /* _i=0...16 */
+#define I40E_VFMSIX_TADD(_i) (0x00000000 + ((_i) * 16)) /* _i=0...16 */
 #define I40E_VFMSIX_TADD_MAX_INDEX 16
 #define I40E_VFMSIX_TADD_MSIXTADD10_SHIFT 0
 #define I40E_VFMSIX_TADD_MSIXTADD10_MASK (0x3 << I40E_VFMSIX_TADD_MSIXTADD10_SHIFT)
 #define I40E_VFMSIX_TADD_MSIXTADD_SHIFT 2
 #define I40E_VFMSIX_TADD_MSIXTADD_MASK (0x3FFFFFFF << I40E_VFMSIX_TADD_MSIXTADD_SHIFT)
-#define I40E_VFMSIX_TMSG(_i) (0x0000000C + ((_i) * 16)) /* _i=0...16 */
+#define I40E_VFMSIX_TMSG(_i) (0x00000008 + ((_i) * 16)) /* _i=0...16 */
 #define I40E_VFMSIX_TMSG_MAX_INDEX 16
 #define I40E_VFMSIX_TMSG_MSIXTMSG_SHIFT 0
 #define I40E_VFMSIX_TMSG_MSIXTMSG_MASK (0xFFFFFFFF << I40E_VFMSIX_TMSG_MSIXTMSG_SHIFT)
-#define I40E_VFMSIX_TUADD(_i) (0x00000000 + ((_i) * 16)) /* _i=0...16 */
+#define I40E_VFMSIX_TUADD(_i) (0x00000004 + ((_i) * 16)) /* _i=0...16 */
 #define I40E_VFMSIX_TUADD_MAX_INDEX 16
 #define I40E_VFMSIX_TUADD_MSIXTUADD_SHIFT 0
 #define I40E_VFMSIX_TUADD_MSIXTUADD_MASK (0xFFFFFFFF << I40E_VFMSIX_TUADD_MSIXTUADD_SHIFT)
-#define I40E_VFMSIX_TVCTRL(_i) (0x00000004 + ((_i) * 16)) /* _i=0...16 */
+#define I40E_VFMSIX_TVCTRL(_i) (0x0000000C + ((_i) * 16)) /* _i=0...16 */
 #define I40E_VFMSIX_TVCTRL_MAX_INDEX 16
 #define I40E_VFMSIX_TVCTRL_MASK_SHIFT 0
 #define I40E_VFMSIX_TVCTRL_MASK_MASK (0x1 << I40E_VFMSIX_TVCTRL_MASK_SHIFT)
 #define I40E_VFPE_IPCONFIG01_PEIPID_MASK (0xFFFF << I40E_VFPE_IPCONFIG01_PEIPID_SHIFT)
 #define I40E_VFPE_IPCONFIG01_USEENTIREIDRANGE_SHIFT 16
 #define I40E_VFPE_IPCONFIG01_USEENTIREIDRANGE_MASK (0x1 << I40E_VFPE_IPCONFIG01_USEENTIREIDRANGE_SHIFT)
-#define I40E_VFPE_IPCONFIG01_USEUPPERIDRANGE_SHIFT 17
-#define I40E_VFPE_IPCONFIG01_USEUPPERIDRANGE_MASK (0x1 << I40E_VFPE_IPCONFIG01_USEUPPERIDRANGE_SHIFT)
 #define I40E_VFPE_MRTEIDXMASK1 0x00009000
 #define I40E_VFPE_MRTEIDXMASK1_MRTEIDXMASKBITS_SHIFT 0
 #define I40E_VFPE_MRTEIDXMASK1_MRTEIDXMASKBITS_MASK (0x1F << I40E_VFPE_MRTEIDXMASK1_MRTEIDXMASKBITS_SHIFT)
 #define I40E_VFQF_HREGION_OVERRIDE_ENA_7_MASK (0x1 << I40E_VFQF_HREGION_OVERRIDE_ENA_7_SHIFT)
 #define I40E_VFQF_HREGION_REGION_7_SHIFT 29
 #define I40E_VFQF_HREGION_REGION_7_MASK (0x7 << I40E_VFQF_HREGION_REGION_7_SHIFT)
-
+#define I40E_RCU_PST_FOC_ACCESS_STATUS 0x00270110
+#define I40E_RCU_PST_FOC_ACCESS_STATUS_WR_ACCESS_CNT_SHIFT 0
+#define I40E_RCU_PST_FOC_ACCESS_STATUS_WR_ACCESS_CNT_MASK (0xFF << I40E_RCU_PST_FOC_ACCESS_STATUS_WR_ACCESS_CNT_SHIFT)
+#define I40E_RCU_PST_FOC_ACCESS_STATUS_RD_ACCESS_CNT_SHIFT 8
+#define I40E_RCU_PST_FOC_ACCESS_STATUS_RD_ACCESS_CNT_MASK (0xFF << I40E_RCU_PST_FOC_ACCESS_STATUS_RD_ACCESS_CNT_SHIFT)
+#define I40E_RCU_PST_FOC_ACCESS_STATUS_ERR_CNT_SHIFT 16
+#define I40E_RCU_PST_FOC_ACCESS_STATUS_ERR_CNT_MASK (0xFF << I40E_RCU_PST_FOC_ACCESS_STATUS_ERR_CNT_SHIFT)
+#define I40E_RCU_PST_FOC_ACCESS_STATUS_LAST_ERR_CODE_SHIFT 24
+#define I40E_RCU_PST_FOC_ACCESS_STATUS_LAST_ERR_CODE_MASK (0x7 << I40E_RCU_PST_FOC_ACCESS_STATUS_LAST_ERR_CODE_SHIFT)
 #endif
index f1f03bc5c729131bacdb13e243213b18b5b43132..01d0334fa926b3e5c73039a0fa90805b1e4c2786 100644 (file)
@@ -891,13 +891,15 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi,
 static inline u32 i40e_rx_hash(struct i40e_ring *ring,
                               union i40e_rx_desc *rx_desc)
 {
-       if (ring->netdev->features & NETIF_F_RXHASH) {
-               if ((le64_to_cpu(rx_desc->wb.qword1.status_error_len) >>
-                    I40E_RX_DESC_STATUS_FLTSTAT_SHIFT) &
-                   I40E_RX_DESC_FLTSTAT_RSS_HASH)
-                       return le32_to_cpu(rx_desc->wb.qword0.hi_dword.rss);
-       }
-       return 0;
+       const __le64 rss_mask =
+               cpu_to_le64((u64)I40E_RX_DESC_FLTSTAT_RSS_HASH <<
+                           I40E_RX_DESC_STATUS_FLTSTAT_SHIFT);
+
+       if ((ring->netdev->features & NETIF_F_RXHASH) &&
+           (rx_desc->wb.qword1.status_error_len & rss_mask) == rss_mask)
+               return le32_to_cpu(rx_desc->wb.qword0.hi_dword.rss);
+       else
+               return 0;
 }
 
 /**
index db55d9947f151cf19c17f2f55e8ee24e69364cbd..faabf22fbd202751343053daf839f7edf838191b 100644 (file)
 
 #define I40E_QUEUE_END_OF_LIST 0x7FF
 
-#define I40E_ITR_NONE  3
-#define I40E_RX_ITR    0
-#define I40E_TX_ITR    1
-#define I40E_PE_ITR    2
+/* this enum matches hardware bits and is meant to be used by DYN_CTLN
+ * registers and QINT registers or more generally anywhere in the manual
+ * mentioning ITR_INDX, ITR_NONE cannot be used as an index 'n' into any
+ * register but instead is a special value meaning "don't update" ITR0/1/2.
+ */
+enum i40e_dyn_idx_t {
+       I40E_IDX_ITR0 = 0,
+       I40E_IDX_ITR1 = 1,
+       I40E_IDX_ITR2 = 2,
+       I40E_ITR_NONE = 3       /* ITR_NONE must not be used as an index */
+};
+
+/* these are indexes into ITRN registers */
+#define I40E_RX_ITR    I40E_IDX_ITR0
+#define I40E_TX_ITR    I40E_IDX_ITR1
+#define I40E_PE_ITR    I40E_IDX_ITR2
+
 /* Supported Rx Buffer Sizes */
 #define I40E_RXBUFFER_512   512    /* Used for packet split */
 #define I40E_RXBUFFER_2048  2048
index f3f22b20f02f3bc3b19d7aa8f17380b4d8518182..8ae64457026348deb5ac8aa3efdcad35abe09d3c 100644 (file)
@@ -134,6 +134,7 @@ enum i40e_media_type {
        I40E_MEDIA_TYPE_BASET,
        I40E_MEDIA_TYPE_BACKPLANE,
        I40E_MEDIA_TYPE_CX4,
+       I40E_MEDIA_TYPE_DA,
        I40E_MEDIA_TYPE_VIRTUAL
 };
 
@@ -171,6 +172,7 @@ struct i40e_link_status {
        u8 link_info;
        u8 an_info;
        u8 ext_info;
+       u8 loopback;
        /* is Link Status Event notification to SW enabled */
        bool lse_enable;
 };
@@ -500,7 +502,8 @@ enum i40e_rx_desc_status_bits {
        I40E_RX_DESC_STATUS_L2TAG1P_SHIFT       = 2,
        I40E_RX_DESC_STATUS_L3L4P_SHIFT         = 3,
        I40E_RX_DESC_STATUS_CRCP_SHIFT          = 4,
-       I40E_RX_DESC_STATUS_TSYNINDX_SHIFT      = 5, /* 3 BITS */
+       I40E_RX_DESC_STATUS_TSYNINDX_SHIFT      = 5, /* 2 BITS */
+       I40E_RX_DESC_STATUS_TSYNVALID_SHIFT     = 7,
        I40E_RX_DESC_STATUS_PIF_SHIFT           = 8,
        I40E_RX_DESC_STATUS_UMBCAST_SHIFT       = 9, /* 2 BITS */
        I40E_RX_DESC_STATUS_FLM_SHIFT           = 11,
@@ -509,9 +512,13 @@ enum i40e_rx_desc_status_bits {
 };
 
 #define I40E_RXD_QW1_STATUS_TSYNINDX_SHIFT   I40E_RX_DESC_STATUS_TSYNINDX_SHIFT
-#define I40E_RXD_QW1_STATUS_TSYNINDX_MASK      (0x7UL << \
+#define I40E_RXD_QW1_STATUS_TSYNINDX_MASK      (0x3UL << \
                                             I40E_RXD_QW1_STATUS_TSYNINDX_SHIFT)
 
+#define I40E_RXD_QW1_STATUS_TSYNVALID_SHIFT  I40E_RX_DESC_STATUS_TSYNVALID_SHIFT
+#define I40E_RXD_QW1_STATUS_TSYNVALID_MASK     (0x1UL << \
+                                            I40E_RXD_QW1_STATUS_TSYNVALID_SHIFT)
+
 enum i40e_rx_desc_fltstat_values {
        I40E_RX_DESC_FLTSTAT_NO_DATA    = 0,
        I40E_RX_DESC_FLTSTAT_RSV_FD_ID  = 1, /* 16byte desc? FD_ID : RSV */
@@ -852,10 +859,7 @@ struct i40e_filter_program_desc {
 
 /* Packet Classifier Types for filters */
 enum i40e_filter_pctype {
-       /* Note: Value 0-25 are reserved for future use */
-       I40E_FILTER_PCTYPE_IPV4_TEREDO_UDP              = 26,
-       I40E_FILTER_PCTYPE_IPV6_TEREDO_UDP              = 27,
-       I40E_FILTER_PCTYPE_NONF_IPV4_1588_UDP           = 28,
+       /* Note: Values 0-28 are reserved for future use */
        I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP        = 29,
        I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP      = 30,
        I40E_FILTER_PCTYPE_NONF_IPV4_UDP                = 31,
@@ -864,8 +868,7 @@ enum i40e_filter_pctype {
        I40E_FILTER_PCTYPE_NONF_IPV4_SCTP               = 34,
        I40E_FILTER_PCTYPE_NONF_IPV4_OTHER              = 35,
        I40E_FILTER_PCTYPE_FRAG_IPV4                    = 36,
-       /* Note: Value 37 is reserved for future use */
-       I40E_FILTER_PCTYPE_NONF_IPV6_1588_UDP           = 38,
+       /* Note: Values 37-38 are reserved for future use */
        I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP        = 39,
        I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP      = 40,
        I40E_FILTER_PCTYPE_NONF_IPV6_UDP                = 41,
@@ -877,7 +880,8 @@ enum i40e_filter_pctype {
        /* Note: Value 47 is reserved for future use */
        I40E_FILTER_PCTYPE_FCOE_OX                      = 48,
        I40E_FILTER_PCTYPE_FCOE_RX                      = 49,
-       /* Note: Value 50-62 are reserved for future use */
+       I40E_FILTER_PCTYPE_FCOE_OTHER                   = 50,
+       /* Note: Values 51-62 are reserved for future use */
        I40E_FILTER_PCTYPE_L2_PAYLOAD                   = 63,
 };
 
index 07596982a4773fc942a5a0c3b8a458bdaa837768..e7bdd47bafcfb78d309407222c0c035c9e77fdaf 100644 (file)
@@ -70,7 +70,7 @@ static inline bool i40e_vc_isvalid_vector_id(struct i40e_vf *vf, u8 vector_id)
 {
        struct i40e_pf *pf = vf->pf;
 
-       return vector_id < pf->hw.func_caps.num_msix_vectors_vf;
+       return vector_id <= pf->hw.func_caps.num_msix_vectors_vf;
 }
 
 /***********************vf resource mgmt routines*****************/
@@ -620,13 +620,13 @@ int i40e_reset_vf(struct i40e_vf *vf, bool flr)
                if (ret)
                        dev_info(&pf->pdev->dev,
                                 "Queue control check failed on Tx queue %d of VSI %d VF %d\n",
-                                vf->lan_vsi_index, j, vf->vf_id);
+                                j, vf->lan_vsi_index, vf->vf_id);
                ret = i40e_ctrl_vsi_rx_queue(vf, vf->lan_vsi_index, j,
                                             I40E_QUEUE_CTRL_FASTDISABLECHECK);
                if (ret)
                        dev_info(&pf->pdev->dev,
                                 "Queue control check failed on Rx queue %d of VSI %d VF %d\n",
-                                vf->lan_vsi_index, j, vf->vf_id);
+                                j, vf->lan_vsi_index, vf->vf_id);
        }
 
        /* clear the irq settings */
@@ -1603,7 +1603,7 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
                struct i40e_mac_filter *f;
 
                f = i40e_find_mac(vsi, al->list[i].addr, true, false);
-               if (f) {
+               if (!f) {
                        if (i40e_is_vsi_in_vlan(vsi))
                                f = i40e_put_mac_in_vlan(vsi, al->list[i].addr,
                                                         true, false);
index 47c2d10df8263422d8e23169939adc84a5f3012b..06df6928f44c2942f3e9b51647d047d790a2d6af 100644 (file)
@@ -112,6 +112,59 @@ static bool igb_sgmii_uses_mdio_82575(struct e1000_hw *hw)
        return ext_mdio;
 }
 
+/**
+ *  igb_check_for_link_media_swap - Check which M88E1112 interface linked
+ *  @hw: pointer to the HW structure
+ *
+ *  Poll the M88E1112 interfaces to see which interface achieved link.
+ */
+static s32 igb_check_for_link_media_swap(struct e1000_hw *hw)
+{
+       struct e1000_phy_info *phy = &hw->phy;
+       s32 ret_val;
+       u16 data;
+       u8 port = 0;
+
+       /* Check the copper medium. */
+       ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0);
+       if (ret_val)
+               return ret_val;
+
+       ret_val = phy->ops.read_reg(hw, E1000_M88E1112_STATUS, &data);
+       if (ret_val)
+               return ret_val;
+
+       if (data & E1000_M88E1112_STATUS_LINK)
+               port = E1000_MEDIA_PORT_COPPER;
+
+       /* Check the other medium. */
+       ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 1);
+       if (ret_val)
+               return ret_val;
+
+       ret_val = phy->ops.read_reg(hw, E1000_M88E1112_STATUS, &data);
+       if (ret_val)
+               return ret_val;
+
+       /* reset page to 0 */
+       ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0);
+       if (ret_val)
+               return ret_val;
+
+       if (data & E1000_M88E1112_STATUS_LINK)
+               port = E1000_MEDIA_PORT_OTHER;
+
+       /* Determine if a swap needs to happen. */
+       if (port && (hw->dev_spec._82575.media_port != port)) {
+               hw->dev_spec._82575.media_port = port;
+               hw->dev_spec._82575.media_changed = true;
+       } else {
+               ret_val = igb_check_for_link_82575(hw);
+       }
+
+       return E1000_SUCCESS;
+}
+
 /**
  *  igb_init_phy_params_82575 - Init PHY func ptrs.
  *  @hw: pointer to the HW structure
@@ -189,6 +242,29 @@ static s32 igb_init_phy_params_82575(struct e1000_hw *hw)
                else
                        phy->ops.get_cable_length = igb_get_cable_length_m88;
                phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_m88;
+               /* Check if this PHY is confgured for media swap. */
+               if (phy->id == M88E1112_E_PHY_ID) {
+                       u16 data;
+
+                       ret_val = phy->ops.write_reg(hw,
+                                                    E1000_M88E1112_PAGE_ADDR,
+                                                    2);
+                       if (ret_val)
+                               goto out;
+
+                       ret_val = phy->ops.read_reg(hw,
+                                                   E1000_M88E1112_MAC_CTRL_1,
+                                                   &data);
+                       if (ret_val)
+                               goto out;
+
+                       data = (data & E1000_M88E1112_MAC_CTRL_1_MODE_MASK) >>
+                              E1000_M88E1112_MAC_CTRL_1_MODE_SHIFT;
+                       if (data == E1000_M88E1112_AUTO_COPPER_SGMII ||
+                           data == E1000_M88E1112_AUTO_COPPER_BASEX)
+                               hw->mac.ops.check_for_link =
+                                               igb_check_for_link_media_swap;
+               }
                break;
        case IGP03E1000_E_PHY_ID:
                phy->type = e1000_phy_igp_3;
@@ -365,6 +441,19 @@ static s32 igb_init_mac_params_82575(struct e1000_hw *hw)
                        ? igb_setup_copper_link_82575
                        : igb_setup_serdes_link_82575;
 
+       if (mac->type == e1000_82580) {
+               switch (hw->device_id) {
+               /* feature not supported on these id's */
+               case E1000_DEV_ID_DH89XXCC_SGMII:
+               case E1000_DEV_ID_DH89XXCC_SERDES:
+               case E1000_DEV_ID_DH89XXCC_BACKPLANE:
+               case E1000_DEV_ID_DH89XXCC_SFP:
+                       break;
+               default:
+                       hw->dev_spec._82575.mas_capable = true;
+                       break;
+               }
+       }
        return 0;
 }
 
index 978eca31ceda94a146bc9095221a0205f65325e8..0571b973be80d357bbbe4fec67c0fef0b3859546 100644 (file)
  */
 
 #define E1000_CONNSW_ENRGSRC             0x4
+#define E1000_CONNSW_PHYSD             0x400
+#define E1000_CONNSW_PHY_PDN           0x800
+#define E1000_CONNSW_SERDESD           0x200
+#define E1000_CONNSW_AUTOSENSE_CONF    0x2
+#define E1000_CONNSW_AUTOSENSE_EN      0x1
 #define E1000_PCS_CFG_PCS_EN             8
 #define E1000_PCS_LCTL_FLV_LINK_UP       1
 #define E1000_PCS_LCTL_FSV_100           2
 #define E1000_MDICNFG_PHY_MASK    0x03E00000
 #define E1000_MDICNFG_PHY_SHIFT   21
 
+#define E1000_MEDIA_PORT_COPPER                        1
+#define E1000_MEDIA_PORT_OTHER                 2
+#define E1000_M88E1112_AUTO_COPPER_SGMII       0x2
+#define E1000_M88E1112_AUTO_COPPER_BASEX       0x3
+#define E1000_M88E1112_STATUS_LINK             0x0004 /* Interface Link Bit */
+#define E1000_M88E1112_MAC_CTRL_1              0x10
+#define E1000_M88E1112_MAC_CTRL_1_MODE_MASK    0x0380 /* Mode Select */
+#define E1000_M88E1112_MAC_CTRL_1_MODE_SHIFT   7
+#define E1000_M88E1112_PAGE_ADDR               0x16
+#define E1000_M88E1112_STATUS                  0x01
+
 /* PCI Express Control */
 #define E1000_GCR_CMPL_TMOUT_MASK       0x0000F000
 #define E1000_GCR_CMPL_TMOUT_10ms       0x00001000
index 2e166b22d52b6374e3814a9526d6cad9decfa5a3..ab99e2b582a85c7b445d54ec85f867c431cf1e29 100644 (file)
@@ -533,6 +533,9 @@ struct e1000_dev_spec_82575 {
        bool clear_semaphore_once;
        struct e1000_sfp_flags eth_flags;
        bool module_plugged;
+       u8 media_port;
+       bool media_changed;
+       bool mas_capable;
 };
 
 struct e1000_hw {
index 5e9ed89403aa45adb9238330e4937e8aa1f4cd09..8aaca0a1dca0781566d32788ea44b084f7eeb8a3 100644 (file)
@@ -337,8 +337,10 @@ struct hwmon_attr {
        };
 
 struct hwmon_buff {
-       struct device *device;
-       struct hwmon_attr *hwmon_list;
+       struct attribute_group group;
+       const struct attribute_group *groups[2];
+       struct attribute *attrs[E1000_MAX_SENSORS * 4 + 1];
+       struct hwmon_attr hwmon_list[E1000_MAX_SENSORS * 4];
        unsigned int n_hwmon;
        };
 #endif
@@ -440,7 +442,7 @@ struct igb_adapter {
 
        char fw_version[32];
 #ifdef CONFIG_IGB_HWMON
-       struct hwmon_buff igb_hwmon_buff;
+       struct hwmon_buff *igb_hwmon_buff;
        bool ets;
 #endif
        struct i2c_algo_bit_data i2c_algo;
@@ -450,6 +452,8 @@ struct igb_adapter {
        u8 rss_indir_tbl[IGB_RETA_SIZE];
 
        unsigned long link_check_timeout;
+       int copper_tries;
+       struct e1000_info ei;
 };
 
 #define IGB_FLAG_HAS_MSI               (1 << 0)
@@ -462,6 +466,15 @@ struct igb_adapter {
 #define IGB_FLAG_RSS_FIELD_IPV6_UDP    (1 << 7)
 #define IGB_FLAG_WOL_SUPPORTED         (1 << 8)
 #define IGB_FLAG_NEED_LINK_UPDATE      (1 << 9)
+#define IGB_FLAG_MEDIA_RESET           (1 << 10)
+#define IGB_FLAG_MAS_CAPABLE           (1 << 11)
+#define IGB_FLAG_MAS_ENABLE            (1 << 12)
+
+/* Media Auto Sense */
+#define IGB_MAS_ENABLE_0               0X0001
+#define IGB_MAS_ENABLE_1               0X0002
+#define IGB_MAS_ENABLE_2               0X0004
+#define IGB_MAS_ENABLE_3               0X0008
 
 /* DMA Coalescing defines */
 #define IGB_MIN_TXPBSIZE       20408
index b0f3666b1d7f1c669181a9f62534aa8096baeccc..1c7d2381af8c626e7f5175223597257c323be2ba 100644 (file)
@@ -1983,6 +1983,10 @@ static void igb_diag_test(struct net_device *netdev,
        bool if_running = netif_running(netdev);
 
        set_bit(__IGB_TESTING, &adapter->state);
+
+       /* can't do offline tests on media switching devices */
+       if (adapter->hw.dev_spec._82575.mas_capable)
+               eth_test->flags &= ~ETH_TEST_FL_OFFLINE;
        if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
                /* Offline tests */
 
@@ -2062,14 +2066,15 @@ static void igb_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
 {
        struct igb_adapter *adapter = netdev_priv(netdev);
 
-       wol->supported = WAKE_UCAST | WAKE_MCAST |
-                        WAKE_BCAST | WAKE_MAGIC |
-                        WAKE_PHY;
        wol->wolopts = 0;
 
        if (!(adapter->flags & IGB_FLAG_WOL_SUPPORTED))
                return;
 
+       wol->supported = WAKE_UCAST | WAKE_MCAST |
+                        WAKE_BCAST | WAKE_MAGIC |
+                        WAKE_PHY;
+
        /* apply any specific unsupported masks here */
        switch (adapter->hw.device_id) {
        default:
index 58f1ce967aebfed707ed2986c968654dd49fa829..e0af5bc616139bc6540577952175345053399dd1 100644 (file)
@@ -117,29 +117,29 @@ static int igb_add_hwmon_attr(struct igb_adapter *adapter,
        unsigned int n_attr;
        struct hwmon_attr *igb_attr;
 
-       n_attr = adapter->igb_hwmon_buff.n_hwmon;
-       igb_attr = &adapter->igb_hwmon_buff.hwmon_list[n_attr];
+       n_attr = adapter->igb_hwmon_buff->n_hwmon;
+       igb_attr = &adapter->igb_hwmon_buff->hwmon_list[n_attr];
 
        switch (type) {
        case IGB_HWMON_TYPE_LOC:
                igb_attr->dev_attr.show = igb_hwmon_show_location;
                snprintf(igb_attr->name, sizeof(igb_attr->name),
-                        "temp%u_label", offset);
+                        "temp%u_label", offset + 1);
                break;
        case IGB_HWMON_TYPE_TEMP:
                igb_attr->dev_attr.show = igb_hwmon_show_temp;
                snprintf(igb_attr->name, sizeof(igb_attr->name),
-                        "temp%u_input", offset);
+                        "temp%u_input", offset + 1);
                break;
        case IGB_HWMON_TYPE_CAUTION:
                igb_attr->dev_attr.show = igb_hwmon_show_cautionthresh;
                snprintf(igb_attr->name, sizeof(igb_attr->name),
-                        "temp%u_max", offset);
+                        "temp%u_max", offset + 1);
                break;
        case IGB_HWMON_TYPE_MAX:
                igb_attr->dev_attr.show = igb_hwmon_show_maxopthresh;
                snprintf(igb_attr->name, sizeof(igb_attr->name),
-                        "temp%u_crit", offset);
+                        "temp%u_crit", offset + 1);
                break;
        default:
                rc = -EPERM;
@@ -154,30 +154,16 @@ static int igb_add_hwmon_attr(struct igb_adapter *adapter,
        igb_attr->dev_attr.attr.mode = S_IRUGO;
        igb_attr->dev_attr.attr.name = igb_attr->name;
        sysfs_attr_init(&igb_attr->dev_attr.attr);
-       rc = device_create_file(&adapter->pdev->dev,
-                               &igb_attr->dev_attr);
-       if (rc == 0)
-               ++adapter->igb_hwmon_buff.n_hwmon;
 
-       return rc;
+       adapter->igb_hwmon_buff->attrs[n_attr] = &igb_attr->dev_attr.attr;
+
+       ++adapter->igb_hwmon_buff->n_hwmon;
+
+       return 0;
 }
 
 static void igb_sysfs_del_adapter(struct igb_adapter *adapter)
 {
-       int i;
-
-       if (adapter == NULL)
-               return;
-
-       for (i = 0; i < adapter->igb_hwmon_buff.n_hwmon; i++) {
-               device_remove_file(&adapter->pdev->dev,
-                          &adapter->igb_hwmon_buff.hwmon_list[i].dev_attr);
-       }
-
-       kfree(adapter->igb_hwmon_buff.hwmon_list);
-
-       if (adapter->igb_hwmon_buff.device)
-               hwmon_device_unregister(adapter->igb_hwmon_buff.device);
 }
 
 /* called from igb_main.c */
@@ -189,11 +175,11 @@ void igb_sysfs_exit(struct igb_adapter *adapter)
 /* called from igb_main.c */
 int igb_sysfs_init(struct igb_adapter *adapter)
 {
-       struct hwmon_buff *igb_hwmon = &adapter->igb_hwmon_buff;
+       struct hwmon_buff *igb_hwmon;
+       struct i2c_client *client;
+       struct device *hwmon_dev;
        unsigned int i;
-       int n_attrs;
        int rc = 0;
-       struct i2c_client *client = NULL;
 
        /* If this method isn't defined we don't support thermals */
        if (adapter->hw.mac.ops.init_thermal_sensor_thresh == NULL)
@@ -201,34 +187,16 @@ int igb_sysfs_init(struct igb_adapter *adapter)
 
        /* Don't create thermal hwmon interface if no sensors present */
        rc = (adapter->hw.mac.ops.init_thermal_sensor_thresh(&adapter->hw));
-               if (rc)
-                       goto exit;
-
-       /* init i2c_client */
-       client = i2c_new_device(&adapter->i2c_adap, &i350_sensor_info);
-       if (client == NULL) {
-               dev_info(&adapter->pdev->dev,
-                       "Failed to create new i2c device..\n");
+       if (rc)
                goto exit;
-       }
-       adapter->i2c_client = client;
 
-       /* Allocation space for max attributes
-        * max num sensors * values (loc, temp, max, caution)
-        */
-       n_attrs = E1000_MAX_SENSORS * 4;
-       igb_hwmon->hwmon_list = kcalloc(n_attrs, sizeof(struct hwmon_attr),
-                                       GFP_KERNEL);
-       if (!igb_hwmon->hwmon_list) {
+       igb_hwmon = devm_kzalloc(&adapter->pdev->dev, sizeof(*igb_hwmon),
+                                GFP_KERNEL);
+       if (!igb_hwmon) {
                rc = -ENOMEM;
-               goto err;
-       }
-
-       igb_hwmon->device = hwmon_device_register(&adapter->pdev->dev);
-       if (IS_ERR(igb_hwmon->device)) {
-               rc = PTR_ERR(igb_hwmon->device);
-               goto err;
+               goto exit;
        }
+       adapter->igb_hwmon_buff = igb_hwmon;
 
        for (i = 0; i < E1000_MAX_SENSORS; i++) {
 
@@ -240,11 +208,39 @@ int igb_sysfs_init(struct igb_adapter *adapter)
 
                /* Bail if any hwmon attr struct fails to initialize */
                rc = igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_CAUTION);
-               rc |= igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_LOC);
-               rc |= igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_TEMP);
-               rc |= igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_MAX);
                if (rc)
-                       goto err;
+                       goto exit;
+               rc = igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_LOC);
+               if (rc)
+                       goto exit;
+               rc = igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_TEMP);
+               if (rc)
+                       goto exit;
+               rc = igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_MAX);
+               if (rc)
+                       goto exit;
+       }
+
+       /* init i2c_client */
+       client = i2c_new_device(&adapter->i2c_adap, &i350_sensor_info);
+       if (client == NULL) {
+               dev_info(&adapter->pdev->dev,
+                        "Failed to create new i2c device.\n");
+               rc = -ENODEV;
+               goto exit;
+       }
+       adapter->i2c_client = client;
+
+       igb_hwmon->groups[0] = &igb_hwmon->group;
+       igb_hwmon->group.attrs = igb_hwmon->attrs;
+
+       hwmon_dev = devm_hwmon_device_register_with_groups(&adapter->pdev->dev,
+                                                          client->name,
+                                                          igb_hwmon,
+                                                          igb_hwmon->groups);
+       if (IS_ERR(hwmon_dev)) {
+               rc = PTR_ERR(hwmon_dev);
+               goto err;
        }
 
        goto exit;
index 025e5f4b7481d680f6b2dff0491a857615af250b..3bc10bd5bbc199ef3ade30d5ec28dea7b683392e 100644 (file)
@@ -1606,6 +1606,73 @@ static void igb_power_down_link(struct igb_adapter *adapter)
                igb_shutdown_serdes_link_82575(&adapter->hw);
 }
 
+/**
+ * Detect and switch function for Media Auto Sense
+ * @adapter: address of the board private structure
+ **/
+static void igb_check_swap_media(struct igb_adapter *adapter)
+{
+       struct e1000_hw *hw = &adapter->hw;
+       u32 ctrl_ext, connsw;
+       bool swap_now = false;
+
+       ctrl_ext = rd32(E1000_CTRL_EXT);
+       connsw = rd32(E1000_CONNSW);
+
+       /* need to live swap if current media is copper and we have fiber/serdes
+        * to go to.
+        */
+
+       if ((hw->phy.media_type == e1000_media_type_copper) &&
+           (!(connsw & E1000_CONNSW_AUTOSENSE_EN))) {
+               swap_now = true;
+       } else if (!(connsw & E1000_CONNSW_SERDESD)) {
+               /* copper signal takes time to appear */
+               if (adapter->copper_tries < 4) {
+                       adapter->copper_tries++;
+                       connsw |= E1000_CONNSW_AUTOSENSE_CONF;
+                       wr32(E1000_CONNSW, connsw);
+                       return;
+               } else {
+                       adapter->copper_tries = 0;
+                       if ((connsw & E1000_CONNSW_PHYSD) &&
+                           (!(connsw & E1000_CONNSW_PHY_PDN))) {
+                               swap_now = true;
+                               connsw &= ~E1000_CONNSW_AUTOSENSE_CONF;
+                               wr32(E1000_CONNSW, connsw);
+                       }
+               }
+       }
+
+       if (!swap_now)
+               return;
+
+       switch (hw->phy.media_type) {
+       case e1000_media_type_copper:
+               netdev_info(adapter->netdev,
+                       "MAS: changing media to fiber/serdes\n");
+               ctrl_ext |=
+                       E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES;
+               adapter->flags |= IGB_FLAG_MEDIA_RESET;
+               adapter->copper_tries = 0;
+               break;
+       case e1000_media_type_internal_serdes:
+       case e1000_media_type_fiber:
+               netdev_info(adapter->netdev,
+                       "MAS: changing media to copper\n");
+               ctrl_ext &=
+                       ~E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES;
+               adapter->flags |= IGB_FLAG_MEDIA_RESET;
+               break;
+       default:
+               /* shouldn't get here during regular operation */
+               netdev_err(adapter->netdev,
+                       "AMS: Invalid media type found, returning\n");
+               break;
+       }
+       wr32(E1000_CTRL_EXT, ctrl_ext);
+}
+
 /**
  *  igb_up - Open the interface and prepare it to handle traffic
  *  @adapter: board private structure
@@ -1719,6 +1786,37 @@ void igb_reinit_locked(struct igb_adapter *adapter)
        clear_bit(__IGB_RESETTING, &adapter->state);
 }
 
+/** igb_enable_mas - Media Autosense re-enable after swap
+ *
+ * @adapter: adapter struct
+ **/
+static s32 igb_enable_mas(struct igb_adapter *adapter)
+{
+       struct e1000_hw *hw = &adapter->hw;
+       u32 connsw;
+       s32 ret_val = 0;
+
+       connsw = rd32(E1000_CONNSW);
+       if (!(hw->phy.media_type == e1000_media_type_copper))
+               return ret_val;
+
+       /* configure for SerDes media detect */
+       if (!(connsw & E1000_CONNSW_SERDESD)) {
+               connsw |= E1000_CONNSW_ENRGSRC;
+               connsw |= E1000_CONNSW_AUTOSENSE_EN;
+               wr32(E1000_CONNSW, connsw);
+               wrfl();
+       } else if (connsw & E1000_CONNSW_SERDESD) {
+               /* already SerDes, no need to enable anything */
+               return ret_val;
+       } else {
+               netdev_info(adapter->netdev,
+                       "MAS: Unable to configure feature, disabling..\n");
+               adapter->flags &= ~IGB_FLAG_MAS_ENABLE;
+       }
+       return ret_val;
+}
+
 void igb_reset(struct igb_adapter *adapter)
 {
        struct pci_dev *pdev = adapter->pdev;
@@ -1830,6 +1928,16 @@ void igb_reset(struct igb_adapter *adapter)
        hw->mac.ops.reset_hw(hw);
        wr32(E1000_WUC, 0);
 
+       if (adapter->flags & IGB_FLAG_MEDIA_RESET) {
+               /* need to resetup here after media swap */
+               adapter->ei.get_invariants(hw);
+               adapter->flags &= ~IGB_FLAG_MEDIA_RESET;
+       }
+       if (adapter->flags & IGB_FLAG_MAS_ENABLE) {
+               if (igb_enable_mas(adapter))
+                       dev_err(&pdev->dev,
+                               "Error enabling Media Auto Sense\n");
+       }
        if (hw->mac.ops.init_hw(hw))
                dev_err(&pdev->dev, "Hardware Error\n");
 
@@ -1975,6 +2083,58 @@ void igb_set_fw_version(struct igb_adapter *adapter)
        return;
 }
 
+/**
+ * igb_init_mas - init Media Autosense feature if enabled in the NVM
+ *
+ * @adapter: adapter struct
+ **/
+static void igb_init_mas(struct igb_adapter *adapter)
+{
+       struct e1000_hw *hw = &adapter->hw;
+       u16 eeprom_data;
+
+       hw->nvm.ops.read(hw, NVM_COMPAT, 1, &eeprom_data);
+       switch (hw->bus.func) {
+       case E1000_FUNC_0:
+               if (eeprom_data & IGB_MAS_ENABLE_0) {
+                       adapter->flags |= IGB_FLAG_MAS_ENABLE;
+                       netdev_info(adapter->netdev,
+                               "MAS: Enabling Media Autosense for port %d\n",
+                               hw->bus.func);
+               }
+               break;
+       case E1000_FUNC_1:
+               if (eeprom_data & IGB_MAS_ENABLE_1) {
+                       adapter->flags |= IGB_FLAG_MAS_ENABLE;
+                       netdev_info(adapter->netdev,
+                               "MAS: Enabling Media Autosense for port %d\n",
+                               hw->bus.func);
+               }
+               break;
+       case E1000_FUNC_2:
+               if (eeprom_data & IGB_MAS_ENABLE_2) {
+                       adapter->flags |= IGB_FLAG_MAS_ENABLE;
+                       netdev_info(adapter->netdev,
+                               "MAS: Enabling Media Autosense for port %d\n",
+                               hw->bus.func);
+               }
+               break;
+       case E1000_FUNC_3:
+               if (eeprom_data & IGB_MAS_ENABLE_3) {
+                       adapter->flags |= IGB_FLAG_MAS_ENABLE;
+                       netdev_info(adapter->netdev,
+                               "MAS: Enabling Media Autosense for port %d\n",
+                               hw->bus.func);
+               }
+               break;
+       default:
+               /* Shouldn't get here */
+               netdev_err(adapter->netdev,
+                       "MAS: Invalid port configuration, returning\n");
+               break;
+       }
+}
+
 /**
  *  igb_init_i2c - Init I2C interface
  *  @adapter: pointer to adapter structure
@@ -2022,7 +2182,6 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        s32 ret_val;
        static int global_quad_port_a; /* global quad port a indication */
        const struct e1000_info *ei = igb_info_tbl[ent->driver_data];
-       unsigned long mmio_start, mmio_len;
        int err, pci_using_dac;
        u8 part_str[E1000_PBANUM_LENGTH];
 
@@ -2079,11 +2238,8 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        hw->back = adapter;
        adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
 
-       mmio_start = pci_resource_start(pdev, 0);
-       mmio_len = pci_resource_len(pdev, 0);
-
        err = -EIO;
-       hw->hw_addr = ioremap(mmio_start, mmio_len);
+       hw->hw_addr = pci_iomap(pdev, 0, 0);
        if (!hw->hw_addr)
                goto err_ioremap;
 
@@ -2093,8 +2249,8 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
 
-       netdev->mem_start = mmio_start;
-       netdev->mem_end = mmio_start + mmio_len;
+       netdev->mem_start = pci_resource_start(pdev, 0);
+       netdev->mem_end = pci_resource_end(pdev, 0);
 
        /* PCI config space info */
        hw->vendor_id = pdev->vendor;
@@ -2350,6 +2506,11 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                adapter->ets = false;
        }
 #endif
+       /* Check if Media Autosense is enabled */
+       adapter->ei = *ei;
+       if (hw->dev_spec._82575.mas_capable)
+               igb_init_mas(adapter);
+
        /* do hw tstamp init after resetting */
        igb_ptp_init(adapter);
 
@@ -3935,6 +4096,7 @@ static void igb_watchdog_task(struct work_struct *work)
        struct net_device *netdev = adapter->netdev;
        u32 link;
        int i;
+       u32 connsw;
 
        link = igb_has_link(adapter);
 
@@ -3945,7 +4107,21 @@ static void igb_watchdog_task(struct work_struct *work)
                        link = false;
        }
 
+       /* Force link down if we have fiber to swap to */
+       if (adapter->flags & IGB_FLAG_MAS_ENABLE) {
+               if (hw->phy.media_type == e1000_media_type_copper) {
+                       connsw = rd32(E1000_CONNSW);
+                       if (!(connsw & E1000_CONNSW_AUTOSENSE_EN))
+                               link = 0;
+               }
+       }
        if (link) {
+               /* Perform a reset if the media type changed. */
+               if (hw->dev_spec._82575.media_changed) {
+                       hw->dev_spec._82575.media_changed = false;
+                       adapter->flags |= IGB_FLAG_MEDIA_RESET;
+                       igb_reset(adapter);
+               }
                /* Cancel scheduled suspend requests. */
                pm_runtime_resume(netdev->dev.parent);
 
@@ -4026,8 +4202,27 @@ static void igb_watchdog_task(struct work_struct *work)
                                mod_timer(&adapter->phy_info_timer,
                                          round_jiffies(jiffies + 2 * HZ));
 
+                       /* link is down, time to check for alternate media */
+                       if (adapter->flags & IGB_FLAG_MAS_ENABLE) {
+                               igb_check_swap_media(adapter);
+                               if (adapter->flags & IGB_FLAG_MEDIA_RESET) {
+                                       schedule_work(&adapter->reset_task);
+                                       /* return immediately */
+                                       return;
+                               }
+                       }
                        pm_schedule_suspend(netdev->dev.parent,
                                            MSEC_PER_SEC * 5);
+
+               /* also check for alternate media here */
+               } else if (!netif_carrier_ok(netdev) &&
+                          (adapter->flags & IGB_FLAG_MAS_ENABLE)) {
+                       igb_check_swap_media(adapter);
+                       if (adapter->flags & IGB_FLAG_MEDIA_RESET) {
+                               schedule_work(&adapter->reset_task);
+                               /* return immediately */
+                               return;
+                       }
                }
        }
 
index 0c55079ebee37c03d0a5a9a5cbdc6681d78c19a9..cc06854296a379a6f5d1fac21ecf9412d94d477b 100644 (file)
@@ -4251,8 +4251,8 @@ static void ixgbe_disable_fwd_ring(struct ixgbe_fwd_adapter *vadapter,
        rx_ring->l2_accel_priv = NULL;
 }
 
-int ixgbe_fwd_ring_down(struct net_device *vdev,
-                       struct ixgbe_fwd_adapter *accel)
+static int ixgbe_fwd_ring_down(struct net_device *vdev,
+                              struct ixgbe_fwd_adapter *accel)
 {
        struct ixgbe_adapter *adapter = accel->real_adapter;
        unsigned int rxbase = accel->rx_base_queue;
@@ -7986,10 +7986,9 @@ skip_sriov:
                           NETIF_F_TSO |
                           NETIF_F_TSO6 |
                           NETIF_F_RXHASH |
-                          NETIF_F_RXCSUM |
-                          NETIF_F_HW_L2FW_DOFFLOAD;
+                          NETIF_F_RXCSUM;
 
-       netdev->hw_features = netdev->features;
+       netdev->hw_features = netdev->features | NETIF_F_HW_L2FW_DOFFLOAD;
 
        switch (adapter->hw.mac.type) {
        case ixgbe_mac_82599EB:
index e4c676006be97db79d3208607f36bb503bdaecaa..39217e5ff7dcd74ddcfc49c7e33e43ec2633c515 100644 (file)
@@ -46,6 +46,7 @@ static bool ixgbe_get_i2c_data(u32 *i2cctl);
 static void ixgbe_i2c_bus_clear(struct ixgbe_hw *hw);
 static enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id);
 static s32 ixgbe_get_phy_id(struct ixgbe_hw *hw);
+static s32 ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw);
 
 /**
  *  ixgbe_identify_phy_generic - Get physical layer module
@@ -1164,7 +1165,7 @@ err_read_i2c_eeprom:
  *
  * Searches for and identifies the QSFP module and assigns appropriate PHY type
  **/
-s32 ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw)
+static s32 ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw)
 {
        struct ixgbe_adapter *adapter = hw->back;
        s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
index aae900a256da98601a501a121eed1f14347d3997..fffcbdd2bf0e49ab129abf04cd16a650a4d5cb91 100644 (file)
@@ -145,7 +145,6 @@ s32 ixgbe_get_phy_firmware_version_generic(struct ixgbe_hw *hw,
 s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw);
 s32 ixgbe_identify_module_generic(struct ixgbe_hw *hw);
 s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw);
-s32 ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw);
 s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw,
                                         u16 *list_offset,
                                         u16 *data_offset);
index 8971e2d0a984d74055b788742190f9654fb5ac13..eaaa3ecacfd7d338abd723c0f2826b685feb19f7 100644 (file)
@@ -86,9 +86,7 @@ struct ixgbevf_ring {
        u64 bp_misses;
        u64 bp_cleaned;
 #endif
-
-       u16 head;
-       u16 tail;
+       u8 __iomem *tail;
 
        u16 reg_idx; /* holds the special value that gets the hardware register
                      * offset associated with this ring, which is different
index 92ef4cb5a8e8e1f3d4de0e457399861ab2d1b8bf..84b55fe71546ef3526d55ee6b4a1c70d7dddd376 100644 (file)
@@ -98,10 +98,11 @@ MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
 static void ixgbevf_set_itr(struct ixgbevf_q_vector *q_vector);
 static void ixgbevf_free_all_rx_resources(struct ixgbevf_adapter *adapter);
 
-static inline void ixgbevf_release_rx_desc(struct ixgbe_hw *hw,
-                                          struct ixgbevf_ring *rx_ring,
+static inline void ixgbevf_release_rx_desc(struct ixgbevf_ring *rx_ring,
                                           u32 val)
 {
+       rx_ring->next_to_use = val;
+
        /*
         * Force memory writes to complete before letting h/w
         * know there are new descriptors to fetch.  (Only
@@ -109,7 +110,7 @@ static inline void ixgbevf_release_rx_desc(struct ixgbe_hw *hw,
         * such as IA-64).
         */
        wmb();
-       IXGBE_WRITE_REG(hw, IXGBE_VFRDT(rx_ring->reg_idx), val);
+       writel(val, rx_ring->tail);
 }
 
 /**
@@ -406,10 +407,8 @@ static void ixgbevf_alloc_rx_buffers(struct ixgbevf_adapter *adapter,
        }
 
 no_buffers:
-       if (rx_ring->next_to_use != i) {
-               rx_ring->next_to_use = i;
-               ixgbevf_release_rx_desc(&adapter->hw, rx_ring, i);
-       }
+       if (rx_ring->next_to_use != i)
+               ixgbevf_release_rx_desc(rx_ring, i);
 }
 
 static inline void ixgbevf_irq_enable_queues(struct ixgbevf_adapter *adapter,
@@ -1110,8 +1109,9 @@ static void ixgbevf_configure_tx(struct ixgbevf_adapter *adapter)
                IXGBE_WRITE_REG(hw, IXGBE_VFTDLEN(j), tdlen);
                IXGBE_WRITE_REG(hw, IXGBE_VFTDH(j), 0);
                IXGBE_WRITE_REG(hw, IXGBE_VFTDT(j), 0);
-               adapter->tx_ring[i].head = IXGBE_VFTDH(j);
-               adapter->tx_ring[i].tail = IXGBE_VFTDT(j);
+               ring->tail = hw->hw_addr + IXGBE_VFTDT(j);
+               ring->next_to_clean = 0;
+               ring->next_to_use = 0;
                /* Disable Tx Head Writeback RO bit, since this hoses
                 * bookkeeping if things aren't delivered in order.
                 */
@@ -1208,20 +1208,22 @@ static void ixgbevf_configure_rx(struct ixgbevf_adapter *adapter)
        /* set_rx_buffer_len must be called before ring initialization */
        ixgbevf_set_rx_buffer_len(adapter);
 
-       rdlen = adapter->rx_ring[0].count * sizeof(union ixgbe_adv_rx_desc);
        /* Setup the HW Rx Head and Tail Descriptor Pointers and
         * the Base and Length of the Rx Descriptor Ring */
        for (i = 0; i < adapter->num_rx_queues; i++) {
-               rdba = adapter->rx_ring[i].dma;
-               j = adapter->rx_ring[i].reg_idx;
+               struct ixgbevf_ring *ring = &adapter->rx_ring[i];
+               rdba = ring->dma;
+               j = ring->reg_idx;
+               rdlen = ring->count * sizeof(union ixgbe_adv_rx_desc);
                IXGBE_WRITE_REG(hw, IXGBE_VFRDBAL(j),
                                (rdba & DMA_BIT_MASK(32)));
                IXGBE_WRITE_REG(hw, IXGBE_VFRDBAH(j), (rdba >> 32));
                IXGBE_WRITE_REG(hw, IXGBE_VFRDLEN(j), rdlen);
                IXGBE_WRITE_REG(hw, IXGBE_VFRDH(j), 0);
                IXGBE_WRITE_REG(hw, IXGBE_VFRDT(j), 0);
-               adapter->rx_ring[i].head = IXGBE_VFRDH(j);
-               adapter->rx_ring[i].tail = IXGBE_VFRDT(j);
+               ring->tail = hw->hw_addr + IXGBE_VFRDT(j);
+               ring->next_to_clean = 0;
+               ring->next_to_use = 0;
 
                ixgbevf_configure_srrctl(adapter, j);
        }
@@ -1402,7 +1404,7 @@ static void ixgbevf_rx_desc_queue_enable(struct ixgbevf_adapter *adapter,
                hw_dbg(hw, "RXDCTL.ENABLE queue %d not set while polling\n",
                       rxr);
 
-       ixgbevf_release_rx_desc(&adapter->hw, &adapter->rx_ring[rxr],
+       ixgbevf_release_rx_desc(&adapter->rx_ring[rxr],
                                (adapter->rx_ring[rxr].count - 1));
 }
 
@@ -1680,14 +1682,6 @@ static void ixgbevf_clean_rx_ring(struct ixgbevf_adapter *adapter,
 
        /* Zero out the descriptor ring */
        memset(rx_ring->desc, 0, rx_ring->size);
-
-       rx_ring->next_to_clean = 0;
-       rx_ring->next_to_use = 0;
-
-       if (rx_ring->head)
-               writel(0, adapter->hw.hw_addr + rx_ring->head);
-       if (rx_ring->tail)
-               writel(0, adapter->hw.hw_addr + rx_ring->tail);
 }
 
 /**
@@ -1715,14 +1709,6 @@ static void ixgbevf_clean_tx_ring(struct ixgbevf_adapter *adapter,
        memset(tx_ring->tx_buffer_info, 0, size);
 
        memset(tx_ring->desc, 0, tx_ring->size);
-
-       tx_ring->next_to_use = 0;
-       tx_ring->next_to_clean = 0;
-
-       if (tx_ring->head)
-               writel(0, adapter->hw.hw_addr + tx_ring->head);
-       if (tx_ring->tail)
-               writel(0, adapter->hw.hw_addr + tx_ring->tail);
 }
 
 /**
@@ -2473,8 +2459,6 @@ int ixgbevf_setup_tx_resources(struct ixgbevf_adapter *adapter,
        if (!tx_ring->desc)
                goto err;
 
-       tx_ring->next_to_use = 0;
-       tx_ring->next_to_clean = 0;
        return 0;
 
 err:
@@ -2542,9 +2526,6 @@ int ixgbevf_setup_rx_resources(struct ixgbevf_adapter *adapter,
                goto alloc_failed;
        }
 
-       rx_ring->next_to_clean = 0;
-       rx_ring->next_to_use = 0;
-
        return 0;
 alloc_failed:
        return -ENOMEM;
@@ -3181,7 +3162,7 @@ static int ixgbevf_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
                         ixgbevf_tx_map(tx_ring, skb, tx_flags),
                         first, skb->len, hdr_len);
 
-       writel(tx_ring->next_to_use, adapter->hw.hw_addr + tx_ring->tail);
+       writel(tx_ring->next_to_use, tx_ring->tail);
 
        ixgbevf_maybe_stop_tx(tx_ring, DESC_NEEDED);
 
index 6a6c1f76d8e04406b1c6de12820a48a7d27337fd..974a007c427727d0799fc74eba161d7757b333d0 100644 (file)
@@ -9,8 +9,7 @@
  *   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.
+ *   along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  *   Copyright (C) 2011 John Crispin <blogic@openwrt.org>
  */
index 61088a6a94245144f46fa42e92fdce9eb07f1599..b3d9327f78b9124cdd297fdbdb8d02bacbbbe335 100644 (file)
@@ -33,8 +33,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -2067,23 +2066,6 @@ static inline void oom_timer_wrapper(unsigned long data)
        napi_schedule(&mp->napi);
 }
 
-static void phy_reset(struct mv643xx_eth_private *mp)
-{
-       int data;
-
-       data = phy_read(mp->phy, MII_BMCR);
-       if (data < 0)
-               return;
-
-       data |= BMCR_RESET;
-       if (phy_write(mp->phy, MII_BMCR, data) < 0)
-               return;
-
-       do {
-               data = phy_read(mp->phy, MII_BMCR);
-       } while (data >= 0 && data & BMCR_RESET);
-}
-
 static void port_start(struct mv643xx_eth_private *mp)
 {
        u32 pscr;
@@ -2096,7 +2078,7 @@ static void port_start(struct mv643xx_eth_private *mp)
                struct ethtool_cmd cmd;
 
                mv643xx_eth_get_settings(mp->dev, &cmd);
-               phy_reset(mp);
+               phy_init_hw(mp->phy);
                mv643xx_eth_set_settings(mp->dev, &cmd);
        }
 
@@ -2764,8 +2746,6 @@ static void phy_init(struct mv643xx_eth_private *mp, int speed, int duplex)
 {
        struct phy_device *phy = mp->phy;
 
-       phy_reset(mp);
-
        if (speed == 0) {
                phy->autoneg = AUTONEG_ENABLE;
                phy->speed = 0;
index b8e232b4ea2da88aca164039f81f1852ba9f779e..d5f0d72e5e331792bb8a0078078627df66a83fb5 100644 (file)
@@ -1378,7 +1378,7 @@ static void mvneta_rxq_drop_pkts(struct mvneta_port *pp,
 
                dev_kfree_skb_any(skb);
                dma_unmap_single(pp->dev->dev.parent, rx_desc->buf_phys_addr,
-                                rx_desc->data_size, DMA_FROM_DEVICE);
+                                MVNETA_RX_BUF_SIZE(pp->pkt_size), DMA_FROM_DEVICE);
        }
 
        if (rx_done)
@@ -1424,7 +1424,7 @@ static int mvneta_rx(struct mvneta_port *pp, int rx_todo,
                }
 
                dma_unmap_single(pp->dev->dev.parent, rx_desc->buf_phys_addr,
-                                rx_desc->data_size, DMA_FROM_DEVICE);
+                                MVNETA_RX_BUF_SIZE(pp->pkt_size), DMA_FROM_DEVICE);
 
                rx_bytes = rx_desc->data_size -
                        (ETH_FCS_LEN + MVNETA_MH_SIZE);
index fff62460185c3ea26572a4cf7c9aa2bfe28bfb72..452e81de33dec96df01095cc66286008ffc56c00 100644 (file)
@@ -19,8 +19,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/init.h>
@@ -321,23 +320,6 @@ static void ethernet_phy_set_addr(struct pxa168_eth_private *pep, int phy_addr)
        wrl(pep, PHY_ADDRESS, reg_data);
 }
 
-static void ethernet_phy_reset(struct pxa168_eth_private *pep)
-{
-       int data;
-
-       data = phy_read(pep->phy, MII_BMCR);
-       if (data < 0)
-               return;
-
-       data |= BMCR_RESET;
-       if (phy_write(pep->phy, MII_BMCR, data) < 0)
-               return;
-
-       do {
-               data = phy_read(pep->phy, MII_BMCR);
-       } while (data >= 0 && data & BMCR_RESET);
-}
-
 static void rxq_refill(struct net_device *dev)
 {
        struct pxa168_eth_private *pep = netdev_priv(dev);
@@ -646,7 +628,7 @@ static void eth_port_start(struct net_device *dev)
                struct ethtool_cmd cmd;
 
                pxa168_get_settings(pep->dev, &cmd);
-               ethernet_phy_reset(pep);
+               phy_init_hw(pep->phy);
                pxa168_set_settings(pep->dev, &cmd);
        }
 
@@ -1383,7 +1365,6 @@ static struct phy_device *phy_scan(struct pxa168_eth_private *pep, int phy_addr)
 static void phy_init(struct pxa168_eth_private *pep, int speed, int duplex)
 {
        struct phy_device *phy = pep->phy;
-       ethernet_phy_reset(pep);
 
        phy_attach(pep->dev, dev_name(&phy->dev), PHY_INTERFACE_MODE_MII);
 
index 06fef5b44f7747d3b3f6df534130686fd723e4a2..c3ad464d0627b3291b100ad692d18406ad79d1c7 100644 (file)
@@ -71,9 +71,9 @@ u32 mlx4_bitmap_alloc(struct mlx4_bitmap *bitmap)
        return obj;
 }
 
-void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj)
+void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj, int use_rr)
 {
-       mlx4_bitmap_free_range(bitmap, obj, 1);
+       mlx4_bitmap_free_range(bitmap, obj, 1, use_rr);
 }
 
 u32 mlx4_bitmap_alloc_range(struct mlx4_bitmap *bitmap, int cnt, int align)
@@ -118,11 +118,17 @@ u32 mlx4_bitmap_avail(struct mlx4_bitmap *bitmap)
        return bitmap->avail;
 }
 
-void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt)
+void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt,
+                           int use_rr)
 {
        obj &= bitmap->max + bitmap->reserved_top - 1;
 
        spin_lock(&bitmap->lock);
+       if (!use_rr) {
+               bitmap->last = min(bitmap->last, obj);
+               bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top)
+                               & bitmap->mask;
+       }
        bitmap_clear(bitmap->table, obj, cnt);
        bitmap->avail += cnt;
        spin_unlock(&bitmap->lock);
index 22fcbe78311ca50892d5ae6a0a69c4bbeff75196..34c5b87a1c2af0857709767bc0746d1ce18fb3a2 100644 (file)
@@ -187,7 +187,7 @@ err_put:
        mlx4_table_put(dev, &cq_table->table, *cqn);
 
 err_out:
-       mlx4_bitmap_free(&cq_table->bitmap, *cqn);
+       mlx4_bitmap_free(&cq_table->bitmap, *cqn, MLX4_NO_RR);
        return err;
 }
 
@@ -217,7 +217,7 @@ void __mlx4_cq_free_icm(struct mlx4_dev *dev, int cqn)
 
        mlx4_table_put(dev, &cq_table->cmpt_table, cqn);
        mlx4_table_put(dev, &cq_table->table, cqn);
-       mlx4_bitmap_free(&cq_table->bitmap, cqn);
+       mlx4_bitmap_free(&cq_table->bitmap, cqn, MLX4_NO_RR);
 }
 
 static void mlx4_cq_free_icm(struct mlx4_dev *dev, int cqn)
index e72d8a112a6bdc03e3d1f33763e8134b19f92d99..709e5ec5ce14db599aec1cd8535852a0e6d3a0fd 100644 (file)
@@ -2025,7 +2025,7 @@ static int mlx4_en_change_mtu(struct net_device *dev, int new_mtu)
        return 0;
 }
 
-static int mlx4_en_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
+static int mlx4_en_hwtstamp_set(struct net_device *dev, struct ifreq *ifr)
 {
        struct mlx4_en_priv *priv = netdev_priv(dev);
        struct mlx4_en_dev *mdev = priv->mdev;
@@ -2084,11 +2084,21 @@ static int mlx4_en_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
                            sizeof(config)) ? -EFAULT : 0;
 }
 
+static int mlx4_en_hwtstamp_get(struct net_device *dev, struct ifreq *ifr)
+{
+       struct mlx4_en_priv *priv = netdev_priv(dev);
+
+       return copy_to_user(ifr->ifr_data, &priv->hwtstamp_config,
+                           sizeof(priv->hwtstamp_config)) ? -EFAULT : 0;
+}
+
 static int mlx4_en_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
        switch (cmd) {
        case SIOCSHWTSTAMP:
-               return mlx4_en_hwtstamp_ioctl(dev, ifr);
+               return mlx4_en_hwtstamp_set(dev, ifr);
+       case SIOCGHWTSTAMP:
+               return mlx4_en_hwtstamp_get(dev, ifr);
        default:
                return -EOPNOTSUPP;
        }
index 40626690e8a8679d9812d4edee4ede897ec55a2a..c11d063473e5f9aaa162aacd32b4cac386d53464 100644 (file)
@@ -140,7 +140,6 @@ void mlx4_en_ex_selftest(struct net_device *dev, u32 *flags, u64 *buf)
 {
        struct mlx4_en_priv *priv = netdev_priv(dev);
        struct mlx4_en_dev *mdev = priv->mdev;
-       struct mlx4_en_tx_ring *tx_ring;
        int i, carrier_ok;
 
        memset(buf, 0, sizeof(u64) * MLX4_EN_NUM_SELF_TEST);
@@ -150,16 +149,10 @@ void mlx4_en_ex_selftest(struct net_device *dev, u32 *flags, u64 *buf)
                carrier_ok = netif_carrier_ok(dev);
 
                netif_carrier_off(dev);
-retry_tx:
                /* Wait until all tx queues are empty.
                 * there should not be any additional incoming traffic
                 * since we turned the carrier off */
                msleep(200);
-               for (i = 0; i < priv->tx_ring_num && carrier_ok; i++) {
-                       tx_ring = priv->tx_ring[i];
-                       if (tx_ring->prod != (tx_ring->cons + tx_ring->last_nr_txbb))
-                               goto retry_tx;
-               }
 
                if (priv->mdev->dev->caps.flags &
                                        MLX4_DEV_CAP_FLAG_UC_LOOPBACK) {
index c9cdb2a2c596e889ec5f2ae67a3b8912e0f687eb..ae5212f8f09098d9139fd0ea2869f8ad227461bf 100644 (file)
@@ -963,7 +963,7 @@ err_out_free_mtt:
        mlx4_mtt_cleanup(dev, &eq->mtt);
 
 err_out_free_eq:
-       mlx4_bitmap_free(&priv->eq_table.bitmap, eq->eqn);
+       mlx4_bitmap_free(&priv->eq_table.bitmap, eq->eqn, MLX4_USE_RR);
 
 err_out_free_pages:
        for (i = 0; i < npages; ++i)
@@ -1018,7 +1018,7 @@ static void mlx4_free_eq(struct mlx4_dev *dev,
                                    eq->page_list[i].map);
 
        kfree(eq->page_list);
-       mlx4_bitmap_free(&priv->eq_table.bitmap, eq->eqn);
+       mlx4_bitmap_free(&priv->eq_table.bitmap, eq->eqn, MLX4_USE_RR);
        mlx4_free_cmd_mailbox(dev, mailbox);
 }
 
index 5789ea2c934d4aaa15218bdaea2d565f42a82b41..b37478db9851b11710b570b0e7e5c2e50257b4a8 100644 (file)
@@ -1654,7 +1654,7 @@ EXPORT_SYMBOL_GPL(mlx4_counter_alloc);
 
 void __mlx4_counter_free(struct mlx4_dev *dev, u32 idx)
 {
-       mlx4_bitmap_free(&mlx4_priv(dev)->counters_bitmap, idx);
+       mlx4_bitmap_free(&mlx4_priv(dev)->counters_bitmap, idx, MLX4_USE_RR);
        return;
 }
 
@@ -2635,6 +2635,8 @@ static int __init mlx4_init(void)
                return -ENOMEM;
 
        ret = pci_register_driver(&mlx4_driver);
+       if (ret < 0)
+               destroy_workqueue(mlx4_wq);
        return ret < 0 ? ret : 0;
 }
 
index acf9d5f1f9223fbfa0e4efa1b9d886186a12c0cf..40594055b83194f8d18b73e056a5e561603fe9f4 100644 (file)
@@ -996,7 +996,7 @@ out:
                                  index, dev->caps.num_mgms);
                else
                        mlx4_bitmap_free(&priv->mcg_table.bitmap,
-                                        index - dev->caps.num_mgms);
+                                        index - dev->caps.num_mgms, MLX4_USE_RR);
        }
        mutex_unlock(&priv->mcg_table.mutex);
 
@@ -1087,7 +1087,7 @@ int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
                                          index, amgm_index, dev->caps.num_mgms);
                        else
                                mlx4_bitmap_free(&priv->mcg_table.bitmap,
-                                                amgm_index - dev->caps.num_mgms);
+                                                amgm_index - dev->caps.num_mgms, MLX4_USE_RR);
                }
        } else {
                /* Remove entry from AMGM */
@@ -1107,7 +1107,7 @@ int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
                                  prev, index, dev->caps.num_mgms);
                else
                        mlx4_bitmap_free(&priv->mcg_table.bitmap,
-                                        index - dev->caps.num_mgms);
+                                        index - dev->caps.num_mgms, MLX4_USE_RR);
        }
 
 out:
index e582a41a802baeddba0aa9c68dd79113a1cd236e..6ed9dfa5f05bcbba11a8047d9e165f94fce7d86c 100644 (file)
@@ -783,6 +783,11 @@ enum {
        MLX4_PCI_DEV_FORCE_SENSE_PORT   = 1 << 1,
 };
 
+enum {
+       MLX4_NO_RR      = 0,
+       MLX4_USE_RR     = 1,
+};
+
 struct mlx4_priv {
        struct mlx4_dev         dev;
 
@@ -844,9 +849,10 @@ static inline struct mlx4_priv *mlx4_priv(struct mlx4_dev *dev)
 extern struct workqueue_struct *mlx4_wq;
 
 u32 mlx4_bitmap_alloc(struct mlx4_bitmap *bitmap);
-void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj);
+void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj, int use_rr);
 u32 mlx4_bitmap_alloc_range(struct mlx4_bitmap *bitmap, int cnt, int align);
-void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt);
+void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt,
+                           int use_rr);
 u32 mlx4_bitmap_avail(struct mlx4_bitmap *bitmap);
 int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask,
                     u32 reserved_bot, u32 resetrved_top);
index b3ee9bafff5ecdb9f48a6ff526bd5a2d1912a37d..0558dddd81e5b80066560f1d59482a148b26af50 100644 (file)
@@ -346,7 +346,7 @@ void __mlx4_mpt_release(struct mlx4_dev *dev, u32 index)
 {
        struct mlx4_priv *priv = mlx4_priv(dev);
 
-       mlx4_bitmap_free(&priv->mr_table.mpt_bitmap, index);
+       mlx4_bitmap_free(&priv->mr_table.mpt_bitmap, index, MLX4_NO_RR);
 }
 
 static void mlx4_mpt_release(struct mlx4_dev *dev, u32 index)
index 84cfb40bf4513495d9997625e61d580a25c56d1f..c6af9619ce6d263f5f443211e5ba7d52cdef37f9 100644 (file)
@@ -59,7 +59,7 @@ EXPORT_SYMBOL_GPL(mlx4_pd_alloc);
 
 void mlx4_pd_free(struct mlx4_dev *dev, u32 pdn)
 {
-       mlx4_bitmap_free(&mlx4_priv(dev)->pd_bitmap, pdn);
+       mlx4_bitmap_free(&mlx4_priv(dev)->pd_bitmap, pdn, MLX4_USE_RR);
 }
 EXPORT_SYMBOL_GPL(mlx4_pd_free);
 
@@ -96,7 +96,7 @@ EXPORT_SYMBOL_GPL(mlx4_xrcd_alloc);
 
 void __mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn)
 {
-       mlx4_bitmap_free(&mlx4_priv(dev)->xrcd_bitmap, xrcdn);
+       mlx4_bitmap_free(&mlx4_priv(dev)->xrcd_bitmap, xrcdn, MLX4_USE_RR);
 }
 
 void mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn)
@@ -164,7 +164,7 @@ EXPORT_SYMBOL_GPL(mlx4_uar_alloc);
 
 void mlx4_uar_free(struct mlx4_dev *dev, struct mlx4_uar *uar)
 {
-       mlx4_bitmap_free(&mlx4_priv(dev)->uar_table.bitmap, uar->index);
+       mlx4_bitmap_free(&mlx4_priv(dev)->uar_table.bitmap, uar->index, MLX4_USE_RR);
 }
 EXPORT_SYMBOL_GPL(mlx4_uar_free);
 
index 2715e61dbb74613371b13e324c7f76c7482cb3d3..06b2d13d531016186bb15951dcd568878a120383 100644 (file)
@@ -250,7 +250,7 @@ void __mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt)
 
        if (mlx4_is_qp_reserved(dev, (u32) base_qpn))
                return;
-       mlx4_bitmap_free_range(&qp_table->bitmap, base_qpn, cnt);
+       mlx4_bitmap_free_range(&qp_table->bitmap, base_qpn, cnt, MLX4_USE_RR);
 }
 
 void mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt)
index 8fdf237537791da5568fc7be38ca36bed3fc57a3..1d2f9d3862a74558e79d5f44df23ce057627ace1 100644 (file)
@@ -117,7 +117,7 @@ err_put:
        mlx4_table_put(dev, &srq_table->table, *srqn);
 
 err_out:
-       mlx4_bitmap_free(&srq_table->bitmap, *srqn);
+       mlx4_bitmap_free(&srq_table->bitmap, *srqn, MLX4_NO_RR);
        return err;
 }
 
@@ -145,7 +145,7 @@ void __mlx4_srq_free_icm(struct mlx4_dev *dev, int srqn)
 
        mlx4_table_put(dev, &srq_table->cmpt_table, srqn);
        mlx4_table_put(dev, &srq_table->table, srqn);
-       mlx4_bitmap_free(&srq_table->bitmap, srqn);
+       mlx4_bitmap_free(&srq_table->bitmap, srqn, MLX4_NO_RR);
 }
 
 static void mlx4_srq_free_icm(struct mlx4_dev *dev, int srqn)
index 346a4e025c34100315b1ca2785d631d3bc5d3408..04b3ec1352f1eb9f532f7a6ab770615441f023fd 100644 (file)
@@ -52,7 +52,6 @@
 #include <linux/bitrev.h>
 #include <linux/slab.h>
 
-#include <asm/bootinfo.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
 #include <asm/hwtest.h>
index d3b47003a5757067f47340c60e6d2dc08d299c10..dbccf1de49ecbf7011a167585caefdeb082fa4de 100644 (file)
@@ -22,8 +22,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  *
  * ChangeLog
@@ -2236,7 +2235,6 @@ out_disable:
        pci_disable_device(pci_dev);
 out_free:
        free_netdev(ndev);
-       pci_set_drvdata(pci_dev, NULL);
 out:
        return err;
 }
@@ -2260,7 +2258,6 @@ static void ns83820_remove_one(struct pci_dev *pci_dev)
                        dev->rx_info.descs, dev->rx_info.phy_descs);
        pci_disable_device(dev->pci_dev);
        free_netdev(ndev);
-       pci_set_drvdata(pci_dev, NULL);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(ns83820_pci_tbl) = {
index f9876ea8c8bfd75b9e53214f56ba624cb55396b4..5d4ad589ebf321fc23db7c0f995cf56a15e21992 100644 (file)
@@ -3189,7 +3189,7 @@ static enum vxge_hw_status vxge_timestamp_config(struct __vxge_hw_device *devh)
        return status;
 }
 
-static int vxge_hwtstamp_ioctl(struct vxgedev *vdev, void __user *data)
+static int vxge_hwtstamp_set(struct vxgedev *vdev, void __user *data)
 {
        struct hwtstamp_config config;
        int i;
@@ -3250,6 +3250,21 @@ static int vxge_hwtstamp_ioctl(struct vxgedev *vdev, void __user *data)
        return 0;
 }
 
+static int vxge_hwtstamp_get(struct vxgedev *vdev, void __user *data)
+{
+       struct hwtstamp_config config;
+
+       config.flags = 0;
+       config.tx_type = HWTSTAMP_TX_OFF;
+       config.rx_filter = (vdev->rx_hwts ?
+                           HWTSTAMP_FILTER_ALL : HWTSTAMP_FILTER_NONE);
+
+       if (copy_to_user(data, &config, sizeof(config)))
+               return -EFAULT;
+
+       return 0;
+}
+
 /**
  * vxge_ioctl
  * @dev: Device pointer.
@@ -3263,19 +3278,15 @@ static int vxge_hwtstamp_ioctl(struct vxgedev *vdev, void __user *data)
 static int vxge_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
        struct vxgedev *vdev = netdev_priv(dev);
-       int ret;
 
        switch (cmd) {
        case SIOCSHWTSTAMP:
-               ret = vxge_hwtstamp_ioctl(vdev, rq->ifr_data);
-               if (ret)
-                       return ret;
-               break;
+               return vxge_hwtstamp_set(vdev, rq->ifr_data);
+       case SIOCGHWTSTAMP:
+               return vxge_hwtstamp_get(vdev, rq->ifr_data);
        default:
                return -EOPNOTSUPP;
        }
-
-       return 0;
 }
 
 /**
index e6f0a4366f905796777aac8fd1e006b177b83bfc..31eb911e4763c691bb288912a8e48900cf986552 100644 (file)
@@ -13,8 +13,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/init.h>
index 2d045be4b5cf64a5921a6687b127609093df376e..493a1125f54f2a841019c2b4959f5043c8969934 100644 (file)
@@ -26,8 +26,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * Known bugs:
  * We suspect that on some hardware no TX done interrupts are generated.
@@ -5150,8 +5149,10 @@ static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64
 {
        struct fe_priv *np = netdev_priv(dev);
        u8 __iomem *base = get_hwbase(dev);
-       int result;
-       memset(buffer, 0, nv_get_sset_count(dev, ETH_SS_TEST)*sizeof(u64));
+       int result, count;
+
+       count = nv_get_sset_count(dev, ETH_SS_TEST);
+       memset(buffer, 0, count * sizeof(u64));
 
        if (!nv_link_test(dev)) {
                test->flags |= ETH_TEST_FL_FAILED;
@@ -5195,7 +5196,7 @@ static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64
                        return;
                }
 
-               if (!nv_loopback_test(dev)) {
+               if (count > NV_TEST_COUNT_BASE && !nv_loopback_test(dev)) {
                        test->flags |= ETH_TEST_FL_FAILED;
                        buffer[3] = 1;
                }
@@ -6018,7 +6019,6 @@ static int nv_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
 out_error:
        if (phystate_orig)
                writel(phystate|NVREG_ADAPTCTL_RUNNING, base + NvRegAdapterControl);
-       pci_set_drvdata(pci_dev, NULL);
 out_freering:
        free_rings(dev);
 out_unmap:
@@ -6089,7 +6089,6 @@ static void nv_remove(struct pci_dev *pci_dev)
        pci_release_regions(pci_dev);
        pci_disable_device(pci_dev);
        free_netdev(dev);
-       pci_set_drvdata(pci_dev, NULL);
 }
 
 #ifdef CONFIG_PM_SLEEP
index 2a9003071d51a985be9b133fea76a585dabdf2d4..2a55d6d53ee61635806725d5167638b926f63363 100644 (file)
@@ -14,8 +14,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef _PCH_GBE_H_
index ff3ad70935a692210946557e9eb510473edb00fd..51250363566b0d3c579a76847eb65c3c2eca3dec 100644 (file)
@@ -14,8 +14,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 #include "pch_gbe.h"
 #include "pch_gbe_phy.h"
index 94aaac5b057bcb0bbd9bda5bbaec8cc8db718dcc..91ce07c8306c54c34e99cc1b76f25f77feb5eb42 100644 (file)
@@ -14,8 +14,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 #ifndef _PCH_GBE_API_H_
 #define _PCH_GBE_API_H_
index f0ceb89af93110c874eee7ec3d23cce82871d8a9..826f0ccdc23c818139d3951c953b56a3b885d6e8 100644 (file)
@@ -14,8 +14,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 #include "pch_gbe.h"
 #include "pch_gbe_api.h"
index 27ffe0ebf0a686793c30f25f033895bf70ddfe51..464e91058c81157da7fa8d3c25a03b266ed0ffe6 100644 (file)
@@ -14,8 +14,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "pch_gbe.h"
index cf7c9b3a255b40cf6e4c949e248303994be07287..08d4be61606480d645f5e772f998b335b508ed65 100644 (file)
@@ -14,8 +14,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "pch_gbe.h"
index 8b7ff75fc8e0d5201c94a014c64781b632a896cc..a5cad5ea9436bae73fd8fa58f2cfb01b7c713a63 100644 (file)
@@ -14,8 +14,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "pch_gbe.h"
index 0cbe69206e04db47eb77956d7466937e6c357144..95ad0151ad028aca6312f3b0c65157a3f2d0ba7d 100644 (file)
@@ -14,8 +14,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 #ifndef _PCH_GBE_PHY_H_
 #define _PCH_GBE_PHY_H_
index dbaa49e58b0cd8610c71a83c8170c7f10255453e..0734758ff5ba744fd47b917fefa61e090472d2b1 100644 (file)
@@ -13,8 +13,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/init.h>
index f2749d46c125f738ce38e406958015fc37246640..a5807703ab9650f176c268f828415c81a5598a5e 100644 (file)
@@ -14,8 +14,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef PASEMI_MAC_H
index 4825959a0efe1288712ce1080d47a45f6daf254b..25fae568261f6d2b51ea1011c4610b2019b88de7 100644 (file)
@@ -13,8 +13,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 
index 861a0590b1f4fd2bff47e25a0d84d9f69917c5f0..e14e60c883817c1a33b3466f1b90744d0312488b 100644 (file)
@@ -13,9 +13,7 @@
 # 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.
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 # 
 # The full GNU General Public License is included in this distribution
 # in the file called "COPYING".
index 9adcdbb49476e53face68f353dd7261ffea356b3..6e426ae9469228ed55586bca15a8eef1dcb5e5c4 100644 (file)
@@ -14,9 +14,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * The full GNU General Public License is included in this distribution
  * in the file called "COPYING".
index 1bcaf45aa8641f5302dde03a5a432dac3a71a799..6f6be57f46901a0e5eb3280c146fc6193cdc5171 100644 (file)
@@ -14,9 +14,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * The full GNU General Public License is included in this distribution
  * in the file called "COPYING".
index 4ca2c196c98a1e79a77434e7ba56c14c2e98801c..87e073c6e291609793106bfc5646c4695b9698d2 100644 (file)
@@ -14,9 +14,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * The full GNU General Public License is included in this distribution
  * in the file called "COPYING".
index 0c64c82b9acffdcfd58b9471f971d0eebe95a9cc..a310c2f6502a7256be2372e3c665ec8dc07f3895 100644 (file)
@@ -14,9 +14,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * The full GNU General Public License is included in this distribution
  * in the file called "COPYING".
index 67efe754367de10d78e6bb1cbacd65caa6f1524c..b72b6bea326eaac359fe38f2ce3cc516424e7484 100644 (file)
@@ -14,9 +14,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * The full GNU General Public License is included in this distribution
  * in the file called "COPYING".
index e2c5b6f2df0361e54a6fcb2c8f9df41098610fd4..7433c4d2160140cace3896596fc0179bcfe43f58 100644 (file)
@@ -14,9 +14,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * The full GNU General Public License is included in this distribution
  * in the file called "COPYING".
index 7692dfd4f262db9045f285aadc194c1713fb724a..3010abb55fbdb22173930b36d896ad10934dc357 100644 (file)
@@ -14,9 +14,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * The full GNU General Public License is included in this distribution
  * in the file called "COPYING".
index 3bec8cfebf99299ef9c3733b47033a26fe8ba7b1..70849dea32b1306400822919ca0bd547339cbd4a 100644 (file)
@@ -14,9 +14,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * The full GNU General Public License is included in this distribution
  * in the file called "COPYING".
index 0c9c4e89559524d78aa789dfb65e5e32211b8bc1..03517478e589495dd763a13eaab31101a9ea0a08 100644 (file)
@@ -18,7 +18,7 @@
  */
 #define DRV_NAME       "qlge"
 #define DRV_STRING     "QLogic 10 Gigabit PCI-E Ethernet Driver "
-#define DRV_VERSION    "1.00.00.33"
+#define DRV_VERSION    "1.00.00.34"
 
 #define WQ_ADDR_ALIGN  0x3     /* 4 byte alignment */
 
index 0780e039b2718d902805414daeb6844b7d2086e7..8dee1beb9854813c94c1de36264a241703f9d0be 100644 (file)
@@ -181,6 +181,7 @@ static const char ql_gstrings_test[][ETH_GSTRING_LEN] = {
 };
 #define QLGE_TEST_LEN (sizeof(ql_gstrings_test) / ETH_GSTRING_LEN)
 #define QLGE_STATS_LEN ARRAY_SIZE(ql_gstrings_stats)
+#define QLGE_RCV_MAC_ERR_STATS 7
 
 static int ql_update_ring_coalescing(struct ql_adapter *qdev)
 {
@@ -280,6 +281,9 @@ static void ql_update_stats(struct ql_adapter *qdev)
                iter++;
        }
 
+       /* Update receive mac error statistics */
+       iter += QLGE_RCV_MAC_ERR_STATS;
+
        /*
         * Get Per-priority TX pause frame counter statistics.
         */
index a245dc18d769241bcf23d607458e33538c7ee99c..449f506d2e8ff3e71abc22bba6ce8e67bcf45305 100644 (file)
@@ -2376,14 +2376,6 @@ static netdev_features_t qlge_fix_features(struct net_device *ndev,
        netdev_features_t features)
 {
        int err;
-       /*
-        * Since there is no support for separate rx/tx vlan accel
-        * enable/disable make sure tx flag is always in same state as rx.
-        */
-       if (features & NETIF_F_HW_VLAN_CTAG_RX)
-               features |= NETIF_F_HW_VLAN_CTAG_TX;
-       else
-               features &= ~NETIF_F_HW_VLAN_CTAG_TX;
 
        /* Update the behavior of vlan accel in the adapter */
        err = qlge_update_hw_vlan_features(ndev, features);
index f2a2128165dd98b4c41598fb481c4e4f40417614..737c1a881f781917061d8b39ad43762f62ee7a6e 100644 (file)
@@ -678,9 +678,6 @@ static void cp_tx (struct cp_private *cp)
                                 le32_to_cpu(txd->opts1) & 0xffff,
                                 PCI_DMA_TODEVICE);
 
-               bytes_compl += skb->len;
-               pkts_compl++;
-
                if (status & LastFrag) {
                        if (status & (TxError | TxFIFOUnder)) {
                                netif_dbg(cp, tx_err, cp->dev,
@@ -702,6 +699,8 @@ static void cp_tx (struct cp_private *cp)
                                netif_dbg(cp, tx_done, cp->dev,
                                          "tx done, slot %d\n", tx_tail);
                        }
+                       bytes_compl += skb->len;
+                       pkts_compl++;
                        dev_kfree_skb_irq(skb);
                }
 
index 799387570766b6642ad4fdbc13f917acd358887a..c737f0ea5de751b7de9b1cb710fb101dc170ee41 100644 (file)
@@ -3465,6 +3465,11 @@ static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp)
        rtl_writephy(tp, 0x14, 0x9065);
        rtl_writephy(tp, 0x14, 0x1065);
 
+       /* Check ALDPS bit, disable it if enabled */
+       rtl_writephy(tp, 0x1f, 0x0a43);
+       if (rtl_readphy(tp, 0x10) & 0x0004)
+               rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0004);
+
        rtl_writephy(tp, 0x1f, 0x0000);
 }
 
index a30c4395b23220902d4b785333b31b53abfb24c7..9e757c792d846f300288c9848225e1db9a9584fa 100644 (file)
@@ -13,4 +13,4 @@ config SH_ETH
          Renesas SuperH Ethernet device driver.
          This driver supporting CPUs are:
                - SH7619, SH7710, SH7712, SH7724, SH7734, SH7763, SH7757,
-                 R8A7740, R8A777x and R8A7790.
+                 R8A7740, R8A777x and R8A779x.
index d256ce19d4de1cf6e93b51700b3ed8f5d813a3e0..8601d0c638cc2a7ab76bf5092ab80e280a90e483 100644 (file)
@@ -395,8 +395,8 @@ static struct sh_eth_cpu_data r8a777x_data = {
        .hw_swap        = 1,
 };
 
-/* R8A7790 */
-static struct sh_eth_cpu_data r8a7790_data = {
+/* R8A7790/1 */
+static struct sh_eth_cpu_data r8a779x_data = {
        .set_duplex     = sh_eth_set_duplex,
        .set_rate       = sh_eth_set_rate_r8a777x,
 
@@ -1704,7 +1704,10 @@ static int sh_eth_phy_start(struct net_device *ndev)
                return ret;
 
        /* reset phy - this also wakes it from PDOWN */
-       phy_write(mdp->phydev, MII_BMCR, BMCR_RESET);
+       ret = phy_init_hw(mdp->phydev);
+       if (ret)
+               return ret;
+
        phy_start(mdp->phydev);
 
        return 0;
@@ -2807,7 +2810,8 @@ static struct platform_device_id sh_eth_id_table[] = {
        { "sh7763-gether", (kernel_ulong_t)&sh7763_data },
        { "r8a7740-gether", (kernel_ulong_t)&r8a7740_data },
        { "r8a777x-ether", (kernel_ulong_t)&r8a777x_data },
-       { "r8a7790-ether", (kernel_ulong_t)&r8a7790_data },
+       { "r8a7790-ether", (kernel_ulong_t)&r8a779x_data },
+       { "r8a7791-ether", (kernel_ulong_t)&r8a779x_data },
        { }
 };
 MODULE_DEVICE_TABLE(platform, sh_eth_id_table);
index 2e27837ce6a289dc033c806e613f8dbca42496b9..f09860423d19f6f192cd498e2b592be6156ea897 100644 (file)
@@ -585,7 +585,7 @@ static void efx_start_datapath(struct efx_nic *efx)
                           EFX_MAX_FRAME_LEN(efx->net_dev->mtu) +
                           efx->type->rx_buffer_padding);
        rx_buf_len = (sizeof(struct efx_rx_page_state) +
-                     NET_IP_ALIGN + efx->rx_dma_len);
+                     efx->rx_ip_align + efx->rx_dma_len);
        if (rx_buf_len <= PAGE_SIZE) {
                efx->rx_scatter = efx->type->always_rx_scatter;
                efx->rx_buffer_order = 0;
@@ -645,6 +645,8 @@ static void efx_start_datapath(struct efx_nic *efx)
                WARN_ON(channel->rx_pkt_n_frags);
        }
 
+       efx_ptp_start_datapath(efx);
+
        if (netif_device_present(efx->net_dev))
                netif_tx_wake_all_queues(efx->net_dev);
 }
@@ -659,6 +661,8 @@ static void efx_stop_datapath(struct efx_nic *efx)
        EFX_ASSERT_RESET_SERIALISED(efx);
        BUG_ON(efx->port_enabled);
 
+       efx_ptp_stop_datapath(efx);
+
        /* Stop RX refill */
        efx_for_each_channel(channel, efx) {
                efx_for_each_channel_rx_queue(rx_queue, channel)
@@ -1847,7 +1851,9 @@ static int efx_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd)
        struct mii_ioctl_data *data = if_mii(ifr);
 
        if (cmd == SIOCSHWTSTAMP)
-               return efx_ptp_ioctl(efx, ifr, cmd);
+               return efx_ptp_set_ts_config(efx, ifr);
+       if (cmd == SIOCGHWTSTAMP)
+               return efx_ptp_get_ts_config(efx, ifr);
 
        /* Convert phy_id from older PRTAD/DEVAD format */
        if ((cmd == SIOCGMIIREG || cmd == SIOCSMIIREG) &&
@@ -2540,6 +2546,8 @@ static int efx_init_struct(struct efx_nic *efx,
 
        efx->net_dev = net_dev;
        efx->rx_prefix_size = efx->type->rx_prefix_size;
+       efx->rx_ip_align =
+               NET_IP_ALIGN ? (efx->rx_prefix_size + NET_IP_ALIGN) % 4 : 0;
        efx->rx_packet_hash_offset =
                efx->type->rx_hash_offset - efx->type->rx_prefix_size;
        spin_lock_init(&efx->stats_lock);
@@ -2641,7 +2649,6 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
        netif_dbg(efx, drv, efx->net_dev, "shutdown successful\n");
 
        efx_fini_struct(efx);
-       pci_set_drvdata(pci_dev, NULL);
        free_netdev(efx->net_dev);
 
        pci_disable_pcie_error_reporting(pci_dev);
@@ -2835,7 +2842,6 @@ static int efx_pci_probe(struct pci_dev *pci_dev,
  fail2:
        efx_fini_struct(efx);
  fail1:
-       pci_set_drvdata(pci_dev, NULL);
        WARN_ON(rc > 0);
        netif_dbg(efx, drv, efx->net_dev, "initialisation failed. rc=%d\n", rc);
        free_netdev(net_dev);
index 366c8e3e37844c8e2d8840a4662467067e937b3b..4b0bd8a1514dbb7035c7c0562cefc072901e585c 100644 (file)
@@ -50,6 +50,7 @@ struct efx_mcdi_async_param {
 static void efx_mcdi_timeout_async(unsigned long context);
 static int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating,
                               bool *was_attached_out);
+static bool efx_mcdi_poll_once(struct efx_nic *efx);
 
 static inline struct efx_mcdi_iface *efx_mcdi(struct efx_nic *efx)
 {
@@ -237,6 +238,21 @@ static void efx_mcdi_read_response_header(struct efx_nic *efx)
        }
 }
 
+static bool efx_mcdi_poll_once(struct efx_nic *efx)
+{
+       struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
+
+       rmb();
+       if (!efx->type->mcdi_poll_response(efx))
+               return false;
+
+       spin_lock_bh(&mcdi->iface_lock);
+       efx_mcdi_read_response_header(efx);
+       spin_unlock_bh(&mcdi->iface_lock);
+
+       return true;
+}
+
 static int efx_mcdi_poll(struct efx_nic *efx)
 {
        struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
@@ -272,18 +288,13 @@ static int efx_mcdi_poll(struct efx_nic *efx)
 
                time = jiffies;
 
-               rmb();
-               if (efx->type->mcdi_poll_response(efx))
+               if (efx_mcdi_poll_once(efx))
                        break;
 
                if (time_after(time, finish))
                        return -ETIMEDOUT;
        }
 
-       spin_lock_bh(&mcdi->iface_lock);
-       efx_mcdi_read_response_header(efx);
-       spin_unlock_bh(&mcdi->iface_lock);
-
        /* Return rc=0 like wait_event_timeout() */
        return 0;
 }
@@ -619,6 +630,16 @@ int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen,
                rc = efx_mcdi_await_completion(efx);
 
        if (rc != 0) {
+               netif_err(efx, hw, efx->net_dev,
+                         "MC command 0x%x inlen %d mode %d timed out\n",
+                         cmd, (int)inlen, mcdi->mode);
+
+               if (mcdi->mode == MCDI_MODE_EVENTS && efx_mcdi_poll_once(efx)) {
+                       netif_err(efx, hw, efx->net_dev,
+                                 "MCDI request was completed without an event\n");
+                       rc = 0;
+               }
+
                /* Close the race with efx_mcdi_ev_cpl() executing just too late
                 * and completing a request we've just cancelled, by ensuring
                 * that the seqno check therein fails.
@@ -627,11 +648,9 @@ int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen,
                ++mcdi->seqno;
                ++mcdi->credits;
                spin_unlock_bh(&mcdi->iface_lock);
+       }
 
-               netif_err(efx, hw, efx->net_dev,
-                         "MC command 0x%x inlen %d mode %d timed out\n",
-                         cmd, (int)inlen, mcdi->mode);
-       } else {
+       if (rc == 0) {
                size_t hdr_len, data_len;
 
                /* At the very least we need a memory barrier here to ensure
index 656a3277c2b210e69ffd028d059ce10b809e8db8..15816cacb548161bd4a7299909bb83ccd9c222be 100644 (file)
@@ -75,6 +75,8 @@ struct efx_mcdi_mon {
        unsigned long last_update;
        struct device *device;
        struct efx_mcdi_mon_attribute *attrs;
+       struct attribute_group group;
+       const struct attribute_group *groups[2];
        unsigned int n_attrs;
 };
 
index 4cc5d95b2a5a5ea36869625843bf4daba064e84f..d72ad4fc36172241d5aeccbe883f4a82c8ee2daf 100644 (file)
@@ -139,17 +139,10 @@ static int efx_mcdi_mon_update(struct efx_nic *efx)
        return rc;
 }
 
-static ssize_t efx_mcdi_mon_show_name(struct device *dev,
-                                     struct device_attribute *attr,
-                                     char *buf)
-{
-       return sprintf(buf, "%s\n", KBUILD_MODNAME);
-}
-
 static int efx_mcdi_mon_get_entry(struct device *dev, unsigned int index,
                                  efx_dword_t *entry)
 {
-       struct efx_nic *efx = dev_get_drvdata(dev);
+       struct efx_nic *efx = dev_get_drvdata(dev->parent);
        struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx);
        int rc;
 
@@ -263,7 +256,7 @@ static ssize_t efx_mcdi_mon_show_label(struct device *dev,
                       efx_mcdi_sensor_type[mon_attr->type].label);
 }
 
-static int
+static void
 efx_mcdi_mon_add_attr(struct efx_nic *efx, const char *name,
                      ssize_t (*reader)(struct device *,
                                        struct device_attribute *, char *),
@@ -272,7 +265,6 @@ efx_mcdi_mon_add_attr(struct efx_nic *efx, const char *name,
 {
        struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx);
        struct efx_mcdi_mon_attribute *attr = &hwmon->attrs[hwmon->n_attrs];
-       int rc;
 
        strlcpy(attr->name, name, sizeof(attr->name));
        attr->index = index;
@@ -286,10 +278,7 @@ efx_mcdi_mon_add_attr(struct efx_nic *efx, const char *name,
        attr->dev_attr.attr.name = attr->name;
        attr->dev_attr.attr.mode = S_IRUGO;
        attr->dev_attr.show = reader;
-       rc = device_create_file(&efx->pci_dev->dev, &attr->dev_attr);
-       if (rc == 0)
-               ++hwmon->n_attrs;
-       return rc;
+       hwmon->group.attrs[hwmon->n_attrs++] = &attr->dev_attr.attr;
 }
 
 int efx_mcdi_mon_probe(struct efx_nic *efx)
@@ -338,26 +327,22 @@ int efx_mcdi_mon_probe(struct efx_nic *efx)
        efx_mcdi_mon_update(efx);
 
        /* Allocate space for the maximum possible number of
-        * attributes for this set of sensors: name of the driver plus
+        * attributes for this set of sensors:
         * value, min, max, crit, alarm and label for each sensor.
         */
-       n_attrs = 1 + 6 * n_sensors;
+       n_attrs = 6 * n_sensors;
        hwmon->attrs = kcalloc(n_attrs, sizeof(*hwmon->attrs), GFP_KERNEL);
        if (!hwmon->attrs) {
                rc = -ENOMEM;
                goto fail;
        }
-
-       hwmon->device = hwmon_device_register(&efx->pci_dev->dev);
-       if (IS_ERR(hwmon->device)) {
-               rc = PTR_ERR(hwmon->device);
+       hwmon->group.attrs = kcalloc(n_attrs + 1, sizeof(struct attribute *),
+                                    GFP_KERNEL);
+       if (!hwmon->group.attrs) {
+               rc = -ENOMEM;
                goto fail;
        }
 
-       rc = efx_mcdi_mon_add_attr(efx, "name", efx_mcdi_mon_show_name, 0, 0, 0);
-       if (rc)
-               goto fail;
-
        for (i = 0, j = -1, type = -1; ; i++) {
                enum efx_hwmon_type hwmon_type;
                const char *hwmon_prefix;
@@ -372,7 +357,7 @@ int efx_mcdi_mon_probe(struct efx_nic *efx)
                                page = type / 32;
                                j = -1;
                                if (page == n_pages)
-                                       return 0;
+                                       goto hwmon_register;
 
                                MCDI_SET_DWORD(inbuf, SENSOR_INFO_EXT_IN_PAGE,
                                               page);
@@ -453,28 +438,22 @@ int efx_mcdi_mon_probe(struct efx_nic *efx)
                if (min1 != max1) {
                        snprintf(name, sizeof(name), "%s%u_input",
                                 hwmon_prefix, hwmon_index);
-                       rc = efx_mcdi_mon_add_attr(
+                       efx_mcdi_mon_add_attr(
                                efx, name, efx_mcdi_mon_show_value, i, type, 0);
-                       if (rc)
-                               goto fail;
 
                        if (hwmon_type != EFX_HWMON_POWER) {
                                snprintf(name, sizeof(name), "%s%u_min",
                                         hwmon_prefix, hwmon_index);
-                               rc = efx_mcdi_mon_add_attr(
+                               efx_mcdi_mon_add_attr(
                                        efx, name, efx_mcdi_mon_show_limit,
                                        i, type, min1);
-                               if (rc)
-                                       goto fail;
                        }
 
                        snprintf(name, sizeof(name), "%s%u_max",
                                 hwmon_prefix, hwmon_index);
-                       rc = efx_mcdi_mon_add_attr(
+                       efx_mcdi_mon_add_attr(
                                efx, name, efx_mcdi_mon_show_limit,
                                i, type, max1);
-                       if (rc)
-                               goto fail;
 
                        if (min2 != max2) {
                                /* Assume max2 is critical value.
@@ -482,32 +461,38 @@ int efx_mcdi_mon_probe(struct efx_nic *efx)
                                 */
                                snprintf(name, sizeof(name), "%s%u_crit",
                                         hwmon_prefix, hwmon_index);
-                               rc = efx_mcdi_mon_add_attr(
+                               efx_mcdi_mon_add_attr(
                                        efx, name, efx_mcdi_mon_show_limit,
                                        i, type, max2);
-                               if (rc)
-                                       goto fail;
                        }
                }
 
                snprintf(name, sizeof(name), "%s%u_alarm",
                         hwmon_prefix, hwmon_index);
-               rc = efx_mcdi_mon_add_attr(
+               efx_mcdi_mon_add_attr(
                        efx, name, efx_mcdi_mon_show_alarm, i, type, 0);
-               if (rc)
-                       goto fail;
 
                if (type < ARRAY_SIZE(efx_mcdi_sensor_type) &&
                    efx_mcdi_sensor_type[type].label) {
                        snprintf(name, sizeof(name), "%s%u_label",
                                 hwmon_prefix, hwmon_index);
-                       rc = efx_mcdi_mon_add_attr(
+                       efx_mcdi_mon_add_attr(
                                efx, name, efx_mcdi_mon_show_label, i, type, 0);
-                       if (rc)
-                               goto fail;
                }
        }
 
+hwmon_register:
+       hwmon->groups[0] = &hwmon->group;
+       hwmon->device = hwmon_device_register_with_groups(&efx->pci_dev->dev,
+                                                         KBUILD_MODNAME, NULL,
+                                                         hwmon->groups);
+       if (IS_ERR(hwmon->device)) {
+               rc = PTR_ERR(hwmon->device);
+               goto fail;
+       }
+
+       return 0;
+
 fail:
        efx_mcdi_mon_remove(efx);
        return rc;
@@ -516,14 +501,11 @@ fail:
 void efx_mcdi_mon_remove(struct efx_nic *efx)
 {
        struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx);
-       unsigned int i;
 
-       for (i = 0; i < hwmon->n_attrs; i++)
-               device_remove_file(&efx->pci_dev->dev,
-                                  &hwmon->attrs[i].dev_attr);
-       kfree(hwmon->attrs);
        if (hwmon->device)
                hwmon_device_unregister(hwmon->device);
+       kfree(hwmon->attrs);
+       kfree(hwmon->group.attrs);
        efx_nic_free_buffer(efx, &hwmon->dma_buf);
 }
 
index b14a717ac3e8d95099b5d2648be590e138bc9e61..542a0d252ae0c25f6c60167c1ec9dba3943ba3d8 100644 (file)
@@ -683,6 +683,8 @@ struct vfdi_status;
  * @n_channels: Number of channels in use
  * @n_rx_channels: Number of channels used for RX (= number of RX queues)
  * @n_tx_channels: Number of channels used for TX
+ * @rx_ip_align: RX DMA address offset to have IP header aligned in
+ *     in accordance with NET_IP_ALIGN
  * @rx_dma_len: Current maximum RX DMA length
  * @rx_buffer_order: Order (log2) of number of pages for each RX buffer
  * @rx_buffer_truesize: Amortised allocation size of an RX buffer,
@@ -816,6 +818,7 @@ struct efx_nic {
        unsigned rss_spread;
        unsigned tx_channel_offset;
        unsigned n_tx_channels;
+       unsigned int rx_ip_align;
        unsigned int rx_dma_len;
        unsigned int rx_buffer_order;
        unsigned int rx_buffer_truesize;
index 11b6112d9249a734701eebe66414bd039702bcdd..fe71e81ee8bf0cb9284b04a234457d77bbf5a0f5 100644 (file)
@@ -555,11 +555,14 @@ int efx_sriov_set_vf_spoofchk(struct net_device *net_dev, int vf,
 
 struct ethtool_ts_info;
 void efx_ptp_probe(struct efx_nic *efx);
-int efx_ptp_ioctl(struct efx_nic *efx, struct ifreq *ifr, int cmd);
+int efx_ptp_set_ts_config(struct efx_nic *efx, struct ifreq *ifr);
+int efx_ptp_get_ts_config(struct efx_nic *efx, struct ifreq *ifr);
 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);
+void efx_ptp_start_datapath(struct efx_nic *efx);
+void efx_ptp_stop_datapath(struct efx_nic *efx);
 
 extern const struct efx_nic_type falcon_a1_nic_type;
 extern const struct efx_nic_type falcon_b0_nic_type;
index 03acf57df04579bed5d0986f735f807491248cfb..34b25864b12105cd521824cdde1daab9a16b2d59 100644 (file)
@@ -220,6 +220,7 @@ struct efx_ptp_timeset {
  * @evt_list: List of MC receive events awaiting packets
  * @evt_free_list: List of free events
  * @evt_lock: Lock for manipulating evt_list and evt_free_list
+ * @evt_overflow: Boolean indicating that event list has overflowed
  * @rx_evts: Instantiated events (on evt_list and evt_free_list)
  * @workwq: Work queue for processing pending PTP operations
  * @work: Work task
@@ -270,6 +271,7 @@ struct efx_ptp_data {
        struct list_head evt_list;
        struct list_head evt_free_list;
        spinlock_t evt_lock;
+       bool evt_overflow;
        struct efx_ptp_event_rx rx_evts[MAX_RECEIVE_EVENTS];
        struct workqueue_struct *workwq;
        struct work_struct work;
@@ -635,6 +637,11 @@ static void efx_ptp_drop_time_expired_events(struct efx_nic *efx)
                        }
                }
        }
+       /* If the event overflow flag is set and the event list is now empty
+        * clear the flag to re-enable the overflow warning message.
+        */
+       if (ptp->evt_overflow && list_empty(&ptp->evt_list))
+               ptp->evt_overflow = false;
        spin_unlock_bh(&ptp->evt_lock);
 }
 
@@ -676,6 +683,11 @@ static enum ptp_packet_state efx_ptp_match_rx(struct efx_nic *efx,
                        break;
                }
        }
+       /* If the event overflow flag is set and the event list is now empty
+        * clear the flag to re-enable the overflow warning message.
+        */
+       if (ptp->evt_overflow && list_empty(&ptp->evt_list))
+               ptp->evt_overflow = false;
        spin_unlock_bh(&ptp->evt_lock);
 
        return rc;
@@ -705,8 +717,9 @@ static bool efx_ptp_process_events(struct efx_nic *efx, struct sk_buff_head *q)
                        __skb_queue_tail(q, skb);
                } else if (time_after(jiffies, match->expiry)) {
                        match->state = PTP_PACKET_STATE_TIMED_OUT;
-                       netif_warn(efx, rx_err, efx->net_dev,
-                                  "PTP packet - no timestamp seen\n");
+                       if (net_ratelimit())
+                               netif_warn(efx, rx_err, efx->net_dev,
+                                          "PTP packet - no timestamp seen\n");
                        __skb_queue_tail(q, skb);
                } else {
                        /* Replace unprocessed entry and stop */
@@ -788,9 +801,14 @@ fail:
 static int efx_ptp_stop(struct efx_nic *efx)
 {
        struct efx_ptp_data *ptp = efx->ptp_data;
-       int rc = efx_ptp_disable(efx);
        struct list_head *cursor;
        struct list_head *next;
+       int rc;
+
+       if (ptp == NULL)
+               return 0;
+
+       rc = efx_ptp_disable(efx);
 
        if (ptp->rxfilter_installed) {
                efx_filter_remove_id_safe(efx, EFX_FILTER_PRI_REQUIRED,
@@ -809,11 +827,19 @@ static int efx_ptp_stop(struct efx_nic *efx)
        list_for_each_safe(cursor, next, &efx->ptp_data->evt_list) {
                list_move(cursor, &efx->ptp_data->evt_free_list);
        }
+       ptp->evt_overflow = false;
        spin_unlock_bh(&efx->ptp_data->evt_lock);
 
        return rc;
 }
 
+static int efx_ptp_restart(struct efx_nic *efx)
+{
+       if (efx->ptp_data && efx->ptp_data->enabled)
+               return efx_ptp_start(efx);
+       return 0;
+}
+
 static void efx_ptp_pps_worker(struct work_struct *work)
 {
        struct efx_ptp_data *ptp =
@@ -901,6 +927,7 @@ static int efx_ptp_probe_channel(struct efx_channel *channel)
        spin_lock_init(&ptp->evt_lock);
        for (pos = 0; pos < MAX_RECEIVE_EVENTS; pos++)
                list_add(&ptp->rx_evts[pos].link, &ptp->evt_free_list);
+       ptp->evt_overflow = false;
 
        ptp->phc_clock_info.owner = THIS_MODULE;
        snprintf(ptp->phc_clock_info.name,
@@ -989,7 +1016,11 @@ bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb)
                skb->len >= PTP_MIN_LENGTH &&
                skb->len <= MC_CMD_PTP_IN_TRANSMIT_PACKET_MAXNUM &&
                likely(skb->protocol == htons(ETH_P_IP)) &&
+               skb_transport_header_was_set(skb) &&
+               skb_network_header_len(skb) >= sizeof(struct iphdr) &&
                ip_hdr(skb)->protocol == IPPROTO_UDP &&
+               skb_headlen(skb) >=
+               skb_transport_offset(skb) + sizeof(struct udphdr) &&
                udp_hdr(skb)->dest == htons(PTP_EVENT_PORT);
 }
 
@@ -1106,7 +1137,7 @@ static int efx_ptp_change_mode(struct efx_nic *efx, bool enable_wanted,
 {
        if ((enable_wanted != efx->ptp_data->enabled) ||
            (enable_wanted && (efx->ptp_data->mode != new_mode))) {
-               int rc;
+               int rc = 0;
 
                if (enable_wanted) {
                        /* Change of mode requires disable */
@@ -1123,7 +1154,8 @@ static int efx_ptp_change_mode(struct efx_nic *efx, bool enable_wanted,
                         * succeed.
                         */
                        efx->ptp_data->mode = new_mode;
-                       rc = efx_ptp_start(efx);
+                       if (netif_running(efx->net_dev))
+                               rc = efx_ptp_start(efx);
                        if (rc == 0) {
                                rc = efx_ptp_synchronize(efx,
                                                         PTP_SYNC_ATTEMPTS * 2);
@@ -1231,7 +1263,7 @@ void efx_ptp_get_ts_info(struct efx_nic *efx, struct ethtool_ts_info *ts_info)
                               1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ);
 }
 
-int efx_ptp_ioctl(struct efx_nic *efx, struct ifreq *ifr, int cmd)
+int efx_ptp_set_ts_config(struct efx_nic *efx, struct ifreq *ifr)
 {
        struct hwtstamp_config config;
        int rc;
@@ -1251,6 +1283,15 @@ int efx_ptp_ioctl(struct efx_nic *efx, struct ifreq *ifr, int cmd)
                ? -EFAULT : 0;
 }
 
+int efx_ptp_get_ts_config(struct efx_nic *efx, struct ifreq *ifr)
+{
+       if (!efx->ptp_data)
+               return -EOPNOTSUPP;
+
+       return copy_to_user(ifr->ifr_data, &efx->ptp_data->config,
+                           sizeof(efx->ptp_data->config)) ? -EFAULT : 0;
+}
+
 static void ptp_event_failure(struct efx_nic *efx, int expected_frag_len)
 {
        struct efx_ptp_data *ptp = efx->ptp_data;
@@ -1295,8 +1336,13 @@ static void ptp_event_rx(struct efx_nic *efx, struct efx_ptp_data *ptp)
                list_add_tail(&evt->link, &ptp->evt_list);
 
                queue_work(ptp->workwq, &ptp->work);
-       } else {
-               netif_err(efx, rx_err, efx->net_dev, "No free PTP event");
+       } else if (!ptp->evt_overflow) {
+               /* Log a warning message and set the event overflow flag.
+                * The message won't be logged again until the event queue
+                * becomes empty.
+                */
+               netif_err(efx, rx_err, efx->net_dev, "PTP event queue overflow\n");
+               ptp->evt_overflow = true;
        }
        spin_unlock_bh(&ptp->evt_lock);
 }
@@ -1389,7 +1435,7 @@ static int efx_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta)
        if (rc != 0)
                return rc;
 
-       ptp_data->current_adjfreq = delta;
+       ptp_data->current_adjfreq = adjustment_ns;
        return 0;
 }
 
@@ -1404,7 +1450,7 @@ static int efx_phc_adjtime(struct ptp_clock_info *ptp, s64 delta)
 
        MCDI_SET_DWORD(inbuf, PTP_IN_OP, MC_CMD_PTP_OP_ADJUST);
        MCDI_SET_DWORD(inbuf, PTP_IN_PERIPH_ID, 0);
-       MCDI_SET_QWORD(inbuf, PTP_IN_ADJUST_FREQ, 0);
+       MCDI_SET_QWORD(inbuf, PTP_IN_ADJUST_FREQ, ptp_data->current_adjfreq);
        MCDI_SET_DWORD(inbuf, PTP_IN_ADJUST_SECONDS, (u32)delta_ts.tv_sec);
        MCDI_SET_DWORD(inbuf, PTP_IN_ADJUST_NANOSECONDS, (u32)delta_ts.tv_nsec);
        return efx_mcdi_rpc(efx, MC_CMD_PTP, inbuf, sizeof(inbuf),
@@ -1491,3 +1537,14 @@ void efx_ptp_probe(struct efx_nic *efx)
                efx->extra_channel_type[EFX_EXTRA_CHANNEL_PTP] =
                        &efx_ptp_channel_type;
 }
+
+void efx_ptp_start_datapath(struct efx_nic *efx)
+{
+       if (efx_ptp_restart(efx))
+               netif_err(efx, drv, efx->net_dev, "Failed to restart PTP.\n");
+}
+
+void efx_ptp_stop_datapath(struct efx_nic *efx)
+{
+       efx_ptp_stop(efx);
+}
index 8f09e686fc2392a80f56610c78a61c6374b4a410..42488df1f4ec2af02feb9a46c408168b6a7dabec 100644 (file)
@@ -94,7 +94,7 @@ static inline void efx_sync_rx_buffer(struct efx_nic *efx,
 
 void efx_rx_config_page_split(struct efx_nic *efx)
 {
-       efx->rx_page_buf_step = ALIGN(efx->rx_dma_len + NET_IP_ALIGN,
+       efx->rx_page_buf_step = ALIGN(efx->rx_dma_len + efx->rx_ip_align,
                                      EFX_RX_BUF_ALIGNMENT);
        efx->rx_bufs_per_page = efx->rx_buffer_order ? 1 :
                ((PAGE_SIZE - sizeof(struct efx_rx_page_state)) /
@@ -189,9 +189,9 @@ static int efx_init_rx_buffers(struct efx_rx_queue *rx_queue)
                do {
                        index = rx_queue->added_count & rx_queue->ptr_mask;
                        rx_buf = efx_rx_buffer(rx_queue, index);
-                       rx_buf->dma_addr = dma_addr + NET_IP_ALIGN;
+                       rx_buf->dma_addr = dma_addr + efx->rx_ip_align;
                        rx_buf->page = page;
-                       rx_buf->page_offset = page_offset + NET_IP_ALIGN;
+                       rx_buf->page_offset = page_offset + efx->rx_ip_align;
                        rx_buf->len = efx->rx_dma_len;
                        rx_buf->flags = 0;
                        ++rx_queue->added_count;
index 975dc2d8e548c0942f58cac47550883528f6ebb8..ff57a46388eefed67c81b70dc67e8ddd6a698826 100644 (file)
@@ -576,7 +576,6 @@ err_unmap_tx:
 err_out_unmap:
        pci_iounmap(pci_dev, ioaddr);
 err_out_cleardev:
-       pci_set_drvdata(pci_dev, NULL);
        pci_release_regions(pci_dev);
  err_out:
        free_netdev(net_dev);
@@ -2427,7 +2426,6 @@ static void sis900_remove(struct pci_dev *pci_dev)
        pci_iounmap(pci_dev, sis_priv->ioaddr);
        free_netdev(net_dev);
        pci_release_regions(pci_dev);
-       pci_set_drvdata(pci_dev, NULL);
 }
 
 #ifdef CONFIG_PM
index 0f096a890059255170976ee78a3f169cdafb7c90..5a4278d1f7d0be1963624c48d3d8153c01555fdc 100644 (file)
@@ -17,8 +17,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * Arguments:
  *      watchdog  = TX watchdog timeout
index 9965da39281b5ec720f9f2ce8851cf09a653a8b9..04b35f55df970eedc19ab57a4af88ee77d27cc61 100644 (file)
@@ -15,8 +15,7 @@
  . 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
+ . along with this program; if not, see <http://www.gnu.org/licenses/>.
  .
  . Information contained in this file was obtained from the LAN9118
  . manual from SMC.  To get a copy, if you really want one, you can find
index 0c9b5d94154f8d215ddaf40d3fb252764983d73b..96f79f7c439546dc1f015dfea3055b5cb0492ae6 100644 (file)
@@ -19,8 +19,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * Arguments:
  *     io      = for the base address
@@ -82,6 +81,7 @@ static const char version[] =
 #include <linux/mii.h>
 #include <linux/workqueue.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -2184,6 +2184,15 @@ static void smc_release_datacs(struct platform_device *pdev, struct net_device *
        }
 }
 
+#if IS_BUILTIN(CONFIG_OF)
+static const struct of_device_id smc91x_match[] = {
+       { .compatible = "smsc,lan91c94", },
+       { .compatible = "smsc,lan91c111", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, smc91x_match);
+#endif
+
 /*
  * smc_init(void)
  *   Input parameters:
@@ -2198,6 +2207,7 @@ static void smc_release_datacs(struct platform_device *pdev, struct net_device *
 static int smc_drv_probe(struct platform_device *pdev)
 {
        struct smc91x_platdata *pd = dev_get_platdata(&pdev->dev);
+       const struct of_device_id *match = NULL;
        struct smc_local *lp;
        struct net_device *ndev;
        struct resource *res, *ires;
@@ -2217,11 +2227,34 @@ static int smc_drv_probe(struct platform_device *pdev)
         */
 
        lp = netdev_priv(ndev);
+       lp->cfg.flags = 0;
 
        if (pd) {
                memcpy(&lp->cfg, pd, sizeof(lp->cfg));
                lp->io_shift = SMC91X_IO_SHIFT(lp->cfg.flags);
-       } else {
+       }
+
+#if IS_BUILTIN(CONFIG_OF)
+       match = of_match_device(of_match_ptr(smc91x_match), &pdev->dev);
+       if (match) {
+               struct device_node *np = pdev->dev.of_node;
+               u32 val;
+
+               /* Combination of IO widths supported, default to 16-bit */
+               if (!of_property_read_u32(np, "reg-io-width", &val)) {
+                       if (val & 1)
+                               lp->cfg.flags |= SMC91X_USE_8BIT;
+                       if ((val == 0) || (val & 2))
+                               lp->cfg.flags |= SMC91X_USE_16BIT;
+                       if (val & 4)
+                               lp->cfg.flags |= SMC91X_USE_32BIT;
+               } else {
+                       lp->cfg.flags |= SMC91X_USE_16BIT;
+               }
+       }
+#endif
+
+       if (!pd && !match) {
                lp->cfg.flags |= (SMC_CAN_USE_8BIT)  ? SMC91X_USE_8BIT  : 0;
                lp->cfg.flags |= (SMC_CAN_USE_16BIT) ? SMC91X_USE_16BIT : 0;
                lp->cfg.flags |= (SMC_CAN_USE_32BIT) ? SMC91X_USE_32BIT : 0;
@@ -2370,15 +2403,6 @@ static int smc_drv_resume(struct device *dev)
        return 0;
 }
 
-#ifdef CONFIG_OF
-static const struct of_device_id smc91x_match[] = {
-       { .compatible = "smsc,lan91c94", },
-       { .compatible = "smsc,lan91c111", },
-       {},
-};
-MODULE_DEVICE_TABLE(of, smc91x_match);
-#endif
-
 static struct dev_pm_ops smc_drv_pm_ops = {
        .suspend        = smc_drv_suspend,
        .resume         = smc_drv_resume,
index c9d4c872e81da1888cf8678ceb2fd7df5381ac03..47dce918eb0f49741a9dec7ae3cee68354fb7a0a 100644 (file)
@@ -18,8 +18,7 @@
  . 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
+ . along with this program; if not, see <http://www.gnu.org/licenses/>.
  .
  . Information contained in this file was obtained from the LAN91C111
  . manual from SMC.  To get a copy, if you really want one, you can find
@@ -46,7 +45,8 @@
     defined(CONFIG_MACH_LITTLETON) ||\
     defined(CONFIG_MACH_ZYLONITE2) ||\
     defined(CONFIG_ARCH_VIPER) ||\
-    defined(CONFIG_MACH_STARGATE2)
+    defined(CONFIG_MACH_STARGATE2) ||\
+    defined(CONFIG_ARCH_VERSATILE)
 
 #include <asm/mach-types.h>
 
@@ -154,6 +154,8 @@ static inline void SMC_outw(u16 val, void __iomem *ioaddr, int reg)
 #define SMC_outl(v, a, r)      writel(v, (a) + (r))
 #define SMC_insl(a, r, p, l)   readsl((a) + (r), p, l)
 #define SMC_outsl(a, r, p, l)  writesl((a) + (r), p, l)
+#define SMC_insw(a, r, p, l)   readsw((a) + (r), p, l)
+#define SMC_outsw(a, r, p, l)  writesw((a) + (r), p, l)
 #define SMC_IRQ_FLAGS          (-1)    /* from resource */
 
 /* We actually can't write halfwords properly if not word aligned */
@@ -206,23 +208,6 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg)
 #define RPC_LSA_DEFAULT                RPC_LED_TX_RX
 #define RPC_LSB_DEFAULT                RPC_LED_100_10
 
-#elif  defined(CONFIG_ARCH_VERSATILE)
-
-#define SMC_CAN_USE_8BIT       1
-#define SMC_CAN_USE_16BIT      1
-#define SMC_CAN_USE_32BIT      1
-#define SMC_NOWAIT             1
-
-#define SMC_inb(a, r)          readb((a) + (r))
-#define SMC_inw(a, r)          readw((a) + (r))
-#define SMC_inl(a, r)          readl((a) + (r))
-#define SMC_outb(v, a, r)      writeb(v, (a) + (r))
-#define SMC_outw(v, a, r)      writew(v, (a) + (r))
-#define SMC_outl(v, a, r)      writel(v, (a) + (r))
-#define SMC_insl(a, r, p, l)   readsl((a) + (r), p, l)
-#define SMC_outsl(a, r, p, l)  writesl((a) + (r), p, l)
-#define SMC_IRQ_FLAGS          (-1)    /* from resource */
-
 #elif defined(CONFIG_MN10300)
 
 /*
index 8564f23a679615b63df2059b9482444679193c72..6382b7c416f4a4e2e6a7769e2846f19c84565251 100644 (file)
@@ -14,8 +14,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  ***************************************************************************
  * Rewritten, heavily based on smsc911x simple driver by SMSC.
index 9ad5e5d39a03823c4389ee5842d0ecdd0b6db5fc..23953957fed8a37e7e8daa81d6474e9d33b5413d 100644 (file)
@@ -14,8 +14,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  ***************************************************************************/
 #ifndef __SMSC911X_H__
index f433d97aa09703eb295284f97825851f483b7807..9d6effe5f699a08a01dc64e047be64e6c898690c 100644 (file)
@@ -13,8 +13,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  ***************************************************************************
  */
index e441402f77a2e3134d888dd7c1cb49402f27e3d7..c63c76381af66fcd70c6f3972329c8a38793c6be 100644 (file)
@@ -13,8 +13,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  ***************************************************************************
  */
index b4d50d74ba183b29156bce538af3c5c03369d9ea..df8d383acf48ed0da087bb19d144499484ac0376 100644 (file)
@@ -14,9 +14,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * This driver uses the sungem driver (c) David Miller
  * (davem@redhat.com) as its basis.
index b361424d5f5799209d0c21fec9acf974aed2644e..882ce168a799b158c194652a08d31249b3fa7119 100644 (file)
@@ -15,9 +15,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * vendor id: 0x108E (Sun Microsystems, Inc.)
  * device id: 0xabba (Cassini)
index dd0dd6279b4eec8168c006457643568032ee358f..4f1d2549130e3396909f5287776663fa5bfb4e9e 100644 (file)
@@ -2019,7 +2019,6 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                ndev->features = NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO
                    | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
                    NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_RXCSUM
-                   /*| NETIF_F_FRAGLIST */
                    ;
                ndev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG |
                        NETIF_F_TSO | NETIF_F_HW_VLAN_CTAG_TX;
index 7536a4c01293a9b3e97bf1171941b6724213ad6c..c8a54f96cf5dba128eab5d10e771a12bc8b0d0cf 100644 (file)
@@ -1322,7 +1322,7 @@ static void cpsw_hwtstamp_v2(struct cpsw_priv *priv)
        __raw_writel(ETH_P_1588, &priv->regs->ts_ltype);
 }
 
-static int cpsw_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
+static int cpsw_hwtstamp_set(struct net_device *dev, struct ifreq *ifr)
 {
        struct cpsw_priv *priv = netdev_priv(dev);
        struct cpts *cpts = priv->cpts;
@@ -1383,6 +1383,24 @@ static int cpsw_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
        return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
 }
 
+static int cpsw_hwtstamp_get(struct net_device *dev, struct ifreq *ifr)
+{
+       struct cpsw_priv *priv = netdev_priv(dev);
+       struct cpts *cpts = priv->cpts;
+       struct hwtstamp_config cfg;
+
+       if (priv->version != CPSW_VERSION_1 &&
+           priv->version != CPSW_VERSION_2)
+               return -EOPNOTSUPP;
+
+       cfg.flags = 0;
+       cfg.tx_type = cpts->tx_enable ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
+       cfg.rx_filter = (cpts->rx_enable ?
+                        HWTSTAMP_FILTER_PTP_V2_EVENT : HWTSTAMP_FILTER_NONE);
+
+       return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
+}
+
 #endif /*CONFIG_TI_CPTS*/
 
 static int cpsw_ndo_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
@@ -1397,7 +1415,9 @@ static int cpsw_ndo_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
        switch (cmd) {
 #ifdef CONFIG_TI_CPTS
        case SIOCSHWTSTAMP:
-               return cpsw_hwtstamp_ioctl(dev, req);
+               return cpsw_hwtstamp_set(dev, req);
+       case SIOCGHWTSTAMP:
+               return cpsw_hwtstamp_get(dev, req);
 #endif
        case SIOCGMIIPHY:
                data->phy_id = priv->slaves[slave_no].phy->addr;
@@ -1816,6 +1836,8 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
                }
 
                i++;
+               if (i == data->slaves)
+                       break;
        }
 
        return 0;
index 41ba974bf37cb9175c74ab40bba1817e890749e7..cd9b164a0434acb3a51066b5d0e17262a4bdc0dd 100644 (file)
@@ -61,6 +61,7 @@
 #include <linux/davinci_emac.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/of_device.h>
 #include <linux/of_irq.h>
 #include <linux/of_net.h>
 
@@ -1752,10 +1753,14 @@ static const struct net_device_ops emac_netdev_ops = {
 #endif
 };
 
+static const struct of_device_id davinci_emac_of_match[];
+
 static struct emac_platform_data *
 davinci_emac_of_get_pdata(struct platform_device *pdev, struct emac_priv *priv)
 {
        struct device_node *np;
+       const struct of_device_id *match;
+       const struct emac_platform_data *auxdata;
        struct emac_platform_data *pdata = NULL;
        const u8 *mac_addr;
 
@@ -1793,7 +1798,20 @@ davinci_emac_of_get_pdata(struct platform_device *pdev, struct emac_priv *priv)
 
        priv->phy_node = of_parse_phandle(np, "phy-handle", 0);
        if (!priv->phy_node)
-               pdata->phy_id = "";
+               pdata->phy_id = NULL;
+
+       auxdata = pdev->dev.platform_data;
+       if (auxdata) {
+               pdata->interrupt_enable = auxdata->interrupt_enable;
+               pdata->interrupt_disable = auxdata->interrupt_disable;
+       }
+
+       match = of_match_device(davinci_emac_of_match, &pdev->dev);
+       if (match && match->data) {
+               auxdata = match->data;
+               pdata->version = auxdata->version;
+               pdata->hw_ram_addr = auxdata->hw_ram_addr;
+       }
 
        pdev->dev.platform_data = pdata;
 
@@ -2020,8 +2038,14 @@ static const struct dev_pm_ops davinci_emac_pm_ops = {
 };
 
 #if IS_ENABLED(CONFIG_OF)
+static const struct emac_platform_data am3517_emac_data = {
+       .version                = EMAC_VERSION_2,
+       .hw_ram_addr            = 0x01e20000,
+};
+
 static const struct of_device_id davinci_emac_of_match[] = {
        {.compatible = "ti,davinci-dm6467-emac", },
+       {.compatible = "ti,am3517-emac", .data = &am3517_emac_data, },
        {},
 };
 MODULE_DEVICE_TABLE(of, davinci_emac_of_match);
index 628b736e5ae776fcf00333bed8c355e4b518314e..858f9a786b8cf3b27be0bdc51f287e029579d167 100644 (file)
@@ -481,8 +481,7 @@ static void tile_tx_timestamp(struct sk_buff *skb, int instance)
 }
 
 /* Use ioctl() to enable or disable TX or RX timestamping. */
-static int tile_hwtstamp_ioctl(struct net_device *dev, struct ifreq *rq,
-                              int cmd)
+static int tile_hwtstamp_set(struct net_device *dev, struct ifreq *rq)
 {
 #ifdef CONFIG_PTP_1588_CLOCK_TILEGX
        struct hwtstamp_config config;
@@ -535,6 +534,21 @@ static int tile_hwtstamp_ioctl(struct net_device *dev, struct ifreq *rq,
 #endif
 }
 
+static int tile_hwtstamp_get(struct net_device *dev, struct ifreq *rq)
+{
+#ifdef CONFIG_PTP_1588_CLOCK_TILEGX
+       struct tile_net_priv *priv = netdev_priv(dev);
+
+       if (copy_to_user(rq->ifr_data, &priv->stamp_cfg,
+                        sizeof(priv->stamp_cfg)))
+               return -EFAULT;
+
+       return 0;
+#else
+       return -EOPNOTSUPP;
+#endif
+}
+
 static inline bool filter_packet(struct net_device *dev, void *buf)
 {
        /* Filter packets received before we're up. */
@@ -2098,7 +2112,9 @@ static void tile_net_tx_timeout(struct net_device *dev)
 static int tile_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
        if (cmd == SIOCSHWTSTAMP)
-               return tile_hwtstamp_ioctl(dev, rq, cmd);
+               return tile_hwtstamp_set(dev, rq);
+       if (cmd == SIOCGHWTSTAMP)
+               return tile_hwtstamp_get(dev, rq);
 
        return -EOPNOTSUPP;
 }
index 1322546d92ac97287a358cbea644568aedb98168..f6b3212ec339ef512be110a3e5fb4358b6c997c0 100644 (file)
@@ -1170,19 +1170,12 @@ static int tc35815_tx_full(struct net_device *dev)
 static void tc35815_restart(struct net_device *dev)
 {
        struct tc35815_local *lp = netdev_priv(dev);
+       int ret;
 
        if (lp->phy_dev) {
-               int timeout;
-
-               phy_write(lp->phy_dev, MII_BMCR, BMCR_RESET);
-               timeout = 100;
-               while (--timeout) {
-                       if (!(phy_read(lp->phy_dev, MII_BMCR) & BMCR_RESET))
-                               break;
-                       udelay(1);
-               }
-               if (!timeout)
-                       printk(KERN_ERR "%s: BMCR reset failed.\n", dev->name);
+               ret = phy_init_hw(lp->phy_dev);
+               if (ret)
+                       printk(KERN_ERR "%s: PHY init failed.\n", dev->name);
        }
 
        spin_lock_bh(&lp->rx_lock);
index 5fee7d78dc6dd70c89de368f8e336c00e37da602..4a03c594b2b15aee763d3d8b4a8b51f60ef3a558 100644 (file)
@@ -16,9 +16,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index d022bf936572ea857cbcb9f0fded1899077d5a95..ad61d26a44f31d26fc3b6d96f8430a5264e28e6f 100644 (file)
@@ -2172,16 +2172,13 @@ static int velocity_poll(struct napi_struct *napi, int budget)
        unsigned int rx_done;
        unsigned long flags;
 
-       spin_lock_irqsave(&vptr->lock, flags);
        /*
         * Do rx and tx twice for performance (taken from the VIA
         * out-of-tree driver).
         */
-       rx_done = velocity_rx_srv(vptr, budget / 2);
-       velocity_tx_srv(vptr);
-       rx_done += velocity_rx_srv(vptr, budget - rx_done);
+       rx_done = velocity_rx_srv(vptr, budget);
+       spin_lock_irqsave(&vptr->lock, flags);
        velocity_tx_srv(vptr);
-
        /* If budget not fully consumed, exit the polling mode */
        if (rx_done < budget) {
                napi_complete(napi);
@@ -2342,6 +2339,8 @@ static int velocity_change_mtu(struct net_device *dev, int new_mtu)
                if (ret < 0)
                        goto out_free_tmp_vptr_1;
 
+               napi_disable(&vptr->napi);
+
                spin_lock_irqsave(&vptr->lock, flags);
 
                netif_stop_queue(dev);
@@ -2362,6 +2361,8 @@ static int velocity_change_mtu(struct net_device *dev, int new_mtu)
 
                velocity_give_many_rx_descs(vptr);
 
+               napi_enable(&vptr->napi);
+
                mac_enable_int(vptr->mac_regs);
                netif_start_queue(dev);
 
index 1f23641263232fce0255d237976cbf5470e22a6c..2166e879a0961544af056802b1dbcff5a011d2aa 100644 (file)
@@ -1017,7 +1017,7 @@ static int temac_of_probe(struct platform_device *op)
        platform_set_drvdata(op, ndev);
        SET_NETDEV_DEV(ndev, &op->dev);
        ndev->flags &= ~IFF_MULTICAST;  /* clear multicast */
-       ndev->features = NETIF_F_SG | NETIF_F_FRAGLIST;
+       ndev->features = NETIF_F_SG;
        ndev->netdev_ops = &temac_netdev_ops;
        ndev->ethtool_ops = &temac_ethtool_ops;
 #if 0
index b2ff038d6d200abc5dbcd9315806e6791cec3335..f9293da19e260caa8e06829242150ccc72c0ded0 100644 (file)
@@ -1486,7 +1486,7 @@ static int axienet_of_probe(struct platform_device *op)
 
        SET_NETDEV_DEV(ndev, &op->dev);
        ndev->flags &= ~IFF_MULTICAST;  /* clear multicast */
-       ndev->features = NETIF_F_SG | NETIF_F_FRAGLIST;
+       ndev->features = NETIF_F_SG;
        ndev->netdev_ops = &axienet_netdev_ops;
        ndev->ethtool_ops = &axienet_ethtool_ops;
 
index 74234a51c851186c0c9bcfbc140b261724144e20..fefb8cd5eb65e1cb462f2a277c0bda422a89cd60 100644 (file)
@@ -163,26 +163,9 @@ static void xemaclite_enable_interrupts(struct net_local *drvdata)
        __raw_writel(reg_data | XEL_TSR_XMIT_IE_MASK,
                     drvdata->base_addr + XEL_TSR_OFFSET);
 
-       /* Enable the Tx interrupts for the second Buffer if
-        * configured in HW */
-       if (drvdata->tx_ping_pong != 0) {
-               reg_data = __raw_readl(drvdata->base_addr +
-                                  XEL_BUFFER_OFFSET + XEL_TSR_OFFSET);
-               __raw_writel(reg_data | XEL_TSR_XMIT_IE_MASK,
-                            drvdata->base_addr + XEL_BUFFER_OFFSET +
-                            XEL_TSR_OFFSET);
-       }
-
        /* Enable the Rx interrupts for the first buffer */
        __raw_writel(XEL_RSR_RECV_IE_MASK, drvdata->base_addr + XEL_RSR_OFFSET);
 
-       /* Enable the Rx interrupts for the second Buffer if
-        * configured in HW */
-       if (drvdata->rx_ping_pong != 0) {
-               __raw_writel(XEL_RSR_RECV_IE_MASK, drvdata->base_addr +
-                            XEL_BUFFER_OFFSET + XEL_RSR_OFFSET);
-       }
-
        /* Enable the Global Interrupt Enable */
        __raw_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET);
 }
@@ -206,31 +189,10 @@ static void xemaclite_disable_interrupts(struct net_local *drvdata)
        __raw_writel(reg_data & (~XEL_TSR_XMIT_IE_MASK),
                     drvdata->base_addr + XEL_TSR_OFFSET);
 
-       /* Disable the Tx interrupts for the second Buffer
-        * if configured in HW */
-       if (drvdata->tx_ping_pong != 0) {
-               reg_data = __raw_readl(drvdata->base_addr + XEL_BUFFER_OFFSET +
-                                  XEL_TSR_OFFSET);
-               __raw_writel(reg_data & (~XEL_TSR_XMIT_IE_MASK),
-                            drvdata->base_addr + XEL_BUFFER_OFFSET +
-                            XEL_TSR_OFFSET);
-       }
-
        /* Disable the Rx interrupts for the first buffer */
        reg_data = __raw_readl(drvdata->base_addr + XEL_RSR_OFFSET);
        __raw_writel(reg_data & (~XEL_RSR_RECV_IE_MASK),
                     drvdata->base_addr + XEL_RSR_OFFSET);
-
-       /* Disable the Rx interrupts for the second buffer
-        * if configured in HW */
-       if (drvdata->rx_ping_pong != 0) {
-
-               reg_data = __raw_readl(drvdata->base_addr + XEL_BUFFER_OFFSET +
-                                  XEL_RSR_OFFSET);
-               __raw_writel(reg_data & (~XEL_RSR_RECV_IE_MASK),
-                            drvdata->base_addr + XEL_BUFFER_OFFSET +
-                            XEL_RSR_OFFSET);
-       }
 }
 
 /**
@@ -258,6 +220,13 @@ static void xemaclite_aligned_write(void *src_ptr, u32 *dest_ptr,
                *to_u16_ptr++ = *from_u16_ptr++;
                *to_u16_ptr++ = *from_u16_ptr++;
 
+               /* This barrier resolves occasional issues seen around
+                * cases where the data is not properly flushed out
+                * from the processor store buffers to the destination
+                * memory locations.
+                */
+               wmb();
+
                /* Output a word */
                *to_u32_ptr++ = align_buffer;
        }
@@ -273,6 +242,12 @@ static void xemaclite_aligned_write(void *src_ptr, u32 *dest_ptr,
                for (; length > 0; length--)
                        *to_u8_ptr++ = *from_u8_ptr++;
 
+               /* This barrier resolves occasional issues seen around
+                * cases where the data is not properly flushed out
+                * from the processor store buffers to the destination
+                * memory locations.
+                */
+               wmb();
                *to_u32_ptr = align_buffer;
        }
 }
index bdd20b888cf647306f8fc19a78591a0241b0a2a2..7c81ffb861e8cf99d8e66490e6b3026df71879cd 100644 (file)
@@ -27,8 +27,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  *
  * ALTERNATIVELY, this driver may be distributed under the terms of
index bcc224a83734cdb49c25993066babe904a42d32f..25283f17d82f34e093e8b41fe195f82ebb66db26 100644 (file)
@@ -373,7 +373,7 @@ static void ixp_tx_timestamp(struct port *port, struct sk_buff *skb)
        __raw_writel(TX_SNAPSHOT_LOCKED, &regs->channel[ch].ch_event);
 }
 
-static int hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+static int hwtstamp_set(struct net_device *netdev, struct ifreq *ifr)
 {
        struct hwtstamp_config cfg;
        struct ixp46x_ts_regs *regs;
@@ -417,6 +417,32 @@ static int hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
        return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
 }
 
+static int hwtstamp_get(struct net_device *netdev, struct ifreq *ifr)
+{
+       struct hwtstamp_config cfg;
+       struct port *port = netdev_priv(netdev);
+
+       cfg.flags = 0;
+       cfg.tx_type = port->hwts_tx_en ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
+
+       switch (port->hwts_rx_en) {
+       case 0:
+               cfg.rx_filter = HWTSTAMP_FILTER_NONE;
+               break;
+       case PTP_SLAVE_MODE:
+               cfg.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_SYNC;
+               break;
+       case PTP_MASTER_MODE:
+               cfg.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ;
+               break;
+       default:
+               WARN_ON_ONCE(1);
+               return -ERANGE;
+       }
+
+       return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
+}
+
 static int ixp4xx_mdio_cmd(struct mii_bus *bus, int phy_id, int location,
                           int write, u16 cmd)
 {
@@ -959,8 +985,12 @@ static int eth_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
        if (!netif_running(dev))
                return -EINVAL;
 
-       if (cpu_is_ixp46x() && cmd == SIOCSHWTSTAMP)
-               return hwtstamp_ioctl(dev, req, cmd);
+       if (cpu_is_ixp46x()) {
+               if (cmd == SIOCSHWTSTAMP)
+                       return hwtstamp_set(dev, req);
+               if (cmd == SIOCGHWTSTAMP)
+                       return hwtstamp_get(dev, req);
+       }
 
        return phy_mii_ioctl(port->phydev, req, cmd);
 }
index 0b40e1c46f07a15a32ab4ba17c54e610e1ccd64e..0344f71bf4a5f4a7e467875bc803453c38141fd6 100644 (file)
@@ -241,12 +241,6 @@ static char version[] =
  */
 #define NEW_SKB_SIZE (PI_RCV_DATA_K_SIZE_MAX+128)
 
-#ifdef CONFIG_PCI
-#define DFX_BUS_PCI(dev) (dev->bus == &pci_bus_type)
-#else
-#define DFX_BUS_PCI(dev) 0
-#endif
-
 #ifdef CONFIG_EISA
 #define DFX_BUS_EISA(dev) (dev->bus == &eisa_bus_type)
 #else
@@ -436,7 +430,7 @@ static void dfx_port_read_long(DFX_board_t *bp, int offset, u32 *data)
 static void dfx_get_bars(struct device *bdev,
                         resource_size_t *bar_start, resource_size_t *bar_len)
 {
-       int dfx_bus_pci = DFX_BUS_PCI(bdev);
+       int dfx_bus_pci = dev_is_pci(bdev);
        int dfx_bus_eisa = DFX_BUS_EISA(bdev);
        int dfx_bus_tc = DFX_BUS_TC(bdev);
        int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
@@ -518,7 +512,7 @@ static const struct net_device_ops dfx_netdev_ops = {
 static int dfx_register(struct device *bdev)
 {
        static int version_disp;
-       int dfx_bus_pci = DFX_BUS_PCI(bdev);
+       int dfx_bus_pci = dev_is_pci(bdev);
        int dfx_bus_tc = DFX_BUS_TC(bdev);
        int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
        const char *print_name = dev_name(bdev);
@@ -667,7 +661,7 @@ static void dfx_bus_init(struct net_device *dev)
 {
        DFX_board_t *bp = netdev_priv(dev);
        struct device *bdev = bp->bus_dev;
-       int dfx_bus_pci = DFX_BUS_PCI(bdev);
+       int dfx_bus_pci = dev_is_pci(bdev);
        int dfx_bus_eisa = DFX_BUS_EISA(bdev);
        int dfx_bus_tc = DFX_BUS_TC(bdev);
        int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
@@ -813,7 +807,7 @@ static void dfx_bus_uninit(struct net_device *dev)
 {
        DFX_board_t *bp = netdev_priv(dev);
        struct device *bdev = bp->bus_dev;
-       int dfx_bus_pci = DFX_BUS_PCI(bdev);
+       int dfx_bus_pci = dev_is_pci(bdev);
        int dfx_bus_eisa = DFX_BUS_EISA(bdev);
        u8 val;
 
@@ -967,7 +961,7 @@ static int dfx_driver_init(struct net_device *dev, const char *print_name,
 {
        DFX_board_t *bp = netdev_priv(dev);
        struct device *bdev = bp->bus_dev;
-       int dfx_bus_pci = DFX_BUS_PCI(bdev);
+       int dfx_bus_pci = dev_is_pci(bdev);
        int dfx_bus_eisa = DFX_BUS_EISA(bdev);
        int dfx_bus_tc = DFX_BUS_TC(bdev);
        int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
@@ -1877,7 +1871,7 @@ static irqreturn_t dfx_interrupt(int irq, void *dev_id)
        struct net_device *dev = dev_id;
        DFX_board_t *bp = netdev_priv(dev);
        struct device *bdev = bp->bus_dev;
-       int dfx_bus_pci = DFX_BUS_PCI(bdev);
+       int dfx_bus_pci = dev_is_pci(bdev);
        int dfx_bus_eisa = DFX_BUS_EISA(bdev);
        int dfx_bus_tc = DFX_BUS_TC(bdev);
 
@@ -3579,7 +3573,7 @@ static void dfx_unregister(struct device *bdev)
 {
        struct net_device *dev = dev_get_drvdata(bdev);
        DFX_board_t *bp = netdev_priv(dev);
-       int dfx_bus_pci = DFX_BUS_PCI(bdev);
+       int dfx_bus_pci = dev_is_pci(bdev);
        int dfx_bus_tc = DFX_BUS_TC(bdev);
        int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
        resource_size_t bar_start = 0;          /* pointer to port */
index 713d303a06a9e1d2ea06e198a9682beb4bc54fc2..d5f58121b2e22d9463e805ebd3547d79eb874d69 100644 (file)
@@ -351,7 +351,6 @@ static void skfp_remove_one(struct pci_dev *pdev)
        free_netdev(p);
 
        pci_disable_device(pdev);
-       pci_set_drvdata(pdev, NULL);
 }
 
 /*
index 8e01c457015b4dc05c9fd4a85b77a0e3c0ded74b..8a6c720a4cc9a86f073cf73bfdc4157820286bfa 100644 (file)
@@ -9,8 +9,7 @@
  *  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.
+ *  with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * Copyright (C) Hans Alblas PE1AYX <hans@esrac.ele.tue.nl>
  * Copyright (C) 2004, 05 Ralf Baechle DL5RB <ralf@linux-mips.org>
index 00ed75155ce8d4b7faff9ca9f3a98c28d355ff4c..cd85f24637e1558207e4472941fd13a5efd3abd1 100644 (file)
@@ -213,10 +213,8 @@ static int rr_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                                    rrpriv->tx_ring_dma);
        if (rrpriv->regs)
                pci_iounmap(pdev, rrpriv->regs);
-       if (pdev) {
+       if (pdev)
                pci_release_regions(pdev);
-               pci_set_drvdata(pdev, NULL);
-       }
  out2:
        free_netdev(dev);
  out3:
@@ -244,7 +242,6 @@ static void rr_remove_one(struct pci_dev *pdev)
        pci_iounmap(pdev, rr->regs);
        pci_release_regions(pdev);
        pci_disable_device(pdev);
-       pci_set_drvdata(pdev, NULL);
        free_netdev(dev);
 }
 
index e6fe0d80d6122fcd8dfcf7bb65fa71dac68c1e73..a26eecb1212ce735a2de234e31a12ae9a4e90b37 100644 (file)
@@ -12,8 +12,7 @@
  * 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.
+ * this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * Authors:
  *   Haiyang Zhang <haiyangz@microsoft.com>
index 2b0480416b31a2586afd0467ab539e1065caeb5b..93b485b96249b32347586f6494b7e1d15ab3cc2a 100644 (file)
@@ -11,8 +11,7 @@
  * 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.
+ * this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * Authors:
  *   Haiyang Zhang <haiyangz@microsoft.com>
index 524f713f60170b2d5632bbac6958ae0529a80b1c..9184c82d5c502f6743c6431fe9d61e7f80106c2a 100644 (file)
@@ -11,8 +11,7 @@
  * 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.
+ * this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * Authors:
  *   Haiyang Zhang <haiyangz@microsoft.com>
index 0775f0aefd1e67715ab77750ac898660d3ca6267..1084e5de3ceb4c805d2ef9e98b90c6d68a9a9991 100644 (file)
@@ -11,8 +11,7 @@
  * 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.
+ * this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * Authors:
  *   Haiyang Zhang <haiyangz@microsoft.com>
index 2cbe1c24999660a198ededf163584d9cc9e51bdd..ab31544bc25487ac82b1703beef9df6c069e615e 100644 (file)
@@ -987,7 +987,6 @@ err_gpio_dir:
 err_slp_tr:
        gpio_free(lp->rstn);
 err_rstn:
-       spi_set_drvdata(spi, NULL);
        mutex_destroy(&lp->bmux);
        ieee802154_free_device(lp->dev);
        return rc;
@@ -1006,7 +1005,6 @@ static int at86rf230_remove(struct spi_device *spi)
                gpio_free(lp->slp_tr);
        gpio_free(lp->rstn);
 
-       spi_set_drvdata(spi, NULL);
        mutex_destroy(&lp->bmux);
        ieee802154_free_device(lp->dev);
 
index c6e46d6e9f752040e2a6aa48588466556fbc09e9..246befa4ba0571383f13cbdef2a701156b0326d0 100644 (file)
@@ -715,7 +715,6 @@ static int mrf24j40_remove(struct spi_device *spi)
         * complete? */
 
        /* Clean up the SPI stuff. */
-       spi_set_drvdata(spi, NULL);
        kfree(devrec->buf);
        kfree(devrec);
        return 0;
index 7a1f684edcb597b5cdd499d54517708f598a1e7a..5b7a665c6d8365fddb4148c188bd7665f094223a 100644 (file)
@@ -15,8 +15,7 @@
  *  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.
+ *  with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/init.h>
index a908df7c4b9dcada826e9da35e3ecfe17b0febe8..019a3e848bcb7d7db1465fd5c3129a765c8a0fe0 100644 (file)
@@ -25,9 +25,7 @@
  *     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
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  *     
  ********************************************************************/
 
index d6d9d2e5ad492306eb695692e8b40fe78010331d..6827777cbeea95c77ead150bccd6dc3c97a2a5d8 100644 (file)
@@ -22,9 +22,7 @@
  *     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
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  *     
  ********************************************************************/
 
index e91216452379f318d53b2c953555593d7c796eae..a9a81358477bcafc817b16497312ab29b850b760 100644 (file)
@@ -25,9 +25,7 @@
  *     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
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  *     
  ********************************************************************/
 
index 75714bc7103065501bc5bfc938584a06b77cebae..f237136f38278ca018f6d612bd48a28568b50104 100644 (file)
@@ -22,9 +22,7 @@
  *     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
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  *     
  ********************************************************************/
 
index 0dcdf1592f6b2ee516d2d57c34cf78a5dd425441..282120430f1271bfbfb4ea06b301d4560ef1daf0 100644 (file)
@@ -34,9 +34,7 @@
  *     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
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  ********************************************************************/
 
index 317b7fd69bb35a6035445f44ab8e6b503a6f0004..4829fa22cb299f8286766154853d199dcb6a3b09 100644 (file)
@@ -25,9 +25,7 @@
  *     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
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  ********************************************************************/
 
index 9abaec27f96259c5c3360d12f7ffb3dfc3699832..2900af091c2d5f718bd14a083fb42cf11a72af3b 100644 (file)
@@ -17,8 +17,7 @@ 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.
+this program; if not, see <http://www.gnu.org/licenses/>.
 
 F01 Oct/02/02: Modify code for V0.11(move out back to back transfer)
 F02 Oct/28/02: Add SB device ID for 3147 and 3177.
@@ -408,7 +407,6 @@ static int via_ircc_open(struct pci_dev *pdev, chipio_t *info, unsigned int id)
  err_out2:
        release_region(self->io.fir_base, self->io.fir_ext);
  err_out1:
-       pci_set_drvdata(pdev, NULL);
        free_netdev(dev);
        return err;
 }
@@ -442,7 +440,6 @@ static void via_remove_one(struct pci_dev *pdev)
        if (self->rx_buff.head)
                dma_free_coherent(&pdev->dev, self->rx_buff.truesize,
                                  self->rx_buff.head, self->rx_buff_dma);
-       pci_set_drvdata(pdev, NULL);
 
        free_netdev(self->netdev);
 
index f903a6a2dcb7d5c5969ec5f384dbb4705e916670..7ce820ecc361519243a98f2f150eb145b2715f74 100644 (file)
@@ -18,8 +18,7 @@ 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.
+this program; if not, see <http://www.gnu.org/licenses/>.
 
  * Comment:
  * jul/08/2002 : Rx buffer length should use Rx ring ptr.      
index c5bd58b4d8a82a61ad2a87a3f854f7d6b033e803..485006604bbc0da7716e754485c945f064c5188e 100644 (file)
@@ -15,9 +15,7 @@
  *     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
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  ********************************************************************/
 
@@ -1695,7 +1693,6 @@ out_freedev:
 out_disable:
        pci_disable_device(pdev);
 out:
-       pci_set_drvdata(pdev, NULL);
        return -ENODEV;
 }
 
@@ -1721,8 +1718,6 @@ static void vlsi_irda_remove(struct pci_dev *pdev)
 
        free_netdev(ndev);
 
-       pci_set_drvdata(pdev, NULL);
-
        IRDA_MESSAGE("%s: %s removed\n", drivername, pci_name(pdev));
 }
 
index a076eb1253490ac4557feb743c78d368efa4bbe4..56399204e68cf38503d831585e7931ef9b04d3f7 100644 (file)
@@ -18,9 +18,7 @@
  *     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
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  ********************************************************************/
 
index acf93798dc675929394e82ffed96cd1616c3a31d..cfb91570cdddccdfc02f9b860d1bf26d8b836b48 100644 (file)
@@ -820,13 +820,11 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
        if (lowerdev == NULL)
                return -ENODEV;
 
-       /* When creating macvlans on top of other macvlans - use
+       /* When creating macvlans or macvtaps on top of other macvlans - use
         * the real device as the lowerdev.
         */
-       if (lowerdev->rtnl_link_ops == dev->rtnl_link_ops) {
-               struct macvlan_dev *lowervlan = netdev_priv(lowerdev);
-               lowerdev = lowervlan->lowerdev;
-       }
+       if (netif_is_macvlan(lowerdev))
+               lowerdev = macvlan_dev_real_dev(lowerdev);
 
        if (!tb[IFLA_MTU])
                dev->mtu = lowerdev->mtu;
index dc76670c2f2a16c244d0ec58a779a8742d0e6c3e..99d8d67be520eaa15d1345d1b8ecf0a1dd6a5c25 100644 (file)
@@ -588,7 +588,7 @@ static int macvtap_skb_from_vnet_hdr(struct sk_buff *skb,
        return 0;
 }
 
-static int macvtap_skb_to_vnet_hdr(const struct sk_buff *skb,
+static void macvtap_skb_to_vnet_hdr(const struct sk_buff *skb,
                                   struct virtio_net_hdr *vnet_hdr)
 {
        memset(vnet_hdr, 0, sizeof(*vnet_hdr));
@@ -619,8 +619,6 @@ static int macvtap_skb_to_vnet_hdr(const struct sk_buff *skb,
        } else if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
                vnet_hdr->flags = VIRTIO_NET_HDR_F_DATA_VALID;
        } /* else everything is zero */
-
-       return 0;
 }
 
 /* Get packet from user space buffer */
@@ -744,7 +742,7 @@ err:
        rcu_read_lock();
        vlan = rcu_dereference(q->vlan);
        if (vlan)
-               vlan->dev->stats.tx_dropped++;
+               this_cpu_inc(vlan->pcpu_stats->tx_dropped);
        rcu_read_unlock();
 
        return err;
@@ -767,11 +765,10 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q,
                                const struct sk_buff *skb,
                                const struct iovec *iv, int len)
 {
-       struct macvlan_dev *vlan;
        int ret;
        int vnet_hdr_len = 0;
        int vlan_offset = 0;
-       int copied;
+       int copied, total;
 
        if (q->flags & IFF_VNET_HDR) {
                struct virtio_net_hdr vnet_hdr;
@@ -779,14 +776,13 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q,
                if ((len -= vnet_hdr_len) < 0)
                        return -EINVAL;
 
-               ret = macvtap_skb_to_vnet_hdr(skb, &vnet_hdr);
-               if (ret)
-                       return ret;
+               macvtap_skb_to_vnet_hdr(skb, &vnet_hdr);
 
                if (memcpy_toiovecend(iv, (void *)&vnet_hdr, 0, sizeof(vnet_hdr)))
                        return -EFAULT;
        }
-       copied = vnet_hdr_len;
+       total = copied = vnet_hdr_len;
+       total += skb->len;
 
        if (!vlan_tx_tag_present(skb))
                len = min_t(int, skb->len, len);
@@ -801,6 +797,7 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q,
 
                vlan_offset = offsetof(struct vlan_ethhdr, h_vlan_proto);
                len = min_t(int, skb->len + VLAN_HLEN, len);
+               total += VLAN_HLEN;
 
                copy = min_t(int, vlan_offset, len);
                ret = skb_copy_datagram_const_iovec(skb, 0, iv, copied, copy);
@@ -818,22 +815,12 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q,
        }
 
        ret = skb_copy_datagram_const_iovec(skb, vlan_offset, iv, copied, len);
-       copied += len;
 
 done:
-       rcu_read_lock();
-       vlan = rcu_dereference(q->vlan);
-       if (vlan) {
-               preempt_disable();
-               macvlan_count_rx(vlan, copied - vnet_hdr_len, ret == 0, 0);
-               preempt_enable();
-       }
-       rcu_read_unlock();
-
-       return ret ? ret : copied;
+       return ret ? ret : total;
 }
 
-static ssize_t macvtap_do_read(struct macvtap_queue *q, struct kiocb *iocb,
+static ssize_t macvtap_do_read(struct macvtap_queue *q,
                               const struct iovec *iv, unsigned long len,
                               int noblock)
 {
@@ -884,8 +871,10 @@ static ssize_t macvtap_aio_read(struct kiocb *iocb, const struct iovec *iv,
                goto out;
        }
 
-       ret = macvtap_do_read(q, iocb, iv, len, file->f_flags & O_NONBLOCK);
-       ret = min_t(ssize_t, ret, len); /* XXX copied from tun.c. Why? */
+       ret = macvtap_do_read(q, iv, len, file->f_flags & O_NONBLOCK);
+       ret = min_t(ssize_t, ret, len);
+       if (ret > 0)
+               iocb->ki_pos = ret;
 out:
        return ret;
 }
@@ -1116,7 +1105,7 @@ static int macvtap_recvmsg(struct kiocb *iocb, struct socket *sock,
        int ret;
        if (flags & ~(MSG_DONTWAIT|MSG_TRUNC))
                return -EINVAL;
-       ret = macvtap_do_read(q, iocb, m->msg_iov, total_len,
+       ret = macvtap_do_read(q, m->msg_iov, total_len,
                          flags & MSG_DONTWAIT);
        if (ret > total_len) {
                m->msg_flags |= MSG_TRUNC;
index 3ae28f420868fc35af3b3ed4e652f96e43a8f35b..26fa05a472b467679071ee6d76642e87f8bc10cf 100644 (file)
@@ -335,6 +335,21 @@ static struct phy_driver ksphy_driver[] = {
        .suspend        = genphy_suspend,
        .resume         = genphy_resume,
        .driver         = { .owner = THIS_MODULE,},
+}, {
+       .phy_id         = PHY_ID_KSZ8041RNLI,
+       .phy_id_mask    = 0x00fffff0,
+       .name           = "Micrel KSZ8041RNLI",
+       .features       = PHY_BASIC_FEATURES |
+                         SUPPORTED_Pause | SUPPORTED_Asym_Pause,
+       .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
+       .config_init    = kszphy_config_init,
+       .config_aneg    = genphy_config_aneg,
+       .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,
        .phy_id_mask    = 0x00fffff0,
index 36c6994436b7ce7edb9ff9a0d9725c1aa09a4407..e3dd69100da882a913ec754df29a5099b550ee2f 100644 (file)
@@ -289,6 +289,7 @@ int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd)
        cmd->supported = phydev->supported;
 
        cmd->advertising = phydev->advertising;
+       cmd->lp_advertising = phydev->lp_advertising;
 
        ethtool_cmd_speed_set(cmd, phydev->speed);
        cmd->duplex = phydev->duplex;
@@ -317,6 +318,7 @@ int phy_mii_ioctl(struct phy_device *phydev,
 {
        struct mii_ioctl_data *mii_data = if_mii(ifr);
        u16 val = mii_data->val_in;
+       int ret = 0;
 
        switch (cmd) {
        case SIOCGMIIPHY:
@@ -360,11 +362,8 @@ int phy_mii_ioctl(struct phy_device *phydev,
                              mii_data->reg_num, val);
 
                if (mii_data->reg_num == MII_BMCR &&
-                   val & BMCR_RESET &&
-                   phydev->drv->config_init) {
-                       phy_scan_fixups(phydev);
-                       phydev->drv->config_init(phydev);
-               }
+                   val & BMCR_RESET)
+                       ret = phy_init_hw(phydev);
                break;
 
        case SIOCSHWTSTAMP:
@@ -376,7 +375,7 @@ int phy_mii_ioctl(struct phy_device *phydev,
                return -EOPNOTSUPP;
        }
 
-       return 0;
+       return ret;
 }
 EXPORT_SYMBOL(phy_mii_ioctl);
 
index d6447b3f7409d2b19a5c5186f017780bb29080b8..5a619f0dcf73c7ca47b728116786aaa65c236f57 100644 (file)
@@ -364,7 +364,11 @@ int phy_device_register(struct phy_device *phydev)
        phydev->bus->phy_map[phydev->addr] = phydev;
 
        /* Run all of the fixups for this PHY */
-       phy_scan_fixups(phydev);
+       err = phy_init_hw(phydev);
+       if (err) {
+               pr_err("PHY %d failed to initialize\n", phydev->addr);
+               goto out;
+       }
 
        err = device_add(&phydev->dev);
        if (err) {
@@ -497,6 +501,47 @@ void phy_disconnect(struct phy_device *phydev)
 }
 EXPORT_SYMBOL(phy_disconnect);
 
+/**
+ * phy_poll_reset - Safely wait until a PHY reset has properly completed
+ * @phydev: The PHY device to poll
+ *
+ * Description: According to IEEE 802.3, Section 2, Subsection 22.2.4.1.1, as
+ *   published in 2008, a PHY reset may take up to 0.5 seconds.  The MII BMCR
+ *   register must be polled until the BMCR_RESET bit clears.
+ *
+ *   Furthermore, any attempts to write to PHY registers may have no effect
+ *   or even generate MDIO bus errors until this is complete.
+ *
+ *   Some PHYs (such as the Marvell 88E1111) don't entirely conform to the
+ *   standard and do not fully reset after the BMCR_RESET bit is set, and may
+ *   even *REQUIRE* a soft-reset to properly restart autonegotiation.  In an
+ *   effort to support such broken PHYs, this function is separate from the
+ *   standard phy_init_hw() which will zero all the other bits in the BMCR
+ *   and reapply all driver-specific and board-specific fixups.
+ */
+static int phy_poll_reset(struct phy_device *phydev)
+{
+       /* Poll until the reset bit clears (50ms per retry == 0.6 sec) */
+       unsigned int retries = 12;
+       int ret;
+
+       do {
+               msleep(50);
+               ret = phy_read(phydev, MII_BMCR);
+               if (ret < 0)
+                       return ret;
+       } while (ret & BMCR_RESET && --retries);
+       if (ret & BMCR_RESET)
+               return -ETIMEDOUT;
+
+       /*
+        * Some chips (smsc911x) may still need up to another 1ms after the
+        * BMCR_RESET bit is cleared before they are usable.
+        */
+       msleep(1);
+       return 0;
+}
+
 int phy_init_hw(struct phy_device *phydev)
 {
        int ret;
@@ -504,12 +549,21 @@ int phy_init_hw(struct phy_device *phydev)
        if (!phydev->drv || !phydev->drv->config_init)
                return 0;
 
+       ret = phy_write(phydev, MII_BMCR, BMCR_RESET);
+       if (ret < 0)
+               return ret;
+
+       ret = phy_poll_reset(phydev);
+       if (ret < 0)
+               return ret;
+
        ret = phy_scan_fixups(phydev);
        if (ret < 0)
                return ret;
 
        return phydev->drv->config_init(phydev);
 }
+EXPORT_SYMBOL(phy_init_hw);
 
 /**
  * phy_attach_direct - attach a network device to a given PHY device pointer
@@ -839,6 +893,8 @@ int genphy_read_status(struct phy_device *phydev)
        if (err)
                return err;
 
+       phydev->lp_advertising = 0;
+
        if (AUTONEG_ENABLE == phydev->autoneg) {
                if (phydev->supported & (SUPPORTED_1000baseT_Half
                                        | SUPPORTED_1000baseT_Full)) {
@@ -852,6 +908,8 @@ int genphy_read_status(struct phy_device *phydev)
                        if (adv < 0)
                                return adv;
 
+                       phydev->lp_advertising =
+                               mii_stat1000_to_ethtool_lpa_t(lpagb);
                        lpagb &= adv << 2;
                }
 
@@ -860,6 +918,8 @@ int genphy_read_status(struct phy_device *phydev)
                if (lpa < 0)
                        return lpa;
 
+               phydev->lp_advertising |= mii_lpa_to_ethtool_lpa_t(lpa);
+
                adv = phy_read(phydev, MII_ADVERTISE);
 
                if (adv < 0)
index f3bea1346021273b85cfc8d5016e3def067eec46..98fb9f360d83c464373036c050ff9382a1ff7372 100644 (file)
@@ -325,7 +325,6 @@ static int ks8995_probe(struct spi_device *spi)
        return 0;
 
 err_drvdata:
-       spi_set_drvdata(spi, NULL);
        kfree(ks);
        return err;
 }
@@ -337,7 +336,6 @@ static int ks8995_remove(struct spi_device *spi)
        ks8995 = spi_get_drvdata(spi);
        sysfs_remove_bin_file(&spi->dev.kobj, &ks8995_registers_attr);
 
-       spi_set_drvdata(spi, NULL);
        kfree(ks8995);
 
        return 0;
index 508e4359338bc385dc2a0901e24a6351f735f780..14372c65a7e8209b5f97da6416ef80d1f41a522c 100644 (file)
@@ -64,6 +64,7 @@
 
 #define PHY_ID_VSC8234                 0x000fc620
 #define PHY_ID_VSC8244                 0x000fc6c0
+#define PHY_ID_VSC8514                 0x00070670
 #define PHY_ID_VSC8574                 0x000704a0
 #define PHY_ID_VSC8662                 0x00070660
 #define PHY_ID_VSC8221                 0x000fc550
@@ -131,6 +132,7 @@ static int vsc82xx_config_intr(struct phy_device *phydev)
                err = phy_write(phydev, MII_VSC8244_IMASK,
                        (phydev->drv->phy_id == PHY_ID_VSC8234 ||
                         phydev->drv->phy_id == PHY_ID_VSC8244 ||
+                        phydev->drv->phy_id == PHY_ID_VSC8514 ||
                         phydev->drv->phy_id == PHY_ID_VSC8574) ?
                                MII_VSC8244_IMASK_MASK :
                                MII_VSC8221_IMASK_MASK);
@@ -245,6 +247,18 @@ static struct phy_driver vsc82xx_driver[] = {
        .ack_interrupt  = &vsc824x_ack_interrupt,
        .config_intr    = &vsc82xx_config_intr,
        .driver         = { .owner = THIS_MODULE,},
+}, {
+       .phy_id         = PHY_ID_VSC8514,
+       .name           = "Vitesse VSC8514",
+       .phy_id_mask    = 0x000ffff0,
+       .features       = PHY_GBIT_FEATURES,
+       .flags          = PHY_HAS_INTERRUPT,
+       .config_init    = &vsc824x_config_init,
+       .config_aneg    = &vsc82x4_config_aneg,
+       .read_status    = &genphy_read_status,
+       .ack_interrupt  = &vsc824x_ack_interrupt,
+       .config_intr    = &vsc82xx_config_intr,
+       .driver         = { .owner = THIS_MODULE,},
 }, {
        .phy_id         = PHY_ID_VSC8574,
        .name           = "Vitesse VSC8574",
@@ -315,6 +329,7 @@ module_exit(vsc82xx_exit);
 static struct mdio_device_id __maybe_unused vitesse_tbl[] = {
        { PHY_ID_VSC8234, 0x000ffff0 },
        { PHY_ID_VSC8244, 0x000fffc0 },
+       { PHY_ID_VSC8514, 0x000ffff0 },
        { PHY_ID_VSC8574, 0x000ffff0 },
        { PHY_ID_VSC8662, 0x000ffff0 },
        { PHY_ID_VSC8221, 0x000ffff0 },
index 9a1849a83e2ad06778a8b0fb612641ce17a8128d..911b21602ff271885c2dbfb4c5c04f69fb028e7e 100644 (file)
@@ -27,8 +27,7 @@
  *   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
+ *   along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  *
  * Changelog:
index 34b0de09d88190a04e30d867e31ad001f35f0e34..736050d6b4516b3de85eb2c214d0464ff690d99f 100644 (file)
@@ -1366,6 +1366,8 @@ static int team_user_linkup_option_get(struct team *team,
        return 0;
 }
 
+static void __team_carrier_check(struct team *team);
+
 static int team_user_linkup_option_set(struct team *team,
                                       struct team_gsetter_ctx *ctx)
 {
@@ -1373,6 +1375,7 @@ static int team_user_linkup_option_set(struct team *team,
 
        port->user.linkup = ctx->data.bool_val;
        team_refresh_port_linkup(port);
+       __team_carrier_check(port->team);
        return 0;
 }
 
@@ -1392,6 +1395,7 @@ static int team_user_linkup_en_option_set(struct team *team,
 
        port->user.linkup_enabled = ctx->data.bool_val;
        team_refresh_port_linkup(port);
+       __team_carrier_check(port->team);
        return 0;
 }
 
index 782e38bfc1eeea38215492aee5aaa587cc534525..a835c245c9240faa6ac3bdfcc70f00885a04cd09 100644 (file)
@@ -110,7 +110,7 @@ struct tap_filter {
        unsigned char   addr[FLT_EXACT_COUNT][ETH_ALEN];
 };
 
-/* DEFAULT_MAX_NUM_RSS_QUEUES were choosed to let the rx/tx queues allocated for
+/* DEFAULT_MAX_NUM_RSS_QUEUES were chosen to let the rx/tx queues allocated for
  * the netdevice to be fit in one page. So we can make sure the success of
  * memory allocation. TODO: increase the limit. */
 #define MAX_TAP_QUEUES DEFAULT_MAX_NUM_RSS_QUEUES
@@ -119,7 +119,7 @@ struct tap_filter {
 #define TUN_FLOW_EXPIRE (3 * HZ)
 
 /* A tun_file connects an open character device to a tuntap netdevice. It
- * also contains all socket related strctures (except sock_fprog and tap_filter)
+ * also contains all socket related structures (except sock_fprog and tap_filter)
  * to serve as one transmit queue for tuntap device. The sock_fprog and
  * tap_filter were kept in tun_struct since they were used for filtering for the
  * netdevice not for a specific queue (at least I didn't see the requirement for
@@ -342,7 +342,7 @@ unlock:
 }
 
 /* We try to identify a flow through its rxhash first. The reason that
- * we do not check rxq no. is becuase some cards(e.g 82599), chooses
+ * we do not check rxq no. is because some cards(e.g 82599), chooses
  * the rxq based on the txq where the last packet of the flow comes. As
  * the userspace application move between processors, we may get a
  * different rxq no. here. If we could not get rxhash, then we would
@@ -531,7 +531,7 @@ static int tun_attach(struct tun_struct *tun, struct file *file, bool skip_filte
 
        err = 0;
 
-       /* Re-attach the filter to presist device */
+       /* Re-attach the filter to persist device */
        if (!skip_filter && (tun->filter_attached == true)) {
                err = sk_attach_filter(&tun->fprog, tfile->socket.sk);
                if (!err)
@@ -819,9 +819,9 @@ static void tun_poll_controller(struct net_device *dev)
         * Tun only receives frames when:
         * 1) the char device endpoint gets data from user space
         * 2) the tun socket gets a sendmsg call from user space
-        * Since both of those are syncronous operations, we are guaranteed
+        * Since both of those are synchronous operations, we are guaranteed
         * never to have pending data when we poll for it
-        * so theres nothing to do here but return.
+        * so there is nothing to do here but return.
         * We need this though so netpoll recognizes us as an interface that
         * supports polling, which enables bridge devices in virt setups to
         * still use netconsole
@@ -1184,7 +1184,7 @@ static ssize_t tun_put_user(struct tun_struct *tun,
 {
        struct tun_pi pi = { 0, skb->protocol };
        ssize_t total = 0;
-       int vlan_offset = 0;
+       int vlan_offset = 0, copied;
 
        if (!(tun->flags & TUN_NO_PI)) {
                if ((len -= sizeof(pi)) < 0)
@@ -1248,6 +1248,8 @@ static ssize_t tun_put_user(struct tun_struct *tun,
                total += tun->vnet_hdr_sz;
        }
 
+       copied = total;
+       total += skb->len;
        if (!vlan_tx_tag_present(skb)) {
                len = min_t(int, skb->len, len);
        } else {
@@ -1262,24 +1264,24 @@ static ssize_t tun_put_user(struct tun_struct *tun,
 
                vlan_offset = offsetof(struct vlan_ethhdr, h_vlan_proto);
                len = min_t(int, skb->len + VLAN_HLEN, len);
+               total += VLAN_HLEN;
 
                copy = min_t(int, vlan_offset, len);
-               ret = skb_copy_datagram_const_iovec(skb, 0, iv, total, copy);
+               ret = skb_copy_datagram_const_iovec(skb, 0, iv, copied, copy);
                len -= copy;
-               total += copy;
+               copied += copy;
                if (ret || !len)
                        goto done;
 
                copy = min_t(int, sizeof(veth), len);
-               ret = memcpy_toiovecend(iv, (void *)&veth, total, copy);
+               ret = memcpy_toiovecend(iv, (void *)&veth, copied, copy);
                len -= copy;
-               total += copy;
+               copied += copy;
                if (ret || !len)
                        goto done;
        }
 
-       skb_copy_datagram_const_iovec(skb, vlan_offset, iv, total, len);
-       total += len;
+       skb_copy_datagram_const_iovec(skb, vlan_offset, iv, copied, len);
 
 done:
        tun->dev->stats.tx_packets++;
@@ -1289,8 +1291,7 @@ done:
 }
 
 static ssize_t tun_do_read(struct tun_struct *tun, struct tun_file *tfile,
-                          struct kiocb *iocb, const struct iovec *iv,
-                          ssize_t len, int noblock)
+                          const struct iovec *iv, ssize_t len, int noblock)
 {
        DECLARE_WAITQUEUE(wait, current);
        struct sk_buff *skb;
@@ -1353,9 +1354,11 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv,
                goto out;
        }
 
-       ret = tun_do_read(tun, tfile, iocb, iv, len,
+       ret = tun_do_read(tun, tfile, iv, len,
                          file->f_flags & O_NONBLOCK);
        ret = min_t(ssize_t, ret, len);
+       if (ret > 0)
+               iocb->ki_pos = ret;
 out:
        tun_put(tun);
        return ret;
@@ -1452,7 +1455,7 @@ static int tun_recvmsg(struct kiocb *iocb, struct socket *sock,
                                         SOL_PACKET, TUN_TX_TIMESTAMP);
                goto out;
        }
-       ret = tun_do_read(tun, tfile, iocb, m->msg_iov, total_len,
+       ret = tun_do_read(tun, tfile, m->msg_iov, total_len,
                          flags & MSG_DONTWAIT);
        if (ret > total_len) {
                m->msg_flags |= MSG_TRUNC;
index bdaa12d07a127fae11a6209986d0473c32644f27..bad857aacd1a6898bf5e19d0fc8246dcd514085c 100644 (file)
@@ -16,8 +16,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef _ASIX_H
index 577c72d5f3690dd3917d05fc8dcb9f9d89c354a4..5c55f11572baa0a3e0dd3877ae886935cb8a6eb9 100644 (file)
@@ -16,8 +16,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "asix.h"
index 386a3df53678a23761308938221f4aa79b520538..9765a7d4766dcd4a717bd7cd0bea56c71953deb1 100644 (file)
@@ -16,8 +16,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "asix.h"
index 723b3879ecc2e195515037404f1bb4eae8a6f3f4..5f18fcb8dcc767494d26373aabc4d137592eb14d 100644 (file)
@@ -21,8 +21,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "asix.h"
index 8e8d0fcd4979f10c71ff1e37140313d255429847..d6f64dad05bcb707c0c26dbe2886abd73e760db1 100644 (file)
@@ -14,8 +14,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/module.h>
index df507e6dbb9c99d9a15f718128e008f06ba11cdb..da6b8a5dcc0debc9522758f8f6558c474d19dd4e 100644 (file)
@@ -24,8 +24,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  * 
  * Should you need to contact me, the author, you can do so either by
  * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
index 08d55b6bf272bc5293a8a8d059d54d652aca27e1..57fd7170ae60849bf377211ca285c2b7df7d5be8 100644 (file)
@@ -14,8 +14,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/module.h>
index 2023f3ea891e6bf75f0c62d3d78213e30d1a11f4..4b1c0f3f727da0d8061782dc1cf7d0c2caeeba6f 100644 (file)
@@ -14,8 +14,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 // #define     DEBUG                   // error path messages, extra info
index 0d1fe89ae0bde94d813a44bc9c507fa3dac01f16..3b2593a7602b76291bf61bcaee7b72ed9041459f 100644 (file)
@@ -13,8 +13,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/module.h>
index 1e207f086b759416a916cb9180af1be85e8a3fce..5233e6d070ec9d1758a23aca962bed3d7a2eb459 100644 (file)
@@ -14,8 +14,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/module.h>
index a7e3f4e55bf3651b3874710ffcf4cfcdeb37e299..3569da1135c140f65a7b1c56430ca064594b8a5a 100644 (file)
@@ -14,8 +14,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 // #define     DEBUG                   // error path messages, extra info
index ace9e74ffbdd90ece5da77dab76890d46877a344..4ff70b22c6eec0e0516373b02b66c71fae158028 100644 (file)
@@ -20,8 +20,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/module.h>
index afb117c16d2d3688b62952ec2251f29c29eee06c..250fc21d97810a0cb212d0abc11d25168479a8fc 100644 (file)
@@ -25,8 +25,7 @@
  *     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.
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  ****************************************************************/
 
index 808d6506da41293ed9689ab2c064cfca7a99853d..acfcc32b323d87c1b6f4e64788802af932f74319 100644 (file)
@@ -15,8 +15,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
index 03832d3780aa6134059dc4768bb7614d71075b82..aea68bc33583c88a32a42ee41fea24111b5e5a2a 100644 (file)
@@ -36,8 +36,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/crc32.h>
index 93e0716a118c309f90859e4ee913d2e2e32b41e0..8b2493f05a1c6415e4fd731d6fc5b1567a705262 100644 (file)
@@ -13,8 +13,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 // #define     DEBUG                   // error path messages, extra info
index 0fcc8e65a06800a390b2aab1ab4ff1f7486cd051..ee705b7bba08b09f71051b83b52099446406dc3c 100644 (file)
@@ -13,8 +13,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 // #define     DEBUG                   // error path messages, extra info
index cc49aac70224910f63fc6c5ed6b0b2fc720ff674..72aee8516ca8511c7b02d307ac51dcf2425fa3f2 100644 (file)
@@ -13,8 +13,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 #include <linux/module.h>
 #include <linux/init.h>
index a79e9d3349284ac7c8371ae495d03110f87a3d42..a251588762ec6aa4053ec8af337e714411ec877c 100644 (file)
@@ -21,8 +21,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #define DRIVER_VERSION "v.2.0"
index 66ebbacf066f6692ba21d2fa07538535827074b9..0217b282e7ecaf3fdb6cd47ad7f813fddc71a445 100644 (file)
@@ -13,8 +13,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  *****************************************************************************/
 
index 67eba39e6ee23cb28248f0be099313c320339799..2c7ea8fd184f2ab397e42c0c79408aea9554eb45 100644 (file)
@@ -13,8 +13,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  *****************************************************************************/
 
index 3f38ba868f6182152093e8efad0a864439c5cef0..96f5eee20fa43b84da5ac21f5752ebb65785c99b 100644 (file)
@@ -13,8 +13,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  *****************************************************************************/
 
index f360ee372554d5b1ce40c789aac44a6d066fc730..526faa0c44e65ee76c420cd4aa104a72da213ee5 100644 (file)
@@ -13,8 +13,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  *****************************************************************************/
 
index 8494bb53ebdc9f33abee1d8e5a27f7d0dea3cc17..56c175ebae3ca9b55a40e019e61b5a59840d35de 100644 (file)
@@ -14,8 +14,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 35c90307d473009250aa7e711d8e4949db891607..25d1e667a0616a45a0fdcaeb43be83ecb79db048 100644 (file)
@@ -13,8 +13,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 // #define     DEBUG                   // error path messages, extra info
index 7bab4de658a91d9fb1231f5e45461a268efc8487..c51a98867a40bead7fd137a51f2f398d7336825d 100644 (file)
@@ -13,8 +13,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 //#define DEBUG
 #include <linux/netdevice.h>
@@ -299,35 +298,76 @@ static struct sk_buff *page_to_skb(struct receive_queue *rq,
        return skb;
 }
 
-static int receive_mergeable(struct receive_queue *rq, struct sk_buff *head_skb)
+static struct sk_buff *receive_small(void *buf, unsigned int len)
 {
-       struct skb_vnet_hdr *hdr = skb_vnet_hdr(head_skb);
+       struct sk_buff * skb = buf;
+
+       len -= sizeof(struct virtio_net_hdr);
+       skb_trim(skb, len);
+
+       return skb;
+}
+
+static struct sk_buff *receive_big(struct net_device *dev,
+                                  struct receive_queue *rq,
+                                  void *buf,
+                                  unsigned int len)
+{
+       struct page *page = buf;
+       struct sk_buff *skb = page_to_skb(rq, page, 0, len, PAGE_SIZE);
+
+       if (unlikely(!skb))
+               goto err;
+
+       return skb;
+
+err:
+       dev->stats.rx_dropped++;
+       give_pages(rq, page);
+       return NULL;
+}
+
+static struct sk_buff *receive_mergeable(struct net_device *dev,
+                                        struct receive_queue *rq,
+                                        void *buf,
+                                        unsigned int len)
+{
+       struct skb_vnet_hdr *hdr = buf;
+       int num_buf = hdr->mhdr.num_buffers;
+       struct page *page = virt_to_head_page(buf);
+       int offset = buf - page_address(page);
+       struct sk_buff *head_skb = page_to_skb(rq, page, offset, len,
+                                              MERGE_BUFFER_LEN);
        struct sk_buff *curr_skb = head_skb;
-       char *buf;
-       struct page *page;
-       int num_buf, len, offset;
 
-       num_buf = hdr->mhdr.num_buffers;
+       if (unlikely(!curr_skb))
+               goto err_skb;
+
        while (--num_buf) {
-               int num_skb_frags = skb_shinfo(curr_skb)->nr_frags;
+               int num_skb_frags;
+
                buf = virtqueue_get_buf(rq->vq, &len);
                if (unlikely(!buf)) {
-                       pr_debug("%s: rx error: %d buffers missing\n",
-                                head_skb->dev->name, hdr->mhdr.num_buffers);
-                       head_skb->dev->stats.rx_length_errors++;
-                       return -EINVAL;
+                       pr_debug("%s: rx error: %d buffers out of %d missing\n",
+                                dev->name, num_buf, hdr->mhdr.num_buffers);
+                       dev->stats.rx_length_errors++;
+                       goto err_buf;
                }
                if (unlikely(len > MERGE_BUFFER_LEN)) {
                        pr_debug("%s: rx error: merge buffer too long\n",
-                                head_skb->dev->name);
+                                dev->name);
                        len = MERGE_BUFFER_LEN;
                }
+
+               page = virt_to_head_page(buf);
+               --rq->num;
+
+               num_skb_frags = skb_shinfo(curr_skb)->nr_frags;
                if (unlikely(num_skb_frags == MAX_SKB_FRAGS)) {
                        struct sk_buff *nskb = alloc_skb(0, GFP_ATOMIC);
-                       if (unlikely(!nskb)) {
-                               head_skb->dev->stats.rx_dropped++;
-                               return -ENOMEM;
-                       }
+
+                       if (unlikely(!nskb))
+                               goto err_skb;
                        if (curr_skb == head_skb)
                                skb_shinfo(curr_skb)->frag_list = nskb;
                        else
@@ -341,8 +381,7 @@ static int receive_mergeable(struct receive_queue *rq, struct sk_buff *head_skb)
                        head_skb->len += len;
                        head_skb->truesize += MERGE_BUFFER_LEN;
                }
-               page = virt_to_head_page(buf);
-               offset = buf - (char *)page_address(page);
+               offset = buf - page_address(page);
                if (skb_can_coalesce(curr_skb, num_skb_frags, page, offset)) {
                        put_page(page);
                        skb_coalesce_rx_frag(curr_skb, num_skb_frags - 1,
@@ -351,9 +390,28 @@ static int receive_mergeable(struct receive_queue *rq, struct sk_buff *head_skb)
                        skb_add_rx_frag(curr_skb, num_skb_frags, page,
                                        offset, len, MERGE_BUFFER_LEN);
                }
+       }
+
+       return head_skb;
+
+err_skb:
+       put_page(page);
+       while (--num_buf) {
+               buf = virtqueue_get_buf(rq->vq, &len);
+               if (unlikely(!buf)) {
+                       pr_debug("%s: rx error: %d buffers missing\n",
+                                dev->name, num_buf);
+                       dev->stats.rx_length_errors++;
+                       break;
+               }
+               page = virt_to_head_page(buf);
+               put_page(page);
                --rq->num;
        }
-       return 0;
+err_buf:
+       dev->stats.rx_dropped++;
+       dev_kfree_skb(head_skb);
+       return NULL;
 }
 
 static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len)
@@ -362,48 +420,29 @@ static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len)
        struct net_device *dev = vi->dev;
        struct virtnet_stats *stats = this_cpu_ptr(vi->stats);
        struct sk_buff *skb;
-       struct page *page;
        struct skb_vnet_hdr *hdr;
 
        if (unlikely(len < sizeof(struct virtio_net_hdr) + ETH_HLEN)) {
                pr_debug("%s: short packet %i\n", dev->name, len);
                dev->stats.rx_length_errors++;
-               if (vi->big_packets)
-                       give_pages(rq, buf);
-               else if (vi->mergeable_rx_bufs)
+               if (vi->mergeable_rx_bufs)
                        put_page(virt_to_head_page(buf));
+               else if (vi->big_packets)
+                       give_pages(rq, buf);
                else
                        dev_kfree_skb(buf);
                return;
        }
 
-       if (!vi->mergeable_rx_bufs && !vi->big_packets) {
-               skb = buf;
-               len -= sizeof(struct virtio_net_hdr);
-               skb_trim(skb, len);
-       } else if (vi->mergeable_rx_bufs) {
-               struct page *page = virt_to_head_page(buf);
-               skb = page_to_skb(rq, page,
-                                 (char *)buf - (char *)page_address(page),
-                                 len, MERGE_BUFFER_LEN);
-               if (unlikely(!skb)) {
-                       dev->stats.rx_dropped++;
-                       put_page(page);
-                       return;
-               }
-               if (receive_mergeable(rq, skb)) {
-                       dev_kfree_skb(skb);
-                       return;
-               }
-       } else {
-               page = buf;
-               skb = page_to_skb(rq, page, 0, len, PAGE_SIZE);
-               if (unlikely(!skb)) {
-                       dev->stats.rx_dropped++;
-                       give_pages(rq, page);
-                       return;
-               }
-       }
+       if (vi->mergeable_rx_bufs)
+               skb = receive_mergeable(dev, rq, buf, len);
+       else if (vi->big_packets)
+               skb = receive_big(dev, rq, buf, len);
+       else
+               skb = receive_small(buf, len);
+
+       if (unlikely(!skb))
+               return;
 
        hdr = skb_vnet_hdr(skb);
 
@@ -834,16 +873,15 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
 /*
  * Send command via the control virtqueue and check status.  Commands
  * supported by the hypervisor, as indicated by feature bits, should
- * never fail unless improperly formated.
+ * never fail unless improperly formatted.
  */
 static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd,
-                                struct scatterlist *out,
-                                struct scatterlist *in)
+                                struct scatterlist *out)
 {
        struct scatterlist *sgs[4], hdr, stat;
        struct virtio_net_ctrl_hdr ctrl;
        virtio_net_ctrl_ack status = ~0;
-       unsigned out_num = 0, in_num = 0, tmp;
+       unsigned out_num = 0, tmp;
 
        /* Caller should know better */
        BUG_ON(!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ));
@@ -856,16 +894,13 @@ static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd,
 
        if (out)
                sgs[out_num++] = out;
-       if (in)
-               sgs[out_num + in_num++] = in;
 
        /* Add return status. */
        sg_init_one(&stat, &status, sizeof(status));
-       sgs[out_num + in_num++] = &stat;
+       sgs[out_num] = &stat;
 
-       BUG_ON(out_num + in_num > ARRAY_SIZE(sgs));
-       BUG_ON(virtqueue_add_sgs(vi->cvq, sgs, out_num, in_num, vi, GFP_ATOMIC)
-              < 0);
+       BUG_ON(out_num + 1 > ARRAY_SIZE(sgs));
+       BUG_ON(virtqueue_add_sgs(vi->cvq, sgs, out_num, 1, vi, GFP_ATOMIC) < 0);
 
        if (unlikely(!virtqueue_kick(vi->cvq)))
                return status == VIRTIO_NET_OK;
@@ -895,8 +930,7 @@ static int virtnet_set_mac_address(struct net_device *dev, void *p)
        if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_MAC_ADDR)) {
                sg_init_one(&sg, addr->sa_data, dev->addr_len);
                if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MAC,
-                                         VIRTIO_NET_CTRL_MAC_ADDR_SET,
-                                         &sg, NULL)) {
+                                         VIRTIO_NET_CTRL_MAC_ADDR_SET, &sg)) {
                        dev_warn(&vdev->dev,
                                 "Failed to set mac address by vq command.\n");
                        return -EINVAL;
@@ -969,7 +1003,7 @@ static void virtnet_ack_link_announce(struct virtnet_info *vi)
 {
        rtnl_lock();
        if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_ANNOUNCE,
-                                 VIRTIO_NET_CTRL_ANNOUNCE_ACK, NULL, NULL))
+                                 VIRTIO_NET_CTRL_ANNOUNCE_ACK, NULL))
                dev_warn(&vi->dev->dev, "Failed to ack link announce.\n");
        rtnl_unlock();
 }
@@ -987,7 +1021,7 @@ static int virtnet_set_queues(struct virtnet_info *vi, u16 queue_pairs)
        sg_init_one(&sg, &s, sizeof(s));
 
        if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MQ,
-                                 VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET, &sg, NULL)) {
+                                 VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET, &sg)) {
                dev_warn(&dev->dev, "Fail to set num of queue pairs to %d\n",
                         queue_pairs);
                return -EINVAL;
@@ -1027,7 +1061,7 @@ static void virtnet_set_rx_mode(struct net_device *dev)
        void *buf;
        int i;
 
-       /* We can't dynamicaly set ndo_set_rx_mode, so return gracefully */
+       /* We can't dynamically set ndo_set_rx_mode, so return gracefully */
        if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_RX))
                return;
 
@@ -1037,16 +1071,14 @@ static void virtnet_set_rx_mode(struct net_device *dev)
        sg_init_one(sg, &promisc, sizeof(promisc));
 
        if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX,
-                                 VIRTIO_NET_CTRL_RX_PROMISC,
-                                 sg, NULL))
+                                 VIRTIO_NET_CTRL_RX_PROMISC, sg))
                dev_warn(&dev->dev, "Failed to %sable promisc mode.\n",
                         promisc ? "en" : "dis");
 
        sg_init_one(sg, &allmulti, sizeof(allmulti));
 
        if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX,
-                                 VIRTIO_NET_CTRL_RX_ALLMULTI,
-                                 sg, NULL))
+                                 VIRTIO_NET_CTRL_RX_ALLMULTI, sg))
                dev_warn(&dev->dev, "Failed to %sable allmulti mode.\n",
                         allmulti ? "en" : "dis");
 
@@ -1082,9 +1114,8 @@ static void virtnet_set_rx_mode(struct net_device *dev)
                   sizeof(mac_data->entries) + (mc_count * ETH_ALEN));
 
        if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MAC,
-                                 VIRTIO_NET_CTRL_MAC_TABLE_SET,
-                                 sg, NULL))
-               dev_warn(&dev->dev, "Failed to set MAC fitler table.\n");
+                                 VIRTIO_NET_CTRL_MAC_TABLE_SET, sg))
+               dev_warn(&dev->dev, "Failed to set MAC filter table.\n");
 
        kfree(buf);
 }
@@ -1098,7 +1129,7 @@ static int virtnet_vlan_rx_add_vid(struct net_device *dev,
        sg_init_one(&sg, &vid, sizeof(vid));
 
        if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_VLAN,
-                                 VIRTIO_NET_CTRL_VLAN_ADD, &sg, NULL))
+                                 VIRTIO_NET_CTRL_VLAN_ADD, &sg))
                dev_warn(&dev->dev, "Failed to add VLAN ID %d.\n", vid);
        return 0;
 }
@@ -1112,7 +1143,7 @@ static int virtnet_vlan_rx_kill_vid(struct net_device *dev,
        sg_init_one(&sg, &vid, sizeof(vid));
 
        if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_VLAN,
-                                 VIRTIO_NET_CTRL_VLAN_DEL, &sg, NULL))
+                                 VIRTIO_NET_CTRL_VLAN_DEL, &sg))
                dev_warn(&dev->dev, "Failed to kill VLAN ID %d.\n", vid);
        return 0;
 }
@@ -1327,6 +1358,11 @@ static void virtnet_config_changed(struct virtio_device *vdev)
 
 static void virtnet_free_queues(struct virtnet_info *vi)
 {
+       int i;
+
+       for (i = 0; i < vi->max_queue_pairs; i++)
+               netif_napi_del(&vi->rq[i].napi);
+
        kfree(vi->rq);
        kfree(vi->sq);
 }
@@ -1356,10 +1392,10 @@ static void free_unused_bufs(struct virtnet_info *vi)
                struct virtqueue *vq = vi->rq[i].vq;
 
                while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) {
-                       if (vi->big_packets)
-                               give_pages(&vi->rq[i], buf);
-                       else if (vi->mergeable_rx_bufs)
+                       if (vi->mergeable_rx_bufs)
                                put_page(virt_to_head_page(buf));
+                       else if (vi->big_packets)
+                               give_pages(&vi->rq[i], buf);
                        else
                                dev_kfree_skb(buf);
                        --vi->rq[i].num;
index 7e2788c488edce4536fa0039337b5b267d2dc270..a300a18c550a82ecb69832f06d35f51813fc21b8 100644 (file)
@@ -3132,7 +3132,6 @@ err_alloc_queue_desc:
 err_alloc_shared:
        dma_unmap_single(&adapter->pdev->dev, adapter->adapter_pa,
                         sizeof(struct vmxnet3_adapter), PCI_DMA_TODEVICE);
-       pci_set_drvdata(pdev, NULL);
        free_netdev(netdev);
        return err;
 }
index 0358c07f7669142034e089660425a8fdb88236e2..4e1e5ba7bc5af49ea8978f24d8325193efbe2015 100644 (file)
@@ -916,17 +916,32 @@ static bool vxlan_snoop(struct net_device *dev,
 }
 
 /* See if multicast group is already in use by other ID */
-static bool vxlan_group_used(struct vxlan_net *vn, union vxlan_addr *remote_ip)
+static bool vxlan_group_used(struct vxlan_net *vn, struct vxlan_dev *dev)
 {
        struct vxlan_dev *vxlan;
 
+       /* The vxlan_sock is only used by dev, leaving group has
+        * no effect on other vxlan devices.
+        */
+       if (atomic_read(&dev->vn_sock->refcnt) == 1)
+               return false;
+
        list_for_each_entry(vxlan, &vn->vxlan_list, next) {
-               if (!netif_running(vxlan->dev))
+               if (!netif_running(vxlan->dev) || vxlan == dev)
                        continue;
 
-               if (vxlan_addr_equal(&vxlan->default_dst.remote_ip,
-                                    remote_ip))
-                       return true;
+               if (vxlan->vn_sock != dev->vn_sock)
+                       continue;
+
+               if (!vxlan_addr_equal(&vxlan->default_dst.remote_ip,
+                                     &dev->default_dst.remote_ip))
+                       continue;
+
+               if (vxlan->default_dst.remote_ifindex !=
+                   dev->default_dst.remote_ifindex)
+                       continue;
+
+               return true;
        }
 
        return false;
@@ -1668,7 +1683,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
                        netdev_dbg(dev, "circular route to %pI4\n",
                                   &dst->sin.sin_addr.s_addr);
                        dev->stats.collisions++;
-                       goto tx_error;
+                       goto rt_tx_error;
                }
 
                /* Bypass encapsulation if the destination is local */
@@ -1935,7 +1950,6 @@ static void vxlan_uninit(struct net_device *dev)
 /* Start ageing timer and join group when device is brought up */
 static int vxlan_open(struct net_device *dev)
 {
-       struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id);
        struct vxlan_dev *vxlan = netdev_priv(dev);
        struct vxlan_sock *vs = vxlan->vn_sock;
 
@@ -1943,8 +1957,7 @@ static int vxlan_open(struct net_device *dev)
        if (!vs)
                return -ENOTCONN;
 
-       if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip) &&
-           vxlan_group_used(vn, &vxlan->default_dst.remote_ip)) {
+       if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip)) {
                vxlan_sock_hold(vs);
                dev_hold(dev);
                queue_work(vxlan_wq, &vxlan->igmp_join);
@@ -1983,7 +1996,7 @@ static int vxlan_stop(struct net_device *dev)
        struct vxlan_sock *vs = vxlan->vn_sock;
 
        if (vs && vxlan_addr_multicast(&vxlan->default_dst.remote_ip) &&
-           ! vxlan_group_used(vn, &vxlan->default_dst.remote_ip)) {
+           !vxlan_group_used(vn, vxlan)) {
                vxlan_sock_hold(vs);
                dev_hold(dev);
                queue_work(vxlan_wq, &vxlan->igmp_leave);
index 851dc7b7e8b0a650482df9b86d2abf50d666e67a..288610df205c29efedcb4fb039998176de63746c 100644 (file)
@@ -699,8 +699,6 @@ static void dscc4_free1(struct pci_dev *pdev)
        for (i = 0; i < dev_per_card; i++)
                unregister_hdlc_device(dscc4_to_dev(root + i));
 
-       pci_set_drvdata(pdev, NULL);
-
        for (i = 0; i < dev_per_card; i++)
                free_netdev(root[i].dev);
        kfree(root);
index 7ef435bab42550ee4f220333e192be158634e875..c59b91f03660f412daa96a04d85c8b03986b3095 100644 (file)
@@ -973,7 +973,6 @@ static int lmc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
     return 0;
 
 err_hdlcdev:
-       pci_set_drvdata(pdev, NULL);
        kfree(sc);
 err_kzalloc:
        pci_release_regions(pdev);
@@ -995,7 +994,6 @@ static void lmc_remove_one(struct pci_dev *pdev)
                free_netdev(dev);
                pci_release_regions(pdev);
                pci_disable_device(pdev);
-               pci_set_drvdata(pdev, NULL);
        }
 }
 
index 53efc57fcacebd776ff810108a48e619c79eca03..5b72f7f8c516121ffdbf57c38e98b43c46e2fea8 100644 (file)
@@ -281,7 +281,6 @@ static void pc300_pci_remove_one(struct pci_dev *pdev)
 
        pci_release_regions(pdev);
        pci_disable_device(pdev);
-       pci_set_drvdata(pdev, NULL);
        if (card->ports[0].netdev)
                free_netdev(card->ports[0].netdev);
        if (card->ports[1].netdev)
index ddbce54040e2ca5e0a49c3fbde8b77528499c792..fe4e3ece3c42ac25efc4a207c4493540ea0f4578 100644 (file)
@@ -260,7 +260,6 @@ static void pci200_pci_remove_one(struct pci_dev *pdev)
 
        pci_release_regions(pdev);
        pci_disable_device(pdev);
-       pci_set_drvdata(pdev, NULL);
        if (card->ports[0].netdev)
                free_netdev(card->ports[0].netdev);
        if (card->ports[1].netdev)
index 4c0a69779b8980a16ccca5a90acc5ece605cf06a..f76aa9081585542321a423162662109edd742e47 100644 (file)
@@ -542,7 +542,6 @@ static void wanxl_pci_remove_one(struct pci_dev *pdev)
 
        pci_release_regions(pdev);
        pci_disable_device(pdev);
-       pci_set_drvdata(pdev, NULL);
        kfree(card);
 }
 
index e46951b8fb925df8a4cd4bb4ed14a738871175b2..d44d618b05f91f17defaddbeed4946fe27b6aa17 100644 (file)
@@ -243,6 +243,16 @@ static inline void ath10k_ce_error_intr_enable(struct ath10k *ar,
                           misc_ie_addr | CE_ERROR_MASK);
 }
 
+static inline void ath10k_ce_error_intr_disable(struct ath10k *ar,
+                                               u32 ce_ctrl_addr)
+{
+       u32 misc_ie_addr = ath10k_pci_read32(ar,
+                                            ce_ctrl_addr + MISC_IE_ADDRESS);
+
+       ath10k_pci_write32(ar, ce_ctrl_addr + MISC_IE_ADDRESS,
+                          misc_ie_addr & ~CE_ERROR_MASK);
+}
+
 static inline void ath10k_ce_engine_int_status_clear(struct ath10k *ar,
                                                     u32 ce_ctrl_addr,
                                                     unsigned int mask)
@@ -731,7 +741,6 @@ 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, ret;
        u32 intr_summary;
 
@@ -741,7 +750,7 @@ void ath10k_ce_per_engine_service_any(struct ath10k *ar)
 
        intr_summary = CE_INTERRUPT_SUMMARY(ar);
 
-       for (ce_id = 0; intr_summary && (ce_id < ar_pci->ce_count); ce_id++) {
+       for (ce_id = 0; intr_summary && (ce_id < CE_COUNT); ce_id++) {
                if (intr_summary & (1 << ce_id))
                        intr_summary &= ~(1 << ce_id);
                else
@@ -783,22 +792,25 @@ static void ath10k_ce_per_engine_handler_adjust(struct ath10k_ce_pipe *ce_state,
        ath10k_pci_sleep(ar);
 }
 
-void ath10k_ce_disable_interrupts(struct ath10k *ar)
+int ath10k_ce_disable_interrupts(struct ath10k *ar)
 {
-       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
        int ce_id, ret;
 
        ret = ath10k_pci_wake(ar);
        if (ret)
-               return;
+               return ret;
 
-       for (ce_id = 0; ce_id < ar_pci->ce_count; ce_id++) {
-               struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id];
-               u32 ctrl_addr = ce_state->ctrl_addr;
+       for (ce_id = 0; ce_id < CE_COUNT; ce_id++) {
+               u32 ctrl_addr = ath10k_ce_base_address(ce_id);
 
                ath10k_ce_copy_complete_intr_disable(ar, ctrl_addr);
+               ath10k_ce_error_intr_disable(ar, ctrl_addr);
+               ath10k_ce_watermark_intr_disable(ar, ctrl_addr);
        }
+
        ath10k_pci_sleep(ar);
+
+       return 0;
 }
 
 void ath10k_ce_send_cb_register(struct ath10k_ce_pipe *ce_state,
@@ -1047,9 +1059,19 @@ struct ath10k_ce_pipe *ath10k_ce_init(struct ath10k *ar,
                                const struct ce_attr *attr)
 {
        struct ath10k_ce_pipe *ce_state;
-       u32 ctrl_addr = ath10k_ce_base_address(ce_id);
        int ret;
 
+       /*
+        * Make sure there's enough CE ringbuffer entries for HTT TX to avoid
+        * additional TX locking checks.
+        *
+        * For the lack of a better place do the check here.
+        */
+       BUILD_BUG_ON(TARGET_NUM_MSDU_DESC >
+                    (CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
+       BUILD_BUG_ON(TARGET_10X_NUM_MSDU_DESC >
+                    (CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
+
        ret = ath10k_pci_wake(ar);
        if (ret)
                return NULL;
@@ -1057,7 +1079,7 @@ struct ath10k_ce_pipe *ath10k_ce_init(struct ath10k *ar,
        ce_state = ath10k_ce_init_state(ar, ce_id, attr);
        if (!ce_state) {
                ath10k_err("Failed to initialize CE state for ID: %d\n", ce_id);
-               return NULL;
+               goto out;
        }
 
        if (attr->src_nentries) {
@@ -1066,7 +1088,8 @@ struct ath10k_ce_pipe *ath10k_ce_init(struct ath10k *ar,
                        ath10k_err("Failed to initialize CE src ring for ID: %d (%d)\n",
                                   ce_id, ret);
                        ath10k_ce_deinit(ce_state);
-                       return NULL;
+                       ce_state = NULL;
+                       goto out;
                }
        }
 
@@ -1076,15 +1099,13 @@ struct ath10k_ce_pipe *ath10k_ce_init(struct ath10k *ar,
                        ath10k_err("Failed to initialize CE dest ring for ID: %d (%d)\n",
                                   ce_id, ret);
                        ath10k_ce_deinit(ce_state);
-                       return NULL;
+                       ce_state = NULL;
+                       goto out;
                }
        }
 
-       /* Enable CE error interrupts */
-       ath10k_ce_error_intr_enable(ar, ctrl_addr);
-
+out:
        ath10k_pci_sleep(ar);
-
        return ce_state;
 }
 
index 15d45b5b76153b60133502be39b1803eb86c8517..67dbde6a5c7430fbd4507355755e479d58d4d289 100644 (file)
@@ -234,7 +234,7 @@ void ath10k_ce_deinit(struct ath10k_ce_pipe *ce_state);
 /*==================CE Interrupt Handlers====================*/
 void ath10k_ce_per_engine_service_any(struct ath10k *ar);
 void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id);
-void ath10k_ce_disable_interrupts(struct ath10k *ar);
+int ath10k_ce_disable_interrupts(struct ath10k *ar);
 
 /* ce_attr.flags values */
 /* Use NonSnooping PCIe accesses? */
index 1129994fb10505864c57e1025d95cec8aa009093..3b59af3bddf4a6e4506f027472c41832f41c43c9 100644 (file)
@@ -597,10 +597,8 @@ static int ath10k_init_uart(struct ath10k *ar)
                return ret;
        }
 
-       if (!uart_print) {
-               ath10k_info("UART prints disabled\n");
+       if (!uart_print)
                return 0;
-       }
 
        ret = ath10k_bmi_write32(ar, hi_dbg_uart_txpin, 7);
        if (ret) {
@@ -645,8 +643,8 @@ static int ath10k_init_hw_params(struct ath10k *ar)
 
        ar->hw_params = *hw_params;
 
-       ath10k_info("Hardware name %s version 0x%x\n",
-                   ar->hw_params.name, ar->target_version);
+       ath10k_dbg(ATH10K_DBG_BOOT, "Hardware name %s version 0x%x\n",
+                  ar->hw_params.name, ar->target_version);
 
        return 0;
 }
@@ -664,7 +662,8 @@ static void ath10k_core_restart(struct work_struct *work)
                ieee80211_restart_hw(ar->hw);
                break;
        case ATH10K_STATE_OFF:
-               /* this can happen if driver is being unloaded */
+               /* this can happen if driver is being unloaded
+                * or if the crash happens during FW probing */
                ath10k_warn("cannot restart a device that hasn't been started\n");
                break;
        case ATH10K_STATE_RESTARTING:
@@ -737,8 +736,6 @@ EXPORT_SYMBOL(ath10k_core_create);
 
 void ath10k_core_destroy(struct ath10k *ar)
 {
-       ath10k_debug_destroy(ar);
-
        flush_workqueue(ar->workqueue);
        destroy_workqueue(ar->workqueue);
 
@@ -786,21 +783,30 @@ int ath10k_core_start(struct ath10k *ar)
                goto err;
        }
 
-       status = ath10k_htc_wait_target(&ar->htc);
-       if (status)
+       status = ath10k_hif_start(ar);
+       if (status) {
+               ath10k_err("could not start HIF: %d\n", status);
                goto err_wmi_detach;
+       }
+
+       status = ath10k_htc_wait_target(&ar->htc);
+       if (status) {
+               ath10k_err("failed to connect to HTC: %d\n", status);
+               goto err_hif_stop;
+       }
 
        status = ath10k_htt_attach(ar);
        if (status) {
                ath10k_err("could not attach htt (%d)\n", status);
-               goto err_wmi_detach;
+               goto err_hif_stop;
        }
 
        status = ath10k_init_connect_htc(ar);
        if (status)
                goto err_htt_detach;
 
-       ath10k_info("firmware %s booted\n", ar->hw->wiphy->fw_version);
+       ath10k_dbg(ATH10K_DBG_BOOT, "firmware %s booted\n",
+                  ar->hw->wiphy->fw_version);
 
        status = ath10k_wmi_cmd_init(ar);
        if (status) {
@@ -826,12 +832,23 @@ int ath10k_core_start(struct ath10k *ar)
        ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1;
        INIT_LIST_HEAD(&ar->arvifs);
 
+       if (!test_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags))
+               ath10k_info("%s (0x%x) fw %s api %d htt %d.%d\n",
+                           ar->hw_params.name, ar->target_version,
+                           ar->hw->wiphy->fw_version, ar->fw_api,
+                           ar->htt.target_version_major,
+                           ar->htt.target_version_minor);
+
+       __set_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags);
+
        return 0;
 
 err_disconnect_htc:
        ath10k_htc_stop(&ar->htc);
 err_htt_detach:
        ath10k_htt_detach(&ar->htt);
+err_hif_stop:
+       ath10k_hif_stop(ar);
 err_wmi_detach:
        ath10k_wmi_detach(ar);
 err:
@@ -985,6 +1002,8 @@ void ath10k_core_unregister(struct ath10k *ar)
        ath10k_mac_unregister(ar);
 
        ath10k_core_free_firmware_files(ar);
+
+       ath10k_debug_destroy(ar);
 }
 EXPORT_SYMBOL(ath10k_core_unregister);
 
index 0934f7633de399df82df8ab74a9e0f6ef64f5b82..79726e0fe2f0dd00005c29800739d9886d0a3576 100644 (file)
@@ -30,6 +30,7 @@
 #include "wmi.h"
 #include "../ath.h"
 #include "../regd.h"
+#include "../dfs_pattern_detector.h"
 
 #define MS(_v, _f) (((_v) & _f##_MASK) >> _f##_LSB)
 #define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
@@ -43,7 +44,7 @@
 /* Antenna noise floor */
 #define ATH10K_DEFAULT_NOISE_FLOOR -95
 
-#define ATH10K_MAX_NUM_MGMT_PENDING 16
+#define ATH10K_MAX_NUM_MGMT_PENDING 128
 
 struct ath10k;
 
@@ -192,6 +193,14 @@ struct ath10k_target_stats {
 
 };
 
+struct ath10k_dfs_stats {
+       u32 phy_errors;
+       u32 pulses_total;
+       u32 pulses_detected;
+       u32 pulses_discarded;
+       u32 radar_detected;
+};
+
 #define ATH10K_MAX_NUM_PEER_IDS (1 << 11) /* htt rx_desc limit */
 
 struct ath10k_peer {
@@ -261,6 +270,8 @@ struct ath10k_debug {
 
        unsigned long htt_stats_mask;
        struct delayed_work htt_stats_dwork;
+       struct ath10k_dfs_stats dfs_stats;
+       struct ath_dfs_pool_stats dfs_pool_stats;
 };
 
 enum ath10k_state {
@@ -299,6 +310,12 @@ enum ath10k_fw_features {
        ATH10K_FW_FEATURE_COUNT,
 };
 
+enum ath10k_dev_flags {
+       /* Indicates that ath10k device is during CAC phase of DFS */
+       ATH10K_CAC_RUNNING,
+       ATH10K_FLAG_FIRST_BOOT_DONE,
+};
+
 struct ath10k {
        struct ath_common ath_common;
        struct ieee80211_hw *hw;
@@ -392,6 +409,8 @@ struct ath10k {
        bool monitor_enabled;
        bool monitor_present;
        unsigned int filter_flags;
+       unsigned long dev_flags;
+       u32 dfs_block_radar_events;
 
        struct wmi_pdev_set_wmm_params_arg wmm_params;
        struct completion install_key_done;
@@ -428,6 +447,8 @@ struct ath10k {
        u32 survey_last_cycle_count;
        struct survey_info survey[ATH10K_NUM_CHANS];
 
+       struct dfs_pattern_detector *dfs_detector;
+
 #ifdef CONFIG_ATH10K_DEBUGFS
        struct ath10k_debug debug;
 #endif
index 760ff2289e3cf2903773544d3349cab7bde1a852..6bdfad3144afb68131bf087e2c20ba553cf34e5f 100644 (file)
@@ -639,6 +639,86 @@ void ath10k_debug_stop(struct ath10k *ar)
                cancel_delayed_work(&ar->debug.htt_stats_dwork);
 }
 
+static ssize_t ath10k_write_simulate_radar(struct file *file,
+                                          const char __user *user_buf,
+                                          size_t count, loff_t *ppos)
+{
+       struct ath10k *ar = file->private_data;
+
+       ieee80211_radar_detected(ar->hw);
+
+       return count;
+}
+
+static const struct file_operations fops_simulate_radar = {
+       .write = ath10k_write_simulate_radar,
+       .open = simple_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+#define ATH10K_DFS_STAT(s, p) (\
+       len += scnprintf(buf + len, size - len, "%-28s : %10u\n", s, \
+                        ar->debug.dfs_stats.p))
+
+#define ATH10K_DFS_POOL_STAT(s, p) (\
+       len += scnprintf(buf + len, size - len, "%-28s : %10u\n", s, \
+                        ar->debug.dfs_pool_stats.p))
+
+static ssize_t ath10k_read_dfs_stats(struct file *file, char __user *user_buf,
+                                    size_t count, loff_t *ppos)
+{
+       int retval = 0, len = 0;
+       const int size = 8000;
+       struct ath10k *ar = file->private_data;
+       char *buf;
+
+       buf = kzalloc(size, GFP_KERNEL);
+       if (buf == NULL)
+               return -ENOMEM;
+
+       if (!ar->dfs_detector) {
+               len += scnprintf(buf + len, size - len, "DFS not enabled\n");
+               goto exit;
+       }
+
+       ar->debug.dfs_pool_stats =
+                       ar->dfs_detector->get_stats(ar->dfs_detector);
+
+       len += scnprintf(buf + len, size - len, "Pulse detector statistics:\n");
+
+       ATH10K_DFS_STAT("reported phy errors", phy_errors);
+       ATH10K_DFS_STAT("pulse events reported", pulses_total);
+       ATH10K_DFS_STAT("DFS pulses detected", pulses_detected);
+       ATH10K_DFS_STAT("DFS pulses discarded", pulses_discarded);
+       ATH10K_DFS_STAT("Radars detected", radar_detected);
+
+       len += scnprintf(buf + len, size - len, "Global Pool statistics:\n");
+       ATH10K_DFS_POOL_STAT("Pool references", pool_reference);
+       ATH10K_DFS_POOL_STAT("Pulses allocated", pulse_allocated);
+       ATH10K_DFS_POOL_STAT("Pulses alloc error", pulse_alloc_error);
+       ATH10K_DFS_POOL_STAT("Pulses in use", pulse_used);
+       ATH10K_DFS_POOL_STAT("Seqs. allocated", pseq_allocated);
+       ATH10K_DFS_POOL_STAT("Seqs. alloc error", pseq_alloc_error);
+       ATH10K_DFS_POOL_STAT("Seqs. in use", pseq_used);
+
+exit:
+       if (len > size)
+               len = size;
+
+       retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+       kfree(buf);
+
+       return retval;
+}
+
+static const struct file_operations fops_dfs_stats = {
+       .read = ath10k_read_dfs_stats,
+       .open = simple_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
 int ath10k_debug_create(struct ath10k *ar)
 {
        ar->debug.debugfs_phy = debugfs_create_dir("ath10k",
@@ -667,6 +747,20 @@ int ath10k_debug_create(struct ath10k *ar)
        debugfs_create_file("htt_stats_mask", S_IRUSR, ar->debug.debugfs_phy,
                            ar, &fops_htt_stats_mask);
 
+       if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) {
+               debugfs_create_file("dfs_simulate_radar", S_IWUSR,
+                                   ar->debug.debugfs_phy, ar,
+                                   &fops_simulate_radar);
+
+               debugfs_create_bool("dfs_block_radar_events", S_IWUSR,
+                                   ar->debug.debugfs_phy,
+                                   &ar->dfs_block_radar_events);
+
+               debugfs_create_file("dfs_stats", S_IRUSR,
+                                   ar->debug.debugfs_phy, ar,
+                                   &fops_dfs_stats);
+       }
+
        return 0;
 }
 
index 3cfe3ee90dbe1d802d7c3b8b4fe0c7cd8c815ee9..1773c36c71a01a179177b887a3485c9f05c505cf 100644 (file)
@@ -33,6 +33,7 @@ enum ath10k_debug_mask {
        ATH10K_DBG_MGMT         = 0x00000100,
        ATH10K_DBG_DATA         = 0x00000200,
        ATH10K_DBG_BMI          = 0x00000400,
+       ATH10K_DBG_REGULATORY   = 0x00000800,
        ATH10K_DBG_ANY          = 0xffffffff,
 };
 
@@ -53,6 +54,8 @@ void ath10k_debug_read_service_map(struct ath10k *ar,
 void ath10k_debug_read_target_stats(struct ath10k *ar,
                                    struct wmi_stats_event *ev);
 
+#define ATH10K_DFS_STAT_INC(ar, c) (ar->debug.dfs_stats.c++)
+
 #else
 static inline int ath10k_debug_start(struct ath10k *ar)
 {
@@ -82,6 +85,9 @@ static inline void ath10k_debug_read_target_stats(struct ath10k *ar,
                                                  struct wmi_stats_event *ev)
 {
 }
+
+#define ATH10K_DFS_STAT_INC(ar, c) do { } while (0)
+
 #endif /* CONFIG_ATH10K_DEBUGFS */
 
 #ifdef CONFIG_ATH10K_DEBUG
index edae50b52806f5382fc6ee7296ac810fda2eb9b5..edc57ab505c893c3dd295d01a3f44fd2126e3dee 100644 (file)
@@ -191,6 +191,11 @@ static int ath10k_htc_tx_completion_handler(struct ath10k *ar,
        struct ath10k_htc *htc = &ar->htc;
        struct ath10k_htc_ep *ep = &htc->endpoint[eid];
 
+       if (!skb) {
+               ath10k_warn("invalid sk_buff completion - NULL pointer. firmware crashed?\n");
+               return 0;
+       }
+
        ath10k_htc_notify_tx_completion(ep, skb);
        /* the skb now belongs to the completion handler */
 
@@ -534,14 +539,6 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
        u16 credit_count;
        u16 credit_size;
 
-       reinit_completion(&htc->ctl_resp);
-
-       status = ath10k_hif_start(htc->ar);
-       if (status) {
-               ath10k_err("could not start HIF (%d)\n", status);
-               goto err_start;
-       }
-
        status = wait_for_completion_timeout(&htc->ctl_resp,
                                             ATH10K_HTC_WAIT_TIMEOUT_HZ);
        if (status <= 0) {
@@ -549,15 +546,13 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
                        status = -ETIMEDOUT;
 
                ath10k_err("ctl_resp never came in (%d)\n", status);
-               goto err_target;
+               return status;
        }
 
        if (htc->control_resp_len < sizeof(msg->hdr) + sizeof(msg->ready)) {
                ath10k_err("Invalid HTC ready msg len:%d\n",
                           htc->control_resp_len);
-
-               status = -ECOMM;
-               goto err_target;
+               return -ECOMM;
        }
 
        msg = (struct ath10k_htc_msg *)htc->control_resp_buffer;
@@ -567,8 +562,7 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
 
        if (message_id != ATH10K_HTC_MSG_READY_ID) {
                ath10k_err("Invalid HTC ready msg: 0x%x\n", message_id);
-               status = -ECOMM;
-               goto err_target;
+               return -ECOMM;
        }
 
        htc->total_transmit_credits = credit_count;
@@ -581,9 +575,8 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
 
        if ((htc->total_transmit_credits == 0) ||
            (htc->target_credit_size == 0)) {
-               status = -ECOMM;
                ath10k_err("Invalid credit size received\n");
-               goto err_target;
+               return -ECOMM;
        }
 
        ath10k_htc_setup_target_buffer_assignments(htc);
@@ -600,14 +593,10 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
        status = ath10k_htc_connect_service(htc, &conn_req, &conn_resp);
        if (status) {
                ath10k_err("could not connect to htc service (%d)\n", status);
-               goto err_target;
+               return status;
        }
 
        return 0;
-err_target:
-       ath10k_hif_stop(htc->ar);
-err_start:
-       return status;
 }
 
 int ath10k_htc_connect_service(struct ath10k_htc *htc,
index 5f7eeebc54327736cbfc2b6fb77bc030029bf7c3..69697af59ce06f9ab070cf01562e240607c9fc93 100644 (file)
@@ -104,8 +104,8 @@ err_htc_attach:
 
 static int ath10k_htt_verify_version(struct ath10k_htt *htt)
 {
-       ath10k_info("htt target version %d.%d\n",
-                   htt->target_version_major, htt->target_version_minor);
+       ath10k_dbg(ATH10K_DBG_BOOT, "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) {
index 1a337e93b7e95e9ef70ab9053696dce7cf4e4c95..7fc7919ea5f51f85e08c20b820c9bc458707e07b 100644 (file)
@@ -1182,6 +1182,7 @@ struct htt_rx_info {
                u32 info2;
        } rate;
        bool fcs_err;
+       bool amsdu_more;
 };
 
 struct ath10k_htt {
index 90d4f74c28d7deaa4c087bfdbc47ca83ac1a9716..fcb534f2f28fb7eea0febea3a0c68672d227712f 100644 (file)
@@ -659,23 +659,6 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
        memcpy(hdr_buf, hdr, hdr_len);
        hdr = (struct ieee80211_hdr *)hdr_buf;
 
-       /* FIXME: Hopefully this is a temporary measure.
-        *
-        * Reporting individual A-MSDU subframes means each reported frame
-        * shares the same sequence number.
-        *
-        * mac80211 drops frames it recognizes as duplicates, i.e.
-        * retransmission flag is set and sequence number matches sequence
-        * number from a previous frame (as per IEEE 802.11-2012: 9.3.2.10
-        * "Duplicate detection and recovery")
-        *
-        * To avoid frames being dropped clear retransmission flag for all
-        * received A-MSDUs.
-        *
-        * Worst case: actual duplicate frames will be reported but this should
-        * still be handled gracefully by other OSI/ISO layers. */
-       hdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_RETRY);
-
        first = skb;
        while (skb) {
                void *decap_hdr;
@@ -746,6 +729,9 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
                skb = skb->next;
                info->skb->next = NULL;
 
+               if (skb)
+                       info->amsdu_more = true;
+
                ath10k_process_rx(htt->ar, info);
        }
 
@@ -959,6 +945,11 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
                                continue;
                        }
 
+                       if (test_bit(ATH10K_CAC_RUNNING, &htt->ar->dev_flags)) {
+                               ath10k_htt_rx_free_msdu_chain(msdu_head);
+                               continue;
+                       }
+
                        /* FIXME: we do not support chaining yet.
                         * this needs investigation */
                        if (msdu_chaining) {
index d9335e9d0d04d247e868e465323037e4f9f78d9e..f1d36d2d27235aeec979fed652d2925ec6e94513 100644 (file)
@@ -85,16 +85,13 @@ void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id)
 
 int ath10k_htt_tx_attach(struct ath10k_htt *htt)
 {
-       u8 pipe;
-
        spin_lock_init(&htt->tx_lock);
        init_waitqueue_head(&htt->empty_tx_wq);
 
-       /* At the beginning free queue number should hint us the maximum
-        * queue length */
-       pipe = htt->ar->htc.endpoint[htt->eid].ul_pipe_id;
-       htt->max_num_pending_tx = ath10k_hif_get_free_queue_number(htt->ar,
-                                                                  pipe);
+       if (test_bit(ATH10K_FW_FEATURE_WMI_10X, htt->ar->fw_features))
+               htt->max_num_pending_tx = TARGET_10X_NUM_MSDU_DESC;
+       else
+               htt->max_num_pending_tx = TARGET_NUM_MSDU_DESC;
 
        ath10k_dbg(ATH10K_DBG_BOOT, "htt tx max num pending tx %d\n",
                   htt->max_num_pending_tx);
index 8aeb46d9b53409da2ced923d49780b763105a5d6..9535eaa09f099b1ed8c7469ffe73f87236e3a9f3 100644 (file)
@@ -269,6 +269,7 @@ enum ath10k_mcast2ucast_mode {
 #define CORE_CTRL_CPU_INTR_MASK                        0x00002000
 #define CORE_CTRL_ADDRESS                      0x0000
 #define PCIE_INTR_ENABLE_ADDRESS               0x0008
+#define PCIE_INTR_CAUSE_ADDRESS                        0x000c
 #define PCIE_INTR_CLR_ADDRESS                  0x0014
 #define SCRATCH_3_ADDRESS                      0x0030
 
index 97ac8c87cba232646f5f82617ea396b8c2573870..ce9ef3499ecb8a90fecc87071437bb7310e17e89 100644 (file)
@@ -322,12 +322,16 @@ static int ath10k_peer_create(struct ath10k *ar, u32 vdev_id, const u8 *addr)
        lockdep_assert_held(&ar->conf_mutex);
 
        ret = ath10k_wmi_peer_create(ar, vdev_id, addr);
-       if (ret)
+       if (ret) {
+               ath10k_warn("Failed to create wmi peer: %i\n", ret);
                return ret;
+       }
 
        ret = ath10k_wait_for_peer_created(ar, vdev_id, addr);
-       if (ret)
+       if (ret) {
+               ath10k_warn("Failed to wait for created wmi peer: %i\n", ret);
                return ret;
+       }
 
        return 0;
 }
@@ -450,15 +454,19 @@ static int ath10k_vdev_start(struct ath10k_vif *arvif)
 
        arg.channel.mode = chan_to_phymode(&conf->chandef);
 
-       arg.channel.min_power = channel->max_power * 3;
-       arg.channel.max_power = channel->max_power * 4;
-       arg.channel.max_reg_power = channel->max_reg_power * 4;
-       arg.channel.max_antenna_gain = channel->max_antenna_gain;
+       arg.channel.min_power = 0;
+       arg.channel.max_power = channel->max_power * 2;
+       arg.channel.max_reg_power = channel->max_reg_power * 2;
+       arg.channel.max_antenna_gain = channel->max_antenna_gain * 2;
 
        if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
                arg.ssid = arvif->u.ap.ssid;
                arg.ssid_len = arvif->u.ap.ssid_len;
                arg.hidden_ssid = arvif->u.ap.hidden_ssid;
+
+               /* For now allow DFS for AP mode */
+               arg.channel.chan_radar =
+                       !!(channel->flags & IEEE80211_CHAN_RADAR);
        } else if (arvif->vdev_type == WMI_VDEV_TYPE_IBSS) {
                arg.ssid = arvif->vif->bss_conf.ssid;
                arg.ssid_len = arvif->vif->bss_conf.ssid_len;
@@ -516,6 +524,11 @@ static int ath10k_monitor_start(struct ath10k *ar, int vdev_id)
 
        lockdep_assert_held(&ar->conf_mutex);
 
+       if (!ar->monitor_present) {
+               ath10k_warn("mac montor stop -- monitor is not present\n");
+               return -EINVAL;
+       }
+
        arg.vdev_id = vdev_id;
        arg.channel.freq = channel->center_freq;
        arg.channel.band_center_freq1 = ar->hw->conf.chandef.center_freq1;
@@ -523,11 +536,13 @@ static int ath10k_monitor_start(struct ath10k *ar, int vdev_id)
        /* TODO setup this dynamically, what in case we
           don't have any vifs? */
        arg.channel.mode = chan_to_phymode(&ar->hw->conf.chandef);
+       arg.channel.chan_radar =
+                       !!(channel->flags & IEEE80211_CHAN_RADAR);
 
-       arg.channel.min_power = channel->max_power * 3;
-       arg.channel.max_power = channel->max_power * 4;
-       arg.channel.max_reg_power = channel->max_reg_power * 4;
-       arg.channel.max_antenna_gain = channel->max_antenna_gain;
+       arg.channel.min_power = 0;
+       arg.channel.max_power = channel->max_power * 2;
+       arg.channel.max_reg_power = channel->max_reg_power * 2;
+       arg.channel.max_antenna_gain = channel->max_antenna_gain * 2;
 
        ret = ath10k_wmi_vdev_start(ar, &arg);
        if (ret) {
@@ -566,6 +581,16 @@ static int ath10k_monitor_stop(struct ath10k *ar)
 
        lockdep_assert_held(&ar->conf_mutex);
 
+       if (!ar->monitor_present) {
+               ath10k_warn("mac montor stop -- monitor is not present\n");
+               return -EINVAL;
+       }
+
+       if (!ar->monitor_enabled) {
+               ath10k_warn("mac montor stop -- monitor is not enabled\n");
+               return -EINVAL;
+       }
+
        ret = ath10k_wmi_vdev_down(ar, ar->monitor_vdev_id);
        if (ret)
                ath10k_warn("Monitor vdev down failed: %d\n", ret);
@@ -647,6 +672,107 @@ static int ath10k_monitor_destroy(struct ath10k *ar)
        return ret;
 }
 
+static int ath10k_start_cac(struct ath10k *ar)
+{
+       int ret;
+
+       lockdep_assert_held(&ar->conf_mutex);
+
+       set_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
+
+       ret = ath10k_monitor_create(ar);
+       if (ret) {
+               clear_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
+               return ret;
+       }
+
+       ret = ath10k_monitor_start(ar, ar->monitor_vdev_id);
+       if (ret) {
+               clear_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
+               ath10k_monitor_destroy(ar);
+               return ret;
+       }
+
+       ath10k_dbg(ATH10K_DBG_MAC, "mac cac start monitor vdev %d\n",
+                  ar->monitor_vdev_id);
+
+       return 0;
+}
+
+static int ath10k_stop_cac(struct ath10k *ar)
+{
+       lockdep_assert_held(&ar->conf_mutex);
+
+       /* CAC is not running - do nothing */
+       if (!test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags))
+               return 0;
+
+       ath10k_monitor_stop(ar);
+       ath10k_monitor_destroy(ar);
+       clear_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
+
+       ath10k_dbg(ATH10K_DBG_MAC, "mac cac finished\n");
+
+       return 0;
+}
+
+static const char *ath10k_dfs_state(enum nl80211_dfs_state dfs_state)
+{
+       switch (dfs_state) {
+       case NL80211_DFS_USABLE:
+               return "USABLE";
+       case NL80211_DFS_UNAVAILABLE:
+               return "UNAVAILABLE";
+       case NL80211_DFS_AVAILABLE:
+               return "AVAILABLE";
+       default:
+               WARN_ON(1);
+               return "bug";
+       }
+}
+
+static void ath10k_config_radar_detection(struct ath10k *ar)
+{
+       struct ieee80211_channel *chan = ar->hw->conf.chandef.chan;
+       bool radar = ar->hw->conf.radar_enabled;
+       bool chan_radar = !!(chan->flags & IEEE80211_CHAN_RADAR);
+       enum nl80211_dfs_state dfs_state = chan->dfs_state;
+       int ret;
+
+       lockdep_assert_held(&ar->conf_mutex);
+
+       ath10k_dbg(ATH10K_DBG_MAC,
+                  "mac radar config update: chan %dMHz radar %d chan radar %d chan state %s\n",
+                  chan->center_freq, radar, chan_radar,
+                  ath10k_dfs_state(dfs_state));
+
+       /*
+        * It's safe to call it even if CAC is not started.
+        * This call here guarantees changing channel, etc. will stop CAC.
+        */
+       ath10k_stop_cac(ar);
+
+       if (!radar)
+               return;
+
+       if (!chan_radar)
+               return;
+
+       if (dfs_state != NL80211_DFS_USABLE)
+               return;
+
+       ret = ath10k_start_cac(ar);
+       if (ret) {
+               /*
+                * Not possible to start CAC on current channel so starting
+                * radiation is not allowed, make this channel DFS_UNAVAILABLE
+                * by indicating that radar was detected.
+                */
+               ath10k_warn("failed to start CAC (%d)\n", ret);
+               ieee80211_radar_detected(ar->hw);
+       }
+}
+
 static void ath10k_control_beaconing(struct ath10k_vif *arvif,
                                struct ieee80211_bss_conf *info)
 {
@@ -1351,19 +1477,22 @@ static int ath10k_update_channel_list(struct ath10k *ar)
                        ch->allow_vht = true;
 
                        ch->allow_ibss =
-                               !(channel->flags & IEEE80211_CHAN_NO_IBSS);
+                               !(channel->flags & IEEE80211_CHAN_NO_IR);
 
                        ch->ht40plus =
                                !(channel->flags & IEEE80211_CHAN_NO_HT40PLUS);
 
-                       passive = channel->flags & IEEE80211_CHAN_PASSIVE_SCAN;
+                       ch->chan_radar =
+                               !!(channel->flags & IEEE80211_CHAN_RADAR);
+
+                       passive = channel->flags & IEEE80211_CHAN_NO_IR;
                        ch->passive = passive;
 
                        ch->freq = channel->center_freq;
-                       ch->min_power = channel->max_power * 3;
-                       ch->max_power = channel->max_power * 4;
-                       ch->max_reg_power = channel->max_reg_power * 4;
-                       ch->max_antenna_gain = channel->max_antenna_gain;
+                       ch->min_power = 0;
+                       ch->max_power = channel->max_power * 2;
+                       ch->max_reg_power = channel->max_reg_power * 2;
+                       ch->max_antenna_gain = channel->max_antenna_gain * 2;
                        ch->reg_class_id = 0; /* FIXME */
 
                        /* FIXME: why use only legacy modes, why not any
@@ -1423,9 +1552,20 @@ static void ath10k_reg_notifier(struct wiphy *wiphy,
 {
        struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
        struct ath10k *ar = hw->priv;
+       bool result;
 
        ath_reg_notifier_apply(wiphy, request, &ar->ath_common.regulatory);
 
+       if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED) && ar->dfs_detector) {
+               ath10k_dbg(ATH10K_DBG_REGULATORY, "dfs region 0x%x\n",
+                          request->dfs_region);
+               result = ar->dfs_detector->set_dfs_domain(ar->dfs_detector,
+                                                         request->dfs_region);
+               if (!result)
+                       ath10k_warn("dfs region 0x%X not supported, will trigger radar for every pulse\n",
+                                   request->dfs_region);
+       }
+
        mutex_lock(&ar->conf_mutex);
        if (ar->state == ATH10K_STATE_ON)
                ath10k_regd_update(ar);
@@ -1714,8 +1854,10 @@ void ath10k_mgmt_over_wmi_tx_work(struct work_struct *work)
                        break;
 
                ret = ath10k_wmi_mgmt_tx(ar, skb);
-               if (ret)
+               if (ret) {
                        ath10k_warn("wmi mgmt_tx failed (%d)\n", ret);
+                       ieee80211_free_txskb(ar->hw, skb);
+               }
        }
 }
 
@@ -1889,6 +2031,7 @@ void ath10k_halt(struct ath10k *ar)
 {
        lockdep_assert_held(&ar->conf_mutex);
 
+       ath10k_stop_cac(ar);
        del_timer_sync(&ar->scan.timeout);
        ath10k_offchan_tx_purge(ar);
        ath10k_mgmt_over_wmi_tx_purge(ar);
@@ -1943,7 +2086,7 @@ static int ath10k_start(struct ieee80211_hw *hw)
                ath10k_warn("could not enable WMI_PDEV_PARAM_PMF_QOS (%d)\n",
                            ret);
 
-       ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->dynamic_bw, 0);
+       ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->dynamic_bw, 1);
        if (ret)
                ath10k_warn("could not init WMI_PDEV_PARAM_DYNAMIC_BW (%d)\n",
                            ret);
@@ -1998,15 +2141,40 @@ static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
        struct ath10k *ar = hw->priv;
        struct ieee80211_conf *conf = &hw->conf;
        int ret = 0;
+       u32 param;
 
        mutex_lock(&ar->conf_mutex);
 
        if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
-               ath10k_dbg(ATH10K_DBG_MAC, "mac config channel %d mhz\n",
-                          conf->chandef.chan->center_freq);
+               ath10k_dbg(ATH10K_DBG_MAC,
+                          "mac config channel %d mhz flags 0x%x\n",
+                          conf->chandef.chan->center_freq,
+                          conf->chandef.chan->flags);
+
                spin_lock_bh(&ar->data_lock);
                ar->rx_channel = conf->chandef.chan;
                spin_unlock_bh(&ar->data_lock);
+
+               ath10k_config_radar_detection(ar);
+       }
+
+       if (changed & IEEE80211_CONF_CHANGE_POWER) {
+               ath10k_dbg(ATH10K_DBG_MAC, "mac config power %d\n",
+                          hw->conf.power_level);
+
+               param = ar->wmi.pdev_param->txpower_limit2g;
+               ret = ath10k_wmi_pdev_set_param(ar, param,
+                                               hw->conf.power_level * 2);
+               if (ret)
+                       ath10k_warn("mac failed to set 2g txpower %d (%d)\n",
+                                   hw->conf.power_level, ret);
+
+               param = ar->wmi.pdev_param->txpower_limit5g;
+               ret = ath10k_wmi_pdev_set_param(ar, param,
+                                               hw->conf.power_level * 2);
+               if (ret)
+                       ath10k_warn("mac failed to set 5g txpower %d (%d)\n",
+                                   hw->conf.power_level, ret);
        }
 
        if (changed & IEEE80211_CONF_CHANGE_PS)
@@ -2049,6 +2217,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
        arvif->vif = vif;
 
        INIT_WORK(&arvif->wep_key_work, ath10k_tx_wep_key_work);
+       INIT_LIST_HEAD(&arvif->list);
 
        if ((vif->type == NL80211_IFTYPE_MONITOR) && ar->monitor_present) {
                ath10k_warn("Only one monitor interface allowed\n");
@@ -2265,8 +2434,14 @@ static void ath10k_configure_filter(struct ieee80211_hw *hw,
        *total_flags &= SUPPORTED_FILTERS;
        ar->filter_flags = *total_flags;
 
+       /* Monitor must not be started if it wasn't created first.
+        * Promiscuous mode may be started on a non-monitor interface - in
+        * such case the monitor vdev is not created so starting the
+        * monitor makes no sense. Since ath10k uses no special RX filters
+        * (only BSS filter in STA mode) there's no need for any special
+        * action here. */
        if ((ar->filter_flags & FIF_PROMISC_IN_BSS) &&
-           !ar->monitor_enabled) {
+           !ar->monitor_enabled && ar->monitor_present) {
                ath10k_dbg(ATH10K_DBG_MAC, "mac monitor %d start\n",
                           ar->monitor_vdev_id);
 
@@ -2274,7 +2449,7 @@ static void ath10k_configure_filter(struct ieee80211_hw *hw,
                if (ret)
                        ath10k_warn("Unable to start monitor mode\n");
        } else if (!(ar->filter_flags & FIF_PROMISC_IN_BSS) &&
-                  ar->monitor_enabled) {
+                  ar->monitor_enabled && ar->monitor_present) {
                ath10k_dbg(ATH10K_DBG_MAC, "mac monitor %d stop\n",
                           ar->monitor_vdev_id);
 
@@ -2360,8 +2535,8 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
                        ret = ath10k_peer_create(ar, arvif->vdev_id,
                                                 info->bssid);
                        if (ret)
-                               ath10k_warn("Failed to add peer: %pM for VDEV: %d\n",
-                                           info->bssid, arvif->vdev_id);
+                               ath10k_warn("Failed to add peer %pM for vdev %d when changin bssid: %i\n",
+                                           info->bssid, arvif->vdev_id, ret);
 
                        if (vif->type == NL80211_IFTYPE_STATION) {
                                /*
@@ -2542,6 +2717,44 @@ static void ath10k_cancel_hw_scan(struct ieee80211_hw *hw,
        mutex_unlock(&ar->conf_mutex);
 }
 
+static void ath10k_set_key_h_def_keyidx(struct ath10k *ar,
+                                       struct ath10k_vif *arvif,
+                                       enum set_key_cmd cmd,
+                                       struct ieee80211_key_conf *key)
+{
+       u32 vdev_param = arvif->ar->wmi.vdev_param->def_keyid;
+       int ret;
+
+       /* 10.1 firmware branch requires default key index to be set to group
+        * key index after installing it. Otherwise FW/HW Txes corrupted
+        * frames with multi-vif APs. This is not required for main firmware
+        * branch (e.g. 636).
+        *
+        * FIXME: This has been tested only in AP. It remains unknown if this
+        * is required for multi-vif STA interfaces on 10.1 */
+
+       if (arvif->vdev_type != WMI_VDEV_TYPE_AP)
+               return;
+
+       if (key->cipher == WLAN_CIPHER_SUITE_WEP40)
+               return;
+
+       if (key->cipher == WLAN_CIPHER_SUITE_WEP104)
+               return;
+
+       if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
+               return;
+
+       if (cmd != SET_KEY)
+               return;
+
+       ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
+                                       key->keyidx);
+       if (ret)
+               ath10k_warn("failed to set group key as default key: %d\n",
+                           ret);
+}
+
 static int ath10k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
                          struct ieee80211_vif *vif, struct ieee80211_sta *sta,
                          struct ieee80211_key_conf *key)
@@ -2603,6 +2816,8 @@ static int ath10k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
                goto exit;
        }
 
+       ath10k_set_key_h_def_keyidx(ar, arvif, cmd, key);
+
        spin_lock_bh(&ar->data_lock);
        peer = ath10k_peer_find(ar, arvif->vdev_id, peer_addr);
        if (peer && cmd == SET_KEY)
@@ -2643,8 +2858,8 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
 
                ret = ath10k_peer_create(ar, arvif->vdev_id, sta->addr);
                if (ret)
-                       ath10k_warn("Failed to add peer: %pM for VDEV: %d\n",
-                                   sta->addr, arvif->vdev_id);
+                       ath10k_warn("Failed to add peer %pM for vdev %d when adding a new sta: %i\n",
+                                   sta->addr, arvif->vdev_id, ret);
        } else if ((old_state == IEEE80211_STA_NONE &&
                    new_state == IEEE80211_STA_NOTEXIST)) {
                /*
@@ -3249,12 +3464,36 @@ static const struct ieee80211_iface_limit ath10k_if_limits[] = {
        },
 };
 
-static const struct ieee80211_iface_combination ath10k_if_comb = {
-       .limits = ath10k_if_limits,
-       .n_limits = ARRAY_SIZE(ath10k_if_limits),
-       .max_interfaces = 8,
-       .num_different_channels = 1,
-       .beacon_int_infra_match = true,
+#ifdef CONFIG_ATH10K_DFS_CERTIFIED
+static const struct ieee80211_iface_limit ath10k_if_dfs_limits[] = {
+       {
+       .max    = 8,
+       .types  = BIT(NL80211_IFTYPE_AP)
+       },
+};
+#endif
+
+static const struct ieee80211_iface_combination ath10k_if_comb[] = {
+       {
+               .limits = ath10k_if_limits,
+               .n_limits = ARRAY_SIZE(ath10k_if_limits),
+               .max_interfaces = 8,
+               .num_different_channels = 1,
+               .beacon_int_infra_match = true,
+       },
+#ifdef CONFIG_ATH10K_DFS_CERTIFIED
+       {
+               .limits = ath10k_if_dfs_limits,
+               .n_limits = ARRAY_SIZE(ath10k_if_dfs_limits),
+               .max_interfaces = 8,
+               .num_different_channels = 1,
+               .beacon_int_infra_match = true,
+               .radar_detect_widths =  BIT(NL80211_CHAN_WIDTH_20_NOHT) |
+                                       BIT(NL80211_CHAN_WIDTH_20) |
+                                       BIT(NL80211_CHAN_WIDTH_40) |
+                                       BIT(NL80211_CHAN_WIDTH_80),
+       }
+#endif
 };
 
 static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar)
@@ -3478,11 +3717,21 @@ int ath10k_mac_register(struct ath10k *ar)
         */
        ar->hw->queues = 4;
 
-       ar->hw->wiphy->iface_combinations = &ath10k_if_comb;
-       ar->hw->wiphy->n_iface_combinations = 1;
+       ar->hw->wiphy->iface_combinations = ath10k_if_comb;
+       ar->hw->wiphy->n_iface_combinations = ARRAY_SIZE(ath10k_if_comb);
 
        ar->hw->netdev_features = NETIF_F_HW_CSUM;
 
+       if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) {
+               /* Init ath dfs pattern detector */
+               ar->ath_common.debug_mask = ATH_DBG_DFS;
+               ar->dfs_detector = dfs_pattern_detector_init(&ar->ath_common,
+                                                            NL80211_DFS_UNSET);
+
+               if (!ar->dfs_detector)
+                       ath10k_warn("dfs pattern detector init failed\n");
+       }
+
        ret = ath_regd_init(&ar->ath_common.regulatory, ar->hw->wiphy,
                            ath10k_reg_notifier);
        if (ret) {
@@ -3518,6 +3767,9 @@ void ath10k_mac_unregister(struct ath10k *ar)
 {
        ieee80211_unregister_hw(ar->hw);
 
+       if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED) && ar->dfs_detector)
+               ar->dfs_detector->exit(ar->dfs_detector);
+
        kfree(ar->mac.sbands[IEEE80211_BAND_2GHZ].channels);
        kfree(ar->mac.sbands[IEEE80211_BAND_5GHZ].channels);
 
index 9e86a811086f6bf2e8316afdecdd29a4ec5195c9..29fd197d1fd8b3b7e8da66b212d0452c4e3ec3de 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
+#include <linux/bitops.h>
 
 #include "core.h"
 #include "debug.h"
 #include "ce.h"
 #include "pci.h"
 
+enum ath10k_pci_irq_mode {
+       ATH10K_PCI_IRQ_AUTO = 0,
+       ATH10K_PCI_IRQ_LEGACY = 1,
+       ATH10K_PCI_IRQ_MSI = 2,
+};
+
 static unsigned int ath10k_target_ps;
+static unsigned int ath10k_pci_irq_mode = ATH10K_PCI_IRQ_AUTO;
+
 module_param(ath10k_target_ps, uint, 0644);
 MODULE_PARM_DESC(ath10k_target_ps, "Enable ath10k Target (SoC) PS option");
 
+module_param_named(irq_mode, ath10k_pci_irq_mode, uint, 0644);
+MODULE_PARM_DESC(irq_mode, "0: auto, 1: legacy, 2: msi (default: 0)");
+
 #define QCA988X_2_0_DEVICE_ID  (0x003c)
 
 static DEFINE_PCI_DEVICE_TABLE(ath10k_pci_id_table) = {
@@ -52,10 +64,16 @@ static int ath10k_pci_post_rx_pipe(struct ath10k_pci_pipe *pipe_info,
                                             int num);
 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);
-static int ath10k_pci_start_intr(struct ath10k *ar);
-static void ath10k_pci_stop_intr(struct ath10k *ar);
+static int ath10k_pci_device_reset(struct ath10k *ar);
+static int ath10k_pci_wait_for_target_init(struct ath10k *ar);
+static int ath10k_pci_init_irq(struct ath10k *ar);
+static int ath10k_pci_deinit_irq(struct ath10k *ar);
+static int ath10k_pci_request_irq(struct ath10k *ar);
+static void ath10k_pci_free_irq(struct ath10k *ar);
+static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe,
+                              struct ath10k_ce_pipe *rx_pipe,
+                              struct bmi_xfer *xfer);
+static void ath10k_pci_cleanup_ce(struct ath10k *ar);
 
 static const struct ce_attr host_ce_config_wlan[] = {
        /* CE0: host->target HTC control and raw streams */
@@ -200,6 +218,87 @@ static const struct ce_pipe_config target_ce_config_wlan[] = {
        /* CE7 used only by Host */
 };
 
+static bool ath10k_pci_irq_pending(struct ath10k *ar)
+{
+       u32 cause;
+
+       /* Check if the shared legacy irq is for us */
+       cause = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
+                                 PCIE_INTR_CAUSE_ADDRESS);
+       if (cause & (PCIE_INTR_FIRMWARE_MASK | PCIE_INTR_CE_MASK_ALL))
+               return true;
+
+       return false;
+}
+
+static void ath10k_pci_disable_and_clear_legacy_irq(struct ath10k *ar)
+{
+       /* IMPORTANT: INTR_CLR register has to be set after
+        * INTR_ENABLE is set to 0, otherwise interrupt can not be
+        * really cleared. */
+       ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + PCIE_INTR_ENABLE_ADDRESS,
+                          0);
+       ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + PCIE_INTR_CLR_ADDRESS,
+                          PCIE_INTR_FIRMWARE_MASK | PCIE_INTR_CE_MASK_ALL);
+
+       /* IMPORTANT: this extra read transaction is required to
+        * flush the posted write buffer. */
+       (void) ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
+                                PCIE_INTR_ENABLE_ADDRESS);
+}
+
+static void ath10k_pci_enable_legacy_irq(struct ath10k *ar)
+{
+       ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS +
+                          PCIE_INTR_ENABLE_ADDRESS,
+                          PCIE_INTR_FIRMWARE_MASK | PCIE_INTR_CE_MASK_ALL);
+
+       /* IMPORTANT: this extra read transaction is required to
+        * flush the posted write buffer. */
+       (void) ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
+                                PCIE_INTR_ENABLE_ADDRESS);
+}
+
+static irqreturn_t ath10k_pci_early_irq_handler(int irq, void *arg)
+{
+       struct ath10k *ar = arg;
+       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+
+       if (ar_pci->num_msi_intrs == 0) {
+               if (!ath10k_pci_irq_pending(ar))
+                       return IRQ_NONE;
+
+               ath10k_pci_disable_and_clear_legacy_irq(ar);
+       }
+
+       tasklet_schedule(&ar_pci->early_irq_tasklet);
+
+       return IRQ_HANDLED;
+}
+
+static int ath10k_pci_request_early_irq(struct ath10k *ar)
+{
+       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+       int ret;
+
+       /* Regardless whether MSI-X/MSI/legacy irqs have been set up the first
+        * interrupt from irq vector is triggered in all cases for FW
+        * indication/errors */
+       ret = request_irq(ar_pci->pdev->irq, ath10k_pci_early_irq_handler,
+                         IRQF_SHARED, "ath10k_pci (early)", ar);
+       if (ret) {
+               ath10k_warn("failed to request early irq: %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static void ath10k_pci_free_early_irq(struct ath10k *ar)
+{
+       free_irq(ath10k_pci_priv(ar)->pdev->irq, ar);
+}
+
 /*
  * Diagnostic read/write access is provided for startup/config/debug usage.
  * Caller must guarantee proper alignment, when applicable, and single user
@@ -526,17 +625,6 @@ static bool ath10k_pci_target_is_awake(struct ath10k *ar)
        return (RTC_STATE_V_GET(val) == RTC_STATE_V_ON);
 }
 
-static void ath10k_pci_wait(struct ath10k *ar)
-{
-       int n = 100;
-
-       while (n-- && !ath10k_pci_target_is_awake(ar))
-               msleep(10);
-
-       if (n < 0)
-               ath10k_warn("Unable to wakeup target\n");
-}
-
 int ath10k_do_pci_wake(struct ath10k *ar)
 {
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
@@ -723,7 +811,7 @@ static int ath10k_pci_hif_send_head(struct ath10k *ar, u8 pipe_id,
        ret = ath10k_ce_send(ce_hdl, nbuf, skb_cb->paddr, len, transfer_id,
                             flags);
        if (ret)
-               ath10k_warn("CE send failed: %p\n", nbuf);
+               ath10k_warn("failed to send sk_buff to CE: %p\n", nbuf);
 
        return ret;
 }
@@ -750,9 +838,10 @@ static void ath10k_pci_hif_dump_area(struct ath10k *ar)
                   ar->fw_version_build);
 
        host_addr = host_interest_item_address(HI_ITEM(hi_failure_state));
-       if (ath10k_pci_diag_read_mem(ar, host_addr,
-                                    &reg_dump_area, sizeof(u32)) != 0) {
-               ath10k_warn("could not read hi_failure_state\n");
+       ret = ath10k_pci_diag_read_mem(ar, host_addr,
+                                      &reg_dump_area, sizeof(u32));
+       if (ret) {
+               ath10k_err("failed to read FW dump area address: %d\n", ret);
                return;
        }
 
@@ -762,7 +851,7 @@ static void ath10k_pci_hif_dump_area(struct ath10k *ar)
                                       &reg_dump_values[0],
                                       REG_DUMP_COUNT_QCA988X * sizeof(u32));
        if (ret != 0) {
-               ath10k_err("could not dump FW Dump Area\n");
+               ath10k_err("failed to read FW dump area: %d\n", ret);
                return;
        }
 
@@ -777,7 +866,7 @@ static void ath10k_pci_hif_dump_area(struct ath10k *ar)
                           reg_dump_values[i + 2],
                           reg_dump_values[i + 3]);
 
-       ieee80211_queue_work(ar->hw, &ar->restart_work);
+       queue_work(ar->workqueue, &ar->restart_work);
 }
 
 static void ath10k_pci_hif_send_complete_check(struct ath10k *ar, u8 pipe,
@@ -815,53 +904,41 @@ static void ath10k_pci_hif_set_callbacks(struct ath10k *ar,
               sizeof(ar_pci->msg_callbacks_current));
 }
 
-static int ath10k_pci_start_ce(struct ath10k *ar)
+static int ath10k_pci_alloc_compl(struct ath10k *ar)
 {
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-       struct ath10k_ce_pipe *ce_diag = ar_pci->ce_diag;
        const struct ce_attr *attr;
        struct ath10k_pci_pipe *pipe_info;
        struct ath10k_pci_compl *compl;
-       int i, pipe_num, completions, disable_interrupts;
+       int i, pipe_num, completions;
 
        spin_lock_init(&ar_pci->compl_lock);
        INIT_LIST_HEAD(&ar_pci->compl_process);
 
-       for (pipe_num = 0; pipe_num < ar_pci->ce_count; pipe_num++) {
+       for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) {
                pipe_info = &ar_pci->pipe_info[pipe_num];
 
                spin_lock_init(&pipe_info->pipe_lock);
                INIT_LIST_HEAD(&pipe_info->compl_free);
 
                /* Handle Diagnostic CE specially */
-               if (pipe_info->ce_hdl == ce_diag)
+               if (pipe_info->ce_hdl == ar_pci->ce_diag)
                        continue;
 
                attr = &host_ce_config_wlan[pipe_num];
                completions = 0;
 
-               if (attr->src_nentries) {
-                       disable_interrupts = attr->flags & CE_ATTR_DIS_INTR;
-                       ath10k_ce_send_cb_register(pipe_info->ce_hdl,
-                                                  ath10k_pci_ce_send_done,
-                                                  disable_interrupts);
+               if (attr->src_nentries)
                        completions += attr->src_nentries;
-               }
 
-               if (attr->dest_nentries) {
-                       ath10k_ce_recv_cb_register(pipe_info->ce_hdl,
-                                                  ath10k_pci_ce_recv_data);
+               if (attr->dest_nentries)
                        completions += attr->dest_nentries;
-               }
-
-               if (completions == 0)
-                       continue;
 
                for (i = 0; i < completions; i++) {
                        compl = kmalloc(sizeof(*compl), GFP_KERNEL);
                        if (!compl) {
                                ath10k_warn("No memory for completion state\n");
-                               ath10k_pci_stop_ce(ar);
+                               ath10k_pci_cleanup_ce(ar);
                                return -ENOMEM;
                        }
 
@@ -873,20 +950,55 @@ static int ath10k_pci_start_ce(struct ath10k *ar)
        return 0;
 }
 
-static void ath10k_pci_stop_ce(struct ath10k *ar)
+static int ath10k_pci_setup_ce_irq(struct ath10k *ar)
 {
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-       struct ath10k_pci_compl *compl;
-       struct sk_buff *skb;
-       int i;
+       const struct ce_attr *attr;
+       struct ath10k_pci_pipe *pipe_info;
+       int pipe_num, disable_interrupts;
 
-       ath10k_ce_disable_interrupts(ar);
+       for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) {
+               pipe_info = &ar_pci->pipe_info[pipe_num];
+
+               /* Handle Diagnostic CE specially */
+               if (pipe_info->ce_hdl == ar_pci->ce_diag)
+                       continue;
+
+               attr = &host_ce_config_wlan[pipe_num];
+
+               if (attr->src_nentries) {
+                       disable_interrupts = attr->flags & CE_ATTR_DIS_INTR;
+                       ath10k_ce_send_cb_register(pipe_info->ce_hdl,
+                                                  ath10k_pci_ce_send_done,
+                                                  disable_interrupts);
+               }
+
+               if (attr->dest_nentries)
+                       ath10k_ce_recv_cb_register(pipe_info->ce_hdl,
+                                                  ath10k_pci_ce_recv_data);
+       }
+
+       return 0;
+}
+
+static void ath10k_pci_kill_tasklet(struct ath10k *ar)
+{
+       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+       int i;
 
-       /* Cancel the pending tasklet */
        tasklet_kill(&ar_pci->intr_tq);
+       tasklet_kill(&ar_pci->msi_fw_err);
+       tasklet_kill(&ar_pci->early_irq_tasklet);
 
        for (i = 0; i < CE_COUNT; i++)
                tasklet_kill(&ar_pci->pipe_info[i].intr);
+}
+
+static void ath10k_pci_stop_ce(struct ath10k *ar)
+{
+       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+       struct ath10k_pci_compl *compl;
+       struct sk_buff *skb;
 
        /* Mark pending completions as aborted, so that upper layers free up
         * their associated resources */
@@ -920,7 +1032,7 @@ static void ath10k_pci_cleanup_ce(struct ath10k *ar)
        spin_unlock_bh(&ar_pci->compl_lock);
 
        /* Free unused completions for each pipe. */
-       for (pipe_num = 0; pipe_num < ar_pci->ce_count; pipe_num++) {
+       for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) {
                pipe_info = &ar_pci->pipe_info[pipe_num];
 
                spin_lock_bh(&pipe_info->pipe_lock);
@@ -974,8 +1086,8 @@ static void ath10k_pci_process_ce(struct ath10k *ar)
                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",
-                                           compl->pipe_info->pipe_num);
+                               ath10k_warn("failed to post RX buffer for pipe %d: %d\n",
+                                           compl->pipe_info->pipe_num, ret);
                                break;
                        }
 
@@ -1114,7 +1226,7 @@ static int ath10k_pci_post_rx_pipe(struct ath10k_pci_pipe *pipe_info,
        for (i = 0; i < num; i++) {
                skb = dev_alloc_skb(pipe_info->buf_sz);
                if (!skb) {
-                       ath10k_warn("could not allocate skbuff for pipe %d\n",
+                       ath10k_warn("failed to allocate skbuff for pipe %d\n",
                                    num);
                        ret = -ENOMEM;
                        goto err;
@@ -1127,7 +1239,7 @@ static int ath10k_pci_post_rx_pipe(struct ath10k_pci_pipe *pipe_info,
                                         DMA_FROM_DEVICE);
 
                if (unlikely(dma_mapping_error(ar->dev, ce_data))) {
-                       ath10k_warn("could not dma map skbuff\n");
+                       ath10k_warn("failed to DMA map sk_buff\n");
                        dev_kfree_skb_any(skb);
                        ret = -EIO;
                        goto err;
@@ -1142,7 +1254,7 @@ static int ath10k_pci_post_rx_pipe(struct ath10k_pci_pipe *pipe_info,
                ret = ath10k_ce_recv_buf_enqueue(ce_state, (void *)skb,
                                                 ce_data);
                if (ret) {
-                       ath10k_warn("could not enqueue to pipe %d (%d)\n",
+                       ath10k_warn("failed to enqueue to pipe %d: %d\n",
                                    num, ret);
                        goto err;
                }
@@ -1162,7 +1274,7 @@ static int ath10k_pci_post_rx(struct ath10k *ar)
        const struct ce_attr *attr;
        int pipe_num, ret = 0;
 
-       for (pipe_num = 0; pipe_num < ar_pci->ce_count; pipe_num++) {
+       for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) {
                pipe_info = &ar_pci->pipe_info[pipe_num];
                attr = &host_ce_config_wlan[pipe_num];
 
@@ -1172,8 +1284,8 @@ static int ath10k_pci_post_rx(struct ath10k *ar)
                ret = ath10k_pci_post_rx_pipe(pipe_info,
                                              attr->dest_nentries - 1);
                if (ret) {
-                       ath10k_warn("Unable to replenish recv buffers for pipe: %d\n",
-                                   pipe_num);
+                       ath10k_warn("failed to post RX buffer for pipe %d: %d\n",
+                                   pipe_num, ret);
 
                        for (; pipe_num >= 0; pipe_num--) {
                                pipe_info = &ar_pci->pipe_info[pipe_num];
@@ -1189,23 +1301,58 @@ static int ath10k_pci_post_rx(struct ath10k *ar)
 static int ath10k_pci_hif_start(struct ath10k *ar)
 {
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-       int ret;
+       int ret, ret_early;
 
-       ret = ath10k_pci_start_ce(ar);
+       ath10k_pci_free_early_irq(ar);
+       ath10k_pci_kill_tasklet(ar);
+
+       ret = ath10k_pci_alloc_compl(ar);
        if (ret) {
-               ath10k_warn("could not start CE (%d)\n", ret);
-               return ret;
+               ath10k_warn("failed to allocate CE completions: %d\n", ret);
+               goto err_early_irq;
+       }
+
+       ret = ath10k_pci_request_irq(ar);
+       if (ret) {
+               ath10k_warn("failed to post RX buffers for all pipes: %d\n",
+                           ret);
+               goto err_free_compl;
+       }
+
+       ret = ath10k_pci_setup_ce_irq(ar);
+       if (ret) {
+               ath10k_warn("failed to setup CE interrupts: %d\n", ret);
+               goto err_stop;
        }
 
        /* Post buffers once to start things off. */
        ret = ath10k_pci_post_rx(ar);
        if (ret) {
-               ath10k_warn("could not post rx pipes (%d)\n", ret);
-               return ret;
+               ath10k_warn("failed to post RX buffers for all pipes: %d\n",
+                           ret);
+               goto err_stop;
        }
 
        ar_pci->started = 1;
        return 0;
+
+err_stop:
+       ath10k_ce_disable_interrupts(ar);
+       ath10k_pci_free_irq(ar);
+       ath10k_pci_kill_tasklet(ar);
+       ath10k_pci_stop_ce(ar);
+       ath10k_pci_process_ce(ar);
+err_free_compl:
+       ath10k_pci_cleanup_ce(ar);
+err_early_irq:
+       /* Though there should be no interrupts (device was reset)
+        * power_down() expects the early IRQ to be installed as per the
+        * driver lifecycle. */
+       ret_early = ath10k_pci_request_early_irq(ar);
+       if (ret_early)
+               ath10k_warn("failed to re-enable early irq: %d\n", ret_early);
+
+       return ret;
 }
 
 static void ath10k_pci_rx_pipe_cleanup(struct ath10k_pci_pipe *pipe_info)
@@ -1271,6 +1418,13 @@ static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pipe_info)
                 * Indicate the completion to higer layer to free
                 * the buffer
                 */
+
+               if (!netbuf) {
+                       ath10k_warn("invalid sk_buff on CE %d - NULL pointer. firmware crashed?\n",
+                                   ce_hdl->id);
+                       continue;
+               }
+
                ATH10K_SKB_CB(netbuf)->is_aborted = true;
                ar_pci->msg_callbacks_current.tx_completion(ar,
                                                            netbuf,
@@ -1291,7 +1445,7 @@ static void ath10k_pci_buffer_cleanup(struct ath10k *ar)
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
        int pipe_num;
 
-       for (pipe_num = 0; pipe_num < ar_pci->ce_count; pipe_num++) {
+       for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) {
                struct ath10k_pci_pipe *pipe_info;
 
                pipe_info = &ar_pci->pipe_info[pipe_num];
@@ -1306,7 +1460,7 @@ static void ath10k_pci_ce_deinit(struct ath10k *ar)
        struct ath10k_pci_pipe *pipe_info;
        int pipe_num;
 
-       for (pipe_num = 0; pipe_num < ar_pci->ce_count; pipe_num++) {
+       for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) {
                pipe_info = &ar_pci->pipe_info[pipe_num];
                if (pipe_info->ce_hdl) {
                        ath10k_ce_deinit(pipe_info->ce_hdl);
@@ -1316,27 +1470,25 @@ static void ath10k_pci_ce_deinit(struct ath10k *ar)
        }
 }
 
-static void ath10k_pci_disable_irqs(struct ath10k *ar)
-{
-       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-       int i;
-
-       for (i = 0; i < max(1, ar_pci->num_msi_intrs); i++)
-               disable_irq(ar_pci->pdev->irq + i);
-}
-
 static void ath10k_pci_hif_stop(struct ath10k *ar)
 {
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+       int ret;
 
        ath10k_dbg(ATH10K_DBG_PCI, "%s\n", __func__);
 
-       /* Irqs are never explicitly re-enabled. They are implicitly re-enabled
-        * by ath10k_pci_start_intr(). */
-       ath10k_pci_disable_irqs(ar);
+       ret = ath10k_ce_disable_interrupts(ar);
+       if (ret)
+               ath10k_warn("failed to disable CE interrupts: %d\n", ret);
 
+       ath10k_pci_free_irq(ar);
+       ath10k_pci_kill_tasklet(ar);
        ath10k_pci_stop_ce(ar);
 
+       ret = ath10k_pci_request_early_irq(ar);
+       if (ret)
+               ath10k_warn("failed to re-enable early irq: %d\n", ret);
+
        /* At this point, asynchronous threads are stopped, the target should
         * not DMA nor interrupt. We process the leftovers and then free
         * everything else up. */
@@ -1345,6 +1497,13 @@ static void ath10k_pci_hif_stop(struct ath10k *ar)
        ath10k_pci_cleanup_ce(ar);
        ath10k_pci_buffer_cleanup(ar);
 
+       /* Make the sure the device won't access any structures on the host by
+        * resetting it. The device was fed with PCI CE ringbuffer
+        * configuration during init. If ringbuffers are freed and the device
+        * were to access them this could lead to memory corruption on the
+        * host. */
+       ath10k_pci_device_reset(ar);
+
        ar_pci->started = 0;
 }
 
@@ -1363,6 +1522,8 @@ static int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar,
        void *treq, *tresp = NULL;
        int ret = 0;
 
+       might_sleep();
+
        if (resp && !resp_len)
                return -EINVAL;
 
@@ -1403,14 +1564,12 @@ static int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar,
        if (ret)
                goto err_resp;
 
-       ret = wait_for_completion_timeout(&xfer.done,
-                                         BMI_COMMUNICATION_TIMEOUT_HZ);
-       if (ret <= 0) {
+       ret = ath10k_pci_bmi_wait(ce_tx, ce_rx, &xfer);
+       if (ret) {
                u32 unused_buffer;
                unsigned int unused_nbytes;
                unsigned int unused_id;
 
-               ret = -ETIMEDOUT;
                ath10k_ce_cancel_send_next(ce_tx, NULL, &unused_buffer,
                                           &unused_nbytes, &unused_id);
        } else {
@@ -1478,6 +1637,25 @@ static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state)
        complete(&xfer->done);
 }
 
+static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe,
+                              struct ath10k_ce_pipe *rx_pipe,
+                              struct bmi_xfer *xfer)
+{
+       unsigned long timeout = jiffies + BMI_COMMUNICATION_TIMEOUT_HZ;
+
+       while (time_before_eq(jiffies, timeout)) {
+               ath10k_pci_bmi_send_done(tx_pipe);
+               ath10k_pci_bmi_recv_data(rx_pipe);
+
+               if (completion_done(&xfer->done))
+                       return 0;
+
+               schedule();
+       }
+
+       return -ETIMEDOUT;
+}
+
 /*
  * Map from service/endpoint to Copy Engine.
  * This table is derived from the CE_PCI TABLE, above.
@@ -1587,7 +1765,7 @@ static int ath10k_pci_wake_target_cpu(struct ath10k *ar)
                                              CORE_CTRL_ADDRESS,
                                          &core_ctrl);
        if (ret) {
-               ath10k_warn("Unable to read core ctrl\n");
+               ath10k_warn("failed to read core_ctrl: %d\n", ret);
                return ret;
        }
 
@@ -1597,10 +1775,13 @@ static int ath10k_pci_wake_target_cpu(struct ath10k *ar)
        ret = ath10k_pci_diag_write_access(ar, SOC_CORE_BASE_ADDRESS |
                                               CORE_CTRL_ADDRESS,
                                           core_ctrl);
-       if (ret)
-               ath10k_warn("Unable to set interrupt mask\n");
+       if (ret) {
+               ath10k_warn("failed to set target CPU interrupt mask: %d\n",
+                           ret);
+               return ret;
+       }
 
-       return ret;
+       return 0;
 }
 
 static int ath10k_pci_init_config(struct ath10k *ar)
@@ -1751,7 +1932,7 @@ static int ath10k_pci_ce_init(struct ath10k *ar)
        const struct ce_attr *attr;
        int pipe_num;
 
-       for (pipe_num = 0; pipe_num < ar_pci->ce_count; pipe_num++) {
+       for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) {
                pipe_info = &ar_pci->pipe_info[pipe_num];
                pipe_info->pipe_num = pipe_num;
                pipe_info->hif_ce_state = ar;
@@ -1759,7 +1940,7 @@ static int ath10k_pci_ce_init(struct ath10k *ar)
 
                pipe_info->ce_hdl = ath10k_ce_init(ar, pipe_num, attr);
                if (pipe_info->ce_hdl == NULL) {
-                       ath10k_err("Unable to initialize CE for pipe: %d\n",
+                       ath10k_err("failed to initialize CE for pipe: %d\n",
                                   pipe_num);
 
                        /* It is safe to call it here. It checks if ce_hdl is
@@ -1768,31 +1949,18 @@ static int ath10k_pci_ce_init(struct ath10k *ar)
                        return -1;
                }
 
-               if (pipe_num == ar_pci->ce_count - 1) {
+               if (pipe_num == CE_COUNT - 1) {
                        /*
                         * Reserve the ultimate CE for
                         * diagnostic Window support
                         */
-                       ar_pci->ce_diag =
-                       ar_pci->pipe_info[ar_pci->ce_count - 1].ce_hdl;
+                       ar_pci->ce_diag = pipe_info->ce_hdl;
                        continue;
                }
 
                pipe_info->buf_sz = (size_t) (attr->src_sz_max);
        }
 
-       /*
-        * Initially, establish CE completion handlers for use with BMI.
-        * These are overwritten with generic handlers after we exit BMI phase.
-        */
-       pipe_info = &ar_pci->pipe_info[BMI_CE_NUM_TO_TARG];
-       ath10k_ce_send_cb_register(pipe_info->ce_hdl,
-                                  ath10k_pci_bmi_send_done, 0);
-
-       pipe_info = &ar_pci->pipe_info[BMI_CE_NUM_TO_HOST];
-       ath10k_ce_recv_cb_register(pipe_info->ce_hdl,
-                                  ath10k_pci_bmi_recv_data);
-
        return 0;
 }
 
@@ -1828,14 +1996,9 @@ static void ath10k_pci_fw_interrupt_handler(struct ath10k *ar)
 static int ath10k_pci_hif_power_up(struct ath10k *ar)
 {
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+       const char *irq_mode;
        int ret;
 
-       ret = ath10k_pci_start_intr(ar);
-       if (ret) {
-               ath10k_err("could not start interrupt handling (%d)\n", ret);
-               goto err;
-       }
-
        /*
         * Bring the target up cleanly.
         *
@@ -1846,39 +2009,80 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar)
         * is in an unexpected state. We try to catch that here in order to
         * reset the Target and retry the probe.
         */
-       ath10k_pci_device_reset(ar);
-
-       ret = ath10k_pci_reset_target(ar);
-       if (ret)
-               goto err_irq;
+       ret = ath10k_pci_device_reset(ar);
+       if (ret) {
+               ath10k_err("failed to reset target: %d\n", ret);
+               goto err;
+       }
 
        if (!test_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features))
                /* Force AWAKE forever */
                ath10k_do_pci_wake(ar);
 
        ret = ath10k_pci_ce_init(ar);
-       if (ret)
+       if (ret) {
+               ath10k_err("failed to initialize CE: %d\n", ret);
                goto err_ps;
+       }
 
-       ret = ath10k_pci_init_config(ar);
-       if (ret)
+       ret = ath10k_ce_disable_interrupts(ar);
+       if (ret) {
+               ath10k_err("failed to disable CE interrupts: %d\n", ret);
                goto err_ce;
+       }
 
-       ret = ath10k_pci_wake_target_cpu(ar);
+       ret = ath10k_pci_init_irq(ar);
        if (ret) {
-               ath10k_err("could not wake up target CPU (%d)\n", ret);
+               ath10k_err("failed to init irqs: %d\n", ret);
                goto err_ce;
        }
 
+       ret = ath10k_pci_request_early_irq(ar);
+       if (ret) {
+               ath10k_err("failed to request early irq: %d\n", ret);
+               goto err_deinit_irq;
+       }
+
+       ret = ath10k_pci_wait_for_target_init(ar);
+       if (ret) {
+               ath10k_err("failed to wait for target to init: %d\n", ret);
+               goto err_free_early_irq;
+       }
+
+       ret = ath10k_pci_init_config(ar);
+       if (ret) {
+               ath10k_err("failed to setup init config: %d\n", ret);
+               goto err_free_early_irq;
+       }
+
+       ret = ath10k_pci_wake_target_cpu(ar);
+       if (ret) {
+               ath10k_err("could not wake up target CPU: %d\n", ret);
+               goto err_free_early_irq;
+       }
+
+       if (ar_pci->num_msi_intrs > 1)
+               irq_mode = "MSI-X";
+       else if (ar_pci->num_msi_intrs == 1)
+               irq_mode = "MSI";
+       else
+               irq_mode = "legacy";
+
+       if (!test_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags))
+               ath10k_info("pci irq %s\n", irq_mode);
+
        return 0;
 
+err_free_early_irq:
+       ath10k_pci_free_early_irq(ar);
+err_deinit_irq:
+       ath10k_pci_deinit_irq(ar);
 err_ce:
        ath10k_pci_ce_deinit(ar);
+       ath10k_pci_device_reset(ar);
 err_ps:
        if (!test_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features))
                ath10k_do_pci_sleep(ar);
-err_irq:
-       ath10k_pci_stop_intr(ar);
 err:
        return ret;
 }
@@ -1887,7 +2091,10 @@ static void ath10k_pci_hif_power_down(struct ath10k *ar)
 {
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
 
-       ath10k_pci_stop_intr(ar);
+       ath10k_pci_free_early_irq(ar);
+       ath10k_pci_kill_tasklet(ar);
+       ath10k_pci_deinit_irq(ar);
+       ath10k_pci_device_reset(ar);
 
        ath10k_pci_ce_deinit(ar);
        if (!test_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features))
@@ -2023,25 +2230,10 @@ static irqreturn_t ath10k_pci_interrupt_handler(int irq, void *arg)
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
 
        if (ar_pci->num_msi_intrs == 0) {
-               /*
-                * IMPORTANT: INTR_CLR regiser has to be set after
-                * INTR_ENABLE is set to 0, otherwise interrupt can not be
-                * really cleared.
-                */
-               iowrite32(0, ar_pci->mem +
-                         (SOC_CORE_BASE_ADDRESS |
-                          PCIE_INTR_ENABLE_ADDRESS));
-               iowrite32(PCIE_INTR_FIRMWARE_MASK |
-                         PCIE_INTR_CE_MASK_ALL,
-                         ar_pci->mem + (SOC_CORE_BASE_ADDRESS |
-                                        PCIE_INTR_CLR_ADDRESS));
-               /*
-                * IMPORTANT: this extra read transaction is required to
-                * flush the posted write buffer.
-                */
-               (void) ioread32(ar_pci->mem +
-                               (SOC_CORE_BASE_ADDRESS |
-                                PCIE_INTR_ENABLE_ADDRESS));
+               if (!ath10k_pci_irq_pending(ar))
+                       return IRQ_NONE;
+
+               ath10k_pci_disable_and_clear_legacy_irq(ar);
        }
 
        tasklet_schedule(&ar_pci->intr_tq);
@@ -2049,6 +2241,34 @@ static irqreturn_t ath10k_pci_interrupt_handler(int irq, void *arg)
        return IRQ_HANDLED;
 }
 
+static void ath10k_pci_early_irq_tasklet(unsigned long data)
+{
+       struct ath10k *ar = (struct ath10k *)data;
+       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+       u32 fw_ind;
+       int ret;
+
+       ret = ath10k_pci_wake(ar);
+       if (ret) {
+               ath10k_warn("failed to wake target in early irq tasklet: %d\n",
+                           ret);
+               return;
+       }
+
+       fw_ind = ath10k_pci_read32(ar, ar_pci->fw_indicator_address);
+       if (fw_ind & FW_IND_EVENT_PENDING) {
+               ath10k_pci_write32(ar, ar_pci->fw_indicator_address,
+                                  fw_ind & ~FW_IND_EVENT_PENDING);
+
+               /* Some structures are unavailable during early boot or at
+                * driver teardown so just print that the device has crashed. */
+               ath10k_warn("device crashed - no diagnostics available\n");
+       }
+
+       ath10k_pci_sleep(ar);
+       ath10k_pci_enable_legacy_irq(ar);
+}
+
 static void ath10k_pci_tasklet(unsigned long data)
 {
        struct ath10k *ar = (struct ath10k *)data;
@@ -2057,40 +2277,22 @@ static void ath10k_pci_tasklet(unsigned long data)
        ath10k_pci_fw_interrupt_handler(ar); /* FIXME: Handle FW error */
        ath10k_ce_per_engine_service_any(ar);
 
-       if (ar_pci->num_msi_intrs == 0) {
-               /* Enable Legacy PCI line interrupts */
-               iowrite32(PCIE_INTR_FIRMWARE_MASK |
-                         PCIE_INTR_CE_MASK_ALL,
-                         ar_pci->mem + (SOC_CORE_BASE_ADDRESS |
-                                        PCIE_INTR_ENABLE_ADDRESS));
-               /*
-                * IMPORTANT: this extra read transaction is required to
-                * flush the posted write buffer
-                */
-               (void) ioread32(ar_pci->mem +
-                               (SOC_CORE_BASE_ADDRESS |
-                                PCIE_INTR_ENABLE_ADDRESS));
-       }
+       /* Re-enable legacy irq that was disabled in the irq handler */
+       if (ar_pci->num_msi_intrs == 0)
+               ath10k_pci_enable_legacy_irq(ar);
 }
 
-static int ath10k_pci_start_intr_msix(struct ath10k *ar, int num)
+static int ath10k_pci_request_irq_msix(struct ath10k *ar)
 {
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-       int ret;
-       int i;
-
-       ret = pci_enable_msi_block(ar_pci->pdev, num);
-       if (ret)
-               return ret;
+       int ret, i;
 
        ret = request_irq(ar_pci->pdev->irq + MSI_ASSIGN_FW,
                          ath10k_pci_msi_fw_handler,
                          IRQF_SHARED, "ath10k_pci", ar);
        if (ret) {
-               ath10k_warn("request_irq(%d) failed %d\n",
+               ath10k_warn("failed to request MSI-X fw irq %d: %d\n",
                            ar_pci->pdev->irq + MSI_ASSIGN_FW, ret);
-
-               pci_disable_msi(ar_pci->pdev);
                return ret;
        }
 
@@ -2099,44 +2301,38 @@ static int ath10k_pci_start_intr_msix(struct ath10k *ar, int num)
                                  ath10k_pci_per_engine_handler,
                                  IRQF_SHARED, "ath10k_pci", ar);
                if (ret) {
-                       ath10k_warn("request_irq(%d) failed %d\n",
+                       ath10k_warn("failed to request MSI-X ce irq %d: %d\n",
                                    ar_pci->pdev->irq + i, ret);
 
                        for (i--; i >= MSI_ASSIGN_CE_INITIAL; i--)
                                free_irq(ar_pci->pdev->irq + i, ar);
 
                        free_irq(ar_pci->pdev->irq + MSI_ASSIGN_FW, ar);
-                       pci_disable_msi(ar_pci->pdev);
                        return ret;
                }
        }
 
-       ath10k_info("MSI-X interrupt handling (%d intrs)\n", num);
        return 0;
 }
 
-static int ath10k_pci_start_intr_msi(struct ath10k *ar)
+static int ath10k_pci_request_irq_msi(struct ath10k *ar)
 {
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
        int ret;
 
-       ret = pci_enable_msi(ar_pci->pdev);
-       if (ret < 0)
-               return ret;
-
        ret = request_irq(ar_pci->pdev->irq,
                          ath10k_pci_interrupt_handler,
                          IRQF_SHARED, "ath10k_pci", ar);
-       if (ret < 0) {
-               pci_disable_msi(ar_pci->pdev);
+       if (ret) {
+               ath10k_warn("failed to request MSI irq %d: %d\n",
+                           ar_pci->pdev->irq, ret);
                return ret;
        }
 
-       ath10k_info("MSI interrupt handling\n");
        return 0;
 }
 
-static int ath10k_pci_start_intr_legacy(struct ath10k *ar)
+static int ath10k_pci_request_irq_legacy(struct ath10k *ar)
 {
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
        int ret;
@@ -2144,112 +2340,165 @@ static int ath10k_pci_start_intr_legacy(struct ath10k *ar)
        ret = request_irq(ar_pci->pdev->irq,
                          ath10k_pci_interrupt_handler,
                          IRQF_SHARED, "ath10k_pci", ar);
-       if (ret < 0)
+       if (ret) {
+               ath10k_warn("failed to request legacy irq %d: %d\n",
+                           ar_pci->pdev->irq, ret);
                return ret;
+       }
 
-       /*
-        * Make sure to wake the Target before enabling Legacy
-        * Interrupt.
-        */
-       iowrite32(PCIE_SOC_WAKE_V_MASK,
-                 ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS +
-                 PCIE_SOC_WAKE_ADDRESS);
+       return 0;
+}
+
+static int ath10k_pci_request_irq(struct ath10k *ar)
+{
+       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
 
-       ath10k_pci_wait(ar);
+       switch (ar_pci->num_msi_intrs) {
+       case 0:
+               return ath10k_pci_request_irq_legacy(ar);
+       case 1:
+               return ath10k_pci_request_irq_msi(ar);
+       case MSI_NUM_REQUEST:
+               return ath10k_pci_request_irq_msix(ar);
+       }
 
-       /*
-        * A potential race occurs here: The CORE_BASE write
-        * depends on target correctly decoding AXI address but
-        * host won't know when target writes BAR to CORE_CTRL.
-        * This write might get lost if target has NOT written BAR.
-        * For now, fix the race by repeating the write in below
-        * synchronization checking.
-        */
-       iowrite32(PCIE_INTR_FIRMWARE_MASK |
-                 PCIE_INTR_CE_MASK_ALL,
-                 ar_pci->mem + (SOC_CORE_BASE_ADDRESS |
-                                PCIE_INTR_ENABLE_ADDRESS));
-       iowrite32(PCIE_SOC_WAKE_RESET,
-                 ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS +
-                 PCIE_SOC_WAKE_ADDRESS);
-
-       ath10k_info("legacy interrupt handling\n");
-       return 0;
+       ath10k_warn("unknown irq configuration upon request\n");
+       return -EINVAL;
 }
 
-static int ath10k_pci_start_intr(struct ath10k *ar)
+static void ath10k_pci_free_irq(struct ath10k *ar)
+{
+       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+       int i;
+
+       /* There's at least one interrupt irregardless whether its legacy INTR
+        * or MSI or MSI-X */
+       for (i = 0; i < max(1, ar_pci->num_msi_intrs); i++)
+               free_irq(ar_pci->pdev->irq + i, ar);
+}
+
+static void ath10k_pci_init_irq_tasklets(struct ath10k *ar)
 {
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-       int num = MSI_NUM_REQUEST;
-       int ret;
        int i;
 
-       tasklet_init(&ar_pci->intr_tq, ath10k_pci_tasklet, (unsigned long) ar);
+       tasklet_init(&ar_pci->intr_tq, ath10k_pci_tasklet, (unsigned long)ar);
        tasklet_init(&ar_pci->msi_fw_err, ath10k_msi_err_tasklet,
-                    (unsigned long) ar);
+                    (unsigned long)ar);
+       tasklet_init(&ar_pci->early_irq_tasklet, ath10k_pci_early_irq_tasklet,
+                    (unsigned long)ar);
 
        for (i = 0; i < CE_COUNT; i++) {
                ar_pci->pipe_info[i].ar_pci = ar_pci;
-               tasklet_init(&ar_pci->pipe_info[i].intr,
-                            ath10k_pci_ce_tasklet,
+               tasklet_init(&ar_pci->pipe_info[i].intr, ath10k_pci_ce_tasklet,
                             (unsigned long)&ar_pci->pipe_info[i]);
        }
+}
+
+static int ath10k_pci_init_irq(struct ath10k *ar)
+{
+       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+       bool msix_supported = test_bit(ATH10K_PCI_FEATURE_MSI_X,
+                                      ar_pci->features);
+       int ret;
 
-       if (!test_bit(ATH10K_PCI_FEATURE_MSI_X, ar_pci->features))
-               num = 1;
+       ath10k_pci_init_irq_tasklets(ar);
 
-       if (num > 1) {
-               ret = ath10k_pci_start_intr_msix(ar, num);
+       if (ath10k_pci_irq_mode != ATH10K_PCI_IRQ_AUTO &&
+           !test_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags))
+               ath10k_info("limiting irq mode to: %d\n", ath10k_pci_irq_mode);
+
+       /* Try MSI-X */
+       if (ath10k_pci_irq_mode == ATH10K_PCI_IRQ_AUTO && msix_supported) {
+               ar_pci->num_msi_intrs = MSI_NUM_REQUEST;
+               ret = pci_enable_msi_block(ar_pci->pdev, ar_pci->num_msi_intrs);
                if (ret == 0)
-                       goto exit;
+                       return 0;
+               if (ret > 0)
+                       pci_disable_msi(ar_pci->pdev);
 
-               ath10k_warn("MSI-X didn't succeed (%d), trying MSI\n", ret);
-               num = 1;
+               /* fall-through */
        }
 
-       if (num == 1) {
-               ret = ath10k_pci_start_intr_msi(ar);
+       /* Try MSI */
+       if (ath10k_pci_irq_mode != ATH10K_PCI_IRQ_LEGACY) {
+               ar_pci->num_msi_intrs = 1;
+               ret = pci_enable_msi(ar_pci->pdev);
                if (ret == 0)
-                       goto exit;
+                       return 0;
 
-               ath10k_warn("MSI didn't succeed (%d), trying legacy INTR\n",
-                           ret);
-               num = 0;
+               /* fall-through */
        }
 
-       ret = ath10k_pci_start_intr_legacy(ar);
+       /* Try legacy irq
+        *
+        * A potential race occurs here: The CORE_BASE write
+        * depends on target correctly decoding AXI address but
+        * host won't know when target writes BAR to CORE_CTRL.
+        * This write might get lost if target has NOT written BAR.
+        * For now, fix the race by repeating the write in below
+        * synchronization checking. */
+       ar_pci->num_msi_intrs = 0;
 
-exit:
-       ar_pci->num_msi_intrs = num;
-       ar_pci->ce_count = CE_COUNT;
-       return ret;
+       ret = ath10k_pci_wake(ar);
+       if (ret) {
+               ath10k_warn("failed to wake target: %d\n", ret);
+               return ret;
+       }
+
+       ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + PCIE_INTR_ENABLE_ADDRESS,
+                          PCIE_INTR_FIRMWARE_MASK | PCIE_INTR_CE_MASK_ALL);
+       ath10k_pci_sleep(ar);
+
+       return 0;
 }
 
-static void ath10k_pci_stop_intr(struct ath10k *ar)
+static int ath10k_pci_deinit_irq_legacy(struct ath10k *ar)
 {
-       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-       int i;
+       int ret;
 
-       /* There's at least one interrupt irregardless whether its legacy INTR
-        * or MSI or MSI-X */
-       for (i = 0; i < max(1, ar_pci->num_msi_intrs); i++)
-               free_irq(ar_pci->pdev->irq + i, ar);
+       ret = ath10k_pci_wake(ar);
+       if (ret) {
+               ath10k_warn("failed to wake target: %d\n", ret);
+               return ret;
+       }
 
-       if (ar_pci->num_msi_intrs > 0)
+       ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + PCIE_INTR_ENABLE_ADDRESS,
+                          0);
+       ath10k_pci_sleep(ar);
+
+       return 0;
+}
+
+static int ath10k_pci_deinit_irq(struct ath10k *ar)
+{
+       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+
+       switch (ar_pci->num_msi_intrs) {
+       case 0:
+               return ath10k_pci_deinit_irq_legacy(ar);
+       case 1:
+               /* fall-through */
+       case MSI_NUM_REQUEST:
                pci_disable_msi(ar_pci->pdev);
+               return 0;
+       }
+
+       ath10k_warn("unknown irq configuration upon deinit\n");
+       return -EINVAL;
 }
 
-static int ath10k_pci_reset_target(struct ath10k *ar)
+static int ath10k_pci_wait_for_target_init(struct ath10k *ar)
 {
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
        int wait_limit = 300; /* 3 sec */
+       int ret;
 
-       /* Wait for Target to finish initialization before we proceed. */
-       iowrite32(PCIE_SOC_WAKE_V_MASK,
-                 ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS +
-                 PCIE_SOC_WAKE_ADDRESS);
-
-       ath10k_pci_wait(ar);
+       ret = ath10k_pci_wake(ar);
+       if (ret) {
+               ath10k_err("failed to wake up target: %d\n", ret);
+               return ret;
+       }
 
        while (wait_limit-- &&
               !(ioread32(ar_pci->mem + FW_INDICATOR_ADDRESS) &
@@ -2264,34 +2513,26 @@ static int ath10k_pci_reset_target(struct ath10k *ar)
        }
 
        if (wait_limit < 0) {
-               ath10k_err("Target stalled\n");
-               iowrite32(PCIE_SOC_WAKE_RESET,
-                         ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS +
-                         PCIE_SOC_WAKE_ADDRESS);
-               return -EIO;
+               ath10k_err("target stalled\n");
+               ret = -EIO;
+               goto out;
        }
 
-       iowrite32(PCIE_SOC_WAKE_RESET,
-                 ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS +
-                 PCIE_SOC_WAKE_ADDRESS);
-
-       return 0;
+out:
+       ath10k_pci_sleep(ar);
+       return ret;
 }
 
-static void ath10k_pci_device_reset(struct ath10k *ar)
+static int ath10k_pci_device_reset(struct ath10k *ar)
 {
-       int i;
+       int i, ret;
        u32 val;
 
-       if (!SOC_GLOBAL_RESET_ADDRESS)
-               return;
-
-       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))
-                       break;
-               msleep(1);
+       ret = ath10k_do_pci_wake(ar);
+       if (ret) {
+               ath10k_err("failed to wake up target: %d\n",
+                          ret);
+               return ret;
        }
 
        /* Put Target, including PCIe, into RESET. */
@@ -2317,7 +2558,8 @@ static void ath10k_pci_device_reset(struct ath10k *ar)
                msleep(1);
        }
 
-       ath10k_pci_reg_write32(ar, PCIE_SOC_WAKE_ADDRESS, PCIE_SOC_WAKE_RESET);
+       ath10k_do_pci_sleep(ar);
+       return 0;
 }
 
 static void ath10k_pci_dump_features(struct ath10k_pci *ar_pci)
@@ -2374,7 +2616,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
 
        ar = ath10k_core_create(ar_pci, ar_pci->dev, &ath10k_pci_hif_ops);
        if (!ar) {
-               ath10k_err("ath10k_core_create failed!\n");
+               ath10k_err("failed to create driver core\n");
                ret = -EINVAL;
                goto err_ar_pci;
        }
@@ -2393,20 +2635,20 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
         */
        ret = pci_assign_resource(pdev, BAR_NUM);
        if (ret) {
-               ath10k_err("cannot assign PCI space: %d\n", ret);
+               ath10k_err("failed to assign PCI space: %d\n", ret);
                goto err_ar;
        }
 
        ret = pci_enable_device(pdev);
        if (ret) {
-               ath10k_err("cannot enable PCI device: %d\n", ret);
+               ath10k_err("failed to enable PCI device: %d\n", ret);
                goto err_ar;
        }
 
        /* Request MMIO resources */
        ret = pci_request_region(pdev, BAR_NUM, "ath");
        if (ret) {
-               ath10k_err("PCI MMIO reservation error: %d\n", ret);
+               ath10k_err("failed to request MMIO region: %d\n", ret);
                goto err_device;
        }
 
@@ -2416,13 +2658,13 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
         */
        ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
        if (ret) {
-               ath10k_err("32-bit DMA not available: %d\n", ret);
+               ath10k_err("failed to set DMA mask to 32-bit: %d\n", ret);
                goto err_region;
        }
 
        ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
        if (ret) {
-               ath10k_err("cannot enable 32-bit consistent DMA\n");
+               ath10k_err("failed to set consistent DMA mask to 32-bit\n");
                goto err_region;
        }
 
@@ -2439,7 +2681,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
        /* Arrange for access to Target SoC registers. */
        mem = pci_iomap(pdev, BAR_NUM, 0);
        if (!mem) {
-               ath10k_err("PCI iomap error\n");
+               ath10k_err("failed to perform IOMAP for BAR%d\n", BAR_NUM);
                ret = -EIO;
                goto err_master;
        }
@@ -2451,11 +2693,10 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
        ret = ath10k_do_pci_wake(ar);
        if (ret) {
                ath10k_err("Failed to get chip id: %d\n", ret);
-               return ret;
+               goto err_iomap;
        }
 
-       chip_id = ath10k_pci_read32(ar,
-                                   RTC_SOC_BASE_ADDRESS + SOC_CHIP_ID_ADDRESS);
+       chip_id = ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS);
 
        ath10k_do_pci_sleep(ar);
 
@@ -2463,7 +2704,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
 
        ret = ath10k_core_register(ar, chip_id);
        if (ret) {
-               ath10k_err("could not register driver core (%d)\n", ret);
+               ath10k_err("failed to register driver core: %d\n", ret);
                goto err_iomap;
        }
 
@@ -2529,7 +2770,7 @@ static int __init ath10k_pci_init(void)
 
        ret = pci_register_driver(&ath10k_pci_driver);
        if (ret)
-               ath10k_err("pci_register_driver failed [%d]\n", ret);
+               ath10k_err("failed to register PCI driver: %d\n", ret);
 
        return ret;
 }
index 52fb7b9735714ea3f2dbf3ed03936ac3ae11f5c7..a4f32038c440b7d36009496cde6b5f26ea95c23b 100644 (file)
@@ -198,9 +198,7 @@ struct ath10k_pci {
 
        struct tasklet_struct intr_tq;
        struct tasklet_struct msi_fw_err;
-
-       /* Number of Copy Engines supported */
-       unsigned int ce_count;
+       struct tasklet_struct early_irq_tasklet;
 
        int started;
 
@@ -318,6 +316,16 @@ static inline u32 ath10k_pci_read32(struct ath10k *ar, u32 offset)
        return ioread32(ar_pci->mem + offset);
 }
 
+static inline u32 ath10k_pci_soc_read32(struct ath10k *ar, u32 addr)
+{
+       return ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + addr);
+}
+
+static inline void ath10k_pci_soc_write32(struct ath10k *ar, u32 addr, u32 val)
+{
+       ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + addr, val);
+}
+
 int ath10k_do_pci_wake(struct ath10k *ar);
 void ath10k_do_pci_sleep(struct ath10k *ar);
 
index 5ae373a1e2942fbcb3d185533d41eaf9dd8e24bd..22829803f087bf63c5946d788e4ae386613b6cb8 100644 (file)
@@ -75,6 +75,7 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
        ath10k_report_offchan_tx(htt->ar, msdu);
 
        info = IEEE80211_SKB_CB(msdu);
+       memset(&info->status, 0, sizeof(info->status));
 
        if (tx_done->discard) {
                ieee80211_free_txskb(htt->ar->hw, msdu);
@@ -183,7 +184,7 @@ static void process_rx_rates(struct ath10k *ar, struct htt_rx_info *info,
                /* VHT-SIG-A1 in info 1, VHT-SIG-A2 in info2
                   TODO check this */
                mcs = (info2 >> 4) & 0x0F;
-               nss = (info1 >> 10) & 0x07;
+               nss = ((info1 >> 10) & 0x07) + 1;
                bw = info1 & 3;
                sgi = info2 & 1;
 
@@ -236,6 +237,9 @@ void ath10k_process_rx(struct ath10k *ar, struct htt_rx_info *info)
        if (info->fcs_err)
                status->flag |= RX_FLAG_FAILED_FCS_CRC;
 
+       if (info->amsdu_more)
+               status->flag |= RX_FLAG_AMSDU_MORE;
+
        status->signal = info->signal;
 
        spin_lock_bh(&ar->data_lock);
index ccf3597fd9e2511c11cce44e136c3d1c50c59d06..1260a8d15dc3a5672f1eda93652fc7aa5133d121 100644 (file)
@@ -674,10 +674,8 @@ int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb)
 
        /* Send the management frame buffer to the target */
        ret = ath10k_wmi_cmd_send(ar, wmi_skb, ar->wmi.cmd->mgmt_tx_cmdid);
-       if (ret) {
-               dev_kfree_skb_any(skb);
+       if (ret)
                return ret;
-       }
 
        /* TODO: report tx status to mac80211 - temporary just ACK */
        info->flags |= IEEE80211_TX_STAT_ACK;
@@ -909,6 +907,11 @@ static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
        ath10k_dbg(ATH10K_DBG_MGMT,
                   "event mgmt rx status %08x\n", rx_status);
 
+       if (test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags)) {
+               dev_kfree_skb(skb);
+               return 0;
+       }
+
        if (rx_status & WMI_RX_STATUS_ERR_DECRYPT) {
                dev_kfree_skb(skb);
                return 0;
@@ -1383,9 +1386,259 @@ static void ath10k_wmi_event_tbttoffset_update(struct ath10k *ar,
        ath10k_dbg(ATH10K_DBG_WMI, "WMI_TBTTOFFSET_UPDATE_EVENTID\n");
 }
 
+static void ath10k_dfs_radar_report(struct ath10k *ar,
+                                   struct wmi_single_phyerr_rx_event *event,
+                                   struct phyerr_radar_report *rr,
+                                   u64 tsf)
+{
+       u32 reg0, reg1, tsf32l;
+       struct pulse_event pe;
+       u64 tsf64;
+       u8 rssi, width;
+
+       reg0 = __le32_to_cpu(rr->reg0);
+       reg1 = __le32_to_cpu(rr->reg1);
+
+       ath10k_dbg(ATH10K_DBG_REGULATORY,
+                  "wmi phyerr radar report chirp %d max_width %d agc_total_gain %d pulse_delta_diff %d\n",
+                  MS(reg0, RADAR_REPORT_REG0_PULSE_IS_CHIRP),
+                  MS(reg0, RADAR_REPORT_REG0_PULSE_IS_MAX_WIDTH),
+                  MS(reg0, RADAR_REPORT_REG0_AGC_TOTAL_GAIN),
+                  MS(reg0, RADAR_REPORT_REG0_PULSE_DELTA_DIFF));
+       ath10k_dbg(ATH10K_DBG_REGULATORY,
+                  "wmi phyerr radar report pulse_delta_pean %d pulse_sidx %d fft_valid %d agc_mb_gain %d subchan_mask %d\n",
+                  MS(reg0, RADAR_REPORT_REG0_PULSE_DELTA_PEAK),
+                  MS(reg0, RADAR_REPORT_REG0_PULSE_SIDX),
+                  MS(reg1, RADAR_REPORT_REG1_PULSE_SRCH_FFT_VALID),
+                  MS(reg1, RADAR_REPORT_REG1_PULSE_AGC_MB_GAIN),
+                  MS(reg1, RADAR_REPORT_REG1_PULSE_SUBCHAN_MASK));
+       ath10k_dbg(ATH10K_DBG_REGULATORY,
+                  "wmi phyerr radar report pulse_tsf_offset 0x%X pulse_dur: %d\n",
+                  MS(reg1, RADAR_REPORT_REG1_PULSE_TSF_OFFSET),
+                  MS(reg1, RADAR_REPORT_REG1_PULSE_DUR));
+
+       if (!ar->dfs_detector)
+               return;
+
+       /* report event to DFS pattern detector */
+       tsf32l = __le32_to_cpu(event->hdr.tsf_timestamp);
+       tsf64 = tsf & (~0xFFFFFFFFULL);
+       tsf64 |= tsf32l;
+
+       width = MS(reg1, RADAR_REPORT_REG1_PULSE_DUR);
+       rssi = event->hdr.rssi_combined;
+
+       /* hardware store this as 8 bit signed value,
+        * set to zero if negative number
+        */
+       if (rssi & 0x80)
+               rssi = 0;
+
+       pe.ts = tsf64;
+       pe.freq = ar->hw->conf.chandef.chan->center_freq;
+       pe.width = width;
+       pe.rssi = rssi;
+
+       ath10k_dbg(ATH10K_DBG_REGULATORY,
+                  "dfs add pulse freq: %d, width: %d, rssi %d, tsf: %llX\n",
+                  pe.freq, pe.width, pe.rssi, pe.ts);
+
+       ATH10K_DFS_STAT_INC(ar, pulses_detected);
+
+       if (!ar->dfs_detector->add_pulse(ar->dfs_detector, &pe)) {
+               ath10k_dbg(ATH10K_DBG_REGULATORY,
+                          "dfs no pulse pattern detected, yet\n");
+               return;
+       }
+
+       ath10k_dbg(ATH10K_DBG_REGULATORY, "dfs radar detected\n");
+       ATH10K_DFS_STAT_INC(ar, radar_detected);
+
+       /* Control radar events reporting in debugfs file
+          dfs_block_radar_events */
+       if (ar->dfs_block_radar_events) {
+               ath10k_info("DFS Radar detected, but ignored as requested\n");
+               return;
+       }
+
+       ieee80211_radar_detected(ar->hw);
+}
+
+static int ath10k_dfs_fft_report(struct ath10k *ar,
+                                struct wmi_single_phyerr_rx_event *event,
+                                struct phyerr_fft_report *fftr,
+                                u64 tsf)
+{
+       u32 reg0, reg1;
+       u8 rssi, peak_mag;
+
+       reg0 = __le32_to_cpu(fftr->reg0);
+       reg1 = __le32_to_cpu(fftr->reg1);
+       rssi = event->hdr.rssi_combined;
+
+       ath10k_dbg(ATH10K_DBG_REGULATORY,
+                  "wmi phyerr fft report total_gain_db %d base_pwr_db %d fft_chn_idx %d peak_sidx %d\n",
+                  MS(reg0, SEARCH_FFT_REPORT_REG0_TOTAL_GAIN_DB),
+                  MS(reg0, SEARCH_FFT_REPORT_REG0_BASE_PWR_DB),
+                  MS(reg0, SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX),
+                  MS(reg0, SEARCH_FFT_REPORT_REG0_PEAK_SIDX));
+       ath10k_dbg(ATH10K_DBG_REGULATORY,
+                  "wmi phyerr fft report rel_pwr_db %d avgpwr_db %d peak_mag %d num_store_bin %d\n",
+                  MS(reg1, SEARCH_FFT_REPORT_REG1_RELPWR_DB),
+                  MS(reg1, SEARCH_FFT_REPORT_REG1_AVGPWR_DB),
+                  MS(reg1, SEARCH_FFT_REPORT_REG1_PEAK_MAG),
+                  MS(reg1, SEARCH_FFT_REPORT_REG1_NUM_STR_BINS_IB));
+
+       peak_mag = MS(reg1, SEARCH_FFT_REPORT_REG1_PEAK_MAG);
+
+       /* false event detection */
+       if (rssi == DFS_RSSI_POSSIBLY_FALSE &&
+           peak_mag < 2 * DFS_PEAK_MAG_THOLD_POSSIBLY_FALSE) {
+               ath10k_dbg(ATH10K_DBG_REGULATORY, "dfs false pulse detected\n");
+               ATH10K_DFS_STAT_INC(ar, pulses_discarded);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void ath10k_wmi_event_dfs(struct ath10k *ar,
+                                struct wmi_single_phyerr_rx_event *event,
+                                u64 tsf)
+{
+       int buf_len, tlv_len, res, i = 0;
+       struct phyerr_tlv *tlv;
+       struct phyerr_radar_report *rr;
+       struct phyerr_fft_report *fftr;
+       u8 *tlv_buf;
+
+       buf_len = __le32_to_cpu(event->hdr.buf_len);
+       ath10k_dbg(ATH10K_DBG_REGULATORY,
+                  "wmi event dfs err_code %d rssi %d tsfl 0x%X tsf64 0x%llX len %d\n",
+                  event->hdr.phy_err_code, event->hdr.rssi_combined,
+                  __le32_to_cpu(event->hdr.tsf_timestamp), tsf, buf_len);
+
+       /* Skip event if DFS disabled */
+       if (!config_enabled(CONFIG_ATH10K_DFS_CERTIFIED))
+               return;
+
+       ATH10K_DFS_STAT_INC(ar, pulses_total);
+
+       while (i < buf_len) {
+               if (i + sizeof(*tlv) > buf_len) {
+                       ath10k_warn("too short buf for tlv header (%d)\n", i);
+                       return;
+               }
+
+               tlv = (struct phyerr_tlv *)&event->bufp[i];
+               tlv_len = __le16_to_cpu(tlv->len);
+               tlv_buf = &event->bufp[i + sizeof(*tlv)];
+               ath10k_dbg(ATH10K_DBG_REGULATORY,
+                          "wmi event dfs tlv_len %d tlv_tag 0x%02X tlv_sig 0x%02X\n",
+                          tlv_len, tlv->tag, tlv->sig);
+
+               switch (tlv->tag) {
+               case PHYERR_TLV_TAG_RADAR_PULSE_SUMMARY:
+                       if (i + sizeof(*tlv) + sizeof(*rr) > buf_len) {
+                               ath10k_warn("too short radar pulse summary (%d)\n",
+                                           i);
+                               return;
+                       }
+
+                       rr = (struct phyerr_radar_report *)tlv_buf;
+                       ath10k_dfs_radar_report(ar, event, rr, tsf);
+                       break;
+               case PHYERR_TLV_TAG_SEARCH_FFT_REPORT:
+                       if (i + sizeof(*tlv) + sizeof(*fftr) > buf_len) {
+                               ath10k_warn("too short fft report (%d)\n", i);
+                               return;
+                       }
+
+                       fftr = (struct phyerr_fft_report *)tlv_buf;
+                       res = ath10k_dfs_fft_report(ar, event, fftr, tsf);
+                       if (res)
+                               return;
+                       break;
+               }
+
+               i += sizeof(*tlv) + tlv_len;
+       }
+}
+
+static void ath10k_wmi_event_spectral_scan(struct ath10k *ar,
+                               struct wmi_single_phyerr_rx_event *event,
+                               u64 tsf)
+{
+       ath10k_dbg(ATH10K_DBG_WMI, "wmi event spectral scan\n");
+}
+
 static void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb)
 {
-       ath10k_dbg(ATH10K_DBG_WMI, "WMI_PHYERR_EVENTID\n");
+       struct wmi_comb_phyerr_rx_event *comb_event;
+       struct wmi_single_phyerr_rx_event *event;
+       u32 count, i, buf_len, phy_err_code;
+       u64 tsf;
+       int left_len = skb->len;
+
+       ATH10K_DFS_STAT_INC(ar, phy_errors);
+
+       /* Check if combined event available */
+       if (left_len < sizeof(*comb_event)) {
+               ath10k_warn("wmi phyerr combined event wrong len\n");
+               return;
+       }
+
+       left_len -= sizeof(*comb_event);
+
+       /* Check number of included events */
+       comb_event = (struct wmi_comb_phyerr_rx_event *)skb->data;
+       count = __le32_to_cpu(comb_event->hdr.num_phyerr_events);
+
+       tsf = __le32_to_cpu(comb_event->hdr.tsf_u32);
+       tsf <<= 32;
+       tsf |= __le32_to_cpu(comb_event->hdr.tsf_l32);
+
+       ath10k_dbg(ATH10K_DBG_WMI,
+                  "wmi event phyerr count %d tsf64 0x%llX\n",
+                  count, tsf);
+
+       event = (struct wmi_single_phyerr_rx_event *)comb_event->bufp;
+       for (i = 0; i < count; i++) {
+               /* Check if we can read event header */
+               if (left_len < sizeof(*event)) {
+                       ath10k_warn("single event (%d) wrong head len\n", i);
+                       return;
+               }
+
+               left_len -= sizeof(*event);
+
+               buf_len = __le32_to_cpu(event->hdr.buf_len);
+               phy_err_code = event->hdr.phy_err_code;
+
+               if (left_len < buf_len) {
+                       ath10k_warn("single event (%d) wrong buf len\n", i);
+                       return;
+               }
+
+               left_len -= buf_len;
+
+               switch (phy_err_code) {
+               case PHY_ERROR_RADAR:
+                       ath10k_wmi_event_dfs(ar, event, tsf);
+                       break;
+               case PHY_ERROR_SPECTRAL_SCAN:
+                       ath10k_wmi_event_spectral_scan(ar, event, tsf);
+                       break;
+               case PHY_ERROR_FALSE_RADAR_EXT:
+                       ath10k_wmi_event_dfs(ar, event, tsf);
+                       ath10k_wmi_event_spectral_scan(ar, event, tsf);
+                       break;
+               default:
+                       break;
+               }
+
+               event += sizeof(*event) + buf_len;
+       }
 }
 
 static void ath10k_wmi_event_roam(struct ath10k *ar, struct sk_buff *skb)
@@ -2062,6 +2315,7 @@ int ath10k_wmi_pdev_set_channel(struct ath10k *ar,
 {
        struct wmi_set_channel_cmd *cmd;
        struct sk_buff *skb;
+       u32 ch_flags = 0;
 
        if (arg->passive)
                return -EINVAL;
@@ -2070,10 +2324,14 @@ int ath10k_wmi_pdev_set_channel(struct ath10k *ar,
        if (!skb)
                return -ENOMEM;
 
+       if (arg->chan_radar)
+               ch_flags |= WMI_CHAN_FLAG_DFS;
+
        cmd = (struct wmi_set_channel_cmd *)skb->data;
        cmd->chan.mhz               = __cpu_to_le32(arg->freq);
        cmd->chan.band_center_freq1 = __cpu_to_le32(arg->freq);
        cmd->chan.mode              = arg->mode;
+       cmd->chan.flags            |= __cpu_to_le32(ch_flags);
        cmd->chan.min_power         = arg->min_power;
        cmd->chan.max_power         = arg->max_power;
        cmd->chan.reg_power         = arg->max_reg_power;
@@ -2211,7 +2469,7 @@ static int ath10k_wmi_main_cmd_init(struct ath10k *ar)
        }
 
        ath10k_dbg(ATH10K_DBG_WMI, "wmi sending %d memory chunks info.\n",
-                  __cpu_to_le32(ar->wmi.num_mem_chunks));
+                  ar->wmi.num_mem_chunks);
 
        cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks);
 
@@ -2224,10 +2482,10 @@ static int ath10k_wmi_main_cmd_init(struct ath10k *ar)
                        __cpu_to_le32(ar->wmi.mem_chunks[i].req_id);
 
                ath10k_dbg(ATH10K_DBG_WMI,
-                          "wmi chunk %d len %d requested, addr 0x%x\n",
+                          "wmi chunk %d len %d requested, addr 0x%llx\n",
                           i,
-                          cmd->host_mem_chunks[i].size,
-                          cmd->host_mem_chunks[i].ptr);
+                          ar->wmi.mem_chunks[i].len,
+                          (unsigned long long)ar->wmi.mem_chunks[i].paddr);
        }
 out:
        memcpy(&cmd->resource_config, &config, sizeof(config));
@@ -2302,7 +2560,7 @@ static int ath10k_wmi_10x_cmd_init(struct ath10k *ar)
        }
 
        ath10k_dbg(ATH10K_DBG_WMI, "wmi sending %d memory chunks info.\n",
-                  __cpu_to_le32(ar->wmi.num_mem_chunks));
+                  ar->wmi.num_mem_chunks);
 
        cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks);
 
@@ -2315,10 +2573,10 @@ static int ath10k_wmi_10x_cmd_init(struct ath10k *ar)
                        __cpu_to_le32(ar->wmi.mem_chunks[i].req_id);
 
                ath10k_dbg(ATH10K_DBG_WMI,
-                          "wmi chunk %d len %d requested, addr 0x%x\n",
+                          "wmi chunk %d len %d requested, addr 0x%llx\n",
                           i,
-                          cmd->host_mem_chunks[i].size,
-                          cmd->host_mem_chunks[i].ptr);
+                          ar->wmi.mem_chunks[i].len,
+                          (unsigned long long)ar->wmi.mem_chunks[i].paddr);
        }
 out:
        memcpy(&cmd->resource_config, &config, sizeof(config));
@@ -2622,6 +2880,7 @@ static int ath10k_wmi_vdev_start_restart(struct ath10k *ar,
        struct sk_buff *skb;
        const char *cmdname;
        u32 flags = 0;
+       u32 ch_flags = 0;
 
        if (cmd_id != ar->wmi.cmd->vdev_start_request_cmdid &&
            cmd_id != ar->wmi.cmd->vdev_restart_request_cmdid)
@@ -2648,6 +2907,8 @@ static int ath10k_wmi_vdev_start_restart(struct ath10k *ar,
                flags |= WMI_VDEV_START_HIDDEN_SSID;
        if (arg->pmf_enabled)
                flags |= WMI_VDEV_START_PMF_ENABLED;
+       if (arg->channel.chan_radar)
+               ch_flags |= WMI_CHAN_FLAG_DFS;
 
        cmd = (struct wmi_vdev_start_request_cmd *)skb->data;
        cmd->vdev_id         = __cpu_to_le32(arg->vdev_id);
@@ -2669,6 +2930,7 @@ static int ath10k_wmi_vdev_start_restart(struct ath10k *ar,
                __cpu_to_le32(arg->channel.band_center_freq1);
 
        cmd->chan.mode = arg->channel.mode;
+       cmd->chan.flags |= __cpu_to_le32(ch_flags);
        cmd->chan.min_power = arg->channel.min_power;
        cmd->chan.max_power = arg->channel.max_power;
        cmd->chan.reg_power = arg->channel.max_reg_power;
@@ -2676,9 +2938,10 @@ static int ath10k_wmi_vdev_start_restart(struct ath10k *ar,
        cmd->chan.antenna_max = arg->channel.max_antenna_gain;
 
        ath10k_dbg(ATH10K_DBG_WMI,
-                  "wmi vdev %s id 0x%x freq %d, mode %d, ch_flags: 0x%0X,"
-                  "max_power: %d\n", cmdname, arg->vdev_id, arg->channel.freq,
-                  arg->channel.mode, flags, arg->channel.max_power);
+                  "wmi vdev %s id 0x%x flags: 0x%0X, freq %d, mode %d, "
+                  "ch_flags: 0x%0X, max_power: %d\n", cmdname, arg->vdev_id,
+                  flags, arg->channel.freq, arg->channel.mode,
+                  cmd->chan.flags, arg->channel.max_power);
 
        return ath10k_wmi_cmd_send(ar, skb, cmd_id);
 }
@@ -3012,6 +3275,8 @@ int ath10k_wmi_scan_chan_list(struct ath10k *ar,
                        flags |= WMI_CHAN_FLAG_ALLOW_VHT;
                if (ch->ht40plus)
                        flags |= WMI_CHAN_FLAG_HT40_PLUS;
+               if (ch->chan_radar)
+                       flags |= WMI_CHAN_FLAG_DFS;
 
                ci->mhz               = __cpu_to_le32(ch->freq);
                ci->band_center_freq1 = __cpu_to_le32(ch->freq);
@@ -3094,6 +3359,7 @@ int ath10k_wmi_beacon_send_nowait(struct ath10k *ar,
 {
        struct wmi_bcn_tx_cmd *cmd;
        struct sk_buff *skb;
+       int ret;
 
        skb = ath10k_wmi_alloc_skb(sizeof(*cmd) + arg->bcn_len);
        if (!skb)
@@ -3106,7 +3372,11 @@ int ath10k_wmi_beacon_send_nowait(struct ath10k *ar,
        cmd->hdr.bcn_len  = __cpu_to_le32(arg->bcn_len);
        memcpy(cmd->bcn, arg->bcn, arg->bcn_len);
 
-       return ath10k_wmi_cmd_send_nowait(ar, skb, ar->wmi.cmd->bcn_tx_cmdid);
+       ret = ath10k_wmi_cmd_send_nowait(ar, skb, ar->wmi.cmd->bcn_tx_cmdid);
+       if (ret)
+               dev_kfree_skb(skb);
+
+       return ret;
 }
 
 static void ath10k_wmi_pdev_set_wmm_param(struct wmi_wmm_params *params,
index 78c991aec7f93d6419cc62d1b09ea2f63033b627..0087d699b85bcd8987182987a2a47896edfc7a1d 100644 (file)
@@ -893,6 +893,7 @@ struct wmi_channel {
        union {
                __le32 reginfo0;
                struct {
+                       /* note: power unit is 0.5 dBm */
                        u8 min_power;
                        u8 max_power;
                        u8 reg_power;
@@ -915,7 +916,8 @@ struct wmi_channel_arg {
        bool allow_ht;
        bool allow_vht;
        bool ht40plus;
-       /* note: power unit is 1/4th of dBm */
+       bool chan_radar;
+       /* note: power unit is 0.5 dBm */
        u32 min_power;
        u32 max_power;
        u32 max_reg_power;
@@ -1977,6 +1979,10 @@ struct wmi_mgmt_rx_event_v2 {
 #define WMI_RX_STATUS_ERR_MIC                  0x10
 #define WMI_RX_STATUS_ERR_KEY_CACHE_MISS       0x20
 
+#define PHY_ERROR_SPECTRAL_SCAN                0x26
+#define PHY_ERROR_FALSE_RADAR_EXT              0x24
+#define PHY_ERROR_RADAR                                0x05
+
 struct wmi_single_phyerr_rx_hdr {
        /* TSF timestamp */
        __le32 tsf_timestamp;
@@ -2068,6 +2074,87 @@ struct wmi_comb_phyerr_rx_event {
        u8 bufp[0];
 } __packed;
 
+#define PHYERR_TLV_SIG                         0xBB
+#define PHYERR_TLV_TAG_SEARCH_FFT_REPORT       0xFB
+#define PHYERR_TLV_TAG_RADAR_PULSE_SUMMARY     0xF8
+
+struct phyerr_radar_report {
+       __le32 reg0; /* RADAR_REPORT_REG0_* */
+       __le32 reg1; /* REDAR_REPORT_REG1_* */
+} __packed;
+
+#define RADAR_REPORT_REG0_PULSE_IS_CHIRP_MASK          0x80000000
+#define RADAR_REPORT_REG0_PULSE_IS_CHIRP_LSB           31
+
+#define RADAR_REPORT_REG0_PULSE_IS_MAX_WIDTH_MASK      0x40000000
+#define RADAR_REPORT_REG0_PULSE_IS_MAX_WIDTH_LSB       30
+
+#define RADAR_REPORT_REG0_AGC_TOTAL_GAIN_MASK          0x3FF00000
+#define RADAR_REPORT_REG0_AGC_TOTAL_GAIN_LSB           20
+
+#define RADAR_REPORT_REG0_PULSE_DELTA_DIFF_MASK                0x000F0000
+#define RADAR_REPORT_REG0_PULSE_DELTA_DIFF_LSB         16
+
+#define RADAR_REPORT_REG0_PULSE_DELTA_PEAK_MASK                0x0000FC00
+#define RADAR_REPORT_REG0_PULSE_DELTA_PEAK_LSB         10
+
+#define RADAR_REPORT_REG0_PULSE_SIDX_MASK              0x000003FF
+#define RADAR_REPORT_REG0_PULSE_SIDX_LSB               0
+
+#define RADAR_REPORT_REG1_PULSE_SRCH_FFT_VALID_MASK    0x80000000
+#define RADAR_REPORT_REG1_PULSE_SRCH_FFT_VALID_LSB     31
+
+#define RADAR_REPORT_REG1_PULSE_AGC_MB_GAIN_MASK       0x7F000000
+#define RADAR_REPORT_REG1_PULSE_AGC_MB_GAIN_LSB                24
+
+#define RADAR_REPORT_REG1_PULSE_SUBCHAN_MASK_MASK      0x00FF0000
+#define RADAR_REPORT_REG1_PULSE_SUBCHAN_MASK_LSB       16
+
+#define RADAR_REPORT_REG1_PULSE_TSF_OFFSET_MASK                0x0000FF00
+#define RADAR_REPORT_REG1_PULSE_TSF_OFFSET_LSB         8
+
+#define RADAR_REPORT_REG1_PULSE_DUR_MASK               0x000000FF
+#define RADAR_REPORT_REG1_PULSE_DUR_LSB                        0
+
+struct phyerr_fft_report {
+       __le32 reg0; /* SEARCH_FFT_REPORT_REG0_ * */
+       __le32 reg1; /* SEARCH_FFT_REPORT_REG1_ * */
+} __packed;
+
+#define SEARCH_FFT_REPORT_REG0_TOTAL_GAIN_DB_MASK      0xFF800000
+#define SEARCH_FFT_REPORT_REG0_TOTAL_GAIN_DB_LSB       23
+
+#define SEARCH_FFT_REPORT_REG0_BASE_PWR_DB_MASK                0x007FC000
+#define SEARCH_FFT_REPORT_REG0_BASE_PWR_DB_LSB         14
+
+#define SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX_MASK                0x00003000
+#define SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX_LSB         12
+
+#define SEARCH_FFT_REPORT_REG0_PEAK_SIDX_MASK          0x00000FFF
+#define SEARCH_FFT_REPORT_REG0_PEAK_SIDX_LSB           0
+
+#define SEARCH_FFT_REPORT_REG1_RELPWR_DB_MASK          0xFC000000
+#define SEARCH_FFT_REPORT_REG1_RELPWR_DB_LSB           26
+
+#define SEARCH_FFT_REPORT_REG1_AVGPWR_DB_MASK          0x03FC0000
+#define SEARCH_FFT_REPORT_REG1_AVGPWR_DB_LSB           18
+
+#define SEARCH_FFT_REPORT_REG1_PEAK_MAG_MASK           0x0003FF00
+#define SEARCH_FFT_REPORT_REG1_PEAK_MAG_LSB            8
+
+#define SEARCH_FFT_REPORT_REG1_NUM_STR_BINS_IB_MASK    0x000000FF
+#define SEARCH_FFT_REPORT_REG1_NUM_STR_BINS_IB_LSB     0
+
+
+struct phyerr_tlv {
+       __le16 len;
+       u8 tag;
+       u8 sig;
+} __packed;
+
+#define DFS_RSSI_POSSIBLY_FALSE                        50
+#define DFS_PEAK_MAG_THOLD_POSSIBLY_FALSE      40
+
 struct wmi_mgmt_tx_hdr {
        __le32 vdev_id;
        struct wmi_mac_addr peer_macaddr;
@@ -2233,7 +2320,12 @@ enum wmi_pdev_param {
         * 0: no protection 1:use CTS-to-self 2: use RTS/CTS
         */
        WMI_PDEV_PARAM_PROTECTION_MODE,
-       /* Dynamic bandwidth 0: disable 1: enable */
+       /*
+        * Dynamic bandwidth - 0: disable, 1: enable
+        *
+        * When enabled HW rate control tries different bandwidths when
+        * retransmitting frames.
+        */
        WMI_PDEV_PARAM_DYNAMIC_BW,
        /* Non aggregrate/ 11g sw retry threshold.0-disable */
        WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH,
index ba200b24be64cd307483fad13fef4a9283a93784..e6c52f7c26e73a1495cff43bed603059e517b9ab 100644 (file)
@@ -616,7 +616,16 @@ ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
                 * SISRs will also clear PISR so no need to worry here.
                 */
 
-               pisr_clear = pisr & ~AR5K_ISR_BITS_FROM_SISRS;
+               /* XXX: There seems to be  an issue on some cards
+                *      with tx interrupt flags not being updated
+                *      on PISR despite that all Tx interrupt bits
+                *      are cleared on SISRs. Since we handle all
+                *      Tx queues all together it shouldn't be an
+                *      issue if we clear Tx interrupt flags also
+                *      on PISR to avoid that.
+                */
+               pisr_clear = (pisr & ~AR5K_ISR_BITS_FROM_SISRS) |
+                                       (pisr & AR5K_INT_TX_ALL);
 
                /*
                 * Write to clear them...
index 2437ad26949d1c43617204fc7c887bf196a1e2f5..fd4c89df67e1658ae404686a911fc62607cee1cd 100644 (file)
@@ -1109,7 +1109,9 @@ void ath6kl_cfg80211_ch_switch_notify(struct ath6kl_vif *vif, int freq,
                                (mode == WMI_11G_HT20) ?
                                        NL80211_CHAN_HT20 : NL80211_CHAN_NO_HT);
 
+       mutex_lock(&vif->wdev.mtx);
        cfg80211_ch_switch_notify(vif->ndev, &chandef);
+       mutex_unlock(&vif->wdev.mtx);
 }
 
 static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
@@ -3169,12 +3171,15 @@ static bool ath6kl_is_p2p_go_ssid(const u8 *buf, size_t len)
 }
 
 static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
-                         struct ieee80211_channel *chan, bool offchan,
-                         unsigned int wait, const u8 *buf, size_t len,
-                         bool no_cck, bool dont_wait_for_ack, u64 *cookie)
+                         struct cfg80211_mgmt_tx_params *params, u64 *cookie)
 {
        struct ath6kl_vif *vif = ath6kl_vif_from_wdev(wdev);
        struct ath6kl *ar = ath6kl_priv(vif->ndev);
+       struct ieee80211_channel *chan = params->chan;
+       const u8 *buf = params->buf;
+       size_t len = params->len;
+       unsigned int wait = params->wait;
+       bool no_cck = params->no_cck;
        u32 id, freq;
        const struct ieee80211_mgmt *mgmt;
        bool more_data, queued;
index 32f139e2e897e255b4c378c33c6d99df8abd51e0..30d273c61bffb8f4e040e5f2eaddd37154f439f7 100644 (file)
@@ -86,7 +86,7 @@ config ATH9K_DFS_CERTIFIED
 
 config ATH9K_TX99
        bool "Atheros ath9k TX99 testing support"
-       depends on CFG80211_CERTIFICATION_ONUS
+       depends on ATH9K_DEBUGFS && CFG80211_CERTIFICATION_ONUS
        default n
        ---help---
          Say N. This should only be enabled on systems undergoing
@@ -104,6 +104,14 @@ config ATH9K_TX99
          be evaluated to meet the RF exposure limits set forth in the
          governmental SAR regulations.
 
+config ATH9K_WOW
+       bool "Wake on Wireless LAN support (EXPERIMENTAL)"
+       depends on ATH9K && PM
+       default n
+       ---help---
+         This option enables Wake on Wireless LAN support for certain cards.
+         Currently, AR9462 is supported.
+
 config ATH9K_LEGACY_RATE_CONTROL
        bool "Atheros ath9k rate control"
        depends on ATH9K
index 6205ef5a9321e8072c283d24e8e7814b2a8392df..337c459eda284770c61dbb654b1762aac3965e9b 100644 (file)
@@ -13,9 +13,9 @@ ath9k-$(CONFIG_ATH9K_PCI) += pci.o
 ath9k-$(CONFIG_ATH9K_AHB) += ahb.o
 ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o
 ath9k-$(CONFIG_ATH9K_DFS_DEBUGFS) += dfs_debug.o
-ath9k-$(CONFIG_ATH9K_DFS_CERTIFIED) += \
-               dfs.o
-ath9k-$(CONFIG_PM_SLEEP) += wow.o
+ath9k-$(CONFIG_ATH9K_DFS_CERTIFIED) += dfs.o
+ath9k-$(CONFIG_ATH9K_TX99) += tx99.o
+ath9k-$(CONFIG_ATH9K_WOW) += wow.o
 
 obj-$(CONFIG_ATH9K) += ath9k.o
 
@@ -41,6 +41,8 @@ ath9k_hw-y:=  \
                ar9003_eeprom.o \
                ar9003_paprd.o
 
+ath9k_hw-$(CONFIG_ATH9K_WOW) += ar9003_wow.o
+
 ath9k_hw-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += btcoex.o \
                                           ar9003_mci.o
 obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o
index 7546b9a7dcbfa2252bf896e70fe48ad38b3b4646..0a6163e9248c0fdefa0f0e78a695201fb8a7d0f2 100644 (file)
@@ -303,7 +303,7 @@ static const u32 ar9300_2p2_mac_postamble[][5] = {
        {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
        {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
        {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
-       {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+       {0x00008120, 0x18f04800, 0x18f04800, 0x18f04810, 0x18f04810},
        {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
        {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
 };
@@ -352,7 +352,7 @@ static const u32 ar9300_2p2_baseband_postamble[][5] = {
        {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
        {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
        {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
-       {0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982},
+       {0x0000a2d0, 0x00041983, 0x00041983, 0x00041981, 0x00041982},
        {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
        {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
        {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
@@ -378,9 +378,9 @@ static const u32 ar9300_2p2_baseband_core[][2] = {
        {0x00009814, 0x9280c00a},
        {0x00009818, 0x00000000},
        {0x0000981c, 0x00020028},
-       {0x00009834, 0x6400a290},
+       {0x00009834, 0x6400a190},
        {0x00009838, 0x0108ecff},
-       {0x0000983c, 0x0d000600},
+       {0x0000983c, 0x14000600},
        {0x00009880, 0x201fff00},
        {0x00009884, 0x00001042},
        {0x000098a4, 0x00200400},
@@ -401,7 +401,7 @@ static const u32 ar9300_2p2_baseband_core[][2] = {
        {0x00009d04, 0x40206c10},
        {0x00009d08, 0x009c4060},
        {0x00009d0c, 0x9883800a},
-       {0x00009d10, 0x01834061},
+       {0x00009d10, 0x01884061},
        {0x00009d14, 0x00c0040b},
        {0x00009d18, 0x00000000},
        {0x00009e08, 0x0038230c},
@@ -459,7 +459,7 @@ static const u32 ar9300_2p2_baseband_core[][2] = {
        {0x0000a3e8, 0x20202020},
        {0x0000a3ec, 0x20202020},
        {0x0000a3f0, 0x00000000},
-       {0x0000a3f4, 0x00000246},
+       {0x0000a3f4, 0x00000000},
        {0x0000a3f8, 0x0c9bd380},
        {0x0000a3fc, 0x000f0f01},
        {0x0000a400, 0x8fa91f01},
@@ -534,107 +534,107 @@ static const u32 ar9300_2p2_baseband_core[][2] = {
 
 static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-       {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
-       {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
-       {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000a2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
+       {0x0000a2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
+       {0x0000a2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
        {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
-       {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
-       {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
-       {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
-       {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004},
-       {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200},
-       {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202},
-       {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400},
-       {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402},
-       {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404},
-       {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603},
-       {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02},
-       {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04},
-       {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20},
-       {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20},
-       {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22},
-       {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24},
-       {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640},
-       {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660},
-       {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861},
-       {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81},
-       {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83},
-       {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84},
-       {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3},
-       {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5},
-       {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9},
-       {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb},
-       {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
-       {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
-       {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
-       {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
-       {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
-       {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
-       {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
-       {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000},
-       {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002},
-       {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004},
-       {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200},
-       {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202},
-       {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400},
-       {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402},
-       {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404},
-       {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603},
-       {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02},
-       {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04},
-       {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20},
-       {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20},
-       {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22},
-       {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24},
-       {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640},
-       {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660},
-       {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861},
-       {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81},
-       {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83},
-       {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84},
-       {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3},
-       {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5},
-       {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9},
-       {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb},
-       {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
-       {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
-       {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
-       {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
-       {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
-       {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
-       {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+       {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
+       {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
+       {0x0000a510, 0x15000028, 0x15000028, 0x0f000202, 0x0f000202},
+       {0x0000a514, 0x1b00002b, 0x1b00002b, 0x12000400, 0x12000400},
+       {0x0000a518, 0x1f020028, 0x1f020028, 0x16000402, 0x16000402},
+       {0x0000a51c, 0x2502002b, 0x2502002b, 0x19000404, 0x19000404},
+       {0x0000a520, 0x2a04002a, 0x2a04002a, 0x1c000603, 0x1c000603},
+       {0x0000a524, 0x2e06002a, 0x2e06002a, 0x21000a02, 0x21000a02},
+       {0x0000a528, 0x3302202d, 0x3302202d, 0x25000a04, 0x25000a04},
+       {0x0000a52c, 0x3804202c, 0x3804202c, 0x28000a20, 0x28000a20},
+       {0x0000a530, 0x3c06202c, 0x3c06202c, 0x2c000e20, 0x2c000e20},
+       {0x0000a534, 0x4108202d, 0x4108202d, 0x30000e22, 0x30000e22},
+       {0x0000a538, 0x4506402d, 0x4506402d, 0x34000e24, 0x34000e24},
+       {0x0000a53c, 0x4906222d, 0x4906222d, 0x38001640, 0x38001640},
+       {0x0000a540, 0x4d062231, 0x4d062231, 0x3c001660, 0x3c001660},
+       {0x0000a544, 0x50082231, 0x50082231, 0x3f001861, 0x3f001861},
+       {0x0000a548, 0x5608422e, 0x5608422e, 0x43001a81, 0x43001a81},
+       {0x0000a54c, 0x5e08442e, 0x5e08442e, 0x47001a83, 0x47001a83},
+       {0x0000a550, 0x620a4431, 0x620a4431, 0x4a001c84, 0x4a001c84},
+       {0x0000a554, 0x640a4432, 0x640a4432, 0x4e001ce3, 0x4e001ce3},
+       {0x0000a558, 0x680a4434, 0x680a4434, 0x52001ce5, 0x52001ce5},
+       {0x0000a55c, 0x6c0a6434, 0x6c0a6434, 0x56001ce9, 0x56001ce9},
+       {0x0000a560, 0x6f0a6633, 0x6f0a6633, 0x5a001ceb, 0x5a001ceb},
+       {0x0000a564, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+       {0x0000a568, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+       {0x0000a56c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+       {0x0000a570, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+       {0x0000a574, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+       {0x0000a578, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+       {0x0000a57c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+       {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
+       {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
+       {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
+       {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200},
+       {0x0000a590, 0x15800028, 0x15800028, 0x0f800202, 0x0f800202},
+       {0x0000a594, 0x1b80002b, 0x1b80002b, 0x12800400, 0x12800400},
+       {0x0000a598, 0x1f820028, 0x1f820028, 0x16800402, 0x16800402},
+       {0x0000a59c, 0x2582002b, 0x2582002b, 0x19800404, 0x19800404},
+       {0x0000a5a0, 0x2a84002a, 0x2a84002a, 0x1c800603, 0x1c800603},
+       {0x0000a5a4, 0x2e86002a, 0x2e86002a, 0x21800a02, 0x21800a02},
+       {0x0000a5a8, 0x3382202d, 0x3382202d, 0x25800a04, 0x25800a04},
+       {0x0000a5ac, 0x3884202c, 0x3884202c, 0x28800a20, 0x28800a20},
+       {0x0000a5b0, 0x3c86202c, 0x3c86202c, 0x2c800e20, 0x2c800e20},
+       {0x0000a5b4, 0x4188202d, 0x4188202d, 0x30800e22, 0x30800e22},
+       {0x0000a5b8, 0x4586402d, 0x4586402d, 0x34800e24, 0x34800e24},
+       {0x0000a5bc, 0x4986222d, 0x4986222d, 0x38801640, 0x38801640},
+       {0x0000a5c0, 0x4d862231, 0x4d862231, 0x3c801660, 0x3c801660},
+       {0x0000a5c4, 0x50882231, 0x50882231, 0x3f801861, 0x3f801861},
+       {0x0000a5c8, 0x5688422e, 0x5688422e, 0x43801a81, 0x43801a81},
+       {0x0000a5cc, 0x5e88442e, 0x5e88442e, 0x47801a83, 0x47801a83},
+       {0x0000a5d0, 0x628a4431, 0x628a4431, 0x4a801c84, 0x4a801c84},
+       {0x0000a5d4, 0x648a4432, 0x648a4432, 0x4e801ce3, 0x4e801ce3},
+       {0x0000a5d8, 0x688a4434, 0x688a4434, 0x52801ce5, 0x52801ce5},
+       {0x0000a5dc, 0x6c8a6434, 0x6c8a6434, 0x56801ce9, 0x56801ce9},
+       {0x0000a5e0, 0x6f8a6633, 0x6f8a6633, 0x5a801ceb, 0x5a801ceb},
+       {0x0000a5e4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+       {0x0000a5e8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+       {0x0000a5ec, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f0, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+       {0x0000a5fc, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
        {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
        {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000},
-       {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000},
-       {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501},
-       {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501},
-       {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03},
-       {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04},
-       {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04},
-       {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
-       {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
-       {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
-       {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
-       {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
-       {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
-       {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
-       {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000a608, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
+       {0x0000a610, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
+       {0x0000a614, 0x01804601, 0x01804601, 0x01404000, 0x01404000},
+       {0x0000a618, 0x01804601, 0x01804601, 0x01404501, 0x01404501},
+       {0x0000a61c, 0x01804601, 0x01804601, 0x02008501, 0x02008501},
+       {0x0000a620, 0x03408d02, 0x03408d02, 0x0280ca03, 0x0280ca03},
+       {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
+       {0x0000a628, 0x03410d04, 0x03410d04, 0x04014c04, 0x04014c04},
+       {0x0000a62c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
+       {0x0000a630, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
+       {0x0000a634, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
+       {0x0000a638, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
+       {0x0000a63c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
+       {0x0000b2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
+       {0x0000b2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
+       {0x0000b2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
        {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
-       {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
-       {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
-       {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000c2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
+       {0x0000c2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
+       {0x0000c2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
        {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
        {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
-       {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
+       {0x00016048, 0x61200001, 0x61200001, 0x66480001, 0x66480001},
        {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
        {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
-       {0x00016448, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
+       {0x00016448, 0x61200001, 0x61200001, 0x66480001, 0x66480001},
        {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
        {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
-       {0x00016848, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
+       {0x00016848, 0x61200001, 0x61200001, 0x66480001, 0x66480001},
        {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
 };
 
@@ -644,7 +644,7 @@ static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = {
        {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
        {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
        {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
-       {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
+       {0x0000a410, 0x000050d4, 0x000050d4, 0x000050d9, 0x000050d9},
        {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
        {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
        {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004},
@@ -1086,8 +1086,8 @@ static const u32 ar9300Common_rx_gain_table_2p2[][2] = {
        {0x0000b074, 0x00000000},
        {0x0000b078, 0x00000000},
        {0x0000b07c, 0x00000000},
-       {0x0000b080, 0x2a2d2f32},
-       {0x0000b084, 0x21232328},
+       {0x0000b080, 0x23232323},
+       {0x0000b084, 0x21232323},
        {0x0000b088, 0x19191c1e},
        {0x0000b08c, 0x12141417},
        {0x0000b090, 0x07070e0e},
@@ -1385,9 +1385,9 @@ static const u32 ar9300_2p2_mac_core[][2] = {
        {0x000081f8, 0x00000000},
        {0x000081fc, 0x00000000},
        {0x00008240, 0x00100000},
-       {0x00008244, 0x0010f424},
+       {0x00008244, 0x0010f400},
        {0x00008248, 0x00000800},
-       {0x0000824c, 0x0001e848},
+       {0x0000824c, 0x0001e800},
        {0x00008250, 0x00000000},
        {0x00008254, 0x00000000},
        {0x00008258, 0x00000000},
@@ -1726,16 +1726,30 @@ static const u32 ar9300PciePhy_pll_on_clkreq_disable_L1_2p2[][2] = {
 
 static const u32 ar9300PciePhy_clkreq_enable_L1_2p2[][2] = {
        /* Addr      allmodes  */
-       {0x00004040, 0x08253e5e},
+       {0x00004040, 0x0825365e},
        {0x00004040, 0x0008003b},
        {0x00004044, 0x00000000},
 };
 
 static const u32 ar9300PciePhy_clkreq_disable_L1_2p2[][2] = {
        /* Addr      allmodes  */
-       {0x00004040, 0x08213e5e},
+       {0x00004040, 0x0821365e},
        {0x00004040, 0x0008003b},
        {0x00004044, 0x00000000},
 };
 
+static const u32 ar9300_2p2_baseband_core_txfir_coeff_japan_2484[][2] = {
+       /* Addr      allmodes  */
+       {0x0000a398, 0x00000000},
+       {0x0000a39c, 0x6f7f0301},
+       {0x0000a3a0, 0xca9228ee},
+};
+
+static const u32 ar9300_2p2_baseband_postamble_dfs_channel[][3] = {
+       /* Addr      5G          2G        */
+       {0x00009824, 0x5ac668d0, 0x5ac668d0},
+       {0x00009e0c, 0x6d4000e2, 0x6d4000e2},
+       {0x00009e14, 0x37b9625e, 0x37b9625e},
+};
+
 #endif /* INITVALS_9003_2P2_H */
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_buffalo_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_buffalo_initvals.h
new file mode 100644 (file)
index 0000000..59cf738
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2013 Qualcomm Atheros Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef INITVALS_9003_BUFFALO_H
+#define INITVALS_9003_BUFFALO_H
+
+static const u32 ar9300Modes_high_power_tx_gain_table_buffalo[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+       {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+       {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9},
+       {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
+       {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002},
+       {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200},
+       {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202},
+       {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400},
+       {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402},
+       {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404},
+       {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603},
+       {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02},
+       {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04},
+       {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20},
+       {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20},
+       {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22},
+       {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24},
+       {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640},
+       {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660},
+       {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861},
+       {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81},
+       {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83},
+       {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84},
+       {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3},
+       {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5},
+       {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9},
+       {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb},
+       {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+       {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+       {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+       {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+       {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+       {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+       {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec},
+       {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000},
+       {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002},
+       {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004},
+       {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200},
+       {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202},
+       {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400},
+       {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402},
+       {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404},
+       {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603},
+       {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02},
+       {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04},
+       {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20},
+       {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20},
+       {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22},
+       {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24},
+       {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640},
+       {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660},
+       {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861},
+       {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81},
+       {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83},
+       {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84},
+       {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3},
+       {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5},
+       {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9},
+       {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb},
+       {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec},
+       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000},
+       {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501},
+       {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501},
+       {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03},
+       {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04},
+       {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04},
+       {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
+       {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+       {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+       {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+       {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+       {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+       {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
+       {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+       {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+       {0x00016448, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
+       {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+       {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+       {0x00016848, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
+       {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+};
+
+#endif /* INITVALS_9003_BUFFALO_H */
index 22934d3ca54413fa9558a928fdccbc4ab108131a..97e09d5f3a427eade9008c33959a8e7f29836951 100644 (file)
@@ -898,7 +898,7 @@ static void ar9003_hw_tx_iq_cal_reload(struct ath_hw *ah)
 
 static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g)
 {
-       int offset[8], total = 0, test;
+       int offset[8] = {0}, total = 0, test;
        int agc_out, i;
 
        REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
@@ -923,12 +923,18 @@ static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g)
                      AR_PHY_65NM_RXRF_AGC_AGC_ON_OVR, 0x1);
        REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
                      AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR, 0x1);
-       if (is_2g)
-               REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
-                             AR_PHY_65NM_RXRF_AGC_AGC2G_DBDAC_OVR, 0x0);
-       else
+
+       if (AR_SREV_9330_11(ah)) {
                REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
-                             AR_PHY_65NM_RXRF_AGC_AGC5G_DBDAC_OVR, 0x0);
+                             AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR, 0x0);
+       } else {
+               if (is_2g)
+                       REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
+                                     AR_PHY_65NM_RXRF_AGC_AGC2G_DBDAC_OVR, 0x0);
+               else
+                       REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
+                                     AR_PHY_65NM_RXRF_AGC_AGC5G_DBDAC_OVR, 0x0);
+       }
 
        for (i = 6; i > 0; i--) {
                offset[i] = BIT(i - 1);
@@ -964,9 +970,9 @@ static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g)
                      AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR, 0);
 }
 
-static void ar9003_hw_do_manual_peak_cal(struct ath_hw *ah,
-                                        struct ath9k_channel *chan,
-                                        bool run_rtt_cal)
+static void ar9003_hw_do_pcoem_manual_peak_cal(struct ath_hw *ah,
+                                              struct ath9k_channel *chan,
+                                              bool run_rtt_cal)
 {
        struct ath9k_hw_cal_data *caldata = ah->caldata;
        int i;
@@ -1040,14 +1046,14 @@ static void ar9003_hw_cl_cal_post_proc(struct ath_hw *ah, bool is_reusable)
        }
 }
 
-static bool ar9003_hw_init_cal(struct ath_hw *ah,
-                              struct ath9k_channel *chan)
+static bool ar9003_hw_init_cal_pcoem(struct ath_hw *ah,
+                                    struct ath9k_channel *chan)
 {
        struct ath_common *common = ath9k_hw_common(ah);
        struct ath9k_hw_cal_data *caldata = ah->caldata;
        bool txiqcal_done = false;
        bool is_reusable = true, status = true;
-       bool run_rtt_cal = false, run_agc_cal, sep_iq_cal = false;
+       bool run_rtt_cal = false, run_agc_cal;
        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 |
@@ -1119,22 +1125,12 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
                        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 && !test_bit(TXIQCAL_DONE, &caldata->cal_flags)) {
-               run_agc_cal = true;
-               sep_iq_cal = true;
        }
 
 skip_tx_iqcal:
        if (ath9k_hw_mci_is_enabled(ah) && IS_CHAN_2GHZ(chan) && run_agc_cal)
                ar9003_mci_init_cal_req(ah, &is_reusable);
 
-       if (sep_iq_cal) {
-               txiqcal_done = ar9003_hw_tx_iq_cal_run(ah);
-               REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
-               udelay(5);
-               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 */
@@ -1155,7 +1151,7 @@ skip_tx_iqcal:
                                       AR_PHY_AGC_CONTROL_CAL,
                                       0, AH_WAIT_TIMEOUT);
 
-               ar9003_hw_do_manual_peak_cal(ah, chan, run_rtt_cal);
+               ar9003_hw_do_pcoem_manual_peak_cal(ah, chan, run_rtt_cal);
        }
 
        if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE) {
@@ -1228,13 +1224,112 @@ skip_tx_iqcal:
        return true;
 }
 
+static bool ar9003_hw_init_cal_soc(struct ath_hw *ah,
+                                  struct ath9k_channel *chan)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath9k_hw_cal_data *caldata = ah->caldata;
+       bool txiqcal_done = false;
+       bool is_reusable = true, status = true;
+       bool run_agc_cal = false, sep_iq_cal = false;
+
+       /* Use chip chainmask only for calibration */
+       ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask);
+
+       if (ah->enabled_cals & TX_CL_CAL) {
+               REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
+               run_agc_cal = true;
+       }
+
+       if (IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan))
+               goto skip_tx_iqcal;
+
+       /* Do Tx IQ Calibration */
+       REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1,
+                     AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT,
+                     DELPT);
+
+       /*
+        * For AR9485 or later chips, TxIQ cal runs as part of
+        * AGC calibration. Specifically, AR9550 in SoC chips.
+        */
+       if (ah->enabled_cals & TX_IQ_ON_AGC_CAL) {
+               txiqcal_done = true;
+               run_agc_cal = true;
+       } else {
+               sep_iq_cal = true;
+               run_agc_cal = true;
+       }
+
+       /*
+        * In the SoC family, this will run for AR9300, AR9331 and AR9340.
+        */
+       if (sep_iq_cal) {
+               txiqcal_done = ar9003_hw_tx_iq_cal_run(ah);
+               REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
+               udelay(5);
+               REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
+       }
+
+skip_tx_iqcal:
+       if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) {
+               if (AR_SREV_9330_11(ah))
+                       ar9003_hw_manual_peak_cal(ah, 0, IS_CHAN_2GHZ(chan));
+
+               /* Calibrate the AGC */
+               REG_WRITE(ah, AR_PHY_AGC_CONTROL,
+                         REG_READ(ah, AR_PHY_AGC_CONTROL) |
+                         AR_PHY_AGC_CONTROL_CAL);
+
+               /* Poll for offset calibration complete */
+               status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
+                                      AR_PHY_AGC_CONTROL_CAL,
+                                      0, AH_WAIT_TIMEOUT);
+       }
+
+       if (!status) {
+               ath_dbg(common, CALIBRATE,
+                       "offset calibration failed to complete in %d ms; noisy environment?\n",
+                       AH_WAIT_TIMEOUT / 1000);
+               return false;
+       }
+
+       if (txiqcal_done)
+               ar9003_hw_tx_iq_cal_post_proc(ah, is_reusable);
+
+       /* Revert chainmask to runtime parameters */
+       ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
+
+       /* Initialize list pointers */
+       ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
+
+       INIT_CAL(&ah->iq_caldata);
+       INSERT_CAL(ah, &ah->iq_caldata);
+       ath_dbg(common, CALIBRATE, "enabling IQ Calibration\n");
+
+       /* Initialize current pointer to first element in list */
+       ah->cal_list_curr = ah->cal_list;
+
+       if (ah->cal_list_curr)
+               ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
+
+       if (caldata)
+               caldata->CalValid = 0;
+
+       return true;
+}
+
 void ar9003_hw_attach_calib_ops(struct ath_hw *ah)
 {
        struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
        struct ath_hw_ops *ops = ath9k_hw_ops(ah);
 
+       if (AR_SREV_9485(ah) || AR_SREV_9462(ah) || AR_SREV_9565(ah))
+               priv_ops->init_cal = ar9003_hw_init_cal_pcoem;
+       else
+               priv_ops->init_cal = ar9003_hw_init_cal_soc;
+
        priv_ops->init_cal_settings = ar9003_hw_init_cal_settings;
-       priv_ops->init_cal = ar9003_hw_init_cal;
        priv_ops->setup_calibration = ar9003_hw_setup_calibration;
 
        ops->calibrate = ar9003_hw_calibrate;
index 1ec52356b5a16956dda70a2f7365103497b43c68..ec317d6937d646e8cb9269675649d284789f5399 100644 (file)
@@ -3965,7 +3965,7 @@ static void ar9003_hw_apply_tuning_caps(struct ath_hw *ah)
        struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
        u8 tuning_caps_param = eep->baseEepHeader.params_for_tuning_caps[0];
 
-       if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah))
+       if (AR_SREV_9340(ah))
                return;
 
        if (eep->baseEepHeader.featureEnable & 0x40) {
@@ -3984,18 +3984,20 @@ static void ar9003_hw_quick_drop_apply(struct ath_hw *ah, u16 freq)
        int quick_drop;
        s32 t[3], f[3] = {5180, 5500, 5785};
 
-       if (!(pBase->miscConfiguration & BIT(1)))
+       if (!(pBase->miscConfiguration & BIT(4)))
                return;
 
-       if (freq < 4000)
-               quick_drop = eep->modalHeader2G.quick_drop;
-       else {
-               t[0] = eep->base_ext1.quick_drop_low;
-               t[1] = eep->modalHeader5G.quick_drop;
-               t[2] = eep->base_ext1.quick_drop_high;
-               quick_drop = ar9003_hw_power_interpolate(freq, f, t, 3);
+       if (AR_SREV_9300(ah) || AR_SREV_9580(ah) || AR_SREV_9340(ah)) {
+               if (freq < 4000) {
+                       quick_drop = eep->modalHeader2G.quick_drop;
+               } else {
+                       t[0] = eep->base_ext1.quick_drop_low;
+                       t[1] = eep->modalHeader5G.quick_drop;
+                       t[2] = eep->base_ext1.quick_drop_high;
+                       quick_drop = ar9003_hw_power_interpolate(freq, f, t, 3);
+               }
+               REG_RMW_FIELD(ah, AR_PHY_AGC, AR_PHY_AGC_QUICK_DROP, quick_drop);
        }
-       REG_RMW_FIELD(ah, AR_PHY_AGC, AR_PHY_AGC_QUICK_DROP, quick_drop);
 }
 
 static void ar9003_hw_txend_to_xpa_off_apply(struct ath_hw *ah, bool is2ghz)
@@ -4035,7 +4037,7 @@ static void ar9003_hw_xlna_bias_strength_apply(struct ath_hw *ah, bool is2ghz)
        struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
        u8 bias;
 
-       if (!(eep->baseEepHeader.featureEnable & 0x40))
+       if (!(eep->baseEepHeader.miscConfiguration & 0x40))
                return;
 
        if (!AR_SREV_9300(ah))
@@ -4120,7 +4122,7 @@ static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah,
        ar9003_hw_xlna_bias_strength_apply(ah, is2ghz);
        ar9003_hw_atten_apply(ah, chan);
        ar9003_hw_quick_drop_apply(ah, chan->channel);
-       if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah) && !AR_SREV_9550(ah))
+       if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah))
                ar9003_hw_internal_regulator_apply(ah);
        ar9003_hw_apply_tuning_caps(ah);
        ar9003_hw_txend_to_xpa_off_apply(ah, is2ghz);
index 20e49095db2ae2ba0c2d7d83071aa2a14a81252d..29613ebbc5d730832b06bbfdf3fb11df32c858d8 100644 (file)
@@ -17,6 +17,7 @@
 #include "hw.h"
 #include "ar9003_mac.h"
 #include "ar9003_2p2_initvals.h"
+#include "ar9003_buffalo_initvals.h"
 #include "ar9485_initvals.h"
 #include "ar9340_initvals.h"
 #include "ar9330_1p1_initvals.h"
@@ -26,6 +27,7 @@
 #include "ar9462_2p0_initvals.h"
 #include "ar9462_2p1_initvals.h"
 #include "ar9565_1p0_initvals.h"
+#include "ar9565_1p1_initvals.h"
 
 /* General hardware code for the AR9003 hadware family */
 
@@ -148,7 +150,11 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
                                ar9340Modes_high_ob_db_tx_gain_table_1p0);
 
                INIT_INI_ARRAY(&ah->iniModesFastClock,
-                               ar9340Modes_fast_clock_1p0);
+                              ar9340Modes_fast_clock_1p0);
+               INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
+                              ar9340_1p0_baseband_core_txfir_coeff_japan_2484);
+               INIT_INI_ARRAY(&ah->ini_dfs,
+                              ar9340_1p0_baseband_postamble_dfs_channel);
 
                if (!ah->is_clk_25mhz)
                        INIT_INI_ARRAY(&ah->iniAdditional,
@@ -223,6 +229,10 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
                               ar9462_2p1_modes_fast_clock);
                INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
                               ar9462_2p1_baseband_core_txfir_coeff_japan_2484);
+               INIT_INI_ARRAY(&ah->iniPcieSerdes,
+                              ar9462_2p1_pciephy_clkreq_disable_L1);
+               INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
+                              ar9462_2p1_pciephy_clkreq_disable_L1);
        } else if (AR_SREV_9462_20(ah)) {
 
                INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], ar9462_2p0_mac_core);
@@ -247,18 +257,18 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
                                ar9462_2p0_soc_postamble);
 
                INIT_INI_ARRAY(&ah->iniModesRxGain,
-                               ar9462_common_rx_gain_table_2p0);
+                               ar9462_2p0_common_rx_gain);
 
                /* Awake -> Sleep Setting */
                INIT_INI_ARRAY(&ah->iniPcieSerdes,
-                              ar9462_pciephy_clkreq_disable_L1_2p0);
+                              ar9462_2p0_pciephy_clkreq_disable_L1);
                /* Sleep -> Awake Setting */
                INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
-                              ar9462_pciephy_clkreq_disable_L1_2p0);
+                              ar9462_2p0_pciephy_clkreq_disable_L1);
 
                /* Fast clock modal settings */
                INIT_INI_ARRAY(&ah->iniModesFastClock,
-                               ar9462_modes_fast_clock_2p0);
+                               ar9462_2p0_modes_fast_clock);
 
                INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
                               ar9462_2p0_baseband_core_txfir_coeff_japan_2484);
@@ -330,7 +340,46 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
                                ar9580_1p0_low_ob_db_tx_gain_table);
 
                INIT_INI_ARRAY(&ah->iniModesFastClock,
-                               ar9580_1p0_modes_fast_clock);
+                              ar9580_1p0_modes_fast_clock);
+               INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
+                              ar9580_1p0_baseband_core_txfir_coeff_japan_2484);
+               INIT_INI_ARRAY(&ah->ini_dfs,
+                              ar9580_1p0_baseband_postamble_dfs_channel);
+       } else if (AR_SREV_9565_11_OR_LATER(ah)) {
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
+                              ar9565_1p1_mac_core);
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
+                              ar9565_1p1_mac_postamble);
+
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+                              ar9565_1p1_baseband_core);
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+                              ar9565_1p1_baseband_postamble);
+
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
+                              ar9565_1p1_radio_core);
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
+                              ar9565_1p1_radio_postamble);
+
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
+                              ar9565_1p1_soc_preamble);
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
+                              ar9565_1p1_soc_postamble);
+
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                              ar9565_1p1_Common_rx_gain_table);
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                              ar9565_1p1_Modes_lowest_ob_db_tx_gain_table);
+
+               INIT_INI_ARRAY(&ah->iniPcieSerdes,
+                              ar9565_1p1_pciephy_clkreq_disable_L1);
+               INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
+                              ar9565_1p1_pciephy_clkreq_disable_L1);
+
+               INIT_INI_ARRAY(&ah->iniModesFastClock,
+                               ar9565_1p1_modes_fast_clock);
+               INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
+                              ar9565_1p1_baseband_core_txfir_coeff_japan_2484);
        } else if (AR_SREV_9565(ah)) {
                INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
                               ar9565_1p0_mac_core);
@@ -411,7 +460,11 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
 
                /* Fast clock modal settings */
                INIT_INI_ARRAY(&ah->iniModesFastClock,
-                               ar9300Modes_fast_clock_2p2);
+                              ar9300Modes_fast_clock_2p2);
+               INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
+                              ar9300_2p2_baseband_core_txfir_coeff_japan_2484);
+               INIT_INI_ARRAY(&ah->ini_dfs,
+                              ar9300_2p2_baseband_postamble_dfs_channel);
        }
 }
 
@@ -440,7 +493,10 @@ static void ar9003_tx_gain_table_mode0(struct ath_hw *ah)
                        ar9462_2p1_modes_low_ob_db_tx_gain);
        else if (AR_SREV_9462_20(ah))
                INIT_INI_ARRAY(&ah->iniModesTxGain,
-                       ar9462_modes_low_ob_db_tx_gain_table_2p0);
+                       ar9462_2p0_modes_low_ob_db_tx_gain);
+       else if (AR_SREV_9565_11(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                              ar9565_1p1_modes_low_ob_db_tx_gain_table);
        else if (AR_SREV_9565(ah))
                INIT_INI_ARRAY(&ah->iniModesTxGain,
                               ar9565_1p0_modes_low_ob_db_tx_gain_table);
@@ -474,7 +530,10 @@ static void ar9003_tx_gain_table_mode1(struct ath_hw *ah)
                        ar9462_2p1_modes_high_ob_db_tx_gain);
        else if (AR_SREV_9462_20(ah))
                INIT_INI_ARRAY(&ah->iniModesTxGain,
-                       ar9462_modes_high_ob_db_tx_gain_table_2p0);
+                       ar9462_2p0_modes_high_ob_db_tx_gain);
+       else if (AR_SREV_9565_11(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                              ar9565_1p1_modes_high_ob_db_tx_gain_table);
        else if (AR_SREV_9565(ah))
                INIT_INI_ARRAY(&ah->iniModesTxGain,
                               ar9565_1p0_modes_high_ob_db_tx_gain_table);
@@ -500,6 +559,9 @@ static void ar9003_tx_gain_table_mode2(struct ath_hw *ah)
        else if (AR_SREV_9580(ah))
                INIT_INI_ARRAY(&ah->iniModesTxGain,
                        ar9580_1p0_low_ob_db_tx_gain_table);
+       else if (AR_SREV_9565_11(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                              ar9565_1p1_modes_low_ob_db_tx_gain_table);
        else if (AR_SREV_9565(ah))
                INIT_INI_ARRAY(&ah->iniModesTxGain,
                               ar9565_1p0_modes_low_ob_db_tx_gain_table);
@@ -525,12 +587,20 @@ static void ar9003_tx_gain_table_mode3(struct ath_hw *ah)
        else if (AR_SREV_9580(ah))
                INIT_INI_ARRAY(&ah->iniModesTxGain,
                        ar9580_1p0_high_power_tx_gain_table);
+       else if (AR_SREV_9565_11(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                              ar9565_1p1_modes_high_power_tx_gain_table);
        else if (AR_SREV_9565(ah))
                INIT_INI_ARRAY(&ah->iniModesTxGain,
                               ar9565_1p0_modes_high_power_tx_gain_table);
-       else
-               INIT_INI_ARRAY(&ah->iniModesTxGain,
-                       ar9300Modes_high_power_tx_gain_table_2p2);
+       else {
+               if (ah->config.tx_gain_buffalo)
+                       INIT_INI_ARRAY(&ah->iniModesTxGain,
+                                      ar9300Modes_high_power_tx_gain_table_buffalo);
+               else
+                       INIT_INI_ARRAY(&ah->iniModesTxGain,
+                                      ar9300Modes_high_power_tx_gain_table_2p2);
+       }
 }
 
 static void ar9003_tx_gain_table_mode4(struct ath_hw *ah)
@@ -546,7 +616,7 @@ static void ar9003_tx_gain_table_mode4(struct ath_hw *ah)
                       ar9462_2p1_modes_mix_ob_db_tx_gain);
        else if (AR_SREV_9462_20(ah))
                INIT_INI_ARRAY(&ah->iniModesTxGain,
-                      ar9462_modes_mix_ob_db_tx_gain_table_2p0);
+                      ar9462_2p0_modes_mix_ob_db_tx_gain);
        else
                INIT_INI_ARRAY(&ah->iniModesTxGain,
                        ar9300Modes_mixed_ob_db_tx_gain_table_2p2);
@@ -581,6 +651,13 @@ static void ar9003_tx_gain_table_mode6(struct ath_hw *ah)
                        ar9580_1p0_type6_tx_gain_table);
 }
 
+static void ar9003_tx_gain_table_mode7(struct ath_hw *ah)
+{
+       if (AR_SREV_9340(ah))
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                              ar9340_cus227_tx_gain_table_1p0);
+}
+
 typedef void (*ath_txgain_tab)(struct ath_hw *ah);
 
 static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
@@ -593,6 +670,7 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
                ar9003_tx_gain_table_mode4,
                ar9003_tx_gain_table_mode5,
                ar9003_tx_gain_table_mode6,
+               ar9003_tx_gain_table_mode7,
        };
        int idx = ar9003_hw_get_tx_gain_idx(ah);
 
@@ -629,7 +707,10 @@ static void ar9003_rx_gain_table_mode0(struct ath_hw *ah)
                                ar9462_2p1_common_rx_gain);
        else if (AR_SREV_9462_20(ah))
                INIT_INI_ARRAY(&ah->iniModesRxGain,
-                               ar9462_common_rx_gain_table_2p0);
+                               ar9462_2p0_common_rx_gain);
+       else if (AR_SREV_9565_11(ah))
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                              ar9565_1p1_Common_rx_gain_table);
        else if (AR_SREV_9565(ah))
                INIT_INI_ARRAY(&ah->iniModesRxGain,
                               ar9565_1p0_Common_rx_gain_table);
@@ -657,7 +738,7 @@ static void ar9003_rx_gain_table_mode1(struct ath_hw *ah)
                        ar9462_2p1_common_wo_xlna_rx_gain);
        else if (AR_SREV_9462_20(ah))
                INIT_INI_ARRAY(&ah->iniModesRxGain,
-                       ar9462_common_wo_xlna_rx_gain_table_2p0);
+                       ar9462_2p0_common_wo_xlna_rx_gain);
        else if (AR_SREV_9550(ah)) {
                INIT_INI_ARRAY(&ah->iniModesRxGain,
                        ar955x_1p0_common_wo_xlna_rx_gain_table);
@@ -666,6 +747,9 @@ static void ar9003_rx_gain_table_mode1(struct ath_hw *ah)
        } else if (AR_SREV_9580(ah))
                INIT_INI_ARRAY(&ah->iniModesRxGain,
                        ar9580_1p0_wo_xlna_rx_gain_table);
+       else if (AR_SREV_9565_11(ah))
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                              ar9565_1p1_common_wo_xlna_rx_gain_table);
        else if (AR_SREV_9565(ah))
                INIT_INI_ARRAY(&ah->iniModesRxGain,
                               ar9565_1p0_common_wo_xlna_rx_gain_table);
@@ -687,7 +771,7 @@ static void ar9003_rx_gain_table_mode2(struct ath_hw *ah)
                               ar9462_2p1_baseband_postamble_5g_xlna);
        } else if (AR_SREV_9462_20(ah)) {
                INIT_INI_ARRAY(&ah->iniModesRxGain,
-                              ar9462_common_mixed_rx_gain_table_2p0);
+                              ar9462_2p0_common_mixed_rx_gain);
                INIT_INI_ARRAY(&ah->ini_modes_rxgain_bb_core,
                               ar9462_2p0_baseband_core_mix_rxgain);
                INIT_INI_ARRAY(&ah->ini_modes_rxgain_bb_postamble,
@@ -701,12 +785,12 @@ static void ar9003_rx_gain_table_mode3(struct ath_hw *ah)
 {
        if (AR_SREV_9462_21(ah)) {
                INIT_INI_ARRAY(&ah->iniModesRxGain,
-                              ar9462_2p1_common_5g_xlna_only_rx_gain);
+                              ar9462_2p1_common_5g_xlna_only_rxgain);
                INIT_INI_ARRAY(&ah->ini_modes_rxgain_5g_xlna,
                               ar9462_2p1_baseband_postamble_5g_xlna);
        } else if (AR_SREV_9462_20(ah)) {
                INIT_INI_ARRAY(&ah->iniModesRxGain,
-                              ar9462_2p0_5g_xlna_only_rxgain);
+                              ar9462_2p0_common_5g_xlna_only_rxgain);
                INIT_INI_ARRAY(&ah->ini_modes_rxgain_5g_xlna,
                               ar9462_2p0_baseband_postamble_5g_xlna);
        }
@@ -750,6 +834,9 @@ static void ar9003_hw_init_mode_gain_regs(struct ath_hw *ah)
 static void ar9003_hw_configpcipowersave(struct ath_hw *ah,
                                         bool power_off)
 {
+       unsigned int i;
+       struct ar5416IniArray *array;
+
        /*
         * Increase L1 Entry Latency. Some WB222 boards don't have
         * this change in eeprom/OTP.
@@ -775,18 +862,13 @@ static void ar9003_hw_configpcipowersave(struct ath_hw *ah,
         * Configire PCIE after Ini init. SERDES values now come from ini file
         * This enables PCIe low power mode.
         */
-       if (ah->config.pcieSerDesWrite) {
-               unsigned int i;
-               struct ar5416IniArray *array;
+       array = power_off ? &ah->iniPcieSerdes :
+               &ah->iniPcieSerdesLowPower;
 
-               array = power_off ? &ah->iniPcieSerdes :
-                                   &ah->iniPcieSerdesLowPower;
-
-               for (i = 0; i < array->ia_rows; i++) {
-                       REG_WRITE(ah,
-                                 INI_RA(array, i, 0),
-                                 INI_RA(array, i, 1));
-               }
+       for (i = 0; i < array->ia_rows; i++) {
+               REG_WRITE(ah,
+                         INI_RA(array, i, 0),
+                         INI_RA(array, i, 1));
        }
 }
 
index d39b79f5e841ada25c0e1bf435e7c7fd926c15ea..9f051a08e1431e4696d52536197752fd4d305918 100644 (file)
@@ -641,11 +641,12 @@ static void ar9003_hw_override_ini(struct ath_hw *ah)
                else
                        ah->enabled_cals &= ~TX_IQ_CAL;
 
-               if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE)
-                       ah->enabled_cals |= TX_CL_CAL;
-               else
-                       ah->enabled_cals &= ~TX_CL_CAL;
        }
+
+       if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE)
+               ah->enabled_cals |= TX_CL_CAL;
+       else
+               ah->enabled_cals &= ~TX_CL_CAL;
 }
 
 static void ar9003_hw_prog_ini(struct ath_hw *ah,
@@ -1331,6 +1332,7 @@ static void ar9003_hw_ani_cache_ini_regs(struct ath_hw *ah)
 static void ar9003_hw_set_radar_params(struct ath_hw *ah,
                                       struct ath_hw_radar_conf *conf)
 {
+       unsigned int regWrites = 0;
        u32 radar_0 = 0, radar_1 = 0;
 
        if (!conf) {
@@ -1357,6 +1359,11 @@ static void ar9003_hw_set_radar_params(struct ath_hw *ah,
                REG_SET_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
        else
                REG_CLR_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
+
+       if (AR_SREV_9300(ah) || AR_SREV_9340(ah) || AR_SREV_9580(ah)) {
+               REG_WRITE_ARRAY(&ah->ini_dfs,
+                               IS_CHAN_HT40(ah->curchan) ? 2 : 1, regWrites);
+       }
 }
 
 static void ar9003_hw_set_radar_conf(struct ath_hw *ah)
index 2af667beb2738ea498c87ed171d8e4aed5e31bd5..bbbfc4dc59eb1e14f69fbd1e4c78eee38c3ad215 100644 (file)
 #define AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ     -95
 #define AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ     -100
 
+#define AR_PHY_CCA_MAX_GOOD_VAL_9300_FCC_2GHZ -95
+#define AR_PHY_CCA_MAX_GOOD_VAL_9300_FCC_5GHZ -100
+
 #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_wow.c b/drivers/net/wireless/ath/ath9k/ar9003_wow.c
new file mode 100644 (file)
index 0000000..81c88dd
--- /dev/null
@@ -0,0 +1,422 @@
+/*
+ * Copyright (c) 2012 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/export.h>
+#include "ath9k.h"
+#include "reg.h"
+#include "hw-ops.h"
+
+const char *ath9k_hw_wow_event_to_string(u32 wow_event)
+{
+       if (wow_event & AH_WOW_MAGIC_PATTERN_EN)
+               return "Magic pattern";
+       if (wow_event & AH_WOW_USER_PATTERN_EN)
+               return "User pattern";
+       if (wow_event & AH_WOW_LINK_CHANGE)
+               return "Link change";
+       if (wow_event & AH_WOW_BEACON_MISS)
+               return "Beacon miss";
+
+       return  "unknown reason";
+}
+EXPORT_SYMBOL(ath9k_hw_wow_event_to_string);
+
+static void ath9k_hw_set_powermode_wow_sleep(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
+
+       /* set rx disable bit */
+       REG_WRITE(ah, AR_CR, AR_CR_RXD);
+
+       if (!ath9k_hw_wait(ah, AR_CR, AR_CR_RXE, 0, AH_WAIT_TIMEOUT)) {
+               ath_err(common, "Failed to stop Rx DMA in 10ms AR_CR=0x%08x AR_DIAG_SW=0x%08x\n",
+                       REG_READ(ah, AR_CR), REG_READ(ah, AR_DIAG_SW));
+               return;
+       }
+
+       REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_ON_INT);
+}
+
+static void ath9k_wow_create_keep_alive_pattern(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       u8 sta_mac_addr[ETH_ALEN], ap_mac_addr[ETH_ALEN];
+       u32 ctl[13] = {0};
+       u32 data_word[KAL_NUM_DATA_WORDS];
+       u8 i;
+       u32 wow_ka_data_word0;
+
+       memcpy(sta_mac_addr, common->macaddr, ETH_ALEN);
+       memcpy(ap_mac_addr, common->curbssid, ETH_ALEN);
+
+       /* set the transmit buffer */
+       ctl[0] = (KAL_FRAME_LEN | (MAX_RATE_POWER << 16));
+       ctl[1] = 0;
+       ctl[3] = 0xb;   /* OFDM_6M hardware value for this rate */
+       ctl[4] = 0;
+       ctl[7] = (ah->txchainmask) << 2;
+       ctl[2] = 0xf << 16; /* tx_tries 0 */
+
+       for (i = 0; i < KAL_NUM_DESC_WORDS; i++)
+               REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]);
+
+       REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]);
+
+       data_word[0] = (KAL_FRAME_TYPE << 2) | (KAL_FRAME_SUB_TYPE << 4) |
+                      (KAL_TO_DS << 8) | (KAL_DURATION_ID << 16);
+       data_word[1] = (ap_mac_addr[3] << 24) | (ap_mac_addr[2] << 16) |
+                      (ap_mac_addr[1] << 8) | (ap_mac_addr[0]);
+       data_word[2] = (sta_mac_addr[1] << 24) | (sta_mac_addr[0] << 16) |
+                      (ap_mac_addr[5] << 8) | (ap_mac_addr[4]);
+       data_word[3] = (sta_mac_addr[5] << 24) | (sta_mac_addr[4] << 16) |
+                      (sta_mac_addr[3] << 8) | (sta_mac_addr[2]);
+       data_word[4] = (ap_mac_addr[3] << 24) | (ap_mac_addr[2] << 16) |
+                      (ap_mac_addr[1] << 8) | (ap_mac_addr[0]);
+       data_word[5] = (ap_mac_addr[5] << 8) | (ap_mac_addr[4]);
+
+       if (AR_SREV_9462_20(ah)) {
+               /* AR9462 2.0 has an extra descriptor word (time based
+                * discard) compared to other chips */
+               REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + (12 * 4)), 0);
+               wow_ka_data_word0 = AR_WOW_TXBUF(13);
+       } else {
+               wow_ka_data_word0 = AR_WOW_TXBUF(12);
+       }
+
+       for (i = 0; i < KAL_NUM_DATA_WORDS; i++)
+               REG_WRITE(ah, (wow_ka_data_word0 + i*4), data_word[i]);
+
+}
+
+void ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern,
+                               u8 *user_mask, int pattern_count,
+                               int pattern_len)
+{
+       int i;
+       u32 pattern_val, mask_val;
+       u32 set, clr;
+
+       /* FIXME: should check count by querying the hardware capability */
+       if (pattern_count >= MAX_NUM_PATTERN)
+               return;
+
+       REG_SET_BIT(ah, AR_WOW_PATTERN, BIT(pattern_count));
+
+       /* set the registers for pattern */
+       for (i = 0; i < MAX_PATTERN_SIZE; i += 4) {
+               memcpy(&pattern_val, user_pattern, 4);
+               REG_WRITE(ah, (AR_WOW_TB_PATTERN(pattern_count) + i),
+                         pattern_val);
+               user_pattern += 4;
+       }
+
+       /* set the registers for mask */
+       for (i = 0; i < MAX_PATTERN_MASK_SIZE; i += 4) {
+               memcpy(&mask_val, user_mask, 4);
+               REG_WRITE(ah, (AR_WOW_TB_MASK(pattern_count) + i), mask_val);
+               user_mask += 4;
+       }
+
+       /* set the pattern length to be matched
+        *
+        * AR_WOW_LENGTH1_REG1
+        * bit 31:24 pattern 0 length
+        * bit 23:16 pattern 1 length
+        * bit 15:8 pattern 2 length
+        * bit 7:0 pattern 3 length
+        *
+        * AR_WOW_LENGTH1_REG2
+        * bit 31:24 pattern 4 length
+        * bit 23:16 pattern 5 length
+        * bit 15:8 pattern 6 length
+        * bit 7:0 pattern 7 length
+        *
+        * the below logic writes out the new
+        * pattern length for the corresponding
+        * pattern_count, while masking out the
+        * other fields
+        */
+
+       ah->wow_event_mask |= BIT(pattern_count + AR_WOW_PAT_FOUND_SHIFT);
+
+       if (pattern_count < 4) {
+               /* Pattern 0-3 uses AR_WOW_LENGTH1 register */
+               set = (pattern_len & AR_WOW_LENGTH_MAX) <<
+                      AR_WOW_LEN1_SHIFT(pattern_count);
+               clr = AR_WOW_LENGTH1_MASK(pattern_count);
+               REG_RMW(ah, AR_WOW_LENGTH1, set, clr);
+       } else {
+               /* Pattern 4-7 uses AR_WOW_LENGTH2 register */
+               set = (pattern_len & AR_WOW_LENGTH_MAX) <<
+                      AR_WOW_LEN2_SHIFT(pattern_count);
+               clr = AR_WOW_LENGTH2_MASK(pattern_count);
+               REG_RMW(ah, AR_WOW_LENGTH2, set, clr);
+       }
+
+}
+EXPORT_SYMBOL(ath9k_hw_wow_apply_pattern);
+
+u32 ath9k_hw_wow_wakeup(struct ath_hw *ah)
+{
+       u32 wow_status = 0;
+       u32 val = 0, rval;
+
+       /*
+        * read the WoW status register to know
+        * the wakeup reason
+        */
+       rval = REG_READ(ah, AR_WOW_PATTERN);
+       val = AR_WOW_STATUS(rval);
+
+       /*
+        * mask only the WoW events that we have enabled. Sometimes
+        * we have spurious WoW events from the AR_WOW_PATTERN
+        * register. This mask will clean it up.
+        */
+
+       val &= ah->wow_event_mask;
+
+       if (val) {
+               if (val & AR_WOW_MAGIC_PAT_FOUND)
+                       wow_status |= AH_WOW_MAGIC_PATTERN_EN;
+               if (AR_WOW_PATTERN_FOUND(val))
+                       wow_status |= AH_WOW_USER_PATTERN_EN;
+               if (val & AR_WOW_KEEP_ALIVE_FAIL)
+                       wow_status |= AH_WOW_LINK_CHANGE;
+               if (val & AR_WOW_BEACON_FAIL)
+                       wow_status |= AH_WOW_BEACON_MISS;
+       }
+
+       /*
+        * set and clear WOW_PME_CLEAR registers for the chip to
+        * generate next wow signal.
+        * disable D3 before accessing other registers ?
+        */
+
+       /* do we need to check the bit value 0x01000000 (7-10) ?? */
+       REG_RMW(ah, AR_PCIE_PM_CTRL, AR_PMCTRL_WOW_PME_CLR,
+               AR_PMCTRL_PWR_STATE_D1D3);
+
+       /*
+        * clear all events
+        */
+       REG_WRITE(ah, AR_WOW_PATTERN,
+                 AR_WOW_CLEAR_EVENTS(REG_READ(ah, AR_WOW_PATTERN)));
+
+       /*
+        * restore the beacon threshold to init value
+        */
+       REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR);
+
+       /*
+        * Restore the way the PCI-E reset, Power-On-Reset, external
+        * PCIE_POR_SHORT pins are tied to its original value.
+        * Previously just before WoW sleep, we untie the PCI-E
+        * reset to our Chip's Power On Reset so that any PCI-E
+        * reset from the bus will not reset our chip
+        */
+       if (ah->is_pciexpress)
+               ath9k_hw_configpcipowersave(ah, false);
+
+       ah->wow_event_mask = 0;
+
+       return wow_status;
+}
+EXPORT_SYMBOL(ath9k_hw_wow_wakeup);
+
+void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable)
+{
+       u32 wow_event_mask;
+       u32 set, clr;
+
+       /*
+        * wow_event_mask is a mask to the AR_WOW_PATTERN register to
+        * indicate which WoW events we have enabled. The WoW events
+        * are from the 'pattern_enable' in this function and
+        * 'pattern_count' of ath9k_hw_wow_apply_pattern()
+        */
+       wow_event_mask = ah->wow_event_mask;
+
+       /*
+        * Untie Power-on-Reset from the PCI-E-Reset. When we are in
+        * WOW sleep, we do want the Reset from the PCI-E to disturb
+        * our hw state
+        */
+       if (ah->is_pciexpress) {
+               /*
+                * we need to untie the internal POR (power-on-reset)
+                * to the external PCI-E reset. We also need to tie
+                * the PCI-E Phy reset to the PCI-E reset.
+                */
+               set = AR_WA_RESET_EN | AR_WA_POR_SHORT;
+               clr = AR_WA_UNTIE_RESET_EN | AR_WA_D3_L1_DISABLE;
+               REG_RMW(ah, AR_WA, set, clr);
+       }
+
+       /*
+        * set the power states appropriately and enable PME
+        */
+       set = AR_PMCTRL_HOST_PME_EN | AR_PMCTRL_PWR_PM_CTRL_ENA |
+             AR_PMCTRL_AUX_PWR_DET | AR_PMCTRL_WOW_PME_CLR;
+
+       /*
+        * set and clear WOW_PME_CLEAR registers for the chip
+        * to generate next wow signal.
+        */
+       REG_SET_BIT(ah, AR_PCIE_PM_CTRL, set);
+       clr = AR_PMCTRL_WOW_PME_CLR;
+       REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, clr);
+
+       /*
+        * Setup for:
+        *      - beacon misses
+        *      - magic pattern
+        *      - keep alive timeout
+        *      - pattern matching
+        */
+
+       /*
+        * Program default values for pattern backoff, aifs/slot/KAL count,
+        * beacon miss timeout, KAL timeout, etc.
+        */
+       set = AR_WOW_BACK_OFF_SHIFT(AR_WOW_PAT_BACKOFF);
+       REG_SET_BIT(ah, AR_WOW_PATTERN, set);
+
+       set = AR_WOW_AIFS_CNT(AR_WOW_CNT_AIFS_CNT) |
+             AR_WOW_SLOT_CNT(AR_WOW_CNT_SLOT_CNT) |
+             AR_WOW_KEEP_ALIVE_CNT(AR_WOW_CNT_KA_CNT);
+       REG_SET_BIT(ah, AR_WOW_COUNT, set);
+
+       if (pattern_enable & AH_WOW_BEACON_MISS)
+               set = AR_WOW_BEACON_TIMO;
+       /* We are not using beacon miss, program a large value */
+       else
+               set = AR_WOW_BEACON_TIMO_MAX;
+
+       REG_WRITE(ah, AR_WOW_BCN_TIMO, set);
+
+       /*
+        * Keep alive timo in ms except AR9280
+        */
+       if (!pattern_enable)
+               set = AR_WOW_KEEP_ALIVE_NEVER;
+       else
+               set = KAL_TIMEOUT * 32;
+
+       REG_WRITE(ah, AR_WOW_KEEP_ALIVE_TIMO, set);
+
+       /*
+        * Keep alive delay in us. based on 'power on clock',
+        * therefore in usec
+        */
+       set = KAL_DELAY * 1000;
+       REG_WRITE(ah, AR_WOW_KEEP_ALIVE_DELAY, set);
+
+       /*
+        * Create keep alive pattern to respond to beacons
+        */
+       ath9k_wow_create_keep_alive_pattern(ah);
+
+       /*
+        * Configure MAC WoW Registers
+        */
+       set = 0;
+       /* Send keep alive timeouts anyway */
+       clr = AR_WOW_KEEP_ALIVE_AUTO_DIS;
+
+       if (pattern_enable & AH_WOW_LINK_CHANGE)
+               wow_event_mask |= AR_WOW_KEEP_ALIVE_FAIL;
+       else
+               set = AR_WOW_KEEP_ALIVE_FAIL_DIS;
+
+       set = AR_WOW_KEEP_ALIVE_FAIL_DIS;
+       REG_RMW(ah, AR_WOW_KEEP_ALIVE, set, clr);
+
+       /*
+        * we are relying on a bmiss failure. ensure we have
+        * enough threshold to prevent false positives
+        */
+       REG_RMW_FIELD(ah, AR_RSSI_THR, AR_RSSI_THR_BM_THR,
+                     AR_WOW_BMISSTHRESHOLD);
+
+       set = 0;
+       clr = 0;
+
+       if (pattern_enable & AH_WOW_BEACON_MISS) {
+               set = AR_WOW_BEACON_FAIL_EN;
+               wow_event_mask |= AR_WOW_BEACON_FAIL;
+       } else {
+               clr = AR_WOW_BEACON_FAIL_EN;
+       }
+
+       REG_RMW(ah, AR_WOW_BCN_EN, set, clr);
+
+       set = 0;
+       clr = 0;
+       /*
+        * Enable the magic packet registers
+        */
+       if (pattern_enable & AH_WOW_MAGIC_PATTERN_EN) {
+               set = AR_WOW_MAGIC_EN;
+               wow_event_mask |= AR_WOW_MAGIC_PAT_FOUND;
+       } else {
+               clr = AR_WOW_MAGIC_EN;
+       }
+       set |= AR_WOW_MAC_INTR_EN;
+       REG_RMW(ah, AR_WOW_PATTERN, set, clr);
+
+       REG_WRITE(ah, AR_WOW_PATTERN_MATCH_LT_256B,
+                 AR_WOW_PATTERN_SUPPORTED);
+
+       /*
+        * Set the power states appropriately and enable PME
+        */
+       clr = 0;
+       set = AR_PMCTRL_PWR_STATE_D1D3 | AR_PMCTRL_HOST_PME_EN |
+             AR_PMCTRL_PWR_PM_CTRL_ENA;
+
+       clr = AR_PCIE_PM_CTRL_ENA;
+       REG_RMW(ah, AR_PCIE_PM_CTRL, set, clr);
+
+       /*
+        * this is needed to prevent the chip waking up
+        * the host within 3-4 seconds with certain
+        * platform/BIOS. The fix is to enable
+        * D1 & D3 to match original definition and
+        * also match the OTP value. Anyway this
+        * is more related to SW WOW.
+        */
+       clr = AR_PMCTRL_PWR_STATE_D1D3;
+       REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, clr);
+
+       set = AR_PMCTRL_PWR_STATE_D1D3_REAL;
+       REG_SET_BIT(ah, AR_PCIE_PM_CTRL, set);
+
+       REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM);
+
+       /* to bring down WOW power low margin */
+       set = BIT(13);
+       REG_SET_BIT(ah, AR_PCIE_PHY_REG3, set);
+       /* HW WoW */
+       clr = BIT(5);
+       REG_CLR_BIT(ah, AR_PCU_MISC_MODE3, clr);
+
+       ath9k_hw_set_powermode_wow_sleep(ah);
+       ah->wow_event_mask = wow_event_mask;
+}
+EXPORT_SYMBOL(ath9k_hw_wow_enable);
index 6e1756bc38336ed63fadafa22b161bd1f93f64e2..f76139bbb74f0fcf144e22dd382be140c48cf08b 100644 (file)
 #ifndef INITVALS_9330_1P1_H
 #define INITVALS_9330_1P1_H
 
+#define ar9331_1p1_baseband_core_txfir_coeff_japan_2484 ar9300_2p2_baseband_core_txfir_coeff_japan_2484
+
+#define ar9331_modes_high_power_tx_gain_1p1 ar9331_modes_lowest_ob_db_tx_gain_1p1
+
 static const u32 ar9331_1p1_baseband_postamble[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
        {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005},
@@ -55,7 +59,7 @@ static const u32 ar9331_1p1_baseband_postamble[][5] = {
        {0x0000a284, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
        {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
        {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+       {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00058d18, 0x00058d18},
        {0x0000a2d0, 0x00071982, 0x00071982, 0x00071982, 0x00071982},
        {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
        {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
@@ -252,7 +256,7 @@ static const u32 ar9331_modes_low_ob_db_tx_gain_1p1[][5] = {
        {0x0000a2e0, 0xffffcc84, 0xffffcc84, 0xffffcc84, 0xffffcc84},
        {0x0000a2e4, 0xfffff000, 0xfffff000, 0xfffff000, 0xfffff000},
        {0x0000a2e8, 0xfffe0000, 0xfffe0000, 0xfffe0000, 0xfffe0000},
-       {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d0, 0x000050d0},
+       {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d4, 0x000050d4},
        {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
        {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
        {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
@@ -337,8 +341,6 @@ static const u32 ar9331_modes_low_ob_db_tx_gain_1p1[][5] = {
        {0x00016284, 0x14d3f000, 0x14d3f000, 0x14d3f000, 0x14d3f000},
 };
 
-#define ar9331_1p1_baseband_core_txfir_coeff_japan_2484 ar9462_2p0_baseband_core_txfir_coeff_japan_2484
-
 static const u32 ar9331_1p1_xtal_25M[][2] = {
        /* Addr      allmodes  */
        {0x00007038, 0x000002f8},
@@ -373,17 +375,17 @@ static const u32 ar9331_1p1_radio_core[][2] = {
        {0x000160b4, 0x92480040},
        {0x000160c0, 0x006db6db},
        {0x000160c4, 0x0186db60},
-       {0x000160c8, 0x6db4db6c},
+       {0x000160c8, 0x6db6db6c},
        {0x000160cc, 0x6de6c300},
        {0x000160d0, 0x14500820},
        {0x00016100, 0x04cb0001},
        {0x00016104, 0xfff80015},
        {0x00016108, 0x00080010},
        {0x0001610c, 0x00170000},
-       {0x00016140, 0x10800000},
+       {0x00016140, 0x50804000},
        {0x00016144, 0x01884080},
        {0x00016148, 0x000080c0},
-       {0x00016280, 0x01000015},
+       {0x00016280, 0x01001015},
        {0x00016284, 0x14d20000},
        {0x00016288, 0x00318000},
        {0x0001628c, 0x50000000},
@@ -622,12 +624,12 @@ static const u32 ar9331_1p1_baseband_core[][2] = {
        {0x0000a370, 0x00000000},
        {0x0000a390, 0x00000001},
        {0x0000a394, 0x00000444},
-       {0x0000a398, 0x001f0e0f},
-       {0x0000a39c, 0x0075393f},
-       {0x0000a3a0, 0xb79f6427},
-       {0x0000a3a4, 0x00000000},
-       {0x0000a3a8, 0xaaaaaaaa},
-       {0x0000a3ac, 0x3c466478},
+       {0x0000a398, 0x00000000},
+       {0x0000a39c, 0x210d0401},
+       {0x0000a3a0, 0xab9a7144},
+       {0x0000a3a4, 0x00000011},
+       {0x0000a3a8, 0x3c3c003d},
+       {0x0000a3ac, 0x30310030},
        {0x0000a3c0, 0x20202020},
        {0x0000a3c4, 0x22222220},
        {0x0000a3c8, 0x20200020},
@@ -686,100 +688,18 @@ static const u32 ar9331_1p1_baseband_core[][2] = {
        {0x0000a7dc, 0x00000001},
 };
 
-static const u32 ar9331_modes_high_power_tx_gain_1p1[][5] = {
+static const u32 ar9331_1p1_mac_postamble[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-       {0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a},
-       {0x0000a2dc, 0xffff2a52, 0xffff2a52, 0xffff2a52, 0xffff2a52},
-       {0x0000a2e0, 0xffffcc84, 0xffffcc84, 0xffffcc84, 0xffffcc84},
-       {0x0000a2e4, 0xfffff000, 0xfffff000, 0xfffff000, 0xfffff000},
-       {0x0000a2e8, 0xfffe0000, 0xfffe0000, 0xfffe0000, 0xfffe0000},
-       {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d0, 0x000050d0},
-       {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, 0x23000a00, 0x23000a00},
-       {0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
-       {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
-       {0x0000a52c, 0x41023e85, 0x41023e85, 0x2d000a20, 0x2d000a20},
-       {0x0000a530, 0x48023ec6, 0x48023ec6, 0x31000a22, 0x31000a22},
-       {0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000a24, 0x35000a24},
-       {0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000a43, 0x38000a43},
-       {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3b000e42, 0x3b000e42},
-       {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x3f000e44, 0x3f000e44},
-       {0x0000a544, 0x6502feca, 0x6502feca, 0x42000e64, 0x42000e64},
-       {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46000e66, 0x46000e66},
-       {0x0000a54c, 0x7203feca, 0x7203feca, 0x4a000ea6, 0x4a000ea6},
-       {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4a000ea6, 0x4a000ea6},
-       {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4a000ea6, 0x4a000ea6},
-       {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x4a000ea6, 0x4a000ea6},
-       {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x4a000ea6, 0x4a000ea6},
-       {0x0000a560, 0x900fff0b, 0x900fff0b, 0x4a000ea6, 0x4a000ea6},
-       {0x0000a564, 0x960fffcb, 0x960fffcb, 0x4a000ea6, 0x4a000ea6},
-       {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
-       {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
-       {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
-       {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
-       {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
-       {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
-       {0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
-       {0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
-       {0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
-       {0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
-       {0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
-       {0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
-       {0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
-       {0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
-       {0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
-       {0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
-       {0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
-       {0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
-       {0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
-       {0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
-       {0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
-       {0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
-       {0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
-       {0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
-       {0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
-       {0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
-       {0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
-       {0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
-       {0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
-       {0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
-       {0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
-       {0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
-       {0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
-       {0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
-       {0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
-       {0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
-       {0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
-       {0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
-       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
-       {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
-       {0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
-       {0x0000a620, 0x0280c802, 0x0280c802, 0x0280c802, 0x0280c802},
-       {0x0000a624, 0x03010a03, 0x03010a03, 0x03010a03, 0x03010a03},
-       {0x0000a628, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
-       {0x0000a62c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
-       {0x0000a630, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
-       {0x0000a634, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
-       {0x0000a638, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
-       {0x0000a63c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
-       {0x00016044, 0x034922db, 0x034922db, 0x034922db, 0x034922db},
-       {0x00016284, 0x14d3f000, 0x14d3f000, 0x14d3f000, 0x14d3f000},
+       {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},
 };
 
-#define ar9331_1p1_mac_postamble ar9300_2p2_mac_postamble
-
 static const u32 ar9331_1p1_soc_preamble[][2] = {
        /* Addr      allmodes  */
        {0x00007020, 0x00000000},
index 57ed8a112173187d16b15ea15e12b8a38d8244b4..0ac8be96097f2e70f436f75aadb4be1b2d2bc44b 100644 (file)
 #ifndef INITVALS_9330_1P2_H
 #define INITVALS_9330_1P2_H
 
+#define ar9331_modes_high_power_tx_gain_1p2 ar9331_modes_high_ob_db_tx_gain_1p2
+
+#define ar9331_modes_low_ob_db_tx_gain_1p2 ar9331_modes_high_ob_db_tx_gain_1p2
+
+#define ar9331_modes_lowest_ob_db_tx_gain_1p2 ar9331_modes_high_ob_db_tx_gain_1p2
+
+#define ar9331_1p2_baseband_core_txfir_coeff_japan_2484 ar9331_1p1_baseband_core_txfir_coeff_japan_2484
+
+#define ar9331_1p2_xtal_25M ar9331_1p1_xtal_25M
+
+#define ar9331_1p2_xtal_40M ar9331_1p1_xtal_40M
+
+#define ar9331_1p2_soc_postamble ar9331_1p1_soc_postamble
+
+#define ar9331_1p2_mac_postamble ar9331_1p1_mac_postamble
+
+#define ar9331_1p2_soc_preamble ar9331_1p1_soc_preamble
+
+#define ar9331_1p2_mac_core ar9331_1p1_mac_core
+
+#define ar9331_common_wo_xlna_rx_gain_1p2 ar9331_common_wo_xlna_rx_gain_1p1
+
 static const u32 ar9331_modes_high_ob_db_tx_gain_1p2[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
        {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7},
@@ -103,57 +125,6 @@ static const u32 ar9331_modes_high_ob_db_tx_gain_1p2[][5] = {
        {0x0000a63c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
 };
 
-#define ar9331_modes_high_power_tx_gain_1p2 ar9331_modes_high_ob_db_tx_gain_1p2
-
-#define ar9331_modes_low_ob_db_tx_gain_1p2 ar9331_modes_high_power_tx_gain_1p2
-
-#define ar9331_modes_lowest_ob_db_tx_gain_1p2 ar9331_modes_low_ob_db_tx_gain_1p2
-
-static const u32 ar9331_1p2_baseband_postamble[][5] = {
-       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-       {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005},
-       {0x00009820, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e},
-       {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
-       {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
-       {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
-       {0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c},
-       {0x00009c00, 0x00000044, 0x00000044, 0x00000044, 0x00000044},
-       {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a4, 0x037216a4},
-       {0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020},
-       {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
-       {0x00009e10, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e},
-       {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
-       {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
-       {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
-       {0x00009e2c, 0x0000001c, 0x0000001c, 0x00003221, 0x00003221},
-       {0x00009e3c, 0xcf946222, 0xcf946222, 0xcf946222, 0xcf946222},
-       {0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324},
-       {0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010},
-       {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
-       {0x0000a204, 0x00003fc0, 0x00003fc4, 0x00003fc4, 0x00003fc0},
-       {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
-       {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
-       {0x0000a234, 0x00000fff, 0x00000fff, 0x10000fff, 0x00000fff},
-       {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018},
-       {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
-       {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
-       {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
-       {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
-       {0x0000a260, 0x3a021501, 0x3a021501, 0x3a021501, 0x3a021501},
-       {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
-       {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
-       {0x0000a284, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
-       {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071981},
-       {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
-       {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000ae04, 0x00802020, 0x00802020, 0x00802020, 0x00802020},
-       {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-};
-
 static const u32 ar9331_1p2_radio_core[][2] = {
        /* Addr      allmodes  */
        {0x00016000, 0x36db6db6},
@@ -219,24 +190,318 @@ static const u32 ar9331_1p2_radio_core[][2] = {
        {0x000163d4, 0x00000000},
 };
 
-#define ar9331_1p2_baseband_core_txfir_coeff_japan_2484 ar9331_1p1_baseband_core_txfir_coeff_japan_2484
-
-#define ar9331_1p2_xtal_25M ar9331_1p1_xtal_25M
-
-#define ar9331_1p2_xtal_40M ar9331_1p1_xtal_40M
-
-#define ar9331_1p2_baseband_core ar9331_1p1_baseband_core
-
-#define ar9331_1p2_soc_postamble ar9331_1p1_soc_postamble
-
-#define ar9331_1p2_mac_postamble ar9331_1p1_mac_postamble
-
-#define ar9331_1p2_soc_preamble ar9331_1p1_soc_preamble
-
-#define ar9331_1p2_mac_core ar9331_1p1_mac_core
+static const u32 ar9331_1p2_baseband_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00009800, 0xafe68e30},
+       {0x00009804, 0xfd14e000},
+       {0x00009808, 0x9c0a8f6b},
+       {0x0000980c, 0x04800000},
+       {0x00009814, 0x9280c00a},
+       {0x00009818, 0x00000000},
+       {0x0000981c, 0x00020028},
+       {0x00009834, 0x5f3ca3de},
+       {0x00009838, 0x0108ecff},
+       {0x0000983c, 0x14750600},
+       {0x00009880, 0x201fff00},
+       {0x00009884, 0x00001042},
+       {0x000098a4, 0x00200400},
+       {0x000098b0, 0x32840bbe},
+       {0x000098d0, 0x004b6a8e},
+       {0x000098d4, 0x00000820},
+       {0x000098dc, 0x00000000},
+       {0x000098f0, 0x00000000},
+       {0x000098f4, 0x00000000},
+       {0x00009c04, 0x00000000},
+       {0x00009c08, 0x03200000},
+       {0x00009c0c, 0x00000000},
+       {0x00009c10, 0x00000000},
+       {0x00009c14, 0x00046384},
+       {0x00009c18, 0x05b6b440},
+       {0x00009c1c, 0x00b6b440},
+       {0x00009d00, 0xc080a333},
+       {0x00009d04, 0x40206c10},
+       {0x00009d08, 0x009c4060},
+       {0x00009d0c, 0x1883800a},
+       {0x00009d10, 0x01834061},
+       {0x00009d14, 0x00c00400},
+       {0x00009d18, 0x00000000},
+       {0x00009e08, 0x0038233c},
+       {0x00009e24, 0x9927b515},
+       {0x00009e28, 0x12ef0200},
+       {0x00009e30, 0x06336f77},
+       {0x00009e34, 0x6af6532f},
+       {0x00009e38, 0x0cc80c00},
+       {0x00009e40, 0x0d261820},
+       {0x00009e4c, 0x00001004},
+       {0x00009e50, 0x00ff03f1},
+       {0x00009fc0, 0x803e4788},
+       {0x00009fc4, 0x0001efb5},
+       {0x00009fcc, 0x40000014},
+       {0x0000a20c, 0x00000000},
+       {0x0000a220, 0x00000000},
+       {0x0000a224, 0x00000000},
+       {0x0000a228, 0x10002310},
+       {0x0000a23c, 0x00000000},
+       {0x0000a244, 0x0c000000},
+       {0x0000a2a0, 0x00000001},
+       {0x0000a2c0, 0x00000001},
+       {0x0000a2c8, 0x00000000},
+       {0x0000a2cc, 0x18c43433},
+       {0x0000a2d4, 0x00000000},
+       {0x0000a2dc, 0x00000000},
+       {0x0000a2e0, 0x00000000},
+       {0x0000a2e4, 0x00000000},
+       {0x0000a2e8, 0x00000000},
+       {0x0000a2ec, 0x00000000},
+       {0x0000a2f0, 0x00000000},
+       {0x0000a2f4, 0x00000000},
+       {0x0000a2f8, 0x00000000},
+       {0x0000a344, 0x00000000},
+       {0x0000a34c, 0x00000000},
+       {0x0000a350, 0x0000a000},
+       {0x0000a364, 0x00000000},
+       {0x0000a370, 0x00000000},
+       {0x0000a390, 0x00000001},
+       {0x0000a394, 0x00000444},
+       {0x0000a398, 0x001f0e0f},
+       {0x0000a39c, 0x0075393f},
+       {0x0000a3a0, 0xb79f6427},
+       {0x0000a3a4, 0x00000000},
+       {0x0000a3a8, 0xaaaaaaaa},
+       {0x0000a3ac, 0x3c466478},
+       {0x0000a3c0, 0x20202020},
+       {0x0000a3c4, 0x22222220},
+       {0x0000a3c8, 0x20200020},
+       {0x0000a3cc, 0x20202020},
+       {0x0000a3d0, 0x20202020},
+       {0x0000a3d4, 0x20202020},
+       {0x0000a3d8, 0x20202020},
+       {0x0000a3dc, 0x20202020},
+       {0x0000a3e0, 0x20202020},
+       {0x0000a3e4, 0x20202020},
+       {0x0000a3e8, 0x20202020},
+       {0x0000a3ec, 0x20202020},
+       {0x0000a3f0, 0x00000000},
+       {0x0000a3f4, 0x00000006},
+       {0x0000a3f8, 0x0cdbd380},
+       {0x0000a3fc, 0x000f0f01},
+       {0x0000a400, 0x8fa91f01},
+       {0x0000a404, 0x00000000},
+       {0x0000a408, 0x0e79e5c6},
+       {0x0000a40c, 0x00820820},
+       {0x0000a414, 0x1ce739ce},
+       {0x0000a418, 0x2d001dce},
+       {0x0000a41c, 0x1ce739ce},
+       {0x0000a420, 0x000001ce},
+       {0x0000a424, 0x1ce739ce},
+       {0x0000a428, 0x000001ce},
+       {0x0000a42c, 0x1ce739ce},
+       {0x0000a430, 0x1ce739ce},
+       {0x0000a434, 0x00000000},
+       {0x0000a438, 0x00001801},
+       {0x0000a43c, 0x00000000},
+       {0x0000a440, 0x00000000},
+       {0x0000a444, 0x00000000},
+       {0x0000a448, 0x04000000},
+       {0x0000a44c, 0x00000001},
+       {0x0000a450, 0x00010000},
+       {0x0000a458, 0x00000000},
+       {0x0000a640, 0x00000000},
+       {0x0000a644, 0x3fad9d74},
+       {0x0000a648, 0x0048060a},
+       {0x0000a64c, 0x00003c37},
+       {0x0000a670, 0x03020100},
+       {0x0000a674, 0x09080504},
+       {0x0000a678, 0x0d0c0b0a},
+       {0x0000a67c, 0x13121110},
+       {0x0000a680, 0x31301514},
+       {0x0000a684, 0x35343332},
+       {0x0000a688, 0x00000036},
+       {0x0000a690, 0x00000838},
+       {0x0000a7c0, 0x00000000},
+       {0x0000a7c4, 0xfffffffc},
+       {0x0000a7c8, 0x00000000},
+       {0x0000a7cc, 0x00000000},
+       {0x0000a7d0, 0x00000000},
+       {0x0000a7d4, 0x00000004},
+       {0x0000a7dc, 0x00000001},
+};
 
-#define ar9331_common_wo_xlna_rx_gain_1p2 ar9331_common_wo_xlna_rx_gain_1p1
+static const u32 ar9331_1p2_baseband_postamble[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005},
+       {0x00009820, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e},
+       {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+       {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+       {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+       {0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c},
+       {0x00009c00, 0x00000044, 0x00000044, 0x00000044, 0x00000044},
+       {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a4, 0x037216a4},
+       {0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020},
+       {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+       {0x00009e10, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e},
+       {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
+       {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
+       {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+       {0x00009e2c, 0x0000001c, 0x0000001c, 0x00003221, 0x00003221},
+       {0x00009e3c, 0xcf946222, 0xcf946222, 0xcf946222, 0xcf946222},
+       {0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324},
+       {0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010},
+       {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
+       {0x0000a204, 0x00003fc0, 0x00003fc4, 0x00003fc4, 0x00003fc0},
+       {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
+       {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+       {0x0000a234, 0x00000fff, 0x00000fff, 0x10000fff, 0x00000fff},
+       {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018},
+       {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+       {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+       {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
+       {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+       {0x0000a260, 0x3a021501, 0x3a021501, 0x3a021501, 0x3a021501},
+       {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+       {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
+       {0x0000a284, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+       {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071981},
+       {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
+       {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000ae04, 0x00802020, 0x00802020, 0x00802020, 0x00802020},
+       {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+};
 
-#define ar9331_common_rx_gain_1p2 ar9485_common_rx_gain_1_1
+static const u32 ar9331_common_rx_gain_1p2[][2] = {
+       /* Addr      allmodes  */
+       {0x0000a000, 0x00010000},
+       {0x0000a004, 0x00030002},
+       {0x0000a008, 0x00050004},
+       {0x0000a00c, 0x00810080},
+       {0x0000a010, 0x01800082},
+       {0x0000a014, 0x01820181},
+       {0x0000a018, 0x01840183},
+       {0x0000a01c, 0x01880185},
+       {0x0000a020, 0x018a0189},
+       {0x0000a024, 0x02850284},
+       {0x0000a028, 0x02890288},
+       {0x0000a02c, 0x03850384},
+       {0x0000a030, 0x03890388},
+       {0x0000a034, 0x038b038a},
+       {0x0000a038, 0x038d038c},
+       {0x0000a03c, 0x03910390},
+       {0x0000a040, 0x03930392},
+       {0x0000a044, 0x03950394},
+       {0x0000a048, 0x00000396},
+       {0x0000a04c, 0x00000000},
+       {0x0000a050, 0x00000000},
+       {0x0000a054, 0x00000000},
+       {0x0000a058, 0x00000000},
+       {0x0000a05c, 0x00000000},
+       {0x0000a060, 0x00000000},
+       {0x0000a064, 0x00000000},
+       {0x0000a068, 0x00000000},
+       {0x0000a06c, 0x00000000},
+       {0x0000a070, 0x00000000},
+       {0x0000a074, 0x00000000},
+       {0x0000a078, 0x00000000},
+       {0x0000a07c, 0x00000000},
+       {0x0000a080, 0x28282828},
+       {0x0000a084, 0x28282828},
+       {0x0000a088, 0x28282828},
+       {0x0000a08c, 0x28282828},
+       {0x0000a090, 0x28282828},
+       {0x0000a094, 0x21212128},
+       {0x0000a098, 0x171c1c1c},
+       {0x0000a09c, 0x02020212},
+       {0x0000a0a0, 0x00000202},
+       {0x0000a0a4, 0x00000000},
+       {0x0000a0a8, 0x00000000},
+       {0x0000a0ac, 0x00000000},
+       {0x0000a0b0, 0x00000000},
+       {0x0000a0b4, 0x00000000},
+       {0x0000a0b8, 0x00000000},
+       {0x0000a0bc, 0x00000000},
+       {0x0000a0c0, 0x001f0000},
+       {0x0000a0c4, 0x111f1100},
+       {0x0000a0c8, 0x111d111e},
+       {0x0000a0cc, 0x111b111c},
+       {0x0000a0d0, 0x22032204},
+       {0x0000a0d4, 0x22012202},
+       {0x0000a0d8, 0x221f2200},
+       {0x0000a0dc, 0x221d221e},
+       {0x0000a0e0, 0x33013302},
+       {0x0000a0e4, 0x331f3300},
+       {0x0000a0e8, 0x4402331e},
+       {0x0000a0ec, 0x44004401},
+       {0x0000a0f0, 0x441e441f},
+       {0x0000a0f4, 0x55015502},
+       {0x0000a0f8, 0x551f5500},
+       {0x0000a0fc, 0x6602551e},
+       {0x0000a100, 0x66006601},
+       {0x0000a104, 0x661e661f},
+       {0x0000a108, 0x7703661d},
+       {0x0000a10c, 0x77017702},
+       {0x0000a110, 0x00007700},
+       {0x0000a114, 0x00000000},
+       {0x0000a118, 0x00000000},
+       {0x0000a11c, 0x00000000},
+       {0x0000a120, 0x00000000},
+       {0x0000a124, 0x00000000},
+       {0x0000a128, 0x00000000},
+       {0x0000a12c, 0x00000000},
+       {0x0000a130, 0x00000000},
+       {0x0000a134, 0x00000000},
+       {0x0000a138, 0x00000000},
+       {0x0000a13c, 0x00000000},
+       {0x0000a140, 0x001f0000},
+       {0x0000a144, 0x111f1100},
+       {0x0000a148, 0x111d111e},
+       {0x0000a14c, 0x111b111c},
+       {0x0000a150, 0x22032204},
+       {0x0000a154, 0x22012202},
+       {0x0000a158, 0x221f2200},
+       {0x0000a15c, 0x221d221e},
+       {0x0000a160, 0x33013302},
+       {0x0000a164, 0x331f3300},
+       {0x0000a168, 0x4402331e},
+       {0x0000a16c, 0x44004401},
+       {0x0000a170, 0x441e441f},
+       {0x0000a174, 0x55015502},
+       {0x0000a178, 0x551f5500},
+       {0x0000a17c, 0x6602551e},
+       {0x0000a180, 0x66006601},
+       {0x0000a184, 0x661e661f},
+       {0x0000a188, 0x7703661d},
+       {0x0000a18c, 0x77017702},
+       {0x0000a190, 0x00007700},
+       {0x0000a194, 0x00000000},
+       {0x0000a198, 0x00000000},
+       {0x0000a19c, 0x00000000},
+       {0x0000a1a0, 0x00000000},
+       {0x0000a1a4, 0x00000000},
+       {0x0000a1a8, 0x00000000},
+       {0x0000a1ac, 0x00000000},
+       {0x0000a1b0, 0x00000000},
+       {0x0000a1b4, 0x00000000},
+       {0x0000a1b8, 0x00000000},
+       {0x0000a1bc, 0x00000000},
+       {0x0000a1c0, 0x00000000},
+       {0x0000a1c4, 0x00000000},
+       {0x0000a1c8, 0x00000000},
+       {0x0000a1cc, 0x00000000},
+       {0x0000a1d0, 0x00000000},
+       {0x0000a1d4, 0x00000000},
+       {0x0000a1d8, 0x00000000},
+       {0x0000a1dc, 0x00000000},
+       {0x0000a1e0, 0x00000000},
+       {0x0000a1e4, 0x00000000},
+       {0x0000a1e8, 0x00000000},
+       {0x0000a1ec, 0x00000000},
+       {0x0000a1f0, 0x00000396},
+       {0x0000a1f4, 0x00000396},
+       {0x0000a1f8, 0x00000396},
+       {0x0000a1fc, 0x00000296},
+};
 
 #endif /* INITVALS_9330_1P2_H */
index 25db9215985aa1519e0901cb698b312811d6dc91..a01f0edb65182a16b95181038786c9d8073a1cab 100644 (file)
 #ifndef INITVALS_9340_H
 #define INITVALS_9340_H
 
+#define ar9340_1p0_mac_postamble ar9300_2p2_mac_postamble
+
+#define ar9340_1p0_soc_postamble ar9300_2p2_soc_postamble
+
+#define ar9340Modes_fast_clock_1p0 ar9300Modes_fast_clock_2p2
+
+#define ar9340Common_rx_gain_table_1p0 ar9300Common_rx_gain_table_2p2
+
+#define ar9340Common_wo_xlna_rx_gain_table_1p0 ar9300Common_wo_xlna_rx_gain_table_2p2
+
+#define ar9340_1p0_baseband_core_txfir_coeff_japan_2484 ar9300_2p2_baseband_core_txfir_coeff_japan_2484
+
+#define ar9340_1p0_baseband_postamble_dfs_channel ar9300_2p2_baseband_postamble_dfs_channel
+
 static const u32 ar9340_1p0_radio_postamble[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
        {0x000160ac, 0xa4646800, 0xa4646800, 0xa4646800, 0xa4646800},
@@ -100,8 +114,6 @@ static const u32 ar9340Modes_lowest_ob_db_tx_gain_table_1p0[][5] = {
        {0x00016448, 0x24925266, 0x24925266, 0x24925266, 0x24925266},
 };
 
-#define ar9340Modes_fast_clock_1p0 ar9300Modes_fast_clock_2p2
-
 static const u32 ar9340_1p0_radio_core[][2] = {
        /* Addr      allmodes  */
        {0x00016000, 0x36db6db6},
@@ -215,16 +227,12 @@ static const u32 ar9340_1p0_radio_core_40M[][2] = {
        {0x0000824c, 0x0001e800},
 };
 
-#define ar9340_1p0_mac_postamble ar9300_2p2_mac_postamble
-
-#define ar9340_1p0_soc_postamble ar9300_2p2_soc_postamble
-
 static const u32 ar9340_1p0_baseband_postamble[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
        {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011},
        {0x00009820, 0x206a022e, 0x206a022e, 0x206a022e, 0x206a022e},
        {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
-       {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+       {0x00009828, 0x06903081, 0x06903081, 0x09103881, 0x09103881},
        {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
        {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c},
        {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4},
@@ -340,9 +348,9 @@ static const u32 ar9340_1p0_baseband_core[][2] = {
        {0x0000a370, 0x00000000},
        {0x0000a390, 0x00000001},
        {0x0000a394, 0x00000444},
-       {0x0000a398, 0x001f0e0f},
-       {0x0000a39c, 0x0075393f},
-       {0x0000a3a0, 0xb79f6427},
+       {0x0000a398, 0x00000000},
+       {0x0000a39c, 0x210d0401},
+       {0x0000a3a0, 0xab9a7144},
        {0x0000a3a4, 0x00000000},
        {0x0000a3a8, 0xaaaaaaaa},
        {0x0000a3ac, 0x3c466478},
@@ -714,266 +722,6 @@ static const u32 ar9340Modes_ub124_tx_gain_table_1p0[][5] = {
        {0x0000b2e8, 0xfffe0000, 0xfffe0000, 0xfffc0000, 0xfffc0000},
 };
 
-static const u32 ar9340Common_rx_gain_table_1p0[][2] = {
-       /* Addr      allmodes  */
-       {0x0000a000, 0x00010000},
-       {0x0000a004, 0x00030002},
-       {0x0000a008, 0x00050004},
-       {0x0000a00c, 0x00810080},
-       {0x0000a010, 0x00830082},
-       {0x0000a014, 0x01810180},
-       {0x0000a018, 0x01830182},
-       {0x0000a01c, 0x01850184},
-       {0x0000a020, 0x01890188},
-       {0x0000a024, 0x018b018a},
-       {0x0000a028, 0x018d018c},
-       {0x0000a02c, 0x01910190},
-       {0x0000a030, 0x01930192},
-       {0x0000a034, 0x01950194},
-       {0x0000a038, 0x038a0196},
-       {0x0000a03c, 0x038c038b},
-       {0x0000a040, 0x0390038d},
-       {0x0000a044, 0x03920391},
-       {0x0000a048, 0x03940393},
-       {0x0000a04c, 0x03960395},
-       {0x0000a050, 0x00000000},
-       {0x0000a054, 0x00000000},
-       {0x0000a058, 0x00000000},
-       {0x0000a05c, 0x00000000},
-       {0x0000a060, 0x00000000},
-       {0x0000a064, 0x00000000},
-       {0x0000a068, 0x00000000},
-       {0x0000a06c, 0x00000000},
-       {0x0000a070, 0x00000000},
-       {0x0000a074, 0x00000000},
-       {0x0000a078, 0x00000000},
-       {0x0000a07c, 0x00000000},
-       {0x0000a080, 0x22222229},
-       {0x0000a084, 0x1d1d1d1d},
-       {0x0000a088, 0x1d1d1d1d},
-       {0x0000a08c, 0x1d1d1d1d},
-       {0x0000a090, 0x171d1d1d},
-       {0x0000a094, 0x11111717},
-       {0x0000a098, 0x00030311},
-       {0x0000a09c, 0x00000000},
-       {0x0000a0a0, 0x00000000},
-       {0x0000a0a4, 0x00000000},
-       {0x0000a0a8, 0x00000000},
-       {0x0000a0ac, 0x00000000},
-       {0x0000a0b0, 0x00000000},
-       {0x0000a0b4, 0x00000000},
-       {0x0000a0b8, 0x00000000},
-       {0x0000a0bc, 0x00000000},
-       {0x0000a0c0, 0x001f0000},
-       {0x0000a0c4, 0x01000101},
-       {0x0000a0c8, 0x011e011f},
-       {0x0000a0cc, 0x011c011d},
-       {0x0000a0d0, 0x02030204},
-       {0x0000a0d4, 0x02010202},
-       {0x0000a0d8, 0x021f0200},
-       {0x0000a0dc, 0x0302021e},
-       {0x0000a0e0, 0x03000301},
-       {0x0000a0e4, 0x031e031f},
-       {0x0000a0e8, 0x0402031d},
-       {0x0000a0ec, 0x04000401},
-       {0x0000a0f0, 0x041e041f},
-       {0x0000a0f4, 0x0502041d},
-       {0x0000a0f8, 0x05000501},
-       {0x0000a0fc, 0x051e051f},
-       {0x0000a100, 0x06010602},
-       {0x0000a104, 0x061f0600},
-       {0x0000a108, 0x061d061e},
-       {0x0000a10c, 0x07020703},
-       {0x0000a110, 0x07000701},
-       {0x0000a114, 0x00000000},
-       {0x0000a118, 0x00000000},
-       {0x0000a11c, 0x00000000},
-       {0x0000a120, 0x00000000},
-       {0x0000a124, 0x00000000},
-       {0x0000a128, 0x00000000},
-       {0x0000a12c, 0x00000000},
-       {0x0000a130, 0x00000000},
-       {0x0000a134, 0x00000000},
-       {0x0000a138, 0x00000000},
-       {0x0000a13c, 0x00000000},
-       {0x0000a140, 0x001f0000},
-       {0x0000a144, 0x01000101},
-       {0x0000a148, 0x011e011f},
-       {0x0000a14c, 0x011c011d},
-       {0x0000a150, 0x02030204},
-       {0x0000a154, 0x02010202},
-       {0x0000a158, 0x021f0200},
-       {0x0000a15c, 0x0302021e},
-       {0x0000a160, 0x03000301},
-       {0x0000a164, 0x031e031f},
-       {0x0000a168, 0x0402031d},
-       {0x0000a16c, 0x04000401},
-       {0x0000a170, 0x041e041f},
-       {0x0000a174, 0x0502041d},
-       {0x0000a178, 0x05000501},
-       {0x0000a17c, 0x051e051f},
-       {0x0000a180, 0x06010602},
-       {0x0000a184, 0x061f0600},
-       {0x0000a188, 0x061d061e},
-       {0x0000a18c, 0x07020703},
-       {0x0000a190, 0x07000701},
-       {0x0000a194, 0x00000000},
-       {0x0000a198, 0x00000000},
-       {0x0000a19c, 0x00000000},
-       {0x0000a1a0, 0x00000000},
-       {0x0000a1a4, 0x00000000},
-       {0x0000a1a8, 0x00000000},
-       {0x0000a1ac, 0x00000000},
-       {0x0000a1b0, 0x00000000},
-       {0x0000a1b4, 0x00000000},
-       {0x0000a1b8, 0x00000000},
-       {0x0000a1bc, 0x00000000},
-       {0x0000a1c0, 0x00000000},
-       {0x0000a1c4, 0x00000000},
-       {0x0000a1c8, 0x00000000},
-       {0x0000a1cc, 0x00000000},
-       {0x0000a1d0, 0x00000000},
-       {0x0000a1d4, 0x00000000},
-       {0x0000a1d8, 0x00000000},
-       {0x0000a1dc, 0x00000000},
-       {0x0000a1e0, 0x00000000},
-       {0x0000a1e4, 0x00000000},
-       {0x0000a1e8, 0x00000000},
-       {0x0000a1ec, 0x00000000},
-       {0x0000a1f0, 0x00000396},
-       {0x0000a1f4, 0x00000396},
-       {0x0000a1f8, 0x00000396},
-       {0x0000a1fc, 0x00000196},
-       {0x0000b000, 0x00010000},
-       {0x0000b004, 0x00030002},
-       {0x0000b008, 0x00050004},
-       {0x0000b00c, 0x00810080},
-       {0x0000b010, 0x00830082},
-       {0x0000b014, 0x01810180},
-       {0x0000b018, 0x01830182},
-       {0x0000b01c, 0x01850184},
-       {0x0000b020, 0x02810280},
-       {0x0000b024, 0x02830282},
-       {0x0000b028, 0x02850284},
-       {0x0000b02c, 0x02890288},
-       {0x0000b030, 0x028b028a},
-       {0x0000b034, 0x0388028c},
-       {0x0000b038, 0x038a0389},
-       {0x0000b03c, 0x038c038b},
-       {0x0000b040, 0x0390038d},
-       {0x0000b044, 0x03920391},
-       {0x0000b048, 0x03940393},
-       {0x0000b04c, 0x03960395},
-       {0x0000b050, 0x00000000},
-       {0x0000b054, 0x00000000},
-       {0x0000b058, 0x00000000},
-       {0x0000b05c, 0x00000000},
-       {0x0000b060, 0x00000000},
-       {0x0000b064, 0x00000000},
-       {0x0000b068, 0x00000000},
-       {0x0000b06c, 0x00000000},
-       {0x0000b070, 0x00000000},
-       {0x0000b074, 0x00000000},
-       {0x0000b078, 0x00000000},
-       {0x0000b07c, 0x00000000},
-       {0x0000b080, 0x23232323},
-       {0x0000b084, 0x21232323},
-       {0x0000b088, 0x19191c1e},
-       {0x0000b08c, 0x12141417},
-       {0x0000b090, 0x07070e0e},
-       {0x0000b094, 0x03030305},
-       {0x0000b098, 0x00000003},
-       {0x0000b09c, 0x00000000},
-       {0x0000b0a0, 0x00000000},
-       {0x0000b0a4, 0x00000000},
-       {0x0000b0a8, 0x00000000},
-       {0x0000b0ac, 0x00000000},
-       {0x0000b0b0, 0x00000000},
-       {0x0000b0b4, 0x00000000},
-       {0x0000b0b8, 0x00000000},
-       {0x0000b0bc, 0x00000000},
-       {0x0000b0c0, 0x003f0020},
-       {0x0000b0c4, 0x00400041},
-       {0x0000b0c8, 0x0140005f},
-       {0x0000b0cc, 0x0160015f},
-       {0x0000b0d0, 0x017e017f},
-       {0x0000b0d4, 0x02410242},
-       {0x0000b0d8, 0x025f0240},
-       {0x0000b0dc, 0x027f0260},
-       {0x0000b0e0, 0x0341027e},
-       {0x0000b0e4, 0x035f0340},
-       {0x0000b0e8, 0x037f0360},
-       {0x0000b0ec, 0x04400441},
-       {0x0000b0f0, 0x0460045f},
-       {0x0000b0f4, 0x0541047f},
-       {0x0000b0f8, 0x055f0540},
-       {0x0000b0fc, 0x057f0560},
-       {0x0000b100, 0x06400641},
-       {0x0000b104, 0x0660065f},
-       {0x0000b108, 0x067e067f},
-       {0x0000b10c, 0x07410742},
-       {0x0000b110, 0x075f0740},
-       {0x0000b114, 0x077f0760},
-       {0x0000b118, 0x07800781},
-       {0x0000b11c, 0x07a0079f},
-       {0x0000b120, 0x07c107bf},
-       {0x0000b124, 0x000007c0},
-       {0x0000b128, 0x00000000},
-       {0x0000b12c, 0x00000000},
-       {0x0000b130, 0x00000000},
-       {0x0000b134, 0x00000000},
-       {0x0000b138, 0x00000000},
-       {0x0000b13c, 0x00000000},
-       {0x0000b140, 0x003f0020},
-       {0x0000b144, 0x00400041},
-       {0x0000b148, 0x0140005f},
-       {0x0000b14c, 0x0160015f},
-       {0x0000b150, 0x017e017f},
-       {0x0000b154, 0x02410242},
-       {0x0000b158, 0x025f0240},
-       {0x0000b15c, 0x027f0260},
-       {0x0000b160, 0x0341027e},
-       {0x0000b164, 0x035f0340},
-       {0x0000b168, 0x037f0360},
-       {0x0000b16c, 0x04400441},
-       {0x0000b170, 0x0460045f},
-       {0x0000b174, 0x0541047f},
-       {0x0000b178, 0x055f0540},
-       {0x0000b17c, 0x057f0560},
-       {0x0000b180, 0x06400641},
-       {0x0000b184, 0x0660065f},
-       {0x0000b188, 0x067e067f},
-       {0x0000b18c, 0x07410742},
-       {0x0000b190, 0x075f0740},
-       {0x0000b194, 0x077f0760},
-       {0x0000b198, 0x07800781},
-       {0x0000b19c, 0x07a0079f},
-       {0x0000b1a0, 0x07c107bf},
-       {0x0000b1a4, 0x000007c0},
-       {0x0000b1a8, 0x00000000},
-       {0x0000b1ac, 0x00000000},
-       {0x0000b1b0, 0x00000000},
-       {0x0000b1b4, 0x00000000},
-       {0x0000b1b8, 0x00000000},
-       {0x0000b1bc, 0x00000000},
-       {0x0000b1c0, 0x00000000},
-       {0x0000b1c4, 0x00000000},
-       {0x0000b1c8, 0x00000000},
-       {0x0000b1cc, 0x00000000},
-       {0x0000b1d0, 0x00000000},
-       {0x0000b1d4, 0x00000000},
-       {0x0000b1d8, 0x00000000},
-       {0x0000b1dc, 0x00000000},
-       {0x0000b1e0, 0x00000000},
-       {0x0000b1e4, 0x00000000},
-       {0x0000b1e8, 0x00000000},
-       {0x0000b1ec, 0x00000000},
-       {0x0000b1f0, 0x00000396},
-       {0x0000b1f4, 0x00000396},
-       {0x0000b1f8, 0x00000396},
-       {0x0000b1fc, 0x00000196},
-};
-
 static const u32 ar9340Modes_low_ob_db_tx_gain_table_1p0[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
        {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
@@ -1437,8 +1185,6 @@ static const u32 ar9340_1p0_mac_core[][2] = {
        {0x000083d0, 0x000101ff},
 };
 
-#define ar9340Common_wo_xlna_rx_gain_table_1p0 ar9300Common_wo_xlna_rx_gain_table_2p2
-
 static const u32 ar9340_1p0_soc_preamble[][2] = {
        /* Addr      allmodes  */
        {0x00007008, 0x00000000},
@@ -1447,4 +1193,106 @@ static const u32 ar9340_1p0_soc_preamble[][2] = {
        {0x00007038, 0x000004c2},
 };
 
+static const u32 ar9340_cus227_tx_gain_table_1p0[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+       {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+       {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+       {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
+       {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
+       {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
+       {0x0000a514, 0x1c000223, 0x1c000223, 0x11000400, 0x11000400},
+       {0x0000a518, 0x21002220, 0x21002220, 0x15000402, 0x15000402},
+       {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404},
+       {0x0000a520, 0x2c022220, 0x2c022220, 0x1b000603, 0x1b000603},
+       {0x0000a524, 0x30022222, 0x30022222, 0x1f000a02, 0x1f000a02},
+       {0x0000a528, 0x35022225, 0x35022225, 0x23000a04, 0x23000a04},
+       {0x0000a52c, 0x3b02222a, 0x3b02222a, 0x26000a20, 0x26000a20},
+       {0x0000a530, 0x3f02222c, 0x3f02222c, 0x2a000e20, 0x2a000e20},
+       {0x0000a534, 0x4202242a, 0x4202242a, 0x2e000e22, 0x2e000e22},
+       {0x0000a538, 0x4702244a, 0x4702244a, 0x31000e24, 0x31000e24},
+       {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x34001640, 0x34001640},
+       {0x0000a540, 0x4e02246c, 0x4e02246c, 0x38001660, 0x38001660},
+       {0x0000a544, 0x5302266c, 0x5302266c, 0x3b001861, 0x3b001861},
+       {0x0000a548, 0x5702286c, 0x5702286c, 0x3e001a81, 0x3e001a81},
+       {0x0000a54c, 0x5c02486b, 0x5c02486b, 0x42001a83, 0x42001a83},
+       {0x0000a550, 0x61024a6c, 0x61024a6c, 0x44001c84, 0x44001c84},
+       {0x0000a554, 0x66026a6c, 0x66026a6c, 0x48001ce3, 0x48001ce3},
+       {0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x4c001ce5, 0x4c001ce5},
+       {0x0000a55c, 0x7002708c, 0x7002708c, 0x50001ce9, 0x50001ce9},
+       {0x0000a560, 0x7302b08a, 0x7302b08a, 0x54001ceb, 0x54001ceb},
+       {0x0000a564, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec},
+       {0x0000a568, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec},
+       {0x0000a56c, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec},
+       {0x0000a570, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec},
+       {0x0000a574, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec},
+       {0x0000a578, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec},
+       {0x0000a57c, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec},
+       {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
+       {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
+       {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
+       {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200},
+       {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202},
+       {0x0000a594, 0x1c800223, 0x1c800223, 0x11800400, 0x11800400},
+       {0x0000a598, 0x21820220, 0x21820220, 0x15800402, 0x15800402},
+       {0x0000a59c, 0x27820223, 0x27820223, 0x19800404, 0x19800404},
+       {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1b800603, 0x1b800603},
+       {0x0000a5a4, 0x2f822222, 0x2f822222, 0x1f800a02, 0x1f800a02},
+       {0x0000a5a8, 0x34822225, 0x34822225, 0x23800a04, 0x23800a04},
+       {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x26800a20, 0x26800a20},
+       {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2a800e20, 0x2a800e20},
+       {0x0000a5b4, 0x4282242a, 0x4282242a, 0x2e800e22, 0x2e800e22},
+       {0x0000a5b8, 0x4782244a, 0x4782244a, 0x31800e24, 0x31800e24},
+       {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x34801640, 0x34801640},
+       {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x38801660, 0x38801660},
+       {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3b801861, 0x3b801861},
+       {0x0000a5c8, 0x5782286c, 0x5782286c, 0x3e801a81, 0x3e801a81},
+       {0x0000a5cc, 0x5c84286b, 0x5c84286b, 0x42801a83, 0x42801a83},
+       {0x0000a5d0, 0x61842a6c, 0x61842a6c, 0x44801c84, 0x44801c84},
+       {0x0000a5d4, 0x66862a6c, 0x66862a6c, 0x48801ce3, 0x48801ce3},
+       {0x0000a5d8, 0x6b862e6c, 0x6b862e6c, 0x4c801ce5, 0x4c801ce5},
+       {0x0000a5dc, 0x7086308c, 0x7086308c, 0x50801ce9, 0x50801ce9},
+       {0x0000a5e0, 0x738a308a, 0x738a308a, 0x54801ceb, 0x54801ceb},
+       {0x0000a5e4, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec},
+       {0x0000a5e8, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec},
+       {0x0000a5ec, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec},
+       {0x0000a5f0, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec},
+       {0x0000a5f4, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec},
+       {0x0000a5f8, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec},
+       {0x0000a5fc, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec},
+       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+       {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
+       {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501},
+       {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03},
+       {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
+       {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04},
+       {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005},
+       {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+       {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+       {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x00016044, 0x056db2db, 0x056db2db, 0x03b6d2e4, 0x03b6d2e4},
+       {0x00016048, 0x24925666, 0x24925666, 0x8e481266, 0x8e481266},
+       {0x00016280, 0x01000015, 0x01000015, 0x01001015, 0x01001015},
+       {0x00016288, 0x30318000, 0x30318000, 0x00318000, 0x00318000},
+       {0x00016444, 0x056db2db, 0x056db2db, 0x03b6d2e4, 0x03b6d2e4},
+       {0x00016448, 0x24925666, 0x24925666, 0x8e481266, 0x8e481266},
+       {0x0000a3a4, 0x00000011, 0x00000011, 0x00000011, 0x00000011},
+       {0x0000a3a8, 0x3c3c3c3c, 0x3c3c3c3c, 0x3c3c3c3c, 0x3c3c3c3c},
+       {0x0000a3ac, 0x30303030, 0x30303030, 0x30303030, 0x30303030},
+};
+
 #endif /* INITVALS_9340_H */
index 092b9d412e7fd7f70b5f1996b94a66703325f830..1cc13569b17b8ed7126a9aae49a2d519c360337b 100644 (file)
 
 /* AR9462 2.0 */
 
-static const u32 ar9462_modes_fast_clock_2p0[][3] = {
+#define ar9462_2p0_mac_postamble ar9331_1p1_mac_postamble
+
+#define ar9462_2p0_common_wo_xlna_rx_gain ar9300Common_wo_xlna_rx_gain_table_2p2
+
+#define ar9462_2p0_common_5g_xlna_only_rxgain ar9462_2p0_common_mixed_rx_gain
+
+#define ar9462_2p0_baseband_core_txfir_coeff_japan_2484 ar9300_2p2_baseband_core_txfir_coeff_japan_2484
+
+static const u32 ar9462_2p0_modes_fast_clock[][3] = {
        /* Addr      5G_HT20     5G_HT40   */
        {0x00001030, 0x00000268, 0x000004d0},
        {0x00001070, 0x0000018c, 0x00000318},
@@ -33,13 +41,6 @@ static const u32 ar9462_modes_fast_clock_2p0[][3] = {
        {0x0000a254, 0x00000898, 0x00001130},
 };
 
-static const u32 ar9462_pciephy_clkreq_enable_L1_2p0[][2] = {
-       /* Addr      allmodes  */
-       {0x00018c00, 0x18253ede},
-       {0x00018c04, 0x000801d8},
-       {0x00018c08, 0x0003780c},
-};
-
 static const u32 ar9462_2p0_baseband_postamble[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
        {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a800d},
@@ -99,7 +100,7 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = {
        {0x0000b284, 0x00000000, 0x00000000, 0x00000550, 0x00000550},
 };
 
-static const u32 ar9462_common_rx_gain_table_2p0[][2] = {
+static const u32 ar9462_2p0_common_rx_gain[][2] = {
        /* Addr      allmodes  */
        {0x0000a000, 0x00010000},
        {0x0000a004, 0x00030002},
@@ -359,20 +360,13 @@ static const u32 ar9462_common_rx_gain_table_2p0[][2] = {
        {0x0000b1fc, 0x00000196},
 };
 
-static const u32 ar9462_pciephy_clkreq_disable_L1_2p0[][2] = {
+static const u32 ar9462_2p0_pciephy_clkreq_disable_L1[][2] = {
        /* Addr      allmodes  */
        {0x00018c00, 0x18213ede},
        {0x00018c04, 0x000801d8},
        {0x00018c08, 0x0003780c},
 };
 
-static const u32 ar9462_pciephy_pll_on_clkreq_disable_L1_2p0[][2] = {
-       /* Addr      allmodes  */
-       {0x00018c00, 0x18212ede},
-       {0x00018c04, 0x000801d8},
-       {0x00018c08, 0x0003780c},
-};
-
 static const u32 ar9462_2p0_radio_postamble_sys2ant[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
        {0x000160ac, 0xa4646c08, 0xa4646c08, 0x24645808, 0x24645808},
@@ -380,348 +374,81 @@ static const u32 ar9462_2p0_radio_postamble_sys2ant[][5] = {
        {0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
 };
 
-static const u32 ar9462_common_wo_xlna_rx_gain_table_2p0[][2] = {
-       /* Addr      allmodes  */
-       {0x0000a000, 0x00010000},
-       {0x0000a004, 0x00030002},
-       {0x0000a008, 0x00050004},
-       {0x0000a00c, 0x00810080},
-       {0x0000a010, 0x00830082},
-       {0x0000a014, 0x01810180},
-       {0x0000a018, 0x01830182},
-       {0x0000a01c, 0x01850184},
-       {0x0000a020, 0x01890188},
-       {0x0000a024, 0x018b018a},
-       {0x0000a028, 0x018d018c},
-       {0x0000a02c, 0x03820190},
-       {0x0000a030, 0x03840383},
-       {0x0000a034, 0x03880385},
-       {0x0000a038, 0x038a0389},
-       {0x0000a03c, 0x038c038b},
-       {0x0000a040, 0x0390038d},
-       {0x0000a044, 0x03920391},
-       {0x0000a048, 0x03940393},
-       {0x0000a04c, 0x03960395},
-       {0x0000a050, 0x00000000},
-       {0x0000a054, 0x00000000},
-       {0x0000a058, 0x00000000},
-       {0x0000a05c, 0x00000000},
-       {0x0000a060, 0x00000000},
-       {0x0000a064, 0x00000000},
-       {0x0000a068, 0x00000000},
-       {0x0000a06c, 0x00000000},
-       {0x0000a070, 0x00000000},
-       {0x0000a074, 0x00000000},
-       {0x0000a078, 0x00000000},
-       {0x0000a07c, 0x00000000},
-       {0x0000a080, 0x29292929},
-       {0x0000a084, 0x29292929},
-       {0x0000a088, 0x29292929},
-       {0x0000a08c, 0x29292929},
-       {0x0000a090, 0x22292929},
-       {0x0000a094, 0x1d1d2222},
-       {0x0000a098, 0x0c111117},
-       {0x0000a09c, 0x00030303},
-       {0x0000a0a0, 0x00000000},
-       {0x0000a0a4, 0x00000000},
-       {0x0000a0a8, 0x00000000},
-       {0x0000a0ac, 0x00000000},
-       {0x0000a0b0, 0x00000000},
-       {0x0000a0b4, 0x00000000},
-       {0x0000a0b8, 0x00000000},
-       {0x0000a0bc, 0x00000000},
-       {0x0000a0c0, 0x001f0000},
-       {0x0000a0c4, 0x01000101},
-       {0x0000a0c8, 0x011e011f},
-       {0x0000a0cc, 0x011c011d},
-       {0x0000a0d0, 0x02030204},
-       {0x0000a0d4, 0x02010202},
-       {0x0000a0d8, 0x021f0200},
-       {0x0000a0dc, 0x0302021e},
-       {0x0000a0e0, 0x03000301},
-       {0x0000a0e4, 0x031e031f},
-       {0x0000a0e8, 0x0402031d},
-       {0x0000a0ec, 0x04000401},
-       {0x0000a0f0, 0x041e041f},
-       {0x0000a0f4, 0x0502041d},
-       {0x0000a0f8, 0x05000501},
-       {0x0000a0fc, 0x051e051f},
-       {0x0000a100, 0x06010602},
-       {0x0000a104, 0x061f0600},
-       {0x0000a108, 0x061d061e},
-       {0x0000a10c, 0x07020703},
-       {0x0000a110, 0x07000701},
-       {0x0000a114, 0x00000000},
-       {0x0000a118, 0x00000000},
-       {0x0000a11c, 0x00000000},
-       {0x0000a120, 0x00000000},
-       {0x0000a124, 0x00000000},
-       {0x0000a128, 0x00000000},
-       {0x0000a12c, 0x00000000},
-       {0x0000a130, 0x00000000},
-       {0x0000a134, 0x00000000},
-       {0x0000a138, 0x00000000},
-       {0x0000a13c, 0x00000000},
-       {0x0000a140, 0x001f0000},
-       {0x0000a144, 0x01000101},
-       {0x0000a148, 0x011e011f},
-       {0x0000a14c, 0x011c011d},
-       {0x0000a150, 0x02030204},
-       {0x0000a154, 0x02010202},
-       {0x0000a158, 0x021f0200},
-       {0x0000a15c, 0x0302021e},
-       {0x0000a160, 0x03000301},
-       {0x0000a164, 0x031e031f},
-       {0x0000a168, 0x0402031d},
-       {0x0000a16c, 0x04000401},
-       {0x0000a170, 0x041e041f},
-       {0x0000a174, 0x0502041d},
-       {0x0000a178, 0x05000501},
-       {0x0000a17c, 0x051e051f},
-       {0x0000a180, 0x06010602},
-       {0x0000a184, 0x061f0600},
-       {0x0000a188, 0x061d061e},
-       {0x0000a18c, 0x07020703},
-       {0x0000a190, 0x07000701},
-       {0x0000a194, 0x00000000},
-       {0x0000a198, 0x00000000},
-       {0x0000a19c, 0x00000000},
-       {0x0000a1a0, 0x00000000},
-       {0x0000a1a4, 0x00000000},
-       {0x0000a1a8, 0x00000000},
-       {0x0000a1ac, 0x00000000},
-       {0x0000a1b0, 0x00000000},
-       {0x0000a1b4, 0x00000000},
-       {0x0000a1b8, 0x00000000},
-       {0x0000a1bc, 0x00000000},
-       {0x0000a1c0, 0x00000000},
-       {0x0000a1c4, 0x00000000},
-       {0x0000a1c8, 0x00000000},
-       {0x0000a1cc, 0x00000000},
-       {0x0000a1d0, 0x00000000},
-       {0x0000a1d4, 0x00000000},
-       {0x0000a1d8, 0x00000000},
-       {0x0000a1dc, 0x00000000},
-       {0x0000a1e0, 0x00000000},
-       {0x0000a1e4, 0x00000000},
-       {0x0000a1e8, 0x00000000},
-       {0x0000a1ec, 0x00000000},
-       {0x0000a1f0, 0x00000396},
-       {0x0000a1f4, 0x00000396},
-       {0x0000a1f8, 0x00000396},
-       {0x0000a1fc, 0x00000196},
-       {0x0000b000, 0x00010000},
-       {0x0000b004, 0x00030002},
-       {0x0000b008, 0x00050004},
-       {0x0000b00c, 0x00810080},
-       {0x0000b010, 0x00830082},
-       {0x0000b014, 0x01810180},
-       {0x0000b018, 0x01830182},
-       {0x0000b01c, 0x01850184},
-       {0x0000b020, 0x02810280},
-       {0x0000b024, 0x02830282},
-       {0x0000b028, 0x02850284},
-       {0x0000b02c, 0x02890288},
-       {0x0000b030, 0x028b028a},
-       {0x0000b034, 0x0388028c},
-       {0x0000b038, 0x038a0389},
-       {0x0000b03c, 0x038c038b},
-       {0x0000b040, 0x0390038d},
-       {0x0000b044, 0x03920391},
-       {0x0000b048, 0x03940393},
-       {0x0000b04c, 0x03960395},
-       {0x0000b050, 0x00000000},
-       {0x0000b054, 0x00000000},
-       {0x0000b058, 0x00000000},
-       {0x0000b05c, 0x00000000},
-       {0x0000b060, 0x00000000},
-       {0x0000b064, 0x00000000},
-       {0x0000b068, 0x00000000},
-       {0x0000b06c, 0x00000000},
-       {0x0000b070, 0x00000000},
-       {0x0000b074, 0x00000000},
-       {0x0000b078, 0x00000000},
-       {0x0000b07c, 0x00000000},
-       {0x0000b080, 0x32323232},
-       {0x0000b084, 0x2f2f3232},
-       {0x0000b088, 0x23282a2d},
-       {0x0000b08c, 0x1c1e2123},
-       {0x0000b090, 0x14171919},
-       {0x0000b094, 0x0e0e1214},
-       {0x0000b098, 0x03050707},
-       {0x0000b09c, 0x00030303},
-       {0x0000b0a0, 0x00000000},
-       {0x0000b0a4, 0x00000000},
-       {0x0000b0a8, 0x00000000},
-       {0x0000b0ac, 0x00000000},
-       {0x0000b0b0, 0x00000000},
-       {0x0000b0b4, 0x00000000},
-       {0x0000b0b8, 0x00000000},
-       {0x0000b0bc, 0x00000000},
-       {0x0000b0c0, 0x003f0020},
-       {0x0000b0c4, 0x00400041},
-       {0x0000b0c8, 0x0140005f},
-       {0x0000b0cc, 0x0160015f},
-       {0x0000b0d0, 0x017e017f},
-       {0x0000b0d4, 0x02410242},
-       {0x0000b0d8, 0x025f0240},
-       {0x0000b0dc, 0x027f0260},
-       {0x0000b0e0, 0x0341027e},
-       {0x0000b0e4, 0x035f0340},
-       {0x0000b0e8, 0x037f0360},
-       {0x0000b0ec, 0x04400441},
-       {0x0000b0f0, 0x0460045f},
-       {0x0000b0f4, 0x0541047f},
-       {0x0000b0f8, 0x055f0540},
-       {0x0000b0fc, 0x057f0560},
-       {0x0000b100, 0x06400641},
-       {0x0000b104, 0x0660065f},
-       {0x0000b108, 0x067e067f},
-       {0x0000b10c, 0x07410742},
-       {0x0000b110, 0x075f0740},
-       {0x0000b114, 0x077f0760},
-       {0x0000b118, 0x07800781},
-       {0x0000b11c, 0x07a0079f},
-       {0x0000b120, 0x07c107bf},
-       {0x0000b124, 0x000007c0},
-       {0x0000b128, 0x00000000},
-       {0x0000b12c, 0x00000000},
-       {0x0000b130, 0x00000000},
-       {0x0000b134, 0x00000000},
-       {0x0000b138, 0x00000000},
-       {0x0000b13c, 0x00000000},
-       {0x0000b140, 0x003f0020},
-       {0x0000b144, 0x00400041},
-       {0x0000b148, 0x0140005f},
-       {0x0000b14c, 0x0160015f},
-       {0x0000b150, 0x017e017f},
-       {0x0000b154, 0x02410242},
-       {0x0000b158, 0x025f0240},
-       {0x0000b15c, 0x027f0260},
-       {0x0000b160, 0x0341027e},
-       {0x0000b164, 0x035f0340},
-       {0x0000b168, 0x037f0360},
-       {0x0000b16c, 0x04400441},
-       {0x0000b170, 0x0460045f},
-       {0x0000b174, 0x0541047f},
-       {0x0000b178, 0x055f0540},
-       {0x0000b17c, 0x057f0560},
-       {0x0000b180, 0x06400641},
-       {0x0000b184, 0x0660065f},
-       {0x0000b188, 0x067e067f},
-       {0x0000b18c, 0x07410742},
-       {0x0000b190, 0x075f0740},
-       {0x0000b194, 0x077f0760},
-       {0x0000b198, 0x07800781},
-       {0x0000b19c, 0x07a0079f},
-       {0x0000b1a0, 0x07c107bf},
-       {0x0000b1a4, 0x000007c0},
-       {0x0000b1a8, 0x00000000},
-       {0x0000b1ac, 0x00000000},
-       {0x0000b1b0, 0x00000000},
-       {0x0000b1b4, 0x00000000},
-       {0x0000b1b8, 0x00000000},
-       {0x0000b1bc, 0x00000000},
-       {0x0000b1c0, 0x00000000},
-       {0x0000b1c4, 0x00000000},
-       {0x0000b1c8, 0x00000000},
-       {0x0000b1cc, 0x00000000},
-       {0x0000b1d0, 0x00000000},
-       {0x0000b1d4, 0x00000000},
-       {0x0000b1d8, 0x00000000},
-       {0x0000b1dc, 0x00000000},
-       {0x0000b1e0, 0x00000000},
-       {0x0000b1e4, 0x00000000},
-       {0x0000b1e8, 0x00000000},
-       {0x0000b1ec, 0x00000000},
-       {0x0000b1f0, 0x00000396},
-       {0x0000b1f4, 0x00000396},
-       {0x0000b1f8, 0x00000396},
-       {0x0000b1fc, 0x00000196},
-};
-
-static const u32 ar9462_2p0_baseband_core_txfir_coeff_japan_2484[][2] = {
-       /* Addr      allmodes  */
-       {0x0000a398, 0x00000000},
-       {0x0000a39c, 0x6f7f0301},
-       {0x0000a3a0, 0xca9228ee},
-};
-
-static const u32 ar9462_modes_low_ob_db_tx_gain_table_2p0[][5] = {
-       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-       {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
-       {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
-       {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
-       {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
-       {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
-       {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
-       {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
-       {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
-       {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
-       {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
-       {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400},
-       {0x0000a518, 0x21020220, 0x21020220, 0x16000402, 0x16000402},
-       {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404},
-       {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603},
-       {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02},
-       {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04},
-       {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20},
-       {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20},
-       {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22},
-       {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
-       {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
-       {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
-       {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861},
-       {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81},
-       {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x47001a83, 0x47001a83},
-       {0x0000a550, 0x61042a6c, 0x61042a6c, 0x4a001c84, 0x4a001c84},
-       {0x0000a554, 0x66062a6c, 0x66062a6c, 0x4e001ce3, 0x4e001ce3},
-       {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x52001ce5, 0x52001ce5},
-       {0x0000a55c, 0x7006308c, 0x7006308c, 0x56001ce9, 0x56001ce9},
-       {0x0000a560, 0x730a308a, 0x730a308a, 0x5a001ceb, 0x5a001ceb},
-       {0x0000a564, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
-       {0x0000a568, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
-       {0x0000a56c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
-       {0x0000a570, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
-       {0x0000a574, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
-       {0x0000a578, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
-       {0x0000a57c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
-       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
-       {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
-       {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501},
-       {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03},
-       {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
-       {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04},
-       {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005},
-       {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
-       {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
-       {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
-       {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
-       {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
-       {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
-       {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
-       {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
-       {0x00016044, 0x012482d4, 0x012482d4, 0x012482d4, 0x012482d4},
-       {0x00016048, 0x64992060, 0x64992060, 0x64992060, 0x64992060},
-       {0x00016054, 0x6db60000, 0x6db60000, 0x6db60000, 0x6db60000},
-       {0x00016444, 0x012482d4, 0x012482d4, 0x012482d4, 0x012482d4},
-       {0x00016448, 0x64992000, 0x64992000, 0x64992000, 0x64992000},
-       {0x00016454, 0x6db60000, 0x6db60000, 0x6db60000, 0x6db60000},
-};
-
-static const u32 ar9462_2p0_soc_postamble[][5] = {
-       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-       {0x00007010, 0x00000033, 0x00000033, 0x00000033, 0x00000033},
-};
-
-static const u32 ar9462_2p0_baseband_core[][2] = {
+static const u32 ar9462_2p0_modes_low_ob_db_tx_gain[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
+       {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+       {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+       {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+       {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
+       {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
+       {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
+       {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400},
+       {0x0000a518, 0x21020220, 0x21020220, 0x16000402, 0x16000402},
+       {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404},
+       {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603},
+       {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02},
+       {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04},
+       {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20},
+       {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20},
+       {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22},
+       {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
+       {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
+       {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
+       {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861},
+       {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81},
+       {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x47001a83, 0x47001a83},
+       {0x0000a550, 0x61042a6c, 0x61042a6c, 0x4a001c84, 0x4a001c84},
+       {0x0000a554, 0x66062a6c, 0x66062a6c, 0x4e001ce3, 0x4e001ce3},
+       {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x52001ce5, 0x52001ce5},
+       {0x0000a55c, 0x7006308c, 0x7006308c, 0x56001ce9, 0x56001ce9},
+       {0x0000a560, 0x730a308a, 0x730a308a, 0x5a001ceb, 0x5a001ceb},
+       {0x0000a564, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+       {0x0000a568, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+       {0x0000a56c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+       {0x0000a570, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+       {0x0000a574, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+       {0x0000a578, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+       {0x0000a57c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
+       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+       {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
+       {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501},
+       {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03},
+       {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
+       {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04},
+       {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005},
+       {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
+       {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
+       {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
+       {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
+       {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x00016044, 0x012482d4, 0x012482d4, 0x012482d4, 0x012482d4},
+       {0x00016048, 0x64992060, 0x64992060, 0x64992060, 0x64992060},
+       {0x00016054, 0x6db60000, 0x6db60000, 0x6db60000, 0x6db60000},
+       {0x00016444, 0x012482d4, 0x012482d4, 0x012482d4, 0x012482d4},
+       {0x00016448, 0x64992000, 0x64992000, 0x64992000, 0x64992000},
+       {0x00016454, 0x6db60000, 0x6db60000, 0x6db60000, 0x6db60000},
+};
+
+static const u32 ar9462_2p0_soc_postamble[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x00007010, 0x00000033, 0x00000033, 0x00000033, 0x00000033},
+};
+
+static const u32 ar9462_2p0_baseband_core[][2] = {
        /* Addr      allmodes  */
        {0x00009800, 0xafe68e30},
        {0x00009804, 0xfd14e000},
@@ -879,7 +606,7 @@ static const u32 ar9462_2p0_radio_postamble[][5] = {
        {0x0001650c, 0x48000000, 0x40000000, 0x40000000, 0x40000000},
 };
 
-static const u32 ar9462_modes_mix_ob_db_tx_gain_table_2p0[][5] = {
+static const u32 ar9462_2p0_modes_mix_ob_db_tx_gain[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
        {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
        {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
@@ -942,7 +669,7 @@ static const u32 ar9462_modes_mix_ob_db_tx_gain_table_2p0[][5] = {
        {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
 };
 
-static const u32 ar9462_modes_high_ob_db_tx_gain_table_2p0[][5] = {
+static const u32 ar9462_2p0_modes_high_ob_db_tx_gain[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
        {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
        {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
@@ -1240,19 +967,7 @@ static const u32 ar9462_2p0_mac_core[][2] = {
        {0x000083d0, 0x000301ff},
 };
 
-static const u32 ar9462_2p0_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 ar9462_common_mixed_rx_gain_table_2p0[][2] = {
+static const u32 ar9462_2p0_common_mixed_rx_gain[][2] = {
        /* Addr      allmodes  */
        {0x0000a000, 0x00010000},
        {0x0000a004, 0x00030002},
@@ -1517,266 +1232,6 @@ static const u32 ar9462_2p0_baseband_postamble_5g_xlna[][5] = {
        {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282},
 };
 
-static const u32 ar9462_2p0_5g_xlna_only_rxgain[][2] = {
-       /* Addr      allmodes  */
-       {0x0000a000, 0x00010000},
-       {0x0000a004, 0x00030002},
-       {0x0000a008, 0x00050004},
-       {0x0000a00c, 0x00810080},
-       {0x0000a010, 0x00830082},
-       {0x0000a014, 0x01810180},
-       {0x0000a018, 0x01830182},
-       {0x0000a01c, 0x01850184},
-       {0x0000a020, 0x01890188},
-       {0x0000a024, 0x018b018a},
-       {0x0000a028, 0x018d018c},
-       {0x0000a02c, 0x03820190},
-       {0x0000a030, 0x03840383},
-       {0x0000a034, 0x03880385},
-       {0x0000a038, 0x038a0389},
-       {0x0000a03c, 0x038c038b},
-       {0x0000a040, 0x0390038d},
-       {0x0000a044, 0x03920391},
-       {0x0000a048, 0x03940393},
-       {0x0000a04c, 0x03960395},
-       {0x0000a050, 0x00000000},
-       {0x0000a054, 0x00000000},
-       {0x0000a058, 0x00000000},
-       {0x0000a05c, 0x00000000},
-       {0x0000a060, 0x00000000},
-       {0x0000a064, 0x00000000},
-       {0x0000a068, 0x00000000},
-       {0x0000a06c, 0x00000000},
-       {0x0000a070, 0x00000000},
-       {0x0000a074, 0x00000000},
-       {0x0000a078, 0x00000000},
-       {0x0000a07c, 0x00000000},
-       {0x0000a080, 0x29292929},
-       {0x0000a084, 0x29292929},
-       {0x0000a088, 0x29292929},
-       {0x0000a08c, 0x29292929},
-       {0x0000a090, 0x22292929},
-       {0x0000a094, 0x1d1d2222},
-       {0x0000a098, 0x0c111117},
-       {0x0000a09c, 0x00030303},
-       {0x0000a0a0, 0x00000000},
-       {0x0000a0a4, 0x00000000},
-       {0x0000a0a8, 0x00000000},
-       {0x0000a0ac, 0x00000000},
-       {0x0000a0b0, 0x00000000},
-       {0x0000a0b4, 0x00000000},
-       {0x0000a0b8, 0x00000000},
-       {0x0000a0bc, 0x00000000},
-       {0x0000a0c0, 0x001f0000},
-       {0x0000a0c4, 0x01000101},
-       {0x0000a0c8, 0x011e011f},
-       {0x0000a0cc, 0x011c011d},
-       {0x0000a0d0, 0x02030204},
-       {0x0000a0d4, 0x02010202},
-       {0x0000a0d8, 0x021f0200},
-       {0x0000a0dc, 0x0302021e},
-       {0x0000a0e0, 0x03000301},
-       {0x0000a0e4, 0x031e031f},
-       {0x0000a0e8, 0x0402031d},
-       {0x0000a0ec, 0x04000401},
-       {0x0000a0f0, 0x041e041f},
-       {0x0000a0f4, 0x0502041d},
-       {0x0000a0f8, 0x05000501},
-       {0x0000a0fc, 0x051e051f},
-       {0x0000a100, 0x06010602},
-       {0x0000a104, 0x061f0600},
-       {0x0000a108, 0x061d061e},
-       {0x0000a10c, 0x07020703},
-       {0x0000a110, 0x07000701},
-       {0x0000a114, 0x00000000},
-       {0x0000a118, 0x00000000},
-       {0x0000a11c, 0x00000000},
-       {0x0000a120, 0x00000000},
-       {0x0000a124, 0x00000000},
-       {0x0000a128, 0x00000000},
-       {0x0000a12c, 0x00000000},
-       {0x0000a130, 0x00000000},
-       {0x0000a134, 0x00000000},
-       {0x0000a138, 0x00000000},
-       {0x0000a13c, 0x00000000},
-       {0x0000a140, 0x001f0000},
-       {0x0000a144, 0x01000101},
-       {0x0000a148, 0x011e011f},
-       {0x0000a14c, 0x011c011d},
-       {0x0000a150, 0x02030204},
-       {0x0000a154, 0x02010202},
-       {0x0000a158, 0x021f0200},
-       {0x0000a15c, 0x0302021e},
-       {0x0000a160, 0x03000301},
-       {0x0000a164, 0x031e031f},
-       {0x0000a168, 0x0402031d},
-       {0x0000a16c, 0x04000401},
-       {0x0000a170, 0x041e041f},
-       {0x0000a174, 0x0502041d},
-       {0x0000a178, 0x05000501},
-       {0x0000a17c, 0x051e051f},
-       {0x0000a180, 0x06010602},
-       {0x0000a184, 0x061f0600},
-       {0x0000a188, 0x061d061e},
-       {0x0000a18c, 0x07020703},
-       {0x0000a190, 0x07000701},
-       {0x0000a194, 0x00000000},
-       {0x0000a198, 0x00000000},
-       {0x0000a19c, 0x00000000},
-       {0x0000a1a0, 0x00000000},
-       {0x0000a1a4, 0x00000000},
-       {0x0000a1a8, 0x00000000},
-       {0x0000a1ac, 0x00000000},
-       {0x0000a1b0, 0x00000000},
-       {0x0000a1b4, 0x00000000},
-       {0x0000a1b8, 0x00000000},
-       {0x0000a1bc, 0x00000000},
-       {0x0000a1c0, 0x00000000},
-       {0x0000a1c4, 0x00000000},
-       {0x0000a1c8, 0x00000000},
-       {0x0000a1cc, 0x00000000},
-       {0x0000a1d0, 0x00000000},
-       {0x0000a1d4, 0x00000000},
-       {0x0000a1d8, 0x00000000},
-       {0x0000a1dc, 0x00000000},
-       {0x0000a1e0, 0x00000000},
-       {0x0000a1e4, 0x00000000},
-       {0x0000a1e8, 0x00000000},
-       {0x0000a1ec, 0x00000000},
-       {0x0000a1f0, 0x00000396},
-       {0x0000a1f4, 0x00000396},
-       {0x0000a1f8, 0x00000396},
-       {0x0000a1fc, 0x00000196},
-       {0x0000b000, 0x00010000},
-       {0x0000b004, 0x00030002},
-       {0x0000b008, 0x00050004},
-       {0x0000b00c, 0x00810080},
-       {0x0000b010, 0x00830082},
-       {0x0000b014, 0x01810180},
-       {0x0000b018, 0x01830182},
-       {0x0000b01c, 0x01850184},
-       {0x0000b020, 0x02810280},
-       {0x0000b024, 0x02830282},
-       {0x0000b028, 0x02850284},
-       {0x0000b02c, 0x02890288},
-       {0x0000b030, 0x028b028a},
-       {0x0000b034, 0x0388028c},
-       {0x0000b038, 0x038a0389},
-       {0x0000b03c, 0x038c038b},
-       {0x0000b040, 0x0390038d},
-       {0x0000b044, 0x03920391},
-       {0x0000b048, 0x03940393},
-       {0x0000b04c, 0x03960395},
-       {0x0000b050, 0x00000000},
-       {0x0000b054, 0x00000000},
-       {0x0000b058, 0x00000000},
-       {0x0000b05c, 0x00000000},
-       {0x0000b060, 0x00000000},
-       {0x0000b064, 0x00000000},
-       {0x0000b068, 0x00000000},
-       {0x0000b06c, 0x00000000},
-       {0x0000b070, 0x00000000},
-       {0x0000b074, 0x00000000},
-       {0x0000b078, 0x00000000},
-       {0x0000b07c, 0x00000000},
-       {0x0000b080, 0x2a2d2f32},
-       {0x0000b084, 0x21232328},
-       {0x0000b088, 0x19191c1e},
-       {0x0000b08c, 0x12141417},
-       {0x0000b090, 0x07070e0e},
-       {0x0000b094, 0x03030305},
-       {0x0000b098, 0x00000003},
-       {0x0000b09c, 0x00000000},
-       {0x0000b0a0, 0x00000000},
-       {0x0000b0a4, 0x00000000},
-       {0x0000b0a8, 0x00000000},
-       {0x0000b0ac, 0x00000000},
-       {0x0000b0b0, 0x00000000},
-       {0x0000b0b4, 0x00000000},
-       {0x0000b0b8, 0x00000000},
-       {0x0000b0bc, 0x00000000},
-       {0x0000b0c0, 0x003f0020},
-       {0x0000b0c4, 0x00400041},
-       {0x0000b0c8, 0x0140005f},
-       {0x0000b0cc, 0x0160015f},
-       {0x0000b0d0, 0x017e017f},
-       {0x0000b0d4, 0x02410242},
-       {0x0000b0d8, 0x025f0240},
-       {0x0000b0dc, 0x027f0260},
-       {0x0000b0e0, 0x0341027e},
-       {0x0000b0e4, 0x035f0340},
-       {0x0000b0e8, 0x037f0360},
-       {0x0000b0ec, 0x04400441},
-       {0x0000b0f0, 0x0460045f},
-       {0x0000b0f4, 0x0541047f},
-       {0x0000b0f8, 0x055f0540},
-       {0x0000b0fc, 0x057f0560},
-       {0x0000b100, 0x06400641},
-       {0x0000b104, 0x0660065f},
-       {0x0000b108, 0x067e067f},
-       {0x0000b10c, 0x07410742},
-       {0x0000b110, 0x075f0740},
-       {0x0000b114, 0x077f0760},
-       {0x0000b118, 0x07800781},
-       {0x0000b11c, 0x07a0079f},
-       {0x0000b120, 0x07c107bf},
-       {0x0000b124, 0x000007c0},
-       {0x0000b128, 0x00000000},
-       {0x0000b12c, 0x00000000},
-       {0x0000b130, 0x00000000},
-       {0x0000b134, 0x00000000},
-       {0x0000b138, 0x00000000},
-       {0x0000b13c, 0x00000000},
-       {0x0000b140, 0x003f0020},
-       {0x0000b144, 0x00400041},
-       {0x0000b148, 0x0140005f},
-       {0x0000b14c, 0x0160015f},
-       {0x0000b150, 0x017e017f},
-       {0x0000b154, 0x02410242},
-       {0x0000b158, 0x025f0240},
-       {0x0000b15c, 0x027f0260},
-       {0x0000b160, 0x0341027e},
-       {0x0000b164, 0x035f0340},
-       {0x0000b168, 0x037f0360},
-       {0x0000b16c, 0x04400441},
-       {0x0000b170, 0x0460045f},
-       {0x0000b174, 0x0541047f},
-       {0x0000b178, 0x055f0540},
-       {0x0000b17c, 0x057f0560},
-       {0x0000b180, 0x06400641},
-       {0x0000b184, 0x0660065f},
-       {0x0000b188, 0x067e067f},
-       {0x0000b18c, 0x07410742},
-       {0x0000b190, 0x075f0740},
-       {0x0000b194, 0x077f0760},
-       {0x0000b198, 0x07800781},
-       {0x0000b19c, 0x07a0079f},
-       {0x0000b1a0, 0x07c107bf},
-       {0x0000b1a4, 0x000007c0},
-       {0x0000b1a8, 0x00000000},
-       {0x0000b1ac, 0x00000000},
-       {0x0000b1b0, 0x00000000},
-       {0x0000b1b4, 0x00000000},
-       {0x0000b1b8, 0x00000000},
-       {0x0000b1bc, 0x00000000},
-       {0x0000b1c0, 0x00000000},
-       {0x0000b1c4, 0x00000000},
-       {0x0000b1c8, 0x00000000},
-       {0x0000b1cc, 0x00000000},
-       {0x0000b1d0, 0x00000000},
-       {0x0000b1d4, 0x00000000},
-       {0x0000b1d8, 0x00000000},
-       {0x0000b1dc, 0x00000000},
-       {0x0000b1e0, 0x00000000},
-       {0x0000b1e4, 0x00000000},
-       {0x0000b1e8, 0x00000000},
-       {0x0000b1ec, 0x00000000},
-       {0x0000b1f0, 0x00000396},
-       {0x0000b1f4, 0x00000396},
-       {0x0000b1f8, 0x00000396},
-       {0x0000b1fc, 0x00000196},
-};
-
 static const u32 ar9462_2p0_baseband_core_mix_rxgain[][2] = {
        /* Addr      allmodes  */
        {0x00009fd0, 0x0a2d6b93},
index 57fc5f459d0aa6a40719407b8c287ac7f3786d00..dc3adda46e8b92700ee1c274ba734fc2c4ec7a4f 100644 (file)
 
 /* AR9462 2.1 */
 
+#define ar9462_2p1_mac_postamble ar9462_2p0_mac_postamble
+
+#define ar9462_2p1_baseband_core ar9462_2p0_baseband_core
+
+#define ar9462_2p1_radio_core ar9462_2p0_radio_core
+
+#define ar9462_2p1_radio_postamble ar9462_2p0_radio_postamble
+
+#define ar9462_2p1_soc_postamble ar9462_2p0_soc_postamble
+
+#define ar9462_2p1_radio_postamble_sys2ant ar9462_2p0_radio_postamble_sys2ant
+
+#define ar9462_2p1_common_rx_gain ar9462_2p0_common_rx_gain
+
+#define ar9462_2p1_common_mixed_rx_gain ar9462_2p0_common_mixed_rx_gain
+
+#define ar9462_2p1_common_5g_xlna_only_rxgain ar9462_2p0_common_5g_xlna_only_rxgain
+
+#define ar9462_2p1_baseband_core_mix_rxgain ar9462_2p0_baseband_core_mix_rxgain
+
+#define ar9462_2p1_baseband_postamble_mix_rxgain ar9462_2p0_baseband_postamble_mix_rxgain
+
+#define ar9462_2p1_baseband_postamble_5g_xlna ar9462_2p0_baseband_postamble_5g_xlna
+
+#define ar9462_2p1_common_wo_xlna_rx_gain ar9462_2p0_common_wo_xlna_rx_gain
+
+#define ar9462_2p1_modes_low_ob_db_tx_gain ar9462_2p0_modes_low_ob_db_tx_gain
+
+#define ar9462_2p1_modes_high_ob_db_tx_gain ar9462_2p0_modes_high_ob_db_tx_gain
+
+#define ar9462_2p1_modes_mix_ob_db_tx_gain ar9462_2p0_modes_mix_ob_db_tx_gain
+
+#define ar9462_2p1_modes_fast_clock ar9462_2p0_modes_fast_clock
+
+#define ar9462_2p1_baseband_core_txfir_coeff_japan_2484 ar9462_2p0_baseband_core_txfir_coeff_japan_2484
+
+#define ar9462_2p1_pciephy_clkreq_disable_L1 ar9462_2p0_pciephy_clkreq_disable_L1
+
 static const u32 ar9462_2p1_mac_core[][2] = {
        /* Addr      allmodes  */
        {0x00000008, 0x00000000},
@@ -183,168 +221,6 @@ static const u32 ar9462_2p1_mac_core[][2] = {
        {0x000083d0, 0x000301ff},
 };
 
-static const u32 ar9462_2p1_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 ar9462_2p1_baseband_core[][2] = {
-       /* Addr      allmodes  */
-       {0x00009800, 0xafe68e30},
-       {0x00009804, 0xfd14e000},
-       {0x00009808, 0x9c0a9f6b},
-       {0x0000980c, 0x04900000},
-       {0x00009814, 0x9280c00a},
-       {0x00009818, 0x00000000},
-       {0x0000981c, 0x00020028},
-       {0x00009834, 0x6400a290},
-       {0x00009838, 0x0108ecff},
-       {0x0000983c, 0x0d000600},
-       {0x00009880, 0x201fff00},
-       {0x00009884, 0x00001042},
-       {0x000098a4, 0x00200400},
-       {0x000098b0, 0x32440bbe},
-       {0x000098d0, 0x004b6a8e},
-       {0x000098d4, 0x00000820},
-       {0x000098dc, 0x00000000},
-       {0x000098e4, 0x01ffffff},
-       {0x000098e8, 0x01ffffff},
-       {0x000098ec, 0x01ffffff},
-       {0x000098f0, 0x00000000},
-       {0x000098f4, 0x00000000},
-       {0x00009bf0, 0x80000000},
-       {0x00009c04, 0xff55ff55},
-       {0x00009c08, 0x0320ff55},
-       {0x00009c0c, 0x00000000},
-       {0x00009c10, 0x00000000},
-       {0x00009c14, 0x00046384},
-       {0x00009c18, 0x05b6b440},
-       {0x00009c1c, 0x00b6b440},
-       {0x00009d00, 0xc080a333},
-       {0x00009d04, 0x40206c10},
-       {0x00009d08, 0x009c4060},
-       {0x00009d0c, 0x9883800a},
-       {0x00009d10, 0x01834061},
-       {0x00009d14, 0x00c0040b},
-       {0x00009d18, 0x00000000},
-       {0x00009e08, 0x0038230c},
-       {0x00009e24, 0x990bb515},
-       {0x00009e28, 0x0c6f0000},
-       {0x00009e30, 0x06336f77},
-       {0x00009e34, 0x6af6532f},
-       {0x00009e38, 0x0cc80c00},
-       {0x00009e40, 0x15262820},
-       {0x00009e4c, 0x00001004},
-       {0x00009e50, 0x00ff03f1},
-       {0x00009e54, 0xe4c555c2},
-       {0x00009e58, 0xfd857722},
-       {0x00009e5c, 0xe9198724},
-       {0x00009fc0, 0x803e4788},
-       {0x00009fc4, 0x0001efb5},
-       {0x00009fcc, 0x40000014},
-       {0x00009fd0, 0x0a193b93},
-       {0x0000a20c, 0x00000000},
-       {0x0000a220, 0x00000000},
-       {0x0000a224, 0x00000000},
-       {0x0000a228, 0x10002310},
-       {0x0000a23c, 0x00000000},
-       {0x0000a244, 0x0c000000},
-       {0x0000a2a0, 0x00000001},
-       {0x0000a2c0, 0x00000001},
-       {0x0000a2c8, 0x00000000},
-       {0x0000a2cc, 0x18c43433},
-       {0x0000a2d4, 0x00000000},
-       {0x0000a2ec, 0x00000000},
-       {0x0000a2f0, 0x00000000},
-       {0x0000a2f4, 0x00000000},
-       {0x0000a2f8, 0x00000000},
-       {0x0000a344, 0x00000000},
-       {0x0000a34c, 0x00000000},
-       {0x0000a350, 0x0000a000},
-       {0x0000a364, 0x00000000},
-       {0x0000a370, 0x00000000},
-       {0x0000a390, 0x00000001},
-       {0x0000a394, 0x00000444},
-       {0x0000a398, 0x001f0e0f},
-       {0x0000a39c, 0x0075393f},
-       {0x0000a3a0, 0xb79f6427},
-       {0x0000a3c0, 0x20202020},
-       {0x0000a3c4, 0x22222220},
-       {0x0000a3c8, 0x20200020},
-       {0x0000a3cc, 0x20202020},
-       {0x0000a3d0, 0x20202020},
-       {0x0000a3d4, 0x20202020},
-       {0x0000a3d8, 0x20202020},
-       {0x0000a3dc, 0x20202020},
-       {0x0000a3e0, 0x20202020},
-       {0x0000a3e4, 0x20202020},
-       {0x0000a3e8, 0x20202020},
-       {0x0000a3ec, 0x20202020},
-       {0x0000a3f0, 0x00000000},
-       {0x0000a3f4, 0x00000006},
-       {0x0000a3f8, 0x0c9bd380},
-       {0x0000a3fc, 0x000f0f01},
-       {0x0000a400, 0x8fa91f01},
-       {0x0000a404, 0x00000000},
-       {0x0000a408, 0x0e79e5c6},
-       {0x0000a40c, 0x00820820},
-       {0x0000a414, 0x1ce739ce},
-       {0x0000a418, 0x2d001dce},
-       {0x0000a434, 0x00000000},
-       {0x0000a438, 0x00001801},
-       {0x0000a43c, 0x00100000},
-       {0x0000a444, 0x00000000},
-       {0x0000a448, 0x05000080},
-       {0x0000a44c, 0x00000001},
-       {0x0000a450, 0x00010000},
-       {0x0000a454, 0x07000000},
-       {0x0000a644, 0xbfad9d74},
-       {0x0000a648, 0x0048060a},
-       {0x0000a64c, 0x00002037},
-       {0x0000a670, 0x03020100},
-       {0x0000a674, 0x09080504},
-       {0x0000a678, 0x0d0c0b0a},
-       {0x0000a67c, 0x13121110},
-       {0x0000a680, 0x31301514},
-       {0x0000a684, 0x35343332},
-       {0x0000a688, 0x00000036},
-       {0x0000a690, 0x00000838},
-       {0x0000a6b0, 0x0000000a},
-       {0x0000a6b4, 0x00512c01},
-       {0x0000a7c0, 0x00000000},
-       {0x0000a7c4, 0xfffffffc},
-       {0x0000a7c8, 0x00000000},
-       {0x0000a7cc, 0x00000000},
-       {0x0000a7d0, 0x00000000},
-       {0x0000a7d4, 0x00000004},
-       {0x0000a7dc, 0x00000000},
-       {0x0000a7f0, 0x80000000},
-       {0x0000a8d0, 0x004b6a8e},
-       {0x0000a8d4, 0x00000820},
-       {0x0000a8dc, 0x00000000},
-       {0x0000a8f0, 0x00000000},
-       {0x0000a8f4, 0x00000000},
-       {0x0000abf0, 0x80000000},
-       {0x0000b2d0, 0x00000080},
-       {0x0000b2d4, 0x00000000},
-       {0x0000b2ec, 0x00000000},
-       {0x0000b2f0, 0x00000000},
-       {0x0000b2f4, 0x00000000},
-       {0x0000b2f8, 0x00000000},
-       {0x0000b408, 0x0e79e5c0},
-       {0x0000b40c, 0x00820820},
-       {0x0000b420, 0x00000000},
-       {0x0000b6b0, 0x0000000a},
-       {0x0000b6b4, 0x00000001},
-};
-
 static const u32 ar9462_2p1_baseband_postamble[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
        {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a800d},
@@ -404,72 +280,6 @@ static const u32 ar9462_2p1_baseband_postamble[][5] = {
        {0x0000b284, 0x00000000, 0x00000000, 0x00000550, 0x00000550},
 };
 
-static const u32 ar9462_2p1_radio_core[][2] = {
-       /* Addr      allmodes  */
-       {0x00016000, 0x36db6db6},
-       {0x00016004, 0x6db6db40},
-       {0x00016008, 0x73f00000},
-       {0x0001600c, 0x00000000},
-       {0x00016010, 0x6d820001},
-       {0x00016040, 0x7f80fff8},
-       {0x0001604c, 0x2699e04f},
-       {0x00016050, 0x6db6db6c},
-       {0x00016058, 0x6c200000},
-       {0x00016080, 0x000c0000},
-       {0x00016084, 0x9a68048c},
-       {0x00016088, 0x54214514},
-       {0x0001608c, 0x1203040b},
-       {0x00016090, 0x24926490},
-       {0x00016098, 0xd2888888},
-       {0x000160a0, 0x0a108ffe},
-       {0x000160a4, 0x812fc491},
-       {0x000160a8, 0x423c8000},
-       {0x000160b4, 0x92000000},
-       {0x000160b8, 0x0285dddc},
-       {0x000160bc, 0x02908888},
-       {0x000160c0, 0x00adb6d0},
-       {0x000160c4, 0x6db6db60},
-       {0x000160c8, 0x6db6db6c},
-       {0x000160cc, 0x0de6c1b0},
-       {0x00016100, 0x3fffbe04},
-       {0x00016104, 0xfff80000},
-       {0x00016108, 0x00200400},
-       {0x00016110, 0x00000000},
-       {0x00016144, 0x02084080},
-       {0x00016148, 0x000080c0},
-       {0x00016280, 0x050a0001},
-       {0x00016284, 0x3d841418},
-       {0x00016288, 0x00000000},
-       {0x0001628c, 0xe3000000},
-       {0x00016290, 0xa1005080},
-       {0x00016294, 0x00000020},
-       {0x00016298, 0x54a82900},
-       {0x00016340, 0x121e4276},
-       {0x00016344, 0x00300000},
-       {0x00016400, 0x36db6db6},
-       {0x00016404, 0x6db6db40},
-       {0x00016408, 0x73f00000},
-       {0x0001640c, 0x00000000},
-       {0x00016410, 0x6c800001},
-       {0x00016440, 0x7f80fff8},
-       {0x0001644c, 0x4699e04f},
-       {0x00016450, 0x6db6db6c},
-       {0x00016500, 0x3fffbe04},
-       {0x00016504, 0xfff80000},
-       {0x00016508, 0x00200400},
-       {0x00016510, 0x00000000},
-       {0x00016544, 0x02084080},
-       {0x00016548, 0x000080c0},
-};
-
-static const u32 ar9462_2p1_radio_postamble[][5] = {
-       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-       {0x0001609c, 0x0b8ee524, 0x0b8ee524, 0x0b8ee524, 0x0b8ee524},
-       {0x000160b0, 0x01d67f70, 0x01d67f70, 0x01d67f70, 0x01d67f70},
-       {0x0001610c, 0x48000000, 0x40000000, 0x40000000, 0x40000000},
-       {0x0001650c, 0x48000000, 0x40000000, 0x40000000, 0x40000000},
-};
-
 static const u32 ar9462_2p1_soc_preamble[][2] = {
        /* Addr      allmodes  */
        {0x000040a4, 0x00a0c9c9},
@@ -478,1297 +288,4 @@ static const u32 ar9462_2p1_soc_preamble[][2] = {
        {0x00007038, 0x000004c2},
 };
 
-static const u32 ar9462_2p1_soc_postamble[][5] = {
-       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-       {0x00007010, 0x00000033, 0x00000033, 0x00000033, 0x00000033},
-};
-
-static const u32 ar9462_2p1_radio_postamble_sys2ant[][5] = {
-       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-       {0x000160ac, 0xa4646c08, 0xa4646c08, 0x24645808, 0x24645808},
-       {0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
-       {0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
-};
-
-static const u32 ar9462_2p1_common_rx_gain[][2] = {
-       /* Addr      allmodes  */
-       {0x0000a000, 0x00010000},
-       {0x0000a004, 0x00030002},
-       {0x0000a008, 0x00050004},
-       {0x0000a00c, 0x00810080},
-       {0x0000a010, 0x00830082},
-       {0x0000a014, 0x01810180},
-       {0x0000a018, 0x01830182},
-       {0x0000a01c, 0x01850184},
-       {0x0000a020, 0x01890188},
-       {0x0000a024, 0x018b018a},
-       {0x0000a028, 0x018d018c},
-       {0x0000a02c, 0x01910190},
-       {0x0000a030, 0x01930192},
-       {0x0000a034, 0x01950194},
-       {0x0000a038, 0x038a0196},
-       {0x0000a03c, 0x038c038b},
-       {0x0000a040, 0x0390038d},
-       {0x0000a044, 0x03920391},
-       {0x0000a048, 0x03940393},
-       {0x0000a04c, 0x03960395},
-       {0x0000a050, 0x00000000},
-       {0x0000a054, 0x00000000},
-       {0x0000a058, 0x00000000},
-       {0x0000a05c, 0x00000000},
-       {0x0000a060, 0x00000000},
-       {0x0000a064, 0x00000000},
-       {0x0000a068, 0x00000000},
-       {0x0000a06c, 0x00000000},
-       {0x0000a070, 0x00000000},
-       {0x0000a074, 0x00000000},
-       {0x0000a078, 0x00000000},
-       {0x0000a07c, 0x00000000},
-       {0x0000a080, 0x22222229},
-       {0x0000a084, 0x1d1d1d1d},
-       {0x0000a088, 0x1d1d1d1d},
-       {0x0000a08c, 0x1d1d1d1d},
-       {0x0000a090, 0x171d1d1d},
-       {0x0000a094, 0x11111717},
-       {0x0000a098, 0x00030311},
-       {0x0000a09c, 0x00000000},
-       {0x0000a0a0, 0x00000000},
-       {0x0000a0a4, 0x00000000},
-       {0x0000a0a8, 0x00000000},
-       {0x0000a0ac, 0x00000000},
-       {0x0000a0b0, 0x00000000},
-       {0x0000a0b4, 0x00000000},
-       {0x0000a0b8, 0x00000000},
-       {0x0000a0bc, 0x00000000},
-       {0x0000a0c0, 0x001f0000},
-       {0x0000a0c4, 0x01000101},
-       {0x0000a0c8, 0x011e011f},
-       {0x0000a0cc, 0x011c011d},
-       {0x0000a0d0, 0x02030204},
-       {0x0000a0d4, 0x02010202},
-       {0x0000a0d8, 0x021f0200},
-       {0x0000a0dc, 0x0302021e},
-       {0x0000a0e0, 0x03000301},
-       {0x0000a0e4, 0x031e031f},
-       {0x0000a0e8, 0x0402031d},
-       {0x0000a0ec, 0x04000401},
-       {0x0000a0f0, 0x041e041f},
-       {0x0000a0f4, 0x0502041d},
-       {0x0000a0f8, 0x05000501},
-       {0x0000a0fc, 0x051e051f},
-       {0x0000a100, 0x06010602},
-       {0x0000a104, 0x061f0600},
-       {0x0000a108, 0x061d061e},
-       {0x0000a10c, 0x07020703},
-       {0x0000a110, 0x07000701},
-       {0x0000a114, 0x00000000},
-       {0x0000a118, 0x00000000},
-       {0x0000a11c, 0x00000000},
-       {0x0000a120, 0x00000000},
-       {0x0000a124, 0x00000000},
-       {0x0000a128, 0x00000000},
-       {0x0000a12c, 0x00000000},
-       {0x0000a130, 0x00000000},
-       {0x0000a134, 0x00000000},
-       {0x0000a138, 0x00000000},
-       {0x0000a13c, 0x00000000},
-       {0x0000a140, 0x001f0000},
-       {0x0000a144, 0x01000101},
-       {0x0000a148, 0x011e011f},
-       {0x0000a14c, 0x011c011d},
-       {0x0000a150, 0x02030204},
-       {0x0000a154, 0x02010202},
-       {0x0000a158, 0x021f0200},
-       {0x0000a15c, 0x0302021e},
-       {0x0000a160, 0x03000301},
-       {0x0000a164, 0x031e031f},
-       {0x0000a168, 0x0402031d},
-       {0x0000a16c, 0x04000401},
-       {0x0000a170, 0x041e041f},
-       {0x0000a174, 0x0502041d},
-       {0x0000a178, 0x05000501},
-       {0x0000a17c, 0x051e051f},
-       {0x0000a180, 0x06010602},
-       {0x0000a184, 0x061f0600},
-       {0x0000a188, 0x061d061e},
-       {0x0000a18c, 0x07020703},
-       {0x0000a190, 0x07000701},
-       {0x0000a194, 0x00000000},
-       {0x0000a198, 0x00000000},
-       {0x0000a19c, 0x00000000},
-       {0x0000a1a0, 0x00000000},
-       {0x0000a1a4, 0x00000000},
-       {0x0000a1a8, 0x00000000},
-       {0x0000a1ac, 0x00000000},
-       {0x0000a1b0, 0x00000000},
-       {0x0000a1b4, 0x00000000},
-       {0x0000a1b8, 0x00000000},
-       {0x0000a1bc, 0x00000000},
-       {0x0000a1c0, 0x00000000},
-       {0x0000a1c4, 0x00000000},
-       {0x0000a1c8, 0x00000000},
-       {0x0000a1cc, 0x00000000},
-       {0x0000a1d0, 0x00000000},
-       {0x0000a1d4, 0x00000000},
-       {0x0000a1d8, 0x00000000},
-       {0x0000a1dc, 0x00000000},
-       {0x0000a1e0, 0x00000000},
-       {0x0000a1e4, 0x00000000},
-       {0x0000a1e8, 0x00000000},
-       {0x0000a1ec, 0x00000000},
-       {0x0000a1f0, 0x00000396},
-       {0x0000a1f4, 0x00000396},
-       {0x0000a1f8, 0x00000396},
-       {0x0000a1fc, 0x00000196},
-       {0x0000b000, 0x00010000},
-       {0x0000b004, 0x00030002},
-       {0x0000b008, 0x00050004},
-       {0x0000b00c, 0x00810080},
-       {0x0000b010, 0x00830082},
-       {0x0000b014, 0x01810180},
-       {0x0000b018, 0x01830182},
-       {0x0000b01c, 0x01850184},
-       {0x0000b020, 0x02810280},
-       {0x0000b024, 0x02830282},
-       {0x0000b028, 0x02850284},
-       {0x0000b02c, 0x02890288},
-       {0x0000b030, 0x028b028a},
-       {0x0000b034, 0x0388028c},
-       {0x0000b038, 0x038a0389},
-       {0x0000b03c, 0x038c038b},
-       {0x0000b040, 0x0390038d},
-       {0x0000b044, 0x03920391},
-       {0x0000b048, 0x03940393},
-       {0x0000b04c, 0x03960395},
-       {0x0000b050, 0x00000000},
-       {0x0000b054, 0x00000000},
-       {0x0000b058, 0x00000000},
-       {0x0000b05c, 0x00000000},
-       {0x0000b060, 0x00000000},
-       {0x0000b064, 0x00000000},
-       {0x0000b068, 0x00000000},
-       {0x0000b06c, 0x00000000},
-       {0x0000b070, 0x00000000},
-       {0x0000b074, 0x00000000},
-       {0x0000b078, 0x00000000},
-       {0x0000b07c, 0x00000000},
-       {0x0000b080, 0x2a2d2f32},
-       {0x0000b084, 0x21232328},
-       {0x0000b088, 0x19191c1e},
-       {0x0000b08c, 0x12141417},
-       {0x0000b090, 0x07070e0e},
-       {0x0000b094, 0x03030305},
-       {0x0000b098, 0x00000003},
-       {0x0000b09c, 0x00000000},
-       {0x0000b0a0, 0x00000000},
-       {0x0000b0a4, 0x00000000},
-       {0x0000b0a8, 0x00000000},
-       {0x0000b0ac, 0x00000000},
-       {0x0000b0b0, 0x00000000},
-       {0x0000b0b4, 0x00000000},
-       {0x0000b0b8, 0x00000000},
-       {0x0000b0bc, 0x00000000},
-       {0x0000b0c0, 0x003f0020},
-       {0x0000b0c4, 0x00400041},
-       {0x0000b0c8, 0x0140005f},
-       {0x0000b0cc, 0x0160015f},
-       {0x0000b0d0, 0x017e017f},
-       {0x0000b0d4, 0x02410242},
-       {0x0000b0d8, 0x025f0240},
-       {0x0000b0dc, 0x027f0260},
-       {0x0000b0e0, 0x0341027e},
-       {0x0000b0e4, 0x035f0340},
-       {0x0000b0e8, 0x037f0360},
-       {0x0000b0ec, 0x04400441},
-       {0x0000b0f0, 0x0460045f},
-       {0x0000b0f4, 0x0541047f},
-       {0x0000b0f8, 0x055f0540},
-       {0x0000b0fc, 0x057f0560},
-       {0x0000b100, 0x06400641},
-       {0x0000b104, 0x0660065f},
-       {0x0000b108, 0x067e067f},
-       {0x0000b10c, 0x07410742},
-       {0x0000b110, 0x075f0740},
-       {0x0000b114, 0x077f0760},
-       {0x0000b118, 0x07800781},
-       {0x0000b11c, 0x07a0079f},
-       {0x0000b120, 0x07c107bf},
-       {0x0000b124, 0x000007c0},
-       {0x0000b128, 0x00000000},
-       {0x0000b12c, 0x00000000},
-       {0x0000b130, 0x00000000},
-       {0x0000b134, 0x00000000},
-       {0x0000b138, 0x00000000},
-       {0x0000b13c, 0x00000000},
-       {0x0000b140, 0x003f0020},
-       {0x0000b144, 0x00400041},
-       {0x0000b148, 0x0140005f},
-       {0x0000b14c, 0x0160015f},
-       {0x0000b150, 0x017e017f},
-       {0x0000b154, 0x02410242},
-       {0x0000b158, 0x025f0240},
-       {0x0000b15c, 0x027f0260},
-       {0x0000b160, 0x0341027e},
-       {0x0000b164, 0x035f0340},
-       {0x0000b168, 0x037f0360},
-       {0x0000b16c, 0x04400441},
-       {0x0000b170, 0x0460045f},
-       {0x0000b174, 0x0541047f},
-       {0x0000b178, 0x055f0540},
-       {0x0000b17c, 0x057f0560},
-       {0x0000b180, 0x06400641},
-       {0x0000b184, 0x0660065f},
-       {0x0000b188, 0x067e067f},
-       {0x0000b18c, 0x07410742},
-       {0x0000b190, 0x075f0740},
-       {0x0000b194, 0x077f0760},
-       {0x0000b198, 0x07800781},
-       {0x0000b19c, 0x07a0079f},
-       {0x0000b1a0, 0x07c107bf},
-       {0x0000b1a4, 0x000007c0},
-       {0x0000b1a8, 0x00000000},
-       {0x0000b1ac, 0x00000000},
-       {0x0000b1b0, 0x00000000},
-       {0x0000b1b4, 0x00000000},
-       {0x0000b1b8, 0x00000000},
-       {0x0000b1bc, 0x00000000},
-       {0x0000b1c0, 0x00000000},
-       {0x0000b1c4, 0x00000000},
-       {0x0000b1c8, 0x00000000},
-       {0x0000b1cc, 0x00000000},
-       {0x0000b1d0, 0x00000000},
-       {0x0000b1d4, 0x00000000},
-       {0x0000b1d8, 0x00000000},
-       {0x0000b1dc, 0x00000000},
-       {0x0000b1e0, 0x00000000},
-       {0x0000b1e4, 0x00000000},
-       {0x0000b1e8, 0x00000000},
-       {0x0000b1ec, 0x00000000},
-       {0x0000b1f0, 0x00000396},
-       {0x0000b1f4, 0x00000396},
-       {0x0000b1f8, 0x00000396},
-       {0x0000b1fc, 0x00000196},
-};
-
-static const u32 ar9462_2p1_common_mixed_rx_gain[][2] = {
-       /* Addr      allmodes  */
-       {0x0000a000, 0x00010000},
-       {0x0000a004, 0x00030002},
-       {0x0000a008, 0x00050004},
-       {0x0000a00c, 0x00810080},
-       {0x0000a010, 0x00830082},
-       {0x0000a014, 0x01810180},
-       {0x0000a018, 0x01830182},
-       {0x0000a01c, 0x01850184},
-       {0x0000a020, 0x01890188},
-       {0x0000a024, 0x018b018a},
-       {0x0000a028, 0x018d018c},
-       {0x0000a02c, 0x03820190},
-       {0x0000a030, 0x03840383},
-       {0x0000a034, 0x03880385},
-       {0x0000a038, 0x038a0389},
-       {0x0000a03c, 0x038c038b},
-       {0x0000a040, 0x0390038d},
-       {0x0000a044, 0x03920391},
-       {0x0000a048, 0x03940393},
-       {0x0000a04c, 0x03960395},
-       {0x0000a050, 0x00000000},
-       {0x0000a054, 0x00000000},
-       {0x0000a058, 0x00000000},
-       {0x0000a05c, 0x00000000},
-       {0x0000a060, 0x00000000},
-       {0x0000a064, 0x00000000},
-       {0x0000a068, 0x00000000},
-       {0x0000a06c, 0x00000000},
-       {0x0000a070, 0x00000000},
-       {0x0000a074, 0x00000000},
-       {0x0000a078, 0x00000000},
-       {0x0000a07c, 0x00000000},
-       {0x0000a080, 0x29292929},
-       {0x0000a084, 0x29292929},
-       {0x0000a088, 0x29292929},
-       {0x0000a08c, 0x29292929},
-       {0x0000a090, 0x22292929},
-       {0x0000a094, 0x1d1d2222},
-       {0x0000a098, 0x0c111117},
-       {0x0000a09c, 0x00030303},
-       {0x0000a0a0, 0x00000000},
-       {0x0000a0a4, 0x00000000},
-       {0x0000a0a8, 0x00000000},
-       {0x0000a0ac, 0x00000000},
-       {0x0000a0b0, 0x00000000},
-       {0x0000a0b4, 0x00000000},
-       {0x0000a0b8, 0x00000000},
-       {0x0000a0bc, 0x00000000},
-       {0x0000a0c0, 0x001f0000},
-       {0x0000a0c4, 0x01000101},
-       {0x0000a0c8, 0x011e011f},
-       {0x0000a0cc, 0x011c011d},
-       {0x0000a0d0, 0x02030204},
-       {0x0000a0d4, 0x02010202},
-       {0x0000a0d8, 0x021f0200},
-       {0x0000a0dc, 0x0302021e},
-       {0x0000a0e0, 0x03000301},
-       {0x0000a0e4, 0x031e031f},
-       {0x0000a0e8, 0x0402031d},
-       {0x0000a0ec, 0x04000401},
-       {0x0000a0f0, 0x041e041f},
-       {0x0000a0f4, 0x0502041d},
-       {0x0000a0f8, 0x05000501},
-       {0x0000a0fc, 0x051e051f},
-       {0x0000a100, 0x06010602},
-       {0x0000a104, 0x061f0600},
-       {0x0000a108, 0x061d061e},
-       {0x0000a10c, 0x07020703},
-       {0x0000a110, 0x07000701},
-       {0x0000a114, 0x00000000},
-       {0x0000a118, 0x00000000},
-       {0x0000a11c, 0x00000000},
-       {0x0000a120, 0x00000000},
-       {0x0000a124, 0x00000000},
-       {0x0000a128, 0x00000000},
-       {0x0000a12c, 0x00000000},
-       {0x0000a130, 0x00000000},
-       {0x0000a134, 0x00000000},
-       {0x0000a138, 0x00000000},
-       {0x0000a13c, 0x00000000},
-       {0x0000a140, 0x001f0000},
-       {0x0000a144, 0x01000101},
-       {0x0000a148, 0x011e011f},
-       {0x0000a14c, 0x011c011d},
-       {0x0000a150, 0x02030204},
-       {0x0000a154, 0x02010202},
-       {0x0000a158, 0x021f0200},
-       {0x0000a15c, 0x0302021e},
-       {0x0000a160, 0x03000301},
-       {0x0000a164, 0x031e031f},
-       {0x0000a168, 0x0402031d},
-       {0x0000a16c, 0x04000401},
-       {0x0000a170, 0x041e041f},
-       {0x0000a174, 0x0502041d},
-       {0x0000a178, 0x05000501},
-       {0x0000a17c, 0x051e051f},
-       {0x0000a180, 0x06010602},
-       {0x0000a184, 0x061f0600},
-       {0x0000a188, 0x061d061e},
-       {0x0000a18c, 0x07020703},
-       {0x0000a190, 0x07000701},
-       {0x0000a194, 0x00000000},
-       {0x0000a198, 0x00000000},
-       {0x0000a19c, 0x00000000},
-       {0x0000a1a0, 0x00000000},
-       {0x0000a1a4, 0x00000000},
-       {0x0000a1a8, 0x00000000},
-       {0x0000a1ac, 0x00000000},
-       {0x0000a1b0, 0x00000000},
-       {0x0000a1b4, 0x00000000},
-       {0x0000a1b8, 0x00000000},
-       {0x0000a1bc, 0x00000000},
-       {0x0000a1c0, 0x00000000},
-       {0x0000a1c4, 0x00000000},
-       {0x0000a1c8, 0x00000000},
-       {0x0000a1cc, 0x00000000},
-       {0x0000a1d0, 0x00000000},
-       {0x0000a1d4, 0x00000000},
-       {0x0000a1d8, 0x00000000},
-       {0x0000a1dc, 0x00000000},
-       {0x0000a1e0, 0x00000000},
-       {0x0000a1e4, 0x00000000},
-       {0x0000a1e8, 0x00000000},
-       {0x0000a1ec, 0x00000000},
-       {0x0000a1f0, 0x00000396},
-       {0x0000a1f4, 0x00000396},
-       {0x0000a1f8, 0x00000396},
-       {0x0000a1fc, 0x00000196},
-       {0x0000b000, 0x00010000},
-       {0x0000b004, 0x00030002},
-       {0x0000b008, 0x00050004},
-       {0x0000b00c, 0x00810080},
-       {0x0000b010, 0x00830082},
-       {0x0000b014, 0x01810180},
-       {0x0000b018, 0x01830182},
-       {0x0000b01c, 0x01850184},
-       {0x0000b020, 0x02810280},
-       {0x0000b024, 0x02830282},
-       {0x0000b028, 0x02850284},
-       {0x0000b02c, 0x02890288},
-       {0x0000b030, 0x028b028a},
-       {0x0000b034, 0x0388028c},
-       {0x0000b038, 0x038a0389},
-       {0x0000b03c, 0x038c038b},
-       {0x0000b040, 0x0390038d},
-       {0x0000b044, 0x03920391},
-       {0x0000b048, 0x03940393},
-       {0x0000b04c, 0x03960395},
-       {0x0000b050, 0x00000000},
-       {0x0000b054, 0x00000000},
-       {0x0000b058, 0x00000000},
-       {0x0000b05c, 0x00000000},
-       {0x0000b060, 0x00000000},
-       {0x0000b064, 0x00000000},
-       {0x0000b068, 0x00000000},
-       {0x0000b06c, 0x00000000},
-       {0x0000b070, 0x00000000},
-       {0x0000b074, 0x00000000},
-       {0x0000b078, 0x00000000},
-       {0x0000b07c, 0x00000000},
-       {0x0000b080, 0x2a2d2f32},
-       {0x0000b084, 0x21232328},
-       {0x0000b088, 0x19191c1e},
-       {0x0000b08c, 0x12141417},
-       {0x0000b090, 0x07070e0e},
-       {0x0000b094, 0x03030305},
-       {0x0000b098, 0x00000003},
-       {0x0000b09c, 0x00000000},
-       {0x0000b0a0, 0x00000000},
-       {0x0000b0a4, 0x00000000},
-       {0x0000b0a8, 0x00000000},
-       {0x0000b0ac, 0x00000000},
-       {0x0000b0b0, 0x00000000},
-       {0x0000b0b4, 0x00000000},
-       {0x0000b0b8, 0x00000000},
-       {0x0000b0bc, 0x00000000},
-       {0x0000b0c0, 0x003f0020},
-       {0x0000b0c4, 0x00400041},
-       {0x0000b0c8, 0x0140005f},
-       {0x0000b0cc, 0x0160015f},
-       {0x0000b0d0, 0x017e017f},
-       {0x0000b0d4, 0x02410242},
-       {0x0000b0d8, 0x025f0240},
-       {0x0000b0dc, 0x027f0260},
-       {0x0000b0e0, 0x0341027e},
-       {0x0000b0e4, 0x035f0340},
-       {0x0000b0e8, 0x037f0360},
-       {0x0000b0ec, 0x04400441},
-       {0x0000b0f0, 0x0460045f},
-       {0x0000b0f4, 0x0541047f},
-       {0x0000b0f8, 0x055f0540},
-       {0x0000b0fc, 0x057f0560},
-       {0x0000b100, 0x06400641},
-       {0x0000b104, 0x0660065f},
-       {0x0000b108, 0x067e067f},
-       {0x0000b10c, 0x07410742},
-       {0x0000b110, 0x075f0740},
-       {0x0000b114, 0x077f0760},
-       {0x0000b118, 0x07800781},
-       {0x0000b11c, 0x07a0079f},
-       {0x0000b120, 0x07c107bf},
-       {0x0000b124, 0x000007c0},
-       {0x0000b128, 0x00000000},
-       {0x0000b12c, 0x00000000},
-       {0x0000b130, 0x00000000},
-       {0x0000b134, 0x00000000},
-       {0x0000b138, 0x00000000},
-       {0x0000b13c, 0x00000000},
-       {0x0000b140, 0x003f0020},
-       {0x0000b144, 0x00400041},
-       {0x0000b148, 0x0140005f},
-       {0x0000b14c, 0x0160015f},
-       {0x0000b150, 0x017e017f},
-       {0x0000b154, 0x02410242},
-       {0x0000b158, 0x025f0240},
-       {0x0000b15c, 0x027f0260},
-       {0x0000b160, 0x0341027e},
-       {0x0000b164, 0x035f0340},
-       {0x0000b168, 0x037f0360},
-       {0x0000b16c, 0x04400441},
-       {0x0000b170, 0x0460045f},
-       {0x0000b174, 0x0541047f},
-       {0x0000b178, 0x055f0540},
-       {0x0000b17c, 0x057f0560},
-       {0x0000b180, 0x06400641},
-       {0x0000b184, 0x0660065f},
-       {0x0000b188, 0x067e067f},
-       {0x0000b18c, 0x07410742},
-       {0x0000b190, 0x075f0740},
-       {0x0000b194, 0x077f0760},
-       {0x0000b198, 0x07800781},
-       {0x0000b19c, 0x07a0079f},
-       {0x0000b1a0, 0x07c107bf},
-       {0x0000b1a4, 0x000007c0},
-       {0x0000b1a8, 0x00000000},
-       {0x0000b1ac, 0x00000000},
-       {0x0000b1b0, 0x00000000},
-       {0x0000b1b4, 0x00000000},
-       {0x0000b1b8, 0x00000000},
-       {0x0000b1bc, 0x00000000},
-       {0x0000b1c0, 0x00000000},
-       {0x0000b1c4, 0x00000000},
-       {0x0000b1c8, 0x00000000},
-       {0x0000b1cc, 0x00000000},
-       {0x0000b1d0, 0x00000000},
-       {0x0000b1d4, 0x00000000},
-       {0x0000b1d8, 0x00000000},
-       {0x0000b1dc, 0x00000000},
-       {0x0000b1e0, 0x00000000},
-       {0x0000b1e4, 0x00000000},
-       {0x0000b1e8, 0x00000000},
-       {0x0000b1ec, 0x00000000},
-       {0x0000b1f0, 0x00000396},
-       {0x0000b1f4, 0x00000396},
-       {0x0000b1f8, 0x00000396},
-       {0x0000b1fc, 0x00000196},
-};
-
-static const u32 ar9462_2p1_baseband_core_mix_rxgain[][2] = {
-       /* Addr      allmodes  */
-       {0x00009fd0, 0x0a2d6b93},
-};
-
-static const u32 ar9462_2p1_baseband_postamble_mix_rxgain[][5] = {
-       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-       {0x00009820, 0x206a022e, 0x206a022e, 0x206a01ae, 0x206a01ae},
-       {0x00009824, 0x63c640de, 0x5ac640d0, 0x63c640da, 0x63c640da},
-       {0x00009828, 0x0796be89, 0x0696b081, 0x0916be81, 0x0916be81},
-       {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000d8, 0x6c4000d8},
-       {0x00009e10, 0x92c88d2e, 0x7ec88d2e, 0x7ec86d2e, 0x7ec86d2e},
-       {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3236605e, 0x32395c5e},
-};
-
-static const u32 ar9462_2p1_baseband_postamble_5g_xlna[][5] = {
-       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-       {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282},
-};
-
-static const u32 ar9462_2p1_common_wo_xlna_rx_gain[][2] = {
-       /* Addr      allmodes  */
-       {0x0000a000, 0x00010000},
-       {0x0000a004, 0x00030002},
-       {0x0000a008, 0x00050004},
-       {0x0000a00c, 0x00810080},
-       {0x0000a010, 0x00830082},
-       {0x0000a014, 0x01810180},
-       {0x0000a018, 0x01830182},
-       {0x0000a01c, 0x01850184},
-       {0x0000a020, 0x01890188},
-       {0x0000a024, 0x018b018a},
-       {0x0000a028, 0x018d018c},
-       {0x0000a02c, 0x03820190},
-       {0x0000a030, 0x03840383},
-       {0x0000a034, 0x03880385},
-       {0x0000a038, 0x038a0389},
-       {0x0000a03c, 0x038c038b},
-       {0x0000a040, 0x0390038d},
-       {0x0000a044, 0x03920391},
-       {0x0000a048, 0x03940393},
-       {0x0000a04c, 0x03960395},
-       {0x0000a050, 0x00000000},
-       {0x0000a054, 0x00000000},
-       {0x0000a058, 0x00000000},
-       {0x0000a05c, 0x00000000},
-       {0x0000a060, 0x00000000},
-       {0x0000a064, 0x00000000},
-       {0x0000a068, 0x00000000},
-       {0x0000a06c, 0x00000000},
-       {0x0000a070, 0x00000000},
-       {0x0000a074, 0x00000000},
-       {0x0000a078, 0x00000000},
-       {0x0000a07c, 0x00000000},
-       {0x0000a080, 0x29292929},
-       {0x0000a084, 0x29292929},
-       {0x0000a088, 0x29292929},
-       {0x0000a08c, 0x29292929},
-       {0x0000a090, 0x22292929},
-       {0x0000a094, 0x1d1d2222},
-       {0x0000a098, 0x0c111117},
-       {0x0000a09c, 0x00030303},
-       {0x0000a0a0, 0x00000000},
-       {0x0000a0a4, 0x00000000},
-       {0x0000a0a8, 0x00000000},
-       {0x0000a0ac, 0x00000000},
-       {0x0000a0b0, 0x00000000},
-       {0x0000a0b4, 0x00000000},
-       {0x0000a0b8, 0x00000000},
-       {0x0000a0bc, 0x00000000},
-       {0x0000a0c0, 0x001f0000},
-       {0x0000a0c4, 0x01000101},
-       {0x0000a0c8, 0x011e011f},
-       {0x0000a0cc, 0x011c011d},
-       {0x0000a0d0, 0x02030204},
-       {0x0000a0d4, 0x02010202},
-       {0x0000a0d8, 0x021f0200},
-       {0x0000a0dc, 0x0302021e},
-       {0x0000a0e0, 0x03000301},
-       {0x0000a0e4, 0x031e031f},
-       {0x0000a0e8, 0x0402031d},
-       {0x0000a0ec, 0x04000401},
-       {0x0000a0f0, 0x041e041f},
-       {0x0000a0f4, 0x0502041d},
-       {0x0000a0f8, 0x05000501},
-       {0x0000a0fc, 0x051e051f},
-       {0x0000a100, 0x06010602},
-       {0x0000a104, 0x061f0600},
-       {0x0000a108, 0x061d061e},
-       {0x0000a10c, 0x07020703},
-       {0x0000a110, 0x07000701},
-       {0x0000a114, 0x00000000},
-       {0x0000a118, 0x00000000},
-       {0x0000a11c, 0x00000000},
-       {0x0000a120, 0x00000000},
-       {0x0000a124, 0x00000000},
-       {0x0000a128, 0x00000000},
-       {0x0000a12c, 0x00000000},
-       {0x0000a130, 0x00000000},
-       {0x0000a134, 0x00000000},
-       {0x0000a138, 0x00000000},
-       {0x0000a13c, 0x00000000},
-       {0x0000a140, 0x001f0000},
-       {0x0000a144, 0x01000101},
-       {0x0000a148, 0x011e011f},
-       {0x0000a14c, 0x011c011d},
-       {0x0000a150, 0x02030204},
-       {0x0000a154, 0x02010202},
-       {0x0000a158, 0x021f0200},
-       {0x0000a15c, 0x0302021e},
-       {0x0000a160, 0x03000301},
-       {0x0000a164, 0x031e031f},
-       {0x0000a168, 0x0402031d},
-       {0x0000a16c, 0x04000401},
-       {0x0000a170, 0x041e041f},
-       {0x0000a174, 0x0502041d},
-       {0x0000a178, 0x05000501},
-       {0x0000a17c, 0x051e051f},
-       {0x0000a180, 0x06010602},
-       {0x0000a184, 0x061f0600},
-       {0x0000a188, 0x061d061e},
-       {0x0000a18c, 0x07020703},
-       {0x0000a190, 0x07000701},
-       {0x0000a194, 0x00000000},
-       {0x0000a198, 0x00000000},
-       {0x0000a19c, 0x00000000},
-       {0x0000a1a0, 0x00000000},
-       {0x0000a1a4, 0x00000000},
-       {0x0000a1a8, 0x00000000},
-       {0x0000a1ac, 0x00000000},
-       {0x0000a1b0, 0x00000000},
-       {0x0000a1b4, 0x00000000},
-       {0x0000a1b8, 0x00000000},
-       {0x0000a1bc, 0x00000000},
-       {0x0000a1c0, 0x00000000},
-       {0x0000a1c4, 0x00000000},
-       {0x0000a1c8, 0x00000000},
-       {0x0000a1cc, 0x00000000},
-       {0x0000a1d0, 0x00000000},
-       {0x0000a1d4, 0x00000000},
-       {0x0000a1d8, 0x00000000},
-       {0x0000a1dc, 0x00000000},
-       {0x0000a1e0, 0x00000000},
-       {0x0000a1e4, 0x00000000},
-       {0x0000a1e8, 0x00000000},
-       {0x0000a1ec, 0x00000000},
-       {0x0000a1f0, 0x00000396},
-       {0x0000a1f4, 0x00000396},
-       {0x0000a1f8, 0x00000396},
-       {0x0000a1fc, 0x00000196},
-       {0x0000b000, 0x00010000},
-       {0x0000b004, 0x00030002},
-       {0x0000b008, 0x00050004},
-       {0x0000b00c, 0x00810080},
-       {0x0000b010, 0x00830082},
-       {0x0000b014, 0x01810180},
-       {0x0000b018, 0x01830182},
-       {0x0000b01c, 0x01850184},
-       {0x0000b020, 0x02810280},
-       {0x0000b024, 0x02830282},
-       {0x0000b028, 0x02850284},
-       {0x0000b02c, 0x02890288},
-       {0x0000b030, 0x028b028a},
-       {0x0000b034, 0x0388028c},
-       {0x0000b038, 0x038a0389},
-       {0x0000b03c, 0x038c038b},
-       {0x0000b040, 0x0390038d},
-       {0x0000b044, 0x03920391},
-       {0x0000b048, 0x03940393},
-       {0x0000b04c, 0x03960395},
-       {0x0000b050, 0x00000000},
-       {0x0000b054, 0x00000000},
-       {0x0000b058, 0x00000000},
-       {0x0000b05c, 0x00000000},
-       {0x0000b060, 0x00000000},
-       {0x0000b064, 0x00000000},
-       {0x0000b068, 0x00000000},
-       {0x0000b06c, 0x00000000},
-       {0x0000b070, 0x00000000},
-       {0x0000b074, 0x00000000},
-       {0x0000b078, 0x00000000},
-       {0x0000b07c, 0x00000000},
-       {0x0000b080, 0x32323232},
-       {0x0000b084, 0x2f2f3232},
-       {0x0000b088, 0x23282a2d},
-       {0x0000b08c, 0x1c1e2123},
-       {0x0000b090, 0x14171919},
-       {0x0000b094, 0x0e0e1214},
-       {0x0000b098, 0x03050707},
-       {0x0000b09c, 0x00030303},
-       {0x0000b0a0, 0x00000000},
-       {0x0000b0a4, 0x00000000},
-       {0x0000b0a8, 0x00000000},
-       {0x0000b0ac, 0x00000000},
-       {0x0000b0b0, 0x00000000},
-       {0x0000b0b4, 0x00000000},
-       {0x0000b0b8, 0x00000000},
-       {0x0000b0bc, 0x00000000},
-       {0x0000b0c0, 0x003f0020},
-       {0x0000b0c4, 0x00400041},
-       {0x0000b0c8, 0x0140005f},
-       {0x0000b0cc, 0x0160015f},
-       {0x0000b0d0, 0x017e017f},
-       {0x0000b0d4, 0x02410242},
-       {0x0000b0d8, 0x025f0240},
-       {0x0000b0dc, 0x027f0260},
-       {0x0000b0e0, 0x0341027e},
-       {0x0000b0e4, 0x035f0340},
-       {0x0000b0e8, 0x037f0360},
-       {0x0000b0ec, 0x04400441},
-       {0x0000b0f0, 0x0460045f},
-       {0x0000b0f4, 0x0541047f},
-       {0x0000b0f8, 0x055f0540},
-       {0x0000b0fc, 0x057f0560},
-       {0x0000b100, 0x06400641},
-       {0x0000b104, 0x0660065f},
-       {0x0000b108, 0x067e067f},
-       {0x0000b10c, 0x07410742},
-       {0x0000b110, 0x075f0740},
-       {0x0000b114, 0x077f0760},
-       {0x0000b118, 0x07800781},
-       {0x0000b11c, 0x07a0079f},
-       {0x0000b120, 0x07c107bf},
-       {0x0000b124, 0x000007c0},
-       {0x0000b128, 0x00000000},
-       {0x0000b12c, 0x00000000},
-       {0x0000b130, 0x00000000},
-       {0x0000b134, 0x00000000},
-       {0x0000b138, 0x00000000},
-       {0x0000b13c, 0x00000000},
-       {0x0000b140, 0x003f0020},
-       {0x0000b144, 0x00400041},
-       {0x0000b148, 0x0140005f},
-       {0x0000b14c, 0x0160015f},
-       {0x0000b150, 0x017e017f},
-       {0x0000b154, 0x02410242},
-       {0x0000b158, 0x025f0240},
-       {0x0000b15c, 0x027f0260},
-       {0x0000b160, 0x0341027e},
-       {0x0000b164, 0x035f0340},
-       {0x0000b168, 0x037f0360},
-       {0x0000b16c, 0x04400441},
-       {0x0000b170, 0x0460045f},
-       {0x0000b174, 0x0541047f},
-       {0x0000b178, 0x055f0540},
-       {0x0000b17c, 0x057f0560},
-       {0x0000b180, 0x06400641},
-       {0x0000b184, 0x0660065f},
-       {0x0000b188, 0x067e067f},
-       {0x0000b18c, 0x07410742},
-       {0x0000b190, 0x075f0740},
-       {0x0000b194, 0x077f0760},
-       {0x0000b198, 0x07800781},
-       {0x0000b19c, 0x07a0079f},
-       {0x0000b1a0, 0x07c107bf},
-       {0x0000b1a4, 0x000007c0},
-       {0x0000b1a8, 0x00000000},
-       {0x0000b1ac, 0x00000000},
-       {0x0000b1b0, 0x00000000},
-       {0x0000b1b4, 0x00000000},
-       {0x0000b1b8, 0x00000000},
-       {0x0000b1bc, 0x00000000},
-       {0x0000b1c0, 0x00000000},
-       {0x0000b1c4, 0x00000000},
-       {0x0000b1c8, 0x00000000},
-       {0x0000b1cc, 0x00000000},
-       {0x0000b1d0, 0x00000000},
-       {0x0000b1d4, 0x00000000},
-       {0x0000b1d8, 0x00000000},
-       {0x0000b1dc, 0x00000000},
-       {0x0000b1e0, 0x00000000},
-       {0x0000b1e4, 0x00000000},
-       {0x0000b1e8, 0x00000000},
-       {0x0000b1ec, 0x00000000},
-       {0x0000b1f0, 0x00000396},
-       {0x0000b1f4, 0x00000396},
-       {0x0000b1f8, 0x00000396},
-       {0x0000b1fc, 0x00000196},
-};
-
-static const u32 ar9462_2p1_common_5g_xlna_only_rx_gain[][2] = {
-       /* Addr      allmodes  */
-       {0x0000a000, 0x00010000},
-       {0x0000a004, 0x00030002},
-       {0x0000a008, 0x00050004},
-       {0x0000a00c, 0x00810080},
-       {0x0000a010, 0x00830082},
-       {0x0000a014, 0x01810180},
-       {0x0000a018, 0x01830182},
-       {0x0000a01c, 0x01850184},
-       {0x0000a020, 0x01890188},
-       {0x0000a024, 0x018b018a},
-       {0x0000a028, 0x018d018c},
-       {0x0000a02c, 0x03820190},
-       {0x0000a030, 0x03840383},
-       {0x0000a034, 0x03880385},
-       {0x0000a038, 0x038a0389},
-       {0x0000a03c, 0x038c038b},
-       {0x0000a040, 0x0390038d},
-       {0x0000a044, 0x03920391},
-       {0x0000a048, 0x03940393},
-       {0x0000a04c, 0x03960395},
-       {0x0000a050, 0x00000000},
-       {0x0000a054, 0x00000000},
-       {0x0000a058, 0x00000000},
-       {0x0000a05c, 0x00000000},
-       {0x0000a060, 0x00000000},
-       {0x0000a064, 0x00000000},
-       {0x0000a068, 0x00000000},
-       {0x0000a06c, 0x00000000},
-       {0x0000a070, 0x00000000},
-       {0x0000a074, 0x00000000},
-       {0x0000a078, 0x00000000},
-       {0x0000a07c, 0x00000000},
-       {0x0000a080, 0x29292929},
-       {0x0000a084, 0x29292929},
-       {0x0000a088, 0x29292929},
-       {0x0000a08c, 0x29292929},
-       {0x0000a090, 0x22292929},
-       {0x0000a094, 0x1d1d2222},
-       {0x0000a098, 0x0c111117},
-       {0x0000a09c, 0x00030303},
-       {0x0000a0a0, 0x00000000},
-       {0x0000a0a4, 0x00000000},
-       {0x0000a0a8, 0x00000000},
-       {0x0000a0ac, 0x00000000},
-       {0x0000a0b0, 0x00000000},
-       {0x0000a0b4, 0x00000000},
-       {0x0000a0b8, 0x00000000},
-       {0x0000a0bc, 0x00000000},
-       {0x0000a0c0, 0x001f0000},
-       {0x0000a0c4, 0x01000101},
-       {0x0000a0c8, 0x011e011f},
-       {0x0000a0cc, 0x011c011d},
-       {0x0000a0d0, 0x02030204},
-       {0x0000a0d4, 0x02010202},
-       {0x0000a0d8, 0x021f0200},
-       {0x0000a0dc, 0x0302021e},
-       {0x0000a0e0, 0x03000301},
-       {0x0000a0e4, 0x031e031f},
-       {0x0000a0e8, 0x0402031d},
-       {0x0000a0ec, 0x04000401},
-       {0x0000a0f0, 0x041e041f},
-       {0x0000a0f4, 0x0502041d},
-       {0x0000a0f8, 0x05000501},
-       {0x0000a0fc, 0x051e051f},
-       {0x0000a100, 0x06010602},
-       {0x0000a104, 0x061f0600},
-       {0x0000a108, 0x061d061e},
-       {0x0000a10c, 0x07020703},
-       {0x0000a110, 0x07000701},
-       {0x0000a114, 0x00000000},
-       {0x0000a118, 0x00000000},
-       {0x0000a11c, 0x00000000},
-       {0x0000a120, 0x00000000},
-       {0x0000a124, 0x00000000},
-       {0x0000a128, 0x00000000},
-       {0x0000a12c, 0x00000000},
-       {0x0000a130, 0x00000000},
-       {0x0000a134, 0x00000000},
-       {0x0000a138, 0x00000000},
-       {0x0000a13c, 0x00000000},
-       {0x0000a140, 0x001f0000},
-       {0x0000a144, 0x01000101},
-       {0x0000a148, 0x011e011f},
-       {0x0000a14c, 0x011c011d},
-       {0x0000a150, 0x02030204},
-       {0x0000a154, 0x02010202},
-       {0x0000a158, 0x021f0200},
-       {0x0000a15c, 0x0302021e},
-       {0x0000a160, 0x03000301},
-       {0x0000a164, 0x031e031f},
-       {0x0000a168, 0x0402031d},
-       {0x0000a16c, 0x04000401},
-       {0x0000a170, 0x041e041f},
-       {0x0000a174, 0x0502041d},
-       {0x0000a178, 0x05000501},
-       {0x0000a17c, 0x051e051f},
-       {0x0000a180, 0x06010602},
-       {0x0000a184, 0x061f0600},
-       {0x0000a188, 0x061d061e},
-       {0x0000a18c, 0x07020703},
-       {0x0000a190, 0x07000701},
-       {0x0000a194, 0x00000000},
-       {0x0000a198, 0x00000000},
-       {0x0000a19c, 0x00000000},
-       {0x0000a1a0, 0x00000000},
-       {0x0000a1a4, 0x00000000},
-       {0x0000a1a8, 0x00000000},
-       {0x0000a1ac, 0x00000000},
-       {0x0000a1b0, 0x00000000},
-       {0x0000a1b4, 0x00000000},
-       {0x0000a1b8, 0x00000000},
-       {0x0000a1bc, 0x00000000},
-       {0x0000a1c0, 0x00000000},
-       {0x0000a1c4, 0x00000000},
-       {0x0000a1c8, 0x00000000},
-       {0x0000a1cc, 0x00000000},
-       {0x0000a1d0, 0x00000000},
-       {0x0000a1d4, 0x00000000},
-       {0x0000a1d8, 0x00000000},
-       {0x0000a1dc, 0x00000000},
-       {0x0000a1e0, 0x00000000},
-       {0x0000a1e4, 0x00000000},
-       {0x0000a1e8, 0x00000000},
-       {0x0000a1ec, 0x00000000},
-       {0x0000a1f0, 0x00000396},
-       {0x0000a1f4, 0x00000396},
-       {0x0000a1f8, 0x00000396},
-       {0x0000a1fc, 0x00000196},
-       {0x0000b000, 0x00010000},
-       {0x0000b004, 0x00030002},
-       {0x0000b008, 0x00050004},
-       {0x0000b00c, 0x00810080},
-       {0x0000b010, 0x00830082},
-       {0x0000b014, 0x01810180},
-       {0x0000b018, 0x01830182},
-       {0x0000b01c, 0x01850184},
-       {0x0000b020, 0x02810280},
-       {0x0000b024, 0x02830282},
-       {0x0000b028, 0x02850284},
-       {0x0000b02c, 0x02890288},
-       {0x0000b030, 0x028b028a},
-       {0x0000b034, 0x0388028c},
-       {0x0000b038, 0x038a0389},
-       {0x0000b03c, 0x038c038b},
-       {0x0000b040, 0x0390038d},
-       {0x0000b044, 0x03920391},
-       {0x0000b048, 0x03940393},
-       {0x0000b04c, 0x03960395},
-       {0x0000b050, 0x00000000},
-       {0x0000b054, 0x00000000},
-       {0x0000b058, 0x00000000},
-       {0x0000b05c, 0x00000000},
-       {0x0000b060, 0x00000000},
-       {0x0000b064, 0x00000000},
-       {0x0000b068, 0x00000000},
-       {0x0000b06c, 0x00000000},
-       {0x0000b070, 0x00000000},
-       {0x0000b074, 0x00000000},
-       {0x0000b078, 0x00000000},
-       {0x0000b07c, 0x00000000},
-       {0x0000b080, 0x2a2d2f32},
-       {0x0000b084, 0x21232328},
-       {0x0000b088, 0x19191c1e},
-       {0x0000b08c, 0x12141417},
-       {0x0000b090, 0x07070e0e},
-       {0x0000b094, 0x03030305},
-       {0x0000b098, 0x00000003},
-       {0x0000b09c, 0x00000000},
-       {0x0000b0a0, 0x00000000},
-       {0x0000b0a4, 0x00000000},
-       {0x0000b0a8, 0x00000000},
-       {0x0000b0ac, 0x00000000},
-       {0x0000b0b0, 0x00000000},
-       {0x0000b0b4, 0x00000000},
-       {0x0000b0b8, 0x00000000},
-       {0x0000b0bc, 0x00000000},
-       {0x0000b0c0, 0x003f0020},
-       {0x0000b0c4, 0x00400041},
-       {0x0000b0c8, 0x0140005f},
-       {0x0000b0cc, 0x0160015f},
-       {0x0000b0d0, 0x017e017f},
-       {0x0000b0d4, 0x02410242},
-       {0x0000b0d8, 0x025f0240},
-       {0x0000b0dc, 0x027f0260},
-       {0x0000b0e0, 0x0341027e},
-       {0x0000b0e4, 0x035f0340},
-       {0x0000b0e8, 0x037f0360},
-       {0x0000b0ec, 0x04400441},
-       {0x0000b0f0, 0x0460045f},
-       {0x0000b0f4, 0x0541047f},
-       {0x0000b0f8, 0x055f0540},
-       {0x0000b0fc, 0x057f0560},
-       {0x0000b100, 0x06400641},
-       {0x0000b104, 0x0660065f},
-       {0x0000b108, 0x067e067f},
-       {0x0000b10c, 0x07410742},
-       {0x0000b110, 0x075f0740},
-       {0x0000b114, 0x077f0760},
-       {0x0000b118, 0x07800781},
-       {0x0000b11c, 0x07a0079f},
-       {0x0000b120, 0x07c107bf},
-       {0x0000b124, 0x000007c0},
-       {0x0000b128, 0x00000000},
-       {0x0000b12c, 0x00000000},
-       {0x0000b130, 0x00000000},
-       {0x0000b134, 0x00000000},
-       {0x0000b138, 0x00000000},
-       {0x0000b13c, 0x00000000},
-       {0x0000b140, 0x003f0020},
-       {0x0000b144, 0x00400041},
-       {0x0000b148, 0x0140005f},
-       {0x0000b14c, 0x0160015f},
-       {0x0000b150, 0x017e017f},
-       {0x0000b154, 0x02410242},
-       {0x0000b158, 0x025f0240},
-       {0x0000b15c, 0x027f0260},
-       {0x0000b160, 0x0341027e},
-       {0x0000b164, 0x035f0340},
-       {0x0000b168, 0x037f0360},
-       {0x0000b16c, 0x04400441},
-       {0x0000b170, 0x0460045f},
-       {0x0000b174, 0x0541047f},
-       {0x0000b178, 0x055f0540},
-       {0x0000b17c, 0x057f0560},
-       {0x0000b180, 0x06400641},
-       {0x0000b184, 0x0660065f},
-       {0x0000b188, 0x067e067f},
-       {0x0000b18c, 0x07410742},
-       {0x0000b190, 0x075f0740},
-       {0x0000b194, 0x077f0760},
-       {0x0000b198, 0x07800781},
-       {0x0000b19c, 0x07a0079f},
-       {0x0000b1a0, 0x07c107bf},
-       {0x0000b1a4, 0x000007c0},
-       {0x0000b1a8, 0x00000000},
-       {0x0000b1ac, 0x00000000},
-       {0x0000b1b0, 0x00000000},
-       {0x0000b1b4, 0x00000000},
-       {0x0000b1b8, 0x00000000},
-       {0x0000b1bc, 0x00000000},
-       {0x0000b1c0, 0x00000000},
-       {0x0000b1c4, 0x00000000},
-       {0x0000b1c8, 0x00000000},
-       {0x0000b1cc, 0x00000000},
-       {0x0000b1d0, 0x00000000},
-       {0x0000b1d4, 0x00000000},
-       {0x0000b1d8, 0x00000000},
-       {0x0000b1dc, 0x00000000},
-       {0x0000b1e0, 0x00000000},
-       {0x0000b1e4, 0x00000000},
-       {0x0000b1e8, 0x00000000},
-       {0x0000b1ec, 0x00000000},
-       {0x0000b1f0, 0x00000396},
-       {0x0000b1f4, 0x00000396},
-       {0x0000b1f8, 0x00000396},
-       {0x0000b1fc, 0x00000196},
-};
-
-static const u32 ar9462_2p1_modes_low_ob_db_tx_gain[][5] = {
-       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-       {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
-       {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
-       {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
-       {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
-       {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
-       {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
-       {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
-       {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
-       {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
-       {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
-       {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400},
-       {0x0000a518, 0x21020220, 0x21020220, 0x16000402, 0x16000402},
-       {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404},
-       {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603},
-       {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02},
-       {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04},
-       {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20},
-       {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20},
-       {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22},
-       {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
-       {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
-       {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
-       {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861},
-       {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81},
-       {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x47001a83, 0x47001a83},
-       {0x0000a550, 0x61042a6c, 0x61042a6c, 0x4a001c84, 0x4a001c84},
-       {0x0000a554, 0x66062a6c, 0x66062a6c, 0x4e001ce3, 0x4e001ce3},
-       {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x52001ce5, 0x52001ce5},
-       {0x0000a55c, 0x7006308c, 0x7006308c, 0x56001ce9, 0x56001ce9},
-       {0x0000a560, 0x730a308a, 0x730a308a, 0x5a001ceb, 0x5a001ceb},
-       {0x0000a564, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
-       {0x0000a568, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
-       {0x0000a56c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
-       {0x0000a570, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
-       {0x0000a574, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
-       {0x0000a578, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
-       {0x0000a57c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
-       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
-       {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
-       {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501},
-       {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03},
-       {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
-       {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04},
-       {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005},
-       {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
-       {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
-       {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
-       {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
-       {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
-       {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584},
-       {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800},
-       {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
-       {0x00016044, 0x012482d4, 0x012482d4, 0x012482d4, 0x012482d4},
-       {0x00016048, 0x64992060, 0x64992060, 0x64992060, 0x64992060},
-       {0x00016054, 0x6db60000, 0x6db60000, 0x6db60000, 0x6db60000},
-       {0x00016444, 0x012482d4, 0x012482d4, 0x012482d4, 0x012482d4},
-       {0x00016448, 0x64992000, 0x64992000, 0x64992000, 0x64992000},
-       {0x00016454, 0x6db60000, 0x6db60000, 0x6db60000, 0x6db60000},
-};
-
-static const u32 ar9462_2p1_modes_high_ob_db_tx_gain[][5] = {
-       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-       {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
-       {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
-       {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
-       {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
-       {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
-       {0x0000a410, 0x000050da, 0x000050da, 0x000050de, 0x000050de},
-       {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
-       {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002},
-       {0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004},
-       {0x0000a50c, 0x0f022223, 0x0f022223, 0x0b000200, 0x0b000200},
-       {0x0000a510, 0x14022620, 0x14022620, 0x0f000202, 0x0f000202},
-       {0x0000a514, 0x18022622, 0x18022622, 0x11000400, 0x11000400},
-       {0x0000a518, 0x1b022822, 0x1b022822, 0x15000402, 0x15000402},
-       {0x0000a51c, 0x20022842, 0x20022842, 0x19000404, 0x19000404},
-       {0x0000a520, 0x22022c41, 0x22022c41, 0x1b000603, 0x1b000603},
-       {0x0000a524, 0x28023042, 0x28023042, 0x1f000a02, 0x1f000a02},
-       {0x0000a528, 0x2c023044, 0x2c023044, 0x23000a04, 0x23000a04},
-       {0x0000a52c, 0x2f023644, 0x2f023644, 0x26000a20, 0x26000a20},
-       {0x0000a530, 0x34025643, 0x34025643, 0x2a000e20, 0x2a000e20},
-       {0x0000a534, 0x38025a44, 0x38025a44, 0x2e000e22, 0x2e000e22},
-       {0x0000a538, 0x3b025e45, 0x3b025e45, 0x31000e24, 0x31000e24},
-       {0x0000a53c, 0x41025e4a, 0x41025e4a, 0x34001640, 0x34001640},
-       {0x0000a540, 0x48025e6c, 0x48025e6c, 0x38001660, 0x38001660},
-       {0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861},
-       {0x0000a548, 0x55025eb3, 0x55025eb3, 0x3e001a81, 0x3e001a81},
-       {0x0000a54c, 0x58025ef3, 0x58025ef3, 0x42001a83, 0x42001a83},
-       {0x0000a550, 0x5d025ef6, 0x5d025ef6, 0x44001a84, 0x44001a84},
-       {0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3},
-       {0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5},
-       {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9},
-       {0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb},
-       {0x0000a564, 0x751ffff6, 0x751ffff6, 0x56001eec, 0x56001eec},
-       {0x0000a568, 0x751ffff6, 0x751ffff6, 0x58001ef0, 0x58001ef0},
-       {0x0000a56c, 0x751ffff6, 0x751ffff6, 0x5a001ef4, 0x5a001ef4},
-       {0x0000a570, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6},
-       {0x0000a574, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6},
-       {0x0000a578, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6},
-       {0x0000a57c, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6},
-       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000},
-       {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000},
-       {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501},
-       {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501},
-       {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03},
-       {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04},
-       {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04},
-       {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
-       {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
-       {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
-       {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
-       {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
-       {0x0000b2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
-       {0x0000b2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
-       {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
-       {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
-       {0x00016044, 0x056d82e4, 0x056d82e4, 0x056d82e4, 0x056d82e4},
-       {0x00016048, 0x8db49060, 0x8db49060, 0x8db49060, 0x8db49060},
-       {0x00016054, 0x6db60000, 0x6db60000, 0x6db60000, 0x6db60000},
-       {0x00016444, 0x056d82e4, 0x056d82e4, 0x056d82e4, 0x056d82e4},
-       {0x00016448, 0x8db49000, 0x8db49000, 0x8db49000, 0x8db49000},
-       {0x00016454, 0x6db60000, 0x6db60000, 0x6db60000, 0x6db60000},
-};
-
-static const u32 ar9462_2p1_modes_mix_ob_db_tx_gain[][5] = {
-       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-       {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
-       {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
-       {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
-       {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
-       {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
-       {0x0000a410, 0x0000d0da, 0x0000d0da, 0x0000d0de, 0x0000d0de},
-       {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
-       {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002},
-       {0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004},
-       {0x0000a50c, 0x0f022223, 0x0f022223, 0x0b000200, 0x0b000200},
-       {0x0000a510, 0x14022620, 0x14022620, 0x0f000202, 0x0f000202},
-       {0x0000a514, 0x18022622, 0x18022622, 0x12000400, 0x12000400},
-       {0x0000a518, 0x1b022822, 0x1b022822, 0x16000402, 0x16000402},
-       {0x0000a51c, 0x20022842, 0x20022842, 0x19000404, 0x19000404},
-       {0x0000a520, 0x22022c41, 0x22022c41, 0x1c000603, 0x1c000603},
-       {0x0000a524, 0x28023042, 0x28023042, 0x21000a02, 0x21000a02},
-       {0x0000a528, 0x2c023044, 0x2c023044, 0x25000a04, 0x25000a04},
-       {0x0000a52c, 0x2f023644, 0x2f023644, 0x28000a20, 0x28000a20},
-       {0x0000a530, 0x34025643, 0x34025643, 0x2c000e20, 0x2c000e20},
-       {0x0000a534, 0x38025a44, 0x38025a44, 0x30000e22, 0x30000e22},
-       {0x0000a538, 0x3b025e45, 0x3b025e45, 0x34000e24, 0x34000e24},
-       {0x0000a53c, 0x41025e4a, 0x41025e4a, 0x38001640, 0x38001640},
-       {0x0000a540, 0x48025e6c, 0x48025e6c, 0x3c001660, 0x3c001660},
-       {0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3f001861, 0x3f001861},
-       {0x0000a548, 0x55025eb3, 0x55025eb3, 0x43001a81, 0x43001a81},
-       {0x0000a54c, 0x58025ef3, 0x58025ef3, 0x47001a83, 0x47001a83},
-       {0x0000a550, 0x5d025ef6, 0x5d025ef6, 0x4a001c84, 0x4a001c84},
-       {0x0000a554, 0x62025f56, 0x62025f56, 0x4e001ce3, 0x4e001ce3},
-       {0x0000a558, 0x66027f56, 0x66027f56, 0x52001ce5, 0x52001ce5},
-       {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x56001ce9, 0x56001ce9},
-       {0x0000a560, 0x70049f56, 0x70049f56, 0x5a001ceb, 0x5a001ceb},
-       {0x0000a564, 0x751ffff6, 0x751ffff6, 0x5c001eec, 0x5c001eec},
-       {0x0000a568, 0x751ffff6, 0x751ffff6, 0x5e001ef0, 0x5e001ef0},
-       {0x0000a56c, 0x751ffff6, 0x751ffff6, 0x60001ef4, 0x60001ef4},
-       {0x0000a570, 0x751ffff6, 0x751ffff6, 0x62001ff6, 0x62001ff6},
-       {0x0000a574, 0x751ffff6, 0x751ffff6, 0x62001ff6, 0x62001ff6},
-       {0x0000a578, 0x751ffff6, 0x751ffff6, 0x62001ff6, 0x62001ff6},
-       {0x0000a57c, 0x751ffff6, 0x751ffff6, 0x62001ff6, 0x62001ff6},
-       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000},
-       {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000},
-       {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501},
-       {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501},
-       {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03},
-       {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04},
-       {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04},
-       {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
-       {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
-       {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
-       {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
-       {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005},
-       {0x0000b2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352},
-       {0x0000b2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
-       {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
-       {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
-};
-
-static const u32 ar9462_2p1_modes_fast_clock[][3] = {
-       /* Addr      5G_HT20     5G_HT40   */
-       {0x00001030, 0x00000268, 0x000004d0},
-       {0x00001070, 0x0000018c, 0x00000318},
-       {0x000010b0, 0x00000fd0, 0x00001fa0},
-       {0x00008014, 0x044c044c, 0x08980898},
-       {0x0000801c, 0x148ec02b, 0x148ec057},
-       {0x00008318, 0x000044c0, 0x00008980},
-       {0x00009e00, 0x0372131c, 0x0372131c},
-       {0x0000a230, 0x0000400b, 0x00004016},
-       {0x0000a254, 0x00000898, 0x00001130},
-};
-
-static const u32 ar9462_2p1_baseband_core_txfir_coeff_japan_2484[][2] = {
-       /* Addr      allmodes  */
-       {0x0000a398, 0x00000000},
-       {0x0000a39c, 0x6f7f0301},
-       {0x0000a3a0, 0xca9228ee},
-};
-
 #endif /* INITVALS_9462_2P1_H */
index 7c1845221e1cc08a0904b35a491e64b1cd70b953..ce83ce47a1ca9b7b28dc68e6b414f21236392117 100644 (file)
 
 /* AR9485 1.1 */
 
-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},
-};
+#define ar9485_modes_lowest_ob_db_tx_gain_1_1 ar9485Modes_low_ob_db_tx_gain_1_1
+
+#define ar9485_1_1_mac_postamble ar9331_1p1_mac_postamble
+
+#define ar9485_1_1_baseband_core_txfir_coeff_japan_2484 ar9300_2p2_baseband_core_txfir_coeff_japan_2484
 
 static const u32 ar9485Common_wo_xlna_rx_gain_1_1[][2] = {
        /* Addr      allmodes  */
@@ -546,100 +540,6 @@ static const u32 ar9485Modes_low_ob_db_tx_gain_1_1[][5] = {
        {0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
 };
 
-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},
-       {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},
-       {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, 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},
-       {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_green_spur_ob_db_tx_gain_1_1[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
        {0x000098bc, 0x00000003, 0x00000003, 0x00000003, 0x00000003},
@@ -1323,13 +1223,6 @@ static const u32 ar9485_1_1_mac_core[][2] = {
        {0x000083d0, 0x000301ff},
 };
 
-static const u32 ar9485_1_1_baseband_core_txfir_coeff_japan_2484[][2] = {
-       /* Addr      allmodes  */
-       {0x0000a398, 0x00000000},
-       {0x0000a39c, 0x6f7f0301},
-       {0x0000a3a0, 0xca9228ee},
-};
-
 static const u32 ar9485_1_1_pcie_phy_clkreq_disable_L1[][2] = {
        /* Addr      allmodes  */
        {0x00018c00, 0x18013e5e},
index ccc5b6c99add76617b4b990e106bd57be0d1f09f..74d8bc05b317af2818317b5d1e77dc30ec8d8e8c 100644 (file)
 
 /* AR955X 1.0 */
 
+#define ar955x_1p0_soc_postamble ar9300_2p2_soc_postamble
+
+#define ar955x_1p0_common_rx_gain_table ar9300Common_rx_gain_table_2p2
+
+#define ar955x_1p0_common_wo_xlna_rx_gain_table ar9300Common_wo_xlna_rx_gain_table_2p2
+
+#define ar955x_1p0_baseband_core_txfir_coeff_japan_2484 ar9300_2p2_baseband_core_txfir_coeff_japan_2484
+
 static const u32 ar955x_1p0_radio_postamble[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
        {0x00016098, 0xd2dd5554, 0xd2dd5554, 0xd28b3330, 0xd28b3330},
@@ -37,13 +45,6 @@ static const u32 ar955x_1p0_radio_postamble[][5] = {
        {0x00016940, 0x10804008, 0x10804008, 0x10804008, 0x10804008},
 };
 
-static const u32 ar955x_1p0_baseband_core_txfir_coeff_japan_2484[][2] = {
-       /* Addr      allmodes  */
-       {0x0000a398, 0x00000000},
-       {0x0000a39c, 0x6f7f0301},
-       {0x0000a3a0, 0xca9228ee},
-};
-
 static const u32 ar955x_1p0_baseband_postamble[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
        {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011},
@@ -473,266 +474,6 @@ static const u32 ar955x_1p0_mac_core[][2] = {
        {0x000083d0, 0x8c7901ff},
 };
 
-static const u32 ar955x_1p0_common_rx_gain_table[][2] = {
-       /* Addr      allmodes  */
-       {0x0000a000, 0x00010000},
-       {0x0000a004, 0x00030002},
-       {0x0000a008, 0x00050004},
-       {0x0000a00c, 0x00810080},
-       {0x0000a010, 0x00830082},
-       {0x0000a014, 0x01810180},
-       {0x0000a018, 0x01830182},
-       {0x0000a01c, 0x01850184},
-       {0x0000a020, 0x01890188},
-       {0x0000a024, 0x018b018a},
-       {0x0000a028, 0x018d018c},
-       {0x0000a02c, 0x01910190},
-       {0x0000a030, 0x01930192},
-       {0x0000a034, 0x01950194},
-       {0x0000a038, 0x038a0196},
-       {0x0000a03c, 0x038c038b},
-       {0x0000a040, 0x0390038d},
-       {0x0000a044, 0x03920391},
-       {0x0000a048, 0x03940393},
-       {0x0000a04c, 0x03960395},
-       {0x0000a050, 0x00000000},
-       {0x0000a054, 0x00000000},
-       {0x0000a058, 0x00000000},
-       {0x0000a05c, 0x00000000},
-       {0x0000a060, 0x00000000},
-       {0x0000a064, 0x00000000},
-       {0x0000a068, 0x00000000},
-       {0x0000a06c, 0x00000000},
-       {0x0000a070, 0x00000000},
-       {0x0000a074, 0x00000000},
-       {0x0000a078, 0x00000000},
-       {0x0000a07c, 0x00000000},
-       {0x0000a080, 0x22222229},
-       {0x0000a084, 0x1d1d1d1d},
-       {0x0000a088, 0x1d1d1d1d},
-       {0x0000a08c, 0x1d1d1d1d},
-       {0x0000a090, 0x171d1d1d},
-       {0x0000a094, 0x11111717},
-       {0x0000a098, 0x00030311},
-       {0x0000a09c, 0x00000000},
-       {0x0000a0a0, 0x00000000},
-       {0x0000a0a4, 0x00000000},
-       {0x0000a0a8, 0x00000000},
-       {0x0000a0ac, 0x00000000},
-       {0x0000a0b0, 0x00000000},
-       {0x0000a0b4, 0x00000000},
-       {0x0000a0b8, 0x00000000},
-       {0x0000a0bc, 0x00000000},
-       {0x0000a0c0, 0x001f0000},
-       {0x0000a0c4, 0x01000101},
-       {0x0000a0c8, 0x011e011f},
-       {0x0000a0cc, 0x011c011d},
-       {0x0000a0d0, 0x02030204},
-       {0x0000a0d4, 0x02010202},
-       {0x0000a0d8, 0x021f0200},
-       {0x0000a0dc, 0x0302021e},
-       {0x0000a0e0, 0x03000301},
-       {0x0000a0e4, 0x031e031f},
-       {0x0000a0e8, 0x0402031d},
-       {0x0000a0ec, 0x04000401},
-       {0x0000a0f0, 0x041e041f},
-       {0x0000a0f4, 0x0502041d},
-       {0x0000a0f8, 0x05000501},
-       {0x0000a0fc, 0x051e051f},
-       {0x0000a100, 0x06010602},
-       {0x0000a104, 0x061f0600},
-       {0x0000a108, 0x061d061e},
-       {0x0000a10c, 0x07020703},
-       {0x0000a110, 0x07000701},
-       {0x0000a114, 0x00000000},
-       {0x0000a118, 0x00000000},
-       {0x0000a11c, 0x00000000},
-       {0x0000a120, 0x00000000},
-       {0x0000a124, 0x00000000},
-       {0x0000a128, 0x00000000},
-       {0x0000a12c, 0x00000000},
-       {0x0000a130, 0x00000000},
-       {0x0000a134, 0x00000000},
-       {0x0000a138, 0x00000000},
-       {0x0000a13c, 0x00000000},
-       {0x0000a140, 0x001f0000},
-       {0x0000a144, 0x01000101},
-       {0x0000a148, 0x011e011f},
-       {0x0000a14c, 0x011c011d},
-       {0x0000a150, 0x02030204},
-       {0x0000a154, 0x02010202},
-       {0x0000a158, 0x021f0200},
-       {0x0000a15c, 0x0302021e},
-       {0x0000a160, 0x03000301},
-       {0x0000a164, 0x031e031f},
-       {0x0000a168, 0x0402031d},
-       {0x0000a16c, 0x04000401},
-       {0x0000a170, 0x041e041f},
-       {0x0000a174, 0x0502041d},
-       {0x0000a178, 0x05000501},
-       {0x0000a17c, 0x051e051f},
-       {0x0000a180, 0x06010602},
-       {0x0000a184, 0x061f0600},
-       {0x0000a188, 0x061d061e},
-       {0x0000a18c, 0x07020703},
-       {0x0000a190, 0x07000701},
-       {0x0000a194, 0x00000000},
-       {0x0000a198, 0x00000000},
-       {0x0000a19c, 0x00000000},
-       {0x0000a1a0, 0x00000000},
-       {0x0000a1a4, 0x00000000},
-       {0x0000a1a8, 0x00000000},
-       {0x0000a1ac, 0x00000000},
-       {0x0000a1b0, 0x00000000},
-       {0x0000a1b4, 0x00000000},
-       {0x0000a1b8, 0x00000000},
-       {0x0000a1bc, 0x00000000},
-       {0x0000a1c0, 0x00000000},
-       {0x0000a1c4, 0x00000000},
-       {0x0000a1c8, 0x00000000},
-       {0x0000a1cc, 0x00000000},
-       {0x0000a1d0, 0x00000000},
-       {0x0000a1d4, 0x00000000},
-       {0x0000a1d8, 0x00000000},
-       {0x0000a1dc, 0x00000000},
-       {0x0000a1e0, 0x00000000},
-       {0x0000a1e4, 0x00000000},
-       {0x0000a1e8, 0x00000000},
-       {0x0000a1ec, 0x00000000},
-       {0x0000a1f0, 0x00000396},
-       {0x0000a1f4, 0x00000396},
-       {0x0000a1f8, 0x00000396},
-       {0x0000a1fc, 0x00000196},
-       {0x0000b000, 0x00010000},
-       {0x0000b004, 0x00030002},
-       {0x0000b008, 0x00050004},
-       {0x0000b00c, 0x00810080},
-       {0x0000b010, 0x00830082},
-       {0x0000b014, 0x01810180},
-       {0x0000b018, 0x01830182},
-       {0x0000b01c, 0x01850184},
-       {0x0000b020, 0x02810280},
-       {0x0000b024, 0x02830282},
-       {0x0000b028, 0x02850284},
-       {0x0000b02c, 0x02890288},
-       {0x0000b030, 0x028b028a},
-       {0x0000b034, 0x0388028c},
-       {0x0000b038, 0x038a0389},
-       {0x0000b03c, 0x038c038b},
-       {0x0000b040, 0x0390038d},
-       {0x0000b044, 0x03920391},
-       {0x0000b048, 0x03940393},
-       {0x0000b04c, 0x03960395},
-       {0x0000b050, 0x00000000},
-       {0x0000b054, 0x00000000},
-       {0x0000b058, 0x00000000},
-       {0x0000b05c, 0x00000000},
-       {0x0000b060, 0x00000000},
-       {0x0000b064, 0x00000000},
-       {0x0000b068, 0x00000000},
-       {0x0000b06c, 0x00000000},
-       {0x0000b070, 0x00000000},
-       {0x0000b074, 0x00000000},
-       {0x0000b078, 0x00000000},
-       {0x0000b07c, 0x00000000},
-       {0x0000b080, 0x23232323},
-       {0x0000b084, 0x21232323},
-       {0x0000b088, 0x19191c1e},
-       {0x0000b08c, 0x12141417},
-       {0x0000b090, 0x07070e0e},
-       {0x0000b094, 0x03030305},
-       {0x0000b098, 0x00000003},
-       {0x0000b09c, 0x00000000},
-       {0x0000b0a0, 0x00000000},
-       {0x0000b0a4, 0x00000000},
-       {0x0000b0a8, 0x00000000},
-       {0x0000b0ac, 0x00000000},
-       {0x0000b0b0, 0x00000000},
-       {0x0000b0b4, 0x00000000},
-       {0x0000b0b8, 0x00000000},
-       {0x0000b0bc, 0x00000000},
-       {0x0000b0c0, 0x003f0020},
-       {0x0000b0c4, 0x00400041},
-       {0x0000b0c8, 0x0140005f},
-       {0x0000b0cc, 0x0160015f},
-       {0x0000b0d0, 0x017e017f},
-       {0x0000b0d4, 0x02410242},
-       {0x0000b0d8, 0x025f0240},
-       {0x0000b0dc, 0x027f0260},
-       {0x0000b0e0, 0x0341027e},
-       {0x0000b0e4, 0x035f0340},
-       {0x0000b0e8, 0x037f0360},
-       {0x0000b0ec, 0x04400441},
-       {0x0000b0f0, 0x0460045f},
-       {0x0000b0f4, 0x0541047f},
-       {0x0000b0f8, 0x055f0540},
-       {0x0000b0fc, 0x057f0560},
-       {0x0000b100, 0x06400641},
-       {0x0000b104, 0x0660065f},
-       {0x0000b108, 0x067e067f},
-       {0x0000b10c, 0x07410742},
-       {0x0000b110, 0x075f0740},
-       {0x0000b114, 0x077f0760},
-       {0x0000b118, 0x07800781},
-       {0x0000b11c, 0x07a0079f},
-       {0x0000b120, 0x07c107bf},
-       {0x0000b124, 0x000007c0},
-       {0x0000b128, 0x00000000},
-       {0x0000b12c, 0x00000000},
-       {0x0000b130, 0x00000000},
-       {0x0000b134, 0x00000000},
-       {0x0000b138, 0x00000000},
-       {0x0000b13c, 0x00000000},
-       {0x0000b140, 0x003f0020},
-       {0x0000b144, 0x00400041},
-       {0x0000b148, 0x0140005f},
-       {0x0000b14c, 0x0160015f},
-       {0x0000b150, 0x017e017f},
-       {0x0000b154, 0x02410242},
-       {0x0000b158, 0x025f0240},
-       {0x0000b15c, 0x027f0260},
-       {0x0000b160, 0x0341027e},
-       {0x0000b164, 0x035f0340},
-       {0x0000b168, 0x037f0360},
-       {0x0000b16c, 0x04400441},
-       {0x0000b170, 0x0460045f},
-       {0x0000b174, 0x0541047f},
-       {0x0000b178, 0x055f0540},
-       {0x0000b17c, 0x057f0560},
-       {0x0000b180, 0x06400641},
-       {0x0000b184, 0x0660065f},
-       {0x0000b188, 0x067e067f},
-       {0x0000b18c, 0x07410742},
-       {0x0000b190, 0x075f0740},
-       {0x0000b194, 0x077f0760},
-       {0x0000b198, 0x07800781},
-       {0x0000b19c, 0x07a0079f},
-       {0x0000b1a0, 0x07c107bf},
-       {0x0000b1a4, 0x000007c0},
-       {0x0000b1a8, 0x00000000},
-       {0x0000b1ac, 0x00000000},
-       {0x0000b1b0, 0x00000000},
-       {0x0000b1b4, 0x00000000},
-       {0x0000b1b8, 0x00000000},
-       {0x0000b1bc, 0x00000000},
-       {0x0000b1c0, 0x00000000},
-       {0x0000b1c4, 0x00000000},
-       {0x0000b1c8, 0x00000000},
-       {0x0000b1cc, 0x00000000},
-       {0x0000b1d0, 0x00000000},
-       {0x0000b1d4, 0x00000000},
-       {0x0000b1d8, 0x00000000},
-       {0x0000b1dc, 0x00000000},
-       {0x0000b1e0, 0x00000000},
-       {0x0000b1e4, 0x00000000},
-       {0x0000b1e8, 0x00000000},
-       {0x0000b1ec, 0x00000000},
-       {0x0000b1f0, 0x00000396},
-       {0x0000b1f4, 0x00000396},
-       {0x0000b1f8, 0x00000396},
-       {0x0000b1fc, 0x00000196},
-};
-
 static const u32 ar955x_1p0_baseband_core[][2] = {
        /* Addr      allmodes  */
        {0x00009800, 0xafe68e30},
@@ -891,266 +632,6 @@ static const u32 ar955x_1p0_baseband_core[][2] = {
        {0x0000c420, 0x00000000},
 };
 
-static const u32 ar955x_1p0_common_wo_xlna_rx_gain_table[][2] = {
-       /* Addr      allmodes  */
-       {0x0000a000, 0x00010000},
-       {0x0000a004, 0x00030002},
-       {0x0000a008, 0x00050004},
-       {0x0000a00c, 0x00810080},
-       {0x0000a010, 0x00830082},
-       {0x0000a014, 0x01810180},
-       {0x0000a018, 0x01830182},
-       {0x0000a01c, 0x01850184},
-       {0x0000a020, 0x01890188},
-       {0x0000a024, 0x018b018a},
-       {0x0000a028, 0x018d018c},
-       {0x0000a02c, 0x03820190},
-       {0x0000a030, 0x03840383},
-       {0x0000a034, 0x03880385},
-       {0x0000a038, 0x038a0389},
-       {0x0000a03c, 0x038c038b},
-       {0x0000a040, 0x0390038d},
-       {0x0000a044, 0x03920391},
-       {0x0000a048, 0x03940393},
-       {0x0000a04c, 0x03960395},
-       {0x0000a050, 0x00000000},
-       {0x0000a054, 0x00000000},
-       {0x0000a058, 0x00000000},
-       {0x0000a05c, 0x00000000},
-       {0x0000a060, 0x00000000},
-       {0x0000a064, 0x00000000},
-       {0x0000a068, 0x00000000},
-       {0x0000a06c, 0x00000000},
-       {0x0000a070, 0x00000000},
-       {0x0000a074, 0x00000000},
-       {0x0000a078, 0x00000000},
-       {0x0000a07c, 0x00000000},
-       {0x0000a080, 0x29292929},
-       {0x0000a084, 0x29292929},
-       {0x0000a088, 0x29292929},
-       {0x0000a08c, 0x29292929},
-       {0x0000a090, 0x22292929},
-       {0x0000a094, 0x1d1d2222},
-       {0x0000a098, 0x0c111117},
-       {0x0000a09c, 0x00030303},
-       {0x0000a0a0, 0x00000000},
-       {0x0000a0a4, 0x00000000},
-       {0x0000a0a8, 0x00000000},
-       {0x0000a0ac, 0x00000000},
-       {0x0000a0b0, 0x00000000},
-       {0x0000a0b4, 0x00000000},
-       {0x0000a0b8, 0x00000000},
-       {0x0000a0bc, 0x00000000},
-       {0x0000a0c0, 0x001f0000},
-       {0x0000a0c4, 0x01000101},
-       {0x0000a0c8, 0x011e011f},
-       {0x0000a0cc, 0x011c011d},
-       {0x0000a0d0, 0x02030204},
-       {0x0000a0d4, 0x02010202},
-       {0x0000a0d8, 0x021f0200},
-       {0x0000a0dc, 0x0302021e},
-       {0x0000a0e0, 0x03000301},
-       {0x0000a0e4, 0x031e031f},
-       {0x0000a0e8, 0x0402031d},
-       {0x0000a0ec, 0x04000401},
-       {0x0000a0f0, 0x041e041f},
-       {0x0000a0f4, 0x0502041d},
-       {0x0000a0f8, 0x05000501},
-       {0x0000a0fc, 0x051e051f},
-       {0x0000a100, 0x06010602},
-       {0x0000a104, 0x061f0600},
-       {0x0000a108, 0x061d061e},
-       {0x0000a10c, 0x07020703},
-       {0x0000a110, 0x07000701},
-       {0x0000a114, 0x00000000},
-       {0x0000a118, 0x00000000},
-       {0x0000a11c, 0x00000000},
-       {0x0000a120, 0x00000000},
-       {0x0000a124, 0x00000000},
-       {0x0000a128, 0x00000000},
-       {0x0000a12c, 0x00000000},
-       {0x0000a130, 0x00000000},
-       {0x0000a134, 0x00000000},
-       {0x0000a138, 0x00000000},
-       {0x0000a13c, 0x00000000},
-       {0x0000a140, 0x001f0000},
-       {0x0000a144, 0x01000101},
-       {0x0000a148, 0x011e011f},
-       {0x0000a14c, 0x011c011d},
-       {0x0000a150, 0x02030204},
-       {0x0000a154, 0x02010202},
-       {0x0000a158, 0x021f0200},
-       {0x0000a15c, 0x0302021e},
-       {0x0000a160, 0x03000301},
-       {0x0000a164, 0x031e031f},
-       {0x0000a168, 0x0402031d},
-       {0x0000a16c, 0x04000401},
-       {0x0000a170, 0x041e041f},
-       {0x0000a174, 0x0502041d},
-       {0x0000a178, 0x05000501},
-       {0x0000a17c, 0x051e051f},
-       {0x0000a180, 0x06010602},
-       {0x0000a184, 0x061f0600},
-       {0x0000a188, 0x061d061e},
-       {0x0000a18c, 0x07020703},
-       {0x0000a190, 0x07000701},
-       {0x0000a194, 0x00000000},
-       {0x0000a198, 0x00000000},
-       {0x0000a19c, 0x00000000},
-       {0x0000a1a0, 0x00000000},
-       {0x0000a1a4, 0x00000000},
-       {0x0000a1a8, 0x00000000},
-       {0x0000a1ac, 0x00000000},
-       {0x0000a1b0, 0x00000000},
-       {0x0000a1b4, 0x00000000},
-       {0x0000a1b8, 0x00000000},
-       {0x0000a1bc, 0x00000000},
-       {0x0000a1c0, 0x00000000},
-       {0x0000a1c4, 0x00000000},
-       {0x0000a1c8, 0x00000000},
-       {0x0000a1cc, 0x00000000},
-       {0x0000a1d0, 0x00000000},
-       {0x0000a1d4, 0x00000000},
-       {0x0000a1d8, 0x00000000},
-       {0x0000a1dc, 0x00000000},
-       {0x0000a1e0, 0x00000000},
-       {0x0000a1e4, 0x00000000},
-       {0x0000a1e8, 0x00000000},
-       {0x0000a1ec, 0x00000000},
-       {0x0000a1f0, 0x00000396},
-       {0x0000a1f4, 0x00000396},
-       {0x0000a1f8, 0x00000396},
-       {0x0000a1fc, 0x00000196},
-       {0x0000b000, 0x00010000},
-       {0x0000b004, 0x00030002},
-       {0x0000b008, 0x00050004},
-       {0x0000b00c, 0x00810080},
-       {0x0000b010, 0x00830082},
-       {0x0000b014, 0x01810180},
-       {0x0000b018, 0x01830182},
-       {0x0000b01c, 0x01850184},
-       {0x0000b020, 0x02810280},
-       {0x0000b024, 0x02830282},
-       {0x0000b028, 0x02850284},
-       {0x0000b02c, 0x02890288},
-       {0x0000b030, 0x028b028a},
-       {0x0000b034, 0x0388028c},
-       {0x0000b038, 0x038a0389},
-       {0x0000b03c, 0x038c038b},
-       {0x0000b040, 0x0390038d},
-       {0x0000b044, 0x03920391},
-       {0x0000b048, 0x03940393},
-       {0x0000b04c, 0x03960395},
-       {0x0000b050, 0x00000000},
-       {0x0000b054, 0x00000000},
-       {0x0000b058, 0x00000000},
-       {0x0000b05c, 0x00000000},
-       {0x0000b060, 0x00000000},
-       {0x0000b064, 0x00000000},
-       {0x0000b068, 0x00000000},
-       {0x0000b06c, 0x00000000},
-       {0x0000b070, 0x00000000},
-       {0x0000b074, 0x00000000},
-       {0x0000b078, 0x00000000},
-       {0x0000b07c, 0x00000000},
-       {0x0000b080, 0x32323232},
-       {0x0000b084, 0x2f2f3232},
-       {0x0000b088, 0x23282a2d},
-       {0x0000b08c, 0x1c1e2123},
-       {0x0000b090, 0x14171919},
-       {0x0000b094, 0x0e0e1214},
-       {0x0000b098, 0x03050707},
-       {0x0000b09c, 0x00030303},
-       {0x0000b0a0, 0x00000000},
-       {0x0000b0a4, 0x00000000},
-       {0x0000b0a8, 0x00000000},
-       {0x0000b0ac, 0x00000000},
-       {0x0000b0b0, 0x00000000},
-       {0x0000b0b4, 0x00000000},
-       {0x0000b0b8, 0x00000000},
-       {0x0000b0bc, 0x00000000},
-       {0x0000b0c0, 0x003f0020},
-       {0x0000b0c4, 0x00400041},
-       {0x0000b0c8, 0x0140005f},
-       {0x0000b0cc, 0x0160015f},
-       {0x0000b0d0, 0x017e017f},
-       {0x0000b0d4, 0x02410242},
-       {0x0000b0d8, 0x025f0240},
-       {0x0000b0dc, 0x027f0260},
-       {0x0000b0e0, 0x0341027e},
-       {0x0000b0e4, 0x035f0340},
-       {0x0000b0e8, 0x037f0360},
-       {0x0000b0ec, 0x04400441},
-       {0x0000b0f0, 0x0460045f},
-       {0x0000b0f4, 0x0541047f},
-       {0x0000b0f8, 0x055f0540},
-       {0x0000b0fc, 0x057f0560},
-       {0x0000b100, 0x06400641},
-       {0x0000b104, 0x0660065f},
-       {0x0000b108, 0x067e067f},
-       {0x0000b10c, 0x07410742},
-       {0x0000b110, 0x075f0740},
-       {0x0000b114, 0x077f0760},
-       {0x0000b118, 0x07800781},
-       {0x0000b11c, 0x07a0079f},
-       {0x0000b120, 0x07c107bf},
-       {0x0000b124, 0x000007c0},
-       {0x0000b128, 0x00000000},
-       {0x0000b12c, 0x00000000},
-       {0x0000b130, 0x00000000},
-       {0x0000b134, 0x00000000},
-       {0x0000b138, 0x00000000},
-       {0x0000b13c, 0x00000000},
-       {0x0000b140, 0x003f0020},
-       {0x0000b144, 0x00400041},
-       {0x0000b148, 0x0140005f},
-       {0x0000b14c, 0x0160015f},
-       {0x0000b150, 0x017e017f},
-       {0x0000b154, 0x02410242},
-       {0x0000b158, 0x025f0240},
-       {0x0000b15c, 0x027f0260},
-       {0x0000b160, 0x0341027e},
-       {0x0000b164, 0x035f0340},
-       {0x0000b168, 0x037f0360},
-       {0x0000b16c, 0x04400441},
-       {0x0000b170, 0x0460045f},
-       {0x0000b174, 0x0541047f},
-       {0x0000b178, 0x055f0540},
-       {0x0000b17c, 0x057f0560},
-       {0x0000b180, 0x06400641},
-       {0x0000b184, 0x0660065f},
-       {0x0000b188, 0x067e067f},
-       {0x0000b18c, 0x07410742},
-       {0x0000b190, 0x075f0740},
-       {0x0000b194, 0x077f0760},
-       {0x0000b198, 0x07800781},
-       {0x0000b19c, 0x07a0079f},
-       {0x0000b1a0, 0x07c107bf},
-       {0x0000b1a4, 0x000007c0},
-       {0x0000b1a8, 0x00000000},
-       {0x0000b1ac, 0x00000000},
-       {0x0000b1b0, 0x00000000},
-       {0x0000b1b4, 0x00000000},
-       {0x0000b1b8, 0x00000000},
-       {0x0000b1bc, 0x00000000},
-       {0x0000b1c0, 0x00000000},
-       {0x0000b1c4, 0x00000000},
-       {0x0000b1c8, 0x00000000},
-       {0x0000b1cc, 0x00000000},
-       {0x0000b1d0, 0x00000000},
-       {0x0000b1d4, 0x00000000},
-       {0x0000b1d8, 0x00000000},
-       {0x0000b1dc, 0x00000000},
-       {0x0000b1e0, 0x00000000},
-       {0x0000b1e4, 0x00000000},
-       {0x0000b1e8, 0x00000000},
-       {0x0000b1ec, 0x00000000},
-       {0x0000b1f0, 0x00000396},
-       {0x0000b1f4, 0x00000396},
-       {0x0000b1f8, 0x00000396},
-       {0x0000b1fc, 0x00000196},
-};
-
 static const u32 ar955x_1p0_soc_preamble[][2] = {
        /* Addr      allmodes  */
        {0x00007000, 0x00000000},
@@ -1263,11 +744,6 @@ static const u32 ar955x_1p0_modes_no_xpa_tx_gain_table[][9] = {
        {0x00016848, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401},
 };
 
-static const u32 ar955x_1p0_soc_postamble[][5] = {
-       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-       {0x00007010, 0x00000023, 0x00000023, 0x00000023, 0x00000023},
-};
-
 static const u32 ar955x_1p0_modes_fast_clock[][3] = {
        /* Addr      5G_HT20     5G_HT40   */
        {0x00001030, 0x00000268, 0x000004d0},
index a8c757b6124fdac483e21149733c18944f160fd7..10d4a6cb1c3b96730d3056a70aa27124ebd8c5b0 100644 (file)
 
 /* AR9565 1.0 */
 
+#define ar9565_1p0_mac_postamble ar9331_1p1_mac_postamble
+
+#define ar9565_1p0_Modes_lowest_ob_db_tx_gain_table ar9565_1p0_modes_low_ob_db_tx_gain_table
+
+#define ar9565_1p0_baseband_core_txfir_coeff_japan_2484 ar9300_2p2_baseband_core_txfir_coeff_japan_2484
+
 static const u32 ar9565_1p0_mac_core[][2] = {
        /* Addr      allmodes  */
        {0x00000008, 0x00000000},
@@ -182,18 +188,6 @@ static const u32 ar9565_1p0_mac_core[][2] = {
        {0x000083d0, 0x800301ff},
 };
 
-static const u32 ar9565_1p0_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 ar9565_1p0_baseband_core[][2] = {
        /* Addr      allmodes  */
        {0x00009800, 0xafe68e30},
@@ -711,66 +705,6 @@ static const u32 ar9565_1p0_Common_rx_gain_table[][2] = {
        {0x0000b1fc, 0x00000196},
 };
 
-static const u32 ar9565_1p0_Modes_lowest_ob_db_tx_gain_table[][5] = {
-       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-       {0x0000a2dc, 0xfc0a9380, 0xfc0a9380, 0xfdab5b52, 0xfdab5b52},
-       {0x0000a2e0, 0xffecec00, 0xffecec00, 0xfd339c84, 0xfd339c84},
-       {0x0000a2e4, 0xfc0f0000, 0xfc0f0000, 0xfec3e000, 0xfec3e000},
-       {0x0000a2e8, 0xfc100000, 0xfc100000, 0xfffc0000, 0xfffc0000},
-       {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
-       {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
-       {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
-       {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
-       {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
-       {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400},
-       {0x0000a518, 0x21020220, 0x21020220, 0x16000402, 0x16000402},
-       {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404},
-       {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603},
-       {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02},
-       {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04},
-       {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20},
-       {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20},
-       {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22},
-       {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
-       {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
-       {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
-       {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861},
-       {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81},
-       {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x47001a83, 0x47001a83},
-       {0x0000a550, 0x61042a6c, 0x61042a6c, 0x4a001c84, 0x4a001c84},
-       {0x0000a554, 0x66062a6c, 0x66062a6c, 0x4e001ce3, 0x4e001ce3},
-       {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x52001ce5, 0x52001ce5},
-       {0x0000a55c, 0x7006308c, 0x7006308c, 0x56001ce9, 0x56001ce9},
-       {0x0000a560, 0x730a308a, 0x730a308a, 0x5a001ceb, 0x5a001ceb},
-       {0x0000a564, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
-       {0x0000a568, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
-       {0x0000a56c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
-       {0x0000a570, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
-       {0x0000a574, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
-       {0x0000a578, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
-       {0x0000a57c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec},
-       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a614, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a618, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a61c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a620, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a624, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a628, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a62c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a630, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a634, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a638, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a63c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x00016044, 0x012482d4, 0x012482d4, 0x012482d4, 0x012482d4},
-       {0x00016048, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x00016054, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-};
-
 static const u32 ar9565_1p0_pciephy_clkreq_disable_L1[][2] = {
        /* Addr      allmodes  */
        {0x00018c00, 0x18212ede},
@@ -1231,11 +1165,4 @@ 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/ar9565_1p1_initvals.h b/drivers/net/wireless/ath/ath9k/ar9565_1p1_initvals.h
new file mode 100644 (file)
index 0000000..5681053
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ * Copyright (c) 2011-2012 Qualcomm Atheros Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef INITVALS_9565_1P1_H
+#define INITVALS_9565_1P1_H
+
+/* AR9565 1.1 */
+
+#define ar9565_1p1_mac_core ar9565_1p0_mac_core
+
+#define ar9565_1p1_mac_postamble ar9565_1p0_mac_postamble
+
+#define ar9565_1p1_baseband_core ar9565_1p0_baseband_core
+
+#define ar9565_1p1_baseband_postamble ar9565_1p0_baseband_postamble
+
+#define ar9565_1p1_radio_core ar9565_1p0_radio_core
+
+#define ar9565_1p1_soc_preamble ar9565_1p0_soc_preamble
+
+#define ar9565_1p1_soc_postamble ar9565_1p0_soc_postamble
+
+#define ar9565_1p1_Common_rx_gain_table ar9565_1p0_Common_rx_gain_table
+
+#define ar9565_1p1_Modes_lowest_ob_db_tx_gain_table ar9565_1p0_Modes_lowest_ob_db_tx_gain_table
+
+#define ar9565_1p1_pciephy_clkreq_disable_L1 ar9565_1p0_pciephy_clkreq_disable_L1
+
+#define ar9565_1p1_modes_fast_clock ar9565_1p0_modes_fast_clock
+
+#define ar9565_1p1_common_wo_xlna_rx_gain_table ar9565_1p0_common_wo_xlna_rx_gain_table
+
+#define ar9565_1p1_modes_low_ob_db_tx_gain_table ar9565_1p0_modes_low_ob_db_tx_gain_table
+
+#define ar9565_1p1_modes_high_ob_db_tx_gain_table ar9565_1p0_modes_high_ob_db_tx_gain_table
+
+#define ar9565_1p1_modes_high_power_tx_gain_table ar9565_1p0_modes_high_power_tx_gain_table
+
+#define ar9565_1p1_baseband_core_txfir_coeff_japan_2484 ar9565_1p0_baseband_core_txfir_coeff_japan_2484
+
+static const u32 ar9565_1p1_radio_postamble[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0001609c, 0x0b8ee524, 0x0b8ee524, 0x0b8ee524, 0x0b8ee524},
+       {0x000160ac, 0xa4646c08, 0xa4646c08, 0x24645808, 0x24645808},
+       {0x000160b0, 0x01d67f70, 0x01d67f70, 0x01d67f70, 0x01d67f70},
+       {0x0001610c, 0x40000000, 0x40000000, 0x40000000, 0x40000000},
+       {0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
+};
+
+#endif /* INITVALS_9565_1P1_H */
index bdee2ed67219b6e1c56a0f03a6a28391ba3283aa..e6aec2c0207ff43754a79a236a769a33bacf401e 100644 (file)
 
 /* AR9580 1.0 */
 
+#define ar9580_1p0_soc_preamble ar9300_2p2_soc_preamble
+
+#define ar9580_1p0_soc_postamble ar9300_2p2_soc_postamble
+
+#define ar9580_1p0_radio_core ar9300_2p2_radio_core
+
+#define ar9580_1p0_mac_postamble ar9300_2p2_mac_postamble
+
+#define ar9580_1p0_wo_xlna_rx_gain_table ar9300Common_wo_xlna_rx_gain_table_2p2
+
+#define ar9580_1p0_type5_tx_gain_table ar9300Modes_type5_tx_gain_table_2p2
+
+#define ar9580_1p0_high_ob_db_tx_gain_table ar9300Modes_high_ob_db_tx_gain_table_2p2
+
 #define ar9580_1p0_modes_fast_clock ar9300Modes_fast_clock_2p2
 
+#define ar9580_1p0_baseband_core_txfir_coeff_japan_2484 ar9300_2p2_baseband_core_txfir_coeff_japan_2484
+
 static const u32 ar9580_1p0_radio_postamble[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
        {0x0001609c, 0x0dd08f29, 0x0dd08f29, 0x0b283f31, 0x0b283f31},
        {0x000160ac, 0xa4653c00, 0xa4653c00, 0x24652800, 0x24652800},
        {0x000160b0, 0x03284f3e, 0x03284f3e, 0x05d08f20, 0x05d08f20},
-       {0x0001610c, 0x08000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0001610c, 0xc8000000, 0xc0000000, 0xc0000000, 0xc0000000},
        {0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
-       {0x0001650c, 0x08000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0001650c, 0xc8000000, 0xc0000000, 0xc0000000, 0xc0000000},
        {0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
-       {0x0001690c, 0x08000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0001690c, 0xc8000000, 0xc0000000, 0xc0000000, 0xc0000000},
        {0x00016940, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
 };
 
@@ -41,12 +57,10 @@ static const u32 ar9580_1p0_baseband_core[][2] = {
        {0x00009804, 0xfd14e000},
        {0x00009808, 0x9c0a9f6b},
        {0x0000980c, 0x04900000},
-       {0x00009814, 0x3280c00a},
-       {0x00009818, 0x00000000},
        {0x0000981c, 0x00020028},
-       {0x00009834, 0x6400a290},
+       {0x00009834, 0x6400a190},
        {0x00009838, 0x0108ecff},
-       {0x0000983c, 0x0d000600},
+       {0x0000983c, 0x14000600},
        {0x00009880, 0x201fff00},
        {0x00009884, 0x00001042},
        {0x000098a4, 0x00200400},
@@ -67,7 +81,7 @@ static const u32 ar9580_1p0_baseband_core[][2] = {
        {0x00009d04, 0x40206c10},
        {0x00009d08, 0x009c4060},
        {0x00009d0c, 0x9883800a},
-       {0x00009d10, 0x01834061},
+       {0x00009d10, 0x01884061},
        {0x00009d14, 0x00c0040b},
        {0x00009d18, 0x00000000},
        {0x00009e08, 0x0038230c},
@@ -198,8 +212,6 @@ static const u32 ar9580_1p0_baseband_core[][2] = {
        {0x0000c420, 0x00000000},
 };
 
-#define ar9580_1p0_mac_postamble ar9300_2p2_mac_postamble
-
 static const u32 ar9580_1p0_low_ob_db_tx_gain_table[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
        {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352},
@@ -306,7 +318,112 @@ static const u32 ar9580_1p0_low_ob_db_tx_gain_table[][5] = {
        {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
 };
 
-#define ar9580_1p0_high_power_tx_gain_table ar9580_1p0_low_ob_db_tx_gain_table
+static const u32 ar9580_1p0_high_power_tx_gain_table[][5] = {
+       /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
+       {0x0000a2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
+       {0x0000a2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
+       {0x0000a2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
+       {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+       {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
+       {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
+       {0x0000a510, 0x15000028, 0x15000028, 0x0f000202, 0x0f000202},
+       {0x0000a514, 0x1b00002b, 0x1b00002b, 0x12000400, 0x12000400},
+       {0x0000a518, 0x1f020028, 0x1f020028, 0x16000402, 0x16000402},
+       {0x0000a51c, 0x2502002b, 0x2502002b, 0x19000404, 0x19000404},
+       {0x0000a520, 0x2a04002a, 0x2a04002a, 0x1c000603, 0x1c000603},
+       {0x0000a524, 0x2e06002a, 0x2e06002a, 0x21000a02, 0x21000a02},
+       {0x0000a528, 0x3302202d, 0x3302202d, 0x25000a04, 0x25000a04},
+       {0x0000a52c, 0x3804202c, 0x3804202c, 0x28000a20, 0x28000a20},
+       {0x0000a530, 0x3c06202c, 0x3c06202c, 0x2c000e20, 0x2c000e20},
+       {0x0000a534, 0x4108202d, 0x4108202d, 0x30000e22, 0x30000e22},
+       {0x0000a538, 0x4506402d, 0x4506402d, 0x34000e24, 0x34000e24},
+       {0x0000a53c, 0x4906222d, 0x4906222d, 0x38001640, 0x38001640},
+       {0x0000a540, 0x4d062231, 0x4d062231, 0x3c001660, 0x3c001660},
+       {0x0000a544, 0x50082231, 0x50082231, 0x3f001861, 0x3f001861},
+       {0x0000a548, 0x5608422e, 0x5608422e, 0x43001a81, 0x43001a81},
+       {0x0000a54c, 0x5e08442e, 0x5e08442e, 0x47001a83, 0x47001a83},
+       {0x0000a550, 0x620a4431, 0x620a4431, 0x4a001c84, 0x4a001c84},
+       {0x0000a554, 0x640a4432, 0x640a4432, 0x4e001ce3, 0x4e001ce3},
+       {0x0000a558, 0x680a4434, 0x680a4434, 0x52001ce5, 0x52001ce5},
+       {0x0000a55c, 0x6c0a6434, 0x6c0a6434, 0x56001ce9, 0x56001ce9},
+       {0x0000a560, 0x6f0a6633, 0x6f0a6633, 0x5a001ceb, 0x5a001ceb},
+       {0x0000a564, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+       {0x0000a568, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+       {0x0000a56c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+       {0x0000a570, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+       {0x0000a574, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+       {0x0000a578, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+       {0x0000a57c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+       {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
+       {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
+       {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
+       {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200},
+       {0x0000a590, 0x15800028, 0x15800028, 0x0f800202, 0x0f800202},
+       {0x0000a594, 0x1b80002b, 0x1b80002b, 0x12800400, 0x12800400},
+       {0x0000a598, 0x1f820028, 0x1f820028, 0x16800402, 0x16800402},
+       {0x0000a59c, 0x2582002b, 0x2582002b, 0x19800404, 0x19800404},
+       {0x0000a5a0, 0x2a84002a, 0x2a84002a, 0x1c800603, 0x1c800603},
+       {0x0000a5a4, 0x2e86002a, 0x2e86002a, 0x21800a02, 0x21800a02},
+       {0x0000a5a8, 0x3382202d, 0x3382202d, 0x25800a04, 0x25800a04},
+       {0x0000a5ac, 0x3884202c, 0x3884202c, 0x28800a20, 0x28800a20},
+       {0x0000a5b0, 0x3c86202c, 0x3c86202c, 0x2c800e20, 0x2c800e20},
+       {0x0000a5b4, 0x4188202d, 0x4188202d, 0x30800e22, 0x30800e22},
+       {0x0000a5b8, 0x4586402d, 0x4586402d, 0x34800e24, 0x34800e24},
+       {0x0000a5bc, 0x4986222d, 0x4986222d, 0x38801640, 0x38801640},
+       {0x0000a5c0, 0x4d862231, 0x4d862231, 0x3c801660, 0x3c801660},
+       {0x0000a5c4, 0x50882231, 0x50882231, 0x3f801861, 0x3f801861},
+       {0x0000a5c8, 0x5688422e, 0x5688422e, 0x43801a81, 0x43801a81},
+       {0x0000a5cc, 0x5a88442e, 0x5a88442e, 0x47801a83, 0x47801a83},
+       {0x0000a5d0, 0x5e8a4431, 0x5e8a4431, 0x4a801c84, 0x4a801c84},
+       {0x0000a5d4, 0x648a4432, 0x648a4432, 0x4e801ce3, 0x4e801ce3},
+       {0x0000a5d8, 0x688a4434, 0x688a4434, 0x52801ce5, 0x52801ce5},
+       {0x0000a5dc, 0x6c8a6434, 0x6c8a6434, 0x56801ce9, 0x56801ce9},
+       {0x0000a5e0, 0x6f8a6633, 0x6f8a6633, 0x5a801ceb, 0x5a801ceb},
+       {0x0000a5e4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+       {0x0000a5e8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+       {0x0000a5ec, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f0, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+       {0x0000a5fc, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a608, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
+       {0x0000a610, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
+       {0x0000a614, 0x01804601, 0x01804601, 0x01404000, 0x01404000},
+       {0x0000a618, 0x01804601, 0x01804601, 0x01404501, 0x01404501},
+       {0x0000a61c, 0x01804601, 0x01804601, 0x02008501, 0x02008501},
+       {0x0000a620, 0x03408d02, 0x03408d02, 0x0280ca03, 0x0280ca03},
+       {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
+       {0x0000a628, 0x03410d04, 0x03410d04, 0x04014c04, 0x04014c04},
+       {0x0000a62c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
+       {0x0000a630, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
+       {0x0000a634, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
+       {0x0000a638, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
+       {0x0000a63c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
+       {0x0000b2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
+       {0x0000b2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
+       {0x0000b2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
+       {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x0000c2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
+       {0x0000c2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
+       {0x0000c2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
+       {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
+       {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+       {0x00016048, 0x65240001, 0x65240001, 0x66480001, 0x66480001},
+       {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+       {0x00016288, 0x05a2040a, 0x05a2040a, 0x05a20408, 0x05a20408},
+       {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+       {0x00016448, 0x65240001, 0x65240001, 0x66480001, 0x66480001},
+       {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+       {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
+       {0x00016848, 0x65240001, 0x65240001, 0x66480001, 0x66480001},
+       {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
+};
 
 static const u32 ar9580_1p0_lowest_ob_db_tx_gain_table[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
@@ -414,8 +531,6 @@ static const u32 ar9580_1p0_lowest_ob_db_tx_gain_table[][5] = {
        {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
 };
 
-#define ar9580_1p0_baseband_core_txfir_coeff_japan_2484 ar9462_2p0_baseband_core_txfir_coeff_japan_2484
-
 static const u32 ar9580_1p0_mac_core[][2] = {
        /* Addr      allmodes  */
        {0x00000008, 0x00000000},
@@ -679,14 +794,6 @@ static const u32 ar9580_1p0_mixed_ob_db_tx_gain_table[][5] = {
        {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
 };
 
-#define ar9580_1p0_wo_xlna_rx_gain_table ar9300Common_wo_xlna_rx_gain_table_2p2
-
-#define ar9580_1p0_soc_postamble ar9300_2p2_soc_postamble
-
-#define ar9580_1p0_high_ob_db_tx_gain_table ar9300Modes_high_ob_db_tx_gain_table_2p2
-
-#define ar9580_1p0_type5_tx_gain_table ar9300Modes_type5_tx_gain_table_2p2
-
 static const u32 ar9580_1p0_type6_tx_gain_table[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
        {0x0000a2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
@@ -761,165 +868,271 @@ static const u32 ar9580_1p0_type6_tx_gain_table[][5] = {
        {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
 };
 
-static const u32 ar9580_1p0_soc_preamble[][2] = {
+static const u32 ar9580_1p0_rx_gain_table[][2] = {
        /* Addr      allmodes  */
-       {0x000040a4, 0x00a0c1c9},
-       {0x00007008, 0x00000000},
-       {0x00007020, 0x00000000},
-       {0x00007034, 0x00000002},
-       {0x00007038, 0x000004c2},
-       {0x00007048, 0x00000008},
-};
-
-#define ar9580_1p0_rx_gain_table ar9462_common_rx_gain_table_2p0
-
-static const u32 ar9580_1p0_radio_core[][2] = {
-       /* Addr      allmodes  */
-       {0x00016000, 0x36db6db6},
-       {0x00016004, 0x6db6db40},
-       {0x00016008, 0x73f00000},
-       {0x0001600c, 0x00000000},
-       {0x00016040, 0x7f80fff8},
-       {0x0001604c, 0x76d005b5},
-       {0x00016050, 0x556cf031},
-       {0x00016054, 0x13449440},
-       {0x00016058, 0x0c51c92c},
-       {0x0001605c, 0x3db7fffc},
-       {0x00016060, 0xfffffffc},
-       {0x00016064, 0x000f0278},
-       {0x0001606c, 0x6db60000},
-       {0x00016080, 0x00000000},
-       {0x00016084, 0x0e48048c},
-       {0x00016088, 0x54214514},
-       {0x0001608c, 0x119f481e},
-       {0x00016090, 0x24926490},
-       {0x00016098, 0xd2888888},
-       {0x000160a0, 0x0a108ffe},
-       {0x000160a4, 0x812fc370},
-       {0x000160a8, 0x423c8000},
-       {0x000160b4, 0x92480080},
-       {0x000160c0, 0x00adb6d0},
-       {0x000160c4, 0x6db6db60},
-       {0x000160c8, 0x6db6db6c},
-       {0x000160cc, 0x01e6c000},
-       {0x00016100, 0x3fffbe01},
-       {0x00016104, 0xfff80000},
-       {0x00016108, 0x00080010},
-       {0x00016144, 0x02084080},
-       {0x00016148, 0x00000000},
-       {0x00016280, 0x058a0001},
-       {0x00016284, 0x3d840208},
-       {0x00016288, 0x05a20408},
-       {0x0001628c, 0x00038c07},
-       {0x00016290, 0x00000004},
-       {0x00016294, 0x458aa14f},
-       {0x00016380, 0x00000000},
-       {0x00016384, 0x00000000},
-       {0x00016388, 0x00800700},
-       {0x0001638c, 0x00800700},
-       {0x00016390, 0x00800700},
-       {0x00016394, 0x00000000},
-       {0x00016398, 0x00000000},
-       {0x0001639c, 0x00000000},
-       {0x000163a0, 0x00000001},
-       {0x000163a4, 0x00000001},
-       {0x000163a8, 0x00000000},
-       {0x000163ac, 0x00000000},
-       {0x000163b0, 0x00000000},
-       {0x000163b4, 0x00000000},
-       {0x000163b8, 0x00000000},
-       {0x000163bc, 0x00000000},
-       {0x000163c0, 0x000000a0},
-       {0x000163c4, 0x000c0000},
-       {0x000163c8, 0x14021402},
-       {0x000163cc, 0x00001402},
-       {0x000163d0, 0x00000000},
-       {0x000163d4, 0x00000000},
-       {0x00016400, 0x36db6db6},
-       {0x00016404, 0x6db6db40},
-       {0x00016408, 0x73f00000},
-       {0x0001640c, 0x00000000},
-       {0x00016440, 0x7f80fff8},
-       {0x0001644c, 0x76d005b5},
-       {0x00016450, 0x556cf031},
-       {0x00016454, 0x13449440},
-       {0x00016458, 0x0c51c92c},
-       {0x0001645c, 0x3db7fffc},
-       {0x00016460, 0xfffffffc},
-       {0x00016464, 0x000f0278},
-       {0x0001646c, 0x6db60000},
-       {0x00016500, 0x3fffbe01},
-       {0x00016504, 0xfff80000},
-       {0x00016508, 0x00080010},
-       {0x00016544, 0x02084080},
-       {0x00016548, 0x00000000},
-       {0x00016780, 0x00000000},
-       {0x00016784, 0x00000000},
-       {0x00016788, 0x00800700},
-       {0x0001678c, 0x00800700},
-       {0x00016790, 0x00800700},
-       {0x00016794, 0x00000000},
-       {0x00016798, 0x00000000},
-       {0x0001679c, 0x00000000},
-       {0x000167a0, 0x00000001},
-       {0x000167a4, 0x00000001},
-       {0x000167a8, 0x00000000},
-       {0x000167ac, 0x00000000},
-       {0x000167b0, 0x00000000},
-       {0x000167b4, 0x00000000},
-       {0x000167b8, 0x00000000},
-       {0x000167bc, 0x00000000},
-       {0x000167c0, 0x000000a0},
-       {0x000167c4, 0x000c0000},
-       {0x000167c8, 0x14021402},
-       {0x000167cc, 0x00001402},
-       {0x000167d0, 0x00000000},
-       {0x000167d4, 0x00000000},
-       {0x00016800, 0x36db6db6},
-       {0x00016804, 0x6db6db40},
-       {0x00016808, 0x73f00000},
-       {0x0001680c, 0x00000000},
-       {0x00016840, 0x7f80fff8},
-       {0x0001684c, 0x76d005b5},
-       {0x00016850, 0x556cf031},
-       {0x00016854, 0x13449440},
-       {0x00016858, 0x0c51c92c},
-       {0x0001685c, 0x3db7fffc},
-       {0x00016860, 0xfffffffc},
-       {0x00016864, 0x000f0278},
-       {0x0001686c, 0x6db60000},
-       {0x00016900, 0x3fffbe01},
-       {0x00016904, 0xfff80000},
-       {0x00016908, 0x00080010},
-       {0x00016944, 0x02084080},
-       {0x00016948, 0x00000000},
-       {0x00016b80, 0x00000000},
-       {0x00016b84, 0x00000000},
-       {0x00016b88, 0x00800700},
-       {0x00016b8c, 0x00800700},
-       {0x00016b90, 0x00800700},
-       {0x00016b94, 0x00000000},
-       {0x00016b98, 0x00000000},
-       {0x00016b9c, 0x00000000},
-       {0x00016ba0, 0x00000001},
-       {0x00016ba4, 0x00000001},
-       {0x00016ba8, 0x00000000},
-       {0x00016bac, 0x00000000},
-       {0x00016bb0, 0x00000000},
-       {0x00016bb4, 0x00000000},
-       {0x00016bb8, 0x00000000},
-       {0x00016bbc, 0x00000000},
-       {0x00016bc0, 0x000000a0},
-       {0x00016bc4, 0x000c0000},
-       {0x00016bc8, 0x14021402},
-       {0x00016bcc, 0x00001402},
-       {0x00016bd0, 0x00000000},
-       {0x00016bd4, 0x00000000},
+       {0x0000a000, 0x00010000},
+       {0x0000a004, 0x00030002},
+       {0x0000a008, 0x00050004},
+       {0x0000a00c, 0x00810080},
+       {0x0000a010, 0x00830082},
+       {0x0000a014, 0x01810180},
+       {0x0000a018, 0x01830182},
+       {0x0000a01c, 0x01850184},
+       {0x0000a020, 0x01890188},
+       {0x0000a024, 0x018b018a},
+       {0x0000a028, 0x018d018c},
+       {0x0000a02c, 0x01910190},
+       {0x0000a030, 0x01930192},
+       {0x0000a034, 0x01950194},
+       {0x0000a038, 0x038a0196},
+       {0x0000a03c, 0x038c038b},
+       {0x0000a040, 0x0390038d},
+       {0x0000a044, 0x03920391},
+       {0x0000a048, 0x03940393},
+       {0x0000a04c, 0x03960395},
+       {0x0000a050, 0x00000000},
+       {0x0000a054, 0x00000000},
+       {0x0000a058, 0x00000000},
+       {0x0000a05c, 0x00000000},
+       {0x0000a060, 0x00000000},
+       {0x0000a064, 0x00000000},
+       {0x0000a068, 0x00000000},
+       {0x0000a06c, 0x00000000},
+       {0x0000a070, 0x00000000},
+       {0x0000a074, 0x00000000},
+       {0x0000a078, 0x00000000},
+       {0x0000a07c, 0x00000000},
+       {0x0000a080, 0x22222229},
+       {0x0000a084, 0x1d1d1d1d},
+       {0x0000a088, 0x1d1d1d1d},
+       {0x0000a08c, 0x1d1d1d1d},
+       {0x0000a090, 0x171d1d1d},
+       {0x0000a094, 0x11111717},
+       {0x0000a098, 0x00030311},
+       {0x0000a09c, 0x00000000},
+       {0x0000a0a0, 0x00000000},
+       {0x0000a0a4, 0x00000000},
+       {0x0000a0a8, 0x00000000},
+       {0x0000a0ac, 0x00000000},
+       {0x0000a0b0, 0x00000000},
+       {0x0000a0b4, 0x00000000},
+       {0x0000a0b8, 0x00000000},
+       {0x0000a0bc, 0x00000000},
+       {0x0000a0c0, 0x001f0000},
+       {0x0000a0c4, 0x01000101},
+       {0x0000a0c8, 0x011e011f},
+       {0x0000a0cc, 0x011c011d},
+       {0x0000a0d0, 0x02030204},
+       {0x0000a0d4, 0x02010202},
+       {0x0000a0d8, 0x021f0200},
+       {0x0000a0dc, 0x0302021e},
+       {0x0000a0e0, 0x03000301},
+       {0x0000a0e4, 0x031e031f},
+       {0x0000a0e8, 0x0402031d},
+       {0x0000a0ec, 0x04000401},
+       {0x0000a0f0, 0x041e041f},
+       {0x0000a0f4, 0x0502041d},
+       {0x0000a0f8, 0x05000501},
+       {0x0000a0fc, 0x051e051f},
+       {0x0000a100, 0x06010602},
+       {0x0000a104, 0x061f0600},
+       {0x0000a108, 0x061d061e},
+       {0x0000a10c, 0x07020703},
+       {0x0000a110, 0x07000701},
+       {0x0000a114, 0x00000000},
+       {0x0000a118, 0x00000000},
+       {0x0000a11c, 0x00000000},
+       {0x0000a120, 0x00000000},
+       {0x0000a124, 0x00000000},
+       {0x0000a128, 0x00000000},
+       {0x0000a12c, 0x00000000},
+       {0x0000a130, 0x00000000},
+       {0x0000a134, 0x00000000},
+       {0x0000a138, 0x00000000},
+       {0x0000a13c, 0x00000000},
+       {0x0000a140, 0x001f0000},
+       {0x0000a144, 0x01000101},
+       {0x0000a148, 0x011e011f},
+       {0x0000a14c, 0x011c011d},
+       {0x0000a150, 0x02030204},
+       {0x0000a154, 0x02010202},
+       {0x0000a158, 0x021f0200},
+       {0x0000a15c, 0x0302021e},
+       {0x0000a160, 0x03000301},
+       {0x0000a164, 0x031e031f},
+       {0x0000a168, 0x0402031d},
+       {0x0000a16c, 0x04000401},
+       {0x0000a170, 0x041e041f},
+       {0x0000a174, 0x0502041d},
+       {0x0000a178, 0x05000501},
+       {0x0000a17c, 0x051e051f},
+       {0x0000a180, 0x06010602},
+       {0x0000a184, 0x061f0600},
+       {0x0000a188, 0x061d061e},
+       {0x0000a18c, 0x07020703},
+       {0x0000a190, 0x07000701},
+       {0x0000a194, 0x00000000},
+       {0x0000a198, 0x00000000},
+       {0x0000a19c, 0x00000000},
+       {0x0000a1a0, 0x00000000},
+       {0x0000a1a4, 0x00000000},
+       {0x0000a1a8, 0x00000000},
+       {0x0000a1ac, 0x00000000},
+       {0x0000a1b0, 0x00000000},
+       {0x0000a1b4, 0x00000000},
+       {0x0000a1b8, 0x00000000},
+       {0x0000a1bc, 0x00000000},
+       {0x0000a1c0, 0x00000000},
+       {0x0000a1c4, 0x00000000},
+       {0x0000a1c8, 0x00000000},
+       {0x0000a1cc, 0x00000000},
+       {0x0000a1d0, 0x00000000},
+       {0x0000a1d4, 0x00000000},
+       {0x0000a1d8, 0x00000000},
+       {0x0000a1dc, 0x00000000},
+       {0x0000a1e0, 0x00000000},
+       {0x0000a1e4, 0x00000000},
+       {0x0000a1e8, 0x00000000},
+       {0x0000a1ec, 0x00000000},
+       {0x0000a1f0, 0x00000396},
+       {0x0000a1f4, 0x00000396},
+       {0x0000a1f8, 0x00000396},
+       {0x0000a1fc, 0x00000196},
+       {0x0000b000, 0x00010000},
+       {0x0000b004, 0x00030002},
+       {0x0000b008, 0x00050004},
+       {0x0000b00c, 0x00810080},
+       {0x0000b010, 0x00830082},
+       {0x0000b014, 0x01810180},
+       {0x0000b018, 0x01830182},
+       {0x0000b01c, 0x01850184},
+       {0x0000b020, 0x02810280},
+       {0x0000b024, 0x02830282},
+       {0x0000b028, 0x02850284},
+       {0x0000b02c, 0x02890288},
+       {0x0000b030, 0x028b028a},
+       {0x0000b034, 0x0388028c},
+       {0x0000b038, 0x038a0389},
+       {0x0000b03c, 0x038c038b},
+       {0x0000b040, 0x0390038d},
+       {0x0000b044, 0x03920391},
+       {0x0000b048, 0x03940393},
+       {0x0000b04c, 0x03960395},
+       {0x0000b050, 0x00000000},
+       {0x0000b054, 0x00000000},
+       {0x0000b058, 0x00000000},
+       {0x0000b05c, 0x00000000},
+       {0x0000b060, 0x00000000},
+       {0x0000b064, 0x00000000},
+       {0x0000b068, 0x00000000},
+       {0x0000b06c, 0x00000000},
+       {0x0000b070, 0x00000000},
+       {0x0000b074, 0x00000000},
+       {0x0000b078, 0x00000000},
+       {0x0000b07c, 0x00000000},
+       {0x0000b080, 0x23232323},
+       {0x0000b084, 0x21232323},
+       {0x0000b088, 0x19191c1e},
+       {0x0000b08c, 0x12141417},
+       {0x0000b090, 0x07070e0e},
+       {0x0000b094, 0x03030305},
+       {0x0000b098, 0x00000003},
+       {0x0000b09c, 0x00000000},
+       {0x0000b0a0, 0x00000000},
+       {0x0000b0a4, 0x00000000},
+       {0x0000b0a8, 0x00000000},
+       {0x0000b0ac, 0x00000000},
+       {0x0000b0b0, 0x00000000},
+       {0x0000b0b4, 0x00000000},
+       {0x0000b0b8, 0x00000000},
+       {0x0000b0bc, 0x00000000},
+       {0x0000b0c0, 0x003f0020},
+       {0x0000b0c4, 0x00400041},
+       {0x0000b0c8, 0x0140005f},
+       {0x0000b0cc, 0x0160015f},
+       {0x0000b0d0, 0x017e017f},
+       {0x0000b0d4, 0x02410242},
+       {0x0000b0d8, 0x025f0240},
+       {0x0000b0dc, 0x027f0260},
+       {0x0000b0e0, 0x0341027e},
+       {0x0000b0e4, 0x035f0340},
+       {0x0000b0e8, 0x037f0360},
+       {0x0000b0ec, 0x04400441},
+       {0x0000b0f0, 0x0460045f},
+       {0x0000b0f4, 0x0541047f},
+       {0x0000b0f8, 0x055f0540},
+       {0x0000b0fc, 0x057f0560},
+       {0x0000b100, 0x06400641},
+       {0x0000b104, 0x0660065f},
+       {0x0000b108, 0x067e067f},
+       {0x0000b10c, 0x07410742},
+       {0x0000b110, 0x075f0740},
+       {0x0000b114, 0x077f0760},
+       {0x0000b118, 0x07800781},
+       {0x0000b11c, 0x07a0079f},
+       {0x0000b120, 0x07c107bf},
+       {0x0000b124, 0x000007c0},
+       {0x0000b128, 0x00000000},
+       {0x0000b12c, 0x00000000},
+       {0x0000b130, 0x00000000},
+       {0x0000b134, 0x00000000},
+       {0x0000b138, 0x00000000},
+       {0x0000b13c, 0x00000000},
+       {0x0000b140, 0x003f0020},
+       {0x0000b144, 0x00400041},
+       {0x0000b148, 0x0140005f},
+       {0x0000b14c, 0x0160015f},
+       {0x0000b150, 0x017e017f},
+       {0x0000b154, 0x02410242},
+       {0x0000b158, 0x025f0240},
+       {0x0000b15c, 0x027f0260},
+       {0x0000b160, 0x0341027e},
+       {0x0000b164, 0x035f0340},
+       {0x0000b168, 0x037f0360},
+       {0x0000b16c, 0x04400441},
+       {0x0000b170, 0x0460045f},
+       {0x0000b174, 0x0541047f},
+       {0x0000b178, 0x055f0540},
+       {0x0000b17c, 0x057f0560},
+       {0x0000b180, 0x06400641},
+       {0x0000b184, 0x0660065f},
+       {0x0000b188, 0x067e067f},
+       {0x0000b18c, 0x07410742},
+       {0x0000b190, 0x075f0740},
+       {0x0000b194, 0x077f0760},
+       {0x0000b198, 0x07800781},
+       {0x0000b19c, 0x07a0079f},
+       {0x0000b1a0, 0x07c107bf},
+       {0x0000b1a4, 0x000007c0},
+       {0x0000b1a8, 0x00000000},
+       {0x0000b1ac, 0x00000000},
+       {0x0000b1b0, 0x00000000},
+       {0x0000b1b4, 0x00000000},
+       {0x0000b1b8, 0x00000000},
+       {0x0000b1bc, 0x00000000},
+       {0x0000b1c0, 0x00000000},
+       {0x0000b1c4, 0x00000000},
+       {0x0000b1c8, 0x00000000},
+       {0x0000b1cc, 0x00000000},
+       {0x0000b1d0, 0x00000000},
+       {0x0000b1d4, 0x00000000},
+       {0x0000b1d8, 0x00000000},
+       {0x0000b1dc, 0x00000000},
+       {0x0000b1e0, 0x00000000},
+       {0x0000b1e4, 0x00000000},
+       {0x0000b1e8, 0x00000000},
+       {0x0000b1ec, 0x00000000},
+       {0x0000b1f0, 0x00000396},
+       {0x0000b1f4, 0x00000396},
+       {0x0000b1f8, 0x00000396},
+       {0x0000b1fc, 0x00000196},
 };
 
 static const u32 ar9580_1p0_baseband_postamble[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
        {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011},
+       {0x00009814, 0x3280c00a, 0x3280c00a, 0x3280c00a, 0x3280c00a},
+       {0x00009818, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
        {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e},
        {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
        {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
@@ -956,7 +1169,7 @@ static const u32 ar9580_1p0_baseband_postamble[][5] = {
        {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
        {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
        {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
-       {0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982},
+       {0x0000a2d0, 0x00041983, 0x00041983, 0x00041981, 0x00041982},
        {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
        {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
        {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
@@ -994,4 +1207,13 @@ static const u32 ar9580_1p0_pcie_phy_pll_on_clkreq[][2] = {
        {0x00004044, 0x00000000},
 };
 
+static const u32 ar9580_1p0_baseband_postamble_dfs_channel[][3] = {
+       /* Addr      5G          2G        */
+       {0x00009814, 0x3400c00f, 0x3400c00f},
+       {0x00009824, 0x5ac668d0, 0x5ac668d0},
+       {0x00009828, 0x06903080, 0x06903080},
+       {0x00009e0c, 0x6d4000e2, 0x6d4000e2},
+       {0x00009e14, 0x37b9625e, 0x37b9625e},
+};
+
 #endif /* INITVALS_9580_1P0_H */
index 60a5da53668f54f9987692ccf7389794d13ea851..5e5d5cb2458c0a9c492b8ea74aaf83bcc91a4568 100644 (file)
@@ -459,6 +459,7 @@ void ath_check_ani(struct ath_softc *sc);
 int ath_update_survey_stats(struct ath_softc *sc);
 void ath_update_survey_nf(struct ath_softc *sc, int channel);
 void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type);
+void ath_ps_full_sleep(unsigned long data);
 
 /**********/
 /* BTCOEX */
@@ -570,6 +571,34 @@ static inline void ath_fill_led_pin(struct ath_softc *sc)
 }
 #endif
 
+/************************/
+/* Wake on Wireless LAN */
+/************************/
+
+#ifdef CONFIG_ATH9K_WOW
+void ath9k_init_wow(struct ieee80211_hw *hw);
+int ath9k_suspend(struct ieee80211_hw *hw,
+                 struct cfg80211_wowlan *wowlan);
+int ath9k_resume(struct ieee80211_hw *hw);
+void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled);
+#else
+static inline void ath9k_init_wow(struct ieee80211_hw *hw)
+{
+}
+static inline int ath9k_suspend(struct ieee80211_hw *hw,
+                               struct cfg80211_wowlan *wowlan)
+{
+       return 0;
+}
+static inline int ath9k_resume(struct ieee80211_hw *hw)
+{
+       return 0;
+}
+static inline void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled)
+{
+}
+#endif /* CONFIG_ATH9K_WOW */
+
 /*******************************/
 /* Antenna diversity/combining */
 /*******************************/
@@ -642,6 +671,7 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs);
 #define ATH9K_PCI_AR9565_1ANT     0x0080
 #define ATH9K_PCI_AR9565_2ANT     0x0100
 #define ATH9K_PCI_NO_PLL_PWRSAVE  0x0200
+#define ATH9K_PCI_KILLER          0x0400
 
 /*
  * Default cache line size, in bytes.
@@ -724,6 +754,7 @@ struct ath_softc {
        struct work_struct hw_check_work;
        struct work_struct hw_reset_work;
        struct completion paprd_complete;
+       wait_queue_head_t tx_wait;
 
        unsigned int hw_busy_count;
        unsigned long sc_flags;
@@ -760,6 +791,7 @@ struct ath_softc {
        struct delayed_work tx_complete_work;
        struct delayed_work hw_pll_work;
        struct timer_list rx_poll_timer;
+       struct timer_list sleep_timer;
 
 #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
        struct ath_btcoex btcoex;
@@ -784,7 +816,7 @@ struct ath_softc {
        bool tx99_state;
        s16 tx99_power;
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_ATH9K_WOW
        atomic_t wow_got_bmiss_intr;
        atomic_t wow_sleep_proc_intr; /* in the middle of WoW sleep ? */
        u32 wow_intr_before_sleep;
@@ -947,10 +979,25 @@ struct fft_sample_ht20_40 {
        u8 data[SPECTRAL_HT20_40_NUM_BINS];
 } __packed;
 
-int ath9k_tx99_init(struct ath_softc *sc);
-void ath9k_tx99_deinit(struct ath_softc *sc);
+/********/
+/* TX99 */
+/********/
+
+#ifdef CONFIG_ATH9K_TX99
+void ath9k_tx99_init_debug(struct ath_softc *sc);
 int ath9k_tx99_send(struct ath_softc *sc, struct sk_buff *skb,
                    struct ath_tx_control *txctl);
+#else
+static inline void ath9k_tx99_init_debug(struct ath_softc *sc)
+{
+}
+static inline int ath9k_tx99_send(struct ath_softc *sc,
+                                 struct sk_buff *skb,
+                                 struct ath_tx_control *txctl)
+{
+       return 0;
+}
+#endif /* CONFIG_ATH9K_TX99 */
 
 void ath9k_tasklet(unsigned long data);
 int ath_cabq_update(struct ath_softc *);
@@ -967,6 +1014,9 @@ extern bool is_ath9k_unloaded;
 
 u8 ath9k_parse_mpdudensity(u8 mpdudensity);
 irqreturn_t ath_isr(int irq, void *dev);
+int ath_reset(struct ath_softc *sc);
+void ath_cancel_work(struct ath_softc *sc);
+void ath_restart_work(struct ath_softc *sc);
 int ath9k_init_device(u16 devid, struct ath_softc *sc,
                    const struct ath_bus_ops *bus_ops);
 void ath9k_deinit_device(struct ath_softc *sc);
index 83a2c59f680b0445173d25cc5ebccc2f7eb5777e..2f7dccfdb72784bf5c098a72ed703cf3abc0f2a2 100644 (file)
@@ -1778,111 +1778,6 @@ void ath9k_deinit_debug(struct ath_softc *sc)
        }
 }
 
-static ssize_t read_file_tx99(struct file *file, char __user *user_buf,
-                             size_t count, loff_t *ppos)
-{
-       struct ath_softc *sc = file->private_data;
-       char buf[3];
-       unsigned int len;
-
-       len = sprintf(buf, "%d\n", sc->tx99_state);
-       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-}
-
-static ssize_t write_file_tx99(struct file *file, const char __user *user_buf,
-                              size_t count, loff_t *ppos)
-{
-       struct ath_softc *sc = file->private_data;
-       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-       char buf[32];
-       bool start;
-       ssize_t len;
-       int r;
-
-       if (sc->nvifs > 1)
-               return -EOPNOTSUPP;
-
-       len = min(count, sizeof(buf) - 1);
-       if (copy_from_user(buf, user_buf, len))
-               return -EFAULT;
-
-       if (strtobool(buf, &start))
-               return -EINVAL;
-
-       if (start == sc->tx99_state) {
-               if (!start)
-                       return count;
-               ath_dbg(common, XMIT, "Resetting TX99\n");
-               ath9k_tx99_deinit(sc);
-       }
-
-       if (!start) {
-               ath9k_tx99_deinit(sc);
-               return count;
-       }
-
-       r = ath9k_tx99_init(sc);
-       if (r)
-               return r;
-
-       return count;
-}
-
-static const struct file_operations fops_tx99 = {
-       .read = read_file_tx99,
-       .write = write_file_tx99,
-       .open = simple_open,
-       .owner = THIS_MODULE,
-       .llseek = default_llseek,
-};
-
-static ssize_t read_file_tx99_power(struct file *file,
-                                   char __user *user_buf,
-                                   size_t count, loff_t *ppos)
-{
-       struct ath_softc *sc = file->private_data;
-       char buf[32];
-       unsigned int len;
-
-       len = sprintf(buf, "%d (%d dBm)\n",
-                     sc->tx99_power,
-                     sc->tx99_power / 2);
-
-       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-}
-
-static ssize_t write_file_tx99_power(struct file *file,
-                                    const char __user *user_buf,
-                                    size_t count, loff_t *ppos)
-{
-       struct ath_softc *sc = file->private_data;
-       int r;
-       u8 tx_power;
-
-       r = kstrtou8_from_user(user_buf, count, 0, &tx_power);
-       if (r)
-               return r;
-
-       if (tx_power > MAX_RATE_POWER)
-               return -EINVAL;
-
-       sc->tx99_power = tx_power;
-
-       ath9k_ps_wakeup(sc);
-       ath9k_hw_tx99_set_txpower(sc->sc_ah, sc->tx99_power);
-       ath9k_ps_restore(sc);
-
-       return count;
-}
-
-static const struct file_operations fops_tx99_power = {
-       .read = read_file_tx99_power,
-       .write = write_file_tx99_power,
-       .open = simple_open,
-       .owner = THIS_MODULE,
-       .llseek = default_llseek,
-};
-
 int ath9k_init_debug(struct ath_hw *ah)
 {
        struct ath_common *common = ath9k_hw_common(ah);
@@ -1899,6 +1794,7 @@ int ath9k_init_debug(struct ath_hw *ah)
 #endif
 
        ath9k_dfs_init_debug(sc);
+       ath9k_tx99_init_debug(sc);
 
        debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc,
                            &fops_dma);
@@ -1974,15 +1870,6 @@ int ath9k_init_debug(struct ath_hw *ah)
        debugfs_create_file("btcoex", S_IRUSR, sc->debug.debugfs_phy, sc,
                            &fops_btcoex);
 #endif
-       if (config_enabled(CONFIG_ATH9K_TX99) &&
-           AR_SREV_9300_20_OR_LATER(ah)) {
-               debugfs_create_file("tx99", S_IRUSR | S_IWUSR,
-                                   sc->debug.debugfs_phy, sc,
-                                   &fops_tx99);
-               debugfs_create_file("tx99_power", S_IRUSR | S_IWUSR,
-                                   sc->debug.debugfs_phy, sc,
-                                   &fops_tx99_power);
-       }
 
        return 0;
 }
index 54b04155e43b1058575aa44df3e6ece1ab18e55e..4ee24b1eec38fa12ba86c838573a31b8d808f28f 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/time.h>
 #include <asm/unaligned.h>
 
 #include "hw.h"
@@ -146,10 +147,9 @@ static void ath9k_hw_set_clockrate(struct ath_hw *ah)
        else
                clockrate = ATH9K_CLOCK_RATE_5GHZ_OFDM;
 
-       if (IS_CHAN_HT40(chan))
-               clockrate *= 2;
-
-       if (ah->curchan) {
+       if (chan) {
+               if (IS_CHAN_HT40(chan))
+                       clockrate *= 2;
                if (IS_CHAN_HALF_RATE(chan))
                        clockrate /= 2;
                if (IS_CHAN_QUARTER_RATE(chan))
@@ -454,7 +454,6 @@ static void ath9k_hw_init_config(struct ath_hw *ah)
        }
 
        ah->config.rx_intr_mitigation = true;
-       ah->config.pcieSerDesWrite = true;
 
        /*
         * We need this for PCI devices only (Cardbus, PCI, miniPCI)
@@ -549,11 +548,11 @@ static int ath9k_hw_post_init(struct ath_hw *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)) {
+       if (AR_SREV_9300_20_OR_LATER(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;
+                       ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9300_FCC_2GHZ;
+                       ah->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_9300_FCC_5GHZ;
                }
        }
 
@@ -1502,8 +1501,9 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
        int r;
 
        if (pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH) {
-               band_switch = IS_CHAN_5GHZ(ah->curchan) != IS_CHAN_5GHZ(chan);
-               mode_diff = (chan->channelFlags != ah->curchan->channelFlags);
+               u32 flags_diff = chan->channelFlags ^ ah->curchan->channelFlags;
+               band_switch = !!(flags_diff & CHANNEL_5GHZ);
+               mode_diff = !!(flags_diff & ~CHANNEL_HT);
        }
 
        for (qnum = 0; qnum < AR_NUM_QCU; qnum++) {
@@ -1815,7 +1815,7 @@ static int ath9k_hw_do_fastcc(struct ath_hw *ah, struct ath9k_channel *chan)
         * If cross-band fcc is not supoprted, bail out if channelFlags differ.
         */
        if (!(pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH) &&
-           chan->channelFlags != ah->curchan->channelFlags)
+           ((chan->channelFlags ^ ah->curchan->channelFlags) & ~CHANNEL_HT))
                goto fail;
 
        if (!ath9k_hw_check_alive(ah))
@@ -1856,10 +1856,12 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
                   struct ath9k_hw_cal_data *caldata, bool fastcc)
 {
        struct ath_common *common = ath9k_hw_common(ah);
+       struct timespec ts;
        u32 saveLedState;
        u32 saveDefAntenna;
        u32 macStaId1;
        u64 tsf = 0;
+       s64 usec = 0;
        int r;
        bool start_mci_reset = false;
        bool save_fullsleep = ah->chip_fullsleep;
@@ -1902,10 +1904,10 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 
        macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B;
 
-       /* For chips on which RTC reset is done, save TSF before it gets cleared */
-       if (AR_SREV_9100(ah) ||
-           (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)))
-               tsf = ath9k_hw_gettsf64(ah);
+       /* Save TSF before chip reset, a cold reset clears it */
+       tsf = ath9k_hw_gettsf64(ah);
+       getrawmonotonic(&ts);
+       usec = ts.tv_sec * 1000 + ts.tv_nsec / 1000;
 
        saveLedState = REG_READ(ah, AR_CFG_LED) &
                (AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL |
@@ -1938,8 +1940,9 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
        }
 
        /* Restore TSF */
-       if (tsf)
-               ath9k_hw_settsf64(ah, tsf);
+       getrawmonotonic(&ts);
+       usec = ts.tv_sec * 1000 + ts.tv_nsec / 1000 - usec;
+       ath9k_hw_settsf64(ah, tsf + usec);
 
        if (AR_SREV_9280_20_OR_LATER(ah))
                REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE);
index a2c9a5dbac6b0317fba5131ee212d3ef9292c77a..b1ff54631dcaa35c181f3b9f8cd03dbffc5d1259 100644 (file)
@@ -283,7 +283,6 @@ struct ath9k_ops_config {
        int additional_swba_backoff;
        int ack_6mb;
        u32 cwm_ignore_extcca;
-       bool pcieSerDesWrite;
        u8 pcie_clock_req;
        u32 pcie_waen;
        u8 analog_shiftreg;
@@ -317,6 +316,7 @@ struct ath9k_ops_config {
        bool xatten_margin_cfg;
        bool alt_mingainidx;
        bool no_pll_pwrsave;
+       bool tx_gain_buffalo;
 };
 
 enum ath9k_int {
@@ -865,6 +865,7 @@ struct ath_hw {
        u32 gpio_mask;
        u32 gpio_val;
 
+       struct ar5416IniArray ini_dfs;
        struct ar5416IniArray iniModes;
        struct ar5416IniArray iniCommon;
        struct ar5416IniArray iniBB_RfGain;
@@ -921,7 +922,7 @@ struct ath_hw {
        /* Enterprise mode cap */
        u32 ent_mode;
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_ATH9K_WOW
        u32 wow_event_mask;
 #endif
        bool is_clk_25mhz;
@@ -1127,7 +1128,7 @@ ath9k_hw_get_btcoex_scheme(struct ath_hw *ah)
 #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
 
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_ATH9K_WOW
 const char *ath9k_hw_wow_event_to_string(u32 wow_event);
 void ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern,
                                u8 *user_mask, int pattern_count,
index 710192ed27ed3118656f1a3b08bc41ec92c649a1..609b7e13f3f0afaf3c3f86cdb0589c302a5e98d0 100644 (file)
@@ -554,7 +554,7 @@ static void ath9k_init_misc(struct ath_softc *sc)
        sc->spec_config.fft_period = 0xF;
 }
 
-static void ath9k_init_platform(struct ath_softc *sc)
+static void ath9k_init_pcoem_platform(struct ath_softc *sc)
 {
        struct ath_hw *ah = sc->sc_ah;
        struct ath9k_hw_capabilities *pCap = &ah->caps;
@@ -589,6 +589,9 @@ static void ath9k_init_platform(struct ath_softc *sc)
        if (sc->driver_data & ATH9K_PCI_AR9565_2ANT)
                ath_info(common, "WB335 2-ANT card detected\n");
 
+       if (sc->driver_data & ATH9K_PCI_KILLER)
+               ath_info(common, "Killer Wireless card detected\n");
+
        /*
         * Some WB335 cards do not support antenna diversity. Since
         * we use a hardcoded value for AR9565 instead of using the
@@ -661,6 +664,27 @@ static void ath9k_eeprom_release(struct ath_softc *sc)
        release_firmware(sc->sc_ah->eeprom_blob);
 }
 
+static int ath9k_init_soc_platform(struct ath_softc *sc)
+{
+       struct ath9k_platform_data *pdata = sc->dev->platform_data;
+       struct ath_hw *ah = sc->sc_ah;
+       int ret = 0;
+
+       if (!pdata)
+               return 0;
+
+       if (pdata->eeprom_name) {
+               ret = ath9k_eeprom_request(sc, pdata->eeprom_name);
+               if (ret)
+                       return ret;
+       }
+
+       if (pdata->tx_gain_buffalo)
+               ah->config.tx_gain_buffalo = true;
+
+       return ret;
+}
+
 static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
                            const struct ath_bus_ops *bus_ops)
 {
@@ -688,6 +712,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
        common = ath9k_hw_common(ah);
        sc->dfs_detector = dfs_pattern_detector_init(common, NL80211_DFS_UNSET);
        sc->tx99_power = MAX_RATE_POWER + 1;
+       init_waitqueue_head(&sc->tx_wait);
 
        if (!pdata) {
                ah->ah_flags |= AH_USE_EEPROM;
@@ -713,7 +738,11 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
        /*
         * Platform quirks.
         */
-       ath9k_init_platform(sc);
+       ath9k_init_pcoem_platform(sc);
+
+       ret = ath9k_init_soc_platform(sc);
+       if (ret)
+               return ret;
 
        /*
         * Enable WLAN/BT RX Antenna diversity only when:
@@ -727,7 +756,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
                common->bt_ant_diversity = 1;
 
        spin_lock_init(&common->cc_lock);
-
        spin_lock_init(&sc->sc_serial_rw);
        spin_lock_init(&sc->sc_pm_lock);
        mutex_init(&sc->mutex);
@@ -735,6 +763,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
        tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet,
                     (unsigned long)sc);
 
+       setup_timer(&sc->sleep_timer, ath_ps_full_sleep, (unsigned long)sc);
        INIT_WORK(&sc->hw_reset_work, ath_reset_work);
        INIT_WORK(&sc->hw_check_work, ath_hw_check);
        INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
@@ -748,12 +777,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
        ath_read_cachesize(common, &csz);
        common->cachelsz = csz << 2; /* convert to bytes */
 
-       if (pdata && pdata->eeprom_name) {
-               ret = ath9k_eeprom_request(sc, pdata->eeprom_name);
-               if (ret)
-                       return ret;
-       }
-
        /* Initializes the hardware for all supported chipsets */
        ret = ath9k_hw_init(ah);
        if (ret)
@@ -851,6 +874,9 @@ static const struct ieee80211_iface_limit if_limits[] = {
 
 static const struct ieee80211_iface_limit if_dfs_limits[] = {
        { .max = 1,     .types = BIT(NL80211_IFTYPE_AP) |
+#ifdef CONFIG_MAC80211_MESH
+                                BIT(NL80211_IFTYPE_MESH_POINT) |
+#endif
                                 BIT(NL80211_IFTYPE_ADHOC) },
 };
 
@@ -873,15 +899,6 @@ static const struct ieee80211_iface_combination if_comb[] = {
        }
 };
 
-#ifdef CONFIG_PM
-static const struct wiphy_wowlan_support ath9k_wowlan_support = {
-       .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT,
-       .n_patterns = MAX_NUM_USER_PATTERN,
-       .pattern_min_len = 1,
-       .pattern_max_len = MAX_PATTERN_SIZE,
-};
-#endif
-
 void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
 {
        struct ath_hw *ah = sc->sc_ah;
@@ -931,16 +948,6 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
        hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_5_10_MHZ;
        hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
 
-#ifdef CONFIG_PM_SLEEP
-       if ((ah->caps.hw_caps & ATH9K_HW_WOW_DEVICE_CAPABLE) &&
-           (sc->driver_data & ATH9K_PCI_WOW) &&
-           device_can_wakeup(sc->dev))
-               hw->wiphy->wowlan = &ath9k_wowlan_support;
-
-       atomic_set(&sc->wow_sleep_proc_intr, -1);
-       atomic_set(&sc->wow_got_bmiss_intr, -1);
-#endif
-
        hw->queues = 4;
        hw->max_rates = 4;
        hw->channel_change_time = 5000;
@@ -966,6 +973,7 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
                hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
                        &sc->sbands[IEEE80211_BAND_5GHZ];
 
+       ath9k_init_wow(hw);
        ath9k_reload_chainmask_settings(sc);
 
        SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
@@ -1064,6 +1072,7 @@ static void ath9k_deinit_softc(struct ath_softc *sc)
                if (ATH_TXQ_SETUP(sc, i))
                        ath_tx_cleanupq(sc, &sc->tx.txq[i]);
 
+       del_timer_sync(&sc->sleep_timer);
        ath9k_hw_deinit(sc->sc_ah);
        if (sc->dfs_detector != NULL)
                sc->dfs_detector->exit(sc->dfs_detector);
index 74f452c7b1667c47a65506a077042f2b0668c3a8..b1dcf89138d30d4ce8899e9a117ee96ac29212e5 100644 (file)
@@ -82,6 +82,22 @@ static bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode)
        return ret;
 }
 
+void ath_ps_full_sleep(unsigned long data)
+{
+       struct ath_softc *sc = (struct ath_softc *) data;
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       bool reset;
+
+       spin_lock(&common->cc_lock);
+       ath_hw_cycle_counters_update(common);
+       spin_unlock(&common->cc_lock);
+
+       ath9k_hw_setrxabort(sc->sc_ah, 1);
+       ath9k_hw_stopdmarecv(sc->sc_ah, &reset);
+
+       ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP);
+}
+
 void ath9k_ps_wakeup(struct ath_softc *sc)
 {
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
@@ -92,6 +108,7 @@ void ath9k_ps_wakeup(struct ath_softc *sc)
        if (++sc->ps_usecount != 1)
                goto unlock;
 
+       del_timer_sync(&sc->sleep_timer);
        power_mode = sc->sc_ah->power_mode;
        ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
 
@@ -117,17 +134,17 @@ void ath9k_ps_restore(struct ath_softc *sc)
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
        enum ath9k_power_mode mode;
        unsigned long flags;
-       bool reset;
 
        spin_lock_irqsave(&sc->sc_pm_lock, flags);
        if (--sc->ps_usecount != 0)
                goto unlock;
 
        if (sc->ps_idle) {
-               ath9k_hw_setrxabort(sc->sc_ah, 1);
-               ath9k_hw_stopdmarecv(sc->sc_ah, &reset);
-               mode = ATH9K_PM_FULL_SLEEP;
-       } else if (sc->ps_enabled &&
+               mod_timer(&sc->sleep_timer, jiffies + HZ / 10);
+               goto unlock;
+       }
+
+       if (sc->ps_enabled &&
                   !(sc->ps_flags & (PS_WAIT_FOR_BEACON |
                                     PS_WAIT_FOR_CAB |
                                     PS_WAIT_FOR_PSPOLL_DATA |
@@ -163,13 +180,13 @@ static void __ath_cancel_work(struct ath_softc *sc)
 #endif
 }
 
-static void ath_cancel_work(struct ath_softc *sc)
+void ath_cancel_work(struct ath_softc *sc)
 {
        __ath_cancel_work(sc);
        cancel_work_sync(&sc->hw_reset_work);
 }
 
-static void ath_restart_work(struct ath_softc *sc)
+void ath_restart_work(struct ath_softc *sc)
 {
        ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
 
@@ -487,6 +504,8 @@ void ath9k_tasklet(unsigned long data)
                        ath_tx_edma_tasklet(sc);
                else
                        ath_tx_tasklet(sc);
+
+               wake_up(&sc->tx_wait);
        }
 
        ath9k_btcoex_handle_interrupt(sc, status);
@@ -579,7 +598,8 @@ irqreturn_t ath_isr(int irq, void *dev)
 
                goto chip_reset;
        }
-#ifdef CONFIG_PM_SLEEP
+
+#ifdef CONFIG_ATH9K_WOW
        if (status & ATH9K_INT_BMISS) {
                if (atomic_read(&sc->wow_sleep_proc_intr) == 0) {
                        ath_dbg(common, ANY, "during WoW we got a BMISS\n");
@@ -588,6 +608,8 @@ irqreturn_t ath_isr(int irq, void *dev)
                }
        }
 #endif
+
+
        if (status & ATH9K_INT_SWBA)
                tasklet_schedule(&sc->bcon_tasklet);
 
@@ -627,7 +649,7 @@ chip_reset:
 #undef SCHED_INTR
 }
 
-static int ath_reset(struct ath_softc *sc)
+int ath_reset(struct ath_softc *sc)
 {
        int r;
 
@@ -1817,13 +1839,31 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
        mutex_unlock(&sc->mutex);
 }
 
+static bool ath9k_has_tx_pending(struct ath_softc *sc)
+{
+       int i, npend;
+
+       for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+               if (!ATH_TXQ_SETUP(sc, i))
+                       continue;
+
+               if (!sc->tx.txq[i].axq_depth)
+                       continue;
+
+               npend = ath9k_has_pending_frames(sc, &sc->tx.txq[i]);
+               if (npend)
+                       break;
+       }
+
+       return !!npend;
+}
+
 static void ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
 {
        struct ath_softc *sc = hw->priv;
        struct ath_hw *ah = sc->sc_ah;
        struct ath_common *common = ath9k_hw_common(ah);
-       int timeout = 200; /* ms */
-       int i, j;
+       int timeout = HZ / 5; /* 200 ms */
        bool drain_txq;
 
        mutex_lock(&sc->mutex);
@@ -1841,25 +1881,9 @@ static void ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
                return;
        }
 
-       for (j = 0; j < timeout; j++) {
-               bool npend = false;
-
-               if (j)
-                       usleep_range(1000, 2000);
-
-               for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
-                       if (!ATH_TXQ_SETUP(sc, i))
-                               continue;
-
-                       npend = ath9k_has_pending_frames(sc, &sc->tx.txq[i]);
-
-                       if (npend)
-                               break;
-               }
-
-               if (!npend)
-                   break;
-       }
+       if (wait_event_timeout(sc->tx_wait, !ath9k_has_tx_pending(sc),
+                              timeout) > 0)
+               drop = false;
 
        if (drop) {
                ath9k_ps_wakeup(sc);
@@ -2021,333 +2045,6 @@ static int ath9k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
        return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-
-static void ath9k_wow_map_triggers(struct ath_softc *sc,
-                                  struct cfg80211_wowlan *wowlan,
-                                  u32 *wow_triggers)
-{
-       if (wowlan->disconnect)
-               *wow_triggers |= AH_WOW_LINK_CHANGE |
-                                AH_WOW_BEACON_MISS;
-       if (wowlan->magic_pkt)
-               *wow_triggers |= AH_WOW_MAGIC_PATTERN_EN;
-
-       if (wowlan->n_patterns)
-               *wow_triggers |= AH_WOW_USER_PATTERN_EN;
-
-       sc->wow_enabled = *wow_triggers;
-
-}
-
-static void ath9k_wow_add_disassoc_deauth_pattern(struct ath_softc *sc)
-{
-       struct ath_hw *ah = sc->sc_ah;
-       struct ath_common *common = ath9k_hw_common(ah);
-       int pattern_count = 0;
-       int i, byte_cnt;
-       u8 dis_deauth_pattern[MAX_PATTERN_SIZE];
-       u8 dis_deauth_mask[MAX_PATTERN_SIZE];
-
-       memset(dis_deauth_pattern, 0, MAX_PATTERN_SIZE);
-       memset(dis_deauth_mask, 0, MAX_PATTERN_SIZE);
-
-       /*
-        * Create Dissassociate / Deauthenticate packet filter
-        *
-        *     2 bytes        2 byte    6 bytes   6 bytes  6 bytes
-        *  +--------------+----------+---------+--------+--------+----
-        *  + Frame Control+ Duration +   DA    +  SA    +  BSSID +
-        *  +--------------+----------+---------+--------+--------+----
-        *
-        * The above is the management frame format for disassociate/
-        * deauthenticate pattern, from this we need to match the first byte
-        * of 'Frame Control' and DA, SA, and BSSID fields
-        * (skipping 2nd byte of FC and Duration feild.
-        *
-        * Disassociate pattern
-        * --------------------
-        * Frame control = 00 00 1010
-        * DA, SA, BSSID = x:x:x:x:x:x
-        * Pattern will be A0000000 | x:x:x:x:x:x | x:x:x:x:x:x
-        *                          | x:x:x:x:x:x  -- 22 bytes
-        *
-        * Deauthenticate pattern
-        * ----------------------
-        * Frame control = 00 00 1100
-        * DA, SA, BSSID = x:x:x:x:x:x
-        * Pattern will be C0000000 | x:x:x:x:x:x | x:x:x:x:x:x
-        *                          | x:x:x:x:x:x  -- 22 bytes
-        */
-
-       /* Create Disassociate Pattern first */
-
-       byte_cnt = 0;
-
-       /* Fill out the mask with all FF's */
-
-       for (i = 0; i < MAX_PATTERN_MASK_SIZE; i++)
-               dis_deauth_mask[i] = 0xff;
-
-       /* copy the first byte of frame control field */
-       dis_deauth_pattern[byte_cnt] = 0xa0;
-       byte_cnt++;
-
-       /* skip 2nd byte of frame control and Duration field */
-       byte_cnt += 3;
-
-       /*
-        * need not match the destination mac address, it can be a broadcast
-        * mac address or an unicast to this station
-        */
-       byte_cnt += 6;
-
-       /* copy the source mac address */
-       memcpy((dis_deauth_pattern + byte_cnt), common->curbssid, ETH_ALEN);
-
-       byte_cnt += 6;
-
-       /* copy the bssid, its same as the source mac address */
-
-       memcpy((dis_deauth_pattern + byte_cnt), common->curbssid, ETH_ALEN);
-
-       /* Create Disassociate pattern mask */
-
-       dis_deauth_mask[0] = 0xfe;
-       dis_deauth_mask[1] = 0x03;
-       dis_deauth_mask[2] = 0xc0;
-
-       ath_dbg(common, WOW, "Adding disassoc/deauth patterns for WoW\n");
-
-       ath9k_hw_wow_apply_pattern(ah, dis_deauth_pattern, dis_deauth_mask,
-                                  pattern_count, byte_cnt);
-
-       pattern_count++;
-       /*
-        * for de-authenticate pattern, only the first byte of the frame
-        * control field gets changed from 0xA0 to 0xC0
-        */
-       dis_deauth_pattern[0] = 0xC0;
-
-       ath9k_hw_wow_apply_pattern(ah, dis_deauth_pattern, dis_deauth_mask,
-                                  pattern_count, byte_cnt);
-
-}
-
-static void ath9k_wow_add_pattern(struct ath_softc *sc,
-                                 struct cfg80211_wowlan *wowlan)
-{
-       struct ath_hw *ah = sc->sc_ah;
-       struct ath9k_wow_pattern *wow_pattern = NULL;
-       struct cfg80211_pkt_pattern *patterns = wowlan->patterns;
-       int mask_len;
-       s8 i = 0;
-
-       if (!wowlan->n_patterns)
-               return;
-
-       /*
-        * Add the new user configured patterns
-        */
-       for (i = 0; i < wowlan->n_patterns; i++) {
-
-               wow_pattern = kzalloc(sizeof(*wow_pattern), GFP_KERNEL);
-
-               if (!wow_pattern)
-                       return;
-
-               /*
-                * TODO: convert the generic user space pattern to
-                * appropriate chip specific/802.11 pattern.
-                */
-
-               mask_len = DIV_ROUND_UP(wowlan->patterns[i].pattern_len, 8);
-               memset(wow_pattern->pattern_bytes, 0, MAX_PATTERN_SIZE);
-               memset(wow_pattern->mask_bytes, 0, MAX_PATTERN_SIZE);
-               memcpy(wow_pattern->pattern_bytes, patterns[i].pattern,
-                      patterns[i].pattern_len);
-               memcpy(wow_pattern->mask_bytes, patterns[i].mask, mask_len);
-               wow_pattern->pattern_len = patterns[i].pattern_len;
-
-               /*
-                * just need to take care of deauth and disssoc pattern,
-                * make sure we don't overwrite them.
-                */
-
-               ath9k_hw_wow_apply_pattern(ah, wow_pattern->pattern_bytes,
-                                          wow_pattern->mask_bytes,
-                                          i + 2,
-                                          wow_pattern->pattern_len);
-               kfree(wow_pattern);
-
-       }
-
-}
-
-static int ath9k_suspend(struct ieee80211_hw *hw,
-                        struct cfg80211_wowlan *wowlan)
-{
-       struct ath_softc *sc = hw->priv;
-       struct ath_hw *ah = sc->sc_ah;
-       struct ath_common *common = ath9k_hw_common(ah);
-       u32 wow_triggers_enabled = 0;
-       int ret = 0;
-
-       mutex_lock(&sc->mutex);
-
-       ath_cancel_work(sc);
-       ath_stop_ani(sc);
-       del_timer_sync(&sc->rx_poll_timer);
-
-       if (test_bit(SC_OP_INVALID, &sc->sc_flags)) {
-               ath_dbg(common, ANY, "Device not present\n");
-               ret = -EINVAL;
-               goto fail_wow;
-       }
-
-       if (WARN_ON(!wowlan)) {
-               ath_dbg(common, WOW, "None of the WoW triggers enabled\n");
-               ret = -EINVAL;
-               goto fail_wow;
-       }
-
-       if (!device_can_wakeup(sc->dev)) {
-               ath_dbg(common, WOW, "device_can_wakeup failed, WoW is not enabled\n");
-               ret = 1;
-               goto fail_wow;
-       }
-
-       /*
-        * none of the sta vifs are associated
-        * and we are not currently handling multivif
-        * cases, for instance we have to seperately
-        * configure 'keep alive frame' for each
-        * STA.
-        */
-
-       if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) {
-               ath_dbg(common, WOW, "None of the STA vifs are associated\n");
-               ret = 1;
-               goto fail_wow;
-       }
-
-       if (sc->nvifs > 1) {
-               ath_dbg(common, WOW, "WoW for multivif is not yet supported\n");
-               ret = 1;
-               goto fail_wow;
-       }
-
-       ath9k_wow_map_triggers(sc, wowlan, &wow_triggers_enabled);
-
-       ath_dbg(common, WOW, "WoW triggers enabled 0x%x\n",
-               wow_triggers_enabled);
-
-       ath9k_ps_wakeup(sc);
-
-       ath9k_stop_btcoex(sc);
-
-       /*
-        * Enable wake up on recieving disassoc/deauth
-        * frame by default.
-        */
-       ath9k_wow_add_disassoc_deauth_pattern(sc);
-
-       if (wow_triggers_enabled & AH_WOW_USER_PATTERN_EN)
-               ath9k_wow_add_pattern(sc, wowlan);
-
-       spin_lock_bh(&sc->sc_pcu_lock);
-       /*
-        * To avoid false wake, we enable beacon miss interrupt only
-        * when we go to sleep. We save the current interrupt mask
-        * so we can restore it after the system wakes up
-        */
-       sc->wow_intr_before_sleep = ah->imask;
-       ah->imask &= ~ATH9K_INT_GLOBAL;
-       ath9k_hw_disable_interrupts(ah);
-       ah->imask = ATH9K_INT_BMISS | ATH9K_INT_GLOBAL;
-       ath9k_hw_set_interrupts(ah);
-       ath9k_hw_enable_interrupts(ah);
-
-       spin_unlock_bh(&sc->sc_pcu_lock);
-
-       /*
-        * we can now sync irq and kill any running tasklets, since we already
-        * disabled interrupts and not holding a spin lock
-        */
-       synchronize_irq(sc->irq);
-       tasklet_kill(&sc->intr_tq);
-
-       ath9k_hw_wow_enable(ah, wow_triggers_enabled);
-
-       ath9k_ps_restore(sc);
-       ath_dbg(common, ANY, "WoW enabled in ath9k\n");
-       atomic_inc(&sc->wow_sleep_proc_intr);
-
-fail_wow:
-       mutex_unlock(&sc->mutex);
-       return ret;
-}
-
-static int ath9k_resume(struct ieee80211_hw *hw)
-{
-       struct ath_softc *sc = hw->priv;
-       struct ath_hw *ah = sc->sc_ah;
-       struct ath_common *common = ath9k_hw_common(ah);
-       u32 wow_status;
-
-       mutex_lock(&sc->mutex);
-
-       ath9k_ps_wakeup(sc);
-
-       spin_lock_bh(&sc->sc_pcu_lock);
-
-       ath9k_hw_disable_interrupts(ah);
-       ah->imask = sc->wow_intr_before_sleep;
-       ath9k_hw_set_interrupts(ah);
-       ath9k_hw_enable_interrupts(ah);
-
-       spin_unlock_bh(&sc->sc_pcu_lock);
-
-       wow_status = ath9k_hw_wow_wakeup(ah);
-
-       if (atomic_read(&sc->wow_got_bmiss_intr) == 0) {
-               /*
-                * some devices may not pick beacon miss
-                * as the reason they woke up so we add
-                * that here for that shortcoming.
-                */
-               wow_status |= AH_WOW_BEACON_MISS;
-               atomic_dec(&sc->wow_got_bmiss_intr);
-               ath_dbg(common, ANY, "Beacon miss interrupt picked up during WoW sleep\n");
-       }
-
-       atomic_dec(&sc->wow_sleep_proc_intr);
-
-       if (wow_status) {
-               ath_dbg(common, ANY, "Waking up due to WoW triggers %s with WoW status = %x\n",
-                       ath9k_hw_wow_event_to_string(wow_status), wow_status);
-       }
-
-       ath_restart_work(sc);
-       ath9k_start_btcoex(sc);
-
-       ath9k_ps_restore(sc);
-       mutex_unlock(&sc->mutex);
-
-       return 0;
-}
-
-static void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled)
-{
-       struct ath_softc *sc = hw->priv;
-
-       mutex_lock(&sc->mutex);
-       device_init_wakeup(sc->dev, 1);
-       device_set_wakeup_enable(sc->dev, enabled);
-       mutex_unlock(&sc->mutex);
-}
-
-#endif
 static void ath9k_sw_scan_start(struct ieee80211_hw *hw)
 {
        struct ath_softc *sc = hw->priv;
@@ -2373,134 +2070,6 @@ static void ath9k_channel_switch_beacon(struct ieee80211_hw *hw,
        sc->csa_vif = vif;
 }
 
-static void ath9k_tx99_stop(struct ath_softc *sc)
-{
-       struct ath_hw *ah = sc->sc_ah;
-       struct ath_common *common = ath9k_hw_common(ah);
-
-       ath_drain_all_txq(sc);
-       ath_startrecv(sc);
-
-       ath9k_hw_set_interrupts(ah);
-       ath9k_hw_enable_interrupts(ah);
-
-       ieee80211_wake_queues(sc->hw);
-
-       kfree_skb(sc->tx99_skb);
-       sc->tx99_skb = NULL;
-       sc->tx99_state = false;
-
-       ath9k_hw_tx99_stop(sc->sc_ah);
-       ath_dbg(common, XMIT, "TX99 stopped\n");
-}
-
-static struct sk_buff *ath9k_build_tx99_skb(struct ath_softc *sc)
-{
-       static u8 PN9Data[] = {0xff, 0x87, 0xb8, 0x59, 0xb7, 0xa1, 0xcc, 0x24,
-                              0x57, 0x5e, 0x4b, 0x9c, 0x0e, 0xe9, 0xea, 0x50,
-                              0x2a, 0xbe, 0xb4, 0x1b, 0xb6, 0xb0, 0x5d, 0xf1,
-                              0xe6, 0x9a, 0xe3, 0x45, 0xfd, 0x2c, 0x53, 0x18,
-                              0x0c, 0xca, 0xc9, 0xfb, 0x49, 0x37, 0xe5, 0xa8,
-                              0x51, 0x3b, 0x2f, 0x61, 0xaa, 0x72, 0x18, 0x84,
-                              0x02, 0x23, 0x23, 0xab, 0x63, 0x89, 0x51, 0xb3,
-                              0xe7, 0x8b, 0x72, 0x90, 0x4c, 0xe8, 0xfb, 0xc0};
-       u32 len = 1200;
-       struct ieee80211_hw *hw = sc->hw;
-       struct ieee80211_hdr *hdr;
-       struct ieee80211_tx_info *tx_info;
-       struct sk_buff *skb;
-
-       skb = alloc_skb(len, GFP_KERNEL);
-       if (!skb)
-               return NULL;
-
-       skb_put(skb, len);
-
-       memset(skb->data, 0, len);
-
-       hdr = (struct ieee80211_hdr *)skb->data;
-       hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA);
-       hdr->duration_id = 0;
-
-       memcpy(hdr->addr1, hw->wiphy->perm_addr, ETH_ALEN);
-       memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN);
-       memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);
-
-       hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
-
-       tx_info = IEEE80211_SKB_CB(skb);
-       memset(tx_info, 0, sizeof(*tx_info));
-       tx_info->band = hw->conf.chandef.chan->band;
-       tx_info->flags = IEEE80211_TX_CTL_NO_ACK;
-       tx_info->control.vif = sc->tx99_vif;
-
-       memcpy(skb->data + sizeof(*hdr), PN9Data, sizeof(PN9Data));
-
-       return skb;
-}
-
-void ath9k_tx99_deinit(struct ath_softc *sc)
-{
-       ath_reset(sc);
-
-       ath9k_ps_wakeup(sc);
-       ath9k_tx99_stop(sc);
-       ath9k_ps_restore(sc);
-}
-
-int ath9k_tx99_init(struct ath_softc *sc)
-{
-       struct ieee80211_hw *hw = sc->hw;
-       struct ath_hw *ah = sc->sc_ah;
-       struct ath_common *common = ath9k_hw_common(ah);
-       struct ath_tx_control txctl;
-       int r;
-
-       if (sc->sc_flags & SC_OP_INVALID) {
-               ath_err(common,
-                       "driver is in invalid state unable to use TX99");
-               return -EINVAL;
-       }
-
-       sc->tx99_skb = ath9k_build_tx99_skb(sc);
-       if (!sc->tx99_skb)
-               return -ENOMEM;
-
-       memset(&txctl, 0, sizeof(txctl));
-       txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO];
-
-       ath_reset(sc);
-
-       ath9k_ps_wakeup(sc);
-
-       ath9k_hw_disable_interrupts(ah);
-       atomic_set(&ah->intr_ref_cnt, -1);
-       ath_drain_all_txq(sc);
-       ath_stoprecv(sc);
-
-       sc->tx99_state = true;
-
-       ieee80211_stop_queues(hw);
-
-       if (sc->tx99_power == MAX_RATE_POWER + 1)
-               sc->tx99_power = MAX_RATE_POWER;
-
-       ath9k_hw_tx99_set_txpower(ah, sc->tx99_power);
-       r = ath9k_tx99_send(sc, sc->tx99_skb, &txctl);
-       if (r) {
-               ath_dbg(common, XMIT, "Failed to xmit TX99 skb\n");
-               return r;
-       }
-
-       ath_dbg(common, XMIT, "TX99 xmit started using %d ( %ddBm)\n",
-               sc->tx99_power,
-               sc->tx99_power / 2);
-
-       /* We leave the harware awake as it will be chugging on */
-
-       return 0;
-}
-
 struct ieee80211_ops ath9k_ops = {
        .tx                 = ath9k_tx,
        .start              = ath9k_start,
@@ -2531,7 +2100,7 @@ struct ieee80211_ops ath9k_ops = {
        .set_antenna        = ath9k_set_antenna,
        .get_antenna        = ath9k_get_antenna,
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_ATH9K_WOW
        .suspend            = ath9k_suspend,
        .resume             = ath9k_resume,
        .set_wakeup         = ath9k_set_wakeup,
index b5656fce4ff5f042b9053258e31c9b503802d217..e9a585758941fc9305fa859bab091992eb9946a8 100644 (file)
@@ -87,6 +87,19 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {
        { PCI_VDEVICE(ATHEROS, 0x002C) }, /* PCI-E 802.11n bonded out */
        { PCI_VDEVICE(ATHEROS, 0x002D) }, /* PCI   */
        { PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */
+
+       /* Killer Wireless (3x3) */
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0030,
+                        0x1A56,
+                        0x2000),
+         .driver_data = ATH9K_PCI_KILLER },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0030,
+                        0x1A56,
+                        0x2001),
+         .driver_data = ATH9K_PCI_KILLER },
+
        { PCI_VDEVICE(ATHEROS, 0x0030) }, /* PCI-E  AR9300 */
 
        /* PCI-E CUS198 */
@@ -354,6 +367,13 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {
                         0x1783),
          .driver_data = ATH9K_PCI_WOW },
 
+       /* Killer Wireless (2x2) */
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0030,
+                        0x1A56,
+                        0x2003),
+         .driver_data = ATH9K_PCI_KILLER },
+
        { PCI_VDEVICE(ATHEROS, 0x0034) }, /* PCI-E  AR9462 */
        { PCI_VDEVICE(ATHEROS, 0x0037) }, /* PCI-E  AR1111/AR9485 */
 
@@ -446,6 +466,11 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {
                         0x11AD, /* LITEON */
                         0x0662),
          .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        0x11AD, /* LITEON */
+                        0x0682),
+         .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV },
        { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
                         0x0036,
                         PCI_VENDOR_ID_AZWAVE,
@@ -456,6 +481,11 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {
                         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_LENOVO,
+                        0x4026),
+         .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV },
        { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
                         0x0036,
                         PCI_VENDOR_ID_HP,
@@ -466,6 +496,11 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {
                         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_HP,
+                        0x2005),
+         .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV },
        { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
                         0x0036,
                         PCI_VENDOR_ID_DELL,
@@ -545,6 +580,16 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {
                         0x185F, /* WNC */
                         0x3027),
          .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        0x185F, /* WNC */
+                        0xA120),
+         .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+                        0x0036,
+                        PCI_VENDOR_ID_FOXCONN,
+                        0xE07F),
+         .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
 
        /* PCI-E AR9565 (WB335) */
        { PCI_VDEVICE(ATHEROS, 0x0036),
index a13b2d143d9eb31411fcb0f504a91c1ba1026e21..9ad007312c9d4fa53b5c9365c3950f3fbfbb7a86 100644 (file)
 #define AR_SREV_REVISION_9462_21       3
 #define AR_SREV_VERSION_9565            0x2C0
 #define AR_SREV_REVISION_9565_10        0
+#define AR_SREV_REVISION_9565_101       1
+#define AR_SREV_REVISION_9565_11        2
 #define AR_SREV_VERSION_9550           0x400
 
 #define AR_SREV_5416(_ah) \
 
 #define AR_SREV_9330(_ah) \
        (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9330))
-#define AR_SREV_9330_10(_ah) \
-       (AR_SREV_9330((_ah)) && \
-        ((_ah)->hw_version.macRev == AR_SREV_REVISION_9330_10))
 #define AR_SREV_9330_11(_ah) \
        (AR_SREV_9330((_ah)) && \
         ((_ah)->hw_version.macRev == AR_SREV_REVISION_9330_11))
 
 #define AR_SREV_9565(_ah) \
        (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565))
-
 #define AR_SREV_9565_10(_ah) \
        (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \
         ((_ah)->hw_version.macRev == AR_SREV_REVISION_9565_10))
+#define AR_SREV_9565_101(_ah) \
+       (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \
+        ((_ah)->hw_version.macRev == AR_SREV_REVISION_9565_101))
+#define AR_SREV_9565_11(_ah) \
+       (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \
+        ((_ah)->hw_version.macRev == AR_SREV_REVISION_9565_11))
+#define AR_SREV_9565_11_OR_LATER(_ah) \
+       (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \
+        ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9565_11))
 
 #define AR_SREV_9550(_ah) \
        (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9550))
diff --git a/drivers/net/wireless/ath/ath9k/tx99.c b/drivers/net/wireless/ath/ath9k/tx99.c
new file mode 100644 (file)
index 0000000..b686a74
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2013 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ath9k.h"
+
+static void ath9k_tx99_stop(struct ath_softc *sc)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       ath_drain_all_txq(sc);
+       ath_startrecv(sc);
+
+       ath9k_hw_set_interrupts(ah);
+       ath9k_hw_enable_interrupts(ah);
+
+       ieee80211_wake_queues(sc->hw);
+
+       kfree_skb(sc->tx99_skb);
+       sc->tx99_skb = NULL;
+       sc->tx99_state = false;
+
+       ath9k_hw_tx99_stop(sc->sc_ah);
+       ath_dbg(common, XMIT, "TX99 stopped\n");
+}
+
+static struct sk_buff *ath9k_build_tx99_skb(struct ath_softc *sc)
+{
+       static u8 PN9Data[] = {0xff, 0x87, 0xb8, 0x59, 0xb7, 0xa1, 0xcc, 0x24,
+                              0x57, 0x5e, 0x4b, 0x9c, 0x0e, 0xe9, 0xea, 0x50,
+                              0x2a, 0xbe, 0xb4, 0x1b, 0xb6, 0xb0, 0x5d, 0xf1,
+                              0xe6, 0x9a, 0xe3, 0x45, 0xfd, 0x2c, 0x53, 0x18,
+                              0x0c, 0xca, 0xc9, 0xfb, 0x49, 0x37, 0xe5, 0xa8,
+                              0x51, 0x3b, 0x2f, 0x61, 0xaa, 0x72, 0x18, 0x84,
+                              0x02, 0x23, 0x23, 0xab, 0x63, 0x89, 0x51, 0xb3,
+                              0xe7, 0x8b, 0x72, 0x90, 0x4c, 0xe8, 0xfb, 0xc0};
+       u32 len = 1200;
+       struct ieee80211_tx_rate *rate;
+       struct ieee80211_hw *hw = sc->hw;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ieee80211_hdr *hdr;
+       struct ieee80211_tx_info *tx_info;
+       struct sk_buff *skb;
+
+       skb = alloc_skb(len, GFP_KERNEL);
+       if (!skb)
+               return NULL;
+
+       skb_put(skb, len);
+
+       memset(skb->data, 0, len);
+
+       hdr = (struct ieee80211_hdr *)skb->data;
+       hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA);
+       hdr->duration_id = 0;
+
+       memcpy(hdr->addr1, hw->wiphy->perm_addr, ETH_ALEN);
+       memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN);
+       memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);
+
+       hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
+
+       tx_info = IEEE80211_SKB_CB(skb);
+       memset(tx_info, 0, sizeof(*tx_info));
+       rate = &tx_info->control.rates[0];
+       tx_info->band = hw->conf.chandef.chan->band;
+       tx_info->flags = IEEE80211_TX_CTL_NO_ACK;
+       tx_info->control.vif = sc->tx99_vif;
+       rate->count = 1;
+       if (ah->curchan && IS_CHAN_HT(ah->curchan)) {
+               rate->flags |= IEEE80211_TX_RC_MCS;
+               if (IS_CHAN_HT40(ah->curchan))
+                       rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
+       }
+
+       memcpy(skb->data + sizeof(*hdr), PN9Data, sizeof(PN9Data));
+
+       return skb;
+}
+
+static void ath9k_tx99_deinit(struct ath_softc *sc)
+{
+       ath_reset(sc);
+
+       ath9k_ps_wakeup(sc);
+       ath9k_tx99_stop(sc);
+       ath9k_ps_restore(sc);
+}
+
+static int ath9k_tx99_init(struct ath_softc *sc)
+{
+       struct ieee80211_hw *hw = sc->hw;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath_tx_control txctl;
+       int r;
+
+       if (test_bit(SC_OP_INVALID, &sc->sc_flags)) {
+               ath_err(common,
+                       "driver is in invalid state unable to use TX99");
+               return -EINVAL;
+       }
+
+       sc->tx99_skb = ath9k_build_tx99_skb(sc);
+       if (!sc->tx99_skb)
+               return -ENOMEM;
+
+       memset(&txctl, 0, sizeof(txctl));
+       txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO];
+
+       ath_reset(sc);
+
+       ath9k_ps_wakeup(sc);
+
+       ath9k_hw_disable_interrupts(ah);
+       atomic_set(&ah->intr_ref_cnt, -1);
+       ath_drain_all_txq(sc);
+       ath_stoprecv(sc);
+
+       sc->tx99_state = true;
+
+       ieee80211_stop_queues(hw);
+
+       if (sc->tx99_power == MAX_RATE_POWER + 1)
+               sc->tx99_power = MAX_RATE_POWER;
+
+       ath9k_hw_tx99_set_txpower(ah, sc->tx99_power);
+       r = ath9k_tx99_send(sc, sc->tx99_skb, &txctl);
+       if (r) {
+               ath_dbg(common, XMIT, "Failed to xmit TX99 skb\n");
+               return r;
+       }
+
+       ath_dbg(common, XMIT, "TX99 xmit started using %d ( %ddBm)\n",
+               sc->tx99_power,
+               sc->tx99_power / 2);
+
+       /* We leave the harware awake as it will be chugging on */
+
+       return 0;
+}
+
+static ssize_t read_file_tx99(struct file *file, char __user *user_buf,
+                             size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       char buf[3];
+       unsigned int len;
+
+       len = sprintf(buf, "%d\n", sc->tx99_state);
+       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_tx99(struct file *file, const char __user *user_buf,
+                              size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       char buf[32];
+       bool start;
+       ssize_t len;
+       int r;
+
+       if (sc->nvifs > 1)
+               return -EOPNOTSUPP;
+
+       len = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, len))
+               return -EFAULT;
+
+       if (strtobool(buf, &start))
+               return -EINVAL;
+
+       if (start == sc->tx99_state) {
+               if (!start)
+                       return count;
+               ath_dbg(common, XMIT, "Resetting TX99\n");
+               ath9k_tx99_deinit(sc);
+       }
+
+       if (!start) {
+               ath9k_tx99_deinit(sc);
+               return count;
+       }
+
+       r = ath9k_tx99_init(sc);
+       if (r)
+               return r;
+
+       return count;
+}
+
+static const struct file_operations fops_tx99 = {
+       .read = read_file_tx99,
+       .write = write_file_tx99,
+       .open = simple_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+static ssize_t read_file_tx99_power(struct file *file,
+                                   char __user *user_buf,
+                                   size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       char buf[32];
+       unsigned int len;
+
+       len = sprintf(buf, "%d (%d dBm)\n",
+                     sc->tx99_power,
+                     sc->tx99_power / 2);
+
+       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_tx99_power(struct file *file,
+                                    const char __user *user_buf,
+                                    size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       int r;
+       u8 tx_power;
+
+       r = kstrtou8_from_user(user_buf, count, 0, &tx_power);
+       if (r)
+               return r;
+
+       if (tx_power > MAX_RATE_POWER)
+               return -EINVAL;
+
+       sc->tx99_power = tx_power;
+
+       ath9k_ps_wakeup(sc);
+       ath9k_hw_tx99_set_txpower(sc->sc_ah, sc->tx99_power);
+       ath9k_ps_restore(sc);
+
+       return count;
+}
+
+static const struct file_operations fops_tx99_power = {
+       .read = read_file_tx99_power,
+       .write = write_file_tx99_power,
+       .open = simple_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+void ath9k_tx99_init_debug(struct ath_softc *sc)
+{
+       if (!AR_SREV_9300_20_OR_LATER(sc->sc_ah))
+               return;
+
+       debugfs_create_file("tx99", S_IRUSR | S_IWUSR,
+                           sc->debug.debugfs_phy, sc,
+                           &fops_tx99);
+       debugfs_create_file("tx99_power", S_IRUSR | S_IWUSR,
+                           sc->debug.debugfs_phy, sc,
+                           &fops_tx99_power);
+}
index 81c88dd606dcd960f43e740b9af8cffcdc25778a..f1cde81bb7a2573f1905c2725c29c176da7013f0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012 Qualcomm Atheros, Inc.
+ * Copyright (c) 2013 Qualcomm Atheros, Inc.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <linux/export.h>
 #include "ath9k.h"
-#include "reg.h"
-#include "hw-ops.h"
 
-const char *ath9k_hw_wow_event_to_string(u32 wow_event)
-{
-       if (wow_event & AH_WOW_MAGIC_PATTERN_EN)
-               return "Magic pattern";
-       if (wow_event & AH_WOW_USER_PATTERN_EN)
-               return "User pattern";
-       if (wow_event & AH_WOW_LINK_CHANGE)
-               return "Link change";
-       if (wow_event & AH_WOW_BEACON_MISS)
-               return "Beacon miss";
-
-       return  "unknown reason";
-}
-EXPORT_SYMBOL(ath9k_hw_wow_event_to_string);
+static const struct wiphy_wowlan_support ath9k_wowlan_support = {
+       .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT,
+       .n_patterns = MAX_NUM_USER_PATTERN,
+       .pattern_min_len = 1,
+       .pattern_max_len = MAX_PATTERN_SIZE,
+};
 
-static void ath9k_hw_set_powermode_wow_sleep(struct ath_hw *ah)
+static void ath9k_wow_map_triggers(struct ath_softc *sc,
+                                  struct cfg80211_wowlan *wowlan,
+                                  u32 *wow_triggers)
 {
-       struct ath_common *common = ath9k_hw_common(ah);
+       if (wowlan->disconnect)
+               *wow_triggers |= AH_WOW_LINK_CHANGE |
+                                AH_WOW_BEACON_MISS;
+       if (wowlan->magic_pkt)
+               *wow_triggers |= AH_WOW_MAGIC_PATTERN_EN;
 
-       REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
+       if (wowlan->n_patterns)
+               *wow_triggers |= AH_WOW_USER_PATTERN_EN;
 
-       /* set rx disable bit */
-       REG_WRITE(ah, AR_CR, AR_CR_RXD);
-
-       if (!ath9k_hw_wait(ah, AR_CR, AR_CR_RXE, 0, AH_WAIT_TIMEOUT)) {
-               ath_err(common, "Failed to stop Rx DMA in 10ms AR_CR=0x%08x AR_DIAG_SW=0x%08x\n",
-                       REG_READ(ah, AR_CR), REG_READ(ah, AR_DIAG_SW));
-               return;
-       }
+       sc->wow_enabled = *wow_triggers;
 
-       REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_ON_INT);
 }
 
-static void ath9k_wow_create_keep_alive_pattern(struct ath_hw *ah)
+static void ath9k_wow_add_disassoc_deauth_pattern(struct ath_softc *sc)
 {
+       struct ath_hw *ah = sc->sc_ah;
        struct ath_common *common = ath9k_hw_common(ah);
-       u8 sta_mac_addr[ETH_ALEN], ap_mac_addr[ETH_ALEN];
-       u32 ctl[13] = {0};
-       u32 data_word[KAL_NUM_DATA_WORDS];
-       u8 i;
-       u32 wow_ka_data_word0;
-
-       memcpy(sta_mac_addr, common->macaddr, ETH_ALEN);
-       memcpy(ap_mac_addr, common->curbssid, ETH_ALEN);
-
-       /* set the transmit buffer */
-       ctl[0] = (KAL_FRAME_LEN | (MAX_RATE_POWER << 16));
-       ctl[1] = 0;
-       ctl[3] = 0xb;   /* OFDM_6M hardware value for this rate */
-       ctl[4] = 0;
-       ctl[7] = (ah->txchainmask) << 2;
-       ctl[2] = 0xf << 16; /* tx_tries 0 */
-
-       for (i = 0; i < KAL_NUM_DESC_WORDS; i++)
-               REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]);
-
-       REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]);
-
-       data_word[0] = (KAL_FRAME_TYPE << 2) | (KAL_FRAME_SUB_TYPE << 4) |
-                      (KAL_TO_DS << 8) | (KAL_DURATION_ID << 16);
-       data_word[1] = (ap_mac_addr[3] << 24) | (ap_mac_addr[2] << 16) |
-                      (ap_mac_addr[1] << 8) | (ap_mac_addr[0]);
-       data_word[2] = (sta_mac_addr[1] << 24) | (sta_mac_addr[0] << 16) |
-                      (ap_mac_addr[5] << 8) | (ap_mac_addr[4]);
-       data_word[3] = (sta_mac_addr[5] << 24) | (sta_mac_addr[4] << 16) |
-                      (sta_mac_addr[3] << 8) | (sta_mac_addr[2]);
-       data_word[4] = (ap_mac_addr[3] << 24) | (ap_mac_addr[2] << 16) |
-                      (ap_mac_addr[1] << 8) | (ap_mac_addr[0]);
-       data_word[5] = (ap_mac_addr[5] << 8) | (ap_mac_addr[4]);
-
-       if (AR_SREV_9462_20(ah)) {
-               /* AR9462 2.0 has an extra descriptor word (time based
-                * discard) compared to other chips */
-               REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + (12 * 4)), 0);
-               wow_ka_data_word0 = AR_WOW_TXBUF(13);
-       } else {
-               wow_ka_data_word0 = AR_WOW_TXBUF(12);
-       }
-
-       for (i = 0; i < KAL_NUM_DATA_WORDS; i++)
-               REG_WRITE(ah, (wow_ka_data_word0 + i*4), data_word[i]);
-
-}
-
-void ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern,
-                               u8 *user_mask, int pattern_count,
-                               int pattern_len)
-{
-       int i;
-       u32 pattern_val, mask_val;
-       u32 set, clr;
+       int pattern_count = 0;
+       int i, byte_cnt;
+       u8 dis_deauth_pattern[MAX_PATTERN_SIZE];
+       u8 dis_deauth_mask[MAX_PATTERN_SIZE];
 
-       /* FIXME: should check count by querying the hardware capability */
-       if (pattern_count >= MAX_NUM_PATTERN)
-               return;
-
-       REG_SET_BIT(ah, AR_WOW_PATTERN, BIT(pattern_count));
-
-       /* set the registers for pattern */
-       for (i = 0; i < MAX_PATTERN_SIZE; i += 4) {
-               memcpy(&pattern_val, user_pattern, 4);
-               REG_WRITE(ah, (AR_WOW_TB_PATTERN(pattern_count) + i),
-                         pattern_val);
-               user_pattern += 4;
-       }
-
-       /* set the registers for mask */
-       for (i = 0; i < MAX_PATTERN_MASK_SIZE; i += 4) {
-               memcpy(&mask_val, user_mask, 4);
-               REG_WRITE(ah, (AR_WOW_TB_MASK(pattern_count) + i), mask_val);
-               user_mask += 4;
-       }
+       memset(dis_deauth_pattern, 0, MAX_PATTERN_SIZE);
+       memset(dis_deauth_mask, 0, MAX_PATTERN_SIZE);
 
-       /* set the pattern length to be matched
+       /*
+        * Create Dissassociate / Deauthenticate packet filter
+        *
+        *     2 bytes        2 byte    6 bytes   6 bytes  6 bytes
+        *  +--------------+----------+---------+--------+--------+----
+        *  + Frame Control+ Duration +   DA    +  SA    +  BSSID +
+        *  +--------------+----------+---------+--------+--------+----
         *
-        * AR_WOW_LENGTH1_REG1
-        * bit 31:24 pattern 0 length
-        * bit 23:16 pattern 1 length
-        * bit 15:8 pattern 2 length
-        * bit 7:0 pattern 3 length
+        * The above is the management frame format for disassociate/
+        * deauthenticate pattern, from this we need to match the first byte
+        * of 'Frame Control' and DA, SA, and BSSID fields
+        * (skipping 2nd byte of FC and Duration feild.
         *
-        * AR_WOW_LENGTH1_REG2
-        * bit 31:24 pattern 4 length
-        * bit 23:16 pattern 5 length
-        * bit 15:8 pattern 6 length
-        * bit 7:0 pattern 7 length
+        * Disassociate pattern
+        * --------------------
+        * Frame control = 00 00 1010
+        * DA, SA, BSSID = x:x:x:x:x:x
+        * Pattern will be A0000000 | x:x:x:x:x:x | x:x:x:x:x:x
+        *                          | x:x:x:x:x:x  -- 22 bytes
         *
-        * the below logic writes out the new
-        * pattern length for the corresponding
-        * pattern_count, while masking out the
-        * other fields
+        * Deauthenticate pattern
+        * ----------------------
+        * Frame control = 00 00 1100
+        * DA, SA, BSSID = x:x:x:x:x:x
+        * Pattern will be C0000000 | x:x:x:x:x:x | x:x:x:x:x:x
+        *                          | x:x:x:x:x:x  -- 22 bytes
         */
 
-       ah->wow_event_mask |= BIT(pattern_count + AR_WOW_PAT_FOUND_SHIFT);
-
-       if (pattern_count < 4) {
-               /* Pattern 0-3 uses AR_WOW_LENGTH1 register */
-               set = (pattern_len & AR_WOW_LENGTH_MAX) <<
-                      AR_WOW_LEN1_SHIFT(pattern_count);
-               clr = AR_WOW_LENGTH1_MASK(pattern_count);
-               REG_RMW(ah, AR_WOW_LENGTH1, set, clr);
-       } else {
-               /* Pattern 4-7 uses AR_WOW_LENGTH2 register */
-               set = (pattern_len & AR_WOW_LENGTH_MAX) <<
-                      AR_WOW_LEN2_SHIFT(pattern_count);
-               clr = AR_WOW_LENGTH2_MASK(pattern_count);
-               REG_RMW(ah, AR_WOW_LENGTH2, set, clr);
-       }
+       /* Create Disassociate Pattern first */
 
-}
-EXPORT_SYMBOL(ath9k_hw_wow_apply_pattern);
+       byte_cnt = 0;
 
-u32 ath9k_hw_wow_wakeup(struct ath_hw *ah)
-{
-       u32 wow_status = 0;
-       u32 val = 0, rval;
+       /* Fill out the mask with all FF's */
 
-       /*
-        * read the WoW status register to know
-        * the wakeup reason
-        */
-       rval = REG_READ(ah, AR_WOW_PATTERN);
-       val = AR_WOW_STATUS(rval);
+       for (i = 0; i < MAX_PATTERN_MASK_SIZE; i++)
+               dis_deauth_mask[i] = 0xff;
 
-       /*
-        * mask only the WoW events that we have enabled. Sometimes
-        * we have spurious WoW events from the AR_WOW_PATTERN
-        * register. This mask will clean it up.
-        */
+       /* copy the first byte of frame control field */
+       dis_deauth_pattern[byte_cnt] = 0xa0;
+       byte_cnt++;
 
-       val &= ah->wow_event_mask;
-
-       if (val) {
-               if (val & AR_WOW_MAGIC_PAT_FOUND)
-                       wow_status |= AH_WOW_MAGIC_PATTERN_EN;
-               if (AR_WOW_PATTERN_FOUND(val))
-                       wow_status |= AH_WOW_USER_PATTERN_EN;
-               if (val & AR_WOW_KEEP_ALIVE_FAIL)
-                       wow_status |= AH_WOW_LINK_CHANGE;
-               if (val & AR_WOW_BEACON_FAIL)
-                       wow_status |= AH_WOW_BEACON_MISS;
-       }
+       /* skip 2nd byte of frame control and Duration field */
+       byte_cnt += 3;
 
        /*
-        * set and clear WOW_PME_CLEAR registers for the chip to
-        * generate next wow signal.
-        * disable D3 before accessing other registers ?
+        * need not match the destination mac address, it can be a broadcast
+        * mac address or an unicast to this station
         */
+       byte_cnt += 6;
 
-       /* do we need to check the bit value 0x01000000 (7-10) ?? */
-       REG_RMW(ah, AR_PCIE_PM_CTRL, AR_PMCTRL_WOW_PME_CLR,
-               AR_PMCTRL_PWR_STATE_D1D3);
+       /* copy the source mac address */
+       memcpy((dis_deauth_pattern + byte_cnt), common->curbssid, ETH_ALEN);
 
-       /*
-        * clear all events
-        */
-       REG_WRITE(ah, AR_WOW_PATTERN,
-                 AR_WOW_CLEAR_EVENTS(REG_READ(ah, AR_WOW_PATTERN)));
+       byte_cnt += 6;
 
-       /*
-        * restore the beacon threshold to init value
-        */
-       REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR);
+       /* copy the bssid, its same as the source mac address */
+
+       memcpy((dis_deauth_pattern + byte_cnt), common->curbssid, ETH_ALEN);
+
+       /* Create Disassociate pattern mask */
+
+       dis_deauth_mask[0] = 0xfe;
+       dis_deauth_mask[1] = 0x03;
+       dis_deauth_mask[2] = 0xc0;
+
+       ath_dbg(common, WOW, "Adding disassoc/deauth patterns for WoW\n");
 
+       ath9k_hw_wow_apply_pattern(ah, dis_deauth_pattern, dis_deauth_mask,
+                                  pattern_count, byte_cnt);
+
+       pattern_count++;
        /*
-        * Restore the way the PCI-E reset, Power-On-Reset, external
-        * PCIE_POR_SHORT pins are tied to its original value.
-        * Previously just before WoW sleep, we untie the PCI-E
-        * reset to our Chip's Power On Reset so that any PCI-E
-        * reset from the bus will not reset our chip
+        * for de-authenticate pattern, only the first byte of the frame
+        * control field gets changed from 0xA0 to 0xC0
         */
-       if (ah->is_pciexpress)
-               ath9k_hw_configpcipowersave(ah, false);
+       dis_deauth_pattern[0] = 0xC0;
 
-       ah->wow_event_mask = 0;
+       ath9k_hw_wow_apply_pattern(ah, dis_deauth_pattern, dis_deauth_mask,
+                                  pattern_count, byte_cnt);
 
-       return wow_status;
 }
-EXPORT_SYMBOL(ath9k_hw_wow_wakeup);
 
-void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable)
+static void ath9k_wow_add_pattern(struct ath_softc *sc,
+                                 struct cfg80211_wowlan *wowlan)
 {
-       u32 wow_event_mask;
-       u32 set, clr;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath9k_wow_pattern *wow_pattern = NULL;
+       struct cfg80211_pkt_pattern *patterns = wowlan->patterns;
+       int mask_len;
+       s8 i = 0;
 
-       /*
-        * wow_event_mask is a mask to the AR_WOW_PATTERN register to
-        * indicate which WoW events we have enabled. The WoW events
-        * are from the 'pattern_enable' in this function and
-        * 'pattern_count' of ath9k_hw_wow_apply_pattern()
-        */
-       wow_event_mask = ah->wow_event_mask;
+       if (!wowlan->n_patterns)
+               return;
 
        /*
-        * Untie Power-on-Reset from the PCI-E-Reset. When we are in
-        * WOW sleep, we do want the Reset from the PCI-E to disturb
-        * our hw state
+        * Add the new user configured patterns
         */
-       if (ah->is_pciexpress) {
+       for (i = 0; i < wowlan->n_patterns; i++) {
+
+               wow_pattern = kzalloc(sizeof(*wow_pattern), GFP_KERNEL);
+
+               if (!wow_pattern)
+                       return;
+
+               /*
+                * TODO: convert the generic user space pattern to
+                * appropriate chip specific/802.11 pattern.
+                */
+
+               mask_len = DIV_ROUND_UP(wowlan->patterns[i].pattern_len, 8);
+               memset(wow_pattern->pattern_bytes, 0, MAX_PATTERN_SIZE);
+               memset(wow_pattern->mask_bytes, 0, MAX_PATTERN_SIZE);
+               memcpy(wow_pattern->pattern_bytes, patterns[i].pattern,
+                      patterns[i].pattern_len);
+               memcpy(wow_pattern->mask_bytes, patterns[i].mask, mask_len);
+               wow_pattern->pattern_len = patterns[i].pattern_len;
+
                /*
-                * we need to untie the internal POR (power-on-reset)
-                * to the external PCI-E reset. We also need to tie
-                * the PCI-E Phy reset to the PCI-E reset.
+                * just need to take care of deauth and disssoc pattern,
+                * make sure we don't overwrite them.
                 */
-               set = AR_WA_RESET_EN | AR_WA_POR_SHORT;
-               clr = AR_WA_UNTIE_RESET_EN | AR_WA_D3_L1_DISABLE;
-               REG_RMW(ah, AR_WA, set, clr);
+
+               ath9k_hw_wow_apply_pattern(ah, wow_pattern->pattern_bytes,
+                                          wow_pattern->mask_bytes,
+                                          i + 2,
+                                          wow_pattern->pattern_len);
+               kfree(wow_pattern);
+
        }
 
-       /*
-        * set the power states appropriately and enable PME
-        */
-       set = AR_PMCTRL_HOST_PME_EN | AR_PMCTRL_PWR_PM_CTRL_ENA |
-             AR_PMCTRL_AUX_PWR_DET | AR_PMCTRL_WOW_PME_CLR;
+}
 
-       /*
-        * set and clear WOW_PME_CLEAR registers for the chip
-        * to generate next wow signal.
-        */
-       REG_SET_BIT(ah, AR_PCIE_PM_CTRL, set);
-       clr = AR_PMCTRL_WOW_PME_CLR;
-       REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, clr);
+int ath9k_suspend(struct ieee80211_hw *hw,
+                 struct cfg80211_wowlan *wowlan)
+{
+       struct ath_softc *sc = hw->priv;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       u32 wow_triggers_enabled = 0;
+       int ret = 0;
 
-       /*
-        * Setup for:
-        *      - beacon misses
-        *      - magic pattern
-        *      - keep alive timeout
-        *      - pattern matching
-        */
+       mutex_lock(&sc->mutex);
 
-       /*
-        * Program default values for pattern backoff, aifs/slot/KAL count,
-        * beacon miss timeout, KAL timeout, etc.
-        */
-       set = AR_WOW_BACK_OFF_SHIFT(AR_WOW_PAT_BACKOFF);
-       REG_SET_BIT(ah, AR_WOW_PATTERN, set);
+       ath_cancel_work(sc);
+       ath_stop_ani(sc);
+       del_timer_sync(&sc->rx_poll_timer);
 
-       set = AR_WOW_AIFS_CNT(AR_WOW_CNT_AIFS_CNT) |
-             AR_WOW_SLOT_CNT(AR_WOW_CNT_SLOT_CNT) |
-             AR_WOW_KEEP_ALIVE_CNT(AR_WOW_CNT_KA_CNT);
-       REG_SET_BIT(ah, AR_WOW_COUNT, set);
+       if (test_bit(SC_OP_INVALID, &sc->sc_flags)) {
+               ath_dbg(common, ANY, "Device not present\n");
+               ret = -EINVAL;
+               goto fail_wow;
+       }
 
-       if (pattern_enable & AH_WOW_BEACON_MISS)
-               set = AR_WOW_BEACON_TIMO;
-       /* We are not using beacon miss, program a large value */
-       else
-               set = AR_WOW_BEACON_TIMO_MAX;
+       if (WARN_ON(!wowlan)) {
+               ath_dbg(common, WOW, "None of the WoW triggers enabled\n");
+               ret = -EINVAL;
+               goto fail_wow;
+       }
 
-       REG_WRITE(ah, AR_WOW_BCN_TIMO, set);
+       if (!device_can_wakeup(sc->dev)) {
+               ath_dbg(common, WOW, "device_can_wakeup failed, WoW is not enabled\n");
+               ret = 1;
+               goto fail_wow;
+       }
 
        /*
-        * Keep alive timo in ms except AR9280
+        * none of the sta vifs are associated
+        * and we are not currently handling multivif
+        * cases, for instance we have to seperately
+        * configure 'keep alive frame' for each
+        * STA.
         */
-       if (!pattern_enable)
-               set = AR_WOW_KEEP_ALIVE_NEVER;
-       else
-               set = KAL_TIMEOUT * 32;
 
-       REG_WRITE(ah, AR_WOW_KEEP_ALIVE_TIMO, set);
+       if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) {
+               ath_dbg(common, WOW, "None of the STA vifs are associated\n");
+               ret = 1;
+               goto fail_wow;
+       }
+
+       if (sc->nvifs > 1) {
+               ath_dbg(common, WOW, "WoW for multivif is not yet supported\n");
+               ret = 1;
+               goto fail_wow;
+       }
+
+       ath9k_wow_map_triggers(sc, wowlan, &wow_triggers_enabled);
+
+       ath_dbg(common, WOW, "WoW triggers enabled 0x%x\n",
+               wow_triggers_enabled);
+
+       ath9k_ps_wakeup(sc);
+
+       ath9k_stop_btcoex(sc);
 
        /*
-        * Keep alive delay in us. based on 'power on clock',
-        * therefore in usec
+        * Enable wake up on recieving disassoc/deauth
+        * frame by default.
         */
-       set = KAL_DELAY * 1000;
-       REG_WRITE(ah, AR_WOW_KEEP_ALIVE_DELAY, set);
+       ath9k_wow_add_disassoc_deauth_pattern(sc);
+
+       if (wow_triggers_enabled & AH_WOW_USER_PATTERN_EN)
+               ath9k_wow_add_pattern(sc, wowlan);
 
+       spin_lock_bh(&sc->sc_pcu_lock);
        /*
-        * Create keep alive pattern to respond to beacons
+        * To avoid false wake, we enable beacon miss interrupt only
+        * when we go to sleep. We save the current interrupt mask
+        * so we can restore it after the system wakes up
         */
-       ath9k_wow_create_keep_alive_pattern(ah);
+       sc->wow_intr_before_sleep = ah->imask;
+       ah->imask &= ~ATH9K_INT_GLOBAL;
+       ath9k_hw_disable_interrupts(ah);
+       ah->imask = ATH9K_INT_BMISS | ATH9K_INT_GLOBAL;
+       ath9k_hw_set_interrupts(ah);
+       ath9k_hw_enable_interrupts(ah);
+
+       spin_unlock_bh(&sc->sc_pcu_lock);
 
        /*
-        * Configure MAC WoW Registers
+        * we can now sync irq and kill any running tasklets, since we already
+        * disabled interrupts and not holding a spin lock
         */
-       set = 0;
-       /* Send keep alive timeouts anyway */
-       clr = AR_WOW_KEEP_ALIVE_AUTO_DIS;
+       synchronize_irq(sc->irq);
+       tasklet_kill(&sc->intr_tq);
 
-       if (pattern_enable & AH_WOW_LINK_CHANGE)
-               wow_event_mask |= AR_WOW_KEEP_ALIVE_FAIL;
-       else
-               set = AR_WOW_KEEP_ALIVE_FAIL_DIS;
+       ath9k_hw_wow_enable(ah, wow_triggers_enabled);
 
-       set = AR_WOW_KEEP_ALIVE_FAIL_DIS;
-       REG_RMW(ah, AR_WOW_KEEP_ALIVE, set, clr);
+       ath9k_ps_restore(sc);
+       ath_dbg(common, ANY, "WoW enabled in ath9k\n");
+       atomic_inc(&sc->wow_sleep_proc_intr);
 
-       /*
-        * we are relying on a bmiss failure. ensure we have
-        * enough threshold to prevent false positives
-        */
-       REG_RMW_FIELD(ah, AR_RSSI_THR, AR_RSSI_THR_BM_THR,
-                     AR_WOW_BMISSTHRESHOLD);
+fail_wow:
+       mutex_unlock(&sc->mutex);
+       return ret;
+}
+
+int ath9k_resume(struct ieee80211_hw *hw)
+{
+       struct ath_softc *sc = hw->priv;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       u32 wow_status;
 
-       set = 0;
-       clr = 0;
+       mutex_lock(&sc->mutex);
 
-       if (pattern_enable & AH_WOW_BEACON_MISS) {
-               set = AR_WOW_BEACON_FAIL_EN;
-               wow_event_mask |= AR_WOW_BEACON_FAIL;
-       } else {
-               clr = AR_WOW_BEACON_FAIL_EN;
+       ath9k_ps_wakeup(sc);
+
+       spin_lock_bh(&sc->sc_pcu_lock);
+
+       ath9k_hw_disable_interrupts(ah);
+       ah->imask = sc->wow_intr_before_sleep;
+       ath9k_hw_set_interrupts(ah);
+       ath9k_hw_enable_interrupts(ah);
+
+       spin_unlock_bh(&sc->sc_pcu_lock);
+
+       wow_status = ath9k_hw_wow_wakeup(ah);
+
+       if (atomic_read(&sc->wow_got_bmiss_intr) == 0) {
+               /*
+                * some devices may not pick beacon miss
+                * as the reason they woke up so we add
+                * that here for that shortcoming.
+                */
+               wow_status |= AH_WOW_BEACON_MISS;
+               atomic_dec(&sc->wow_got_bmiss_intr);
+               ath_dbg(common, ANY, "Beacon miss interrupt picked up during WoW sleep\n");
        }
 
-       REG_RMW(ah, AR_WOW_BCN_EN, set, clr);
+       atomic_dec(&sc->wow_sleep_proc_intr);
 
-       set = 0;
-       clr = 0;
-       /*
-        * Enable the magic packet registers
-        */
-       if (pattern_enable & AH_WOW_MAGIC_PATTERN_EN) {
-               set = AR_WOW_MAGIC_EN;
-               wow_event_mask |= AR_WOW_MAGIC_PAT_FOUND;
-       } else {
-               clr = AR_WOW_MAGIC_EN;
+       if (wow_status) {
+               ath_dbg(common, ANY, "Waking up due to WoW triggers %s with WoW status = %x\n",
+                       ath9k_hw_wow_event_to_string(wow_status), wow_status);
        }
-       set |= AR_WOW_MAC_INTR_EN;
-       REG_RMW(ah, AR_WOW_PATTERN, set, clr);
 
-       REG_WRITE(ah, AR_WOW_PATTERN_MATCH_LT_256B,
-                 AR_WOW_PATTERN_SUPPORTED);
+       ath_restart_work(sc);
+       ath9k_start_btcoex(sc);
 
-       /*
-        * Set the power states appropriately and enable PME
-        */
-       clr = 0;
-       set = AR_PMCTRL_PWR_STATE_D1D3 | AR_PMCTRL_HOST_PME_EN |
-             AR_PMCTRL_PWR_PM_CTRL_ENA;
+       ath9k_ps_restore(sc);
+       mutex_unlock(&sc->mutex);
 
-       clr = AR_PCIE_PM_CTRL_ENA;
-       REG_RMW(ah, AR_PCIE_PM_CTRL, set, clr);
+       return 0;
+}
 
-       /*
-        * this is needed to prevent the chip waking up
-        * the host within 3-4 seconds with certain
-        * platform/BIOS. The fix is to enable
-        * D1 & D3 to match original definition and
-        * also match the OTP value. Anyway this
-        * is more related to SW WOW.
-        */
-       clr = AR_PMCTRL_PWR_STATE_D1D3;
-       REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, clr);
+void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled)
+{
+       struct ath_softc *sc = hw->priv;
 
-       set = AR_PMCTRL_PWR_STATE_D1D3_REAL;
-       REG_SET_BIT(ah, AR_PCIE_PM_CTRL, set);
+       mutex_lock(&sc->mutex);
+       device_init_wakeup(sc->dev, 1);
+       device_set_wakeup_enable(sc->dev, enabled);
+       mutex_unlock(&sc->mutex);
+}
 
-       REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM);
+void ath9k_init_wow(struct ieee80211_hw *hw)
+{
+       struct ath_softc *sc = hw->priv;
 
-       /* to bring down WOW power low margin */
-       set = BIT(13);
-       REG_SET_BIT(ah, AR_PCIE_PHY_REG3, set);
-       /* HW WoW */
-       clr = BIT(5);
-       REG_CLR_BIT(ah, AR_PCU_MISC_MODE3, clr);
+       if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_WOW_DEVICE_CAPABLE) &&
+           (sc->driver_data & ATH9K_PCI_WOW) &&
+           device_can_wakeup(sc->dev))
+               hw->wiphy->wowlan = &ath9k_wowlan_support;
 
-       ath9k_hw_set_powermode_wow_sleep(ah);
-       ah->wow_event_mask = wow_event_mask;
+       atomic_set(&sc->wow_sleep_proc_intr, -1);
+       atomic_set(&sc->wow_got_bmiss_intr, -1);
 }
-EXPORT_SYMBOL(ath9k_hw_wow_enable);
index 09cdbcd097394a3a2c324230c2743f5d181b0900..a907bc94800d323090a7e4d401d6ba4dab9a8835 100644 (file)
@@ -1276,6 +1276,10 @@ static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf,
                                if (!rts_thresh || (len > rts_thresh))
                                        rts = true;
                        }
+
+                       if (!aggr)
+                               len = fi->framelen;
+
                        ath_buf_set_rate(sc, bf, &info, len, rts);
                }
 
@@ -1786,6 +1790,9 @@ bool ath_drain_all_txq(struct ath_softc *sc)
                if (!ATH_TXQ_SETUP(sc, i))
                        continue;
 
+               if (!sc->tx.txq[i].axq_depth)
+                       continue;
+
                if (ath9k_hw_numtxpending(ah, sc->tx.txq[i].axq_qnum))
                        npend |= BIT(i);
        }
@@ -2749,6 +2756,8 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
        }
 }
 
+#ifdef CONFIG_ATH9K_TX99
+
 int ath9k_tx99_send(struct ath_softc *sc, struct sk_buff *skb,
                    struct ath_tx_control *txctl)
 {
@@ -2791,3 +2800,5 @@ int ath9k_tx99_send(struct ath_softc *sc, struct sk_buff *skb,
 
        return 0;
 }
+
+#endif /* CONFIG_ATH9K_TX99 */
index 1217c52ab28e6b07847217890bb6f1d9840a84b1..9e154732afaacfefe661befa0053e881ba083106 100644 (file)
@@ -37,17 +37,18 @@ static int __ath_regd_init(struct ath_regulatory *reg);
 
 /* We enable active scan on these a case by case basis by regulatory domain */
 #define ATH9K_2GHZ_CH12_13     REG_RULE(2467-10, 2472+10, 40, 0, 20,\
-                                       NL80211_RRF_PASSIVE_SCAN)
+                                        NL80211_RRF_NO_IR)
 #define ATH9K_2GHZ_CH14                REG_RULE(2484-10, 2484+10, 40, 0, 20,\
-                               NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_OFDM)
+                                        NL80211_RRF_NO_IR | \
+                                        NL80211_RRF_NO_OFDM)
 
 /* We allow IBSS on these on a case by case basis by regulatory domain */
 #define ATH9K_5GHZ_5150_5350   REG_RULE(5150-10, 5350+10, 80, 0, 30,\
-                               NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
+                                        NL80211_RRF_NO_IR)
 #define ATH9K_5GHZ_5470_5850   REG_RULE(5470-10, 5850+10, 80, 0, 30,\
-                               NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
+                                        NL80211_RRF_NO_IR)
 #define ATH9K_5GHZ_5725_5850   REG_RULE(5725-10, 5850+10, 80, 0, 30,\
-                               NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
+                                        NL80211_RRF_NO_IR)
 
 #define ATH9K_2GHZ_ALL         ATH9K_2GHZ_CH01_11, \
                                ATH9K_2GHZ_CH12_13, \
@@ -113,6 +114,87 @@ static const struct ieee80211_regdomain ath_world_regdom_67_68_6A_6C = {
        }
 };
 
+static bool dynamic_country_user_possible(struct ath_regulatory *reg)
+{
+       if (config_enabled(CONFIG_ATH_REG_DYNAMIC_USER_CERT_TESTING))
+               return true;
+
+       switch (reg->country_code) {
+       case CTRY_UNITED_STATES:
+       case CTRY_JAPAN1:
+       case CTRY_JAPAN2:
+       case CTRY_JAPAN3:
+       case CTRY_JAPAN4:
+       case CTRY_JAPAN5:
+       case CTRY_JAPAN6:
+       case CTRY_JAPAN7:
+       case CTRY_JAPAN8:
+       case CTRY_JAPAN9:
+       case CTRY_JAPAN10:
+       case CTRY_JAPAN11:
+       case CTRY_JAPAN12:
+       case CTRY_JAPAN13:
+       case CTRY_JAPAN14:
+       case CTRY_JAPAN15:
+       case CTRY_JAPAN16:
+       case CTRY_JAPAN17:
+       case CTRY_JAPAN18:
+       case CTRY_JAPAN19:
+       case CTRY_JAPAN20:
+       case CTRY_JAPAN21:
+       case CTRY_JAPAN22:
+       case CTRY_JAPAN23:
+       case CTRY_JAPAN24:
+       case CTRY_JAPAN25:
+       case CTRY_JAPAN26:
+       case CTRY_JAPAN27:
+       case CTRY_JAPAN28:
+       case CTRY_JAPAN29:
+       case CTRY_JAPAN30:
+       case CTRY_JAPAN31:
+       case CTRY_JAPAN32:
+       case CTRY_JAPAN33:
+       case CTRY_JAPAN34:
+       case CTRY_JAPAN35:
+       case CTRY_JAPAN36:
+       case CTRY_JAPAN37:
+       case CTRY_JAPAN38:
+       case CTRY_JAPAN39:
+       case CTRY_JAPAN40:
+       case CTRY_JAPAN41:
+       case CTRY_JAPAN42:
+       case CTRY_JAPAN43:
+       case CTRY_JAPAN44:
+       case CTRY_JAPAN45:
+       case CTRY_JAPAN46:
+       case CTRY_JAPAN47:
+       case CTRY_JAPAN48:
+       case CTRY_JAPAN49:
+       case CTRY_JAPAN50:
+       case CTRY_JAPAN51:
+       case CTRY_JAPAN52:
+       case CTRY_JAPAN53:
+       case CTRY_JAPAN54:
+       case CTRY_JAPAN55:
+       case CTRY_JAPAN56:
+       case CTRY_JAPAN57:
+       case CTRY_JAPAN58:
+       case CTRY_JAPAN59:
+               return false;
+       }
+
+       return true;
+}
+
+static bool ath_reg_dyn_country_user_allow(struct ath_regulatory *reg)
+{
+       if (!config_enabled(CONFIG_ATH_REG_DYNAMIC_USER_REG_HINTS))
+               return false;
+       if (!dynamic_country_user_possible(reg))
+               return false;
+       return true;
+}
+
 static inline bool is_wwr_sku(u16 regd)
 {
        return ((regd & COUNTRY_ERD_FLAG) != COUNTRY_ERD_FLAG) &&
@@ -177,118 +259,139 @@ static bool ath_is_radar_freq(u16 center_freq)
        return (center_freq >= 5260 && center_freq <= 5700);
 }
 
+static void ath_force_clear_no_ir_chan(struct wiphy *wiphy,
+                                      struct ieee80211_channel *ch)
+{
+       const struct ieee80211_reg_rule *reg_rule;
+
+       reg_rule = freq_reg_info(wiphy, MHZ_TO_KHZ(ch->center_freq));
+       if (IS_ERR(reg_rule))
+               return;
+
+       if (!(reg_rule->flags & NL80211_RRF_NO_IR))
+               if (ch->flags & IEEE80211_CHAN_NO_IR)
+                       ch->flags &= ~IEEE80211_CHAN_NO_IR;
+}
+
+static void ath_force_clear_no_ir_freq(struct wiphy *wiphy, u16 center_freq)
+{
+       struct ieee80211_channel *ch;
+
+       ch = ieee80211_get_channel(wiphy, center_freq);
+       if (!ch)
+               return;
+
+       ath_force_clear_no_ir_chan(wiphy, ch);
+}
+
+static void ath_force_no_ir_chan(struct ieee80211_channel *ch)
+{
+       ch->flags |= IEEE80211_CHAN_NO_IR;
+}
+
+static void ath_force_no_ir_freq(struct wiphy *wiphy, u16 center_freq)
+{
+       struct ieee80211_channel *ch;
+
+       ch = ieee80211_get_channel(wiphy, center_freq);
+       if (!ch)
+               return;
+
+       ath_force_no_ir_chan(ch);
+}
+
+static void
+__ath_reg_apply_beaconing_flags(struct wiphy *wiphy,
+                               struct ath_regulatory *reg,
+                               enum nl80211_reg_initiator initiator,
+                               struct ieee80211_channel *ch)
+{
+       if (ath_is_radar_freq(ch->center_freq) ||
+           (ch->flags & IEEE80211_CHAN_RADAR))
+               return;
+
+       switch (initiator) {
+       case NL80211_REGDOM_SET_BY_COUNTRY_IE:
+               ath_force_clear_no_ir_chan(wiphy, ch);
+               break;
+       case NL80211_REGDOM_SET_BY_USER:
+               if (ath_reg_dyn_country_user_allow(reg))
+                       ath_force_clear_no_ir_chan(wiphy, ch);
+               break;
+       default:
+               if (ch->beacon_found)
+                       ch->flags &= ~IEEE80211_CHAN_NO_IR;
+       }
+}
+
 /*
- * N.B: These exception rules do not apply radar freqs.
+ * These exception rules do not apply radar frequencies.
  *
- * - We enable adhoc (or beaconing) if allowed by 11d
- * - We enable active scan if the channel is allowed by 11d
+ * - We enable initiating radiation if the country IE says its fine:
  * - If no country IE has been processed and a we determine we have
- *   received a beacon on a channel we can enable active scan and
- *   adhoc (or beaconing).
+ *   received a beacon on a channel we can enable initiating radiation.
  */
 static void
 ath_reg_apply_beaconing_flags(struct wiphy *wiphy,
+                             struct ath_regulatory *reg,
                              enum nl80211_reg_initiator initiator)
 {
        enum ieee80211_band band;
        struct ieee80211_supported_band *sband;
-       const struct ieee80211_reg_rule *reg_rule;
        struct ieee80211_channel *ch;
        unsigned int i;
 
        for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
-
                if (!wiphy->bands[band])
                        continue;
-
                sband = wiphy->bands[band];
-
                for (i = 0; i < sband->n_channels; i++) {
-
                        ch = &sband->channels[i];
-
-                       if (ath_is_radar_freq(ch->center_freq) ||
-                           (ch->flags & IEEE80211_CHAN_RADAR))
-                               continue;
-
-                       if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) {
-                               reg_rule = freq_reg_info(wiphy, ch->center_freq);
-                               if (IS_ERR(reg_rule))
-                                       continue;
-                               /*
-                                * If 11d had a rule for this channel ensure
-                                * we enable adhoc/beaconing if it allows us to
-                                * use it. Note that we would have disabled it
-                                * by applying our static world regdomain by
-                                * default during init, prior to calling our
-                                * regulatory_hint().
-                                */
-                               if (!(reg_rule->flags &
-                                   NL80211_RRF_NO_IBSS))
-                                       ch->flags &=
-                                         ~IEEE80211_CHAN_NO_IBSS;
-                               if (!(reg_rule->flags &
-                                   NL80211_RRF_PASSIVE_SCAN))
-                                       ch->flags &=
-                                         ~IEEE80211_CHAN_PASSIVE_SCAN;
-                       } else {
-                               if (ch->beacon_found)
-                                       ch->flags &= ~(IEEE80211_CHAN_NO_IBSS |
-                                         IEEE80211_CHAN_PASSIVE_SCAN);
-                       }
+                       __ath_reg_apply_beaconing_flags(wiphy, reg,
+                                                       initiator, ch);
                }
        }
-
 }
 
-/* Allows active scan scan on Ch 12 and 13 */
+/**
+ * ath_reg_apply_ir_flags()
+ * @wiphy: the wiphy to use
+ * @initiator: the regulatory hint initiator
+ *
+ * If no country IE has been received always enable passive scan
+ * and no-ibss on these channels. This is only done for specific
+ * regulatory SKUs.
+ *
+ * If a country IE has been received check its rule for this
+ * channel first before enabling active scan. The passive scan
+ * would have been enforced by the initial processing of our
+ * custom regulatory domain.
+ */
 static void
-ath_reg_apply_active_scan_flags(struct wiphy *wiphy,
-                               enum nl80211_reg_initiator initiator)
+ath_reg_apply_ir_flags(struct wiphy *wiphy,
+                      struct ath_regulatory *reg,
+                      enum nl80211_reg_initiator initiator)
 {
        struct ieee80211_supported_band *sband;
-       struct ieee80211_channel *ch;
-       const struct ieee80211_reg_rule *reg_rule;
 
        sband = wiphy->bands[IEEE80211_BAND_2GHZ];
        if (!sband)
                return;
 
-       /*
-        * If no country IE has been received always enable active scan
-        * on these channels. This is only done for specific regulatory SKUs
-        */
-       if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) {
-               ch = &sband->channels[11]; /* CH 12 */
-               if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
-                       ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
-               ch = &sband->channels[12]; /* CH 13 */
-               if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
-                       ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
-               return;
-       }
-
-       /*
-        * If a country IE has been received check its rule for this
-        * channel first before enabling active scan. The passive scan
-        * would have been enforced by the initial processing of our
-        * custom regulatory domain.
-        */
-
-       ch = &sband->channels[11]; /* CH 12 */
-       reg_rule = freq_reg_info(wiphy, ch->center_freq);
-       if (!IS_ERR(reg_rule)) {
-               if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
-                       if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
-                               ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
-       }
-
-       ch = &sband->channels[12]; /* CH 13 */
-       reg_rule = freq_reg_info(wiphy, ch->center_freq);
-       if (!IS_ERR(reg_rule)) {
-               if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
-                       if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
-                               ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
+       switch(initiator) {
+       case NL80211_REGDOM_SET_BY_COUNTRY_IE:
+               ath_force_clear_no_ir_freq(wiphy, 2467);
+               ath_force_clear_no_ir_freq(wiphy, 2472);
+               break;
+       case NL80211_REGDOM_SET_BY_USER:
+               if (!ath_reg_dyn_country_user_allow(reg))
+                       break;
+               ath_force_clear_no_ir_freq(wiphy, 2467);
+               ath_force_clear_no_ir_freq(wiphy, 2472);
+               break;
+       default:
+               ath_force_no_ir_freq(wiphy, 2467);
+               ath_force_no_ir_freq(wiphy, 2472);
        }
 }
 
@@ -320,8 +423,7 @@ static void ath_reg_apply_radar_flags(struct wiphy *wiphy)
                 */
                if (!(ch->flags & IEEE80211_CHAN_DISABLED))
                        ch->flags |= IEEE80211_CHAN_RADAR |
-                                    IEEE80211_CHAN_NO_IBSS |
-                                    IEEE80211_CHAN_PASSIVE_SCAN;
+                                    IEEE80211_CHAN_NO_IR;
        }
 }
 
@@ -335,12 +437,15 @@ static void ath_reg_apply_world_flags(struct wiphy *wiphy,
        case 0x66:
        case 0x67:
        case 0x6C:
-               ath_reg_apply_beaconing_flags(wiphy, initiator);
+               ath_reg_apply_beaconing_flags(wiphy, reg, initiator);
                break;
        case 0x68:
-               ath_reg_apply_beaconing_flags(wiphy, initiator);
-               ath_reg_apply_active_scan_flags(wiphy, initiator);
+               ath_reg_apply_beaconing_flags(wiphy, reg, initiator);
+               ath_reg_apply_ir_flags(wiphy, reg, initiator);
                break;
+       default:
+               if (ath_reg_dyn_country_user_allow(reg))
+                       ath_reg_apply_beaconing_flags(wiphy, reg, initiator);
        }
 }
 
@@ -393,89 +498,6 @@ static void ath_reg_dyn_country(struct wiphy *wiphy,
               reg_initiator_name(request->initiator));
 }
 
-static bool dynamic_country_user_possible(struct ath_regulatory *reg)
-{
-       if (config_enabled(CONFIG_ATH_REG_DYNAMIC_USER_CERT_TESTING))
-               return true;
-
-       switch (reg->country_code) {
-       case CTRY_UNITED_STATES:
-       case CTRY_JAPAN1:
-       case CTRY_JAPAN2:
-       case CTRY_JAPAN3:
-       case CTRY_JAPAN4:
-       case CTRY_JAPAN5:
-       case CTRY_JAPAN6:
-       case CTRY_JAPAN7:
-       case CTRY_JAPAN8:
-       case CTRY_JAPAN9:
-       case CTRY_JAPAN10:
-       case CTRY_JAPAN11:
-       case CTRY_JAPAN12:
-       case CTRY_JAPAN13:
-       case CTRY_JAPAN14:
-       case CTRY_JAPAN15:
-       case CTRY_JAPAN16:
-       case CTRY_JAPAN17:
-       case CTRY_JAPAN18:
-       case CTRY_JAPAN19:
-       case CTRY_JAPAN20:
-       case CTRY_JAPAN21:
-       case CTRY_JAPAN22:
-       case CTRY_JAPAN23:
-       case CTRY_JAPAN24:
-       case CTRY_JAPAN25:
-       case CTRY_JAPAN26:
-       case CTRY_JAPAN27:
-       case CTRY_JAPAN28:
-       case CTRY_JAPAN29:
-       case CTRY_JAPAN30:
-       case CTRY_JAPAN31:
-       case CTRY_JAPAN32:
-       case CTRY_JAPAN33:
-       case CTRY_JAPAN34:
-       case CTRY_JAPAN35:
-       case CTRY_JAPAN36:
-       case CTRY_JAPAN37:
-       case CTRY_JAPAN38:
-       case CTRY_JAPAN39:
-       case CTRY_JAPAN40:
-       case CTRY_JAPAN41:
-       case CTRY_JAPAN42:
-       case CTRY_JAPAN43:
-       case CTRY_JAPAN44:
-       case CTRY_JAPAN45:
-       case CTRY_JAPAN46:
-       case CTRY_JAPAN47:
-       case CTRY_JAPAN48:
-       case CTRY_JAPAN49:
-       case CTRY_JAPAN50:
-       case CTRY_JAPAN51:
-       case CTRY_JAPAN52:
-       case CTRY_JAPAN53:
-       case CTRY_JAPAN54:
-       case CTRY_JAPAN55:
-       case CTRY_JAPAN56:
-       case CTRY_JAPAN57:
-       case CTRY_JAPAN58:
-       case CTRY_JAPAN59:
-               return false;
-       }
-
-       return true;
-}
-
-static void ath_reg_dyn_country_user(struct wiphy *wiphy,
-                                    struct ath_regulatory *reg,
-                                    struct regulatory_request *request)
-{
-       if (!config_enabled(CONFIG_ATH_REG_DYNAMIC_USER_REG_HINTS))
-               return;
-       if (!dynamic_country_user_possible(reg))
-               return;
-       ath_reg_dyn_country(wiphy, reg, request);
-}
-
 void ath_reg_notifier_apply(struct wiphy *wiphy,
                            struct regulatory_request *request,
                            struct ath_regulatory *reg)
@@ -508,7 +530,8 @@ void ath_reg_notifier_apply(struct wiphy *wiphy,
        case NL80211_REGDOM_SET_BY_DRIVER:
                break;
        case NL80211_REGDOM_SET_BY_USER:
-               ath_reg_dyn_country_user(wiphy, reg, request);
+               if (ath_reg_dyn_country_user_allow(reg))
+                       ath_reg_dyn_country(wiphy, reg, request);
                break;
        case NL80211_REGDOM_SET_BY_COUNTRY_IE:
                ath_reg_dyn_country(wiphy, reg, request);
@@ -609,7 +632,7 @@ ath_regd_init_wiphy(struct ath_regulatory *reg,
        const struct ieee80211_regdomain *regd;
 
        wiphy->reg_notifier = reg_notifier;
-       wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY;
+       wiphy->regulatory_flags |= REGULATORY_STRICT_REG;
 
        if (ath_is_world_regd(reg)) {
                /*
@@ -617,7 +640,8 @@ ath_regd_init_wiphy(struct ath_regulatory *reg,
                 * saved on the wiphy orig_* parameters
                 */
                regd = ath_world_regdomain(reg);
-               wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
+               wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG |
+                                          REGULATORY_COUNTRY_IE_FOLLOW_POWER;
        } else {
                /*
                 * This gets applied in the case of the absence of CRDA,
index c02dbc618724720cee3c97a3fa86a249188fff5b..3c2ef0c32f72c7ef37b9b032e3b66ec3ab9619d6 100644 (file)
@@ -2644,7 +2644,7 @@ struct wcn36xx_hal_trigger_ba_rsp_candidate {
        struct add_ba_info ba_info[STACFG_MAX_TC];
 } __packed;
 
-struct wcn36xx_hal_trigget_ba_req_candidate {
+struct wcn36xx_hal_trigger_ba_req_candidate {
        u8 sta_index;
        u8 tid_bitmap;
 } __packed;
index 7839b31e4826e5013a391b94f405483f6c4e977f..e64a6784079e20446ad57078f607e0f01b7565a1 100644 (file)
@@ -641,7 +641,8 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
                dev_kfree_skb(skb);
        }
 
-       if (changed & BSS_CHANGED_BEACON_ENABLED) {
+       if (changed & BSS_CHANGED_BEACON_ENABLED ||
+           changed & BSS_CHANGED_BEACON) {
                wcn36xx_dbg(WCN36XX_DBG_MAC,
                            "mac bss changed beacon enabled %d\n",
                            bss_conf->enable_beacon);
index de9eb2cfbf4b5784c36a97da2748acd357250c37..8f37562e0b113d6e5d4b13e50ea87cba679c6628 100644 (file)
@@ -115,6 +115,22 @@ static void wcn36xx_smd_set_sta_ht_params(struct ieee80211_sta *sta,
        }
 }
 
+static void wcn36xx_smd_set_sta_default_ht_params(
+               struct wcn36xx_hal_config_sta_params *sta_params)
+{
+       sta_params->ht_capable = 1;
+       sta_params->tx_channel_width_set = 1;
+       sta_params->lsig_txop_protection = 1;
+       sta_params->max_ampdu_size = 3;
+       sta_params->max_ampdu_density = 5;
+       sta_params->max_amsdu_size = 0;
+       sta_params->sgi_20Mhz = 1;
+       sta_params->sgi_40mhz = 1;
+       sta_params->green_field_capable = 1;
+       sta_params->delayed_ba_support = 0;
+       sta_params->dsss_cck_mode_40mhz = 1;
+}
+
 static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn,
                struct ieee80211_vif *vif,
                struct ieee80211_sta *sta,
@@ -172,6 +188,7 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn,
                        sizeof(priv_sta->supported_rates));
        } else {
                wcn36xx_set_default_rates(&sta_params->supported_rates);
+               wcn36xx_smd_set_sta_default_ht_params(sta_params);
        }
 }
 
@@ -1134,14 +1151,14 @@ int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif,
                /* STA */
                bss->oper_mode = 1;
                bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_MODE;
-       } else if (vif->type == NL80211_IFTYPE_AP) {
+       } else if (vif->type == NL80211_IFTYPE_AP ||
+                  vif->type == NL80211_IFTYPE_MESH_POINT) {
                bss->bss_type = WCN36XX_HAL_INFRA_AP_MODE;
 
                /* AP */
                bss->oper_mode = 0;
                bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_SAP_MODE;
-       } else if (vif->type == NL80211_IFTYPE_ADHOC ||
-                  vif->type == NL80211_IFTYPE_MESH_POINT) {
+       } else if (vif->type == NL80211_IFTYPE_ADHOC) {
                bss->bss_type = WCN36XX_HAL_IBSS_MODE;
 
                /* STA */
@@ -1292,7 +1309,11 @@ int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif,
        memcpy(msg_body.bssid, vif->addr, ETH_ALEN);
 
        /* TODO need to find out why this is needed? */
-       msg_body.tim_ie_offset = tim_off+4;
+       if (vif->type == NL80211_IFTYPE_MESH_POINT)
+               /* mesh beacon don't need this, so push further down */
+               msg_body.tim_ie_offset = 256;
+       else
+               msg_body.tim_ie_offset = tim_off+4;
        msg_body.p2p_ie_offset = p2p_off;
        PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
 
@@ -1838,7 +1859,7 @@ out:
 int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index)
 {
        struct wcn36xx_hal_trigger_ba_req_msg msg_body;
-       struct wcn36xx_hal_trigget_ba_req_candidate *candidate;
+       struct wcn36xx_hal_trigger_ba_req_candidate *candidate;
        int ret = 0;
 
        mutex_lock(&wcn->hal_mutex);
@@ -1849,7 +1870,7 @@ int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index)
        msg_body.header.len += sizeof(*candidate);
        PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
 
-       candidate = (struct wcn36xx_hal_trigget_ba_req_candidate *)
+       candidate = (struct wcn36xx_hal_trigger_ba_req_candidate *)
                (wcn->hal_buf + sizeof(msg_body));
        candidate->sta_index = sta_index;
        candidate->tid_bitmap = 1;
@@ -2041,13 +2062,20 @@ static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len)
        case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
                mutex_lock(&wcn->hal_ind_mutex);
                msg_ind = kmalloc(sizeof(*msg_ind), GFP_KERNEL);
-               msg_ind->msg_len = len;
-               msg_ind->msg = kmalloc(len, GFP_KERNEL);
-               memcpy(msg_ind->msg, buf, len);
-               list_add_tail(&msg_ind->list, &wcn->hal_ind_queue);
-               queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work);
-               wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n");
+               if (msg_ind) {
+                       msg_ind->msg_len = len;
+                       msg_ind->msg = kmalloc(len, GFP_KERNEL);
+                       memcpy(msg_ind->msg, buf, len);
+                       list_add_tail(&msg_ind->list, &wcn->hal_ind_queue);
+                       queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work);
+                       wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n");
+               }
                mutex_unlock(&wcn->hal_ind_mutex);
+               if (msg_ind)
+                       break;
+               /* FIXME: Do something smarter then just printing an error. */
+               wcn36xx_err("Run out of memory while handling SMD_EVENT (%d)\n",
+                           msg_header->msg_type);
                break;
        default:
                wcn36xx_err("SMD_EVENT (%d) not supported\n",
index 58b63833e8e72d1d8dee64b31c14374369ecb072..8fa5cbace5abba1e027954a64b312bdc37f7b13c 100644 (file)
@@ -54,7 +54,7 @@ enum wcn36xx_debug_mask {
 };
 
 #define wcn36xx_err(fmt, arg...)                               \
-       printk(KERN_ERR pr_fmt("ERROR " fmt), ##arg);
+       printk(KERN_ERR pr_fmt("ERROR " fmt), ##arg)
 
 #define wcn36xx_warn(fmt, arg...)                              \
        printk(KERN_WARNING pr_fmt("WARNING " fmt), ##arg)
index 0d950f209dae01efd23ebe9956ac2dc68daa7063..b73b7e3e21961315b61b2515edd8a85bbd323698 100644 (file)
@@ -28,8 +28,8 @@
     GNU General Public License for more details.
 
     You should have received a copy of the GNU General Public License
-    along with Atmel wireless lan drivers; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+    along with Atmel wireless lan drivers; if not, see
+    <http://www.gnu.org/licenses/>.
 
     For all queries about this code, please contact the current author,
     Simon Kelley <simon@thekelleys.org.uk> and not Atmel Corporation.
@@ -4278,8 +4278,7 @@ static void atmel_wmem32(struct atmel_private *priv, u16 pos, u32 data)
     GNU General Public License for more details.
 
     You should have received a copy of the GNU General Public License
-    along with AtmelMACFW; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+    along with AtmelMACFW; if not, see <http://www.gnu.org/licenses/>.
 
 ****************************************************************************/
 /* This firmware should work on the 76C502 RFMD, RFMD_D, and RFMD_E        */
index b9b3e5b765446126d7f7a03e63f0b669f42cb87b..96f7318cbb04dd08d114a10b1a0005084bedd0c1 100644 (file)
@@ -15,8 +15,8 @@
     GNU General Public License for more details.
 
     You should have received a copy of the GNU General Public License
-    along with Atmel wireless lan drivers; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+    along with Atmel wireless lan drivers; if not, see
+    <http://www.gnu.org/licenses/>.
 
 ******************************************************************************/
 
index 52257221921778300323389d94cb7e2f37f6e9ef..5e2749dd112420562a4efde6ca3717de5cc16446 100644 (file)
@@ -24,8 +24,8 @@
     GNU General Public License for more details.
 
     You should have received a copy of the GNU General Public License
-    along with Atmel wireless lan drivers; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+    along with Atmel wireless lan drivers; if not, see
+    <http://www.gnu.org/licenses/>.
 
 ******************************************************************************/
 
index c1b159ebcffee4412987c4ba1d22cb080c1ea8d4..64d5973ec28b1c1ca62d7611bf03169eec45f4cf 100644 (file)
@@ -15,8 +15,8 @@
     GNU General Public License for more details.
 
     You should have received a copy of the GNU General Public License
-    along with Atmel wireless lan drivers; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+    along with Atmel wireless lan drivers; if not, see
+    <http://www.gnu.org/licenses/>.
 
 ******************************************************************************/
 #include <linux/pci.h>
index b00a7e92225f7b928f5a3cf7395f860af27299bd..fcfed6b99a62d6e16e66634df2df85198cbb64da 100644 (file)
@@ -4,11 +4,12 @@ config BRCMUTIL
 config BRCMSMAC
        tristate "Broadcom IEEE802.11n PCIe SoftMAC WLAN driver"
        depends on MAC80211
-       depends on BCMA
+       depends on BCMA_POSSIBLE
+       select BCMA
+       select NEW_LEDS if BCMA_DRIVER_GPIO
+       select LEDS_CLASS if BCMA_DRIVER_GPIO
        select BRCMUTIL
        select FW_LOADER
-       select CRC_CCITT
-       select CRC8
        select CORDIC
        ---help---
          This module adds support for PCIe wireless adapters based on Broadcom
index 8e9b1221b32c1918f7981cf2d4228b44684ac091..2082402d4b6364e03424f4ef00161b0fae9c298b 100644 (file)
@@ -28,7 +28,8 @@ brcmfmac-objs += \
                fweh.o \
                fwsignal.o \
                p2p.o \
-               dhd_cdc.o \
+               proto.o \
+               bcdc.o \
                dhd_common.o \
                dhd_linux.o \
                btcoex.o
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
new file mode 100644 (file)
index 0000000..06848e4
--- /dev/null
@@ -0,0 +1,384 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*******************************************************************************
+ * Communicates with the dongle by using dcmd codes.
+ * For certain dcmd codes, the dongle interprets string data from the host.
+ ******************************************************************************/
+
+#include <linux/types.h>
+#include <linux/netdevice.h>
+
+#include <brcmu_utils.h>
+#include <brcmu_wifi.h>
+
+#include "dhd.h"
+#include "dhd_bus.h"
+#include "fwsignal.h"
+#include "dhd_dbg.h"
+#include "tracepoint.h"
+#include "proto.h"
+#include "bcdc.h"
+
+struct brcmf_proto_bcdc_dcmd {
+       __le32 cmd;     /* dongle command value */
+       __le32 len;     /* lower 16: output buflen;
+                        * upper 16: input buflen (excludes header) */
+       __le32 flags;   /* flag defns given below */
+       __le32 status;  /* status code returned from the device */
+};
+
+/* Max valid buffer size that can be sent to the dongle */
+#define BCDC_MAX_MSG_SIZE      (ETH_FRAME_LEN+ETH_FCS_LEN)
+
+/* BCDC flag definitions */
+#define BCDC_DCMD_ERROR                0x01            /* 1=cmd failed */
+#define BCDC_DCMD_SET          0x02            /* 0=get, 1=set cmd */
+#define BCDC_DCMD_IF_MASK      0xF000          /* I/F index */
+#define BCDC_DCMD_IF_SHIFT     12
+#define BCDC_DCMD_ID_MASK      0xFFFF0000      /* id an cmd pairing */
+#define BCDC_DCMD_ID_SHIFT     16              /* ID Mask shift bits */
+#define BCDC_DCMD_ID(flags)    \
+       (((flags) & BCDC_DCMD_ID_MASK) >> BCDC_DCMD_ID_SHIFT)
+
+/*
+ * BCDC header - Broadcom specific extension of CDC.
+ * Used on data packets to convey priority across USB.
+ */
+#define        BCDC_HEADER_LEN         4
+#define BCDC_PROTO_VER         2       /* Protocol version */
+#define BCDC_FLAG_VER_MASK     0xf0    /* Protocol version mask */
+#define BCDC_FLAG_VER_SHIFT    4       /* Protocol version shift */
+#define BCDC_FLAG_SUM_GOOD     0x04    /* Good RX checksums */
+#define BCDC_FLAG_SUM_NEEDED   0x08    /* Dongle needs to do TX checksums */
+#define BCDC_PRIORITY_MASK     0x7
+#define BCDC_FLAG2_IF_MASK     0x0f    /* packet rx interface in APSTA */
+#define BCDC_FLAG2_IF_SHIFT    0
+
+#define BCDC_GET_IF_IDX(hdr) \
+       ((int)((((hdr)->flags2) & BCDC_FLAG2_IF_MASK) >> BCDC_FLAG2_IF_SHIFT))
+#define BCDC_SET_IF_IDX(hdr, idx) \
+       ((hdr)->flags2 = (((hdr)->flags2 & ~BCDC_FLAG2_IF_MASK) | \
+       ((idx) << BCDC_FLAG2_IF_SHIFT)))
+
+/**
+ * struct brcmf_proto_bcdc_header - BCDC header format
+ *
+ * @flags: flags contain protocol and checksum info.
+ * @priority: 802.1d priority and USB flow control info (bit 4:7).
+ * @flags2: additional flags containing dongle interface index.
+ * @data_offset: start of packet data. header is following by firmware signals.
+ */
+struct brcmf_proto_bcdc_header {
+       u8 flags;
+       u8 priority;
+       u8 flags2;
+       u8 data_offset;
+};
+
+/*
+ * maximum length of firmware signal data between
+ * the BCDC header and packet data in the tx path.
+ */
+#define BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES       12
+
+#define RETRIES 2 /* # of retries to retrieve matching dcmd response */
+#define BUS_HEADER_LEN (16+64)         /* Must be atleast SDPCM_RESERVE
+                                        * (amount of header tha might be added)
+                                        * plus any space that might be needed
+                                        * for bus alignment padding.
+                                        */
+#define ROUND_UP_MARGIN        2048    /* Biggest bus block size possible for
+                                * round off at the end of buffer
+                                * Currently is SDIO
+                                */
+
+struct brcmf_bcdc {
+       u16 reqid;
+       u8 bus_header[BUS_HEADER_LEN];
+       struct brcmf_proto_bcdc_dcmd msg;
+       unsigned char buf[BRCMF_DCMD_MAXLEN + ROUND_UP_MARGIN];
+};
+
+static int brcmf_proto_bcdc_msg(struct brcmf_pub *drvr)
+{
+       struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd;
+       int len = le32_to_cpu(bcdc->msg.len) +
+                       sizeof(struct brcmf_proto_bcdc_dcmd);
+
+       brcmf_dbg(BCDC, "Enter\n");
+
+       /* NOTE : bcdc->msg.len holds the desired length of the buffer to be
+        *        returned. Only up to BCDC_MAX_MSG_SIZE of this buffer area
+        *        is actually sent to the dongle
+        */
+       if (len > BCDC_MAX_MSG_SIZE)
+               len = BCDC_MAX_MSG_SIZE;
+
+       /* Send request */
+       return brcmf_bus_txctl(drvr->bus_if, (unsigned char *)&bcdc->msg, len);
+}
+
+static int brcmf_proto_bcdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len)
+{
+       int ret;
+       struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd;
+
+       brcmf_dbg(BCDC, "Enter\n");
+       len += sizeof(struct brcmf_proto_bcdc_dcmd);
+       do {
+               ret = brcmf_bus_rxctl(drvr->bus_if, (unsigned char *)&bcdc->msg,
+                                     len);
+               if (ret < 0)
+                       break;
+       } while (BCDC_DCMD_ID(le32_to_cpu(bcdc->msg.flags)) != id);
+
+       return ret;
+}
+
+static int
+brcmf_proto_bcdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
+                           void *buf, uint len)
+{
+       struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd;
+       struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg;
+       void *info;
+       int ret = 0, retries = 0;
+       u32 id, flags;
+
+       brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len);
+
+       memset(msg, 0, sizeof(struct brcmf_proto_bcdc_dcmd));
+
+       msg->cmd = cpu_to_le32(cmd);
+       msg->len = cpu_to_le32(len);
+       flags = (++bcdc->reqid << BCDC_DCMD_ID_SHIFT);
+       flags = (flags & ~BCDC_DCMD_IF_MASK) |
+               (ifidx << BCDC_DCMD_IF_SHIFT);
+       msg->flags = cpu_to_le32(flags);
+
+       if (buf)
+               memcpy(bcdc->buf, buf, len);
+
+       ret = brcmf_proto_bcdc_msg(drvr);
+       if (ret < 0) {
+               brcmf_err("brcmf_proto_bcdc_msg failed w/status %d\n",
+                         ret);
+               goto done;
+       }
+
+retry:
+       /* wait for interrupt and get first fragment */
+       ret = brcmf_proto_bcdc_cmplt(drvr, bcdc->reqid, len);
+       if (ret < 0)
+               goto done;
+
+       flags = le32_to_cpu(msg->flags);
+       id = (flags & BCDC_DCMD_ID_MASK) >> BCDC_DCMD_ID_SHIFT;
+
+       if ((id < bcdc->reqid) && (++retries < RETRIES))
+               goto retry;
+       if (id != bcdc->reqid) {
+               brcmf_err("%s: unexpected request id %d (expected %d)\n",
+                         brcmf_ifname(drvr, ifidx), id, bcdc->reqid);
+               ret = -EINVAL;
+               goto done;
+       }
+
+       /* Check info buffer */
+       info = (void *)&msg[1];
+
+       /* Copy info buffer */
+       if (buf) {
+               if (ret < (int)len)
+                       len = ret;
+               memcpy(buf, info, len);
+       }
+
+       /* Check the ERROR flag */
+       if (flags & BCDC_DCMD_ERROR)
+               ret = le32_to_cpu(msg->status);
+
+done:
+       return ret;
+}
+
+static int
+brcmf_proto_bcdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
+                         void *buf, uint len)
+{
+       struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd;
+       struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg;
+       int ret = 0;
+       u32 flags, id;
+
+       brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len);
+
+       memset(msg, 0, sizeof(struct brcmf_proto_bcdc_dcmd));
+
+       msg->cmd = cpu_to_le32(cmd);
+       msg->len = cpu_to_le32(len);
+       flags = (++bcdc->reqid << BCDC_DCMD_ID_SHIFT) | BCDC_DCMD_SET;
+       flags = (flags & ~BCDC_DCMD_IF_MASK) |
+               (ifidx << BCDC_DCMD_IF_SHIFT);
+       msg->flags = cpu_to_le32(flags);
+
+       if (buf)
+               memcpy(bcdc->buf, buf, len);
+
+       ret = brcmf_proto_bcdc_msg(drvr);
+       if (ret < 0)
+               goto done;
+
+       ret = brcmf_proto_bcdc_cmplt(drvr, bcdc->reqid, len);
+       if (ret < 0)
+               goto done;
+
+       flags = le32_to_cpu(msg->flags);
+       id = (flags & BCDC_DCMD_ID_MASK) >> BCDC_DCMD_ID_SHIFT;
+
+       if (id != bcdc->reqid) {
+               brcmf_err("%s: unexpected request id %d (expected %d)\n",
+                         brcmf_ifname(drvr, ifidx), id, bcdc->reqid);
+               ret = -EINVAL;
+               goto done;
+       }
+
+       /* Check the ERROR flag */
+       if (flags & BCDC_DCMD_ERROR)
+               ret = le32_to_cpu(msg->status);
+
+done:
+       return ret;
+}
+
+static void
+brcmf_proto_bcdc_hdrpush(struct brcmf_pub *drvr, int ifidx, u8 offset,
+                        struct sk_buff *pktbuf)
+{
+       struct brcmf_proto_bcdc_header *h;
+
+       brcmf_dbg(BCDC, "Enter\n");
+
+       /* Push BDC header used to convey priority for buses that don't */
+       skb_push(pktbuf, BCDC_HEADER_LEN);
+
+       h = (struct brcmf_proto_bcdc_header *)(pktbuf->data);
+
+       h->flags = (BCDC_PROTO_VER << BCDC_FLAG_VER_SHIFT);
+       if (pktbuf->ip_summed == CHECKSUM_PARTIAL)
+               h->flags |= BCDC_FLAG_SUM_NEEDED;
+
+       h->priority = (pktbuf->priority & BCDC_PRIORITY_MASK);
+       h->flags2 = 0;
+       h->data_offset = offset;
+       BCDC_SET_IF_IDX(h, ifidx);
+       trace_brcmf_bcdchdr(pktbuf->data);
+}
+
+static int
+brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx,
+                        struct sk_buff *pktbuf)
+{
+       struct brcmf_proto_bcdc_header *h;
+
+       brcmf_dbg(BCDC, "Enter\n");
+
+       /* Pop BCDC header used to convey priority for buses that don't */
+       if (pktbuf->len <= BCDC_HEADER_LEN) {
+               brcmf_dbg(INFO, "rx data too short (%d <= %d)\n",
+                         pktbuf->len, BCDC_HEADER_LEN);
+               return -EBADE;
+       }
+
+       trace_brcmf_bcdchdr(pktbuf->data);
+       h = (struct brcmf_proto_bcdc_header *)(pktbuf->data);
+
+       *ifidx = BCDC_GET_IF_IDX(h);
+       if (*ifidx >= BRCMF_MAX_IFS) {
+               brcmf_err("rx data ifnum out of range (%d)\n", *ifidx);
+               return -EBADE;
+       }
+       /* The ifidx is the idx to map to matching netdev/ifp. When receiving
+        * events this is easy because it contains the bssidx which maps
+        * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd.
+        * bssidx 1 is used for p2p0 and no data can be received or
+        * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0
+        */
+       if (*ifidx)
+               (*ifidx)++;
+
+       if (((h->flags & BCDC_FLAG_VER_MASK) >> BCDC_FLAG_VER_SHIFT) !=
+           BCDC_PROTO_VER) {
+               brcmf_err("%s: non-BCDC packet received, flags 0x%x\n",
+                         brcmf_ifname(drvr, *ifidx), h->flags);
+               return -EBADE;
+       }
+
+       if (h->flags & BCDC_FLAG_SUM_GOOD) {
+               brcmf_dbg(BCDC, "%s: BDC rcv, good checksum, flags 0x%x\n",
+                         brcmf_ifname(drvr, *ifidx), h->flags);
+               pktbuf->ip_summed = CHECKSUM_UNNECESSARY;
+       }
+
+       pktbuf->priority = h->priority & BCDC_PRIORITY_MASK;
+
+       skb_pull(pktbuf, BCDC_HEADER_LEN);
+       if (do_fws)
+               brcmf_fws_hdrpull(drvr, *ifidx, h->data_offset << 2, pktbuf);
+       else
+               skb_pull(pktbuf, h->data_offset << 2);
+
+       if (pktbuf->len == 0)
+               return -ENODATA;
+       return 0;
+}
+
+int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr)
+{
+       struct brcmf_bcdc *bcdc;
+
+       bcdc = kzalloc(sizeof(*bcdc), GFP_ATOMIC);
+       if (!bcdc)
+               goto fail;
+
+       /* ensure that the msg buf directly follows the cdc msg struct */
+       if ((unsigned long)(&bcdc->msg + 1) != (unsigned long)bcdc->buf) {
+               brcmf_err("struct brcmf_proto_bcdc is not correctly defined\n");
+               goto fail;
+       }
+
+       drvr->proto->hdrpush = brcmf_proto_bcdc_hdrpush;
+       drvr->proto->hdrpull = brcmf_proto_bcdc_hdrpull;
+       drvr->proto->query_dcmd = brcmf_proto_bcdc_query_dcmd;
+       drvr->proto->set_dcmd = brcmf_proto_bcdc_set_dcmd;
+       drvr->proto->pd = bcdc;
+
+       drvr->hdrlen += BCDC_HEADER_LEN + BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES;
+       drvr->bus_if->maxctl = BRCMF_DCMD_MAXLEN +
+                       sizeof(struct brcmf_proto_bcdc_dcmd) + ROUND_UP_MARGIN;
+       return 0;
+
+fail:
+       kfree(bcdc);
+       return -ENOMEM;
+}
+
+void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr)
+{
+       kfree(drvr->proto->pd);
+       drvr->proto->pd = NULL;
+}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.h b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.h
new file mode 100644 (file)
index 0000000..17e8c03
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2013 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef BRCMFMAC_BCDC_H
+#define BRCMFMAC_BCDC_H
+
+
+int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr);
+void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr);
+
+
+#endif /* BRCMFMAC_BCDC_H */
index 3e10b801eee84bc420867815ced96a3fca3428b4..91651ec7f13fedddaa7c18cce14c7654eb77404e 100644 (file)
@@ -17,7 +17,6 @@
 
 #include <linux/types.h>
 #include <linux/netdevice.h>
-#include <linux/export.h>
 #include <linux/pci.h>
 #include <linux/pci_ids.h>
 #include <linux/sched.h>
@@ -774,7 +773,6 @@ out:
 
        return ret;
 }
-EXPORT_SYMBOL(brcmf_sdio_probe);
 
 int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev)
 {
@@ -791,7 +789,6 @@ int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev)
 
        return 0;
 }
-EXPORT_SYMBOL(brcmf_sdio_remove);
 
 void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev, bool enable)
 {
index 905704e335d7164b90a4ecb6fd51c2324911c154..a511c27122b8c01da665a586675fb10a74a19bfc 100644 (file)
@@ -109,6 +109,8 @@ static inline int brcmf_sdioh_f0_write_byte(struct brcmf_sdio_dev *sdiodev,
                                        brcmf_err("Disable F2 failed:%d\n",
                                                  err_ret);
                        }
+               } else {
+                       err_ret = -ENOENT;
                }
        } else if ((regaddr == SDIO_CCCR_ABORT) ||
                   (regaddr == SDIO_CCCR_IENx)) {
@@ -156,10 +158,21 @@ int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func,
                }
        }
 
-       if (err_ret)
-               brcmf_err("Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n",
-                         rw ? "write" : "read", func, regaddr, *byte, err_ret);
-
+       if (err_ret) {
+               /*
+                * SleepCSR register access can fail when
+                * waking up the device so reduce this noise
+                * in the logs.
+                */
+               if (regaddr != SBSDIO_FUNC1_SLEEPCSR)
+                       brcmf_err("Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n",
+                                 rw ? "write" : "read", func, regaddr, *byte,
+                                 err_ret);
+               else
+                       brcmf_dbg(SDIO, "Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n",
+                                 rw ? "write" : "read", func, regaddr, *byte,
+                                 err_ret);
+       }
        return err_ret;
 }
 
@@ -267,6 +280,9 @@ static int brcmf_sdioh_enablefuncs(struct brcmf_sdio_dev *sdiodev)
 int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev)
 {
        int err_ret = 0;
+       struct mmc_host *host;
+       struct sdio_func *func;
+       uint max_blocks;
 
        brcmf_dbg(SDIO, "\n");
 
@@ -288,6 +304,20 @@ int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev)
 
        brcmf_sdioh_enablefuncs(sdiodev);
 
+       /*
+        * determine host related variables after brcmf_sdio_probe()
+        * as func->cur_blksize is properly set and F2 init has been
+        * completed successfully.
+        */
+       func = sdiodev->func[2];
+       host = func->card->host;
+       sdiodev->sg_support = host->max_segs > 1;
+       max_blocks = min_t(uint, host->max_blk_count, 511u);
+       sdiodev->max_request_size = min_t(uint, host->max_req_size,
+                                         max_blocks * func->cur_blksize);
+       sdiodev->max_segment_count = min_t(uint, host->max_segs,
+                                          SG_MAX_SINGLE_ALLOC);
+       sdiodev->max_segment_size = host->max_seg_size;
 out:
        sdio_release_host(sdiodev->func[1]);
        brcmf_dbg(SDIO, "Done\n");
@@ -316,8 +346,6 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
        int err;
        struct brcmf_sdio_dev *sdiodev;
        struct brcmf_bus *bus_if;
-       struct mmc_host *host;
-       uint max_blocks;
 
        brcmf_dbg(SDIO, "Enter\n");
        brcmf_dbg(SDIO, "Class=%x\n", func->class);
@@ -365,19 +393,6 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
                goto fail;
        }
 
-       /*
-        * determine host related variables after brcmf_sdio_probe()
-        * as func->cur_blksize is properly set and F2 init has been
-        * completed successfully.
-        */
-       host = func->card->host;
-       sdiodev->sg_support = host->max_segs > 1;
-       max_blocks = min_t(uint, host->max_blk_count, 511u);
-       sdiodev->max_request_size = min_t(uint, host->max_req_size,
-                                         max_blocks * func->cur_blksize);
-       sdiodev->max_segment_count = min_t(uint, host->max_segs,
-                                          SG_MAX_SINGLE_ALLOC);
-       sdiodev->max_segment_size = host->max_seg_size;
        brcmf_dbg(SDIO, "F2 init completed...\n");
        return 0;
 
index 899a2ada5b8212f28e30632551910b67474e6080..252024bcbc3ba736c65d18975f2b5106e026737a 100644 (file)
 
 #include "fweh.h"
 
-/*******************************************************************************
- * IO codes that are interpreted by dongle firmware
- ******************************************************************************/
-#define BRCMF_C_GET_VERSION                    1
-#define BRCMF_C_UP                             2
-#define BRCMF_C_DOWN                           3
-#define BRCMF_C_SET_PROMISC                    10
-#define BRCMF_C_GET_RATE                       12
-#define BRCMF_C_GET_INFRA                      19
-#define BRCMF_C_SET_INFRA                      20
-#define BRCMF_C_GET_AUTH                       21
-#define BRCMF_C_SET_AUTH                       22
-#define BRCMF_C_GET_BSSID                      23
-#define BRCMF_C_GET_SSID                       25
-#define BRCMF_C_SET_SSID                       26
-#define BRCMF_C_TERMINATED                     28
-#define BRCMF_C_GET_CHANNEL                    29
-#define BRCMF_C_SET_CHANNEL                    30
-#define BRCMF_C_GET_SRL                                31
-#define BRCMF_C_SET_SRL                                32
-#define BRCMF_C_GET_LRL                                33
-#define BRCMF_C_SET_LRL                                34
-#define BRCMF_C_GET_RADIO                      37
-#define BRCMF_C_SET_RADIO                      38
-#define BRCMF_C_GET_PHYTYPE                    39
-#define BRCMF_C_SET_KEY                                45
-#define BRCMF_C_SET_PASSIVE_SCAN               49
-#define BRCMF_C_SCAN                           50
-#define BRCMF_C_SCAN_RESULTS                   51
-#define BRCMF_C_DISASSOC                       52
-#define BRCMF_C_REASSOC                                53
-#define BRCMF_C_SET_ROAM_TRIGGER               55
-#define BRCMF_C_SET_ROAM_DELTA                 57
-#define BRCMF_C_GET_BCNPRD                     75
-#define BRCMF_C_SET_BCNPRD                     76
-#define BRCMF_C_GET_DTIMPRD                    77
-#define BRCMF_C_SET_DTIMPRD                    78
-#define BRCMF_C_SET_COUNTRY                    84
-#define BRCMF_C_GET_PM                         85
-#define BRCMF_C_SET_PM                         86
-#define BRCMF_C_GET_CURR_RATESET               114
-#define BRCMF_C_GET_AP                         117
-#define BRCMF_C_SET_AP                         118
-#define BRCMF_C_GET_RSSI                       127
-#define BRCMF_C_GET_WSEC                       133
-#define BRCMF_C_SET_WSEC                       134
-#define BRCMF_C_GET_PHY_NOISE                  135
-#define BRCMF_C_GET_BSS_INFO                   136
-#define BRCMF_C_GET_BANDLIST                   140
-#define BRCMF_C_SET_SCB_TIMEOUT                        158
-#define BRCMF_C_GET_PHYLIST                    180
-#define BRCMF_C_SET_SCAN_CHANNEL_TIME          185
-#define BRCMF_C_SET_SCAN_UNASSOC_TIME          187
-#define BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON  201
-#define BRCMF_C_GET_VALID_CHANNELS             217
-#define BRCMF_C_GET_KEY_PRIMARY                        235
-#define BRCMF_C_SET_KEY_PRIMARY                        236
-#define BRCMF_C_SET_SCAN_PASSIVE_TIME          258
-#define BRCMF_C_GET_VAR                                262
-#define BRCMF_C_SET_VAR                                263
-
-/* phy types (returned by WLC_GET_PHYTPE) */
-#define        WLC_PHY_TYPE_A          0
-#define        WLC_PHY_TYPE_B          1
-#define        WLC_PHY_TYPE_G          2
-#define        WLC_PHY_TYPE_N          4
-#define        WLC_PHY_TYPE_LP         5
-#define        WLC_PHY_TYPE_SSN        6
-#define        WLC_PHY_TYPE_HT         7
-#define        WLC_PHY_TYPE_LCN        8
-#define        WLC_PHY_TYPE_NULL       0xf
-
 #define TOE_TX_CSUM_OL         0x00000001
 #define TOE_RX_CSUM_OL         0x00000002
 
-#define        BRCMF_BSS_INFO_VERSION  109 /* curr ver of brcmf_bss_info_le struct */
-
-/* size of brcmf_scan_params not including variable length array */
-#define BRCMF_SCAN_PARAMS_FIXED_SIZE 64
-
-/* masks for channel and ssid count */
-#define BRCMF_SCAN_PARAMS_COUNT_MASK 0x0000ffff
-#define BRCMF_SCAN_PARAMS_NSSID_SHIFT 16
-
-/* primary (ie tx) key */
-#define BRCMF_PRIMARY_KEY      (1 << 1)
-
 /* For supporting multiple interfaces */
 #define BRCMF_MAX_IFS  16
 
-#define DOT11_BSSTYPE_ANY                      2
 #define DOT11_MAX_DEFAULT_KEYS 4
 
-#define BRCMF_ESCAN_REQ_VERSION 1
-
-#define WLC_BSS_RSSI_ON_CHANNEL                0x0002
-
-#define BRCMF_MAXRATES_IN_SET          16      /* max # of rates in rateset */
-#define BRCMF_STA_ASSOC                        0x10            /* Associated */
-
-#define BRCMF_E_STATUS_SUCCESS                 0
-#define BRCMF_E_STATUS_FAIL                    1
-#define BRCMF_E_STATUS_TIMEOUT                 2
-#define BRCMF_E_STATUS_NO_NETWORKS             3
-#define BRCMF_E_STATUS_ABORT                   4
-#define BRCMF_E_STATUS_NO_ACK                  5
-#define BRCMF_E_STATUS_UNSOLICITED             6
-#define BRCMF_E_STATUS_ATTEMPT                 7
-#define BRCMF_E_STATUS_PARTIAL                 8
-#define BRCMF_E_STATUS_NEWSCAN                 9
-#define BRCMF_E_STATUS_NEWASSOC                        10
-#define BRCMF_E_STATUS_11HQUIET                        11
-#define BRCMF_E_STATUS_SUPPRESS                        12
-#define BRCMF_E_STATUS_NOCHANS                 13
-#define BRCMF_E_STATUS_CS_ABORT                        15
-#define BRCMF_E_STATUS_ERROR                   16
-
-#define BRCMF_E_REASON_INITIAL_ASSOC           0
-#define BRCMF_E_REASON_LOW_RSSI                        1
-#define BRCMF_E_REASON_DEAUTH                  2
-#define BRCMF_E_REASON_DISASSOC                        3
-#define BRCMF_E_REASON_BCNS_LOST               4
-#define BRCMF_E_REASON_MINTXRATE               9
-#define BRCMF_E_REASON_TXFAIL                  10
-
-#define BRCMF_E_REASON_LINK_BSSCFG_DIS         4
-#define BRCMF_E_REASON_FAST_ROAM_FAILED                5
-#define BRCMF_E_REASON_DIRECTED_ROAM           6
-#define BRCMF_E_REASON_TSPEC_REJECTED          7
-#define BRCMF_E_REASON_BETTER_AP               8
-
-#define BRCMF_E_PRUNE_ENCR_MISMATCH            1
-#define BRCMF_E_PRUNE_BCAST_BSSID              2
-#define BRCMF_E_PRUNE_MAC_DENY                 3
-#define BRCMF_E_PRUNE_MAC_NA                   4
-#define BRCMF_E_PRUNE_REG_PASSV                        5
-#define BRCMF_E_PRUNE_SPCT_MGMT                        6
-#define BRCMF_E_PRUNE_RADAR                    7
-#define BRCMF_E_RSN_MISMATCH                   8
-#define BRCMF_E_PRUNE_NO_COMMON_RATES          9
-#define BRCMF_E_PRUNE_BASIC_RATES              10
-#define BRCMF_E_PRUNE_CIPHER_NA                        12
-#define BRCMF_E_PRUNE_KNOWN_STA                        13
-#define BRCMF_E_PRUNE_WDS_PEER                 15
-#define BRCMF_E_PRUNE_QBSS_LOAD                        16
-#define BRCMF_E_PRUNE_HOME_AP                  17
-
-#define BRCMF_E_SUP_OTHER                      0
-#define BRCMF_E_SUP_DECRYPT_KEY_DATA           1
-#define BRCMF_E_SUP_BAD_UCAST_WEP128           2
-#define BRCMF_E_SUP_BAD_UCAST_WEP40            3
-#define BRCMF_E_SUP_UNSUP_KEY_LEN              4
-#define BRCMF_E_SUP_PW_KEY_CIPHER              5
-#define BRCMF_E_SUP_MSG3_TOO_MANY_IE           6
-#define BRCMF_E_SUP_MSG3_IE_MISMATCH           7
-#define BRCMF_E_SUP_NO_INSTALL_FLAG            8
-#define BRCMF_E_SUP_MSG3_NO_GTK                        9
-#define BRCMF_E_SUP_GRP_KEY_CIPHER             10
-#define BRCMF_E_SUP_GRP_MSG1_NO_GTK            11
-#define BRCMF_E_SUP_GTK_DECRYPT_FAIL           12
-#define BRCMF_E_SUP_SEND_FAIL                  13
-#define BRCMF_E_SUP_DEAUTH                     14
-
-#define BRCMF_E_IF_ADD                         1
-#define BRCMF_E_IF_DEL                         2
-#define BRCMF_E_IF_CHANGE                      3
-
-#define BRCMF_E_IF_FLAG_NOIF                   1
-
-#define BRCMF_E_IF_ROLE_STA                    0
-#define BRCMF_E_IF_ROLE_AP                     1
-#define BRCMF_E_IF_ROLE_WDS                    2
-
-#define BRCMF_E_LINK_BCN_LOSS                  1
-#define BRCMF_E_LINK_DISASSOC                  2
-#define BRCMF_E_LINK_ASSOC_REC                 3
-#define BRCMF_E_LINK_BSSCFG_DIS                        4
-
 /* Small, medium and maximum buffer size for dcmd
  */
 #define BRCMF_DCMD_SMLEN       256
 
 #define BRCMF_AMPDU_RX_REORDER_MAXFLOWS                256
 
-/* Pattern matching filter. Specifies an offset within received packets to
- * start matching, the pattern to match, the size of the pattern, and a bitmask
- * that indicates which bits within the pattern should be matched.
- */
-struct brcmf_pkt_filter_pattern_le {
-       /*
-        * Offset within received packet to start pattern matching.
-        * Offset '0' is the first byte of the ethernet header.
-        */
-       __le32 offset;
-       /* Size of the pattern.  Bitmask must be the same size.*/
-       __le32 size_bytes;
-       /*
-        * Variable length mask and pattern data. mask starts at offset 0.
-        * Pattern immediately follows mask.
-        */
-       u8 mask_and_pattern[1];
-};
-
-/* IOVAR "pkt_filter_add" parameter. Used to install packet filters. */
-struct brcmf_pkt_filter_le {
-       __le32 id;              /* Unique filter id, specified by app. */
-       __le32 type;            /* Filter type (WL_PKT_FILTER_TYPE_xxx). */
-       __le32 negate_match;    /* Negate the result of filter matches */
-       union {                 /* Filter definitions */
-               struct brcmf_pkt_filter_pattern_le pattern; /* Filter pattern */
-       } u;
-};
-
-/* IOVAR "pkt_filter_enable" parameter. */
-struct brcmf_pkt_filter_enable_le {
-       __le32 id;              /* Unique filter id */
-       __le32 enable;          /* Enable/disable bool */
-};
-
-/* BSS info structure
- * Applications MUST CHECK ie_offset field and length field to access IEs and
- * next bss_info structure in a vector (in struct brcmf_scan_results)
- */
-struct brcmf_bss_info_le {
-       __le32 version;         /* version field */
-       __le32 length;          /* byte length of data in this record,
-                                * starting at version and including IEs
-                                */
-       u8 BSSID[ETH_ALEN];
-       __le16 beacon_period;   /* units are Kusec */
-       __le16 capability;      /* Capability information */
-       u8 SSID_len;
-       u8 SSID[32];
-       struct {
-               __le32 count;   /* # rates in this set */
-               u8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */
-       } rateset;              /* supported rates */
-       __le16 chanspec;        /* chanspec for bss */
-       __le16 atim_window;     /* units are Kusec */
-       u8 dtim_period; /* DTIM period */
-       __le16 RSSI;            /* receive signal strength (in dBm) */
-       s8 phy_noise;           /* noise (in dBm) */
-
-       u8 n_cap;               /* BSS is 802.11N Capable */
-       /* 802.11N BSS Capabilities (based on HT_CAP_*): */
-       __le32 nbss_cap;
-       u8 ctl_ch;              /* 802.11N BSS control channel number */
-       __le32 reserved32[1];   /* Reserved for expansion of BSS properties */
-       u8 flags;               /* flags */
-       u8 reserved[3]; /* Reserved for expansion of BSS properties */
-       u8 basic_mcs[MCSSET_LEN];       /* 802.11N BSS required MCS set */
-
-       __le16 ie_offset;       /* offset at which IEs start, from beginning */
-       __le32 ie_length;       /* byte length of Information Elements */
-       __le16 SNR;             /* average SNR of during frame reception */
-       /* Add new fields here */
-       /* variable length Information Elements */
-};
-
-struct brcm_rateset_le {
-       /* # rates in this set */
-       __le32 count;
-       /* rates in 500kbps units w/hi bit set if basic */
-       u8 rates[BRCMF_MAXRATES_IN_SET];
-};
-
-struct brcmf_ssid {
-       u32 SSID_len;
-       unsigned char SSID[32];
-};
-
-struct brcmf_ssid_le {
-       __le32 SSID_len;
-       unsigned char SSID[32];
-};
-
-struct brcmf_scan_params_le {
-       struct brcmf_ssid_le ssid_le;   /* default: {0, ""} */
-       u8 bssid[ETH_ALEN];     /* default: bcast */
-       s8 bss_type;            /* default: any,
-                                * DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT
-                                */
-       u8 scan_type;   /* flags, 0 use default */
-       __le32 nprobes;   /* -1 use default, number of probes per channel */
-       __le32 active_time;     /* -1 use default, dwell time per channel for
-                                * active scanning
-                                */
-       __le32 passive_time;    /* -1 use default, dwell time per channel
-                                * for passive scanning
-                                */
-       __le32 home_time;       /* -1 use default, dwell time for the
-                                * home channel between channel scans
-                                */
-       __le32 channel_num;     /* count of channels and ssids that follow
-                                *
-                                * low half is count of channels in
-                                * channel_list, 0 means default (use all
-                                * available channels)
-                                *
-                                * high half is entries in struct brcmf_ssid
-                                * array that follows channel_list, aligned for
-                                * s32 (4 bytes) meaning an odd channel count
-                                * implies a 2-byte pad between end of
-                                * channel_list and first ssid
-                                *
-                                * if ssid count is zero, single ssid in the
-                                * fixed parameter portion is assumed, otherwise
-                                * ssid in the fixed portion is ignored
-                                */
-       __le16 channel_list[1]; /* list of chanspecs */
-};
-
-struct brcmf_scan_results {
-       u32 buflen;
-       u32 version;
-       u32 count;
-       struct brcmf_bss_info_le bss_info_le[];
-};
-
-struct brcmf_escan_params_le {
-       __le32 version;
-       __le16 action;
-       __le16 sync_id;
-       struct brcmf_scan_params_le params_le;
-};
-
-struct brcmf_escan_result_le {
-       __le32 buflen;
-       __le32 version;
-       __le16 sync_id;
-       __le16 bss_count;
-       struct brcmf_bss_info_le bss_info_le;
-};
-
-#define WL_ESCAN_RESULTS_FIXED_SIZE (sizeof(struct brcmf_escan_result_le) - \
-       sizeof(struct brcmf_bss_info_le))
-
-/* used for association with a specific BSSID and chanspec list */
-struct brcmf_assoc_params_le {
-       /* 00:00:00:00:00:00: broadcast scan */
-       u8 bssid[ETH_ALEN];
-       /* 0: all available channels, otherwise count of chanspecs in
-        * chanspec_list */
-       __le32 chanspec_num;
-       /* list of chanspecs */
-       __le16 chanspec_list[1];
-};
-
-/* used for join with or without a specific bssid and channel list */
-struct brcmf_join_params {
-       struct brcmf_ssid_le ssid_le;
-       struct brcmf_assoc_params_le params_le;
-};
-
-/* scan params for extended join */
-struct brcmf_join_scan_params_le {
-       u8 scan_type;           /* 0 use default, active or passive scan */
-       __le32 nprobes;         /* -1 use default, nr of probes per channel */
-       __le32 active_time;     /* -1 use default, dwell time per channel for
-                                * active scanning
-                                */
-       __le32 passive_time;    /* -1 use default, dwell time per channel
-                                * for passive scanning
-                                */
-       __le32 home_time;       /* -1 use default, dwell time for the home
-                                * channel between channel scans
-                                */
-};
-
-/* extended join params */
-struct brcmf_ext_join_params_le {
-       struct brcmf_ssid_le ssid_le;   /* {0, ""}: wildcard scan */
-       struct brcmf_join_scan_params_le scan_le;
-       struct brcmf_assoc_params_le assoc_le;
-};
-
-struct brcmf_wsec_key {
-       u32 index;              /* key index */
-       u32 len;                /* key length */
-       u8 data[WLAN_MAX_KEY_LEN];      /* key data */
-       u32 pad_1[18];
-       u32 algo;       /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */
-       u32 flags;      /* misc flags */
-       u32 pad_2[3];
-       u32 iv_initialized;     /* has IV been initialized already? */
-       u32 pad_3;
-       /* Rx IV */
-       struct {
-               u32 hi; /* upper 32 bits of IV */
-               u16 lo; /* lower 16 bits of IV */
-       } rxiv;
-       u32 pad_4[2];
-       u8 ea[ETH_ALEN];        /* per station */
-};
-
-/*
- * dongle requires same struct as above but with fields in little endian order
+/* Length of firmware version string stored for
+ * ethtool driver info which uses 32 bytes as well.
  */
-struct brcmf_wsec_key_le {
-       __le32 index;           /* key index */
-       __le32 len;             /* key length */
-       u8 data[WLAN_MAX_KEY_LEN];      /* key data */
-       __le32 pad_1[18];
-       __le32 algo;    /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */
-       __le32 flags;   /* misc flags */
-       __le32 pad_2[3];
-       __le32 iv_initialized;  /* has IV been initialized already? */
-       __le32 pad_3;
-       /* Rx IV */
-       struct {
-               __le32 hi;      /* upper 32 bits of IV */
-               __le16 lo;      /* lower 16 bits of IV */
-       } rxiv;
-       __le32 pad_4[2];
-       u8 ea[ETH_ALEN];        /* per station */
-};
-
-/* Used to get specific STA parameters */
-struct brcmf_scb_val_le {
-       __le32 val;
-       u8 ea[ETH_ALEN];
-};
-
-/* channel encoding */
-struct brcmf_channel_info_le {
-       __le32 hw_channel;
-       __le32 target_channel;
-       __le32 scan_channel;
-};
-
-struct brcmf_sta_info_le {
-       __le16  ver;            /* version of this struct */
-       __le16  len;            /* length in bytes of this structure */
-       __le16  cap;            /* sta's advertised capabilities */
-       __le32  flags;          /* flags defined below */
-       __le32  idle;           /* time since data pkt rx'd from sta */
-       u8      ea[ETH_ALEN];           /* Station address */
-       __le32  count;                  /* # rates in this set */
-       u8      rates[BRCMF_MAXRATES_IN_SET];   /* rates in 500kbps units */
-                                               /* w/hi bit set if basic */
-       __le32  in;             /* seconds elapsed since associated */
-       __le32  listen_interval_inms; /* Min Listen interval in ms for STA */
-       __le32  tx_pkts;        /* # of packets transmitted */
-       __le32  tx_failures;    /* # of packets failed */
-       __le32  rx_ucast_pkts;  /* # of unicast packets received */
-       __le32  rx_mcast_pkts;  /* # of multicast packets received */
-       __le32  tx_rate;        /* Rate of last successful tx frame */
-       __le32  rx_rate;        /* Rate of last successful rx frame */
-       __le32  rx_decrypt_succeeds;    /* # of packet decrypted successfully */
-       __le32  rx_decrypt_failures;    /* # of packet decrypted failed */
-};
-
-struct brcmf_chanspec_list {
-       __le32  count;          /* # of entries */
-       __le32  element[1];     /* variable length uint32 list */
-};
-
-/*
- * WLC_E_PROBRESP_MSG
- * WLC_E_P2P_PROBREQ_MSG
- * WLC_E_ACTION_FRAME_RX
- */
-struct brcmf_rx_mgmt_data {
-       __be16  version;
-       __be16  chanspec;
-       __be32  rssi;
-       __be32  mactime;
-       __be32  rate;
-};
+#define BRCMF_DRIVER_FIRMWARE_VERSION_LEN      32
 
 /* Bus independent dongle command */
 struct brcmf_dcmd {
@@ -535,7 +84,7 @@ struct brcmf_fws_info; /* firmware signalling info */
 struct brcmf_pub {
        /* Linkage ponters */
        struct brcmf_bus *bus_if;
-       struct brcmf_proto *prot;
+       struct brcmf_proto *proto;
        struct brcmf_cfg80211_info *config;
 
        /* Internal brcmf items */
@@ -544,7 +93,7 @@ struct brcmf_pub {
        u8 wme_dp;              /* wme discard priority */
 
        /* Dongle media info */
-       unsigned long drv_version;      /* Version of dongle-resident driver */
+       char fwver[BRCMF_DRIVER_FIRMWARE_VERSION_LEN];
        u8 mac[ETH_ALEN];               /* MAC address obtained from dongle */
 
        /* Multicast data packets sent to dongle */
@@ -566,14 +115,6 @@ struct brcmf_pub {
 #endif
 };
 
-struct brcmf_if_event {
-       u8 ifidx;
-       u8 action;
-       u8 flags;
-       u8 bssidx;
-       u8 role;
-};
-
 /* forward declarations */
 struct brcmf_cfg80211_vif;
 struct brcmf_fws_mac_descriptor;
@@ -635,16 +176,6 @@ int brcmf_netdev_wait_pend8021x(struct net_device *ndev);
 /* Return pointer to interface name */
 char *brcmf_ifname(struct brcmf_pub *drvr, int idx);
 
-/* Query dongle */
-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. */
-int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx,
-                       struct sk_buff *rxp);
-
 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);
@@ -655,4 +186,7 @@ u32 brcmf_get_chip_info(struct brcmf_if *ifp);
 void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp,
                      bool success);
 
+/* Sets dongle media info (drv_version, mac address). */
+int brcmf_c_preinit_dcmds(struct brcmf_if *ifp);
+
 #endif                         /* _BRCMF_H_ */
index a6eb09e5d46f408acf9205937ebffd772b15846d..6a54905528befd0238ce198acdbd6f9d642d1340 100644 (file)
@@ -34,6 +34,7 @@ struct brcmf_bus_dcmd {
 /**
  * struct brcmf_bus_ops - bus callback operations.
  *
+ * @preinit: execute bus/device specific dongle init commands (optional).
  * @init: prepare for communication with dongle.
  * @stop: clear pending frames, disable data flow.
  * @txdata: send a data frame to the dongle. When the data
@@ -51,6 +52,7 @@ struct brcmf_bus_dcmd {
  * indicated otherwise these callbacks are mandatory.
  */
 struct brcmf_bus_ops {
+       int (*preinit)(struct device *dev);
        int (*init)(struct device *dev);
        void (*stop)(struct device *dev);
        int (*txdata)(struct device *dev, struct sk_buff *skb);
@@ -85,7 +87,6 @@ struct brcmf_bus {
        unsigned long tx_realloc;
        u32 chip;
        u32 chiprev;
-       struct list_head dcmd_list;
 
        struct brcmf_bus_ops *ops;
 };
@@ -93,6 +94,13 @@ struct brcmf_bus {
 /*
  * callback wrappers
  */
+static inline int brcmf_bus_preinit(struct brcmf_bus *bus)
+{
+       if (!bus->ops->preinit)
+               return 0;
+       return bus->ops->preinit(bus->dev);
+}
+
 static inline int brcmf_bus_init(struct brcmf_bus *bus)
 {
        return bus->ops->init(bus->dev);
@@ -139,7 +147,7 @@ bool brcmf_c_prec_enq(struct device *dev, struct pktq *q, struct sk_buff *pkt,
 void brcmf_rx_frame(struct device *dev, struct sk_buff *rxp);
 
 /* Indication from bus module regarding presence/insertion of dongle. */
-int brcmf_attach(uint bus_hdrlen, struct device *dev);
+int brcmf_attach(struct device *dev);
 /* Indication from bus module regarding removal/absence of dongle */
 void brcmf_detach(struct device *dev);
 /* Indication from bus module that dongle should be reset */
@@ -151,6 +159,9 @@ void brcmf_txflowblock(struct device *dev, bool state);
 void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success);
 
 int brcmf_bus_start(struct device *dev);
+s32 brcmf_iovar_data_set(struct device *dev, char *name, void *data,
+                               u32 len);
+void brcmf_bus_add_txhdrlen(struct device *dev, uint len);
 
 #ifdef CONFIG_BRCMFMAC_SDIO
 void brcmf_sdio_exit(void);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c
deleted file mode 100644 (file)
index dd85401..0000000
+++ /dev/null
@@ -1,392 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-/*******************************************************************************
- * Communicates with the dongle by using dcmd codes.
- * For certain dcmd codes, the dongle interprets string data from the host.
- ******************************************************************************/
-
-#include <linux/types.h>
-#include <linux/netdevice.h>
-
-#include <brcmu_utils.h>
-#include <brcmu_wifi.h>
-
-#include "dhd.h"
-#include "dhd_proto.h"
-#include "dhd_bus.h"
-#include "fwsignal.h"
-#include "dhd_dbg.h"
-#include "tracepoint.h"
-
-struct brcmf_proto_cdc_dcmd {
-       __le32 cmd;     /* dongle command value */
-       __le32 len;     /* lower 16: output buflen;
-                        * upper 16: input buflen (excludes header) */
-       __le32 flags;   /* flag defns given below */
-       __le32 status;  /* status code returned from the device */
-};
-
-/* Max valid buffer size that can be sent to the dongle */
-#define CDC_MAX_MSG_SIZE       (ETH_FRAME_LEN+ETH_FCS_LEN)
-
-/* CDC flag definitions */
-#define CDC_DCMD_ERROR         0x01    /* 1=cmd failed */
-#define CDC_DCMD_SET           0x02    /* 0=get, 1=set cmd */
-#define CDC_DCMD_IF_MASK       0xF000          /* I/F index */
-#define CDC_DCMD_IF_SHIFT      12
-#define CDC_DCMD_ID_MASK       0xFFFF0000      /* id an cmd pairing */
-#define CDC_DCMD_ID_SHIFT      16              /* ID Mask shift bits */
-#define CDC_DCMD_ID(flags)     \
-       (((flags) & CDC_DCMD_ID_MASK) >> CDC_DCMD_ID_SHIFT)
-
-/*
- * BDC header - Broadcom specific extension of CDC.
- * Used on data packets to convey priority across USB.
- */
-#define        BDC_HEADER_LEN          4
-#define BDC_PROTO_VER          2       /* Protocol version */
-#define BDC_FLAG_VER_MASK      0xf0    /* Protocol version mask */
-#define BDC_FLAG_VER_SHIFT     4       /* Protocol version shift */
-#define BDC_FLAG_SUM_GOOD      0x04    /* Good RX checksums */
-#define BDC_FLAG_SUM_NEEDED    0x08    /* Dongle needs to do TX checksums */
-#define BDC_PRIORITY_MASK      0x7
-#define BDC_FLAG2_IF_MASK      0x0f    /* packet rx interface in APSTA */
-#define BDC_FLAG2_IF_SHIFT     0
-
-#define BDC_GET_IF_IDX(hdr) \
-       ((int)((((hdr)->flags2) & BDC_FLAG2_IF_MASK) >> BDC_FLAG2_IF_SHIFT))
-#define BDC_SET_IF_IDX(hdr, idx) \
-       ((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | \
-       ((idx) << BDC_FLAG2_IF_SHIFT)))
-
-/**
- * struct brcmf_proto_bdc_header - BDC header format
- *
- * @flags: flags contain protocol and checksum info.
- * @priority: 802.1d priority and USB flow control info (bit 4:7).
- * @flags2: additional flags containing dongle interface index.
- * @data_offset: start of packet data. header is following by firmware signals.
- */
-struct brcmf_proto_bdc_header {
-       u8 flags;
-       u8 priority;
-       u8 flags2;
-       u8 data_offset;
-};
-
-/*
- * maximum length of firmware signal data between
- * the BDC header and packet data in the tx path.
- */
-#define BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES       12
-
-#define RETRIES 2 /* # of retries to retrieve matching dcmd response */
-#define BUS_HEADER_LEN (16+64)         /* Must be atleast SDPCM_RESERVE
-                                        * (amount of header tha might be added)
-                                        * plus any space that might be needed
-                                        * for bus alignment padding.
-                                        */
-#define ROUND_UP_MARGIN        2048    /* Biggest bus block size possible for
-                                * round off at the end of buffer
-                                * Currently is SDIO
-                                */
-
-struct brcmf_proto {
-       u16 reqid;
-       u8 bus_header[BUS_HEADER_LEN];
-       struct brcmf_proto_cdc_dcmd msg;
-       unsigned char buf[BRCMF_DCMD_MAXLEN + ROUND_UP_MARGIN];
-};
-
-static int brcmf_proto_cdc_msg(struct brcmf_pub *drvr)
-{
-       struct brcmf_proto *prot = drvr->prot;
-       int len = le32_to_cpu(prot->msg.len) +
-                       sizeof(struct brcmf_proto_cdc_dcmd);
-
-       brcmf_dbg(CDC, "Enter\n");
-
-       /* NOTE : cdc->msg.len holds the desired length of the buffer to be
-        *        returned. Only up to CDC_MAX_MSG_SIZE of this buffer area
-        *        is actually sent to the dongle
-        */
-       if (len > CDC_MAX_MSG_SIZE)
-               len = CDC_MAX_MSG_SIZE;
-
-       /* Send request */
-       return brcmf_bus_txctl(drvr->bus_if, (unsigned char *)&prot->msg, len);
-}
-
-static int brcmf_proto_cdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len)
-{
-       int ret;
-       struct brcmf_proto *prot = drvr->prot;
-
-       brcmf_dbg(CDC, "Enter\n");
-       len += sizeof(struct brcmf_proto_cdc_dcmd);
-       do {
-               ret = brcmf_bus_rxctl(drvr->bus_if, (unsigned char *)&prot->msg,
-                                     len);
-               if (ret < 0)
-                       break;
-       } while (CDC_DCMD_ID(le32_to_cpu(prot->msg.flags)) != id);
-
-       return ret;
-}
-
-int
-brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
-                              void *buf, uint len)
-{
-       struct brcmf_proto *prot = drvr->prot;
-       struct brcmf_proto_cdc_dcmd *msg = &prot->msg;
-       void *info;
-       int ret = 0, retries = 0;
-       u32 id, flags;
-
-       brcmf_dbg(CDC, "Enter, cmd %d len %d\n", cmd, len);
-
-       memset(msg, 0, sizeof(struct brcmf_proto_cdc_dcmd));
-
-       msg->cmd = cpu_to_le32(cmd);
-       msg->len = cpu_to_le32(len);
-       flags = (++prot->reqid << CDC_DCMD_ID_SHIFT);
-       flags = (flags & ~CDC_DCMD_IF_MASK) |
-               (ifidx << CDC_DCMD_IF_SHIFT);
-       msg->flags = cpu_to_le32(flags);
-
-       if (buf)
-               memcpy(prot->buf, buf, len);
-
-       ret = brcmf_proto_cdc_msg(drvr);
-       if (ret < 0) {
-               brcmf_err("brcmf_proto_cdc_msg failed w/status %d\n",
-                         ret);
-               goto done;
-       }
-
-retry:
-       /* wait for interrupt and get first fragment */
-       ret = brcmf_proto_cdc_cmplt(drvr, prot->reqid, len);
-       if (ret < 0)
-               goto done;
-
-       flags = le32_to_cpu(msg->flags);
-       id = (flags & CDC_DCMD_ID_MASK) >> CDC_DCMD_ID_SHIFT;
-
-       if ((id < prot->reqid) && (++retries < RETRIES))
-               goto retry;
-       if (id != prot->reqid) {
-               brcmf_err("%s: unexpected request id %d (expected %d)\n",
-                         brcmf_ifname(drvr, ifidx), id, prot->reqid);
-               ret = -EINVAL;
-               goto done;
-       }
-
-       /* Check info buffer */
-       info = (void *)&msg[1];
-
-       /* Copy info buffer */
-       if (buf) {
-               if (ret < (int)len)
-                       len = ret;
-               memcpy(buf, info, len);
-       }
-
-       /* Check the ERROR flag */
-       if (flags & CDC_DCMD_ERROR)
-               ret = le32_to_cpu(msg->status);
-
-done:
-       return ret;
-}
-
-int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
-                                void *buf, uint len)
-{
-       struct brcmf_proto *prot = drvr->prot;
-       struct brcmf_proto_cdc_dcmd *msg = &prot->msg;
-       int ret = 0;
-       u32 flags, id;
-
-       brcmf_dbg(CDC, "Enter, cmd %d len %d\n", cmd, len);
-
-       memset(msg, 0, sizeof(struct brcmf_proto_cdc_dcmd));
-
-       msg->cmd = cpu_to_le32(cmd);
-       msg->len = cpu_to_le32(len);
-       flags = (++prot->reqid << CDC_DCMD_ID_SHIFT) | CDC_DCMD_SET;
-       flags = (flags & ~CDC_DCMD_IF_MASK) |
-               (ifidx << CDC_DCMD_IF_SHIFT);
-       msg->flags = cpu_to_le32(flags);
-
-       if (buf)
-               memcpy(prot->buf, buf, len);
-
-       ret = brcmf_proto_cdc_msg(drvr);
-       if (ret < 0)
-               goto done;
-
-       ret = brcmf_proto_cdc_cmplt(drvr, prot->reqid, len);
-       if (ret < 0)
-               goto done;
-
-       flags = le32_to_cpu(msg->flags);
-       id = (flags & CDC_DCMD_ID_MASK) >> CDC_DCMD_ID_SHIFT;
-
-       if (id != prot->reqid) {
-               brcmf_err("%s: unexpected request id %d (expected %d)\n",
-                         brcmf_ifname(drvr, ifidx), id, prot->reqid);
-               ret = -EINVAL;
-               goto done;
-       }
-
-       /* Check the ERROR flag */
-       if (flags & CDC_DCMD_ERROR)
-               ret = le32_to_cpu(msg->status);
-
-done:
-       return ret;
-}
-
-static bool pkt_sum_needed(struct sk_buff *skb)
-{
-       return skb->ip_summed == CHECKSUM_PARTIAL;
-}
-
-static void pkt_set_sum_good(struct sk_buff *skb, bool x)
-{
-       skb->ip_summed = (x ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE);
-}
-
-void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx, u8 offset,
-                        struct sk_buff *pktbuf)
-{
-       struct brcmf_proto_bdc_header *h;
-
-       brcmf_dbg(CDC, "Enter\n");
-
-       /* Push BDC header used to convey priority for buses that don't */
-       skb_push(pktbuf, BDC_HEADER_LEN);
-
-       h = (struct brcmf_proto_bdc_header *)(pktbuf->data);
-
-       h->flags = (BDC_PROTO_VER << BDC_FLAG_VER_SHIFT);
-       if (pkt_sum_needed(pktbuf))
-               h->flags |= BDC_FLAG_SUM_NEEDED;
-
-       h->priority = (pktbuf->priority & BDC_PRIORITY_MASK);
-       h->flags2 = 0;
-       h->data_offset = offset;
-       BDC_SET_IF_IDX(h, ifidx);
-       trace_brcmf_bdchdr(pktbuf->data);
-}
-
-int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx,
-                       struct sk_buff *pktbuf)
-{
-       struct brcmf_proto_bdc_header *h;
-
-       brcmf_dbg(CDC, "Enter\n");
-
-       /* Pop BDC header used to convey priority for buses that don't */
-
-       if (pktbuf->len <= BDC_HEADER_LEN) {
-               brcmf_dbg(INFO, "rx data too short (%d <= %d)\n",
-                         pktbuf->len, BDC_HEADER_LEN);
-               return -EBADE;
-       }
-
-       trace_brcmf_bdchdr(pktbuf->data);
-       h = (struct brcmf_proto_bdc_header *)(pktbuf->data);
-
-       *ifidx = BDC_GET_IF_IDX(h);
-       if (*ifidx >= BRCMF_MAX_IFS) {
-               brcmf_err("rx data ifnum out of range (%d)\n", *ifidx);
-               return -EBADE;
-       }
-       /* The ifidx is the idx to map to matching netdev/ifp. When receiving
-        * events this is easy because it contains the bssidx which maps
-        * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd.
-        * bssidx 1 is used for p2p0 and no data can be received or
-        * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0
-        */
-       if (*ifidx)
-               (*ifidx)++;
-
-       if (((h->flags & BDC_FLAG_VER_MASK) >> BDC_FLAG_VER_SHIFT) !=
-           BDC_PROTO_VER) {
-               brcmf_err("%s: non-BDC packet received, flags 0x%x\n",
-                         brcmf_ifname(drvr, *ifidx), h->flags);
-               return -EBADE;
-       }
-
-       if (h->flags & BDC_FLAG_SUM_GOOD) {
-               brcmf_dbg(CDC, "%s: BDC rcv, good checksum, flags 0x%x\n",
-                         brcmf_ifname(drvr, *ifidx), h->flags);
-               pkt_set_sum_good(pktbuf, true);
-       }
-
-       pktbuf->priority = h->priority & BDC_PRIORITY_MASK;
-
-       skb_pull(pktbuf, BDC_HEADER_LEN);
-       if (do_fws)
-               brcmf_fws_hdrpull(drvr, *ifidx, h->data_offset << 2, pktbuf);
-       else
-               skb_pull(pktbuf, h->data_offset << 2);
-
-       if (pktbuf->len == 0)
-               return -ENODATA;
-       return 0;
-}
-
-int brcmf_proto_attach(struct brcmf_pub *drvr)
-{
-       struct brcmf_proto *cdc;
-
-       cdc = kzalloc(sizeof(struct brcmf_proto), GFP_ATOMIC);
-       if (!cdc)
-               goto fail;
-
-       /* ensure that the msg buf directly follows the cdc msg struct */
-       if ((unsigned long)(&cdc->msg + 1) != (unsigned long)cdc->buf) {
-               brcmf_err("struct brcmf_proto is not correctly defined\n");
-               goto fail;
-       }
-
-       drvr->prot = cdc;
-       drvr->hdrlen += BDC_HEADER_LEN + BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES;
-       drvr->bus_if->maxctl = BRCMF_DCMD_MAXLEN +
-                       sizeof(struct brcmf_proto_cdc_dcmd) + ROUND_UP_MARGIN;
-       return 0;
-
-fail:
-       kfree(cdc);
-       return -ENOMEM;
-}
-
-/* ~NOTE~ What if another thread is waiting on the semaphore?  Holding it? */
-void brcmf_proto_detach(struct brcmf_pub *drvr)
-{
-       kfree(drvr->prot);
-       drvr->prot = NULL;
-}
-
-void brcmf_proto_stop(struct brcmf_pub *drvr)
-{
-       /* Nothing to do for CDC */
-}
index 9431af2465f3135fc76d5df370853a3b85a77d67..548dbb5542c63eb2631aafa8b2344013bfd90752 100644 (file)
@@ -21,9 +21,9 @@
 #include <brcmu_utils.h>
 #include "dhd.h"
 #include "dhd_bus.h"
-#include "dhd_proto.h"
 #include "dhd_dbg.h"
 #include "fwil.h"
+#include "fwil_types.h"
 #include "tracepoint.h"
 
 #define PKTFILTER_BUF_SIZE             128
@@ -257,8 +257,6 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
        u8 buf[BRCMF_DCMD_SMLEN];
        char *ptr;
        s32 err;
-       struct brcmf_bus_dcmd *cmdlst;
-       struct list_head *cur, *q;
 
        /* retreive mac address */
        err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr,
@@ -281,9 +279,14 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
        }
        ptr = (char *)buf;
        strsep(&ptr, "\n");
+
        /* Print fw version info */
        brcmf_err("Firmware version = %s\n", buf);
 
+       /* locate firmware version number for ethtool */
+       ptr = strrchr(buf, ' ') + 1;
+       strlcpy(ifp->drvr->fwver, ptr, sizeof(ifp->drvr->fwver));
+
        /*
         * Setup timeout if Beacons are lost and roam is off to report
         * link down
@@ -342,17 +345,8 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
        brcmf_c_pktfilter_offload_enable(ifp, BRCMF_DEFAULT_PACKET_FILTER,
                                         0, true);
 
-       /* set bus specific command if there is any */
-       list_for_each_safe(cur, q, &ifp->drvr->bus_if->dcmd_list) {
-               cmdlst = list_entry(cur, struct brcmf_bus_dcmd, list);
-               if (cmdlst->name && cmdlst->param && cmdlst->param_len) {
-                       brcmf_fil_iovar_data_set(ifp, cmdlst->name,
-                                                cmdlst->param,
-                                                cmdlst->param_len);
-               }
-               list_del(cur);
-               kfree(cmdlst);
-       }
+       /* do bus specific preinit here */
+       err = brcmf_bus_preinit(ifp->drvr->bus_if);
 done:
        return err;
 }
index 0f9e9057e7dd2dea3868383990bf67b16cc23a65..03fe8aca4d3261c81f704f89853364f0f0bb7507 100644 (file)
@@ -22,7 +22,6 @@
 #include "dhd.h"
 #include "dhd_bus.h"
 #include "dhd_dbg.h"
-#include "tracepoint.h"
 
 static struct dentry *root_folder;
 
@@ -42,6 +41,40 @@ void brcmf_debugfs_exit(void)
        root_folder = NULL;
 }
 
+static
+ssize_t brcmf_debugfs_chipinfo_read(struct file *f, char __user *data,
+                                  size_t count, loff_t *ppos)
+{
+       struct brcmf_pub *drvr = f->private_data;
+       struct brcmf_bus *bus = drvr->bus_if;
+       char buf[40];
+       int res;
+
+       /* only allow read from start */
+       if (*ppos > 0)
+               return 0;
+
+       res = scnprintf(buf, sizeof(buf), "chip: %x(%u) rev %u\n",
+                       bus->chip, bus->chip, bus->chiprev);
+       return simple_read_from_buffer(data, count, ppos, buf, res);
+}
+
+static const struct file_operations brcmf_debugfs_chipinfo_ops = {
+       .owner = THIS_MODULE,
+       .open = simple_open,
+       .read = brcmf_debugfs_chipinfo_read
+};
+
+static int brcmf_debugfs_create_chipinfo(struct brcmf_pub *drvr)
+{
+       struct dentry *dentry =  drvr->dbgfs_dir;
+
+       if (!IS_ERR_OR_NULL(dentry))
+               debugfs_create_file("chipinfo", S_IRUGO, dentry, drvr,
+                                   &brcmf_debugfs_chipinfo_ops);
+       return 0;
+}
+
 int brcmf_debugfs_attach(struct brcmf_pub *drvr)
 {
        struct device *dev = drvr->bus_if->dev;
@@ -50,6 +83,7 @@ int brcmf_debugfs_attach(struct brcmf_pub *drvr)
                return -ENODEV;
 
        drvr->dbgfs_dir = debugfs_create_dir(dev_name(dev), root_folder);
+       brcmf_debugfs_create_chipinfo(drvr);
        return PTR_ERR_OR_ZERO(drvr->dbgfs_dir);
 }
 
index 0af1f5dc583a8fd7dd9a550b6e3e5f585ab64925..ef52ed7abc69349640081292f5f862277900607c 100644 (file)
@@ -33,7 +33,7 @@
 #define BRCMF_USB_VAL  0x00002000
 #define BRCMF_SCAN_VAL 0x00004000
 #define BRCMF_CONN_VAL 0x00008000
-#define BRCMF_CDC_VAL  0x00010000
+#define BRCMF_BCDC_VAL 0x00010000
 #define BRCMF_SDIO_VAL 0x00020000
 
 /* set default print format */
index 64e9cff241b9156745bab110010520bfba730394..bce0b8e511fd22eb085077169050426f42714838 100644 (file)
 
 #include "dhd.h"
 #include "dhd_bus.h"
-#include "dhd_proto.h"
 #include "dhd_dbg.h"
 #include "fwil_types.h"
 #include "p2p.h"
 #include "wl_cfg80211.h"
 #include "fwil.h"
 #include "fwsignal.h"
+#include "proto.h"
 
 MODULE_AUTHOR("Broadcom Corporation");
 MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver.");
@@ -592,28 +592,6 @@ static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev)
        return &ifp->stats;
 }
 
-/*
- * Set current toe component enables in toe_ol iovar,
- * and set toe global enable iovar
- */
-static int brcmf_toe_set(struct brcmf_if *ifp, u32 toe_ol)
-{
-       s32 err;
-
-       err = brcmf_fil_iovar_int_set(ifp, "toe_ol", toe_ol);
-       if (err < 0) {
-               brcmf_err("Setting toe_ol failed, %d\n", err);
-               return err;
-       }
-
-       err = brcmf_fil_iovar_int_set(ifp, "toe", (toe_ol != 0));
-       if (err < 0)
-               brcmf_err("Setting toe failed, %d\n", err);
-
-       return err;
-
-}
-
 static void brcmf_ethtool_get_drvinfo(struct net_device *ndev,
                                    struct ethtool_drvinfo *info)
 {
@@ -621,8 +599,8 @@ static void brcmf_ethtool_get_drvinfo(struct net_device *ndev,
        struct brcmf_pub *drvr = ifp->drvr;
 
        strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
-       snprintf(info->version, sizeof(info->version), "%lu",
-                drvr->drv_version);
+       snprintf(info->version, sizeof(info->version), "n/a");
+       strlcpy(info->fw_version, drvr->fwver, sizeof(info->fw_version));
        strlcpy(info->bus_info, dev_name(drvr->bus_if->dev),
                sizeof(info->bus_info));
 }
@@ -631,124 +609,6 @@ static const struct ethtool_ops brcmf_ethtool_ops = {
        .get_drvinfo = brcmf_ethtool_get_drvinfo,
 };
 
-static int brcmf_ethtool(struct brcmf_if *ifp, void __user *uaddr)
-{
-       struct brcmf_pub *drvr = ifp->drvr;
-       struct ethtool_drvinfo info;
-       char drvname[sizeof(info.driver)];
-       u32 cmd;
-       struct ethtool_value edata;
-       u32 toe_cmpnt, csum_dir;
-       int ret;
-
-       brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
-
-       /* all ethtool calls start with a cmd word */
-       if (copy_from_user(&cmd, uaddr, sizeof(u32)))
-               return -EFAULT;
-
-       switch (cmd) {
-       case ETHTOOL_GDRVINFO:
-               /* Copy out any request driver name */
-               if (copy_from_user(&info, uaddr, sizeof(info)))
-                       return -EFAULT;
-               strncpy(drvname, info.driver, sizeof(info.driver));
-               drvname[sizeof(info.driver) - 1] = '\0';
-
-               /* clear struct for return */
-               memset(&info, 0, sizeof(info));
-               info.cmd = cmd;
-
-               /* if requested, identify ourselves */
-               if (strcmp(drvname, "?dhd") == 0) {
-                       sprintf(info.driver, "dhd");
-                       strcpy(info.version, BRCMF_VERSION_STR);
-               }
-               /* report dongle driver type */
-               else
-                       sprintf(info.driver, "wl");
-
-               sprintf(info.version, "%lu", drvr->drv_version);
-               if (copy_to_user(uaddr, &info, sizeof(info)))
-                       return -EFAULT;
-               brcmf_dbg(TRACE, "given %*s, returning %s\n",
-                         (int)sizeof(drvname), drvname, info.driver);
-               break;
-
-               /* Get toe offload components from dongle */
-       case ETHTOOL_GRXCSUM:
-       case ETHTOOL_GTXCSUM:
-               ret = brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_cmpnt);
-               if (ret < 0)
-                       return ret;
-
-               csum_dir =
-                   (cmd == ETHTOOL_GTXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL;
-
-               edata.cmd = cmd;
-               edata.data = (toe_cmpnt & csum_dir) ? 1 : 0;
-
-               if (copy_to_user(uaddr, &edata, sizeof(edata)))
-                       return -EFAULT;
-               break;
-
-               /* Set toe offload components in dongle */
-       case ETHTOOL_SRXCSUM:
-       case ETHTOOL_STXCSUM:
-               if (copy_from_user(&edata, uaddr, sizeof(edata)))
-                       return -EFAULT;
-
-               /* Read the current settings, update and write back */
-               ret = brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_cmpnt);
-               if (ret < 0)
-                       return ret;
-
-               csum_dir =
-                   (cmd == ETHTOOL_STXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL;
-
-               if (edata.data != 0)
-                       toe_cmpnt |= csum_dir;
-               else
-                       toe_cmpnt &= ~csum_dir;
-
-               ret = brcmf_toe_set(ifp, toe_cmpnt);
-               if (ret < 0)
-                       return ret;
-
-               /* If setting TX checksum mode, tell Linux the new mode */
-               if (cmd == ETHTOOL_STXCSUM) {
-                       if (edata.data)
-                               ifp->ndev->features |= NETIF_F_IP_CSUM;
-                       else
-                               ifp->ndev->features &= ~NETIF_F_IP_CSUM;
-               }
-
-               break;
-
-       default:
-               return -EOPNOTSUPP;
-       }
-
-       return 0;
-}
-
-static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr,
-                                   int cmd)
-{
-       struct brcmf_if *ifp = netdev_priv(ndev);
-       struct brcmf_pub *drvr = ifp->drvr;
-
-       brcmf_dbg(TRACE, "Enter, idx=%d, cmd=0x%04x\n", ifp->bssidx, cmd);
-
-       if (!drvr->iflist[ifp->bssidx])
-               return -1;
-
-       if (cmd == SIOCETHTOOL)
-               return brcmf_ethtool(ifp, ifr->ifr_data);
-
-       return -EOPNOTSUPP;
-}
-
 static int brcmf_netdev_stop(struct net_device *ndev)
 {
        struct brcmf_if *ifp = netdev_priv(ndev);
@@ -769,7 +629,6 @@ static int brcmf_netdev_open(struct net_device *ndev)
        struct brcmf_pub *drvr = ifp->drvr;
        struct brcmf_bus *bus_if = drvr->bus_if;
        u32 toe_ol;
-       s32 ret = 0;
 
        brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
 
@@ -788,21 +647,20 @@ static int brcmf_netdev_open(struct net_device *ndev)
        else
                ndev->features &= ~NETIF_F_IP_CSUM;
 
-       /* Allow transmit calls */
-       netif_start_queue(ndev);
        if (brcmf_cfg80211_up(ndev)) {
                brcmf_err("failed to bring up cfg80211\n");
-               return -1;
+               return -EIO;
        }
 
-       return ret;
+       /* Allow transmit calls */
+       netif_start_queue(ndev);
+       return 0;
 }
 
 static const struct net_device_ops brcmf_netdev_ops_pri = {
        .ndo_open = brcmf_netdev_open,
        .ndo_stop = brcmf_netdev_stop,
        .ndo_get_stats = brcmf_netdev_get_stats,
-       .ndo_do_ioctl = brcmf_netdev_ioctl_entry,
        .ndo_start_xmit = brcmf_netdev_start_xmit,
        .ndo_set_mac_address = brcmf_netdev_set_mac_address,
        .ndo_set_rx_mode = brcmf_netdev_set_multicast_list
@@ -868,13 +726,6 @@ static int brcmf_net_p2p_stop(struct net_device *ndev)
        return brcmf_cfg80211_down(ndev);
 }
 
-static int brcmf_net_p2p_do_ioctl(struct net_device *ndev,
-                                 struct ifreq *ifr, int cmd)
-{
-       brcmf_dbg(TRACE, "Enter\n");
-       return 0;
-}
-
 static netdev_tx_t brcmf_net_p2p_start_xmit(struct sk_buff *skb,
                                            struct net_device *ndev)
 {
@@ -887,7 +738,6 @@ static netdev_tx_t brcmf_net_p2p_start_xmit(struct sk_buff *skb,
 static const struct net_device_ops brcmf_netdev_ops_p2p = {
        .ndo_open = brcmf_net_p2p_open,
        .ndo_stop = brcmf_net_p2p_stop,
-       .ndo_do_ioctl = brcmf_net_p2p_do_ioctl,
        .ndo_start_xmit = brcmf_net_p2p_start_xmit
 };
 
@@ -1016,7 +866,7 @@ void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
        }
 }
 
-int brcmf_attach(uint bus_hdrlen, struct device *dev)
+int brcmf_attach(struct device *dev)
 {
        struct brcmf_pub *drvr = NULL;
        int ret = 0;
@@ -1031,7 +881,7 @@ int brcmf_attach(uint bus_hdrlen, struct device *dev)
        mutex_init(&drvr->proto_block);
 
        /* Link to bus module */
-       drvr->hdrlen = bus_hdrlen;
+       drvr->hdrlen = 0;
        drvr->bus_if = dev_get_drvdata(dev);
        drvr->bus_if->drvr = drvr;
 
@@ -1048,8 +898,6 @@ int brcmf_attach(uint bus_hdrlen, struct device *dev)
        /* attach firmware event handler */
        brcmf_fweh_attach(drvr);
 
-       INIT_LIST_HEAD(&drvr->bus_if->dcmd_list);
-
        return ret;
 
 fail:
@@ -1138,14 +986,21 @@ fail:
        return 0;
 }
 
+void brcmf_bus_add_txhdrlen(struct device *dev, uint len)
+{
+       struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+       struct brcmf_pub *drvr = bus_if->drvr;
+
+       if (drvr) {
+               drvr->hdrlen += len;
+       }
+}
+
 static void brcmf_bus_detach(struct brcmf_pub *drvr)
 {
        brcmf_dbg(TRACE, "Enter\n");
 
        if (drvr) {
-               /* Stop the protocol module */
-               brcmf_proto_stop(drvr);
-
                /* Stop the bus module */
                brcmf_bus_stop(drvr->bus_if);
        }
@@ -1186,8 +1041,7 @@ void brcmf_detach(struct device *dev)
 
        brcmf_bus_detach(drvr);
 
-       if (drvr->prot)
-               brcmf_proto_detach(drvr);
+       brcmf_proto_detach(drvr);
 
        brcmf_fws_deinit(drvr);
 
@@ -1196,6 +1050,14 @@ void brcmf_detach(struct device *dev)
        kfree(drvr);
 }
 
+s32 brcmf_iovar_data_set(struct device *dev, char *name, void *data, u32 len)
+{
+       struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+       struct brcmf_if *ifp = bus_if->drvr->iflist[0];
+
+       return brcmf_fil_iovar_data_set(ifp, name, data, len);
+}
+
 static int brcmf_get_pend_8021x_cnt(struct brcmf_if *ifp)
 {
        return atomic_read(&ifp->pend_8021x_cnt);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h
deleted file mode 100644 (file)
index 53c6e71..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _BRCMF_PROTO_H_
-#define _BRCMF_PROTO_H_
-
-/*
- * Exported from the brcmf protocol module (brcmf_cdc)
- */
-
-/* Linkage, sets prot link and updates hdrlen in pub */
-int brcmf_proto_attach(struct brcmf_pub *drvr);
-
-/* Unlink, frees allocated protocol memory (including brcmf_proto) */
-void brcmf_proto_detach(struct brcmf_pub *drvr);
-
-/* Stop protocol: sync w/dongle state. */
-void brcmf_proto_stop(struct brcmf_pub *drvr);
-
-/* Add any protocol-specific data header.
- * Caller must reserve prot_hdrlen prepend space.
- */
-void brcmf_proto_hdrpush(struct brcmf_pub *, int ifidx, u8 offset,
-                        struct sk_buff *txp);
-
-/* Sets dongle media info (drv_version, mac address). */
-int brcmf_c_preinit_dcmds(struct brcmf_if *ifp);
-
-#endif                         /* _BRCMF_PROTO_H_ */
index b02953c4ade721235fbe0e4ed662aaa422ab21f7..0f95f3e79c10f6e04f8a5735a102e3059739e4f8 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/debugfs.h>
 #include <linux/vmalloc.h>
 #include <linux/platform_data/brcmfmac-sdio.h>
+#include <linux/moduleparam.h>
 #include <asm/unaligned.h>
 #include <defs.h>
 #include <brcmu_wifi.h>
@@ -110,6 +111,8 @@ struct rte_console {
 #define BRCMF_TXBOUND  20      /* Default for max tx frames in
                                 one scheduling */
 
+#define BRCMF_DEFAULT_TXGLOM_SIZE      32  /* max tx frames in glom chain */
+
 #define BRCMF_TXMINMAX 1       /* Max tx frames if rx still pending */
 
 #define MEMBLOCK       2048    /* Block size used for downloading
@@ -360,6 +363,8 @@ struct brcmf_sdio_hdrinfo {
        u16 len_left;
        u16 len_nxtfrm;
        u8 dat_offset;
+       bool lastfrm;
+       u16 tail_pad;
 };
 
 /* misc chip info needed by some of the routines */
@@ -384,7 +389,7 @@ struct brcmf_sdio {
        u8 tx_seq;              /* Transmit sequence number (next) */
        u8 tx_max;              /* Maximum transmit sequence allowed */
 
-       u8 hdrbuf[MAX_HDR_READ + BRCMF_SDALIGN];
+       u8 *hdrbuf;             /* buffer for handling rx frame */
        u8 *rxhdr;              /* Header of current rx frame (in hdrbuf) */
        u8 rx_seq;              /* Receive sequence number (expected) */
        struct brcmf_sdio_hdrinfo cur_read;
@@ -455,6 +460,10 @@ struct brcmf_sdio {
        bool sleeping; /* SDIO bus sleeping */
 
        u8 tx_hdrlen;           /* sdio bus header length for tx packet */
+       bool txglom;            /* host tx glomming enable flag */
+       struct sk_buff *txglom_sgpad;   /* scatter-gather padding buffer */
+       u16 head_align;         /* buffer pointer alignment */
+       u16 sgentry_align;      /* scatter-gather buffer alignment */
 };
 
 /* clkstate */
@@ -479,6 +488,10 @@ static const uint max_roundup = 512;
 
 #define ALIGNMENT  4
 
+static int brcmf_sdio_txglomsz = BRCMF_DEFAULT_TXGLOM_SIZE;
+module_param_named(txglomsz, brcmf_sdio_txglomsz, int, 0);
+MODULE_PARM_DESC(txglomsz, "maximum tx packet chain size [SDIO]");
+
 enum brcmf_sdio_frmtype {
        BRCMF_SDIO_FT_NORMAL,
        BRCMF_SDIO_FT_SUPER,
@@ -499,6 +512,8 @@ enum brcmf_sdio_frmtype {
 #define BCM4334_NVRAM_NAME             "brcm/brcmfmac4334-sdio.txt"
 #define BCM4335_FIRMWARE_NAME          "brcm/brcmfmac4335-sdio.bin"
 #define BCM4335_NVRAM_NAME             "brcm/brcmfmac4335-sdio.txt"
+#define BCM4339_FIRMWARE_NAME          "brcm/brcmfmac4339-sdio.bin"
+#define BCM4339_NVRAM_NAME             "brcm/brcmfmac4339-sdio.txt"
 
 MODULE_FIRMWARE(BCM43143_FIRMWARE_NAME);
 MODULE_FIRMWARE(BCM43143_NVRAM_NAME);
@@ -514,6 +529,8 @@ MODULE_FIRMWARE(BCM4334_FIRMWARE_NAME);
 MODULE_FIRMWARE(BCM4334_NVRAM_NAME);
 MODULE_FIRMWARE(BCM4335_FIRMWARE_NAME);
 MODULE_FIRMWARE(BCM4335_NVRAM_NAME);
+MODULE_FIRMWARE(BCM4339_FIRMWARE_NAME);
+MODULE_FIRMWARE(BCM4339_NVRAM_NAME);
 
 struct brcmf_firmware_names {
        u32 chipid;
@@ -537,7 +554,8 @@ static const struct brcmf_firmware_names brcmf_fwname_data[] = {
        { BCM4329_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4329) },
        { BCM4330_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4330) },
        { BCM4334_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4334) },
-       { BCM4335_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4335) }
+       { BCM4335_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4335) },
+       { BCM4339_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4339) }
 };
 
 
@@ -1097,10 +1115,18 @@ static void brcmf_sdbrcm_free_glom(struct brcmf_sdio *bus)
  * host and WiFi dongle which contains information needed for SDIO core and
  * firmware
  *
- * It consists of 2 parts: hw header and software header
+ * It consists of 3 parts: hardware header, hardware extension header and
+ * software header
  * hardware header (frame tag) - 4 bytes
  * Byte 0~1: Frame length
  * Byte 2~3: Checksum, bit-wise inverse of frame length
+ * hardware extension header - 8 bytes
+ * Tx glom mode only, N/A for Rx or normal Tx
+ * Byte 0~1: Packet length excluding hw frame tag
+ * Byte 2: Reserved
+ * Byte 3: Frame flags, bit 0: last frame indication
+ * Byte 4~5: Reserved
+ * Byte 6~7: Tail padding length
  * software header - 8 bytes
  * Byte 0: Rx/Tx sequence number
  * Byte 1: 4 MSB Channel number, 4 LSB arbitrary flag
@@ -1111,6 +1137,7 @@ static void brcmf_sdbrcm_free_glom(struct brcmf_sdio *bus)
  * Byte 6~7: Reserved
  */
 #define SDPCM_HWHDR_LEN                        4
+#define SDPCM_HWEXT_LEN                        8
 #define SDPCM_SWHDR_LEN                        8
 #define SDPCM_HDRLEN                   (SDPCM_HWHDR_LEN + SDPCM_SWHDR_LEN)
 /* software header */
@@ -1147,7 +1174,7 @@ static int brcmf_sdio_hdparse(struct brcmf_sdio *bus, u8 *header,
        u8 rx_seq, fc, tx_seq_max;
        u32 swheader;
 
-       trace_brcmf_sdpcm_hdr(false, header);
+       trace_brcmf_sdpcm_hdr(SDPCM_RX, header);
 
        /* hw header */
        len = get_unaligned_le16(header);
@@ -1260,25 +1287,34 @@ static inline void brcmf_sdio_update_hwhdr(u8 *header, u16 frm_length)
 static void brcmf_sdio_hdpack(struct brcmf_sdio *bus, u8 *header,
                              struct brcmf_sdio_hdrinfo *hd_info)
 {
-       u32 sw_header;
+       u32 hdrval;
+       u8 hdr_offset;
 
        brcmf_sdio_update_hwhdr(header, hd_info->len);
-
-       sw_header = bus->tx_seq;
-       sw_header |= (hd_info->channel << SDPCM_CHANNEL_SHIFT) &
-                    SDPCM_CHANNEL_MASK;
-       sw_header |= (hd_info->dat_offset << SDPCM_DOFFSET_SHIFT) &
-                    SDPCM_DOFFSET_MASK;
-       *(((__le32 *)header) + 1) = cpu_to_le32(sw_header);
-       *(((__le32 *)header) + 2) = 0;
-       trace_brcmf_sdpcm_hdr(true, header);
+       hdr_offset = SDPCM_HWHDR_LEN;
+
+       if (bus->txglom) {
+               hdrval = (hd_info->len - hdr_offset) | (hd_info->lastfrm << 24);
+               *((__le32 *)(header + hdr_offset)) = cpu_to_le32(hdrval);
+               hdrval = (u16)hd_info->tail_pad << 16;
+               *(((__le32 *)(header + hdr_offset)) + 1) = cpu_to_le32(hdrval);
+               hdr_offset += SDPCM_HWEXT_LEN;
+       }
+
+       hdrval = hd_info->seq_num;
+       hdrval |= (hd_info->channel << SDPCM_CHANNEL_SHIFT) &
+                 SDPCM_CHANNEL_MASK;
+       hdrval |= (hd_info->dat_offset << SDPCM_DOFFSET_SHIFT) &
+                 SDPCM_DOFFSET_MASK;
+       *((__le32 *)(header + hdr_offset)) = cpu_to_le32(hdrval);
+       *(((__le32 *)(header + hdr_offset)) + 1) = 0;
+       trace_brcmf_sdpcm_hdr(SDPCM_TX + !!(bus->txglom), header);
 }
 
 static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
 {
        u16 dlen, totlen;
        u8 *dptr, num = 0;
-       u32 align = 0;
        u16 sublen;
        struct sk_buff *pfirst, *pnext;
 
@@ -1293,11 +1329,6 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
        brcmf_dbg(SDIO, "start: glomd %p glom %p\n",
                  bus->glomd, skb_peek(&bus->glom));
 
-       if (bus->sdiodev->pdata)
-               align = bus->sdiodev->pdata->sd_sgentry_align;
-       if (align < 4)
-               align = 4;
-
        /* If there's a descriptor, generate the packet chain */
        if (bus->glomd) {
                pfirst = pnext = NULL;
@@ -1321,9 +1352,9 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
                                pnext = NULL;
                                break;
                        }
-                       if (sublen % align) {
+                       if (sublen % bus->sgentry_align) {
                                brcmf_err("sublen %d not multiple of %d\n",
-                                         sublen, align);
+                                         sublen, bus->sgentry_align);
                        }
                        totlen += sublen;
 
@@ -1336,7 +1367,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
                        }
 
                        /* Allocate/chain packet for next subframe */
-                       pnext = brcmu_pkt_buf_get_skb(sublen + align);
+                       pnext = brcmu_pkt_buf_get_skb(sublen + bus->sgentry_align);
                        if (pnext == NULL) {
                                brcmf_err("bcm_pkt_buf_get_skb failed, num %d len %d\n",
                                          num, sublen);
@@ -1345,7 +1376,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
                        skb_queue_tail(&bus->glom, pnext);
 
                        /* Adhere to start alignment requirements */
-                       pkt_align(pnext, sublen, align);
+                       pkt_align(pnext, sublen, bus->sgentry_align);
                }
 
                /* If all allocations succeeded, save packet chain
@@ -1549,9 +1580,9 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff)
                goto done;
 
        rbuf = bus->rxbuf;
-       pad = ((unsigned long)rbuf % BRCMF_SDALIGN);
+       pad = ((unsigned long)rbuf % bus->head_align);
        if (pad)
-               rbuf += (BRCMF_SDALIGN - pad);
+               rbuf += (bus->head_align - pad);
 
        /* Copy the already-read portion over */
        memcpy(buf, hdr, BRCMF_FIRSTREAD);
@@ -1565,14 +1596,10 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff)
                if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
                    ((len + pad) < bus->sdiodev->bus_if->maxctl))
                        rdlen += pad;
-       } else if (rdlen % BRCMF_SDALIGN) {
-               rdlen += BRCMF_SDALIGN - (rdlen % BRCMF_SDALIGN);
+       } else if (rdlen % bus->head_align) {
+               rdlen += bus->head_align - (rdlen % bus->head_align);
        }
 
-       /* Satisfy length-alignment requirements */
-       if (rdlen & (ALIGNMENT - 1))
-               rdlen = roundup(rdlen, ALIGNMENT);
-
        /* Drop if the read is too big or it exceeds our maximum */
        if ((rdlen + BRCMF_FIRSTREAD) > bus->sdiodev->bus_if->maxctl) {
                brcmf_err("%d-byte control read exceeds %d-byte buffer\n",
@@ -1637,8 +1664,8 @@ static void brcmf_pad(struct brcmf_sdio *bus, u16 *pad, u16 *rdlen)
                if (*pad <= bus->roundup && *pad < bus->blocksize &&
                    *rdlen + *pad + BRCMF_FIRSTREAD < MAX_RX_DATASZ)
                        *rdlen += *pad;
-       } else if (*rdlen % BRCMF_SDALIGN) {
-               *rdlen += BRCMF_SDALIGN - (*rdlen % BRCMF_SDALIGN);
+       } else if (*rdlen % bus->head_align) {
+               *rdlen += bus->head_align - (*rdlen % bus->head_align);
        }
 }
 
@@ -1726,7 +1753,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
                brcmf_pad(bus, &pad, &rd->len_left);
 
                pkt = brcmu_pkt_buf_get_skb(rd->len_left + head_read +
-                                           BRCMF_SDALIGN);
+                                           bus->head_align);
                if (!pkt) {
                        /* Give up on data, request rtx of events */
                        brcmf_err("brcmu_pkt_buf_get_skb failed\n");
@@ -1736,7 +1763,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
                        continue;
                }
                skb_pull(pkt, head_read);
-               pkt_align(pkt, rd->len_left, BRCMF_SDALIGN);
+               pkt_align(pkt, rd->len_left, bus->head_align);
 
                ret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad,
                                              SDIO_FUNC_2, F2SYNC, pkt);
@@ -1871,6 +1898,29 @@ brcmf_sdbrcm_wait_event_wakeup(struct brcmf_sdio *bus)
        return;
 }
 
+static int brcmf_sdio_txpkt_hdalign(struct brcmf_sdio *bus, struct sk_buff *pkt)
+{
+       u16 head_pad;
+       u8 *dat_buf;
+
+       dat_buf = (u8 *)(pkt->data);
+
+       /* Check head padding */
+       head_pad = ((unsigned long)dat_buf % bus->head_align);
+       if (head_pad) {
+               if (skb_headroom(pkt) < head_pad) {
+                       bus->sdiodev->bus_if->tx_realloc++;
+                       head_pad = 0;
+                       if (skb_cow(pkt, head_pad))
+                               return -ENOMEM;
+               }
+               skb_push(pkt, head_pad);
+               dat_buf = (u8 *)(pkt->data);
+               memset(dat_buf, 0, head_pad + bus->tx_hdrlen);
+       }
+       return head_pad;
+}
+
 /**
  * struct brcmf_skbuff_cb reserves first two bytes in sk_buff::cb for
  * bus layer usage.
@@ -1880,32 +1930,40 @@ brcmf_sdbrcm_wait_event_wakeup(struct brcmf_sdio *bus)
 /* bit mask of data length chopped from the previous packet */
 #define ALIGN_SKB_CHOP_LEN_MASK        0x7fff
 
-static int brcmf_sdio_txpkt_prep_sg(struct brcmf_sdio_dev *sdiodev,
+static int brcmf_sdio_txpkt_prep_sg(struct brcmf_sdio *bus,
                                    struct sk_buff_head *pktq,
-                                   struct sk_buff *pkt, uint chan)
+                                   struct sk_buff *pkt, u16 total_len)
 {
+       struct brcmf_sdio_dev *sdiodev;
        struct sk_buff *pkt_pad;
-       u16 tail_pad, tail_chop, sg_align;
+       u16 tail_pad, tail_chop, chain_pad;
        unsigned int blksize;
-       u8 *dat_buf;
-       int ntail;
+       bool lastfrm;
+       int ntail, ret;
 
+       sdiodev = bus->sdiodev;
        blksize = sdiodev->func[SDIO_FUNC_2]->cur_blksize;
-       sg_align = 4;
-       if (sdiodev->pdata && sdiodev->pdata->sd_sgentry_align > 4)
-               sg_align = sdiodev->pdata->sd_sgentry_align;
        /* sg entry alignment should be a divisor of block size */
-       WARN_ON(blksize % sg_align);
+       WARN_ON(blksize % bus->sgentry_align);
 
        /* Check tail padding */
-       pkt_pad = NULL;
-       tail_chop = pkt->len % sg_align;
-       tail_pad = sg_align - tail_chop;
-       tail_pad += blksize - (pkt->len + tail_pad) % blksize;
+       lastfrm = skb_queue_is_last(pktq, pkt);
+       tail_pad = 0;
+       tail_chop = pkt->len % bus->sgentry_align;
+       if (tail_chop)
+               tail_pad = bus->sgentry_align - tail_chop;
+       chain_pad = (total_len + tail_pad) % blksize;
+       if (lastfrm && chain_pad)
+               tail_pad += blksize - chain_pad;
        if (skb_tailroom(pkt) < tail_pad && pkt->len > blksize) {
-               pkt_pad = brcmu_pkt_buf_get_skb(tail_pad + tail_chop);
+               pkt_pad = bus->txglom_sgpad;
+               if (pkt_pad == NULL)
+                         brcmu_pkt_buf_get_skb(tail_pad + tail_chop);
                if (pkt_pad == NULL)
                        return -ENOMEM;
+               ret = brcmf_sdio_txpkt_hdalign(bus, pkt_pad);
+               if (unlikely(ret < 0))
+                       return ret;
                memcpy(pkt_pad->data,
                       pkt->data + pkt->len - tail_chop,
                       tail_chop);
@@ -1920,14 +1978,10 @@ static int brcmf_sdio_txpkt_prep_sg(struct brcmf_sdio_dev *sdiodev,
                                return -ENOMEM;
                if (skb_linearize(pkt))
                        return -ENOMEM;
-               dat_buf = (u8 *)(pkt->data);
                __skb_put(pkt, tail_pad);
        }
 
-       if (pkt_pad)
-               return pkt->len + tail_chop;
-       else
-               return pkt->len - tail_pad;
+       return tail_pad;
 }
 
 /**
@@ -1946,58 +2000,66 @@ static int
 brcmf_sdio_txpkt_prep(struct brcmf_sdio *bus, struct sk_buff_head *pktq,
                      uint chan)
 {
-       u16 head_pad, head_align;
+       u16 head_pad, total_len;
        struct sk_buff *pkt_next;
-       u8 *dat_buf;
-       int err;
+       u8 txseq;
+       int ret;
        struct brcmf_sdio_hdrinfo hd_info = {0};
 
-       /* SDIO ADMA requires at least 32 bit alignment */
-       head_align = 4;
-       if (bus->sdiodev->pdata && bus->sdiodev->pdata->sd_head_align > 4)
-               head_align = bus->sdiodev->pdata->sd_head_align;
+       txseq = bus->tx_seq;
+       total_len = 0;
+       skb_queue_walk(pktq, pkt_next) {
+               /* alignment packet inserted in previous
+                * loop cycle can be skipped as it is
+                * already properly aligned and does not
+                * need an sdpcm header.
+                */
+               if (*(u32 *)(pkt_next->cb) & ALIGN_SKB_FLAG)
+                       continue;
 
-       pkt_next = pktq->next;
-       dat_buf = (u8 *)(pkt_next->data);
+               /* align packet data pointer */
+               ret = brcmf_sdio_txpkt_hdalign(bus, pkt_next);
+               if (ret < 0)
+                       return ret;
+               head_pad = (u16)ret;
+               if (head_pad)
+                       memset(pkt_next->data, 0, head_pad + bus->tx_hdrlen);
 
-       /* Check head padding */
-       head_pad = ((unsigned long)dat_buf % head_align);
-       if (head_pad) {
-               if (skb_headroom(pkt_next) < head_pad) {
-                       bus->sdiodev->bus_if->tx_realloc++;
-                       head_pad = 0;
-                       if (skb_cow(pkt_next, head_pad))
-                               return -ENOMEM;
-               }
-               skb_push(pkt_next, head_pad);
-               dat_buf = (u8 *)(pkt_next->data);
-               memset(dat_buf, 0, head_pad + bus->tx_hdrlen);
-       }
+               total_len += pkt_next->len;
 
-       if (bus->sdiodev->sg_support && pktq->qlen > 1) {
-               err = brcmf_sdio_txpkt_prep_sg(bus->sdiodev, pktq,
-                                              pkt_next, chan);
-               if (err < 0)
-                       return err;
-               hd_info.len = (u16)err;
-       } else {
                hd_info.len = pkt_next->len;
-       }
-
-       hd_info.channel = chan;
-       hd_info.dat_offset = head_pad + bus->tx_hdrlen;
-
-       /* Now fill the header */
-       brcmf_sdio_hdpack(bus, dat_buf, &hd_info);
-
-       if (BRCMF_BYTES_ON() &&
-           ((BRCMF_CTL_ON() && chan == SDPCM_CONTROL_CHANNEL) ||
-            (BRCMF_DATA_ON() && chan != SDPCM_CONTROL_CHANNEL)))
-               brcmf_dbg_hex_dump(true, pkt_next, hd_info.len, "Tx Frame:\n");
-       else if (BRCMF_HDRS_ON())
-               brcmf_dbg_hex_dump(true, pkt_next, head_pad + bus->tx_hdrlen,
-                                  "Tx Header:\n");
+               hd_info.lastfrm = skb_queue_is_last(pktq, pkt_next);
+               if (bus->txglom && pktq->qlen > 1) {
+                       ret = brcmf_sdio_txpkt_prep_sg(bus, pktq,
+                                                      pkt_next, total_len);
+                       if (ret < 0)
+                               return ret;
+                       hd_info.tail_pad = (u16)ret;
+                       total_len += (u16)ret;
+               }
 
+               hd_info.channel = chan;
+               hd_info.dat_offset = head_pad + bus->tx_hdrlen;
+               hd_info.seq_num = txseq++;
+
+               /* Now fill the header */
+               brcmf_sdio_hdpack(bus, pkt_next->data, &hd_info);
+
+               if (BRCMF_BYTES_ON() &&
+                   ((BRCMF_CTL_ON() && chan == SDPCM_CONTROL_CHANNEL) ||
+                    (BRCMF_DATA_ON() && chan != SDPCM_CONTROL_CHANNEL)))
+                       brcmf_dbg_hex_dump(true, pkt_next, hd_info.len,
+                                          "Tx Frame:\n");
+               else if (BRCMF_HDRS_ON())
+                       brcmf_dbg_hex_dump(true, pkt_next,
+                                          head_pad + bus->tx_hdrlen,
+                                          "Tx Header:\n");
+       }
+       /* Hardware length tag of the first packet should be total
+        * length of the chain (including padding)
+        */
+       if (bus->txglom)
+               brcmf_sdio_update_hwhdr(pktq->next->data, total_len);
        return 0;
 }
 
@@ -2015,6 +2077,7 @@ brcmf_sdio_txpkt_postp(struct brcmf_sdio *bus, struct sk_buff_head *pktq)
 {
        u8 *hdr;
        u32 dat_offset;
+       u16 tail_pad;
        u32 dummy_flags, chop_len;
        struct sk_buff *pkt_next, *tmp, *pkt_prev;
 
@@ -2024,42 +2087,42 @@ brcmf_sdio_txpkt_postp(struct brcmf_sdio *bus, struct sk_buff_head *pktq)
                        chop_len = dummy_flags & ALIGN_SKB_CHOP_LEN_MASK;
                        if (chop_len) {
                                pkt_prev = pkt_next->prev;
-                               memcpy(pkt_prev->data + pkt_prev->len,
-                                      pkt_next->data, chop_len);
                                skb_put(pkt_prev, chop_len);
                        }
                        __skb_unlink(pkt_next, pktq);
                        brcmu_pkt_buf_free_skb(pkt_next);
                } else {
-                       hdr = pkt_next->data + SDPCM_HWHDR_LEN;
+                       hdr = pkt_next->data + bus->tx_hdrlen - SDPCM_SWHDR_LEN;
                        dat_offset = le32_to_cpu(*(__le32 *)hdr);
                        dat_offset = (dat_offset & SDPCM_DOFFSET_MASK) >>
                                     SDPCM_DOFFSET_SHIFT;
                        skb_pull(pkt_next, dat_offset);
+                       if (bus->txglom) {
+                               tail_pad = le16_to_cpu(*(__le16 *)(hdr - 2));
+                               skb_trim(pkt_next, pkt_next->len - tail_pad);
+                       }
                }
        }
 }
 
 /* Writes a HW/SW header into the packet and sends it. */
 /* Assumes: (a) header space already there, (b) caller holds lock */
-static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
+static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff_head *pktq,
                              uint chan)
 {
        int ret;
        int i;
-       struct sk_buff_head localq;
+       struct sk_buff *pkt_next, *tmp;
 
        brcmf_dbg(TRACE, "Enter\n");
 
-       __skb_queue_head_init(&localq);
-       __skb_queue_tail(&localq, pkt);
-       ret = brcmf_sdio_txpkt_prep(bus, &localq, chan);
+       ret = brcmf_sdio_txpkt_prep(bus, pktq, chan);
        if (ret)
                goto done;
 
        sdio_claim_host(bus->sdiodev->func[1]);
        ret = brcmf_sdcard_send_pkt(bus->sdiodev, bus->sdiodev->sbwad,
-                                   SDIO_FUNC_2, F2SYNC, &localq);
+                                   SDIO_FUNC_2, F2SYNC, pktq);
        bus->sdcnt.f2txdata++;
 
        if (ret < 0) {
@@ -2083,42 +2146,56 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
                        if ((hi == 0) && (lo == 0))
                                break;
                }
-
        }
        sdio_release_host(bus->sdiodev->func[1]);
-       if (ret == 0)
-               bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQ_WRAP;
 
 done:
-       brcmf_sdio_txpkt_postp(bus, &localq);
-       __skb_dequeue_tail(&localq);
-       brcmf_txcomplete(bus->sdiodev->dev, pkt, ret == 0);
+       brcmf_sdio_txpkt_postp(bus, pktq);
+       if (ret == 0)
+               bus->tx_seq = (bus->tx_seq + pktq->qlen) % SDPCM_SEQ_WRAP;
+       skb_queue_walk_safe(pktq, pkt_next, tmp) {
+               __skb_unlink(pkt_next, pktq);
+               brcmf_txcomplete(bus->sdiodev->dev, pkt_next, ret == 0);
+       }
        return ret;
 }
 
 static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes)
 {
        struct sk_buff *pkt;
+       struct sk_buff_head pktq;
        u32 intstatus = 0;
-       int ret = 0, prec_out;
+       int ret = 0, prec_out, i;
        uint cnt = 0;
-       u8 tx_prec_map;
+       u8 tx_prec_map, pkt_num;
 
        brcmf_dbg(TRACE, "Enter\n");
 
        tx_prec_map = ~bus->flowcontrol;
 
        /* Send frames until the limit or some other event */
-       for (cnt = 0; (cnt < maxframes) && data_ok(bus); cnt++) {
+       for (cnt = 0; (cnt < maxframes) && data_ok(bus);) {
+               pkt_num = 1;
+               __skb_queue_head_init(&pktq);
+               if (bus->txglom)
+                       pkt_num = min_t(u8, bus->tx_max - bus->tx_seq,
+                                       brcmf_sdio_txglomsz);
+               pkt_num = min_t(u32, pkt_num,
+                               brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol));
                spin_lock_bh(&bus->txqlock);
-               pkt = brcmu_pktq_mdeq(&bus->txq, tx_prec_map, &prec_out);
-               if (pkt == NULL) {
-                       spin_unlock_bh(&bus->txqlock);
-                       break;
+               for (i = 0; i < pkt_num; i++) {
+                       pkt = brcmu_pktq_mdeq(&bus->txq, tx_prec_map,
+                                             &prec_out);
+                       if (pkt == NULL)
+                               break;
+                       __skb_queue_tail(&pktq, pkt);
                }
                spin_unlock_bh(&bus->txqlock);
+               if (i == 0)
+                       break;
 
-               ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL);
+               ret = brcmf_sdbrcm_txpkt(bus, &pktq, SDPCM_DATA_CHANNEL);
+               cnt += i;
 
                /* In poll mode, need to check for other events */
                if (!bus->intr && cnt) {
@@ -2665,7 +2742,7 @@ static int
 brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
 {
        u8 *frame;
-       u16 len;
+       u16 len, pad;
        uint retries = 0;
        u8 doff = 0;
        int ret = -1;
@@ -2681,28 +2758,26 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
        len = (msglen += bus->tx_hdrlen);
 
        /* Add alignment padding (optional for ctl frames) */
-       doff = ((unsigned long)frame % BRCMF_SDALIGN);
+       doff = ((unsigned long)frame % bus->head_align);
        if (doff) {
                frame -= doff;
                len += doff;
                msglen += doff;
                memset(frame, 0, doff + bus->tx_hdrlen);
        }
-       /* precondition: doff < BRCMF_SDALIGN */
+       /* precondition: doff < bus->head_align */
        doff += bus->tx_hdrlen;
 
        /* Round send length to next SDIO block */
+       pad = 0;
        if (bus->roundup && bus->blocksize && (len > bus->blocksize)) {
-               u16 pad = bus->blocksize - (len % bus->blocksize);
-               if ((pad <= bus->roundup) && (pad < bus->blocksize))
-                       len += pad;
-       } else if (len % BRCMF_SDALIGN) {
-               len += BRCMF_SDALIGN - (len % BRCMF_SDALIGN);
+               pad = bus->blocksize - (len % bus->blocksize);
+               if ((pad > bus->roundup) || (pad >= bus->blocksize))
+                       pad = 0;
+       } else if (len % bus->head_align) {
+               pad = bus->head_align - (len % bus->head_align);
        }
-
-       /* Satisfy length-alignment requirements */
-       if (len & (ALIGNMENT - 1))
-               len = roundup(len, ALIGNMENT);
+       len += pad;
 
        /* precondition: IS_ALIGNED((unsigned long)frame, 2) */
 
@@ -2714,8 +2789,14 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
        hd_info.len = (u16)msglen;
        hd_info.channel = SDPCM_CONTROL_CHANNEL;
        hd_info.dat_offset = doff;
+       hd_info.seq_num = bus->tx_seq;
+       hd_info.lastfrm = true;
+       hd_info.tail_pad = pad;
        brcmf_sdio_hdpack(bus, frame, &hd_info);
 
+       if (bus->txglom)
+               brcmf_sdio_update_hwhdr(frame, len);
+
        if (!data_ok(bus)) {
                brcmf_dbg(INFO, "No bus credit bus->tx_max %d, bus->tx_seq %d\n",
                          bus->tx_max, bus->tx_seq);
@@ -3425,6 +3506,65 @@ brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus)
        return ret;
 }
 
+static int brcmf_sdbrcm_bus_preinit(struct device *dev)
+{
+       struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+       struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
+       struct brcmf_sdio *bus = sdiodev->bus;
+       uint pad_size;
+       u32 value;
+       u8 idx;
+       int err;
+
+       /* the commands below use the terms tx and rx from
+        * a device perspective, ie. bus:txglom affects the
+        * bus transfers from device to host.
+        */
+       idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV);
+       if (bus->ci->c_inf[idx].rev < 12) {
+               /* for sdio core rev < 12, disable txgloming */
+               value = 0;
+               err = brcmf_iovar_data_set(dev, "bus:txglom", &value,
+                                          sizeof(u32));
+       } else {
+               /* otherwise, set txglomalign */
+               value = 4;
+               if (sdiodev->pdata)
+                       value = sdiodev->pdata->sd_sgentry_align;
+               /* SDIO ADMA requires at least 32 bit alignment */
+               value = max_t(u32, value, 4);
+               err = brcmf_iovar_data_set(dev, "bus:txglomalign", &value,
+                                          sizeof(u32));
+       }
+
+       if (err < 0)
+               goto done;
+
+       bus->tx_hdrlen = SDPCM_HWHDR_LEN + SDPCM_SWHDR_LEN;
+       if (sdiodev->sg_support) {
+               bus->txglom = false;
+               value = 1;
+               pad_size = bus->sdiodev->func[2]->cur_blksize << 1;
+               bus->txglom_sgpad = brcmu_pkt_buf_get_skb(pad_size);
+               if (!bus->txglom_sgpad)
+                       brcmf_err("allocating txglom padding skb failed, reduced performance\n");
+
+               err = brcmf_iovar_data_set(bus->sdiodev->dev, "bus:rxglom",
+                                          &value, sizeof(u32));
+               if (err < 0) {
+                       /* bus:rxglom is allowed to fail */
+                       err = 0;
+               } else {
+                       bus->txglom = true;
+                       bus->tx_hdrlen += SDPCM_HWEXT_LEN;
+               }
+       }
+       brcmf_bus_add_txhdrlen(bus->sdiodev->dev, bus->tx_hdrlen);
+
+done:
+       return err;
+}
+
 static int brcmf_sdbrcm_bus_init(struct device *dev)
 {
        struct brcmf_bus *bus_if = dev_get_drvdata(dev);
@@ -3673,7 +3813,7 @@ static bool brcmf_sdbrcm_probe_malloc(struct brcmf_sdio *bus)
        if (bus->sdiodev->bus_if->maxctl) {
                bus->rxblen =
                    roundup((bus->sdiodev->bus_if->maxctl + SDPCM_HDRLEN),
-                           ALIGNMENT) + BRCMF_SDALIGN;
+                           ALIGNMENT) + bus->head_align;
                bus->rxbuf = kmalloc(bus->rxblen, GFP_ATOMIC);
                if (!(bus->rxbuf))
                        return false;
@@ -3774,9 +3914,13 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva)
 
        brcmu_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN);
 
+       /* allocate header buffer */
+       bus->hdrbuf = kzalloc(MAX_HDR_READ + bus->head_align, GFP_KERNEL);
+       if (!bus->hdrbuf)
+               return false;
        /* Locate an appropriately-aligned portion of hdrbuf */
        bus->rxhdr = (u8 *) roundup((unsigned long)&bus->hdrbuf[0],
-                                   BRCMF_SDALIGN);
+                                   bus->head_align);
 
        /* Set the poll and/or interrupt flags */
        bus->intr = true;
@@ -3895,8 +4039,9 @@ static void brcmf_sdbrcm_release(struct brcmf_sdio *bus)
                        brcmf_sdbrcm_release_dongle(bus);
                }
 
+               brcmu_pkt_buf_free_skb(bus->txglom_sgpad);
                brcmf_sdbrcm_release_malloc(bus);
-
+               kfree(bus->hdrbuf);
                kfree(bus);
        }
 
@@ -3905,6 +4050,7 @@ static void brcmf_sdbrcm_release(struct brcmf_sdio *bus)
 
 static struct brcmf_bus_ops brcmf_sdio_bus_ops = {
        .stop = brcmf_sdbrcm_bus_stop,
+       .preinit = brcmf_sdbrcm_bus_preinit,
        .init = brcmf_sdbrcm_bus_init,
        .txdata = brcmf_sdbrcm_bus_txdata,
        .txctl = brcmf_sdbrcm_bus_txctl,
@@ -3916,10 +4062,6 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
 {
        int ret;
        struct brcmf_sdio *bus;
-       struct brcmf_bus_dcmd *dlst;
-       u32 dngl_txglom;
-       u32 txglomalign = 0;
-       u8 idx;
 
        brcmf_dbg(TRACE, "Enter\n");
 
@@ -3939,6 +4081,18 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
        bus->txminmax = BRCMF_TXMINMAX;
        bus->tx_seq = SDPCM_SEQ_WRAP - 1;
 
+       /* platform specific configuration:
+        *   alignments must be at least 4 bytes for ADMA
+         */
+       bus->head_align = ALIGNMENT;
+       bus->sgentry_align = ALIGNMENT;
+       if (sdiodev->pdata) {
+               if (sdiodev->pdata->sd_head_align > ALIGNMENT)
+                       bus->head_align = sdiodev->pdata->sd_head_align;
+               if (sdiodev->pdata->sd_sgentry_align > ALIGNMENT)
+                       bus->sgentry_align = sdiodev->pdata->sd_sgentry_align;
+       }
+
        INIT_WORK(&bus->datawork, brcmf_sdio_dataworker);
        bus->brcmf_wq = create_singlethread_workqueue("brcmf_wq");
        if (bus->brcmf_wq == NULL) {
@@ -3983,7 +4137,7 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
        bus->tx_hdrlen = SDPCM_HWHDR_LEN + SDPCM_SWHDR_LEN;
 
        /* Attach to the common layer, reserve hdr space */
-       ret = brcmf_attach(bus->tx_hdrlen, bus->sdiodev->dev);
+       ret = brcmf_attach(bus->sdiodev->dev);
        if (ret != 0) {
                brcmf_err("brcmf_attach failed\n");
                goto fail;
@@ -4003,30 +4157,6 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
        brcmf_sdio_debugfs_create(bus);
        brcmf_dbg(INFO, "completed!!\n");
 
-       /* sdio bus core specific dcmd */
-       idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV);
-       dlst = kzalloc(sizeof(struct brcmf_bus_dcmd), GFP_KERNEL);
-       if (dlst) {
-               if (bus->ci->c_inf[idx].rev < 12) {
-                       /* for sdio core rev < 12, disable txgloming */
-                       dngl_txglom = 0;
-                       dlst->name = "bus:txglom";
-                       dlst->param = (char *)&dngl_txglom;
-                       dlst->param_len = sizeof(u32);
-               } else {
-                       /* otherwise, set txglomalign */
-                       if (sdiodev->pdata)
-                               txglomalign = sdiodev->pdata->sd_sgentry_align;
-                       /* SDIO ADMA requires at least 32 bit alignment */
-                       if (txglomalign < 4)
-                               txglomalign = 4;
-                       dlst->name = "bus:txglomalign";
-                       dlst->param = (char *)&txglomalign;
-                       dlst->param_len = sizeof(u32);
-               }
-               list_add(&dlst->list, &bus->sdiodev->bus_if->dcmd_list);
-       }
-
        /* if firmware path present try to download and bring up bus */
        ret = brcmf_bus_start(bus->sdiodev->dev);
        if (ret != 0) {
index 14bc24dc5baeb1f8272b4da0660d893c4bfc9b48..51b53a73d07464c0bb9b8b5a6f551e20314c37ce 100644 (file)
@@ -122,6 +122,52 @@ enum brcmf_fweh_event_code {
 #define BRCMF_EVENT_MSG_FLUSHTXQ       0x02
 #define BRCMF_EVENT_MSG_GROUP          0x04
 
+/* status field values in struct brcmf_event_msg */
+#define BRCMF_E_STATUS_SUCCESS                 0
+#define BRCMF_E_STATUS_FAIL                    1
+#define BRCMF_E_STATUS_TIMEOUT                 2
+#define BRCMF_E_STATUS_NO_NETWORKS             3
+#define BRCMF_E_STATUS_ABORT                   4
+#define BRCMF_E_STATUS_NO_ACK                  5
+#define BRCMF_E_STATUS_UNSOLICITED             6
+#define BRCMF_E_STATUS_ATTEMPT                 7
+#define BRCMF_E_STATUS_PARTIAL                 8
+#define BRCMF_E_STATUS_NEWSCAN                 9
+#define BRCMF_E_STATUS_NEWASSOC                        10
+#define BRCMF_E_STATUS_11HQUIET                        11
+#define BRCMF_E_STATUS_SUPPRESS                        12
+#define BRCMF_E_STATUS_NOCHANS                 13
+#define BRCMF_E_STATUS_CS_ABORT                        15
+#define BRCMF_E_STATUS_ERROR                   16
+
+/* reason field values in struct brcmf_event_msg */
+#define BRCMF_E_REASON_INITIAL_ASSOC           0
+#define BRCMF_E_REASON_LOW_RSSI                        1
+#define BRCMF_E_REASON_DEAUTH                  2
+#define BRCMF_E_REASON_DISASSOC                        3
+#define BRCMF_E_REASON_BCNS_LOST               4
+#define BRCMF_E_REASON_MINTXRATE               9
+#define BRCMF_E_REASON_TXFAIL                  10
+
+#define BRCMF_E_REASON_LINK_BSSCFG_DIS         4
+#define BRCMF_E_REASON_FAST_ROAM_FAILED                5
+#define BRCMF_E_REASON_DIRECTED_ROAM           6
+#define BRCMF_E_REASON_TSPEC_REJECTED          7
+#define BRCMF_E_REASON_BETTER_AP               8
+
+/* action field values for brcmf_ifevent */
+#define BRCMF_E_IF_ADD                         1
+#define BRCMF_E_IF_DEL                         2
+#define BRCMF_E_IF_CHANGE                      3
+
+/* flag field values for brcmf_ifevent */
+#define BRCMF_E_IF_FLAG_NOIF                   1
+
+/* role field values for brcmf_ifevent */
+#define BRCMF_E_IF_ROLE_STA                    0
+#define BRCMF_E_IF_ROLE_AP                     1
+#define BRCMF_E_IF_ROLE_WDS                    2
+
 /**
  * definitions for event packet validation.
  */
@@ -160,6 +206,14 @@ struct brcmf_event_msg {
        u8 bsscfgidx;
 };
 
+struct brcmf_if_event {
+       u8 ifidx;
+       u8 action;
+       u8 flags;
+       u8 bssidx;
+       u8 role;
+};
+
 typedef int (*brcmf_fweh_handler_t)(struct brcmf_if *ifp,
                                    const struct brcmf_event_msg *evtmsg,
                                    void *data);
index 04f395930d86742372585ff42b3ce3837f0d606d..b72d3395499a3c1e713af54a4379f86e93ca407a 100644 (file)
@@ -27,6 +27,7 @@
 #include "dhd_dbg.h"
 #include "tracepoint.h"
 #include "fwil.h"
+#include "proto.h"
 
 
 #define MAX_HEX_DUMP_LEN       64
@@ -46,11 +47,9 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set)
        if (data != NULL)
                len = min_t(uint, len, BRCMF_DCMD_MAXLEN);
        if (set)
-               err = brcmf_proto_cdc_set_dcmd(drvr, ifp->ifidx, cmd, data,
-                                              len);
+               err = brcmf_proto_set_dcmd(drvr, ifp->ifidx, cmd, data, len);
        else
-               err = brcmf_proto_cdc_query_dcmd(drvr, ifp->ifidx, cmd, data,
-                                                len);
+               err = brcmf_proto_query_dcmd(drvr, ifp->ifidx, cmd, data, len);
 
        if (err >= 0)
                err = 0;
index 16eb8202fb1e4678be1c5b180e2ba964ac43e6f5..77eae86e55c23318e439fa23118f3d10e4b33788 100644 (file)
 #ifndef _fwil_h_
 #define _fwil_h_
 
+/*******************************************************************************
+ * Dongle command codes that are interpreted by firmware
+ ******************************************************************************/
+#define BRCMF_C_GET_VERSION                    1
+#define BRCMF_C_UP                             2
+#define BRCMF_C_DOWN                           3
+#define BRCMF_C_SET_PROMISC                    10
+#define BRCMF_C_GET_RATE                       12
+#define BRCMF_C_GET_INFRA                      19
+#define BRCMF_C_SET_INFRA                      20
+#define BRCMF_C_GET_AUTH                       21
+#define BRCMF_C_SET_AUTH                       22
+#define BRCMF_C_GET_BSSID                      23
+#define BRCMF_C_GET_SSID                       25
+#define BRCMF_C_SET_SSID                       26
+#define BRCMF_C_TERMINATED                     28
+#define BRCMF_C_GET_CHANNEL                    29
+#define BRCMF_C_SET_CHANNEL                    30
+#define BRCMF_C_GET_SRL                                31
+#define BRCMF_C_SET_SRL                                32
+#define BRCMF_C_GET_LRL                                33
+#define BRCMF_C_SET_LRL                                34
+#define BRCMF_C_GET_RADIO                      37
+#define BRCMF_C_SET_RADIO                      38
+#define BRCMF_C_GET_PHYTYPE                    39
+#define BRCMF_C_SET_KEY                                45
+#define BRCMF_C_SET_PASSIVE_SCAN               49
+#define BRCMF_C_SCAN                           50
+#define BRCMF_C_SCAN_RESULTS                   51
+#define BRCMF_C_DISASSOC                       52
+#define BRCMF_C_REASSOC                                53
+#define BRCMF_C_SET_ROAM_TRIGGER               55
+#define BRCMF_C_SET_ROAM_DELTA                 57
+#define BRCMF_C_GET_BCNPRD                     75
+#define BRCMF_C_SET_BCNPRD                     76
+#define BRCMF_C_GET_DTIMPRD                    77
+#define BRCMF_C_SET_DTIMPRD                    78
+#define BRCMF_C_SET_COUNTRY                    84
+#define BRCMF_C_GET_PM                         85
+#define BRCMF_C_SET_PM                         86
+#define BRCMF_C_GET_CURR_RATESET               114
+#define BRCMF_C_GET_AP                         117
+#define BRCMF_C_SET_AP                         118
+#define BRCMF_C_GET_RSSI                       127
+#define BRCMF_C_GET_WSEC                       133
+#define BRCMF_C_SET_WSEC                       134
+#define BRCMF_C_GET_PHY_NOISE                  135
+#define BRCMF_C_GET_BSS_INFO                   136
+#define BRCMF_C_GET_BANDLIST                   140
+#define BRCMF_C_SET_SCB_TIMEOUT                        158
+#define BRCMF_C_GET_PHYLIST                    180
+#define BRCMF_C_SET_SCAN_CHANNEL_TIME          185
+#define BRCMF_C_SET_SCAN_UNASSOC_TIME          187
+#define BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON  201
+#define BRCMF_C_GET_VALID_CHANNELS             217
+#define BRCMF_C_GET_KEY_PRIMARY                        235
+#define BRCMF_C_SET_KEY_PRIMARY                        236
+#define BRCMF_C_SET_SCAN_PASSIVE_TIME          258
+#define BRCMF_C_GET_VAR                                262
+#define BRCMF_C_SET_VAR                                263
+
 s32 brcmf_fil_cmd_data_set(struct brcmf_if *ifp, u32 cmd, void *data, u32 len);
 s32 brcmf_fil_cmd_data_get(struct brcmf_if *ifp, u32 cmd, void *data, u32 len);
 s32 brcmf_fil_cmd_int_set(struct brcmf_if *ifp, u32 cmd, u32 data);
index ecabb04f33c3059c603513511cfd2679d23d6bb0..af17a5bc8b83bdab2ee9d5a5ff2ec17490cb7603 100644 (file)
 #define BRCMF_ARP_OL_HOST_AUTO_REPLY   0x00000004
 #define BRCMF_ARP_OL_PEER_AUTO_REPLY   0x00000008
 
+#define        BRCMF_BSS_INFO_VERSION  109 /* curr ver of brcmf_bss_info_le struct */
+#define BRCMF_BSS_RSSI_ON_CHANNEL      0x0002
+
+#define BRCMF_STA_ASSOC                        0x10            /* Associated */
+
+/* size of brcmf_scan_params not including variable length array */
+#define BRCMF_SCAN_PARAMS_FIXED_SIZE   64
+
+/* masks for channel and ssid count */
+#define BRCMF_SCAN_PARAMS_COUNT_MASK   0x0000ffff
+#define BRCMF_SCAN_PARAMS_NSSID_SHIFT  16
+
+/* primary (ie tx) key */
+#define BRCMF_PRIMARY_KEY              (1 << 1)
+#define DOT11_BSSTYPE_ANY              2
+#define BRCMF_ESCAN_REQ_VERSION                1
+
+#define BRCMF_MAXRATES_IN_SET          16      /* max # of rates in rateset */
 
 enum brcmf_fil_p2p_if_types {
        BRCMF_FIL_P2P_IF_CLIENT,
@@ -90,4 +108,290 @@ enum brcmf_tdls_manual_ep_ops {
        BRCMF_TDLS_MANUAL_EP_DISCOVERY = 6
 };
 
+/* Pattern matching filter. Specifies an offset within received packets to
+ * start matching, the pattern to match, the size of the pattern, and a bitmask
+ * that indicates which bits within the pattern should be matched.
+ */
+struct brcmf_pkt_filter_pattern_le {
+       /*
+        * Offset within received packet to start pattern matching.
+        * Offset '0' is the first byte of the ethernet header.
+        */
+       __le32 offset;
+       /* Size of the pattern.  Bitmask must be the same size.*/
+       __le32 size_bytes;
+       /*
+        * Variable length mask and pattern data. mask starts at offset 0.
+        * Pattern immediately follows mask.
+        */
+       u8 mask_and_pattern[1];
+};
+
+/* IOVAR "pkt_filter_add" parameter. Used to install packet filters. */
+struct brcmf_pkt_filter_le {
+       __le32 id;              /* Unique filter id, specified by app. */
+       __le32 type;            /* Filter type (WL_PKT_FILTER_TYPE_xxx). */
+       __le32 negate_match;    /* Negate the result of filter matches */
+       union {                 /* Filter definitions */
+               struct brcmf_pkt_filter_pattern_le pattern; /* Filter pattern */
+       } u;
+};
+
+/* IOVAR "pkt_filter_enable" parameter. */
+struct brcmf_pkt_filter_enable_le {
+       __le32 id;              /* Unique filter id */
+       __le32 enable;          /* Enable/disable bool */
+};
+
+/* BSS info structure
+ * Applications MUST CHECK ie_offset field and length field to access IEs and
+ * next bss_info structure in a vector (in struct brcmf_scan_results)
+ */
+struct brcmf_bss_info_le {
+       __le32 version;         /* version field */
+       __le32 length;          /* byte length of data in this record,
+                                * starting at version and including IEs
+                                */
+       u8 BSSID[ETH_ALEN];
+       __le16 beacon_period;   /* units are Kusec */
+       __le16 capability;      /* Capability information */
+       u8 SSID_len;
+       u8 SSID[32];
+       struct {
+               __le32 count;   /* # rates in this set */
+               u8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */
+       } rateset;              /* supported rates */
+       __le16 chanspec;        /* chanspec for bss */
+       __le16 atim_window;     /* units are Kusec */
+       u8 dtim_period; /* DTIM period */
+       __le16 RSSI;            /* receive signal strength (in dBm) */
+       s8 phy_noise;           /* noise (in dBm) */
+
+       u8 n_cap;               /* BSS is 802.11N Capable */
+       /* 802.11N BSS Capabilities (based on HT_CAP_*): */
+       __le32 nbss_cap;
+       u8 ctl_ch;              /* 802.11N BSS control channel number */
+       __le32 reserved32[1];   /* Reserved for expansion of BSS properties */
+       u8 flags;               /* flags */
+       u8 reserved[3]; /* Reserved for expansion of BSS properties */
+       u8 basic_mcs[MCSSET_LEN];       /* 802.11N BSS required MCS set */
+
+       __le16 ie_offset;       /* offset at which IEs start, from beginning */
+       __le32 ie_length;       /* byte length of Information Elements */
+       __le16 SNR;             /* average SNR of during frame reception */
+       /* Add new fields here */
+       /* variable length Information Elements */
+};
+
+struct brcm_rateset_le {
+       /* # rates in this set */
+       __le32 count;
+       /* rates in 500kbps units w/hi bit set if basic */
+       u8 rates[BRCMF_MAXRATES_IN_SET];
+};
+
+struct brcmf_ssid {
+       u32 SSID_len;
+       unsigned char SSID[32];
+};
+
+struct brcmf_ssid_le {
+       __le32 SSID_len;
+       unsigned char SSID[32];
+};
+
+struct brcmf_scan_params_le {
+       struct brcmf_ssid_le ssid_le;   /* default: {0, ""} */
+       u8 bssid[ETH_ALEN];     /* default: bcast */
+       s8 bss_type;            /* default: any,
+                                * DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT
+                                */
+       u8 scan_type;   /* flags, 0 use default */
+       __le32 nprobes;   /* -1 use default, number of probes per channel */
+       __le32 active_time;     /* -1 use default, dwell time per channel for
+                                * active scanning
+                                */
+       __le32 passive_time;    /* -1 use default, dwell time per channel
+                                * for passive scanning
+                                */
+       __le32 home_time;       /* -1 use default, dwell time for the
+                                * home channel between channel scans
+                                */
+       __le32 channel_num;     /* count of channels and ssids that follow
+                                *
+                                * low half is count of channels in
+                                * channel_list, 0 means default (use all
+                                * available channels)
+                                *
+                                * high half is entries in struct brcmf_ssid
+                                * array that follows channel_list, aligned for
+                                * s32 (4 bytes) meaning an odd channel count
+                                * implies a 2-byte pad between end of
+                                * channel_list and first ssid
+                                *
+                                * if ssid count is zero, single ssid in the
+                                * fixed parameter portion is assumed, otherwise
+                                * ssid in the fixed portion is ignored
+                                */
+       __le16 channel_list[1]; /* list of chanspecs */
+};
+
+struct brcmf_scan_results {
+       u32 buflen;
+       u32 version;
+       u32 count;
+       struct brcmf_bss_info_le bss_info_le[];
+};
+
+struct brcmf_escan_params_le {
+       __le32 version;
+       __le16 action;
+       __le16 sync_id;
+       struct brcmf_scan_params_le params_le;
+};
+
+struct brcmf_escan_result_le {
+       __le32 buflen;
+       __le32 version;
+       __le16 sync_id;
+       __le16 bss_count;
+       struct brcmf_bss_info_le bss_info_le;
+};
+
+#define WL_ESCAN_RESULTS_FIXED_SIZE (sizeof(struct brcmf_escan_result_le) - \
+       sizeof(struct brcmf_bss_info_le))
+
+/* used for association with a specific BSSID and chanspec list */
+struct brcmf_assoc_params_le {
+       /* 00:00:00:00:00:00: broadcast scan */
+       u8 bssid[ETH_ALEN];
+       /* 0: all available channels, otherwise count of chanspecs in
+        * chanspec_list */
+       __le32 chanspec_num;
+       /* list of chanspecs */
+       __le16 chanspec_list[1];
+};
+
+/* used for join with or without a specific bssid and channel list */
+struct brcmf_join_params {
+       struct brcmf_ssid_le ssid_le;
+       struct brcmf_assoc_params_le params_le;
+};
+
+/* scan params for extended join */
+struct brcmf_join_scan_params_le {
+       u8 scan_type;           /* 0 use default, active or passive scan */
+       __le32 nprobes;         /* -1 use default, nr of probes per channel */
+       __le32 active_time;     /* -1 use default, dwell time per channel for
+                                * active scanning
+                                */
+       __le32 passive_time;    /* -1 use default, dwell time per channel
+                                * for passive scanning
+                                */
+       __le32 home_time;       /* -1 use default, dwell time for the home
+                                * channel between channel scans
+                                */
+};
+
+/* extended join params */
+struct brcmf_ext_join_params_le {
+       struct brcmf_ssid_le ssid_le;   /* {0, ""}: wildcard scan */
+       struct brcmf_join_scan_params_le scan_le;
+       struct brcmf_assoc_params_le assoc_le;
+};
+
+struct brcmf_wsec_key {
+       u32 index;              /* key index */
+       u32 len;                /* key length */
+       u8 data[WLAN_MAX_KEY_LEN];      /* key data */
+       u32 pad_1[18];
+       u32 algo;       /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */
+       u32 flags;      /* misc flags */
+       u32 pad_2[3];
+       u32 iv_initialized;     /* has IV been initialized already? */
+       u32 pad_3;
+       /* Rx IV */
+       struct {
+               u32 hi; /* upper 32 bits of IV */
+               u16 lo; /* lower 16 bits of IV */
+       } rxiv;
+       u32 pad_4[2];
+       u8 ea[ETH_ALEN];        /* per station */
+};
+
+/*
+ * dongle requires same struct as above but with fields in little endian order
+ */
+struct brcmf_wsec_key_le {
+       __le32 index;           /* key index */
+       __le32 len;             /* key length */
+       u8 data[WLAN_MAX_KEY_LEN];      /* key data */
+       __le32 pad_1[18];
+       __le32 algo;    /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */
+       __le32 flags;   /* misc flags */
+       __le32 pad_2[3];
+       __le32 iv_initialized;  /* has IV been initialized already? */
+       __le32 pad_3;
+       /* Rx IV */
+       struct {
+               __le32 hi;      /* upper 32 bits of IV */
+               __le16 lo;      /* lower 16 bits of IV */
+       } rxiv;
+       __le32 pad_4[2];
+       u8 ea[ETH_ALEN];        /* per station */
+};
+
+/* Used to get specific STA parameters */
+struct brcmf_scb_val_le {
+       __le32 val;
+       u8 ea[ETH_ALEN];
+};
+
+/* channel encoding */
+struct brcmf_channel_info_le {
+       __le32 hw_channel;
+       __le32 target_channel;
+       __le32 scan_channel;
+};
+
+struct brcmf_sta_info_le {
+       __le16  ver;            /* version of this struct */
+       __le16  len;            /* length in bytes of this structure */
+       __le16  cap;            /* sta's advertised capabilities */
+       __le32  flags;          /* flags defined below */
+       __le32  idle;           /* time since data pkt rx'd from sta */
+       u8      ea[ETH_ALEN];           /* Station address */
+       __le32  count;                  /* # rates in this set */
+       u8      rates[BRCMF_MAXRATES_IN_SET];   /* rates in 500kbps units */
+                                               /* w/hi bit set if basic */
+       __le32  in;             /* seconds elapsed since associated */
+       __le32  listen_interval_inms; /* Min Listen interval in ms for STA */
+       __le32  tx_pkts;        /* # of packets transmitted */
+       __le32  tx_failures;    /* # of packets failed */
+       __le32  rx_ucast_pkts;  /* # of unicast packets received */
+       __le32  rx_mcast_pkts;  /* # of multicast packets received */
+       __le32  tx_rate;        /* Rate of last successful tx frame */
+       __le32  rx_rate;        /* Rate of last successful rx frame */
+       __le32  rx_decrypt_succeeds;    /* # of packet decrypted successfully */
+       __le32  rx_decrypt_failures;    /* # of packet decrypted failed */
+};
+
+struct brcmf_chanspec_list {
+       __le32  count;          /* # of entries */
+       __le32  element[1];     /* variable length uint32 list */
+};
+
+/*
+ * WLC_E_PROBRESP_MSG
+ * WLC_E_P2P_PROBREQ_MSG
+ * WLC_E_ACTION_FRAME_RX
+ */
+struct brcmf_rx_mgmt_data {
+       __be16  version;
+       __be16  chanspec;
+       __be32  rssi;
+       __be32  mactime;
+       __be32  rate;
+};
+
 #endif /* FWIL_TYPES_H_ */
index d0cd0bf95c5af4393719a981d008049cde67756d..e9bdfdb95d8f06915fc734dd27053a3e092c046e 100644 (file)
@@ -27,7 +27,6 @@
 #include <brcmu_utils.h>
 #include <brcmu_wifi.h>
 #include "dhd.h"
-#include "dhd_proto.h"
 #include "dhd_dbg.h"
 #include "dhd_bus.h"
 #include "fwil.h"
@@ -36,6 +35,7 @@
 #include "fwsignal.h"
 #include "p2p.h"
 #include "wl_cfg80211.h"
+#include "proto.h"
 
 /**
  * DOC: Firmware Signalling
@@ -105,6 +105,7 @@ static struct {
 };
 #undef BRCMF_FWS_TLV_DEF
 
+
 static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id)
 {
        int i;
@@ -122,6 +123,12 @@ static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id)
 }
 #endif /* DEBUG */
 
+/*
+ * The PKTTAG tlv has additional bytes when firmware-signalling
+ * mode has REUSESEQ flag set.
+ */
+#define BRCMF_FWS_TYPE_SEQ_LEN                         2
+
 /*
  * flags used to enable tlv signalling from firmware.
  */
@@ -147,8 +154,15 @@ static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id)
 #define BRCMF_FWS_HTOD_FLAG_PKTFROMHOST                        0x01
 #define BRCMF_FWS_HTOD_FLAG_PKT_REQUESTED              0x02
 
-#define BRCMF_FWS_RET_OK_NOSCHEDULE    0
-#define BRCMF_FWS_RET_OK_SCHEDULE      1
+#define BRCMF_FWS_RET_OK_NOSCHEDULE                    0
+#define BRCMF_FWS_RET_OK_SCHEDULE                      1
+
+#define BRCMF_FWS_MODE_REUSESEQ_SHIFT                  3       /* seq reuse */
+#define BRCMF_FWS_MODE_SET_REUSESEQ(x, val)    ((x) = \
+               ((x) & ~(1 << BRCMF_FWS_MODE_REUSESEQ_SHIFT)) | \
+               (((val) & 1) << BRCMF_FWS_MODE_REUSESEQ_SHIFT))
+#define BRCMF_FWS_MODE_GET_REUSESEQ(x) \
+               (((x) >> BRCMF_FWS_MODE_REUSESEQ_SHIFT) & 1)
 
 /**
  * enum brcmf_fws_skb_state - indicates processing state of skb.
@@ -171,6 +185,7 @@ enum brcmf_fws_skb_state {
  * @bus_flags: 2 bytes reserved for bus specific parameters
  * @if_flags: holds interface index and packet related flags.
  * @htod: host to device packet identifier (used in PKTTAG tlv).
+ * @htod_seq: this 16-bit is original seq number for every suppress packet.
  * @state: transmit state of the packet.
  * @mac: descriptor related to destination for this packet.
  *
@@ -181,6 +196,7 @@ struct brcmf_skbuff_cb {
        u16 bus_flags;
        u16 if_flags;
        u32 htod;
+       u16 htod_seq;
        enum brcmf_fws_skb_state state;
        struct brcmf_fws_mac_descriptor *mac;
 };
@@ -257,6 +273,22 @@ struct brcmf_skbuff_cb {
                        BRCMF_SKB_HTOD_TAG_ ## field ## _MASK, \
                        BRCMF_SKB_HTOD_TAG_ ## field ## _SHIFT)
 
+#define BRCMF_SKB_HTOD_SEQ_FROMFW_MASK                 0x2000
+#define BRCMF_SKB_HTOD_SEQ_FROMFW_SHIFT                        13
+#define BRCMF_SKB_HTOD_SEQ_FROMDRV_MASK                        0x1000
+#define BRCMF_SKB_HTOD_SEQ_FROMDRV_SHIFT               12
+#define BRCMF_SKB_HTOD_SEQ_NR_MASK                     0x0fff
+#define BRCMF_SKB_HTOD_SEQ_NR_SHIFT                    0
+
+#define brcmf_skb_htod_seq_set_field(skb, field, value) \
+       brcmu_maskset16(&(brcmf_skbcb(skb)->htod_seq), \
+                       BRCMF_SKB_HTOD_SEQ_ ## field ## _MASK, \
+                       BRCMF_SKB_HTOD_SEQ_ ## field ## _SHIFT, (value))
+#define brcmf_skb_htod_seq_get_field(skb, field) \
+       brcmu_maskget16(brcmf_skbcb(skb)->htod_seq, \
+                       BRCMF_SKB_HTOD_SEQ_ ## field ## _MASK, \
+                       BRCMF_SKB_HTOD_SEQ_ ## field ## _SHIFT)
+
 #define BRCMF_FWS_TXSTAT_GENERATION_MASK       0x80000000
 #define BRCMF_FWS_TXSTAT_GENERATION_SHIFT      31
 #define BRCMF_FWS_TXSTAT_FLAGS_MASK            0x78000000
@@ -265,8 +297,8 @@ struct brcmf_skbuff_cb {
 #define BRCMF_FWS_TXSTAT_FIFO_SHIFT            24
 #define BRCMF_FWS_TXSTAT_HSLOT_MASK            0x00FFFF00
 #define BRCMF_FWS_TXSTAT_HSLOT_SHIFT           8
-#define BRCMF_FWS_TXSTAT_PKTID_MASK            0x00FFFFFF
-#define BRCMF_FWS_TXSTAT_PKTID_SHIFT           0
+#define BRCMF_FWS_TXSTAT_FREERUN_MASK          0x000000FF
+#define BRCMF_FWS_TXSTAT_FREERUN_SHIFT         0
 
 #define brcmf_txstatus_get_field(txs, field) \
        brcmu_maskget32(txs, BRCMF_FWS_TXSTAT_ ## field ## _MASK, \
@@ -443,6 +475,7 @@ struct brcmf_fws_info {
        unsigned long borrow_defer_timestamp;
        bool bus_flow_blocked;
        bool creditmap_received;
+       u8 mode;
 };
 
 /*
@@ -812,13 +845,16 @@ static int brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb)
        u16 data_offset = 0;
        u8 fillers;
        __le32 pkttag = cpu_to_le32(brcmf_skbcb(skb)->htod);
+       __le16 pktseq = cpu_to_le16(brcmf_skbcb(skb)->htod_seq);
 
-       brcmf_dbg(TRACE, "enter: %s, idx=%d pkttag=0x%08X, hslot=%d\n",
+       brcmf_dbg(TRACE, "enter: %s, idx=%d hslot=%d htod %X seq %X\n",
                  entry->name, brcmf_skb_if_flags_get_field(skb, INDEX),
-                 le32_to_cpu(pkttag), (le32_to_cpu(pkttag) >> 8) & 0xffff);
+                 (le32_to_cpu(pkttag) >> 8) & 0xffff,
+                 brcmf_skbcb(skb)->htod, brcmf_skbcb(skb)->htod_seq);
        if (entry->send_tim_signal)
                data_offset += 2 + BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN;
-
+       if (BRCMF_FWS_MODE_GET_REUSESEQ(fws->mode))
+               data_offset += BRCMF_FWS_TYPE_SEQ_LEN;
        /* +2 is for Type[1] and Len[1] in TLV, plus TIM signal */
        data_offset += 2 + BRCMF_FWS_TYPE_PKTTAG_LEN;
        fillers = round_up(data_offset, 4) - data_offset;
@@ -830,7 +866,12 @@ static int brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb)
        wlh[0] = BRCMF_FWS_TYPE_PKTTAG;
        wlh[1] = BRCMF_FWS_TYPE_PKTTAG_LEN;
        memcpy(&wlh[2], &pkttag, sizeof(pkttag));
-       wlh += BRCMF_FWS_TYPE_PKTTAG_LEN + 2;
+       if (BRCMF_FWS_MODE_GET_REUSESEQ(fws->mode)) {
+               wlh[1] += BRCMF_FWS_TYPE_SEQ_LEN;
+               memcpy(&wlh[2 + BRCMF_FWS_TYPE_PKTTAG_LEN], &pktseq,
+                      sizeof(pktseq));
+       }
+       wlh += wlh[1] + 2;
 
        if (entry->send_tim_signal) {
                entry->send_tim_signal = 0;
@@ -875,6 +916,7 @@ static bool brcmf_fws_tim_update(struct brcmf_fws_info *fws,
                /* create a dummy packet and sent that. The traffic          */
                /* bitmap info will automatically be attached to that packet */
                len = BRCMF_FWS_TYPE_PKTTAG_LEN + 2 +
+                     BRCMF_FWS_TYPE_SEQ_LEN +
                      BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN + 2 +
                      4 + fws->drvr->hdrlen;
                skb = brcmu_pkt_buf_get_skb(len);
@@ -884,6 +926,8 @@ static bool brcmf_fws_tim_update(struct brcmf_fws_info *fws,
                skcb = brcmf_skbcb(skb);
                skcb->mac = entry;
                skcb->state = BRCMF_FWS_SKBSTATE_TIM;
+               skcb->htod = 0;
+               skcb->htod_seq = 0;
                bus = fws->drvr->bus_if;
                err = brcmf_fws_hdrpush(fws, skb);
                if (err == 0) {
@@ -1172,8 +1216,13 @@ static int brcmf_fws_enq(struct brcmf_fws_info *fws,
 {
        int prec = 2 * fifo;
        u32 *qfull_stat = &fws->stats.delayq_full_error;
-
        struct brcmf_fws_mac_descriptor *entry;
+       struct pktq *pq;
+       struct sk_buff_head *queue;
+       struct sk_buff *p_head;
+       struct sk_buff *p_tail;
+       u32 fr_new;
+       u32 fr_compare;
 
        entry = brcmf_skbcb(p)->mac;
        if (entry == NULL) {
@@ -1185,9 +1234,55 @@ static int brcmf_fws_enq(struct brcmf_fws_info *fws,
        if (state == BRCMF_FWS_SKBSTATE_SUPPRESSED) {
                prec += 1;
                qfull_stat = &fws->stats.supprq_full_error;
-       }
 
-       if (brcmu_pktq_penq(&entry->psq, prec, p) == NULL) {
+               /* Fix out of order delivery of frames. Dont assume frame    */
+               /* can be inserted at the end, but look for correct position */
+               pq = &entry->psq;
+               if (pktq_full(pq) || pktq_pfull(pq, prec)) {
+                       *qfull_stat += 1;
+                       return -ENFILE;
+               }
+               queue = &pq->q[prec].skblist;
+
+               p_head = skb_peek(queue);
+               p_tail = skb_peek_tail(queue);
+               fr_new = brcmf_skb_htod_tag_get_field(p, FREERUN);
+
+               while (p_head != p_tail) {
+                       fr_compare = brcmf_skb_htod_tag_get_field(p_tail,
+                                                                 FREERUN);
+                       /* be sure to handle wrap of 256 */
+                       if (((fr_new > fr_compare) &&
+                            ((fr_new - fr_compare) < 128)) ||
+                           ((fr_new < fr_compare) &&
+                            ((fr_compare - fr_new) > 128)))
+                               break;
+                       p_tail = skb_queue_prev(queue, p_tail);
+               }
+               /* Position found. Determine what to do */
+               if (p_tail == NULL) {
+                       /* empty list */
+                       __skb_queue_tail(queue, p);
+               } else {
+                       fr_compare = brcmf_skb_htod_tag_get_field(p_tail,
+                                                                 FREERUN);
+                       if (((fr_new > fr_compare) &&
+                            ((fr_new - fr_compare) < 128)) ||
+                           ((fr_new < fr_compare) &&
+                            ((fr_compare - fr_new) > 128))) {
+                               /* After tail */
+                               __skb_queue_after(queue, p_tail, p);
+                       } else {
+                               /* Before tail */
+                               __skb_insert(p, p_tail->prev, p_tail, queue);
+                       }
+               }
+
+               /* Complete the counters and statistics */
+               pq->len++;
+               if (pq->hi_prec < prec)
+                       pq->hi_prec = (u8) prec;
+       } else if (brcmu_pktq_penq(&entry->psq, prec, p) == NULL) {
                *qfull_stat += 1;
                return -ENFILE;
        }
@@ -1277,7 +1372,8 @@ done:
 }
 
 static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo,
-                                        struct sk_buff *skb, u32 genbit)
+                                        struct sk_buff *skb, u32 genbit,
+                                        u16 seq)
 {
        struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac;
        u32 hslot;
@@ -1298,6 +1394,14 @@ static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo,
 
        ret = brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb);
        if (ret == 0)
+               brcmf_skb_htod_tag_set_field(skb, GENERATION, genbit);
+               brcmf_skbcb(skb)->htod_seq = seq;
+               if (brcmf_skb_htod_seq_get_field(skb, FROMFW)) {
+                       brcmf_skb_htod_seq_set_field(skb, FROMDRV, 1);
+                       brcmf_skb_htod_seq_set_field(skb, FROMFW, 0);
+               } else {
+                       brcmf_skb_htod_seq_set_field(skb, FROMDRV, 0);
+               }
                ret = brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_SUPPRESSED, fifo,
                                    skb);
        if (ret != 0) {
@@ -1317,7 +1421,7 @@ static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo,
 
 static int
 brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot,
-                          u32 genbit)
+                     u32 genbit, u16 seq)
 {
        u32 fifo;
        int ret;
@@ -1360,8 +1464,8 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot,
        if (entry->suppressed && entry->suppr_transit_count)
                entry->suppr_transit_count--;
 
-       brcmf_dbg(DATA, "%s flags %X htod %X\n", entry->name, skcb->if_flags,
-                 skcb->htod);
+       brcmf_dbg(DATA, "%s flags %d htod %X seq %X\n", entry->name, flags,
+                 skcb->htod, seq);
 
        /* pick up the implicit credit from this packet */
        fifo = brcmf_skb_htod_tag_get_field(skb, FIFO);
@@ -1374,7 +1478,8 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot,
        brcmf_fws_macdesc_return_req_credit(skb);
 
        if (!remove_from_hanger)
-               ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, genbit);
+               ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, genbit,
+                                                   seq);
 
        if (remove_from_hanger || ret)
                brcmf_txfinalize(fws->drvr, skb, true);
@@ -1406,10 +1511,12 @@ static int brcmf_fws_fifocreditback_indicate(struct brcmf_fws_info *fws,
 static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data)
 {
        __le32 status_le;
+       __le16 seq_le;
        u32 status;
        u32 hslot;
        u32 genbit;
        u8 flags;
+       u16 seq;
 
        fws->stats.txs_indicate++;
        memcpy(&status_le, data, sizeof(status_le));
@@ -1417,9 +1524,16 @@ static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data)
        flags = brcmf_txstatus_get_field(status, FLAGS);
        hslot = brcmf_txstatus_get_field(status, HSLOT);
        genbit = brcmf_txstatus_get_field(status, GENERATION);
+       if (BRCMF_FWS_MODE_GET_REUSESEQ(fws->mode)) {
+               memcpy(&seq_le, &data[BRCMF_FWS_TYPE_PKTTAG_LEN],
+                      sizeof(seq_le));
+               seq = le16_to_cpu(seq_le);
+       } else {
+               seq = 0;
+       }
 
        brcmf_fws_lock(fws);
-       brcmf_fws_txs_process(fws, flags, hslot, genbit);
+       brcmf_fws_txs_process(fws, flags, hslot, genbit, seq);
        brcmf_fws_unlock(fws);
        return BRCMF_FWS_RET_OK_NOSCHEDULE;
 }
@@ -1610,8 +1724,8 @@ static void brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo,
        struct brcmf_fws_mac_descriptor *entry = skcb->mac;
        u8 flags;
 
-       brcmf_skb_if_flags_set_field(p, TRANSMIT, 1);
-       brcmf_skb_htod_tag_set_field(p, GENERATION, entry->generation);
+       if (skcb->state != BRCMF_FWS_SKBSTATE_SUPPRESSED)
+               brcmf_skb_htod_tag_set_field(p, GENERATION, entry->generation);
        flags = BRCMF_FWS_HTOD_FLAG_PKTFROMHOST;
        if (brcmf_skb_if_flags_get_field(p, REQUESTED)) {
                /*
@@ -1652,7 +1766,7 @@ static void brcmf_fws_rollback_toq(struct brcmf_fws_info *fws,
                fws->stats.rollback_failed++;
                hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
                brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED,
-                                     hslot, 0);
+                                     hslot, 0, 0);
        } else {
                fws->stats.rollback_success++;
                brcmf_fws_return_credits(fws, fifo, 1);
@@ -1732,6 +1846,8 @@ static int brcmf_fws_assign_htod(struct brcmf_fws_info *fws, struct sk_buff *p,
        struct brcmf_skbuff_cb *skcb = brcmf_skbcb(p);
        int rc, hslot;
 
+       skcb->htod = 0;
+       skcb->htod_seq = 0;
        hslot = brcmf_fws_hanger_get_free_slot(&fws->hanger);
        brcmf_skb_htod_tag_set_field(p, HSLOT, hslot);
        brcmf_skb_htod_tag_set_field(p, FREERUN, skcb->mac->seq[fifo]);
@@ -1908,6 +2024,7 @@ int brcmf_fws_init(struct brcmf_pub *drvr)
        struct brcmf_fws_info *fws;
        u32 tlv = BRCMF_FWS_FLAGS_RSSI_SIGNALS;
        int rc;
+       u32 mode;
 
        drvr->fws = kzalloc(sizeof(*(drvr->fws)), GFP_KERNEL);
        if (!drvr->fws) {
@@ -1966,6 +2083,18 @@ int brcmf_fws_init(struct brcmf_pub *drvr)
        if (brcmf_fil_iovar_int_set(drvr->iflist[0], "ampdu_hostreorder", 1))
                brcmf_dbg(INFO, "enabling AMPDU host-reorder failed\n");
 
+       /* Enable seq number reuse, if supported */
+       if (brcmf_fil_iovar_int_get(drvr->iflist[0], "wlfc_mode", &mode) == 0) {
+               if (BRCMF_FWS_MODE_GET_REUSESEQ(mode)) {
+                       mode = 0;
+                       BRCMF_FWS_MODE_SET_REUSESEQ(mode, 1);
+                       if (brcmf_fil_iovar_int_set(drvr->iflist[0],
+                                                   "wlfc_mode", mode) == 0) {
+                               BRCMF_FWS_MODE_SET_REUSESEQ(fws->mode, 1);
+                       }
+               }
+       }
+
        brcmf_fws_hanger_init(&fws->hanger);
        brcmf_fws_macdesc_init(&fws->desc.other, NULL, 0);
        brcmf_fws_macdesc_set_name(fws, &fws->desc.other);
@@ -2022,7 +2151,7 @@ void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb)
        }
        brcmf_fws_lock(fws);
        hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
-       brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED, hslot, 0);
+       brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED, hslot, 0, 0);
        brcmf_fws_unlock(fws);
 }
 
index 4a2293041821ff708c6cefef86ed21406f18266c..d3180360725925c40f6e59bf09bdfb28e18a4300 100644 (file)
@@ -812,7 +812,7 @@ static s32 brcmf_p2p_run_escan(struct brcmf_cfg80211_info *cfg,
                        struct ieee80211_channel *chan = request->channels[i];
 
                        if (chan->flags & (IEEE80211_CHAN_RADAR |
-                                          IEEE80211_CHAN_PASSIVE_SCAN))
+                                          IEEE80211_CHAN_NO_IR))
                                continue;
 
                        chanspecs[i] = channel_to_chanspec(&p2p->cfg->d11inf,
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/proto.c b/drivers/net/wireless/brcm80211/brcmfmac/proto.c
new file mode 100644 (file)
index 0000000..87eb2bd
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2013 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+ #include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/netdevice.h>
+
+#include <brcmu_wifi.h>
+#include "dhd.h"
+#include "dhd_dbg.h"
+#include "proto.h"
+#include "bcdc.h"
+
+
+int brcmf_proto_attach(struct brcmf_pub *drvr)
+{
+       struct brcmf_proto *proto;
+
+       proto = kzalloc(sizeof(*proto), GFP_ATOMIC);
+       if (!proto)
+               goto fail;
+
+       drvr->proto = proto;
+       /* BCDC protocol is only protocol supported for the moment */
+       if (brcmf_proto_bcdc_attach(drvr))
+               goto fail;
+
+       if ((proto->hdrpush == NULL) || (proto->hdrpull == NULL) ||
+           (proto->query_dcmd == NULL) || (proto->set_dcmd == NULL)) {
+               brcmf_err("Not all proto handlers have been installed\n");
+               goto fail;
+       }
+       return 0;
+
+fail:
+       kfree(proto);
+       drvr->proto = NULL;
+       return -ENOMEM;
+}
+
+void brcmf_proto_detach(struct brcmf_pub *drvr)
+{
+       if (drvr->proto) {
+               brcmf_proto_bcdc_detach(drvr);
+               kfree(drvr->proto);
+               drvr->proto = NULL;
+       }
+}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/proto.h b/drivers/net/wireless/brcm80211/brcmfmac/proto.h
new file mode 100644 (file)
index 0000000..8de1b3b
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2013 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef BRCMFMAC_PROTO_H
+#define BRCMFMAC_PROTO_H
+
+struct brcmf_proto {
+       void (*hdrpush)(struct brcmf_pub *drvr, int ifidx, u8 offset,
+                       struct sk_buff *skb);
+       int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx,
+                      struct sk_buff *skb);
+       int (*query_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd,
+                         void *buf, uint len);
+       int (*set_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf,
+                       uint len);
+       void *pd;
+};
+
+
+int brcmf_proto_attach(struct brcmf_pub *drvr);
+void brcmf_proto_detach(struct brcmf_pub *drvr);
+
+static inline void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx,
+                                      u8 offset, struct sk_buff *skb)
+{
+       drvr->proto->hdrpush(drvr, ifidx, offset, skb);
+}
+static inline int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws,
+                                     u8 *ifidx, struct sk_buff *skb)
+{
+       return drvr->proto->hdrpull(drvr, do_fws, ifidx, skb);
+}
+static inline int brcmf_proto_query_dcmd(struct brcmf_pub *drvr, int ifidx,
+                                        uint cmd, void *buf, uint len)
+{
+       return drvr->proto->query_dcmd(drvr, ifidx, cmd, buf, len);
+}
+static inline int brcmf_proto_set_dcmd(struct brcmf_pub *drvr, int ifidx,
+                                      uint cmd, void *buf, uint len)
+{
+       return drvr->proto->set_dcmd(drvr, ifidx, cmd, buf, len);
+}
+
+
+#endif /* BRCMFMAC_PROTO_H */
index 3c67529b90743123691d08aa7ed4d3fdb4a45c6d..4d7d51f9571637de5f9a0a7423f68336af6d2a41 100644 (file)
@@ -89,7 +89,7 @@ TRACE_EVENT(brcmf_hexdump,
        TP_printk("hexdump [addr=%lx, length=%lu]", __entry->addr, __entry->len)
 );
 
-TRACE_EVENT(brcmf_bdchdr,
+TRACE_EVENT(brcmf_bcdchdr,
        TP_PROTO(void *data),
        TP_ARGS(data),
        TP_STRUCT__entry(
@@ -107,24 +107,35 @@ TRACE_EVENT(brcmf_bdchdr,
                memcpy(__get_dynamic_array(signal),
                       (u8 *)data + 4, __entry->siglen);
        ),
-       TP_printk("bdc: prio=%d siglen=%d", __entry->prio, __entry->siglen)
+       TP_printk("bcdc: prio=%d siglen=%d", __entry->prio, __entry->siglen)
 );
 
+#ifndef SDPCM_RX
+#define SDPCM_RX       0
+#endif
+#ifndef SDPCM_TX
+#define SDPCM_TX       1
+#endif
+#ifndef SDPCM_GLOM
+#define SDPCM_GLOM     2
+#endif
+
 TRACE_EVENT(brcmf_sdpcm_hdr,
-       TP_PROTO(bool tx, void *data),
-       TP_ARGS(tx, data),
+       TP_PROTO(u8 dir, void *data),
+       TP_ARGS(dir, data),
        TP_STRUCT__entry(
-               __field(u8, tx)
+               __field(u8, dir)
                __field(u16, len)
-               __array(u8, hdr, 12)
+               __dynamic_array(u8, hdr, dir == SDPCM_GLOM ? 20 : 12)
        ),
        TP_fast_assign(
-               memcpy(__entry->hdr, data, 12);
-               __entry->len = __entry->hdr[0] | (__entry->hdr[1] << 8);
-               __entry->tx = tx ? 1 : 0;
+               memcpy(__get_dynamic_array(hdr), data, dir == SDPCM_GLOM ? 20 : 12);
+               __entry->len = *(u8 *)data | (*((u8 *)data + 1) << 8);
+               __entry->dir = dir;
        ),
-       TP_printk("sdpcm: %s len %u, seq %d", __entry->tx ? "TX" : "RX",
-                 __entry->len, __entry->hdr[4])
+       TP_printk("sdpcm: %s len %u, seq %d",
+                 __entry->dir == SDPCM_RX ? "RX" : "TX",
+                 __entry->len, ((u8 *)__get_dynamic_array(hdr))[4])
 );
 
 #ifdef CONFIG_BRCM_TRACING
index 422f44c631756b2332dc10d4c1fb24c8172343ff..51c4de054b15e9c89c154acb93e3fff79e0c4ffa 100644 (file)
@@ -1255,7 +1255,7 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo)
        bus->chiprev = bus_pub->chiprev;
 
        /* Attach to the common driver interface */
-       ret = brcmf_attach(0, dev);
+       ret = brcmf_attach(dev);
        if (ret) {
                brcmf_err("brcmf_attach failed\n");
                goto fail;
@@ -1454,7 +1454,7 @@ static int brcmf_usb_resume(struct usb_interface *intf)
        struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev);
 
        brcmf_dbg(USB, "Enter\n");
-       if (!brcmf_attach(0, devinfo->dev))
+       if (!brcmf_attach(devinfo->dev))
                return brcmf_bus_start(&usb->dev);
 
        return 0;
index 571f013cebbb0d0a80f32e2351975b659d7d53d1..3966fe0fcfd971418fb3ca22bfc9fcaddf7afaf7 100644 (file)
@@ -202,9 +202,9 @@ static struct ieee80211_supported_band __wl_band_5ghz_a = {
 
 /* This is to override regulatory domains defined in cfg80211 module (reg.c)
  * By default world regulatory domain defined in reg.c puts the flags
- * NL80211_RRF_PASSIVE_SCAN and NL80211_RRF_NO_IBSS for 5GHz channels (for
- * 36..48 and 149..165). With respect to these flags, wpa_supplicant doesn't
- * start p2p operations on 5GHz channels. All the changes in world regulatory
+ * NL80211_RRF_NO_IR for 5GHz channels (for * 36..48 and 149..165).
+ * With respect to these flags, wpa_supplicant doesn't * start p2p
+ * operations on 5GHz channels. All the changes in world regulatory
  * domain are to be done here.
  */
 static const struct ieee80211_regdomain brcmf_regdom = {
@@ -2556,8 +2556,8 @@ brcmf_compare_update_same_bss(struct brcmf_cfg80211_info *cfg,
                ch_bss.band == ch_bss_info_le.band &&
                bss_info_le->SSID_len == bss->SSID_len &&
                !memcmp(bss_info_le->SSID, bss->SSID, bss_info_le->SSID_len)) {
-               if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) ==
-                       (bss_info_le->flags & WLC_BSS_RSSI_ON_CHANNEL)) {
+               if ((bss->flags & BRCMF_BSS_RSSI_ON_CHANNEL) ==
+                       (bss_info_le->flags & BRCMF_BSS_RSSI_ON_CHANNEL)) {
                        s16 bss_rssi = le16_to_cpu(bss->RSSI);
                        s16 bss_info_rssi = le16_to_cpu(bss_info_le->RSSI);
 
@@ -2566,13 +2566,13 @@ brcmf_compare_update_same_bss(struct brcmf_cfg80211_info *cfg,
                        */
                        if (bss_info_rssi > bss_rssi)
                                bss->RSSI = bss_info_le->RSSI;
-               } else if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) &&
-                       (bss_info_le->flags & WLC_BSS_RSSI_ON_CHANNEL) == 0) {
+               } else if ((bss->flags & BRCMF_BSS_RSSI_ON_CHANNEL) &&
+                       (bss_info_le->flags & BRCMF_BSS_RSSI_ON_CHANNEL) == 0) {
                        /* preserve the on-channel rssi measurement
                        * if the new measurement is off channel
                        */
                        bss->RSSI = bss_info_le->RSSI;
-                       bss->flags |= WLC_BSS_RSSI_ON_CHANNEL;
+                       bss->flags |= BRCMF_BSS_RSSI_ON_CHANNEL;
                }
                return 1;
        }
@@ -3973,11 +3973,12 @@ brcmf_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
 
 static int
 brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
-                      struct ieee80211_channel *chan, bool offchan,
-                      unsigned int wait, const u8 *buf, size_t len,
-                      bool no_cck, bool dont_wait_for_ack, u64 *cookie)
+                      struct cfg80211_mgmt_tx_params *params, u64 *cookie)
 {
        struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+       struct ieee80211_channel *chan = params->chan;
+       const u8 *buf = params->buf;
+       size_t len = params->len;
        const struct ieee80211_mgmt *mgmt;
        struct brcmf_cfg80211_vif *vif;
        s32 err = 0;
@@ -4341,7 +4342,7 @@ static struct wiphy *brcmf_setup_wiphy(struct device *phydev)
        wiphy->max_remain_on_channel_duration = 5000;
        brcmf_wiphy_pno_params(wiphy);
        brcmf_dbg(INFO, "Registering custom regulatory\n");
-       wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
+       wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
        wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom);
        err = wiphy_register(wiphy);
        if (err < 0) {
@@ -5197,10 +5198,10 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, u32 bw_cap)
                                        if (channel & WL_CHAN_RADAR)
                                                band_chan_arr[index].flags |=
                                                        (IEEE80211_CHAN_RADAR |
-                                                       IEEE80211_CHAN_NO_IBSS);
+                                                       IEEE80211_CHAN_NO_IR);
                                        if (channel & WL_CHAN_PASSIVE)
                                                band_chan_arr[index].flags |=
-                                                   IEEE80211_CHAN_PASSIVE_SCAN;
+                                                   IEEE80211_CHAN_NO_IR;
                                }
                        }
                        if (!update)
index cc87926f505562335a02c605541c739725cf1a03..635ae034c7e5d8d149cec933b55d7405678fa6ba 100644 (file)
 
 #define BRCM_2GHZ_2412_2462    REG_RULE(2412-10, 2462+10, 40, 0, 19, 0)
 #define BRCM_2GHZ_2467_2472    REG_RULE(2467-10, 2472+10, 20, 0, 19, \
-                                        NL80211_RRF_PASSIVE_SCAN | \
-                                        NL80211_RRF_NO_IBSS)
+                                        NL80211_RRF_NO_IR)
 
 #define BRCM_5GHZ_5180_5240    REG_RULE(5180-10, 5240+10, 40, 0, 21, \
-                                        NL80211_RRF_PASSIVE_SCAN | \
-                                        NL80211_RRF_NO_IBSS)
+                                        NL80211_RRF_NO_IR)
 #define BRCM_5GHZ_5260_5320    REG_RULE(5260-10, 5320+10, 40, 0, 21, \
-                                        NL80211_RRF_PASSIVE_SCAN | \
                                         NL80211_RRF_DFS | \
-                                        NL80211_RRF_NO_IBSS)
+                                        NL80211_RRF_NO_IR)
 #define BRCM_5GHZ_5500_5700    REG_RULE(5500-10, 5700+10, 40, 0, 21, \
-                                        NL80211_RRF_PASSIVE_SCAN | \
                                         NL80211_RRF_DFS | \
-                                        NL80211_RRF_NO_IBSS)
+                                        NL80211_RRF_NO_IR)
 #define BRCM_5GHZ_5745_5825    REG_RULE(5745-10, 5825+10, 40, 0, 21, \
-                                        NL80211_RRF_PASSIVE_SCAN | \
-                                        NL80211_RRF_NO_IBSS)
+                                        NL80211_RRF_NO_IR)
 
 static const struct ieee80211_regdomain brcms_regdom_x2 = {
        .n_reg_rules = 6,
@@ -395,7 +390,7 @@ brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec,
                brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false);
 
        brcms_b_set_chanspec(wlc->hw, chanspec,
-                             !!(ch->flags & IEEE80211_CHAN_PASSIVE_SCAN),
+                             !!(ch->flags & IEEE80211_CHAN_NO_IR),
                              &txpwr);
 }
 
@@ -657,8 +652,8 @@ static void brcms_reg_apply_radar_flags(struct wiphy *wiphy)
                 */
                if (!(ch->flags & IEEE80211_CHAN_DISABLED))
                        ch->flags |= IEEE80211_CHAN_RADAR |
-                                    IEEE80211_CHAN_NO_IBSS |
-                                    IEEE80211_CHAN_PASSIVE_SCAN;
+                                    IEEE80211_CHAN_NO_IR |
+                                    IEEE80211_CHAN_NO_IR;
        }
 }
 
@@ -684,18 +679,15 @@ brcms_reg_apply_beaconing_flags(struct wiphy *wiphy,
                                continue;
 
                        if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) {
-                               rule = freq_reg_info(wiphy, ch->center_freq);
+                               rule = freq_reg_info(wiphy,
+                                                    MHZ_TO_KHZ(ch->center_freq));
                                if (IS_ERR(rule))
                                        continue;
 
-                               if (!(rule->flags & NL80211_RRF_NO_IBSS))
-                                       ch->flags &= ~IEEE80211_CHAN_NO_IBSS;
-                               if (!(rule->flags & NL80211_RRF_PASSIVE_SCAN))
-                                       ch->flags &=
-                                               ~IEEE80211_CHAN_PASSIVE_SCAN;
+                               if (!(rule->flags & NL80211_RRF_NO_IR))
+                                       ch->flags &= ~IEEE80211_CHAN_NO_IR;
                        } else if (ch->beacon_found) {
-                               ch->flags &= ~(IEEE80211_CHAN_NO_IBSS |
-                                              IEEE80211_CHAN_PASSIVE_SCAN);
+                               ch->flags &= ~IEEE80211_CHAN_NO_IR;
                        }
                }
        }
@@ -775,8 +767,8 @@ void brcms_c_regd_init(struct brcms_c_info *wlc)
        }
 
        wlc->wiphy->reg_notifier = brcms_reg_notifier;
-       wlc->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
-                            WIPHY_FLAG_STRICT_REGULATORY;
+       wlc->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG |
+                                       REGULATORY_STRICT_REG;
        wiphy_apply_custom_regulatory(wlc->wiphy, regd->regdomain);
        brcms_reg_apply_beaconing_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER);
 }
index edc5d105ff980e40e1ad2221a4c7686f87b0cea1..e71ce8c842a22f3a337cf1bbf4a08dc0e3e52b70 100644 (file)
@@ -125,13 +125,13 @@ static struct ieee80211_channel brcms_2ghz_chantable[] = {
        CHAN2GHZ(10, 2457, IEEE80211_CHAN_NO_HT40PLUS),
        CHAN2GHZ(11, 2462, IEEE80211_CHAN_NO_HT40PLUS),
        CHAN2GHZ(12, 2467,
-                IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS |
+                IEEE80211_CHAN_NO_IR |
                 IEEE80211_CHAN_NO_HT40PLUS),
        CHAN2GHZ(13, 2472,
-                IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS |
+                IEEE80211_CHAN_NO_IR |
                 IEEE80211_CHAN_NO_HT40PLUS),
        CHAN2GHZ(14, 2484,
-                IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS |
+                IEEE80211_CHAN_NO_IR |
                 IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS |
                 IEEE80211_CHAN_NO_OFDM)
 };
@@ -144,51 +144,51 @@ static struct ieee80211_channel brcms_5ghz_nphy_chantable[] = {
        CHAN5GHZ(48, IEEE80211_CHAN_NO_HT40PLUS),
        /* UNII-2 */
        CHAN5GHZ(52,
-                IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-                IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
+                IEEE80211_CHAN_RADAR |
+                IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS),
        CHAN5GHZ(56,
-                IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-                IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
+                IEEE80211_CHAN_RADAR |
+                IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS),
        CHAN5GHZ(60,
-                IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-                IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
+                IEEE80211_CHAN_RADAR |
+                IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS),
        CHAN5GHZ(64,
-                IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-                IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
+                IEEE80211_CHAN_RADAR |
+                IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS),
        /* MID */
        CHAN5GHZ(100,
-                IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-                IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
+                IEEE80211_CHAN_RADAR |
+                IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS),
        CHAN5GHZ(104,
-                IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-                IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
+                IEEE80211_CHAN_RADAR |
+                IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS),
        CHAN5GHZ(108,
-                IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-                IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
+                IEEE80211_CHAN_RADAR |
+                IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS),
        CHAN5GHZ(112,
-                IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-                IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
+                IEEE80211_CHAN_RADAR |
+                IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS),
        CHAN5GHZ(116,
-                IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-                IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
+                IEEE80211_CHAN_RADAR |
+                IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS),
        CHAN5GHZ(120,
-                IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-                IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
+                IEEE80211_CHAN_RADAR |
+                IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS),
        CHAN5GHZ(124,
-                IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-                IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
+                IEEE80211_CHAN_RADAR |
+                IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS),
        CHAN5GHZ(128,
-                IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-                IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
+                IEEE80211_CHAN_RADAR |
+                IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS),
        CHAN5GHZ(132,
-                IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-                IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
+                IEEE80211_CHAN_RADAR |
+                IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS),
        CHAN5GHZ(136,
-                IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-                IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
+                IEEE80211_CHAN_RADAR |
+                IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS),
        CHAN5GHZ(140,
-                IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-                IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS |
+                IEEE80211_CHAN_RADAR |
+                IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS |
                 IEEE80211_CHAN_NO_HT40MINUS),
        /* UNII-3 */
        CHAN5GHZ(149, IEEE80211_CHAN_NO_HT40MINUS),
index ebdcdf44f1557de4230125be8862e6f333fccbc2..d3acc85932a569024a51d4b9d68b6dbc79dcfec8 100644 (file)
@@ -108,9 +108,9 @@ static irqreturn_t cw1200_gpio_irq(int irq, void *dev_id)
        struct hwbus_priv *self = dev_id;
 
        if (self->core) {
-               sdio_claim_host(self->func);
+               cw1200_sdio_lock(self);
                cw1200_irq_handler(self->core);
-               sdio_release_host(self->func);
+               cw1200_sdio_unlock(self);
                return IRQ_HANDLED;
        } else {
                return IRQ_NONE;
index ee3c19037aac5e039fe023a0fa3fa3b7d08f503d..9afcd4ce3368d37908a055df935f29cf4032f259 100644 (file)
@@ -173,8 +173,9 @@ void cw1200_scan_work(struct work_struct *work)
                        cw1200_set_pm(priv, &priv->powersave_mode);
 
                if (priv->scan.status < 0)
-                       wiphy_dbg(priv->hw->wiphy, "[SCAN] Scan failed (%d).\n",
-                                 priv->scan.status);
+                       wiphy_warn(priv->hw->wiphy,
+                                  "[SCAN] Scan failed (%d).\n",
+                                  priv->scan.status);
                else if (priv->scan.req)
                        wiphy_dbg(priv->hw->wiphy,
                                  "[SCAN] Scan completed.\n");
@@ -197,9 +198,9 @@ void cw1200_scan_work(struct work_struct *work)
                        if ((*it)->band != first->band)
                                break;
                        if (((*it)->flags ^ first->flags) &
-                                       IEEE80211_CHAN_PASSIVE_SCAN)
+                                       IEEE80211_CHAN_NO_IR)
                                break;
-                       if (!(first->flags & IEEE80211_CHAN_PASSIVE_SCAN) &&
+                       if (!(first->flags & IEEE80211_CHAN_NO_IR) &&
                            (*it)->max_power != first->max_power)
                                break;
                }
@@ -210,7 +211,7 @@ void cw1200_scan_work(struct work_struct *work)
                else
                        scan.max_tx_rate = WSM_TRANSMIT_RATE_1;
                scan.num_probes =
-                       (first->flags & IEEE80211_CHAN_PASSIVE_SCAN) ? 0 : 2;
+                       (first->flags & IEEE80211_CHAN_NO_IR) ? 0 : 2;
                scan.num_ssids = priv->scan.n_ssids;
                scan.ssids = &priv->scan.ssids[0];
                scan.num_channels = it - priv->scan.curr;
@@ -233,7 +234,7 @@ void cw1200_scan_work(struct work_struct *work)
                }
                for (i = 0; i < scan.num_channels; ++i) {
                        scan.ch[i].number = priv->scan.curr[i]->hw_value;
-                       if (priv->scan.curr[i]->flags & IEEE80211_CHAN_PASSIVE_SCAN) {
+                       if (priv->scan.curr[i]->flags & IEEE80211_CHAN_NO_IR) {
                                scan.ch[i].min_chan_time = 50;
                                scan.ch[i].max_chan_time = 100;
                        } else {
@@ -241,7 +242,7 @@ void cw1200_scan_work(struct work_struct *work)
                                scan.ch[i].max_chan_time = 25;
                        }
                }
-               if (!(first->flags & IEEE80211_CHAN_PASSIVE_SCAN) &&
+               if (!(first->flags & IEEE80211_CHAN_NO_IR) &&
                    priv->scan.output_power != first->max_power) {
                        priv->scan.output_power = first->max_power;
                        wsm_set_output_power(priv,
index f8ab193009cd9f3044a3d8846d4da4e7cbaec3e5..3aba49259ef1886d09157559977cb7f72ac1d944 100644 (file)
@@ -1930,10 +1930,10 @@ static int ipw2100_wdev_init(struct net_device *dev)
                        bg_band->channels[i].max_power = geo->bg[i].max_power;
                        if (geo->bg[i].flags & LIBIPW_CH_PASSIVE_ONLY)
                                bg_band->channels[i].flags |=
-                                       IEEE80211_CHAN_PASSIVE_SCAN;
+                                       IEEE80211_CHAN_NO_IR;
                        if (geo->bg[i].flags & LIBIPW_CH_NO_IBSS)
                                bg_band->channels[i].flags |=
-                                       IEEE80211_CHAN_NO_IBSS;
+                                       IEEE80211_CHAN_NO_IR;
                        if (geo->bg[i].flags & LIBIPW_CH_RADAR_DETECT)
                                bg_band->channels[i].flags |=
                                        IEEE80211_CHAN_RADAR;
@@ -6362,7 +6362,6 @@ out:
                                   &ipw2100_attribute_group);
 
                free_libipw(dev, 0);
-               pci_set_drvdata(pci_dev, NULL);
        }
 
        pci_iounmap(pci_dev, ioaddr);
index 81903e33d5b1bd4779681da798dc0183c0638f48..9244b3661d343d8908bb72ec3a4516391d1d9900 100644 (file)
@@ -11472,10 +11472,10 @@ static int ipw_wdev_init(struct net_device *dev)
                        bg_band->channels[i].max_power = geo->bg[i].max_power;
                        if (geo->bg[i].flags & LIBIPW_CH_PASSIVE_ONLY)
                                bg_band->channels[i].flags |=
-                                       IEEE80211_CHAN_PASSIVE_SCAN;
+                                       IEEE80211_CHAN_NO_IR;
                        if (geo->bg[i].flags & LIBIPW_CH_NO_IBSS)
                                bg_band->channels[i].flags |=
-                                       IEEE80211_CHAN_NO_IBSS;
+                                       IEEE80211_CHAN_NO_IR;
                        if (geo->bg[i].flags & LIBIPW_CH_RADAR_DETECT)
                                bg_band->channels[i].flags |=
                                        IEEE80211_CHAN_RADAR;
@@ -11511,10 +11511,10 @@ static int ipw_wdev_init(struct net_device *dev)
                        a_band->channels[i].max_power = geo->a[i].max_power;
                        if (geo->a[i].flags & LIBIPW_CH_PASSIVE_ONLY)
                                a_band->channels[i].flags |=
-                                       IEEE80211_CHAN_PASSIVE_SCAN;
+                                       IEEE80211_CHAN_NO_IR;
                        if (geo->a[i].flags & LIBIPW_CH_NO_IBSS)
                                a_band->channels[i].flags |=
-                                       IEEE80211_CHAN_NO_IBSS;
+                                       IEEE80211_CHAN_NO_IR;
                        if (geo->a[i].flags & LIBIPW_CH_RADAR_DETECT)
                                a_band->channels[i].flags |=
                                        IEEE80211_CHAN_RADAR;
index dea3b50d68b9c5bcfc1c95794262992bc59d917d..0487461ae4da22053607bb49178e296787e18dc3 100644 (file)
@@ -1595,7 +1595,7 @@ il3945_get_channels_for_scan(struct il_priv *il, enum ieee80211_band band,
                 *  and use long active_dwell time.
                 */
                if (!is_active || il_is_channel_passive(ch_info) ||
-                   (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) {
+                   (chan->flags & IEEE80211_CHAN_NO_IR)) {
                        scan_ch->type = 0;      /* passive */
                        if (IL_UCODE_API(il->ucode_ver) == 1)
                                scan_ch->active_dwell =
@@ -2396,8 +2396,7 @@ __il3945_up(struct il_priv *il)
                clear_bit(S_RFKILL, &il->status);
        else {
                set_bit(S_RFKILL, &il->status);
-               IL_WARN("Radio disabled by HW RF Kill switch\n");
-               return -ENODEV;
+               return -ERFKILL;
        }
 
        _il_wr(il, CSR_INT, 0xFFFFFFFF);
@@ -3575,9 +3574,9 @@ il3945_setup_mac(struct il_priv *il)
        hw->wiphy->interface_modes =
            BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC);
 
-       hw->wiphy->flags |=
-           WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_DISABLE_BEACON_HINTS |
-           WIPHY_FLAG_IBSS_RSN;
+       hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
+       hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG |
+                                      REGULATORY_DISABLE_BEACON_HINTS;
 
        hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
 
index 3982ab76f3755fdbda4f0cab89aa6cca537a8f43..43f488a8cda21790a646dcd4efa4ffd04d445c96 100644 (file)
@@ -805,7 +805,7 @@ il4965_get_channels_for_scan(struct il_priv *il, struct ieee80211_vif *vif,
                }
 
                if (!is_active || il_is_channel_passive(ch_info) ||
-                   (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN))
+                   (chan->flags & IEEE80211_CHAN_NO_IR))
                        scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
                else
                        scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE;
@@ -5778,9 +5778,9 @@ il4965_mac_setup_register(struct il_priv *il, u32 max_probe_length)
        hw->wiphy->interface_modes =
            BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC);
 
-       hw->wiphy->flags |=
-           WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_DISABLE_BEACON_HINTS |
-           WIPHY_FLAG_IBSS_RSN;
+       hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
+       hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG |
+                                      REGULATORY_DISABLE_BEACON_HINTS;
 
        /*
         * For now, disable PS by default because it affects
index b03e22ef5462d929ea20ffad72a4a01ff067c4a4..a27b14cfeaec05753bb64fe8708ec7c25065995c 100644 (file)
@@ -3445,10 +3445,10 @@ il_init_geos(struct il_priv *il)
 
                if (il_is_channel_valid(ch)) {
                        if (!(ch->flags & EEPROM_CHANNEL_IBSS))
-                               geo_ch->flags |= IEEE80211_CHAN_NO_IBSS;
+                               geo_ch->flags |= IEEE80211_CHAN_NO_IR;
 
                        if (!(ch->flags & EEPROM_CHANNEL_ACTIVE))
-                               geo_ch->flags |= IEEE80211_CHAN_PASSIVE_SCAN;
+                               geo_ch->flags |= IEEE80211_CHAN_NO_IR;
 
                        if (ch->flags & EEPROM_CHANNEL_RADAR)
                                geo_ch->flags |= IEEE80211_CHAN_RADAR;
index eff26501d60a63407fba5b8cff66778d612df54e..3a487a3bb5de8fd62c896409df62562712e41239 100644 (file)
@@ -567,12 +567,12 @@ il_dbgfs_channels_read(struct file *file, char __user *user_buf, size_t count,
                                      flags & IEEE80211_CHAN_RADAR ?
                                      " (IEEE 802.11h required)" : "",
                                      ((channels[i].
-                                       flags & IEEE80211_CHAN_NO_IBSS) ||
+                                       flags & IEEE80211_CHAN_NO_IR) ||
                                       (channels[i].
                                        flags & IEEE80211_CHAN_RADAR)) ? "" :
                                      ", IBSS",
                                      channels[i].
-                                     flags & IEEE80211_CHAN_PASSIVE_SCAN ?
+                                     flags & IEEE80211_CHAN_NO_IR ?
                                      "passive only" : "active/passive");
        }
        supp_band = il_get_hw_mode(il, IEEE80211_BAND_5GHZ);
@@ -594,12 +594,12 @@ il_dbgfs_channels_read(struct file *file, char __user *user_buf, size_t count,
                                      flags & IEEE80211_CHAN_RADAR ?
                                      " (IEEE 802.11h required)" : "",
                                      ((channels[i].
-                                       flags & IEEE80211_CHAN_NO_IBSS) ||
+                                       flags & IEEE80211_CHAN_NO_IR) ||
                                       (channels[i].
                                        flags & IEEE80211_CHAN_RADAR)) ? "" :
                                      ", IBSS",
                                      channels[i].
-                                     flags & IEEE80211_CHAN_PASSIVE_SCAN ?
+                                     flags & IEEE80211_CHAN_NO_IR ?
                                      "passive only" : "active/passive");
        }
        ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
index d94f8ab15004cb93f2e757f92a91fd3e669759cb..f69301e505ee0e8968d5a9b90f9dcb3404c1f843 100644 (file)
@@ -352,12 +352,12 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf,
                                        channels[i].max_power,
                                        channels[i].flags & IEEE80211_CHAN_RADAR ?
                                        " (IEEE 802.11h required)" : "",
-                                       ((channels[i].flags & IEEE80211_CHAN_NO_IBSS)
+                                       ((channels[i].flags & IEEE80211_CHAN_NO_IR)
                                        || (channels[i].flags &
                                        IEEE80211_CHAN_RADAR)) ? "" :
                                        ", IBSS",
                                        channels[i].flags &
-                                       IEEE80211_CHAN_PASSIVE_SCAN ?
+                                       IEEE80211_CHAN_NO_IR ?
                                        "passive only" : "active/passive");
        }
        supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_5GHZ);
@@ -375,12 +375,12 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf,
                                        channels[i].max_power,
                                        channels[i].flags & IEEE80211_CHAN_RADAR ?
                                        " (IEEE 802.11h required)" : "",
-                                       ((channels[i].flags & IEEE80211_CHAN_NO_IBSS)
+                                       ((channels[i].flags & IEEE80211_CHAN_NO_IR)
                                        || (channels[i].flags &
                                        IEEE80211_CHAN_RADAR)) ? "" :
                                        ", IBSS",
                                        channels[i].flags &
-                                       IEEE80211_CHAN_PASSIVE_SCAN ?
+                                       IEEE80211_CHAN_NO_IR ?
                                        "passive only" : "active/passive");
        }
        ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
index cae4d3182e334f9451e38d0afada8a8468785195..217f1ca321a0fecb7aaa876a5a22b5ec214b5818 100644 (file)
@@ -155,9 +155,9 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
                        ARRAY_SIZE(iwlagn_iface_combinations_dualmode);
        }
 
-       hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
-                           WIPHY_FLAG_DISABLE_BEACON_HINTS |
-                           WIPHY_FLAG_IBSS_RSN;
+       hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
+       hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG |
+                                      REGULATORY_DISABLE_BEACON_HINTS;
 
 #ifdef CONFIG_PM_SLEEP
        if (priv->fw->img[IWL_UCODE_WOWLAN].sec[0].len &&
index 26fc550cd68c58ae24342232bda51be2dfd690a5..41988f4b8a5add9ec1c2f87617f8cc64913cd8dc 100644 (file)
@@ -389,13 +389,6 @@ struct iwl_lq_sta {
        u8 last_bt_traffic;
 };
 
-static inline u8 num_of_ant(u8 mask)
-{
-       return  !!((mask) & ANT_A) +
-               !!((mask) & ANT_B) +
-               !!((mask) & ANT_C);
-}
-
 static inline u8 first_antenna(u8 mask)
 {
        if (mask & ANT_A)
index 35e0ee8b4e5b64162ecdb2287ae53ab3acd5ee4b..928f8640a0a7965aebfb5c429265ac71a4970f88 100644 (file)
@@ -544,7 +544,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv,
                channel = chan->hw_value;
                scan_ch->channel = cpu_to_le16(channel);
 
-               if (!is_active || (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN))
+               if (!is_active || (chan->flags & IEEE80211_CHAN_NO_IR))
                        scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
                else
                        scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE;
index 1fef5240e6adc07317b7128bf7d7617385fa9aa8..e12b1a63c484635f64a23f0e27904045a8185cc2 100644 (file)
@@ -368,6 +368,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv,
                goto drop_unlock_priv;
 
        memset(dev_cmd, 0, sizeof(*dev_cmd));
+       dev_cmd->hdr.cmd = REPLY_TX;
        tx_cmd = (struct iwl_tx_cmd *) dev_cmd->payload;
 
        /* Total # bytes to be transmitted */
index 85879dbaa402cdaa88d93247b678aaac9a3ff000..3c34a72a5d64769b8bbf156f9a74d4748fcb0228 100644 (file)
@@ -67,8 +67,8 @@
 #include "iwl-agn-hw.h"
 
 /* Highest firmware API version supported */
-#define IWL7260_UCODE_API_MAX  7
-#define IWL3160_UCODE_API_MAX  7
+#define IWL7260_UCODE_API_MAX  8
+#define IWL3160_UCODE_API_MAX  8
 
 /* Oldest version we won't warn about */
 #define IWL7260_UCODE_API_OK   7
@@ -130,6 +130,7 @@ const struct iwl_cfg iwl7260_2ac_cfg = {
        .ht_params = &iwl7000_ht_params,
        .nvm_ver = IWL7260_NVM_VERSION,
        .nvm_calib_ver = IWL7260_TX_POWER_VERSION,
+       .host_interrupt_operation_mode = true,
 };
 
 const struct iwl_cfg iwl7260_2ac_cfg_high_temp = {
@@ -140,6 +141,7 @@ const struct iwl_cfg iwl7260_2ac_cfg_high_temp = {
        .nvm_ver = IWL7260_NVM_VERSION,
        .nvm_calib_ver = IWL7260_TX_POWER_VERSION,
        .high_temp = true,
+       .host_interrupt_operation_mode = true,
 };
 
 const struct iwl_cfg iwl7260_2n_cfg = {
@@ -149,6 +151,7 @@ const struct iwl_cfg iwl7260_2n_cfg = {
        .ht_params = &iwl7000_ht_params,
        .nvm_ver = IWL7260_NVM_VERSION,
        .nvm_calib_ver = IWL7260_TX_POWER_VERSION,
+       .host_interrupt_operation_mode = true,
 };
 
 const struct iwl_cfg iwl7260_n_cfg = {
@@ -158,6 +161,7 @@ const struct iwl_cfg iwl7260_n_cfg = {
        .ht_params = &iwl7000_ht_params,
        .nvm_ver = IWL7260_NVM_VERSION,
        .nvm_calib_ver = IWL7260_TX_POWER_VERSION,
+       .host_interrupt_operation_mode = true,
 };
 
 const struct iwl_cfg iwl3160_2ac_cfg = {
@@ -167,6 +171,7 @@ const struct iwl_cfg iwl3160_2ac_cfg = {
        .ht_params = &iwl7000_ht_params,
        .nvm_ver = IWL3160_NVM_VERSION,
        .nvm_calib_ver = IWL3160_TX_POWER_VERSION,
+       .host_interrupt_operation_mode = true,
 };
 
 const struct iwl_cfg iwl3160_2n_cfg = {
@@ -176,6 +181,7 @@ const struct iwl_cfg iwl3160_2n_cfg = {
        .ht_params = &iwl7000_ht_params,
        .nvm_ver = IWL3160_NVM_VERSION,
        .nvm_calib_ver = IWL3160_TX_POWER_VERSION,
+       .host_interrupt_operation_mode = true,
 };
 
 const struct iwl_cfg iwl3160_n_cfg = {
@@ -185,6 +191,7 @@ const struct iwl_cfg iwl3160_n_cfg = {
        .ht_params = &iwl7000_ht_params,
        .nvm_ver = IWL3160_NVM_VERSION,
        .nvm_calib_ver = IWL3160_TX_POWER_VERSION,
+       .host_interrupt_operation_mode = true,
 };
 
 const struct iwl_cfg iwl7265_2ac_cfg = {
@@ -196,5 +203,23 @@ const struct iwl_cfg iwl7265_2ac_cfg = {
        .nvm_calib_ver = IWL7265_TX_POWER_VERSION,
 };
 
+const struct iwl_cfg iwl7265_2n_cfg = {
+       .name = "Intel(R) Dual Band Wireless N 7265",
+       .fw_name_pre = IWL7265_FW_PRE,
+       IWL_DEVICE_7000,
+       .ht_params = &iwl7000_ht_params,
+       .nvm_ver = IWL7265_NVM_VERSION,
+       .nvm_calib_ver = IWL7265_TX_POWER_VERSION,
+};
+
+const struct iwl_cfg iwl7265_n_cfg = {
+       .name = "Intel(R) Wireless N 7265",
+       .fw_name_pre = IWL7265_FW_PRE,
+       IWL_DEVICE_7000,
+       .ht_params = &iwl7000_ht_params,
+       .nvm_ver = IWL7265_NVM_VERSION,
+       .nvm_calib_ver = IWL7265_TX_POWER_VERSION,
+};
+
 MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
 MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL3160_UCODE_API_OK));
index 18f232e8e81253b31d730755f242b7a51552157c..0b916249669ed25139db177649e5adcd98f74b7b 100644 (file)
@@ -129,6 +129,12 @@ enum iwl_led_mode {
 #define ANT_BC         (ANT_B | ANT_C)
 #define ANT_ABC                (ANT_A | ANT_B | ANT_C)
 
+static inline u8 num_of_ant(u8 mask)
+{
+       return  !!((mask) & ANT_A) +
+               !!((mask) & ANT_B) +
+               !!((mask) & ANT_C);
+}
 
 /*
  * @max_ll_items: max number of OTP blocks
@@ -207,6 +213,8 @@ struct iwl_eeprom_params {
  * @rx_with_siso_diversity: 1x1 device with rx antenna diversity
  * @internal_wimax_coex: internal wifi/wimax combo device
  * @high_temp: Is this NIC is designated to be in high temperature.
+ * @host_interrupt_operation_mode: device needs host interrupt operation
+ *     mode set
  *
  * We enable the driver to be backward compatible wrt. hardware features.
  * API differences in uCode shouldn't be handled here but through TLVs
@@ -235,6 +243,7 @@ struct iwl_cfg {
        enum iwl_led_mode led_mode;
        const bool rx_with_siso_diversity;
        const bool internal_wimax_coex;
+       const bool host_interrupt_operation_mode;
        bool high_temp;
 };
 
@@ -294,6 +303,8 @@ extern const struct iwl_cfg iwl3160_2ac_cfg;
 extern const struct iwl_cfg iwl3160_2n_cfg;
 extern const struct iwl_cfg iwl3160_n_cfg;
 extern const struct iwl_cfg iwl7265_2ac_cfg;
+extern const struct iwl_cfg iwl7265_2n_cfg;
+extern const struct iwl_cfg iwl7265_n_cfg;
 #endif /* CONFIG_IWLMVM */
 
 #endif /* __IWL_CONFIG_H__ */
index 54a4fdc631b73c987f12e459e8245d38b18f0c0b..da4eca8b3007feabb267a1710c95a70306224455 100644 (file)
@@ -495,14 +495,11 @@ enum secure_load_status_reg {
  * the CSR_INT_COALESCING is an 8 bit register in 32-usec unit
  *
  * default interrupt coalescing timer is 64 x 32 = 2048 usecs
- * default interrupt coalescing calibration timer is 16 x 32 = 512 usecs
  */
 #define IWL_HOST_INT_TIMEOUT_MAX       (0xFF)
 #define IWL_HOST_INT_TIMEOUT_DEF       (0x40)
 #define IWL_HOST_INT_TIMEOUT_MIN       (0x0)
-#define IWL_HOST_INT_CALIB_TIMEOUT_MAX (0xFF)
-#define IWL_HOST_INT_CALIB_TIMEOUT_DEF (0x10)
-#define IWL_HOST_INT_CALIB_TIMEOUT_MIN (0x0)
+#define IWL_HOST_INT_OPER_MODE         BIT(31)
 
 /*****************************************************************************
  *                        7000/3000 series SHR DTS addresses                 *
index 4c887f3659089ea3451bc9cc4f2a8dc44c764601..f4a6d317a023aad241ac4f15351a1cc2deae7a2c 100644 (file)
@@ -614,10 +614,10 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
                        channel->flags = IEEE80211_CHAN_NO_HT40;
 
                        if (!(eeprom_ch->flags & EEPROM_CHANNEL_IBSS))
-                               channel->flags |= IEEE80211_CHAN_NO_IBSS;
+                               channel->flags |= IEEE80211_CHAN_NO_IR;
 
                        if (!(eeprom_ch->flags & EEPROM_CHANNEL_ACTIVE))
-                               channel->flags |= IEEE80211_CHAN_PASSIVE_SCAN;
+                               channel->flags |= IEEE80211_CHAN_NO_IR;
 
                        if (eeprom_ch->flags & EEPROM_CHANNEL_RADAR)
                                channel->flags |= IEEE80211_CHAN_RADAR;
index b76a9a8fc0b3dbe831f74ce7d20a811e6cf17ada..94aef22df73a9f772429f536aa11e71ca98d51d2 100644 (file)
@@ -223,10 +223,10 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
                        channel->flags |= IEEE80211_CHAN_NO_160MHZ;
 
                if (!(ch_flags & NVM_CHANNEL_IBSS))
-                       channel->flags |= IEEE80211_CHAN_NO_IBSS;
+                       channel->flags |= IEEE80211_CHAN_NO_IR;
 
                if (!(ch_flags & NVM_CHANNEL_ACTIVE))
-                       channel->flags |= IEEE80211_CHAN_PASSIVE_SCAN;
+                       channel->flags |= IEEE80211_CHAN_NO_IR;
 
                if (ch_flags & NVM_CHANNEL_RADAR)
                        channel->flags |= IEEE80211_CHAN_RADAR;
@@ -283,7 +283,8 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg,
                            IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 |
                            IEEE80211_VHT_MCS_NOT_SUPPORTED << 14);
 
-       if (data->valid_rx_ant == 1 || cfg->rx_with_siso_diversity) {
+       if (num_of_ant(data->valid_rx_ant) == 1 ||
+           cfg->rx_with_siso_diversity) {
                vht_cap->cap |= IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN |
                                IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN;
                /* this works because NOT_SUPPORTED == 3 */
index a70c7b9d9bad897345fb1e1e89d5c421e0d8a3da..f6412dae26590cbf2f66ae774b11aaf402721179 100644 (file)
 /* Device system time */
 #define DEVICE_SYSTEM_TIME_REG 0xA0206C
 
+/* Device NMI register */
+#define DEVICE_SET_NMI_REG 0x00a01c30
+
 /*****************************************************************************
  *                        7000/3000 series SHR DTS addresses                 *
  *****************************************************************************/
index 6d73817850ce6753c5a88481b78d1d1f0f1d3864..285d8c7486f5a8262209f641d704424036fecce7 100644 (file)
@@ -5,6 +5,7 @@ iwlmvm-y += scan.o time-event.o rs.o
 iwlmvm-y += power.o power_legacy.o bt-coex.o
 iwlmvm-y += led.o tt.o
 iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o
+iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o
 iwlmvm-$(CONFIG_PM_SLEEP) += d3.o
 
 ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/../
index 5d066cbc5ac7eda17914e85c2510c53fe4a5be2a..d126245c48dea219d2161221a56dd0709cfd35f8 100644 (file)
@@ -391,13 +391,13 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
                                            BT_VALID_LUT |
                                            BT_VALID_WIFI_RX_SW_PRIO_BOOST |
                                            BT_VALID_WIFI_TX_SW_PRIO_BOOST |
-                                           BT_VALID_MULTI_PRIO_LUT |
                                            BT_VALID_CORUN_LUT_20 |
                                            BT_VALID_CORUN_LUT_40 |
                                            BT_VALID_ANT_ISOLATION |
                                            BT_VALID_ANT_ISOLATION_THRS |
                                            BT_VALID_TXTX_DELTA_FREQ_THRS |
-                                           BT_VALID_TXRX_MAX_FREQ_0);
+                                           BT_VALID_TXRX_MAX_FREQ_0 |
+                                           BT_VALID_SYNC_TO_SCO);
 
        if (mvm->cfg->bt_shared_single_ant)
                memcpy(&bt_cmd->decision_lut, iwl_single_shared_ant,
@@ -515,7 +515,7 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
        if (IS_ERR_OR_NULL(sta))
                return 0;
 
-       mvmsta = (void *)sta->drv_priv;
+       mvmsta = iwl_mvm_sta_from_mac80211(sta);
 
        /* nothing to do */
        if (mvmsta->bt_reduced_txpower == enable)
@@ -842,7 +842,12 @@ static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac,
 
        sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[mvmvif->ap_sta_id],
                                        lockdep_is_held(&mvm->mutex));
-       mvmsta = (void *)sta->drv_priv;
+
+       /* This can happen if the station has been removed right now */
+       if (IS_ERR_OR_NULL(sta))
+               return;
+
+       mvmsta = iwl_mvm_sta_from_mac80211(sta);
 
        data->num_bss_ifaces++;
 
@@ -913,11 +918,11 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 u16 iwl_mvm_bt_coex_agg_time_limit(struct iwl_mvm *mvm,
                                   struct ieee80211_sta *sta)
 {
-       struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv;
+       struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
        enum iwl_bt_coex_lut_type lut_type;
 
        if (le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) <
-           BT_LOW_TRAFFIC)
+           BT_HIGH_TRAFFIC)
                return LINK_QUAL_AGG_TIME_LIMIT_DEF;
 
        lut_type = iwl_get_coex_type(mvm, mvmsta->vif);
@@ -932,7 +937,7 @@ u16 iwl_mvm_bt_coex_agg_time_limit(struct iwl_mvm *mvm,
 bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm,
                                     struct ieee80211_sta *sta)
 {
-       struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv;
+       struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
 
        if (le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) <
            BT_HIGH_TRAFFIC)
index 6f45966817bb4c1d34cd3a10c4db74536f4a13bf..665f87e788d6ec2a78e9ab1ba6a3af8795c2c752 100644 (file)
@@ -895,7 +895,7 @@ static int iwl_mvm_get_last_nonqos_seq(struct iwl_mvm *mvm,
                /* new API returns next, not last-used seqno */
                if (mvm->fw->ucode_capa.flags &
                                IWL_UCODE_TLV_FLAGS_D3_CONTINUITY_API)
-                       err -= 0x10;
+                       err = (u16) (err - 0x10);
        }
 
        iwl_free_resp(&cmd);
@@ -1216,10 +1216,6 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
        if (len >= sizeof(u32) * 2) {
                mvm->d3_test_pme_ptr =
                        le32_to_cpup((__le32 *)d3_cfg_cmd.resp_pkt->data);
-       } else if (test) {
-               /* in test mode we require the pointer */
-               ret = -EIO;
-               goto out;
        }
 #endif
        iwl_free_resp(&d3_cfg_cmd);
@@ -1231,10 +1227,11 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
        mvm->aux_sta.sta_id = old_aux_sta_id;
        mvm_ap_sta->sta_id = old_ap_sta_id;
        mvmvif->ap_sta_id = old_ap_sta_id;
- out_noreset:
-       kfree(key_data.rsc_tsc);
+
        if (ret < 0)
                ieee80211_restart_hw(mvm->hw);
+ out_noreset:
+       kfree(key_data.rsc_tsc);
 
        mutex_unlock(&mvm->mutex);
 
@@ -1537,10 +1534,16 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
        struct iwl_mvm_d3_gtk_iter_data gtkdata = {
                .status = status,
        };
+       u32 disconnection_reasons =
+               IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_MISSED_BEACON |
+               IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_DEAUTH;
 
        if (!status || !vif->bss_conf.bssid)
                return false;
 
+       if (le32_to_cpu(status->wakeup_reasons) & disconnection_reasons)
+               return false;
+
        /* find last GTK that we used initially, if any */
        gtkdata.find_phase = true;
        ieee80211_iter_keys(mvm->hw, vif,
@@ -1549,7 +1552,7 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
        if (gtkdata.unhandled_cipher)
                return false;
        if (!gtkdata.num_keys)
-               return true;
+               goto out;
        if (!gtkdata.last_gtk)
                return false;
 
@@ -1600,6 +1603,7 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
                                           (void *)&replay_ctr, GFP_KERNEL);
        }
 
+out:
        mvmvif->seqno_valid = true;
        /* +0x10 because the set API expects next-to-use, not last-used */
        mvmvif->seqno = le16_to_cpu(status->non_qos_seq_ctr) + 0x10;
@@ -1804,6 +1808,10 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
        iwl_mvm_read_d3_sram(mvm);
 
        keep = iwl_mvm_query_wakeup_reasons(mvm, vif);
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+       if (keep)
+               mvm->keep_vif = vif;
+#endif
        /* has unlocked the mutex, so skip that */
        goto out;
 
@@ -1860,6 +1868,7 @@ static int iwl_mvm_d3_test_open(struct inode *inode, struct file *file)
                return err;
        }
        mvm->d3_test_active = true;
+       mvm->keep_vif = NULL;
        return 0;
 }
 
@@ -1870,10 +1879,14 @@ static ssize_t iwl_mvm_d3_test_read(struct file *file, char __user *user_buf,
        u32 pme_asserted;
 
        while (true) {
-               pme_asserted = iwl_trans_read_mem32(mvm->trans,
-                                                   mvm->d3_test_pme_ptr);
-               if (pme_asserted)
-                       break;
+               /* read pme_ptr if available */
+               if (mvm->d3_test_pme_ptr) {
+                       pme_asserted = iwl_trans_read_mem32(mvm->trans,
+                                               mvm->d3_test_pme_ptr);
+                       if (pme_asserted)
+                               break;
+               }
+
                if (msleep_interruptible(100))
                        break;
        }
@@ -1884,6 +1897,10 @@ static ssize_t iwl_mvm_d3_test_read(struct file *file, char __user *user_buf,
 static void iwl_mvm_d3_test_disconn_work_iter(void *_data, u8 *mac,
                                              struct ieee80211_vif *vif)
 {
+       /* skip the one we keep connection on */
+       if (_data == vif)
+               return;
+
        if (vif->type == NL80211_IFTYPE_STATION)
                ieee80211_connection_loss(vif);
 }
@@ -1910,7 +1927,7 @@ static int iwl_mvm_d3_test_release(struct inode *inode, struct file *file)
 
        ieee80211_iterate_active_interfaces_atomic(
                mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
-               iwl_mvm_d3_test_disconn_work_iter, NULL);
+               iwl_mvm_d3_test_disconn_work_iter, mvm->keep_vif);
 
        ieee80211_wake_queues(mvm->hw);
 
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c
new file mode 100644 (file)
index 0000000..67f6a20
--- /dev/null
@@ -0,0 +1,190 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+#include "mvm.h"
+#include "debugfs.h"
+
+static ssize_t iwl_dbgfs_mac_params_read(struct file *file,
+                                        char __user *user_buf,
+                                        size_t count, loff_t *ppos)
+{
+       struct ieee80211_vif *vif = file->private_data;
+       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+       struct iwl_mvm *mvm = mvmvif->mvm;
+       u8 ap_sta_id;
+       struct ieee80211_chanctx_conf *chanctx_conf;
+       char buf[512];
+       int bufsz = sizeof(buf);
+       int pos = 0;
+       int i;
+
+       mutex_lock(&mvm->mutex);
+
+       ap_sta_id = mvmvif->ap_sta_id;
+
+       pos += scnprintf(buf+pos, bufsz-pos, "mac id/color: %d / %d\n",
+                        mvmvif->id, mvmvif->color);
+       pos += scnprintf(buf+pos, bufsz-pos, "bssid: %pM\n",
+                        vif->bss_conf.bssid);
+       pos += scnprintf(buf+pos, bufsz-pos, "QoS:\n");
+       for (i = 0; i < ARRAY_SIZE(mvmvif->queue_params); i++)
+               pos += scnprintf(buf+pos, bufsz-pos,
+                                "\t%d: txop:%d - cw_min:%d - cw_max = %d - aifs = %d upasd = %d\n",
+                                i, mvmvif->queue_params[i].txop,
+                                mvmvif->queue_params[i].cw_min,
+                                mvmvif->queue_params[i].cw_max,
+                                mvmvif->queue_params[i].aifs,
+                                mvmvif->queue_params[i].uapsd);
+
+       if (vif->type == NL80211_IFTYPE_STATION &&
+           ap_sta_id != IWL_MVM_STATION_COUNT) {
+               struct ieee80211_sta *sta;
+               struct iwl_mvm_sta *mvm_sta;
+
+               sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[ap_sta_id],
+                                               lockdep_is_held(&mvm->mutex));
+               mvm_sta = (void *)sta->drv_priv;
+               pos += scnprintf(buf+pos, bufsz-pos,
+                                "ap_sta_id %d - reduced Tx power %d\n",
+                                ap_sta_id, mvm_sta->bt_reduced_txpower);
+       }
+
+       rcu_read_lock();
+       chanctx_conf = rcu_dereference(vif->chanctx_conf);
+       if (chanctx_conf)
+               pos += scnprintf(buf+pos, bufsz-pos,
+                                "idle rx chains %d, active rx chains: %d\n",
+                                chanctx_conf->rx_chains_static,
+                                chanctx_conf->rx_chains_dynamic);
+       rcu_read_unlock();
+
+       mutex_unlock(&mvm->mutex);
+
+       return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+#define MVM_DEBUGFS_ADD_FILE_VIF(name, parent, mode) do {              \
+               if (!debugfs_create_file(#name, mode, parent, vif,      \
+                                        &iwl_dbgfs_##name##_ops))      \
+                       goto err;                                       \
+       } while (0)
+
+MVM_DEBUGFS_READ_FILE_OPS(mac_params);
+
+void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
+{
+       struct dentry *dbgfs_dir = vif->debugfs_dir;
+       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+       char buf[100];
+
+       /*
+        * Check if debugfs directory already exist before creating it.
+        * This may happen when, for example, resetting hw or suspend-resume
+        */
+       if (!dbgfs_dir || mvmvif->dbgfs_dir)
+               return;
+
+       mvmvif->dbgfs_dir = debugfs_create_dir("iwlmvm", dbgfs_dir);
+       mvmvif->mvm = mvm;
+
+       if (!mvmvif->dbgfs_dir) {
+               IWL_ERR(mvm, "Failed to create debugfs directory under %s\n",
+                       dbgfs_dir->d_name.name);
+               return;
+       }
+
+       MVM_DEBUGFS_ADD_FILE_VIF(mac_params, mvmvif->dbgfs_dir,
+                                S_IRUSR);
+
+       /*
+        * Create symlink for convenience pointing to interface specific
+        * debugfs entries for the driver. For example, under
+        * /sys/kernel/debug/iwlwifi/0000\:02\:00.0/iwlmvm/
+        * find
+        * netdev:wlan0 -> ../../../ieee80211/phy0/netdev:wlan0/iwlmvm/
+        */
+       snprintf(buf, 100, "../../../%s/%s/%s/%s",
+                dbgfs_dir->d_parent->d_parent->d_name.name,
+                dbgfs_dir->d_parent->d_name.name,
+                dbgfs_dir->d_name.name,
+                mvmvif->dbgfs_dir->d_name.name);
+
+       mvmvif->dbgfs_slink = debugfs_create_symlink(dbgfs_dir->d_name.name,
+                                                    mvm->debugfs_dir, buf);
+       if (!mvmvif->dbgfs_slink)
+               IWL_ERR(mvm, "Can't create debugfs symbolic link under %s\n",
+                       dbgfs_dir->d_name.name);
+       return;
+err:
+       IWL_ERR(mvm, "Can't create debugfs entity\n");
+}
+
+void iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
+{
+       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
+       debugfs_remove(mvmvif->dbgfs_slink);
+       mvmvif->dbgfs_slink = NULL;
+
+       debugfs_remove_recursive(mvmvif->dbgfs_dir);
+       mvmvif->dbgfs_dir = NULL;
+}
index 9864d713eb2cb54920053fb971a65866f5ec0bf4..e8f62a6a1b57098a3f456e9beff974f7caa3493c 100644 (file)
 #include "mvm.h"
 #include "sta.h"
 #include "iwl-io.h"
+#include "iwl-prph.h"
+#include "debugfs.h"
 
-struct iwl_dbgfs_mvm_ctx {
-       struct iwl_mvm *mvm;
-       struct ieee80211_vif *vif;
-};
-
-static ssize_t iwl_dbgfs_tx_flush_write(struct file *file,
-                                       const char __user *user_buf,
+static ssize_t iwl_dbgfs_tx_flush_write(struct iwl_mvm *mvm, char *buf,
                                        size_t count, loff_t *ppos)
 {
-       struct iwl_mvm *mvm = file->private_data;
-
-       char buf[16];
-       int buf_size, ret;
+       int ret;
        u32 scd_q_msk;
 
        if (!mvm->ucode_loaded || mvm->cur_ucode != IWL_UCODE_REGULAR)
                return -EIO;
 
-       memset(buf, 0, sizeof(buf));
-       buf_size = min(count, sizeof(buf) - 1);
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
-
        if (sscanf(buf, "%x", &scd_q_msk) != 1)
                return -EINVAL;
 
@@ -99,26 +87,21 @@ static ssize_t iwl_dbgfs_tx_flush_write(struct file *file,
        return ret;
 }
 
-static ssize_t iwl_dbgfs_sta_drain_write(struct file *file,
-                                        const char __user *user_buf,
+static ssize_t iwl_dbgfs_sta_drain_write(struct iwl_mvm *mvm, char *buf,
                                         size_t count, loff_t *ppos)
 {
-       struct iwl_mvm *mvm = file->private_data;
        struct ieee80211_sta *sta;
-
-       char buf[8];
-       int buf_size, sta_id, drain, ret;
+       int sta_id, drain, ret;
 
        if (!mvm->ucode_loaded || mvm->cur_ucode != IWL_UCODE_REGULAR)
                return -EIO;
 
-       memset(buf, 0, sizeof(buf));
-       buf_size = min(count, sizeof(buf) - 1);
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
-
        if (sscanf(buf, "%d %d", &sta_id, &drain) != 2)
                return -EINVAL;
+       if (sta_id < 0 || sta_id >= IWL_MVM_STATION_COUNT)
+               return -EINVAL;
+       if (drain < 0 || drain > 1)
+               return -EINVAL;
 
        mutex_lock(&mvm->mutex);
 
@@ -190,20 +173,11 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf,
        return ret;
 }
 
-static ssize_t iwl_dbgfs_sram_write(struct file *file,
-                                   const char __user *user_buf, size_t count,
-                                   loff_t *ppos)
+static ssize_t iwl_dbgfs_sram_write(struct iwl_mvm *mvm, char *buf,
+                                   size_t count, loff_t *ppos)
 {
-       struct iwl_mvm *mvm = file->private_data;
-       char buf[64];
-       int buf_size;
        u32 offset, len;
 
-       memset(buf, 0, sizeof(buf));
-       buf_size = min(count, sizeof(buf) -  1);
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
-
        if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
                if ((offset & 0x3) || (len & 0x3))
                        return -EINVAL;
@@ -263,22 +237,14 @@ static ssize_t iwl_dbgfs_disable_power_off_read(struct file *file,
        return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 }
 
-static ssize_t iwl_dbgfs_disable_power_off_write(struct file *file,
-                                                const char __user *user_buf,
+static ssize_t iwl_dbgfs_disable_power_off_write(struct iwl_mvm *mvm, char *buf,
                                                 size_t count, loff_t *ppos)
 {
-       struct iwl_mvm *mvm = file->private_data;
-       char buf[64] = {};
-       int ret;
-       int val;
+       int ret, val;
 
        if (!mvm->ucode_loaded)
                return -EIO;
 
-       count = min_t(size_t, count, sizeof(buf) - 1);
-       if (copy_from_user(buf, user_buf, count))
-               return -EFAULT;
-
        if (!strncmp("disable_power_off_d0=", buf, 21)) {
                if (sscanf(buf + 21, "%d", &val) != 1)
                        return -EINVAL;
@@ -298,212 +264,6 @@ static ssize_t iwl_dbgfs_disable_power_off_write(struct file *file,
        return ret ?: count;
 }
 
-static void iwl_dbgfs_update_pm(struct iwl_mvm *mvm,
-                                struct ieee80211_vif *vif,
-                                enum iwl_dbgfs_pm_mask param, int val)
-{
-       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-       struct iwl_dbgfs_pm *dbgfs_pm = &mvmvif->dbgfs_pm;
-
-       dbgfs_pm->mask |= param;
-
-       switch (param) {
-       case MVM_DEBUGFS_PM_KEEP_ALIVE: {
-               struct ieee80211_hw *hw = mvm->hw;
-               int dtimper = hw->conf.ps_dtim_period ?: 1;
-               int dtimper_msec = dtimper * vif->bss_conf.beacon_int;
-
-               IWL_DEBUG_POWER(mvm, "debugfs: set keep_alive= %d sec\n", val);
-               if (val * MSEC_PER_SEC < 3 * dtimper_msec) {
-                       IWL_WARN(mvm,
-                                "debugfs: keep alive period (%ld msec) is less than minimum required (%d msec)\n",
-                                val * MSEC_PER_SEC, 3 * dtimper_msec);
-               }
-               dbgfs_pm->keep_alive_seconds = val;
-               break;
-       }
-       case MVM_DEBUGFS_PM_SKIP_OVER_DTIM:
-               IWL_DEBUG_POWER(mvm, "skip_over_dtim %s\n",
-                               val ? "enabled" : "disabled");
-               dbgfs_pm->skip_over_dtim = val;
-               break;
-       case MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS:
-               IWL_DEBUG_POWER(mvm, "skip_dtim_periods=%d\n", val);
-               dbgfs_pm->skip_dtim_periods = val;
-               break;
-       case MVM_DEBUGFS_PM_RX_DATA_TIMEOUT:
-               IWL_DEBUG_POWER(mvm, "rx_data_timeout=%d\n", val);
-               dbgfs_pm->rx_data_timeout = val;
-               break;
-       case MVM_DEBUGFS_PM_TX_DATA_TIMEOUT:
-               IWL_DEBUG_POWER(mvm, "tx_data_timeout=%d\n", val);
-               dbgfs_pm->tx_data_timeout = val;
-               break;
-       case MVM_DEBUGFS_PM_DISABLE_POWER_OFF:
-               IWL_DEBUG_POWER(mvm, "disable_power_off=%d\n", val);
-               dbgfs_pm->disable_power_off = val;
-               break;
-       case MVM_DEBUGFS_PM_LPRX_ENA:
-               IWL_DEBUG_POWER(mvm, "lprx %s\n", val ? "enabled" : "disabled");
-               dbgfs_pm->lprx_ena = val;
-               break;
-       case MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD:
-               IWL_DEBUG_POWER(mvm, "lprx_rssi_threshold=%d\n", val);
-               dbgfs_pm->lprx_rssi_threshold = val;
-               break;
-       case MVM_DEBUGFS_PM_SNOOZE_ENABLE:
-               IWL_DEBUG_POWER(mvm, "snooze_enable=%d\n", val);
-               dbgfs_pm->snooze_ena = val;
-               break;
-       }
-}
-
-static ssize_t iwl_dbgfs_pm_params_write(struct file *file,
-                                        const char __user *user_buf,
-                                        size_t count, loff_t *ppos)
-{
-       struct ieee80211_vif *vif = file->private_data;
-       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-       struct iwl_mvm *mvm = mvmvif->dbgfs_data;
-       enum iwl_dbgfs_pm_mask param;
-       char buf[32] = {};
-       int val;
-       int ret;
-
-       count = min_t(size_t, count, sizeof(buf) - 1);
-       if (copy_from_user(buf, user_buf, count))
-               return -EFAULT;
-
-       if (!strncmp("keep_alive=", buf, 11)) {
-               if (sscanf(buf + 11, "%d", &val) != 1)
-                       return -EINVAL;
-               param = MVM_DEBUGFS_PM_KEEP_ALIVE;
-       } else if (!strncmp("skip_over_dtim=", buf, 15)) {
-               if (sscanf(buf + 15, "%d", &val) != 1)
-                       return -EINVAL;
-               param = MVM_DEBUGFS_PM_SKIP_OVER_DTIM;
-       } else if (!strncmp("skip_dtim_periods=", buf, 18)) {
-               if (sscanf(buf + 18, "%d", &val) != 1)
-                       return -EINVAL;
-               param = MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS;
-       } else if (!strncmp("rx_data_timeout=", buf, 16)) {
-               if (sscanf(buf + 16, "%d", &val) != 1)
-                       return -EINVAL;
-               param = MVM_DEBUGFS_PM_RX_DATA_TIMEOUT;
-       } else if (!strncmp("tx_data_timeout=", buf, 16)) {
-               if (sscanf(buf + 16, "%d", &val) != 1)
-                       return -EINVAL;
-               param = MVM_DEBUGFS_PM_TX_DATA_TIMEOUT;
-       } else if (!strncmp("disable_power_off=", buf, 18) &&
-                  !(mvm->fw->ucode_capa.flags &
-                    IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD)) {
-               if (sscanf(buf + 18, "%d", &val) != 1)
-                       return -EINVAL;
-               param = MVM_DEBUGFS_PM_DISABLE_POWER_OFF;
-       } else if (!strncmp("lprx=", buf, 5)) {
-               if (sscanf(buf + 5, "%d", &val) != 1)
-                       return -EINVAL;
-               param = MVM_DEBUGFS_PM_LPRX_ENA;
-       } else if (!strncmp("lprx_rssi_threshold=", buf, 20)) {
-               if (sscanf(buf + 20, "%d", &val) != 1)
-                       return -EINVAL;
-               if (val > POWER_LPRX_RSSI_THRESHOLD_MAX || val <
-                   POWER_LPRX_RSSI_THRESHOLD_MIN)
-                       return -EINVAL;
-               param = MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD;
-       } else if (!strncmp("snooze_enable=", buf, 14)) {
-               if (sscanf(buf + 14, "%d", &val) != 1)
-                       return -EINVAL;
-               param = MVM_DEBUGFS_PM_SNOOZE_ENABLE;
-       } else {
-               return -EINVAL;
-       }
-
-       mutex_lock(&mvm->mutex);
-       iwl_dbgfs_update_pm(mvm, vif, param, val);
-       ret = iwl_mvm_power_update_mode(mvm, vif);
-       mutex_unlock(&mvm->mutex);
-
-       return ret ?: count;
-}
-
-static ssize_t iwl_dbgfs_pm_params_read(struct file *file,
-                                       char __user *user_buf,
-                                       size_t count, loff_t *ppos)
-{
-       struct ieee80211_vif *vif = file->private_data;
-       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-       struct iwl_mvm *mvm = mvmvif->dbgfs_data;
-       char buf[512];
-       int bufsz = sizeof(buf);
-       int pos;
-
-       pos = iwl_mvm_power_dbgfs_read(mvm, vif, buf, bufsz);
-
-       return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-}
-
-static ssize_t iwl_dbgfs_mac_params_read(struct file *file,
-                                        char __user *user_buf,
-                                        size_t count, loff_t *ppos)
-{
-       struct ieee80211_vif *vif = file->private_data;
-       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-       struct iwl_mvm *mvm = mvmvif->dbgfs_data;
-       u8 ap_sta_id;
-       struct ieee80211_chanctx_conf *chanctx_conf;
-       char buf[512];
-       int bufsz = sizeof(buf);
-       int pos = 0;
-       int i;
-
-       mutex_lock(&mvm->mutex);
-
-       ap_sta_id = mvmvif->ap_sta_id;
-
-       pos += scnprintf(buf+pos, bufsz-pos, "mac id/color: %d / %d\n",
-                        mvmvif->id, mvmvif->color);
-       pos += scnprintf(buf+pos, bufsz-pos, "bssid: %pM\n",
-                        vif->bss_conf.bssid);
-       pos += scnprintf(buf+pos, bufsz-pos, "QoS:\n");
-       for (i = 0; i < ARRAY_SIZE(mvmvif->queue_params); i++) {
-               pos += scnprintf(buf+pos, bufsz-pos,
-                                "\t%d: txop:%d - cw_min:%d - cw_max = %d - aifs = %d upasd = %d\n",
-                                i, mvmvif->queue_params[i].txop,
-                                mvmvif->queue_params[i].cw_min,
-                                mvmvif->queue_params[i].cw_max,
-                                mvmvif->queue_params[i].aifs,
-                                mvmvif->queue_params[i].uapsd);
-       }
-
-       if (vif->type == NL80211_IFTYPE_STATION &&
-           ap_sta_id != IWL_MVM_STATION_COUNT) {
-               struct ieee80211_sta *sta;
-               struct iwl_mvm_sta *mvm_sta;
-
-               sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[ap_sta_id],
-                                               lockdep_is_held(&mvm->mutex));
-               mvm_sta = (void *)sta->drv_priv;
-               pos += scnprintf(buf+pos, bufsz-pos,
-                                "ap_sta_id %d - reduced Tx power %d\n",
-                                ap_sta_id, mvm_sta->bt_reduced_txpower);
-       }
-
-       rcu_read_lock();
-       chanctx_conf = rcu_dereference(vif->chanctx_conf);
-       if (chanctx_conf) {
-               pos += scnprintf(buf+pos, bufsz-pos,
-                                "idle rx chains %d, active rx chains: %d\n",
-                                chanctx_conf->rx_chains_static,
-                                chanctx_conf->rx_chains_dynamic);
-       }
-       rcu_read_unlock();
-
-       mutex_unlock(&mvm->mutex);
-
-       return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-}
-
 #define BT_MBOX_MSG(_notif, _num, _field)                                   \
        ((le32_to_cpu((_notif)->mbox_msg[(_num)]) & BT_MBOX##_num##_##_field)\
        >> BT_MBOX##_num##_##_field##_POS)
@@ -779,11 +539,9 @@ static ssize_t iwl_dbgfs_fw_rx_stats_read(struct file *file,
 }
 #undef PRINT_STAT_LE32
 
-static ssize_t iwl_dbgfs_fw_restart_write(struct file *file,
-                                         const char __user *user_buf,
+static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf,
                                          size_t count, loff_t *ppos)
 {
-       struct iwl_mvm *mvm = file->private_data;
        int ret;
 
        mutex_lock(&mvm->mutex);
@@ -800,6 +558,14 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct file *file,
        return count;
 }
 
+static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf,
+                                     size_t count, loff_t *ppos)
+{
+       iwl_write_prph(mvm->trans, DEVICE_SET_NMI_REG, 1);
+
+       return count;
+}
+
 static ssize_t
 iwl_dbgfs_scan_ant_rxchain_read(struct file *file,
                                char __user *user_buf,
@@ -824,21 +590,11 @@ iwl_dbgfs_scan_ant_rxchain_read(struct file *file,
 }
 
 static ssize_t
-iwl_dbgfs_scan_ant_rxchain_write(struct file *file,
-                                const char __user *user_buf,
+iwl_dbgfs_scan_ant_rxchain_write(struct iwl_mvm *mvm, char *buf,
                                 size_t count, loff_t *ppos)
 {
-       struct iwl_mvm *mvm = file->private_data;
-       char buf[8];
-       int buf_size;
        u8 scan_rx_ant;
 
-       memset(buf, 0, sizeof(buf));
-       buf_size = min(count, sizeof(buf) - 1);
-
-       /* get the argument from the user and check if it is valid */
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
        if (sscanf(buf, "%hhx", &scan_rx_ant) != 1)
                return -EINVAL;
        if (scan_rx_ant > ANT_ABC)
@@ -846,228 +602,17 @@ iwl_dbgfs_scan_ant_rxchain_write(struct file *file,
        if (scan_rx_ant & ~iwl_fw_valid_rx_ant(mvm->fw))
                return -EINVAL;
 
-       /* change the rx antennas for scan command */
        mvm->scan_rx_ant = scan_rx_ant;
 
        return count;
 }
 
-
-static void iwl_dbgfs_update_bf(struct ieee80211_vif *vif,
-                               enum iwl_dbgfs_bf_mask param, int value)
-{
-       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-       struct iwl_dbgfs_bf *dbgfs_bf = &mvmvif->dbgfs_bf;
-
-       dbgfs_bf->mask |= param;
-
-       switch (param) {
-       case MVM_DEBUGFS_BF_ENERGY_DELTA:
-               dbgfs_bf->bf_energy_delta = value;
-               break;
-       case MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA:
-               dbgfs_bf->bf_roaming_energy_delta = value;
-               break;
-       case MVM_DEBUGFS_BF_ROAMING_STATE:
-               dbgfs_bf->bf_roaming_state = value;
-               break;
-       case MVM_DEBUGFS_BF_TEMP_THRESHOLD:
-               dbgfs_bf->bf_temp_threshold = value;
-               break;
-       case MVM_DEBUGFS_BF_TEMP_FAST_FILTER:
-               dbgfs_bf->bf_temp_fast_filter = value;
-               break;
-       case MVM_DEBUGFS_BF_TEMP_SLOW_FILTER:
-               dbgfs_bf->bf_temp_slow_filter = value;
-               break;
-       case MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER:
-               dbgfs_bf->bf_enable_beacon_filter = value;
-               break;
-       case MVM_DEBUGFS_BF_DEBUG_FLAG:
-               dbgfs_bf->bf_debug_flag = value;
-               break;
-       case MVM_DEBUGFS_BF_ESCAPE_TIMER:
-               dbgfs_bf->bf_escape_timer = value;
-               break;
-       case MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT:
-               dbgfs_bf->ba_enable_beacon_abort = value;
-               break;
-       case MVM_DEBUGFS_BA_ESCAPE_TIMER:
-               dbgfs_bf->ba_escape_timer = value;
-               break;
-       }
-}
-
-static ssize_t iwl_dbgfs_bf_params_write(struct file *file,
-                                        const char __user *user_buf,
-                                        size_t count, loff_t *ppos)
-{
-       struct ieee80211_vif *vif = file->private_data;
-       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-       struct iwl_mvm *mvm = mvmvif->dbgfs_data;
-       enum iwl_dbgfs_bf_mask param;
-       char buf[256];
-       int buf_size;
-       int value;
-       int ret = 0;
-
-       memset(buf, 0, sizeof(buf));
-       buf_size = min(count, sizeof(buf) - 1);
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
-
-       if (!strncmp("bf_energy_delta=", buf, 16)) {
-               if (sscanf(buf+16, "%d", &value) != 1)
-                       return -EINVAL;
-               if (value < IWL_BF_ENERGY_DELTA_MIN ||
-                   value > IWL_BF_ENERGY_DELTA_MAX)
-                       return -EINVAL;
-               param = MVM_DEBUGFS_BF_ENERGY_DELTA;
-       } else if (!strncmp("bf_roaming_energy_delta=", buf, 24)) {
-               if (sscanf(buf+24, "%d", &value) != 1)
-                       return -EINVAL;
-               if (value < IWL_BF_ROAMING_ENERGY_DELTA_MIN ||
-                   value > IWL_BF_ROAMING_ENERGY_DELTA_MAX)
-                       return -EINVAL;
-               param = MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA;
-       } else if (!strncmp("bf_roaming_state=", buf, 17)) {
-               if (sscanf(buf+17, "%d", &value) != 1)
-                       return -EINVAL;
-               if (value < IWL_BF_ROAMING_STATE_MIN ||
-                   value > IWL_BF_ROAMING_STATE_MAX)
-                       return -EINVAL;
-               param = MVM_DEBUGFS_BF_ROAMING_STATE;
-       } else if (!strncmp("bf_temp_threshold=", buf, 18)) {
-               if (sscanf(buf+18, "%d", &value) != 1)
-                       return -EINVAL;
-               if (value < IWL_BF_TEMP_THRESHOLD_MIN ||
-                   value > IWL_BF_TEMP_THRESHOLD_MAX)
-                       return -EINVAL;
-               param = MVM_DEBUGFS_BF_TEMP_THRESHOLD;
-       } else if (!strncmp("bf_temp_fast_filter=", buf, 20)) {
-               if (sscanf(buf+20, "%d", &value) != 1)
-                       return -EINVAL;
-               if (value < IWL_BF_TEMP_FAST_FILTER_MIN ||
-                   value > IWL_BF_TEMP_FAST_FILTER_MAX)
-                       return -EINVAL;
-               param = MVM_DEBUGFS_BF_TEMP_FAST_FILTER;
-       } else if (!strncmp("bf_temp_slow_filter=", buf, 20)) {
-               if (sscanf(buf+20, "%d", &value) != 1)
-                       return -EINVAL;
-               if (value < IWL_BF_TEMP_SLOW_FILTER_MIN ||
-                   value > IWL_BF_TEMP_SLOW_FILTER_MAX)
-                       return -EINVAL;
-               param = MVM_DEBUGFS_BF_TEMP_SLOW_FILTER;
-       } else if (!strncmp("bf_enable_beacon_filter=", buf, 24)) {
-               if (sscanf(buf+24, "%d", &value) != 1)
-                       return -EINVAL;
-               if (value < 0 || value > 1)
-                       return -EINVAL;
-               param = MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER;
-       } else if (!strncmp("bf_debug_flag=", buf, 14)) {
-               if (sscanf(buf+14, "%d", &value) != 1)
-                       return -EINVAL;
-               if (value < 0 || value > 1)
-                       return -EINVAL;
-               param = MVM_DEBUGFS_BF_DEBUG_FLAG;
-       } else if (!strncmp("bf_escape_timer=", buf, 16)) {
-               if (sscanf(buf+16, "%d", &value) != 1)
-                       return -EINVAL;
-               if (value < IWL_BF_ESCAPE_TIMER_MIN ||
-                   value > IWL_BF_ESCAPE_TIMER_MAX)
-                       return -EINVAL;
-               param = MVM_DEBUGFS_BF_ESCAPE_TIMER;
-       } else if (!strncmp("ba_escape_timer=", buf, 16)) {
-               if (sscanf(buf+16, "%d", &value) != 1)
-                       return -EINVAL;
-               if (value < IWL_BA_ESCAPE_TIMER_MIN ||
-                   value > IWL_BA_ESCAPE_TIMER_MAX)
-                       return -EINVAL;
-               param = MVM_DEBUGFS_BA_ESCAPE_TIMER;
-       } else if (!strncmp("ba_enable_beacon_abort=", buf, 23)) {
-               if (sscanf(buf+23, "%d", &value) != 1)
-                       return -EINVAL;
-               if (value < 0 || value > 1)
-                       return -EINVAL;
-               param = MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT;
-       } else {
-               return -EINVAL;
-       }
-
-       mutex_lock(&mvm->mutex);
-       iwl_dbgfs_update_bf(vif, param, value);
-       if (param == MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER && !value) {
-               ret = iwl_mvm_disable_beacon_filter(mvm, vif);
-       } else {
-               ret = iwl_mvm_enable_beacon_filter(mvm, vif);
-       }
-       mutex_unlock(&mvm->mutex);
-
-       return ret ?: count;
-}
-
-static ssize_t iwl_dbgfs_bf_params_read(struct file *file,
-                                       char __user *user_buf,
-                                       size_t count, loff_t *ppos)
-{
-       struct ieee80211_vif *vif = file->private_data;
-       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-       char buf[256];
-       int pos = 0;
-       const size_t bufsz = sizeof(buf);
-       struct iwl_beacon_filter_cmd cmd = {
-               IWL_BF_CMD_CONFIG_DEFAULTS,
-               .bf_enable_beacon_filter =
-                       cpu_to_le32(IWL_BF_ENABLE_BEACON_FILTER_DEFAULT),
-               .ba_enable_beacon_abort =
-                       cpu_to_le32(IWL_BA_ENABLE_BEACON_ABORT_DEFAULT),
-       };
-
-       iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd);
-       if (mvmvif->bf_data.bf_enabled)
-               cmd.bf_enable_beacon_filter = cpu_to_le32(1);
-       else
-               cmd.bf_enable_beacon_filter = 0;
-
-       pos += scnprintf(buf+pos, bufsz-pos, "bf_energy_delta = %d\n",
-                        le32_to_cpu(cmd.bf_energy_delta));
-       pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_energy_delta = %d\n",
-                        le32_to_cpu(cmd.bf_roaming_energy_delta));
-       pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_state = %d\n",
-                        le32_to_cpu(cmd.bf_roaming_state));
-       pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_threshold = %d\n",
-                        le32_to_cpu(cmd.bf_temp_threshold));
-       pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_fast_filter = %d\n",
-                        le32_to_cpu(cmd.bf_temp_fast_filter));
-       pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_slow_filter = %d\n",
-                        le32_to_cpu(cmd.bf_temp_slow_filter));
-       pos += scnprintf(buf+pos, bufsz-pos, "bf_enable_beacon_filter = %d\n",
-                        le32_to_cpu(cmd.bf_enable_beacon_filter));
-       pos += scnprintf(buf+pos, bufsz-pos, "bf_debug_flag = %d\n",
-                        le32_to_cpu(cmd.bf_debug_flag));
-       pos += scnprintf(buf+pos, bufsz-pos, "bf_escape_timer = %d\n",
-                        le32_to_cpu(cmd.bf_escape_timer));
-       pos += scnprintf(buf+pos, bufsz-pos, "ba_escape_timer = %d\n",
-                        le32_to_cpu(cmd.ba_escape_timer));
-       pos += scnprintf(buf+pos, bufsz-pos, "ba_enable_beacon_abort = %d\n",
-                        le32_to_cpu(cmd.ba_enable_beacon_abort));
-
-       return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-}
-
 #ifdef CONFIG_PM_SLEEP
-static ssize_t iwl_dbgfs_d3_sram_write(struct file *file,
-                                      const char __user *user_buf,
+static ssize_t iwl_dbgfs_d3_sram_write(struct iwl_mvm *mvm, char *buf,
                                       size_t count, loff_t *ppos)
 {
-       struct iwl_mvm *mvm = file->private_data;
-       char buf[8] = {};
        int store;
 
-       count = min_t(size_t, count, sizeof(buf) - 1);
-       if (copy_from_user(buf, user_buf, count))
-               return -EFAULT;
-
        if (sscanf(buf, "%d", &store) != 1)
                return -EINVAL;
 
@@ -1120,61 +665,33 @@ static ssize_t iwl_dbgfs_d3_sram_read(struct file *file, char __user *user_buf,
 }
 #endif
 
-#define MVM_DEBUGFS_READ_FILE_OPS(name)                                        \
-static const struct file_operations iwl_dbgfs_##name##_ops = { \
-       .read = iwl_dbgfs_##name##_read,                                \
-       .open = simple_open,                                            \
-       .llseek = generic_file_llseek,                                  \
-}
-
-#define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name)                          \
-static const struct file_operations iwl_dbgfs_##name##_ops = { \
-       .write = iwl_dbgfs_##name##_write,                              \
-       .read = iwl_dbgfs_##name##_read,                                \
-       .open = simple_open,                                            \
-       .llseek = generic_file_llseek,                                  \
-};
-
-#define MVM_DEBUGFS_WRITE_FILE_OPS(name)                               \
-static const struct file_operations iwl_dbgfs_##name##_ops = { \
-       .write = iwl_dbgfs_##name##_write,                              \
-       .open = simple_open,                                            \
-       .llseek = generic_file_llseek,                                  \
-};
-
+#define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \
+       _MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct iwl_mvm)
+#define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \
+       _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct iwl_mvm)
 #define MVM_DEBUGFS_ADD_FILE(name, parent, mode) do {                  \
                if (!debugfs_create_file(#name, mode, parent, mvm,      \
                                         &iwl_dbgfs_##name##_ops))      \
                        goto err;                                       \
        } while (0)
 
-#define MVM_DEBUGFS_ADD_FILE_VIF(name, parent, mode) do {              \
-               if (!debugfs_create_file(#name, mode, parent, vif,      \
-                                        &iwl_dbgfs_##name##_ops))      \
-                       goto err;                                       \
-       } while (0)
-
 /* Device wide debugfs entries */
-MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush);
-MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain);
-MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram);
+MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush, 16);
+MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain, 8);
+MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram, 64);
 MVM_DEBUGFS_READ_FILE_OPS(stations);
 MVM_DEBUGFS_READ_FILE_OPS(bt_notif);
 MVM_DEBUGFS_READ_FILE_OPS(bt_cmd);
-MVM_DEBUGFS_READ_WRITE_FILE_OPS(disable_power_off);
+MVM_DEBUGFS_READ_WRITE_FILE_OPS(disable_power_off, 64);
 MVM_DEBUGFS_READ_FILE_OPS(fw_rx_stats);
-MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart);
-MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain);
+MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart, 10);
+MVM_DEBUGFS_WRITE_FILE_OPS(fw_nmi, 10);
+MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8);
 
 #ifdef CONFIG_PM_SLEEP
-MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram);
+MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram, 8);
 #endif
 
-/* Interface specific debugfs entries */
-MVM_DEBUGFS_READ_FILE_OPS(mac_params);
-MVM_DEBUGFS_READ_WRITE_FILE_OPS(pm_params);
-MVM_DEBUGFS_READ_WRITE_FILE_OPS(bf_params);
-
 int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
 {
        char buf[100];
@@ -1192,6 +709,7 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
                                     S_IRUSR | S_IWUSR);
        MVM_DEBUGFS_ADD_FILE(fw_rx_stats, mvm->debugfs_dir, S_IRUSR);
        MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR);
+       MVM_DEBUGFS_ADD_FILE(fw_nmi, mvm->debugfs_dir, S_IWUSR);
        MVM_DEBUGFS_ADD_FILE(scan_ant_rxchain, mvm->debugfs_dir,
                             S_IWUSR | S_IRUSR);
 #ifdef CONFIG_PM_SLEEP
@@ -1202,6 +720,19 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
                goto err;
 #endif
 
+       if (!debugfs_create_blob("nvm_hw", S_IRUSR,
+                                 mvm->debugfs_dir, &mvm->nvm_hw_blob))
+               goto err;
+       if (!debugfs_create_blob("nvm_sw", S_IRUSR,
+                                 mvm->debugfs_dir, &mvm->nvm_sw_blob))
+               goto err;
+       if (!debugfs_create_blob("nvm_calib", S_IRUSR,
+                                 mvm->debugfs_dir, &mvm->nvm_calib_blob))
+               goto err;
+       if (!debugfs_create_blob("nvm_prod", S_IRUSR,
+                                 mvm->debugfs_dir, &mvm->nvm_prod_blob))
+               goto err;
+
        /*
         * Create a symlink with mac80211. It will be removed when mac80211
         * exists (before the opmode exists which removes the target.)
@@ -1217,72 +748,3 @@ err:
        IWL_ERR(mvm, "Can't create the mvm debugfs directory\n");
        return -ENOMEM;
 }
-
-void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
-{
-       struct dentry *dbgfs_dir = vif->debugfs_dir;
-       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-       char buf[100];
-
-       /*
-        * Check if debugfs directory already exist before creating it.
-        * This may happen when, for example, resetting hw or suspend-resume
-        */
-       if (!dbgfs_dir || mvmvif->dbgfs_dir)
-               return;
-
-       mvmvif->dbgfs_dir = debugfs_create_dir("iwlmvm", dbgfs_dir);
-       mvmvif->dbgfs_data = mvm;
-
-       if (!mvmvif->dbgfs_dir) {
-               IWL_ERR(mvm, "Failed to create debugfs directory under %s\n",
-                       dbgfs_dir->d_name.name);
-               return;
-       }
-
-       if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM &&
-           vif->type == NL80211_IFTYPE_STATION && !vif->p2p)
-               MVM_DEBUGFS_ADD_FILE_VIF(pm_params, mvmvif->dbgfs_dir, S_IWUSR |
-                                        S_IRUSR);
-
-       MVM_DEBUGFS_ADD_FILE_VIF(mac_params, mvmvif->dbgfs_dir,
-                                S_IRUSR);
-
-       if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p &&
-           mvmvif == mvm->bf_allowed_vif)
-               MVM_DEBUGFS_ADD_FILE_VIF(bf_params, mvmvif->dbgfs_dir,
-                                        S_IRUSR | S_IWUSR);
-
-       /*
-        * Create symlink for convenience pointing to interface specific
-        * debugfs entries for the driver. For example, under
-        * /sys/kernel/debug/iwlwifi/0000\:02\:00.0/iwlmvm/
-        * find
-        * netdev:wlan0 -> ../../../ieee80211/phy0/netdev:wlan0/iwlmvm/
-        */
-       snprintf(buf, 100, "../../../%s/%s/%s/%s",
-                dbgfs_dir->d_parent->d_parent->d_name.name,
-                dbgfs_dir->d_parent->d_name.name,
-                dbgfs_dir->d_name.name,
-                mvmvif->dbgfs_dir->d_name.name);
-
-       mvmvif->dbgfs_slink = debugfs_create_symlink(dbgfs_dir->d_name.name,
-                                                    mvm->debugfs_dir, buf);
-       if (!mvmvif->dbgfs_slink)
-               IWL_ERR(mvm, "Can't create debugfs symbolic link under %s\n",
-                       dbgfs_dir->d_name.name);
-       return;
-err:
-       IWL_ERR(mvm, "Can't create debugfs entity\n");
-}
-
-void iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
-{
-       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-
-       debugfs_remove(mvmvif->dbgfs_slink);
-       mvmvif->dbgfs_slink = NULL;
-
-       debugfs_remove_recursive(mvmvif->dbgfs_dir);
-       mvmvif->dbgfs_dir = NULL;
-}
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.h b/drivers/net/wireless/iwlwifi/mvm/debugfs.h
new file mode 100644 (file)
index 0000000..85f9f95
--- /dev/null
@@ -0,0 +1,101 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+
+#define MVM_DEBUGFS_READ_FILE_OPS(name)                                        \
+static const struct file_operations iwl_dbgfs_##name##_ops = {         \
+       .read = iwl_dbgfs_##name##_read,                                \
+       .open = simple_open,                                            \
+       .llseek = generic_file_llseek,                                  \
+}
+
+#define MVM_DEBUGFS_WRITE_WRAPPER(name, buflen, argtype)               \
+static ssize_t _iwl_dbgfs_##name##_write(struct file *file,            \
+                                        const char __user *user_buf,   \
+                                        size_t count, loff_t *ppos)    \
+{                                                                      \
+       argtype *arg = file->private_data;                              \
+       char buf[buflen] = {};                                          \
+       size_t buf_size = min(count, sizeof(buf) -  1);                 \
+                                                                       \
+       if (copy_from_user(buf, user_buf, buf_size))                    \
+               return -EFAULT;                                         \
+                                                                       \
+       return iwl_dbgfs_##name##_write(arg, buf, buf_size, ppos);      \
+}                                                                      \
+
+#define _MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, buflen, argtype)                \
+MVM_DEBUGFS_WRITE_WRAPPER(name, buflen, argtype)                       \
+static const struct file_operations iwl_dbgfs_##name##_ops = {         \
+       .write = _iwl_dbgfs_##name##_write,                             \
+       .read = iwl_dbgfs_##name##_read,                                \
+       .open = simple_open,                                            \
+       .llseek = generic_file_llseek,                                  \
+};
+
+#define _MVM_DEBUGFS_WRITE_FILE_OPS(name, buflen, argtype)             \
+MVM_DEBUGFS_WRITE_WRAPPER(name, buflen, argtype)                       \
+static const struct file_operations iwl_dbgfs_##name##_ops = {         \
+       .write = _iwl_dbgfs_##name##_write,                             \
+       .open = simple_open,                                            \
+       .llseek = generic_file_llseek,                                  \
+};
index 4ea5e24ca92d8da9a0a366a3ab0e0bf903f55ef1..af500996bbf140e8422f7e6b17e4cf12253c3f8f 100644 (file)
@@ -127,6 +127,7 @@ enum iwl_bt_coex_valid_bit_msk {
        BT_VALID_ANT_ISOLATION_THRS     = BIT(15),
        BT_VALID_TXTX_DELTA_FREQ_THRS   = BIT(16),
        BT_VALID_TXRX_MAX_FREQ_0        = BIT(17),
+       BT_VALID_SYNC_TO_SCO            = BIT(18),
 };
 
 /**
index 538f1c7a59664f9cb7c586eeb0974974c971b6f8..532312c7b93718d3c3a245b893c999459ea90834 100644 (file)
@@ -281,8 +281,31 @@ enum {
 /* # entries in rate scale table to support Tx retries */
 #define  LQ_MAX_RETRY_NUM 16
 
-/* Link quality command flags, only this one is available */
-#define  LQ_FLAG_SET_STA_TLC_RTS_MSK   BIT(0)
+/* Link quality command flags bit fields */
+
+/* Bit 0: (0) Don't use RTS (1) Use RTS */
+#define LQ_FLAG_USE_RTS_POS             0
+#define LQ_FLAG_USE_RTS_MSK            (1 << LQ_FLAG_USE_RTS_POS)
+
+/* Bit 1-3: LQ command color. Used to match responses to LQ commands */
+#define LQ_FLAG_COLOR_POS               1
+#define LQ_FLAG_COLOR_MSK               (7 << LQ_FLAG_COLOR_POS)
+
+/* Bit 4-5: Tx RTS BW Signalling
+ * (0) No RTS BW signalling
+ * (1) Static BW signalling
+ * (2) Dynamic BW signalling
+ */
+#define LQ_FLAG_RTS_BW_SIG_POS          4
+#define LQ_FLAG_RTS_BW_SIG_NONE         (0 << LQ_FLAG_RTS_BW_SIG_POS)
+#define LQ_FLAG_RTS_BW_SIG_STATIC       (1 << LQ_FLAG_RTS_BW_SIG_POS)
+#define LQ_FLAG_RTS_BW_SIG_DYNAMIC      (2 << LQ_FLAG_RTS_BW_SIG_POS)
+
+/* Bit 6: (0) No dynamic BW selection (1) Allow dynamic BW selection
+ * Dyanmic BW selection allows Tx with narrower BW then requested in rates
+ */
+#define LQ_FLAG_DYNAMIC_BW_POS          6
+#define LQ_FLAG_DYNAMIC_BW_MSK          (1 << LQ_FLAG_DYNAMIC_BW_POS)
 
 /**
  * struct iwl_lq_cmd - link quality command
index c3782b48ded14d8a52458f66677dc3d3cd766fd7..b3ed59237cbadfca46f609daec46812ee72ff7e3 100644 (file)
@@ -530,14 +530,13 @@ struct iwl_scan_offload_schedule {
 /*
  * iwl_scan_offload_flags
  *
- * IWL_SCAN_OFFLOAD_FLAG_FILTER_SSID: filter mode - upload every beacon or match
- *     ssid list.
+ * IWL_SCAN_OFFLOAD_FLAG_PASS_ALL: pass all results - no filtering.
  * IWL_SCAN_OFFLOAD_FLAG_CACHED_CHANNEL: add cached channels to partial scan.
  * IWL_SCAN_OFFLOAD_FLAG_ENERGY_SCAN: use energy based scan before partial scan
  *     on A band.
  */
 enum iwl_scan_offload_flags {
-       IWL_SCAN_OFFLOAD_FLAG_FILTER_SSID       = BIT(0),
+       IWL_SCAN_OFFLOAD_FLAG_PASS_ALL          = BIT(0),
        IWL_SCAN_OFFLOAD_FLAG_CACHED_CHANNEL    = BIT(2),
        IWL_SCAN_OFFLOAD_FLAG_ENERGY_SCAN       = BIT(3),
 };
index f41f9b079831cfe7722b4d0c23203640993e7249..fb93961da7500bf1ada5668fb86ef5d4b17c152a 100644 (file)
@@ -488,6 +488,40 @@ static void iwl_mvm_ack_rates(struct iwl_mvm *mvm,
        *ofdm_rates = ofdm;
 }
 
+static void iwl_mvm_mac_ctxt_set_ht_flags(struct iwl_mvm *mvm,
+                                        struct ieee80211_vif *vif,
+                                        struct iwl_mac_ctx_cmd *cmd)
+{
+       /* for both sta and ap, ht_operation_mode hold the protection_mode */
+       u8 protection_mode = vif->bss_conf.ht_operation_mode &
+                                IEEE80211_HT_OP_MODE_PROTECTION;
+       /* The fw does not distinguish between ht and fat */
+       u32 ht_flag = MAC_PROT_FLG_HT_PROT | MAC_PROT_FLG_FAT_PROT;
+
+       IWL_DEBUG_RATE(mvm, "protection mode set to %d\n", protection_mode);
+       /*
+        * See section 9.23.3.1 of IEEE 80211-2012.
+        * Nongreenfield HT STAs Present is not supported.
+        */
+       switch (protection_mode) {
+       case IEEE80211_HT_OP_MODE_PROTECTION_NONE:
+               break;
+       case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER:
+       case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED:
+               cmd->protection_flags |= cpu_to_le32(ht_flag);
+               break;
+       case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:
+               /* Protect when channel wider than 20MHz */
+               if (vif->bss_conf.chandef.width > NL80211_CHAN_WIDTH_20)
+                       cmd->protection_flags |= cpu_to_le32(ht_flag);
+               break;
+       default:
+               IWL_ERR(mvm, "Illegal protection mode %d\n",
+                       protection_mode);
+               break;
+       }
+}
+
 static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
                                        struct ieee80211_vif *vif,
                                        struct iwl_mac_ctx_cmd *cmd,
@@ -495,6 +529,8 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
 {
        struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
        struct ieee80211_chanctx_conf *chanctx;
+       bool ht_enabled = !!(vif->bss_conf.ht_operation_mode &
+                            IEEE80211_HT_OP_MODE_PROTECTION);
        u8 cck_ack_rates, ofdm_ack_rates;
        int i;
 
@@ -573,16 +609,13 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
                        cmd->protection_flags |=
                                cpu_to_le32(MAC_PROT_FLG_SELF_CTS_EN);
        }
-
-       /*
-        * I think that we should enable these 2 flags regardless the HT PROT
-        * fields in the HT IE, but I am not sure. Someone knows whom to ask?...
-        */
-       if (vif->bss_conf.chandef.width != NL80211_CHAN_WIDTH_20_NOHT) {
+       IWL_DEBUG_RATE(mvm, "use_cts_prot %d, ht_operation_mode %d\n",
+                      vif->bss_conf.use_cts_prot,
+                      vif->bss_conf.ht_operation_mode);
+       if (vif->bss_conf.chandef.width != NL80211_CHAN_WIDTH_20_NOHT)
                cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_TGN);
-               cmd->protection_flags |= cpu_to_le32(MAC_PROT_FLG_HT_PROT |
-                                                    MAC_PROT_FLG_FAT_PROT);
-       }
+       if (ht_enabled)
+               iwl_mvm_mac_ctxt_set_ht_flags(mvm, vif, cmd);
 
        cmd->filter_flags = cpu_to_le32(MAC_FILTER_ACCEPT_GRP);
 }
index 74bc2c8af06d62fb360de4357621dca50201a8c2..afc4419be46dd1eaff2f1b419dae01e4b231b1cb 100644 (file)
@@ -199,9 +199,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
        if (IWL_UCODE_API(mvm->fw->ucode_ver) >= 8)
                hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);
 
-       hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
-                           WIPHY_FLAG_DISABLE_BEACON_HINTS |
-                           WIPHY_FLAG_IBSS_RSN;
+       hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
+       hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG |
+                                      REGULATORY_DISABLE_BEACON_HINTS;
 
        hw->wiphy->iface_combinations = iwl_mvm_iface_combinations;
        hw->wiphy->n_iface_combinations =
@@ -256,7 +256,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
        }
 
        hw->wiphy->features |= NL80211_FEATURE_P2P_GO_CTWIN |
-                              NL80211_FEATURE_P2P_GO_OPPPS;
+                              NL80211_FEATURE_P2P_GO_OPPPS |
+                              NL80211_FEATURE_LOW_PRIORITY_SCAN;
 
        mvm->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
 
@@ -990,6 +991,17 @@ iwl_mvm_bss_info_changed_ap_ibss(struct iwl_mvm *mvm,
                                 struct ieee80211_bss_conf *bss_conf,
                                 u32 changes)
 {
+       enum ieee80211_bss_change ht_change = BSS_CHANGED_ERP_CTS_PROT |
+                                             BSS_CHANGED_HT |
+                                             BSS_CHANGED_BANDWIDTH;
+       int ret;
+
+       if (changes & ht_change) {
+               ret = iwl_mvm_mac_ctxt_changed(mvm, vif);
+               if (ret)
+                       IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);
+       }
+
        /* Need to send a new beacon template to the FW */
        if (changes & BSS_CHANGED_BEACON) {
                if (iwl_mvm_mac_ctxt_beacon_changed(mvm, vif))
@@ -1080,7 +1092,7 @@ static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
                                   struct ieee80211_sta *sta)
 {
        struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
-       struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv;
+       struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
 
        switch (cmd) {
        case STA_NOTIFY_SLEEP:
@@ -1149,7 +1161,8 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
                ret = iwl_mvm_update_sta(mvm, vif, sta);
                if (ret == 0)
                        iwl_mvm_rs_rate_init(mvm, sta,
-                                            mvmvif->phy_ctxt->channel->band);
+                                            mvmvif->phy_ctxt->channel->band,
+                                            true);
        } else if (old_state == IEEE80211_STA_ASSOC &&
                   new_state == IEEE80211_STA_AUTHORIZED) {
                /* enable beacon filtering */
index fed21ef4162d231102ab7ae76e3229ac24a86f1f..7dc57cfe58035cfc5128e1fa8f3969f46584d7c9 100644 (file)
@@ -323,9 +323,9 @@ struct iwl_mvm_vif {
 #endif
 
 #ifdef CONFIG_IWLWIFI_DEBUGFS
+       struct iwl_mvm *mvm;
        struct dentry *dbgfs_dir;
        struct dentry *dbgfs_slink;
-       void *dbgfs_data;
        struct iwl_dbgfs_pm dbgfs_pm;
        struct iwl_dbgfs_bf dbgfs_bf;
 #endif
@@ -494,6 +494,11 @@ struct iwl_mvm {
        u32 dbgfs_sram_offset, dbgfs_sram_len;
        bool disable_power_off;
        bool disable_power_off_d3;
+
+       struct debugfs_blob_wrapper nvm_hw_blob;
+       struct debugfs_blob_wrapper nvm_sw_blob;
+       struct debugfs_blob_wrapper nvm_calib_blob;
+       struct debugfs_blob_wrapper nvm_prod_blob;
 #endif
 
        struct iwl_mvm_phy_ctxt phy_ctxts[NUM_PHY_CTX];
@@ -531,6 +536,7 @@ struct iwl_mvm {
        bool store_d3_resume_sram;
        void *d3_resume_sram;
        u32 d3_test_pme_ptr;
+       struct ieee80211_vif *keep_vif;
 #endif
 #endif
 
@@ -750,8 +756,7 @@ iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
 #endif /* CONFIG_IWLWIFI_DEBUGFS */
 
 /* rate scaling */
-int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq,
-                       u8 flags, bool init);
+int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, bool init);
 
 /* power managment */
 static inline int iwl_mvm_power_update_mode(struct iwl_mvm *mvm,
index 2beffd028b67cef7469faa40899b6b6992501976..48089b1625fff7c1dfc804c6f84a9e68ae56d282 100644 (file)
@@ -443,6 +443,29 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
                        }
                        mvm->nvm_sections[section].data = temp;
                        mvm->nvm_sections[section].length = ret;
+
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+                       switch (section) {
+                       case NVM_SECTION_TYPE_HW:
+                               mvm->nvm_hw_blob.data = temp;
+                               mvm->nvm_hw_blob.size = ret;
+                               break;
+                       case NVM_SECTION_TYPE_SW:
+                               mvm->nvm_sw_blob.data = temp;
+                               mvm->nvm_sw_blob.size  = ret;
+                               break;
+                       case NVM_SECTION_TYPE_CALIBRATION:
+                               mvm->nvm_calib_blob.data = temp;
+                               mvm->nvm_calib_blob.size  = ret;
+                               break;
+                       case NVM_SECTION_TYPE_PRODUCTION:
+                               mvm->nvm_prod_blob.data = temp;
+                               mvm->nvm_prod_blob.size  = ret;
+                               break;
+                       default:
+                               WARN(1, "section: %d", section);
+                       }
+#endif
                }
                kfree(nvm_buffer);
                if (ret < 0)
index 17e2bc827f9a3b20b7da9e0d7ee4dd43ac00606a..38165eba2a177da38eb564258a36d81f641e445a 100644 (file)
@@ -217,8 +217,7 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif)
                } else {
                        cmd.quotas[idx].quota =
                                cpu_to_le32(quota * data.n_interfaces[i]);
-                       cmd.quotas[idx].max_duration =
-                               cpu_to_le32(IWL_MVM_MAX_QUOTA);
+                       cmd.quotas[idx].max_duration = cpu_to_le32(0);
                }
                idx++;
        }
index a0b4cc8d9c3b412c931d04606d02b72c4d769e61..bf6e29f5b4d0af23d6422f73f07fa13163936d35 100644 (file)
 #define IWL_HT_NUMBER_TRY   3
 
 #define IWL_RATE_MAX_WINDOW            62      /* # tx in history window */
-#define IWL_RATE_MIN_FAILURE_TH                6       /* min failures to calc tpt */
+#define IWL_RATE_MIN_FAILURE_TH                3       /* min failures to calc tpt */
 #define IWL_RATE_MIN_SUCCESS_TH                8       /* min successes to calc tpt */
 
 /* max allowed rate miss before sync LQ cmd */
 #define IWL_MISSED_RATE_MAX            15
-/* max time to accum history 2 seconds */
-#define IWL_RATE_SCALE_FLUSH_INTVL   (3*HZ)
+#define RS_STAY_IN_COLUMN_TIMEOUT       (5*HZ)
+
 
 static u8 rs_ht_to_legacy[] = {
-       [IWL_RATE_1M_INDEX] = IWL_RATE_6M_INDEX,
-       [IWL_RATE_2M_INDEX] = IWL_RATE_6M_INDEX,
-       [IWL_RATE_5M_INDEX] = IWL_RATE_6M_INDEX,
-       [IWL_RATE_11M_INDEX] = IWL_RATE_6M_INDEX,
-       [IWL_RATE_6M_INDEX] = IWL_RATE_6M_INDEX,
-       [IWL_RATE_9M_INDEX] = IWL_RATE_6M_INDEX,
-       [IWL_RATE_12M_INDEX] = IWL_RATE_9M_INDEX,
-       [IWL_RATE_18M_INDEX] = IWL_RATE_12M_INDEX,
-       [IWL_RATE_24M_INDEX] = IWL_RATE_18M_INDEX,
-       [IWL_RATE_36M_INDEX] = IWL_RATE_24M_INDEX,
-       [IWL_RATE_48M_INDEX] = IWL_RATE_36M_INDEX,
-       [IWL_RATE_54M_INDEX] = IWL_RATE_48M_INDEX,
-       [IWL_RATE_60M_INDEX] = IWL_RATE_54M_INDEX,
+       [IWL_RATE_MCS_0_INDEX] = IWL_RATE_6M_INDEX,
+       [IWL_RATE_MCS_1_INDEX] = IWL_RATE_9M_INDEX,
+       [IWL_RATE_MCS_2_INDEX] = IWL_RATE_12M_INDEX,
+       [IWL_RATE_MCS_3_INDEX] = IWL_RATE_18M_INDEX,
+       [IWL_RATE_MCS_4_INDEX] = IWL_RATE_24M_INDEX,
+       [IWL_RATE_MCS_5_INDEX] = IWL_RATE_36M_INDEX,
+       [IWL_RATE_MCS_6_INDEX] = IWL_RATE_48M_INDEX,
+       [IWL_RATE_MCS_7_INDEX] = IWL_RATE_54M_INDEX,
+       [IWL_RATE_MCS_8_INDEX] = IWL_RATE_54M_INDEX,
+       [IWL_RATE_MCS_9_INDEX] = IWL_RATE_54M_INDEX,
 };
 
 static const u8 ant_toggle_lookup[] = {
@@ -126,6 +123,190 @@ static const struct iwl_rs_rate_info iwl_rates[IWL_RATE_COUNT] = {
        IWL_DECLARE_MCS_RATE(9),                 /* MCS 9 */
 };
 
+enum rs_column_mode {
+       RS_INVALID = 0,
+       RS_LEGACY,
+       RS_SISO,
+       RS_MIMO2,
+};
+
+#define MAX_NEXT_COLUMNS 5
+#define MAX_COLUMN_CHECKS 3
+
+typedef bool (*allow_column_func_t) (struct iwl_mvm *mvm,
+                                    struct ieee80211_sta *sta,
+                                    struct iwl_scale_tbl_info *tbl);
+
+struct rs_tx_column {
+       enum rs_column_mode mode;
+       u8 ant;
+       bool sgi;
+       enum rs_column next_columns[MAX_NEXT_COLUMNS];
+       allow_column_func_t checks[MAX_COLUMN_CHECKS];
+};
+
+static bool rs_mimo_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
+                         struct iwl_scale_tbl_info *tbl)
+{
+       if (!sta->ht_cap.ht_supported)
+               return false;
+
+       if (sta->smps_mode == IEEE80211_SMPS_STATIC)
+               return false;
+
+       if (num_of_ant(iwl_fw_valid_tx_ant(mvm->fw)) < 2)
+               return false;
+
+       if (!iwl_mvm_bt_coex_is_mimo_allowed(mvm, sta))
+               return false;
+
+       return true;
+}
+
+static bool rs_siso_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
+                         struct iwl_scale_tbl_info *tbl)
+{
+       if (!sta->ht_cap.ht_supported)
+               return false;
+
+       return true;
+}
+
+static bool rs_sgi_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
+                        struct iwl_scale_tbl_info *tbl)
+{
+       struct rs_rate *rate = &tbl->rate;
+       struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
+       struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
+
+       if (is_ht20(rate) && (ht_cap->cap &
+                            IEEE80211_HT_CAP_SGI_20))
+               return true;
+       if (is_ht40(rate) && (ht_cap->cap &
+                            IEEE80211_HT_CAP_SGI_40))
+               return true;
+       if (is_ht80(rate) && (vht_cap->cap &
+                            IEEE80211_VHT_CAP_SHORT_GI_80))
+               return true;
+
+       return false;
+}
+
+static const struct rs_tx_column rs_tx_columns[] = {
+       [RS_COLUMN_LEGACY_ANT_A] = {
+               .mode = RS_LEGACY,
+               .ant = ANT_A,
+               .next_columns = {
+                       RS_COLUMN_LEGACY_ANT_B,
+                       RS_COLUMN_SISO_ANT_A,
+                       RS_COLUMN_MIMO2,
+                       RS_COLUMN_INVALID,
+                       RS_COLUMN_INVALID,
+               },
+       },
+       [RS_COLUMN_LEGACY_ANT_B] = {
+               .mode = RS_LEGACY,
+               .ant = ANT_B,
+               .next_columns = {
+                       RS_COLUMN_LEGACY_ANT_A,
+                       RS_COLUMN_SISO_ANT_B,
+                       RS_COLUMN_MIMO2,
+                       RS_COLUMN_INVALID,
+                       RS_COLUMN_INVALID,
+               },
+       },
+       [RS_COLUMN_SISO_ANT_A] = {
+               .mode = RS_SISO,
+               .ant = ANT_A,
+               .next_columns = {
+                       RS_COLUMN_SISO_ANT_B,
+                       RS_COLUMN_MIMO2,
+                       RS_COLUMN_SISO_ANT_A_SGI,
+                       RS_COLUMN_INVALID,
+                       RS_COLUMN_INVALID,
+               },
+               .checks = {
+                       rs_siso_allow,
+               },
+       },
+       [RS_COLUMN_SISO_ANT_B] = {
+               .mode = RS_SISO,
+               .ant = ANT_B,
+               .next_columns = {
+                       RS_COLUMN_SISO_ANT_A,
+                       RS_COLUMN_MIMO2,
+                       RS_COLUMN_SISO_ANT_B_SGI,
+                       RS_COLUMN_INVALID,
+                       RS_COLUMN_INVALID,
+               },
+               .checks = {
+                       rs_siso_allow,
+               },
+       },
+       [RS_COLUMN_SISO_ANT_A_SGI] = {
+               .mode = RS_SISO,
+               .ant = ANT_A,
+               .sgi = true,
+               .next_columns = {
+                       RS_COLUMN_SISO_ANT_B_SGI,
+                       RS_COLUMN_MIMO2_SGI,
+                       RS_COLUMN_SISO_ANT_A,
+                       RS_COLUMN_INVALID,
+                       RS_COLUMN_INVALID,
+               },
+               .checks = {
+                       rs_siso_allow,
+                       rs_sgi_allow,
+               },
+       },
+       [RS_COLUMN_SISO_ANT_B_SGI] = {
+               .mode = RS_SISO,
+               .ant = ANT_B,
+               .sgi = true,
+               .next_columns = {
+                       RS_COLUMN_SISO_ANT_A_SGI,
+                       RS_COLUMN_MIMO2_SGI,
+                       RS_COLUMN_SISO_ANT_B,
+                       RS_COLUMN_INVALID,
+                       RS_COLUMN_INVALID,
+               },
+               .checks = {
+                       rs_siso_allow,
+                       rs_sgi_allow,
+               },
+       },
+       [RS_COLUMN_MIMO2] = {
+               .mode = RS_MIMO2,
+               .ant = ANT_AB,
+               .next_columns = {
+                       RS_COLUMN_SISO_ANT_A,
+                       RS_COLUMN_MIMO2_SGI,
+                       RS_COLUMN_INVALID,
+                       RS_COLUMN_INVALID,
+                       RS_COLUMN_INVALID,
+               },
+               .checks = {
+                       rs_mimo_allow,
+               },
+       },
+       [RS_COLUMN_MIMO2_SGI] = {
+               .mode = RS_MIMO2,
+               .ant = ANT_AB,
+               .sgi = true,
+               .next_columns = {
+                       RS_COLUMN_SISO_ANT_A_SGI,
+                       RS_COLUMN_MIMO2,
+                       RS_COLUMN_INVALID,
+                       RS_COLUMN_INVALID,
+                       RS_COLUMN_INVALID,
+               },
+               .checks = {
+                       rs_mimo_allow,
+                       rs_sgi_allow,
+               },
+       },
+};
+
 static inline u8 rs_extract_rate(u32 rate_n_flags)
 {
        /* also works for HT because bits 7:6 are zero there */
@@ -175,7 +356,6 @@ static void rs_fill_link_cmd(struct iwl_mvm *mvm,
                             struct iwl_lq_sta *lq_sta, u32 rate_n_flags);
 static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search);
 
-
 #ifdef CONFIG_MAC80211_DEBUGFS
 static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
                             u32 *rate_n_flags);
@@ -264,6 +444,52 @@ static const struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = {
 
 #define MCS_INDEX_PER_STREAM   (8)
 
+static const char *rs_pretty_ant(u8 ant)
+{
+       static const char * const ant_name[] = {
+               [ANT_NONE] = "None",
+               [ANT_A]    = "A",
+               [ANT_B]    = "B",
+               [ANT_AB]   = "AB",
+               [ANT_C]    = "C",
+               [ANT_AC]   = "AC",
+               [ANT_BC]   = "BC",
+               [ANT_ABC]  = "ABC",
+       };
+
+       if (ant > ANT_ABC)
+               return "UNKNOWN";
+
+       return ant_name[ant];
+}
+
+static const char *rs_pretty_lq_type(enum iwl_table_type type)
+{
+       static const char * const lq_types[] = {
+               [LQ_NONE] = "NONE",
+               [LQ_LEGACY_A] = "LEGACY_A",
+               [LQ_LEGACY_G] = "LEGACY_G",
+               [LQ_HT_SISO] = "HT SISO",
+               [LQ_HT_MIMO2] = "HT MIMO",
+               [LQ_VHT_SISO] = "VHT SISO",
+               [LQ_VHT_MIMO2] = "VHT MIMO",
+       };
+
+       if (type < LQ_NONE || type >= LQ_MAX)
+               return "UNKNOWN";
+
+       return lq_types[type];
+}
+
+static inline void rs_dump_rate(struct iwl_mvm *mvm, const struct rs_rate *rate,
+                               const char *prefix)
+{
+       IWL_DEBUG_RATE(mvm, "%s: (%s: %d) ANT: %s BW: %d SGI: %d\n",
+                      prefix, rs_pretty_lq_type(rate->type),
+                      rate->index, rs_pretty_ant(rate->ant),
+                      rate->bw, rate->sgi);
+}
+
 static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window)
 {
        window->data = 0;
@@ -271,7 +497,6 @@ static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window)
        window->success_ratio = IWL_INVALID_VALUE;
        window->counter = 0;
        window->average_tpt = IWL_INVALID_VALUE;
-       window->stamp = 0;
 }
 
 static inline u8 rs_is_valid_ant(u8 valid_antenna, u8 ant_type)
@@ -298,7 +523,7 @@ static void rs_program_fix_rate(struct iwl_mvm *mvm,
 
        if (lq_sta->dbg_fixed_rate) {
                rs_fill_link_cmd(NULL, NULL, lq_sta, lq_sta->dbg_fixed_rate);
-               iwl_mvm_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC, false);
+               iwl_mvm_send_lq_cmd(lq_sta->drv, &lq_sta->lq, false);
        }
 }
 #endif
@@ -428,192 +653,174 @@ static int rs_collect_tx_data(struct iwl_scale_tbl_info *tbl,
        else
                window->average_tpt = IWL_INVALID_VALUE;
 
-       /* Tag this window as having been updated */
-       window->stamp = jiffies;
-
        return 0;
 }
 
-/*
- * Fill uCode API rate_n_flags field, based on "search" or "active" table.
- */
-/* FIXME:RS:remove this function and put the flags statically in the table */
-static u32 rate_n_flags_from_tbl(struct iwl_mvm *mvm,
-                                struct iwl_scale_tbl_info *tbl, int index)
+/* Convert rs_rate object into ucode rate bitmask */
+static u32 ucode_rate_from_rs_rate(struct iwl_mvm *mvm,
+                                  struct rs_rate *rate)
 {
-       u32 rate_n_flags = 0;
+       u32 ucode_rate = 0;
+       int index = rate->index;
 
-       rate_n_flags |= ((tbl->ant_type << RATE_MCS_ANT_POS) &
+       ucode_rate |= ((rate->ant << RATE_MCS_ANT_POS) &
                         RATE_MCS_ANT_ABC_MSK);
 
-       if (is_legacy(tbl->lq_type)) {
-               rate_n_flags |= iwl_rates[index].plcp;
+       if (is_legacy(rate)) {
+               ucode_rate |= iwl_rates[index].plcp;
                if (index >= IWL_FIRST_CCK_RATE && index <= IWL_LAST_CCK_RATE)
-                       rate_n_flags |= RATE_MCS_CCK_MSK;
-               return rate_n_flags;
+                       ucode_rate |= RATE_MCS_CCK_MSK;
+               return ucode_rate;
        }
 
-       if (is_ht(tbl->lq_type)) {
+       if (is_ht(rate)) {
                if (index < IWL_FIRST_HT_RATE || index > IWL_LAST_HT_RATE) {
                        IWL_ERR(mvm, "Invalid HT rate index %d\n", index);
                        index = IWL_LAST_HT_RATE;
                }
-               rate_n_flags |= RATE_MCS_HT_MSK;
+               ucode_rate |= RATE_MCS_HT_MSK;
 
-               if (is_ht_siso(tbl->lq_type))
-                       rate_n_flags |= iwl_rates[index].plcp_ht_siso;
-               else if (is_ht_mimo2(tbl->lq_type))
-                       rate_n_flags |= iwl_rates[index].plcp_ht_mimo2;
+               if (is_ht_siso(rate))
+                       ucode_rate |= iwl_rates[index].plcp_ht_siso;
+               else if (is_ht_mimo2(rate))
+                       ucode_rate |= iwl_rates[index].plcp_ht_mimo2;
                else
                        WARN_ON_ONCE(1);
-       } else if (is_vht(tbl->lq_type)) {
+       } else if (is_vht(rate)) {
                if (index < IWL_FIRST_VHT_RATE || index > IWL_LAST_VHT_RATE) {
                        IWL_ERR(mvm, "Invalid VHT rate index %d\n", index);
                        index = IWL_LAST_VHT_RATE;
                }
-               rate_n_flags |= RATE_MCS_VHT_MSK;
-               if (is_vht_siso(tbl->lq_type))
-                       rate_n_flags |= iwl_rates[index].plcp_vht_siso;
-               else if (is_vht_mimo2(tbl->lq_type))
-                       rate_n_flags |= iwl_rates[index].plcp_vht_mimo2;
+               ucode_rate |= RATE_MCS_VHT_MSK;
+               if (is_vht_siso(rate))
+                       ucode_rate |= iwl_rates[index].plcp_vht_siso;
+               else if (is_vht_mimo2(rate))
+                       ucode_rate |= iwl_rates[index].plcp_vht_mimo2;
                else
                        WARN_ON_ONCE(1);
 
        } else {
-               IWL_ERR(mvm, "Invalid tbl->lq_type %d\n", tbl->lq_type);
+               IWL_ERR(mvm, "Invalid rate->type %d\n", rate->type);
        }
 
-       rate_n_flags |= tbl->bw;
-       if (tbl->is_SGI)
-               rate_n_flags |= RATE_MCS_SGI_MSK;
+       ucode_rate |= rate->bw;
+       if (rate->sgi)
+               ucode_rate |= RATE_MCS_SGI_MSK;
 
-       return rate_n_flags;
+       return ucode_rate;
 }
 
-/*
- * Interpret uCode API's rate_n_flags format,
- * fill "search" or "active" tx mode table.
- */
-static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags,
-                                   enum ieee80211_band band,
-                                   struct iwl_scale_tbl_info *tbl,
-                                   int *rate_idx)
+/* Convert a ucode rate into an rs_rate object */
+static int rs_rate_from_ucode_rate(const u32 ucode_rate,
+                                  enum ieee80211_band band,
+                                  struct rs_rate *rate)
 {
-       u32 ant_msk = (rate_n_flags & RATE_MCS_ANT_ABC_MSK);
-       u8 num_of_ant = get_num_of_ant_from_rate(rate_n_flags);
+       u32 ant_msk = ucode_rate & RATE_MCS_ANT_ABC_MSK;
+       u8 num_of_ant = get_num_of_ant_from_rate(ucode_rate);
        u8 nss;
 
-       memset(tbl, 0, offsetof(struct iwl_scale_tbl_info, win));
-       *rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags);
+       memset(rate, 0, sizeof(struct rs_rate));
+       rate->index = iwl_hwrate_to_plcp_idx(ucode_rate);
 
-       if (*rate_idx  == IWL_RATE_INVALID) {
-               *rate_idx = -1;
+       if (rate->index == IWL_RATE_INVALID) {
+               rate->index = -1;
                return -EINVAL;
        }
-       tbl->is_SGI = 0;        /* default legacy setup */
-       tbl->bw = 0;
-       tbl->ant_type = (ant_msk >> RATE_MCS_ANT_POS);
-       tbl->lq_type = LQ_NONE;
-       tbl->max_search = IWL_MAX_SEARCH;
+
+       rate->ant = (ant_msk >> RATE_MCS_ANT_POS);
 
        /* Legacy */
-       if (!(rate_n_flags & RATE_MCS_HT_MSK) &&
-           !(rate_n_flags & RATE_MCS_VHT_MSK)) {
+       if (!(ucode_rate & RATE_MCS_HT_MSK) &&
+           !(ucode_rate & RATE_MCS_VHT_MSK)) {
                if (num_of_ant == 1) {
                        if (band == IEEE80211_BAND_5GHZ)
-                               tbl->lq_type = LQ_LEGACY_A;
+                               rate->type = LQ_LEGACY_A;
                        else
-                               tbl->lq_type = LQ_LEGACY_G;
+                               rate->type = LQ_LEGACY_G;
                }
 
                return 0;
        }
 
        /* HT or VHT */
-       if (rate_n_flags & RATE_MCS_SGI_MSK)
-               tbl->is_SGI = 1;
+       if (ucode_rate & RATE_MCS_SGI_MSK)
+               rate->sgi = true;
 
-       tbl->bw = rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK;
+       rate->bw = ucode_rate & RATE_MCS_CHAN_WIDTH_MSK;
 
-       if (rate_n_flags & RATE_MCS_HT_MSK) {
-               nss = ((rate_n_flags & RATE_HT_MCS_NSS_MSK) >>
+       if (ucode_rate & RATE_MCS_HT_MSK) {
+               nss = ((ucode_rate & RATE_HT_MCS_NSS_MSK) >>
                       RATE_HT_MCS_NSS_POS) + 1;
 
                if (nss == 1) {
-                       tbl->lq_type = LQ_HT_SISO;
+                       rate->type = LQ_HT_SISO;
                        WARN_ON_ONCE(num_of_ant != 1);
                } else if (nss == 2) {
-                       tbl->lq_type = LQ_HT_MIMO2;
+                       rate->type = LQ_HT_MIMO2;
                        WARN_ON_ONCE(num_of_ant != 2);
                } else {
                        WARN_ON_ONCE(1);
                }
-       } else if (rate_n_flags & RATE_MCS_VHT_MSK) {
-               nss = ((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >>
+       } else if (ucode_rate & RATE_MCS_VHT_MSK) {
+               nss = ((ucode_rate & RATE_VHT_MCS_NSS_MSK) >>
                       RATE_VHT_MCS_NSS_POS) + 1;
 
                if (nss == 1) {
-                       tbl->lq_type = LQ_VHT_SISO;
+                       rate->type = LQ_VHT_SISO;
                        WARN_ON_ONCE(num_of_ant != 1);
                } else if (nss == 2) {
-                       tbl->lq_type = LQ_VHT_MIMO2;
+                       rate->type = LQ_VHT_MIMO2;
                        WARN_ON_ONCE(num_of_ant != 2);
                } else {
                        WARN_ON_ONCE(1);
                }
        }
 
-       WARN_ON_ONCE(tbl->bw == RATE_MCS_CHAN_WIDTH_160);
-       WARN_ON_ONCE(tbl->bw == RATE_MCS_CHAN_WIDTH_80 &&
-                    !is_vht(tbl->lq_type));
+       WARN_ON_ONCE(rate->bw == RATE_MCS_CHAN_WIDTH_160);
+       WARN_ON_ONCE(rate->bw == RATE_MCS_CHAN_WIDTH_80 &&
+                    !is_vht(rate));
 
        return 0;
 }
 
 /* switch to another antenna/antennas and return 1 */
 /* if no other valid antenna found, return 0 */
-static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags,
-                            struct iwl_scale_tbl_info *tbl)
+static int rs_toggle_antenna(u32 valid_ant, u32 *ucode_rate,
+                            struct rs_rate *rate)
 {
        u8 new_ant_type;
 
-       if (!tbl->ant_type || tbl->ant_type > ANT_ABC)
+       if (!rate->ant || rate->ant > ANT_ABC)
                return 0;
 
-       if (!rs_is_valid_ant(valid_ant, tbl->ant_type))
+       if (!rs_is_valid_ant(valid_ant, rate->ant))
                return 0;
 
-       new_ant_type = ant_toggle_lookup[tbl->ant_type];
+       new_ant_type = ant_toggle_lookup[rate->ant];
 
-       while ((new_ant_type != tbl->ant_type) &&
+       while ((new_ant_type != rate->ant) &&
               !rs_is_valid_ant(valid_ant, new_ant_type))
                new_ant_type = ant_toggle_lookup[new_ant_type];
 
-       if (new_ant_type == tbl->ant_type)
+       if (new_ant_type == rate->ant)
                return 0;
 
-       tbl->ant_type = new_ant_type;
-       *rate_n_flags &= ~RATE_MCS_ANT_ABC_MSK;
-       *rate_n_flags |= new_ant_type << RATE_MCS_ANT_POS;
+       rate->ant = new_ant_type;
+
+       /* TODO: get rid of ucode_rate here. This should handle only rs_rate */
+       *ucode_rate &= ~RATE_MCS_ANT_ABC_MSK;
+       *ucode_rate |= new_ant_type << RATE_MCS_ANT_POS;
        return 1;
 }
 
-/**
- * rs_get_supported_rates - get the available rates
- *
- * if management frame or broadcast frame only return
- * basic available rates.
- *
- */
 static u16 rs_get_supported_rates(struct iwl_lq_sta *lq_sta,
-                                 struct ieee80211_hdr *hdr,
-                                 enum iwl_table_type rate_type)
+                                 struct rs_rate *rate)
 {
-       if (is_legacy(rate_type))
+       if (is_legacy(rate))
                return lq_sta->active_legacy_rate;
-       else if (is_siso(rate_type))
+       else if (is_siso(rate))
                return lq_sta->active_siso_rate;
-       else if (is_mimo2(rate_type))
+       else if (is_mimo2(rate))
                return lq_sta->active_mimo2_rate;
 
        WARN_ON_ONCE(1);
@@ -628,7 +835,7 @@ static u16 rs_get_adjacent_rate(struct iwl_mvm *mvm, u8 index, u16 rate_mask,
 
        /* 802.11A or ht walks to the next literal adjacent rate in
         * the rate table */
-       if (is_a_band(rate_type) || !is_legacy(rate_type)) {
+       if (is_type_a_band(rate_type) || !is_type_legacy(rate_type)) {
                int i;
                u32 mask;
 
@@ -677,7 +884,7 @@ static u16 rs_get_adjacent_rate(struct iwl_mvm *mvm, u8 index, u16 rate_mask,
 }
 
 static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta,
-                            struct iwl_scale_tbl_info *tbl,
+                            struct rs_rate *rate,
                             u8 scale_index, u8 ht_possible)
 {
        s32 low;
@@ -689,30 +896,31 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta,
        /* check if we need to switch from HT to legacy rates.
         * assumption is that mandatory rates (1Mbps or 6Mbps)
         * are always supported (spec demand) */
-       if (!is_legacy(tbl->lq_type) && (!ht_possible || !scale_index)) {
+       if (!is_legacy(rate) && (!ht_possible || !scale_index)) {
                switch_to_legacy = 1;
+               WARN_ON_ONCE(scale_index < IWL_RATE_MCS_0_INDEX &&
+                            scale_index > IWL_RATE_MCS_9_INDEX);
                scale_index = rs_ht_to_legacy[scale_index];
                if (lq_sta->band == IEEE80211_BAND_5GHZ)
-                       tbl->lq_type = LQ_LEGACY_A;
+                       rate->type = LQ_LEGACY_A;
                else
-                       tbl->lq_type = LQ_LEGACY_G;
+                       rate->type = LQ_LEGACY_G;
 
-               if (num_of_ant(tbl->ant_type) > 1)
-                       tbl->ant_type =
+               if (num_of_ant(rate->ant) > 1)
+                       rate->ant =
                            first_antenna(iwl_fw_valid_tx_ant(mvm->fw));
 
-               tbl->bw = 0;
-               tbl->is_SGI = 0;
-               tbl->max_search = IWL_MAX_SEARCH;
+               rate->bw = RATE_MCS_CHAN_WIDTH_20;
+               rate->sgi = false;
        }
 
-       rate_mask = rs_get_supported_rates(lq_sta, NULL, tbl->lq_type);
+       rate_mask = rs_get_supported_rates(lq_sta, rate);
 
        /* Mask with station rate restriction */
-       if (is_legacy(tbl->lq_type)) {
+       if (is_legacy(rate)) {
                /* supp_rates has no CCK bits in A mode */
                if (lq_sta->band == IEEE80211_BAND_5GHZ)
-                       rate_mask  = (u16)(rate_mask &
+                       rate_mask = (u16)(rate_mask &
                           (lq_sta->supp_rates << IWL_FIRST_OFDM_RATE));
                else
                        rate_mask = (u16)(rate_mask & lq_sta->supp_rates);
@@ -725,24 +933,22 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta,
        }
 
        high_low = rs_get_adjacent_rate(lq_sta->drv, scale_index, rate_mask,
-                                       tbl->lq_type);
+                                       rate->type);
        low = high_low & 0xff;
 
        if (low == IWL_RATE_INVALID)
                low = scale_index;
 
 out:
-       return rate_n_flags_from_tbl(lq_sta->drv, tbl, low);
+       rate->index = low;
+       return ucode_rate_from_rs_rate(lq_sta->drv, rate);
 }
 
-/*
- * Simple function to compare two rate scale table types
- */
-static bool table_type_matches(struct iwl_scale_tbl_info *a,
-                              struct iwl_scale_tbl_info *b)
+/* Simple function to compare two rate scale table types */
+static inline bool rs_rate_match(struct rs_rate *a,
+                                struct rs_rate *b)
 {
-       return (a->lq_type == b->lq_type) && (a->ant_type == b->ant_type) &&
-               (a->is_SGI == b->is_SGI);
+       return (a->type == b->type) && (a->ant == b->ant) && (a->sgi == b->sgi);
 }
 
 static u32 rs_ch_width_from_mac_flags(enum mac80211_rate_control_flags flags)
@@ -766,7 +972,7 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband,
 {
        int legacy_success;
        int retries;
-       int rs_index, mac_index, i;
+       int mac_index, i;
        struct iwl_lq_sta *lq_sta = priv_sta;
        struct iwl_lq_cmd *table;
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
@@ -774,13 +980,10 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband,
        struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        enum mac80211_rate_control_flags mac_flags;
-       u32 tx_rate;
-       struct iwl_scale_tbl_info tbl_type;
+       u32 ucode_rate;
+       struct rs_rate rate;
        struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl;
 
-       IWL_DEBUG_RATE_LIMIT(mvm,
-                            "get frame ack response, update rate scale window\n");
-
        /* Treat uninitialized rate scaling data same as non-existing. */
        if (!lq_sta) {
                IWL_DEBUG_RATE(mvm, "Station rate scaling not created yet.\n");
@@ -808,10 +1011,10 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband,
         * to a new "search" mode (which might become the new "active" mode).
         */
        table = &lq_sta->lq;
-       tx_rate = le32_to_cpu(table->rs_table[0]);
-       rs_get_tbl_info_from_mcs(tx_rate, info->band, &tbl_type, &rs_index);
+       ucode_rate = le32_to_cpu(table->rs_table[0]);
+       rs_rate_from_ucode_rate(ucode_rate, info->band, &rate);
        if (info->band == IEEE80211_BAND_5GHZ)
-               rs_index -= IWL_FIRST_OFDM_RATE;
+               rate.index -= IWL_FIRST_OFDM_RATE;
        mac_flags = info->status.rates[0].flags;
        mac_index = info->status.rates[0].idx;
        /* For HT packets, map MCS to PLCP */
@@ -834,19 +1037,19 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband,
 
        /* Here we actually compare this rate to the latest LQ command */
        if ((mac_index < 0) ||
-           (tbl_type.is_SGI != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) ||
-           (tbl_type.bw != rs_ch_width_from_mac_flags(mac_flags)) ||
-           (tbl_type.ant_type != info->status.antenna) ||
-           (!!(tx_rate & RATE_MCS_HT_MSK) !=
+           (rate.sgi != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) ||
+           (rate.bw != rs_ch_width_from_mac_flags(mac_flags)) ||
+           (rate.ant != info->status.antenna) ||
+           (!!(ucode_rate & RATE_MCS_HT_MSK) !=
             !!(mac_flags & IEEE80211_TX_RC_MCS)) ||
-           (!!(tx_rate & RATE_MCS_VHT_MSK) !=
+           (!!(ucode_rate & RATE_MCS_VHT_MSK) !=
             !!(mac_flags & IEEE80211_TX_RC_VHT_MCS)) ||
-           (!!(tx_rate & RATE_HT_MCS_GF_MSK) !=
+           (!!(ucode_rate & RATE_HT_MCS_GF_MSK) !=
             !!(mac_flags & IEEE80211_TX_RC_GREEN_FIELD)) ||
-           (rs_index != mac_index)) {
+           (rate.index != mac_index)) {
                IWL_DEBUG_RATE(mvm,
                               "initial rate %d does not match %d (0x%x)\n",
-                              mac_index, rs_index, tx_rate);
+                              mac_index, rate.index, ucode_rate);
                /*
                 * Since rates mis-match, the last LQ command may have failed.
                 * After IWL_MISSED_RATE_MAX mis-matches, resync the uCode with
@@ -855,7 +1058,10 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband,
                lq_sta->missed_rate_counter++;
                if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) {
                        lq_sta->missed_rate_counter = 0;
-                       iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, CMD_ASYNC, false);
+                       IWL_DEBUG_RATE(mvm,
+                                      "Too many rates mismatch. Send sync LQ. rs_state %d\n",
+                                      lq_sta->rs_state);
+                       iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false);
                }
                /* Regardless, ignore this status info for outdated rate */
                return;
@@ -864,28 +1070,23 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband,
                lq_sta->missed_rate_counter = 0;
 
        /* Figure out if rate scale algorithm is in active or search table */
-       if (table_type_matches(&tbl_type,
-                              &(lq_sta->lq_info[lq_sta->active_tbl]))) {
+       if (rs_rate_match(&rate,
+                         &(lq_sta->lq_info[lq_sta->active_tbl].rate))) {
                curr_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
                other_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]);
-       } else if (table_type_matches(
-                       &tbl_type, &lq_sta->lq_info[1 - lq_sta->active_tbl])) {
+       } else if (rs_rate_match(&rate,
+                        &lq_sta->lq_info[1 - lq_sta->active_tbl].rate)) {
                curr_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]);
                other_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
        } else {
                IWL_DEBUG_RATE(mvm,
                               "Neither active nor search matches tx rate\n");
                tmp_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
-               IWL_DEBUG_RATE(mvm, "active- lq:%x, ant:%x, SGI:%d\n",
-                              tmp_tbl->lq_type, tmp_tbl->ant_type,
-                              tmp_tbl->is_SGI);
+               rs_dump_rate(mvm, &tmp_tbl->rate, "ACTIVE");
                tmp_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]);
-               IWL_DEBUG_RATE(mvm, "search- lq:%x, ant:%x, SGI:%d\n",
-                              tmp_tbl->lq_type, tmp_tbl->ant_type,
-                              tmp_tbl->is_SGI);
-               IWL_DEBUG_RATE(mvm, "actual- lq:%x, ant:%x, SGI:%d\n",
-                              tbl_type.lq_type, tbl_type.ant_type,
-                              tbl_type.is_SGI);
+               rs_dump_rate(mvm, &tmp_tbl->rate, "SEARCH");
+               rs_dump_rate(mvm, &rate, "ACTUAL");
+
                /*
                 * no matching table found, let's by-pass the data collection
                 * and continue to perform rate scale to find the rate table
@@ -902,15 +1103,14 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband,
         * first index into rate scale table.
         */
        if (info->flags & IEEE80211_TX_STAT_AMPDU) {
-               tx_rate = le32_to_cpu(table->rs_table[0]);
-               rs_get_tbl_info_from_mcs(tx_rate, info->band, &tbl_type,
-                                        &rs_index);
-               rs_collect_tx_data(curr_tbl, rs_index,
+               ucode_rate = le32_to_cpu(table->rs_table[0]);
+               rs_rate_from_ucode_rate(ucode_rate, info->band, &rate);
+               rs_collect_tx_data(curr_tbl, rate.index,
                                   info->status.ampdu_len,
                                   info->status.ampdu_ack_len);
 
                /* Update success/fail counts if not searching for new mode */
-               if (lq_sta->stay_in_tbl) {
+               if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) {
                        lq_sta->total_success += info->status.ampdu_ack_len;
                        lq_sta->total_failed += (info->status.ampdu_len -
                                        info->status.ampdu_ack_len);
@@ -927,31 +1127,36 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband,
                legacy_success = !!(info->flags & IEEE80211_TX_STAT_ACK);
                /* Collect data for each rate used during failed TX attempts */
                for (i = 0; i <= retries; ++i) {
-                       tx_rate = le32_to_cpu(table->rs_table[i]);
-                       rs_get_tbl_info_from_mcs(tx_rate, info->band,
-                                                &tbl_type, &rs_index);
+                       ucode_rate = le32_to_cpu(table->rs_table[i]);
+                       rs_rate_from_ucode_rate(ucode_rate, info->band, &rate);
                        /*
                         * Only collect stats if retried rate is in the same RS
                         * table as active/search.
                         */
-                       if (table_type_matches(&tbl_type, curr_tbl))
+                       if (rs_rate_match(&rate, &curr_tbl->rate))
                                tmp_tbl = curr_tbl;
-                       else if (table_type_matches(&tbl_type, other_tbl))
+                       else if (rs_rate_match(&rate, &other_tbl->rate))
                                tmp_tbl = other_tbl;
-                       else
+                       else {
+                               IWL_DEBUG_RATE(mvm,
+                                              "Tx packet rate doesn't match ACTIVE or SEARCH tables\n");
+                               rs_dump_rate(mvm, &rate, "Tx PACKET:");
+                               rs_dump_rate(mvm, &curr_tbl->rate, "CURRENT:");
+                               rs_dump_rate(mvm, &other_tbl->rate, "OTHER:");
                                continue;
-                       rs_collect_tx_data(tmp_tbl, rs_index, 1,
+                       }
+                       rs_collect_tx_data(tmp_tbl, rate.index, 1,
                                           i < retries ? 0 : legacy_success);
                }
 
                /* Update success/fail counts if not searching for new mode */
-               if (lq_sta->stay_in_tbl) {
+               if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) {
                        lq_sta->total_success += legacy_success;
                        lq_sta->total_failed += retries + (1 - legacy_success);
                }
        }
        /* The last TX rate is cached in lq_sta; it's set in if/else above */
-       lq_sta->last_rate_n_flags = tx_rate;
+       lq_sta->last_rate_n_flags = ucode_rate;
 done:
        /* See if there's a better rate or modulation mode to try. */
        if (sta && sta->supp_rates[sband->band])
@@ -969,8 +1174,8 @@ done:
 static void rs_set_stay_in_table(struct iwl_mvm *mvm, u8 is_legacy,
                                 struct iwl_lq_sta *lq_sta)
 {
-       IWL_DEBUG_RATE(mvm, "we are staying in the same table\n");
-       lq_sta->stay_in_tbl = 1;        /* only place this gets set */
+       IWL_DEBUG_RATE(mvm, "Moving to RS_STATE_STAY_IN_COLUMN\n");
+       lq_sta->rs_state = RS_STATE_STAY_IN_COLUMN;
        if (is_legacy) {
                lq_sta->table_count_limit = IWL_LEGACY_TABLE_COUNT;
                lq_sta->max_failure_limit = IWL_LEGACY_FAILURE_LIMIT;
@@ -984,37 +1189,31 @@ static void rs_set_stay_in_table(struct iwl_mvm *mvm, u8 is_legacy,
        lq_sta->total_failed = 0;
        lq_sta->total_success = 0;
        lq_sta->flush_timer = jiffies;
-       lq_sta->action_counter = 0;
+       lq_sta->visited_columns = 0;
 }
 
-/*
- * Find correct throughput table for given mode of modulation
- */
-static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta,
-                                     struct iwl_scale_tbl_info *tbl)
+static s32 *rs_get_expected_tpt_table(struct iwl_lq_sta *lq_sta,
+                                     const struct rs_tx_column *column,
+                                     u32 bw)
 {
        /* Used to choose among HT tables */
        s32 (*ht_tbl_pointer)[IWL_RATE_COUNT];
 
-       /* Check for invalid LQ type */
-       if (WARN_ON_ONCE(!is_legacy(tbl->lq_type) && !is_ht(tbl->lq_type) &&
-                        !(is_vht(tbl->lq_type)))) {
-               tbl->expected_tpt = expected_tpt_legacy;
-               return;
-       }
+       if (WARN_ON_ONCE(column->mode != RS_LEGACY &&
+                        column->mode != RS_SISO &&
+                        column->mode != RS_MIMO2))
+               return expected_tpt_legacy;
 
        /* Legacy rates have only one table */
-       if (is_legacy(tbl->lq_type)) {
-               tbl->expected_tpt = expected_tpt_legacy;
-               return;
-       }
+       if (column->mode == RS_LEGACY)
+               return expected_tpt_legacy;
 
        ht_tbl_pointer = expected_tpt_mimo2_20MHz;
        /* Choose among many HT tables depending on number of streams
         * (SISO/MIMO2), channel width (20/40/80), SGI, and aggregation
         * status */
-       if (is_siso(tbl->lq_type)) {
-               switch (tbl->bw) {
+       if (column->mode == RS_SISO) {
+               switch (bw) {
                case RATE_MCS_CHAN_WIDTH_20:
                        ht_tbl_pointer = expected_tpt_siso_20MHz;
                        break;
@@ -1027,8 +1226,8 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta,
                default:
                        WARN_ON_ONCE(1);
                }
-       } else if (is_mimo2(tbl->lq_type)) {
-               switch (tbl->bw) {
+       } else if (column->mode == RS_MIMO2) {
+               switch (bw) {
                case RATE_MCS_CHAN_WIDTH_20:
                        ht_tbl_pointer = expected_tpt_mimo2_20MHz;
                        break;
@@ -1045,14 +1244,23 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta,
                WARN_ON_ONCE(1);
        }
 
-       if (!tbl->is_SGI && !lq_sta->is_agg)            /* Normal */
-               tbl->expected_tpt = ht_tbl_pointer[0];
-       else if (tbl->is_SGI && !lq_sta->is_agg)        /* SGI */
-               tbl->expected_tpt = ht_tbl_pointer[1];
-       else if (!tbl->is_SGI && lq_sta->is_agg)        /* AGG */
-               tbl->expected_tpt = ht_tbl_pointer[2];
+       if (!column->sgi && !lq_sta->is_agg)            /* Normal */
+               return ht_tbl_pointer[0];
+       else if (column->sgi && !lq_sta->is_agg)        /* SGI */
+               return ht_tbl_pointer[1];
+       else if (!column->sgi && lq_sta->is_agg)        /* AGG */
+               return ht_tbl_pointer[2];
        else                                            /* AGG+SGI */
-               tbl->expected_tpt = ht_tbl_pointer[3];
+               return ht_tbl_pointer[3];
+}
+
+static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta,
+                                     struct iwl_scale_tbl_info *tbl)
+{
+       struct rs_rate *rate = &tbl->rate;
+       const struct rs_tx_column *column = &rs_tx_columns[tbl->column];
+
+       tbl->expected_tpt = rs_get_expected_tpt_table(lq_sta, column, rate->bw);
 }
 
 /*
@@ -1089,7 +1297,7 @@ static s32 rs_get_best_rate(struct iwl_mvm *mvm,
 
        while (1) {
                high_low = rs_get_adjacent_rate(mvm, rate, rate_mask,
-                                               tbl->lq_type);
+                                               tbl->rate.type);
 
                low = high_low & 0xff;
                high = (high_low >> 8) & 0xff;
@@ -1110,7 +1318,7 @@ static s32 rs_get_best_rate(struct iwl_mvm *mvm,
                 *    "active" throughput (under perfect conditions).
                 */
                if ((((100 * tpt_tbl[rate]) > lq_sta->last_tpt) &&
-                    ((active_sr > IWL_RATE_DECREASE_TH) &&
+                    ((active_sr > RS_SR_FORCE_DECREASE) &&
                      (active_sr <= IWL_RATE_HIGH_TH) &&
                      (tpt_tbl[rate] <= active_tpt))) ||
                    ((active_sr >= IWL_RATE_SCALE_SWITCH) &&
@@ -1157,417 +1365,14 @@ static s32 rs_get_best_rate(struct iwl_mvm *mvm,
        return new_rate;
 }
 
-/* Move to the next action and wrap around to the first action in case
- * we're at the last action. Assumes actions start at 0.
- */
-static inline void rs_move_next_action(struct iwl_scale_tbl_info *tbl,
-                                      u8 last_action)
-{
-       BUILD_BUG_ON(IWL_LEGACY_FIRST_ACTION != 0);
-       BUILD_BUG_ON(IWL_SISO_FIRST_ACTION != 0);
-       BUILD_BUG_ON(IWL_MIMO2_FIRST_ACTION != 0);
-
-       tbl->action = (tbl->action + 1) % (last_action + 1);
-}
-
-static void rs_set_bw_from_sta(struct iwl_scale_tbl_info *tbl,
-                              struct ieee80211_sta *sta)
+static u32 rs_bw_from_sta_bw(struct ieee80211_sta *sta)
 {
        if (sta->bandwidth >= IEEE80211_STA_RX_BW_80)
-               tbl->bw = RATE_MCS_CHAN_WIDTH_80;
+               return RATE_MCS_CHAN_WIDTH_80;
        else if (sta->bandwidth >= IEEE80211_STA_RX_BW_40)
-               tbl->bw = RATE_MCS_CHAN_WIDTH_40;
-       else
-               tbl->bw = RATE_MCS_CHAN_WIDTH_20;
-}
-
-static bool rs_sgi_allowed(struct iwl_scale_tbl_info *tbl,
-                          struct ieee80211_sta *sta)
-{
-       struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
-       struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
-
-       if (is_ht20(tbl) && (ht_cap->cap &
-                            IEEE80211_HT_CAP_SGI_20))
-               return true;
-       if (is_ht40(tbl) && (ht_cap->cap &
-                            IEEE80211_HT_CAP_SGI_40))
-               return true;
-       if (is_ht80(tbl) && (vht_cap->cap &
-                            IEEE80211_VHT_CAP_SHORT_GI_80))
-               return true;
-
-       return false;
-}
-
-/*
- * Set up search table for MIMO2
- */
-static int rs_switch_to_mimo2(struct iwl_mvm *mvm,
-                            struct iwl_lq_sta *lq_sta,
-                            struct ieee80211_sta *sta,
-                            struct iwl_scale_tbl_info *tbl, int index)
-{
-       u16 rate_mask;
-       s32 rate;
-
-       if (!sta->ht_cap.ht_supported)
-               return -1;
-
-       if (sta->smps_mode == IEEE80211_SMPS_STATIC)
-               return -1;
-
-       /* Need both Tx chains/antennas to support MIMO */
-       if (num_of_ant(iwl_fw_valid_tx_ant(mvm->fw)) < 2)
-               return -1;
-
-       IWL_DEBUG_RATE(mvm, "LQ: try to switch to MIMO2\n");
-
-       tbl->lq_type = lq_sta->is_vht ? LQ_VHT_MIMO2 : LQ_HT_MIMO2;
-       tbl->action = 0;
-       tbl->max_search = IWL_MAX_SEARCH;
-       rate_mask = lq_sta->active_mimo2_rate;
-
-       rs_set_bw_from_sta(tbl, sta);
-       rs_set_expected_tpt_table(lq_sta, tbl);
-
-       rate = rs_get_best_rate(mvm, lq_sta, tbl, rate_mask, index);
-
-       IWL_DEBUG_RATE(mvm, "LQ: MIMO2 best rate %d mask %X\n",
-                      rate, rate_mask);
-       if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask)) {
-               IWL_DEBUG_RATE(mvm, "Can't switch with index %d rate mask %x\n",
-                              rate, rate_mask);
-               return -1;
-       }
-       tbl->current_rate = rate_n_flags_from_tbl(mvm, tbl, rate);
-
-       IWL_DEBUG_RATE(mvm, "LQ: Switch to new mcs %X index\n",
-                      tbl->current_rate);
-       return 0;
-}
-
-/*
- * Set up search table for SISO
- */
-static int rs_switch_to_siso(struct iwl_mvm *mvm,
-                            struct iwl_lq_sta *lq_sta,
-                            struct ieee80211_sta *sta,
-                            struct iwl_scale_tbl_info *tbl, int index)
-{
-       u16 rate_mask;
-       s32 rate;
-
-       if (!sta->ht_cap.ht_supported)
-               return -1;
-
-       IWL_DEBUG_RATE(mvm, "LQ: try to switch to SISO\n");
-
-       tbl->lq_type = lq_sta->is_vht ? LQ_VHT_SISO : LQ_HT_SISO;
-       tbl->action = 0;
-       tbl->max_search = IWL_MAX_SEARCH;
-       rate_mask = lq_sta->active_siso_rate;
-
-       rs_set_bw_from_sta(tbl, sta);
-       rs_set_expected_tpt_table(lq_sta, tbl);
-       rate = rs_get_best_rate(mvm, lq_sta, tbl, rate_mask, index);
-
-       IWL_DEBUG_RATE(mvm, "LQ: get best rate %d mask %X\n", rate, rate_mask);
-       if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask)) {
-               IWL_DEBUG_RATE(mvm,
-                              "can not switch with index %d rate mask %x\n",
-                              rate, rate_mask);
-               return -1;
-       }
-       tbl->current_rate = rate_n_flags_from_tbl(mvm, tbl, rate);
-       IWL_DEBUG_RATE(mvm, "LQ: Switch to new mcs %X index\n",
-                      tbl->current_rate);
-       return 0;
-}
-
-/*
- * Try to switch to new modulation mode from legacy
- */
-static int rs_move_legacy_other(struct iwl_mvm *mvm,
-                               struct iwl_lq_sta *lq_sta,
-                               struct ieee80211_sta *sta,
-                               int index)
-{
-       struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
-       struct iwl_scale_tbl_info *search_tbl =
-                               &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
-       struct iwl_rate_scale_data *window = &(tbl->win[index]);
-       u32 sz = (sizeof(struct iwl_scale_tbl_info) -
-                 (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
-       u8 start_action;
-       u8 valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw);
-       u8 tx_chains_num = num_of_ant(valid_tx_ant);
-       int ret;
-       u8 update_search_tbl_counter = 0;
-
-       start_action = tbl->action;
-       while (1) {
-               lq_sta->action_counter++;
-               switch (tbl->action) {
-               case IWL_LEGACY_SWITCH_ANTENNA:
-                       IWL_DEBUG_RATE(mvm, "LQ: Legacy toggle Antenna\n");
-
-                       if (tx_chains_num <= 1)
-                               break;
-
-                       /* Don't change antenna if success has been great */
-                       if (window->success_ratio >= IWL_RS_GOOD_RATIO)
-                               break;
-
-                       /* Set up search table to try other antenna */
-                       memcpy(search_tbl, tbl, sz);
-
-                       if (rs_toggle_antenna(valid_tx_ant,
-                                             &search_tbl->current_rate,
-                                             search_tbl)) {
-                               update_search_tbl_counter = 1;
-                               rs_set_expected_tpt_table(lq_sta, search_tbl);
-                               goto out;
-                       }
-                       break;
-               case IWL_LEGACY_SWITCH_SISO:
-                       IWL_DEBUG_RATE(mvm, "LQ: Legacy switch to SISO\n");
-
-                       /* Set up search table to try SISO */
-                       memcpy(search_tbl, tbl, sz);
-                       search_tbl->is_SGI = 0;
-                       ret = rs_switch_to_siso(mvm, lq_sta, sta,
-                                                search_tbl, index);
-                       if (!ret) {
-                               lq_sta->action_counter = 0;
-                               goto out;
-                       }
-
-                       break;
-               case IWL_LEGACY_SWITCH_MIMO2:
-                       IWL_DEBUG_RATE(mvm, "LQ: Legacy switch to MIMO2\n");
-
-                       /* Set up search table to try MIMO */
-                       memcpy(search_tbl, tbl, sz);
-                       search_tbl->is_SGI = 0;
-
-                       search_tbl->ant_type = ANT_AB;
-
-                       if (!rs_is_valid_ant(valid_tx_ant,
-                                            search_tbl->ant_type))
-                               break;
-
-                       ret = rs_switch_to_mimo2(mvm, lq_sta, sta,
-                                                search_tbl, index);
-                       if (!ret) {
-                               lq_sta->action_counter = 0;
-                               goto out;
-                       }
-                       break;
-               default:
-                       WARN_ON_ONCE(1);
-               }
-               rs_move_next_action(tbl, IWL_LEGACY_LAST_ACTION);
-
-               if (tbl->action == start_action)
-                       break;
-       }
-       search_tbl->lq_type = LQ_NONE;
-       return 0;
-
-out:
-       lq_sta->search_better_tbl = 1;
-       rs_move_next_action(tbl, IWL_LEGACY_LAST_ACTION);
-       if (update_search_tbl_counter)
-               search_tbl->action = tbl->action;
-       return 0;
-}
-
-/*
- * Try to switch to new modulation mode from SISO
- */
-static int rs_move_siso_to_other(struct iwl_mvm *mvm,
-                                struct iwl_lq_sta *lq_sta,
-                                struct ieee80211_sta *sta, int index)
-{
-       struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
-       struct iwl_scale_tbl_info *search_tbl =
-                               &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
-       struct iwl_rate_scale_data *window = &(tbl->win[index]);
-       u32 sz = (sizeof(struct iwl_scale_tbl_info) -
-                 (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
-       u8 start_action;
-       u8 valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw);
-       u8 tx_chains_num = num_of_ant(valid_tx_ant);
-       u8 update_search_tbl_counter = 0;
-       int ret;
-
-       if (tbl->action == IWL_SISO_SWITCH_MIMO2 &&
-           !iwl_mvm_bt_coex_is_mimo_allowed(mvm, sta))
-               tbl->action = IWL_SISO_SWITCH_ANTENNA;
-
-       start_action = tbl->action;
-       while (1) {
-               lq_sta->action_counter++;
-               switch (tbl->action) {
-               case IWL_SISO_SWITCH_ANTENNA:
-                       IWL_DEBUG_RATE(mvm, "LQ: SISO toggle Antenna\n");
-                       if (tx_chains_num <= 1)
-                               break;
-
-                       if (window->success_ratio >= IWL_RS_GOOD_RATIO &&
-                           BT_MBOX_MSG(&mvm->last_bt_notif, 3,
-                                       TRAFFIC_LOAD) == 0)
-                               break;
-
-                       memcpy(search_tbl, tbl, sz);
-                       if (rs_toggle_antenna(valid_tx_ant,
-                                             &search_tbl->current_rate,
-                                             search_tbl)) {
-                               update_search_tbl_counter = 1;
-                               goto out;
-                       }
-                       break;
-               case IWL_SISO_SWITCH_MIMO2:
-                       IWL_DEBUG_RATE(mvm, "LQ: SISO switch to MIMO2\n");
-                       memcpy(search_tbl, tbl, sz);
-                       search_tbl->is_SGI = 0;
-
-                       search_tbl->ant_type = ANT_AB;
-
-                       if (!rs_is_valid_ant(valid_tx_ant,
-                                            search_tbl->ant_type))
-                               break;
-
-                       ret = rs_switch_to_mimo2(mvm, lq_sta, sta,
-                                                search_tbl, index);
-                       if (!ret)
-                               goto out;
-                       break;
-               case IWL_SISO_SWITCH_GI:
-                       if (!rs_sgi_allowed(tbl, sta))
-                               break;
-
-                       IWL_DEBUG_RATE(mvm, "LQ: SISO toggle SGI/NGI\n");
-
-                       memcpy(search_tbl, tbl, sz);
-                       search_tbl->is_SGI = !tbl->is_SGI;
-                       rs_set_expected_tpt_table(lq_sta, search_tbl);
-                       if (tbl->is_SGI) {
-                               s32 tpt = lq_sta->last_tpt / 100;
-                               if (tpt >= search_tbl->expected_tpt[index])
-                                       break;
-                       }
-                       search_tbl->current_rate =
-                               rate_n_flags_from_tbl(mvm, search_tbl, index);
-                       update_search_tbl_counter = 1;
-                       goto out;
-               default:
-                       WARN_ON_ONCE(1);
-               }
-               rs_move_next_action(tbl, IWL_SISO_LAST_ACTION);
-
-               if (tbl->action == start_action)
-                       break;
-       }
-       search_tbl->lq_type = LQ_NONE;
-       return 0;
-
- out:
-       lq_sta->search_better_tbl = 1;
-       rs_move_next_action(tbl, IWL_SISO_LAST_ACTION);
-       if (update_search_tbl_counter)
-               search_tbl->action = tbl->action;
-
-       return 0;
-}
-
-/*
- * Try to switch to new modulation mode from MIMO2
- */
-static int rs_move_mimo2_to_other(struct iwl_mvm *mvm,
-                                struct iwl_lq_sta *lq_sta,
-                                struct ieee80211_sta *sta, int index)
-{
-       struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
-       struct iwl_scale_tbl_info *search_tbl =
-                               &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
-       u32 sz = (sizeof(struct iwl_scale_tbl_info) -
-                 (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
-       u8 start_action;
-       u8 valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw);
-       u8 update_search_tbl_counter = 0;
-       int ret;
-
-       start_action = tbl->action;
-       while (1) {
-               lq_sta->action_counter++;
-               switch (tbl->action) {
-               case IWL_MIMO2_SWITCH_SISO_A:
-               case IWL_MIMO2_SWITCH_SISO_B:
-                       IWL_DEBUG_RATE(mvm, "LQ: MIMO2 switch to SISO\n");
-
-                       /* Set up new search table for SISO */
-                       memcpy(search_tbl, tbl, sz);
-
-                       if (tbl->action == IWL_MIMO2_SWITCH_SISO_A)
-                               search_tbl->ant_type = ANT_A;
-                       else /* tbl->action == IWL_MIMO2_SWITCH_SISO_B */
-                               search_tbl->ant_type = ANT_B;
-
-                       if (!rs_is_valid_ant(valid_tx_ant,
-                                            search_tbl->ant_type))
-                               break;
-
-                       ret = rs_switch_to_siso(mvm, lq_sta, sta,
-                                                search_tbl, index);
-                       if (!ret)
-                               goto out;
-
-                       break;
-
-               case IWL_MIMO2_SWITCH_GI:
-                       if (!rs_sgi_allowed(tbl, sta))
-                               break;
-
-                       IWL_DEBUG_RATE(mvm, "LQ: MIMO2 toggle SGI/NGI\n");
-
-                       /* Set up new search table for MIMO2 */
-                       memcpy(search_tbl, tbl, sz);
-                       search_tbl->is_SGI = !tbl->is_SGI;
-                       rs_set_expected_tpt_table(lq_sta, search_tbl);
-                       /*
-                        * If active table already uses the fastest possible
-                        * modulation (dual stream with short guard interval),
-                        * and it's working well, there's no need to look
-                        * for a better type of modulation!
-                        */
-                       if (tbl->is_SGI) {
-                               s32 tpt = lq_sta->last_tpt / 100;
-                               if (tpt >= search_tbl->expected_tpt[index])
-                                       break;
-                       }
-                       search_tbl->current_rate =
-                               rate_n_flags_from_tbl(mvm, search_tbl, index);
-                       update_search_tbl_counter = 1;
-                       goto out;
-               default:
-                       WARN_ON_ONCE(1);
-               }
-               rs_move_next_action(tbl, IWL_MIMO2_LAST_ACTION);
-
-               if (tbl->action == start_action)
-                       break;
-       }
-       search_tbl->lq_type = LQ_NONE;
-       return 0;
- out:
-       lq_sta->search_better_tbl = 1;
-       rs_move_next_action(tbl, IWL_MIMO2_LAST_ACTION);
-       if (update_search_tbl_counter)
-               search_tbl->action = tbl->action;
+               return RATE_MCS_CHAN_WIDTH_40;
 
-       return 0;
+       return RATE_MCS_CHAN_WIDTH_20;
 }
 
 /*
@@ -1591,13 +1396,13 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search)
        tbl = &(lq_sta->lq_info[active_tbl]);
 
        /* If we've been disallowing search, see if we should now allow it */
-       if (lq_sta->stay_in_tbl) {
+       if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN) {
                /* Elapsed time using current modulation mode */
                if (lq_sta->flush_timer)
                        flush_interval_passed =
                                time_after(jiffies,
                                           (unsigned long)(lq_sta->flush_timer +
-                                               IWL_RATE_SCALE_FLUSH_INTVL));
+                                               RS_STAY_IN_COLUMN_TIMEOUT));
 
                /*
                 * Check if we should allow search for new modulation mode.
@@ -1619,10 +1424,14 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search)
                                     flush_interval_passed);
 
                        /* Allow search for new mode */
-                       lq_sta->stay_in_tbl = 0;        /* only place reset */
+                       lq_sta->rs_state = RS_STATE_SEARCH_CYCLE_STARTED;
+                       IWL_DEBUG_RATE(mvm,
+                                      "Moving to RS_STATE_SEARCH_CYCLE_STARTED\n");
                        lq_sta->total_failed = 0;
                        lq_sta->total_success = 0;
                        lq_sta->flush_timer = 0;
+                       /* mark the current column as visited */
+                       lq_sta->visited_columns = BIT(tbl->column);
                /*
                 * Else if we've used this modulation mode enough repetitions
                 * (regardless of elapsed time or success/failure), reset
@@ -1646,7 +1455,8 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search)
                /* If transitioning to allow "search", reset all history
                 * bitmaps and stats in active table (this will become the new
                 * "search" table). */
-               if (!lq_sta->stay_in_tbl) {
+               if (lq_sta->rs_state == RS_STATE_SEARCH_CYCLE_STARTED) {
+                       IWL_DEBUG_RATE(mvm, "Clearing up window stats\n");
                        for (i = 0; i < IWL_RATE_COUNT; i++)
                                rs_rate_scale_clear_window(&(tbl->win[i]));
                }
@@ -1659,15 +1469,13 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search)
 static void rs_update_rate_tbl(struct iwl_mvm *mvm,
                               struct ieee80211_sta *sta,
                               struct iwl_lq_sta *lq_sta,
-                              struct iwl_scale_tbl_info *tbl,
-                              int index)
+                              struct rs_rate *rate)
 {
-       u32 rate;
+       u32 ucode_rate;
 
-       /* Update uCode's rate table. */
-       rate = rate_n_flags_from_tbl(mvm, tbl, index);
-       rs_fill_link_cmd(mvm, sta, lq_sta, rate);
-       iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, CMD_ASYNC, false);
+       ucode_rate = ucode_rate_from_rs_rate(mvm, rate);
+       rs_fill_link_cmd(mvm, sta, lq_sta, ucode_rate);
+       iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false);
 }
 
 static u8 rs_get_tid(struct iwl_lq_sta *lq_data,
@@ -1686,6 +1494,162 @@ static u8 rs_get_tid(struct iwl_lq_sta *lq_data,
        return tid;
 }
 
+static enum rs_column rs_get_next_column(struct iwl_mvm *mvm,
+                                        struct iwl_lq_sta *lq_sta,
+                                        struct ieee80211_sta *sta,
+                                        struct iwl_scale_tbl_info *tbl)
+{
+       int i, j, n;
+       enum rs_column next_col_id;
+       const struct rs_tx_column *curr_col = &rs_tx_columns[tbl->column];
+       const struct rs_tx_column *next_col;
+       allow_column_func_t allow_func;
+       u8 valid_ants = iwl_fw_valid_tx_ant(mvm->fw);
+       s32 *expected_tpt_tbl;
+       s32 tpt, max_expected_tpt;
+
+       for (i = 0; i < MAX_NEXT_COLUMNS; i++) {
+               next_col_id = curr_col->next_columns[i];
+
+               if (next_col_id == RS_COLUMN_INVALID)
+                       continue;
+
+               if (lq_sta->visited_columns & BIT(next_col_id)) {
+                       IWL_DEBUG_RATE(mvm, "Skip already visited column %d\n",
+                                      next_col_id);
+                       continue;
+               }
+
+               next_col = &rs_tx_columns[next_col_id];
+
+               if (!rs_is_valid_ant(valid_ants, next_col->ant)) {
+                       IWL_DEBUG_RATE(mvm,
+                                      "Skip column %d as ANT config isn't supported by chip. valid_ants 0x%x column ant 0x%x\n",
+                                      next_col_id, valid_ants, next_col->ant);
+                       continue;
+               }
+
+               for (j = 0; j < MAX_COLUMN_CHECKS; j++) {
+                       allow_func = next_col->checks[j];
+                       if (allow_func && !allow_func(mvm, sta, tbl))
+                               break;
+               }
+
+               if (j != MAX_COLUMN_CHECKS) {
+                       IWL_DEBUG_RATE(mvm,
+                                      "Skip column %d: not allowed (check %d failed)\n",
+                                      next_col_id, j);
+
+                       continue;
+               }
+
+               tpt = lq_sta->last_tpt / 100;
+               expected_tpt_tbl = rs_get_expected_tpt_table(lq_sta, next_col,
+                                                            tbl->rate.bw);
+               if (WARN_ON_ONCE(!expected_tpt_tbl))
+                       continue;
+
+               max_expected_tpt = 0;
+               for (n = 0; n < IWL_RATE_COUNT; n++)
+                       if (expected_tpt_tbl[n] > max_expected_tpt)
+                               max_expected_tpt = expected_tpt_tbl[n];
+
+               if (tpt >= max_expected_tpt) {
+                       IWL_DEBUG_RATE(mvm,
+                                      "Skip column %d: can't beat current TPT. Max expected %d current %d\n",
+                                      next_col_id, max_expected_tpt, tpt);
+                       continue;
+               }
+
+               break;
+       }
+
+       if (i == MAX_NEXT_COLUMNS)
+               return RS_COLUMN_INVALID;
+
+       IWL_DEBUG_RATE(mvm, "Found potential column %d\n", next_col_id);
+
+       return next_col_id;
+}
+
+static int rs_switch_to_column(struct iwl_mvm *mvm,
+                              struct iwl_lq_sta *lq_sta,
+                              struct ieee80211_sta *sta,
+                              enum rs_column col_id)
+{
+       struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
+       struct iwl_scale_tbl_info *search_tbl =
+                               &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
+       struct rs_rate *rate = &search_tbl->rate;
+       const struct rs_tx_column *column = &rs_tx_columns[col_id];
+       const struct rs_tx_column *curr_column = &rs_tx_columns[tbl->column];
+       u32 sz = (sizeof(struct iwl_scale_tbl_info) -
+                 (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
+       u16 rate_mask = 0;
+       u32 rate_idx = 0;
+
+       memcpy(search_tbl, tbl, sz);
+
+       rate->sgi = column->sgi;
+       rate->ant = column->ant;
+
+       if (column->mode == RS_LEGACY) {
+               if (lq_sta->band == IEEE80211_BAND_5GHZ)
+                       rate->type = LQ_LEGACY_A;
+               else
+                       rate->type = LQ_LEGACY_G;
+
+               rate_mask = lq_sta->active_legacy_rate;
+       } else if (column->mode == RS_SISO) {
+               rate->type = lq_sta->is_vht ? LQ_VHT_SISO : LQ_HT_SISO;
+               rate_mask = lq_sta->active_siso_rate;
+       } else if (column->mode == RS_MIMO2) {
+               rate->type = lq_sta->is_vht ? LQ_VHT_MIMO2 : LQ_HT_MIMO2;
+               rate_mask = lq_sta->active_mimo2_rate;
+       } else {
+               WARN_ON_ONCE("Bad column mode");
+       }
+
+       rate->bw = rs_bw_from_sta_bw(sta);
+       search_tbl->column = col_id;
+       rs_set_expected_tpt_table(lq_sta, search_tbl);
+
+       /* Get the best matching rate if we're changing modes. e.g.
+        * SISO->MIMO, LEGACY->SISO, MIMO->SISO
+        */
+       if (curr_column->mode != column->mode) {
+               rate_idx = rs_get_best_rate(mvm, lq_sta, search_tbl,
+                                           rate_mask, rate->index);
+
+               if ((rate_idx == IWL_RATE_INVALID) ||
+                   !(BIT(rate_idx) & rate_mask)) {
+                       IWL_DEBUG_RATE(mvm,
+                                      "can not switch with index %d"
+                                      " rate mask %x\n",
+                                      rate_idx, rate_mask);
+
+                       goto err;
+               }
+
+               rate->index = rate_idx;
+       }
+
+       /* TODO: remove current_rate and keep using rs_rate all the way until
+        * we need to fill in the rs_table in the LQ command
+        */
+       search_tbl->current_rate = ucode_rate_from_rs_rate(mvm, rate);
+       IWL_DEBUG_RATE(mvm, "Switched to column %d: Index %d\n",
+                      col_id, rate->index);
+
+       lq_sta->visited_columns |= BIT(col_id);
+       return 0;
+
+err:
+       rate->type = LQ_NONE;
+       return -1;
+}
+
+
 /*
  * Do rate scaling and search for new modulation mode.
  */
@@ -1715,10 +1679,10 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
        u16 high_low;
        s32 sr;
        u8 tid = IWL_MAX_TID_COUNT;
+       u8 prev_agg = lq_sta->is_agg;
        struct iwl_mvm_sta *sta_priv = (void *)sta->drv_priv;
        struct iwl_mvm_tid_data *tid_data;
-
-       IWL_DEBUG_RATE(mvm, "rate scale calculate new rate for skb\n");
+       struct rs_rate *rate;
 
        /* Send management frames and NO_ACK data using lowest rate. */
        /* TODO: this could probably be improved.. */
@@ -1751,20 +1715,23 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
                active_tbl = 1 - lq_sta->active_tbl;
 
        tbl = &(lq_sta->lq_info[active_tbl]);
+       rate = &tbl->rate;
+
+       if (prev_agg != lq_sta->is_agg) {
+               IWL_DEBUG_RATE(mvm,
+                              "Aggregation changed: prev %d current %d. Update expected TPT table\n",
+                              prev_agg, lq_sta->is_agg);
+               rs_set_expected_tpt_table(lq_sta, tbl);
+       }
 
        /* current tx rate */
        index = lq_sta->last_txrate_idx;
 
-       IWL_DEBUG_RATE(mvm, "Rate scale index %d for type %d\n", index,
-                      tbl->lq_type);
-
        /* rates available for this association, and for modulation mode */
-       rate_mask = rs_get_supported_rates(lq_sta, hdr, tbl->lq_type);
-
-       IWL_DEBUG_RATE(mvm, "mask 0x%04X\n", rate_mask);
+       rate_mask = rs_get_supported_rates(lq_sta, rate);
 
        /* mask with station rate restriction */
-       if (is_legacy(tbl->lq_type)) {
+       if (is_legacy(rate)) {
                if (lq_sta->band == IEEE80211_BAND_5GHZ)
                        /* supp_rates has no CCK bits in A mode */
                        rate_scale_index_msk = (u16) (rate_mask &
@@ -1780,16 +1747,17 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
        if (!rate_scale_index_msk)
                rate_scale_index_msk = rate_mask;
 
-       if (!((1 << index) & rate_scale_index_msk)) {
+       if (!((BIT(index) & rate_scale_index_msk))) {
                IWL_ERR(mvm, "Current Rate is not valid\n");
                if (lq_sta->search_better_tbl) {
                        /* revert to active table if search table is not valid*/
-                       tbl->lq_type = LQ_NONE;
+                       rate->type = LQ_NONE;
                        lq_sta->search_better_tbl = 0;
                        tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
                        /* get "active" rate info */
                        index = iwl_hwrate_to_plcp_idx(tbl->current_rate);
-                       rs_update_rate_tbl(mvm, sta, lq_sta, tbl, index);
+                       tbl->rate.index = index;
+                       rs_update_rate_tbl(mvm, sta, lq_sta, &tbl->rate);
                }
                return;
        }
@@ -1806,6 +1774,9 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
                index = lq_sta->max_rate_idx;
                update_lq = 1;
                window = &(tbl->win[index]);
+               IWL_DEBUG_RATE(mvm,
+                              "Forcing user max rate %d\n",
+                              index);
                goto lq_update;
        }
 
@@ -1822,8 +1793,9 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
        if ((fail_count < IWL_RATE_MIN_FAILURE_TH) &&
            (window->success_counter < IWL_RATE_MIN_SUCCESS_TH)) {
                IWL_DEBUG_RATE(mvm,
-                              "LQ: still below TH. succ=%d total=%d for index %d\n",
-                              window->success_counter, window->counter, index);
+                              "(%s: %d): Test Window: succ %d total %d\n",
+                              rs_pretty_lq_type(rate->type),
+                              index, window->success_counter, window->counter);
 
                /* Can't calculate this yet; not enough history */
                window->average_tpt = IWL_INVALID_VALUE;
@@ -1838,8 +1810,6 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
         * actual average throughput */
        if (window->average_tpt != ((window->success_ratio *
                        tbl->expected_tpt[index] + 64) / 128)) {
-               IWL_ERR(mvm,
-                       "expected_tpt should have been calculated by now\n");
                window->average_tpt = ((window->success_ratio *
                                        tbl->expected_tpt[index] + 64) / 128);
        }
@@ -1851,27 +1821,26 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
                 * continuing to use the setup that we've been trying. */
                if (window->average_tpt > lq_sta->last_tpt) {
                        IWL_DEBUG_RATE(mvm,
-                                      "LQ: SWITCHING TO NEW TABLE suc=%d cur-tpt=%d old-tpt=%d\n",
+                                      "SWITCHING TO NEW TABLE SR: %d "
+                                      "cur-tpt %d old-tpt %d\n",
                                       window->success_ratio,
                                       window->average_tpt,
                                       lq_sta->last_tpt);
 
-                       if (!is_legacy(tbl->lq_type))
-                               lq_sta->enable_counter = 1;
-
                        /* Swap tables; "search" becomes "active" */
                        lq_sta->active_tbl = active_tbl;
                        current_tpt = window->average_tpt;
                /* Else poor success; go back to mode in "active" table */
                } else {
                        IWL_DEBUG_RATE(mvm,
-                                      "LQ: GOING BACK TO THE OLD TABLE suc=%d cur-tpt=%d old-tpt=%d\n",
+                                      "GOING BACK TO THE OLD TABLE: SR %d "
+                                      "cur-tpt %d old-tpt %d\n",
                                       window->success_ratio,
                                       window->average_tpt,
                                       lq_sta->last_tpt);
 
                        /* Nullify "search" table */
-                       tbl->lq_type = LQ_NONE;
+                       rate->type = LQ_NONE;
 
                        /* Revert to "active" table */
                        active_tbl = lq_sta->active_tbl;
@@ -1895,7 +1864,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
        /* (Else) not in search of better modulation mode, try for better
         * starting rate, while staying in this mode. */
        high_low = rs_get_adjacent_rate(mvm, index, rate_scale_index_msk,
-                                       tbl->lq_type);
+                                       rate->type);
        low = high_low & 0xff;
        high = (high_low >> 8) & 0xff;
 
@@ -1913,20 +1882,31 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
        if (high != IWL_RATE_INVALID)
                high_tpt = tbl->win[high].average_tpt;
 
+       IWL_DEBUG_RATE(mvm,
+                      "(%s: %d): cur_tpt %d SR %d low %d high %d low_tpt %d high_tpt %d\n",
+                      rs_pretty_lq_type(rate->type), index, current_tpt, sr,
+                      low, high, low_tpt, high_tpt);
+
        scale_action = 0;
 
        /* Too many failures, decrease rate */
-       if ((sr <= IWL_RATE_DECREASE_TH) || (current_tpt == 0)) {
+       if ((sr <= RS_SR_FORCE_DECREASE) || (current_tpt == 0)) {
                IWL_DEBUG_RATE(mvm,
-                              "decrease rate because of low success_ratio\n");
+                              "decrease rate because of low SR\n");
                scale_action = -1;
        /* No throughput measured yet for adjacent rates; try increase. */
        } else if ((low_tpt == IWL_INVALID_VALUE) &&
                   (high_tpt == IWL_INVALID_VALUE)) {
-               if (high != IWL_RATE_INVALID && sr >= IWL_RATE_INCREASE_TH)
+               if (high != IWL_RATE_INVALID && sr >= IWL_RATE_INCREASE_TH) {
+                       IWL_DEBUG_RATE(mvm,
+                                      "Good SR and no high rate measurement. "
+                                      "Increase rate\n");
                        scale_action = 1;
-               else if (low != IWL_RATE_INVALID)
+               } else if (low != IWL_RATE_INVALID) {
+                       IWL_DEBUG_RATE(mvm,
+                                      "Remain in current rate\n");
                        scale_action = 0;
+               }
        }
 
        /* Both adjacent throughputs are measured, but neither one has better
@@ -1934,8 +1914,12 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
        else if ((low_tpt != IWL_INVALID_VALUE) &&
                 (high_tpt != IWL_INVALID_VALUE) &&
                 (low_tpt < current_tpt) &&
-                (high_tpt < current_tpt))
+                (high_tpt < current_tpt)) {
+               IWL_DEBUG_RATE(mvm,
+                              "Both high and low are worse. "
+                              "Maintain rate\n");
                scale_action = 0;
+       }
 
        /* At least one adjacent rate's throughput is measured,
         * and may have better performance. */
@@ -1945,8 +1929,14 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
                        /* Higher rate has better throughput */
                        if (high_tpt > current_tpt &&
                            sr >= IWL_RATE_INCREASE_TH) {
+                               IWL_DEBUG_RATE(mvm,
+                                              "Higher rate is better and good "
+                                              "SR. Increate rate\n");
                                scale_action = 1;
                        } else {
+                               IWL_DEBUG_RATE(mvm,
+                                              "Higher rate isn't better OR "
+                                              "no good SR. Maintain rate\n");
                                scale_action = 0;
                        }
 
@@ -1955,9 +1945,13 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
                        /* Lower rate has better throughput */
                        if (low_tpt > current_tpt) {
                                IWL_DEBUG_RATE(mvm,
-                                              "decrease rate because of low tpt\n");
+                                              "Lower rate is better. "
+                                              "Decrease rate\n");
                                scale_action = -1;
                        } else if (sr >= IWL_RATE_INCREASE_TH) {
+                               IWL_DEBUG_RATE(mvm,
+                                              "Lower rate isn't better and "
+                                              "good SR. Increase rate\n");
                                scale_action = 1;
                        }
                }
@@ -1967,29 +1961,17 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
         * has been good at old rate.  Don't change it. */
        if ((scale_action == -1) && (low != IWL_RATE_INVALID) &&
            ((sr > IWL_RATE_HIGH_TH) ||
-            (current_tpt > (100 * tbl->expected_tpt[low]))))
+            (current_tpt > (100 * tbl->expected_tpt[low])))) {
+               IWL_DEBUG_RATE(mvm,
+                              "Sanity check failed. Maintain rate\n");
                scale_action = 0;
-
-       if ((le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) >=
-            IWL_BT_COEX_TRAFFIC_LOAD_HIGH) && (is_mimo(tbl->lq_type))) {
-               if (lq_sta->last_bt_traffic >
-                   le32_to_cpu(mvm->last_bt_notif.bt_activity_grading)) {
-                       /*
-                        * don't set scale_action, don't want to scale up if
-                        * the rate scale doesn't otherwise think that is a
-                        * good idea.
-                        */
-               } else if (lq_sta->last_bt_traffic <=
-                          le32_to_cpu(mvm->last_bt_notif.bt_activity_grading)) {
-                       scale_action = -1;
-               }
        }
-       lq_sta->last_bt_traffic =
-               le32_to_cpu(mvm->last_bt_notif.bt_activity_grading);
 
-       if ((le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) >=
-            IWL_BT_COEX_TRAFFIC_LOAD_HIGH) && is_mimo(tbl->lq_type)) {
-               /* search for a new modulation */
+       /* Force a search in case BT doesn't like us being in MIMO */
+       if (is_mimo(rate) &&
+           !iwl_mvm_bt_coex_is_mimo_allowed(mvm, sta)) {
+               IWL_DEBUG_RATE(mvm,
+                              "BT Coex forbids MIMO. Search for new config\n");
                rs_stay_in_table(lq_sta, true);
                goto lq_update;
        }
@@ -2000,6 +1982,9 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
                if (low != IWL_RATE_INVALID) {
                        update_lq = 1;
                        index = low;
+               } else {
+                       IWL_DEBUG_RATE(mvm,
+                                      "At the bottom rate. Can't decrease\n");
                }
 
                break;
@@ -2008,6 +1993,9 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
                if (high != IWL_RATE_INVALID) {
                        update_lq = 1;
                        index = high;
+               } else {
+                       IWL_DEBUG_RATE(mvm,
+                                      "At the top rate. Can't increase\n");
                }
 
                break;
@@ -2017,14 +2005,12 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
                break;
        }
 
-       IWL_DEBUG_RATE(mvm,
-                      "choose rate scale index %d action %d low %d high %d type %d\n",
-                      index, scale_action, low, high, tbl->lq_type);
-
 lq_update:
        /* Replace uCode's rate table for the destination station. */
-       if (update_lq)
-               rs_update_rate_tbl(mvm, sta, lq_sta, tbl, index);
+       if (update_lq) {
+               tbl->rate.index = index;
+               rs_update_rate_tbl(mvm, sta, lq_sta, &tbl->rate);
+       }
 
        rs_stay_in_table(lq_sta, false);
 
@@ -2035,20 +2021,29 @@ lq_update:
         * 3)  Allowing a new search
         */
        if (!update_lq && !done_search &&
-           !lq_sta->stay_in_tbl && window->counter) {
+           lq_sta->rs_state == RS_STATE_SEARCH_CYCLE_STARTED
+           && window->counter) {
+               enum rs_column next_column;
+
                /* Save current throughput to compare with "search" throughput*/
                lq_sta->last_tpt = current_tpt;
 
-               /* Select a new "search" modulation mode to try.
-                * If one is found, set up the new "search" table. */
-               if (is_legacy(tbl->lq_type))
-                       rs_move_legacy_other(mvm, lq_sta, sta, index);
-               else if (is_siso(tbl->lq_type))
-                       rs_move_siso_to_other(mvm, lq_sta, sta, index);
-               else if (is_mimo2(tbl->lq_type))
-                       rs_move_mimo2_to_other(mvm, lq_sta, sta, index);
-               else
-                       WARN_ON_ONCE(1);
+               IWL_DEBUG_RATE(mvm,
+                              "Start Search: update_lq %d done_search %d rs_state %d win->counter %d\n",
+                              update_lq, done_search, lq_sta->rs_state,
+                              window->counter);
+
+               next_column = rs_get_next_column(mvm, lq_sta, sta, tbl);
+               if (next_column != RS_COLUMN_INVALID) {
+                       int ret = rs_switch_to_column(mvm, lq_sta, sta,
+                                                     next_column);
+                       if (!ret)
+                               lq_sta->search_better_tbl = 1;
+               } else {
+                       IWL_DEBUG_RATE(mvm,
+                                      "No more columns to explore in search cycle. Go to RS_STATE_SEARCH_CYCLE_ENDED\n");
+                       lq_sta->rs_state = RS_STATE_SEARCH_CYCLE_ENDED;
+               }
 
                /* If new "search" mode was selected, set up in uCode table */
                if (lq_sta->search_better_tbl) {
@@ -2060,34 +2055,29 @@ lq_update:
                        /* Use new "search" start rate */
                        index = iwl_hwrate_to_plcp_idx(tbl->current_rate);
 
-                       IWL_DEBUG_RATE(mvm,
-                                      "Switch current  mcs: %X index: %d\n",
-                                      tbl->current_rate, index);
+                       rs_dump_rate(mvm, &tbl->rate,
+                                    "Switch to SEARCH TABLE:");
                        rs_fill_link_cmd(mvm, sta, lq_sta, tbl->current_rate);
-                       iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, CMD_ASYNC, false);
+                       iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false);
                } else {
                        done_search = 1;
                }
        }
 
-       if (done_search && !lq_sta->stay_in_tbl) {
+       if (done_search && lq_sta->rs_state == RS_STATE_SEARCH_CYCLE_ENDED) {
                /* If the "active" (non-search) mode was legacy,
                 * and we've tried switching antennas,
                 * but we haven't been able to try HT modes (not available),
                 * stay with best antenna legacy modulation for a while
                 * before next round of mode comparisons. */
                tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]);
-               if (is_legacy(tbl1->lq_type) && !sta->ht_cap.ht_supported &&
-                   lq_sta->action_counter > tbl1->max_search) {
+               if (is_legacy(&tbl1->rate) && !sta->ht_cap.ht_supported) {
                        IWL_DEBUG_RATE(mvm, "LQ: STAY in legacy table\n");
                        rs_set_stay_in_table(mvm, 1, lq_sta);
-               }
-
+               } else {
                /* If we're in an HT mode, and all 3 mode switch actions
                 * have been tried and compared, stay in this best modulation
                 * mode for a while before next round of mode comparisons. */
-               if (lq_sta->enable_counter &&
-                   (lq_sta->action_counter >= tbl1->max_search)) {
                        if ((lq_sta->last_tpt > IWL_AGG_TPT_THREHOLD) &&
                            (lq_sta->tx_agg_tid_en & (1 << tid)) &&
                            (tid != IWL_MAX_TID_COUNT)) {
@@ -2105,7 +2095,8 @@ lq_update:
        }
 
 out:
-       tbl->current_rate = rate_n_flags_from_tbl(mvm, tbl, index);
+       tbl->rate.index = index;
+       tbl->current_rate = ucode_rate_from_rs_rate(mvm, &tbl->rate);
        lq_sta->last_txrate_idx = index;
 }
 
@@ -2126,12 +2117,13 @@ out:
 static void rs_initialize_lq(struct iwl_mvm *mvm,
                             struct ieee80211_sta *sta,
                             struct iwl_lq_sta *lq_sta,
-                            enum ieee80211_band band)
+                            enum ieee80211_band band,
+                            bool init)
 {
        struct iwl_scale_tbl_info *tbl;
-       int rate_idx;
+       struct rs_rate *rate;
        int i;
-       u32 rate;
+       u32 ucode_rate;
        u8 active_tbl = 0;
        u8 valid_tx_ant;
 
@@ -2148,27 +2140,33 @@ static void rs_initialize_lq(struct iwl_mvm *mvm,
                active_tbl = 1 - lq_sta->active_tbl;
 
        tbl = &(lq_sta->lq_info[active_tbl]);
+       rate = &tbl->rate;
 
        if ((i < 0) || (i >= IWL_RATE_COUNT))
                i = 0;
 
-       rate = iwl_rates[i].plcp;
-       tbl->ant_type = first_antenna(valid_tx_ant);
-       rate |= tbl->ant_type << RATE_MCS_ANT_POS;
+       rate->index = i;
+       rate->ant = first_antenna(valid_tx_ant);
+       rate->sgi = false;
+       rate->bw = RATE_MCS_CHAN_WIDTH_20;
+       if (band == IEEE80211_BAND_5GHZ)
+               rate->type = LQ_LEGACY_A;
+       else
+               rate->type = LQ_LEGACY_G;
 
-       if (i >= IWL_FIRST_CCK_RATE && i <= IWL_LAST_CCK_RATE)
-               rate |= RATE_MCS_CCK_MSK;
+       ucode_rate = ucode_rate_from_rs_rate(mvm, rate);
+       tbl->current_rate = ucode_rate;
 
-       rs_get_tbl_info_from_mcs(rate, band, tbl, &rate_idx);
-       if (!rs_is_valid_ant(valid_tx_ant, tbl->ant_type))
-               rs_toggle_antenna(valid_tx_ant, &rate, tbl);
+       WARN_ON_ONCE(rate->ant != ANT_A && rate->ant != ANT_B);
+       if (rate->ant == ANT_A)
+               tbl->column = RS_COLUMN_LEGACY_ANT_A;
+       else
+               tbl->column = RS_COLUMN_LEGACY_ANT_B;
 
-       rate = rate_n_flags_from_tbl(mvm, tbl, rate_idx);
-       tbl->current_rate = rate;
        rs_set_expected_tpt_table(lq_sta, tbl);
-       rs_fill_link_cmd(NULL, NULL, lq_sta, rate);
+       rs_fill_link_cmd(NULL, NULL, lq_sta, ucode_rate);
        /* TODO restore station should remember the lq cmd */
-       iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, CMD_SYNC, true);
+       iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, init);
 }
 
 static void rs_get_rate(void *mvm_r, struct ieee80211_sta *sta, void *mvm_sta,
@@ -2182,8 +2180,6 @@ static void rs_get_rate(void *mvm_r, struct ieee80211_sta *sta, void *mvm_sta,
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        struct iwl_lq_sta *lq_sta = mvm_sta;
 
-       IWL_DEBUG_RATE_LIMIT(mvm, "rate scale calculate new rate for skb\n");
-
        /* Get max rate if user set max rate */
        if (lq_sta) {
                lq_sta->max_rate_idx = txrc->max_rate_idx;
@@ -2242,11 +2238,51 @@ static int rs_vht_highest_rx_mcs_index(struct ieee80211_sta_vht_cap *vht_cap,
        return -1;
 }
 
+static void rs_vht_set_enabled_rates(struct ieee80211_sta *sta,
+                                    struct ieee80211_sta_vht_cap *vht_cap,
+                                    struct iwl_lq_sta *lq_sta)
+{
+       int i;
+       int highest_mcs = rs_vht_highest_rx_mcs_index(vht_cap, 1);
+
+       if (highest_mcs >= IWL_RATE_MCS_0_INDEX) {
+               for (i = IWL_RATE_MCS_0_INDEX; i <= highest_mcs; i++) {
+                       if (i == IWL_RATE_9M_INDEX)
+                               continue;
+
+                       /* VHT MCS9 isn't valid for 20Mhz for NSS=1,2 */
+                       if (i == IWL_RATE_MCS_9_INDEX &&
+                           sta->bandwidth == IEEE80211_STA_RX_BW_20)
+                               continue;
+
+                       lq_sta->active_siso_rate |= BIT(i);
+               }
+       }
+
+       if (sta->rx_nss < 2)
+               return;
+
+       highest_mcs = rs_vht_highest_rx_mcs_index(vht_cap, 2);
+       if (highest_mcs >= IWL_RATE_MCS_0_INDEX) {
+               for (i = IWL_RATE_MCS_0_INDEX; i <= highest_mcs; i++) {
+                       if (i == IWL_RATE_9M_INDEX)
+                               continue;
+
+                       /* VHT MCS9 isn't valid for 20Mhz for NSS=1,2 */
+                       if (i == IWL_RATE_MCS_9_INDEX &&
+                           sta->bandwidth == IEEE80211_STA_RX_BW_20)
+                               continue;
+
+                       lq_sta->active_mimo2_rate |= BIT(i);
+               }
+       }
+}
+
 /*
  * Called after adding a new station to initialize rate scaling
  */
 void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
-                         enum ieee80211_band band)
+                         enum ieee80211_band band, bool init)
 {
        int i, j;
        struct ieee80211_hw *hw = mvm->hw;
@@ -2259,6 +2295,8 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
 
        sta_priv = (struct iwl_mvm_sta *)sta->drv_priv;
        lq_sta = &sta_priv->lq_sta;
+       memset(lq_sta, 0, sizeof(*lq_sta));
+
        sband = hw->wiphy->bands[band];
 
        lq_sta->lq.sta_id = sta_priv->sta_id;
@@ -2308,27 +2346,7 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
 
                lq_sta->is_vht = false;
        } else {
-               int highest_mcs = rs_vht_highest_rx_mcs_index(vht_cap, 1);
-               if (highest_mcs >= IWL_RATE_MCS_0_INDEX) {
-                       for (i = IWL_RATE_MCS_0_INDEX; i <= highest_mcs; i++) {
-                               if (i == IWL_RATE_9M_INDEX)
-                                       continue;
-
-                               lq_sta->active_siso_rate |= BIT(i);
-                       }
-               }
-
-               highest_mcs = rs_vht_highest_rx_mcs_index(vht_cap, 2);
-               if (highest_mcs >= IWL_RATE_MCS_0_INDEX) {
-                       for (i = IWL_RATE_MCS_0_INDEX; i <= highest_mcs; i++) {
-                               if (i == IWL_RATE_9M_INDEX)
-                                       continue;
-
-                               lq_sta->active_mimo2_rate |= BIT(i);
-                       }
-               }
-
-               /* TODO: avoid MCS9 in 20Mhz which isn't valid for 11ac */
+               rs_vht_set_enabled_rates(sta, vht_cap, lq_sta);
                lq_sta->is_vht = true;
        }
 
@@ -2341,15 +2359,7 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
        /* These values will be overridden later */
        lq_sta->lq.single_stream_ant_msk =
                first_antenna(iwl_fw_valid_tx_ant(mvm->fw));
-       lq_sta->lq.dual_stream_ant_msk =
-               iwl_fw_valid_tx_ant(mvm->fw) &
-               ~first_antenna(iwl_fw_valid_tx_ant(mvm->fw));
-       if (!lq_sta->lq.dual_stream_ant_msk) {
-               lq_sta->lq.dual_stream_ant_msk = ANT_AB;
-       } else if (num_of_ant(iwl_fw_valid_tx_ant(mvm->fw)) == 2) {
-               lq_sta->lq.dual_stream_ant_msk =
-                       iwl_fw_valid_tx_ant(mvm->fw);
-       }
+       lq_sta->lq.dual_stream_ant_msk = ANT_AB;
 
        /* as default allow aggregation for all tids */
        lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID;
@@ -2364,16 +2374,33 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
        lq_sta->dbg_fixed_rate = 0;
 #endif
 
-       rs_initialize_lq(mvm, sta, lq_sta, band);
+       rs_initialize_lq(mvm, sta, lq_sta, band, init);
+}
+
+static void rs_rate_update(void *mvm_r,
+                          struct ieee80211_supported_band *sband,
+                          struct cfg80211_chan_def *chandef,
+                          struct ieee80211_sta *sta, void *priv_sta,
+                          u32 changed)
+{
+       u8 tid;
+       struct iwl_op_mode *op_mode  =
+                       (struct iwl_op_mode *)mvm_r;
+       struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
+
+       /* Stop any ongoing aggregations as rs starts off assuming no agg */
+       for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++)
+               ieee80211_stop_tx_ba_session(sta, tid);
+
+       iwl_mvm_rs_rate_init(mvm, sta, sband->band, false);
 }
 
 static void rs_fill_link_cmd(struct iwl_mvm *mvm,
                             struct ieee80211_sta *sta,
                             struct iwl_lq_sta *lq_sta, u32 new_rate)
 {
-       struct iwl_scale_tbl_info tbl_type;
+       struct rs_rate rate;
        int index = 0;
-       int rate_idx;
        int repeat_rate = 0;
        u8 ant_toggle_cnt = 0;
        u8 use_ht_possible = 1;
@@ -2383,12 +2410,10 @@ static void rs_fill_link_cmd(struct iwl_mvm *mvm,
        /* Override starting rate (index 0) if needed for debug purposes */
        rs_dbgfs_set_mcs(lq_sta, &new_rate);
 
-       /* Interpret new_rate (rate_n_flags) */
-       rs_get_tbl_info_from_mcs(new_rate, lq_sta->band,
-                                &tbl_type, &rate_idx);
+       rs_rate_from_ucode_rate(new_rate, lq_sta->band, &rate);
 
        /* How many times should we repeat the initial rate? */
-       if (is_legacy(tbl_type.lq_type)) {
+       if (is_legacy(&rate)) {
                ant_toggle_cnt = 1;
                repeat_rate = IWL_NUMBER_TRY;
        } else {
@@ -2396,15 +2421,13 @@ static void rs_fill_link_cmd(struct iwl_mvm *mvm,
                                  LINK_QUAL_AGG_DISABLE_START_DEF - 1);
        }
 
-       lq_cmd->mimo_delim = is_mimo(tbl_type.lq_type) ? 1 : 0;
+       lq_cmd->mimo_delim = is_mimo(&rate) ? 1 : 0;
 
        /* Fill 1st table entry (index 0) */
        lq_cmd->rs_table[index] = cpu_to_le32(new_rate);
 
-       if (num_of_ant(tbl_type.ant_type) == 1)
-               lq_cmd->single_stream_ant_msk = tbl_type.ant_type;
-       else if (num_of_ant(tbl_type.ant_type) == 2)
-               lq_cmd->dual_stream_ant_msk = tbl_type.ant_type;
+       if (num_of_ant(rate.ant) == 1)
+               lq_cmd->single_stream_ant_msk = rate.ant;
        /* otherwise we don't modify the existing value */
 
        index++;
@@ -2418,12 +2441,12 @@ static void rs_fill_link_cmd(struct iwl_mvm *mvm,
                 * For legacy IWL_NUMBER_TRY == 1, this loop will not execute.
                 * For HT IWL_HT_NUMBER_TRY == 3, this executes twice. */
                while (repeat_rate > 0 && (index < LINK_QUAL_MAX_RETRY_NUM)) {
-                       if (is_legacy(tbl_type.lq_type)) {
+                       if (is_legacy(&rate)) {
                                if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE)
                                        ant_toggle_cnt++;
                                else if (mvm &&
                                         rs_toggle_antenna(valid_tx_ant,
-                                                       &new_rate, &tbl_type))
+                                                       &new_rate, &rate))
                                        ant_toggle_cnt = 1;
                        }
 
@@ -2437,26 +2460,25 @@ static void rs_fill_link_cmd(struct iwl_mvm *mvm,
                        index++;
                }
 
-               rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, &tbl_type,
-                                        &rate_idx);
+               rs_rate_from_ucode_rate(new_rate, lq_sta->band, &rate);
 
                /* Indicate to uCode which entries might be MIMO.
                 * If initial rate was MIMO, this will finally end up
                 * as (IWL_HT_NUMBER_TRY * 2), after 2nd pass, otherwise 0. */
-               if (is_mimo(tbl_type.lq_type))
+               if (is_mimo(&rate))
                        lq_cmd->mimo_delim = index;
 
                /* Get next rate */
-               new_rate = rs_get_lower_rate(lq_sta, &tbl_type, rate_idx,
+               new_rate = rs_get_lower_rate(lq_sta, &rate, rate.index,
                                             use_ht_possible);
 
                /* How many times should we repeat the next rate? */
-               if (is_legacy(tbl_type.lq_type)) {
+               if (is_legacy(&rate)) {
                        if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE)
                                ant_toggle_cnt++;
                        else if (mvm &&
                                 rs_toggle_antenna(valid_tx_ant,
-                                                  &new_rate, &tbl_type))
+                                                  &new_rate, &rate))
                                ant_toggle_cnt = 1;
 
                        repeat_rate = IWL_NUMBER_TRY;
@@ -2527,7 +2549,6 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
                  >> RATE_MCS_ANT_POS);
                if ((valid_tx_ant & ant_sel_tx) == ant_sel_tx) {
                        *rate_n_flags = lq_sta->dbg_fixed_rate;
-                       IWL_DEBUG_RATE(mvm, "Fixed rate ON\n");
                } else {
                        lq_sta->dbg_fixed_rate = 0;
                        IWL_ERR(mvm,
@@ -2535,9 +2556,60 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
                                ant_sel_tx, valid_tx_ant);
                        IWL_DEBUG_RATE(mvm, "Fixed rate OFF\n");
                }
+       }
+}
+
+static int rs_pretty_print_rate(char *buf, const u32 rate)
+{
+
+       char *type, *bw;
+       u8 mcs = 0, nss = 0;
+       u8 ant = (rate & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS;
+
+       if (!(rate & RATE_MCS_HT_MSK) &&
+           !(rate & RATE_MCS_VHT_MSK)) {
+               int index = iwl_hwrate_to_plcp_idx(rate);
+
+               return sprintf(buf, "Legacy | ANT: %s Rate: %s Mbps\n",
+                              rs_pretty_ant(ant), iwl_rate_mcs[index].mbps);
+       }
+
+       if (rate & RATE_MCS_VHT_MSK) {
+               type = "VHT";
+               mcs = rate & RATE_VHT_MCS_RATE_CODE_MSK;
+               nss = ((rate & RATE_VHT_MCS_NSS_MSK)
+                      >> RATE_VHT_MCS_NSS_POS) + 1;
+       } else if (rate & RATE_MCS_HT_MSK) {
+               type = "HT";
+               mcs = rate & RATE_HT_MCS_INDEX_MSK;
        } else {
-               IWL_DEBUG_RATE(mvm, "Fixed rate OFF\n");
+               type = "Unknown"; /* shouldn't happen */
+       }
+
+       switch (rate & RATE_MCS_CHAN_WIDTH_MSK) {
+       case RATE_MCS_CHAN_WIDTH_20:
+               bw = "20Mhz";
+               break;
+       case RATE_MCS_CHAN_WIDTH_40:
+               bw = "40Mhz";
+               break;
+       case RATE_MCS_CHAN_WIDTH_80:
+               bw = "80Mhz";
+               break;
+       case RATE_MCS_CHAN_WIDTH_160:
+               bw = "160Mhz";
+               break;
+       default:
+               bw = "BAD BW";
        }
+
+       return sprintf(buf, "%s | ANT: %s BW: %s MCS: %d NSS: %d %s%s%s%s%s\n",
+                      type, rs_pretty_ant(ant), bw, mcs, nss,
+                      (rate & RATE_MCS_SGI_MSK) ? "SGI " : "NGI ",
+                      (rate & RATE_MCS_STBC_MSK) ? "STBC " : "",
+                      (rate & RATE_MCS_LDPC_MSK) ? "LDPC " : "",
+                      (rate & RATE_MCS_BF_MSK) ? "BF " : "",
+                      (rate & RATE_MCS_ZLF_MSK) ? "ZLF " : "");
 }
 
 static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file,
@@ -2572,15 +2644,14 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
        char *buff;
        int desc = 0;
        int i = 0;
-       int index = 0;
        ssize_t ret;
 
        struct iwl_lq_sta *lq_sta = file->private_data;
        struct iwl_mvm *mvm;
        struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
-
+       struct rs_rate *rate = &tbl->rate;
        mvm = lq_sta->drv;
-       buff = kmalloc(1024, GFP_KERNEL);
+       buff = kmalloc(2048, GFP_KERNEL);
        if (!buff)
                return -ENOMEM;
 
@@ -2595,23 +2666,23 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
            (iwl_fw_valid_tx_ant(mvm->fw) & ANT_B) ? "ANT_B," : "",
            (iwl_fw_valid_tx_ant(mvm->fw) & ANT_C) ? "ANT_C" : "");
        desc += sprintf(buff+desc, "lq type %s\n",
-                       (is_legacy(tbl->lq_type)) ? "legacy" :
-                       is_vht(tbl->lq_type) ? "VHT" : "HT");
-       if (is_ht(tbl->lq_type)) {
+                       (is_legacy(rate)) ? "legacy" :
+                       is_vht(rate) ? "VHT" : "HT");
+       if (!is_legacy(rate)) {
                desc += sprintf(buff+desc, " %s",
-                  (is_siso(tbl->lq_type)) ? "SISO" : "MIMO2");
+                  (is_siso(rate)) ? "SISO" : "MIMO2");
                   desc += sprintf(buff+desc, " %s",
-                                  (is_ht20(tbl)) ? "20MHz" :
-                                  (is_ht40(tbl)) ? "40MHz" :
-                                  (is_ht80(tbl)) ? "80Mhz" : "BAD BW");
+                                  (is_ht20(rate)) ? "20MHz" :
+                                  (is_ht40(rate)) ? "40MHz" :
+                                  (is_ht80(rate)) ? "80Mhz" : "BAD BW");
                   desc += sprintf(buff+desc, " %s %s\n",
-                                  (tbl->is_SGI) ? "SGI" : "",
+                                  (rate->sgi) ? "SGI" : "NGI",
                                   (lq_sta->is_agg) ? "AGG on" : "");
        }
        desc += sprintf(buff+desc, "last tx rate=0x%X\n",
                        lq_sta->last_rate_n_flags);
        desc += sprintf(buff+desc,
-                       "general: flags=0x%X mimo-d=%d s-ant0x%x d-ant=0x%x\n",
+                       "general: flags=0x%X mimo-d=%d s-ant=0x%x d-ant=0x%x\n",
                        lq_sta->lq.flags,
                        lq_sta->lq.mimo_delim,
                        lq_sta->lq.single_stream_ant_msk,
@@ -2631,19 +2702,12 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
                        lq_sta->lq.initial_rate_index[3]);
 
        for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
-               index = iwl_hwrate_to_plcp_idx(
-                       le32_to_cpu(lq_sta->lq.rs_table[i]));
-               if (is_legacy(tbl->lq_type)) {
-                       desc += sprintf(buff+desc, " rate[%d] 0x%X %smbps\n",
-                                       i, le32_to_cpu(lq_sta->lq.rs_table[i]),
-                                       iwl_rate_mcs[index].mbps);
-               } else {
-                       desc += sprintf(buff+desc,
-                                       " rate[%d] 0x%X %smbps (%s)\n",
-                                       i, le32_to_cpu(lq_sta->lq.rs_table[i]),
-                                       iwl_rate_mcs[index].mbps,
-                                       iwl_rate_mcs[index].mcs);
-               }
+               u32 rate = le32_to_cpu(lq_sta->lq.rs_table[i]);
+               desc += sprintf(buff+desc,
+                               " rate[%d] 0x%X ",
+                               i, rate);
+
+               desc += rs_pretty_print_rate(buff+desc, rate);
        }
 
        ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
@@ -2665,6 +2729,7 @@ static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file,
        int i, j;
        ssize_t ret;
        struct iwl_scale_tbl_info *tbl;
+       struct rs_rate *rate;
        struct iwl_lq_sta *lq_sta = file->private_data;
 
        buff = kmalloc(1024, GFP_KERNEL);
@@ -2673,15 +2738,16 @@ static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file,
 
        for (i = 0; i < LQ_SIZE; i++) {
                tbl = &(lq_sta->lq_info[i]);
+               rate = &tbl->rate;
                desc += sprintf(buff+desc,
                                "%s type=%d SGI=%d BW=%s DUP=0\n"
                                "rate=0x%X\n",
                                lq_sta->active_tbl == i ? "*" : "x",
-                               tbl->lq_type,
-                               tbl->is_SGI,
-                               is_ht20(tbl) ? "20Mhz" :
-                               is_ht40(tbl) ? "40Mhz" :
-                               is_ht80(tbl) ? "80Mhz" : "ERR",
+                               rate->type,
+                               rate->sgi,
+                               is_ht20(rate) ? "20Mhz" :
+                               is_ht40(rate) ? "40Mhz" :
+                               is_ht80(rate) ? "80Mhz" : "ERR",
                                tbl->current_rate);
                for (j = 0; j < IWL_RATE_COUNT; j++) {
                        desc += sprintf(buff+desc,
@@ -2746,6 +2812,7 @@ static struct rate_control_ops rs_mvm_ops = {
        .free = rs_free,
        .alloc_sta = rs_alloc_sta,
        .free_sta = rs_free_sta,
+       .rate_update = rs_rate_update,
 #ifdef CONFIG_MAC80211_DEBUGFS
        .add_sta_debugfs = rs_add_debugfs,
        .remove_sta_debugfs = rs_remove_debugfs,
@@ -2778,13 +2845,13 @@ int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
 
        if (enable) {
                if (mvmsta->tx_protection == 0)
-                       lq->flags |= LQ_FLAG_SET_STA_TLC_RTS_MSK;
+                       lq->flags |= LQ_FLAG_USE_RTS_MSK;
                mvmsta->tx_protection++;
        } else {
                mvmsta->tx_protection--;
                if (mvmsta->tx_protection == 0)
-                       lq->flags &= ~LQ_FLAG_SET_STA_TLC_RTS_MSK;
+                       lq->flags &= ~LQ_FLAG_USE_RTS_MSK;
        }
 
-       return iwl_mvm_send_lq_cmd(mvm, lq, CMD_ASYNC, false);
+       return iwl_mvm_send_lq_cmd(mvm, lq, false);
 }
index 5d5344f7070bf5de62a4cde464c573b43d01f8db..b32960796384e15331fcd4b8149fbd1fb8cc91a0 100644 (file)
@@ -155,38 +155,7 @@ enum {
 #define IWL_RATE_SCALE_SWITCH          10880   /*  85% */
 #define IWL_RATE_HIGH_TH               10880   /*  85% */
 #define IWL_RATE_INCREASE_TH           6400    /*  50% */
-#define IWL_RATE_DECREASE_TH           1920    /*  15% */
-
-/* possible actions when in legacy mode */
-enum {
-       IWL_LEGACY_SWITCH_ANTENNA,
-       IWL_LEGACY_SWITCH_SISO,
-       IWL_LEGACY_SWITCH_MIMO2,
-       IWL_LEGACY_FIRST_ACTION = IWL_LEGACY_SWITCH_ANTENNA,
-       IWL_LEGACY_LAST_ACTION = IWL_LEGACY_SWITCH_MIMO2,
-};
-
-/* possible actions when in siso mode */
-enum {
-       IWL_SISO_SWITCH_ANTENNA,
-       IWL_SISO_SWITCH_MIMO2,
-       IWL_SISO_SWITCH_GI,
-       IWL_SISO_FIRST_ACTION = IWL_SISO_SWITCH_ANTENNA,
-       IWL_SISO_LAST_ACTION = IWL_SISO_SWITCH_GI,
-};
-
-/* possible actions when in mimo mode */
-enum {
-       IWL_MIMO2_SWITCH_SISO_A,
-       IWL_MIMO2_SWITCH_SISO_B,
-       IWL_MIMO2_SWITCH_GI,
-       IWL_MIMO2_FIRST_ACTION = IWL_MIMO2_SWITCH_SISO_A,
-       IWL_MIMO2_LAST_ACTION = IWL_MIMO2_SWITCH_GI,
-};
-
-#define IWL_MAX_SEARCH IWL_MIMO2_LAST_ACTION
-
-#define IWL_ACTION_LIMIT               3       /* # possible actions */
+#define RS_SR_FORCE_DECREASE           1920    /*  15% */
 
 #define LINK_QUAL_AGG_TIME_LIMIT_DEF   (4000) /* 4 milliseconds */
 #define LINK_QUAL_AGG_TIME_LIMIT_MAX   (8000)
@@ -224,22 +193,45 @@ enum iwl_table_type {
        LQ_MAX,
 };
 
-#define is_legacy(tbl) (((tbl) == LQ_LEGACY_G) || ((tbl) == LQ_LEGACY_A))
-#define is_ht_siso(tbl) ((tbl) == LQ_HT_SISO)
-#define is_ht_mimo2(tbl) ((tbl) == LQ_HT_MIMO2)
-#define is_vht_siso(tbl) ((tbl) == LQ_VHT_SISO)
-#define is_vht_mimo2(tbl) ((tbl) == LQ_VHT_MIMO2)
-#define is_siso(tbl) (is_ht_siso(tbl) || is_vht_siso(tbl))
-#define is_mimo2(tbl) (is_ht_mimo2(tbl) || is_vht_mimo2(tbl))
-#define is_mimo(tbl) (is_mimo2(tbl))
-#define is_ht(tbl) (is_ht_siso(tbl) || is_ht_mimo2(tbl))
-#define is_vht(tbl) (is_vht_siso(tbl) || is_vht_mimo2(tbl))
-#define is_a_band(tbl) ((tbl) == LQ_LEGACY_A)
-#define is_g_band(tbl) ((tbl) == LQ_LEGACY_G)
-
-#define is_ht20(tbl) (tbl->bw == RATE_MCS_CHAN_WIDTH_20)
-#define is_ht40(tbl) (tbl->bw == RATE_MCS_CHAN_WIDTH_40)
-#define is_ht80(tbl) (tbl->bw == RATE_MCS_CHAN_WIDTH_80)
+struct rs_rate {
+       int index;
+       enum iwl_table_type type;
+       u8 ant;
+       u32 bw;
+       bool sgi;
+};
+
+
+#define is_type_legacy(type) (((type) == LQ_LEGACY_G) || \
+                             ((type) == LQ_LEGACY_A))
+#define is_type_ht_siso(type) ((type) == LQ_HT_SISO)
+#define is_type_ht_mimo2(type) ((type) == LQ_HT_MIMO2)
+#define is_type_vht_siso(type) ((type) == LQ_VHT_SISO)
+#define is_type_vht_mimo2(type) ((type) == LQ_VHT_MIMO2)
+#define is_type_siso(type) (is_type_ht_siso(type) || is_type_vht_siso(type))
+#define is_type_mimo2(type) (is_type_ht_mimo2(type) || is_type_vht_mimo2(type))
+#define is_type_mimo(type) (is_type_mimo2(type))
+#define is_type_ht(type) (is_type_ht_siso(type) || is_type_ht_mimo2(type))
+#define is_type_vht(type) (is_type_vht_siso(type) || is_type_vht_mimo2(type))
+#define is_type_a_band(type) ((type) == LQ_LEGACY_A)
+#define is_type_g_band(type) ((type) == LQ_LEGACY_G)
+
+#define is_legacy(rate)       is_type_legacy((rate)->type)
+#define is_ht_siso(rate)      is_type_ht_siso((rate)->type)
+#define is_ht_mimo2(rate)     is_type_ht_mimo2((rate)->type)
+#define is_vht_siso(rate)     is_type_vht_siso((rate)->type)
+#define is_vht_mimo2(rate)    is_type_vht_mimo2((rate)->type)
+#define is_siso(rate)         is_type_siso((rate)->type)
+#define is_mimo2(rate)        is_type_mimo2((rate)->type)
+#define is_mimo(rate)         is_type_mimo((rate)->type)
+#define is_ht(rate)           is_type_ht((rate)->type)
+#define is_vht(rate)          is_type_vht((rate)->type)
+#define is_a_band(rate)       is_type_a_band((rate)->type)
+#define is_g_band(rate)       is_type_g_band((rate)->type)
+
+#define is_ht20(rate)         ((rate)->bw == RATE_MCS_CHAN_WIDTH_20)
+#define is_ht40(rate)         ((rate)->bw == RATE_MCS_CHAN_WIDTH_40)
+#define is_ht80(rate)         ((rate)->bw == RATE_MCS_CHAN_WIDTH_80)
 
 #define IWL_MAX_MCS_DISPLAY_SIZE       12
 
@@ -257,7 +249,23 @@ struct iwl_rate_scale_data {
        s32 success_ratio;      /* per-cent * 128  */
        s32 counter;            /* number of frames attempted */
        s32 average_tpt;        /* success ratio * expected throughput */
-       unsigned long stamp;
+};
+
+/* Possible Tx columns
+ * Tx Column = a combo of legacy/siso/mimo x antenna x SGI
+ */
+enum rs_column {
+       RS_COLUMN_LEGACY_ANT_A = 0,
+       RS_COLUMN_LEGACY_ANT_B,
+       RS_COLUMN_SISO_ANT_A,
+       RS_COLUMN_SISO_ANT_B,
+       RS_COLUMN_SISO_ANT_A_SGI,
+       RS_COLUMN_SISO_ANT_B_SGI,
+       RS_COLUMN_MIMO2,
+       RS_COLUMN_MIMO2_SGI,
+
+       RS_COLUMN_LAST = RS_COLUMN_MIMO2_SGI,
+       RS_COLUMN_INVALID,
 };
 
 /**
@@ -267,17 +275,19 @@ struct iwl_rate_scale_data {
  * one for "active", and one for "search".
  */
 struct iwl_scale_tbl_info {
-       enum iwl_table_type lq_type;
-       u8 ant_type;
-       u8 is_SGI;      /* 1 = short guard interval */
-       u32 bw;         /* channel bandwidth; RATE_MCS_CHAN_WIDTH_XX */
-       u8 action;      /* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */
-       u8 max_search;  /* maximun number of tables we can search */
+       struct rs_rate rate;
+       enum rs_column column;
        s32 *expected_tpt;      /* throughput metrics; expected_tpt_G, etc. */
        u32 current_rate;  /* rate_n_flags, uCode API format */
        struct iwl_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */
 };
 
+enum {
+       RS_STATE_SEARCH_CYCLE_STARTED,
+       RS_STATE_SEARCH_CYCLE_ENDED,
+       RS_STATE_STAY_IN_COLUMN,
+};
+
 /**
  * struct iwl_lq_sta -- driver's rate scaling private structure
  *
@@ -285,8 +295,7 @@ struct iwl_scale_tbl_info {
  */
 struct iwl_lq_sta {
        u8 active_tbl;          /* index of active table, range 0-1 */
-       u8 enable_counter;      /* indicates HT mode */
-       u8 stay_in_tbl;         /* 1: disallow, 0: allow search for new mode */
+       u8 rs_state;            /* RS_STATE_* */
        u8 search_better_tbl;   /* 1: currently trying alternate mode */
        s32 last_tpt;
 
@@ -299,7 +308,9 @@ struct iwl_lq_sta {
        u32 total_success;      /* total successful frames, any/all rates */
        u64 flush_timer;        /* time staying in mode before new search */
 
-       u8 action_counter;      /* # mode-switch actions tried */
+       u32 visited_columns;    /* Bitmask marking which Tx columns were
+                                * explored during a search cycle
+                                */
        bool is_vht;
        enum ieee80211_band band;
 
@@ -328,32 +339,11 @@ struct iwl_lq_sta {
        u32 last_rate_n_flags;
        /* packets destined for this STA are aggregated */
        u8 is_agg;
-       /* BT traffic this sta was last updated in */
-       u8 last_bt_traffic;
-};
-
-enum iwl_bt_coex_profile_traffic_load {
-       IWL_BT_COEX_TRAFFIC_LOAD_NONE           = 0,
-       IWL_BT_COEX_TRAFFIC_LOAD_LOW            = 1,
-       IWL_BT_COEX_TRAFFIC_LOAD_HIGH           = 2,
-       IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS     = 3,
-/*
- * There are no more even though below is a u8, the
- * indication from the BT device only has two bits.
- */
 };
 
-
-static inline u8 num_of_ant(u8 mask)
-{
-       return  !!((mask) & ANT_A) +
-               !!((mask) & ANT_B) +
-               !!((mask) & ANT_C);
-}
-
 /* Initialize station's rate scaling information after adding station */
 void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
-                         enum ieee80211_band band);
+                         enum ieee80211_band band, bool init);
 
 /**
  * iwl_rate_control_register - Register the rate control algorithm callbacks
index dff7592e1ff84e5c3f6a05d673e2a39514cbb870..4ce9bb581144e4a64c8842980e41e0097a4da6e9 100644 (file)
@@ -70,6 +70,9 @@
 
 #define IWL_PLCP_QUIET_THRESH 1
 #define IWL_ACTIVE_QUIET_TIME 10
+#define LONG_OUT_TIME_PERIOD 600
+#define SHORT_OUT_TIME_PERIOD 200
+#define SUSPEND_TIME_PERIOD 100
 
 static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm)
 {
@@ -87,20 +90,22 @@ static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm)
        return cpu_to_le16(rx_chain);
 }
 
-static inline __le32 iwl_mvm_scan_max_out_time(struct ieee80211_vif *vif)
+static inline __le32 iwl_mvm_scan_max_out_time(struct ieee80211_vif *vif,
+                                              u32 flags, bool is_assoc)
 {
-       if (vif->bss_conf.assoc)
-               return cpu_to_le32(200 * 1024);
-       else
+       if (!is_assoc)
                return 0;
+       if (flags & NL80211_SCAN_FLAG_LOW_PRIORITY)
+               return cpu_to_le32(ieee80211_tu_to_usec(SHORT_OUT_TIME_PERIOD));
+       return cpu_to_le32(ieee80211_tu_to_usec(LONG_OUT_TIME_PERIOD));
 }
 
-static inline __le32 iwl_mvm_scan_suspend_time(struct ieee80211_vif *vif)
+static inline __le32 iwl_mvm_scan_suspend_time(struct ieee80211_vif *vif,
+                                              bool is_assoc)
 {
-       if (!vif->bss_conf.assoc)
+       if (!is_assoc)
                return 0;
-
-       return cpu_to_le32(ieee80211_tu_to_usec(vif->bss_conf.beacon_int));
+       return cpu_to_le32(ieee80211_tu_to_usec(SUSPEND_TIME_PERIOD));
 }
 
 static inline __le32
@@ -192,7 +197,7 @@ static void iwl_mvm_scan_fill_channels(struct iwl_scan_cmd *cmd,
        for (i = 0; i < cmd->channel_count; i++) {
                chan->channel = cpu_to_le16(req->channels[i]->hw_value);
                chan->type = cpu_to_le32(type);
-               if (req->channels[i]->flags & IEEE80211_CHAN_PASSIVE_SCAN)
+               if (req->channels[i]->flags & IEEE80211_CHAN_NO_IR)
                        chan->type &= cpu_to_le32(~SCAN_CHANNEL_TYPE_ACTIVE);
                chan->active_dwell = cpu_to_le16(active_dwell);
                chan->passive_dwell = cpu_to_le16(passive_dwell);
@@ -262,6 +267,15 @@ static u16 iwl_mvm_fill_probe_req(struct ieee80211_mgmt *frame, const u8 *ta,
        return (u16)len;
 }
 
+static void iwl_mvm_vif_assoc_iterator(void *data, u8 *mac,
+                                      struct ieee80211_vif *vif)
+{
+       bool *is_assoc = data;
+
+       if (vif->bss_conf.assoc)
+               *is_assoc = true;
+}
+
 int iwl_mvm_scan_request(struct iwl_mvm *mvm,
                         struct ieee80211_vif *vif,
                         struct cfg80211_scan_request *req)
@@ -274,6 +288,7 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm,
                .dataflags = { IWL_HCMD_DFL_NOCOPY, },
        };
        struct iwl_scan_cmd *cmd = mvm->scan_cmd;
+       bool is_assoc = false;
        int ret;
        u32 status;
        int ssid_len = 0;
@@ -289,13 +304,17 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm,
        memset(cmd, 0, sizeof(struct iwl_scan_cmd) +
               mvm->fw->ucode_capa.max_probe_length +
               (MAX_NUM_SCAN_CHANNELS * sizeof(struct iwl_scan_channel)));
-
+       ieee80211_iterate_active_interfaces_atomic(mvm->hw,
+                                           IEEE80211_IFACE_ITER_NORMAL,
+                                           iwl_mvm_vif_assoc_iterator,
+                                           &is_assoc);
        cmd->channel_count = (u8)req->n_channels;
        cmd->quiet_time = cpu_to_le16(IWL_ACTIVE_QUIET_TIME);
        cmd->quiet_plcp_th = cpu_to_le16(IWL_PLCP_QUIET_THRESH);
        cmd->rxchain_sel_flags = iwl_mvm_scan_rx_chain(mvm);
-       cmd->max_out_time = iwl_mvm_scan_max_out_time(vif);
-       cmd->suspend_time = iwl_mvm_scan_suspend_time(vif);
+       cmd->max_out_time = iwl_mvm_scan_max_out_time(vif, req->flags,
+                                                     is_assoc);
+       cmd->suspend_time = iwl_mvm_scan_suspend_time(vif, is_assoc);
        cmd->rxon_flags = iwl_mvm_scan_rxon_flags(req);
        cmd->filter_flags = cpu_to_le32(MAC_FILTER_ACCEPT_GRP |
                                        MAC_FILTER_IN_BEACON);
@@ -522,6 +541,12 @@ static void iwl_build_scan_cmd(struct iwl_mvm *mvm,
                               struct cfg80211_sched_scan_request *req,
                               struct iwl_scan_offload_cmd *scan)
 {
+       bool is_assoc = false;
+
+       ieee80211_iterate_active_interfaces_atomic(mvm->hw,
+                                           IEEE80211_IFACE_ITER_NORMAL,
+                                           iwl_mvm_vif_assoc_iterator,
+                                           &is_assoc);
        scan->channel_count =
                mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels +
                mvm->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels;
@@ -529,8 +554,9 @@ static void iwl_build_scan_cmd(struct iwl_mvm *mvm,
        scan->quiet_plcp_th = cpu_to_le16(IWL_PLCP_QUIET_THRESH);
        scan->good_CRC_th = IWL_GOOD_CRC_TH_DEFAULT;
        scan->rx_chain = iwl_mvm_scan_rx_chain(mvm);
-       scan->max_out_time = cpu_to_le32(200 * 1024);
-       scan->suspend_time = iwl_mvm_scan_suspend_time(vif);
+       scan->max_out_time = iwl_mvm_scan_max_out_time(vif, req->flags,
+                                                      is_assoc);
+       scan->suspend_time = iwl_mvm_scan_suspend_time(vif, is_assoc);
        scan->filter_flags |= cpu_to_le32(MAC_FILTER_ACCEPT_GRP |
                                          MAC_FILTER_IN_BEACON);
        scan->scan_type = cpu_to_le32(SCAN_TYPE_BACKGROUND);
@@ -642,7 +668,7 @@ static void iwl_build_channel_cfg(struct iwl_mvm *mvm,
                channels->iter_count[index] = cpu_to_le16(1);
                channels->iter_interval[index] = 0;
 
-               if (!(s_band->channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN))
+               if (!(s_band->channels[i].flags & IEEE80211_CHAN_NO_IR))
                        channels->type[index] |=
                                cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_ACTIVE);
 
@@ -817,11 +843,10 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
                IWL_DEBUG_SCAN(mvm,
                               "Sending scheduled scan with filtering, filter len %d\n",
                               req->n_match_sets);
-               scan_req.flags |=
-                               cpu_to_le16(IWL_SCAN_OFFLOAD_FLAG_FILTER_SSID);
        } else {
                IWL_DEBUG_SCAN(mvm,
                               "Sending Scheduled scan without filtering\n");
+               scan_req.flags |= cpu_to_le16(IWL_SCAN_OFFLOAD_FLAG_PASS_ALL);
        }
 
        return iwl_mvm_send_cmd_pdu(mvm, SCAN_OFFLOAD_REQUEST_CMD, CMD_SYNC,
index 329952363a54f3b2c0913d018c401e9c7004fcfc..7a5b7473eafa615e946d3d4fe0802129149858bc 100644 (file)
@@ -840,7 +840,7 @@ static const u8 tid_to_ac[] = {
 int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
                             struct ieee80211_sta *sta, u16 tid, u16 *ssn)
 {
-       struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv;
+       struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
        struct iwl_mvm_tid_data *tid_data;
        int txq_id;
 
@@ -895,7 +895,7 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
                            struct ieee80211_sta *sta, u16 tid, u8 buf_size)
 {
-       struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv;
+       struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
        struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid];
        int queue, fifo, ret;
        u16 ssn;
@@ -945,13 +945,13 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
                 */
        }
 
-       return iwl_mvm_send_lq_cmd(mvm, &mvmsta->lq_sta.lq, CMD_ASYNC, false);
+       return iwl_mvm_send_lq_cmd(mvm, &mvmsta->lq_sta.lq, false);
 }
 
 int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
                            struct ieee80211_sta *sta, u16 tid)
 {
-       struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv;
+       struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
        struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid];
        u16 txq_id;
        int err;
@@ -1023,7 +1023,7 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
                            struct ieee80211_sta *sta, u16 tid)
 {
-       struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv;
+       struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
        struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid];
        u16 txq_id;
        enum iwl_mvm_agg_state old_state;
@@ -1416,7 +1416,7 @@ void iwl_mvm_update_tkip_key(struct iwl_mvm *mvm,
 void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm,
                                struct ieee80211_sta *sta)
 {
-       struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv;
+       struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
        struct iwl_mvm_add_sta_cmd_v6 cmd = {
                .add_modify = STA_MODE_MODIFY,
                .sta_id = mvmsta->sta_id,
@@ -1438,7 +1438,7 @@ void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm,
        u16 sleep_state_flags =
                (reason == IEEE80211_FRAME_RELEASE_UAPSD) ?
                        STA_SLEEP_STATE_UAPSD : STA_SLEEP_STATE_PS_POLL;
-       struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv;
+       struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
        struct iwl_mvm_add_sta_cmd_v6 cmd = {
                .add_modify = STA_MODE_MODIFY,
                .sta_id = mvmsta->sta_id,
index 4dfc359a4bdda187cbb1fdcbda8b4cfe112c78fd..b34941148a9834161eea211bfb17e9c568e9aa6d 100644 (file)
@@ -298,6 +298,12 @@ struct iwl_mvm_sta {
        bool tt_tx_protection;
 };
 
+static inline struct iwl_mvm_sta *
+iwl_mvm_sta_from_mac80211(struct ieee80211_sta *sta)
+{
+       return (void *)sta->drv_priv;
+}
+
 /**
  * struct iwl_mvm_int_sta - representation of an internal station (auxiliary or
  * broadcast)
index 33cf56fdfc41f86b8bb517a8824740bdbb71a896..95ce4b601fef3050085518e59a4e32036c57fbfc 100644 (file)
@@ -176,8 +176,11 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
         * P2P Device discoveribility, while there are other higher priority
         * events in the system).
         */
-       if (WARN_ONCE(!le32_to_cpu(notif->status),
-                     "Failed to schedule time event\n")) {
+       if (!le32_to_cpu(notif->status)) {
+               bool start = le32_to_cpu(notif->action) &
+                               TE_V2_NOTIF_HOST_EVENT_START;
+               IWL_WARN(mvm, "Time Event %s notification failure\n",
+                        start ? "start" : "end");
                if (iwl_mvm_te_check_disconnect(mvm, te_data->vif, NULL)) {
                        iwl_mvm_te_clear_data(mvm, te_data);
                        return;
index 1f3282dff5136fa305c894c9c35ee5914dd63ddd..18be04da8e3fe5449307d4c63c5e6714e0e032e1 100644 (file)
@@ -388,7 +388,7 @@ static void iwl_mvm_tt_tx_protection(struct iwl_mvm *mvm, bool enable)
                                                lockdep_is_held(&mvm->mutex));
                if (IS_ERR_OR_NULL(sta))
                        continue;
-               mvmsta = (void *)sta->drv_priv;
+               mvmsta = iwl_mvm_sta_from_mac80211(sta);
                if (enable == mvmsta->tt_tx_protection)
                        continue;
                err = iwl_mvm_tx_protection(mvm, mvmsta, enable);
index 43d97c33a75abcbf3833958b0c5cbca5a91e0950..d87649ac88e1419fde870f4f7fdb4abc1d520fab 100644 (file)
@@ -276,6 +276,7 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
                return NULL;
 
        memset(dev_cmd, 0, sizeof(*dev_cmd));
+       dev_cmd->hdr.cmd = TX_CMD;
        tx_cmd = (struct iwl_tx_cmd *)dev_cmd->payload;
 
        if (info->control.hw_key)
@@ -361,7 +362,7 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
        u8 txq_id = info->hw_queue;
        bool is_data_qos = false, is_ampdu = false;
 
-       mvmsta = (void *)sta->drv_priv;
+       mvmsta = iwl_mvm_sta_from_mac80211(sta);
        fc = hdr->frame_control;
 
        if (WARN_ON_ONCE(!mvmsta))
@@ -432,7 +433,7 @@ drop:
 static void iwl_mvm_check_ratid_empty(struct iwl_mvm *mvm,
                                      struct ieee80211_sta *sta, u8 tid)
 {
-       struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv;
+       struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
        struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid];
        struct ieee80211_vif *vif = mvmsta->vif;
 
@@ -662,7 +663,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
        sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
 
        if (!IS_ERR_OR_NULL(sta)) {
-               mvmsta = (void *)sta->drv_priv;
+               mvmsta = iwl_mvm_sta_from_mac80211(sta);
 
                if (tid != IWL_TID_NON_QOS) {
                        struct iwl_mvm_tid_data *tid_data =
@@ -793,7 +794,7 @@ static void iwl_mvm_rx_tx_cmd_agg(struct iwl_mvm *mvm,
        sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
 
        if (!WARN_ON_ONCE(IS_ERR_OR_NULL(sta))) {
-               struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv;
+               struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
                mvmsta->tid_data[tid].rate_n_flags =
                        le32_to_cpu(tx_resp->initial_rate);
        }
@@ -849,7 +850,7 @@ int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
                return 0;
        }
 
-       mvmsta = (void *)sta->drv_priv;
+       mvmsta = iwl_mvm_sta_from_mac80211(sta);
        tid_data = &mvmsta->tid_data[tid];
 
        if (WARN_ONCE(tid_data->txq_id != scd_flow, "Q %d, tid %d, flow %d",
index ed69e9b78e82ba325a533624107974ea81af526d..56cf819bc0c7003d970a16b08b493804d6e2544b 100644 (file)
@@ -486,22 +486,18 @@ void iwl_mvm_dump_sram(struct iwl_mvm *mvm)
  * this case to clear the state indicating that station creation is in
  * progress.
  */
-int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq,
-                       u8 flags, bool init)
+int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, bool init)
 {
        struct iwl_host_cmd cmd = {
                .id = LQ_CMD,
                .len = { sizeof(struct iwl_lq_cmd), },
-               .flags = flags,
+               .flags = init ? CMD_SYNC : CMD_ASYNC,
                .data = { lq, },
        };
 
        if (WARN_ON(lq->sta_id == IWL_MVM_STATION_COUNT))
                return -EINVAL;
 
-       if (WARN_ON(init && (cmd.flags & CMD_ASYNC)))
-               return -EINVAL;
-
        return iwl_mvm_send_cmd(mvm, &cmd);
 }
 
index 941c0c88f982639b28436a60e52a0fdc6fba8c4b..2e97a39953339abdf436b90c2553c790b342ab07 100644 (file)
@@ -297,6 +297,9 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
        {IWL_PCI_DEVICE(0x08B2, 0x4370, iwl7260_2ac_cfg)},
        {IWL_PCI_DEVICE(0x08B2, 0x4360, iwl7260_2n_cfg)},
        {IWL_PCI_DEVICE(0x08B1, 0x5070, iwl7260_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x08B1, 0x5072, iwl7260_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x08B1, 0x5170, iwl7260_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x08B1, 0x5770, iwl7260_2ac_cfg)},
        {IWL_PCI_DEVICE(0x08B1, 0x4020, iwl7260_2n_cfg)},
        {IWL_PCI_DEVICE(0x08B1, 0x402A, iwl7260_2n_cfg)},
        {IWL_PCI_DEVICE(0x08B2, 0x4220, iwl7260_2n_cfg)},
@@ -350,9 +353,32 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
        {IWL_PCI_DEVICE(0x08B4, 0x8270, iwl3160_2ac_cfg)},
        {IWL_PCI_DEVICE(0x08B3, 0x8470, iwl3160_2ac_cfg)},
        {IWL_PCI_DEVICE(0x08B3, 0x8570, iwl3160_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x08B3, 0x1070, iwl3160_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x08B3, 0x1170, iwl3160_2ac_cfg)},
 
 /* 7265 Series */
        {IWL_PCI_DEVICE(0x095A, 0x5010, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5110, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095B, 0x5310, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095B, 0x5302, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095B, 0x5210, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095B, 0x5012, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095B, 0x500A, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5410, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x1010, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5000, iwl7265_2n_cfg)},
+       {IWL_PCI_DEVICE(0x095B, 0x5200, iwl7265_2n_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5002, iwl7265_n_cfg)},
+       {IWL_PCI_DEVICE(0x095B, 0x5202, iwl7265_n_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x9010, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x9210, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x9410, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5020, iwl7265_2n_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x502A, iwl7265_2n_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5420, iwl7265_2n_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5090, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095B, 0x5290, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5490, iwl7265_2ac_cfg)},
 #endif /* CONFIG_IWLMVM */
 
        {0}
index fa22639b63c947d68247698cf109070a823b792b..051268c037b1d4f7d03715cdbf13b68311f883ff 100644 (file)
@@ -477,4 +477,12 @@ static inline bool iwl_is_rfkill_set(struct iwl_trans *trans)
                CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW);
 }
 
+static inline void iwl_nic_error(struct iwl_trans *trans)
+{
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+
+       set_bit(STATUS_FW_ERROR, &trans_pcie->status);
+       iwl_op_mode_nic_error(trans->op_mode);
+}
+
 #endif /* __iwl_trans_int_pcie_h__ */
index 3f237b42eb36d3c94cc84f94d0ba86b6a7861e41..1d6bf7b98e2d0075c1e09f05b5f4ee96dce71474 100644 (file)
@@ -489,6 +489,10 @@ static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq)
 
        /* Set interrupt coalescing timer to default (2048 usecs) */
        iwl_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF);
+
+       /* W/A for interrupt coalescing bug in 7260 and 3160 */
+       if (trans->cfg->host_interrupt_operation_mode)
+               iwl_set_bit(trans, CSR_INT_COALESCING, IWL_HOST_INT_OPER_MODE);
 }
 
 static void iwl_pcie_rx_init_rxb_lists(struct iwl_rxq *rxq)
@@ -796,12 +800,13 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans)
        iwl_pcie_dump_csr(trans);
        iwl_dump_fh(trans, NULL);
 
+       /* set the ERROR bit before we wake up the caller */
        set_bit(STATUS_FW_ERROR, &trans_pcie->status);
        clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status);
        wake_up(&trans_pcie->wait_command_queue);
 
        local_bh_disable();
-       iwl_op_mode_nic_error(trans->op_mode);
+       iwl_nic_error(trans);
        local_bh_enable();
 }
 
@@ -1121,7 +1126,6 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data)
        struct iwl_trans *trans = data;
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        u32 inta, inta_mask;
-       irqreturn_t ret = IRQ_NONE;
 
        lockdep_assert_held(&trans_pcie->irq_lock);
 
@@ -1150,7 +1154,16 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data)
         * or due to sporadic interrupts thrown from our NIC. */
        if (!inta) {
                IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n");
-               goto none;
+               /*
+                * Re-enable interrupts here since we don't have anything to
+                * service, but only in case the handler won't run. Note that
+                * the handler can be scheduled because of a previous
+                * interrupt.
+                */
+               if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) &&
+                   !trans_pcie->inta)
+                       iwl_enable_interrupts(trans);
+               return IRQ_NONE;
        }
 
        if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
@@ -1168,19 +1181,7 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data)
 
        trans_pcie->inta |= inta;
        /* the thread will service interrupts and re-enable them */
-       if (likely(inta))
-               return IRQ_WAKE_THREAD;
-
-       ret = IRQ_HANDLED;
-
-none:
-       /* re-enable interrupts here since we don't have anything to service. */
-       /* only Re-enable if disabled by irq  and no schedules tasklet. */
-       if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) &&
-           !trans_pcie->inta)
-               iwl_enable_interrupts(trans);
-
-       return ret;
+       return IRQ_WAKE_THREAD;
 }
 
 /* interrupt handler using ict table, with this interrupt driver will
index 5d9337bec67a87c59f3ccef73e5f5b26644930d5..cde9c16f6e4febb26c66c2206068bdba973c708a 100644 (file)
@@ -279,9 +279,6 @@ static int iwl_pcie_nic_init(struct iwl_trans *trans)
        spin_lock_irqsave(&trans_pcie->irq_lock, flags);
        iwl_pcie_apm_init(trans);
 
-       /* Set interrupt coalescing calibration timer to default (512 usecs) */
-       iwl_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF);
-
        spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 
        iwl_pcie_set_pwr(trans, false);
index 059c5acad3a0d2e7b9eb73bf6466ef088e54e5c2..a4ef5cc1110010d76439a670242c8d9a22888094 100644 (file)
@@ -207,7 +207,7 @@ static void iwl_pcie_txq_stuck_timer(unsigned long data)
                IWL_ERR(trans, "scratch %d = 0x%08x\n", i,
                        le32_to_cpu(txq->scratchbufs[i].scratch));
 
-       iwl_op_mode_nic_error(trans->op_mode);
+       iwl_nic_error(trans);
 }
 
 /*
@@ -1023,7 +1023,7 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx)
                if (nfreed++ > 0) {
                        IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n",
                                idx, q->write_ptr, q->read_ptr);
-                       iwl_op_mode_nic_error(trans->op_mode);
+                       iwl_nic_error(trans);
                }
        }
 
@@ -1542,30 +1542,24 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
        }
 
        if (!ret) {
-               if (test_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status)) {
-                       struct iwl_txq *txq =
-                               &trans_pcie->txq[trans_pcie->cmd_queue];
-                       struct iwl_queue *q = &txq->q;
+               struct iwl_txq *txq = &trans_pcie->txq[trans_pcie->cmd_queue];
+               struct iwl_queue *q = &txq->q;
 
-                       IWL_ERR(trans,
-                               "Error sending %s: time out after %dms.\n",
-                               get_cmd_string(trans_pcie, cmd->id),
-                               jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
+               IWL_ERR(trans, "Error sending %s: time out after %dms.\n",
+                       get_cmd_string(trans_pcie, cmd->id),
+                       jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
 
-                       IWL_ERR(trans,
-                               "Current CMD queue read_ptr %d write_ptr %d\n",
-                               q->read_ptr, q->write_ptr);
+               IWL_ERR(trans, "Current CMD queue read_ptr %d write_ptr %d\n",
+                       q->read_ptr, q->write_ptr);
 
-                       clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status);
-                       IWL_DEBUG_INFO(trans,
-                                      "Clearing HCMD_ACTIVE for command %s\n",
-                                      get_cmd_string(trans_pcie, cmd->id));
-                       ret = -ETIMEDOUT;
+               clear_bit(STATUS_HCMD_ACTIVE, &trans_pcie->status);
+               IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n",
+                              get_cmd_string(trans_pcie, cmd->id));
+               ret = -ETIMEDOUT;
 
-                       iwl_op_mode_nic_error(trans->op_mode);
+               iwl_nic_error(trans);
 
-                       goto cancel;
-               }
+               goto cancel;
        }
 
        if (test_bit(STATUS_FW_ERROR, &trans_pcie->status)) {
@@ -1674,7 +1668,6 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
        txq->entries[q->write_ptr].skb = skb;
        txq->entries[q->write_ptr].cmd = dev_cmd;
 
-       dev_cmd->hdr.cmd = REPLY_TX;
        dev_cmd->hdr.sequence =
                cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
                            INDEX_TO_SEQ(q->write_ptr)));
index 91f2ca90c70faa9e010e9ff51ea6d306e199ef40..1a554a685e91f16035dae2396ec1242005e7a2f0 100644 (file)
@@ -8,9 +8,8 @@
  Ltd. under the terms of the GNU General Public License Version 2, June 1991
  (the "License").  You may use, redistribute and/or modify this File in
  accordance with the terms and conditions of the License, a copy of which
- is available along with the File in the license.txt file or by writing to
- the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+ is available along with the File in the license.txt file or on the worldwide
+ web at http://www.gnu.org/licenses/gpl.txt.
 
  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
index 991238afd1b60c04ae437fafeb7a108713ea3134..58c6ee5de98f9256b2e3db4735adbfe1fed299bd 100644 (file)
@@ -849,7 +849,7 @@ static void if_sdio_finish_power_on(struct if_sdio_card *card)
                        card->started = true;
                        /* Tell PM core that we don't need the card to be
                         * powered now */
-                       pm_runtime_put_noidle(&func->dev);
+                       pm_runtime_put(&func->dev);
                }
        }
 
@@ -907,8 +907,8 @@ static int if_sdio_power_on(struct if_sdio_card *card)
        sdio_release_host(func);
        ret = if_sdio_prog_firmware(card);
        if (ret) {
-               sdio_disable_func(func);
-               return ret;
+               sdio_claim_host(func);
+               goto disable;
        }
 
        return 0;
index 83669151bb8242e31931735700eb27fe4cd01821..f11728a866ff3129b44e33ae6aa8597171c7005b 100644 (file)
@@ -93,7 +93,6 @@ static void free_if_spi_card(struct if_spi_card *card)
                list_del(&packet->list);
                kfree(packet);
        }
-       spi_set_drvdata(card->spi, NULL);
        kfree(card);
 }
 
index 9df7bc91a26f54c9812718e481c538895aa5b4f8..9c0cc8ded0216de43d09300dbed19cfa9fe2e3b3 100644 (file)
@@ -159,7 +159,7 @@ static const struct ieee80211_regdomain hwsim_world_regdom_custom_02 = {
        .reg_rules = {
                REG_RULE(2412-10, 2462+10, 40, 0, 20, 0),
                REG_RULE(5725-10, 5850+10, 40, 0, 30,
-                       NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS),
+                        NL80211_RRF_NO_IR),
        }
 };
 
@@ -353,7 +353,6 @@ struct mac80211_hwsim_data {
        } ps;
        bool ps_poll_pending;
        struct dentry *debugfs;
-       struct dentry *debugfs_ps;
 
        struct sk_buff_head pending;    /* packets pending */
        /*
@@ -362,7 +361,6 @@ struct mac80211_hwsim_data {
         * radio can be in more then one group.
         */
        u64 group;
-       struct dentry *debugfs_group;
 
        int power_level;
 
@@ -383,6 +381,14 @@ struct hwsim_radiotap_hdr {
        __le16 rt_chbitmask;
 } __packed;
 
+struct hwsim_radiotap_ack_hdr {
+       struct ieee80211_radiotap_header hdr;
+       u8 rt_flags;
+       u8 pad;
+       __le16 rt_channel;
+       __le16 rt_chbitmask;
+} __packed;
+
 /* MAC80211_HWSIM netlinf family */
 static struct genl_family hwsim_genl_family = {
        .id = GENL_ID_GENERATE,
@@ -500,7 +506,7 @@ static void mac80211_hwsim_monitor_ack(struct ieee80211_channel *chan,
                                       const u8 *addr)
 {
        struct sk_buff *skb;
-       struct hwsim_radiotap_hdr *hdr;
+       struct hwsim_radiotap_ack_hdr *hdr;
        u16 flags;
        struct ieee80211_hdr *hdr11;
 
@@ -511,14 +517,14 @@ static void mac80211_hwsim_monitor_ack(struct ieee80211_channel *chan,
        if (skb == NULL)
                return;
 
-       hdr = (struct hwsim_radiotap_hdr *) skb_put(skb, sizeof(*hdr));
+       hdr = (struct hwsim_radiotap_ack_hdr *) skb_put(skb, sizeof(*hdr));
        hdr->hdr.it_version = PKTHDR_RADIOTAP_VERSION;
        hdr->hdr.it_pad = 0;
        hdr->hdr.it_len = cpu_to_le16(sizeof(*hdr));
        hdr->hdr.it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
                                          (1 << IEEE80211_RADIOTAP_CHANNEL));
        hdr->rt_flags = 0;
-       hdr->rt_rate = 0;
+       hdr->pad = 0;
        hdr->rt_channel = cpu_to_le16(chan->center_freq);
        flags = IEEE80211_CHAN_2GHZ;
        hdr->rt_chbitmask = cpu_to_le16(flags);
@@ -1230,7 +1236,7 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw,
                                              HRTIMER_MODE_REL);
                } else if (!info->enable_beacon) {
                        unsigned int count = 0;
-                       ieee80211_iterate_active_interfaces(
+                       ieee80211_iterate_active_interfaces_atomic(
                                data->hw, IEEE80211_IFACE_ITER_NORMAL,
                                mac80211_hwsim_bcn_en_iter, &count);
                        wiphy_debug(hw->wiphy, "  beaconing vifs remaining: %u",
@@ -1485,7 +1491,7 @@ static void hw_scan_work(struct work_struct *work)
                    req->channels[hwsim->scan_chan_idx]->center_freq);
 
        hwsim->tmp_chan = req->channels[hwsim->scan_chan_idx];
-       if (hwsim->tmp_chan->flags & IEEE80211_CHAN_PASSIVE_SCAN ||
+       if (hwsim->tmp_chan->flags & IEEE80211_CHAN_NO_IR ||
            !req->n_ssids) {
                dwell = 120;
        } else {
@@ -1734,9 +1740,7 @@ static void mac80211_hwsim_free(void)
        spin_unlock_bh(&hwsim_radio_lock);
 
        list_for_each_entry_safe(data, tmpdata, &tmplist, list) {
-               debugfs_remove(data->debugfs_group);
-               debugfs_remove(data->debugfs_ps);
-               debugfs_remove(data->debugfs);
+               debugfs_remove_recursive(data->debugfs);
                ieee80211_unregister_hw(data->hw);
                device_release_driver(data->dev);
                device_unregister(data->dev);
@@ -1893,6 +1897,17 @@ static int hwsim_fops_ps_write(void *dat, u64 val)
 DEFINE_SIMPLE_ATTRIBUTE(hwsim_fops_ps, hwsim_fops_ps_read, hwsim_fops_ps_write,
                        "%llu\n");
 
+static int hwsim_write_simulate_radar(void *dat, u64 val)
+{
+       struct mac80211_hwsim_data *data = dat;
+
+       ieee80211_radar_detected(data->hw);
+
+       return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(hwsim_simulate_radar, NULL,
+                       hwsim_write_simulate_radar, "%llu\n");
 
 static int hwsim_fops_group_read(void *dat, u64 *val)
 {
@@ -2193,11 +2208,28 @@ static const struct ieee80211_iface_limit hwsim_if_limits[] = {
        { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_DEVICE) },
 };
 
-static struct ieee80211_iface_combination hwsim_if_comb = {
-       .limits = hwsim_if_limits,
-       .n_limits = ARRAY_SIZE(hwsim_if_limits),
-       .max_interfaces = 2048,
-       .num_different_channels = 1,
+static const struct ieee80211_iface_limit hwsim_if_dfs_limits[] = {
+       { .max = 8, .types = BIT(NL80211_IFTYPE_AP) },
+};
+
+static struct ieee80211_iface_combination hwsim_if_comb[] = {
+       {
+               .limits = hwsim_if_limits,
+               .n_limits = ARRAY_SIZE(hwsim_if_limits),
+               .max_interfaces = 2048,
+               .num_different_channels = 1,
+       },
+       {
+               .limits = hwsim_if_dfs_limits,
+               .n_limits = ARRAY_SIZE(hwsim_if_dfs_limits),
+               .max_interfaces = 8,
+               .num_different_channels = 1,
+               .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
+                                      BIT(NL80211_CHAN_WIDTH_20) |
+                                      BIT(NL80211_CHAN_WIDTH_40) |
+                                      BIT(NL80211_CHAN_WIDTH_80) |
+                                      BIT(NL80211_CHAN_WIDTH_160),
+       }
 };
 
 static int __init init_mac80211_hwsim(void)
@@ -2215,7 +2247,7 @@ static int __init init_mac80211_hwsim(void)
                return -EINVAL;
 
        if (channels > 1) {
-               hwsim_if_comb.num_different_channels = channels;
+               hwsim_if_comb[0].num_different_channels = channels;
                mac80211_hwsim_ops.hw_scan = mac80211_hwsim_hw_scan;
                mac80211_hwsim_ops.cancel_hw_scan =
                        mac80211_hwsim_cancel_hw_scan;
@@ -2295,13 +2327,15 @@ static int __init init_mac80211_hwsim(void)
                hw->wiphy->n_addresses = 2;
                hw->wiphy->addresses = data->addresses;
 
-               hw->wiphy->iface_combinations = &hwsim_if_comb;
-               hw->wiphy->n_iface_combinations = 1;
+               hw->wiphy->iface_combinations = hwsim_if_comb;
+               hw->wiphy->n_iface_combinations = ARRAY_SIZE(hwsim_if_comb);
 
                if (channels > 1) {
                        hw->wiphy->max_scan_ssids = 255;
                        hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
                        hw->wiphy->max_remain_on_channel_duration = 1000;
+                       /* For channels > 1 DFS is not allowed */
+                       hw->wiphy->n_iface_combinations = 1;
                }
 
                INIT_DELAYED_WORK(&data->roc_done, hw_roc_done);
@@ -2325,7 +2359,8 @@ static int __init init_mac80211_hwsim(void)
                            IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
                            IEEE80211_HW_AMPDU_AGGREGATION |
                            IEEE80211_HW_WANT_MONITOR_VIF |
-                           IEEE80211_HW_QUEUE_CONTROL;
+                           IEEE80211_HW_QUEUE_CONTROL |
+                           IEEE80211_HW_SUPPORTS_HT_CCK_RATES;
                if (rctbl)
                        hw->flags |= IEEE80211_HW_SUPPORTS_RC_TABLE;
 
@@ -2385,6 +2420,7 @@ static int __init init_mac80211_hwsim(void)
                        sband->vht_cap.cap =
                                IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 |
                                IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ |
+                               IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ |
                                IEEE80211_VHT_CAP_RXLDPC |
                                IEEE80211_VHT_CAP_SHORT_GI_80 |
                                IEEE80211_VHT_CAP_SHORT_GI_160 |
@@ -2427,46 +2463,53 @@ static int __init init_mac80211_hwsim(void)
                        break;
                case HWSIM_REGTEST_WORLD_ROAM:
                        if (i == 0) {
-                               hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
+                               hw->wiphy->regulatory_flags |=
+                                       REGULATORY_CUSTOM_REG;
                                wiphy_apply_custom_regulatory(hw->wiphy,
                                        &hwsim_world_regdom_custom_01);
                        }
                        break;
                case HWSIM_REGTEST_CUSTOM_WORLD:
-                       hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
+                       hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
                        wiphy_apply_custom_regulatory(hw->wiphy,
                                &hwsim_world_regdom_custom_01);
                        break;
                case HWSIM_REGTEST_CUSTOM_WORLD_2:
                        if (i == 0) {
-                               hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
+                               hw->wiphy->regulatory_flags |=
+                                       REGULATORY_CUSTOM_REG;
                                wiphy_apply_custom_regulatory(hw->wiphy,
                                        &hwsim_world_regdom_custom_01);
                        } else if (i == 1) {
-                               hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
+                               hw->wiphy->regulatory_flags |=
+                                       REGULATORY_CUSTOM_REG;
                                wiphy_apply_custom_regulatory(hw->wiphy,
                                        &hwsim_world_regdom_custom_02);
                        }
                        break;
                case HWSIM_REGTEST_STRICT_ALL:
-                       hw->wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY;
+                       hw->wiphy->regulatory_flags |= REGULATORY_STRICT_REG;
                        break;
                case HWSIM_REGTEST_STRICT_FOLLOW:
                case HWSIM_REGTEST_STRICT_AND_DRIVER_REG:
                        if (i == 0)
-                               hw->wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY;
+                               hw->wiphy->regulatory_flags |=
+                                       REGULATORY_STRICT_REG;
                        break;
                case HWSIM_REGTEST_ALL:
                        if (i == 0) {
-                               hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
+                               hw->wiphy->regulatory_flags |=
+                                       REGULATORY_CUSTOM_REG;
                                wiphy_apply_custom_regulatory(hw->wiphy,
                                        &hwsim_world_regdom_custom_01);
                        } else if (i == 1) {
-                               hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
+                               hw->wiphy->regulatory_flags |=
+                                       REGULATORY_CUSTOM_REG;
                                wiphy_apply_custom_regulatory(hw->wiphy,
                                        &hwsim_world_regdom_custom_02);
                        } else if (i == 4)
-                               hw->wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY;
+                               hw->wiphy->regulatory_flags |=
+                                       REGULATORY_STRICT_REG;
                        break;
                default:
                        break;
@@ -2533,16 +2576,18 @@ static int __init init_mac80211_hwsim(void)
 
                data->debugfs = debugfs_create_dir("hwsim",
                                                   hw->wiphy->debugfsdir);
-               data->debugfs_ps = debugfs_create_file("ps", 0666,
-                                                      data->debugfs, data,
-                                                      &hwsim_fops_ps);
-               data->debugfs_group = debugfs_create_file("group", 0666,
-                                                       data->debugfs, data,
-                                                       &hwsim_fops_group);
+               debugfs_create_file("ps", 0666, data->debugfs, data,
+                                   &hwsim_fops_ps);
+               debugfs_create_file("group", 0666, data->debugfs, data,
+                                   &hwsim_fops_group);
+               if (channels == 1)
+                       debugfs_create_file("dfs_simulate_radar", 0222,
+                                           data->debugfs,
+                                           data, &hwsim_simulate_radar);
 
                tasklet_hrtimer_init(&data->beacon_timer,
                                     mac80211_hwsim_beacon,
-                                    CLOCK_REALTIME, HRTIMER_MODE_ABS);
+                                    CLOCK_MONOTONIC_RAW, HRTIMER_MODE_ABS);
 
                list_add_tail(&data->list, &hwsim_radios);
        }
index 1214c587fd08587f263b2c979eab9bc902b53ae1..63211707f93955c851bfb96d71f12d5ef1f4a313 100644 (file)
@@ -69,9 +69,9 @@ mwifiex_11n_form_amsdu_pkt(struct sk_buff *skb_aggr,
        memcpy(&tx_header->eth803_hdr, skb_src->data, dt_offset);
 
        /* Copy SNAP header */
-       snap.snap_type =
-               le16_to_cpu(*(__le16 *) ((u8 *)skb_src->data + dt_offset));
-       dt_offset += sizeof(u16);
+       snap.snap_type = ((struct ethhdr *)skb_src->data)->h_proto;
+
+       dt_offset += sizeof(__be16);
 
        memcpy(&tx_header->rfc1042_hdr, &snap, sizeof(struct rfc_1042_hdr));
 
index aeaea0e3b4c414ae925b79a3eb4962f7bb36ad4b..4d23647faef0451ef227804dbe1464bbd2442161 100644 (file)
@@ -50,24 +50,24 @@ static const struct ieee80211_regdomain mwifiex_world_regdom_custom = {
                REG_RULE(2412-10, 2462+10, 40, 3, 20, 0),
                /* Channel 12 - 13 */
                REG_RULE(2467-10, 2472+10, 20, 3, 20,
-                        NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS),
+                        NL80211_RRF_NO_IR),
                /* Channel 14 */
                REG_RULE(2484-10, 2484+10, 20, 3, 20,
-                        NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS |
+                        NL80211_RRF_NO_IR |
                         NL80211_RRF_NO_OFDM),
                /* Channel 36 - 48 */
                REG_RULE(5180-10, 5240+10, 40, 3, 20,
-                        NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS),
+                        NL80211_RRF_NO_IR),
                /* Channel 149 - 165 */
                REG_RULE(5745-10, 5825+10, 40, 3, 20,
-                        NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS),
+                        NL80211_RRF_NO_IR),
                /* Channel 52 - 64 */
                REG_RULE(5260-10, 5320+10, 40, 3, 30,
-                        NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS |
+                        NL80211_RRF_NO_IR |
                         NL80211_RRF_DFS),
                /* Channel 100 - 140 */
                REG_RULE(5500-10, 5700+10, 40, 3, 30,
-                        NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS |
+                        NL80211_RRF_NO_IR |
                         NL80211_RRF_DFS),
        }
 };
@@ -184,10 +184,10 @@ mwifiex_form_mgmt_frame(struct sk_buff *skb, const u8 *buf, size_t len)
  */
 static int
 mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
-                        struct ieee80211_channel *chan, bool offchan,
-                        unsigned int wait, const u8 *buf, size_t len,
-                        bool no_cck, bool dont_wait_for_ack, u64 *cookie)
+                        struct cfg80211_mgmt_tx_params *params, u64 *cookie)
 {
+       const u8 *buf = params->buf;
+       size_t len = params->len;
        struct sk_buff *skb;
        u16 pkt_len;
        const struct ieee80211_mgmt *mgmt;
@@ -222,6 +222,7 @@ mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
        tx_info = MWIFIEX_SKB_TXCB(skb);
        tx_info->bss_num = priv->bss_num;
        tx_info->bss_type = priv->bss_type;
+       tx_info->pkt_len = pkt_len;
 
        mwifiex_form_mgmt_frame(skb, buf, len);
        mwifiex_queue_tx_pkt(priv, skb);
@@ -1968,7 +1969,7 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
                user_scan_cfg->chan_list[i].chan_number = chan->hw_value;
                user_scan_cfg->chan_list[i].radio_type = chan->band;
 
-               if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)
+               if (chan->flags & IEEE80211_CHAN_NO_IR)
                        user_scan_cfg->chan_list[i].scan_type =
                                                MWIFIEX_SCAN_TYPE_PASSIVE;
                else
@@ -2702,9 +2703,10 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
        wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME |
                        WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD |
                        WIPHY_FLAG_AP_UAPSD |
-                       WIPHY_FLAG_CUSTOM_REGULATORY |
-                       WIPHY_FLAG_STRICT_REGULATORY |
                        WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
+       wiphy->regulatory_flags |=
+                       REGULATORY_CUSTOM_REG |
+                       REGULATORY_STRICT_REG;
 
        wiphy_apply_custom_regulatory(wiphy, &mwifiex_world_regdom_custom);
 
index e47f4e3012b85344c7d400d78799634cb5bf0234..1ddc8b2e3722d5d9a9e72fad2422296b1754829f 100644 (file)
@@ -312,14 +312,14 @@ static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter)
        }
        if (GET_BSS_ROLE(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY))
            == MWIFIEX_BSS_ROLE_STA) {
-               if (!sleep_cfm_buf->resp_ctrl)
+               if (!le16_to_cpu(sleep_cfm_buf->resp_ctrl))
                        /* Response is not needed for sleep
                           confirm command */
                        adapter->ps_state = PS_STATE_SLEEP;
                else
                        adapter->ps_state = PS_STATE_SLEEP_CFM;
 
-               if (!sleep_cfm_buf->resp_ctrl &&
+               if (!le16_to_cpu(sleep_cfm_buf->resp_ctrl) &&
                    (adapter->is_hs_configured &&
                     !adapter->sleep_period.period)) {
                        adapter->pm_wakeup_card_req = true;
index 5c85d7803d00a5856765544fc100cc38193f21a1..3a21bd03d6db89f387224428a3c334a30199634f 100644 (file)
@@ -130,6 +130,7 @@ struct mwifiex_txinfo {
        u8 flags;
        u8 bss_num;
        u8 bss_type;
+       u32 pkt_len;
 };
 
 enum mwifiex_wmm_ac_e {
index c8385ec77a86af678b36cf28a5d7c2fa8448de84..8fcb500fa09b37c7e253906350141972998c5c9e 100644 (file)
@@ -30,7 +30,7 @@ struct rfc_1042_hdr {
        u8 llc_ssap;
        u8 llc_ctrl;
        u8 snap_oui[3];
-       u16 snap_type;
+       __be16 snap_type;
 };
 
 struct rx_packet_hdr {
@@ -610,12 +610,12 @@ struct mwifiex_ie_types_tsf_timestamp {
 struct mwifiex_cf_param_set {
        u8 cfp_cnt;
        u8 cfp_period;
-       u16 cfp_max_duration;
-       u16 cfp_duration_remaining;
+       __le16 cfp_max_duration;
+       __le16 cfp_duration_remaining;
 } __packed;
 
 struct mwifiex_ibss_param_set {
-       u16 atim_window;
+       __le16 atim_window;
 } __packed;
 
 struct mwifiex_ie_types_ss_param_set {
@@ -627,7 +627,7 @@ struct mwifiex_ie_types_ss_param_set {
 } __packed;
 
 struct mwifiex_fh_param_set {
-       u16 dwell_time;
+       __le16 dwell_time;
        u8 hop_set;
        u8 hop_pattern;
        u8 hop_index;
@@ -684,10 +684,10 @@ struct host_cmd_ds_802_11_key_material {
 } __packed;
 
 struct host_cmd_ds_gen {
-       u16 command;
-       u16 size;
-       u16 seq_num;
-       u16 result;
+       __le16 command;
+       __le16 size;
+       __le16 seq_num;
+       __le16 result;
 };
 
 #define S_DS_GEN        sizeof(struct host_cmd_ds_gen)
@@ -820,8 +820,8 @@ struct ieee_types_cf_param_set {
        u8 len;
        u8 cfp_cnt;
        u8 cfp_period;
-       u16 cfp_max_duration;
-       u16 cfp_duration_remaining;
+       __le16 cfp_max_duration;
+       __le16 cfp_duration_remaining;
 } __packed;
 
 struct ieee_types_ibss_param_set {
@@ -957,7 +957,7 @@ struct mwifiex_hs_config_param {
 } __packed;
 
 struct hs_activate_param {
-       u16 resp_ctrl;
+       __le16 resp_ctrl;
 } __packed;
 
 struct host_cmd_ds_802_11_hs_cfg_enh {
@@ -1131,7 +1131,7 @@ struct host_cmd_ds_802_11_bg_scan_query {
 } __packed;
 
 struct host_cmd_ds_802_11_bg_scan_query_rsp {
-       u32 report_condition;
+       __le32 report_condition;
        struct host_cmd_ds_802_11_scan_rsp scan_resp;
 } __packed;
 
@@ -1230,7 +1230,7 @@ struct mwifiex_ie_types_wmm_queue_status {
        struct mwifiex_ie_types_header header;
        u8 queue_index;
        u8 disabled;
-       u16 medium_time;
+       __le16 medium_time;
        u8 flow_required;
        u8 flow_created;
        u32 reserved;
@@ -1310,7 +1310,7 @@ struct mwifiex_ie_types_vht_oper {
        u8 chan_center_freq_1;
        u8 chan_center_freq_2;
        /* Basic MCS set map, each 2 bits stands for a NSS */
-       u16 basic_mcs_map;
+       __le16 basic_mcs_map;
 } __packed;
 
 struct mwifiex_ie_types_wmmcap {
index 6499117fce43a3a73f36836c8d91d4e27b51b0ba..1d0a817f2bf05de1c5c7873fad2eacaa6cb1838f 100644 (file)
@@ -643,7 +643,8 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
                        if (priv)
                                priv->stats.rx_dropped++;
 
-                       adapter->if_ops.data_complete(adapter, skb);
+                       dev_kfree_skb_any(skb);
+                       adapter->if_ops.data_complete(adapter);
                }
        }
 
index 78e8a6666cc6edad81bd87c98dcf0353af371866..6bf58aba51d20ca59253efb55ada327888615e5d 100644 (file)
@@ -648,6 +648,7 @@ mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
        tx_info = MWIFIEX_SKB_TXCB(skb);
        tx_info->bss_num = priv->bss_num;
        tx_info->bss_type = priv->bss_type;
+       tx_info->pkt_len = skb->len;
 
        /* Record the current time the packet was queued; used to
         * determine the amount of time the packet was queued in
@@ -991,12 +992,8 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
                rtnl_unlock();
        }
 
-       priv = adapter->priv[0];
-       if (!priv || !priv->wdev)
-               goto exit_remove;
-
-       wiphy_unregister(priv->wdev->wiphy);
-       wiphy_free(priv->wdev->wiphy);
+       wiphy_unregister(adapter->wiphy);
+       wiphy_free(adapter->wiphy);
 
        mwifiex_terminate_workqueue(adapter);
 
index 1d72f13adb9dd5763187bde915fe0300eb5f4dd1..dc34457557f38452de46f47276d6194d4ff766e1 100644 (file)
@@ -615,7 +615,7 @@ struct mwifiex_if_ops {
        void (*cleanup_mpa_buf) (struct mwifiex_adapter *);
        int (*cmdrsp_complete) (struct mwifiex_adapter *, struct sk_buff *);
        int (*event_complete) (struct mwifiex_adapter *, struct sk_buff *);
-       int (*data_complete) (struct mwifiex_adapter *, struct sk_buff *);
+       int (*data_complete) (struct mwifiex_adapter *);
        int (*init_fw_port) (struct mwifiex_adapter *);
        int (*dnld_fw) (struct mwifiex_adapter *, struct mwifiex_fw_image *);
        void (*card_reset) (struct mwifiex_adapter *);
index 8cf7d50a7603121682c7f9a9684a64a978de85c9..0ed06646f19a1e9de631f8874b1cb236dce06340 100644 (file)
@@ -515,14 +515,14 @@ mwifiex_scan_create_channel_list(struct mwifiex_private *priv,
                                scan_chan_list[chan_idx].max_scan_time =
                                        cpu_to_le16((u16) user_scan_in->
                                        chan_list[0].scan_time);
-                       else if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
+                       else if (ch->flags & IEEE80211_CHAN_NO_IR)
                                scan_chan_list[chan_idx].max_scan_time =
                                        cpu_to_le16(adapter->passive_scan_time);
                        else
                                scan_chan_list[chan_idx].max_scan_time =
                                        cpu_to_le16(adapter->active_scan_time);
 
-                       if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
+                       if (ch->flags & IEEE80211_CHAN_NO_IR)
                                scan_chan_list[chan_idx].chan_scan_mode_bitmap
                                        |= MWIFIEX_PASSIVE_SCAN;
                        else
index 2181ee283d823e19dafaa5b1b8a09fcb1b4f2b1a..1efa43ec1c6ec3921d143752b3fb7ab3d6511902 100644 (file)
@@ -354,7 +354,7 @@ mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv,
        }
        if (hs_activate) {
                hs_cfg->action = cpu_to_le16(HS_ACTIVATE);
-               hs_cfg->params.hs_activate.resp_ctrl = RESP_NEEDED;
+               hs_cfg->params.hs_activate.resp_ctrl = cpu_to_le16(RESP_NEEDED);
        } else {
                hs_cfg->action = cpu_to_le16(HS_CONFIGURE);
                hs_cfg->params.hs_config.conditions = hscfg_param->conditions;
index 2675ca7f8d146ca579a7a4bb4c1397f641a95ee0..551194605aa7ae1862c2df113b33a8701c8d5243 100644 (file)
@@ -338,8 +338,7 @@ static int mwifiex_get_power_level(struct mwifiex_private *priv, void *data_buf)
        if (!data_buf)
                return -1;
 
-       pg_tlv_hdr = (struct mwifiex_types_power_group *)
-               ((u8 *) data_buf + sizeof(struct host_cmd_ds_txpwr_cfg));
+       pg_tlv_hdr = (struct mwifiex_types_power_group *)((u8 *)data_buf);
        pg = (struct mwifiex_power_group *)
                ((u8 *) pg_tlv_hdr + sizeof(struct mwifiex_types_power_group));
        length = le16_to_cpu(pg_tlv_hdr->length);
@@ -383,19 +382,25 @@ static int mwifiex_ret_tx_power_cfg(struct mwifiex_private *priv,
        struct mwifiex_types_power_group *pg_tlv_hdr;
        struct mwifiex_power_group *pg;
        u16 action = le16_to_cpu(txp_cfg->action);
+       u16 tlv_buf_left;
 
-       switch (action) {
-       case HostCmd_ACT_GEN_GET:
-               pg_tlv_hdr = (struct mwifiex_types_power_group *)
-                       ((u8 *) txp_cfg +
-                        sizeof(struct host_cmd_ds_txpwr_cfg));
+       pg_tlv_hdr = (struct mwifiex_types_power_group *)
+               ((u8 *)txp_cfg +
+                sizeof(struct host_cmd_ds_txpwr_cfg));
 
-               pg = (struct mwifiex_power_group *)
-                       ((u8 *) pg_tlv_hdr +
-                        sizeof(struct mwifiex_types_power_group));
+       pg = (struct mwifiex_power_group *)
+               ((u8 *)pg_tlv_hdr +
+                sizeof(struct mwifiex_types_power_group));
 
+       tlv_buf_left = le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*txp_cfg);
+       if (tlv_buf_left <
+                       le16_to_cpu(pg_tlv_hdr->length) + sizeof(*pg_tlv_hdr))
+               return 0;
+
+       switch (action) {
+       case HostCmd_ACT_GEN_GET:
                if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING)
-                       mwifiex_get_power_level(priv, txp_cfg);
+                       mwifiex_get_power_level(priv, pg_tlv_hdr);
 
                priv->tx_power_level = (u16) pg->power_min;
                break;
@@ -404,14 +409,6 @@ static int mwifiex_ret_tx_power_cfg(struct mwifiex_private *priv,
                if (!le32_to_cpu(txp_cfg->mode))
                        break;
 
-               pg_tlv_hdr = (struct mwifiex_types_power_group *)
-                       ((u8 *) txp_cfg +
-                        sizeof(struct host_cmd_ds_txpwr_cfg));
-
-               pg = (struct mwifiex_power_group *)
-                       ((u8 *) pg_tlv_hdr +
-                        sizeof(struct mwifiex_types_power_group));
-
                if (pg->power_max == pg->power_min)
                        priv->tx_power_level = (u16) pg->power_min;
                break;
index c8e029df770e38cac9a52dccb660666bd8cc9f74..a09398fe9e2a67218f50530af8a0b4616443cbbb 100644 (file)
@@ -319,8 +319,8 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
                if (bss_desc && bss_desc->ssid.ssid_len &&
                    (!mwifiex_ssid_cmp(&priv->curr_bss_params.bss_descriptor.
                                       ssid, &bss_desc->ssid))) {
-                       kfree(bss_desc);
-                       return 0;
+                       ret = 0;
+                       goto done;
                }
 
                /* Exit Adhoc mode first */
index bb22664923efd24c84aaa5855a13f913b0418182..0bb510de80710a1348c1743ca95fbe107ef223e7 100644 (file)
@@ -36,12 +36,12 @@ mwifiex_discard_gratuitous_arp(struct mwifiex_private *priv,
                               struct sk_buff *skb)
 {
        const struct mwifiex_arp_eth_header *arp;
-       struct ethhdr *eth_hdr;
+       struct ethhdr *eth;
        struct ipv6hdr *ipv6;
        struct icmp6hdr *icmpv6;
 
-       eth_hdr = (struct ethhdr *)skb->data;
-       switch (ntohs(eth_hdr->h_proto)) {
+       eth = (struct ethhdr *)skb->data;
+       switch (ntohs(eth->h_proto)) {
        case ETH_P_ARP:
                arp = (void *)(skb->data + sizeof(struct ethhdr));
                if (arp->hdr.ar_op == htons(ARPOP_REPLY) ||
@@ -87,16 +87,19 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv,
        struct rx_packet_hdr *rx_pkt_hdr;
        struct rxpd *local_rx_pd;
        int hdr_chop;
-       struct ethhdr *eth_hdr;
-       u8 rfc1042_eth_hdr[ETH_ALEN] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
+       struct ethhdr *eth;
 
        local_rx_pd = (struct rxpd *) (skb->data);
 
        rx_pkt_hdr = (void *)local_rx_pd +
                     le16_to_cpu(local_rx_pd->rx_pkt_offset);
 
-       if (!memcmp(&rx_pkt_hdr->rfc1042_hdr,
-                   rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr))) {
+       if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header,
+                    sizeof(bridge_tunnel_header))) ||
+           (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header,
+                    sizeof(rfc1042_header)) &&
+            ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_AARP &&
+            ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_IPX)) {
                /*
                 *  Replace the 803 header and rfc1042 header (llc/snap) with an
                 *    EthernetII header, keep the src/dst and snap_type
@@ -106,7 +109,7 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv,
                 *  To create the Ethernet II, just move the src, dst address
                 *    right before the snap_type.
                 */
-               eth_hdr = (struct ethhdr *)
+               eth = (struct ethhdr *)
                        ((u8 *) &rx_pkt_hdr->eth803_hdr
                         + sizeof(rx_pkt_hdr->eth803_hdr) +
                         sizeof(rx_pkt_hdr->rfc1042_hdr)
@@ -114,14 +117,14 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv,
                         - sizeof(rx_pkt_hdr->eth803_hdr.h_source)
                         - sizeof(rx_pkt_hdr->rfc1042_hdr.snap_type));
 
-               memcpy(eth_hdr->h_source, rx_pkt_hdr->eth803_hdr.h_source,
-                      sizeof(eth_hdr->h_source));
-               memcpy(eth_hdr->h_dest, rx_pkt_hdr->eth803_hdr.h_dest,
-                      sizeof(eth_hdr->h_dest));
+               memcpy(eth->h_source, rx_pkt_hdr->eth803_hdr.h_source,
+                      sizeof(eth->h_source));
+               memcpy(eth->h_dest, rx_pkt_hdr->eth803_hdr.h_dest,
+                      sizeof(eth->h_dest));
 
                /* Chop off the rxpd + the excess memory from the 802.2/llc/snap
                   header that was removed. */
-               hdr_chop = (u8 *) eth_hdr - (u8 *) local_rx_pd;
+               hdr_chop = (u8 *) eth - (u8 *) local_rx_pd;
        } else {
                /* Chop off the rxpd */
                hdr_chop = (u8 *) &rx_pkt_hdr->eth803_hdr -
@@ -185,12 +188,7 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv,
                        "wrong rx packet: len=%d, rx_pkt_offset=%d, rx_pkt_length=%d\n",
                        skb->len, rx_pkt_offset, rx_pkt_length);
                priv->stats.rx_dropped++;
-
-               if (adapter->if_ops.data_complete)
-                       adapter->if_ops.data_complete(adapter, skb);
-               else
-                       dev_kfree_skb_any(skb);
-
+               dev_kfree_skb_any(skb);
                return ret;
        }
 
@@ -244,12 +242,8 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv,
        ret = mwifiex_11n_rx_reorder_pkt(priv, seq_num, local_rx_pd->priority,
                                         ta, (u8) rx_pkt_type, skb);
 
-       if (ret || (rx_pkt_type == PKT_TYPE_BAR)) {
-               if (adapter->if_ops.data_complete)
-                       adapter->if_ops.data_complete(adapter, skb);
-               else
-                       dev_kfree_skb_any(skb);
-       }
+       if (ret || (rx_pkt_type == PKT_TYPE_BAR))
+               dev_kfree_skb_any(skb);
 
        if (ret)
                priv->stats.rx_dropped++;
index 7b581af24f5f6479ac185430be2bb35306e53c0e..354d64c9606ff2ab7788206aeee464265a127225 100644 (file)
@@ -148,6 +148,7 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags)
        tx_info = MWIFIEX_SKB_TXCB(skb);
        tx_info->bss_num = priv->bss_num;
        tx_info->bss_type = priv->bss_type;
+       tx_info->pkt_len = data_len - (sizeof(struct txpd) + INTF_HEADER_LEN);
        skb_reserve(skb, sizeof(struct txpd) + INTF_HEADER_LEN);
        skb_push(skb, sizeof(struct txpd));
 
index 8f923d0d2ba657241c7634b26dc6f04697045e40..37f26afd4314326a984213924128d44d40960285 100644 (file)
@@ -40,6 +40,7 @@ int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter,
                mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
        struct rxpd *local_rx_pd;
        struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
+       int ret;
 
        local_rx_pd = (struct rxpd *) (skb->data);
        /* Get the BSS number from rxpd, get corresponding priv */
@@ -58,9 +59,15 @@ int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter,
        rx_info->bss_type = priv->bss_type;
 
        if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
-               return mwifiex_process_uap_rx_packet(priv, skb);
+               ret = mwifiex_process_uap_rx_packet(priv, skb);
+       else
+               ret = mwifiex_process_sta_rx_packet(priv, skb);
+
+       /* Decrement RX pending counter for each packet */
+       if (adapter->if_ops.data_complete)
+               adapter->if_ops.data_complete(adapter);
 
-       return mwifiex_process_sta_rx_packet(priv, skb);
+       return ret;
 }
 EXPORT_SYMBOL_GPL(mwifiex_handle_rx_packet);
 
@@ -105,7 +112,7 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
 
        switch (ret) {
        case -ENOSR:
-               dev_err(adapter->dev, "data: -ENOSR is returned\n");
+               dev_dbg(adapter->dev, "data: -ENOSR is returned\n");
                break;
        case -EBUSY:
                if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
@@ -168,7 +175,7 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter,
        mwifiex_set_trans_start(priv->netdev);
        if (!status) {
                priv->stats.tx_packets++;
-               priv->stats.tx_bytes += skb->len;
+               priv->stats.tx_bytes += tx_info->pkt_len;
                if (priv->tx_timeout_cnt)
                        priv->tx_timeout_cnt = 0;
        } else {
index 92f76d655e6cc1206e46c4fc0e60b147b62280e0..3c74eb25492790410b9627dbb9a6ca0a0555f010 100644 (file)
@@ -98,7 +98,6 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv,
        int hdr_chop;
        struct timeval tv;
        struct ethhdr *p_ethhdr;
-       u8 rfc1042_eth_hdr[ETH_ALEN] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
 
        uap_rx_pd = (struct uap_rxpd *)(skb->data);
        rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset);
@@ -112,8 +111,12 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv,
                return;
        }
 
-       if (!memcmp(&rx_pkt_hdr->rfc1042_hdr,
-                   rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr))) {
+       if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header,
+                    sizeof(bridge_tunnel_header))) ||
+           (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header,
+                    sizeof(rfc1042_header)) &&
+            ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_AARP &&
+            ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_IPX)) {
                /* Replace the 803 header and rfc1042 header (llc/snap) with
                 * an Ethernet II header, keep the src/dst and snap_type
                 * (ethertype).
@@ -144,7 +147,7 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv,
                hdr_chop = (u8 *)&rx_pkt_hdr->eth803_hdr - (u8 *)uap_rx_pd;
        }
 
-       /* Chop off the leading header bytes so the it points
+       /* Chop off the leading header bytes so that it points
         * to the start of either the reconstructed EthII frame
         * or the 802.2/llc/snap frame.
         */
@@ -176,6 +179,19 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv,
        tx_info->bss_type = priv->bss_type;
        tx_info->flags |= MWIFIEX_BUF_FLAG_BRIDGED_PKT;
 
+       if (is_unicast_ether_addr(rx_pkt_hdr->eth803_hdr.h_dest)) {
+               /* Update bridge packet statistics as the
+                * packet is not going to kernel/upper layer.
+                */
+               priv->stats.rx_bytes += skb->len;
+               priv->stats.rx_packets++;
+
+               /* Sending bridge packet to TX queue, so save the packet
+                * length in TXCB to update statistics in TX complete.
+                */
+               tx_info->pkt_len = skb->len;
+       }
+
        do_gettimeofday(&tv);
        skb->tstamp = timeval_to_ktime(tv);
        mwifiex_wmm_add_buf_txqueue(priv, skb);
@@ -264,12 +280,7 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv,
                        skb->len, le16_to_cpu(uap_rx_pd->rx_pkt_offset),
                        le16_to_cpu(uap_rx_pd->rx_pkt_length));
                priv->stats.rx_dropped++;
-
-               if (adapter->if_ops.data_complete)
-                       adapter->if_ops.data_complete(adapter, skb);
-               else
-                       dev_kfree_skb_any(skb);
-
+               dev_kfree_skb_any(skb);
                return 0;
        }
 
@@ -323,12 +334,8 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv,
                                         uap_rx_pd->priority, ta, pkt_type,
                                         skb);
 
-       if (ret || (rx_pkt_type == PKT_TYPE_BAR)) {
-               if (adapter->if_ops.data_complete)
-                       adapter->if_ops.data_complete(adapter, skb);
-               else
-                       dev_kfree_skb_any(skb);
-       }
+       if (ret || (rx_pkt_type == PKT_TYPE_BAR))
+               dev_kfree_skb_any(skb);
 
        if (ret)
                priv->stats.rx_dropped++;
index edf5b7a24900ec1edf8d1fbb1e426b5268d2d3e2..a9240a2083f2c7f48405e9a2af4ab85729edb814 100644 (file)
@@ -938,11 +938,9 @@ static int mwifiex_usb_cmd_event_complete(struct mwifiex_adapter *adapter,
        return 0;
 }
 
-static int mwifiex_usb_data_complete(struct mwifiex_adapter *adapter,
-                                    struct sk_buff *skb)
+static int mwifiex_usb_data_complete(struct mwifiex_adapter *adapter)
 {
        atomic_dec(&adapter->rx_pending);
-       dev_kfree_skb_any(skb);
 
        return 0;
 }
index 5d9e150f411147f572541cf5b06d913a873fb413..9b82e225880cbc41d1e7b65060407ff2ce8c5cdc 100644 (file)
@@ -191,6 +191,9 @@ int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb)
        if (!skb)
                return -1;
 
+       priv->stats.rx_bytes += skb->len;
+       priv->stats.rx_packets++;
+
        skb->dev = priv->netdev;
        skb->protocol = eth_type_trans(skb, priv->netdev);
        skb->ip_summed = CHECKSUM_NONE;
@@ -217,8 +220,6 @@ int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb)
            (skb->truesize > MWIFIEX_RX_DATA_BUF_SIZE))
                skb->truesize += (skb->len - MWIFIEX_RX_DATA_BUF_SIZE);
 
-       priv->stats.rx_bytes += skb->len;
-       priv->stats.rx_packets++;
        if (in_interrupt())
                netif_rx(skb);
        else
index e3ed893b5aaf7149beedca62a2af7b73b5d6669a..aedfaf24f38602954e498c70d81851927f3a4e01 100644 (file)
@@ -20,8 +20,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*-------------------------------------------------------------------------*/
index 02fc67bccbd0bbf46f198df7ea3afe06b5280411..333c1a2f882ed08b1c46087bea9a27009095050f 100644 (file)
@@ -12,8 +12,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 19c33d3137348b52eeb1b98124b0c2a1a1edb972..547ab885610bed2e8ec7ae34065f9379542cee5e 100644 (file)
@@ -11,8 +11,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 8863a6cb2388d952926cf8fe209a8b67fa004ddb..df784fefb8e3e322ca0fc5dd73c127051a08524a 100644 (file)
@@ -14,8 +14,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index a34bceb6e3cd3ce70e8170f0ff290c91dd8c2ac9..842a2549facc1f3bfaefb51a993d3281bfcc6c9d 100644 (file)
@@ -13,8 +13,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 59e31258d45096b418687b6c54208092f632c335..83fec557997ef17de8ac072988e6986a7b0ffe9a 100644 (file)
@@ -13,8 +13,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index e05d9b4c8317c44df17b9ca0c2dea0577741b1a6..931cf440ff187f432b2ced8a2e2411576ee3cc67 100644 (file)
@@ -13,8 +13,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
@@ -914,7 +913,6 @@ islpci_setup(struct pci_dev *pdev)
       do_islpci_free_memory:
        islpci_free_memory(priv);
       do_free_netdev:
-       pci_set_drvdata(pdev, NULL);
        free_netdev(ndev);
        priv = NULL;
        return NULL;
index c40403877f97bf342036810dfb63655c83d2c080..f6f088e05fe4f2661e2aa50439fd69f1c020d692 100644 (file)
@@ -14,8 +14,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 799e148d03703bb1d71b962bb7b541c1fd11d181..674658f2e6ef4bf8589bb9d35b28f39aa6bd32b7 100644 (file)
@@ -11,8 +11,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 6ca30a5b7bfbc0463a440c19ca5d8aad026d5abe..80f50f1bc6f22632ec4623939a12e49c51ff68e5 100644 (file)
@@ -11,8 +11,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 9e68e0cb718ee0dfff1e00066aef36f1c04e0e15..1105a12dbde802d53a8e12f7b855a56438386927 100644 (file)
@@ -12,8 +12,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
@@ -199,7 +198,6 @@ prism54_probe(struct pci_dev *pdev, const struct pci_device_id *id)
       do_unregister_netdev:
        unregister_netdev(ndev);
        islpci_free_memory(priv);
-       pci_set_drvdata(pdev, NULL);
        free_netdev(ndev);
        priv = NULL;
       do_pci_clear_mwi:
@@ -247,7 +245,6 @@ prism54_remove(struct pci_dev *pdev)
        /* free the PCI memory and unmap the remapped page */
        islpci_free_memory(priv);
 
-       pci_set_drvdata(pdev, NULL);
        free_netdev(ndev);
        priv = NULL;
 
index 9f19cceab487ae0fe8c720fa31077179a14f19f0..0de14dfa68cc3cb675165135aa4762edcff35d80 100644 (file)
@@ -12,8 +12,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 0db93db9b6753efed4354a47408baa98e153c4b4..700c434c8803e410468e72132f0500c7d1d639fe 100644 (file)
@@ -12,8 +12,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 056af38e72e399d88528343e978fec15d512f180..47b34bfe890ae97387e6dc3f03171d4de2e8435c 100644 (file)
@@ -11,8 +11,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 92c8a2d4acd8007de71baf8696b96b54090028af..cf5141df8474a98e888c21d728b69cd86f0ffd49 100644 (file)
@@ -11,8 +11,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index aa1d1747784f37ccfa8e78402ed969eba2b9df0f..bc1401eb4b9d368e7471c70717d093ad2dabb253 100644 (file)
@@ -11,8 +11,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 9b557a1bb7f81e6b785778b6ee7bc8f4f629b1a3..cbf0a589d32af08c392271c7bbc3afa50f8e9c84 100644 (file)
@@ -17,8 +17,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * Changes:
  * Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 08/08/2000
index 8169a85c44986034a958ee01b6dce7052402691c..c3cdda1252defba9d9c27d25e0fdeca72bedf76e 100644 (file)
@@ -15,8 +15,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  *  Portions of this file are based on NDISwrapper project,
  *  Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
index 38ed9a3e44c8c00c06ea8f1cdd9ae1a68bbe2d60..4ad0de9d1d08b4a54bb8b87643be4e7c84ad6511 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index e4b07f0aa3cc0bfd955c1cebfcc1e1443065a4f9..0fd3a9d01a60bb5381ebf7e3bfaf753087327fab 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 0ac5c589ddceaffe7dd0f7d82ce7a508e37e4bd7..4f61ffbcd2f196a2b9fbe0354ab87b8e86f336e2 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 9c10068e4987a384019301542f664bd44f1b130a..573e87bcc553503dbaee92d0f1d25194cd039a8c 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 85acc79f68b840c48ffe76715546fb10fac377a9..1bb76935da717c6fb15a46e9399407a2955b2531 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 1b91a4cef9652c22fe336c2c889ec300d04d685f..afba0739c3b87ded3965521b449408fef35d3d33 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index aab6b5e4f5ddd0fb0a52b7385388f3a07c738add..a394a9a95919b5dcbaf0f87a19e289e43bafe853 100644 (file)
@@ -21,9 +21,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 776aff3678ff23bddda925dfbb48bde925cb7b82..b8f5b06006c4393358d9be88cb11ef4f389476ef 100644 (file)
@@ -24,9 +24,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
@@ -5462,15 +5460,14 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev)
 
        rt2800_bbp_write(rt2x00dev, 68, 0x0b);
 
-       rt2800_bbp_write(rt2x00dev, 69, 0x12);
+       rt2800_bbp_write(rt2x00dev, 69, 0x0d);
+       rt2800_bbp_write(rt2x00dev, 70, 0x06);
        rt2800_bbp_write(rt2x00dev, 73, 0x13);
        rt2800_bbp_write(rt2x00dev, 75, 0x46);
        rt2800_bbp_write(rt2x00dev, 76, 0x28);
 
        rt2800_bbp_write(rt2x00dev, 77, 0x59);
 
-       rt2800_bbp_write(rt2x00dev, 70, 0x0a);
-
        rt2800_bbp_write(rt2x00dev, 79, 0x13);
        rt2800_bbp_write(rt2x00dev, 80, 0x05);
        rt2800_bbp_write(rt2x00dev, 81, 0x33);
@@ -5513,6 +5510,7 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev)
        if (rt2x00_rt(rt2x00dev, RT5392)) {
                rt2800_bbp_write(rt2x00dev, 134, 0xd0);
                rt2800_bbp_write(rt2x00dev, 135, 0xf6);
+               rt2800_bbp_write(rt2x00dev, 148, 0x84);
        }
 
        rt2800_disable_unused_dac_adc(rt2x00dev);
@@ -6453,7 +6451,7 @@ static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev)
        rt2800_rfcsr_write(rt2x00dev, 7, 0x00);
        rt2800_rfcsr_write(rt2x00dev, 10, 0x53);
        rt2800_rfcsr_write(rt2x00dev, 11, 0x4a);
-       rt2800_rfcsr_write(rt2x00dev, 12, 0xc6);
+       rt2800_rfcsr_write(rt2x00dev, 12, 0x46);
        rt2800_rfcsr_write(rt2x00dev, 13, 0x9f);
        rt2800_rfcsr_write(rt2x00dev, 14, 0x00);
        rt2800_rfcsr_write(rt2x00dev, 15, 0x00);
@@ -6466,7 +6464,8 @@ static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev)
        rt2800_rfcsr_write(rt2x00dev, 22, 0x20);
        rt2800_rfcsr_write(rt2x00dev, 23, 0x00);
        rt2800_rfcsr_write(rt2x00dev, 24, 0x00);
-       if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F))
+       if (rt2x00_is_usb(rt2x00dev) &&
+           rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F))
                rt2800_rfcsr_write(rt2x00dev, 25, 0x80);
        else
                rt2800_rfcsr_write(rt2x00dev, 25, 0xc0);
@@ -6486,10 +6485,7 @@ static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev)
        rt2800_rfcsr_write(rt2x00dev, 38, 0x85);
        rt2800_rfcsr_write(rt2x00dev, 39, 0x1b);
 
-       if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F))
-               rt2800_rfcsr_write(rt2x00dev, 40, 0x0b);
-       else
-               rt2800_rfcsr_write(rt2x00dev, 40, 0x4b);
+       rt2800_rfcsr_write(rt2x00dev, 40, 0x0b);
        rt2800_rfcsr_write(rt2x00dev, 41, 0xbb);
        rt2800_rfcsr_write(rt2x00dev, 42, 0xd2);
        rt2800_rfcsr_write(rt2x00dev, 43, 0x9a);
@@ -6510,16 +6506,26 @@ static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev)
                rt2800_rfcsr_write(rt2x00dev, 53, 0x84);
        rt2800_rfcsr_write(rt2x00dev, 54, 0x78);
        rt2800_rfcsr_write(rt2x00dev, 55, 0x44);
-       rt2800_rfcsr_write(rt2x00dev, 56, 0x22);
+       if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F))
+               rt2800_rfcsr_write(rt2x00dev, 56, 0x42);
+       else
+               rt2800_rfcsr_write(rt2x00dev, 56, 0x22);
        rt2800_rfcsr_write(rt2x00dev, 57, 0x80);
        rt2800_rfcsr_write(rt2x00dev, 58, 0x7f);
        rt2800_rfcsr_write(rt2x00dev, 59, 0x8f);
 
        rt2800_rfcsr_write(rt2x00dev, 60, 0x45);
-       if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F))
-               rt2800_rfcsr_write(rt2x00dev, 61, 0xd1);
-       else
-               rt2800_rfcsr_write(rt2x00dev, 61, 0xdd);
+       if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) {
+               if (rt2x00_is_usb(rt2x00dev))
+                       rt2800_rfcsr_write(rt2x00dev, 61, 0xd1);
+               else
+                       rt2800_rfcsr_write(rt2x00dev, 61, 0xd5);
+       } else {
+               if (rt2x00_is_usb(rt2x00dev))
+                       rt2800_rfcsr_write(rt2x00dev, 61, 0xdd);
+               else
+                       rt2800_rfcsr_write(rt2x00dev, 61, 0xb5);
+       }
        rt2800_rfcsr_write(rt2x00dev, 62, 0x00);
        rt2800_rfcsr_write(rt2x00dev, 63, 0x00);
 
@@ -6602,7 +6608,6 @@ static void rt2800_init_rfcsr_5592(struct rt2x00_dev *rt2x00dev)
 
        rt2800_rfcsr_write(rt2x00dev, 1, 0x3F);
        rt2800_rfcsr_write(rt2x00dev, 3, 0x08);
-       rt2800_rfcsr_write(rt2x00dev, 3, 0x08);
        rt2800_rfcsr_write(rt2x00dev, 5, 0x10);
        rt2800_rfcsr_write(rt2x00dev, 6, 0xE4);
        rt2800_rfcsr_write(rt2x00dev, 7, 0x00);
index a94ba447e63c93eb10744ba2adf8ff2aa00f1886..3019db637a4ba3d71e74edf6e07ffc58860f536e 100644 (file)
@@ -14,9 +14,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef RT2800LIB_H
index a8cc736b5063bcc51d3a5d7ef3a6a737a2d6338e..de4790b41be7d64a7c3a9651e27451c3f76183d6 100644 (file)
@@ -19,9 +19,7 @@
  *     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.
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*     Module: rt2800mmio
index 6a10de3eee3e02826c2ae086cf81b963e513b8ee..b63312ce3f27e6599935f695524d3c4a5f807119 100644 (file)
@@ -19,9 +19,7 @@
  *     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.
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*     Module: rt2800mmio
index b504455b4fec10c69c4cc09c1f44be4b92ac3be4..a5b32ca2cf0febdc40b96aa861082af8d92510d9 100644 (file)
@@ -20,9 +20,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index a81c9ee281c075dbf267e6b4b9b9c78de912c315..9dfef4607d6b1042414cfc722859b60f176de7f8 100644 (file)
@@ -20,9 +20,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 1359227ca41122d55825a191b9b4a1aa605a9c46..f6d1bf5be006cd9d8a753d946ebf1f666df1428b 100644 (file)
@@ -19,9 +19,7 @@
  *     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.
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*     Module: rt2800soc
index a81ceb61d746fb392f9eb30ca6ecac81dda04eda..49ff178a0b46eac88cd78156bb7263f4843991d2 100644 (file)
@@ -18,9 +18,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 671ea35926101ad76cce66b441cb57b151096cad..ea7cac09599782785bbea619e58b4e32fc4cef9f 100644 (file)
@@ -17,9 +17,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index e4ba2ce0f212b955f15db89df45d3b32af9942de..e3b885d8f7dbfddda2f4ae71161b24edeefdc02c 100644 (file)
@@ -15,9 +15,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 8cb43f8f3efcb96958ead840e055be1462f3f2f8..1122dc44c9fd3f0c9fb0b0906936020204c263f1 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 3db0d99d9da7a9980f63939186f7c2b7971cd533..a2fd05ba25ca886f2037baec9fb581b718ecbdd7 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 7f7baae5ae029e6c252676841682cf8fabf270f4..2e3d1645e68bb68fb827070f126beaefb1b7e3c6 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index e11d39bdfef77000699e3bfa9dbd8506eab32558..e65712c235bd2829f12a1b3f7d4daa1209837ec0 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 9dd92a700442a4c7e3aa8b2bacc97830b4a95148..00c3fae6fa3c1cfe2a7574a372e868432b073a85 100644 (file)
@@ -14,9 +14,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 063ebcce97f878c52f33d6d86f3d350e3e25e653..4c0e01b5d515a3a4bc11cf32a020ad6849f64001 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 1b4254b4272d089c23c53af030d289f7bbd49c52..fbae2799e3eeb49cf144bfc07b143709412ce774 100644 (file)
@@ -14,9 +14,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 997a6c89e66e4f44567cd9c04b99f86a0aae3a6d..c681d04b506c282dfdf2cd7726bdd6e10ccbd8ea 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 3b46f0c3332a51a191ce57c4e8bff5c3e95a2490..b2c5269570da18126c67cdfc17c792b1b4917229 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 7f40ab8e1bd809d017d6dff41b68b815c7ade240..fb7c349ccc9c04374c5e6a362fb93de94fa77cb1 100644 (file)
@@ -14,9 +14,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index c2b3b66291884e6171b2cd92b78024406ceb7252..9b941c0c12648d4a5b8e42c1e0679d9882febce1 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 2183e79783995eea92cb8d8498d0a8582c43c820..ddeb5a709aa36d6375e58597104f4cc3cb632d12 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 64b06c6abe586d1fda61f79688de66ec12800a16..6f236ea180aa3df23dbf8be831f367c020f4a1a2 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index cda3dbcf7eadf2f395e2ea6833615a0484c801f3..701c3127efb96bdb647ff19e21684134fc25e9e1 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 25da20e7e1f34ab2c0b1fd3e38a82d1faece0f9e..d93db4b0371b6a1e47cdfa5b1fd81fa4b83dd6cc 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
@@ -156,8 +154,6 @@ exit_release_regions:
 exit_disable_device:
        pci_disable_device(pci_dev);
 
-       pci_set_drvdata(pci_dev, NULL);
-
        return retval;
 }
 EXPORT_SYMBOL_GPL(rt2x00pci_probe);
@@ -177,7 +173,6 @@ void rt2x00pci_remove(struct pci_dev *pci_dev)
        /*
         * Free the PCI device data.
         */
-       pci_set_drvdata(pci_dev, NULL);
        pci_disable_device(pci_dev);
        pci_release_regions(pci_dev);
 }
index 60d90b20f8b99216a8dd19b4926364be65725b28..bc0ca5f58f38ca0b7d6b940bfad115a8151a5df0 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index a5d38e8ad9e4925cabd9f90744befd6b9a35d522..5642ccceca7c5544ba6e2aad62b0f00b0870a2c1 100644 (file)
@@ -15,9 +15,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index ebe11722497995a88d941acaa9749cef8fb83e39..c48125be0e34247cfe30ba51be437bb03ef66ed3 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 6f867eec49cce734c7c01ab149423bd8a3f77222..3cc541d13d679e8cc3217e0650919c2f313730c0 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 9271a5fce0a81347fbf6327732009bc6136443ee..69a0cdadb07f3d46a23fb8530c62d631233de743 100644 (file)
@@ -14,9 +14,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 474cbfc1efc79313b298d877ab19bd89bec6a24f..9948d355e9a499571eaaf980adb215b3461e0fb0 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 4e121627925d91db9de550b635b3fcece71c90e3..10572452cc21b76cc8fe4457298ea06bc3c875be 100644 (file)
@@ -14,9 +14,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 323ca7b2b095516f622ac7badfaa99ef3ed444f2..e7bcf62347d519c357b4866b6d6b2ec53eb059d0 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index a5b69cb49012162580ef78291b696ce15abbeb94..b76f6049ad9a9f099e8293f23a403a8e79a0c69a 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 9bc6b6044e34189e6a069a4168a7eaec53565a00..1442075a838218f61366d84d1ec5d40fb45bc7be 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 1baf9c896dcd6477efba878a1c0e407411635206..ade88d7e089cc485fc0f0a9fafb9ac0000cbf217 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 7577e0ba3877363cb63480b42c4e118f599de7ef..4a4f235466d17d43093afdd1e3378af17bcf1bd0 100644 (file)
@@ -13,9 +13,7 @@
        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.
+       along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
index 9a6edb0c014ec3526c5b4c260b8784cc8fd855d0..ec9aa5b6738171f547dc50a45b977795de133486 100644 (file)
@@ -416,7 +416,7 @@ static int rtl8187_init_urbs(struct ieee80211_hw *dev)
        struct rtl8187_rx_info *info;
        int ret = 0;
 
-       while (skb_queue_len(&priv->rx_queue) < 16) {
+       while (skb_queue_len(&priv->rx_queue) < 32) {
                skb = __dev_alloc_skb(RTL8187_MAX_RX, GFP_KERNEL);
                if (!skb) {
                        ret = -ENOMEM;
index ff784072fb4233a29a46a55bf21d75e094bb8d5c..fcf9b621918c07ba2ab42e38622af9b56ac66682 100644 (file)
@@ -1437,7 +1437,8 @@ void rtl_watchdog_wq_callback(void *data)
                        /* if we can't recv beacon for 6s, we should
                         * reconnect this AP
                         */
-                       if (rtlpriv->link_info.roam_times >= 3) {
+                       if ((rtlpriv->link_info.roam_times >= 3) &&
+                           !is_zero_ether_addr(rtlpriv->mac80211.bssid)) {
                                RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
                                         "AP off, try to reconnect now\n");
                                rtlpriv->link_info.roam_times = 0;
index 210ce7cd94d8d14201a68ce285e9c880993d30db..2d337a0c3df027c86742af4367c0c00fe64d2f49 100644 (file)
@@ -46,10 +46,20 @@ void rtl_fw_cb(const struct firmware *firmware, void *context)
                         "Firmware callback routine entered!\n");
        complete(&rtlpriv->firmware_loading_complete);
        if (!firmware) {
+               if (rtlpriv->cfg->alt_fw_name) {
+                       err = request_firmware(&firmware,
+                                              rtlpriv->cfg->alt_fw_name,
+                                              rtlpriv->io.dev);
+                       pr_info("Loading alternative firmware %s\n",
+                               rtlpriv->cfg->alt_fw_name);
+                       if (!err)
+                               goto found_alt;
+               }
                pr_err("Firmware %s not available\n", rtlpriv->cfg->fw_name);
                rtlpriv->max_fw_size = 0;
                return;
        }
+found_alt:
        if (firmware->size > rtlpriv->max_fw_size) {
                RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
                         "Firmware is too big!\n");
@@ -184,6 +194,7 @@ static int rtl_op_add_interface(struct ieee80211_hw *hw,
                                        rtlpriv->cfg->maps
                                        [RTL_IBSS_INT_MASKS]);
                }
+               mac->link_state = MAC80211_LINKED;
                break;
        case NL80211_IFTYPE_ADHOC:
                RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
index 0f494444bcd1d90b457b927d704bf77abe0592ca..8707d1a94995c740d11a5b6cd3dd5d4849616f53 100644 (file)
@@ -688,8 +688,6 @@ static void _rtl_receive_one(struct ieee80211_hw *hw, struct sk_buff *skb,
                rtlpriv->stats.rxbytesunicast += skb->len;
        }
 
-       rtl_is_special_data(hw, skb, false);
-
        if (ieee80211_is_data(fc)) {
                rtlpriv->cfg->ops->led_control(hw, LED_CTL_RX);
 
index d7d0d4948b01f2e804e6bcddfca93b10c7cdb312..a4eb9b271438657e863dc07af8d9ca20ac431301 100644 (file)
@@ -59,30 +59,26 @@ static struct country_code_to_enum_rd allCountries[] = {
  */
 #define RTL819x_2GHZ_CH12_13   \
        REG_RULE(2467-10, 2472+10, 40, 0, 20,\
-       NL80211_RRF_PASSIVE_SCAN)
+                NL80211_RRF_NO_IR)
 
 #define RTL819x_2GHZ_CH14      \
        REG_RULE(2484-10, 2484+10, 40, 0, 20, \
-       NL80211_RRF_PASSIVE_SCAN | \
-       NL80211_RRF_NO_OFDM)
+                NL80211_RRF_NO_IR | NL80211_RRF_NO_OFDM)
 
 /* 5G chan 36 - chan 64*/
 #define RTL819x_5GHZ_5150_5350 \
        REG_RULE(5150-10, 5350+10, 40, 0, 30, \
-       NL80211_RRF_PASSIVE_SCAN | \
-       NL80211_RRF_NO_IBSS)
+                NL80211_RRF_NO_IR)
 
 /* 5G chan 100 - chan 165*/
 #define RTL819x_5GHZ_5470_5850 \
        REG_RULE(5470-10, 5850+10, 40, 0, 30, \
-       NL80211_RRF_PASSIVE_SCAN | \
-       NL80211_RRF_NO_IBSS)
+                NL80211_RRF_NO_IR)
 
 /* 5G chan 149 - chan 165*/
 #define RTL819x_5GHZ_5725_5850 \
        REG_RULE(5725-10, 5850+10, 40, 0, 30, \
-       NL80211_RRF_PASSIVE_SCAN | \
-       NL80211_RRF_NO_IBSS)
+                NL80211_RRF_NO_IR)
 
 #define RTL819x_5GHZ_ALL       \
        (RTL819x_5GHZ_5150_5350, RTL819x_5GHZ_5470_5850)
@@ -172,7 +168,8 @@ static void _rtl_reg_apply_beaconing_flags(struct wiphy *wiphy,
                            (ch->flags & IEEE80211_CHAN_RADAR))
                                continue;
                        if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) {
-                               reg_rule = freq_reg_info(wiphy, ch->center_freq);
+                               reg_rule = freq_reg_info(wiphy,
+                                                        MHZ_TO_KHZ(ch->center_freq));
                                if (IS_ERR(reg_rule))
                                        continue;
 
@@ -185,16 +182,11 @@ static void _rtl_reg_apply_beaconing_flags(struct wiphy *wiphy,
                                 *regulatory_hint().
                                 */
 
-                               if (!(reg_rule->flags & NL80211_RRF_NO_IBSS))
-                                       ch->flags &= ~IEEE80211_CHAN_NO_IBSS;
-                               if (!(reg_rule->
-                                    flags & NL80211_RRF_PASSIVE_SCAN))
-                                       ch->flags &=
-                                           ~IEEE80211_CHAN_PASSIVE_SCAN;
+                               if (!(reg_rule->flags & NL80211_RRF_NO_IR))
+                                       ch->flags &= ~IEEE80211_CHAN_NO_IR;
                        } else {
                                if (ch->beacon_found)
-                                       ch->flags &= ~(IEEE80211_CHAN_NO_IBSS |
-                                                 IEEE80211_CHAN_PASSIVE_SCAN);
+                                       ch->flags &= ~IEEE80211_CHAN_NO_IR;
                        }
                }
        }
@@ -219,11 +211,11 @@ static void _rtl_reg_apply_active_scan_flags(struct wiphy *wiphy,
         */
        if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) {
                ch = &sband->channels[11];      /* CH 12 */
-               if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
-                       ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
+               if (ch->flags & IEEE80211_CHAN_NO_IR)
+                       ch->flags &= ~IEEE80211_CHAN_NO_IR;
                ch = &sband->channels[12];      /* CH 13 */
-               if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
-                       ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
+               if (ch->flags & IEEE80211_CHAN_NO_IR)
+                       ch->flags &= ~IEEE80211_CHAN_NO_IR;
                return;
        }
 
@@ -235,19 +227,19 @@ static void _rtl_reg_apply_active_scan_flags(struct wiphy *wiphy,
         */
 
        ch = &sband->channels[11];      /* CH 12 */
-       reg_rule = freq_reg_info(wiphy, ch->center_freq);
+       reg_rule = freq_reg_info(wiphy, MHZ_TO_KHZ(ch->center_freq));
        if (!IS_ERR(reg_rule)) {
-               if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
-                       if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
-                               ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
+               if (!(reg_rule->flags & NL80211_RRF_NO_IR))
+                       if (ch->flags & IEEE80211_CHAN_NO_IR)
+                               ch->flags &= ~IEEE80211_CHAN_NO_IR;
        }
 
        ch = &sband->channels[12];      /* CH 13 */
-       reg_rule = freq_reg_info(wiphy, ch->center_freq);
+       reg_rule = freq_reg_info(wiphy, MHZ_TO_KHZ(ch->center_freq));
        if (!IS_ERR(reg_rule)) {
-               if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
-                       if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
-                               ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
+               if (!(reg_rule->flags & NL80211_RRF_NO_IR))
+                       if (ch->flags & IEEE80211_CHAN_NO_IR)
+                               ch->flags &= ~IEEE80211_CHAN_NO_IR;
        }
 }
 
@@ -284,8 +276,7 @@ static void _rtl_reg_apply_radar_flags(struct wiphy *wiphy)
                 */
                if (!(ch->flags & IEEE80211_CHAN_DISABLED))
                        ch->flags |= IEEE80211_CHAN_RADAR |
-                           IEEE80211_CHAN_NO_IBSS |
-                           IEEE80211_CHAN_PASSIVE_SCAN;
+                                    IEEE80211_CHAN_NO_IR;
        }
 }
 
@@ -354,9 +345,9 @@ static int _rtl_regd_init_wiphy(struct rtl_regulatory *reg,
 
        wiphy->reg_notifier = reg_notifier;
 
-       wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
-       wiphy->flags &= ~WIPHY_FLAG_STRICT_REGULATORY;
-       wiphy->flags &= ~WIPHY_FLAG_DISABLE_BEACON_HINTS;
+       wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
+       wiphy->regulatory_flags &= ~REGULATORY_STRICT_REG;
+       wiphy->regulatory_flags &= ~REGULATORY_DISABLE_BEACON_HINTS;
 
        regd = _rtl_regdomain_select(reg);
        wiphy_apply_custom_regulatory(wiphy, regd);
index 21a5cf060677494106afced5c7e8907dfcf86f3d..a6184b6e1d57ff50bca6a4f4aa16ac2871dc295f 100644 (file)
@@ -1078,7 +1078,7 @@ static void rtl88e_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw
                                rtldm->swing_flag_ofdm = true;
                        }
 
-                       if (rtldm->swing_idx_cck != rtldm->swing_idx_cck) {
+                       if (rtldm->swing_idx_cck_cur != rtldm->swing_idx_cck) {
                                rtldm->swing_idx_cck_cur = rtldm->swing_idx_cck;
                                rtldm->swing_flag_cck = true;
                        }
index e9caa5d4cff0f910488cd4b22899ad9b5c84665a..eb78fd8607f7e456baf79066cb5e00a7c00e5d88 100644 (file)
@@ -158,6 +158,42 @@ static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = {
        {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00}
 };
 
+static u32 power_index_reg[6] = {0xc90, 0xc91, 0xc92, 0xc98, 0xc99, 0xc9a};
+
+void dm_restorepowerindex(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       u8      index;
+
+       for (index = 0; index < 6; index++)
+               rtl_write_byte(rtlpriv, power_index_reg[index],
+                              rtlpriv->dm.powerindex_backup[index]);
+}
+EXPORT_SYMBOL_GPL(dm_restorepowerindex);
+
+void dm_writepowerindex(struct ieee80211_hw *hw, u8 value)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       u8 index;
+
+       for (index = 0; index < 6; index++)
+               rtl_write_byte(rtlpriv, power_index_reg[index], value);
+}
+EXPORT_SYMBOL_GPL(dm_writepowerindex);
+
+void dm_savepowerindex(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       u8 index;
+       u8 tmp;
+
+       for (index = 0; index < 6; index++) {
+               tmp = rtl_read_byte(rtlpriv, power_index_reg[index]);
+               rtlpriv->dm.powerindex_backup[index] = tmp;
+       }
+}
+EXPORT_SYMBOL_GPL(dm_savepowerindex);
+
 static void rtl92c_dm_diginit(struct ieee80211_hw *hw)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -180,7 +216,12 @@ static void rtl92c_dm_diginit(struct ieee80211_hw *hw)
        dm_digtable->back_range_max = DM_DIG_BACKOFF_MAX;
        dm_digtable->back_range_min = DM_DIG_BACKOFF_MIN;
        dm_digtable->pre_cck_pd_state = CCK_PD_STAGE_MAX;
-       dm_digtable->cur_cck_pd_state = CCK_PD_STAGE_MAX;
+       dm_digtable->cur_cck_pd_state = CCK_PD_STAGE_LowRssi;
+
+       dm_digtable->forbidden_igi = DM_DIG_MIN;
+       dm_digtable->large_fa_hit = 0;
+       dm_digtable->recover_cnt = 0;
+       dm_digtable->dig_dynamic_min  = 0x25;
 }
 
 static u8 rtl92c_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw)
@@ -206,7 +247,9 @@ static u8 rtl92c_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw)
                rssi_val_min = rtlpriv->dm.entry_min_undec_sm_pwdb;
        }
 
-       return (u8) rssi_val_min;
+       if (rssi_val_min > 100)
+               rssi_val_min = 100;
+       return (u8)rssi_val_min;
 }
 
 static void rtl92c_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
@@ -224,9 +267,17 @@ static void rtl92c_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
 
        ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD);
        falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff);
+
+        ret_value = rtl_get_bbreg(hw, ROFDM0_FRAMESYNC, MASKDWORD);
+       falsealm_cnt->cnt_fast_fsync_fail = (ret_value & 0xffff);
+       falsealm_cnt->cnt_sb_search_fail = ((ret_value & 0xffff0000) >> 16);
+
        falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail +
-           falsealm_cnt->cnt_rate_illegal +
-           falsealm_cnt->cnt_crc8_fail + falsealm_cnt->cnt_mcs_fail;
+                                     falsealm_cnt->cnt_rate_illegal +
+                                     falsealm_cnt->cnt_crc8_fail +
+                                     falsealm_cnt->cnt_mcs_fail +
+                                     falsealm_cnt->cnt_fast_fsync_fail +
+                                     falsealm_cnt->cnt_sb_search_fail;
 
        rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(14), 1);
        ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, MASKBYTE0);
@@ -271,12 +322,14 @@ static void rtl92c_dm_ctrl_initgain_by_fa(struct ieee80211_hw *hw)
                value_igi++;
        else if (rtlpriv->falsealm_cnt.cnt_all >= DM_DIG_FA_TH2)
                value_igi += 2;
+
        if (value_igi > DM_DIG_FA_UPPER)
                value_igi = DM_DIG_FA_UPPER;
        else if (value_igi < DM_DIG_FA_LOWER)
                value_igi = DM_DIG_FA_LOWER;
+
        if (rtlpriv->falsealm_cnt.cnt_all > 10000)
-               value_igi = 0x32;
+               value_igi = DM_DIG_FA_UPPER;
 
        dm_digtable->cur_igvalue = value_igi;
        rtl92c_dm_write_dig(hw);
@@ -286,32 +339,80 @@ static void rtl92c_dm_ctrl_initgain_by_rssi(struct ieee80211_hw *hw)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct dig_t *digtable = &rtlpriv->dm_digtable;
+       u32 isbt;
+
+       /* modify DIG lower bound, deal with abnorally large false alarm */
+       if (rtlpriv->falsealm_cnt.cnt_all > 10000) {
+               digtable->large_fa_hit++;
+               if (digtable->forbidden_igi < digtable->cur_igvalue) {
+                       digtable->forbidden_igi = digtable->cur_igvalue;
+                       digtable->large_fa_hit = 1;
+               }
 
-       if (rtlpriv->falsealm_cnt.cnt_all > digtable->fa_highthresh) {
-               if ((digtable->back_val - 2) < digtable->back_range_min)
-                       digtable->back_val = digtable->back_range_min;
-               else
-                       digtable->back_val -= 2;
-       } else if (rtlpriv->falsealm_cnt.cnt_all < digtable->fa_lowthresh) {
-               if ((digtable->back_val + 2) > digtable->back_range_max)
-                       digtable->back_val = digtable->back_range_max;
-               else
-                       digtable->back_val += 2;
+               if (digtable->large_fa_hit >= 3) {
+                       if ((digtable->forbidden_igi + 1) >
+                           digtable->rx_gain_max)
+                               digtable->rx_gain_min = digtable->rx_gain_max;
+                       else
+                               digtable->rx_gain_min = (digtable->forbidden_igi + 1);
+                       digtable->recover_cnt = 3600; /* 3600=2hr */
+               }
+       } else {
+               /* Recovery mechanism for IGI lower bound */
+               if (digtable->recover_cnt != 0) {
+                       digtable->recover_cnt--;
+               } else {
+                       if (digtable->large_fa_hit == 0) {
+                               if ((digtable->forbidden_igi-1) < DM_DIG_MIN) {
+                                       digtable->forbidden_igi = DM_DIG_MIN;
+                                       digtable->rx_gain_min = DM_DIG_MIN;
+                               } else {
+                                       digtable->forbidden_igi--;
+                                       digtable->rx_gain_min = digtable->forbidden_igi + 1;
+                               }
+                       } else if (digtable->large_fa_hit == 3) {
+                               digtable->large_fa_hit = 0;
+                       }
+               }
+       }
+       if (rtlpriv->falsealm_cnt.cnt_all < 250) {
+               isbt = rtl_read_byte(rtlpriv, 0x4fd) & 0x01;
+
+               if (!isbt) {
+                       if (rtlpriv->falsealm_cnt.cnt_all >
+                           digtable->fa_lowthresh) {
+                               if ((digtable->back_val - 2) <
+                                  digtable->back_range_min)
+                                       digtable->back_val = digtable->back_range_min;
+                               else
+                                       digtable->back_val -= 2;
+                       } else if (rtlpriv->falsealm_cnt.cnt_all <
+                                  digtable->fa_lowthresh) {
+                               if ((digtable->back_val + 2) >
+                                   digtable->back_range_max)
+                                       digtable->back_val = digtable->back_range_max;
+                               else
+                                       digtable->back_val += 2;
+                       }
+               } else {
+                       digtable->back_val = DM_DIG_BACKOFF_DEFAULT;
+               }
+       } else {
+               /* Adjust initial gain by false alarm */
+               if (rtlpriv->falsealm_cnt.cnt_all > 1000)
+                       digtable->cur_igvalue = digtable->pre_igvalue + 2;
+               else if (rtlpriv->falsealm_cnt.cnt_all > 750)
+                       digtable->cur_igvalue = digtable->pre_igvalue + 1;
+               else if (rtlpriv->falsealm_cnt.cnt_all < 500)
+                       digtable->cur_igvalue = digtable->pre_igvalue - 1;
        }
 
-       if ((digtable->rssi_val_min + 10 - digtable->back_val) >
-           digtable->rx_gain_max)
+       /* Check initial gain by upper/lower bound */
+       if (digtable->cur_igvalue > digtable->rx_gain_max)
                digtable->cur_igvalue = digtable->rx_gain_max;
-       else if ((digtable->rssi_val_min + 10 -
-                 digtable->back_val) < digtable->rx_gain_min)
-               digtable->cur_igvalue = digtable->rx_gain_min;
-       else
-               digtable->cur_igvalue = digtable->rssi_val_min + 10 -
-                   digtable->back_val;
 
-       RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
-                "rssi_val_min = %x back_val %x\n",
-                digtable->rssi_val_min, digtable->back_val);
+       if (digtable->cur_igvalue < digtable->rx_gain_min)
+               digtable->cur_igvalue = digtable->rx_gain_min;
 
        rtl92c_dm_write_dig(hw);
 }
@@ -329,7 +430,7 @@ static void rtl92c_dm_initial_gain_multi_sta(struct ieee80211_hw *hw)
                multi_sta = true;
 
        if (!multi_sta ||
-           dm_digtable->cursta_cstate != DIG_STA_DISCONNECT) {
+           dm_digtable->cursta_cstate == DIG_STA_DISCONNECT) {
                initialized = false;
                dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
                return;
@@ -375,7 +476,6 @@ static void rtl92c_dm_initial_gain_sta(struct ieee80211_hw *hw)
        RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
                 "presta_cstate = %x, cursta_cstate = %x\n",
                 dm_digtable->presta_cstate, dm_digtable->cursta_cstate);
-
        if (dm_digtable->presta_cstate == dm_digtable->cursta_cstate ||
            dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT ||
            dm_digtable->cursta_cstate == DIG_STA_CONNECT) {
@@ -383,6 +483,8 @@ static void rtl92c_dm_initial_gain_sta(struct ieee80211_hw *hw)
                if (dm_digtable->cursta_cstate != DIG_STA_DISCONNECT) {
                        dm_digtable->rssi_val_min =
                            rtl92c_dm_initial_gain_min_pwdb(hw);
+                       if (dm_digtable->rssi_val_min > 100)
+                               dm_digtable->rssi_val_min = 100;
                        rtl92c_dm_ctrl_initgain_by_rssi(hw);
                }
        } else {
@@ -398,11 +500,12 @@ static void rtl92c_dm_initial_gain_sta(struct ieee80211_hw *hw)
 static void rtl92c_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
-       struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
        struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 
        if (dm_digtable->cursta_cstate == DIG_STA_CONNECT) {
                dm_digtable->rssi_val_min = rtl92c_dm_initial_gain_min_pwdb(hw);
+               if (dm_digtable->rssi_val_min > 100)
+                       dm_digtable->rssi_val_min = 100;
 
                if (dm_digtable->pre_cck_pd_state == CCK_PD_STAGE_LowRssi) {
                        if (dm_digtable->rssi_val_min <= 25)
@@ -424,48 +527,14 @@ static void rtl92c_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
        }
 
        if (dm_digtable->pre_cck_pd_state != dm_digtable->cur_cck_pd_state) {
-               if (dm_digtable->cur_cck_pd_state == CCK_PD_STAGE_LowRssi) {
-                       if (rtlpriv->falsealm_cnt.cnt_cck_fail > 800)
-                               dm_digtable->cur_cck_fa_state =
-                                   CCK_FA_STAGE_High;
-                       else
-                               dm_digtable->cur_cck_fa_state = CCK_FA_STAGE_Low;
-
-                       if (dm_digtable->pre_cck_fa_state !=
-                           dm_digtable->cur_cck_fa_state) {
-                               if (dm_digtable->cur_cck_fa_state ==
-                                   CCK_FA_STAGE_Low)
-                                       rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2,
-                                                     0x83);
-                               else
-                                       rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2,
-                                                     0xcd);
-
-                               dm_digtable->pre_cck_fa_state =
-                                   dm_digtable->cur_cck_fa_state;
-                       }
-
-                       rtl_set_bbreg(hw, RCCK0_SYSTEM, MASKBYTE1, 0x40);
-
-                       if (IS_92C_SERIAL(rtlhal->version))
-                               rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT,
-                                             MASKBYTE2, 0xd7);
-               } else {
+               if ((dm_digtable->cur_cck_pd_state == CCK_PD_STAGE_LowRssi) ||
+                   (dm_digtable->cur_cck_pd_state == CCK_PD_STAGE_MAX))
+                       rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0x83);
+               else
                        rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd);
-                       rtl_set_bbreg(hw, RCCK0_SYSTEM, MASKBYTE1, 0x47);
 
-                       if (IS_92C_SERIAL(rtlhal->version))
-                               rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT,
-                                             MASKBYTE2, 0xd3);
-               }
                dm_digtable->pre_cck_pd_state = dm_digtable->cur_cck_pd_state;
        }
-
-       RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, "CCKPDStage=%x\n",
-                dm_digtable->cur_cck_pd_state);
-
-       RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, "is92C=%x\n",
-                IS_92C_SERIAL(rtlhal->version));
 }
 
 static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw)
@@ -482,6 +551,8 @@ static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw)
        else
                dm_digtable->cursta_cstate = DIG_STA_DISCONNECT;
 
+       dm_digtable->curmultista_cstate = DIG_MULTISTA_DISCONNECT;
+
        rtl92c_dm_initial_gain_sta(hw);
        rtl92c_dm_initial_gain_multi_sta(hw);
        rtl92c_dm_cck_packet_detection_thresh(hw);
@@ -493,23 +564,26 @@ static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw)
 static void rtl92c_dm_dig(struct ieee80211_hw *hw)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
-       struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 
        if (rtlpriv->dm.dm_initialgain_enable == false)
                return;
-       if (dm_digtable->dig_enable_flag == false)
+       if (!(rtlpriv->dm.dm_flag & DYNAMIC_FUNC_DIG))
                return;
 
        rtl92c_dm_ctrl_initgain_by_twoport(hw);
-
 }
 
 static void rtl92c_dm_init_dynamic_txpower(struct ieee80211_hw *hw)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
 
-       rtlpriv->dm.dynamic_txpower_enable = false;
-
+       if (rtlpriv->rtlhal.interface == INTF_USB &&
+           rtlpriv->rtlhal.board_type & 0x1) {
+               dm_savepowerindex(hw);
+               rtlpriv->dm.dynamic_txpower_enable = true;
+       } else {
+               rtlpriv->dm.dynamic_txpower_enable = false;
+       }
        rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL;
        rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
 }
@@ -524,9 +598,14 @@ void rtl92c_dm_write_dig(struct ieee80211_hw *hw)
                 dm_digtable->cur_igvalue, dm_digtable->pre_igvalue,
                 dm_digtable->back_val);
 
-       dm_digtable->cur_igvalue += 2;
-       if (dm_digtable->cur_igvalue > 0x3f)
-               dm_digtable->cur_igvalue = 0x3f;
+       if (rtlpriv->rtlhal.interface == INTF_USB &&
+           !dm_digtable->dig_enable_flag) {
+               dm_digtable->pre_igvalue = 0x17;
+               return;
+       }
+       dm_digtable->cur_igvalue -= 1;
+       if (dm_digtable->cur_igvalue < DM_DIG_MIN)
+               dm_digtable->cur_igvalue = DM_DIG_MIN;
 
        if (dm_digtable->pre_igvalue != dm_digtable->cur_igvalue) {
                rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f,
@@ -536,11 +615,47 @@ void rtl92c_dm_write_dig(struct ieee80211_hw *hw)
 
                dm_digtable->pre_igvalue = dm_digtable->cur_igvalue;
        }
+       RT_TRACE(rtlpriv, COMP_DIG, DBG_WARNING,
+                "dig values 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+                dm_digtable->cur_igvalue, dm_digtable->pre_igvalue,
+                dm_digtable->rssi_val_min, dm_digtable->back_val,
+                dm_digtable->rx_gain_max, dm_digtable->rx_gain_min,
+                dm_digtable->large_fa_hit, dm_digtable->forbidden_igi);
 }
 EXPORT_SYMBOL(rtl92c_dm_write_dig);
 
 static void rtl92c_dm_pwdb_monitor(struct ieee80211_hw *hw)
 {
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+       long tmpentry_max_pwdb = 0, tmpentry_min_pwdb = 0xff;
+
+       if (mac->link_state != MAC80211_LINKED)
+               return;
+
+       if (mac->opmode == NL80211_IFTYPE_ADHOC ||
+           mac->opmode == NL80211_IFTYPE_AP) {
+               /* TODO: Handle ADHOC and AP Mode */
+       }
+
+       if (tmpentry_max_pwdb != 0)
+               rtlpriv->dm.entry_max_undec_sm_pwdb = tmpentry_max_pwdb;
+       else
+               rtlpriv->dm.entry_max_undec_sm_pwdb = 0;
+
+       if (tmpentry_min_pwdb != 0xff)
+               rtlpriv->dm.entry_min_undec_sm_pwdb = tmpentry_min_pwdb;
+       else
+               rtlpriv->dm.entry_min_undec_sm_pwdb = 0;
+
+/* TODO:
+ *     if (mac->opmode == NL80211_IFTYPE_STATION) {
+ *             if (rtlpriv->rtlhal.fw_ready) {
+ *                     u32 param = (u32)(rtlpriv->dm.undec_sm_pwdb << 16);
+ *                     rtl8192c_set_rssi_cmd(hw, param);
+ *             }
+ *     }
+ */
 }
 
 void rtl92c_dm_init_edca_turbo(struct ieee80211_hw *hw)
@@ -750,6 +865,7 @@ static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw
                                rtlpriv->dm.ofdm_index[i] = ofdm_index_old[i];
                        rtlpriv->dm.cck_index = cck_index_old;
                }
+               /* Handle USB High PA boards */
 
                delta = (thermalvalue > rtlpriv->dm.thermalvalue) ?
                    (thermalvalue - rtlpriv->dm.thermalvalue) :
@@ -1140,22 +1256,22 @@ void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct ps_t *dm_pstable = &rtlpriv->dm_pstable;
-       static u8 initialize;
-       static u32 reg_874, reg_c70, reg_85c, reg_a74;
 
-       if (initialize == 0) {
-               reg_874 = (rtl_get_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
-                                        MASKDWORD) & 0x1CC000) >> 14;
+       if (!rtlpriv->reg_init) {
+               rtlpriv->reg_874 = (rtl_get_bbreg(hw,
+                                                 RFPGA0_XCD_RFINTERFACESW,
+                                                 MASKDWORD) & 0x1CC000) >> 14;
 
-               reg_c70 = (rtl_get_bbreg(hw, ROFDM0_AGCPARAMETER1,
-                                        MASKDWORD) & BIT(3)) >> 3;
+               rtlpriv->reg_c70 = (rtl_get_bbreg(hw, ROFDM0_AGCPARAMETER1,
+                                   MASKDWORD) & BIT(3)) >> 3;
 
-               reg_85c = (rtl_get_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL,
-                                        MASKDWORD) & 0xFF000000) >> 24;
+               rtlpriv->reg_85c = (rtl_get_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL,
+                                   MASKDWORD) & 0xFF000000) >> 24;
 
-               reg_a74 = (rtl_get_bbreg(hw, 0xa74, MASKDWORD) & 0xF000) >> 12;
+               rtlpriv->reg_a74 = (rtl_get_bbreg(hw, 0xa74, MASKDWORD) &
+                                   0xF000) >> 12;
 
-               initialize = 1;
+               rtlpriv->reg_init = true;
        }
 
        if (!bforce_in_normal) {
@@ -1192,12 +1308,12 @@ void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal)
                        rtl_set_bbreg(hw, 0x818, BIT(28), 0x1);
                } else {
                        rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
-                                     0x1CC000, reg_874);
+                                     0x1CC000, rtlpriv->reg_874);
                        rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3),
-                                     reg_c70);
+                                     rtlpriv->reg_c70);
                        rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, 0xFF000000,
-                                     reg_85c);
-                       rtl_set_bbreg(hw, 0xa74, 0xF000, reg_a74);
+                                     rtlpriv->reg_85c);
+                       rtl_set_bbreg(hw, 0xa74, 0xF000, rtlpriv->reg_a74);
                        rtl_set_bbreg(hw, 0x818, BIT(28), 0x0);
                }
 
@@ -1213,6 +1329,7 @@ static void rtl92c_dm_dynamic_bb_powersaving(struct ieee80211_hw *hw)
        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 
+       /* Determine the minimum RSSI */
        if (((mac->link_state == MAC80211_NOLINK)) &&
            (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
                dm_pstable->rssi_val_min = 0;
@@ -1241,6 +1358,7 @@ static void rtl92c_dm_dynamic_bb_powersaving(struct ieee80211_hw *hw)
                         dm_pstable->rssi_val_min);
        }
 
+       /* Power Saving for 92C */
        if (IS_92C_SERIAL(rtlhal->version))
                ;/* rtl92c_dm_1r_cca(hw); */
        else
@@ -1252,12 +1370,23 @@ void rtl92c_dm_init(struct ieee80211_hw *hw)
        struct rtl_priv *rtlpriv = rtl_priv(hw);
 
        rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
+       rtlpriv->dm.dm_flag = DYNAMIC_FUNC_DISABLE | DYNAMIC_FUNC_DIG;
+       rtlpriv->dm.undec_sm_pwdb = -1;
+       rtlpriv->dm.undec_sm_cck = -1;
+       rtlpriv->dm.dm_initialgain_enable = true;
        rtl92c_dm_diginit(hw);
+
+       rtlpriv->dm.dm_flag |= HAL_DM_HIPWR_DISABLE;
        rtl92c_dm_init_dynamic_txpower(hw);
+
        rtl92c_dm_init_edca_turbo(hw);
        rtl92c_dm_init_rate_adaptive_mask(hw);
+       rtlpriv->dm.dm_flag |= DYNAMIC_FUNC_SS;
        rtl92c_dm_initialize_txpower_tracking(hw);
        rtl92c_dm_init_dynamic_bb_powersaving(hw);
+
+       rtlpriv->dm.ofdm_pkt_cnt = 0;
+       rtlpriv->dm.dm_rssi_sel = RSSI_DEFAULT;
 }
 EXPORT_SYMBOL(rtl92c_dm_init);
 
@@ -1308,7 +1437,7 @@ void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw)
        }
 
        if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) {
-               rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1;
+               rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL2;
                RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
                         "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n");
        } else if ((undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) &&
@@ -1328,8 +1457,16 @@ void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw)
                         "PHY_SetTxPowerLevel8192S() Channel = %d\n",
                         rtlphy->current_channel);
                rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel);
+               if (rtlpriv->dm.dynamic_txhighpower_lvl ==
+                   TXHIGHPWRLEVEL_NORMAL)
+                       dm_restorepowerindex(hw);
+               else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
+                        TXHIGHPWRLEVEL_LEVEL1)
+                       dm_writepowerindex(hw, 0x14);
+               else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
+                        TXHIGHPWRLEVEL_LEVEL2)
+                       dm_writepowerindex(hw, 0x10);
        }
-
        rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl;
 }
 
@@ -1400,12 +1537,6 @@ u8 rtl92c_bt_rssi_state_change(struct ieee80211_hw *hw)
        else
                curr_bt_rssi_state &= (~BT_RSSI_STATE_SPECIAL_LOW);
 
-       /* Set Tx Power according to BT status. */
-       if (undec_sm_pwdb >= 30)
-               curr_bt_rssi_state |=  BT_RSSI_STATE_TXPOWER_LOW;
-       else if (undec_sm_pwdb < 25)
-               curr_bt_rssi_state &= (~BT_RSSI_STATE_TXPOWER_LOW);
-
        /* Check BT state related to BT_Idle in B/G mode. */
        if (undec_sm_pwdb < 15)
                curr_bt_rssi_state |=  BT_RSSI_STATE_BG_EDCA_LOW;
index 518e208c018064049406a0b653cdd5763d601440..4f232a063636ee01aa137efffca38b0dcc034b21 100644 (file)
 #define TX_POWER_NEAR_FIELD_THRESH_LVL2                74
 #define TX_POWER_NEAR_FIELD_THRESH_LVL1                67
 
+#define DYNAMIC_FUNC_DISABLE                   0x0
+#define DYNAMIC_FUNC_DIG                       BIT(0)
+#define DYNAMIC_FUNC_HP                                BIT(1)
+#define DYNAMIC_FUNC_SS                                BIT(2) /*Tx Power Tracking*/
+#define DYNAMIC_FUNC_BT                                BIT(3)
+#define DYNAMIC_FUNC_ANT_DIV                   BIT(4)
+
+#define        RSSI_CCK                                0
+#define        RSSI_OFDM                               1
+#define        RSSI_DEFAULT                            2
+
 struct swat_t {
        u8 failure_cnt;
        u8 try_flag;
@@ -167,5 +178,8 @@ void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw);
 void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery);
 void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw);
 void rtl92c_dm_bt_coexist(struct ieee80211_hw *hw);
+void dm_savepowerindex(struct ieee80211_hw *hw);
+void dm_writepowerindex(struct ieee80211_hw *hw, u8 value);
+void dm_restorepowerindex(struct ieee80211_hw *hw);
 
 #endif
index 0c0e78263a665190aacf3d33d21fa87b99d4dd86..9e32ac8a4425f5dd9b9d3c8f4c57db66d684c1dd 100644 (file)
@@ -1147,6 +1147,12 @@ static void _rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw,
                0x522, 0x550, 0x551, 0x040
        };
 
+       u32 iqk_bb_reg_92C[9] = {
+               0xc04, 0xc08, 0x874, 0xb68,
+               0xb6c, 0x870, 0x860, 0x864,
+               0x800
+       };
+
        const u32 retrycount = 2;
 
        if (t == 0) {
@@ -1157,6 +1163,8 @@ static void _rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw,
                                                rtlphy->adda_backup, 16);
                _rtl92c_phy_save_mac_registers(hw, iqk_mac_reg,
                                               rtlphy->iqk_mac_backup);
+               _rtl92c_phy_save_adda_registers(hw, iqk_bb_reg_92C,
+                                               rtlphy->iqk_bb_backup, 9);
        }
        _rtl92c_phy_path_adda_on(hw, adda_reg, true, is2t);
        if (t == 0) {
@@ -1167,14 +1175,18 @@ static void _rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw,
 
        if (!rtlphy->rfpi_enable)
                _rtl92c_phy_pi_mode_switch(hw, true);
-       if (t == 0) {
-               rtlphy->reg_c04 = rtl_get_bbreg(hw, 0xc04, MASKDWORD);
-               rtlphy->reg_c08 = rtl_get_bbreg(hw, 0xc08, MASKDWORD);
-               rtlphy->reg_874 = rtl_get_bbreg(hw, 0x874, MASKDWORD);
-       }
+
+       rtl_set_bbreg(hw, 0x800, BIT(24), 0x0);
+
        rtl_set_bbreg(hw, 0xc04, MASKDWORD, 0x03a05600);
        rtl_set_bbreg(hw, 0xc08, MASKDWORD, 0x000800e4);
        rtl_set_bbreg(hw, 0x874, MASKDWORD, 0x22204000);
+
+       rtl_set_bbreg(hw, 0x870, BIT(10), 0x1);
+       rtl_set_bbreg(hw, 0x870, BIT(26), 0x1);
+       rtl_set_bbreg(hw, 0x860, BIT(10), 0x0);
+       rtl_set_bbreg(hw, 0x864, BIT(10), 0x0);
+
        if (is2t) {
                rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000);
                rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00010000);
@@ -1239,13 +1251,9 @@ static void _rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw,
                                        0x3FF0000) >> 16;
                }
        }
-       rtl_set_bbreg(hw, 0xc04, MASKDWORD, rtlphy->reg_c04);
-       rtl_set_bbreg(hw, 0x874, MASKDWORD, rtlphy->reg_874);
-       rtl_set_bbreg(hw, 0xc08, MASKDWORD, rtlphy->reg_c08);
+
        rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0);
-       rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00032ed3);
-       if (is2t)
-               rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00032ed3);
+
        if (t != 0) {
                if (!rtlphy->rfpi_enable)
                        _rtl92c_phy_pi_mode_switch(hw, false);
@@ -1253,6 +1261,15 @@ static void _rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw,
                                                  rtlphy->adda_backup, 16);
                _rtl92c_phy_reload_mac_registers(hw, iqk_mac_reg,
                                                 rtlphy->iqk_mac_backup);
+               _rtl92c_phy_reload_adda_registers(hw, iqk_bb_reg_92C,
+                                                 rtlphy->iqk_bb_backup, 9);
+
+               rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00032ed3);
+               if (is2t)
+                       rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00032ed3);
+
+               rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x01008c00);
+               rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x01008c00);
        }
 }
 
index 16a0b9e59acf726745d3ad90c5480f2c4151096d..c16209a336eac66c6b7ad78afa6ac3d24b197796 100644 (file)
@@ -101,6 +101,15 @@ void rtl92cu_dm_dynamic_txpower(struct ieee80211_hw *hw)
                         "PHY_SetTxPowerLevel8192S() Channel = %d\n",
                         rtlphy->current_channel);
                rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel);
+               if (rtlpriv->dm.dynamic_txhighpower_lvl ==
+                   TXHIGHPWRLEVEL_NORMAL)
+                       dm_restorepowerindex(hw);
+               else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
+                        TXHIGHPWRLEVEL_LEVEL1)
+                       dm_writepowerindex(hw, 0x14);
+               else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
+                        TXHIGHPWRLEVEL_LEVEL2)
+                       dm_writepowerindex(hw, 0x10);
        }
 
        rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl;
index d947e7d350bbc146d7b56b1c463c9dce829b5dce..fafa6bac2a3f5062b98911dc5802dd9e82fc2b95 100644 (file)
@@ -30,3 +30,6 @@
 #include "../rtl8192ce/dm.h"
 
 void rtl92cu_dm_dynamic_txpower(struct ieee80211_hw *hw);
+void dm_savepowerindex(struct ieee80211_hw *hw);
+void dm_writepowerindex(struct ieee80211_hw *hw, u8 value);
+void dm_restorepowerindex(struct ieee80211_hw *hw);
index 189ba124a8c6f4cfca817e77d4b0c7027c976459..468bf73cc883f41bf26222cc7aa52e17c5ed96a3 100644 (file)
@@ -1022,7 +1022,7 @@ int rtl92cu_hw_init(struct ieee80211_hw *hw)
        if (ppsc->rfpwr_state == ERFON) {
                rtl92c_phy_set_rfpath_switch(hw, 1);
                if (iqk_initialized) {
-                       rtl92c_phy_iq_calibrate(hw, false);
+                       rtl92c_phy_iq_calibrate(hw, true);
                } else {
                        rtl92c_phy_iq_calibrate(hw, false);
                        iqk_initialized = true;
index 34e56308301e8942c9ed3f216ad307a9b6b07763..0c09240eadccdee5fe6fd6ab266c561d7019684b 100644 (file)
@@ -120,6 +120,7 @@ bool rtl92cu_phy_bb_config(struct ieee80211_hw *hw)
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
        u16 regval;
+       u32 regval32;
        u8 b_reg_hwparafile = 1;
 
        _rtl92c_phy_init_bb_rf_register_definition(hw);
@@ -135,8 +136,11 @@ bool rtl92cu_phy_bb_config(struct ieee80211_hw *hw)
        } else if (IS_HARDWARE_TYPE_8192CU(rtlhal)) {
                rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, FEN_USBA | FEN_USBD |
                               FEN_BB_GLB_RSTn | FEN_BBRSTB);
-               rtl_write_byte(rtlpriv, REG_LDOHCI12_CTRL, 0x0f);
        }
+       regval32 = rtl_read_dword(rtlpriv, 0x87c);
+       rtl_write_dword(rtlpriv, 0x87c, regval32 & (~BIT(31)));
+       if (IS_HARDWARE_TYPE_8192CU(rtlhal))
+               rtl_write_byte(rtlpriv, REG_LDOHCI12_CTRL, 0x0f);
        rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80);
        if (b_reg_hwparafile == 1)
                rtstatus = _rtl92c_phy_bb8192c_config_parafile(hw);
index 2119313a737bab21e9c304627b2acb56d2a3ab43..b878d56d2f4df6020449e223dfed618c4d36edbc 100644 (file)
@@ -85,17 +85,15 @@ void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
        if (mac->act_scanning) {
                tx_agc[RF90_PATH_A] = 0x3f3f3f3f;
                tx_agc[RF90_PATH_B] = 0x3f3f3f3f;
-               if (turbo_scanoff) {
-                       for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
-                               tx_agc[idx1] = ppowerlevel[idx1] |
-                                   (ppowerlevel[idx1] << 8) |
-                                   (ppowerlevel[idx1] << 16) |
-                                   (ppowerlevel[idx1] << 24);
-                               if (rtlhal->interface == INTF_USB) {
-                                       if (tx_agc[idx1] > 0x20 &&
-                                           rtlefuse->external_pa)
-                                               tx_agc[idx1] = 0x20;
-                               }
+               for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
+                       tx_agc[idx1] = ppowerlevel[idx1] |
+                           (ppowerlevel[idx1] << 8) |
+                           (ppowerlevel[idx1] << 16) |
+                           (ppowerlevel[idx1] << 24);
+                       if (rtlhal->interface == INTF_USB) {
+                               if (tx_agc[idx1] > 0x20 &&
+                                   rtlefuse->external_pa)
+                                       tx_agc[idx1] = 0x20;
                        }
                }
        } else {
@@ -107,7 +105,7 @@ void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
                           TXHIGHPWRLEVEL_LEVEL2) {
                        tx_agc[RF90_PATH_A] = 0x00000000;
                        tx_agc[RF90_PATH_B] = 0x00000000;
-               } else{
+               } else {
                        for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
                                tx_agc[idx1] = ppowerlevel[idx1] |
                                    (ppowerlevel[idx1] << 8) |
@@ -373,7 +371,12 @@ static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw,
                            regoffset == RTXAGC_B_MCS07_MCS04)
                                regoffset = 0xc98;
                        for (i = 0; i < 3; i++) {
-                               writeVal = (writeVal > 6) ? (writeVal - 6) : 0;
+                               if (i != 2)
+                                       writeVal = (writeVal > 8) ?
+                                                  (writeVal - 8) : 0;
+                               else
+                                       writeVal = (writeVal > 6) ?
+                                                  (writeVal - 6) : 0;
                                rtl_write_byte(rtlpriv, (u32)(regoffset + i),
                                              (u8)writeVal);
                        }
index 9936de716ad58929e50dc0e6f02fca77f5efee68..8501954cfb444d8d8f74dfb4d66cf097b45e83fd 100644 (file)
@@ -50,6 +50,9 @@ MODULE_AUTHOR("Larry Finger   <Larry.Finger@lwfinger.net>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Realtek 8192C/8188C 802.11n USB wireless");
 MODULE_FIRMWARE("rtlwifi/rtl8192cufw.bin");
+MODULE_FIRMWARE("rtlwifi/rtl8192cufw_A.bin");
+MODULE_FIRMWARE("rtlwifi/rtl8192cufw_B.bin");
+MODULE_FIRMWARE("rtlwifi/rtl8192cufw_TMSC.bin");
 
 static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw)
 {
@@ -69,14 +72,21 @@ static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw)
                         "Can't alloc buffer for fw\n");
                return 1;
        }
-
+       if (IS_VENDOR_UMC_A_CUT(rtlpriv->rtlhal.version) &&
+           !IS_92C_SERIAL(rtlpriv->rtlhal.version)) {
+               rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cufw_A.bin";
+       } else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlpriv->rtlhal.version)) {
+               rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cufw_B.bin";
+       } else {
+               rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cufw_TMSC.bin";
+       }
+       /* provide name of alternative file */
+       rtlpriv->cfg->alt_fw_name = "rtlwifi/rtl8192cufw.bin";
        pr_info("Loading firmware %s\n", rtlpriv->cfg->fw_name);
        rtlpriv->max_fw_size = 0x4000;
        err = request_firmware_nowait(THIS_MODULE, 1,
                                      rtlpriv->cfg->fw_name, rtlpriv->io.dev,
                                      GFP_KERNEL, hw, rtl_fw_cb);
-
-
        return err;
 }
 
index 966be519edb89b8780778ad0145e4ece80c6621a..7903c154de00d2cd193e54ed0d33a27d68ca9c1c 100644 (file)
@@ -36,7 +36,7 @@ u32 RTL8192CUPHY_REG_2TARRAY[RTL8192CUPHY_REG_2TARRAY_LENGTH] = {
        0x804, 0x00000003,
        0x808, 0x0000fc00,
        0x80c, 0x0000000a,
-       0x810, 0x10005388,
+       0x810, 0x10000330,
        0x814, 0x020c3d10,
        0x818, 0x02200385,
        0x81c, 0x00000000,
@@ -110,22 +110,22 @@ u32 RTL8192CUPHY_REG_2TARRAY[RTL8192CUPHY_REG_2TARRAY_LENGTH] = {
        0xc44, 0x000100b7,
        0xc48, 0xec020107,
        0xc4c, 0x007f037f,
-       0xc50, 0x6954341e,
+       0xc50, 0x69543420,
        0xc54, 0x43bc0094,
-       0xc58, 0x6954341e,
+       0xc58, 0x69543420,
        0xc5c, 0x433c0094,
        0xc60, 0x00000000,
        0xc64, 0x5116848b,
        0xc68, 0x47c00bff,
        0xc6c, 0x00000036,
        0xc70, 0x2c7f000d,
-       0xc74, 0x0186115b,
+       0xc74, 0x2186115b,
        0xc78, 0x0000001f,
        0xc7c, 0x00b99612,
        0xc80, 0x40000100,
        0xc84, 0x20f60000,
        0xc88, 0x40000100,
-       0xc8c, 0x20200000,
+       0xc8c, 0xa0e40000,
        0xc90, 0x00121820,
        0xc94, 0x00000000,
        0xc98, 0x00121820,
@@ -226,7 +226,7 @@ u32 RTL8192CUPHY_REG_1TARRAY[RTL8192CUPHY_REG_1TARRAY_LENGTH] = {
        0x804, 0x00000001,
        0x808, 0x0000fc00,
        0x80c, 0x0000000a,
-       0x810, 0x10005388,
+       0x810, 0x10000330,
        0x814, 0x020c3d10,
        0x818, 0x02200385,
        0x81c, 0x00000000,
@@ -300,9 +300,9 @@ u32 RTL8192CUPHY_REG_1TARRAY[RTL8192CUPHY_REG_1TARRAY_LENGTH] = {
        0xc44, 0x000100b7,
        0xc48, 0xec020107,
        0xc4c, 0x007f037f,
-       0xc50, 0x6954341e,
+       0xc50, 0x69543420,
        0xc54, 0x43bc0094,
-       0xc58, 0x6954341e,
+       0xc58, 0x69543420,
        0xc5c, 0x433c0094,
        0xc60, 0x00000000,
        0xc64, 0x5116848b,
@@ -340,7 +340,7 @@ u32 RTL8192CUPHY_REG_1TARRAY[RTL8192CUPHY_REG_1TARRAY_LENGTH] = {
        0xce4, 0x00000000,
        0xce8, 0x37644302,
        0xcec, 0x2f97d40c,
-       0xd00, 0x00080740,
+       0xd00, 0x00000740,
        0xd04, 0x00020401,
        0xd08, 0x0000907f,
        0xd0c, 0x20010201,
@@ -633,17 +633,17 @@ u32 RTL8192CURADIOA_2TARRAY[RTL8192CURADIOA_2TARRAYLENGTH] = {
        0x012, 0x00071000,
        0x012, 0x000b0000,
        0x012, 0x000fc000,
-       0x013, 0x000287af,
+       0x013, 0x000287b3,
        0x013, 0x000244b7,
        0x013, 0x000204ab,
        0x013, 0x0001c49f,
        0x013, 0x00018493,
-       0x013, 0x00014297,
-       0x013, 0x00010295,
-       0x013, 0x0000c298,
-       0x013, 0x0000819c,
-       0x013, 0x000040a8,
-       0x013, 0x0000001c,
+       0x013, 0x0001429b,
+       0x013, 0x00010299,
+       0x013, 0x0000c29c,
+       0x013, 0x000081a0,
+       0x013, 0x000040ac,
+       0x013, 0x00000020,
        0x014, 0x0001944c,
        0x014, 0x00059444,
        0x014, 0x0009944c,
@@ -932,10 +932,10 @@ u32 RTL8192CUMAC_2T_ARRAY[RTL8192CUMAC_2T_ARRAYLENGTH] = {
        0x608, 0x0000000e,
        0x609, 0x0000002a,
        0x652, 0x00000020,
-       0x63c, 0x0000000a,
-       0x63d, 0x0000000e,
-       0x63e, 0x0000000a,
-       0x63f, 0x0000000e,
+       0x63c, 0x00000008,
+       0x63d, 0x00000008,
+       0x63e, 0x0000000c,
+       0x63f, 0x0000000c,
        0x66e, 0x00000005,
        0x700, 0x00000021,
        0x701, 0x00000043,
index 8ed31744a0548467ad0536108b76e9fcfe0592da..4f083fc1d3607c41eb5a471f30ff04c3d234e557 100644 (file)
@@ -176,6 +176,7 @@ static void rtl_process_pwdb(struct ieee80211_hw *hw, struct rtl_stats *pstatus)
        struct rtl_sta_info *drv_priv = NULL;
        struct ieee80211_sta *sta = NULL;
        long undec_sm_pwdb;
+       long undec_sm_cck;
 
        rcu_read_lock();
        if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION)
@@ -185,12 +186,16 @@ static void rtl_process_pwdb(struct ieee80211_hw *hw, struct rtl_stats *pstatus)
        if (sta) {
                drv_priv = (struct rtl_sta_info *) sta->drv_priv;
                undec_sm_pwdb = drv_priv->rssi_stat.undec_sm_pwdb;
+               undec_sm_cck = drv_priv->rssi_stat.undec_sm_cck;
        } else {
                undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
+               undec_sm_cck = rtlpriv->dm.undec_sm_cck;
        }
 
        if (undec_sm_pwdb < 0)
                undec_sm_pwdb = pstatus->rx_pwdb_all;
+       if (undec_sm_cck < 0)
+               undec_sm_cck = pstatus->rx_pwdb_all;
        if (pstatus->rx_pwdb_all > (u32) undec_sm_pwdb) {
                undec_sm_pwdb = (((undec_sm_pwdb) *
                      (RX_SMOOTH_FACTOR - 1)) +
@@ -200,6 +205,15 @@ static void rtl_process_pwdb(struct ieee80211_hw *hw, struct rtl_stats *pstatus)
                undec_sm_pwdb = (((undec_sm_pwdb) * (RX_SMOOTH_FACTOR - 1)) +
                     (pstatus->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
        }
+       if (pstatus->rx_pwdb_all > (u32) undec_sm_cck) {
+               undec_sm_cck = (((undec_sm_pwdb) *
+                     (RX_SMOOTH_FACTOR - 1)) +
+                    (pstatus->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
+               undec_sm_cck = undec_sm_cck + 1;
+       } else {
+               undec_sm_pwdb = (((undec_sm_cck) * (RX_SMOOTH_FACTOR - 1)) +
+                    (pstatus->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
+       }
 
        if (sta) {
                drv_priv->rssi_stat.undec_sm_pwdb = undec_sm_pwdb;
index 6e2b5c5c83c8d21234ee013c802d7af317f6db8c..4933f02ce1d510cf94ef127b59ea025238ad9476 100644 (file)
@@ -475,14 +475,14 @@ static void _rtl_usb_rx_process_agg(struct ieee80211_hw *hw,
                        rtlpriv->stats.rxbytesunicast +=  skb->len;
                }
 
-               rtl_is_special_data(hw, skb, false);
-
                if (ieee80211_is_data(fc)) {
                        rtlpriv->cfg->ops->led_control(hw, LED_CTL_RX);
 
                        if (unicast)
                                rtlpriv->link_info.num_rx_inperiod++;
                }
+               /* static bcn for roaming */
+               rtl_beacon_statistic(hw, skb);
        }
 }
 
@@ -517,8 +517,6 @@ static void _rtl_usb_rx_process_noagg(struct ieee80211_hw *hw,
                        rtlpriv->stats.rxbytesunicast +=  skb->len;
                }
 
-               rtl_is_special_data(hw, skb, false);
-
                if (ieee80211_is_data(fc)) {
                        rtlpriv->cfg->ops->led_control(hw, LED_CTL_RX);
 
@@ -553,7 +551,7 @@ static void _rtl_rx_pre_process(struct ieee80211_hw *hw, struct sk_buff *skb)
        }
 }
 
-#define __RX_SKB_MAX_QUEUED    32
+#define __RX_SKB_MAX_QUEUED    64
 
 static void _rtl_rx_work(unsigned long param)
 {
index 0c65386fa30d5cecda61d9d4ca290b6577df2f59..8c647391bedf0f4bc5ef4fca39b7ca39a05e1483 100644 (file)
@@ -1033,6 +1033,7 @@ struct rtl_ht_agg {
 
 struct rssi_sta {
        long undec_sm_pwdb;
+       long undec_sm_cck;
 };
 
 struct rtl_tid_data {
@@ -1323,8 +1324,10 @@ struct fast_ant_training {
 struct rtl_dm {
        /*PHY status for Dynamic Management */
        long entry_min_undec_sm_pwdb;
+       long undec_sm_cck;
        long undec_sm_pwdb;     /*out dm */
        long entry_max_undec_sm_pwdb;
+       s32 ofdm_pkt_cnt;
        bool dm_initialgain_enable;
        bool dynamic_txpower_enable;
        bool current_turbo_edca;
@@ -1339,6 +1342,7 @@ struct rtl_dm {
        bool inform_fw_driverctrldm;
        bool current_mrc_switch;
        u8 txpowercount;
+       u8 powerindex_backup[6];
 
        u8 thermalvalue_rxgain;
        u8 thermalvalue_iqk;
@@ -1350,7 +1354,9 @@ struct rtl_dm {
        bool done_txpower;
        u8 dynamic_txhighpower_lvl;     /*Tx high power level */
        u8 dm_flag;             /*Indicate each dynamic mechanism's status. */
+       u8 dm_flag_tmp;
        u8 dm_type;
+       u8 dm_rssi_sel;
        u8 txpower_track_control;
        bool interrupt_migration;
        bool disable_tx_int;
@@ -1804,6 +1810,7 @@ struct rtl_hal_cfg {
        bool write_readback;
        char *name;
        char *fw_name;
+       char *alt_fw_name;
        struct rtl_hal_ops *ops;
        struct rtl_mod_params *mod_params;
        struct rtl_hal_usbint_cfg *usb_interface_cfg;
@@ -1948,6 +1955,7 @@ struct dig_t {
        u8 pre_ccastate;
        u8 cur_ccasate;
        u8 large_fa_hit;
+       u8 dig_dynamic_min;
        u8 forbidden_igi;
        u8 dig_state;
        u8 dig_highpwrstate;
@@ -2028,22 +2036,15 @@ struct rtl_priv {
        struct dig_t dm_digtable;
        struct ps_t dm_pstable;
 
-       /* section shared by individual drivers */
-       union {
-               struct {        /* data buffer pointer for USB reads */
-                       __le32 *usb_data;
-                       int usb_data_index;
-                       bool initialized;
-               };
-               struct {        /* section for 8723ae */
-                       bool reg_init;  /* true if regs saved */
-                       u32 reg_874;
-                       u32 reg_c70;
-                       u32 reg_85c;
-                       u32 reg_a74;
-                       bool bt_operation_on;
-               };
-       };
+       u32 reg_874;
+       u32 reg_c70;
+       u32 reg_85c;
+       u32 reg_a74;
+       bool reg_init;  /* true if regs saved */
+       bool bt_operation_on;
+       __le32 *usb_data;
+       int usb_data_index;
+       bool initialized;
        bool enter_ps;  /* true when entering PS */
        u8 rate_mask[5];
 
index db6430c1a08414650a894d3e8a6d41c57cba1711..374268d5ac6a70e97355269489538ad31d802cbb 100644 (file)
@@ -18,10 +18,8 @@ int wl1251_acx_frame_rates(struct wl1251 *wl, u8 ctrl_rate, u8 ctrl_mod,
        wl1251_debug(DEBUG_ACX, "acx frame rates");
 
        rates = kzalloc(sizeof(*rates), GFP_KERNEL);
-       if (!rates) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!rates)
+               return -ENOMEM;
 
        rates->tx_ctrl_frame_rate = ctrl_rate;
        rates->tx_ctrl_frame_mod = ctrl_mod;
@@ -49,10 +47,8 @@ int wl1251_acx_station_id(struct wl1251 *wl)
        wl1251_debug(DEBUG_ACX, "acx dot11_station_id");
 
        mac = kzalloc(sizeof(*mac), GFP_KERNEL);
-       if (!mac) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!mac)
+               return -ENOMEM;
 
        for (i = 0; i < ETH_ALEN; i++)
                mac->mac[i] = wl->mac_addr[ETH_ALEN - 1 - i];
@@ -74,10 +70,8 @@ int wl1251_acx_default_key(struct wl1251 *wl, u8 key_id)
        wl1251_debug(DEBUG_ACX, "acx dot11_default_key (%d)", key_id);
 
        default_key = kzalloc(sizeof(*default_key), GFP_KERNEL);
-       if (!default_key) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!default_key)
+               return -ENOMEM;
 
        default_key->id = key_id;
 
@@ -104,10 +98,8 @@ int wl1251_acx_wake_up_conditions(struct wl1251 *wl, u8 wake_up_event,
        wl1251_debug(DEBUG_ACX, "acx wake up conditions");
 
        wake_up = kzalloc(sizeof(*wake_up), GFP_KERNEL);
-       if (!wake_up) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!wake_up)
+               return -ENOMEM;
 
        wake_up->wake_up_event = wake_up_event;
        wake_up->listen_interval = listen_interval;
@@ -132,16 +124,13 @@ int wl1251_acx_sleep_auth(struct wl1251 *wl, u8 sleep_auth)
        wl1251_debug(DEBUG_ACX, "acx sleep auth");
 
        auth = kzalloc(sizeof(*auth), GFP_KERNEL);
-       if (!auth) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!auth)
+               return -ENOMEM;
 
        auth->sleep_auth = sleep_auth;
 
        ret = wl1251_cmd_configure(wl, ACX_SLEEP_AUTH, auth, sizeof(*auth));
 
-out:
        kfree(auth);
        return ret;
 }
@@ -154,10 +143,8 @@ int wl1251_acx_fw_version(struct wl1251 *wl, char *buf, size_t len)
        wl1251_debug(DEBUG_ACX, "acx fw rev");
 
        rev = kzalloc(sizeof(*rev), GFP_KERNEL);
-       if (!rev) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!rev)
+               return -ENOMEM;
 
        ret = wl1251_cmd_interrogate(wl, ACX_FW_REV, rev, sizeof(*rev));
        if (ret < 0) {
@@ -191,10 +178,8 @@ int wl1251_acx_tx_power(struct wl1251 *wl, int power)
                return -EINVAL;
 
        acx = kzalloc(sizeof(*acx), GFP_KERNEL);
-       if (!acx) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!acx)
+               return -ENOMEM;
 
        acx->current_tx_power = power * 10;
 
@@ -217,10 +202,8 @@ int wl1251_acx_feature_cfg(struct wl1251 *wl)
        wl1251_debug(DEBUG_ACX, "acx feature cfg");
 
        feature = kzalloc(sizeof(*feature), GFP_KERNEL);
-       if (!feature) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!feature)
+               return -ENOMEM;
 
        /* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */
        feature->data_flow_options = 0;
@@ -261,10 +244,8 @@ int wl1251_acx_data_path_params(struct wl1251 *wl,
        wl1251_debug(DEBUG_ACX, "acx data path params");
 
        params = kzalloc(sizeof(*params), GFP_KERNEL);
-       if (!params) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!params)
+               return -ENOMEM;
 
        params->rx_packet_ring_chunk_size = DP_RX_PACKET_RING_CHUNK_SIZE;
        params->tx_packet_ring_chunk_size = DP_TX_PACKET_RING_CHUNK_SIZE;
@@ -309,10 +290,8 @@ int wl1251_acx_rx_msdu_life_time(struct wl1251 *wl, u32 life_time)
        wl1251_debug(DEBUG_ACX, "acx rx msdu life time");
 
        acx = kzalloc(sizeof(*acx), GFP_KERNEL);
-       if (!acx) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!acx)
+               return -ENOMEM;
 
        acx->lifetime = life_time;
        ret = wl1251_cmd_configure(wl, DOT11_RX_MSDU_LIFE_TIME,
@@ -335,10 +314,8 @@ int wl1251_acx_rx_config(struct wl1251 *wl, u32 config, u32 filter)
        wl1251_debug(DEBUG_ACX, "acx rx config");
 
        rx_config = kzalloc(sizeof(*rx_config), GFP_KERNEL);
-       if (!rx_config) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!rx_config)
+               return -ENOMEM;
 
        rx_config->config_options = config;
        rx_config->filter_options = filter;
@@ -363,10 +340,8 @@ int wl1251_acx_pd_threshold(struct wl1251 *wl)
        wl1251_debug(DEBUG_ACX, "acx data pd threshold");
 
        pd = kzalloc(sizeof(*pd), GFP_KERNEL);
-       if (!pd) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!pd)
+               return -ENOMEM;
 
        /* FIXME: threshold value not set */
 
@@ -389,10 +364,8 @@ int wl1251_acx_slot(struct wl1251 *wl, enum acx_slot_type slot_time)
        wl1251_debug(DEBUG_ACX, "acx slot");
 
        slot = kzalloc(sizeof(*slot), GFP_KERNEL);
-       if (!slot) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!slot)
+               return -ENOMEM;
 
        slot->wone_index = STATION_WONE_INDEX;
        slot->slot_time = slot_time;
@@ -416,10 +389,8 @@ int wl1251_acx_group_address_tbl(struct wl1251 *wl)
        wl1251_debug(DEBUG_ACX, "acx group address tbl");
 
        acx = kzalloc(sizeof(*acx), GFP_KERNEL);
-       if (!acx) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!acx)
+               return -ENOMEM;
 
        /* MAC filtering */
        acx->enabled = 0;
@@ -444,10 +415,8 @@ int wl1251_acx_service_period_timeout(struct wl1251 *wl)
        int ret;
 
        rx_timeout = kzalloc(sizeof(*rx_timeout), GFP_KERNEL);
-       if (!rx_timeout) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!rx_timeout)
+               return -ENOMEM;
 
        wl1251_debug(DEBUG_ACX, "acx service period timeout");
 
@@ -475,10 +444,8 @@ int wl1251_acx_rts_threshold(struct wl1251 *wl, u16 rts_threshold)
        wl1251_debug(DEBUG_ACX, "acx rts threshold");
 
        rts = kzalloc(sizeof(*rts), GFP_KERNEL);
-       if (!rts) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!rts)
+               return -ENOMEM;
 
        rts->threshold = rts_threshold;
 
@@ -501,10 +468,8 @@ int wl1251_acx_beacon_filter_opt(struct wl1251 *wl, bool enable_filter)
        wl1251_debug(DEBUG_ACX, "acx beacon filter opt");
 
        beacon_filter = kzalloc(sizeof(*beacon_filter), GFP_KERNEL);
-       if (!beacon_filter) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!beacon_filter)
+               return -ENOMEM;
 
        beacon_filter->enable = enable_filter;
        beacon_filter->max_num_beacons = 0;
@@ -530,10 +495,8 @@ int wl1251_acx_beacon_filter_table(struct wl1251 *wl)
        wl1251_debug(DEBUG_ACX, "acx beacon filter table");
 
        ie_table = kzalloc(sizeof(*ie_table), GFP_KERNEL);
-       if (!ie_table) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!ie_table)
+               return -ENOMEM;
 
        /* configure default beacon pass-through rules */
        ie_table->num_ie = 1;
@@ -560,10 +523,8 @@ int wl1251_acx_conn_monit_params(struct wl1251 *wl)
        wl1251_debug(DEBUG_ACX, "acx connection monitor parameters");
 
        acx = kzalloc(sizeof(*acx), GFP_KERNEL);
-       if (!acx) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!acx)
+               return -ENOMEM;
 
        acx->synch_fail_thold = SYNCH_FAIL_DEFAULT_THRESHOLD;
        acx->bss_lose_timeout = NO_BEACON_DEFAULT_TIMEOUT;
@@ -589,10 +550,8 @@ int wl1251_acx_sg_enable(struct wl1251 *wl)
        wl1251_debug(DEBUG_ACX, "acx sg enable");
 
        pta = kzalloc(sizeof(*pta), GFP_KERNEL);
-       if (!pta) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!pta)
+               return -ENOMEM;
 
        pta->enable = SG_ENABLE;
 
@@ -615,10 +574,8 @@ int wl1251_acx_sg_cfg(struct wl1251 *wl)
        wl1251_debug(DEBUG_ACX, "acx sg cfg");
 
        param = kzalloc(sizeof(*param), GFP_KERNEL);
-       if (!param) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!param)
+               return -ENOMEM;
 
        /* BT-WLAN coext parameters */
        param->min_rate = RATE_INDEX_24MBPS;
@@ -669,10 +626,8 @@ int wl1251_acx_cca_threshold(struct wl1251 *wl)
        wl1251_debug(DEBUG_ACX, "acx cca threshold");
 
        detection = kzalloc(sizeof(*detection), GFP_KERNEL);
-       if (!detection) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!detection)
+               return -ENOMEM;
 
        detection->rx_cca_threshold = CCA_THRSH_DISABLE_ENERGY_D;
        detection->tx_energy_detection = 0;
@@ -682,7 +637,6 @@ int wl1251_acx_cca_threshold(struct wl1251 *wl)
        if (ret < 0)
                wl1251_warning("failed to set cca threshold: %d", ret);
 
-out:
        kfree(detection);
        return ret;
 }
@@ -695,10 +649,8 @@ int wl1251_acx_bcn_dtim_options(struct wl1251 *wl)
        wl1251_debug(DEBUG_ACX, "acx bcn dtim options");
 
        bb = kzalloc(sizeof(*bb), GFP_KERNEL);
-       if (!bb) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!bb)
+               return -ENOMEM;
 
        bb->beacon_rx_timeout = BCN_RX_TIMEOUT_DEF_VALUE;
        bb->broadcast_timeout = BROADCAST_RX_TIMEOUT_DEF_VALUE;
@@ -724,10 +676,8 @@ int wl1251_acx_aid(struct wl1251 *wl, u16 aid)
        wl1251_debug(DEBUG_ACX, "acx aid");
 
        acx_aid = kzalloc(sizeof(*acx_aid), GFP_KERNEL);
-       if (!acx_aid) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!acx_aid)
+               return -ENOMEM;
 
        acx_aid->aid = aid;
 
@@ -750,10 +700,8 @@ int wl1251_acx_event_mbox_mask(struct wl1251 *wl, u32 event_mask)
        wl1251_debug(DEBUG_ACX, "acx event mbox mask");
 
        mask = kzalloc(sizeof(*mask), GFP_KERNEL);
-       if (!mask) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!mask)
+               return -ENOMEM;
 
        /* high event mask is unused */
        mask->high_event_mask = 0xffffffff;
@@ -805,10 +753,8 @@ int wl1251_acx_set_preamble(struct wl1251 *wl, enum acx_preamble_type preamble)
        wl1251_debug(DEBUG_ACX, "acx_set_preamble");
 
        acx = kzalloc(sizeof(*acx), GFP_KERNEL);
-       if (!acx) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!acx)
+               return -ENOMEM;
 
        acx->preamble = preamble;
 
@@ -832,10 +778,8 @@ int wl1251_acx_cts_protect(struct wl1251 *wl,
        wl1251_debug(DEBUG_ACX, "acx_set_ctsprotect");
 
        acx = kzalloc(sizeof(*acx), GFP_KERNEL);
-       if (!acx) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!acx)
+               return -ENOMEM;
 
        acx->ctsprotect = ctsprotect;
 
@@ -856,10 +800,8 @@ int wl1251_acx_tsf_info(struct wl1251 *wl, u64 *mactime)
        int ret;
 
        tsf_info = kzalloc(sizeof(*tsf_info), GFP_KERNEL);
-       if (!tsf_info) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!tsf_info)
+               return -ENOMEM;
 
        ret = wl1251_cmd_interrogate(wl, ACX_TSF_INFO,
                                     tsf_info, sizeof(*tsf_info));
@@ -900,11 +842,8 @@ int wl1251_acx_rate_policies(struct wl1251 *wl)
        wl1251_debug(DEBUG_ACX, "acx rate policies");
 
        acx = kzalloc(sizeof(*acx), GFP_KERNEL);
-
-       if (!acx) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!acx)
+               return -ENOMEM;
 
        /* configure one default (one-size-fits-all) rate class */
        acx->rate_class_cnt = 1;
@@ -932,10 +871,8 @@ int wl1251_acx_mem_cfg(struct wl1251 *wl)
        wl1251_debug(DEBUG_ACX, "acx mem cfg");
 
        mem_conf = kzalloc(sizeof(*mem_conf), GFP_KERNEL);
-       if (!mem_conf) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!mem_conf)
+               return -ENOMEM;
 
        /* memory config */
        mem_conf->mem_config.num_stations = cpu_to_le16(DEFAULT_NUM_STATIONS);
@@ -979,10 +916,8 @@ int wl1251_acx_wr_tbtt_and_dtim(struct wl1251 *wl, u16 tbtt, u8 dtim)
        wl1251_debug(DEBUG_ACX, "acx tbtt and dtim");
 
        acx = kzalloc(sizeof(*acx), GFP_KERNEL);
-       if (!acx) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!acx)
+               return -ENOMEM;
 
        acx->tbtt = tbtt;
        acx->dtim = dtim;
@@ -1008,10 +943,8 @@ int wl1251_acx_bet_enable(struct wl1251 *wl, enum wl1251_acx_bet_mode mode,
        wl1251_debug(DEBUG_ACX, "acx bet enable");
 
        acx = kzalloc(sizeof(*acx), GFP_KERNEL);
-       if (!acx) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!acx)
+               return -ENOMEM;
 
        acx->enable = mode;
        acx->max_consecutive = max_consecutive;
@@ -1037,11 +970,8 @@ int wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max,
                     "aifs %d txop %d", ac, cw_min, cw_max, aifs, txop);
 
        acx = kzalloc(sizeof(*acx), GFP_KERNEL);
-
-       if (!acx) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!acx)
+               return -ENOMEM;
 
        acx->ac = ac;
        acx->cw_min = cw_min;
@@ -1073,11 +1003,8 @@ int wl1251_acx_tid_cfg(struct wl1251 *wl, u8 queue,
                     ps_scheme, ack_policy);
 
        acx = kzalloc(sizeof(*acx), GFP_KERNEL);
-
-       if (!acx) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!acx)
+               return -ENOMEM;
 
        acx->queue = queue;
        acx->type = type;
index 4a0bbb13806bd6fd61266c729f4a433d110ac838..7541bd1a4a4b40de9b6be249dea94ca8f95e96ae 100644 (file)
@@ -47,7 +47,7 @@ static int wl1271_get_scan_channels(struct wl1271 *wl,
                     * In active scans, we only scan channels not
                     * marked as passive.
                     */
-                   (passive || !(flags & IEEE80211_CHAN_PASSIVE_SCAN))) {
+                   (passive || !(flags & IEEE80211_CHAN_NO_IR))) {
                        wl1271_debug(DEBUG_SCAN, "band %d, center_freq %d ",
                                     req->channels[i]->band,
                                     req->channels[i]->center_freq);
index 34d9dfff2ad39ead03d3da275cd3e4443385a220..9b2ecf52449faa911f25bea176ed12683fe1836e 100644 (file)
@@ -1688,7 +1688,7 @@ int wlcore_cmd_regdomain_config_locked(struct wl1271 *wl)
 
                        if (channel->flags & (IEEE80211_CHAN_DISABLED |
                                              IEEE80211_CHAN_RADAR |
-                                             IEEE80211_CHAN_PASSIVE_SCAN))
+                                             IEEE80211_CHAN_NO_IR))
                                continue;
 
                        ch_bit_idx = wlcore_get_reg_conf_ch_idx(b, ch);
index 0368b9cbfb896d6460da3635b199ef6266805644..e9da47cead587704c7060ebd8ab754c1aa7da16b 100644 (file)
@@ -91,8 +91,7 @@ static void wl1271_reg_notify(struct wiphy *wiphy,
                        continue;
 
                if (ch->flags & IEEE80211_CHAN_RADAR)
-                       ch->flags |= IEEE80211_CHAN_NO_IBSS |
-                                    IEEE80211_CHAN_PASSIVE_SCAN;
+                       ch->flags |= IEEE80211_CHAN_NO_IR;
 
        }
 
index 7ed86203304b700c87e4b1ca48de127f7466420f..1e3d51cd673ab6d2be132c6fda17f698547b3ff7 100644 (file)
@@ -188,16 +188,14 @@ wlcore_scan_get_channels(struct wl1271 *wl,
                flags = req_channels[i]->flags;
 
                if (force_passive)
-                       flags |= IEEE80211_CHAN_PASSIVE_SCAN;
+                       flags |= IEEE80211_CHAN_NO_IR;
 
                if ((req_channels[i]->band == band) &&
                    !(flags & IEEE80211_CHAN_DISABLED) &&
                    (!!(flags & IEEE80211_CHAN_RADAR) == radar) &&
                    /* if radar is set, we ignore the passive flag */
                    (radar ||
-                    !!(flags & IEEE80211_CHAN_PASSIVE_SCAN) == passive)) {
-
-
+                    !!(flags & IEEE80211_CHAN_NO_IR) == passive)) {
                        if (flags & IEEE80211_CHAN_RADAR) {
                                channels[j].flags |= SCAN_CHANNEL_FLAGS_DFS;
 
@@ -220,7 +218,7 @@ wlcore_scan_get_channels(struct wl1271 *wl,
                            (band == IEEE80211_BAND_2GHZ) &&
                            (channels[j].channel >= 12) &&
                            (channels[j].channel <= 14) &&
-                           (flags & IEEE80211_CHAN_PASSIVE_SCAN) &&
+                           (flags & IEEE80211_CHAN_NO_IR) &&
                            !force_passive) {
                                /* pactive channels treated as DFS */
                                channels[j].flags = SCAN_CHANNEL_FLAGS_DFS;
@@ -243,8 +241,8 @@ wlcore_scan_get_channels(struct wl1271 *wl,
                                     max_dwell_time_active,
                                     flags & IEEE80211_CHAN_RADAR ?
                                        ", DFS" : "",
-                                    flags & IEEE80211_CHAN_PASSIVE_SCAN ?
-                                       ", PASSIVE" : "");
+                                    flags & IEEE80211_CHAN_NO_IR ?
+                                       ", NO-IR" : "");
                        j++;
                }
        }
index 71ab320fae821a34b5afc4917f6915248c10fdd6..73a49b868035ee26b18924ab7d48c06bd967add7 100644 (file)
@@ -14,8 +14,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /* This file implements all the hardware specific functions for the ZD1211
index 7ab922209b25940e6716319f7c2d9ebca8acf812..b03786c9f3aa9d0833337daa62ed4ed0344e9564 100644 (file)
@@ -14,8 +14,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef _ZD_CHIP_H
index 9a1b013f81be65151004c5b6ffad6422423e75bd..41bd755bc1353cb54b3dbe1d56e38777fc39b6e2 100644 (file)
@@ -14,8 +14,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef _ZD_DEF_H
index c6208a7988e4736c54883e2fab67bdb1fd85d514..eff79a37bc2aa2faa5ae35891dd84de560ee8da3 100644 (file)
@@ -16,8 +16,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/netdevice.h>
index c01eca859f95cd5c554f51bc28b3e7da9bbb45e4..5a484235308f15420571052373890fc05710f8e9 100644 (file)
@@ -14,8 +14,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef _ZD_MAC_H
index c875ee05e22e056c0f4886d1e2c2e2b1baa313bf..dc179c414518b84b8d201469264819ef87e02024 100644 (file)
@@ -14,8 +14,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/errno.h>
index 725b7c99b23d0973014213c504148adff94b89ee..8f14e25e1041b875b25b8267829aac11542eb6c3 100644 (file)
@@ -14,8 +14,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef _ZD_RF_H
index 12babcb633c3934b4b0bb5d2f23d83230b592b1f..99aed7d789525050f9df16a52a003e22e3b3acb0 100644 (file)
@@ -14,8 +14,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/kernel.h>
index 385c670d1293c82f5f3e38c1febed67626d074f5..5fea485be574ff65716e76deff85839dd163daf7 100644 (file)
@@ -14,8 +14,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/kernel.h>
index 784d9ccb8fef3839ba977fe83e44789ffc74356e..a93f657a41c74c32d6cf0efd5fe1ce1f0cc26b80 100644 (file)
@@ -14,8 +14,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/kernel.h>
index c4d324e19c24b69cf1ca2a8e7a9ba08962fbf481..61b9240273565814800da2ef707a71cdd64b6e1c 100644 (file)
@@ -14,8 +14,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/kernel.h>
index 84d94f572a463b294ed542476eb22e922eab81b9..a912dc051111973367d7b4056f5c793004885f6d 100644 (file)
@@ -15,8 +15,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/kernel.h>
index 45e3bb28a01ceaec1eeddf135010e71a05b5a37c..a9075f2251782056ecc3421471bc8300002370f5 100644 (file)
@@ -14,8 +14,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef _ZD_USB_H
index 08ae01b41c832d7144bdeceb70b976adaf281d4c..ba30a6d9fefabf225631b731a1ce0fc73ea7653d 100644 (file)
@@ -136,12 +136,10 @@ struct xenvif {
        char rx_irq_name[IFNAMSIZ+4]; /* DEVNAME-rx */
        struct xen_netif_rx_back_ring rx;
        struct sk_buff_head rx_queue;
-
-       /* Allow xenvif_start_xmit() to peek ahead in the rx request
-        * ring.  This is a prediction of what rx_req_cons will be
-        * once all queued skbs are put on the ring.
+       /* Set when the RX interrupt is triggered by the frontend.
+        * The worker thread may need to wake the queue.
         */
-       RING_IDX rx_req_cons_peek;
+       bool rx_event;
 
        /* Given MAX_BUFFER_OFFSET of 4096 the worst case is that each
         * head/fragment page uses 2 copy operations because it
@@ -198,8 +196,6 @@ void xenvif_xenbus_fini(void);
 
 int xenvif_schedulable(struct xenvif *vif);
 
-int xenvif_rx_ring_full(struct xenvif *vif);
-
 int xenvif_must_stop_queue(struct xenvif *vif);
 
 /* (Un)Map communication rings. */
@@ -211,21 +207,20 @@ int xenvif_map_frontend_rings(struct xenvif *vif,
 /* Check for SKBs from frontend and schedule backend processing */
 void xenvif_check_rx_xenvif(struct xenvif *vif);
 
-/* Queue an SKB for transmission to the frontend */
-void xenvif_queue_tx_skb(struct xenvif *vif, struct sk_buff *skb);
-/* Notify xenvif that ring now has space to send an skb to the frontend */
-void xenvif_notify_tx_completion(struct xenvif *vif);
-
 /* Prevent the device from generating any further traffic. */
 void xenvif_carrier_off(struct xenvif *vif);
 
-/* Returns number of ring slots required to send an skb to the frontend */
-unsigned int xenvif_count_skb_slots(struct xenvif *vif, struct sk_buff *skb);
-
 int xenvif_tx_action(struct xenvif *vif, int budget);
-void xenvif_rx_action(struct xenvif *vif);
 
 int xenvif_kthread(void *data);
+void xenvif_kick_thread(struct xenvif *vif);
+
+/* Determine whether the needed number of slots (req) are available,
+ * and set req_event if not.
+ */
+bool xenvif_rx_ring_slots_available(struct xenvif *vif, int needed);
+
+void xenvif_stop_queue(struct xenvif *vif);
 
 extern bool separate_tx_rx_irq;
 
index 2329cccf1fa6dd15f65c4dc30c54c62cce0551a7..1dcb9606e6e08f0ab1ac059d51d24b8833415a49 100644 (file)
@@ -46,11 +46,6 @@ int xenvif_schedulable(struct xenvif *vif)
        return netif_running(vif->dev) && netif_carrier_ok(vif->dev);
 }
 
-static int xenvif_rx_schedulable(struct xenvif *vif)
-{
-       return xenvif_schedulable(vif) && !xenvif_rx_ring_full(vif);
-}
-
 static irqreturn_t xenvif_tx_interrupt(int irq, void *dev_id)
 {
        struct xenvif *vif = dev_id;
@@ -104,8 +99,8 @@ static irqreturn_t xenvif_rx_interrupt(int irq, void *dev_id)
 {
        struct xenvif *vif = dev_id;
 
-       if (xenvif_rx_schedulable(vif))
-               netif_wake_queue(vif->dev);
+       vif->rx_event = true;
+       xenvif_kick_thread(vif);
 
        return IRQ_HANDLED;
 }
@@ -121,24 +116,35 @@ static irqreturn_t xenvif_interrupt(int irq, void *dev_id)
 static int xenvif_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct xenvif *vif = netdev_priv(dev);
+       int min_slots_needed;
 
        BUG_ON(skb->dev != dev);
 
        /* Drop the packet if vif is not ready */
-       if (vif->task == NULL)
+       if (vif->task == NULL || !xenvif_schedulable(vif))
                goto drop;
 
-       /* Drop the packet if the target domain has no receive buffers. */
-       if (!xenvif_rx_schedulable(vif))
-               goto drop;
+       /* At best we'll need one slot for the header and one for each
+        * frag.
+        */
+       min_slots_needed = 1 + skb_shinfo(skb)->nr_frags;
 
-       /* Reserve ring slots for the worst-case number of fragments. */
-       vif->rx_req_cons_peek += xenvif_count_skb_slots(vif, skb);
+       /* If the skb is GSO then we'll also need an extra slot for the
+        * metadata.
+        */
+       if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4 ||
+           skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
+               min_slots_needed++;
 
-       if (vif->can_queue && xenvif_must_stop_queue(vif))
-               netif_stop_queue(dev);
+       /* If the skb can't possibly fit in the remaining slots
+        * then turn off the queue to give the ring a chance to
+        * drain.
+        */
+       if (!xenvif_rx_ring_slots_available(vif, min_slots_needed))
+               xenvif_stop_queue(vif);
 
-       xenvif_queue_tx_skb(vif, skb);
+       skb_queue_tail(&vif->rx_queue, skb);
+       xenvif_kick_thread(vif);
 
        return NETDEV_TX_OK;
 
@@ -148,12 +154,6 @@ static int xenvif_start_xmit(struct sk_buff *skb, struct net_device *dev)
        return NETDEV_TX_OK;
 }
 
-void xenvif_notify_tx_completion(struct xenvif *vif)
-{
-       if (netif_queue_stopped(vif->dev) && xenvif_rx_schedulable(vif))
-               netif_wake_queue(vif->dev);
-}
-
 static struct net_device_stats *xenvif_get_stats(struct net_device *dev)
 {
        struct xenvif *vif = netdev_priv(dev);
@@ -368,16 +368,18 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref,
                   unsigned long rx_ring_ref, unsigned int tx_evtchn,
                   unsigned int rx_evtchn)
 {
+       struct task_struct *task;
        int err = -ENOMEM;
 
-       /* Already connected through? */
-       if (vif->tx_irq)
-               return 0;
+       BUG_ON(vif->tx_irq);
+       BUG_ON(vif->task);
 
        err = xenvif_map_frontend_rings(vif, tx_ring_ref, rx_ring_ref);
        if (err < 0)
                goto err;
 
+       init_waitqueue_head(&vif->wq);
+
        if (tx_evtchn == rx_evtchn) {
                /* feature-split-event-channels == 0 */
                err = bind_interdomain_evtchn_to_irqhandler(
@@ -410,15 +412,16 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref,
                disable_irq(vif->rx_irq);
        }
 
-       init_waitqueue_head(&vif->wq);
-       vif->task = kthread_create(xenvif_kthread,
-                                  (void *)vif, "%s", vif->dev->name);
-       if (IS_ERR(vif->task)) {
+       task = kthread_create(xenvif_kthread,
+                             (void *)vif, "%s", vif->dev->name);
+       if (IS_ERR(task)) {
                pr_warn("Could not allocate kthread for %s\n", vif->dev->name);
-               err = PTR_ERR(vif->task);
+               err = PTR_ERR(task);
                goto err_rx_unbind;
        }
 
+       vif->task = task;
+
        rtnl_lock();
        if (!vif->can_sg && vif->dev->mtu > ETH_DATA_LEN)
                dev_set_mtu(vif->dev, ETH_DATA_LEN);
@@ -461,8 +464,10 @@ void xenvif_disconnect(struct xenvif *vif)
        if (netif_carrier_ok(vif->dev))
                xenvif_carrier_off(vif);
 
-       if (vif->task)
+       if (vif->task) {
                kthread_stop(vif->task);
+               vif->task = NULL;
+       }
 
        if (vif->tx_irq) {
                if (vif->tx_irq == vif->rx_irq)
index 919b6509455cfbaf45ba63c7d8b378fa13a8e758..07f00b8bce8e79e1acb6c47cb4f18bfc17b52cd9 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/udp.h>
 
 #include <net/tcp.h>
+#include <net/ip6_checksum.h>
 
 #include <xen/xen.h>
 #include <xen/events.h>
@@ -137,36 +138,26 @@ static inline pending_ring_idx_t nr_pending_reqs(struct xenvif *vif)
                vif->pending_prod + vif->pending_cons;
 }
 
-static int max_required_rx_slots(struct xenvif *vif)
+bool xenvif_rx_ring_slots_available(struct xenvif *vif, int needed)
 {
-       int max = DIV_ROUND_UP(vif->dev->mtu, PAGE_SIZE);
+       RING_IDX prod, cons;
 
-       /* XXX FIXME: RX path dependent on MAX_SKB_FRAGS */
-       if (vif->can_sg || vif->gso_mask || vif->gso_prefix_mask)
-               max += MAX_SKB_FRAGS + 1; /* extra_info + frags */
+       do {
+               prod = vif->rx.sring->req_prod;
+               cons = vif->rx.req_cons;
 
-       return max;
-}
+               if (prod - cons >= needed)
+                       return true;
 
-int xenvif_rx_ring_full(struct xenvif *vif)
-{
-       RING_IDX peek   = vif->rx_req_cons_peek;
-       RING_IDX needed = max_required_rx_slots(vif);
-
-       return ((vif->rx.sring->req_prod - peek) < needed) ||
-              ((vif->rx.rsp_prod_pvt + XEN_NETIF_RX_RING_SIZE - peek) < needed);
-}
+               vif->rx.sring->req_event = prod + 1;
 
-int xenvif_must_stop_queue(struct xenvif *vif)
-{
-       if (!xenvif_rx_ring_full(vif))
-               return 0;
-
-       vif->rx.sring->req_event = vif->rx_req_cons_peek +
-               max_required_rx_slots(vif);
-       mb(); /* request notification /then/ check the queue */
+               /* Make sure event is visible before we check prod
+                * again.
+                */
+               mb();
+       } while (vif->rx.sring->req_prod != prod);
 
-       return xenvif_rx_ring_full(vif);
+       return false;
 }
 
 /*
@@ -209,93 +200,6 @@ static bool start_new_rx_buffer(int offset, unsigned long size, int head)
        return false;
 }
 
-struct xenvif_count_slot_state {
-       unsigned long copy_off;
-       bool head;
-};
-
-unsigned int xenvif_count_frag_slots(struct xenvif *vif,
-                                    unsigned long offset, unsigned long size,
-                                    struct xenvif_count_slot_state *state)
-{
-       unsigned count = 0;
-
-       offset &= ~PAGE_MASK;
-
-       while (size > 0) {
-               unsigned long bytes;
-
-               bytes = PAGE_SIZE - offset;
-
-               if (bytes > size)
-                       bytes = size;
-
-               if (start_new_rx_buffer(state->copy_off, bytes, state->head)) {
-                       count++;
-                       state->copy_off = 0;
-               }
-
-               if (state->copy_off + bytes > MAX_BUFFER_OFFSET)
-                       bytes = MAX_BUFFER_OFFSET - state->copy_off;
-
-               state->copy_off += bytes;
-
-               offset += bytes;
-               size -= bytes;
-
-               if (offset == PAGE_SIZE)
-                       offset = 0;
-
-               state->head = false;
-       }
-
-       return count;
-}
-
-/*
- * Figure out how many ring slots we're going to need to send @skb to
- * the guest. This function is essentially a dry run of
- * xenvif_gop_frag_copy.
- */
-unsigned int xenvif_count_skb_slots(struct xenvif *vif, struct sk_buff *skb)
-{
-       struct xenvif_count_slot_state state;
-       unsigned int count;
-       unsigned char *data;
-       unsigned i;
-
-       state.head = true;
-       state.copy_off = 0;
-
-       /* Slot for the first (partial) page of data. */
-       count = 1;
-
-       /* Need a slot for the GSO prefix for GSO extra data? */
-       if (skb_shinfo(skb)->gso_size)
-               count++;
-
-       data = skb->data;
-       while (data < skb_tail_pointer(skb)) {
-               unsigned long offset = offset_in_page(data);
-               unsigned long size = PAGE_SIZE - offset;
-
-               if (data + size > skb_tail_pointer(skb))
-                       size = skb_tail_pointer(skb) - data;
-
-               count += xenvif_count_frag_slots(vif, offset, size, &state);
-
-               data += size;
-       }
-
-       for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-               unsigned long size = skb_frag_size(&skb_shinfo(skb)->frags[i]);
-               unsigned long offset = skb_shinfo(skb)->frags[i].page_offset;
-
-               count += xenvif_count_frag_slots(vif, offset, size, &state);
-       }
-       return count;
-}
-
 struct netrx_pending_operations {
        unsigned copy_prod, copy_cons;
        unsigned meta_prod, meta_cons;
@@ -556,12 +460,12 @@ struct skb_cb_overlay {
        int meta_slots_used;
 };
 
-static void xenvif_kick_thread(struct xenvif *vif)
+void xenvif_kick_thread(struct xenvif *vif)
 {
        wake_up(&vif->wq);
 }
 
-void xenvif_rx_action(struct xenvif *vif)
+static void xenvif_rx_action(struct xenvif *vif)
 {
        s8 status;
        u16 flags;
@@ -570,8 +474,6 @@ void xenvif_rx_action(struct xenvif *vif)
        struct sk_buff *skb;
        LIST_HEAD(notify);
        int ret;
-       int nr_frags;
-       int count;
        unsigned long offset;
        struct skb_cb_overlay *sco;
        int need_to_notify = 0;
@@ -583,29 +485,44 @@ void xenvif_rx_action(struct xenvif *vif)
 
        skb_queue_head_init(&rxq);
 
-       count = 0;
-
        while ((skb = skb_dequeue(&vif->rx_queue)) != NULL) {
-               vif = netdev_priv(skb->dev);
-               nr_frags = skb_shinfo(skb)->nr_frags;
+               int max_slots_needed;
+               int i;
+
+               /* We need a cheap worse case estimate for the number of
+                * slots we'll use.
+                */
+
+               max_slots_needed = DIV_ROUND_UP(offset_in_page(skb->data) +
+                                               skb_headlen(skb),
+                                               PAGE_SIZE);
+               for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+                       unsigned int size;
+                       size = skb_frag_size(&skb_shinfo(skb)->frags[i]);
+                       max_slots_needed += DIV_ROUND_UP(size, PAGE_SIZE);
+               }
+               if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4 ||
+                   skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
+                       max_slots_needed++;
+
+               /* If the skb may not fit then bail out now */
+               if (!xenvif_rx_ring_slots_available(vif, max_slots_needed)) {
+                       skb_queue_head(&vif->rx_queue, skb);
+                       need_to_notify = 1;
+                       break;
+               }
 
                sco = (struct skb_cb_overlay *)skb->cb;
                sco->meta_slots_used = xenvif_gop_skb(skb, &npo);
-
-               count += nr_frags + 1;
+               BUG_ON(sco->meta_slots_used > max_slots_needed);
 
                __skb_queue_tail(&rxq, skb);
-
-               /* Filled the batch queue? */
-               /* XXX FIXME: RX path dependent on MAX_SKB_FRAGS */
-               if (count + MAX_SKB_FRAGS >= XEN_NETIF_RX_RING_SIZE)
-                       break;
        }
 
        BUG_ON(npo.meta_prod > ARRAY_SIZE(vif->meta));
 
        if (!npo.copy_prod)
-               return;
+               goto done;
 
        BUG_ON(npo.copy_prod > ARRAY_SIZE(vif->grant_copy_op));
        gnttab_batch_copy(vif->grant_copy_op, npo.copy_prod);
@@ -613,8 +530,6 @@ void xenvif_rx_action(struct xenvif *vif)
        while ((skb = __skb_dequeue(&rxq)) != NULL) {
                sco = (struct skb_cb_overlay *)skb->cb;
 
-               vif = netdev_priv(skb->dev);
-
                if ((1 << vif->meta[npo.meta_cons].gso_type) &
                    vif->gso_prefix_mask) {
                        resp = RING_GET_RESPONSE(&vif->rx,
@@ -680,25 +595,13 @@ void xenvif_rx_action(struct xenvif *vif)
                if (ret)
                        need_to_notify = 1;
 
-               xenvif_notify_tx_completion(vif);
-
                npo.meta_cons += sco->meta_slots_used;
                dev_kfree_skb(skb);
        }
 
+done:
        if (need_to_notify)
                notify_remote_via_irq(vif->rx_irq);
-
-       /* More work to do? */
-       if (!skb_queue_empty(&vif->rx_queue))
-               xenvif_kick_thread(vif);
-}
-
-void xenvif_queue_tx_skb(struct xenvif *vif, struct sk_buff *skb)
-{
-       skb_queue_tail(&vif->rx_queue, skb);
-
-       xenvif_kick_thread(vif);
 }
 
 void xenvif_check_rx_xenvif(struct xenvif *vif)
@@ -1148,75 +1051,92 @@ static int xenvif_set_skb_gso(struct xenvif *vif,
        return 0;
 }
 
-static inline void maybe_pull_tail(struct sk_buff *skb, unsigned int len)
+static inline int maybe_pull_tail(struct sk_buff *skb, unsigned int len,
+                                 unsigned int max)
 {
-       if (skb_is_nonlinear(skb) && skb_headlen(skb) < len) {
-               /* If we need to pullup then pullup to the max, so we
-                * won't need to do it again.
-                */
-               int target = min_t(int, skb->len, MAX_TCP_HEADER);
-               __pskb_pull_tail(skb, target - skb_headlen(skb));
-       }
+       if (skb_headlen(skb) >= len)
+               return 0;
+
+       /* If we need to pullup then pullup to the max, so we
+        * won't need to do it again.
+        */
+       if (max > skb->len)
+               max = skb->len;
+
+       if (__pskb_pull_tail(skb, max - skb_headlen(skb)) == NULL)
+               return -ENOMEM;
+
+       if (skb_headlen(skb) < len)
+               return -EPROTO;
+
+       return 0;
 }
 
+/* This value should be large enough to cover a tagged ethernet header plus
+ * maximally sized IP and TCP or UDP headers.
+ */
+#define MAX_IP_HDR_LEN 128
+
 static int checksum_setup_ip(struct xenvif *vif, struct sk_buff *skb,
                             int recalculate_partial_csum)
 {
-       struct iphdr *iph = (void *)skb->data;
-       unsigned int header_size;
        unsigned int off;
-       int err = -EPROTO;
+       bool fragment;
+       int err;
+
+       fragment = false;
 
-       off = sizeof(struct iphdr);
+       err = maybe_pull_tail(skb,
+                             sizeof(struct iphdr),
+                             MAX_IP_HDR_LEN);
+       if (err < 0)
+               goto out;
+
+       if (ip_hdr(skb)->frag_off & htons(IP_OFFSET | IP_MF))
+               fragment = true;
 
-       header_size = skb->network_header + off + MAX_IPOPTLEN;
-       maybe_pull_tail(skb, header_size);
+       off = ip_hdrlen(skb);
 
-       off = iph->ihl * 4;
+       err = -EPROTO;
 
-       switch (iph->protocol) {
+       switch (ip_hdr(skb)->protocol) {
        case IPPROTO_TCP:
+               err = maybe_pull_tail(skb,
+                                     off + sizeof(struct tcphdr),
+                                     MAX_IP_HDR_LEN);
+               if (err < 0)
+                       goto out;
+
                if (!skb_partial_csum_set(skb, off,
                                          offsetof(struct tcphdr, check)))
                        goto out;
 
-               if (recalculate_partial_csum) {
-                       struct tcphdr *tcph = tcp_hdr(skb);
-
-                       header_size = skb->network_header +
-                               off +
-                               sizeof(struct tcphdr);
-                       maybe_pull_tail(skb, header_size);
-
-                       tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
-                                                        skb->len - off,
-                                                        IPPROTO_TCP, 0);
-               }
+               if (recalculate_partial_csum)
+                       tcp_hdr(skb)->check =
+                               ~csum_tcpudp_magic(ip_hdr(skb)->saddr,
+                                                  ip_hdr(skb)->daddr,
+                                                  skb->len - off,
+                                                  IPPROTO_TCP, 0);
                break;
        case IPPROTO_UDP:
+               err = maybe_pull_tail(skb,
+                                     off + sizeof(struct udphdr),
+                                     MAX_IP_HDR_LEN);
+               if (err < 0)
+                       goto out;
+
                if (!skb_partial_csum_set(skb, off,
                                          offsetof(struct udphdr, check)))
                        goto out;
 
-               if (recalculate_partial_csum) {
-                       struct udphdr *udph = udp_hdr(skb);
-
-                       header_size = skb->network_header +
-                               off +
-                               sizeof(struct udphdr);
-                       maybe_pull_tail(skb, header_size);
-
-                       udph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
-                                                        skb->len - off,
-                                                        IPPROTO_UDP, 0);
-               }
+               if (recalculate_partial_csum)
+                       udp_hdr(skb)->check =
+                               ~csum_tcpudp_magic(ip_hdr(skb)->saddr,
+                                                  ip_hdr(skb)->daddr,
+                                                  skb->len - off,
+                                                  IPPROTO_UDP, 0);
                break;
        default:
-               if (net_ratelimit())
-                       netdev_err(vif->dev,
-                                  "Attempting to checksum a non-TCP/UDP packet, "
-                                  "dropping a protocol %d packet\n",
-                                  iph->protocol);
                goto out;
        }
 
@@ -1226,121 +1146,138 @@ out:
        return err;
 }
 
+/* This value should be large enough to cover a tagged ethernet header plus
+ * an IPv6 header, all options, and a maximal TCP or UDP header.
+ */
+#define MAX_IPV6_HDR_LEN 256
+
+#define OPT_HDR(type, skb, off) \
+       (type *)(skb_network_header(skb) + (off))
+
 static int checksum_setup_ipv6(struct xenvif *vif, struct sk_buff *skb,
                               int recalculate_partial_csum)
 {
-       int err = -EPROTO;
-       struct ipv6hdr *ipv6h = (void *)skb->data;
+       int err;
        u8 nexthdr;
-       unsigned int header_size;
        unsigned int off;
+       unsigned int len;
        bool fragment;
        bool done;
 
+       fragment = false;
        done = false;
 
        off = sizeof(struct ipv6hdr);
 
-       header_size = skb->network_header + off;
-       maybe_pull_tail(skb, header_size);
+       err = maybe_pull_tail(skb, off, MAX_IPV6_HDR_LEN);
+       if (err < 0)
+               goto out;
 
-       nexthdr = ipv6h->nexthdr;
+       nexthdr = ipv6_hdr(skb)->nexthdr;
 
-       while ((off <= sizeof(struct ipv6hdr) + ntohs(ipv6h->payload_len)) &&
-              !done) {
+       len = sizeof(struct ipv6hdr) + ntohs(ipv6_hdr(skb)->payload_len);
+       while (off <= len && !done) {
                switch (nexthdr) {
                case IPPROTO_DSTOPTS:
                case IPPROTO_HOPOPTS:
                case IPPROTO_ROUTING: {
-                       struct ipv6_opt_hdr *hp = (void *)(skb->data + off);
+                       struct ipv6_opt_hdr *hp;
 
-                       header_size = skb->network_header +
-                               off +
-                               sizeof(struct ipv6_opt_hdr);
-                       maybe_pull_tail(skb, header_size);
+                       err = maybe_pull_tail(skb,
+                                             off +
+                                             sizeof(struct ipv6_opt_hdr),
+                                             MAX_IPV6_HDR_LEN);
+                       if (err < 0)
+                               goto out;
 
+                       hp = OPT_HDR(struct ipv6_opt_hdr, skb, off);
                        nexthdr = hp->nexthdr;
                        off += ipv6_optlen(hp);
                        break;
                }
                case IPPROTO_AH: {
-                       struct ip_auth_hdr *hp = (void *)(skb->data + off);
+                       struct ip_auth_hdr *hp;
 
-                       header_size = skb->network_header +
-                               off +
-                               sizeof(struct ip_auth_hdr);
-                       maybe_pull_tail(skb, header_size);
+                       err = maybe_pull_tail(skb,
+                                             off +
+                                             sizeof(struct ip_auth_hdr),
+                                             MAX_IPV6_HDR_LEN);
+                       if (err < 0)
+                               goto out;
 
+                       hp = OPT_HDR(struct ip_auth_hdr, skb, off);
                        nexthdr = hp->nexthdr;
-                       off += (hp->hdrlen+2)<<2;
+                       off += ipv6_authlen(hp);
+                       break;
+               }
+               case IPPROTO_FRAGMENT: {
+                       struct frag_hdr *hp;
+
+                       err = maybe_pull_tail(skb,
+                                             off +
+                                             sizeof(struct frag_hdr),
+                                             MAX_IPV6_HDR_LEN);
+                       if (err < 0)
+                               goto out;
+
+                       hp = OPT_HDR(struct frag_hdr, skb, off);
+
+                       if (hp->frag_off & htons(IP6_OFFSET | IP6_MF))
+                               fragment = true;
+
+                       nexthdr = hp->nexthdr;
+                       off += sizeof(struct frag_hdr);
                        break;
                }
-               case IPPROTO_FRAGMENT:
-                       fragment = true;
-                       /* fall through */
                default:
                        done = true;
                        break;
                }
        }
 
-       if (!done) {
-               if (net_ratelimit())
-                       netdev_err(vif->dev, "Failed to parse packet header\n");
-               goto out;
-       }
+       err = -EPROTO;
 
-       if (fragment) {
-               if (net_ratelimit())
-                       netdev_err(vif->dev, "Packet is a fragment!\n");
+       if (!done || fragment)
                goto out;
-       }
 
        switch (nexthdr) {
        case IPPROTO_TCP:
+               err = maybe_pull_tail(skb,
+                                     off + sizeof(struct tcphdr),
+                                     MAX_IPV6_HDR_LEN);
+               if (err < 0)
+                       goto out;
+
                if (!skb_partial_csum_set(skb, off,
                                          offsetof(struct tcphdr, check)))
                        goto out;
 
-               if (recalculate_partial_csum) {
-                       struct tcphdr *tcph = tcp_hdr(skb);
-
-                       header_size = skb->network_header +
-                               off +
-                               sizeof(struct tcphdr);
-                       maybe_pull_tail(skb, header_size);
-
-                       tcph->check = ~csum_ipv6_magic(&ipv6h->saddr,
-                                                      &ipv6h->daddr,
-                                                      skb->len - off,
-                                                      IPPROTO_TCP, 0);
-               }
+               if (recalculate_partial_csum)
+                       tcp_hdr(skb)->check =
+                               ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
+                                                &ipv6_hdr(skb)->daddr,
+                                                skb->len - off,
+                                                IPPROTO_TCP, 0);
                break;
        case IPPROTO_UDP:
+               err = maybe_pull_tail(skb,
+                                     off + sizeof(struct udphdr),
+                                     MAX_IPV6_HDR_LEN);
+               if (err < 0)
+                       goto out;
+
                if (!skb_partial_csum_set(skb, off,
                                          offsetof(struct udphdr, check)))
                        goto out;
 
-               if (recalculate_partial_csum) {
-                       struct udphdr *udph = udp_hdr(skb);
-
-                       header_size = skb->network_header +
-                               off +
-                               sizeof(struct udphdr);
-                       maybe_pull_tail(skb, header_size);
-
-                       udph->check = ~csum_ipv6_magic(&ipv6h->saddr,
-                                                      &ipv6h->daddr,
-                                                      skb->len - off,
-                                                      IPPROTO_UDP, 0);
-               }
+               if (recalculate_partial_csum)
+                       udp_hdr(skb)->check =
+                               ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
+                                                &ipv6_hdr(skb)->daddr,
+                                                skb->len - off,
+                                                IPPROTO_UDP, 0);
                break;
        default:
-               if (net_ratelimit())
-                       netdev_err(vif->dev,
-                                  "Attempting to checksum a non-TCP/UDP packet, "
-                                  "dropping a protocol %d packet\n",
-                                  nexthdr);
                goto out;
        }
 
@@ -1765,7 +1702,7 @@ static struct xen_netif_rx_response *make_rx_response(struct xenvif *vif,
 
 static inline int rx_work_todo(struct xenvif *vif)
 {
-       return !skb_queue_empty(&vif->rx_queue);
+       return !skb_queue_empty(&vif->rx_queue) || vif->rx_event;
 }
 
 static inline int tx_work_todo(struct xenvif *vif)
@@ -1815,8 +1752,6 @@ int xenvif_map_frontend_rings(struct xenvif *vif,
        rxs = (struct xen_netif_rx_sring *)addr;
        BACK_RING_INIT(&vif->rx, rxs, PAGE_SIZE);
 
-       vif->rx_req_cons_peek = 0;
-
        return 0;
 
 err:
@@ -1824,9 +1759,24 @@ err:
        return err;
 }
 
+void xenvif_stop_queue(struct xenvif *vif)
+{
+       if (!vif->can_queue)
+               return;
+
+       netif_stop_queue(vif->dev);
+}
+
+static void xenvif_start_queue(struct xenvif *vif)
+{
+       if (xenvif_schedulable(vif))
+               netif_wake_queue(vif->dev);
+}
+
 int xenvif_kthread(void *data)
 {
        struct xenvif *vif = data;
+       struct sk_buff *skb;
 
        while (!kthread_should_stop()) {
                wait_event_interruptible(vif->wq,
@@ -1835,12 +1785,22 @@ int xenvif_kthread(void *data)
                if (kthread_should_stop())
                        break;
 
-               if (rx_work_todo(vif))
+               if (!skb_queue_empty(&vif->rx_queue))
                        xenvif_rx_action(vif);
 
+               vif->rx_event = false;
+
+               if (skb_queue_empty(&vif->rx_queue) &&
+                   netif_queue_stopped(vif->dev))
+                       xenvif_start_queue(vif);
+
                cond_resched();
        }
 
+       /* Bin any remaining skbs */
+       while ((skb = skb_dequeue(&vif->rx_queue)) != NULL)
+               dev_kfree_skb(skb);
+
        return 0;
 }
 
index f0358992b04fa820cb083300765271b92823320a..7a206cffb062c0b3a2521ca7a6ee22d4cd3bcefd 100644 (file)
@@ -15,8 +15,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "common.h"
index 85f90090cc1d1e167de6391e3481b597451555bd..1d78605519850b5392c8c25ff51fc358f6dea308 100644 (file)
@@ -13,9 +13,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
index 696e3467eccc33ab1ee97c6da2a4940c489ee086..df85cd3d9db0c76e1d80ebbf3bcc204f3e3f8a0c 100644 (file)
@@ -13,9 +13,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
index 72fafec3d46058908ea841f2c89273c179b6d30d..2d1395be64ae93e9a33f8d5c20603bff84e77d3e 100644 (file)
@@ -13,9 +13,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
index 970ded6bfcf562b278e43b03e5112042c798fd0c..f868333271aafc665d45f7e3b1ec6dfcdbf35246 100644 (file)
@@ -13,9 +13,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
index 64b447a1c5bf6d18e247b468f10767ea20c1ddab..f538641431a2b28d517f49fc4007937778fced21 100644 (file)
@@ -12,9 +12,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef __LOCAL_MICROREAD_H_
index 71308645593f638a2879df4348f1349f0e031ce4..683671a71c7e9313ab2d646da37a450bc24e7da8 100644 (file)
@@ -22,8 +22,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 #include <linux/platform_device.h>
index 2daf04c073383c53ae4374d8a9613546fe13d09b..3df19e657bc1e23aea6b28baec9adeef3337ca13 100644 (file)
@@ -13,9 +13,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/device.h>
index b158ee1c2ac69fc8ec0ff3fc667df10e5eb3f70e..d6185ff2f87b0aa80aba29a55a806057301e39d4 100644 (file)
@@ -13,9 +13,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
index ee67de50c36fc47d57551db072f6c9a474ae8afc..330cd40310098e22333d6a35f66fa451a3aaa72e 100644 (file)
@@ -13,9 +13,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/module.h>
index 74cfa0a88b9e7c0ae6cdedd66d77deedd15e9872..51e21a87cd847896754fece3b17f02293b8de86c 100644 (file)
@@ -13,9 +13,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
index 01020e5854437e29b5bb254e14b2e920eefb29fc..491bf45da35822f706401bd25bbf9b9eaaa78e99 100644 (file)
@@ -12,9 +12,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef __LOCAL_PN544_H_
index f807d0edabf3206561bbcefa6009bb1d0fc89c1a..8d007d8b8c780e36e0f471f0329b9a140e401a0b 100644 (file)
@@ -731,24 +731,42 @@ static
 const struct of_device_id *__of_match_node(const struct of_device_id *matches,
                                           const struct device_node *node)
 {
+       const char *cp;
+       int cplen, l;
+
        if (!matches)
                return NULL;
 
-       while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
-               int match = 1;
-               if (matches->name[0])
-                       match &= node->name
-                               && !strcmp(matches->name, node->name);
-               if (matches->type[0])
-                       match &= node->type
-                               && !strcmp(matches->type, node->type);
-               if (matches->compatible[0])
-                       match &= __of_device_is_compatible(node,
-                                                          matches->compatible);
-               if (match)
-                       return matches;
-               matches++;
-       }
+       cp = __of_get_property(node, "compatible", &cplen);
+       do {
+               const struct of_device_id *m = matches;
+
+               /* Check against matches with current compatible string */
+               while (m->name[0] || m->type[0] || m->compatible[0]) {
+                       int match = 1;
+                       if (m->name[0])
+                               match &= node->name
+                                       && !strcmp(m->name, node->name);
+                       if (m->type[0])
+                               match &= node->type
+                                       && !strcmp(m->type, node->type);
+                       if (m->compatible[0])
+                               match &= cp
+                                       && !of_compat_cmp(m->compatible, cp,
+                                                       strlen(m->compatible));
+                       if (match)
+                               return m;
+                       m++;
+               }
+
+               /* Get node's next compatible string */ 
+               if (cp) {
+                       l = strlen(cp) + 1;
+                       cp += l;
+                       cplen -= l;
+               }
+       } while (cp && (cplen > 0));
+
        return NULL;
 }
 
@@ -757,7 +775,10 @@ const struct of_device_id *__of_match_node(const struct of_device_id *matches,
  *     @matches:       array of of device match structures to search in
  *     @node:          the of device structure to match against
  *
- *     Low level utility function used by device matching.
+ *     Low level utility function used by device matching. Matching order
+ *     is to compare each of the node's compatibles with all given matches
+ *     first. This implies node's compatible is sorted from specific to
+ *     generic while matches can be in any order.
  */
 const struct of_device_id *of_match_node(const struct of_device_id *matches,
                                         const struct device_node *node)
index 786b0b47fae46802503ecbecee5719887830c44c..bf8026895c5e07e41c802f2ed1fb5775380edbaa 100644 (file)
@@ -217,6 +217,9 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
                                goto fail;
                        }
 
+                       if (!of_device_is_available(newpar))
+                               match = 0;
+
                        /* Get #interrupt-cells and #address-cells of new
                         * parent
                         */
@@ -438,7 +441,8 @@ void __init of_irq_init(const struct of_device_id *matches)
        INIT_LIST_HEAD(&intc_parent_list);
 
        for_each_matching_node(np, matches) {
-               if (!of_find_property(np, "interrupt-controller", NULL))
+               if (!of_find_property(np, "interrupt-controller", NULL) ||
+                               !of_device_is_available(np))
                        continue;
                /*
                 * Here, we allocate and populate an intc_desc with the node
index d5a57a9e329c85de3e48722e8b9576f56dcea577..a43b8523c61e13fbff9af821a92131390304fc49 100644 (file)
 MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
 MODULE_LICENSE("GPL");
 
+static void of_set_phy_supported(struct phy_device *phydev, u32 max_speed)
+{
+       phydev->supported |= PHY_DEFAULT_FEATURES;
+
+       switch (max_speed) {
+       default:
+               return;
+
+       case SPEED_1000:
+               phydev->supported |= PHY_1000BT_FEATURES;
+       case SPEED_100:
+               phydev->supported |= PHY_100BT_FEATURES;
+       case SPEED_10:
+               phydev->supported |= PHY_10BT_FEATURES;
+       }
+}
+
+static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *child,
+                                  u32 addr)
+{
+       struct phy_device *phy;
+       bool is_c45;
+       int rc, prev_irq;
+       u32 max_speed = 0;
+
+       is_c45 = of_device_is_compatible(child,
+                                        "ethernet-phy-ieee802.3-c45");
+
+       phy = get_phy_device(mdio, addr, is_c45);
+       if (!phy || IS_ERR(phy))
+               return 1;
+
+       if (mdio->irq) {
+               prev_irq = mdio->irq[addr];
+               mdio->irq[addr] =
+                       irq_of_parse_and_map(child, 0);
+               if (!mdio->irq[addr])
+                       mdio->irq[addr] = prev_irq;
+       }
+
+       /* Associate the OF node with the device structure so it
+        * can be looked up later */
+       of_node_get(child);
+       phy->dev.of_node = child;
+
+       /* All data is now stored in the phy struct;
+        * register it */
+       rc = phy_device_register(phy);
+       if (rc) {
+               phy_device_free(phy);
+               of_node_put(child);
+               return 1;
+       }
+
+       /* Set phydev->supported based on the "max-speed" property
+        * if present */
+       if (!of_property_read_u32(child, "max-speed", &max_speed))
+               of_set_phy_supported(phy, max_speed);
+
+       dev_dbg(&mdio->dev, "registered phy %s at address %i\n",
+               child->name, addr);
+
+       return 0;
+}
+
 /**
  * of_mdiobus_register - Register mii_bus and create PHYs from the device tree
  * @mdio: pointer to mii_bus structure
@@ -32,11 +97,10 @@ MODULE_LICENSE("GPL");
  */
 int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
 {
-       struct phy_device *phy;
        struct device_node *child;
        const __be32 *paddr;
        u32 addr;
-       bool is_c45, scanphys = false;
+       bool scanphys = false;
        int rc, i, len;
 
        /* Mask out all PHYs from auto probing.  Instead the PHYs listed in
@@ -67,44 +131,15 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
                }
 
                addr = be32_to_cpup(paddr);
-               if (addr >= 32) {
+               if (addr >= PHY_MAX_ADDR) {
                        dev_err(&mdio->dev, "%s PHY address %i is too large\n",
                                child->full_name, addr);
                        continue;
                }
 
-               if (mdio->irq) {
-                       mdio->irq[addr] = irq_of_parse_and_map(child, 0);
-                       if (!mdio->irq[addr])
-                               mdio->irq[addr] = PHY_POLL;
-               }
-
-               is_c45 = of_device_is_compatible(child,
-                                                "ethernet-phy-ieee802.3-c45");
-               phy = get_phy_device(mdio, addr, is_c45);
-
-               if (!phy || IS_ERR(phy)) {
-                       dev_err(&mdio->dev,
-                               "cannot get PHY at address %i\n",
-                               addr);
-                       continue;
-               }
-
-               /* Associate the OF node with the device structure so it
-                * can be looked up later */
-               of_node_get(child);
-               phy->dev.of_node = child;
-
-               /* All data is now stored in the phy struct; register it */
-               rc = phy_device_register(phy);
-               if (rc) {
-                       phy_device_free(phy);
-                       of_node_put(child);
+               rc = of_mdiobus_register_phy(mdio, child, addr);
+               if (rc)
                        continue;
-               }
-
-               dev_dbg(&mdio->dev, "registered phy %s at address %i\n",
-                       child->name, addr);
        }
 
        if (!scanphys)
@@ -117,9 +152,6 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
                if (paddr)
                        continue;
 
-               is_c45 = of_device_is_compatible(child,
-                                                "ethernet-phy-ieee802.3-c45");
-
                for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
                        /* skip already registered PHYs */
                        if (mdio->phy_map[addr])
@@ -129,34 +161,9 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
                        dev_info(&mdio->dev, "scan phy %s at address %i\n",
                                 child->name, addr);
 
-                       phy = get_phy_device(mdio, addr, is_c45);
-                       if (!phy || IS_ERR(phy))
+                       rc = of_mdiobus_register_phy(mdio, child, addr);
+                       if (rc)
                                continue;
-
-                       if (mdio->irq) {
-                               mdio->irq[addr] =
-                                       irq_of_parse_and_map(child, 0);
-                               if (!mdio->irq[addr])
-                                       mdio->irq[addr] = PHY_POLL;
-                       }
-
-                       /* Associate the OF node with the device structure so it
-                        * can be looked up later */
-                       of_node_get(child);
-                       phy->dev.of_node = child;
-
-                       /* All data is now stored in the phy struct;
-                        * register it */
-                       rc = phy_device_register(phy);
-                       if (rc) {
-                               phy_device_free(phy);
-                               of_node_put(child);
-                               continue;
-                       }
-
-                       dev_info(&mdio->dev, "registered phy %s at address %i\n",
-                                child->name, addr);
-                       break;
                }
        }
 
index 7578d79b368831085dc5ee70850fd6578ee13357..2f650f68af14e4ec9e37e2c837db3fd55408b9ff 100644 (file)
@@ -300,7 +300,7 @@ static int __init parport_mfc3_init(void)
                if (!request_mem_region(piabase, sizeof(struct pia), "PIA"))
                        continue;
 
-               pp = (struct pia *)ZTWO_VADDR(piabase);
+               pp = ZTWO_VADDR(piabase);
                pp->crb = 0;
                pp->pddrb = 255; /* all data pins output */
                pp->crb = PIA_DDR|32|8;
index c269e430c760a9bc80ad982db9cb4aa211f16f45..2aa7b77c7c88bab6c2b70b79666205c061afec7d 100644 (file)
@@ -447,6 +447,11 @@ static int mvebu_sw_pci_bridge_read(struct mvebu_pcie_port *port,
                *value = 0;
                break;
 
+       case PCI_INTERRUPT_LINE:
+               /* LINE PIN MIN_GNT MAX_LAT */
+               *value = 0;
+               break;
+
        default:
                *value = 0xffffffff;
                return PCIBIOS_BAD_REGISTER_NUMBER;
index 1cf605f6767357947e9a097981caa7d7869ca2f0..ec4ddae1fb54a68641bf4e4b90e6cbec2def6814 100644 (file)
@@ -279,7 +279,9 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data,
 
        status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
        if (ACPI_FAILURE(status)) {
-               acpi_handle_warn(handle, "can't evaluate _ADR (%#x)\n", status);
+               if (status != AE_NOT_FOUND)
+                       acpi_handle_warn(handle,
+                               "can't evaluate _ADR (%#x)\n", status);
                return AE_OK;
        }
 
@@ -489,7 +491,7 @@ static void acpiphp_bus_add(acpi_handle handle)
 
        acpi_bus_scan(handle);
        acpi_bus_get_device(handle, &adev);
-       if (adev)
+       if (acpi_device_enumerated(adev))
                acpi_device_set_power(adev, ACPI_STATE_D0);
 }
 
index ecfac7e72d91ae29a3ec8a5b6e8d159d0f7b7178..8dcccffd6e216b8529da5530019fe557e0f61ff1 100644 (file)
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <acpi/acpi_bus.h>
 #include <linux/sysfs.h>
 #include <linux/kobject.h>
-#include <asm/uaccess.h>
 #include <linux/moduleparam.h>
 #include <linux/pci.h>
+#include <asm/uaccess.h>
 
 #include "acpiphp.h"
 #include "../pci.h"
index 21e865ded1dce01fde77bb29312e2a653be6b4fa..24e147cae667e33dd46346dddeb994e96e868f4e 100644 (file)
@@ -163,8 +163,6 @@ static inline const char *slot_name(struct slot *slot)
 }
 
 #ifdef CONFIG_ACPI
-#include <acpi/acpi.h>
-#include <acpi/acpi_bus.h>
 #include <linux/pci-acpi.h>
 
 void __init pciehp_acpi_slot_detection_init(void);
index 50ce6809829836c38d4aedfa58aeb642b126d9df..2122b2bf006f37576d5bb2e3a22190c5ccacba00 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/module.h>
 #include <linux/acpi.h>
 #include <linux/slab.h>
-#include <acpi/acpi_bus.h>
 
 struct ioapic {
        acpi_handle     handle;
index 577074efbe62f93f39ac00c6f5c4963d53bd2b0d..ce31eb0cdca7396ad64a9891d5cee74056887f9e 100644 (file)
@@ -12,9 +12,6 @@
 #include <linux/pci.h>
 #include <linux/module.h>
 #include <linux/pci-aspm.h>
-#include <acpi/acpi.h>
-#include <acpi/acpi_bus.h>
-
 #include <linux/pci-acpi.h>
 #include <linux/pm_runtime.h>
 #include <linux/pm_qos.h>
@@ -306,10 +303,10 @@ void acpi_pci_remove_bus(struct pci_bus *bus)
 }
 
 /* ACPI bus type */
-static int acpi_pci_find_device(struct device *dev, acpi_handle *handle)
+static struct acpi_device *acpi_pci_find_companion(struct device *dev)
 {
        struct pci_dev *pci_dev = to_pci_dev(dev);
-       bool is_bridge;
+       bool check_children;
        u64 addr;
 
        /*
@@ -317,14 +314,12 @@ static int acpi_pci_find_device(struct device *dev, acpi_handle *handle)
         * is set only after acpi_pci_find_device() has been called for the
         * given device.
         */
-       is_bridge = pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE
+       check_children = pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE
                        || pci_dev->hdr_type == PCI_HEADER_TYPE_CARDBUS;
        /* Please ref to ACPI spec for the syntax of _ADR */
        addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn);
-       *handle = acpi_find_child(ACPI_HANDLE(dev->parent), addr, is_bridge);
-       if (!*handle)
-               return -ENODEV;
-       return 0;
+       return acpi_find_child_device(ACPI_COMPANION(dev->parent), addr,
+                                     check_children);
 }
 
 static void pci_acpi_setup(struct device *dev)
@@ -364,7 +359,7 @@ static bool pci_acpi_bus_match(struct device *dev)
 static struct acpi_bus_type acpi_pci_bus = {
        .name = "PCI",
        .match = pci_acpi_bus_match,
-       .find_device = acpi_pci_find_device,
+       .find_companion = acpi_pci_find_companion,
        .setup = pci_acpi_setup,
        .cleanup = pci_acpi_cleanup,
 };
index 9042fdbd724405bc96808ed699a1d543fcf17c17..25f0bc6591645707bb3b452bbaa4c28bee0efc59 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/cpu.h>
 #include <linux/pm_runtime.h>
 #include <linux/suspend.h>
+#include <linux/kexec.h>
 #include "pci.h"
 
 struct pci_dynid {
@@ -288,12 +289,27 @@ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
        int error, node;
        struct drv_dev_and_id ddi = { drv, dev, id };
 
-       /* Execute driver initialization on node where the device's
-          bus is attached to.  This way the driver likely allocates
-          its local memory on the right node without any need to
-          change it. */
+       /*
+        * Execute driver initialization on node where the device is
+        * attached.  This way the driver likely allocates its local memory
+        * on the right node.
+        */
        node = dev_to_node(&dev->dev);
-       if (node >= 0) {
+
+       /*
+        * On NUMA systems, we are likely to call a PF probe function using
+        * work_on_cpu().  If that probe calls pci_enable_sriov() (which
+        * adds the VF devices via pci_bus_add_device()), we may re-enter
+        * this function to call the VF probe function.  Calling
+        * work_on_cpu() again will cause a lockdep warning.  Since VFs are
+        * always on the same node as the PF, we can work around this by
+        * avoiding work_on_cpu() when we're already on the correct node.
+        *
+        * Preemption is enabled, so it's theoretically unsafe to use
+        * numa_node_id(), but even if we run the probe function on the
+        * wrong node, it should be functionally correct.
+        */
+       if (node >= 0 && node != numa_node_id()) {
                int cpu;
 
                get_online_cpus();
@@ -305,6 +321,7 @@ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
                put_online_cpus();
        } else
                error = local_pci_probe(&ddi);
+
        return error;
 }
 
@@ -399,12 +416,17 @@ static void pci_device_shutdown(struct device *dev)
        pci_msi_shutdown(pci_dev);
        pci_msix_shutdown(pci_dev);
 
+#ifdef CONFIG_KEXEC
        /*
-        * Turn off Bus Master bit on the device to tell it to not
-        * continue to do DMA. Don't touch devices in D3cold or unknown states.
+        * If this is a kexec reboot, turn off Bus Master bit on the
+        * device to tell it to not continue to do DMA. Don't touch
+        * devices in D3cold or unknown states.
+        * If it is not a kexec reboot, firmware will hit the PCI
+        * devices with big hammer and stop their DMA any way.
         */
-       if (pci_dev->current_state <= PCI_D3hot)
+       if (kexec_in_progress && (pci_dev->current_state <= PCI_D3hot))
                pci_clear_master(pci_dev);
+#endif
 }
 
 #ifdef CONFIG_PM
index d51f45aa669e5ff9184daab1df72776e8165aa84..dbafcc8ef67396da56ce21568d1fb89fe5c8778d 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/nls.h>
 #include <linux/acpi.h>
 #include <linux/pci-acpi.h>
-#include <acpi/acpi_bus.h>
 #include "pci.h"
 
 #define        DEVICE_LABEL_DSM        0x07
index 33120d15666895a2b48aec1c83f7b41f7b93c3be..07369f32e8bbdd79b1294ad844baeb7dc80ef7ea 100644 (file)
@@ -4165,6 +4165,14 @@ int pci_set_vga_state(struct pci_dev *dev, bool decode,
        return 0;
 }
 
+bool pci_device_is_present(struct pci_dev *pdev)
+{
+       u32 v;
+
+       return pci_bus_read_dev_vendor_id(pdev->bus, pdev->devfn, &v, 0);
+}
+EXPORT_SYMBOL_GPL(pci_device_is_present);
+
 #define RESOURCE_ALIGNMENT_PARAM_SIZE COMMAND_LINE_SIZE
 static char resource_alignment_param[RESOURCE_ALIGNMENT_PARAM_SIZE] = {0};
 static DEFINE_SPINLOCK(resource_alignment_lock);
index 1576851028db700be2413b01e815cc8387b3cd47..cc9337a71529180eaebc7beb991dfb7c9e186ea8 100644 (file)
@@ -24,7 +24,7 @@ static void pci_stop_dev(struct pci_dev *dev)
        if (dev->is_added) {
                pci_proc_detach_device(dev);
                pci_remove_sysfs_dev_files(dev);
-               device_del(&dev->dev);
+               device_release_driver(&dev->dev);
                dev->is_added = 0;
        }
 
@@ -34,6 +34,8 @@ static void pci_stop_dev(struct pci_dev *dev)
 
 static void pci_destroy_dev(struct pci_dev *dev)
 {
+       device_del(&dev->dev);
+
        down_write(&pci_bus_sem);
        list_del(&dev->bus_list);
        up_write(&pci_bus_sem);
index a344f3d52361f0eed4d2a0d1fdc81a957e3a7967..330ef2d065670eb91b84a6d553bdf1df2dabf79f 100644 (file)
@@ -24,8 +24,8 @@ config PHY_EXYNOS_MIPI_VIDEO
 config OMAP_USB2
        tristate "OMAP USB2 PHY Driver"
        depends on ARCH_OMAP2PLUS
+       depends on USB_PHY
        select GENERIC_PHY
-       select USB_PHY
        select OMAP_CONTROL_USB
        help
          Enable this to support the transceiver that is part of SOC. This
@@ -36,8 +36,8 @@ config OMAP_USB2
 config TWL4030_USB
        tristate "TWL4030 USB Transceiver Driver"
        depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
+       depends on USB_PHY
        select GENERIC_PHY
-       select USB_PHY
        help
          Enable this to support the USB OTG transceiver on TWL4030
          family chips (including the TWL5030 and TPS659x0 devices).
index 03cf8fb815543537fb14995fde36a5216706dab9..58e0e97390287364287eae1eecdf8b43ba7b72f1 100644 (file)
@@ -437,23 +437,18 @@ struct phy *phy_create(struct device *dev, const struct phy_ops *ops,
        int id;
        struct phy *phy;
 
-       if (!dev) {
-               dev_WARN(dev, "no device provided for PHY\n");
-               ret = -EINVAL;
-               goto err0;
-       }
+       if (WARN_ON(!dev))
+               return ERR_PTR(-EINVAL);
 
        phy = kzalloc(sizeof(*phy), GFP_KERNEL);
-       if (!phy) {
-               ret = -ENOMEM;
-               goto err0;
-       }
+       if (!phy)
+               return ERR_PTR(-ENOMEM);
 
        id = ida_simple_get(&phy_ida, 0, 0, GFP_KERNEL);
        if (id < 0) {
                dev_err(dev, "unable to get id\n");
                ret = id;
-               goto err0;
+               goto free_phy;
        }
 
        device_initialize(&phy->dev);
@@ -468,11 +463,11 @@ struct phy *phy_create(struct device *dev, const struct phy_ops *ops,
 
        ret = dev_set_name(&phy->dev, "phy-%s.%d", dev_name(dev), id);
        if (ret)
-               goto err1;
+               goto put_dev;
 
        ret = device_add(&phy->dev);
        if (ret)
-               goto err1;
+               goto put_dev;
 
        if (pm_runtime_enabled(dev)) {
                pm_runtime_enable(&phy->dev);
@@ -481,12 +476,11 @@ struct phy *phy_create(struct device *dev, const struct phy_ops *ops,
 
        return phy;
 
-err1:
-       ida_remove(&phy_ida, phy->id);
+put_dev:
        put_device(&phy->dev);
+       ida_remove(&phy_ida, phy->id);
+free_phy:
        kfree(phy);
-
-err0:
        return ERR_PTR(ret);
 }
 EXPORT_SYMBOL_GPL(phy_create);
index 33f9dc1f14fdd3e64db47325550b9f5ba93360b5..e216a46f41948f919cefce779de11d88aafc2768 100644 (file)
@@ -116,7 +116,6 @@ config PINCTRL_IMX1_CORE
 
 config PINCTRL_IMX27
        bool "IMX27 pinctrl driver"
-       depends on OF
        depends on SOC_IMX27
        select PINCTRL_IMX1_CORE
        help
@@ -124,7 +123,6 @@ config PINCTRL_IMX27
 
 config PINCTRL_IMX35
        bool "IMX35 pinctrl driver"
-       depends on OF
        depends on SOC_IMX35
        select PINCTRL_IMX
        help
@@ -132,7 +130,6 @@ config PINCTRL_IMX35
 
 config PINCTRL_IMX50
        bool "IMX50 pinctrl driver"
-       depends on OF
        depends on SOC_IMX50
        select PINCTRL_IMX
        help
@@ -140,7 +137,6 @@ config PINCTRL_IMX50
 
 config PINCTRL_IMX51
        bool "IMX51 pinctrl driver"
-       depends on OF
        depends on SOC_IMX51
        select PINCTRL_IMX
        help
@@ -148,7 +144,6 @@ config PINCTRL_IMX51
 
 config PINCTRL_IMX53
        bool "IMX53 pinctrl driver"
-       depends on OF
        depends on SOC_IMX53
        select PINCTRL_IMX
        help
@@ -156,7 +151,6 @@ config PINCTRL_IMX53
 
 config PINCTRL_IMX6Q
        bool "IMX6Q/DL pinctrl driver"
-       depends on OF
        depends on SOC_IMX6Q
        select PINCTRL_IMX
        help
@@ -164,7 +158,6 @@ config PINCTRL_IMX6Q
 
 config PINCTRL_IMX6SL
        bool "IMX6SL pinctrl driver"
-       depends on OF
        depends on SOC_IMX6SL
        select PINCTRL_IMX
        help
@@ -172,7 +165,6 @@ config PINCTRL_IMX6SL
 
 config PINCTRL_VF610
        bool "Freescale Vybrid VF610 pinctrl driver"
-       depends on OF
        depends on SOC_VF610
        select PINCTRL_IMX
        help
index 4780959e11d4c858e55703bee4a3835876d05550..163da9c3ea0e164c228bff771ed8b41347632fa7 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/bitops.h>
 #include <linux/mfd/abx500.h>
 #include <linux/mfd/abx500/ab8500.h>
-#include <linux/mfd/abx500/ab8500-gpio.h>
 #include <linux/pinctrl/pinctrl.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/pinctrl/pinmux.h>
@@ -418,7 +417,7 @@ static int abx500_set_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
                        ret = abx500_gpio_set_bits(chip,
                                        AB8500_GPIO_ALTFUN_REG,
                                        af.alt_bit1,
-                                       !!(af.alta_val && BIT(0)));
+                                       !!(af.alta_val & BIT(0)));
                        if (ret < 0)
                                goto out;
 
@@ -439,7 +438,7 @@ static int abx500_set_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
                        goto out;
 
                ret = abx500_gpio_set_bits(chip, AB8500_GPIO_ALTFUN_REG,
-                               af.alt_bit1, !!(af.altb_val && BIT(0)));
+                               af.alt_bit1, !!(af.altb_val & BIT(0)));
                if (ret < 0)
                        goto out;
 
@@ -462,7 +461,7 @@ static int abx500_set_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
                        goto out;
 
                ret = abx500_gpio_set_bits(chip, AB8500_GPIO_ALTFUN_REG,
-                               af.alt_bit2, !!(af.altc_val && BIT(1)));
+                               af.alt_bit2, !!(af.altc_val & BIT(1)));
                break;
 
        default:
@@ -1218,21 +1217,15 @@ static const struct of_device_id abx500_gpio_match[] = {
 
 static int abx500_gpio_probe(struct platform_device *pdev)
 {
-       struct ab8500_platform_data *abx500_pdata =
-                               dev_get_platdata(pdev->dev.parent);
-       struct abx500_gpio_platform_data *pdata = NULL;
        struct device_node *np = pdev->dev.of_node;
+       const struct of_device_id *match;
        struct abx500_pinctrl *pct;
-       const struct platform_device_id *platid = platform_get_device_id(pdev);
        unsigned int id = -1;
        int ret, err;
        int i;
 
-       if (abx500_pdata)
-               pdata = abx500_pdata->gpio;
-
-       if (!(pdata || np)) {
-               dev_err(&pdev->dev, "gpio dt and platform data missing\n");
+       if (!np) {
+               dev_err(&pdev->dev, "gpio dt node missing\n");
                return -ENODEV;
        }
 
@@ -1248,17 +1241,14 @@ static int abx500_gpio_probe(struct platform_device *pdev)
        pct->parent = dev_get_drvdata(pdev->dev.parent);
        pct->chip = abx500gpio_chip;
        pct->chip.dev = &pdev->dev;
-       pct->chip.base = (np) ? -1 : pdata->gpio_base;
-
-       if (platid)
-               id = platid->driver_data;
-       else if (np) {
-               const struct of_device_id *match;
+       pct->chip.base = -1; /* Dynamic allocation */
 
-               match = of_match_device(abx500_gpio_match, &pdev->dev);
-               if (match)
-                       id = (unsigned long)match->data;
+       match = of_match_device(abx500_gpio_match, &pdev->dev);
+       if (!match) {
+               dev_err(&pdev->dev, "gpio dt not matching\n");
+               return -ENODEV;
        }
+       id = (unsigned long)match->data;
 
        /* Poke in other ASIC variants here */
        switch (id) {
@@ -1349,14 +1339,6 @@ static int abx500_gpio_remove(struct platform_device *pdev)
        return 0;
 }
 
-static const struct platform_device_id abx500_pinctrl_id[] = {
-       { "pinctrl-ab8500", PINCTRL_AB8500 },
-       { "pinctrl-ab8540", PINCTRL_AB8540 },
-       { "pinctrl-ab9540", PINCTRL_AB9540 },
-       { "pinctrl-ab8505", PINCTRL_AB8505 },
-       { },
-};
-
 static struct platform_driver abx500_gpio_driver = {
        .driver = {
                .name = "abx500-gpio",
@@ -1365,7 +1347,6 @@ static struct platform_driver abx500_gpio_driver = {
        },
        .probe = abx500_gpio_probe,
        .remove = abx500_gpio_remove,
-       .id_table = abx500_pinctrl_id,
 };
 
 static int __init abx500_gpio_init(void)
index eeca8f97399923c462f43328b1850ad3da7ee77d..2beef3bfe9ca93f3857361a879e76e38ee7161ac 100644 (file)
@@ -1,4 +1,4 @@
-#ifndef PINCTRL_PINCTRL_ABx5O0_H
+#ifndef PINCTRL_PINCTRL_ABx500_H
 #define PINCTRL_PINCTRL_ABx500_H
 
 /* Package definitions */
@@ -15,6 +15,18 @@ enum abx500_pin_func {
        ABX500_ALT_C,
 };
 
+enum abx500_gpio_pull_updown {
+       ABX500_GPIO_PULL_DOWN = 0x0,
+       ABX500_GPIO_PULL_NONE = 0x1,
+       ABX500_GPIO_PULL_UP = 0x3,
+};
+
+enum abx500_gpio_vinsel {
+       ABX500_GPIO_VINSEL_VBAT = 0x0,
+       ABX500_GPIO_VINSEL_VIN_1V8 = 0x1,
+       ABX500_GPIO_VINSEL_VDD_BIF = 0x2,
+};
+
 /**
  * struct abx500_function - ABx500 pinctrl mux function
  * @name: The name of the function, exported to pinctrl core.
index 2832576d8b12ee7c99e24896c3fe333dd8cffadc..114f5ef4b73abdbcd02e524a1a34f84aeeb5b7cb 100644 (file)
@@ -512,6 +512,7 @@ static const struct dev_pm_ops byt_gpio_pm_ops = {
 
 static const struct acpi_device_id byt_gpio_acpi_match[] = {
        { "INT33B2", 0 },
+       { "INT33FC", 0 },
        { }
 };
 MODULE_DEVICE_TABLE(acpi, byt_gpio_acpi_match);
index f77914ac081a237684035a42be4e2252a945cdc8..17aecde1b51d912584765556188121fa82413795 100644 (file)
@@ -638,6 +638,13 @@ int imx1_pinctrl_core_probe(struct platform_device *pdev,
                return -EINVAL;
        }
 
+       ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
+       if (ret) {
+               pinctrl_unregister(ipctl->pctl);
+               dev_err(&pdev->dev, "Failed to populate subdevices\n");
+               return ret;
+       }
+
        dev_info(&pdev->dev, "initialized IMX pinctrl driver\n");
 
        return 0;
index 7111c3b591303cec2f3daa36d22329989c0847b9..6559e143676870d4fc63d589310a822257784e7d 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (C) 2008,2009 STMicroelectronics
  * Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it>
  *   Rewritten based on work by Prafulla WADASKAR <prafulla.wadaskar@st.com>
- * Copyright (C) 2011 Linus Walleij <linus.walleij@linaro.org>
+ * Copyright (C) 2011-2013 Linus Walleij <linus.walleij@linaro.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -33,7 +33,6 @@
 #include <linux/pinctrl/pinconf.h>
 /* Since we request GPIOs from ourself */
 #include <linux/pinctrl/consumer.h>
-#include <linux/platform_data/pinctrl-nomadik.h>
 #include "pinctrl-nomadik.h"
 #include "core.h"
 
  * Symbols in this file are called "nmk_gpio" for "nomadik gpio"
  */
 
+/*
+ * pin configurations are represented by 32-bit integers:
+ *
+ *     bit  0.. 8 - Pin Number (512 Pins Maximum)
+ *     bit  9..10 - Alternate Function Selection
+ *     bit 11..12 - Pull up/down state
+ *     bit     13 - Sleep mode behaviour
+ *     bit     14 - Direction
+ *     bit     15 - Value (if output)
+ *     bit 16..18 - SLPM pull up/down state
+ *     bit 19..20 - SLPM direction
+ *     bit 21..22 - SLPM Value (if output)
+ *     bit 23..25 - PDIS value (if input)
+ *     bit     26 - Gpio mode
+ *     bit     27 - Sleep mode
+ *
+ * to facilitate the definition, the following macros are provided
+ *
+ * PIN_CFG_DEFAULT - default config (0):
+ *                  pull up/down = disabled
+ *                  sleep mode = input/wakeup
+ *                  direction = input
+ *                  value = low
+ *                  SLPM direction = same as normal
+ *                  SLPM pull = same as normal
+ *                  SLPM value = same as normal
+ *
+ * PIN_CFG        - default config with alternate function
+ */
+
+typedef unsigned long pin_cfg_t;
+
+#define PIN_NUM_MASK           0x1ff
+#define PIN_NUM(x)             ((x) & PIN_NUM_MASK)
+
+#define PIN_ALT_SHIFT          9
+#define PIN_ALT_MASK           (0x3 << PIN_ALT_SHIFT)
+#define PIN_ALT(x)             (((x) & PIN_ALT_MASK) >> PIN_ALT_SHIFT)
+#define PIN_GPIO               (NMK_GPIO_ALT_GPIO << PIN_ALT_SHIFT)
+#define PIN_ALT_A              (NMK_GPIO_ALT_A << PIN_ALT_SHIFT)
+#define PIN_ALT_B              (NMK_GPIO_ALT_B << PIN_ALT_SHIFT)
+#define PIN_ALT_C              (NMK_GPIO_ALT_C << PIN_ALT_SHIFT)
+
+#define PIN_PULL_SHIFT         11
+#define PIN_PULL_MASK          (0x3 << PIN_PULL_SHIFT)
+#define PIN_PULL(x)            (((x) & PIN_PULL_MASK) >> PIN_PULL_SHIFT)
+#define PIN_PULL_NONE          (NMK_GPIO_PULL_NONE << PIN_PULL_SHIFT)
+#define PIN_PULL_UP            (NMK_GPIO_PULL_UP << PIN_PULL_SHIFT)
+#define PIN_PULL_DOWN          (NMK_GPIO_PULL_DOWN << PIN_PULL_SHIFT)
+
+#define PIN_SLPM_SHIFT         13
+#define PIN_SLPM_MASK          (0x1 << PIN_SLPM_SHIFT)
+#define PIN_SLPM(x)            (((x) & PIN_SLPM_MASK) >> PIN_SLPM_SHIFT)
+#define PIN_SLPM_MAKE_INPUT    (NMK_GPIO_SLPM_INPUT << PIN_SLPM_SHIFT)
+#define PIN_SLPM_NOCHANGE      (NMK_GPIO_SLPM_NOCHANGE << PIN_SLPM_SHIFT)
+/* These two replace the above in DB8500v2+ */
+#define PIN_SLPM_WAKEUP_ENABLE (NMK_GPIO_SLPM_WAKEUP_ENABLE << PIN_SLPM_SHIFT)
+#define PIN_SLPM_WAKEUP_DISABLE        (NMK_GPIO_SLPM_WAKEUP_DISABLE << PIN_SLPM_SHIFT)
+#define PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP PIN_SLPM_WAKEUP_DISABLE
+
+#define PIN_SLPM_GPIO  PIN_SLPM_WAKEUP_ENABLE /* In SLPM, pin is a gpio */
+#define PIN_SLPM_ALTFUNC PIN_SLPM_WAKEUP_DISABLE /* In SLPM, pin is altfunc */
+
+#define PIN_DIR_SHIFT          14
+#define PIN_DIR_MASK           (0x1 << PIN_DIR_SHIFT)
+#define PIN_DIR(x)             (((x) & PIN_DIR_MASK) >> PIN_DIR_SHIFT)
+#define PIN_DIR_INPUT          (0 << PIN_DIR_SHIFT)
+#define PIN_DIR_OUTPUT         (1 << PIN_DIR_SHIFT)
+
+#define PIN_VAL_SHIFT          15
+#define PIN_VAL_MASK           (0x1 << PIN_VAL_SHIFT)
+#define PIN_VAL(x)             (((x) & PIN_VAL_MASK) >> PIN_VAL_SHIFT)
+#define PIN_VAL_LOW            (0 << PIN_VAL_SHIFT)
+#define PIN_VAL_HIGH           (1 << PIN_VAL_SHIFT)
+
+#define PIN_SLPM_PULL_SHIFT    16
+#define PIN_SLPM_PULL_MASK     (0x7 << PIN_SLPM_PULL_SHIFT)
+#define PIN_SLPM_PULL(x)       \
+       (((x) & PIN_SLPM_PULL_MASK) >> PIN_SLPM_PULL_SHIFT)
+#define PIN_SLPM_PULL_NONE     \
+       ((1 + NMK_GPIO_PULL_NONE) << PIN_SLPM_PULL_SHIFT)
+#define PIN_SLPM_PULL_UP       \
+       ((1 + NMK_GPIO_PULL_UP) << PIN_SLPM_PULL_SHIFT)
+#define PIN_SLPM_PULL_DOWN     \
+       ((1 + NMK_GPIO_PULL_DOWN) << PIN_SLPM_PULL_SHIFT)
+
+#define PIN_SLPM_DIR_SHIFT     19
+#define PIN_SLPM_DIR_MASK      (0x3 << PIN_SLPM_DIR_SHIFT)
+#define PIN_SLPM_DIR(x)                \
+       (((x) & PIN_SLPM_DIR_MASK) >> PIN_SLPM_DIR_SHIFT)
+#define PIN_SLPM_DIR_INPUT     ((1 + 0) << PIN_SLPM_DIR_SHIFT)
+#define PIN_SLPM_DIR_OUTPUT    ((1 + 1) << PIN_SLPM_DIR_SHIFT)
+
+#define PIN_SLPM_VAL_SHIFT     21
+#define PIN_SLPM_VAL_MASK      (0x3 << PIN_SLPM_VAL_SHIFT)
+#define PIN_SLPM_VAL(x)                \
+       (((x) & PIN_SLPM_VAL_MASK) >> PIN_SLPM_VAL_SHIFT)
+#define PIN_SLPM_VAL_LOW       ((1 + 0) << PIN_SLPM_VAL_SHIFT)
+#define PIN_SLPM_VAL_HIGH      ((1 + 1) << PIN_SLPM_VAL_SHIFT)
+
+#define PIN_SLPM_PDIS_SHIFT            23
+#define PIN_SLPM_PDIS_MASK             (0x3 << PIN_SLPM_PDIS_SHIFT)
+#define PIN_SLPM_PDIS(x)       \
+       (((x) & PIN_SLPM_PDIS_MASK) >> PIN_SLPM_PDIS_SHIFT)
+#define PIN_SLPM_PDIS_NO_CHANGE                (0 << PIN_SLPM_PDIS_SHIFT)
+#define PIN_SLPM_PDIS_DISABLED         (1 << PIN_SLPM_PDIS_SHIFT)
+#define PIN_SLPM_PDIS_ENABLED          (2 << PIN_SLPM_PDIS_SHIFT)
+
+#define PIN_LOWEMI_SHIFT       25
+#define PIN_LOWEMI_MASK                (0x1 << PIN_LOWEMI_SHIFT)
+#define PIN_LOWEMI(x)          (((x) & PIN_LOWEMI_MASK) >> PIN_LOWEMI_SHIFT)
+#define PIN_LOWEMI_DISABLED    (0 << PIN_LOWEMI_SHIFT)
+#define PIN_LOWEMI_ENABLED     (1 << PIN_LOWEMI_SHIFT)
+
+#define PIN_GPIOMODE_SHIFT     26
+#define PIN_GPIOMODE_MASK      (0x1 << PIN_GPIOMODE_SHIFT)
+#define PIN_GPIOMODE(x)                (((x) & PIN_GPIOMODE_MASK) >> PIN_GPIOMODE_SHIFT)
+#define PIN_GPIOMODE_DISABLED  (0 << PIN_GPIOMODE_SHIFT)
+#define PIN_GPIOMODE_ENABLED   (1 << PIN_GPIOMODE_SHIFT)
+
+#define PIN_SLEEPMODE_SHIFT    27
+#define PIN_SLEEPMODE_MASK     (0x1 << PIN_SLEEPMODE_SHIFT)
+#define PIN_SLEEPMODE(x)       (((x) & PIN_SLEEPMODE_MASK) >> PIN_SLEEPMODE_SHIFT)
+#define PIN_SLEEPMODE_DISABLED (0 << PIN_SLEEPMODE_SHIFT)
+#define PIN_SLEEPMODE_ENABLED  (1 << PIN_SLEEPMODE_SHIFT)
+
+
+/* Shortcuts.  Use these instead of separate DIR, PULL, and VAL.  */
+#define PIN_INPUT_PULLDOWN     (PIN_DIR_INPUT | PIN_PULL_DOWN)
+#define PIN_INPUT_PULLUP       (PIN_DIR_INPUT | PIN_PULL_UP)
+#define PIN_INPUT_NOPULL       (PIN_DIR_INPUT | PIN_PULL_NONE)
+#define PIN_OUTPUT_LOW         (PIN_DIR_OUTPUT | PIN_VAL_LOW)
+#define PIN_OUTPUT_HIGH                (PIN_DIR_OUTPUT | PIN_VAL_HIGH)
+
+#define PIN_SLPM_INPUT_PULLDOWN        (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_DOWN)
+#define PIN_SLPM_INPUT_PULLUP  (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_UP)
+#define PIN_SLPM_INPUT_NOPULL  (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_NONE)
+#define PIN_SLPM_OUTPUT_LOW    (PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_LOW)
+#define PIN_SLPM_OUTPUT_HIGH   (PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_HIGH)
+
+#define PIN_CFG_DEFAULT                (0)
+
+#define PIN_CFG(num, alt)              \
+       (PIN_CFG_DEFAULT |\
+        (PIN_NUM(num) | PIN_##alt))
+
+#define PIN_CFG_INPUT(num, alt, pull)          \
+       (PIN_CFG_DEFAULT |\
+        (PIN_NUM(num) | PIN_##alt | PIN_INPUT_##pull))
+
+#define PIN_CFG_OUTPUT(num, alt, val)          \
+       (PIN_CFG_DEFAULT |\
+        (PIN_NUM(num) | PIN_##alt | PIN_OUTPUT_##val))
+
+/*
+ * "nmk_gpio" and "NMK_GPIO" stand for "Nomadik GPIO", leaving
+ * the "gpio" namespace for generic and cross-machine functions
+ */
+
+#define GPIO_BLOCK_SHIFT 5
+#define NMK_GPIO_PER_CHIP (1 << GPIO_BLOCK_SHIFT)
+
+/* Register in the logic block */
+#define NMK_GPIO_DAT   0x00
+#define NMK_GPIO_DATS  0x04
+#define NMK_GPIO_DATC  0x08
+#define NMK_GPIO_PDIS  0x0c
+#define NMK_GPIO_DIR   0x10
+#define NMK_GPIO_DIRS  0x14
+#define NMK_GPIO_DIRC  0x18
+#define NMK_GPIO_SLPC  0x1c
+#define NMK_GPIO_AFSLA 0x20
+#define NMK_GPIO_AFSLB 0x24
+#define NMK_GPIO_LOWEMI        0x28
+
+#define NMK_GPIO_RIMSC 0x40
+#define NMK_GPIO_FIMSC 0x44
+#define NMK_GPIO_IS    0x48
+#define NMK_GPIO_IC    0x4c
+#define NMK_GPIO_RWIMSC        0x50
+#define NMK_GPIO_FWIMSC        0x54
+#define NMK_GPIO_WKS   0x58
+/* These appear in DB8540 and later ASICs */
+#define NMK_GPIO_EDGELEVEL 0x5C
+#define NMK_GPIO_LEVEL 0x60
+
+
+/* Pull up/down values */
+enum nmk_gpio_pull {
+       NMK_GPIO_PULL_NONE,
+       NMK_GPIO_PULL_UP,
+       NMK_GPIO_PULL_DOWN,
+};
+
+/* Sleep mode */
+enum nmk_gpio_slpm {
+       NMK_GPIO_SLPM_INPUT,
+       NMK_GPIO_SLPM_WAKEUP_ENABLE = NMK_GPIO_SLPM_INPUT,
+       NMK_GPIO_SLPM_NOCHANGE,
+       NMK_GPIO_SLPM_WAKEUP_DISABLE = NMK_GPIO_SLPM_NOCHANGE,
+};
+
+/*
+ * Platform data to register a block: only the initial gpio/irq number.
+ */
+struct nmk_gpio_platform_data {
+       char *name;
+       int first_gpio;
+       int first_irq;
+       int num_gpio;
+       u32 (*get_secondary_status)(unsigned int bank);
+       void (*set_ioforce)(bool enable);
+       bool supports_sleepmode;
+};
+
 struct nmk_gpio_chip {
        struct gpio_chip chip;
        struct irq_domain *domain;
@@ -846,14 +1060,14 @@ static void nmk_gpio_dbg_show_one(struct seq_file *s,
                   (mode < 0) ? "unknown" : modes[mode],
                   pull ? "pull" : "none");
 
-       if (label && !is_out) {
-               int             irq = gpio_to_irq(gpio);
+       if (!is_out) {
+               int irq = gpio_to_irq(gpio);
                struct irq_desc *desc = irq_to_desc(irq);
 
                /* This races with request_irq(), set_irq_type(),
                 * and set_irq_wake() ... but those are "rare".
                 */
-               if (irq >= 0 && desc->action) {
+               if (irq > 0 && desc && desc->action) {
                        char *trigger;
                        u32 bitmask = nmk_gpio_get_bitmask(gpio);
 
@@ -1026,7 +1240,7 @@ static const struct irq_domain_ops nmk_gpio_irq_simple_ops = {
 
 static int nmk_gpio_probe(struct platform_device *dev)
 {
-       struct nmk_gpio_platform_data *pdata = dev->dev.platform_data;
+       struct nmk_gpio_platform_data *pdata;
        struct device_node *np = dev->dev.of_node;
        struct nmk_gpio_chip *nmk_chip;
        struct gpio_chip *chip;
@@ -1034,32 +1248,24 @@ static int nmk_gpio_probe(struct platform_device *dev)
        struct clk *clk;
        int secondary_irq;
        void __iomem *base;
-       int irq_start = 0;
        int irq;
        int ret;
 
-       if (!pdata && !np) {
-               dev_err(&dev->dev, "No platform data or device tree found\n");
-               return -ENODEV;
-       }
-
-       if (np) {
-               pdata = devm_kzalloc(&dev->dev, sizeof(*pdata), GFP_KERNEL);
-               if (!pdata)
-                       return -ENOMEM;
-
-               if (of_get_property(np, "st,supports-sleepmode", NULL))
-                       pdata->supports_sleepmode = true;
+       pdata = devm_kzalloc(&dev->dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               return -ENOMEM;
 
-               if (of_property_read_u32(np, "gpio-bank", &dev->id)) {
-                       dev_err(&dev->dev, "gpio-bank property not found\n");
-                       return -EINVAL;
-               }
+       if (of_get_property(np, "st,supports-sleepmode", NULL))
+               pdata->supports_sleepmode = true;
 
-               pdata->first_gpio = dev->id * NMK_GPIO_PER_CHIP;
-               pdata->num_gpio   = NMK_GPIO_PER_CHIP;
+       if (of_property_read_u32(np, "gpio-bank", &dev->id)) {
+               dev_err(&dev->dev, "gpio-bank property not found\n");
+               return -EINVAL;
        }
 
+       pdata->first_gpio = dev->id * NMK_GPIO_PER_CHIP;
+       pdata->num_gpio = NMK_GPIO_PER_CHIP;
+
        irq = platform_get_irq(dev, 0);
        if (irq < 0)
                return irq;
@@ -1107,10 +1313,7 @@ static int nmk_gpio_probe(struct platform_device *dev)
        clk_enable(nmk_chip->clk);
        nmk_chip->lowemi = readl_relaxed(nmk_chip->addr + NMK_GPIO_LOWEMI);
        clk_disable(nmk_chip->clk);
-
-#ifdef CONFIG_OF_GPIO
        chip->of_node = np;
-#endif
 
        ret = gpiochip_add(&nmk_chip->chip);
        if (ret)
@@ -1122,10 +1325,8 @@ static int nmk_gpio_probe(struct platform_device *dev)
 
        platform_set_drvdata(dev, nmk_chip);
 
-       if (!np)
-               irq_start = pdata->first_irq;
        nmk_chip->domain = irq_domain_add_simple(np,
-                               NMK_GPIO_PER_CHIP, irq_start,
+                               NMK_GPIO_PER_CHIP, 0,
                                &nmk_gpio_irq_simple_ops, nmk_chip);
        if (!nmk_chip->domain) {
                dev_err(&dev->dev, "failed to create irqdomain\n");
@@ -1858,11 +2059,10 @@ static int nmk_pinctrl_resume(struct platform_device *pdev)
 
 static int nmk_pinctrl_probe(struct platform_device *pdev)
 {
-       const struct platform_device_id *platid = platform_get_device_id(pdev);
+       const struct of_device_id *match;
        struct device_node *np = pdev->dev.of_node;
        struct device_node *prcm_np;
        struct nmk_pinctrl *npct;
-       struct resource *res;
        unsigned int version = 0;
        int i;
 
@@ -1870,16 +2070,10 @@ static int nmk_pinctrl_probe(struct platform_device *pdev)
        if (!npct)
                return -ENOMEM;
 
-       if (platid)
-               version = platid->driver_data;
-       else if (np) {
-               const struct of_device_id *match;
-
-               match = of_match_device(nmk_pinctrl_match, &pdev->dev);
-               if (!match)
-                       return -ENODEV;
-               version = (unsigned int) match->data;
-       }
+       match = of_match_device(nmk_pinctrl_match, &pdev->dev);
+       if (!match)
+               return -ENODEV;
+       version = (unsigned int) match->data;
 
        /* Poke in other ASIC variants here */
        if (version == PINCTRL_NMK_STN8815)
@@ -1889,17 +2083,9 @@ static int nmk_pinctrl_probe(struct platform_device *pdev)
        if (version == PINCTRL_NMK_DB8540)
                nmk_pinctrl_db8540_init(&npct->soc);
 
-       if (np) {
-               prcm_np = of_parse_phandle(np, "prcm", 0);
-               if (prcm_np)
-                       npct->prcm_base = of_iomap(prcm_np, 0);
-       }
-
-       /* Allow platform passed information to over-write DT. */
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (res)
-               npct->prcm_base = devm_ioremap(&pdev->dev, res->start,
-                                              resource_size(res));
+       prcm_np = of_parse_phandle(np, "prcm", 0);
+       if (prcm_np)
+               npct->prcm_base = of_iomap(prcm_np, 0);
        if (!npct->prcm_base) {
                if (version == PINCTRL_NMK_STN8815) {
                        dev_info(&pdev->dev,
@@ -1958,13 +2144,6 @@ static struct platform_driver nmk_gpio_driver = {
        .probe = nmk_gpio_probe,
 };
 
-static const struct platform_device_id nmk_pinctrl_id[] = {
-       { "pinctrl-stn8815", PINCTRL_NMK_STN8815 },
-       { "pinctrl-db8500", PINCTRL_NMK_DB8500 },
-       { "pinctrl-db8540", PINCTRL_NMK_DB8540 },
-       { }
-};
-
 static struct platform_driver nmk_pinctrl_driver = {
        .driver = {
                .owner = THIS_MODULE,
@@ -1972,7 +2151,6 @@ static struct platform_driver nmk_pinctrl_driver = {
                .of_match_table = nmk_pinctrl_match,
        },
        .probe = nmk_pinctrl_probe,
-       .id_table = nmk_pinctrl_id,
 #ifdef CONFIG_PM
        .suspend = nmk_pinctrl_suspend,
        .resume = nmk_pinctrl_resume,
index bcd4191e10ea8ced278c469799d521e4a82dee65..d8215f1e70c747c61df871f6a4181c52852d6dfc 100644 (file)
@@ -1,13 +1,23 @@
 #ifndef PINCTRL_PINCTRL_NOMADIK_H
 #define PINCTRL_PINCTRL_NOMADIK_H
 
-#include <linux/platform_data/pinctrl-nomadik.h>
-
 /* Package definitions */
 #define PINCTRL_NMK_STN8815    0
 #define PINCTRL_NMK_DB8500     1
 #define PINCTRL_NMK_DB8540     2
 
+/* Alternate functions: function C is set in hw by setting both A and B */
+#define NMK_GPIO_ALT_GPIO      0
+#define NMK_GPIO_ALT_A 1
+#define NMK_GPIO_ALT_B 2
+#define NMK_GPIO_ALT_C (NMK_GPIO_ALT_A | NMK_GPIO_ALT_B)
+
+#define NMK_GPIO_ALT_CX_SHIFT 2
+#define NMK_GPIO_ALT_C1        ((1<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
+#define NMK_GPIO_ALT_C2        ((2<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
+#define NMK_GPIO_ALT_C3        ((3<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
+#define NMK_GPIO_ALT_C4        ((4<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
+
 #define PRCM_GPIOCR_ALTCX(pin_num,\
        altc1_used, altc1_ri, altc1_cb,\
        altc2_used, altc2_ri, altc2_cb,\
index e939c28cbf1fe13573f7538a2e9d01071b094aa1..46dddc159286387dbbbe979d729d4d00cf159d43 100644 (file)
@@ -504,6 +504,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
                        data |= (3 << bit);
                        break;
                default:
+                       spin_unlock_irqrestore(&bank->slock, flags);
                        dev_err(info->dev, "unsupported pull setting %d\n",
                                pull);
                        return -EINVAL;
@@ -1453,8 +1454,8 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev)
        if (ctrl->type == RK3188) {
                res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
                info->reg_pull = devm_ioremap_resource(&pdev->dev, res);
-               if (IS_ERR(info->reg_base))
-                       return PTR_ERR(info->reg_base);
+               if (IS_ERR(info->reg_pull))
+                       return PTR_ERR(info->reg_pull);
        }
 
        ret = rockchip_gpiolib_register(pdev, info);
index 009174d07767ff71451ac70cb4ce4de8b50efdf1..bc5eb453a45ccfb7826e60825b75afed8de868a7 100644 (file)
@@ -3720,7 +3720,7 @@ static void __iomem *r8a7740_pinmux_portcr(struct sh_pfc *pfc, unsigned int pin)
                const struct r8a7740_portcr_group *group =
                        &r8a7740_portcr_offsets[i];
 
-               if (i <= group->end_pin)
+               if (pin <= group->end_pin)
                        return pfc->window->virt + group->offset + pin;
        }
 
index bf76a654c02f4d9d4f64b26e52c2e0acfadaa605..d26c16360161ae683026001d3d9ca93f4b425718 100644 (file)
@@ -1730,11 +1730,11 @@ static const unsigned int du_clk_out_1_pins[] = {
 static const unsigned int du_clk_out_1_mux[] = {
        DU1_DOTCLKOUT1_MARK
 };
-static const unsigned int du_sync_1_pins[] = {
+static const unsigned int du_sync_pins[] = {
        /* EXVSYNC/VSYNC, EXHSYNC/HSYNC, EXDISP/EXODDF/EXCDE */
        RCAR_GP_PIN(3, 29), RCAR_GP_PIN(3, 28), RCAR_GP_PIN(3, 27),
 };
-static const unsigned int du_sync_1_mux[] = {
+static const unsigned int du_sync_mux[] = {
        DU1_EXODDF_DU1_ODDF_DISP_CDE_MARK,
        DU1_EXVSYNC_DU1_VSYNC_MARK, DU1_EXHSYNC_DU1_HSYNC_MARK
 };
@@ -1742,6 +1742,9 @@ static const unsigned int du_cde_disp_pins[] = {
        /* CDE DISP */
        RCAR_GP_PIN(3, 31), RCAR_GP_PIN(3, 30),
 };
+static const unsigned int du_cde_disp_mux[] = {
+       DU1_CDE_MARK, DU1_DISP_MARK
+};
 static const unsigned int du0_clk_in_pins[] = {
        /* CLKIN */
        RCAR_GP_PIN(6, 31),
@@ -1749,15 +1752,26 @@ static const unsigned int du0_clk_in_pins[] = {
 static const unsigned int du0_clk_in_mux[] = {
        DU0_DOTCLKIN_MARK
 };
-static const unsigned int du_cde_disp_mux[] = {
-       DU1_CDE_MARK, DU1_DISP_MARK
-};
 static const unsigned int du1_clk_in_pins[] = {
        /* CLKIN */
-       RCAR_GP_PIN(7, 20), RCAR_GP_PIN(7, 19), RCAR_GP_PIN(3, 24),
+       RCAR_GP_PIN(3, 24),
 };
 static const unsigned int du1_clk_in_mux[] = {
-       DU1_DOTCLKIN_C_MARK, DU1_DOTCLKIN_B_MARK, DU1_DOTCLKIN_MARK
+       DU1_DOTCLKIN_MARK
+};
+static const unsigned int du1_clk_in_b_pins[] = {
+       /* CLKIN */
+       RCAR_GP_PIN(7, 19),
+};
+static const unsigned int du1_clk_in_b_mux[] = {
+       DU1_DOTCLKIN_B_MARK,
+};
+static const unsigned int du1_clk_in_c_pins[] = {
+       /* CLKIN */
+       RCAR_GP_PIN(7, 20),
+};
+static const unsigned int du1_clk_in_c_mux[] = {
+       DU1_DOTCLKIN_C_MARK,
 };
 /* - ETH -------------------------------------------------------------------- */
 static const unsigned int eth_link_pins[] = {
@@ -2670,10 +2684,12 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
        SH_PFC_PIN_GROUP(du_rgb888),
        SH_PFC_PIN_GROUP(du_clk_out_0),
        SH_PFC_PIN_GROUP(du_clk_out_1),
-       SH_PFC_PIN_GROUP(du_sync_1),
+       SH_PFC_PIN_GROUP(du_sync),
        SH_PFC_PIN_GROUP(du_cde_disp),
        SH_PFC_PIN_GROUP(du0_clk_in),
        SH_PFC_PIN_GROUP(du1_clk_in),
+       SH_PFC_PIN_GROUP(du1_clk_in_b),
+       SH_PFC_PIN_GROUP(du1_clk_in_c),
        SH_PFC_PIN_GROUP(eth_link),
        SH_PFC_PIN_GROUP(eth_magic),
        SH_PFC_PIN_GROUP(eth_mdio),
@@ -2805,7 +2821,7 @@ static const char * const du_groups[] = {
        "du_rgb888",
        "du_clk_out_0",
        "du_clk_out_1",
-       "du_sync_1",
+       "du_sync",
        "du_cde_disp",
 };
 
@@ -2815,6 +2831,8 @@ static const char * const du0_groups[] = {
 
 static const char * const du1_groups[] = {
        "du1_clk_in",
+       "du1_clk_in_b",
+       "du1_clk_in_c",
 };
 
 static const char * const eth_groups[] = {
index 70b522d348218e43dad2952f9c54b3c90c18c215..cc097b6938208ea029902f8dc2f68af548f9429a 100644 (file)
@@ -2584,7 +2584,7 @@ static void __iomem *sh7372_pinmux_portcr(struct sh_pfc *pfc, unsigned int pin)
                const struct sh7372_portcr_group *group =
                        &sh7372_portcr_offsets[i];
 
-               if (i <= group->end_pin)
+               if (pin <= group->end_pin)
                        return pfc->window->virt + group->offset + pin;
        }
 
index c9076bdaf2c18fc9a34c3d3f906cd333971f57e5..c91f69b39db4b8c637d5182eb5f8f85aed1bf79b 100644 (file)
@@ -41,8 +41,6 @@
 #include <linux/slab.h>
 #include <linux/input.h>
 #include <linux/input/sparse-keymap.h>
-
-#include <acpi/acpi_drivers.h>
 #include <acpi/video.h>
 
 MODULE_AUTHOR("Carlos Corbacho");
index 594323a926cf0b8c62c4accfd88d297fe0caa567..7f4dc6f51f8afdf9df7984818585e10bf2047280 100644 (file)
@@ -53,8 +53,7 @@
 #include <linux/rfkill.h>
 #include <linux/slab.h>
 #include <linux/dmi.h>
-#include <acpi/acpi_drivers.h>
-#include <acpi/acpi_bus.h>
+#include <linux/acpi.h>
 
 #define ASUS_LAPTOP_VERSION    "0.42"
 
index 19c313b056c334c771e678b05146ee7676e7edac..df7ecb9ecd9d7c95b66cdbc79f4f17bfaf4bf49c 100644 (file)
@@ -45,8 +45,7 @@
 #include <linux/seq_file.h>
 #include <linux/platform_device.h>
 #include <linux/thermal.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
 #include <acpi/video.h>
 
 #include "asus-wmi.h"
index 6dfa8d3b4eec22dfd826e6d7de7cc811d565340b..70d355a9ae2cc2f7cdc2efb04941a2c76688139f 100644 (file)
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
 #include <linux/backlight.h>
 #include <linux/input.h>
 #include <linux/rfkill.h>
 
 MODULE_LICENSE("GPL");
 
-
 struct cmpc_accel {
        int sensitivity;
        int g_select;
index bcf8cc6b5537cca1a1c3ad016d700ca3f30104a4..dbc97a33bbc8ea2cbd61590590f533c13680a3a4 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/types.h>
 #include <linux/input.h>
 #include <linux/input/sparse-keymap.h>
-#include <acpi/acpi_drivers.h>
 #include <linux/acpi.h>
 #include <linux/string.h>
 
index 60e0900bc117995e6373bfb5bedfcc1c8aac2aed..390e8e33d5e31b77d67c7d7a1a8c659ead20e791 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/types.h>
 #include <linux/input.h>
 #include <linux/input/sparse-keymap.h>
-#include <acpi/acpi_drivers.h>
 #include <linux/acpi.h>
 #include <linux/string.h>
 #include <linux/dmi.h>
index dec68e7a99c79482f5f7cf4eb78b98bd0e2cd58d..bcde1ea02dd36ecb7024292cf03187edeab1fdd6 100644 (file)
@@ -28,8 +28,7 @@
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
 #include <linux/slab.h>
-#include <acpi/acpi_drivers.h>
-#include <acpi/acpi_bus.h>
+#include <linux/acpi.h>
 #include <linux/uaccess.h>
 #include <linux/input.h>
 #include <linux/input/sparse-keymap.h>
index af67e6e56ebbf3165d6c315daf6e88b155328d8f..6112933f627834cc1c4561feb68a3edc28492e5e 100644 (file)
@@ -33,7 +33,7 @@
 #include <linux/input/sparse-keymap.h>
 #include <linux/dmi.h>
 #include <linux/fb.h>
-#include <acpi/acpi_bus.h>
+#include <linux/acpi.h>
 
 #include "asus-wmi.h"
 
index a8e43cf70fac96309d7b689265b7c2b6ba2a19db..aff4d0670edfec733e131c0137fd82f70e0d2206 100644 (file)
@@ -36,7 +36,7 @@
 #include <linux/uaccess.h>
 #include <linux/leds.h>
 #include <linux/atomic.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
 #include "../../misc/lis3lv02d/lis3lv02d.h"
 
 #define DRIVER_NAME     "hp_accel"
index 19ec95147f6925d1de52e99886f7efc6a10dff7a..6dd060a0bb65293d47a2d02669a62785403b8ae0 100644 (file)
@@ -26,8 +26,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
 #include <linux/rfkill.h>
 #include <linux/platform_device.h>
 #include <linux/input.h>
index a2083a9e5662d660fd95cbb297815aa0570c8268..d45bca34bf1b3bc935f5dc9b729fd87219cf4825 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
 
 MODULE_LICENSE("GPL");
 
index 1838400dc0360615f799fac64a82b51f7efb9c17..04cf5dffdfd9152436719e69955df00afe30e144 100644 (file)
@@ -19,7 +19,7 @@
 
 #include <linux/init.h>
 #include <linux/module.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
 
 MODULE_LICENSE("GPL");
 
index 11244f8703c402c876fb34b0e107383781661416..e8b46d2c468c963b37f338534b40aad814ac8792 100644 (file)
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/pm.h>
-
 #include <linux/thermal.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
 
 MODULE_AUTHOR("Thomas Sujith");
 MODULE_AUTHOR("Zhang Rui");
index f6f18cde0f11c70f035e88c1da80f96506e0b3ab..4bc96041678573ec89eed8cf8c0e185f7e53d864 100644 (file)
@@ -50,9 +50,6 @@
 #include <linux/platform_device.h>
 #include <linux/dmi.h>
 #include <linux/rfkill.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
-
 
 #define DRIVER_NAME    "intel_oaktrail"
 #define DRIVER_VERSION "0.4ac1"
index 0aea63b3729a4481ece3bc5d1c8dfb041fe0f2bc..3c59c0a3ee0f0f2d57a895f853d6915c37d39822 100644 (file)
@@ -20,8 +20,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
 
 MODULE_AUTHOR("Dave Airlie");
 MODULE_DESCRIPTION("MXM WMI Driver");
index 3008fd20572e96a2d93823c4d15db27592fed2e2..609d38779b2680175660557b1093fa1026c91aad 100644 (file)
 #include <linux/seq_file.h>
 #include <linux/uaccess.h>
 #include <linux/slab.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
 #include <linux/input.h>
 #include <linux/input/sparse-keymap.h>
 
-
 #ifndef ACPI_HOTKEY_COMPONENT
 #define ACPI_HOTKEY_COMPONENT  0x10000000
 #endif
index 47ae0c47d4b5ccf67749cc110f86788e7c74753f..c9f6e511daa639f9656f6e96de7603be944e934b 100644 (file)
@@ -24,8 +24,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
 
 MODULE_AUTHOR("Hu Tao <hutao@cn.fujitsu.com>");
 MODULE_DESCRIPTION("pvpanic device driver");
index cae7098e9b0d70adf271eb9c31a1e833919a54b1..5413f62d2e6136b62327abdd0d32c8f000b3c531 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/platform_device.h>
 #include <linux/backlight.h>
 #include <linux/dmi.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
 
 #define SAMSUNGQ10_BL_MAX_INTENSITY 7
 
index fb233ae7bb0e3e8374691818cfe61125e66371a5..563e4f595f836c1d1ad966688d61c33e4a8d33d5 100644 (file)
@@ -61,9 +61,6 @@
 #include <linux/workqueue.h>
 #include <linux/acpi.h>
 #include <linux/slab.h>
-#include <acpi/acpi_drivers.h>
-#include <acpi/acpi_bus.h>
-#include <asm/uaccess.h>
 #include <linux/sonypi.h>
 #include <linux/sony-laptop.h>
 #include <linux/rfkill.h>
@@ -71,6 +68,7 @@
 #include <linux/poll.h>
 #include <linux/miscdevice.h>
 #endif
+#include <asm/uaccess.h>
 
 #define dprintk(fmt, ...)                      \
 do {                                           \
index 9b93fdb61ed7c03733ead31aaa7f0ef632a6bd00..6a6ea28a7e51df054ff2f514fde39d7d9f10b264 100644 (file)
@@ -32,9 +32,7 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <acpi/acpi.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
 #include <linux/platform_device.h>
 
 #define GUID "C364AC71-36DB-495A-8494-B439D472A505"
index 58b0274d24cc2968e35e6a9cdad75b1533c35e2d..defb6afc1409cc7fff0863d6829c5c26478b6a4a 100644 (file)
@@ -61,7 +61,6 @@
 #include <linux/freezer.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-
 #include <linux/nvram.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/input.h>
 #include <linux/leds.h>
 #include <linux/rfkill.h>
-#include <asm/uaccess.h>
-
 #include <linux/dmi.h>
 #include <linux/jiffies.h>
 #include <linux/workqueue.h>
-
+#include <linux/acpi.h>
+#include <linux/pci_ids.h>
+#include <linux/thinkpad_acpi.h>
 #include <sound/core.h>
 #include <sound/control.h>
 #include <sound/initval.h>
-
-#include <acpi/acpi_drivers.h>
-
-#include <linux/pci_ids.h>
-
-#include <linux/thinkpad_acpi.h>
+#include <asm/uaccess.h>
 
 /* ThinkPad CMOS commands */
 #define TP_CMOS_VOLUME_DOWN    0
index 7fce391818d30a183962b7888a8bfd275b10423c..7ad1ed091f9225fc572a1b70fde9ecf622d06ad1 100644 (file)
 #include <linux/slab.h>
 #include <linux/workqueue.h>
 #include <linux/i8042.h>
-
+#include <linux/acpi.h>
 #include <asm/uaccess.h>
 
-#include <acpi/acpi_drivers.h>
-
 MODULE_AUTHOR("John Belmonte");
 MODULE_DESCRIPTION("Toshiba Laptop ACPI Extras Driver");
 MODULE_LICENSE("GPL");
index 74dd01ae343b01f5f5a9827c5ec02f11ceee61b5..2cb1ea62b4a7f9ac7b268adadb251105be279923 100644 (file)
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
 
 MODULE_AUTHOR("Jes Sorensen <Jes.Sorensen@gmail.com>");
 MODULE_DESCRIPTION("Toshiba Laptop ACPI Bluetooth Enable Driver");
 MODULE_LICENSE("GPL");
 
-
 static int toshiba_bt_rfkill_add(struct acpi_device *device);
 static int toshiba_bt_rfkill_remove(struct acpi_device *device);
 static void toshiba_bt_rfkill_notify(struct acpi_device *device, u32 event);
index c2e7b2657aeb31bf5ab50a4f8a8821e2ad53f696..43d13295e63d53a50b62dae995d3a63b7e112a3a 100644 (file)
@@ -37,8 +37,6 @@
 #include <linux/acpi.h>
 #include <linux/slab.h>
 #include <linux/module.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
 
 ACPI_MODULE_NAME("wmi");
 MODULE_AUTHOR("Carlos Corbacho");
index 4b1377bd59446a50405e00414418adf9ac8f8381..49cbccec6e2de1ecffa260348c3582e609ba1507 100644 (file)
@@ -18,8 +18,7 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/input.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
 
 #define MODULE_NAME "xo15-ebook"
 
index 6936e0acedcd6bfce4b8166bb4b8da6a922e0f47..f748cc8cbb031cf3ad3fd943688fc6172a452bd2 100644 (file)
@@ -197,6 +197,11 @@ static int pnp_bus_freeze(struct device *dev)
        return __pnp_bus_suspend(dev, PMSG_FREEZE);
 }
 
+static int pnp_bus_poweroff(struct device *dev)
+{
+       return __pnp_bus_suspend(dev, PMSG_HIBERNATE);
+}
+
 static int pnp_bus_resume(struct device *dev)
 {
        struct pnp_dev *pnp_dev = to_pnp_dev(dev);
@@ -234,9 +239,14 @@ static int pnp_bus_resume(struct device *dev)
 }
 
 static const struct dev_pm_ops pnp_bus_dev_pm_ops = {
+       /* Suspend callbacks */
        .suspend = pnp_bus_suspend,
-       .freeze = pnp_bus_freeze,
        .resume = pnp_bus_resume,
+       /* Hibernate callbacks */
+       .freeze = pnp_bus_freeze,
+       .thaw = pnp_bus_resume,
+       .poweroff = pnp_bus_poweroff,
+       .restore = pnp_bus_resume,
 };
 
 struct bus_type pnp_bus_type = {
index 14655a0f0431b35bd9a0988b669c510a162155e3..156d14e2587e1ede2cfb0e6c93266a9d1735be73 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/pnp.h>
 #include <linux/slab.h>
 #include <linux/mod_devicetable.h>
-#include <acpi/acpi_bus.h>
 
 #include "../base.h"
 #include "pnpacpi.h"
@@ -329,20 +328,15 @@ static int __init acpi_pnp_match(struct device *dev, void *_pnp)
            && compare_pnp_id(pnp->id, acpi_device_hid(acpi));
 }
 
-static int __init acpi_pnp_find_device(struct device *dev, acpi_handle * handle)
+static struct acpi_device * __init acpi_pnp_find_companion(struct device *dev)
 {
-       struct device *adev;
-       struct acpi_device *acpi;
-
-       adev = bus_find_device(&acpi_bus_type, NULL,
-                              to_pnp_dev(dev), acpi_pnp_match);
-       if (!adev)
-               return -ENODEV;
+       dev = bus_find_device(&acpi_bus_type, NULL, to_pnp_dev(dev),
+                             acpi_pnp_match);
+       if (!dev)
+               return NULL;
 
-       acpi = to_acpi_device(adev);
-       *handle = acpi->handle;
-       put_device(adev);
-       return 0;
+       put_device(dev);
+       return to_acpi_device(dev);
 }
 
 /* complete initialization of a PNPACPI device includes having
@@ -356,7 +350,7 @@ static bool acpi_pnp_bus_match(struct device *dev)
 static struct acpi_bus_type __initdata acpi_pnp_bus = {
        .name        = "PNP",
        .match       = acpi_pnp_bus_match,
-       .find_device = acpi_pnp_find_device,
+       .find_companion = acpi_pnp_find_companion,
 };
 
 int pnpacpi_disabled __initdata;
index 3e60225b0227b2d6ff8f0c2ad863f195256c4b2e..051ef9699777519951c2c87b2e39c6dc5b69d27c 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef ACPI_PNP_H
 #define ACPI_PNP_H
 
-#include <acpi/acpi_bus.h>
 #include <linux/acpi.h>
 #include <linux/pnp.h>
 
index 5e2054afe840e9d6412a28c5250f34d1017aa7b2..85ad58c6da17233a9503650500b69579887c84bb 100644 (file)
@@ -196,6 +196,7 @@ config BATTERY_MAX17040
 config BATTERY_MAX17042
        tristate "Maxim MAX17042/17047/17050/8997/8966 Fuel Gauge"
        depends on I2C
+       select REGMAP_I2C
        help
          MAX17042 is fuel-gauge systems for lithium-ion (Li+) batteries
          in handheld and portable equipment. The MAX17042 is configured
index 00e6672963601754262ced9e842f31c27e07c69e..6aac23cc65663ada046958869dc6d5b8b32e9648 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/device.h>
+#include <linux/notifier.h>
 #include <linux/err.h>
 #include <linux/power_supply.h>
 #include <linux/thermal.h>
@@ -24,6 +25,9 @@
 struct class *power_supply_class;
 EXPORT_SYMBOL_GPL(power_supply_class);
 
+ATOMIC_NOTIFIER_HEAD(power_supply_notifier);
+EXPORT_SYMBOL_GPL(power_supply_notifier);
+
 static struct device_type power_supply_dev_type;
 
 static bool __power_supply_is_supplied_by(struct power_supply *supplier,
@@ -80,6 +84,8 @@ static void power_supply_changed_work(struct work_struct *work)
                class_for_each_device(power_supply_class, NULL, psy,
                                      __power_supply_changed_work);
                power_supply_update_leds(psy);
+               atomic_notifier_call_chain(&power_supply_notifier,
+                               PSY_EVENT_PROP_CHANGED, psy);
                kobject_uevent(&psy->dev->kobj, KOBJ_CHANGE);
                spin_lock_irqsave(&psy->changed_lock, flags);
        }
@@ -347,6 +353,18 @@ static void power_supply_dev_release(struct device *dev)
        kfree(dev);
 }
 
+int power_supply_reg_notifier(struct notifier_block *nb)
+{
+       return atomic_notifier_chain_register(&power_supply_notifier, nb);
+}
+EXPORT_SYMBOL_GPL(power_supply_reg_notifier);
+
+void power_supply_unreg_notifier(struct notifier_block *nb)
+{
+       atomic_notifier_chain_unregister(&power_supply_notifier, nb);
+}
+EXPORT_SYMBOL_GPL(power_supply_unreg_notifier);
+
 #ifdef CONFIG_THERMAL
 static int power_supply_read_temp(struct thermal_zone_device *tzd,
                unsigned long *temp)
@@ -511,6 +529,10 @@ int power_supply_register(struct device *parent, struct power_supply *psy)
        dev_set_drvdata(dev, psy);
        psy->dev = dev;
 
+       rc = dev_set_name(dev, "%s", psy->name);
+       if (rc)
+               goto dev_set_name_failed;
+
        INIT_WORK(&psy->changed_work, power_supply_changed_work);
 
        rc = power_supply_check_supplies(psy);
@@ -524,10 +546,6 @@ int power_supply_register(struct device *parent, struct power_supply *psy)
        if (rc)
                goto wakeup_init_failed;
 
-       rc = kobject_set_name(&dev->kobj, "%s", psy->name);
-       if (rc)
-               goto kobject_set_name_failed;
-
        rc = device_add(dev);
        if (rc)
                goto device_add_failed;
@@ -553,11 +571,11 @@ create_triggers_failed:
 register_cooler_failed:
        psy_unregister_thermal(psy);
 register_thermal_failed:
-wakeup_init_failed:
        device_del(dev);
-kobject_set_name_failed:
 device_add_failed:
+wakeup_init_failed:
 check_supplies_failed:
+dev_set_name_failed:
        put_device(dev);
 success:
        return rc;
index 8d0fe431dbdd54ef0c175c06dbbc4b5d76f6d9cd..84419af16f777095687eddb59d74c7ca6762e3bb 100644 (file)
@@ -377,9 +377,14 @@ static void create_power_zone_common_attributes(
        if (power_zone->ops->get_max_energy_range_uj)
                power_zone->zone_dev_attrs[count++] =
                                        &dev_attr_max_energy_range_uj.attr;
-       if (power_zone->ops->get_energy_uj)
+       if (power_zone->ops->get_energy_uj) {
+               if (power_zone->ops->reset_energy_uj)
+                       dev_attr_energy_uj.attr.mode = S_IWUSR | S_IRUGO;
+               else
+                       dev_attr_energy_uj.attr.mode = S_IRUGO;
                power_zone->zone_dev_attrs[count++] =
                                        &dev_attr_energy_uj.attr;
+       }
        if (power_zone->ops->get_power_uw)
                power_zone->zone_dev_attrs[count++] =
                                        &dev_attr_power_uw.attr;
index eece329d78729049c4dd7b2e49668217309a5668..7acab93d5a47effcb69a94062efb33fe16ffda24 100644 (file)
@@ -90,6 +90,16 @@ config PWM_JZ4740
          To compile this driver as a module, choose M here: the module
          will be called pwm-jz4740.
 
+config PWM_LP3943
+       tristate "TI/National Semiconductor LP3943 PWM support"
+       depends on MFD_LP3943
+       help
+         Generic PWM framework driver for LP3943 which supports two PWM
+         channels.
+
+         To compile this driver as a module, choose M here: the module
+         will be called pwm-lp3943.
+
 config PWM_LPC32XX
        tristate "LPC32XX PWM support"
        depends on ARCH_LPC32XX
index 8b754e4dba4aae03cc36562d5e0c079e6327c4d2..4abf337dcd0231759d0450943516b3d45026c02b 100644 (file)
@@ -6,6 +6,7 @@ obj-$(CONFIG_PWM_BFIN)          += pwm-bfin.o
 obj-$(CONFIG_PWM_EP93XX)       += pwm-ep93xx.o
 obj-$(CONFIG_PWM_IMX)          += pwm-imx.o
 obj-$(CONFIG_PWM_JZ4740)       += pwm-jz4740.o
+obj-$(CONFIG_PWM_LP3943)       += pwm-lp3943.o
 obj-$(CONFIG_PWM_LPC32XX)      += pwm-lpc32xx.o
 obj-$(CONFIG_PWM_MXS)          += pwm-mxs.o
 obj-$(CONFIG_PWM_PCA9685)      += pwm-pca9685.o
diff --git a/drivers/pwm/pwm-lp3943.c b/drivers/pwm/pwm-lp3943.c
new file mode 100644 (file)
index 0000000..8a843a0
--- /dev/null
@@ -0,0 +1,314 @@
+/*
+ * TI/National Semiconductor LP3943 PWM driver
+ *
+ * Copyright 2013 Texas Instruments
+ *
+ * Author: Milo Kim <milo.kim@ti.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.
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/mfd/lp3943.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/slab.h>
+
+#define LP3943_MAX_DUTY                        255
+#define LP3943_MIN_PERIOD              6250
+#define LP3943_MAX_PERIOD              1600000
+
+struct lp3943_pwm {
+       struct pwm_chip chip;
+       struct lp3943 *lp3943;
+       struct lp3943_platform_data *pdata;
+};
+
+static inline struct lp3943_pwm *to_lp3943_pwm(struct pwm_chip *_chip)
+{
+       return container_of(_chip, struct lp3943_pwm, chip);
+}
+
+static struct lp3943_pwm_map *
+lp3943_pwm_request_map(struct lp3943_pwm *lp3943_pwm, int hwpwm)
+{
+       struct lp3943_platform_data *pdata = lp3943_pwm->pdata;
+       struct lp3943 *lp3943 = lp3943_pwm->lp3943;
+       struct lp3943_pwm_map *pwm_map;
+       int i, offset;
+
+       pwm_map = kzalloc(sizeof(*pwm_map), GFP_KERNEL);
+       if (!pwm_map)
+               return ERR_PTR(-ENOMEM);
+
+       pwm_map->output = pdata->pwms[hwpwm]->output;
+       pwm_map->num_outputs = pdata->pwms[hwpwm]->num_outputs;
+
+       for (i = 0; i < pwm_map->num_outputs; i++) {
+               offset = pwm_map->output[i];
+
+               /* Return an error if the pin is already assigned */
+               if (test_and_set_bit(offset, &lp3943->pin_used))
+                       return ERR_PTR(-EBUSY);
+       }
+
+       return pwm_map;
+}
+
+static int lp3943_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+       struct lp3943_pwm *lp3943_pwm = to_lp3943_pwm(chip);
+       struct lp3943_pwm_map *pwm_map;
+
+       pwm_map = lp3943_pwm_request_map(lp3943_pwm, pwm->hwpwm);
+       if (IS_ERR(pwm_map))
+               return PTR_ERR(pwm_map);
+
+       return pwm_set_chip_data(pwm, pwm_map);
+}
+
+static void lp3943_pwm_free_map(struct lp3943_pwm *lp3943_pwm,
+                               struct lp3943_pwm_map *pwm_map)
+{
+       struct lp3943 *lp3943 = lp3943_pwm->lp3943;
+       int i, offset;
+
+       for (i = 0; i < pwm_map->num_outputs; i++) {
+               offset = pwm_map->output[i];
+               clear_bit(offset, &lp3943->pin_used);
+       }
+
+       kfree(pwm_map);
+}
+
+static void lp3943_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+       struct lp3943_pwm *lp3943_pwm = to_lp3943_pwm(chip);
+       struct lp3943_pwm_map *pwm_map = pwm_get_chip_data(pwm);
+
+       lp3943_pwm_free_map(lp3943_pwm, pwm_map);
+}
+
+static int lp3943_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
+                            int duty_ns, int period_ns)
+{
+       struct lp3943_pwm *lp3943_pwm = to_lp3943_pwm(chip);
+       struct lp3943 *lp3943 = lp3943_pwm->lp3943;
+       u8 val, reg_duty, reg_prescale;
+       int err;
+
+       /*
+        * How to configure the LP3943 PWMs
+        *
+        * 1) Period = 6250 ~ 1600000
+        * 2) Prescale = period / 6250 -1
+        * 3) Duty = input duty
+        *
+        * Prescale and duty are register values
+        */
+
+       if (pwm->hwpwm == 0) {
+               reg_prescale = LP3943_REG_PRESCALE0;
+               reg_duty     = LP3943_REG_PWM0;
+       } else {
+               reg_prescale = LP3943_REG_PRESCALE1;
+               reg_duty     = LP3943_REG_PWM1;
+       }
+
+       period_ns = clamp(period_ns, LP3943_MIN_PERIOD, LP3943_MAX_PERIOD);
+       val       = (u8)(period_ns / LP3943_MIN_PERIOD - 1);
+
+       err = lp3943_write_byte(lp3943, reg_prescale, val);
+       if (err)
+               return err;
+
+       val = (u8)(duty_ns * LP3943_MAX_DUTY / period_ns);
+
+       return lp3943_write_byte(lp3943, reg_duty, val);
+}
+
+static int lp3943_pwm_set_mode(struct lp3943_pwm *lp3943_pwm,
+                              struct lp3943_pwm_map *pwm_map,
+                              u8 val)
+{
+       struct lp3943 *lp3943 = lp3943_pwm->lp3943;
+       const struct lp3943_reg_cfg *mux = lp3943->mux_cfg;
+       int i, index, err;
+
+       for (i = 0; i < pwm_map->num_outputs; i++) {
+               index = pwm_map->output[i];
+               err = lp3943_update_bits(lp3943, mux[index].reg,
+                                        mux[index].mask,
+                                        val << mux[index].shift);
+               if (err)
+                       return err;
+       }
+
+       return 0;
+}
+
+static int lp3943_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+       struct lp3943_pwm *lp3943_pwm = to_lp3943_pwm(chip);
+       struct lp3943_pwm_map *pwm_map = pwm_get_chip_data(pwm);
+       u8 val;
+
+       if (pwm->hwpwm == 0)
+               val = LP3943_DIM_PWM0;
+       else
+               val = LP3943_DIM_PWM1;
+
+       /*
+        * Each PWM generator is set to control any of outputs of LP3943.
+        * To enable/disable the PWM, these output pins should be configured.
+        */
+
+       return lp3943_pwm_set_mode(lp3943_pwm, pwm_map, val);
+}
+
+static void lp3943_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+       struct lp3943_pwm *lp3943_pwm = to_lp3943_pwm(chip);
+       struct lp3943_pwm_map *pwm_map = pwm_get_chip_data(pwm);
+
+       /*
+        * LP3943 outputs are open-drain, so the pin should be configured
+        * when the PWM is disabled.
+        */
+
+       lp3943_pwm_set_mode(lp3943_pwm, pwm_map, LP3943_GPIO_OUT_HIGH);
+}
+
+static const struct pwm_ops lp3943_pwm_ops = {
+       .request        = lp3943_pwm_request,
+       .free           = lp3943_pwm_free,
+       .config         = lp3943_pwm_config,
+       .enable         = lp3943_pwm_enable,
+       .disable        = lp3943_pwm_disable,
+       .owner          = THIS_MODULE,
+};
+
+static int lp3943_pwm_parse_dt(struct device *dev,
+                              struct lp3943_pwm *lp3943_pwm)
+{
+       static const char * const name[] = { "ti,pwm0", "ti,pwm1", };
+       struct device_node *node = dev->of_node;
+       struct lp3943_platform_data *pdata;
+       struct lp3943_pwm_map *pwm_map;
+       enum lp3943_pwm_output *output;
+       int i, err, proplen, count = 0;
+       u32 num_outputs;
+
+       if (!node)
+               return -EINVAL;
+
+       pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               return -ENOMEM;
+
+       /*
+        * Read the output map configuration from the device tree.
+        * Each of the two PWM generators can drive zero or more outputs.
+        */
+
+       for (i = 0; i < LP3943_NUM_PWMS; i++) {
+               if (!of_get_property(node, name[i], &proplen))
+                       continue;
+
+               num_outputs = proplen / sizeof(u32);
+               if (num_outputs == 0)
+                       continue;
+
+               output = devm_kzalloc(dev, sizeof(*output) * num_outputs,
+                                     GFP_KERNEL);
+               if (!output)
+                       return -ENOMEM;
+
+               err = of_property_read_u32_array(node, name[i], output,
+                                                num_outputs);
+               if (err)
+                       return err;
+
+               pwm_map = devm_kzalloc(dev, sizeof(*pwm_map), GFP_KERNEL);
+               if (!pwm_map)
+                       return -ENOMEM;
+
+               pwm_map->output = output;
+               pwm_map->num_outputs = num_outputs;
+               pdata->pwms[i] = pwm_map;
+
+               count++;
+       }
+
+       if (count == 0)
+               return -ENODATA;
+
+       lp3943_pwm->pdata = pdata;
+       return 0;
+}
+
+static int lp3943_pwm_probe(struct platform_device *pdev)
+{
+       struct lp3943 *lp3943 = dev_get_drvdata(pdev->dev.parent);
+       struct lp3943_pwm *lp3943_pwm;
+       int ret;
+
+       lp3943_pwm = devm_kzalloc(&pdev->dev, sizeof(*lp3943_pwm), GFP_KERNEL);
+       if (!lp3943_pwm)
+               return -ENOMEM;
+
+       lp3943_pwm->pdata = lp3943->pdata;
+       if (!lp3943_pwm->pdata) {
+               if (IS_ENABLED(CONFIG_OF))
+                       ret = lp3943_pwm_parse_dt(&pdev->dev, lp3943_pwm);
+               else
+                       ret = -ENODEV;
+
+               if (ret)
+                       return ret;
+       }
+
+       lp3943_pwm->lp3943 = lp3943;
+       lp3943_pwm->chip.dev = &pdev->dev;
+       lp3943_pwm->chip.ops = &lp3943_pwm_ops;
+       lp3943_pwm->chip.npwm = LP3943_NUM_PWMS;
+
+       platform_set_drvdata(pdev, lp3943_pwm);
+
+       return pwmchip_add(&lp3943_pwm->chip);
+}
+
+static int lp3943_pwm_remove(struct platform_device *pdev)
+{
+       struct lp3943_pwm *lp3943_pwm = platform_get_drvdata(pdev);
+
+       return pwmchip_remove(&lp3943_pwm->chip);
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id lp3943_pwm_of_match[] = {
+       { .compatible = "ti,lp3943-pwm", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, lp3943_pwm_of_match);
+#endif
+
+static struct platform_driver lp3943_pwm_driver = {
+       .probe = lp3943_pwm_probe,
+       .remove = lp3943_pwm_remove,
+       .driver = {
+               .name = "lp3943-pwm",
+               .owner = THIS_MODULE,
+               .of_match_table = of_match_ptr(lp3943_pwm_of_match),
+       },
+};
+module_platform_driver(lp3943_pwm_driver);
+
+MODULE_DESCRIPTION("LP3943 PWM driver");
+MODULE_ALIAS("platform:lp3943-pwm");
+MODULE_AUTHOR("Milo Kim");
+MODULE_LICENSE("GPL");
index 603f192e84f1736b5e116baaf07a3ca1eaf0cbaf..c625468c7f2c9b2894b83f3fe24b7a22b0ed5069 100644 (file)
@@ -2998,37 +2998,6 @@ static void abx500_get_regulator_info(struct ab8500 *ab8500)
        }
 }
 
-static int ab8500_regulator_init_registers(struct platform_device *pdev,
-                                          int id, int mask, int value)
-{
-       struct ab8500_reg_init *reg_init = abx500_regulator.init;
-       int err;
-
-       BUG_ON(value & ~mask);
-       BUG_ON(mask & ~reg_init[id].mask);
-
-       /* initialize register */
-       err = abx500_mask_and_set_register_interruptible(
-               &pdev->dev,
-               reg_init[id].bank,
-               reg_init[id].addr,
-               mask, value);
-       if (err < 0) {
-               dev_err(&pdev->dev,
-                       "Failed to initialize 0x%02x, 0x%02x.\n",
-                       reg_init[id].bank,
-                       reg_init[id].addr);
-               return err;
-       }
-       dev_vdbg(&pdev->dev,
-                "  init: 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
-                reg_init[id].bank,
-                reg_init[id].addr,
-                mask, value);
-
-       return 0;
-}
-
 static int ab8500_regulator_register(struct platform_device *pdev,
                                     struct regulator_init_data *init_data,
                                     int id, struct device_node *np)
@@ -3036,7 +3005,6 @@ static int ab8500_regulator_register(struct platform_device *pdev,
        struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
        struct ab8500_regulator_info *info = NULL;
        struct regulator_config config = { };
-       int err;
 
        /* assign per-regulator data */
        info = &abx500_regulator.info[id];
@@ -3058,17 +3026,12 @@ static int ab8500_regulator_register(struct platform_device *pdev,
        }
 
        /* register regulator with framework */
-       info->regulator = regulator_register(&info->desc, &config);
+       info->regulator = devm_regulator_register(&pdev->dev, &info->desc,
+                                               &config);
        if (IS_ERR(info->regulator)) {
-               err = PTR_ERR(info->regulator);
                dev_err(&pdev->dev, "failed to register regulator %s\n",
                        info->desc.name);
-               /* when we fail, un-register all earlier regulators */
-               while (--id >= 0) {
-                       info = &abx500_regulator.info[id];
-                       regulator_unregister(info->regulator);
-               }
-               return err;
+               return PTR_ERR(info->regulator);
        }
 
        return 0;
@@ -3095,9 +3058,7 @@ static int ab8500_regulator_probe(struct platform_device *pdev)
 {
        struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
        struct device_node *np = pdev->dev.of_node;
-       struct ab8500_platform_data *ppdata;
-       struct ab8500_regulator_platform_data *pdata;
-       int i, err;
+       int err;
 
        if (!ab8500) {
                dev_err(&pdev->dev, "null mfd parent\n");
@@ -3106,83 +3067,20 @@ static int ab8500_regulator_probe(struct platform_device *pdev)
 
        abx500_get_regulator_info(ab8500);
 
-       if (np) {
-               err = of_regulator_match(&pdev->dev, np,
-                                        abx500_regulator.match,
-                                        abx500_regulator.match_size);
-               if (err < 0) {
-                       dev_err(&pdev->dev,
-                               "Error parsing regulator init data: %d\n", err);
-                       return err;
-               }
-
-               err = ab8500_regulator_of_probe(pdev, np);
-               return err;
-       }
-
-       ppdata = dev_get_platdata(ab8500->dev);
-       if (!ppdata) {
-               dev_err(&pdev->dev, "null parent pdata\n");
-               return -EINVAL;
-       }
-
-       pdata = ppdata->regulator;
-       if (!pdata) {
-               dev_err(&pdev->dev, "null pdata\n");
-               return -EINVAL;
-       }
-
-       /* make sure the platform data has the correct size */
-       if (pdata->num_regulator != abx500_regulator.info_size) {
-               dev_err(&pdev->dev, "Configuration error: size mismatch.\n");
-               return -EINVAL;
-       }
-
-       /* initialize debug (initial state is recorded with this call) */
-       err = ab8500_regulator_debug_init(pdev);
-       if (err)
+       err = of_regulator_match(&pdev->dev, np,
+                                abx500_regulator.match,
+                                abx500_regulator.match_size);
+       if (err < 0) {
+               dev_err(&pdev->dev,
+                       "Error parsing regulator init data: %d\n", err);
                return err;
-
-       /* initialize registers */
-       for (i = 0; i < pdata->num_reg_init; i++) {
-               int id, mask, value;
-
-               id = pdata->reg_init[i].id;
-               mask = pdata->reg_init[i].mask;
-               value = pdata->reg_init[i].value;
-
-               /* check for configuration errors */
-               BUG_ON(id >= abx500_regulator.init_size);
-
-               err = ab8500_regulator_init_registers(pdev, id, mask, value);
-               if (err < 0)
-                       return err;
        }
-
-       /* register all regulators */
-       for (i = 0; i < abx500_regulator.info_size; i++) {
-               err = ab8500_regulator_register(pdev, &pdata->regulator[i],
-                                               i, NULL);
-               if (err < 0)
-                       return err;
-       }
-
-       return 0;
+       return ab8500_regulator_of_probe(pdev, np);
 }
 
 static int ab8500_regulator_remove(struct platform_device *pdev)
 {
-       int i, err;
-
-       for (i = 0; i < abx500_regulator.info_size; i++) {
-               struct ab8500_regulator_info *info = NULL;
-               info = &abx500_regulator.info[i];
-
-               dev_vdbg(rdev_get_dev(info->regulator),
-                       "%s-remove\n", info->desc.name);
-
-               regulator_unregister(info->regulator);
-       }
+       int err;
 
        /* remove regulator debug */
        err = ab8500_regulator_debug_exit(pdev);
index fd3154d86901fcf3865139d42bc997d72b4ff608..034ece7070838991a59d45f88f0e0ace95c6abba 100644 (file)
@@ -28,8 +28,6 @@
 #include <linux/mfd/arizona/pdata.h>
 #include <linux/mfd/arizona/registers.h>
 
-#define ARIZONA_MICSUPP_MAX_SELECTOR 0x1f
-
 struct arizona_micsupp {
        struct regulator_dev *regulator;
        struct arizona *arizona;
@@ -40,42 +38,6 @@ struct arizona_micsupp {
        struct work_struct check_cp_work;
 };
 
-static int arizona_micsupp_list_voltage(struct regulator_dev *rdev,
-                                       unsigned int selector)
-{
-       if (selector > ARIZONA_MICSUPP_MAX_SELECTOR)
-               return -EINVAL;
-
-       if (selector == ARIZONA_MICSUPP_MAX_SELECTOR)
-               return 3300000;
-       else
-               return (selector * 50000) + 1700000;
-}
-
-static int arizona_micsupp_map_voltage(struct regulator_dev *rdev,
-                                      int min_uV, int max_uV)
-{
-       unsigned int voltage;
-       int selector;
-
-       if (min_uV < 1700000)
-               min_uV = 1700000;
-
-       if (min_uV > 3200000)
-               selector = ARIZONA_MICSUPP_MAX_SELECTOR;
-       else
-               selector = DIV_ROUND_UP(min_uV - 1700000, 50000);
-
-       if (selector < 0)
-               return -EINVAL;
-
-       voltage = arizona_micsupp_list_voltage(rdev, selector);
-       if (voltage < min_uV || voltage > max_uV)
-               return -EINVAL;
-
-       return selector;
-}
-
 static void arizona_micsupp_check_cp(struct work_struct *work)
 {
        struct arizona_micsupp *micsupp =
@@ -145,8 +107,8 @@ static struct regulator_ops arizona_micsupp_ops = {
        .disable = arizona_micsupp_disable,
        .is_enabled = regulator_is_enabled_regmap,
 
-       .list_voltage = arizona_micsupp_list_voltage,
-       .map_voltage = arizona_micsupp_map_voltage,
+       .list_voltage = regulator_list_voltage_linear_range,
+       .map_voltage = regulator_map_voltage_linear_range,
 
        .get_voltage_sel = regulator_get_voltage_sel_regmap,
        .set_voltage_sel = regulator_set_voltage_sel_regmap,
@@ -155,11 +117,16 @@ static struct regulator_ops arizona_micsupp_ops = {
        .set_bypass = arizona_micsupp_set_bypass,
 };
 
+static const struct regulator_linear_range arizona_micsupp_ranges[] = {
+       REGULATOR_LINEAR_RANGE(1700000, 0,    0x1e, 50000),
+       REGULATOR_LINEAR_RANGE(3300000, 0x1f, 0x1f, 0),
+};
+
 static const struct regulator_desc arizona_micsupp = {
        .name = "MICVDD",
        .supply_name = "CPVDD",
        .type = REGULATOR_VOLTAGE,
-       .n_voltages = ARIZONA_MICSUPP_MAX_SELECTOR + 1,
+       .n_voltages = 32,
        .ops = &arizona_micsupp_ops,
 
        .vsel_reg = ARIZONA_LDO2_CONTROL_1,
@@ -169,6 +136,9 @@ static const struct regulator_desc arizona_micsupp = {
        .bypass_reg = ARIZONA_MIC_CHARGE_PUMP_1,
        .bypass_mask = ARIZONA_CPMIC_BYPASS,
 
+       .linear_ranges = arizona_micsupp_ranges,
+       .n_linear_ranges = ARRAY_SIZE(arizona_micsupp_ranges),
+
        .enable_time = 3000,
 
        .owner = THIS_MODULE,
index 5917fe3dc983dc5335d62e393fe079459817d439..b9f1d24c6812eb91d0cf55031c617888b914c560 100644 (file)
@@ -590,8 +590,8 @@ static int as3722_sd016_set_current_limit(struct regulator_dev *rdev,
        default:
                return -EINVAL;
        }
+       ret <<= ffs(mask) - 1;
        val = ret & mask;
-       val <<= ffs(mask) - 1;
        return as3722_update_bits(as3722, reg, mask, val);
 }
 
index 3fe13130baec12218a58230863b313bf4c20d034..d85f31385b24fe9b68ae45dfe0ece4be0ecc2ceb 100644 (file)
@@ -119,6 +119,11 @@ static const char *rdev_get_name(struct regulator_dev *rdev)
                return "";
 }
 
+static bool have_full_constraints(void)
+{
+       return has_full_constraints || of_have_populated_dt();
+}
+
 /**
  * of_get_regulator - get a regulator device node based on supply name
  * @dev: Device pointer for the consumer (of regulator) device
@@ -1340,7 +1345,7 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
         * 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 && allow_dummy) {
+       if (have_full_constraints() && allow_dummy) {
                pr_warn("%s supply %s not found, using dummy regulator\n",
                        devname, id);
 
@@ -3627,7 +3632,7 @@ int regulator_suspend_finish(void)
                        if (error)
                                ret = error;
                } else {
-                       if (!has_full_constraints)
+                       if (!have_full_constraints())
                                goto unlock;
                        if (!ops->disable)
                                goto unlock;
@@ -3825,7 +3830,7 @@ static int __init regulator_init_complete(void)
                if (!enabled)
                        goto unlock;
 
-               if (has_full_constraints) {
+               if (have_full_constraints()) {
                        /* We log since this may kill the system if it
                         * goes wrong. */
                        rdev_info(rdev, "disabling\n");
index a53c11a529d5f65dc55e6790167c4d69f5c68de0..846acf240e486d138319cbf26ce9434b71e6bc6e 100644 (file)
@@ -431,17 +431,11 @@ static int db8500_regulator_register(struct platform_device *pdev,
        config.of_node = np;
 
        /* register with the regulator framework */
-       info->rdev = regulator_register(&info->desc, &config);
+       info->rdev = devm_regulator_register(&pdev->dev, &info->desc, &config);
        if (IS_ERR(info->rdev)) {
                err = PTR_ERR(info->rdev);
                dev_err(&pdev->dev, "failed to register %s: err %i\n",
                        info->desc.name, err);
-
-               /* if failing, unregister all earlier regulators */
-               while (--id >= 0) {
-                       info = &dbx500_regulator_info[id];
-                       regulator_unregister(info->rdev);
-               }
                return err;
        }
 
@@ -530,20 +524,8 @@ static int db8500_regulator_probe(struct platform_device *pdev)
 
 static int db8500_regulator_remove(struct platform_device *pdev)
 {
-       int i;
-
        ux500_regulator_debug_exit();
 
-       for (i = 0; i < ARRAY_SIZE(dbx500_regulator_info); i++) {
-               struct dbx500_regulator_info *info;
-               info = &dbx500_regulator_info[i];
-
-               dev_vdbg(rdev_get_dev(info->rdev),
-                       "regulator-%s-remove\n", info->desc.name);
-
-               regulator_unregister(info->rdev);
-       }
-
        return 0;
 }
 
index 234960dc96077389460632cdc832f0c6ea5e69e1..c0a1d00b78c932a6982961334f9e3e9501592c50 100644 (file)
@@ -203,17 +203,18 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np)
        }
        config->nr_states = i;
 
+       config->type = REGULATOR_VOLTAGE;
        ret = of_property_read_string(np, "regulator-type", &regtype);
-       if (ret < 0) {
-               dev_err(dev, "Missing 'regulator-type' property\n");
-               return ERR_PTR(-EINVAL);
+       if (ret >= 0) {
+               if (!strncmp("voltage", regtype, 7))
+                       config->type = REGULATOR_VOLTAGE;
+               else if (!strncmp("current", regtype, 7))
+                       config->type = REGULATOR_CURRENT;
+               else
+                       dev_warn(dev, "Unknown regulator-type '%s'\n",
+                                regtype);
        }
 
-       if (!strncmp("voltage", regtype, 7))
-               config->type = REGULATOR_VOLTAGE;
-       else if (!strncmp("current", regtype, 7))
-               config->type = REGULATOR_CURRENT;
-
        return config;
 }
 
index 947c05ffe0ab9887899a871a1576936b01b8ba3a..3b1102b75071f9d9f73fa0b34db63e43f9784614 100644 (file)
@@ -25,8 +25,6 @@ struct lp3971 {
        struct device *dev;
        struct mutex io_lock;
        struct i2c_client *i2c;
-       int num_regulators;
-       struct regulator_dev **rdev;
 };
 
 static u8 lp3971_reg_read(struct lp3971 *lp3971, u8 reg);
@@ -383,42 +381,27 @@ static int setup_regulators(struct lp3971 *lp3971,
 {
        int i, err;
 
-       lp3971->num_regulators = pdata->num_regulators;
-       lp3971->rdev = kcalloc(pdata->num_regulators,
-                               sizeof(struct regulator_dev *), GFP_KERNEL);
-       if (!lp3971->rdev) {
-               err = -ENOMEM;
-               goto err_nomem;
-       }
-
        /* Instantiate the regulators */
        for (i = 0; i < pdata->num_regulators; i++) {
                struct regulator_config config = { };
                struct lp3971_regulator_subdev *reg = &pdata->regulators[i];
+               struct regulator_dev *rdev;
 
                config.dev = lp3971->dev;
                config.init_data = reg->initdata;
                config.driver_data = lp3971;
 
-               lp3971->rdev[i] = regulator_register(&regulators[reg->id],
-                                                    &config);
-               if (IS_ERR(lp3971->rdev[i])) {
-                       err = PTR_ERR(lp3971->rdev[i]);
+               rdev = devm_regulator_register(lp3971->dev,
+                                              &regulators[reg->id], &config);
+               if (IS_ERR(rdev)) {
+                       err = PTR_ERR(rdev);
                        dev_err(lp3971->dev, "regulator init failed: %d\n",
                                err);
-                       goto error;
+                       return err;
                }
        }
 
        return 0;
-
-error:
-       while (--i >= 0)
-               regulator_unregister(lp3971->rdev[i]);
-       kfree(lp3971->rdev);
-       lp3971->rdev = NULL;
-err_nomem:
-       return err;
 }
 
 static int lp3971_i2c_probe(struct i2c_client *i2c,
@@ -460,19 +443,6 @@ static int lp3971_i2c_probe(struct i2c_client *i2c,
        return 0;
 }
 
-static int lp3971_i2c_remove(struct i2c_client *i2c)
-{
-       struct lp3971 *lp3971 = i2c_get_clientdata(i2c);
-       int i;
-
-       for (i = 0; i < lp3971->num_regulators; i++)
-               regulator_unregister(lp3971->rdev[i]);
-
-       kfree(lp3971->rdev);
-
-       return 0;
-}
-
 static const struct i2c_device_id lp3971_i2c_id[] = {
        { "lp3971", 0 },
        { }
@@ -485,7 +455,6 @@ static struct i2c_driver lp3971_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe    = lp3971_i2c_probe,
-       .remove   = lp3971_i2c_remove,
        .id_table = lp3971_i2c_id,
 };
 
index 093e6f44ff8a3e0d9f17eb6cd0001c36d5911b37..aea485afcc1a8a9983781320182ed9078ff9517c 100644 (file)
@@ -22,8 +22,6 @@ struct lp3972 {
        struct device *dev;
        struct mutex io_lock;
        struct i2c_client *i2c;
-       int num_regulators;
-       struct regulator_dev **rdev;
 };
 
 /* LP3972 Control Registers */
@@ -478,41 +476,27 @@ static int setup_regulators(struct lp3972 *lp3972,
 {
        int i, err;
 
-       lp3972->num_regulators = pdata->num_regulators;
-       lp3972->rdev = kcalloc(pdata->num_regulators,
-                               sizeof(struct regulator_dev *), GFP_KERNEL);
-       if (!lp3972->rdev) {
-               err = -ENOMEM;
-               goto err_nomem;
-       }
-
        /* Instantiate the regulators */
        for (i = 0; i < pdata->num_regulators; i++) {
                struct lp3972_regulator_subdev *reg = &pdata->regulators[i];
                struct regulator_config config = { };
+               struct regulator_dev *rdev;
 
                config.dev = lp3972->dev;
                config.init_data = reg->initdata;
                config.driver_data = lp3972;
 
-               lp3972->rdev[i] = regulator_register(&regulators[reg->id],
-                                                    &config);
-               if (IS_ERR(lp3972->rdev[i])) {
-                       err = PTR_ERR(lp3972->rdev[i]);
+               rdev = devm_regulator_register(lp3972->dev,
+                                              &regulators[reg->id], &config);
+               if (IS_ERR(rdev)) {
+                       err = PTR_ERR(rdev);
                        dev_err(lp3972->dev, "regulator init failed: %d\n",
                                err);
-                       goto error;
+                       return err;
                }
        }
 
        return 0;
-error:
-       while (--i >= 0)
-               regulator_unregister(lp3972->rdev[i]);
-       kfree(lp3972->rdev);
-       lp3972->rdev = NULL;
-err_nomem:
-       return err;
 }
 
 static int lp3972_i2c_probe(struct i2c_client *i2c,
@@ -557,18 +541,6 @@ static int lp3972_i2c_probe(struct i2c_client *i2c,
        return 0;
 }
 
-static int lp3972_i2c_remove(struct i2c_client *i2c)
-{
-       struct lp3972 *lp3972 = i2c_get_clientdata(i2c);
-       int i;
-
-       for (i = 0; i < lp3972->num_regulators; i++)
-               regulator_unregister(lp3972->rdev[i]);
-       kfree(lp3972->rdev);
-
-       return 0;
-}
-
 static const struct i2c_device_id lp3972_i2c_id[] = {
        { "lp3972", 0 },
        { }
@@ -581,7 +553,6 @@ static struct i2c_driver lp3972_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe    = lp3972_i2c_probe,
-       .remove   = lp3972_i2c_remove,
        .id_table = lp3972_i2c_id,
 };
 
index d7da1c15a6da447d699e080a4bfda259f734c5f0..134f90ec9ca1fc80c1728d0ae4d6778edc93e2f6 100644 (file)
@@ -105,7 +105,7 @@ static int pcf50633_regulator_probe(struct platform_device *pdev)
 
 static struct platform_driver pcf50633_regulator_driver = {
        .driver = {
-               .name = "pcf50633-regltr",
+               .name = "pcf50633-regulator",
        },
        .probe = pcf50633_regulator_probe,
 };
index 032df3799efb7a144f6c1eef5cd0a3dfe17b6e50..0c511ae52c4228be93bcd52cc48d24977d78c647 100644 (file)
@@ -38,7 +38,7 @@
 
 #define PFUZE100_DEVICEID      0x0
 #define PFUZE100_REVID         0x3
-#define PFUZE100_FABID         0x3
+#define PFUZE100_FABID         0x4
 
 #define PFUZE100_SW1ABVOL      0x20
 #define PFUZE100_SW1CVOL       0x2e
@@ -408,31 +408,18 @@ static int pfuze100_regulator_probe(struct i2c_client *client,
                config.driver_data = pfuze_chip;
                config.of_node = match_of_node(i);
 
-               pfuze_chip->regulators[i] = regulator_register(desc, &config);
+               pfuze_chip->regulators[i] =
+                       devm_regulator_register(&client->dev, desc, &config);
                if (IS_ERR(pfuze_chip->regulators[i])) {
                        dev_err(&client->dev, "register regulator%s failed\n",
                                pfuze100_regulators[i].desc.name);
-                       ret = PTR_ERR(pfuze_chip->regulators[i]);
-                       while (--i >= 0)
-                               regulator_unregister(pfuze_chip->regulators[i]);
-                       return ret;
+                       return PTR_ERR(pfuze_chip->regulators[i]);
                }
        }
 
        return 0;
 }
 
-static int pfuze100_regulator_remove(struct i2c_client *client)
-{
-       int i;
-       struct pfuze_chip *pfuze_chip = i2c_get_clientdata(client);
-
-       for (i = 0; i < PFUZE100_MAX_REGULATOR; i++)
-               regulator_unregister(pfuze_chip->regulators[i]);
-
-       return 0;
-}
-
 static struct i2c_driver pfuze_driver = {
        .id_table = pfuze_device_id,
        .driver = {
@@ -441,7 +428,6 @@ static struct i2c_driver pfuze_driver = {
                .of_match_table = pfuze_dt_ids,
        },
        .probe = pfuze100_regulator_probe,
-       .remove = pfuze100_regulator_remove,
 };
 module_i2c_driver(pfuze_driver);
 
index f78857bd6a158ad8b86b5b103fd5ba4bcb7ad8c9..a7e152696a022f4ed20b2175fb2689e21072e3cc 100644 (file)
@@ -74,7 +74,8 @@ static int stw481x_vmmc_regulator_probe(struct platform_device *pdev)
        config.init_data = of_get_regulator_init_data(&pdev->dev,
                                                      pdev->dev.of_node);
 
-       stw481x->vmmc_regulator = regulator_register(&vmmc_regulator, &config);
+       stw481x->vmmc_regulator = devm_regulator_register(&pdev->dev,
+                                               &vmmc_regulator, &config);
        if (IS_ERR(stw481x->vmmc_regulator)) {
                dev_err(&pdev->dev,
                        "error initializing STw481x VMMC regulator\n");
@@ -85,14 +86,6 @@ static int stw481x_vmmc_regulator_probe(struct platform_device *pdev)
        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", },
        {},
@@ -105,7 +98,6 @@ static struct platform_driver stw481x_vmmc_regulator_driver = {
                .of_match_table = stw481x_vmmc_match,
        },
        .probe = stw481x_vmmc_regulator_probe,
-       .remove = stw481x_vmmc_regulator_remove,
 };
 
 module_platform_driver(stw481x_vmmc_regulator_driver);
index b0a3f0917a27ea841f3fffefdda7b67b163e8168..3486be935bec367b3721476218028aec364b46f8 100644 (file)
@@ -305,7 +305,7 @@ static int tps51632_probe(struct i2c_client *client,
        }
 
        tps->dev = &client->dev;
-       tps->desc.name = id->name;
+       tps->desc.name = client->name;
        tps->desc.id = 0;
        tps->desc.ramp_delay = TPS51632_DEFAULT_RAMP_DELAY;
        tps->desc.min_uV = TPS51632_MIN_VOLATGE;
index e8e3a8afd3e279be7c524b3599316be05f9606a9..0485d47f0d8a82d9de595a8df5bd73c16111d4f2 100644 (file)
@@ -93,6 +93,8 @@ static const unsigned int tps6586x_ldo4_voltages[] = {
        2300000, 2325000, 2350000, 2375000, 2400000, 2425000, 2450000, 2475000,
 };
 
+#define tps658623_sm2_voltages tps6586x_ldo4_voltages
+
 static const unsigned int tps6586x_ldo_voltages[] = {
        1250000, 1500000, 1800000, 2500000, 2700000, 2850000, 3100000, 3300000,
 };
@@ -104,6 +106,13 @@ static const unsigned int tps6586x_sm2_voltages[] = {
        4200000, 4250000, 4300000, 4350000, 4400000, 4450000, 4500000, 4550000,
 };
 
+static const unsigned int tps658643_sm2_voltages[] = {
+       1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, 1200000,
+       1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000, 1400000,
+       1425000, 1450000, 1475000, 1500000, 1525000, 1550000, 1575000, 1600000,
+       1625000, 1650000, 1675000, 1700000, 1725000, 1750000, 1775000, 1800000,
+};
+
 static const unsigned int tps6586x_dvm_voltages[] = {
         725000,  750000,  775000,  800000,  825000,  850000,  875000,  900000,
         925000,  950000,  975000, 1000000, 1025000, 1050000, 1075000, 1100000,
@@ -119,8 +128,8 @@ static const unsigned int tps6586x_dvm_voltages[] = {
                .ops    = &tps6586x_regulator_ops,                      \
                .type   = REGULATOR_VOLTAGE,                            \
                .id     = TPS6586X_ID_##_id,                            \
-               .n_voltages = ARRAY_SIZE(tps6586x_##vdata##_voltages),  \
-               .volt_table = tps6586x_##vdata##_voltages,              \
+               .n_voltages = ARRAY_SIZE(vdata##_voltages),             \
+               .volt_table = vdata##_voltages,                         \
                .owner  = THIS_MODULE,                                  \
                .enable_reg = TPS6586X_SUPPLY##ereg0,                   \
                .enable_mask = 1 << (ebit0),                            \
@@ -162,27 +171,47 @@ static const unsigned int tps6586x_dvm_voltages[] = {
 
 static struct tps6586x_regulator tps6586x_regulator[] = {
        TPS6586X_SYS_REGULATOR(),
-       TPS6586X_LDO(LDO_0, "vinldo01", ldo0, SUPPLYV1, 5, 3, ENC, 0, END, 0),
-       TPS6586X_LDO(LDO_3, "vinldo23", ldo, SUPPLYV4, 0, 3, ENC, 2, END, 2),
-       TPS6586X_LDO(LDO_5, "REG-SYS", ldo, SUPPLYV6, 0, 3, ENE, 6, ENE, 6),
-       TPS6586X_LDO(LDO_6, "vinldo678", ldo, SUPPLYV3, 0, 3, ENC, 4, END, 4),
-       TPS6586X_LDO(LDO_7, "vinldo678", ldo, SUPPLYV3, 3, 3, ENC, 5, END, 5),
-       TPS6586X_LDO(LDO_8, "vinldo678", ldo, SUPPLYV2, 5, 3, ENC, 6, END, 6),
-       TPS6586X_LDO(LDO_9, "vinldo9", ldo, SUPPLYV6, 3, 3, ENE, 7, ENE, 7),
-       TPS6586X_LDO(LDO_RTC, "REG-SYS", ldo, SUPPLYV4, 3, 3, V4, 7, V4, 7),
-       TPS6586X_LDO(LDO_1, "vinldo01", dvm, SUPPLYV1, 0, 5, ENC, 1, END, 1),
-       TPS6586X_LDO(SM_2, "vin-sm2", sm2, SUPPLYV2, 0, 5, ENC, 7, END, 7),
-
-       TPS6586X_DVM(LDO_2, "vinldo23", dvm, LDO2BV1, 0, 5, ENA, 3,
+       TPS6586X_LDO(LDO_0, "vinldo01", tps6586x_ldo0, SUPPLYV1, 5, 3, ENC, 0,
+                                       END, 0),
+       TPS6586X_LDO(LDO_3, "vinldo23", tps6586x_ldo, SUPPLYV4, 0, 3, ENC, 2,
+                                       END, 2),
+       TPS6586X_LDO(LDO_5, "REG-SYS", tps6586x_ldo, SUPPLYV6, 0, 3, ENE, 6,
+                                       ENE, 6),
+       TPS6586X_LDO(LDO_6, "vinldo678", tps6586x_ldo, SUPPLYV3, 0, 3, ENC, 4,
+                                       END, 4),
+       TPS6586X_LDO(LDO_7, "vinldo678", tps6586x_ldo, SUPPLYV3, 3, 3, ENC, 5,
+                                       END, 5),
+       TPS6586X_LDO(LDO_8, "vinldo678", tps6586x_ldo, SUPPLYV2, 5, 3, ENC, 6,
+                                       END, 6),
+       TPS6586X_LDO(LDO_9, "vinldo9", tps6586x_ldo, SUPPLYV6, 3, 3, ENE, 7,
+                                       ENE, 7),
+       TPS6586X_LDO(LDO_RTC, "REG-SYS", tps6586x_ldo, SUPPLYV4, 3, 3, V4, 7,
+                                       V4, 7),
+       TPS6586X_LDO(LDO_1, "vinldo01", tps6586x_dvm, SUPPLYV1, 0, 5, ENC, 1,
+                                       END, 1),
+       TPS6586X_LDO(SM_2, "vin-sm2", tps6586x_sm2, SUPPLYV2, 0, 5, ENC, 7,
+                                       END, 7),
+
+       TPS6586X_DVM(LDO_2, "vinldo23", tps6586x_dvm, LDO2BV1, 0, 5, ENA, 3,
                                        ENB, 3, TPS6586X_VCC2, BIT(6)),
-       TPS6586X_DVM(LDO_4, "vinldo4", ldo4, LDO4V1, 0, 5, ENC, 3,
+       TPS6586X_DVM(LDO_4, "vinldo4", tps6586x_ldo4, LDO4V1, 0, 5, ENC, 3,
                                        END, 3, TPS6586X_VCC1, BIT(6)),
-       TPS6586X_DVM(SM_0, "vin-sm0", dvm, SM0V1, 0, 5, ENA, 1,
+       TPS6586X_DVM(SM_0, "vin-sm0", tps6586x_dvm, SM0V1, 0, 5, ENA, 1,
                                        ENB, 1, TPS6586X_VCC1, BIT(2)),
-       TPS6586X_DVM(SM_1, "vin-sm1", dvm, SM1V1, 0, 5, ENA, 0,
+       TPS6586X_DVM(SM_1, "vin-sm1", tps6586x_dvm, SM1V1, 0, 5, ENA, 0,
                                        ENB, 0, TPS6586X_VCC1, BIT(0)),
 };
 
+static struct tps6586x_regulator tps658623_regulator[] = {
+       TPS6586X_LDO(SM_2, "vin-sm2", tps658623_sm2, SUPPLYV2, 0, 5, ENC, 7,
+                                       END, 7),
+};
+
+static struct tps6586x_regulator tps658643_regulator[] = {
+       TPS6586X_LDO(SM_2, "vin-sm2", tps658643_sm2, SUPPLYV2, 0, 5, ENC, 7,
+                                       END, 7),
+};
+
 /*
  * TPS6586X has 2 enable bits that are OR'ed to determine the actual
  * regulator state. Clearing one of this bits allows switching
@@ -254,11 +283,33 @@ static int tps6586x_regulator_set_slew_rate(struct platform_device *pdev,
                        setting->slew_rate & TPS6586X_SLEW_RATE_MASK);
 }
 
-static inline struct tps6586x_regulator *find_regulator_info(int id)
+static struct tps6586x_regulator *find_regulator_info(int id, int version)
 {
        struct tps6586x_regulator *ri;
+       struct tps6586x_regulator *table = NULL;
+       int num;
        int i;
 
+       switch (version) {
+       case TPS658623:
+               table = tps658623_regulator;
+               num = ARRAY_SIZE(tps658623_regulator);
+               break;
+       case TPS658643:
+               table = tps658643_regulator;
+               num = ARRAY_SIZE(tps658643_regulator);
+               break;
+       }
+
+       /* Search version specific table first */
+       if (table) {
+               for (i = 0; i < num; i++) {
+                       ri = &table[i];
+                       if (ri->desc.id == id)
+                               return ri;
+               }
+       }
+
        for (i = 0; i < ARRAY_SIZE(tps6586x_regulator); i++) {
                ri = &tps6586x_regulator[i];
                if (ri->desc.id == id)
@@ -351,6 +402,7 @@ static int tps6586x_regulator_probe(struct platform_device *pdev)
        struct regulator_init_data *reg_data;
        struct tps6586x_platform_data *pdata;
        struct of_regulator_match *tps6586x_reg_matches = NULL;
+       int version;
        int id;
        int err;
 
@@ -373,10 +425,13 @@ static int tps6586x_regulator_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
 
+       version = tps6586x_get_version(pdev->dev.parent);
+
        for (id = 0; id < TPS6586X_ID_MAX_REGULATOR; ++id) {
                reg_data = pdata->reg_init_data[id];
 
-               ri = find_regulator_info(id);
+               ri = find_regulator_info(id, version);
+
                if (!ri) {
                        dev_err(&pdev->dev, "invalid regulator ID specified\n");
                        return -EINVAL;
index 92bd22ce676012697be18504d96741b4a3910466..9cbc567698cefd0d3933f7c77198d4ccf34ceeeb 100644 (file)
@@ -504,7 +504,7 @@ static struct dasd_ccw_req *dasd_diag_build_cp(struct dasd_device *memdev,
        struct dasd_diag_req *dreq;
        struct dasd_diag_bio *dbio;
        struct req_iterator iter;
-       struct bio_vec *bv;
+       struct bio_vec bv;
        char *dst;
        unsigned int count, datasize;
        sector_t recid, first_rec, last_rec;
@@ -525,10 +525,10 @@ static struct dasd_ccw_req *dasd_diag_build_cp(struct dasd_device *memdev,
        /* Check struct bio and count the number of blocks for the request. */
        count = 0;
        rq_for_each_segment(bv, req, iter) {
-               if (bv->bv_len & (blksize - 1))
+               if (bv.bv_len & (blksize - 1))
                        /* Fba can only do full blocks. */
                        return ERR_PTR(-EINVAL);
-               count += bv->bv_len >> (block->s2b_shift + 9);
+               count += bv.bv_len >> (block->s2b_shift + 9);
        }
        /* Paranoia. */
        if (count != last_rec - first_rec + 1)
@@ -545,8 +545,8 @@ static struct dasd_ccw_req *dasd_diag_build_cp(struct dasd_device *memdev,
        dbio = dreq->bio;
        recid = first_rec;
        rq_for_each_segment(bv, req, iter) {
-               dst = page_address(bv->bv_page) + bv->bv_offset;
-               for (off = 0; off < bv->bv_len; off += blksize) {
+               dst = page_address(bv.bv_page) + bv.bv_offset;
+               for (off = 0; off < bv.bv_len; off += blksize) {
                        memset(dbio, 0, sizeof (struct dasd_diag_bio));
                        dbio->type = rw_cmd;
                        dbio->block_number = recid + 1;
index 95e45782692fa7bb2a89e9ec566a6a035f736381..2e8e0755070b609b13e9e49f5db5f17ac232ef69 100644 (file)
@@ -2551,7 +2551,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_single(
        struct dasd_ccw_req *cqr;
        struct ccw1 *ccw;
        struct req_iterator iter;
-       struct bio_vec *bv;
+       struct bio_vec bv;
        char *dst;
        unsigned int off;
        int count, cidaw, cplength, datasize;
@@ -2573,13 +2573,13 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_single(
        count = 0;
        cidaw = 0;
        rq_for_each_segment(bv, req, iter) {
-               if (bv->bv_len & (blksize - 1))
+               if (bv.bv_len & (blksize - 1))
                        /* Eckd can only do full blocks. */
                        return ERR_PTR(-EINVAL);
-               count += bv->bv_len >> (block->s2b_shift + 9);
+               count += bv.bv_len >> (block->s2b_shift + 9);
 #if defined(CONFIG_64BIT)
-               if (idal_is_needed (page_address(bv->bv_page), bv->bv_len))
-                       cidaw += bv->bv_len >> (block->s2b_shift + 9);
+               if (idal_is_needed (page_address(bv.bv_page), bv.bv_len))
+                       cidaw += bv.bv_len >> (block->s2b_shift + 9);
 #endif
        }
        /* Paranoia. */
@@ -2650,16 +2650,16 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_single(
                              last_rec - recid + 1, cmd, basedev, blksize);
        }
        rq_for_each_segment(bv, req, iter) {
-               dst = page_address(bv->bv_page) + bv->bv_offset;
+               dst = page_address(bv.bv_page) + bv.bv_offset;
                if (dasd_page_cache) {
                        char *copy = kmem_cache_alloc(dasd_page_cache,
                                                      GFP_DMA | __GFP_NOWARN);
                        if (copy && rq_data_dir(req) == WRITE)
-                               memcpy(copy + bv->bv_offset, dst, bv->bv_len);
+                               memcpy(copy + bv.bv_offset, dst, bv.bv_len);
                        if (copy)
-                               dst = copy + bv->bv_offset;
+                               dst = copy + bv.bv_offset;
                }
-               for (off = 0; off < bv->bv_len; off += blksize) {
+               for (off = 0; off < bv.bv_len; off += blksize) {
                        sector_t trkid = recid;
                        unsigned int recoffs = sector_div(trkid, blk_per_trk);
                        rcmd = cmd;
@@ -2735,7 +2735,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_track(
        struct dasd_ccw_req *cqr;
        struct ccw1 *ccw;
        struct req_iterator iter;
-       struct bio_vec *bv;
+       struct bio_vec bv;
        char *dst, *idaw_dst;
        unsigned int cidaw, cplength, datasize;
        unsigned int tlf;
@@ -2813,8 +2813,8 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_track(
        idaw_dst = NULL;
        idaw_len = 0;
        rq_for_each_segment(bv, req, iter) {
-               dst = page_address(bv->bv_page) + bv->bv_offset;
-               seg_len = bv->bv_len;
+               dst = page_address(bv.bv_page) + bv.bv_offset;
+               seg_len = bv.bv_len;
                while (seg_len) {
                        if (new_track) {
                                trkid = recid;
@@ -3039,7 +3039,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track(
 {
        struct dasd_ccw_req *cqr;
        struct req_iterator iter;
-       struct bio_vec *bv;
+       struct bio_vec bv;
        char *dst;
        unsigned int trkcount, ctidaw;
        unsigned char cmd;
@@ -3125,8 +3125,8 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track(
                new_track = 1;
                recid = first_rec;
                rq_for_each_segment(bv, req, iter) {
-                       dst = page_address(bv->bv_page) + bv->bv_offset;
-                       seg_len = bv->bv_len;
+                       dst = page_address(bv.bv_page) + bv.bv_offset;
+                       seg_len = bv.bv_len;
                        while (seg_len) {
                                if (new_track) {
                                        trkid = recid;
@@ -3158,9 +3158,9 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track(
                }
        } else {
                rq_for_each_segment(bv, req, iter) {
-                       dst = page_address(bv->bv_page) + bv->bv_offset;
+                       dst = page_address(bv.bv_page) + bv.bv_offset;
                        last_tidaw = itcw_add_tidaw(itcw, 0x00,
-                                                   dst, bv->bv_len);
+                                                   dst, bv.bv_len);
                        if (IS_ERR(last_tidaw)) {
                                ret = -EINVAL;
                                goto out_error;
@@ -3278,7 +3278,7 @@ static struct dasd_ccw_req *dasd_raw_build_cp(struct dasd_device *startdev,
        struct dasd_ccw_req *cqr;
        struct ccw1 *ccw;
        struct req_iterator iter;
-       struct bio_vec *bv;
+       struct bio_vec bv;
        char *dst;
        unsigned char cmd;
        unsigned int trkcount;
@@ -3378,8 +3378,8 @@ static struct dasd_ccw_req *dasd_raw_build_cp(struct dasd_device *startdev,
                        idaws = idal_create_words(idaws, rawpadpage, PAGE_SIZE);
        }
        rq_for_each_segment(bv, req, iter) {
-               dst = page_address(bv->bv_page) + bv->bv_offset;
-               seg_len = bv->bv_len;
+               dst = page_address(bv.bv_page) + bv.bv_offset;
+               seg_len = bv.bv_len;
                if (cmd == DASD_ECKD_CCW_READ_TRACK)
                        memset(dst, 0, seg_len);
                if (!len_to_track_end) {
@@ -3424,7 +3424,7 @@ dasd_eckd_free_cp(struct dasd_ccw_req *cqr, struct request *req)
        struct dasd_eckd_private *private;
        struct ccw1 *ccw;
        struct req_iterator iter;
-       struct bio_vec *bv;
+       struct bio_vec bv;
        char *dst, *cda;
        unsigned int blksize, blk_per_trk, off;
        sector_t recid;
@@ -3442,8 +3442,8 @@ dasd_eckd_free_cp(struct dasd_ccw_req *cqr, struct request *req)
        if (private->uses_cdl == 0 || recid > 2*blk_per_trk)
                ccw++;
        rq_for_each_segment(bv, req, iter) {
-               dst = page_address(bv->bv_page) + bv->bv_offset;
-               for (off = 0; off < bv->bv_len; off += blksize) {
+               dst = page_address(bv.bv_page) + bv.bv_offset;
+               for (off = 0; off < bv.bv_len; off += blksize) {
                        /* Skip locate record. */
                        if (private->uses_cdl && recid <= 2*blk_per_trk)
                                ccw++;
@@ -3454,7 +3454,7 @@ dasd_eckd_free_cp(struct dasd_ccw_req *cqr, struct request *req)
                                        cda = (char *)((addr_t) ccw->cda);
                                if (dst != cda) {
                                        if (rq_data_dir(req) == READ)
-                                               memcpy(dst, cda, bv->bv_len);
+                                               memcpy(dst, cda, bv.bv_len);
                                        kmem_cache_free(dasd_page_cache,
                                            (void *)((addr_t)cda & PAGE_MASK));
                                }
index 9cbc8c32ba595739cdff63da752a8f080b51e0de..2c8e68bf9a1cd658be919151387fe3ae24bffad3 100644 (file)
@@ -260,7 +260,7 @@ static struct dasd_ccw_req *dasd_fba_build_cp(struct dasd_device * memdev,
        struct dasd_ccw_req *cqr;
        struct ccw1 *ccw;
        struct req_iterator iter;
-       struct bio_vec *bv;
+       struct bio_vec bv;
        char *dst;
        int count, cidaw, cplength, datasize;
        sector_t recid, first_rec, last_rec;
@@ -283,13 +283,13 @@ static struct dasd_ccw_req *dasd_fba_build_cp(struct dasd_device * memdev,
        count = 0;
        cidaw = 0;
        rq_for_each_segment(bv, req, iter) {
-               if (bv->bv_len & (blksize - 1))
+               if (bv.bv_len & (blksize - 1))
                        /* Fba can only do full blocks. */
                        return ERR_PTR(-EINVAL);
-               count += bv->bv_len >> (block->s2b_shift + 9);
+               count += bv.bv_len >> (block->s2b_shift + 9);
 #if defined(CONFIG_64BIT)
-               if (idal_is_needed (page_address(bv->bv_page), bv->bv_len))
-                       cidaw += bv->bv_len / blksize;
+               if (idal_is_needed (page_address(bv.bv_page), bv.bv_len))
+                       cidaw += bv.bv_len / blksize;
 #endif
        }
        /* Paranoia. */
@@ -326,16 +326,16 @@ static struct dasd_ccw_req *dasd_fba_build_cp(struct dasd_device * memdev,
        }
        recid = first_rec;
        rq_for_each_segment(bv, req, iter) {
-               dst = page_address(bv->bv_page) + bv->bv_offset;
+               dst = page_address(bv.bv_page) + bv.bv_offset;
                if (dasd_page_cache) {
                        char *copy = kmem_cache_alloc(dasd_page_cache,
                                                      GFP_DMA | __GFP_NOWARN);
                        if (copy && rq_data_dir(req) == WRITE)
-                               memcpy(copy + bv->bv_offset, dst, bv->bv_len);
+                               memcpy(copy + bv.bv_offset, dst, bv.bv_len);
                        if (copy)
-                               dst = copy + bv->bv_offset;
+                               dst = copy + bv.bv_offset;
                }
-               for (off = 0; off < bv->bv_len; off += blksize) {
+               for (off = 0; off < bv.bv_len; off += blksize) {
                        /* Locate record for stupid devices. */
                        if (private->rdc_data.mode.bits.data_chain == 0) {
                                ccw[-1].flags |= CCW_FLAG_CC;
@@ -384,7 +384,7 @@ dasd_fba_free_cp(struct dasd_ccw_req *cqr, struct request *req)
        struct dasd_fba_private *private;
        struct ccw1 *ccw;
        struct req_iterator iter;
-       struct bio_vec *bv;
+       struct bio_vec bv;
        char *dst, *cda;
        unsigned int blksize, off;
        int status;
@@ -399,8 +399,8 @@ dasd_fba_free_cp(struct dasd_ccw_req *cqr, struct request *req)
        if (private->rdc_data.mode.bits.data_chain != 0)
                ccw++;
        rq_for_each_segment(bv, req, iter) {
-               dst = page_address(bv->bv_page) + bv->bv_offset;
-               for (off = 0; off < bv->bv_len; off += blksize) {
+               dst = page_address(bv.bv_page) + bv.bv_offset;
+               for (off = 0; off < bv.bv_len; off += blksize) {
                        /* Skip locate record. */
                        if (private->rdc_data.mode.bits.data_chain == 0)
                                ccw++;
@@ -411,7 +411,7 @@ dasd_fba_free_cp(struct dasd_ccw_req *cqr, struct request *req)
                                        cda = (char *)((addr_t) ccw->cda);
                                if (dst != cda) {
                                        if (rq_data_dir(req) == READ)
-                                               memcpy(dst, cda, bv->bv_len);
+                                               memcpy(dst, cda, bv.bv_len);
                                        kmem_cache_free(dasd_page_cache,
                                            (void *)((addr_t)cda & PAGE_MASK));
                                }
index f64921756ad610375134b3b59f13bbdb5d9906af..f224d59c4b6be35b8a5d827dde6cdc173953f3f5 100644 (file)
@@ -87,7 +87,6 @@ void dasd_gendisk_free(struct dasd_block *block)
 {
        if (block->gdp) {
                del_gendisk(block->gdp);
-               block->gdp->queue = NULL;
                block->gdp->private_data = NULL;
                put_disk(block->gdp);
                block->gdp = NULL;
index 6eca019bcf30a50edfab1a80daf1b351d2320474..ebf41e228e55836e6ec764b105c357e1856c9d1b 100644 (file)
@@ -808,18 +808,19 @@ static void
 dcssblk_make_request(struct request_queue *q, struct bio *bio)
 {
        struct dcssblk_dev_info *dev_info;
-       struct bio_vec *bvec;
+       struct bio_vec bvec;
+       struct bvec_iter iter;
        unsigned long index;
        unsigned long page_addr;
        unsigned long source_addr;
        unsigned long bytes_done;
-       int i;
 
        bytes_done = 0;
        dev_info = bio->bi_bdev->bd_disk->private_data;
        if (dev_info == NULL)
                goto fail;
-       if ((bio->bi_sector & 7) != 0 || (bio->bi_size & 4095) != 0)
+       if ((bio->bi_iter.bi_sector & 7) != 0 ||
+           (bio->bi_iter.bi_size & 4095) != 0)
                /* Request is not page-aligned. */
                goto fail;
        if (bio_end_sector(bio) > get_capacity(bio->bi_bdev->bd_disk)) {
@@ -842,22 +843,22 @@ dcssblk_make_request(struct request_queue *q, struct bio *bio)
                }
        }
 
-       index = (bio->bi_sector >> 3);
-       bio_for_each_segment(bvec, bio, i) {
+       index = (bio->bi_iter.bi_sector >> 3);
+       bio_for_each_segment(bvec, bio, iter) {
                page_addr = (unsigned long)
-                       page_address(bvec->bv_page) + bvec->bv_offset;
+                       page_address(bvec.bv_page) + bvec.bv_offset;
                source_addr = dev_info->start + (index<<12) + bytes_done;
-               if (unlikely((page_addr & 4095) != 0) || (bvec->bv_len & 4095) != 0)
+               if (unlikely((page_addr & 4095) != 0) || (bvec.bv_len & 4095) != 0)
                        // More paranoia.
                        goto fail;
                if (bio_data_dir(bio) == READ) {
                        memcpy((void*)page_addr, (void*)source_addr,
-                               bvec->bv_len);
+                               bvec.bv_len);
                } else {
                        memcpy((void*)source_addr, (void*)page_addr,
-                               bvec->bv_len);
+                               bvec.bv_len);
                }
-               bytes_done += bvec->bv_len;
+               bytes_done += bvec.bv_len;
        }
        bio_endio(bio, 0);
        return;
index d0ab5019d885cea6113f677a4f58990fa4a3ca55..76bed1743db1c7ef23576282b13d9ef8f551aed8 100644 (file)
@@ -130,7 +130,7 @@ static void scm_request_prepare(struct scm_request *scmrq)
        struct aidaw *aidaw = scmrq->aidaw;
        struct msb *msb = &scmrq->aob->msb[0];
        struct req_iterator iter;
-       struct bio_vec *bv;
+       struct bio_vec bv;
 
        msb->bs = MSB_BS_4K;
        scmrq->aob->request.msb_count = 1;
@@ -142,9 +142,9 @@ static void scm_request_prepare(struct scm_request *scmrq)
        msb->data_addr = (u64) aidaw;
 
        rq_for_each_segment(bv, scmrq->request, iter) {
-               WARN_ON(bv->bv_offset);
-               msb->blk_count += bv->bv_len >> 12;
-               aidaw->data_addr = (u64) page_address(bv->bv_page);
+               WARN_ON(bv.bv_offset);
+               msb->blk_count += bv.bv_len >> 12;
+               aidaw->data_addr = (u64) page_address(bv.bv_page);
                aidaw++;
        }
 }
index 27f930cd657fcdd3a223412cb68c393ebd565556..9aae909d47a53c88d6345101db2f344b8bc1f7a9 100644 (file)
@@ -122,7 +122,7 @@ static void scm_prepare_cluster_request(struct scm_request *scmrq)
        struct aidaw *aidaw = scmrq->aidaw;
        struct msb *msb = &scmrq->aob->msb[0];
        struct req_iterator iter;
-       struct bio_vec *bv;
+       struct bio_vec bv;
        int i = 0;
        u64 addr;
 
@@ -163,7 +163,7 @@ static void scm_prepare_cluster_request(struct scm_request *scmrq)
                        i++;
                }
                rq_for_each_segment(bv, req, iter) {
-                       aidaw->data_addr = (u64) page_address(bv->bv_page);
+                       aidaw->data_addr = (u64) page_address(bv.bv_page);
                        aidaw++;
                        i++;
                }
index 464dd29d06c07dcbeb1e6ee96a439dbb037a25a9..3e530f9da8c48a42a2c11b1e4c58b04b284d161c 100644 (file)
@@ -184,25 +184,26 @@ static unsigned long xpram_highest_page_index(void)
 static void xpram_make_request(struct request_queue *q, struct bio *bio)
 {
        xpram_device_t *xdev = bio->bi_bdev->bd_disk->private_data;
-       struct bio_vec *bvec;
+       struct bio_vec bvec;
+       struct bvec_iter iter;
        unsigned int index;
        unsigned long page_addr;
        unsigned long bytes;
-       int i;
 
-       if ((bio->bi_sector & 7) != 0 || (bio->bi_size & 4095) != 0)
+       if ((bio->bi_iter.bi_sector & 7) != 0 ||
+           (bio->bi_iter.bi_size & 4095) != 0)
                /* Request is not page-aligned. */
                goto fail;
-       if ((bio->bi_size >> 12) > xdev->size)
+       if ((bio->bi_iter.bi_size >> 12) > xdev->size)
                /* Request size is no page-aligned. */
                goto fail;
-       if ((bio->bi_sector >> 3) > 0xffffffffU - xdev->offset)
+       if ((bio->bi_iter.bi_sector >> 3) > 0xffffffffU - xdev->offset)
                goto fail;
-       index = (bio->bi_sector >> 3) + xdev->offset;
-       bio_for_each_segment(bvec, bio, i) {
+       index = (bio->bi_iter.bi_sector >> 3) + xdev->offset;
+       bio_for_each_segment(bvec, bio, iter) {
                page_addr = (unsigned long)
-                       kmap(bvec->bv_page) + bvec->bv_offset;
-               bytes = bvec->bv_len;
+                       kmap(bvec.bv_page) + bvec.bv_offset;
+               bytes = bvec.bv_len;
                if ((page_addr & 4095) != 0 || (bytes & 4095) != 0)
                        /* More paranoia. */
                        goto fail;
index f7aa080e9b28db1d5b962de7b5380f60ae97cc10..1465e9563101f0a2cbc697a8f26edb2200368d5f 100644 (file)
@@ -35,7 +35,6 @@ struct read_info_sccb {
        u8      _reserved5[4096 - 112]; /* 112-4095 */
 } __packed __aligned(PAGE_SIZE);
 
-static __initdata struct init_sccb early_event_mask_sccb __aligned(PAGE_SIZE);
 static __initdata struct read_info_sccb early_read_info_sccb;
 static __initdata char sccb_early[PAGE_SIZE] __aligned(PAGE_SIZE);
 static unsigned long sclp_hsa_size;
@@ -113,7 +112,7 @@ static void __init sclp_facilities_detect(void)
 
 bool __init sclp_has_linemode(void)
 {
-       struct init_sccb *sccb = &early_event_mask_sccb;
+       struct init_sccb *sccb = (void *) &sccb_early;
 
        if (sccb->header.response_code != 0x20)
                return 0;
@@ -126,7 +125,7 @@ bool __init sclp_has_linemode(void)
 
 bool __init sclp_has_vt220(void)
 {
-       struct init_sccb *sccb = &early_event_mask_sccb;
+       struct init_sccb *sccb = (void *) &sccb_early;
 
        if (sccb->header.response_code != 0x20)
                return 0;
index a9fe3de2dec17fcce1717d99389468dfc46f4f98..b3f791b2c1f8994de2287052275fc8853b3b946a 100644 (file)
@@ -260,16 +260,16 @@ static int blacklist_parse_proc_parameters(char *buf)
 
        parm = strsep(&buf, " ");
 
-       if (strcmp("free", parm) == 0)
+       if (strcmp("free", parm) == 0) {
                rc = blacklist_parse_parameters(buf, free, 0);
-       else if (strcmp("add", parm) == 0)
+               css_schedule_eval_all_unreg(0);
+       } else if (strcmp("add", parm) == 0)
                rc = blacklist_parse_parameters(buf, add, 0);
        else if (strcmp("purge", parm) == 0)
                return ccw_purge_blacklisted();
        else
                return -EINVAL;
 
-       css_schedule_reprobe();
 
        return rc;
 }
index 13299f902676e647d43dce13d95f864c81300f53..eee70cb8730bf381fe4da4373a7fc65b98361fba 100644 (file)
@@ -237,26 +237,6 @@ void chsc_chp_offline(struct chp_id chpid)
        for_each_subchannel_staged(s390_subchannel_remove_chpid, NULL, &link);
 }
 
-static int s390_process_res_acc_new_sch(struct subchannel_id schid, void *data)
-{
-       struct schib schib;
-       /*
-        * We don't know the device yet, but since a path
-        * may be available now to the device we'll have
-        * to do recognition again.
-        * Since we don't have any idea about which chpid
-        * that beast may be on we'll have to do a stsch
-        * on all devices, grr...
-        */
-       if (stsch_err(schid, &schib))
-               /* We're through */
-               return -ENXIO;
-
-       /* Put it on the slow path. */
-       css_schedule_eval(schid);
-       return 0;
-}
-
 static int __s390_process_res_acc(struct subchannel *sch, void *data)
 {
        spin_lock_irq(sch->lock);
@@ -287,8 +267,8 @@ static void s390_process_res_acc(struct chp_link *link)
         * The more information we have (info), the less scanning
         * will we have to do.
         */
-       for_each_subchannel_staged(__s390_process_res_acc,
-                                  s390_process_res_acc_new_sch, link);
+       for_each_subchannel_staged(__s390_process_res_acc, NULL, link);
+       css_schedule_reprobe();
 }
 
 static int
@@ -663,19 +643,6 @@ static int s390_subchannel_vary_chpid_on(struct subchannel *sch, void *data)
        return 0;
 }
 
-static int
-__s390_vary_chpid_on(struct subchannel_id schid, void *data)
-{
-       struct schib schib;
-
-       if (stsch_err(schid, &schib))
-               /* We're through */
-               return -ENXIO;
-       /* Put it on the slow path. */
-       css_schedule_eval(schid);
-       return 0;
-}
-
 /**
  * chsc_chp_vary - propagate channel-path vary operation to subchannels
  * @chpid: channl-path ID
@@ -694,7 +661,8 @@ int chsc_chp_vary(struct chp_id chpid, int on)
                /* Try to update the channel path description. */
                chp_update_desc(chp);
                for_each_subchannel_staged(s390_subchannel_vary_chpid_on,
-                                          __s390_vary_chpid_on, &chpid);
+                                          NULL, &chpid);
+               css_schedule_reprobe();
        } else
                for_each_subchannel_staged(s390_subchannel_vary_chpid_off,
                                           NULL, &chpid);
index 8c2cb87bccc5d8b1a195ff1dc43181309aa75d82..0268e5fd59b5522fe1d61dbf90ddf17ed4e2df1f 100644 (file)
@@ -69,7 +69,8 @@ static int call_fn_known_sch(struct device *dev, void *data)
        struct cb_data *cb = data;
        int rc = 0;
 
-       idset_sch_del(cb->set, sch->schid);
+       if (cb->set)
+               idset_sch_del(cb->set, sch->schid);
        if (cb->fn_known_sch)
                rc = cb->fn_known_sch(sch, cb->data);
        return rc;
@@ -115,6 +116,13 @@ int for_each_subchannel_staged(int (*fn_known)(struct subchannel *, void *),
        cb.fn_known_sch = fn_known;
        cb.fn_unknown_sch = fn_unknown;
 
+       if (fn_known && !fn_unknown) {
+               /* Skip idset allocation in case of known-only loop. */
+               cb.set = NULL;
+               return bus_for_each_dev(&css_bus_type, NULL, &cb,
+                                       call_fn_known_sch);
+       }
+
        cb.set = idset_sch_new();
        if (!cb.set)
                /* fall back to brute force scanning in case of oom */
@@ -553,6 +561,9 @@ static int slow_eval_unknown_fn(struct subchannel_id schid, void *data)
                default:
                        rc = 0;
                }
+               /* Allow scheduling here since the containing loop might
+                * take a while.  */
+               cond_resched();
        }
        return rc;
 }
@@ -572,7 +583,7 @@ static void css_slow_path_func(struct work_struct *unused)
        spin_unlock_irqrestore(&slow_subchannel_lock, flags);
 }
 
-static DECLARE_WORK(slow_path_work, css_slow_path_func);
+static DECLARE_DELAYED_WORK(slow_path_work, css_slow_path_func);
 struct workqueue_struct *cio_work_q;
 
 void css_schedule_eval(struct subchannel_id schid)
@@ -582,7 +593,7 @@ void css_schedule_eval(struct subchannel_id schid)
        spin_lock_irqsave(&slow_subchannel_lock, flags);
        idset_sch_add(slow_subchannel_set, schid);
        atomic_set(&css_eval_scheduled, 1);
-       queue_work(cio_work_q, &slow_path_work);
+       queue_delayed_work(cio_work_q, &slow_path_work, 0);
        spin_unlock_irqrestore(&slow_subchannel_lock, flags);
 }
 
@@ -593,7 +604,7 @@ void css_schedule_eval_all(void)
        spin_lock_irqsave(&slow_subchannel_lock, flags);
        idset_fill(slow_subchannel_set);
        atomic_set(&css_eval_scheduled, 1);
-       queue_work(cio_work_q, &slow_path_work);
+       queue_delayed_work(cio_work_q, &slow_path_work, 0);
        spin_unlock_irqrestore(&slow_subchannel_lock, flags);
 }
 
@@ -606,7 +617,7 @@ static int __unset_registered(struct device *dev, void *data)
        return 0;
 }
 
-static void css_schedule_eval_all_unreg(void)
+void css_schedule_eval_all_unreg(unsigned long delay)
 {
        unsigned long flags;
        struct idset *unreg_set;
@@ -624,7 +635,7 @@ static void css_schedule_eval_all_unreg(void)
        spin_lock_irqsave(&slow_subchannel_lock, flags);
        idset_add_set(slow_subchannel_set, unreg_set);
        atomic_set(&css_eval_scheduled, 1);
-       queue_work(cio_work_q, &slow_path_work);
+       queue_delayed_work(cio_work_q, &slow_path_work, delay);
        spin_unlock_irqrestore(&slow_subchannel_lock, flags);
        idset_free(unreg_set);
 }
@@ -637,7 +648,8 @@ void css_wait_for_slow_path(void)
 /* Schedule reprobing of all unregistered subchannels. */
 void css_schedule_reprobe(void)
 {
-       css_schedule_eval_all_unreg();
+       /* Schedule with a delay to allow merging of subsequent calls. */
+       css_schedule_eval_all_unreg(1 * HZ);
 }
 EXPORT_SYMBOL_GPL(css_schedule_reprobe);
 
index 29351321bad6c73b97cdfc490c1d5d71ae12e6ce..2c9107e2025143b34fc5da2be3118b0fe013e7c9 100644 (file)
@@ -133,6 +133,7 @@ extern struct channel_subsystem *channel_subsystems[];
 /* Helper functions to build lists for the slow path. */
 void css_schedule_eval(struct subchannel_id schid);
 void css_schedule_eval_all(void);
+void css_schedule_eval_all_unreg(unsigned long delay);
 int css_complete_work(void);
 
 int sch_is_pseudo_sch(struct subchannel *);
index 02300dcfac91f87397c030f11eab825d1361f393..ab3baa7f95082e0cabf03906354c69ae9ed8880b 100644 (file)
@@ -591,7 +591,13 @@ static int ap_init_queue(ap_qid_t qid)
                if (rc != -ENODEV && rc != -EBUSY)
                        break;
                if (i < AP_MAX_RESET - 1) {
-                       udelay(5);
+                       /* Time we are waiting until we give up (0.7sec * 90).
+                        * Since the actual request (in progress) will not
+                        * interrupted immediately for the reset command,
+                        * we have to be patient. In worst case we have to
+                        * wait 60sec + reset time (some msec).
+                        */
+                       schedule_timeout(AP_RESET_TIMEOUT);
                        status = ap_test_queue(qid, &dummy, &dummy);
                }
        }
@@ -992,6 +998,28 @@ static ssize_t ap_domain_show(struct bus_type *bus, char *buf)
 
 static BUS_ATTR(ap_domain, 0444, ap_domain_show, NULL);
 
+static ssize_t ap_control_domain_mask_show(struct bus_type *bus, char *buf)
+{
+       if (ap_configuration != NULL) { /* QCI not supported */
+               if (test_facility(76)) { /* format 1 - 256 bit domain field */
+                       return snprintf(buf, PAGE_SIZE,
+                               "0x%08x%08x%08x%08x%08x%08x%08x%08x\n",
+                       ap_configuration->adm[0], ap_configuration->adm[1],
+                       ap_configuration->adm[2], ap_configuration->adm[3],
+                       ap_configuration->adm[4], ap_configuration->adm[5],
+                       ap_configuration->adm[6], ap_configuration->adm[7]);
+               } else { /* format 0 - 16 bit domain field */
+                       return snprintf(buf, PAGE_SIZE, "%08x%08x\n",
+                       ap_configuration->adm[0], ap_configuration->adm[1]);
+                 }
+       } else {
+               return snprintf(buf, PAGE_SIZE, "not supported\n");
+         }
+}
+
+static BUS_ATTR(ap_control_domain_mask, 0444,
+               ap_control_domain_mask_show, NULL);
+
 static ssize_t ap_config_time_show(struct bus_type *bus, char *buf)
 {
        return snprintf(buf, PAGE_SIZE, "%d\n", ap_config_time);
@@ -1077,6 +1105,7 @@ static BUS_ATTR(poll_timeout, 0644, poll_timeout_show, poll_timeout_store);
 
 static struct bus_attribute *const ap_bus_attrs[] = {
        &bus_attr_ap_domain,
+       &bus_attr_ap_control_domain_mask,
        &bus_attr_config_time,
        &bus_attr_poll_thread,
        &bus_attr_ap_interrupts,
index 685f6cc022f92e929e60d865d817caca13269afb..6405ae24a7a69674ddc602d5bbef2a9ccd29d7bf 100644 (file)
@@ -33,7 +33,7 @@
 #define AP_DEVICES 64          /* Number of AP devices. */
 #define AP_DOMAINS 16          /* Number of AP domains. */
 #define AP_MAX_RESET 90                /* Maximum number of resets. */
-#define AP_RESET_TIMEOUT (HZ/2)        /* Time in ticks for reset timeouts. */
+#define AP_RESET_TIMEOUT (HZ*0.7)      /* Time in ticks for reset timeouts. */
 #define AP_CONFIG_TIME 30      /* Time in seconds between AP bus rescans. */
 #define AP_POLL_TIME 1         /* Time in ticks between receive polls. */
 
@@ -125,6 +125,8 @@ static inline int ap_test_bit(unsigned int *ptr, unsigned int nr)
 #define AP_FUNC_CRT4K 2
 #define AP_FUNC_COPRO 3
 #define AP_FUNC_ACCEL 4
+#define AP_FUNC_EP11  5
+#define AP_FUNC_APXA  6
 
 /*
  * AP reset flag states
index 31cfaa556072c0154373d0d3a7fbccb0b54a30e9..3d4bc904d149706cfb8c5c65f9f0b933614e31b6 100644 (file)
@@ -44,6 +44,8 @@
 #include "zcrypt_debug.h"
 #include "zcrypt_api.h"
 
+#include "zcrypt_msgtype6.h"
+
 /*
  * Module description.
  */
@@ -554,9 +556,9 @@ static long zcrypt_send_cprb(struct ica_xcRB *xcRB)
        spin_lock_bh(&zcrypt_device_lock);
        list_for_each_entry(zdev, &zcrypt_device_list, list) {
                if (!zdev->online || !zdev->ops->send_cprb ||
-                   (xcRB->user_defined != AUTOSELECT &&
-                       AP_QID_DEVICE(zdev->ap_dev->qid) != xcRB->user_defined)
-                   )
+                  (zdev->ops->variant == MSGTYPE06_VARIANT_EP11) ||
+                  (xcRB->user_defined != AUTOSELECT &&
+                   AP_QID_DEVICE(zdev->ap_dev->qid) != xcRB->user_defined))
                        continue;
                zcrypt_device_get(zdev);
                get_device(&zdev->ap_dev->device);
@@ -581,6 +583,82 @@ static long zcrypt_send_cprb(struct ica_xcRB *xcRB)
        return -ENODEV;
 }
 
+struct ep11_target_dev_list {
+       short                   targets_num;
+       struct ep11_target_dev  *targets;
+};
+
+static bool is_desired_ep11dev(unsigned int dev_qid,
+                              struct ep11_target_dev_list dev_list)
+{
+       int n;
+
+       for (n = 0; n < dev_list.targets_num; n++, dev_list.targets++) {
+               if ((AP_QID_DEVICE(dev_qid) == dev_list.targets->ap_id) &&
+                   (AP_QID_QUEUE(dev_qid) == dev_list.targets->dom_id)) {
+                       return true;
+               }
+       }
+       return false;
+}
+
+static long zcrypt_send_ep11_cprb(struct ep11_urb *xcrb)
+{
+       struct zcrypt_device *zdev;
+       bool autoselect = false;
+       struct ep11_target_dev_list ep11_dev_list;
+       int rc;
+
+       ep11_dev_list.targets_num = (short) xcrb->targets_num,
+       ep11_dev_list.targets = kmalloc((short)xcrb->targets_num *
+                                        sizeof(struct ep11_target_dev),
+                                        GFP_KERNEL);
+       if (!ep11_dev_list.targets)
+               return -ENOMEM;
+
+       if (copy_from_user(ep11_dev_list.targets, xcrb->targets,
+                          xcrb->targets_num * sizeof(struct ep11_target_dev)))
+               return -EFAULT;
+
+       /* empty list indicates autoselect (all available targets) */
+       if (ep11_dev_list.targets_num == 0)
+               autoselect = true;
+
+       spin_lock_bh(&zcrypt_device_lock);
+       list_for_each_entry(zdev, &zcrypt_device_list, list) {
+               /* check if device is eligible */
+               if (!zdev->online ||
+                   zdev->ops->variant != MSGTYPE06_VARIANT_EP11)
+                       continue;
+
+               /* check if device is selected as valid target */
+               if (!is_desired_ep11dev(zdev->ap_dev->qid, ep11_dev_list) &&
+                   !autoselect)
+                       continue;
+
+               zcrypt_device_get(zdev);
+               get_device(&zdev->ap_dev->device);
+               zdev->request_count++;
+               __zcrypt_decrease_preference(zdev);
+               if (try_module_get(zdev->ap_dev->drv->driver.owner)) {
+                       spin_unlock_bh(&zcrypt_device_lock);
+                       rc = zdev->ops->send_ep11_cprb(zdev, xcrb);
+                       spin_lock_bh(&zcrypt_device_lock);
+                       module_put(zdev->ap_dev->drv->driver.owner);
+               } else {
+                       rc = -EAGAIN;
+                 }
+               zdev->request_count--;
+               __zcrypt_increase_preference(zdev);
+               put_device(&zdev->ap_dev->device);
+               zcrypt_device_put(zdev);
+               spin_unlock_bh(&zcrypt_device_lock);
+               return rc;
+       }
+       spin_unlock_bh(&zcrypt_device_lock);
+       return -ENODEV;
+}
+
 static long zcrypt_rng(char *buffer)
 {
        struct zcrypt_device *zdev;
@@ -784,6 +862,23 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd,
                        return -EFAULT;
                return rc;
        }
+       case ZSENDEP11CPRB: {
+               struct ep11_urb __user *uxcrb = (void __user *)arg;
+               struct ep11_urb xcrb;
+               if (copy_from_user(&xcrb, uxcrb, sizeof(xcrb)))
+                       return -EFAULT;
+               do {
+                       rc = zcrypt_send_ep11_cprb(&xcrb);
+               } while (rc == -EAGAIN);
+               /* on failure: retry once again after a requested rescan */
+               if ((rc == -ENODEV) && (zcrypt_process_rescan()))
+                       do {
+                               rc = zcrypt_send_ep11_cprb(&xcrb);
+                       } while (rc == -EAGAIN);
+               if (copy_to_user(uxcrb, &xcrb, sizeof(xcrb)))
+                       return -EFAULT;
+               return rc;
+       }
        case Z90STAT_STATUS_MASK: {
                char status[AP_DEVICES];
                zcrypt_status_mask(status);
index 89632919c993ab4ea436c8bf38ade793820de824..b3d496bfaa7eadd08aa27e15a26c0e177a507685 100644 (file)
@@ -74,6 +74,7 @@ struct ica_z90_status {
 #define ZCRYPT_CEX2A           6
 #define ZCRYPT_CEX3C           7
 #define ZCRYPT_CEX3A           8
+#define ZCRYPT_CEX4           10
 
 /**
  * Large random numbers are pulled in 4096 byte chunks from the crypto cards
@@ -89,6 +90,7 @@ struct zcrypt_ops {
        long (*rsa_modexpo_crt)(struct zcrypt_device *,
                                struct ica_rsa_modexpo_crt *);
        long (*send_cprb)(struct zcrypt_device *, struct ica_xcRB *);
+       long (*send_ep11_cprb)(struct zcrypt_device *, struct ep11_urb *);
        long (*rng)(struct zcrypt_device *, char *);
        struct list_head list;          /* zcrypt ops list. */
        struct module *owner;
index ce1226398ac996a13b0546ba11df3ccfee6fa272..569f8b1d86c05305501530b33d2fdfba84e114a9 100644 (file)
 #define CEX4A_MAX_MESSAGE_SIZE MSGTYPE50_CRB3_MAX_MSG_SIZE
 #define CEX4C_MAX_MESSAGE_SIZE MSGTYPE06_MAX_MSG_SIZE
 
-#define CEX4_CLEANUP_TIME      (15*HZ)
+/* Waiting time for requests to be processed.
+ * Currently there are some types of request which are not deterministic.
+ * But the maximum time limit managed by the stomper code is set to 60sec.
+ * Hence we have to wait at least that time period.
+ */
+#define CEX4_CLEANUP_TIME      (61*HZ)
 
 static struct ap_device_id zcrypt_cex4_ids[] = {
        { AP_DEVICE(AP_DEVICE_TYPE_CEX4)  },
@@ -101,6 +106,19 @@ static int zcrypt_cex4_probe(struct ap_device *ap_dev)
                        zdev->speed_rating = CEX4C_SPEED_RATING;
                        zdev->ops = zcrypt_msgtype_request(MSGTYPE06_NAME,
                                                           MSGTYPE06_VARIANT_DEFAULT);
+               } else if (ap_test_bit(&ap_dev->functions, AP_FUNC_EP11)) {
+                       zdev = zcrypt_device_alloc(CEX4C_MAX_MESSAGE_SIZE);
+                       if (!zdev)
+                               return -ENOMEM;
+                       zdev->type_string = "CEX4P";
+                       zdev->user_space_type = ZCRYPT_CEX4;
+                       zdev->min_mod_size = CEX4C_MIN_MOD_SIZE;
+                       zdev->max_mod_size = CEX4C_MAX_MOD_SIZE;
+                       zdev->max_exp_bit_length = CEX4C_MAX_MOD_SIZE;
+                       zdev->short_crt = 0;
+                       zdev->speed_rating = CEX4C_SPEED_RATING;
+                       zdev->ops = zcrypt_msgtype_request(MSGTYPE06_NAME,
+                                                       MSGTYPE06_VARIANT_EP11);
                }
                break;
        }
index 0079b661721139e4f8ec7f58ef39bb99d08b045f..7b23f43c7b080cc81b4de94ed9016cc0d8a91546 100644 (file)
@@ -106,15 +106,15 @@ static inline int convert_error(struct zcrypt_device *zdev,
        //   REP88_ERROR_MESSAGE_TYPE           // '20' CEX2A
                /*
                 * To sent a message of the wrong type is a bug in the
-                * device driver. Warn about it, disable the device
+                * device driver. Send error msg, disable the device
                 * and then repeat the request.
                 */
-               WARN_ON(1);
                atomic_set(&zcrypt_rescan_req, 1);
                zdev->online = 0;
+               pr_err("Cryptographic device %x failed and was set offline\n",
+                      zdev->ap_dev->qid);
                ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d",
-                              zdev->ap_dev->qid,
-                              zdev->online, ehdr->reply_code);
+                       zdev->ap_dev->qid, zdev->online, ehdr->reply_code);
                return -EAGAIN;
        case REP82_ERROR_TRANSPORT_FAIL:
        case REP82_ERROR_MACHINE_FAILURE:
@@ -122,15 +122,17 @@ static inline int convert_error(struct zcrypt_device *zdev,
                /* If a card fails disable it and repeat the request. */
                atomic_set(&zcrypt_rescan_req, 1);
                zdev->online = 0;
+               pr_err("Cryptographic device %x failed and was set offline\n",
+                      zdev->ap_dev->qid);
                ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d",
-                              zdev->ap_dev->qid,
-                              zdev->online, ehdr->reply_code);
+                       zdev->ap_dev->qid, zdev->online, ehdr->reply_code);
                return -EAGAIN;
        default:
                zdev->online = 0;
+               pr_err("Cryptographic device %x failed and was set offline\n",
+                      zdev->ap_dev->qid);
                ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d",
-                              zdev->ap_dev->qid,
-                              zdev->online, ehdr->reply_code);
+                       zdev->ap_dev->qid, zdev->online, ehdr->reply_code);
                return -EAGAIN; /* repeat the request on a different device. */
        }
 }
index 7c522f338bda16a50f11cf04aa845a8f6f937637..334e282f255b7d9b0a6288bad94d6702a729a556 100644 (file)
@@ -25,6 +25,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define KMSG_COMPONENT "zcrypt"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/init.h>
@@ -332,6 +335,11 @@ static int convert_type80(struct zcrypt_device *zdev,
        if (t80h->len < sizeof(*t80h) + outputdatalength) {
                /* The result is too short, the CEX2A card may not do that.. */
                zdev->online = 0;
+               pr_err("Cryptographic device %x failed and was set offline\n",
+                      zdev->ap_dev->qid);
+               ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d",
+                              zdev->ap_dev->qid, zdev->online, t80h->code);
+
                return -EAGAIN; /* repeat the request on a different device. */
        }
        if (zdev->user_space_type == ZCRYPT_CEX2A)
@@ -359,6 +367,10 @@ static int convert_response(struct zcrypt_device *zdev,
                                      outputdata, outputdatalength);
        default: /* Unknown response type, this should NEVER EVER happen */
                zdev->online = 0;
+               pr_err("Cryptographic device %x failed and was set offline\n",
+                      zdev->ap_dev->qid);
+               ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail",
+                              zdev->ap_dev->qid, zdev->online);
                return -EAGAIN; /* repeat the request on a different device. */
        }
 }
index 7d97fa5a26d0cca4e6f318e5d57d392728f3c5f9..3210e8db42d30578aae8da78715b307fef91dd7a 100644 (file)
@@ -25,6 +25,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define KMSG_COMPONENT "zcrypt"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/err.h>
@@ -50,6 +53,7 @@ struct response_type {
 };
 #define PCIXCC_RESPONSE_TYPE_ICA  0
 #define PCIXCC_RESPONSE_TYPE_XCRB 1
+#define PCIXCC_RESPONSE_TYPE_EP11 2
 
 MODULE_AUTHOR("IBM Corporation");
 MODULE_DESCRIPTION("Cryptographic Coprocessor (message type 6), " \
@@ -358,6 +362,90 @@ static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev,
        return 0;
 }
 
+static int xcrb_msg_to_type6_ep11cprb_msgx(struct zcrypt_device *zdev,
+                                      struct ap_message *ap_msg,
+                                      struct ep11_urb *xcRB)
+{
+       unsigned int lfmt;
+
+       static struct type6_hdr static_type6_ep11_hdr = {
+               .type           =  0x06,
+               .rqid           = {0x00, 0x01},
+               .function_code  = {0x00, 0x00},
+               .agent_id[0]    =  0x58,        /* {'X'} */
+               .agent_id[1]    =  0x43,        /* {'C'} */
+               .offset1        =  0x00000058,
+       };
+
+       struct {
+               struct type6_hdr hdr;
+               struct ep11_cprb cprbx;
+               unsigned char   pld_tag;        /* fixed value 0x30 */
+               unsigned char   pld_lenfmt;     /* payload length format */
+       } __packed * msg = ap_msg->message;
+
+       struct pld_hdr {
+               unsigned char   func_tag;       /* fixed value 0x4 */
+               unsigned char   func_len;       /* fixed value 0x4 */
+               unsigned int    func_val;       /* function ID     */
+               unsigned char   dom_tag;        /* fixed value 0x4 */
+               unsigned char   dom_len;        /* fixed value 0x4 */
+               unsigned int    dom_val;        /* domain id       */
+       } __packed * payload_hdr;
+
+       /* length checks */
+       ap_msg->length = sizeof(struct type6_hdr) + xcRB->req_len;
+       if (ap_msg->length > MSGTYPE06_MAX_MSG_SIZE)
+               return -EINVAL;
+
+       if ((sizeof(struct type86_fmt2_msg) + CEIL4(xcRB->resp_len))
+                                        > MSGTYPE06_MAX_MSG_SIZE)
+               return -EINVAL;
+
+       /* prepare type6 header */
+       msg->hdr = static_type6_ep11_hdr;
+       msg->hdr.ToCardLen1   = xcRB->req_len;
+       msg->hdr.FromCardLen1 = xcRB->resp_len;
+
+       /* Import CPRB data from the ioctl input parameter */
+       if (copy_from_user(&(msg->cprbx.cprb_len),
+                          xcRB->req, xcRB->req_len)) {
+               return -EFAULT;
+       }
+
+       /*
+        The target domain field within the cprb body/payload block will be
+        replaced by the usage domain for non-management commands only.
+        Therefore we check the first bit of the 'flags' parameter for
+        management command indication.
+          0 - non managment command
+          1 - management command
+       */
+       if (!((msg->cprbx.flags & 0x80) == 0x80)) {
+               msg->cprbx.target_id = (unsigned int)
+                                       AP_QID_QUEUE(zdev->ap_dev->qid);
+
+               if ((msg->pld_lenfmt & 0x80) == 0x80) { /*ext.len.fmt 2 or 3*/
+                       switch (msg->pld_lenfmt & 0x03) {
+                       case 1:
+                               lfmt = 2;
+                               break;
+                       case 2:
+                               lfmt = 3;
+                               break;
+                       default:
+                               return -EINVAL;
+                       }
+               } else {
+                       lfmt = 1; /* length format #1 */
+                 }
+               payload_hdr = (struct pld_hdr *)((&(msg->pld_lenfmt))+lfmt);
+               payload_hdr->dom_val = (unsigned int)
+                                       AP_QID_QUEUE(zdev->ap_dev->qid);
+       }
+       return 0;
+}
+
 /**
  * Copy results from a type 86 ICA reply message back to user space.
  *
@@ -377,6 +465,12 @@ struct type86x_reply {
        char text[0];
 } __packed;
 
+struct type86_ep11_reply {
+       struct type86_hdr hdr;
+       struct type86_fmt2_ext fmt2;
+       struct ep11_cprb cprbx;
+} __packed;
+
 static int convert_type86_ica(struct zcrypt_device *zdev,
                          struct ap_message *reply,
                          char __user *outputdata,
@@ -440,6 +534,11 @@ static int convert_type86_ica(struct zcrypt_device *zdev,
                if (service_rc == 8 && service_rs == 72)
                        return -EINVAL;
                zdev->online = 0;
+               pr_err("Cryptographic device %x failed and was set offline\n",
+                      zdev->ap_dev->qid);
+               ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d",
+                              zdev->ap_dev->qid, zdev->online,
+                              msg->hdr.reply_code);
                return -EAGAIN; /* repeat the request on a different device. */
        }
        data = msg->text;
@@ -503,6 +602,30 @@ static int convert_type86_xcrb(struct zcrypt_device *zdev,
        return 0;
 }
 
+/**
+ * Copy results from a type 86 EP11 XCRB reply message back to user space.
+ *
+ * @zdev: crypto device pointer
+ * @reply: reply AP message.
+ * @xcRB: pointer to EP11 user request block
+ *
+ * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error.
+ */
+static int convert_type86_ep11_xcrb(struct zcrypt_device *zdev,
+                                   struct ap_message *reply,
+                                   struct ep11_urb *xcRB)
+{
+       struct type86_fmt2_msg *msg = reply->message;
+       char *data = reply->message;
+
+       /* Copy response CPRB to user */
+       if (copy_to_user(xcRB->resp,
+                        data + msg->fmt2.offset1, msg->fmt2.count1))
+               return -EFAULT;
+       xcRB->resp_len = msg->fmt2.count1;
+       return 0;
+}
+
 static int convert_type86_rng(struct zcrypt_device *zdev,
                          struct ap_message *reply,
                          char *buffer)
@@ -551,6 +674,10 @@ static int convert_response_ica(struct zcrypt_device *zdev,
                 * response */
        default: /* Unknown response type, this should NEVER EVER happen */
                zdev->online = 0;
+               pr_err("Cryptographic device %x failed and was set offline\n",
+                      zdev->ap_dev->qid);
+               ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail",
+                              zdev->ap_dev->qid, zdev->online);
                return -EAGAIN; /* repeat the request on a different device. */
        }
 }
@@ -579,10 +706,40 @@ static int convert_response_xcrb(struct zcrypt_device *zdev,
        default: /* Unknown response type, this should NEVER EVER happen */
                xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
                zdev->online = 0;
+               pr_err("Cryptographic device %x failed and was set offline\n",
+                      zdev->ap_dev->qid);
+               ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail",
+                              zdev->ap_dev->qid, zdev->online);
                return -EAGAIN; /* repeat the request on a different device. */
        }
 }
 
+static int convert_response_ep11_xcrb(struct zcrypt_device *zdev,
+       struct ap_message *reply, struct ep11_urb *xcRB)
+{
+       struct type86_ep11_reply *msg = reply->message;
+
+       /* Response type byte is the second byte in the response. */
+       switch (((unsigned char *)reply->message)[1]) {
+       case TYPE82_RSP_CODE:
+       case TYPE87_RSP_CODE:
+               return convert_error(zdev, reply);
+       case TYPE86_RSP_CODE:
+               if (msg->hdr.reply_code)
+                       return convert_error(zdev, reply);
+               if (msg->cprbx.cprb_ver_id == 0x04)
+                       return convert_type86_ep11_xcrb(zdev, reply, xcRB);
+       /* Fall through, no break, incorrect cprb version is an unknown resp.*/
+       default: /* Unknown response type, this should NEVER EVER happen */
+               zdev->online = 0;
+               pr_err("Cryptographic device %x failed and was set offline\n",
+                      zdev->ap_dev->qid);
+               ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail",
+                              zdev->ap_dev->qid, zdev->online);
+               return -EAGAIN; /* repeat the request on a different device. */
+       }
+}
+
 static int convert_response_rng(struct zcrypt_device *zdev,
                                 struct ap_message *reply,
                                 char *data)
@@ -602,6 +759,10 @@ static int convert_response_rng(struct zcrypt_device *zdev,
                 * response */
        default: /* Unknown response type, this should NEVER EVER happen */
                zdev->online = 0;
+               pr_err("Cryptographic device %x failed and was set offline\n",
+                      zdev->ap_dev->qid);
+               ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail",
+                              zdev->ap_dev->qid, zdev->online);
                return -EAGAIN; /* repeat the request on a different device. */
        }
 }
@@ -657,6 +818,51 @@ out:
        complete(&(resp_type->work));
 }
 
+/**
+ * This function is called from the AP bus code after a crypto request
+ * "msg" has finished with the reply message "reply".
+ * It is called from tasklet context.
+ * @ap_dev: pointer to the AP device
+ * @msg: pointer to the AP message
+ * @reply: pointer to the AP reply message
+ */
+static void zcrypt_msgtype6_receive_ep11(struct ap_device *ap_dev,
+                                        struct ap_message *msg,
+                                        struct ap_message *reply)
+{
+       static struct error_hdr error_reply = {
+               .type = TYPE82_RSP_CODE,
+               .reply_code = REP82_ERROR_MACHINE_FAILURE,
+       };
+       struct response_type *resp_type =
+               (struct response_type *)msg->private;
+       struct type86_ep11_reply *t86r;
+       int length;
+
+       /* Copy the reply message to the request message buffer. */
+       if (IS_ERR(reply)) {
+               memcpy(msg->message, &error_reply, sizeof(error_reply));
+               goto out;
+       }
+       t86r = reply->message;
+       if (t86r->hdr.type == TYPE86_RSP_CODE &&
+           t86r->cprbx.cprb_ver_id == 0x04) {
+               switch (resp_type->type) {
+               case PCIXCC_RESPONSE_TYPE_EP11:
+                       length = t86r->fmt2.offset1 + t86r->fmt2.count1;
+                       length = min(MSGTYPE06_MAX_MSG_SIZE, length);
+                       memcpy(msg->message, reply->message, length);
+                       break;
+               default:
+                       memcpy(msg->message, &error_reply, sizeof(error_reply));
+               }
+       } else {
+               memcpy(msg->message, reply->message, sizeof(error_reply));
+         }
+out:
+       complete(&(resp_type->work));
+}
+
 static atomic_t zcrypt_step = ATOMIC_INIT(0);
 
 /**
@@ -781,6 +987,46 @@ out_free:
        return rc;
 }
 
+/**
+ * The request distributor calls this function if it picked the CEX4P
+ * device to handle a send_ep11_cprb request.
+ * @zdev: pointer to zcrypt_device structure that identifies the
+ *       CEX4P device to the request distributor
+ * @xcRB: pointer to the ep11 user request block
+ */
+static long zcrypt_msgtype6_send_ep11_cprb(struct zcrypt_device *zdev,
+                                               struct ep11_urb *xcrb)
+{
+       struct ap_message ap_msg;
+       struct response_type resp_type = {
+               .type = PCIXCC_RESPONSE_TYPE_EP11,
+       };
+       int rc;
+
+       ap_init_message(&ap_msg);
+       ap_msg.message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL);
+       if (!ap_msg.message)
+               return -ENOMEM;
+       ap_msg.receive = zcrypt_msgtype6_receive_ep11;
+       ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
+                               atomic_inc_return(&zcrypt_step);
+       ap_msg.private = &resp_type;
+       rc = xcrb_msg_to_type6_ep11cprb_msgx(zdev, &ap_msg, xcrb);
+       if (rc)
+               goto out_free;
+       init_completion(&resp_type.work);
+       ap_queue_message(zdev->ap_dev, &ap_msg);
+       rc = wait_for_completion_interruptible(&resp_type.work);
+       if (rc == 0)
+               rc = convert_response_ep11_xcrb(zdev, &ap_msg, xcrb);
+       else /* Signal pending. */
+               ap_cancel_message(zdev->ap_dev, &ap_msg);
+
+out_free:
+       kzfree(ap_msg.message);
+       return rc;
+}
+
 /**
  * The request distributor calls this function if it picked the PCIXCC/CEX2C
  * device to generate random data.
@@ -839,10 +1085,19 @@ static struct zcrypt_ops zcrypt_msgtype6_ops = {
        .rng = zcrypt_msgtype6_rng,
 };
 
+static struct zcrypt_ops zcrypt_msgtype6_ep11_ops = {
+       .owner = THIS_MODULE,
+       .variant = MSGTYPE06_VARIANT_EP11,
+       .rsa_modexpo = NULL,
+       .rsa_modexpo_crt = NULL,
+       .send_ep11_cprb = zcrypt_msgtype6_send_ep11_cprb,
+};
+
 int __init zcrypt_msgtype6_init(void)
 {
        zcrypt_msgtype_register(&zcrypt_msgtype6_norng_ops);
        zcrypt_msgtype_register(&zcrypt_msgtype6_ops);
+       zcrypt_msgtype_register(&zcrypt_msgtype6_ep11_ops);
        return 0;
 }
 
@@ -850,6 +1105,7 @@ void __exit zcrypt_msgtype6_exit(void)
 {
        zcrypt_msgtype_unregister(&zcrypt_msgtype6_norng_ops);
        zcrypt_msgtype_unregister(&zcrypt_msgtype6_ops);
+       zcrypt_msgtype_unregister(&zcrypt_msgtype6_ep11_ops);
 }
 
 module_init(zcrypt_msgtype6_init);
index 1e500d3c073571fe764bd1111cd8a2a7b10e7751..207247570623709c946f3a7708d3e3bfc7a0313e 100644 (file)
@@ -32,6 +32,7 @@
 #define MSGTYPE06_NAME                 "zcrypt_msgtype6"
 #define MSGTYPE06_VARIANT_DEFAULT      0
 #define MSGTYPE06_VARIANT_NORNG                1
+#define MSGTYPE06_VARIANT_EP11         2
 
 #define MSGTYPE06_MAX_MSG_SIZE         (12*1024)
 
@@ -99,6 +100,7 @@ struct type86_hdr {
 } __packed;
 
 #define TYPE86_RSP_CODE 0x86
+#define TYPE87_RSP_CODE 0x87
 #define TYPE86_FMT2    0x02
 
 struct type86_fmt2_ext {
index f2b71d8df01f0c1e42e75bd7b0f9786bbf881cae..7a743f4c646c0e46dadcaed195acc9bccf1bf183 100644 (file)
@@ -24,6 +24,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define KMSG_COMPONENT "zcrypt"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/init.h>
@@ -199,6 +202,10 @@ static int convert_type84(struct zcrypt_device *zdev,
        if (t84h->len < sizeof(*t84h) + outputdatalength) {
                /* The result is too short, the PCICA card may not do that.. */
                zdev->online = 0;
+               pr_err("Cryptographic device %x failed and was set offline\n",
+                      zdev->ap_dev->qid);
+               ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d",
+                              zdev->ap_dev->qid, zdev->online, t84h->code);
                return -EAGAIN; /* repeat the request on a different device. */
        }
        BUG_ON(t84h->len > PCICA_MAX_RESPONSE_SIZE);
@@ -223,6 +230,10 @@ static int convert_response(struct zcrypt_device *zdev,
                                      outputdata, outputdatalength);
        default: /* Unknown response type, this should NEVER EVER happen */
                zdev->online = 0;
+               pr_err("Cryptographic device %x failed and was set offline\n",
+                      zdev->ap_dev->qid);
+               ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail",
+                              zdev->ap_dev->qid, zdev->online);
                return -EAGAIN; /* repeat the request on a different device. */
        }
 }
index 0d90a4334055efcc22ae73a290c53d83fcee8530..4d14c04b746e14ebe656ae08bc14843aee093a45 100644 (file)
@@ -24,6 +24,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define KMSG_COMPONENT "zcrypt"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/gfp.h>
@@ -372,6 +375,11 @@ static int convert_type86(struct zcrypt_device *zdev,
                if (service_rc == 8 && service_rs == 72)
                        return -EINVAL;
                zdev->online = 0;
+               pr_err("Cryptographic device %x failed and was set offline\n",
+                      zdev->ap_dev->qid);
+               ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d",
+                              zdev->ap_dev->qid, zdev->online,
+                              msg->hdr.reply_code);
                return -EAGAIN; /* repeat the request on a different device. */
        }
        data = msg->text;
@@ -425,6 +433,10 @@ static int convert_response(struct zcrypt_device *zdev,
                /* no break, incorrect cprb version is an unknown response */
        default: /* Unknown response type, this should NEVER EVER happen */
                zdev->online = 0;
+               pr_err("Cryptographic device %x failed and was set offline\n",
+                      zdev->ap_dev->qid);
+               ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail",
+                              zdev->ap_dev->qid, zdev->online);
                return -EAGAIN; /* repeat the request on a different device. */
        }
 }
index 5e1e12c0cf4220796112d2d6dd9d9e102fdf537d..0a7325361d2958dceeae99da5959e518f8490985 100644 (file)
@@ -2025,7 +2025,8 @@ static struct scsi_host_template driver_template = {
        .cmd_per_lun            = TW_MAX_CMDS_PER_LUN,
        .use_clustering         = ENABLE_CLUSTERING,
        .shost_attrs            = twa_host_attrs,
-       .emulated               = 1
+       .emulated               = 1,
+       .no_write_same          = 1,
 };
 
 /* This function will probe and initialize a card */
index c845bdbeb6c06f971923300e7f8e11182d18d84c..4de346017e9ff91b43aed80d48231ac60f23a4e3 100644 (file)
@@ -1600,7 +1600,8 @@ static struct scsi_host_template driver_template = {
        .cmd_per_lun            = TW_MAX_CMDS_PER_LUN,
        .use_clustering         = ENABLE_CLUSTERING,
        .shost_attrs            = twl_host_attrs,
-       .emulated               = 1
+       .emulated               = 1,
+       .no_write_same          = 1,
 };
 
 /* This function will probe and initialize a card */
index b9276d10b25c2e277c05e1b6e48e196a11b38fa4..752624e6bc0022807c6265539cad6d8b42d1611f 100644 (file)
@@ -2279,7 +2279,8 @@ static struct scsi_host_template driver_template = {
        .cmd_per_lun            = TW_MAX_CMDS_PER_LUN,  
        .use_clustering         = ENABLE_CLUSTERING,
        .shost_attrs            = tw_host_attrs,
-       .emulated               = 1
+       .emulated               = 1,
+       .no_write_same          = 1,
 };
 
 /* This function will probe and initialize a card */
index fe25677a551162789b0299247d88327dcbd48940..a2d61d061be7ba096374edde4dc0e3b47d7ff986 100644 (file)
@@ -204,9 +204,9 @@ config SCSI_MULTI_LUN
          Some devices support more than one LUN (Logical Unit Number) in order
          to allow access to several media, e.g. CD jukebox, USB card reader,
          mobile phone in mass storage mode. This option forces the kernel to
-         probe for all LUNs by default. This setting can be overriden by
+         probe for all LUNs by default. This setting can be overridden by
          max_luns boot/module parameter. Note that this option does not affect
-         devices conforming to SCSI-3 or higher as they can explicitely report
+         devices conforming to SCSI-3 or higher as they can explicitly report
          their number of LUNs. It is safe to say Y here unless you have one of
          those rare devices which reacts in an unexpected way when probed for
          multiple LUNs.
index 30fa38a0ad39a33102f1cd4656b4d800c498ae07..9176bfbd574586ab04a62786253271b1a1636006 100644 (file)
@@ -201,7 +201,7 @@ static int a2091_probe(struct zorro_dev *z, const struct zorro_device_id *ent)
        instance->irq = IRQ_AMIGA_PORTS;
        instance->unique_id = z->slotaddr;
 
-       regs = (struct a2091_scsiregs *)ZTWO_VADDR(z->resource.start);
+       regs = ZTWO_VADDR(z->resource.start);
        regs->DAWR = DAWR_A2091;
 
        wdregs.SASR = &regs->SASR;
index c0f4f4290dd60dbeb836f547b097ca8b7141eaaf..dd5b64726ddc3c5f9dcee231501630c66424b9ab 100644 (file)
@@ -220,7 +220,7 @@ static int __init amiga_a3000_scsi_probe(struct platform_device *pdev)
 
        instance->irq = IRQ_AMIGA_PORTS;
 
-       regs = (struct a3000_scsiregs *)ZTWO_VADDR(res->start);
+       regs = ZTWO_VADDR(res->start);
        regs->DAWR = DAWR_A3000;
 
        wdregs.SASR = &regs->SASR;
index 70c521f79f7c26fbc92b65645b780e927c7fcac3..f5a2ab41543bd0bd9006a3af5687085343a25220 100644 (file)
@@ -56,7 +56,7 @@ static int __init amiga_a4000t_scsi_probe(struct platform_device *pdev)
        scsi_addr = res->start + A4000T_SCSI_OFFSET;
 
        /* Fill in the required pieces of hostdata */
-       hostdata->base = (void __iomem *)ZTWO_VADDR(scsi_addr);
+       hostdata->base = ZTWO_VADDR(scsi_addr);
        hostdata->clock = 50;
        hostdata->chip710 = 1;
        hostdata->dmode_extra = DMODE_FC2;
index f0d432c139d0cecedf51295562c858d22a9f44f0..4921ed19a027f819b731271c4804be74d2426e5a 100644 (file)
@@ -1081,6 +1081,7 @@ static struct scsi_host_template aac_driver_template = {
 #endif
        .use_clustering                 = ENABLE_CLUSTERING,
        .emulated                       = 1,
+       .no_write_same                  = 1,
 };
 
 static void __aac_shutdown(struct aac_dev * aac)
index 97fd450aff09315194233e7a8ea1f06b566248ef..4f6a30b8e5f99bb3cba345bfec806cdc4972b9f3 100644 (file)
@@ -137,6 +137,7 @@ static struct scsi_host_template arcmsr_scsi_host_template = {
        .cmd_per_lun            = ARCMSR_MAX_CMD_PERLUN,
        .use_clustering         = ENABLE_CLUSTERING,
        .shost_attrs            = arcmsr_host_attrs,
+       .no_write_same          = 1,
 };
 static struct pci_device_id arcmsr_device_id_table[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1110)},
index 94d5d0102f7dcc4da5754591a828b47699cec644..42bcb970445a8a7212fafa1aa7285639d5c7d8a3 100644 (file)
@@ -296,6 +296,7 @@ wwn_t bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn,
 struct bfa_fcs_lport_s *bfa_fcs_lookup_port(struct bfa_fcs_s *fcs,
                                            u16 vf_id, wwn_t lpwwn);
 
+void bfa_fcs_lport_set_symname(struct bfa_fcs_lport_s *port, char *symname);
 void bfa_fcs_lport_get_info(struct bfa_fcs_lport_s *port,
                            struct bfa_lport_info_s *port_info);
 void bfa_fcs_lport_get_attr(struct bfa_fcs_lport_s *port,
index 2f61a5af36581bce4db052d09d7024352063f0a4..f5e4e61a0fd7ba5bd461e0f79bd2f333317bf74a 100644 (file)
@@ -1097,6 +1097,17 @@ bfa_fcs_lport_init(struct bfa_fcs_lport_s *lport,
        bfa_sm_send_event(lport, BFA_FCS_PORT_SM_CREATE);
 }
 
+void
+bfa_fcs_lport_set_symname(struct bfa_fcs_lport_s *port,
+                               char *symname)
+{
+       strcpy(port->port_cfg.sym_name.symname, symname);
+
+       if (bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online))
+               bfa_fcs_lport_ns_util_send_rspn_id(
+                       BFA_FCS_GET_NS_FROM_PORT(port), NULL);
+}
+
 /*
  *  fcs_lport_api
  */
@@ -5140,9 +5151,6 @@ bfa_fcs_lport_ns_util_send_rspn_id(void *cbarg, struct bfa_fcxp_s *fcxp_alloced)
        u8 *psymbl = &symbl[0];
        int len;
 
-       if (!bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online))
-               return;
-
        /* Avoid sending RSPN in the following states. */
        if (bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_offline) ||
            bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_plogi_sending) ||
index e9a681d31223cffca67210615a45c6813f1d56af..40be670a1cbc865c4b39694d10e86584f0dc6321 100644 (file)
@@ -593,11 +593,8 @@ bfad_im_vport_set_symbolic_name(struct fc_vport *fc_vport)
                return;
 
        spin_lock_irqsave(&bfad->bfad_lock, flags);
-       if (strlen(sym_name) > 0) {
-               strcpy(fcs_vport->lport.port_cfg.sym_name.symname, sym_name);
-               bfa_fcs_lport_ns_util_send_rspn_id(
-                       BFA_FCS_GET_NS_FROM_PORT((&fcs_vport->lport)), NULL);
-       }
+       if (strlen(sym_name) > 0)
+               bfa_fcs_lport_set_symname(&fcs_vport->lport, sym_name);
        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 }
 
index ee4fa40a50b131597a3e1b6960bffc17191f2d03..ce5ef0190bad3f99f7459a859ce0ca0a1e947246 100644 (file)
@@ -4684,6 +4684,7 @@ static struct scsi_host_template gdth_template = {
         .cmd_per_lun            = GDTH_MAXC_P_L,
         .unchecked_isa_dma      = 1,
         .use_clustering         = ENABLE_CLUSTERING,
+       .no_write_same          = 1,
 };
 
 #ifdef CONFIG_ISA
index 2203ac281103b964917f47c1095d6c6a233ec7bf..3b6f83ffddc4e87c59057d0f7eb8a4ded51f11f4 100644 (file)
@@ -310,7 +310,7 @@ static int gvp11_probe(struct zorro_dev *z, const struct zorro_device_id *ent)
        if (!request_mem_region(address, 256, "wd33c93"))
                return -EBUSY;
 
-       regs = (struct gvp11_scsiregs *)(ZTWO_VADDR(address));
+       regs = ZTWO_VADDR(address);
 
        error = check_wd33c93(regs);
        if (error)
index f334859024c0652e3ce9bd197c66ca39b877af65..f2c5005f312af9aabeb25f8831ee17b5f28f6a42 100644 (file)
@@ -395,6 +395,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
        shost->use_clustering = sht->use_clustering;
        shost->ordered_tag = sht->ordered_tag;
        shost->eh_deadline = shost_eh_deadline * HZ;
+       shost->no_write_same = sht->no_write_same;
 
        if (sht->supported_mode == MODE_UNKNOWN)
                /* means we didn't set it ... default to INITIATOR */
index 22f6432eb4755a20af732e8c4d4060e9fbb9e909..20a5e6ecf945fab55a982840d6921046b4c552bf 100644 (file)
@@ -561,6 +561,7 @@ static struct scsi_host_template hpsa_driver_template = {
        .sdev_attrs = hpsa_sdev_attrs,
        .shost_attrs = hpsa_shost_attrs,
        .max_sectors = 8192,
+       .no_write_same = 1,
 };
 
 
@@ -1288,7 +1289,7 @@ static void complete_scsi_command(struct CommandList *cp)
                                        "has check condition: aborted command: "
                                        "ASC: 0x%x, ASCQ: 0x%x\n",
                                        cp, asc, ascq);
-                               cmd->result = DID_SOFT_ERROR << 16;
+                               cmd->result |= DID_SOFT_ERROR << 16;
                                break;
                        }
                        /* Must be some other type of check condition */
@@ -4925,7 +4926,7 @@ reinit_after_soft_reset:
        hpsa_hba_inquiry(h);
        hpsa_register_scsi(h);  /* hook ourselves into SCSI subsystem */
        start_controller_lockup_detector(h);
-       return 1;
+       return 0;
 
 clean4:
        hpsa_free_sg_chain_blocks(h);
index 36ac1c34ce97eb53374f55451b8b42f4752b88f2..573f4128b6b68018f43a3263d166232ef39601fc 100644 (file)
@@ -6305,7 +6305,8 @@ static struct scsi_host_template driver_template = {
        .use_clustering = ENABLE_CLUSTERING,
        .shost_attrs = ipr_ioa_attrs,
        .sdev_attrs = ipr_dev_attrs,
-       .proc_name = IPR_NAME
+       .proc_name = IPR_NAME,
+       .no_write_same = 1,
 };
 
 /**
index 8d5ea8a1e5a6f33ab8235b300417d7ba352f84f7..52a216f21ae579644b97c093e89e12306a265595 100644 (file)
@@ -374,6 +374,7 @@ static struct scsi_host_template ips_driver_template = {
        .sg_tablesize           = IPS_MAX_SG,
        .cmd_per_lun            = 3,
        .use_clustering         = ENABLE_CLUSTERING,
+       .no_write_same          = 1,
 };
 
 
index 161c98efade9b9f290c04588e4638df0f3c421ac..d2895836f9fa4c00fec1a46d993074ecb3edeaea 100644 (file)
@@ -211,7 +211,7 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc)
                qc->tf.nsect = 0;
        }
 
-       ata_tf_to_fis(&qc->tf, 1, 0, (u8*)&task->ata_task.fis);
+       ata_tf_to_fis(&qc->tf, qc->dev->link->pmp, 1, (u8 *)&task->ata_task.fis);
        task->uldd_task = qc;
        if (ata_is_atapi(qc->tf.protocol)) {
                memcpy(task->ata_task.atapi_packet, qc->cdb, qc->dev->cdb_len);
index 446b85110a1fc0a69b07e42bb3ecc7144d76d1ce..0cac7d8fd0f7cac75b0ecc2d63662d18eeda4a56 100644 (file)
@@ -2163,10 +2163,10 @@ int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
        }
 
        /* do we need to support multiple segments? */
-       if (bio_segments(req->bio) > 1 || bio_segments(rsp->bio) > 1) {
-               printk("%s: multiple segments req %u %u, rsp %u %u\n",
-                      __func__, bio_segments(req->bio), blk_rq_bytes(req),
-                      bio_segments(rsp->bio), blk_rq_bytes(rsp));
+       if (bio_multiple_segments(req->bio) ||
+           bio_multiple_segments(rsp->bio)) {
+               printk("%s: multiple segments req %u, rsp %u\n",
+                      __func__, blk_rq_bytes(req), blk_rq_bytes(rsp));
                return -EINVAL;
        }
 
index 90c95a3385d18bb52f93093da10c8d400514f712..816db12ef5d555159226c5eb618b110ebb790776 100644 (file)
@@ -4244,6 +4244,7 @@ static struct scsi_host_template megaraid_template = {
        .eh_device_reset_handler        = megaraid_reset,
        .eh_bus_reset_handler           = megaraid_reset,
        .eh_host_reset_handler          = megaraid_reset,
+       .no_write_same                  = 1,
 };
 
 static int
index d1a4b82836ea6936f55504e33bcaabb5db9adbee..e2237a97cb9d314b485869cc37da7e3de8062531 100644 (file)
@@ -367,6 +367,7 @@ static struct scsi_host_template megaraid_template_g = {
        .eh_host_reset_handler          = megaraid_reset_handler,
        .change_queue_depth             = megaraid_change_queue_depth,
        .use_clustering                 = ENABLE_CLUSTERING,
+       .no_write_same                  = 1,
        .sdev_attrs                     = megaraid_sdev_attrs,
        .shost_attrs                    = megaraid_shost_attrs,
 };
index 0a743a5d16477a5e168f02a77a99e90f201caac3..c99812bf2a732f7180c291f3dcc23b5eda81a74c 100644 (file)
@@ -2148,6 +2148,7 @@ static struct scsi_host_template megasas_template = {
        .bios_param = megasas_bios_param,
        .use_clustering = ENABLE_CLUSTERING,
        .change_queue_depth = megasas_change_queue_depth,
+       .no_write_same = 1,
 };
 
 /**
index 9d26637308bebe2fc2b2fdec681891cfcbaf9b07..410f4a3e88887a6f0087c06f9da42f22b61f556d 100644 (file)
@@ -1901,7 +1901,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
        struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
        Mpi2SmpPassthroughRequest_t *mpi_request;
        Mpi2SmpPassthroughReply_t *mpi_reply;
-       int rc, i;
+       int rc;
        u16 smid;
        u32 ioc_state;
        unsigned long timeleft;
@@ -1916,7 +1916,8 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
        void *pci_addr_out = NULL;
        u16 wait_state_count;
        struct request *rsp = req->next_rq;
-       struct bio_vec *bvec = NULL;
+       struct bio_vec bvec;
+       struct bvec_iter iter;
 
        if (!rsp) {
                printk(MPT2SAS_ERR_FMT "%s: the smp response space is "
@@ -1942,7 +1943,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
        ioc->transport_cmds.status = MPT2_CMD_PENDING;
 
        /* Check if the request is split across multiple segments */
-       if (bio_segments(req->bio) > 1) {
+       if (bio_multiple_segments(req->bio)) {
                u32 offset = 0;
 
                /* Allocate memory and copy the request */
@@ -1955,11 +1956,11 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
                        goto out;
                }
 
-               bio_for_each_segment(bvec, req->bio, i) {
+               bio_for_each_segment(bvec, req->bio, iter) {
                        memcpy(pci_addr_out + offset,
-                           page_address(bvec->bv_page) + bvec->bv_offset,
-                           bvec->bv_len);
-                       offset += bvec->bv_len;
+                           page_address(bvec.bv_page) + bvec.bv_offset,
+                           bvec.bv_len);
+                       offset += bvec.bv_len;
                }
        } else {
                dma_addr_out = pci_map_single(ioc->pdev, bio_data(req->bio),
@@ -1974,7 +1975,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
 
        /* Check if the response needs to be populated across
         * multiple segments */
-       if (bio_segments(rsp->bio) > 1) {
+       if (bio_multiple_segments(rsp->bio)) {
                pci_addr_in = pci_alloc_consistent(ioc->pdev, blk_rq_bytes(rsp),
                    &pci_dma_in);
                if (!pci_addr_in) {
@@ -2041,7 +2042,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
        sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
            MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
        sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
-       if (bio_segments(req->bio) > 1) {
+       if (bio_multiple_segments(req->bio)) {
                ioc->base_add_sg_single(psge, sgl_flags |
                    (blk_rq_bytes(req) - 4), pci_dma_out);
        } else {
@@ -2057,7 +2058,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
            MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
            MPI2_SGE_FLAGS_END_OF_LIST);
        sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
-       if (bio_segments(rsp->bio) > 1) {
+       if (bio_multiple_segments(rsp->bio)) {
                ioc->base_add_sg_single(psge, sgl_flags |
                    (blk_rq_bytes(rsp) + 4), pci_dma_in);
        } else {
@@ -2102,23 +2103,23 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
                    le16_to_cpu(mpi_reply->ResponseDataLength);
                /* check if the resp needs to be copied from the allocated
                 * pci mem */
-               if (bio_segments(rsp->bio) > 1) {
+               if (bio_multiple_segments(rsp->bio)) {
                        u32 offset = 0;
                        u32 bytes_to_copy =
                            le16_to_cpu(mpi_reply->ResponseDataLength);
-                       bio_for_each_segment(bvec, rsp->bio, i) {
-                               if (bytes_to_copy <= bvec->bv_len) {
-                                       memcpy(page_address(bvec->bv_page) +
-                                           bvec->bv_offset, pci_addr_in +
+                       bio_for_each_segment(bvec, rsp->bio, iter) {
+                               if (bytes_to_copy <= bvec.bv_len) {
+                                       memcpy(page_address(bvec.bv_page) +
+                                           bvec.bv_offset, pci_addr_in +
                                            offset, bytes_to_copy);
                                        break;
                                } else {
-                                       memcpy(page_address(bvec->bv_page) +
-                                           bvec->bv_offset, pci_addr_in +
-                                           offset, bvec->bv_len);
-                                       bytes_to_copy -= bvec->bv_len;
+                                       memcpy(page_address(bvec.bv_page) +
+                                           bvec.bv_offset, pci_addr_in +
+                                           offset, bvec.bv_len);
+                                       bytes_to_copy -= bvec.bv_len;
                                }
-                               offset += bvec->bv_len;
+                               offset += bvec.bv_len;
                        }
                }
        } else {
index e771a88c6a7441c45c6b49e8ffb85d5258b22e99..65170cb1a00fa5fa0ca3c95a94e3ed686edca9f7 100644 (file)
@@ -1884,7 +1884,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
        struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
        Mpi2SmpPassthroughRequest_t *mpi_request;
        Mpi2SmpPassthroughReply_t *mpi_reply;
-       int rc, i;
+       int rc;
        u16 smid;
        u32 ioc_state;
        unsigned long timeleft;
@@ -1898,7 +1898,8 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
        void *pci_addr_out = NULL;
        u16 wait_state_count;
        struct request *rsp = req->next_rq;
-       struct bio_vec *bvec = NULL;
+       struct bio_vec bvec;
+       struct bvec_iter iter;
 
        if (!rsp) {
                pr_err(MPT3SAS_FMT "%s: the smp response space is missing\n",
@@ -1925,7 +1926,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
        ioc->transport_cmds.status = MPT3_CMD_PENDING;
 
        /* Check if the request is split across multiple segments */
-       if (req->bio->bi_vcnt > 1) {
+       if (bio_multiple_segments(req->bio)) {
                u32 offset = 0;
 
                /* Allocate memory and copy the request */
@@ -1938,11 +1939,11 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
                        goto out;
                }
 
-               bio_for_each_segment(bvec, req->bio, i) {
+               bio_for_each_segment(bvec, req->bio, iter) {
                        memcpy(pci_addr_out + offset,
-                           page_address(bvec->bv_page) + bvec->bv_offset,
-                           bvec->bv_len);
-                       offset += bvec->bv_len;
+                           page_address(bvec.bv_page) + bvec.bv_offset,
+                           bvec.bv_len);
+                       offset += bvec.bv_len;
                }
        } else {
                dma_addr_out = pci_map_single(ioc->pdev, bio_data(req->bio),
@@ -1957,7 +1958,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
 
        /* Check if the response needs to be populated across
         * multiple segments */
-       if (rsp->bio->bi_vcnt > 1) {
+       if (bio_multiple_segments(rsp->bio)) {
                pci_addr_in = pci_alloc_consistent(ioc->pdev, blk_rq_bytes(rsp),
                    &pci_dma_in);
                if (!pci_addr_in) {
@@ -2018,7 +2019,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
        mpi_request->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4);
        psge = &mpi_request->SGL;
 
-       if (req->bio->bi_vcnt > 1)
+       if (bio_multiple_segments(req->bio))
                ioc->build_sg(ioc, psge, pci_dma_out, (blk_rq_bytes(req) - 4),
                    pci_dma_in, (blk_rq_bytes(rsp) + 4));
        else
@@ -2063,23 +2064,23 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
 
                /* check if the resp needs to be copied from the allocated
                 * pci mem */
-               if (rsp->bio->bi_vcnt > 1) {
+               if (bio_multiple_segments(rsp->bio)) {
                        u32 offset = 0;
                        u32 bytes_to_copy =
                            le16_to_cpu(mpi_reply->ResponseDataLength);
-                       bio_for_each_segment(bvec, rsp->bio, i) {
-                               if (bytes_to_copy <= bvec->bv_len) {
-                                       memcpy(page_address(bvec->bv_page) +
-                                           bvec->bv_offset, pci_addr_in +
+                       bio_for_each_segment(bvec, rsp->bio, iter) {
+                               if (bytes_to_copy <= bvec.bv_len) {
+                                       memcpy(page_address(bvec.bv_page) +
+                                           bvec.bv_offset, pci_addr_in +
                                            offset, bytes_to_copy);
                                        break;
                                } else {
-                                       memcpy(page_address(bvec->bv_page) +
-                                           bvec->bv_offset, pci_addr_in +
-                                           offset, bvec->bv_len);
-                                       bytes_to_copy -= bvec->bv_len;
+                                       memcpy(page_address(bvec.bv_page) +
+                                           bvec.bv_offset, pci_addr_in +
+                                           offset, bvec.bv_len);
+                                       bytes_to_copy -= bvec.bv_len;
                                }
-                               offset += bvec->bv_len;
+                               offset += bvec.bv_len;
                        }
                }
        } else {
index aa66361ed44b71772da913c74c69640b43909f23..bac04c2335aaf997c73e7b3b8b8a08129bfca455 100644 (file)
@@ -731,7 +731,7 @@ static int _osd_req_list_objects(struct osd_request *or,
 
        bio->bi_rw &= ~REQ_WRITE;
        or->in.bio = bio;
-       or->in.total_bytes = bio->bi_size;
+       or->in.total_bytes = bio->bi_iter.bi_size;
        return 0;
 }
 
index f16ece91b94ac73de979eda5496925c1d253b37b..0a1296a87d66d5919859ea586a8637109b537c50 100644 (file)
@@ -3403,6 +3403,7 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
        unsigned long flags;
        u8 deviceType = pPayload->sas_identify.dev_type;
        port->port_state =  portstate;
+       phy->phy_state = PHY_STATE_LINK_UP_SPC;
        PM8001_MSG_DBG(pm8001_ha,
                pm8001_printk("HW_EVENT_SAS_PHY_UP port id = %d, phy id = %d\n",
                port_id, phy_id));
@@ -3483,6 +3484,7 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
                pm8001_printk("HW_EVENT_SATA_PHY_UP port id = %d,"
                " phy id = %d\n", port_id, phy_id));
        port->port_state =  portstate;
+       phy->phy_state = PHY_STATE_LINK_UP_SPC;
        port->port_attached = 1;
        pm8001_get_lrate_mode(phy, link_rate);
        phy->phy_type |= PORT_TYPE_SATA;
index 6d91e2446542c78290dfba8f9e846380ccda3067..e4867e690c846db4ab2954644b959cc044f39f83 100644 (file)
 #define LINKRATE_30                    (0x02 << 8)
 #define LINKRATE_60                    (0x04 << 8)
 
+/* for phy state */
+
+#define PHY_STATE_LINK_UP_SPC          0x1
+
 /* for new SPC controllers MEMBASE III is shared between BIOS and DATA */
 #define GSM_SM_BASE                    0x4F0000
 struct mpi_msg_hdr{
index 34f5f5ffef056ec2e86e44726dd99c13ae204877..73a120d81b4dacf7c22e3b99c07458680dacbaf5 100644 (file)
@@ -175,20 +175,16 @@ static void pm8001_free(struct pm8001_hba_info *pm8001_ha)
 static void pm8001_tasklet(unsigned long opaque)
 {
        struct pm8001_hba_info *pm8001_ha;
-       u32 vec;
-       pm8001_ha = (struct pm8001_hba_info *)opaque;
+       struct isr_param *irq_vector;
+
+       irq_vector = (struct isr_param *)opaque;
+       pm8001_ha = irq_vector->drv_inst;
        if (unlikely(!pm8001_ha))
                BUG_ON(1);
-       vec = pm8001_ha->int_vector;
-       PM8001_CHIP_DISP->isr(pm8001_ha, vec);
+       PM8001_CHIP_DISP->isr(pm8001_ha, irq_vector->irq_id);
 }
 #endif
 
-static struct  pm8001_hba_info *outq_to_hba(u8 *outq)
-{
-       return container_of((outq - *outq), struct pm8001_hba_info, outq[0]);
-}
-
 /**
  * pm8001_interrupt_handler_msix - main MSIX interrupt handler.
  * It obtains the vector number and calls the equivalent bottom
@@ -198,18 +194,20 @@ static struct  pm8001_hba_info *outq_to_hba(u8 *outq)
  */
 static irqreturn_t pm8001_interrupt_handler_msix(int irq, void *opaque)
 {
-       struct pm8001_hba_info *pm8001_ha = outq_to_hba(opaque);
-       u8 outq = *(u8 *)opaque;
+       struct isr_param *irq_vector;
+       struct pm8001_hba_info *pm8001_ha;
        irqreturn_t ret = IRQ_HANDLED;
+       irq_vector = (struct isr_param *)opaque;
+       pm8001_ha = irq_vector->drv_inst;
+
        if (unlikely(!pm8001_ha))
                return IRQ_NONE;
        if (!PM8001_CHIP_DISP->is_our_interupt(pm8001_ha))
                return IRQ_NONE;
-       pm8001_ha->int_vector = outq;
 #ifdef PM8001_USE_TASKLET
-       tasklet_schedule(&pm8001_ha->tasklet);
+       tasklet_schedule(&pm8001_ha->tasklet[irq_vector->irq_id]);
 #else
-       ret = PM8001_CHIP_DISP->isr(pm8001_ha, outq);
+       ret = PM8001_CHIP_DISP->isr(pm8001_ha, irq_vector->irq_id);
 #endif
        return ret;
 }
@@ -230,9 +228,8 @@ static irqreturn_t pm8001_interrupt_handler_intx(int irq, void *dev_id)
        if (!PM8001_CHIP_DISP->is_our_interupt(pm8001_ha))
                return IRQ_NONE;
 
-       pm8001_ha->int_vector = 0;
 #ifdef PM8001_USE_TASKLET
-       tasklet_schedule(&pm8001_ha->tasklet);
+       tasklet_schedule(&pm8001_ha->tasklet[0]);
 #else
        ret = PM8001_CHIP_DISP->isr(pm8001_ha, 0);
 #endif
@@ -457,7 +454,7 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev,
 {
        struct pm8001_hba_info *pm8001_ha;
        struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
-
+       int j;
 
        pm8001_ha = sha->lldd_ha;
        if (!pm8001_ha)
@@ -480,12 +477,14 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev,
                pm8001_ha->iomb_size = IOMB_SIZE_SPC;
 
 #ifdef PM8001_USE_TASKLET
-       /**
-       * default tasklet for non msi-x interrupt handler/first msi-x
-       * interrupt handler
-       **/
-       tasklet_init(&pm8001_ha->tasklet, pm8001_tasklet,
-                       (unsigned long)pm8001_ha);
+       /* Tasklet for non msi-x interrupt handler */
+       if ((!pdev->msix_cap) || (pm8001_ha->chip_id == chip_8001))
+               tasklet_init(&pm8001_ha->tasklet[0], pm8001_tasklet,
+                       (unsigned long)&(pm8001_ha->irq_vector[0]));
+       else
+               for (j = 0; j < PM8001_MAX_MSIX_VEC; j++)
+                       tasklet_init(&pm8001_ha->tasklet[j], pm8001_tasklet,
+                               (unsigned long)&(pm8001_ha->irq_vector[j]));
 #endif
        pm8001_ioremap(pm8001_ha);
        if (!pm8001_alloc(pm8001_ha, ent))
@@ -733,19 +732,20 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha)
                        "pci_enable_msix request ret:%d no of intr %d\n",
                                        rc, pm8001_ha->number_of_intr));
 
-               for (i = 0; i < number_of_intr; i++)
-                       pm8001_ha->outq[i] = i;
 
                for (i = 0; i < number_of_intr; i++) {
                        snprintf(intr_drvname[i], sizeof(intr_drvname[0]),
                                        DRV_NAME"%d", i);
+                       pm8001_ha->irq_vector[i].irq_id = i;
+                       pm8001_ha->irq_vector[i].drv_inst = pm8001_ha;
+
                        if (request_irq(pm8001_ha->msix_entries[i].vector,
                                pm8001_interrupt_handler_msix, flag,
-                               intr_drvname[i], &pm8001_ha->outq[i])) {
+                               intr_drvname[i], &(pm8001_ha->irq_vector[i]))) {
                                for (j = 0; j < i; j++)
                                        free_irq(
                                        pm8001_ha->msix_entries[j].vector,
-                                       &pm8001_ha->outq[j]);
+                                       &(pm8001_ha->irq_vector[i]));
                                pci_disable_msix(pm8001_ha->pdev);
                                break;
                        }
@@ -907,7 +907,7 @@ static void pm8001_pci_remove(struct pci_dev *pdev)
 {
        struct sas_ha_struct *sha = pci_get_drvdata(pdev);
        struct pm8001_hba_info *pm8001_ha;
-       int i;
+       int i, j;
        pm8001_ha = sha->lldd_ha;
        sas_unregister_ha(sha);
        sas_remove_host(pm8001_ha->shost);
@@ -921,13 +921,18 @@ static void pm8001_pci_remove(struct pci_dev *pdev)
                synchronize_irq(pm8001_ha->msix_entries[i].vector);
        for (i = 0; i < pm8001_ha->number_of_intr; i++)
                free_irq(pm8001_ha->msix_entries[i].vector,
-                               &pm8001_ha->outq[i]);
+                               &(pm8001_ha->irq_vector[i]));
        pci_disable_msix(pdev);
 #else
        free_irq(pm8001_ha->irq, sha);
 #endif
 #ifdef PM8001_USE_TASKLET
-       tasklet_kill(&pm8001_ha->tasklet);
+       /* For non-msix and msix interrupts */
+       if ((!pdev->msix_cap) || (pm8001_ha->chip_id == chip_8001))
+               tasklet_kill(&pm8001_ha->tasklet[0]);
+       else
+               for (j = 0; j < PM8001_MAX_MSIX_VEC; j++)
+                       tasklet_kill(&pm8001_ha->tasklet[j]);
 #endif
        pm8001_free(pm8001_ha);
        kfree(sha->sas_phy);
@@ -948,7 +953,7 @@ static int pm8001_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 {
        struct sas_ha_struct *sha = pci_get_drvdata(pdev);
        struct pm8001_hba_info *pm8001_ha;
-       int i;
+       int  i, j;
        u32 device_state;
        pm8001_ha = sha->lldd_ha;
        flush_workqueue(pm8001_wq);
@@ -964,13 +969,18 @@ static int pm8001_pci_suspend(struct pci_dev *pdev, pm_message_t state)
                synchronize_irq(pm8001_ha->msix_entries[i].vector);
        for (i = 0; i < pm8001_ha->number_of_intr; i++)
                free_irq(pm8001_ha->msix_entries[i].vector,
-                               &pm8001_ha->outq[i]);
+                               &(pm8001_ha->irq_vector[i]));
        pci_disable_msix(pdev);
 #else
        free_irq(pm8001_ha->irq, sha);
 #endif
 #ifdef PM8001_USE_TASKLET
-       tasklet_kill(&pm8001_ha->tasklet);
+       /* For non-msix and msix interrupts */
+       if ((!pdev->msix_cap) || (pm8001_ha->chip_id == chip_8001))
+               tasklet_kill(&pm8001_ha->tasklet[0]);
+       else
+               for (j = 0; j < PM8001_MAX_MSIX_VEC; j++)
+                       tasklet_kill(&pm8001_ha->tasklet[j]);
 #endif
        device_state = pci_choose_state(pdev, state);
        pm8001_printk("pdev=0x%p, slot=%s, entering "
@@ -993,7 +1003,7 @@ static int pm8001_pci_resume(struct pci_dev *pdev)
        struct sas_ha_struct *sha = pci_get_drvdata(pdev);
        struct pm8001_hba_info *pm8001_ha;
        int rc;
-       u8 i = 0;
+       u8 i = 0, j;
        u32 device_state;
        pm8001_ha = sha->lldd_ha;
        device_state = pdev->current_state;
@@ -1033,10 +1043,14 @@ static int pm8001_pci_resume(struct pci_dev *pdev)
        if (rc)
                goto err_out_disable;
 #ifdef PM8001_USE_TASKLET
-       /* default tasklet for non msi-x interrupt handler/first msi-x
-       * interrupt handler */
-       tasklet_init(&pm8001_ha->tasklet, pm8001_tasklet,
-                       (unsigned long)pm8001_ha);
+       /*  Tasklet for non msi-x interrupt handler */
+       if ((!pdev->msix_cap) || (pm8001_ha->chip_id == chip_8001))
+               tasklet_init(&pm8001_ha->tasklet[0], pm8001_tasklet,
+                       (unsigned long)&(pm8001_ha->irq_vector[0]));
+       else
+               for (j = 0; j < PM8001_MAX_MSIX_VEC; j++)
+                       tasklet_init(&pm8001_ha->tasklet[j], pm8001_tasklet,
+                               (unsigned long)&(pm8001_ha->irq_vector[j]));
 #endif
        PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, 0);
        if (pm8001_ha->chip_id != chip_8001) {
@@ -1169,6 +1183,7 @@ module_exit(pm8001_exit);
 MODULE_AUTHOR("Jack Wang <jack_wang@usish.com>");
 MODULE_AUTHOR("Anand Kumar Santhanam <AnandKumar.Santhanam@pmcs.com>");
 MODULE_AUTHOR("Sangeetha Gnanasekaran <Sangeetha.Gnanasekaran@pmcs.com>");
+MODULE_AUTHOR("Nikith Ganigarakoppal <Nikith.Ganigarakoppal@pmcs.com>");
 MODULE_DESCRIPTION(
                "PMC-Sierra PM8001/8081/8088/8089/8074/8076/8077 "
                "SAS/SATA controller driver");
index f4eb18e5163152b414fc8b0a08b4a07a7f844111..f50ac44b950e5f0fbd12772689a03c5aaebfea87 100644 (file)
@@ -1098,15 +1098,17 @@ int pm8001_lu_reset(struct domain_device *dev, u8 *lun)
        struct pm8001_tmf_task tmf_task;
        struct pm8001_device *pm8001_dev = dev->lldd_dev;
        struct pm8001_hba_info *pm8001_ha = pm8001_find_ha_by_dev(dev);
+       DECLARE_COMPLETION_ONSTACK(completion_setstate);
        if (dev_is_sata(dev)) {
                struct sas_phy *phy = sas_get_local_phy(dev);
                rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev ,
                        dev, 1, 0);
                rc = sas_phy_reset(phy, 1);
                sas_put_local_phy(phy);
+               pm8001_dev->setds_completion = &completion_setstate;
                rc = PM8001_CHIP_DISP->set_dev_state_req(pm8001_ha,
                        pm8001_dev, 0x01);
-               msleep(2000);
+               wait_for_completion(&completion_setstate);
        } else {
                tmf_task.tmf = TMF_LU_RESET;
                rc = pm8001_issue_ssp_tmf(dev, lun, &tmf_task);
index 6037d477a183241c0010d73a00580c3667f3aaa9..6c5fd5ee22d30cf5f1ef0b38cbcc8666f46b0d79 100644 (file)
@@ -466,6 +466,10 @@ struct pm8001_hba_memspace {
        u64                     membase;
        u32                     memsize;
 };
+struct isr_param {
+       struct pm8001_hba_info *drv_inst;
+       u32 irq_id;
+};
 struct pm8001_hba_info {
        char                    name[PM8001_NAME_LENGTH];
        struct list_head        list;
@@ -519,14 +523,13 @@ struct pm8001_hba_info {
        int                     number_of_intr;/*will be used in remove()*/
 #endif
 #ifdef PM8001_USE_TASKLET
-       struct tasklet_struct   tasklet;
+       struct tasklet_struct   tasklet[PM8001_MAX_MSIX_VEC];
 #endif
        u32                     logging_level;
        u32                     fw_status;
        u32                     smp_exp_mode;
-       u32                     int_vector;
        const struct firmware   *fw_image;
-       u8                      outq[PM8001_MAX_MSIX_VEC];
+       struct isr_param irq_vector[PM8001_MAX_MSIX_VEC];
 };
 
 struct pm8001_work {
index 8987b1706216436ef36392eb329e56320547ab23..c950dc5c99432967891c093d7bddb0bb24186e7e 100644 (file)
@@ -2894,6 +2894,7 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
        unsigned long flags;
        u8 deviceType = pPayload->sas_identify.dev_type;
        port->port_state = portstate;
+       phy->phy_state = PHY_STATE_LINK_UP_SPCV;
        PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
                "portid:%d; phyid:%d; linkrate:%d; "
                "portstate:%x; devicetype:%x\n",
@@ -2978,6 +2979,7 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb)
                                port_id, phy_id, link_rate, portstate));
 
        port->port_state = portstate;
+       phy->phy_state = PHY_STATE_LINK_UP_SPCV;
        port->port_attached = 1;
        pm8001_get_lrate_mode(phy, link_rate);
        phy->phy_type |= PORT_TYPE_SATA;
index c86816bea4243354d8864a5422778996ebec215e..9970a385795d16c5328ca6c7711ebf146e02c63c 100644 (file)
 #define SAS_DOPNRJT_RTRY_TMO            128
 #define SAS_COPNRJT_RTRY_TMO            128
 
+/* for phy state */
+#define PHY_STATE_LINK_UP_SPCV         0x2
 /*
   Making ORR bigger than IT NEXUS LOSS which is 2000000us = 2 second.
   Assuming a bigger value 3 second, 3000000/128 = 23437.5 where 128
index bd6f743d87a78af19c698d38d70291723fd28dfb..be8ce54f99b247bcba427a16c2f4873b987329c8 100644 (file)
@@ -1404,11 +1404,22 @@ enum {
 };
 #define PMCRAID_AEN_CMD_MAX (__PMCRAID_AEN_CMD_MAX - 1)
 
+static struct genl_multicast_group pmcraid_mcgrps[] = {
+       { .name = "events", /* not really used - see ID discussion below */ },
+};
+
 static struct genl_family pmcraid_event_family = {
-       .id = GENL_ID_GENERATE,
+       /*
+        * Due to prior multicast group abuse (the code having assumed that
+        * the family ID can be used as a multicast group ID) we need to
+        * statically allocate a family (and thus group) ID.
+        */
+       .id = GENL_ID_PMCRAID,
        .name = "pmcraid",
        .version = 1,
-       .maxattr = PMCRAID_AEN_ATTR_MAX
+       .maxattr = PMCRAID_AEN_ATTR_MAX,
+       .mcgrps = pmcraid_mcgrps,
+       .n_mcgrps = ARRAY_SIZE(pmcraid_mcgrps),
 };
 
 /**
@@ -1511,9 +1522,8 @@ static int pmcraid_notify_aen(
                return result;
        }
 
-       result =
-               genlmsg_multicast(&pmcraid_event_family, skb, 0,
-                                 pmcraid_event_family.id, GFP_ATOMIC);
+       result = genlmsg_multicast(&pmcraid_event_family, skb,
+                                  0, 0, GFP_ATOMIC);
 
        /* If there are no listeners, genlmsg_multicast may return non-zero
         * value.
@@ -4315,6 +4325,7 @@ static struct scsi_host_template pmcraid_host_template = {
        .this_id = -1,
        .sg_tablesize = PMCRAID_MAX_IOADLS,
        .max_sectors = PMCRAID_IOA_MAX_SECTORS,
+       .no_write_same = 1,
        .cmd_per_lun = PMCRAID_MAX_CMD_PER_LUN,
        .use_clustering = ENABLE_CLUSTERING,
        .shost_attrs = pmcraid_host_attrs,
index e6c4bff04339cb1975637a92bb3842601e1e158f..5c8a3b696a1dbf3ab18f914225e36f7c4d0a3a31 100644 (file)
@@ -801,7 +801,7 @@ static int sd_setup_write_same_cmnd(struct scsi_device *sdp, struct request *rq)
        if (sdkp->device->no_write_same)
                return BLKPREP_KILL;
 
-       BUG_ON(bio_offset(bio) || bio_iovec(bio)->bv_len != sdp->sector_size);
+       BUG_ON(bio_offset(bio) || bio_iovec(bio).bv_len != sdp->sector_size);
 
        sector >>= ilog2(sdp->sector_size) - 9;
        nr_sectors >>= ilog2(sdp->sector_size) - 9;
@@ -2659,6 +2659,12 @@ static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer)
 {
        struct scsi_device *sdev = sdkp->device;
 
+       if (sdev->host->no_write_same) {
+               sdev->no_write_same = 1;
+
+               return;
+       }
+
        if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, INQUIRY) < 0) {
                /* too large values might cause issues with arcmsr */
                int vpd_buf_len = 64;
index 6174ca4ea27594487d7dc0828d9e21841742b8ed..a7a691d0af7d105a431ba3b560a5496acb71d58b 100644 (file)
@@ -365,7 +365,6 @@ void sd_dif_prepare(struct request *rq, sector_t hw_sector,
        struct bio *bio;
        struct scsi_disk *sdkp;
        struct sd_dif_tuple *sdt;
-       unsigned int i, j;
        u32 phys, virt;
 
        sdkp = rq->bio->bi_bdev->bd_disk->private_data;
@@ -376,19 +375,21 @@ void sd_dif_prepare(struct request *rq, sector_t hw_sector,
        phys = hw_sector & 0xffffffff;
 
        __rq_for_each_bio(bio, rq) {
-               struct bio_vec *iv;
+               struct bio_vec iv;
+               struct bvec_iter iter;
+               unsigned int j;
 
                /* Already remapped? */
                if (bio_flagged(bio, BIO_MAPPED_INTEGRITY))
                        break;
 
-               virt = bio->bi_integrity->bip_sector & 0xffffffff;
+               virt = bio->bi_integrity->bip_iter.bi_sector & 0xffffffff;
 
-               bip_for_each_vec(iv, bio->bi_integrity, i) {
-                       sdt = kmap_atomic(iv->bv_page)
-                               + iv->bv_offset;
+               bip_for_each_vec(iv, bio->bi_integrity, iter) {
+                       sdt = kmap_atomic(iv.bv_page)
+                               + iv.bv_offset;
 
-                       for (j = 0 ; j < iv->bv_len ; j += tuple_sz, sdt++) {
+                       for (j = 0; j < iv.bv_len; j += tuple_sz, sdt++) {
 
                                if (be32_to_cpu(sdt->ref_tag) == virt)
                                        sdt->ref_tag = cpu_to_be32(phys);
@@ -414,7 +415,7 @@ void sd_dif_complete(struct scsi_cmnd *scmd, unsigned int good_bytes)
        struct scsi_disk *sdkp;
        struct bio *bio;
        struct sd_dif_tuple *sdt;
-       unsigned int i, j, sectors, sector_sz;
+       unsigned int j, sectors, sector_sz;
        u32 phys, virt;
 
        sdkp = scsi_disk(scmd->request->rq_disk);
@@ -430,15 +431,16 @@ void sd_dif_complete(struct scsi_cmnd *scmd, unsigned int good_bytes)
                phys >>= 3;
 
        __rq_for_each_bio(bio, scmd->request) {
-               struct bio_vec *iv;
+               struct bio_vec iv;
+               struct bvec_iter iter;
 
-               virt = bio->bi_integrity->bip_sector & 0xffffffff;
+               virt = bio->bi_integrity->bip_iter.bi_sector & 0xffffffff;
 
-               bip_for_each_vec(iv, bio->bi_integrity, i) {
-                       sdt = kmap_atomic(iv->bv_page)
-                               + iv->bv_offset;
+               bip_for_each_vec(iv, bio->bi_integrity, iter) {
+                       sdt = kmap_atomic(iv.bv_page)
+                               + iv.bv_offset;
 
-                       for (j = 0 ; j < iv->bv_len ; j += tuple_sz, sdt++) {
+                       for (j = 0; j < iv.bv_len; j += tuple_sz, sdt++) {
 
                                if (sectors == 0) {
                                        kunmap_atomic(sdt);
index 1a28f5632797ed2da2f27c0752013e3c7e4dde5d..17d7404272400dd1a76989a3965e0c4b85343036 100644 (file)
@@ -1697,6 +1697,7 @@ static struct scsi_host_template scsi_driver = {
        .use_clustering =       DISABLE_CLUSTERING,
        /* Make sure we dont get a sg segment crosses a page boundary */
        .dma_boundary =         PAGE_SIZE-1,
+       .no_write_same =        1,
 };
 
 enum {
index cbf3476c68cd3511e13592296198da53ddcc441d..aff31991aea9808f5f98180cb126be87be12db26 100644 (file)
@@ -104,7 +104,7 @@ static int zorro7xx_init_one(struct zorro_dev *z,
        if (ioaddr > 0x01000000)
                hostdata->base = ioremap(ioaddr, zorro_resource_len(z));
        else
-               hostdata->base = (void __iomem *)ZTWO_VADDR(ioaddr);
+               hostdata->base = ZTWO_VADDR(ioaddr);
 
        hostdata->clock = 50;
        hostdata->chip710 = 1;
index f5b4ca581541539f8336aaec73c286de1f0773fb..5e753d799f617d7e2feb997d3ce27658dd6d5dc0 100644 (file)
@@ -60,7 +60,7 @@
 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
 #include <linux/kernel.h>
-#include <acpi/acpi.h>
+#include <acpi/acpi.h> /* FIXME: inclusion should be removed */
 
 #include <linux/sfi.h>
 #include "sfi_core.h"
index eb1f1ef5fa2eb69db729b6061b2d96c85aaf968b..43947df798d35d1417d8c90a671896474ca2da96 100644 (file)
@@ -118,6 +118,13 @@ config SPI_BCM63XX
        help
           Enable support for the SPI controller on the Broadcom BCM63xx SoCs.
 
+config SPI_BCM63XX_HSSPI
+       tristate "Broadcom BCM63XX HS SPI controller driver"
+       depends on BCM63XX || COMPILE_TEST
+       help
+         This enables support for the High Speed SPI controller present on
+         newer Broadcom BCM63XX SoCs.
+
 config SPI_BITBANG
        tristate "Utilities for Bitbanging SPI masters"
        help
@@ -301,6 +308,7 @@ config SPI_OMAP_UWIRE
 
 config SPI_OMAP24XX
        tristate "McSPI driver for OMAP"
+       depends on ARM || ARM64 || AVR32 || HEXAGON || MIPS || SH
        depends on ARCH_OMAP2PLUS || COMPILE_TEST
        help
          SPI master controller for OMAP24XX and later Multichannel SPI
@@ -395,7 +403,7 @@ config SPI_S3C24XX_FIQ
 config SPI_S3C64XX
        tristate "Samsung S3C64XX series type SPI"
        depends on PLAT_SAMSUNG
-       select S3C64XX_DMA if ARCH_S3C64XX
+       select S3C64XX_PL080 if ARCH_S3C64XX
        help
          SPI driver for Samsung S3C64XX and newer SoCs.
 
@@ -407,7 +415,8 @@ config SPI_SC18IS602
 
 config SPI_SH_MSIOF
        tristate "SuperH MSIOF SPI controller"
-       depends on (SUPERH || ARCH_SHMOBILE) && HAVE_CLK
+       depends on HAVE_CLK
+       depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST
        select SPI_BITBANG
        help
          SPI driver for SuperH and SH Mobile MSIOF blocks.
index ab8d8644af0e9e97e66d082c472f2a83793dfbd7..95af48d2d360d694e25012c80fa0cf127222db16 100644 (file)
@@ -16,6 +16,7 @@ obj-$(CONFIG_SPI_ATH79)                       += spi-ath79.o
 obj-$(CONFIG_SPI_AU1550)               += spi-au1550.o
 obj-$(CONFIG_SPI_BCM2835)              += spi-bcm2835.o
 obj-$(CONFIG_SPI_BCM63XX)              += spi-bcm63xx.o
+obj-$(CONFIG_SPI_BCM63XX_HSSPI)                += spi-bcm63xx-hsspi.o
 obj-$(CONFIG_SPI_BFIN5XX)              += spi-bfin5xx.o
 obj-$(CONFIG_SPI_BFIN_V3)               += spi-bfin-v3.o
 obj-$(CONFIG_SPI_BFIN_SPORT)           += spi-bfin-sport.o
index 273db0beb2b88ffeb588307ce08b2cb40120c790..57fa738762239d9065a8a1b658af94adb2ab3ee0 100644 (file)
@@ -1510,7 +1510,7 @@ static int atmel_spi_probe(struct platform_device *pdev)
        if (irq < 0)
                return irq;
 
-       clk = clk_get(&pdev->dev, "spi_clk");
+       clk = devm_clk_get(&pdev->dev, "spi_clk");
        if (IS_ERR(clk))
                return PTR_ERR(clk);
 
@@ -1570,14 +1570,14 @@ static int atmel_spi_probe(struct platform_device *pdev)
                dev_info(&pdev->dev, "Atmel SPI Controller using PIO only\n");
 
        if (as->use_pdc) {
-               ret = request_irq(irq, atmel_spi_pdc_interrupt, 0,
-                                       dev_name(&pdev->dev), master);
+               ret = devm_request_irq(&pdev->dev, irq, atmel_spi_pdc_interrupt,
+                                       0, dev_name(&pdev->dev), master);
        } else {
                tasklet_init(&as->tasklet, atmel_spi_tasklet_func,
                                        (unsigned long)master);
 
-               ret = request_irq(irq, atmel_spi_pio_interrupt, 0,
-                                       dev_name(&pdev->dev), master);
+               ret = devm_request_irq(&pdev->dev, irq, atmel_spi_pio_interrupt,
+                                       0, dev_name(&pdev->dev), master);
        }
        if (ret)
                goto out_unmap_regs;
@@ -1603,7 +1603,7 @@ static int atmel_spi_probe(struct platform_device *pdev)
        dev_info(&pdev->dev, "Atmel SPI Controller at 0x%08lx (irq %d)\n",
                        (unsigned long)regs->start, irq);
 
-       ret = spi_register_master(master);
+       ret = devm_spi_register_master(&pdev->dev, master);
        if (ret)
                goto out_free_dma;
 
@@ -1617,7 +1617,6 @@ out_free_dma:
        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:
 out_free_buffer:
        if (!as->use_pdc)
@@ -1625,7 +1624,6 @@ out_free_buffer:
        dma_free_coherent(&pdev->dev, BUFFER_SIZE, as->buffer,
                        as->buffer_dma);
 out_free:
-       clk_put(clk);
        spi_master_put(master);
        return ret;
 }
@@ -1668,10 +1666,6 @@ static int atmel_spi_remove(struct platform_device *pdev)
                        as->buffer_dma);
 
        clk_disable_unprepare(as->clk);
-       clk_put(as->clk);
-       free_irq(as->irq, master);
-
-       spi_unregister_master(master);
 
        return 0;
 }
index 3ed666fe840a0cdbaf1a2a2c6cd75670dd25fb48..9025edd7dc45fde131c7c9c6004ce5434829c785 100644 (file)
@@ -377,7 +377,7 @@ out_master_put:
 
 static int bcm2835_spi_remove(struct platform_device *pdev)
 {
-       struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
+       struct spi_master *master = platform_get_drvdata(pdev);
        struct bcm2835_spi *bs = spi_master_get_devdata(master);
 
        free_irq(bs->irq, master);
diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c
new file mode 100644 (file)
index 0000000..2cfe8eb
--- /dev/null
@@ -0,0 +1,484 @@
+/*
+ * Broadcom BCM63XX High Speed SPI Controller driver
+ *
+ * Copyright 2000-2010 Broadcom Corporation
+ * Copyright 2012-2013 Jonas Gorski <jogo@openwrt.org>
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/spi/spi.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+
+#define HSSPI_GLOBAL_CTRL_REG                  0x0
+#define GLOBAL_CTRL_CS_POLARITY_SHIFT          0
+#define GLOBAL_CTRL_CS_POLARITY_MASK           0x000000ff
+#define GLOBAL_CTRL_PLL_CLK_CTRL_SHIFT         8
+#define GLOBAL_CTRL_PLL_CLK_CTRL_MASK          0x0000ff00
+#define GLOBAL_CTRL_CLK_GATE_SSOFF             BIT(16)
+#define GLOBAL_CTRL_CLK_POLARITY               BIT(17)
+#define GLOBAL_CTRL_MOSI_IDLE                  BIT(18)
+
+#define HSSPI_GLOBAL_EXT_TRIGGER_REG           0x4
+
+#define HSSPI_INT_STATUS_REG                   0x8
+#define HSSPI_INT_STATUS_MASKED_REG            0xc
+#define HSSPI_INT_MASK_REG                     0x10
+
+#define HSSPI_PINGx_CMD_DONE(i)                        BIT((i * 8) + 0)
+#define HSSPI_PINGx_RX_OVER(i)                 BIT((i * 8) + 1)
+#define HSSPI_PINGx_TX_UNDER(i)                        BIT((i * 8) + 2)
+#define HSSPI_PINGx_POLL_TIMEOUT(i)            BIT((i * 8) + 3)
+#define HSSPI_PINGx_CTRL_INVAL(i)              BIT((i * 8) + 4)
+
+#define HSSPI_INT_CLEAR_ALL                    0xff001f1f
+
+#define HSSPI_PINGPONG_COMMAND_REG(x)          (0x80 + (x) * 0x40)
+#define PINGPONG_CMD_COMMAND_MASK              0xf
+#define PINGPONG_COMMAND_NOOP                  0
+#define PINGPONG_COMMAND_START_NOW             1
+#define PINGPONG_COMMAND_START_TRIGGER         2
+#define PINGPONG_COMMAND_HALT                  3
+#define PINGPONG_COMMAND_FLUSH                 4
+#define PINGPONG_CMD_PROFILE_SHIFT             8
+#define PINGPONG_CMD_SS_SHIFT                  12
+
+#define HSSPI_PINGPONG_STATUS_REG(x)           (0x84 + (x) * 0x40)
+
+#define HSSPI_PROFILE_CLK_CTRL_REG(x)          (0x100 + (x) * 0x20)
+#define CLK_CTRL_FREQ_CTRL_MASK                        0x0000ffff
+#define CLK_CTRL_SPI_CLK_2X_SEL                        BIT(14)
+#define CLK_CTRL_ACCUM_RST_ON_LOOP             BIT(15)
+
+#define HSSPI_PROFILE_SIGNAL_CTRL_REG(x)       (0x104 + (x) * 0x20)
+#define SIGNAL_CTRL_LATCH_RISING               BIT(12)
+#define SIGNAL_CTRL_LAUNCH_RISING              BIT(13)
+#define SIGNAL_CTRL_ASYNC_INPUT_PATH           BIT(16)
+
+#define HSSPI_PROFILE_MODE_CTRL_REG(x)         (0x108 + (x) * 0x20)
+#define MODE_CTRL_MULTIDATA_RD_STRT_SHIFT      8
+#define MODE_CTRL_MULTIDATA_WR_STRT_SHIFT      12
+#define MODE_CTRL_MULTIDATA_RD_SIZE_SHIFT      16
+#define MODE_CTRL_MULTIDATA_WR_SIZE_SHIFT      18
+#define MODE_CTRL_MODE_3WIRE                   BIT(20)
+#define MODE_CTRL_PREPENDBYTE_CNT_SHIFT                24
+
+#define HSSPI_FIFO_REG(x)                      (0x200 + (x) * 0x200)
+
+
+#define HSSPI_OP_CODE_SHIFT                    13
+#define HSSPI_OP_SLEEP                         (0 << HSSPI_OP_CODE_SHIFT)
+#define HSSPI_OP_READ_WRITE                    (1 << HSSPI_OP_CODE_SHIFT)
+#define HSSPI_OP_WRITE                         (2 << HSSPI_OP_CODE_SHIFT)
+#define HSSPI_OP_READ                          (3 << HSSPI_OP_CODE_SHIFT)
+#define HSSPI_OP_SETIRQ                                (4 << HSSPI_OP_CODE_SHIFT)
+
+#define HSSPI_BUFFER_LEN                       512
+#define HSSPI_OPCODE_LEN                       2
+
+#define HSSPI_MAX_PREPEND_LEN                  15
+
+#define HSSPI_MAX_SYNC_CLOCK                   30000000
+
+#define HSSPI_BUS_NUM                          1 /* 0 is legacy SPI */
+
+struct bcm63xx_hsspi {
+       struct completion done;
+       struct mutex bus_mutex;
+
+       struct platform_device *pdev;
+       struct clk *clk;
+       void __iomem *regs;
+       u8 __iomem *fifo;
+
+       u32 speed_hz;
+       u8 cs_polarity;
+};
+
+static void bcm63xx_hsspi_set_cs(struct bcm63xx_hsspi *bs, unsigned cs,
+                                bool active)
+{
+       u32 reg;
+
+       mutex_lock(&bs->bus_mutex);
+       reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG);
+
+       reg &= ~BIT(cs);
+       if (active == !(bs->cs_polarity & BIT(cs)))
+               reg |= BIT(cs);
+
+       __raw_writel(reg, bs->regs + HSSPI_GLOBAL_CTRL_REG);
+       mutex_unlock(&bs->bus_mutex);
+}
+
+static void bcm63xx_hsspi_set_clk(struct bcm63xx_hsspi *bs,
+                                 struct spi_device *spi, int hz)
+{
+       unsigned profile = spi->chip_select;
+       u32 reg;
+
+       reg = DIV_ROUND_UP(2048, DIV_ROUND_UP(bs->speed_hz, hz));
+       __raw_writel(CLK_CTRL_ACCUM_RST_ON_LOOP | reg,
+                    bs->regs + HSSPI_PROFILE_CLK_CTRL_REG(profile));
+
+       reg = __raw_readl(bs->regs + HSSPI_PROFILE_SIGNAL_CTRL_REG(profile));
+       if (hz > HSSPI_MAX_SYNC_CLOCK)
+               reg |= SIGNAL_CTRL_ASYNC_INPUT_PATH;
+       else
+               reg &= ~SIGNAL_CTRL_ASYNC_INPUT_PATH;
+       __raw_writel(reg, bs->regs + HSSPI_PROFILE_SIGNAL_CTRL_REG(profile));
+
+       mutex_lock(&bs->bus_mutex);
+       /* setup clock polarity */
+       reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG);
+       reg &= ~GLOBAL_CTRL_CLK_POLARITY;
+       if (spi->mode & SPI_CPOL)
+               reg |= GLOBAL_CTRL_CLK_POLARITY;
+       __raw_writel(reg, bs->regs + HSSPI_GLOBAL_CTRL_REG);
+       mutex_unlock(&bs->bus_mutex);
+}
+
+static int bcm63xx_hsspi_do_txrx(struct spi_device *spi, struct spi_transfer *t)
+{
+       struct bcm63xx_hsspi *bs = spi_master_get_devdata(spi->master);
+       unsigned chip_select = spi->chip_select;
+       u16 opcode = 0;
+       int pending = t->len;
+       int step_size = HSSPI_BUFFER_LEN;
+       const u8 *tx = t->tx_buf;
+       u8 *rx = t->rx_buf;
+
+       bcm63xx_hsspi_set_clk(bs, spi, t->speed_hz);
+       bcm63xx_hsspi_set_cs(bs, spi->chip_select, true);
+
+       if (tx && rx)
+               opcode = HSSPI_OP_READ_WRITE;
+       else if (tx)
+               opcode = HSSPI_OP_WRITE;
+       else if (rx)
+               opcode = HSSPI_OP_READ;
+
+       if (opcode != HSSPI_OP_READ)
+               step_size -= HSSPI_OPCODE_LEN;
+
+       __raw_writel(0 << MODE_CTRL_PREPENDBYTE_CNT_SHIFT |
+                    2 << MODE_CTRL_MULTIDATA_WR_STRT_SHIFT |
+                    2 << MODE_CTRL_MULTIDATA_RD_STRT_SHIFT | 0xff,
+                    bs->regs + HSSPI_PROFILE_MODE_CTRL_REG(chip_select));
+
+       while (pending > 0) {
+               int curr_step = min_t(int, step_size, pending);
+
+               init_completion(&bs->done);
+               if (tx) {
+                       memcpy_toio(bs->fifo + HSSPI_OPCODE_LEN, tx, curr_step);
+                       tx += curr_step;
+               }
+
+               __raw_writew(opcode | curr_step, bs->fifo);
+
+               /* enable interrupt */
+               __raw_writel(HSSPI_PINGx_CMD_DONE(0),
+                            bs->regs + HSSPI_INT_MASK_REG);
+
+               /* start the transfer */
+               __raw_writel(!chip_select << PINGPONG_CMD_SS_SHIFT |
+                            chip_select << PINGPONG_CMD_PROFILE_SHIFT |
+                            PINGPONG_COMMAND_START_NOW,
+                            bs->regs + HSSPI_PINGPONG_COMMAND_REG(0));
+
+               if (wait_for_completion_timeout(&bs->done, HZ) == 0) {
+                       dev_err(&bs->pdev->dev, "transfer timed out!\n");
+                       return -ETIMEDOUT;
+               }
+
+               if (rx) {
+                       memcpy_fromio(rx, bs->fifo, curr_step);
+                       rx += curr_step;
+               }
+
+               pending -= curr_step;
+       }
+
+       return 0;
+}
+
+static int bcm63xx_hsspi_setup(struct spi_device *spi)
+{
+       struct bcm63xx_hsspi *bs = spi_master_get_devdata(spi->master);
+       u32 reg;
+
+       reg = __raw_readl(bs->regs +
+                         HSSPI_PROFILE_SIGNAL_CTRL_REG(spi->chip_select));
+       reg &= ~(SIGNAL_CTRL_LAUNCH_RISING | SIGNAL_CTRL_LATCH_RISING);
+       if (spi->mode & SPI_CPHA)
+               reg |= SIGNAL_CTRL_LAUNCH_RISING;
+       else
+               reg |= SIGNAL_CTRL_LATCH_RISING;
+       __raw_writel(reg, bs->regs +
+                    HSSPI_PROFILE_SIGNAL_CTRL_REG(spi->chip_select));
+
+       mutex_lock(&bs->bus_mutex);
+       reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG);
+
+       /* only change actual polarities if there is no transfer */
+       if ((reg & GLOBAL_CTRL_CS_POLARITY_MASK) == bs->cs_polarity) {
+               if (spi->mode & SPI_CS_HIGH)
+                       reg |= BIT(spi->chip_select);
+               else
+                       reg &= ~BIT(spi->chip_select);
+               __raw_writel(reg, bs->regs + HSSPI_GLOBAL_CTRL_REG);
+       }
+
+       if (spi->mode & SPI_CS_HIGH)
+               bs->cs_polarity |= BIT(spi->chip_select);
+       else
+               bs->cs_polarity &= ~BIT(spi->chip_select);
+
+       mutex_unlock(&bs->bus_mutex);
+
+       return 0;
+}
+
+static int bcm63xx_hsspi_transfer_one(struct spi_master *master,
+                                     struct spi_message *msg)
+{
+       struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
+       struct spi_transfer *t;
+       struct spi_device *spi = msg->spi;
+       int status = -EINVAL;
+       int dummy_cs;
+       u32 reg;
+
+       /* This controller does not support keeping CS active during idle.
+        * To work around this, we use the following ugly hack:
+        *
+        * a. Invert the target chip select's polarity so it will be active.
+        * b. Select a "dummy" chip select to use as the hardware target.
+        * c. Invert the dummy chip select's polarity so it will be inactive
+        *    during the actual transfers.
+        * d. Tell the hardware to send to the dummy chip select. Thanks to
+        *    the multiplexed nature of SPI the actual target will receive
+        *    the transfer and we see its response.
+        *
+        * e. At the end restore the polarities again to their default values.
+        */
+
+       dummy_cs = !spi->chip_select;
+       bcm63xx_hsspi_set_cs(bs, dummy_cs, true);
+
+       list_for_each_entry(t, &msg->transfers, transfer_list) {
+               status = bcm63xx_hsspi_do_txrx(spi, t);
+               if (status)
+                       break;
+
+               msg->actual_length += t->len;
+
+               if (t->delay_usecs)
+                       udelay(t->delay_usecs);
+
+               if (t->cs_change)
+                       bcm63xx_hsspi_set_cs(bs, spi->chip_select, false);
+       }
+
+       mutex_lock(&bs->bus_mutex);
+       reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG);
+       reg &= ~GLOBAL_CTRL_CS_POLARITY_MASK;
+       reg |= bs->cs_polarity;
+       __raw_writel(reg, bs->regs + HSSPI_GLOBAL_CTRL_REG);
+       mutex_unlock(&bs->bus_mutex);
+
+       msg->status = status;
+       spi_finalize_current_message(master);
+
+       return 0;
+}
+
+static irqreturn_t bcm63xx_hsspi_interrupt(int irq, void *dev_id)
+{
+       struct bcm63xx_hsspi *bs = (struct bcm63xx_hsspi *)dev_id;
+
+       if (__raw_readl(bs->regs + HSSPI_INT_STATUS_MASKED_REG) == 0)
+               return IRQ_NONE;
+
+       __raw_writel(HSSPI_INT_CLEAR_ALL, bs->regs + HSSPI_INT_STATUS_REG);
+       __raw_writel(0, bs->regs + HSSPI_INT_MASK_REG);
+
+       complete(&bs->done);
+
+       return IRQ_HANDLED;
+}
+
+static int bcm63xx_hsspi_probe(struct platform_device *pdev)
+{
+       struct spi_master *master;
+       struct bcm63xx_hsspi *bs;
+       struct resource *res_mem;
+       void __iomem *regs;
+       struct device *dev = &pdev->dev;
+       struct clk *clk;
+       int irq, ret;
+       u32 reg, rate;
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_err(dev, "no irq\n");
+               return -ENXIO;
+       }
+
+       res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       regs = devm_ioremap_resource(dev, res_mem);
+       if (IS_ERR(regs))
+               return PTR_ERR(regs);
+
+       clk = clk_get(dev, "hsspi");
+
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
+
+       rate = clk_get_rate(clk);
+       if (!rate) {
+               ret = -EINVAL;
+               goto out_put_clk;
+       }
+
+       clk_prepare_enable(clk);
+
+       master = spi_alloc_master(&pdev->dev, sizeof(*bs));
+       if (!master) {
+               ret = -ENOMEM;
+               goto out_disable_clk;
+       }
+
+       bs = spi_master_get_devdata(master);
+       bs->pdev = pdev;
+       bs->clk = clk;
+       bs->regs = regs;
+       bs->speed_hz = rate;
+       bs->fifo = (u8 __iomem *)(bs->regs + HSSPI_FIFO_REG(0));
+
+       mutex_init(&bs->bus_mutex);
+
+       master->bus_num = HSSPI_BUS_NUM;
+       master->num_chipselect = 8;
+       master->setup = bcm63xx_hsspi_setup;
+       master->transfer_one_message = bcm63xx_hsspi_transfer_one;
+       master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+       master->bits_per_word_mask = SPI_BPW_MASK(8);
+       master->auto_runtime_pm = true;
+
+       platform_set_drvdata(pdev, master);
+
+       /* Initialize the hardware */
+       __raw_writel(0, bs->regs + HSSPI_INT_MASK_REG);
+
+       /* clean up any pending interrupts */
+       __raw_writel(HSSPI_INT_CLEAR_ALL, bs->regs + HSSPI_INT_STATUS_REG);
+
+       /* read out default CS polarities */
+       reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG);
+       bs->cs_polarity = reg & GLOBAL_CTRL_CS_POLARITY_MASK;
+       __raw_writel(reg | GLOBAL_CTRL_CLK_GATE_SSOFF,
+                    bs->regs + HSSPI_GLOBAL_CTRL_REG);
+
+       ret = devm_request_irq(dev, irq, bcm63xx_hsspi_interrupt, IRQF_SHARED,
+                              pdev->name, bs);
+
+       if (ret)
+               goto out_put_master;
+
+       /* register and we are done */
+       ret = spi_register_master(master);
+       if (ret)
+               goto out_put_master;
+
+       return 0;
+
+out_put_master:
+       spi_master_put(master);
+out_disable_clk:
+       clk_disable_unprepare(clk);
+out_put_clk:
+       clk_put(clk);
+
+       return ret;
+}
+
+
+static int bcm63xx_hsspi_remove(struct platform_device *pdev)
+{
+       struct spi_master *master = platform_get_drvdata(pdev);
+       struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
+
+       spi_unregister_master(master);
+
+       /* reset the hardware and block queue progress */
+       __raw_writel(0, bs->regs + HSSPI_INT_MASK_REG);
+       clk_disable_unprepare(bs->clk);
+       clk_put(bs->clk);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int bcm63xx_hsspi_suspend(struct device *dev)
+{
+       struct spi_master *master = dev_get_drvdata(dev);
+       struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
+
+       spi_master_suspend(master);
+       clk_disable(bs->clk);
+
+       return 0;
+}
+
+static int bcm63xx_hsspi_resume(struct device *dev)
+{
+       struct spi_master *master = dev_get_drvdata(dev);
+       struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
+
+       clk_enable(bs->clk);
+       spi_master_resume(master);
+
+       return 0;
+}
+
+static const struct dev_pm_ops bcm63xx_hsspi_pm_ops = {
+       .suspend        = bcm63xx_hsspi_suspend,
+       .resume         = bcm63xx_hsspi_resume,
+};
+
+#define BCM63XX_HSSPI_PM_OPS   (&bcm63xx_hsspi_pm_ops)
+#else
+#define BCM63XX_HSSPI_PM_OPS   NULL
+#endif
+
+
+
+static struct platform_driver bcm63xx_hsspi_driver = {
+       .driver = {
+               .name   = "bcm63xx-hsspi",
+               .owner  = THIS_MODULE,
+               .pm     = BCM63XX_HSSPI_PM_OPS,
+       },
+       .probe          = bcm63xx_hsspi_probe,
+       .remove         = bcm63xx_hsspi_remove,
+};
+
+module_platform_driver(bcm63xx_hsspi_driver);
+
+MODULE_ALIAS("platform:bcm63xx_hsspi");
+MODULE_DESCRIPTION("Broadcom BCM63xx High Speed SPI Controller driver");
+MODULE_AUTHOR("Jonas Gorski <jogo@openwrt.org>");
+MODULE_LICENSE("GPL");
index 80d56b214eb51af96ceb9e9d55ffea6bbb2d7302..469ecd8763581c3628c033e00adc47699e033f12 100644 (file)
@@ -435,7 +435,7 @@ out:
 
 static int bcm63xx_spi_remove(struct platform_device *pdev)
 {
-       struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
+       struct spi_master *master = platform_get_drvdata(pdev);
        struct bcm63xx_spi *bs = spi_master_get_devdata(master);
 
        /* reset spi block */
index cc5b75d10c386145dad24ac595c5495e4b7564f0..cabed8f9119e1af30d80766420d548b94567c91c 100644 (file)
@@ -397,44 +397,31 @@ static int mcfqspi_probe(struct platform_device *pdev)
        mcfqspi = spi_master_get_devdata(master);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_dbg(&pdev->dev, "platform_get_resource failed\n");
-               status = -ENXIO;
+       mcfqspi->iobase = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(mcfqspi->iobase)) {
+               status = PTR_ERR(mcfqspi->iobase);
                goto fail0;
        }
 
-       if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
-               dev_dbg(&pdev->dev, "request_mem_region failed\n");
-               status = -EBUSY;
-               goto fail0;
-       }
-
-       mcfqspi->iobase = ioremap(res->start, resource_size(res));
-       if (!mcfqspi->iobase) {
-               dev_dbg(&pdev->dev, "ioremap failed\n");
-               status = -ENOMEM;
-               goto fail1;
-       }
-
        mcfqspi->irq = platform_get_irq(pdev, 0);
        if (mcfqspi->irq < 0) {
                dev_dbg(&pdev->dev, "platform_get_irq failed\n");
                status = -ENXIO;
-               goto fail2;
+               goto fail0;
        }
 
-       status = request_irq(mcfqspi->irq, mcfqspi_irq_handler, 0,
-                            pdev->name, mcfqspi);
+       status = devm_request_irq(&pdev->dev, mcfqspi->irq, mcfqspi_irq_handler,
+                               0, pdev->name, mcfqspi);
        if (status) {
                dev_dbg(&pdev->dev, "request_irq failed\n");
-               goto fail2;
+               goto fail0;
        }
 
-       mcfqspi->clk = clk_get(&pdev->dev, "qspi_clk");
+       mcfqspi->clk = devm_clk_get(&pdev->dev, "qspi_clk");
        if (IS_ERR(mcfqspi->clk)) {
                dev_dbg(&pdev->dev, "clk_get failed\n");
                status = PTR_ERR(mcfqspi->clk);
-               goto fail3;
+               goto fail0;
        }
        clk_enable(mcfqspi->clk);
 
@@ -445,7 +432,7 @@ static int mcfqspi_probe(struct platform_device *pdev)
        status = mcfqspi_cs_setup(mcfqspi);
        if (status) {
                dev_dbg(&pdev->dev, "error initializing cs_control\n");
-               goto fail4;
+               goto fail1;
        }
 
        init_waitqueue_head(&mcfqspi->waitq);
@@ -459,10 +446,10 @@ static int mcfqspi_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, master);
 
-       status = spi_register_master(master);
+       status = devm_spi_register_master(&pdev->dev, master);
        if (status) {
                dev_dbg(&pdev->dev, "spi_register_master failed\n");
-               goto fail5;
+               goto fail2;
        }
        pm_runtime_enable(mcfqspi->dev);
 
@@ -470,17 +457,10 @@ static int mcfqspi_probe(struct platform_device *pdev)
 
        return 0;
 
-fail5:
-       mcfqspi_cs_teardown(mcfqspi);
-fail4:
-       clk_disable(mcfqspi->clk);
-       clk_put(mcfqspi->clk);
-fail3:
-       free_irq(mcfqspi->irq, mcfqspi);
 fail2:
-       iounmap(mcfqspi->iobase);
+       mcfqspi_cs_teardown(mcfqspi);
 fail1:
-       release_mem_region(res->start, resource_size(res));
+       clk_disable(mcfqspi->clk);
 fail0:
        spi_master_put(master);
 
@@ -501,11 +481,6 @@ static int mcfqspi_remove(struct platform_device *pdev)
 
        mcfqspi_cs_teardown(mcfqspi);
        clk_disable(mcfqspi->clk);
-       clk_put(mcfqspi->clk);
-       free_irq(mcfqspi->irq, mcfqspi);
-       iounmap(mcfqspi->iobase);
-       release_mem_region(res->start, resource_size(res));
-       spi_unregister_master(master);
 
        return 0;
 }
index 50b2d88c81901c2b0b0ec1720f7e802ccf4924fb..d3f638613b4093f8413d2848771c0392b4ae9927 100644 (file)
@@ -963,8 +963,8 @@ static int davinci_spi_probe(struct platform_device *pdev)
                        goto free_clk;
 
                dev_info(&pdev->dev, "DMA: supported\n");
-               dev_info(&pdev->dev, "DMA: RX channel: %d, TX channel: %d, "
-                               "event queue: %d\n", dma_rx_chan, dma_tx_chan,
+               dev_info(&pdev->dev, "DMA: RX channel: %pa, TX channel: %pa, "
+                               "event queue: %d\n", &dma_rx_chan, &dma_tx_chan,
                                pdata->dma_event_q);
        }
 
index 66fa9955ea148e5c10c3cfda9b3b90da65902ef0..f7be4be59353f56dd824cebf2e7f9fa38e750023 100644 (file)
@@ -148,7 +148,7 @@ static int spi_resume(struct pci_dev *pdev)
 #define spi_resume     NULL
 #endif
 
-static DEFINE_PCI_DEVICE_TABLE(pci_ids) = {
+static const struct pci_device_id pci_ids[] = {
        /* Intel MID platform SPI controller 0 */
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0800) },
        {},
index c7a74f0ef89285eb2f14926dd979145987509dc6..dd5bd468e9621698c7a130418d5a74994c474cbe 100644 (file)
@@ -433,21 +433,12 @@ static int falcon_sflash_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, priv);
 
-       ret = spi_register_master(master);
+       ret = devm_spi_register_master(&pdev->dev, master);
        if (ret)
                spi_master_put(master);
        return ret;
 }
 
-static int falcon_sflash_remove(struct platform_device *pdev)
-{
-       struct falcon_sflash *priv = platform_get_drvdata(pdev);
-
-       spi_unregister_master(priv->master);
-
-       return 0;
-}
-
 static const struct of_device_id falcon_sflash_match[] = {
        { .compatible = "lantiq,sflash-falcon" },
        {},
@@ -456,7 +447,6 @@ MODULE_DEVICE_TABLE(of, falcon_sflash_match);
 
 static struct platform_driver falcon_sflash_driver = {
        .probe  = falcon_sflash_probe,
-       .remove = falcon_sflash_remove,
        .driver = {
                .name   = DRV_NAME,
                .owner  = THIS_MODULE,
index 80d8f40f7e0553d600f1e36b018daa7fae275a64..8106006cdc39e5da4dae382122e5acbd19d1699b 100644 (file)
@@ -705,7 +705,7 @@ static int of_fsl_espi_probe(struct platform_device *ofdev)
                goto err;
 
        irq = irq_of_parse_and_map(np, 0);
-       if (!ret) {
+       if (!irq) {
                ret = -EINVAL;
                goto err;
        }
index 3fb09f981980aedb23a760dd0b14d604c843661b..7beeb29472ac73f59fcf0e92e04c9c31ef88a75a 100644 (file)
@@ -115,17 +115,17 @@ spi_to_pdata(const struct spi_device *spi)
 
 static inline void setsck(const struct spi_device *spi, int is_on)
 {
-       gpio_set_value(SPI_SCK_GPIO, is_on);
+       gpio_set_value_cansleep(SPI_SCK_GPIO, is_on);
 }
 
 static inline void setmosi(const struct spi_device *spi, int is_on)
 {
-       gpio_set_value(SPI_MOSI_GPIO, is_on);
+       gpio_set_value_cansleep(SPI_MOSI_GPIO, is_on);
 }
 
 static inline int getmiso(const struct spi_device *spi)
 {
-       return !!gpio_get_value(SPI_MISO_GPIO);
+       return !!gpio_get_value_cansleep(SPI_MISO_GPIO);
 }
 
 #undef pdata
@@ -229,7 +229,7 @@ static void spi_gpio_chipselect(struct spi_device *spi, int is_active)
 
        if (cs != SPI_GPIO_NO_CHIPSELECT) {
                /* SPI is normally active-low */
-               gpio_set_value(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active);
+               gpio_set_value_cansleep(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active);
        }
 }
 
index 9602bbd8d7eac061fffb5543704fc9d68a48f135..2babea28b310af7071b1ca091833cc27809c9139 100644 (file)
@@ -40,6 +40,7 @@ struct mpc512x_psc_spi {
        unsigned int irq;
        u8 bits_per_word;
        struct clk *clk_mclk;
+       struct clk *clk_ipg;
        u32 mclk_rate;
 
        struct completion txisrdone;
@@ -475,8 +476,6 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
        struct spi_master *master;
        int ret;
        void *tempp;
-       int psc_num;
-       char clk_name[16];
        struct clk *clk;
 
        master = spi_alloc_master(dev, sizeof *mps);
@@ -520,9 +519,7 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
                goto free_master;
        init_completion(&mps->txisrdone);
 
-       psc_num = master->bus_num;
-       snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
-       clk = devm_clk_get(dev, clk_name);
+       clk = devm_clk_get(dev, "mclk");
        if (IS_ERR(clk)) {
                ret = PTR_ERR(clk);
                goto free_irq;
@@ -533,17 +530,29 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
        mps->clk_mclk = clk;
        mps->mclk_rate = clk_get_rate(clk);
 
+       clk = devm_clk_get(dev, "ipg");
+       if (IS_ERR(clk)) {
+               ret = PTR_ERR(clk);
+               goto free_mclk_clock;
+       }
+       ret = clk_prepare_enable(clk);
+       if (ret)
+               goto free_mclk_clock;
+       mps->clk_ipg = clk;
+
        ret = mpc512x_psc_spi_port_config(master, mps);
        if (ret < 0)
-               goto free_clock;
+               goto free_ipg_clock;
 
        ret = devm_spi_register_master(dev, master);
        if (ret < 0)
-               goto free_clock;
+               goto free_ipg_clock;
 
        return ret;
 
-free_clock:
+free_ipg_clock:
+       clk_disable_unprepare(mps->clk_ipg);
+free_mclk_clock:
        clk_disable_unprepare(mps->clk_mclk);
 free_irq:
        free_irq(mps->irq, mps);
@@ -557,10 +566,11 @@ free_master:
 
 static int mpc512x_psc_spi_do_remove(struct device *dev)
 {
-       struct spi_master *master = spi_master_get(dev_get_drvdata(dev));
+       struct spi_master *master = dev_get_drvdata(dev);
        struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
 
        clk_disable_unprepare(mps->clk_mclk);
+       clk_disable_unprepare(mps->clk_ipg);
        free_irq(mps->irq, mps);
        if (mps->psc)
                iounmap(mps->psc);
index 73afb56c08cc26826d468ad4aaacdce3a7e7043f..3adebfa22e3d785b6bf7ffb2149e77652039c3c3 100644 (file)
@@ -565,7 +565,7 @@ static int mxs_spi_remove(struct platform_device *pdev)
        struct mxs_spi *spi;
        struct mxs_ssp *ssp;
 
-       master = spi_master_get(platform_get_drvdata(pdev));
+       master = platform_get_drvdata(pdev);
        spi = spi_master_get_devdata(master);
        ssp = &spi->ssp;
 
index b6ed82beb01dc651d687f374ce5536ce289d440c..0d32054bfc0dd624c1d99ec37f47f6c8244b3ab2 100644 (file)
@@ -470,31 +470,12 @@ err:
        return status;
 }
 
-static int omap1_spi100k_remove(struct platform_device *pdev)
-{
-       struct spi_master       *master;
-       struct omap1_spi100k    *spi100k;
-       struct resource         *r;
-       int                     status = 0;
-
-       master = platform_get_drvdata(pdev);
-       spi100k = spi_master_get_devdata(master);
-
-       if (status != 0)
-               return status;
-
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
-       return 0;
-}
-
 static struct platform_driver omap1_spi100k_driver = {
        .driver = {
                .name           = "omap1_spi100k",
                .owner          = THIS_MODULE,
        },
        .probe          = omap1_spi100k_probe,
-       .remove         = omap1_spi100k_remove,
 };
 
 module_platform_driver(omap1_spi100k_driver);
@@ -502,4 +483,3 @@ module_platform_driver(omap1_spi100k_driver);
 MODULE_DESCRIPTION("OMAP7xx SPI 100k controller driver");
 MODULE_AUTHOR("Fabrice Crohas <fcrohas@gmail.com>");
 MODULE_LICENSE("GPL");
-
index 443df39840bc899fb3525dcb141ed82da87d72f4..a72127f08e39faa04d1433094590094ea1ac357d 100644 (file)
@@ -157,14 +157,14 @@ static inline void mcspi_write_reg(struct spi_master *master,
 {
        struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
 
-       __raw_writel(val, mcspi->base + idx);
+       writel_relaxed(val, mcspi->base + idx);
 }
 
 static inline u32 mcspi_read_reg(struct spi_master *master, int idx)
 {
        struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
 
-       return __raw_readl(mcspi->base + idx);
+       return readl_relaxed(mcspi->base + idx);
 }
 
 static inline void mcspi_write_cs_reg(const struct spi_device *spi,
@@ -172,14 +172,14 @@ static inline void mcspi_write_cs_reg(const struct spi_device *spi,
 {
        struct omap2_mcspi_cs   *cs = spi->controller_state;
 
-       __raw_writel(val, cs->base +  idx);
+       writel_relaxed(val, cs->base +  idx);
 }
 
 static inline u32 mcspi_read_cs_reg(const struct spi_device *spi, int idx)
 {
        struct omap2_mcspi_cs   *cs = spi->controller_state;
 
-       return __raw_readl(cs->base + idx);
+       return readl_relaxed(cs->base + idx);
 }
 
 static inline u32 mcspi_cached_chconf0(const struct spi_device *spi)
@@ -338,7 +338,7 @@ static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi)
        mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_WAKEUPENABLE, ctx->wakeupenable);
 
        list_for_each_entry(cs, &ctx->cs, node)
-               __raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
+               writel_relaxed(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
 }
 
 static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
@@ -346,9 +346,9 @@ static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
        unsigned long timeout;
 
        timeout = jiffies + msecs_to_jiffies(1000);
-       while (!(__raw_readl(reg) & bit)) {
+       while (!(readl_relaxed(reg) & bit)) {
                if (time_after(jiffies, timeout)) {
-                       if (!(__raw_readl(reg) & bit))
+                       if (!(readl_relaxed(reg) & bit))
                                return -ETIMEDOUT;
                        else
                                return 0;
@@ -675,7 +675,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                }
                                dev_vdbg(&spi->dev, "write-%d %02x\n",
                                                word_len, *tx);
-                               __raw_writel(*tx++, tx_reg);
+                               writel_relaxed(*tx++, tx_reg);
                        }
                        if (rx != NULL) {
                                if (mcspi_wait_for_reg_bit(chstat_reg,
@@ -687,7 +687,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                if (c == 1 && tx == NULL &&
                                    (l & OMAP2_MCSPI_CHCONF_TURBO)) {
                                        omap2_mcspi_set_enable(spi, 0);
-                                       *rx++ = __raw_readl(rx_reg);
+                                       *rx++ = readl_relaxed(rx_reg);
                                        dev_vdbg(&spi->dev, "read-%d %02x\n",
                                                    word_len, *(rx - 1));
                                        if (mcspi_wait_for_reg_bit(chstat_reg,
@@ -701,7 +701,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                        omap2_mcspi_set_enable(spi, 0);
                                }
 
-                               *rx++ = __raw_readl(rx_reg);
+                               *rx++ = readl_relaxed(rx_reg);
                                dev_vdbg(&spi->dev, "read-%d %02x\n",
                                                word_len, *(rx - 1));
                        }
@@ -722,7 +722,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                }
                                dev_vdbg(&spi->dev, "write-%d %04x\n",
                                                word_len, *tx);
-                               __raw_writel(*tx++, tx_reg);
+                               writel_relaxed(*tx++, tx_reg);
                        }
                        if (rx != NULL) {
                                if (mcspi_wait_for_reg_bit(chstat_reg,
@@ -734,7 +734,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                if (c == 2 && tx == NULL &&
                                    (l & OMAP2_MCSPI_CHCONF_TURBO)) {
                                        omap2_mcspi_set_enable(spi, 0);
-                                       *rx++ = __raw_readl(rx_reg);
+                                       *rx++ = readl_relaxed(rx_reg);
                                        dev_vdbg(&spi->dev, "read-%d %04x\n",
                                                    word_len, *(rx - 1));
                                        if (mcspi_wait_for_reg_bit(chstat_reg,
@@ -748,7 +748,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                        omap2_mcspi_set_enable(spi, 0);
                                }
 
-                               *rx++ = __raw_readl(rx_reg);
+                               *rx++ = readl_relaxed(rx_reg);
                                dev_vdbg(&spi->dev, "read-%d %04x\n",
                                                word_len, *(rx - 1));
                        }
@@ -769,7 +769,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                }
                                dev_vdbg(&spi->dev, "write-%d %08x\n",
                                                word_len, *tx);
-                               __raw_writel(*tx++, tx_reg);
+                               writel_relaxed(*tx++, tx_reg);
                        }
                        if (rx != NULL) {
                                if (mcspi_wait_for_reg_bit(chstat_reg,
@@ -781,7 +781,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                if (c == 4 && tx == NULL &&
                                    (l & OMAP2_MCSPI_CHCONF_TURBO)) {
                                        omap2_mcspi_set_enable(spi, 0);
-                                       *rx++ = __raw_readl(rx_reg);
+                                       *rx++ = readl_relaxed(rx_reg);
                                        dev_vdbg(&spi->dev, "read-%d %08x\n",
                                                    word_len, *(rx - 1));
                                        if (mcspi_wait_for_reg_bit(chstat_reg,
@@ -795,7 +795,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
                                        omap2_mcspi_set_enable(spi, 0);
                                }
 
-                               *rx++ = __raw_readl(rx_reg);
+                               *rx++ = readl_relaxed(rx_reg);
                                dev_vdbg(&spi->dev, "read-%d %08x\n",
                                                word_len, *(rx - 1));
                        }
@@ -1107,7 +1107,7 @@ static void omap2_mcspi_work(struct omap2_mcspi *mcspi, struct spi_message *m)
 
                        /* RX_ONLY mode needs dummy data in TX reg */
                        if (t->tx_buf == NULL)
-                               __raw_writel(0, cs->base
+                               writel_relaxed(0, cs->base
                                                + OMAP2_MCSPI_TX0);
 
                        if ((mcspi_dma->dma_rx && mcspi_dma->dma_tx) &&
@@ -1470,9 +1470,9 @@ static int omap2_mcspi_resume(struct device *dev)
                         * change in account.
                         */
                        cs->chconf0 |= OMAP2_MCSPI_CHCONF_FORCE;
-                       __raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
+                       writel_relaxed(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
                        cs->chconf0 &= ~OMAP2_MCSPI_CHCONF_FORCE;
-                       __raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
+                       writel_relaxed(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
                }
        }
        pm_runtime_mark_last_busy(mcspi->dev);
index 744841e095e4be7d4a8b7e6f057b2bed2915cf9a..7f2121fe262223391185bfc458be0ced703463a6 100644 (file)
@@ -434,7 +434,7 @@ static int orion_spi_probe(struct platform_device *pdev)
        spi = spi_master_get_devdata(master);
        spi->master = master;
 
-       spi->clk = clk_get(&pdev->dev, NULL);
+       spi->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(spi->clk)) {
                status = PTR_ERR(spi->clk);
                goto out;
@@ -465,7 +465,6 @@ static int orion_spi_probe(struct platform_device *pdev)
 
 out_rel_clk:
        clk_disable_unprepare(spi->clk);
-       clk_put(spi->clk);
 out:
        spi_master_put(master);
        return status;
@@ -481,7 +480,6 @@ static int orion_spi_remove(struct platform_device *pdev)
        spi = spi_master_get_devdata(master);
 
        clk_disable_unprepare(spi->clk);
-       clk_put(spi->clk);
 
        return 0;
 }
index 74bc18775658667617464aa865a7fb939161c438..3f006d3ed2a8bad5f749e5433aa1572ea23df15b 100644 (file)
@@ -62,7 +62,7 @@ static void ce4100_spi_remove(struct pci_dev *dev)
        platform_device_unregister(pdev);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(ce4100_spi_devices) = {
+static const struct pci_device_id ce4100_spi_devices[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2e6a) },
        { },
 };
index cb0e1f1137adb65384188ce31651171cb3f5f311..7765b1999537a08e5c6d95eed39bdea4c8c9c9dd 100644 (file)
@@ -1073,6 +1073,8 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
 static struct acpi_device_id pxa2xx_spi_acpi_match[] = {
        { "INT33C0", 0 },
        { "INT33C1", 0 },
+       { "INT3430", 0 },
+       { "INT3431", 0 },
        { "80860F0E", 0 },
        { },
 };
@@ -1291,6 +1293,9 @@ static int pxa2xx_spi_resume(struct device *dev)
        /* Enable the SSP clock */
        clk_prepare_enable(ssp->clk);
 
+       /* Restore LPSS private register bits */
+       lpss_ssp_setup(drv_data);
+
        /* Start the queue running */
        status = spi_master_resume(drv_data->master);
        if (status != 0) {
index 58449ad4ad0d3a83eb273b49f292909078519ca1..cfdbb422a40a9283b7e1a1200811dd5c2ff037fb 100644 (file)
@@ -268,7 +268,7 @@ static int qspi_set_config_register(struct rspi_data *rspi, int access_size)
                spcmd = SPCMD_SPB_8BIT;
        else if (access_size == 16)
                spcmd = SPCMD_SPB_16BIT;
-       else if (access_size == 32)
+       else
                spcmd = SPCMD_SPB_32BIT;
 
        spcmd |= SPCMD_SCKDEN | SPCMD_SLNDEN | SPCMD_SSLKP | SPCMD_SPNDEN;
@@ -885,14 +885,9 @@ static void rspi_release_dma(struct rspi_data *rspi)
 
 static int rspi_remove(struct platform_device *pdev)
 {
-       struct rspi_data *rspi = spi_master_get(platform_get_drvdata(pdev));
+       struct rspi_data *rspi = platform_get_drvdata(pdev);
 
-       spi_unregister_master(rspi->master);
        rspi_release_dma(rspi);
-       free_irq(platform_get_irq(pdev, 0), rspi);
-       clk_put(rspi->clk);
-       iounmap(rspi->addr);
-       spi_master_put(rspi->master);
 
        return 0;
 }
@@ -914,12 +909,6 @@ static int rspi_probe(struct platform_device *pdev)
                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)) {
-               dev_err(&pdev->dev, "invalid resource\n");
-               return -EINVAL;
-       }
 
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
@@ -937,19 +926,20 @@ static int rspi_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, rspi);
        rspi->ops = ops;
        rspi->master = master;
-       rspi->addr = ioremap(res->start, resource_size(res));
-       if (rspi->addr == NULL) {
-               dev_err(&pdev->dev, "ioremap error.\n");
-               ret = -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       rspi->addr = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(rspi->addr)) {
+               ret = PTR_ERR(rspi->addr);
                goto error1;
        }
 
        snprintf(clk_name, sizeof(clk_name), "%s%d", id_entry->name, pdev->id);
-       rspi->clk = clk_get(&pdev->dev, clk_name);
+       rspi->clk = devm_clk_get(&pdev->dev, clk_name);
        if (IS_ERR(rspi->clk)) {
                dev_err(&pdev->dev, "cannot get clock\n");
                ret = PTR_ERR(rspi->clk);
-               goto error2;
+               goto error1;
        }
        clk_enable(rspi->clk);
 
@@ -967,36 +957,32 @@ static int rspi_probe(struct platform_device *pdev)
        master->transfer = rspi_transfer;
        master->cleanup = rspi_cleanup;
 
-       ret = request_irq(irq, rspi_irq, 0, dev_name(&pdev->dev), rspi);
+       ret = devm_request_irq(&pdev->dev, irq, rspi_irq, 0,
+                              dev_name(&pdev->dev), rspi);
        if (ret < 0) {
                dev_err(&pdev->dev, "request_irq error\n");
-               goto error3;
+               goto error1;
        }
 
        rspi->irq = irq;
        ret = rspi_request_dma(rspi, pdev);
        if (ret < 0) {
                dev_err(&pdev->dev, "rspi_request_dma failed.\n");
-               goto error4;
+               goto error2;
        }
 
-       ret = spi_register_master(master);
+       ret = devm_spi_register_master(&pdev->dev, master);
        if (ret < 0) {
                dev_err(&pdev->dev, "spi_register_master error.\n");
-               goto error4;
+               goto error2;
        }
 
        dev_info(&pdev->dev, "probed\n");
 
        return 0;
 
-error4:
-       rspi_release_dma(rspi);
-       free_irq(irq, rspi);
-error3:
-       clk_put(rspi->clk);
 error2:
-       iounmap(rspi->addr);
+       rspi_release_dma(rspi);
 error1:
        spi_master_put(master);
 
index 9eda21d739c627706a40e101f5ea0b9eed9e4fab..c1a01d1ac3157211e0359a9a8b3235fae948db4f 100644 (file)
@@ -319,7 +319,7 @@ static int sc18is602_probe(struct i2c_client *client,
        master->transfer_one_message = sc18is602_transfer_one;
        master->dev.of_node = np;
 
-       error = spi_register_master(master);
+       error = devm_spi_register_master(dev, master);
        if (error)
                goto error_reg;
 
@@ -330,16 +330,6 @@ error_reg:
        return error;
 }
 
-static int sc18is602_remove(struct i2c_client *client)
-{
-       struct sc18is602 *hw = i2c_get_clientdata(client);
-       struct spi_master *master = hw->master;
-
-       spi_unregister_master(master);
-
-       return 0;
-}
-
 static const struct i2c_device_id sc18is602_id[] = {
        { "sc18is602", sc18is602 },
        { "sc18is602b", sc18is602b },
@@ -353,7 +343,6 @@ static struct i2c_driver sc18is602_driver = {
                .name = "sc18is602",
        },
        .probe = sc18is602_probe,
-       .remove = sc18is602_remove,
        .id_table = sc18is602_id,
 };
 
index c74298cf70e2406d8972f4fe75cc2fcd59a15864..81cc02f5f9b02494379bbc7cfb5547f17c48fb20 100644 (file)
@@ -152,7 +152,7 @@ static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p,
        size_t k;
 
        if (!WARN_ON(!spi_hz || !parent_rate))
-               div = parent_rate / spi_hz;
+               div = DIV_ROUND_UP(parent_rate, spi_hz);
 
        /* TODO: make more fine grained */
 
@@ -169,7 +169,7 @@ static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p,
 
 static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p,
                                      u32 cpol, u32 cpha,
-                                     u32 tx_hi_z, u32 lsb_first)
+                                     u32 tx_hi_z, u32 lsb_first, u32 cs_high)
 {
        u32 tmp;
        int edge;
@@ -182,8 +182,12 @@ static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p,
         *    1    1         11     11    1    1
         */
        sh_msiof_write(p, FCTR, 0);
-       sh_msiof_write(p, TMDR1, 0xe2000005 | (lsb_first << 24));
-       sh_msiof_write(p, RMDR1, 0x22000005 | (lsb_first << 24));
+
+       tmp = 0;
+       tmp |= !cs_high << 25;
+       tmp |= lsb_first << 24;
+       sh_msiof_write(p, TMDR1, 0xe0000005 | tmp);
+       sh_msiof_write(p, RMDR1, 0x20000005 | tmp);
 
        tmp = 0xa0000000;
        tmp |= cpol << 30; /* TSCKIZ */
@@ -417,11 +421,12 @@ static void sh_msiof_spi_chipselect(struct spi_device *spi, int is_on)
                sh_msiof_spi_set_pin_regs(p, !!(spi->mode & SPI_CPOL),
                                          !!(spi->mode & SPI_CPHA),
                                          !!(spi->mode & SPI_3WIRE),
-                                         !!(spi->mode & SPI_LSB_FIRST));
+                                         !!(spi->mode & SPI_LSB_FIRST),
+                                         !!(spi->mode & SPI_CS_HIGH));
        }
 
        /* use spi->controller data for CS (same strategy as spi_gpio) */
-       gpio_set_value((unsigned)spi->controller_data, value);
+       gpio_set_value((uintptr_t)spi->controller_data, value);
 
        if (is_on == BITBANG_CS_INACTIVE) {
                if (test_and_clear_bit(0, &p->flags)) {
@@ -635,8 +640,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
        master = spi_alloc_master(&pdev->dev, sizeof(struct sh_msiof_spi_priv));
        if (master == NULL) {
                dev_err(&pdev->dev, "failed to allocate spi master\n");
-               ret = -ENOMEM;
-               goto err0;
+               return -ENOMEM;
        }
 
        p = spi_master_get_devdata(master);
@@ -655,32 +659,38 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
 
        init_completion(&p->done);
 
-       p->clk = clk_get(&pdev->dev, NULL);
+       p->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(p->clk)) {
                dev_err(&pdev->dev, "cannot get clock\n");
                ret = PTR_ERR(p->clk);
                goto err1;
        }
 
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        i = platform_get_irq(pdev, 0);
-       if (!r || i < 0) {
-               dev_err(&pdev->dev, "cannot get platform resources\n");
+       if (i < 0) {
+               dev_err(&pdev->dev, "cannot get platform IRQ\n");
                ret = -ENOENT;
-               goto err2;
+               goto err1;
        }
-       p->mapbase = ioremap_nocache(r->start, resource_size(r));
-       if (!p->mapbase) {
-               dev_err(&pdev->dev, "unable to ioremap\n");
-               ret = -ENXIO;
-               goto err2;
+
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       p->mapbase = devm_ioremap_resource(&pdev->dev, r);
+       if (IS_ERR(p->mapbase)) {
+               ret = PTR_ERR(p->mapbase);
+               goto err1;
        }
 
-       ret = request_irq(i, sh_msiof_spi_irq, 0,
-                         dev_name(&pdev->dev), p);
+       ret = devm_request_irq(&pdev->dev, i, sh_msiof_spi_irq, 0,
+                              dev_name(&pdev->dev), p);
        if (ret) {
                dev_err(&pdev->dev, "unable to request irq\n");
-               goto err3;
+               goto err1;
+       }
+
+       ret = clk_prepare(p->clk);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "unable to prepare clock\n");
+               goto err1;
        }
 
        p->pdev = pdev;
@@ -719,13 +729,9 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
                return 0;
 
        pm_runtime_disable(&pdev->dev);
- err3:
-       iounmap(p->mapbase);
- err2:
-       clk_put(p->clk);
+       clk_unprepare(p->clk);
  err1:
        spi_master_put(master);
- err0:
        return ret;
 }
 
@@ -737,9 +743,7 @@ static int sh_msiof_spi_remove(struct platform_device *pdev)
        ret = spi_bitbang_stop(&p->bitbang);
        if (!ret) {
                pm_runtime_disable(&pdev->dev);
-               free_irq(platform_get_irq(pdev, 0), p);
-               iounmap(p->mapbase);
-               clk_put(p->clk);
+               clk_unprepare(p->clk);
                spi_master_put(p->bitbang.master);
        }
        return ret;
index aaecfb3ebf580bd9f746458b26175da61f1bc994..47b93cc4bd1912d584d520eb39b4ae24f8595dcd 100644 (file)
 #define SPI_CS_SS_VAL                          (1 << 20)
 #define SPI_CS_SW_HW                           (1 << 21)
 /* SPI_CS_POL_INACTIVE bits are default high */
-#define SPI_CS_POL_INACTIVE                    22
-#define SPI_CS_POL_INACTIVE_0                  (1 << 22)
-#define SPI_CS_POL_INACTIVE_1                  (1 << 23)
-#define SPI_CS_POL_INACTIVE_2                  (1 << 24)
-#define SPI_CS_POL_INACTIVE_3                  (1 << 25)
+                                               /* n from 0 to 3 */
+#define SPI_CS_POL_INACTIVE(n)                 (1 << (22 + (n)))
 #define SPI_CS_POL_INACTIVE_MASK               (0xF << 22)
 
 #define SPI_CS_SEL_0                           (0 << 26)
 #define MAX_HOLD_CYCLES                                16
 #define SPI_DEFAULT_SPEED                      25000000
 
-#define MAX_CHIP_SELECT                                4
-#define SPI_FIFO_DEPTH                         64
-
 struct tegra_spi_data {
        struct device                           *dev;
        struct spi_master                       *master;
@@ -184,7 +178,6 @@ struct tegra_spi_data {
        struct spi_device                       *cur_spi;
        struct spi_device                       *cs_control;
        unsigned                                cur_pos;
-       unsigned                                cur_len;
        unsigned                                words_per_32bit;
        unsigned                                bytes_per_word;
        unsigned                                curr_dma_words;
@@ -204,12 +197,10 @@ struct tegra_spi_data {
        u32                                     rx_status;
        u32                                     status_reg;
        bool                                    is_packed;
-       unsigned long                           packed_size;
 
        u32                                     command1_reg;
        u32                                     dma_control_reg;
        u32                                     def_command1_reg;
-       u32                                     spi_cs_timing;
 
        struct completion                       xfer_completion;
        struct spi_transfer                     *curr_xfer;
@@ -227,14 +218,14 @@ struct tegra_spi_data {
 static int tegra_spi_runtime_suspend(struct device *dev);
 static int tegra_spi_runtime_resume(struct device *dev);
 
-static inline unsigned long tegra_spi_readl(struct tegra_spi_data *tspi,
+static inline u32 tegra_spi_readl(struct tegra_spi_data *tspi,
                unsigned long reg)
 {
        return readl(tspi->base + reg);
 }
 
 static inline void tegra_spi_writel(struct tegra_spi_data *tspi,
-               unsigned long val, unsigned long reg)
+               u32 val, unsigned long reg)
 {
        writel(val, tspi->base + reg);
 
@@ -245,7 +236,7 @@ static inline void tegra_spi_writel(struct tegra_spi_data *tspi,
 
 static void tegra_spi_clear_status(struct tegra_spi_data *tspi)
 {
-       unsigned long val;
+       u32 val;
 
        /* Write 1 to clear status register */
        val = tegra_spi_readl(tspi, SPI_TRANS_STATUS);
@@ -296,10 +287,9 @@ static unsigned tegra_spi_fill_tx_fifo_from_client_txbuf(
 {
        unsigned nbytes;
        unsigned tx_empty_count;
-       unsigned long fifo_status;
+       u32 fifo_status;
        unsigned max_n_32bit;
        unsigned i, count;
-       unsigned long x;
        unsigned int written_words;
        unsigned fifo_words_left;
        u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_tx_pos;
@@ -313,9 +303,9 @@ static unsigned tegra_spi_fill_tx_fifo_from_client_txbuf(
                nbytes = written_words * tspi->bytes_per_word;
                max_n_32bit = DIV_ROUND_UP(nbytes, 4);
                for (count = 0; count < max_n_32bit; count++) {
-                       x = 0;
+                       u32 x = 0;
                        for (i = 0; (i < 4) && nbytes; i++, nbytes--)
-                               x |= (*tx_buf++) << (i*8);
+                               x |= (u32)(*tx_buf++) << (i * 8);
                        tegra_spi_writel(tspi, x, SPI_TX_FIFO);
                }
        } else {
@@ -323,10 +313,10 @@ static unsigned tegra_spi_fill_tx_fifo_from_client_txbuf(
                written_words = max_n_32bit;
                nbytes = written_words * tspi->bytes_per_word;
                for (count = 0; count < max_n_32bit; count++) {
-                       x = 0;
+                       u32 x = 0;
                        for (i = 0; nbytes && (i < tspi->bytes_per_word);
                                                        i++, nbytes--)
-                               x |= ((*tx_buf++) << i*8);
+                               x |= (u32)(*tx_buf++) << (i * 8);
                        tegra_spi_writel(tspi, x, SPI_TX_FIFO);
                }
        }
@@ -338,9 +328,8 @@ static unsigned int tegra_spi_read_rx_fifo_to_client_rxbuf(
                struct tegra_spi_data *tspi, struct spi_transfer *t)
 {
        unsigned rx_full_count;
-       unsigned long fifo_status;
+       u32 fifo_status;
        unsigned i, count;
-       unsigned long x;
        unsigned int read_words = 0;
        unsigned len;
        u8 *rx_buf = (u8 *)t->rx_buf + tspi->cur_rx_pos;
@@ -350,20 +339,16 @@ static unsigned int tegra_spi_read_rx_fifo_to_client_rxbuf(
        if (tspi->is_packed) {
                len = tspi->curr_dma_words * tspi->bytes_per_word;
                for (count = 0; count < rx_full_count; count++) {
-                       x = tegra_spi_readl(tspi, SPI_RX_FIFO);
+                       u32 x = tegra_spi_readl(tspi, SPI_RX_FIFO);
                        for (i = 0; len && (i < 4); i++, len--)
                                *rx_buf++ = (x >> i*8) & 0xFF;
                }
                tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word;
                read_words += tspi->curr_dma_words;
        } else {
-               unsigned int rx_mask;
-               unsigned int bits_per_word = t->bits_per_word;
-
-               rx_mask = (1 << bits_per_word) - 1;
+               u32 rx_mask = ((u32)1 << t->bits_per_word) - 1;
                for (count = 0; count < rx_full_count; count++) {
-                       x = tegra_spi_readl(tspi, SPI_RX_FIFO);
-                       x &= rx_mask;
+                       u32 x = tegra_spi_readl(tspi, SPI_RX_FIFO) & rx_mask;
                        for (i = 0; (i < tspi->bytes_per_word); i++)
                                *rx_buf++ = (x >> (i*8)) & 0xFF;
                }
@@ -376,27 +361,24 @@ static unsigned int tegra_spi_read_rx_fifo_to_client_rxbuf(
 static void tegra_spi_copy_client_txbuf_to_spi_txbuf(
                struct tegra_spi_data *tspi, struct spi_transfer *t)
 {
-       unsigned len;
-
        /* Make the dma buffer to read by cpu */
        dma_sync_single_for_cpu(tspi->dev, tspi->tx_dma_phys,
                                tspi->dma_buf_size, DMA_TO_DEVICE);
 
        if (tspi->is_packed) {
-               len = tspi->curr_dma_words * tspi->bytes_per_word;
+               unsigned len = tspi->curr_dma_words * tspi->bytes_per_word;
                memcpy(tspi->tx_dma_buf, t->tx_buf + tspi->cur_pos, len);
        } else {
                unsigned int i;
                unsigned int count;
                u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_tx_pos;
                unsigned consume = tspi->curr_dma_words * tspi->bytes_per_word;
-               unsigned int x;
 
                for (count = 0; count < tspi->curr_dma_words; count++) {
-                       x = 0;
+                       u32 x = 0;
                        for (i = 0; consume && (i < tspi->bytes_per_word);
                                                        i++, consume--)
-                               x |= ((*tx_buf++) << i * 8);
+                               x |= (u32)(*tx_buf++) << (i * 8);
                        tspi->tx_dma_buf[count] = x;
                }
        }
@@ -410,27 +392,21 @@ static void tegra_spi_copy_client_txbuf_to_spi_txbuf(
 static void tegra_spi_copy_spi_rxbuf_to_client_rxbuf(
                struct tegra_spi_data *tspi, struct spi_transfer *t)
 {
-       unsigned len;
-
        /* Make the dma buffer to read by cpu */
        dma_sync_single_for_cpu(tspi->dev, tspi->rx_dma_phys,
                tspi->dma_buf_size, DMA_FROM_DEVICE);
 
        if (tspi->is_packed) {
-               len = tspi->curr_dma_words * tspi->bytes_per_word;
+               unsigned len = tspi->curr_dma_words * tspi->bytes_per_word;
                memcpy(t->rx_buf + tspi->cur_rx_pos, tspi->rx_dma_buf, len);
        } else {
                unsigned int i;
                unsigned int count;
                unsigned char *rx_buf = t->rx_buf + tspi->cur_rx_pos;
-               unsigned int x;
-               unsigned int rx_mask;
-               unsigned int bits_per_word = t->bits_per_word;
+               u32 rx_mask = ((u32)1 << t->bits_per_word) - 1;
 
-               rx_mask = (1 << bits_per_word) - 1;
                for (count = 0; count < tspi->curr_dma_words; count++) {
-                       x = tspi->rx_dma_buf[count];
-                       x &= rx_mask;
+                       u32 x = tspi->rx_dma_buf[count] & rx_mask;
                        for (i = 0; (i < tspi->bytes_per_word); i++)
                                *rx_buf++ = (x >> (i*8)) & 0xFF;
                }
@@ -490,16 +466,16 @@ static int tegra_spi_start_rx_dma(struct tegra_spi_data *tspi, int len)
 static int tegra_spi_start_dma_based_transfer(
                struct tegra_spi_data *tspi, struct spi_transfer *t)
 {
-       unsigned long val;
+       u32 val;
        unsigned int len;
        int ret = 0;
-       unsigned long status;
+       u32 status;
 
        /* Make sure that Rx and Tx fifo are empty */
        status = tegra_spi_readl(tspi, SPI_FIFO_STATUS);
        if ((status & SPI_FIFO_EMPTY) != SPI_FIFO_EMPTY) {
-               dev_err(tspi->dev,
-                       "Rx/Tx fifo are not empty status 0x%08lx\n", status);
+               dev_err(tspi->dev, "Rx/Tx fifo are not empty status 0x%08x\n",
+                       (unsigned)status);
                return -EIO;
        }
 
@@ -564,7 +540,7 @@ static int tegra_spi_start_dma_based_transfer(
 static int tegra_spi_start_cpu_based_transfer(
                struct tegra_spi_data *tspi, struct spi_transfer *t)
 {
-       unsigned long val;
+       u32 val;
        unsigned cur_words;
 
        if (tspi->cur_direction & DATA_DIR_TX)
@@ -677,13 +653,13 @@ static void tegra_spi_deinit_dma_param(struct tegra_spi_data *tspi,
        dma_release_channel(dma_chan);
 }
 
-static unsigned long tegra_spi_setup_transfer_one(struct spi_device *spi,
+static u32 tegra_spi_setup_transfer_one(struct spi_device *spi,
                struct spi_transfer *t, bool is_first_of_msg)
 {
        struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master);
        u32 speed = t->speed_hz;
        u8 bits_per_word = t->bits_per_word;
-       unsigned long command1;
+       u32 command1;
        int req_mode;
 
        if (speed != tspi->cur_speed) {
@@ -738,7 +714,7 @@ static unsigned long tegra_spi_setup_transfer_one(struct spi_device *spi,
 }
 
 static int tegra_spi_start_transfer_one(struct spi_device *spi,
-               struct spi_transfer *t, unsigned long command1)
+               struct spi_transfer *t, u32 command1)
 {
        struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master);
        unsigned total_fifo_words;
@@ -763,8 +739,8 @@ static int tegra_spi_start_transfer_one(struct spi_device *spi,
        tegra_spi_writel(tspi, command1, SPI_COMMAND1);
        tspi->command1_reg = command1;
 
-       dev_dbg(tspi->dev, "The def 0x%x and written 0x%lx\n",
-                               tspi->def_command1_reg, command1);
+       dev_dbg(tspi->dev, "The def 0x%x and written 0x%x\n",
+               tspi->def_command1_reg, (unsigned)command1);
 
        if (total_fifo_words > SPI_FIFO_DEPTH)
                ret = tegra_spi_start_dma_based_transfer(tspi, t);
@@ -776,15 +752,9 @@ static int tegra_spi_start_transfer_one(struct spi_device *spi,
 static int tegra_spi_setup(struct spi_device *spi)
 {
        struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master);
-       unsigned long val;
+       u32 val;
        unsigned long flags;
        int ret;
-       unsigned int cs_pol_bit[MAX_CHIP_SELECT] = {
-                       SPI_CS_POL_INACTIVE_0,
-                       SPI_CS_POL_INACTIVE_1,
-                       SPI_CS_POL_INACTIVE_2,
-                       SPI_CS_POL_INACTIVE_3,
-       };
 
        dev_dbg(&spi->dev, "setup %d bpw, %scpol, %scpha, %dHz\n",
                spi->bits_per_word,
@@ -806,9 +776,9 @@ static int tegra_spi_setup(struct spi_device *spi)
        spin_lock_irqsave(&tspi->lock, flags);
        val = tspi->def_command1_reg;
        if (spi->mode & SPI_CS_HIGH)
-               val &= ~cs_pol_bit[spi->chip_select];
+               val &= ~SPI_CS_POL_INACTIVE(spi->chip_select);
        else
-               val |= cs_pol_bit[spi->chip_select];
+               val |= SPI_CS_POL_INACTIVE(spi->chip_select);
        tspi->def_command1_reg = val;
        tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1);
        spin_unlock_irqrestore(&tspi->lock, flags);
@@ -842,7 +812,7 @@ static int tegra_spi_transfer_one_message(struct spi_master *master,
        msg->actual_length = 0;
 
        list_for_each_entry(xfer, &msg->transfers, transfer_list) {
-               unsigned long cmd1;
+               u32 cmd1;
 
                reinit_completion(&tspi->xfer_completion);
 
index 4dc8e8129459b3eaa4bb18744e33dcbd578b0da2..af78c17388d24097bd23d8b5b99a45868d41b12a 100644 (file)
@@ -148,14 +148,14 @@ struct tegra_sflash_data {
 static int tegra_sflash_runtime_suspend(struct device *dev);
 static int tegra_sflash_runtime_resume(struct device *dev);
 
-static inline unsigned long tegra_sflash_readl(struct tegra_sflash_data *tsd,
+static inline u32 tegra_sflash_readl(struct tegra_sflash_data *tsd,
                unsigned long reg)
 {
        return readl(tsd->base + reg);
 }
 
 static inline void tegra_sflash_writel(struct tegra_sflash_data *tsd,
-               unsigned long val, unsigned long reg)
+               u32 val, unsigned long reg)
 {
        writel(val, tsd->base + reg);
 }
@@ -185,7 +185,7 @@ static unsigned tegra_sflash_fill_tx_fifo_from_client_txbuf(
        struct tegra_sflash_data *tsd, struct spi_transfer *t)
 {
        unsigned nbytes;
-       unsigned long status;
+       u32 status;
        unsigned max_n_32bit = tsd->curr_xfer_words;
        u8 *tx_buf = (u8 *)t->tx_buf + tsd->cur_tx_pos;
 
@@ -196,11 +196,11 @@ static unsigned tegra_sflash_fill_tx_fifo_from_client_txbuf(
        status = tegra_sflash_readl(tsd, SPI_STATUS);
        while (!(status & SPI_TXF_FULL)) {
                int i;
-               unsigned int x = 0;
+               u32 x = 0;
 
                for (i = 0; nbytes && (i < tsd->bytes_per_word);
                                                        i++, nbytes--)
-                               x |= ((*tx_buf++) << i*8);
+                       x |= (u32)(*tx_buf++) << (i * 8);
                tegra_sflash_writel(tsd, x, SPI_TX_FIFO);
                if (!nbytes)
                        break;
@@ -214,16 +214,14 @@ static unsigned tegra_sflash_fill_tx_fifo_from_client_txbuf(
 static int tegra_sflash_read_rx_fifo_to_client_rxbuf(
                struct tegra_sflash_data *tsd, struct spi_transfer *t)
 {
-       unsigned long status;
+       u32 status;
        unsigned int read_words = 0;
        u8 *rx_buf = (u8 *)t->rx_buf + tsd->cur_rx_pos;
 
        status = tegra_sflash_readl(tsd, SPI_STATUS);
        while (!(status & SPI_RXF_EMPTY)) {
                int i;
-               unsigned long x;
-
-               x = tegra_sflash_readl(tsd, SPI_RX_FIFO);
+               u32 x = tegra_sflash_readl(tsd, SPI_RX_FIFO);
                for (i = 0; (i < tsd->bytes_per_word); i++)
                        *rx_buf++ = (x >> (i*8)) & 0xFF;
                read_words++;
@@ -236,7 +234,7 @@ static int tegra_sflash_read_rx_fifo_to_client_rxbuf(
 static int tegra_sflash_start_cpu_based_transfer(
                struct tegra_sflash_data *tsd, struct spi_transfer *t)
 {
-       unsigned long val = 0;
+       u32 val = 0;
        unsigned cur_words;
 
        if (tsd->cur_direction & DATA_DIR_TX)
@@ -266,7 +264,7 @@ static int tegra_sflash_start_transfer_one(struct spi_device *spi,
 {
        struct tegra_sflash_data *tsd = spi_master_get_devdata(spi->master);
        u32 speed;
-       unsigned long command;
+       u32 command;
 
        speed = t->speed_hz;
        if (speed != tsd->cur_speed) {
@@ -313,7 +311,7 @@ static int tegra_sflash_start_transfer_one(struct spi_device *spi,
        tegra_sflash_writel(tsd, command, SPI_COMMAND);
        tsd->command_reg = command;
 
-       return  tegra_sflash_start_cpu_based_transfer(tsd, t);
+       return tegra_sflash_start_cpu_based_transfer(tsd, t);
 }
 
 static int tegra_sflash_setup(struct spi_device *spi)
index e66715ba37ed680811d7a53eb08e1b66979994c7..3ce1de8872f0ad3e34445d7fd58ae50a2f9c4609 100644 (file)
@@ -196,7 +196,7 @@ struct tegra_slink_data {
        u32                                     rx_status;
        u32                                     status_reg;
        bool                                    is_packed;
-       unsigned long                           packed_size;
+       u32                                     packed_size;
 
        u32                                     command_reg;
        u32                                     command2_reg;
@@ -220,14 +220,14 @@ struct tegra_slink_data {
 static int tegra_slink_runtime_suspend(struct device *dev);
 static int tegra_slink_runtime_resume(struct device *dev);
 
-static inline unsigned long tegra_slink_readl(struct tegra_slink_data *tspi,
+static inline u32 tegra_slink_readl(struct tegra_slink_data *tspi,
                unsigned long reg)
 {
        return readl(tspi->base + reg);
 }
 
 static inline void tegra_slink_writel(struct tegra_slink_data *tspi,
-               unsigned long val, unsigned long reg)
+               u32 val, unsigned long reg)
 {
        writel(val, tspi->base + reg);
 
@@ -238,38 +238,30 @@ static inline void tegra_slink_writel(struct tegra_slink_data *tspi,
 
 static void tegra_slink_clear_status(struct tegra_slink_data *tspi)
 {
-       unsigned long val;
-       unsigned long val_write = 0;
+       u32 val_write;
 
-       val = tegra_slink_readl(tspi, SLINK_STATUS);
+       tegra_slink_readl(tspi, SLINK_STATUS);
 
        /* Write 1 to clear status register */
        val_write = SLINK_RDY | SLINK_FIFO_ERROR;
        tegra_slink_writel(tspi, val_write, SLINK_STATUS);
 }
 
-static unsigned long tegra_slink_get_packed_size(struct tegra_slink_data *tspi,
+static u32 tegra_slink_get_packed_size(struct tegra_slink_data *tspi,
                                  struct spi_transfer *t)
 {
-       unsigned long val;
-
        switch (tspi->bytes_per_word) {
        case 0:
-               val = SLINK_PACK_SIZE_4;
-               break;
+               return SLINK_PACK_SIZE_4;
        case 1:
-               val = SLINK_PACK_SIZE_8;
-               break;
+               return SLINK_PACK_SIZE_8;
        case 2:
-               val = SLINK_PACK_SIZE_16;
-               break;
+               return SLINK_PACK_SIZE_16;
        case 4:
-               val = SLINK_PACK_SIZE_32;
-               break;
+               return SLINK_PACK_SIZE_32;
        default:
-               val = 0;
+               return 0;
        }
-       return val;
 }
 
 static unsigned tegra_slink_calculate_curr_xfer_param(
@@ -312,10 +304,9 @@ static unsigned tegra_slink_fill_tx_fifo_from_client_txbuf(
 {
        unsigned nbytes;
        unsigned tx_empty_count;
-       unsigned long fifo_status;
+       u32 fifo_status;
        unsigned max_n_32bit;
        unsigned i, count;
-       unsigned long x;
        unsigned int written_words;
        unsigned fifo_words_left;
        u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_tx_pos;
@@ -329,9 +320,9 @@ static unsigned tegra_slink_fill_tx_fifo_from_client_txbuf(
                nbytes = written_words * tspi->bytes_per_word;
                max_n_32bit = DIV_ROUND_UP(nbytes, 4);
                for (count = 0; count < max_n_32bit; count++) {
-                       x = 0;
+                       u32 x = 0;
                        for (i = 0; (i < 4) && nbytes; i++, nbytes--)
-                               x |= (*tx_buf++) << (i*8);
+                               x |= (u32)(*tx_buf++) << (i * 8);
                        tegra_slink_writel(tspi, x, SLINK_TX_FIFO);
                }
        } else {
@@ -339,10 +330,10 @@ static unsigned tegra_slink_fill_tx_fifo_from_client_txbuf(
                written_words = max_n_32bit;
                nbytes = written_words * tspi->bytes_per_word;
                for (count = 0; count < max_n_32bit; count++) {
-                       x = 0;
+                       u32 x = 0;
                        for (i = 0; nbytes && (i < tspi->bytes_per_word);
                                                        i++, nbytes--)
-                               x |= ((*tx_buf++) << i*8);
+                               x |= (u32)(*tx_buf++) << (i * 8);
                        tegra_slink_writel(tspi, x, SLINK_TX_FIFO);
                }
        }
@@ -354,9 +345,8 @@ static unsigned int tegra_slink_read_rx_fifo_to_client_rxbuf(
                struct tegra_slink_data *tspi, struct spi_transfer *t)
 {
        unsigned rx_full_count;
-       unsigned long fifo_status;
+       u32 fifo_status;
        unsigned i, count;
-       unsigned long x;
        unsigned int read_words = 0;
        unsigned len;
        u8 *rx_buf = (u8 *)t->rx_buf + tspi->cur_rx_pos;
@@ -366,7 +356,7 @@ static unsigned int tegra_slink_read_rx_fifo_to_client_rxbuf(
        if (tspi->is_packed) {
                len = tspi->curr_dma_words * tspi->bytes_per_word;
                for (count = 0; count < rx_full_count; count++) {
-                       x = tegra_slink_readl(tspi, SLINK_RX_FIFO);
+                       u32 x = tegra_slink_readl(tspi, SLINK_RX_FIFO);
                        for (i = 0; len && (i < 4); i++, len--)
                                *rx_buf++ = (x >> i*8) & 0xFF;
                }
@@ -374,7 +364,7 @@ static unsigned int tegra_slink_read_rx_fifo_to_client_rxbuf(
                read_words += tspi->curr_dma_words;
        } else {
                for (count = 0; count < rx_full_count; count++) {
-                       x = tegra_slink_readl(tspi, SLINK_RX_FIFO);
+                       u32 x = tegra_slink_readl(tspi, SLINK_RX_FIFO);
                        for (i = 0; (i < tspi->bytes_per_word); i++)
                                *rx_buf++ = (x >> (i*8)) & 0xFF;
                }
@@ -387,27 +377,24 @@ static unsigned int tegra_slink_read_rx_fifo_to_client_rxbuf(
 static void tegra_slink_copy_client_txbuf_to_spi_txbuf(
                struct tegra_slink_data *tspi, struct spi_transfer *t)
 {
-       unsigned len;
-
        /* Make the dma buffer to read by cpu */
        dma_sync_single_for_cpu(tspi->dev, tspi->tx_dma_phys,
                                tspi->dma_buf_size, DMA_TO_DEVICE);
 
        if (tspi->is_packed) {
-               len = tspi->curr_dma_words * tspi->bytes_per_word;
+               unsigned len = tspi->curr_dma_words * tspi->bytes_per_word;
                memcpy(tspi->tx_dma_buf, t->tx_buf + tspi->cur_pos, len);
        } else {
                unsigned int i;
                unsigned int count;
                u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_tx_pos;
                unsigned consume = tspi->curr_dma_words * tspi->bytes_per_word;
-               unsigned int x;
 
                for (count = 0; count < tspi->curr_dma_words; count++) {
-                       x = 0;
+                       u32 x = 0;
                        for (i = 0; consume && (i < tspi->bytes_per_word);
                                                        i++, consume--)
-                               x |= ((*tx_buf++) << i * 8);
+                               x |= (u32)(*tx_buf++) << (i * 8);
                        tspi->tx_dma_buf[count] = x;
                }
        }
@@ -434,14 +421,10 @@ static void tegra_slink_copy_spi_rxbuf_to_client_rxbuf(
                unsigned int i;
                unsigned int count;
                unsigned char *rx_buf = t->rx_buf + tspi->cur_rx_pos;
-               unsigned int x;
-               unsigned int rx_mask, bits_per_word;
+               u32 rx_mask = ((u32)1 << t->bits_per_word) - 1;
 
-               bits_per_word = t->bits_per_word;
-               rx_mask = (1 << bits_per_word) - 1;
                for (count = 0; count < tspi->curr_dma_words; count++) {
-                       x = tspi->rx_dma_buf[count];
-                       x &= rx_mask;
+                       u32 x = tspi->rx_dma_buf[count] & rx_mask;
                        for (i = 0; (i < tspi->bytes_per_word); i++)
                                *rx_buf++ = (x >> (i*8)) & 0xFF;
                }
@@ -501,17 +484,16 @@ static int tegra_slink_start_rx_dma(struct tegra_slink_data *tspi, int len)
 static int tegra_slink_start_dma_based_transfer(
                struct tegra_slink_data *tspi, struct spi_transfer *t)
 {
-       unsigned long val;
-       unsigned long test_val;
+       u32 val;
        unsigned int len;
        int ret = 0;
-       unsigned long status;
+       u32 status;
 
        /* Make sure that Rx and Tx fifo are empty */
        status = tegra_slink_readl(tspi, SLINK_STATUS);
        if ((status & SLINK_FIFO_EMPTY) != SLINK_FIFO_EMPTY) {
-               dev_err(tspi->dev,
-                       "Rx/Tx fifo are not empty status 0x%08lx\n", status);
+               dev_err(tspi->dev, "Rx/Tx fifo are not empty status 0x%08x\n",
+                       (unsigned)status);
                return -EIO;
        }
 
@@ -551,9 +533,9 @@ static int tegra_slink_start_dma_based_transfer(
                }
 
                /* Wait for tx fifo to be fill before starting slink */
-               test_val = tegra_slink_readl(tspi, SLINK_STATUS);
-               while (!(test_val & SLINK_TX_FULL))
-                       test_val = tegra_slink_readl(tspi, SLINK_STATUS);
+               status = tegra_slink_readl(tspi, SLINK_STATUS);
+               while (!(status & SLINK_TX_FULL))
+                       status = tegra_slink_readl(tspi, SLINK_STATUS);
        }
 
        if (tspi->cur_direction & DATA_DIR_RX) {
@@ -587,7 +569,7 @@ static int tegra_slink_start_dma_based_transfer(
 static int tegra_slink_start_cpu_based_transfer(
                struct tegra_slink_data *tspi, struct spi_transfer *t)
 {
-       unsigned long val;
+       u32 val;
        unsigned cur_words;
 
        val = tspi->packed_size;
@@ -714,8 +696,8 @@ static int tegra_slink_start_transfer_one(struct spi_device *spi,
        u8 bits_per_word;
        unsigned total_fifo_words;
        int ret;
-       unsigned long command;
-       unsigned long command2;
+       u32 command;
+       u32 command2;
 
        bits_per_word = t->bits_per_word;
        speed = t->speed_hz;
@@ -762,17 +744,18 @@ static int tegra_slink_start_transfer_one(struct spi_device *spi,
 
 static int tegra_slink_setup(struct spi_device *spi)
 {
-       struct tegra_slink_data *tspi = spi_master_get_devdata(spi->master);
-       unsigned long val;
-       unsigned long flags;
-       int ret;
-       unsigned int cs_pol_bit[MAX_CHIP_SELECT] = {
+       static const u32 cs_pol_bit[MAX_CHIP_SELECT] = {
                        SLINK_CS_POLARITY,
                        SLINK_CS_POLARITY1,
                        SLINK_CS_POLARITY2,
                        SLINK_CS_POLARITY3,
        };
 
+       struct tegra_slink_data *tspi = spi_master_get_devdata(spi->master);
+       u32 val;
+       unsigned long flags;
+       int ret;
+
        dev_dbg(&spi->dev, "setup %d bpw, %scpol, %scpha, %dHz\n",
                spi->bits_per_word,
                spi->mode & SPI_CPOL ? "" : "~",
index 0b71270fbf67ba671dd43f116db48de30076514c..4396bd44854063d9488cfd5dadc863c40c9e1dbf 100644 (file)
@@ -161,7 +161,7 @@ static int ti_qspi_setup(struct spi_device *spi)
                        qspi->spi_max_frequency, clk_div);
 
        ret = pm_runtime_get_sync(qspi->dev);
-       if (ret) {
+       if (ret < 0) {
                dev_err(qspi->dev, "pm_runtime_get_sync() failed\n");
                return ret;
        }
@@ -459,11 +459,10 @@ static int ti_qspi_probe(struct platform_device *pdev)
        if (!of_property_read_u32(np, "num-cs", &num_cs))
                master->num_chipselect = num_cs;
 
-       platform_set_drvdata(pdev, master);
-
        qspi = spi_master_get_devdata(master);
        qspi->master = master;
        qspi->dev = &pdev->dev;
+       platform_set_drvdata(pdev, qspi);
 
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
@@ -517,10 +516,26 @@ free_master:
 
 static int ti_qspi_remove(struct platform_device *pdev)
 {
-       struct  ti_qspi *qspi = platform_get_drvdata(pdev);
+       struct spi_master *master;
+       struct ti_qspi *qspi;
+       int ret;
+
+       master = platform_get_drvdata(pdev);
+       qspi = spi_master_get_devdata(master);
+
+       ret = pm_runtime_get_sync(qspi->dev);
+       if (ret < 0) {
+               dev_err(qspi->dev, "pm_runtime_get_sync() failed\n");
+               return ret;
+       }
 
        ti_qspi_write(qspi, QSPI_WC_INT_DISABLE, QSPI_INTR_ENABLE_CLEAR_REG);
 
+       pm_runtime_put(qspi->dev);
+       pm_runtime_disable(&pdev->dev);
+
+       spi_unregister_master(master);
+
        return 0;
 }
 
index 446131308acb26a1fac3ed8bfc1aad9e287404d5..338fc11913c18c2ff74b4dd9d181748c2cfe8512 100644 (file)
@@ -217,7 +217,7 @@ struct pch_pd_dev_save {
        struct pch_spi_board_data *board_dat;
 };
 
-static DEFINE_PCI_DEVICE_TABLE(pch_spi_pcidev_id) = {
+static const struct pci_device_id pch_spi_pcidev_id[] = {
        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_GE_SPI),    1, },
        { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7213_SPI), 2, },
        { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_SPI), 1, },
index 637cce2b8bdde8d3f37c8134a5f3aee7c4adead8..18c9bb2b5f39108793a32a2b71624f0e59434712 100644 (file)
@@ -425,7 +425,7 @@ exit:
 
 static int txx9spi_remove(struct platform_device *dev)
 {
-       struct spi_master *master = spi_master_get(platform_get_drvdata(dev));
+       struct spi_master *master = platform_get_drvdata(dev);
        struct txx9spi *c = spi_master_get_devdata(master);
 
        destroy_workqueue(c->workqueue);
index 4258c712ad3c273d5f8ab571e9b3f829d0f256cf..24c40b13dab1596edb6756e4f6311523393b418a 100644 (file)
@@ -231,22 +231,13 @@ static int spi_xcomm_probe(struct i2c_client *i2c,
        master->dev.of_node = i2c->dev.of_node;
        i2c_set_clientdata(i2c, master);
 
-       ret = spi_register_master(master);
+       ret = devm_spi_register_master(&i2c->dev, master);
        if (ret < 0)
                spi_master_put(master);
 
        return ret;
 }
 
-static int spi_xcomm_remove(struct i2c_client *i2c)
-{
-       struct spi_master *master = i2c_get_clientdata(i2c);
-
-       spi_unregister_master(master);
-
-       return 0;
-}
-
 static const struct i2c_device_id spi_xcomm_ids[] = {
        { "spi-xcomm" },
        { },
@@ -259,7 +250,6 @@ static struct i2c_driver spi_xcomm_driver = {
        },
        .id_table       = spi_xcomm_ids,
        .probe          = spi_xcomm_probe,
-       .remove         = spi_xcomm_remove,
 };
 module_i2c_driver(spi_xcomm_driver);
 
index 18cc625d887f796aed4b082eb2366262aec8aaa8..98f4b77380df1d1d5739a6b7de743b6cc0442575 100644 (file)
@@ -1415,7 +1415,7 @@ int devm_spi_register_master(struct device *dev, struct spi_master *master)
                return -ENOMEM;
 
        ret = spi_register_master(master);
-       if (ret != 0) {
+       if (!ret) {
                *ptr = master;
                devres_add(dev, ptr);
        } else {
@@ -1596,15 +1596,11 @@ int spi_setup(struct spi_device *spi)
 }
 EXPORT_SYMBOL_GPL(spi_setup);
 
-static int __spi_async(struct spi_device *spi, struct spi_message *message)
+static int __spi_validate(struct spi_device *spi, struct spi_message *message)
 {
        struct spi_master *master = spi->master;
        struct spi_transfer *xfer;
 
-       message->spi = spi;
-
-       trace_spi_message_submit(message);
-
        if (list_empty(&message->transfers))
                return -EINVAL;
        if (!message->complete)
@@ -1705,6 +1701,18 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
        }
 
        message->status = -EINPROGRESS;
+
+       return 0;
+}
+
+static int __spi_async(struct spi_device *spi, struct spi_message *message)
+{
+       struct spi_master *master = spi->master;
+
+       message->spi = spi;
+
+       trace_spi_message_submit(message);
+
        return master->transfer(spi, message);
 }
 
@@ -1743,6 +1751,10 @@ int spi_async(struct spi_device *spi, struct spi_message *message)
        int ret;
        unsigned long flags;
 
+       ret = __spi_validate(spi, message);
+       if (ret != 0)
+               return ret;
+
        spin_lock_irqsave(&master->bus_lock_spinlock, flags);
 
        if (master->bus_lock_flag)
@@ -1791,6 +1803,10 @@ int spi_async_locked(struct spi_device *spi, struct spi_message *message)
        int ret;
        unsigned long flags;
 
+       ret = __spi_validate(spi, message);
+       if (ret != 0)
+               return ret;
+
        spin_lock_irqsave(&master->bus_lock_spinlock, flags);
 
        ret = __spi_async(spi, message);
index e2421ea6135292aa37af132259356602770dcb67..581ff78be1a2a4b6e19d39d0cd36e5075fd997c0 100644 (file)
@@ -194,10 +194,10 @@ static int do_bio_lustrebacked(struct lloop_device *lo, struct bio *head)
        struct cl_object     *obj = ll_i2info(inode)->lli_clob;
        pgoff_t        offset;
        int                ret;
-       int                i;
        int                rw;
        obd_count            page_count = 0;
-       struct bio_vec       *bvec;
+       struct bio_vec       bvec;
+       struct bvec_iter   iter;
        struct bio         *bio;
        ssize_t        bytes;
 
@@ -220,15 +220,15 @@ static int do_bio_lustrebacked(struct lloop_device *lo, struct bio *head)
        for (bio = head; bio != NULL; bio = bio->bi_next) {
                LASSERT(rw == bio->bi_rw);
 
-               offset = (pgoff_t)(bio->bi_sector << 9) + lo->lo_offset;
-               bio_for_each_segment(bvec, bio, i) {
-                       BUG_ON(bvec->bv_offset != 0);
-                       BUG_ON(bvec->bv_len != PAGE_CACHE_SIZE);
+               offset = (pgoff_t)(bio->bi_iter.bi_sector << 9) + lo->lo_offset;
+               bio_for_each_segment(bvec, bio, iter) {
+                       BUG_ON(bvec.bv_offset != 0);
+                       BUG_ON(bvec.bv_len != PAGE_CACHE_SIZE);
 
-                       pages[page_count] = bvec->bv_page;
+                       pages[page_count] = bvec.bv_page;
                        offsets[page_count] = offset;
                        page_count++;
-                       offset += bvec->bv_len;
+                       offset += bvec.bv_len;
                }
                LASSERT(page_count <= LLOOP_MAX_SEGMENTS);
        }
@@ -313,7 +313,8 @@ static unsigned int loop_get_bio(struct lloop_device *lo, struct bio **req)
        bio = &lo->lo_bio;
        while (*bio && (*bio)->bi_rw == rw) {
                CDEBUG(D_INFO, "bio sector %llu size %u count %u vcnt%u \n",
-                      (unsigned long long)(*bio)->bi_sector, (*bio)->bi_size,
+                      (unsigned long long)(*bio)->bi_iter.bi_sector,
+                      (*bio)->bi_iter.bi_size,
                       page_count, (*bio)->bi_vcnt);
                if (page_count + (*bio)->bi_vcnt > LLOOP_MAX_SEGMENTS)
                        break;
@@ -347,7 +348,8 @@ static void loop_make_request(struct request_queue *q, struct bio *old_bio)
                goto err;
 
        CDEBUG(D_INFO, "submit bio sector %llu size %u\n",
-              (unsigned long long)old_bio->bi_sector, old_bio->bi_size);
+              (unsigned long long)old_bio->bi_iter.bi_sector,
+              old_bio->bi_iter.bi_size);
 
        spin_lock_irq(&lo->lo_lock);
        inactive = (lo->lo_state != LLOOP_BOUND);
@@ -367,7 +369,7 @@ static void loop_make_request(struct request_queue *q, struct bio *old_bio)
        loop_add_bio(lo, old_bio);
        return;
 err:
-       cfs_bio_io_error(old_bio, old_bio->bi_size);
+       cfs_bio_io_error(old_bio, old_bio->bi_iter.bi_size);
 }
 
 
@@ -378,7 +380,7 @@ static inline void loop_handle_bio(struct lloop_device *lo, struct bio *bio)
        while (bio) {
                struct bio *tmp = bio->bi_next;
                bio->bi_next = NULL;
-               cfs_bio_endio(bio, bio->bi_size, ret);
+               cfs_bio_endio(bio, bio->bi_iter.bi_size, ret);
                bio = tmp;
        }
 }
index 46f1e619cbd838f29bd9891832db00b6610a44a7..77288796540b042bb067a64910d8d674b23f093b 100644 (file)
@@ -21,6 +21,8 @@ if STAGING_MEDIA
 # Please keep them in alphabetic order
 source "drivers/staging/media/as102/Kconfig"
 
+source "drivers/staging/media/bcm2048/Kconfig"
+
 source "drivers/staging/media/cxd2099/Kconfig"
 
 source "drivers/staging/media/davinci_vpfe/Kconfig"
@@ -33,6 +35,8 @@ source "drivers/staging/media/msi3101/Kconfig"
 
 source "drivers/staging/media/solo6x10/Kconfig"
 
+source "drivers/staging/media/omap4iss/Kconfig"
+
 # Keep LIRC at the end, as it has sub-menus
 source "drivers/staging/media/lirc/Kconfig"
 
index eb7f30b1ccd8863ddf0399c30e38df56e0e89a4f..0bd1a88a27faca6417a575626f9c679b93de7ced 100644 (file)
@@ -1,4 +1,5 @@
 obj-$(CONFIG_DVB_AS102)                += as102/
+obj-$(CONFIG_I2C_BCM2048)      += bcm2048/
 obj-$(CONFIG_DVB_CXD2099)      += cxd2099/
 obj-$(CONFIG_LIRC_STAGING)     += lirc/
 obj-$(CONFIG_SOLO6X10)         += solo6x10/
@@ -6,3 +7,4 @@ obj-$(CONFIG_VIDEO_DT3155)      += dt3155v4l/
 obj-$(CONFIG_VIDEO_GO7007)     += go7007/
 obj-$(CONFIG_USB_MSI3101)      += msi3101/
 obj-$(CONFIG_VIDEO_DM365_VPFE) += davinci_vpfe/
+obj-$(CONFIG_VIDEO_OMAP4)      += omap4iss/
diff --git a/drivers/staging/media/bcm2048/Kconfig b/drivers/staging/media/bcm2048/Kconfig
new file mode 100644 (file)
index 0000000..a9fc6e1
--- /dev/null
@@ -0,0 +1,13 @@
+#
+# Multimedia Video device configuration
+#
+
+config I2C_BCM2048
+       tristate "Broadcom BCM2048 FM Radio Receiver support"
+       depends on I2C && VIDEO_V4L2 && RADIO_ADAPTERS
+       ---help---
+         Say Y here if you want support to BCM2048 FM Radio Receiver.
+         This device driver supports only i2c bus.
+
+         To compile this driver as a module, choose M here: the
+         module will be called radio-bcm2048.
diff --git a/drivers/staging/media/bcm2048/Makefile b/drivers/staging/media/bcm2048/Makefile
new file mode 100644 (file)
index 0000000..b4f5663
--- /dev/null
@@ -0,0 +1 @@
+obj-$(CONFIG_I2C_BCM2048) += radio-bcm2048.o
diff --git a/drivers/staging/media/bcm2048/TODO b/drivers/staging/media/bcm2048/TODO
new file mode 100644 (file)
index 0000000..051f85d
--- /dev/null
@@ -0,0 +1,24 @@
+TODO:
+
+From the initial code review:
+
+The main thing you need to do is to implement all the controls using the
+control framework (see Documentation/video4linux/v4l2-controls.txt).
+Most drivers are by now converted to the control framework, so you will
+find many examples of how to do this in drivers/media/radio.
+
+The sysfs stuff should be replaced by controls as well. A lot of the RDS
+support is now available as controls (although there may well be some
+missing features, but that is easy enough to add). Since the RDS data is
+actually read() from the device I am not sure whether the RDS
+properties/controls should be there at all.
+
+Correct Coding Style, as this driver also violates several Style
+rules, and do evil tricks, like returning from a function inside a
+macro.
+
+Finally this driver should probably be split up into two parts: one
+v4l2_subdev-based core driver and one platform driver. See e.g.
+radio-si4713/si4713-i2c.c as a good example. But I would wait with that
+until the rest of the driver is cleaned up. Then I have a better idea of
+whether this is necessary or not.
diff --git a/drivers/staging/media/bcm2048/radio-bcm2048.c b/drivers/staging/media/bcm2048/radio-bcm2048.c
new file mode 100644 (file)
index 0000000..494ec39
--- /dev/null
@@ -0,0 +1,2745 @@
+/*
+ * drivers/staging/media/radio-bcm2048.c
+ *
+ * Driver for I2C Broadcom BCM2048 FM Radio Receiver:
+ *
+ * Copyright (C) Nokia Corporation
+ * Contact: Eero Nurkkala <ext-eero.nurkkala@nokia.com>
+ *
+ * Copyright (C) Nils Faerber <nils.faerber@kernelconcepts.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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
+ */
+
+/*
+ * History:
+ *             Eero Nurkkala <ext-eero.nurkkala@nokia.com>
+ *             Version 0.0.1
+ *             - Initial implementation
+ * 2010-02-21  Nils Faerber <nils.faerber@kernelconcepts.de>
+ *             Version 0.0.2
+ *             - Add support for interrupt driven rds data reading
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/version.h>
+#include <linux/interrupt.h>
+#include <linux/sysfs.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include "radio-bcm2048.h"
+
+/* driver definitions */
+#define BCM2048_DRIVER_AUTHOR  "Eero Nurkkala <ext-eero.nurkkala@nokia.com>"
+#define BCM2048_DRIVER_NAME    BCM2048_NAME
+#define BCM2048_DRIVER_VERSION KERNEL_VERSION(0, 0, 1)
+#define BCM2048_DRIVER_CARD    "Broadcom bcm2048 FM Radio Receiver"
+#define BCM2048_DRIVER_DESC    "I2C driver for BCM2048 FM Radio Receiver"
+
+/* I2C Control Registers */
+#define BCM2048_I2C_FM_RDS_SYSTEM      0x00
+#define BCM2048_I2C_FM_CTRL            0x01
+#define BCM2048_I2C_RDS_CTRL0          0x02
+#define BCM2048_I2C_RDS_CTRL1          0x03
+#define BCM2048_I2C_FM_AUDIO_PAUSE     0x04
+#define BCM2048_I2C_FM_AUDIO_CTRL0     0x05
+#define BCM2048_I2C_FM_AUDIO_CTRL1     0x06
+#define BCM2048_I2C_FM_SEARCH_CTRL0    0x07
+#define BCM2048_I2C_FM_SEARCH_CTRL1    0x08
+#define BCM2048_I2C_FM_SEARCH_TUNE_MODE        0x09
+#define BCM2048_I2C_FM_FREQ0           0x0a
+#define BCM2048_I2C_FM_FREQ1           0x0b
+#define BCM2048_I2C_FM_AF_FREQ0                0x0c
+#define BCM2048_I2C_FM_AF_FREQ1                0x0d
+#define BCM2048_I2C_FM_CARRIER         0x0e
+#define BCM2048_I2C_FM_RSSI            0x0f
+#define BCM2048_I2C_FM_RDS_MASK0       0x10
+#define BCM2048_I2C_FM_RDS_MASK1       0x11
+#define BCM2048_I2C_FM_RDS_FLAG0       0x12
+#define BCM2048_I2C_FM_RDS_FLAG1       0x13
+#define BCM2048_I2C_RDS_WLINE          0x14
+#define BCM2048_I2C_RDS_BLKB_MATCH0    0x16
+#define BCM2048_I2C_RDS_BLKB_MATCH1    0x17
+#define BCM2048_I2C_RDS_BLKB_MASK0     0x18
+#define BCM2048_I2C_RDS_BLKB_MASK1     0x19
+#define BCM2048_I2C_RDS_PI_MATCH0      0x1a
+#define BCM2048_I2C_RDS_PI_MATCH1      0x1b
+#define BCM2048_I2C_RDS_PI_MASK0       0x1c
+#define BCM2048_I2C_RDS_PI_MASK1       0x1d
+#define BCM2048_I2C_SPARE1             0x20
+#define BCM2048_I2C_SPARE2             0x21
+#define BCM2048_I2C_FM_RDS_REV         0x28
+#define BCM2048_I2C_SLAVE_CONFIGURATION        0x29
+#define BCM2048_I2C_RDS_DATA           0x80
+#define BCM2048_I2C_FM_BEST_TUNE_MODE  0x90
+
+/* BCM2048_I2C_FM_RDS_SYSTEM */
+#define BCM2048_FM_ON                  0x01
+#define BCM2048_RDS_ON                 0x02
+
+/* BCM2048_I2C_FM_CTRL */
+#define BCM2048_BAND_SELECT                    0x01
+#define BCM2048_STEREO_MONO_AUTO_SELECT                0x02
+#define BCM2048_STEREO_MONO_MANUAL_SELECT      0x04
+#define BCM2048_STEREO_MONO_BLEND_SWITCH       0x08
+#define BCM2048_HI_LO_INJECTION                        0x10
+
+/* BCM2048_I2C_RDS_CTRL0 */
+#define BCM2048_RBDS_RDS_SELECT                0x01
+#define BCM2048_FLUSH_FIFO             0x02
+
+/* BCM2048_I2C_FM_AUDIO_PAUSE */
+#define BCM2048_AUDIO_PAUSE_RSSI_TRESH 0x0f
+#define BCM2048_AUDIO_PAUSE_DURATION   0xf0
+
+/* BCM2048_I2C_FM_AUDIO_CTRL0 */
+#define BCM2048_RF_MUTE                        0x01
+#define BCM2048_MANUAL_MUTE            0x02
+#define BCM2048_DAC_OUTPUT_LEFT                0x04
+#define BCM2048_DAC_OUTPUT_RIGHT       0x08
+#define BCM2048_AUDIO_ROUTE_DAC                0x10
+#define BCM2048_AUDIO_ROUTE_I2S                0x20
+#define BCM2048_DE_EMPHASIS_SELECT     0x40
+#define BCM2048_AUDIO_BANDWIDTH_SELECT 0x80
+
+/* BCM2048_I2C_FM_SEARCH_CTRL0 */
+#define BCM2048_SEARCH_RSSI_THRESHOLD  0x7f
+#define BCM2048_SEARCH_DIRECTION       0x80
+
+/* BCM2048_I2C_FM_SEARCH_TUNE_MODE */
+#define BCM2048_FM_AUTO_SEARCH         0x03
+
+/* BCM2048_I2C_FM_RSSI */
+#define BCM2048_RSSI_VALUE             0xff
+
+/* BCM2048_I2C_FM_RDS_MASK0 */
+/* BCM2048_I2C_FM_RDS_MASK1 */
+#define BCM2048_FM_FLAG_SEARCH_TUNE_FINISHED   0x01
+#define BCM2048_FM_FLAG_SEARCH_TUNE_FAIL       0x02
+#define BCM2048_FM_FLAG_RSSI_LOW               0x04
+#define BCM2048_FM_FLAG_CARRIER_ERROR_HIGH     0x08
+#define BCM2048_FM_FLAG_AUDIO_PAUSE_INDICATION 0x10
+#define BCM2048_FLAG_STEREO_DETECTED           0x20
+#define BCM2048_FLAG_STEREO_ACTIVE             0x40
+
+/* BCM2048_I2C_RDS_DATA */
+#define BCM2048_SLAVE_ADDRESS                  0x3f
+#define BCM2048_SLAVE_ENABLE                   0x80
+
+/* BCM2048_I2C_FM_BEST_TUNE_MODE */
+#define BCM2048_BEST_TUNE_MODE                 0x80
+
+#define BCM2048_FM_FLAG_SEARCH_TUNE_FINISHED   0x01
+#define BCM2048_FM_FLAG_SEARCH_TUNE_FAIL       0x02
+#define BCM2048_FM_FLAG_RSSI_LOW               0x04
+#define BCM2048_FM_FLAG_CARRIER_ERROR_HIGH     0x08
+#define BCM2048_FM_FLAG_AUDIO_PAUSE_INDICATION 0x10
+#define BCM2048_FLAG_STEREO_DETECTED           0x20
+#define BCM2048_FLAG_STEREO_ACTIVE             0x40
+
+#define BCM2048_RDS_FLAG_FIFO_WLINE            0x02
+#define BCM2048_RDS_FLAG_B_BLOCK_MATCH         0x08
+#define BCM2048_RDS_FLAG_SYNC_LOST             0x10
+#define BCM2048_RDS_FLAG_PI_MATCH              0x20
+
+#define BCM2048_RDS_MARK_END_BYTE0             0x7C
+#define BCM2048_RDS_MARK_END_BYTEN             0xFF
+
+#define BCM2048_FM_FLAGS_ALL   (FM_FLAG_SEARCH_TUNE_FINISHED | \
+                                FM_FLAG_SEARCH_TUNE_FAIL | \
+                                FM_FLAG_RSSI_LOW | \
+                                FM_FLAG_CARRIER_ERROR_HIGH | \
+                                FM_FLAG_AUDIO_PAUSE_INDICATION | \
+                                FLAG_STEREO_DETECTED | FLAG_STEREO_ACTIVE)
+
+#define BCM2048_RDS_FLAGS_ALL  (RDS_FLAG_FIFO_WLINE | \
+                                RDS_FLAG_B_BLOCK_MATCH | \
+                                RDS_FLAG_SYNC_LOST | RDS_FLAG_PI_MATCH)
+
+#define BCM2048_DEFAULT_TIMEOUT                1500
+#define BCM2048_AUTO_SEARCH_TIMEOUT    3000
+
+
+#define BCM2048_FREQDEV_UNIT           10000
+#define BCM2048_FREQV4L2_MULTI         625
+#define dev_to_v4l2(f) ((f * BCM2048_FREQDEV_UNIT) / BCM2048_FREQV4L2_MULTI)
+#define v4l2_to_dev(f) ((f * BCM2048_FREQV4L2_MULTI) / BCM2048_FREQDEV_UNIT)
+
+#define msb(x)                  ((u8)((u16) x >> 8))
+#define lsb(x)                  ((u8)((u16) x &  0x00FF))
+#define compose_u16(msb, lsb)  (((u16)msb << 8) | lsb)
+
+#define BCM2048_DEFAULT_POWERING_DELAY 20
+#define BCM2048_DEFAULT_REGION         0x02
+#define BCM2048_DEFAULT_MUTE           0x01
+#define BCM2048_DEFAULT_RSSI_THRESHOLD 0x64
+#define BCM2048_DEFAULT_RDS_WLINE      0x7E
+
+#define BCM2048_FM_SEARCH_INACTIVE     0x00
+#define BCM2048_FM_PRE_SET_MODE                0x01
+#define BCM2048_FM_AUTO_SEARCH_MODE    0x02
+#define BCM2048_FM_AF_JUMP_MODE                0x03
+
+#define BCM2048_FREQUENCY_BASE         64000
+
+#define BCM2048_POWER_ON               0x01
+#define BCM2048_POWER_OFF              0x00
+
+#define BCM2048_ITEM_ENABLED           0x01
+#define BCM2048_SEARCH_DIRECTION_UP    0x01
+
+#define BCM2048_DE_EMPHASIS_75us       75
+#define BCM2048_DE_EMPHASIS_50us       50
+
+#define BCM2048_SCAN_FAIL              0x00
+#define BCM2048_SCAN_OK                        0x01
+
+#define BCM2048_FREQ_ERROR_FLOOR       -20
+#define BCM2048_FREQ_ERROR_ROOF                20
+
+/* -60 dB is reported as full signal strenght */
+#define BCM2048_RSSI_LEVEL_BASE                -60
+#define BCM2048_RSSI_LEVEL_ROOF                -100
+#define BCM2048_RSSI_LEVEL_ROOF_NEG    100
+#define BCM2048_SIGNAL_MULTIPLIER      (0xFFFF / \
+                                        (BCM2048_RSSI_LEVEL_ROOF_NEG + \
+                                         BCM2048_RSSI_LEVEL_BASE))
+
+#define BCM2048_RDS_FIFO_DUPLE_SIZE    0x03
+#define BCM2048_RDS_CRC_MASK           0x0F
+#define BCM2048_RDS_CRC_NONE           0x00
+#define BCM2048_RDS_CRC_MAX_2BITS      0x04
+#define BCM2048_RDS_CRC_LEAST_2BITS    0x08
+#define BCM2048_RDS_CRC_UNRECOVARABLE  0x0C
+
+#define BCM2048_RDS_BLOCK_MASK         0xF0
+#define BCM2048_RDS_BLOCK_A            0x00
+#define BCM2048_RDS_BLOCK_B            0x10
+#define BCM2048_RDS_BLOCK_C            0x20
+#define BCM2048_RDS_BLOCK_D            0x30
+#define BCM2048_RDS_BLOCK_C_SCORED     0x40
+#define BCM2048_RDS_BLOCK_E            0x60
+
+#define BCM2048_RDS_RT                 0x20
+#define BCM2048_RDS_PS                 0x00
+
+#define BCM2048_RDS_GROUP_AB_MASK      0x08
+#define BCM2048_RDS_GROUP_A            0x00
+#define BCM2048_RDS_GROUP_B            0x08
+
+#define BCM2048_RDS_RT_AB_MASK         0x10
+#define BCM2048_RDS_RT_A               0x00
+#define BCM2048_RDS_RT_B               0x10
+#define BCM2048_RDS_RT_INDEX           0x0F
+
+#define BCM2048_RDS_PS_INDEX           0x03
+
+struct rds_info {
+       u16 rds_pi;
+#define BCM2048_MAX_RDS_RT (64 + 1)
+       u8 rds_rt[BCM2048_MAX_RDS_RT];
+       u8 rds_rt_group_b;
+       u8 rds_rt_ab;
+#define BCM2048_MAX_RDS_PS (8 + 1)
+       u8 rds_ps[BCM2048_MAX_RDS_PS];
+       u8 rds_ps_group;
+       u8 rds_ps_group_cnt;
+#define BCM2048_MAX_RDS_RADIO_TEXT 255
+       u8 radio_text[BCM2048_MAX_RDS_RADIO_TEXT + 3];
+       u8 text_len;
+};
+
+struct region_info {
+       u32 bottom_frequency;
+       u32 top_frequency;
+       u8 deemphasis;
+       u8 channel_spacing;
+       u8 region;
+};
+
+struct bcm2048_device {
+       struct i2c_client *client;
+       struct video_device *videodev;
+       struct work_struct work;
+       struct completion compl;
+       struct mutex mutex;
+       struct bcm2048_platform_data *platform_data;
+       struct rds_info rds_info;
+       struct region_info region_info;
+       u16 frequency;
+       u8 cache_fm_rds_system;
+       u8 cache_fm_ctrl;
+       u8 cache_fm_audio_ctrl0;
+       u8 cache_fm_search_ctrl0;
+       u8 power_state;
+       u8 rds_state;
+       u8 fifo_size;
+       u8 scan_state;
+       u8 mute_state;
+
+       /* for rds data device read */
+       wait_queue_head_t read_queue;
+       unsigned int users;
+       unsigned char rds_data_available;
+       unsigned int rd_index;
+};
+
+static int radio_nr = -1;      /* radio device minor (-1 ==> auto assign) */
+module_param(radio_nr, int, 0);
+MODULE_PARM_DESC(radio_nr,
+                "Minor number for radio device (-1 ==> auto assign)");
+
+static struct region_info region_configs[] = {
+       /* USA */
+       {
+               .channel_spacing        = 20,
+               .bottom_frequency       = 87500,
+               .top_frequency          = 108000,
+               .deemphasis             = 75,
+               .region                 = 0,
+       },
+       /* Australia */
+       {
+               .channel_spacing        = 20,
+               .bottom_frequency       = 87500,
+               .top_frequency          = 108000,
+               .deemphasis             = 50,
+               .region                 = 1,
+       },
+       /* Europe */
+       {
+               .channel_spacing        = 10,
+               .bottom_frequency       = 87500,
+               .top_frequency          = 108000,
+               .deemphasis             = 50,
+               .region                 = 2,
+       },
+       /* Japan */
+       {
+               .channel_spacing        = 10,
+               .bottom_frequency       = 76000,
+               .top_frequency          = 90000,
+               .deemphasis             = 50,
+               .region                 = 3,
+       },
+       /* Japan wide band */
+       {
+               .channel_spacing        = 10,
+               .bottom_frequency       = 76000,
+               .top_frequency          = 108000,
+               .deemphasis             = 50,
+               .region                 = 4,
+       },
+};
+
+/*
+ *     I2C Interface read / write
+ */
+static int bcm2048_send_command(struct bcm2048_device *bdev, unsigned int reg,
+                                       unsigned int value)
+{
+       struct i2c_client *client = bdev->client;
+       u8 data[2];
+
+       if (!bdev->power_state) {
+               dev_err(&bdev->client->dev, "bcm2048: chip not powered!\n");
+               return -EIO;
+       }
+
+       data[0] = reg & 0xff;
+       data[1] = value & 0xff;
+
+       if (i2c_master_send(client, data, 2) == 2) {
+               return 0;
+       } else {
+               dev_err(&bdev->client->dev, "BCM I2C error!\n");
+               dev_err(&bdev->client->dev, "Is Bluetooth up and running?\n");
+               return -EIO;
+       }
+}
+
+static int bcm2048_recv_command(struct bcm2048_device *bdev, unsigned int reg,
+                       u8 *value)
+{
+       struct i2c_client *client = bdev->client;
+
+       if (!bdev->power_state) {
+               dev_err(&bdev->client->dev, "bcm2048: chip not powered!\n");
+               return -EIO;
+       }
+
+       value[0] = i2c_smbus_read_byte_data(client, reg & 0xff);
+
+       return 0;
+}
+
+static int bcm2048_recv_duples(struct bcm2048_device *bdev, unsigned int reg,
+                       u8 *value, u8 duples)
+{
+       struct i2c_client *client = bdev->client;
+       struct i2c_adapter *adap = client->adapter;
+       struct i2c_msg msg[2];
+       u8 buf;
+
+       if (!bdev->power_state) {
+               dev_err(&bdev->client->dev, "bcm2048: chip not powered!\n");
+               return -EIO;
+       }
+
+       buf = reg & 0xff;
+
+       msg[0].addr = client->addr;
+       msg[0].flags = client->flags & I2C_M_TEN;
+       msg[0].len = 1;
+       msg[0].buf = &buf;
+
+       msg[1].addr = client->addr;
+       msg[1].flags = client->flags & I2C_M_TEN;
+       msg[1].flags |= I2C_M_RD;
+       msg[1].len = duples;
+       msg[1].buf = value;
+
+       return i2c_transfer(adap, msg, 2);
+}
+
+/*
+ *     BCM2048 - I2C register programming helpers
+ */
+static int bcm2048_set_power_state(struct bcm2048_device *bdev, u8 power)
+{
+       int err = 0;
+
+       mutex_lock(&bdev->mutex);
+
+       if (power) {
+               bdev->power_state = BCM2048_POWER_ON;
+               bdev->cache_fm_rds_system |= BCM2048_FM_ON;
+       } else {
+               bdev->cache_fm_rds_system &= ~BCM2048_FM_ON;
+       }
+
+       /*
+        * Warning! FM cannot be turned off because then
+        * the I2C communications get ruined!
+        * Comment off the "if (power)" when the chip works!
+        */
+       if (power)
+               err = bcm2048_send_command(bdev, BCM2048_I2C_FM_RDS_SYSTEM,
+                                       bdev->cache_fm_rds_system);
+       msleep(BCM2048_DEFAULT_POWERING_DELAY);
+
+       if (!power)
+               bdev->power_state = BCM2048_POWER_OFF;
+
+       mutex_unlock(&bdev->mutex);
+       return err;
+}
+
+static int bcm2048_get_power_state(struct bcm2048_device *bdev)
+{
+       int err;
+       u8 value;
+
+       mutex_lock(&bdev->mutex);
+
+       err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_RDS_SYSTEM, &value);
+
+       mutex_unlock(&bdev->mutex);
+
+       if (!err && (value & BCM2048_FM_ON))
+               return BCM2048_POWER_ON;
+
+       return err;
+}
+
+static int bcm2048_set_rds_no_lock(struct bcm2048_device *bdev, u8 rds_on)
+{
+       int err;
+       u8 flags;
+
+       bdev->cache_fm_rds_system &= ~BCM2048_RDS_ON;
+
+       if (rds_on) {
+               bdev->cache_fm_rds_system |= BCM2048_RDS_ON;
+               bdev->rds_state = BCM2048_RDS_ON;
+               flags = BCM2048_RDS_FLAG_FIFO_WLINE;
+               err = bcm2048_send_command(bdev, BCM2048_I2C_FM_RDS_MASK1,
+                                               flags);
+       } else {
+               flags = 0;
+               bdev->rds_state = 0;
+               err = bcm2048_send_command(bdev, BCM2048_I2C_FM_RDS_MASK1,
+                                               flags);
+               memset(&bdev->rds_info, 0, sizeof(bdev->rds_info));
+       }
+
+       err = bcm2048_send_command(bdev, BCM2048_I2C_FM_RDS_SYSTEM,
+                                       bdev->cache_fm_rds_system);
+
+       return err;
+}
+
+static int bcm2048_get_rds_no_lock(struct bcm2048_device *bdev)
+{
+       int err;
+       u8 value;
+
+       err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_RDS_SYSTEM, &value);
+
+       if (!err && (value & BCM2048_RDS_ON))
+               return BCM2048_ITEM_ENABLED;
+
+       return err;
+}
+
+static int bcm2048_set_rds(struct bcm2048_device *bdev, u8 rds_on)
+{
+       int err;
+
+       mutex_lock(&bdev->mutex);
+
+       err = bcm2048_set_rds_no_lock(bdev, rds_on);
+
+       mutex_unlock(&bdev->mutex);
+       return err;
+}
+
+static int bcm2048_get_rds(struct bcm2048_device *bdev)
+{
+       int err;
+
+       mutex_lock(&bdev->mutex);
+
+       err = bcm2048_get_rds_no_lock(bdev);
+
+       mutex_unlock(&bdev->mutex);
+       return err;
+}
+
+static int bcm2048_get_rds_pi(struct bcm2048_device *bdev)
+{
+       return bdev->rds_info.rds_pi;
+}
+
+static int bcm2048_set_fm_automatic_stereo_mono(struct bcm2048_device *bdev,
+                                               u8 enabled)
+{
+       int err;
+
+       mutex_lock(&bdev->mutex);
+
+       bdev->cache_fm_ctrl &= ~BCM2048_STEREO_MONO_AUTO_SELECT;
+
+       if (enabled)
+               bdev->cache_fm_ctrl |= BCM2048_STEREO_MONO_AUTO_SELECT;
+
+       err = bcm2048_send_command(bdev, BCM2048_I2C_FM_CTRL,
+                                       bdev->cache_fm_ctrl);
+
+       mutex_unlock(&bdev->mutex);
+       return err;
+}
+
+static int bcm2048_set_fm_hi_lo_injection(struct bcm2048_device *bdev,
+                                               u8 hi_lo)
+{
+       int err;
+
+       mutex_lock(&bdev->mutex);
+
+       bdev->cache_fm_ctrl &= ~BCM2048_HI_LO_INJECTION;
+
+       if (hi_lo)
+               bdev->cache_fm_ctrl |= BCM2048_HI_LO_INJECTION;
+
+       err = bcm2048_send_command(bdev, BCM2048_I2C_FM_CTRL,
+                                       bdev->cache_fm_ctrl);
+
+       mutex_unlock(&bdev->mutex);
+       return err;
+}
+
+static int bcm2048_get_fm_hi_lo_injection(struct bcm2048_device *bdev)
+{
+       int err;
+       u8 value;
+
+       mutex_lock(&bdev->mutex);
+
+       err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_CTRL, &value);
+
+       mutex_unlock(&bdev->mutex);
+
+       if (!err && (value & BCM2048_HI_LO_INJECTION))
+               return BCM2048_ITEM_ENABLED;
+
+       return err;
+}
+
+static int bcm2048_set_fm_frequency(struct bcm2048_device *bdev, u32 frequency)
+{
+       int err;
+
+       if (frequency < bdev->region_info.bottom_frequency ||
+               frequency > bdev->region_info.top_frequency)
+               return -EDOM;
+
+       frequency -= BCM2048_FREQUENCY_BASE;
+
+       mutex_lock(&bdev->mutex);
+
+       err = bcm2048_send_command(bdev, BCM2048_I2C_FM_FREQ0, lsb(frequency));
+       err |= bcm2048_send_command(bdev, BCM2048_I2C_FM_FREQ1,
+                                       msb(frequency));
+
+       if (!err)
+               bdev->frequency = frequency;
+
+       mutex_unlock(&bdev->mutex);
+       return err;
+}
+
+static int bcm2048_get_fm_frequency(struct bcm2048_device *bdev)
+{
+       int err;
+       u8 lsb, msb;
+
+       mutex_lock(&bdev->mutex);
+
+       err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_FREQ0, &lsb);
+       err |= bcm2048_recv_command(bdev, BCM2048_I2C_FM_FREQ1, &msb);
+
+       mutex_unlock(&bdev->mutex);
+
+       if (err)
+               return err;
+
+       err = compose_u16(msb, lsb);
+       err += BCM2048_FREQUENCY_BASE;
+
+       return err;
+}
+
+static int bcm2048_set_fm_af_frequency(struct bcm2048_device *bdev,
+                                               u32 frequency)
+{
+       int err;
+
+       if (frequency < bdev->region_info.bottom_frequency ||
+               frequency > bdev->region_info.top_frequency)
+               return -EDOM;
+
+       frequency -= BCM2048_FREQUENCY_BASE;
+
+       mutex_lock(&bdev->mutex);
+
+       err = bcm2048_send_command(bdev, BCM2048_I2C_FM_AF_FREQ0,
+                                       lsb(frequency));
+       err |= bcm2048_send_command(bdev, BCM2048_I2C_FM_AF_FREQ1,
+                                       msb(frequency));
+       if (!err)
+               bdev->frequency = frequency;
+
+       mutex_unlock(&bdev->mutex);
+       return err;
+}
+
+static int bcm2048_get_fm_af_frequency(struct bcm2048_device *bdev)
+{
+       int err;
+       u8 lsb, msb;
+
+       mutex_lock(&bdev->mutex);
+
+       err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_AF_FREQ0, &lsb);
+       err |= bcm2048_recv_command(bdev, BCM2048_I2C_FM_AF_FREQ1, &msb);
+
+       mutex_unlock(&bdev->mutex);
+
+       if (err)
+               return err;
+
+       err = compose_u16(msb, lsb);
+       err += BCM2048_FREQUENCY_BASE;
+
+       return err;
+}
+
+static int bcm2048_set_fm_deemphasis(struct bcm2048_device *bdev, int d)
+{
+       int err;
+       u8 deemphasis;
+
+       if (d == BCM2048_DE_EMPHASIS_75us)
+               deemphasis = BCM2048_DE_EMPHASIS_SELECT;
+       else
+               deemphasis = 0;
+
+       mutex_lock(&bdev->mutex);
+
+       bdev->cache_fm_audio_ctrl0 &= ~BCM2048_DE_EMPHASIS_SELECT;
+       bdev->cache_fm_audio_ctrl0 |= deemphasis;
+
+       err = bcm2048_send_command(bdev, BCM2048_I2C_FM_AUDIO_CTRL0,
+               bdev->cache_fm_audio_ctrl0);
+
+       if (!err)
+               bdev->region_info.deemphasis = d;
+
+       mutex_unlock(&bdev->mutex);
+
+       return err;
+}
+
+static int bcm2048_get_fm_deemphasis(struct bcm2048_device *bdev)
+{
+       int err;
+       u8 value;
+
+       mutex_lock(&bdev->mutex);
+
+       err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_AUDIO_CTRL0, &value);
+
+       mutex_unlock(&bdev->mutex);
+
+       if (!err) {
+               if (value & BCM2048_DE_EMPHASIS_SELECT)
+                       return BCM2048_DE_EMPHASIS_75us;
+               else
+                       return BCM2048_DE_EMPHASIS_50us;
+       }
+
+       return err;
+}
+
+static int bcm2048_set_region(struct bcm2048_device *bdev, u8 region)
+{
+       int err;
+       u32 new_frequency = 0;
+
+       if (region > ARRAY_SIZE(region_configs))
+               return -EINVAL;
+
+       mutex_lock(&bdev->mutex);
+       memcpy(&bdev->region_info, &region_configs[region],
+               sizeof(struct region_info));
+       mutex_unlock(&bdev->mutex);
+
+       if (bdev->frequency < region_configs[region].bottom_frequency ||
+               bdev->frequency > region_configs[region].top_frequency)
+               new_frequency = region_configs[region].bottom_frequency;
+
+       if (new_frequency > 0) {
+               err = bcm2048_set_fm_frequency(bdev, new_frequency);
+
+               if (err)
+                       goto done;
+       }
+
+       err = bcm2048_set_fm_deemphasis(bdev,
+                       region_configs[region].deemphasis);
+
+done:
+       return err;
+}
+
+static int bcm2048_get_region(struct bcm2048_device *bdev)
+{
+       int err;
+
+       mutex_lock(&bdev->mutex);
+       err = bdev->region_info.region;
+       mutex_unlock(&bdev->mutex);
+
+       return err;
+}
+
+static int bcm2048_set_mute(struct bcm2048_device *bdev, u16 mute)
+{
+       int err;
+
+       mutex_lock(&bdev->mutex);
+
+       bdev->cache_fm_audio_ctrl0 &= ~(BCM2048_RF_MUTE | BCM2048_MANUAL_MUTE);
+
+       if (mute)
+               bdev->cache_fm_audio_ctrl0 |= (BCM2048_RF_MUTE |
+                                               BCM2048_MANUAL_MUTE);
+
+       err = bcm2048_send_command(bdev, BCM2048_I2C_FM_AUDIO_CTRL0,
+                                       bdev->cache_fm_audio_ctrl0);
+
+       if (!err)
+               bdev->mute_state = mute;
+
+       mutex_unlock(&bdev->mutex);
+       return err;
+}
+
+static int bcm2048_get_mute(struct bcm2048_device *bdev)
+{
+       int err;
+       u8 value;
+
+       mutex_lock(&bdev->mutex);
+
+       if (bdev->power_state) {
+               err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_AUDIO_CTRL0,
+                                               &value);
+               if (!err)
+                       err = value & (BCM2048_RF_MUTE | BCM2048_MANUAL_MUTE);
+       } else {
+               err = bdev->mute_state;
+       }
+
+       mutex_unlock(&bdev->mutex);
+       return err;
+}
+
+static int bcm2048_set_audio_route(struct bcm2048_device *bdev, u8 route)
+{
+       int err;
+
+       mutex_lock(&bdev->mutex);
+
+       route &= (BCM2048_AUDIO_ROUTE_DAC | BCM2048_AUDIO_ROUTE_I2S);
+       bdev->cache_fm_audio_ctrl0 &= ~(BCM2048_AUDIO_ROUTE_DAC |
+               BCM2048_AUDIO_ROUTE_I2S);
+       bdev->cache_fm_audio_ctrl0 |= route;
+
+       err = bcm2048_send_command(bdev, BCM2048_I2C_FM_AUDIO_CTRL0,
+                                       bdev->cache_fm_audio_ctrl0);
+
+       mutex_unlock(&bdev->mutex);
+       return err;
+}
+
+static int bcm2048_get_audio_route(struct bcm2048_device *bdev)
+{
+       int err;
+       u8 value;
+
+       mutex_lock(&bdev->mutex);
+
+       err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_AUDIO_CTRL0, &value);
+
+       mutex_unlock(&bdev->mutex);
+
+       if (!err)
+               return value & (BCM2048_AUDIO_ROUTE_DAC |
+                       BCM2048_AUDIO_ROUTE_I2S);
+
+       return err;
+}
+
+static int bcm2048_set_dac_output(struct bcm2048_device *bdev, u8 channels)
+{
+       int err;
+
+       mutex_lock(&bdev->mutex);
+
+       bdev->cache_fm_audio_ctrl0 &= ~(BCM2048_DAC_OUTPUT_LEFT |
+                                       BCM2048_DAC_OUTPUT_RIGHT);
+       bdev->cache_fm_audio_ctrl0 |= channels;
+
+       err = bcm2048_send_command(bdev, BCM2048_I2C_FM_AUDIO_CTRL0,
+                                       bdev->cache_fm_audio_ctrl0);
+
+       mutex_unlock(&bdev->mutex);
+       return err;
+}
+
+static int bcm2048_get_dac_output(struct bcm2048_device *bdev)
+{
+       int err;
+       u8 value;
+
+       mutex_lock(&bdev->mutex);
+
+       err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_AUDIO_CTRL0, &value);
+
+       mutex_unlock(&bdev->mutex);
+
+       if (!err)
+               return value & (BCM2048_DAC_OUTPUT_LEFT |
+                       BCM2048_DAC_OUTPUT_RIGHT);
+
+       return err;
+}
+
+static int bcm2048_set_fm_search_rssi_threshold(struct bcm2048_device *bdev,
+                                                       u8 threshold)
+{
+       int err;
+
+       mutex_lock(&bdev->mutex);
+
+       threshold &= BCM2048_SEARCH_RSSI_THRESHOLD;
+       bdev->cache_fm_search_ctrl0 &= ~BCM2048_SEARCH_RSSI_THRESHOLD;
+       bdev->cache_fm_search_ctrl0 |= threshold;
+
+       err = bcm2048_send_command(bdev, BCM2048_I2C_FM_SEARCH_CTRL0,
+                                       bdev->cache_fm_search_ctrl0);
+
+       mutex_unlock(&bdev->mutex);
+       return err;
+}
+
+static int bcm2048_get_fm_search_rssi_threshold(struct bcm2048_device *bdev)
+{
+       int err;
+       u8 value;
+
+       mutex_lock(&bdev->mutex);
+
+       err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_SEARCH_CTRL0, &value);
+
+       mutex_unlock(&bdev->mutex);
+
+       if (!err)
+               return value & BCM2048_SEARCH_RSSI_THRESHOLD;
+
+       return err;
+}
+
+static int bcm2048_set_fm_search_mode_direction(struct bcm2048_device *bdev,
+                                               u8 direction)
+{
+       int err;
+
+       mutex_lock(&bdev->mutex);
+
+       bdev->cache_fm_search_ctrl0 &= ~BCM2048_SEARCH_DIRECTION;
+
+       if (direction)
+               bdev->cache_fm_search_ctrl0 |= BCM2048_SEARCH_DIRECTION;
+
+       err = bcm2048_send_command(bdev, BCM2048_I2C_FM_SEARCH_CTRL0,
+                                       bdev->cache_fm_search_ctrl0);
+
+       mutex_unlock(&bdev->mutex);
+       return err;
+}
+
+static int bcm2048_get_fm_search_mode_direction(struct bcm2048_device *bdev)
+{
+       int err;
+       u8 value;
+
+       mutex_lock(&bdev->mutex);
+
+       err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_SEARCH_CTRL0, &value);
+
+       mutex_unlock(&bdev->mutex);
+
+       if (!err && (value & BCM2048_SEARCH_DIRECTION))
+               return BCM2048_SEARCH_DIRECTION_UP;
+
+       return err;
+}
+
+static int bcm2048_set_fm_search_tune_mode(struct bcm2048_device *bdev,
+                                               u8 mode)
+{
+       int err, timeout, restart_rds = 0;
+       u8 value, flags;
+
+       value = mode & BCM2048_FM_AUTO_SEARCH;
+
+       flags = BCM2048_FM_FLAG_SEARCH_TUNE_FINISHED |
+               BCM2048_FM_FLAG_SEARCH_TUNE_FAIL;
+
+       mutex_lock(&bdev->mutex);
+
+       /*
+        * If RDS is enabled, and frequency is changed, RDS quits working.
+        * Thus, always restart RDS if it's enabled. Moreover, RDS must
+        * not be enabled while changing the frequency because it can
+        * provide a race to the mutex from the workqueue handler if RDS
+        * IRQ occurs while waiting for frequency changed IRQ.
+        */
+       if (bcm2048_get_rds_no_lock(bdev)) {
+               err = bcm2048_set_rds_no_lock(bdev, 0);
+               if (err)
+                       goto unlock;
+               restart_rds = 1;
+       }
+
+       err = bcm2048_send_command(bdev, BCM2048_I2C_FM_RDS_MASK0, flags);
+
+       if (err)
+               goto unlock;
+
+       bcm2048_send_command(bdev, BCM2048_I2C_FM_SEARCH_TUNE_MODE, value);
+
+       if (mode != BCM2048_FM_AUTO_SEARCH_MODE)
+               timeout = BCM2048_DEFAULT_TIMEOUT;
+       else
+               timeout = BCM2048_AUTO_SEARCH_TIMEOUT;
+
+       if (!wait_for_completion_timeout(&bdev->compl,
+                       msecs_to_jiffies(timeout)))
+                       dev_err(&bdev->client->dev, "IRQ timeout.\n");
+
+       if (value)
+               if (!bdev->scan_state)
+                       err = -EIO;
+
+unlock:
+       if (restart_rds)
+               err |= bcm2048_set_rds_no_lock(bdev, 1);
+
+       mutex_unlock(&bdev->mutex);
+
+       return err;
+}
+
+static int bcm2048_get_fm_search_tune_mode(struct bcm2048_device *bdev)
+{
+       int err;
+       u8 value;
+
+       mutex_lock(&bdev->mutex);
+
+       err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_SEARCH_TUNE_MODE,
+                                       &value);
+
+       mutex_unlock(&bdev->mutex);
+
+       if (!err)
+               return value & BCM2048_FM_AUTO_SEARCH;
+
+       return err;
+}
+
+static int bcm2048_set_rds_b_block_mask(struct bcm2048_device *bdev, u16 mask)
+{
+       int err;
+
+       mutex_lock(&bdev->mutex);
+
+       err = bcm2048_send_command(bdev,
+                       BCM2048_I2C_RDS_BLKB_MASK0, lsb(mask));
+       err |= bcm2048_send_command(bdev,
+                       BCM2048_I2C_RDS_BLKB_MASK1, msb(mask));
+
+       mutex_unlock(&bdev->mutex);
+       return err;
+}
+
+static int bcm2048_get_rds_b_block_mask(struct bcm2048_device *bdev)
+{
+       int err;
+       u8 lsb, msb;
+
+       mutex_lock(&bdev->mutex);
+
+       err = bcm2048_recv_command(bdev,
+                       BCM2048_I2C_RDS_BLKB_MASK0, &lsb);
+       err |= bcm2048_recv_command(bdev,
+                       BCM2048_I2C_RDS_BLKB_MASK1, &msb);
+
+       mutex_unlock(&bdev->mutex);
+
+       if (!err)
+               return compose_u16(msb, lsb);
+
+       return err;
+}
+
+static int bcm2048_set_rds_b_block_match(struct bcm2048_device *bdev,
+                                               u16 match)
+{
+       int err;
+
+       mutex_lock(&bdev->mutex);
+
+       err = bcm2048_send_command(bdev,
+                       BCM2048_I2C_RDS_BLKB_MATCH0, lsb(match));
+       err |= bcm2048_send_command(bdev,
+                       BCM2048_I2C_RDS_BLKB_MATCH1, msb(match));
+
+       mutex_unlock(&bdev->mutex);
+       return err;
+}
+
+static int bcm2048_get_rds_b_block_match(struct bcm2048_device *bdev)
+{
+       int err;
+       u8 lsb, msb;
+
+       mutex_lock(&bdev->mutex);
+
+       err = bcm2048_recv_command(bdev,
+                       BCM2048_I2C_RDS_BLKB_MATCH0, &lsb);
+       err |= bcm2048_recv_command(bdev,
+                       BCM2048_I2C_RDS_BLKB_MATCH1, &msb);
+
+       mutex_unlock(&bdev->mutex);
+
+       if (!err)
+               return compose_u16(msb, lsb);
+
+       return err;
+}
+
+static int bcm2048_set_rds_pi_mask(struct bcm2048_device *bdev, u16 mask)
+{
+       int err;
+
+       mutex_lock(&bdev->mutex);
+
+       err = bcm2048_send_command(bdev,
+                       BCM2048_I2C_RDS_PI_MASK0, lsb(mask));
+       err |= bcm2048_send_command(bdev,
+                       BCM2048_I2C_RDS_PI_MASK1, msb(mask));
+
+       mutex_unlock(&bdev->mutex);
+       return err;
+}
+
+static int bcm2048_get_rds_pi_mask(struct bcm2048_device *bdev)
+{
+       int err;
+       u8 lsb, msb;
+
+       mutex_lock(&bdev->mutex);
+
+       err = bcm2048_recv_command(bdev,
+                       BCM2048_I2C_RDS_PI_MASK0, &lsb);
+       err |= bcm2048_recv_command(bdev,
+                       BCM2048_I2C_RDS_PI_MASK1, &msb);
+
+       mutex_unlock(&bdev->mutex);
+
+       if (!err)
+               return compose_u16(msb, lsb);
+
+       return err;
+}
+
+static int bcm2048_set_rds_pi_match(struct bcm2048_device *bdev, u16 match)
+{
+       int err;
+
+       mutex_lock(&bdev->mutex);
+
+       err = bcm2048_send_command(bdev,
+                       BCM2048_I2C_RDS_PI_MATCH0, lsb(match));
+       err |= bcm2048_send_command(bdev,
+                       BCM2048_I2C_RDS_PI_MATCH1, msb(match));
+
+       mutex_unlock(&bdev->mutex);
+       return err;
+}
+
+static int bcm2048_get_rds_pi_match(struct bcm2048_device *bdev)
+{
+       int err;
+       u8 lsb, msb;
+
+       mutex_lock(&bdev->mutex);
+
+       err = bcm2048_recv_command(bdev,
+                       BCM2048_I2C_RDS_PI_MATCH0, &lsb);
+       err |= bcm2048_recv_command(bdev,
+                       BCM2048_I2C_RDS_PI_MATCH1, &msb);
+
+       mutex_unlock(&bdev->mutex);
+
+       if (!err)
+               return compose_u16(msb, lsb);
+
+       return err;
+}
+
+static int bcm2048_set_fm_rds_mask(struct bcm2048_device *bdev, u16 mask)
+{
+       int err;
+
+       mutex_lock(&bdev->mutex);
+
+       err = bcm2048_send_command(bdev,
+                       BCM2048_I2C_FM_RDS_MASK0, lsb(mask));
+       err |= bcm2048_send_command(bdev,
+                       BCM2048_I2C_FM_RDS_MASK1, msb(mask));
+
+       mutex_unlock(&bdev->mutex);
+       return err;
+}
+
+static int bcm2048_get_fm_rds_mask(struct bcm2048_device *bdev)
+{
+       int err;
+       u8 value0, value1;
+
+       mutex_lock(&bdev->mutex);
+
+       err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_RDS_MASK0, &value0);
+       err |= bcm2048_recv_command(bdev, BCM2048_I2C_FM_RDS_MASK1, &value1);
+
+       mutex_unlock(&bdev->mutex);
+
+       if (!err)
+               return compose_u16(value1, value0);
+
+       return err;
+}
+
+static int bcm2048_get_fm_rds_flags(struct bcm2048_device *bdev)
+{
+       int err;
+       u8 value0, value1;
+
+       mutex_lock(&bdev->mutex);
+
+       err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_RDS_FLAG0, &value0);
+       err |= bcm2048_recv_command(bdev, BCM2048_I2C_FM_RDS_FLAG1, &value1);
+
+       mutex_unlock(&bdev->mutex);
+
+       if (!err)
+               return compose_u16(value1, value0);
+
+       return err;
+}
+
+static int bcm2048_get_region_bottom_frequency(struct bcm2048_device *bdev)
+{
+       return bdev->region_info.bottom_frequency;
+}
+
+static int bcm2048_get_region_top_frequency(struct bcm2048_device *bdev)
+{
+       return bdev->region_info.top_frequency;
+}
+
+static int bcm2048_set_fm_best_tune_mode(struct bcm2048_device *bdev, u8 mode)
+{
+       int err;
+       u8 value;
+
+       mutex_lock(&bdev->mutex);
+
+       /* Perform read as the manual indicates */
+       err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_BEST_TUNE_MODE,
+                                       &value);
+       value &= ~BCM2048_BEST_TUNE_MODE;
+
+       if (mode)
+               value |= BCM2048_BEST_TUNE_MODE;
+       err |= bcm2048_send_command(bdev, BCM2048_I2C_FM_BEST_TUNE_MODE,
+                                       value);
+
+       mutex_unlock(&bdev->mutex);
+       return err;
+}
+
+static int bcm2048_get_fm_best_tune_mode(struct bcm2048_device *bdev)
+{
+       int err;
+       u8 value;
+
+       mutex_lock(&bdev->mutex);
+
+       err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_BEST_TUNE_MODE,
+                                       &value);
+
+       mutex_unlock(&bdev->mutex);
+
+       if (!err && (value & BCM2048_BEST_TUNE_MODE))
+               return BCM2048_ITEM_ENABLED;
+
+       return err;
+}
+
+static int bcm2048_get_fm_carrier_error(struct bcm2048_device *bdev)
+{
+       int err = 0;
+       s8 value;
+
+       mutex_lock(&bdev->mutex);
+       err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_CARRIER, &value);
+       mutex_unlock(&bdev->mutex);
+
+       if (!err)
+               return value;
+
+       return err;
+}
+
+static int bcm2048_get_fm_rssi(struct bcm2048_device *bdev)
+{
+       int err;
+       s8 value;
+
+       mutex_lock(&bdev->mutex);
+       err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_RSSI, &value);
+       mutex_unlock(&bdev->mutex);
+
+       if (!err)
+               return value;
+
+       return err;
+}
+
+static int bcm2048_set_rds_wline(struct bcm2048_device *bdev, u8 wline)
+{
+       int err;
+
+       mutex_lock(&bdev->mutex);
+
+       err = bcm2048_send_command(bdev, BCM2048_I2C_RDS_WLINE, wline);
+
+       if (!err)
+               bdev->fifo_size = wline;
+
+       mutex_unlock(&bdev->mutex);
+       return err;
+}
+
+static int bcm2048_get_rds_wline(struct bcm2048_device *bdev)
+{
+       int err;
+       u8 value;
+
+       mutex_lock(&bdev->mutex);
+
+       err = bcm2048_recv_command(bdev, BCM2048_I2C_RDS_WLINE, &value);
+
+       mutex_unlock(&bdev->mutex);
+
+       if (!err) {
+               bdev->fifo_size = value;
+               return value;
+       }
+
+       return err;
+}
+
+static int bcm2048_checkrev(struct bcm2048_device *bdev)
+{
+       int err;
+       u8 version;
+
+       mutex_lock(&bdev->mutex);
+
+       err = bcm2048_recv_command(bdev, BCM2048_I2C_FM_RDS_REV, &version);
+
+       mutex_unlock(&bdev->mutex);
+
+       if (!err) {
+               dev_info(&bdev->client->dev, "BCM2048 Version 0x%x\n",
+                       version);
+               return version;
+       }
+
+       return err;
+}
+
+static int bcm2048_get_rds_rt(struct bcm2048_device *bdev, char *data)
+{
+       int err = 0, i, j = 0, ce = 0, cr = 0;
+       char data_buffer[BCM2048_MAX_RDS_RT+1];
+
+       mutex_lock(&bdev->mutex);
+
+       if (!bdev->rds_info.text_len) {
+               err = -EINVAL;
+               goto unlock;
+       }
+
+       for (i = 0; i < BCM2048_MAX_RDS_RT; i++) {
+               if (bdev->rds_info.rds_rt[i]) {
+                       ce = i;
+                       /* Skip the carriage return */
+                       if (bdev->rds_info.rds_rt[i] != 0x0d) {
+                               data_buffer[j++] = bdev->rds_info.rds_rt[i];
+                       } else {
+                               cr = i;
+                               break;
+                       }
+               }
+       }
+
+       if (j <= BCM2048_MAX_RDS_RT)
+               data_buffer[j] = 0;
+
+       for (i = 0; i < BCM2048_MAX_RDS_RT; i++) {
+               if (!bdev->rds_info.rds_rt[i]) {
+                       if (cr && (i < cr)) {
+                               err = -EBUSY;
+                               goto unlock;
+                       }
+                       if (i < ce) {
+                               if (cr && (i >= cr))
+                                       break;
+                               err = -EBUSY;
+                               goto unlock;
+                       }
+               }
+       }
+
+       memcpy(data, data_buffer, sizeof(data_buffer));
+
+unlock:
+       mutex_unlock(&bdev->mutex);
+       return err;
+}
+
+static int bcm2048_get_rds_ps(struct bcm2048_device *bdev, char *data)
+{
+       int err = 0, i, j = 0;
+       char data_buffer[BCM2048_MAX_RDS_PS+1];
+
+       mutex_lock(&bdev->mutex);
+
+       if (!bdev->rds_info.text_len) {
+               err = -EINVAL;
+               goto unlock;
+       }
+
+       for (i = 0; i < BCM2048_MAX_RDS_PS; i++) {
+               if (bdev->rds_info.rds_ps[i]) {
+                       data_buffer[j++] = bdev->rds_info.rds_ps[i];
+               } else {
+                       if (i < (BCM2048_MAX_RDS_PS - 1)) {
+                               err = -EBUSY;
+                               goto unlock;
+                       }
+               }
+       }
+
+       if (j <= BCM2048_MAX_RDS_PS)
+               data_buffer[j] = 0;
+
+       memcpy(data, data_buffer, sizeof(data_buffer));
+
+unlock:
+       mutex_unlock(&bdev->mutex);
+       return err;
+}
+
+static void bcm2048_parse_rds_pi(struct bcm2048_device *bdev)
+{
+       int i, cnt = 0;
+       u16 pi;
+
+       for (i = 0; i < bdev->fifo_size; i += BCM2048_RDS_FIFO_DUPLE_SIZE) {
+
+               /* Block A match, only data without crc errors taken */
+               if (bdev->rds_info.radio_text[i] == BCM2048_RDS_BLOCK_A) {
+
+                       pi = ((bdev->rds_info.radio_text[i+1] << 8) +
+                               bdev->rds_info.radio_text[i+2]);
+
+                       if (!bdev->rds_info.rds_pi) {
+                               bdev->rds_info.rds_pi = pi;
+                               return;
+                       }
+                       if (pi != bdev->rds_info.rds_pi) {
+                               cnt++;
+                               if (cnt > 3) {
+                                       bdev->rds_info.rds_pi = pi;
+                                       cnt = 0;
+                               }
+                       } else {
+                               cnt = 0;
+                       }
+               }
+       }
+}
+
+static int bcm2048_rds_block_crc(struct bcm2048_device *bdev, int i)
+{
+       return bdev->rds_info.radio_text[i] & BCM2048_RDS_CRC_MASK;
+}
+
+static void bcm2048_parse_rds_rt_block(struct bcm2048_device *bdev, int i,
+                                       int index, int crc)
+{
+       /* Good data will overwrite poor data */
+       if (crc) {
+               if (!bdev->rds_info.rds_rt[index])
+                       bdev->rds_info.rds_rt[index] =
+                               bdev->rds_info.radio_text[i+1];
+               if (!bdev->rds_info.rds_rt[index+1])
+                       bdev->rds_info.rds_rt[index+1] =
+                               bdev->rds_info.radio_text[i+2];
+       } else {
+               bdev->rds_info.rds_rt[index] = bdev->rds_info.radio_text[i+1];
+               bdev->rds_info.rds_rt[index+1] =
+                       bdev->rds_info.radio_text[i+2];
+       }
+}
+
+static int bcm2048_parse_rt_match_b(struct bcm2048_device *bdev, int i)
+{
+       int crc, rt_id, rt_group_b, rt_ab, index = 0;
+
+       crc = bcm2048_rds_block_crc(bdev, i);
+
+       if (crc == BCM2048_RDS_CRC_UNRECOVARABLE)
+               return -EIO;
+
+       if ((bdev->rds_info.radio_text[i] & BCM2048_RDS_BLOCK_MASK) ==
+               BCM2048_RDS_BLOCK_B) {
+
+               rt_id = (bdev->rds_info.radio_text[i+1] &
+                       BCM2048_RDS_BLOCK_MASK);
+               rt_group_b = bdev->rds_info.radio_text[i+1] &
+                       BCM2048_RDS_GROUP_AB_MASK;
+               rt_ab = bdev->rds_info.radio_text[i+2] &
+                               BCM2048_RDS_RT_AB_MASK;
+
+               if (rt_group_b != bdev->rds_info.rds_rt_group_b) {
+                       memset(bdev->rds_info.rds_rt, 0,
+                               sizeof(bdev->rds_info.rds_rt));
+                       bdev->rds_info.rds_rt_group_b = rt_group_b;
+               }
+
+               if (rt_id == BCM2048_RDS_RT) {
+                       /* A to B or (vice versa), means: clear screen */
+                       if (rt_ab != bdev->rds_info.rds_rt_ab) {
+                               memset(bdev->rds_info.rds_rt, 0,
+                                       sizeof(bdev->rds_info.rds_rt));
+                               bdev->rds_info.rds_rt_ab = rt_ab;
+                       }
+
+                       index = bdev->rds_info.radio_text[i+2] &
+                                       BCM2048_RDS_RT_INDEX;
+
+                       if (bdev->rds_info.rds_rt_group_b)
+                               index <<= 1;
+                       else
+                               index <<= 2;
+
+                       return index;
+               }
+       }
+
+       return -EIO;
+}
+
+static int bcm2048_parse_rt_match_c(struct bcm2048_device *bdev, int i,
+                                       int index)
+{
+       int crc;
+
+       crc = bcm2048_rds_block_crc(bdev, i);
+
+       if (crc == BCM2048_RDS_CRC_UNRECOVARABLE)
+               return 0;
+
+       BUG_ON((index+2) >= BCM2048_MAX_RDS_RT);
+
+       if ((bdev->rds_info.radio_text[i] & BCM2048_RDS_BLOCK_MASK) ==
+               BCM2048_RDS_BLOCK_C) {
+               if (bdev->rds_info.rds_rt_group_b)
+                       return 1;
+               bcm2048_parse_rds_rt_block(bdev, i, index, crc);
+               return 1;
+       }
+
+       return 0;
+}
+
+static void bcm2048_parse_rt_match_d(struct bcm2048_device *bdev, int i,
+                                       int index)
+{
+       int crc;
+
+       crc = bcm2048_rds_block_crc(bdev, i);
+
+       if (crc == BCM2048_RDS_CRC_UNRECOVARABLE)
+               return;
+
+       BUG_ON((index+4) >= BCM2048_MAX_RDS_RT);
+
+       if ((bdev->rds_info.radio_text[i] & BCM2048_RDS_BLOCK_MASK) ==
+               BCM2048_RDS_BLOCK_D)
+               bcm2048_parse_rds_rt_block(bdev, i, index+2, crc);
+}
+
+static int bcm2048_parse_rds_rt(struct bcm2048_device *bdev)
+{
+       int i, index = 0, crc, match_b = 0, match_c = 0, match_d = 0;
+
+       for (i = 0; i < bdev->fifo_size; i += BCM2048_RDS_FIFO_DUPLE_SIZE) {
+
+               if (match_b) {
+                       match_b = 0;
+                       index = bcm2048_parse_rt_match_b(bdev, i);
+                       if (index >= 0 && index <= (BCM2048_MAX_RDS_RT - 5))
+                               match_c = 1;
+                       continue;
+               } else if (match_c) {
+                       match_c = 0;
+                       if (bcm2048_parse_rt_match_c(bdev, i, index))
+                               match_d = 1;
+                       continue;
+               } else if (match_d) {
+                       match_d = 0;
+                       bcm2048_parse_rt_match_d(bdev, i, index);
+                       continue;
+               }
+
+               /* Skip erroneous blocks due to messed up A block altogether */
+               if ((bdev->rds_info.radio_text[i] & BCM2048_RDS_BLOCK_MASK)
+                       == BCM2048_RDS_BLOCK_A) {
+                       crc = bcm2048_rds_block_crc(bdev, i);
+                       if (crc == BCM2048_RDS_CRC_UNRECOVARABLE)
+                               continue;
+                       /* Syncronize to a good RDS PI */
+                       if (((bdev->rds_info.radio_text[i+1] << 8) +
+                               bdev->rds_info.radio_text[i+2]) ==
+                               bdev->rds_info.rds_pi)
+                                       match_b = 1;
+               }
+       }
+
+       return 0;
+}
+
+static void bcm2048_parse_rds_ps_block(struct bcm2048_device *bdev, int i,
+                                       int index, int crc)
+{
+       /* Good data will overwrite poor data */
+       if (crc) {
+               if (!bdev->rds_info.rds_ps[index])
+                       bdev->rds_info.rds_ps[index] =
+                               bdev->rds_info.radio_text[i+1];
+               if (!bdev->rds_info.rds_ps[index+1])
+                       bdev->rds_info.rds_ps[index+1] =
+                               bdev->rds_info.radio_text[i+2];
+       } else {
+               bdev->rds_info.rds_ps[index] = bdev->rds_info.radio_text[i+1];
+               bdev->rds_info.rds_ps[index+1] =
+                       bdev->rds_info.radio_text[i+2];
+       }
+}
+
+static int bcm2048_parse_ps_match_c(struct bcm2048_device *bdev, int i,
+                                       int index)
+{
+       int crc;
+
+       crc = bcm2048_rds_block_crc(bdev, i);
+
+       if (crc == BCM2048_RDS_CRC_UNRECOVARABLE)
+               return 0;
+
+       if ((bdev->rds_info.radio_text[i] & BCM2048_RDS_BLOCK_MASK) ==
+               BCM2048_RDS_BLOCK_C)
+               return 1;
+
+       return 0;
+}
+
+static void bcm2048_parse_ps_match_d(struct bcm2048_device *bdev, int i,
+                                       int index)
+{
+       int crc;
+
+       crc = bcm2048_rds_block_crc(bdev, i);
+
+       if (crc == BCM2048_RDS_CRC_UNRECOVARABLE)
+               return;
+
+       if ((bdev->rds_info.radio_text[i] & BCM2048_RDS_BLOCK_MASK) ==
+               BCM2048_RDS_BLOCK_D)
+               bcm2048_parse_rds_ps_block(bdev, i, index, crc);
+}
+
+static int bcm2048_parse_ps_match_b(struct bcm2048_device *bdev, int i)
+{
+       int crc, index, ps_id, ps_group;
+
+       crc = bcm2048_rds_block_crc(bdev, i);
+
+       if (crc == BCM2048_RDS_CRC_UNRECOVARABLE)
+               return -EIO;
+
+       /* Block B Radio PS match */
+       if ((bdev->rds_info.radio_text[i] & BCM2048_RDS_BLOCK_MASK) ==
+               BCM2048_RDS_BLOCK_B) {
+               ps_id = bdev->rds_info.radio_text[i+1] &
+                       BCM2048_RDS_BLOCK_MASK;
+               ps_group = bdev->rds_info.radio_text[i+1] &
+                       BCM2048_RDS_GROUP_AB_MASK;
+
+               /*
+                * Poor RSSI will lead to RDS data corruption
+                * So using 3 (same) sequential values to justify major changes
+                */
+               if (ps_group != bdev->rds_info.rds_ps_group) {
+                       if (crc == BCM2048_RDS_CRC_NONE) {
+                               bdev->rds_info.rds_ps_group_cnt++;
+                               if (bdev->rds_info.rds_ps_group_cnt > 2) {
+                                       bdev->rds_info.rds_ps_group = ps_group;
+                                       bdev->rds_info.rds_ps_group_cnt = 0;
+                                       dev_err(&bdev->client->dev,
+                                               "RDS PS Group change!\n");
+                               } else {
+                                       return -EIO;
+                               }
+                       } else {
+                               bdev->rds_info.rds_ps_group_cnt = 0;
+                       }
+               }
+
+               if (ps_id == BCM2048_RDS_PS) {
+                       index = bdev->rds_info.radio_text[i+2] &
+                               BCM2048_RDS_PS_INDEX;
+                       index <<= 1;
+                       return index;
+               }
+       }
+
+       return -EIO;
+}
+
+static void bcm2048_parse_rds_ps(struct bcm2048_device *bdev)
+{
+       int i, index = 0, crc, match_b = 0, match_c = 0, match_d = 0;
+
+       for (i = 0; i < bdev->fifo_size; i += BCM2048_RDS_FIFO_DUPLE_SIZE) {
+
+               if (match_b) {
+                       match_b = 0;
+                       index = bcm2048_parse_ps_match_b(bdev, i);
+                       if (index >= 0 && index < (BCM2048_MAX_RDS_PS - 1))
+                               match_c = 1;
+                       continue;
+               } else if (match_c) {
+                       match_c = 0;
+                       if (bcm2048_parse_ps_match_c(bdev, i, index))
+                               match_d = 1;
+                       continue;
+               } else if (match_d) {
+                       match_d = 0;
+                       bcm2048_parse_ps_match_d(bdev, i, index);
+                       continue;
+               }
+
+               /* Skip erroneous blocks due to messed up A block altogether */
+               if ((bdev->rds_info.radio_text[i] & BCM2048_RDS_BLOCK_MASK)
+                       == BCM2048_RDS_BLOCK_A) {
+                       crc = bcm2048_rds_block_crc(bdev, i);
+                       if (crc == BCM2048_RDS_CRC_UNRECOVARABLE)
+                               continue;
+                       /* Syncronize to a good RDS PI */
+                       if (((bdev->rds_info.radio_text[i+1] << 8) +
+                               bdev->rds_info.radio_text[i+2]) ==
+                               bdev->rds_info.rds_pi)
+                                       match_b = 1;
+               }
+       }
+}
+
+static void bcm2048_rds_fifo_receive(struct bcm2048_device *bdev)
+{
+       int err;
+
+       mutex_lock(&bdev->mutex);
+
+       err = bcm2048_recv_duples(bdev, BCM2048_I2C_RDS_DATA,
+                               bdev->rds_info.radio_text, bdev->fifo_size);
+       if (err != 2) {
+               dev_err(&bdev->client->dev, "RDS Read problem\n");
+               return;
+       }
+
+       bdev->rds_info.text_len = bdev->fifo_size;
+
+       bcm2048_parse_rds_pi(bdev);
+       bcm2048_parse_rds_rt(bdev);
+       bcm2048_parse_rds_ps(bdev);
+
+       mutex_unlock(&bdev->mutex);
+
+       wake_up_interruptible(&bdev->read_queue);
+}
+
+static int bcm2048_get_rds_data(struct bcm2048_device *bdev, char *data)
+{
+       int err = 0, i, p = 0;
+       char *data_buffer;
+
+       mutex_lock(&bdev->mutex);
+
+       if (!bdev->rds_info.text_len) {
+               err = -EINVAL;
+               goto unlock;
+       }
+
+       data_buffer = kzalloc(BCM2048_MAX_RDS_RADIO_TEXT*5, GFP_KERNEL);
+       if (!data_buffer) {
+               err = -ENOMEM;
+               goto unlock;
+       }
+
+       for (i = 0; i < bdev->rds_info.text_len; i++) {
+               p += sprintf(data_buffer+p, "%x ",
+                       bdev->rds_info.radio_text[i]);
+       }
+
+       memcpy(data, data_buffer, p);
+       kfree(data_buffer);
+
+unlock:
+       mutex_unlock(&bdev->mutex);
+       return err;
+}
+
+/*
+ *     BCM2048 default initialization sequence
+ */
+static int bcm2048_init(struct bcm2048_device *bdev)
+{
+       int err;
+
+       err = bcm2048_set_power_state(bdev, BCM2048_POWER_ON);
+       if (err < 0)
+               goto exit;
+
+       err = bcm2048_set_audio_route(bdev, BCM2048_AUDIO_ROUTE_DAC);
+       if (err < 0)
+               goto exit;
+
+       err = bcm2048_set_dac_output(bdev, BCM2048_DAC_OUTPUT_LEFT |
+               BCM2048_DAC_OUTPUT_RIGHT);
+
+exit:
+       return err;
+}
+
+/*
+ *     BCM2048 default deinitialization sequence
+ */
+static int bcm2048_deinit(struct bcm2048_device *bdev)
+{
+       int err;
+
+       err = bcm2048_set_audio_route(bdev, 0);
+       if (err < 0)
+               goto exit;
+
+       err = bcm2048_set_dac_output(bdev, 0);
+       if (err < 0)
+               goto exit;
+
+       err = bcm2048_set_power_state(bdev, BCM2048_POWER_OFF);
+       if (err < 0)
+               goto exit;
+
+exit:
+       return err;
+}
+
+/*
+ *     BCM2048 probe sequence
+ */
+static int bcm2048_probe(struct bcm2048_device *bdev)
+{
+       int err;
+
+       err = bcm2048_set_power_state(bdev, BCM2048_POWER_ON);
+       if (err < 0)
+               goto unlock;
+
+       err = bcm2048_checkrev(bdev);
+       if (err < 0)
+               goto unlock;
+
+       err = bcm2048_set_mute(bdev, BCM2048_DEFAULT_MUTE);
+       if (err < 0)
+               goto unlock;
+
+       err = bcm2048_set_region(bdev, BCM2048_DEFAULT_REGION);
+       if (err < 0)
+               goto unlock;
+
+       err = bcm2048_set_fm_search_rssi_threshold(bdev,
+                                       BCM2048_DEFAULT_RSSI_THRESHOLD);
+       if (err < 0)
+               goto unlock;
+
+       err = bcm2048_set_fm_automatic_stereo_mono(bdev, BCM2048_ITEM_ENABLED);
+       if (err < 0)
+               goto unlock;
+
+       err = bcm2048_get_rds_wline(bdev);
+       if (err < BCM2048_DEFAULT_RDS_WLINE)
+               err = bcm2048_set_rds_wline(bdev, BCM2048_DEFAULT_RDS_WLINE);
+       if (err < 0)
+               goto unlock;
+
+       err = bcm2048_set_power_state(bdev, BCM2048_POWER_OFF);
+
+       init_waitqueue_head(&bdev->read_queue);
+       bdev->rds_data_available = 0;
+       bdev->rd_index = 0;
+       bdev->users = 0;
+
+unlock:
+       return err;
+}
+
+/*
+ *     BCM2048 workqueue handler
+ */
+static void bcm2048_work(struct work_struct *work)
+{
+       struct bcm2048_device *bdev;
+       u8 flag_lsb, flag_msb, flags;
+
+       bdev = container_of(work, struct bcm2048_device, work);
+       bcm2048_recv_command(bdev, BCM2048_I2C_FM_RDS_FLAG0, &flag_lsb);
+       bcm2048_recv_command(bdev, BCM2048_I2C_FM_RDS_FLAG1, &flag_msb);
+
+       if (flag_lsb & (BCM2048_FM_FLAG_SEARCH_TUNE_FINISHED |
+                       BCM2048_FM_FLAG_SEARCH_TUNE_FAIL)) {
+
+               if (flag_lsb & BCM2048_FM_FLAG_SEARCH_TUNE_FAIL)
+                       bdev->scan_state = BCM2048_SCAN_FAIL;
+               else
+                       bdev->scan_state = BCM2048_SCAN_OK;
+
+               complete(&bdev->compl);
+       }
+
+       if (flag_msb & BCM2048_RDS_FLAG_FIFO_WLINE) {
+               bcm2048_rds_fifo_receive(bdev);
+               if (bdev->rds_state) {
+                       flags = BCM2048_RDS_FLAG_FIFO_WLINE;
+                       bcm2048_send_command(bdev, BCM2048_I2C_FM_RDS_MASK1,
+                                               flags);
+               }
+               bdev->rds_data_available = 1;
+               bdev->rd_index = 0; /* new data, new start */
+       }
+}
+
+/*
+ *     BCM2048 interrupt handler
+ */
+static irqreturn_t bcm2048_handler(int irq, void *dev)
+{
+       struct bcm2048_device *bdev = dev;
+
+       dev_dbg(&bdev->client->dev, "IRQ called, queuing work\n");
+       if (bdev->power_state)
+               schedule_work(&bdev->work);
+
+       return IRQ_HANDLED;
+}
+
+/*
+ *     BCM2048 sysfs interface definitions
+ */
+#define property_write(prop, type, mask, check)                                \
+static ssize_t bcm2048_##prop##_write(struct device *dev,              \
+                                       struct device_attribute *attr,  \
+                                       const char *buf,                \
+                                       size_t count)                   \
+{                                                                      \
+       struct bcm2048_device *bdev = dev_get_drvdata(dev);             \
+       type value;                                                     \
+       int err;                                                        \
+                                                                       \
+       if (!bdev)                                                      \
+               return -ENODEV;                                         \
+                                                                       \
+       sscanf(buf, mask, &value);                                      \
+                                                                       \
+       if (check)                                                      \
+               return -EDOM;                                           \
+                                                                       \
+       err = bcm2048_set_##prop(bdev, value);                          \
+                                                                       \
+       return err < 0 ? err : count;                                   \
+}
+
+#define property_read(prop, size, mask)                                        \
+static ssize_t bcm2048_##prop##_read(struct device *dev,               \
+                                       struct device_attribute *attr,  \
+                                       char *buf)                      \
+{                                                                      \
+       struct bcm2048_device *bdev = dev_get_drvdata(dev);             \
+       int value;                                                      \
+                                                                       \
+       if (!bdev)                                                      \
+               return -ENODEV;                                         \
+                                                                       \
+       value = bcm2048_get_##prop(bdev);                               \
+                                                                       \
+       if (value >= 0)                                                 \
+               value = sprintf(buf, mask "\n", value);                 \
+                                                                       \
+       return value;                                                   \
+}
+
+#define property_signed_read(prop, size, mask)                         \
+static ssize_t bcm2048_##prop##_read(struct device *dev,               \
+                                       struct device_attribute *attr,  \
+                                       char *buf)                      \
+{                                                                      \
+       struct bcm2048_device *bdev = dev_get_drvdata(dev);             \
+       size value;                                                     \
+                                                                       \
+       if (!bdev)                                                      \
+               return -ENODEV;                                         \
+                                                                       \
+       value = bcm2048_get_##prop(bdev);                               \
+                                                                       \
+       value = sprintf(buf, mask "\n", value);                         \
+                                                                       \
+       return value;                                                   \
+}
+
+#define DEFINE_SYSFS_PROPERTY(prop, signal, size, mask, check)         \
+property_write(prop, signal size, mask, check)                         \
+property_read(prop, size, mask)
+
+#define property_str_read(prop, size)                                  \
+static ssize_t bcm2048_##prop##_read(struct device *dev,               \
+                                       struct device_attribute *attr,  \
+                                       char *buf)                      \
+{                                                                      \
+       struct bcm2048_device *bdev = dev_get_drvdata(dev);             \
+       int count;                                                      \
+       u8 *out;                                                        \
+                                                                       \
+       if (!bdev)                                                      \
+               return -ENODEV;                                         \
+                                                                       \
+       out = kzalloc(size + 1, GFP_KERNEL);                            \
+       if (!out)                                                       \
+               return -ENOMEM;                                         \
+                                                                       \
+       bcm2048_get_##prop(bdev, out);                                  \
+       count = sprintf(buf, "%s\n", out);                              \
+                                                                       \
+       kfree(out);                                                     \
+                                                                       \
+       return count;                                                   \
+}
+
+DEFINE_SYSFS_PROPERTY(power_state, unsigned, int, "%u", 0)
+DEFINE_SYSFS_PROPERTY(mute, unsigned, int, "%u", 0)
+DEFINE_SYSFS_PROPERTY(audio_route, unsigned, int, "%u", 0)
+DEFINE_SYSFS_PROPERTY(dac_output, unsigned, int, "%u", 0)
+
+DEFINE_SYSFS_PROPERTY(fm_hi_lo_injection, unsigned, int, "%u", 0)
+DEFINE_SYSFS_PROPERTY(fm_frequency, unsigned, int, "%u", 0)
+DEFINE_SYSFS_PROPERTY(fm_af_frequency, unsigned, int, "%u", 0)
+DEFINE_SYSFS_PROPERTY(fm_deemphasis, unsigned, int, "%u", 0)
+DEFINE_SYSFS_PROPERTY(fm_rds_mask, unsigned, int, "%u", 0)
+DEFINE_SYSFS_PROPERTY(fm_best_tune_mode, unsigned, int, "%u", 0)
+DEFINE_SYSFS_PROPERTY(fm_search_rssi_threshold, unsigned, int, "%u", 0)
+DEFINE_SYSFS_PROPERTY(fm_search_mode_direction, unsigned, int, "%u", 0)
+DEFINE_SYSFS_PROPERTY(fm_search_tune_mode, unsigned, int, "%u", value > 3)
+
+DEFINE_SYSFS_PROPERTY(rds, unsigned, int, "%u", 0)
+DEFINE_SYSFS_PROPERTY(rds_b_block_mask, unsigned, int, "%u", 0)
+DEFINE_SYSFS_PROPERTY(rds_b_block_match, unsigned, int, "%u", 0)
+DEFINE_SYSFS_PROPERTY(rds_pi_mask, unsigned, int, "%u", 0)
+DEFINE_SYSFS_PROPERTY(rds_pi_match, unsigned, int, "%u", 0)
+DEFINE_SYSFS_PROPERTY(rds_wline, unsigned, int, "%u", 0)
+property_read(rds_pi, unsigned int, "%x")
+property_str_read(rds_rt, (BCM2048_MAX_RDS_RT + 1))
+property_str_read(rds_ps, (BCM2048_MAX_RDS_PS + 1))
+
+property_read(fm_rds_flags, unsigned int, "%u")
+property_str_read(rds_data, BCM2048_MAX_RDS_RADIO_TEXT*5)
+
+property_read(region_bottom_frequency, unsigned int, "%u")
+property_read(region_top_frequency, unsigned int, "%u")
+property_signed_read(fm_carrier_error, int, "%d")
+property_signed_read(fm_rssi, int, "%d")
+DEFINE_SYSFS_PROPERTY(region, unsigned, int, "%u", 0)
+
+static struct device_attribute attrs[] = {
+       __ATTR(power_state, S_IRUGO | S_IWUSR, bcm2048_power_state_read,
+               bcm2048_power_state_write),
+       __ATTR(mute, S_IRUGO | S_IWUSR, bcm2048_mute_read,
+               bcm2048_mute_write),
+       __ATTR(audio_route, S_IRUGO | S_IWUSR, bcm2048_audio_route_read,
+               bcm2048_audio_route_write),
+       __ATTR(dac_output, S_IRUGO | S_IWUSR, bcm2048_dac_output_read,
+               bcm2048_dac_output_write),
+       __ATTR(fm_hi_lo_injection, S_IRUGO | S_IWUSR,
+               bcm2048_fm_hi_lo_injection_read,
+               bcm2048_fm_hi_lo_injection_write),
+       __ATTR(fm_frequency, S_IRUGO | S_IWUSR, bcm2048_fm_frequency_read,
+               bcm2048_fm_frequency_write),
+       __ATTR(fm_af_frequency, S_IRUGO | S_IWUSR,
+               bcm2048_fm_af_frequency_read,
+               bcm2048_fm_af_frequency_write),
+       __ATTR(fm_deemphasis, S_IRUGO | S_IWUSR, bcm2048_fm_deemphasis_read,
+               bcm2048_fm_deemphasis_write),
+       __ATTR(fm_rds_mask, S_IRUGO | S_IWUSR, bcm2048_fm_rds_mask_read,
+               bcm2048_fm_rds_mask_write),
+       __ATTR(fm_best_tune_mode, S_IRUGO | S_IWUSR,
+               bcm2048_fm_best_tune_mode_read,
+               bcm2048_fm_best_tune_mode_write),
+       __ATTR(fm_search_rssi_threshold, S_IRUGO | S_IWUSR,
+               bcm2048_fm_search_rssi_threshold_read,
+               bcm2048_fm_search_rssi_threshold_write),
+       __ATTR(fm_search_mode_direction, S_IRUGO | S_IWUSR,
+               bcm2048_fm_search_mode_direction_read,
+               bcm2048_fm_search_mode_direction_write),
+       __ATTR(fm_search_tune_mode, S_IRUGO | S_IWUSR,
+               bcm2048_fm_search_tune_mode_read,
+               bcm2048_fm_search_tune_mode_write),
+       __ATTR(rds, S_IRUGO | S_IWUSR, bcm2048_rds_read,
+               bcm2048_rds_write),
+       __ATTR(rds_b_block_mask, S_IRUGO | S_IWUSR,
+               bcm2048_rds_b_block_mask_read,
+               bcm2048_rds_b_block_mask_write),
+       __ATTR(rds_b_block_match, S_IRUGO | S_IWUSR,
+               bcm2048_rds_b_block_match_read,
+               bcm2048_rds_b_block_match_write),
+       __ATTR(rds_pi_mask, S_IRUGO | S_IWUSR, bcm2048_rds_pi_mask_read,
+               bcm2048_rds_pi_mask_write),
+       __ATTR(rds_pi_match, S_IRUGO | S_IWUSR, bcm2048_rds_pi_match_read,
+               bcm2048_rds_pi_match_write),
+       __ATTR(rds_wline, S_IRUGO | S_IWUSR, bcm2048_rds_wline_read,
+               bcm2048_rds_wline_write),
+       __ATTR(rds_pi, S_IRUGO, bcm2048_rds_pi_read, NULL),
+       __ATTR(rds_rt, S_IRUGO, bcm2048_rds_rt_read, NULL),
+       __ATTR(rds_ps, S_IRUGO, bcm2048_rds_ps_read, NULL),
+       __ATTR(fm_rds_flags, S_IRUGO, bcm2048_fm_rds_flags_read, NULL),
+       __ATTR(region_bottom_frequency, S_IRUGO,
+               bcm2048_region_bottom_frequency_read, NULL),
+       __ATTR(region_top_frequency, S_IRUGO,
+               bcm2048_region_top_frequency_read, NULL),
+       __ATTR(fm_carrier_error, S_IRUGO,
+               bcm2048_fm_carrier_error_read, NULL),
+       __ATTR(fm_rssi, S_IRUGO,
+               bcm2048_fm_rssi_read, NULL),
+       __ATTR(region, S_IRUGO | S_IWUSR, bcm2048_region_read,
+               bcm2048_region_write),
+       __ATTR(rds_data, S_IRUGO, bcm2048_rds_data_read, NULL),
+};
+
+static int bcm2048_sysfs_unregister_properties(struct bcm2048_device *bdev,
+                                               int size)
+{
+       int i;
+
+       for (i = 0; i < size; i++)
+               device_remove_file(&bdev->client->dev, &attrs[i]);
+
+       return 0;
+}
+
+static int bcm2048_sysfs_register_properties(struct bcm2048_device *bdev)
+{
+       int err = 0;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(attrs); i++) {
+               if (device_create_file(&bdev->client->dev, &attrs[i]) != 0) {
+                       dev_err(&bdev->client->dev,
+                                       "could not register sysfs entry\n");
+                       err = -EBUSY;
+                       bcm2048_sysfs_unregister_properties(bdev, i);
+                       break;
+               }
+       }
+
+       return err;
+}
+
+
+static int bcm2048_fops_open(struct file *file)
+{
+       struct bcm2048_device *bdev = video_drvdata(file);
+
+       bdev->users++;
+       bdev->rd_index = 0;
+       bdev->rds_data_available = 0;
+
+       return 0;
+}
+
+static int bcm2048_fops_release(struct file *file)
+{
+       struct bcm2048_device *bdev = video_drvdata(file);
+
+       bdev->users--;
+
+       return 0;
+}
+
+static unsigned int bcm2048_fops_poll(struct file *file,
+               struct poll_table_struct *pts)
+{
+       struct bcm2048_device *bdev = video_drvdata(file);
+       int retval = 0;
+
+       poll_wait(file, &bdev->read_queue, pts);
+
+       if (bdev->rds_data_available)
+               retval = POLLIN | POLLRDNORM;
+
+       return retval;
+}
+
+static ssize_t bcm2048_fops_read(struct file *file, char __user *buf,
+       size_t count, loff_t *ppos)
+{
+       struct bcm2048_device *bdev = video_drvdata(file);
+       int i;
+       int retval = 0;
+
+       /* we return at least 3 bytes, one block */
+       count = (count / 3) * 3; /* only multiples of 3 */
+       if (count < 3)
+               return -ENOBUFS;
+
+       while (!bdev->rds_data_available) {
+               if (file->f_flags & O_NONBLOCK) {
+                       retval = -EWOULDBLOCK;
+                       goto done;
+               }
+               /* interruptible_sleep_on(&bdev->read_queue); */
+               if (wait_event_interruptible(bdev->read_queue,
+                       bdev->rds_data_available) < 0) {
+                       retval = -EINTR;
+                       goto done;
+               }
+       }
+
+       mutex_lock(&bdev->mutex);
+       /* copy data to userspace */
+       i = bdev->fifo_size - bdev->rd_index;
+       if (count > i)
+               count = (i / 3) * 3;
+
+       i = 0;
+       while (i < count) {
+               unsigned char tmpbuf[3];
+               tmpbuf[i] = bdev->rds_info.radio_text[bdev->rd_index+i+2];
+               tmpbuf[i+1] = bdev->rds_info.radio_text[bdev->rd_index+i+1];
+               tmpbuf[i+2] = ((bdev->rds_info.radio_text[bdev->rd_index+i]
+                               & 0xf0) >> 4);
+               if ((bdev->rds_info.radio_text[bdev->rd_index+i] &
+                       BCM2048_RDS_CRC_MASK) == BCM2048_RDS_CRC_UNRECOVARABLE)
+                       tmpbuf[i+2] |= 0x80;
+               if (copy_to_user(buf+i, tmpbuf, 3)) {
+                       retval = -EFAULT;
+                       break;
+               };
+               i += 3;
+       }
+
+       bdev->rd_index += i;
+       if (bdev->rd_index >= bdev->fifo_size)
+               bdev->rds_data_available = 0;
+
+       mutex_unlock(&bdev->mutex);
+       if (retval == 0)
+               retval = i;
+
+done:
+       return retval;
+}
+
+/*
+ *     bcm2048_fops - file operations interface
+ */
+static const struct v4l2_file_operations bcm2048_fops = {
+       .owner          = THIS_MODULE,
+       .ioctl          = video_ioctl2,
+       /* for RDS read support */
+       .open           = bcm2048_fops_open,
+       .release        = bcm2048_fops_release,
+       .read           = bcm2048_fops_read,
+       .poll           = bcm2048_fops_poll
+};
+
+/*
+ *     Video4Linux Interface
+ */
+static struct v4l2_queryctrl bcm2048_v4l2_queryctrl[] = {
+       {
+               .id             = V4L2_CID_AUDIO_VOLUME,
+               .flags          = V4L2_CTRL_FLAG_DISABLED,
+       },
+       {
+               .id             = V4L2_CID_AUDIO_BALANCE,
+               .flags          = V4L2_CTRL_FLAG_DISABLED,
+       },
+       {
+               .id             = V4L2_CID_AUDIO_BASS,
+               .flags          = V4L2_CTRL_FLAG_DISABLED,
+       },
+       {
+               .id             = V4L2_CID_AUDIO_TREBLE,
+               .flags          = V4L2_CTRL_FLAG_DISABLED,
+       },
+       {
+               .id             = V4L2_CID_AUDIO_MUTE,
+               .type           = V4L2_CTRL_TYPE_BOOLEAN,
+               .name           = "Mute",
+               .minimum        = 0,
+               .maximum        = 1,
+               .step           = 1,
+               .default_value  = 1,
+       },
+       {
+               .id             = V4L2_CID_AUDIO_LOUDNESS,
+               .flags          = V4L2_CTRL_FLAG_DISABLED,
+       },
+};
+
+static int bcm2048_vidioc_querycap(struct file *file, void *priv,
+               struct v4l2_capability *capability)
+{
+       struct bcm2048_device *bdev = video_get_drvdata(video_devdata(file));
+
+       strlcpy(capability->driver, BCM2048_DRIVER_NAME,
+               sizeof(capability->driver));
+       strlcpy(capability->card, BCM2048_DRIVER_CARD,
+               sizeof(capability->card));
+       snprintf(capability->bus_info, 32, "I2C: 0x%X", bdev->client->addr);
+       capability->version = BCM2048_DRIVER_VERSION;
+       capability->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO |
+                                       V4L2_CAP_HW_FREQ_SEEK;
+
+       return 0;
+}
+
+static int bcm2048_vidioc_g_input(struct file *filp, void *priv,
+               unsigned int *i)
+{
+       *i = 0;
+
+       return 0;
+}
+
+static int bcm2048_vidioc_s_input(struct file *filp, void *priv,
+                                       unsigned int i)
+{
+       if (i)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int bcm2048_vidioc_queryctrl(struct file *file, void *priv,
+               struct v4l2_queryctrl *qc)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(bcm2048_v4l2_queryctrl); i++) {
+               if (qc->id && qc->id == bcm2048_v4l2_queryctrl[i].id) {
+                       memcpy(qc, &(bcm2048_v4l2_queryctrl[i]), sizeof(*qc));
+                       return 0;
+               }
+       }
+
+       return -EINVAL;
+}
+
+static int bcm2048_vidioc_g_ctrl(struct file *file, void *priv,
+               struct v4l2_control *ctrl)
+{
+       struct bcm2048_device *bdev = video_get_drvdata(video_devdata(file));
+       int err = 0;
+
+       if (!bdev)
+               return -ENODEV;
+
+       switch (ctrl->id) {
+       case V4L2_CID_AUDIO_MUTE:
+               err = bcm2048_get_mute(bdev);
+               if (err >= 0)
+                       ctrl->value = err;
+               break;
+       }
+
+       return err;
+}
+
+static int bcm2048_vidioc_s_ctrl(struct file *file, void *priv,
+               struct v4l2_control *ctrl)
+{
+       struct bcm2048_device *bdev = video_get_drvdata(video_devdata(file));
+       int err = 0;
+
+       if (!bdev)
+               return -ENODEV;
+
+       switch (ctrl->id) {
+       case V4L2_CID_AUDIO_MUTE:
+               if (ctrl->value) {
+                       if (bdev->power_state) {
+                               err = bcm2048_set_mute(bdev, ctrl->value);
+                               err |= bcm2048_deinit(bdev);
+                       }
+               } else {
+                       if (!bdev->power_state) {
+                               err = bcm2048_init(bdev);
+                               err |= bcm2048_set_mute(bdev, ctrl->value);
+                       }
+               }
+               break;
+       }
+
+       return err;
+}
+
+static int bcm2048_vidioc_g_audio(struct file *file, void *priv,
+               struct v4l2_audio *audio)
+{
+       if (audio->index > 1)
+               return -EINVAL;
+
+       strncpy(audio->name, "Radio", 32);
+       audio->capability = V4L2_AUDCAP_STEREO;
+
+       return 0;
+}
+
+static int bcm2048_vidioc_s_audio(struct file *file, void *priv,
+               const struct v4l2_audio *audio)
+{
+       if (audio->index != 0)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int bcm2048_vidioc_g_tuner(struct file *file, void *priv,
+               struct v4l2_tuner *tuner)
+{
+       struct bcm2048_device *bdev = video_get_drvdata(video_devdata(file));
+       s8 f_error;
+       s8 rssi;
+
+       if (!bdev)
+               return -ENODEV;
+
+       if (tuner->index > 0)
+               return -EINVAL;
+
+       strncpy(tuner->name, "FM Receiver", 32);
+       tuner->type = V4L2_TUNER_RADIO;
+       tuner->rangelow =
+               dev_to_v4l2(bcm2048_get_region_bottom_frequency(bdev));
+       tuner->rangehigh =
+               dev_to_v4l2(bcm2048_get_region_top_frequency(bdev));
+       tuner->rxsubchans = V4L2_TUNER_SUB_STEREO;
+       tuner->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LOW;
+       tuner->audmode = V4L2_TUNER_MODE_STEREO;
+       tuner->afc = 0;
+       if (bdev->power_state) {
+               /*
+                * Report frequencies with high carrier errors to have zero
+                * signal level
+                */
+               f_error = bcm2048_get_fm_carrier_error(bdev);
+               if (f_error < BCM2048_FREQ_ERROR_FLOOR ||
+                   f_error > BCM2048_FREQ_ERROR_ROOF) {
+                       tuner->signal = 0;
+               } else {
+                       /*
+                        * RSSI level -60 dB is defined to report full
+                        * signal strenght
+                        */
+                       rssi = bcm2048_get_fm_rssi(bdev);
+                       if (rssi >= BCM2048_RSSI_LEVEL_BASE) {
+                               tuner->signal = 0xFFFF;
+                       } else if (rssi > BCM2048_RSSI_LEVEL_ROOF) {
+                               tuner->signal = (rssi +
+                                                BCM2048_RSSI_LEVEL_ROOF_NEG)
+                                                * BCM2048_SIGNAL_MULTIPLIER;
+                       } else {
+                               tuner->signal = 0;
+                       }
+               }
+       } else {
+               tuner->signal = 0;
+       }
+
+       return 0;
+}
+
+static int bcm2048_vidioc_s_tuner(struct file *file, void *priv,
+               const struct v4l2_tuner *tuner)
+{
+       struct bcm2048_device *bdev = video_get_drvdata(video_devdata(file));
+
+       if (!bdev)
+               return -ENODEV;
+
+       if (tuner->index > 0)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int bcm2048_vidioc_g_frequency(struct file *file, void *priv,
+               struct v4l2_frequency *freq)
+{
+       struct bcm2048_device *bdev = video_get_drvdata(video_devdata(file));
+       int err = 0;
+       int f;
+
+       if (!bdev->power_state)
+               return -ENODEV;
+
+       freq->type = V4L2_TUNER_RADIO;
+       f = bcm2048_get_fm_frequency(bdev);
+
+       if (f < 0)
+               err = f;
+       else
+               freq->frequency = dev_to_v4l2(f);
+
+       return err;
+}
+
+static int bcm2048_vidioc_s_frequency(struct file *file, void *priv,
+               const struct v4l2_frequency *freq)
+{
+       struct bcm2048_device *bdev = video_get_drvdata(video_devdata(file));
+       int err;
+
+       if (freq->type != V4L2_TUNER_RADIO)
+               return -EINVAL;
+
+       if (!bdev->power_state)
+               return -ENODEV;
+
+       err = bcm2048_set_fm_frequency(bdev, v4l2_to_dev(freq->frequency));
+       err |= bcm2048_set_fm_search_tune_mode(bdev, BCM2048_FM_PRE_SET_MODE);
+
+       return err;
+}
+
+static int bcm2048_vidioc_s_hw_freq_seek(struct file *file, void *priv,
+                                       const struct v4l2_hw_freq_seek *seek)
+{
+       struct bcm2048_device *bdev = video_get_drvdata(video_devdata(file));
+       int err;
+
+       if (!bdev->power_state)
+               return -ENODEV;
+
+       if ((seek->tuner != 0) || (seek->type != V4L2_TUNER_RADIO))
+               return -EINVAL;
+
+       err = bcm2048_set_fm_search_mode_direction(bdev, seek->seek_upward);
+       err |= bcm2048_set_fm_search_tune_mode(bdev,
+                       BCM2048_FM_AUTO_SEARCH_MODE);
+
+       return err;
+}
+
+static struct v4l2_ioctl_ops bcm2048_ioctl_ops = {
+       .vidioc_querycap        = bcm2048_vidioc_querycap,
+       .vidioc_g_input         = bcm2048_vidioc_g_input,
+       .vidioc_s_input         = bcm2048_vidioc_s_input,
+       .vidioc_queryctrl       = bcm2048_vidioc_queryctrl,
+       .vidioc_g_ctrl          = bcm2048_vidioc_g_ctrl,
+       .vidioc_s_ctrl          = bcm2048_vidioc_s_ctrl,
+       .vidioc_g_audio         = bcm2048_vidioc_g_audio,
+       .vidioc_s_audio         = bcm2048_vidioc_s_audio,
+       .vidioc_g_tuner         = bcm2048_vidioc_g_tuner,
+       .vidioc_s_tuner         = bcm2048_vidioc_s_tuner,
+       .vidioc_g_frequency     = bcm2048_vidioc_g_frequency,
+       .vidioc_s_frequency     = bcm2048_vidioc_s_frequency,
+       .vidioc_s_hw_freq_seek  = bcm2048_vidioc_s_hw_freq_seek,
+};
+
+/*
+ * bcm2048_viddev_template - video device interface
+ */
+static struct video_device bcm2048_viddev_template = {
+       .fops                   = &bcm2048_fops,
+       .name                   = BCM2048_DRIVER_NAME,
+       .release                = video_device_release,
+       .ioctl_ops              = &bcm2048_ioctl_ops,
+};
+
+/*
+ *     I2C driver interface
+ */
+static int bcm2048_i2c_driver_probe(struct i2c_client *client,
+                                       const struct i2c_device_id *id)
+{
+       struct bcm2048_device *bdev;
+       int err, skip_release = 0;
+
+       bdev = kzalloc(sizeof(*bdev), GFP_KERNEL);
+       if (!bdev) {
+               dev_dbg(&client->dev, "Failed to alloc video device.\n");
+               err = -ENOMEM;
+               goto exit;
+       }
+
+       bdev->videodev = video_device_alloc();
+       if (!bdev->videodev) {
+               dev_dbg(&client->dev, "Failed to alloc video device.\n");
+               err = -ENOMEM;
+               goto free_bdev;
+       }
+
+       bdev->client = client;
+       i2c_set_clientdata(client, bdev);
+       mutex_init(&bdev->mutex);
+       init_completion(&bdev->compl);
+       INIT_WORK(&bdev->work, bcm2048_work);
+
+       if (client->irq) {
+               err = request_irq(client->irq,
+                       bcm2048_handler, IRQF_TRIGGER_FALLING | IRQF_DISABLED,
+                       client->name, bdev);
+               if (err < 0) {
+                       dev_err(&client->dev, "Could not request IRQ\n");
+                       goto free_vdev;
+               }
+               dev_dbg(&client->dev, "IRQ requested.\n");
+       } else {
+               dev_dbg(&client->dev, "IRQ not configured. Using timeouts.\n");
+       }
+
+       memcpy(bdev->videodev, &bcm2048_viddev_template,
+                       sizeof(bcm2048_viddev_template));
+       video_set_drvdata(bdev->videodev, bdev);
+       if (video_register_device(bdev->videodev, VFL_TYPE_RADIO, radio_nr)) {
+               dev_dbg(&client->dev, "Could not register video device.\n");
+               err = -EIO;
+               goto free_irq;
+       }
+
+       err = bcm2048_sysfs_register_properties(bdev);
+       if (err < 0) {
+               dev_dbg(&client->dev, "Could not register sysfs interface.\n");
+               goto free_registration;
+       }
+
+       err = bcm2048_probe(bdev);
+       if (err < 0) {
+               dev_dbg(&client->dev, "Failed to probe device information.\n");
+               goto free_sysfs;
+       }
+
+       return 0;
+
+free_sysfs:
+       bcm2048_sysfs_unregister_properties(bdev, ARRAY_SIZE(attrs));
+free_registration:
+       video_unregister_device(bdev->videodev);
+       /* video_unregister_device frees bdev->videodev */
+       bdev->videodev = NULL;
+       skip_release = 1;
+free_irq:
+       if (client->irq)
+               free_irq(client->irq, bdev);
+free_vdev:
+       if (!skip_release)
+               video_device_release(bdev->videodev);
+       i2c_set_clientdata(client, NULL);
+free_bdev:
+       kfree(bdev);
+exit:
+       return err;
+}
+
+static int __exit bcm2048_i2c_driver_remove(struct i2c_client *client)
+{
+       struct bcm2048_device *bdev = i2c_get_clientdata(client);
+       struct video_device *vd;
+
+       if (!client->adapter)
+               return -ENODEV;
+
+       if (bdev) {
+               vd = bdev->videodev;
+
+               bcm2048_sysfs_unregister_properties(bdev, ARRAY_SIZE(attrs));
+
+               if (vd)
+                       video_unregister_device(vd);
+
+               if (bdev->power_state)
+                       bcm2048_set_power_state(bdev, BCM2048_POWER_OFF);
+
+               if (client->irq > 0)
+                       free_irq(client->irq, bdev);
+
+               cancel_work_sync(&bdev->work);
+
+               kfree(bdev);
+       }
+
+       i2c_set_clientdata(client, NULL);
+
+       return 0;
+}
+
+/*
+ *     bcm2048_i2c_driver - i2c driver interface
+ */
+static const struct i2c_device_id bcm2048_id[] = {
+       { "bcm2048" , 0 },
+       { },
+};
+MODULE_DEVICE_TABLE(i2c, bcm2048_id);
+
+static struct i2c_driver bcm2048_i2c_driver = {
+       .driver         = {
+               .name   = BCM2048_DRIVER_NAME,
+       },
+       .probe          = bcm2048_i2c_driver_probe,
+       .remove         = __exit_p(bcm2048_i2c_driver_remove),
+       .id_table       = bcm2048_id,
+};
+
+/*
+ *     Module Interface
+ */
+static int __init bcm2048_module_init(void)
+{
+       pr_info(BCM2048_DRIVER_DESC "\n");
+
+       return i2c_add_driver(&bcm2048_i2c_driver);
+}
+module_init(bcm2048_module_init);
+
+static void __exit bcm2048_module_exit(void)
+{
+       i2c_del_driver(&bcm2048_i2c_driver);
+}
+module_exit(bcm2048_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR(BCM2048_DRIVER_AUTHOR);
+MODULE_DESCRIPTION(BCM2048_DRIVER_DESC);
+MODULE_VERSION("0.0.2");
diff --git a/drivers/staging/media/bcm2048/radio-bcm2048.h b/drivers/staging/media/bcm2048/radio-bcm2048.h
new file mode 100644 (file)
index 0000000..4c90a32
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * drivers/staging/media/radio-bcm2048.h
+ *
+ * Property and command definitions for bcm2048 radio receiver chip.
+ *
+ * Copyright (C) Nokia Corporation
+ * Contact: Eero Nurkkala <ext-eero.nurkkala@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef BCM2048_H
+#define BCM2048_H
+
+#define BCM2048_NAME           "bcm2048"
+#define BCM2048_I2C_ADDR       0x22
+
+#endif /* ifndef BCM2048_H */
diff --git a/drivers/staging/media/omap4iss/Kconfig b/drivers/staging/media/omap4iss/Kconfig
new file mode 100644 (file)
index 0000000..b9fe753
--- /dev/null
@@ -0,0 +1,12 @@
+config VIDEO_OMAP4
+       bool "OMAP 4 Camera support"
+       depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && I2C && ARCH_OMAP4
+       select VIDEOBUF2_DMA_CONTIG
+       ---help---
+         Driver for an OMAP 4 ISS controller.
+
+config VIDEO_OMAP4_DEBUG
+       bool "OMAP 4 Camera debug messages"
+       depends on VIDEO_OMAP4
+       ---help---
+         Enable debug messages on OMAP 4 ISS controller driver.
diff --git a/drivers/staging/media/omap4iss/Makefile b/drivers/staging/media/omap4iss/Makefile
new file mode 100644 (file)
index 0000000..a716ce9
--- /dev/null
@@ -0,0 +1,6 @@
+# Makefile for OMAP4 ISS driver
+
+omap4-iss-objs += \
+       iss.o iss_csi2.o iss_csiphy.o iss_ipipeif.o iss_ipipe.o iss_resizer.o iss_video.o
+
+obj-$(CONFIG_VIDEO_OMAP4) += omap4-iss.o
diff --git a/drivers/staging/media/omap4iss/TODO b/drivers/staging/media/omap4iss/TODO
new file mode 100644 (file)
index 0000000..fcde888
--- /dev/null
@@ -0,0 +1,4 @@
+* Make the driver compile as a module
+* Fix FIFO/buffer overflows and underflows
+* Replace dummy resizer code with a real implementation
+* Fix checkpatch errors and warnings
diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c
new file mode 100644 (file)
index 0000000..b7c8a6b
--- /dev/null
@@ -0,0 +1,1462 @@
+/*
+ * TI OMAP4 ISS V4L2 Driver
+ *
+ * Copyright (C) 2012, Texas Instruments
+ *
+ * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/vmalloc.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+
+#include "iss.h"
+#include "iss_regs.h"
+
+#define ISS_PRINT_REGISTER(iss, name)\
+       dev_dbg(iss->dev, "###ISS " #name "=0x%08x\n", \
+               readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_##name))
+
+static void iss_print_status(struct iss_device *iss)
+{
+       dev_dbg(iss->dev, "-------------ISS HL Register dump-------------\n");
+
+       ISS_PRINT_REGISTER(iss, HL_REVISION);
+       ISS_PRINT_REGISTER(iss, HL_SYSCONFIG);
+       ISS_PRINT_REGISTER(iss, HL_IRQSTATUS_5);
+       ISS_PRINT_REGISTER(iss, HL_IRQENABLE_5_SET);
+       ISS_PRINT_REGISTER(iss, HL_IRQENABLE_5_CLR);
+       ISS_PRINT_REGISTER(iss, CTRL);
+       ISS_PRINT_REGISTER(iss, CLKCTRL);
+       ISS_PRINT_REGISTER(iss, CLKSTAT);
+
+       dev_dbg(iss->dev, "-----------------------------------------------\n");
+}
+
+/*
+ * omap4iss_flush - Post pending L3 bus writes by doing a register readback
+ * @iss: OMAP4 ISS device
+ *
+ * In order to force posting of pending writes, we need to write and
+ * readback the same register, in this case the revision register.
+ *
+ * See this link for reference:
+ *   http://www.mail-archive.com/linux-omap@vger.kernel.org/msg08149.html
+ */
+void omap4iss_flush(struct iss_device *iss)
+{
+       writel(0, iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_REVISION);
+       readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_REVISION);
+}
+
+/*
+ * iss_enable_interrupts - Enable ISS interrupts.
+ * @iss: OMAP4 ISS device
+ */
+static void iss_enable_interrupts(struct iss_device *iss)
+{
+       static const u32 hl_irq = ISS_HL_IRQ_CSIA | ISS_HL_IRQ_CSIB | ISS_HL_IRQ_ISP(0);
+
+       /* Enable HL interrupts */
+       writel(hl_irq, iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_IRQSTATUS_5);
+       writel(hl_irq, iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_IRQENABLE_5_SET);
+
+}
+
+/*
+ * iss_disable_interrupts - Disable ISS interrupts.
+ * @iss: OMAP4 ISS device
+ */
+static void iss_disable_interrupts(struct iss_device *iss)
+{
+       writel(-1, iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_IRQENABLE_5_CLR);
+}
+
+/*
+ * iss_isp_enable_interrupts - Enable ISS ISP interrupts.
+ * @iss: OMAP4 ISS device
+ */
+void omap4iss_isp_enable_interrupts(struct iss_device *iss)
+{
+       static const u32 isp_irq = ISP5_IRQ_OCP_ERR |
+                                  ISP5_IRQ_RSZ_FIFO_IN_BLK |
+                                  ISP5_IRQ_RSZ_FIFO_OVF |
+                                  ISP5_IRQ_RSZ_INT_DMA |
+                                  ISP5_IRQ_ISIF0;
+
+       /* Enable ISP interrupts */
+       writel(isp_irq, iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_IRQSTATUS(0));
+       writel(isp_irq, iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_IRQENABLE_SET(0));
+}
+
+/*
+ * iss_isp_disable_interrupts - Disable ISS interrupts.
+ * @iss: OMAP4 ISS device
+ */
+void omap4iss_isp_disable_interrupts(struct iss_device *iss)
+{
+       writel(-1, iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_IRQENABLE_CLR(0));
+}
+
+int omap4iss_get_external_info(struct iss_pipeline *pipe,
+                              struct media_link *link)
+{
+       struct iss_device *iss =
+               container_of(pipe, struct iss_video, pipe)->iss;
+       struct v4l2_subdev_format fmt;
+       struct v4l2_ctrl *ctrl;
+       int ret;
+
+       if (!pipe->external)
+               return 0;
+
+       if (pipe->external_rate)
+               return 0;
+
+       memset(&fmt, 0, sizeof(fmt));
+
+       fmt.pad = link->source->index;
+       fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+       ret = v4l2_subdev_call(media_entity_to_v4l2_subdev(link->sink->entity),
+                              pad, get_fmt, NULL, &fmt);
+       if (ret < 0)
+               return -EPIPE;
+
+       pipe->external_bpp = omap4iss_video_format_info(fmt.format.code)->bpp;
+
+       ctrl = v4l2_ctrl_find(pipe->external->ctrl_handler,
+                             V4L2_CID_PIXEL_RATE);
+       if (ctrl == NULL) {
+               dev_warn(iss->dev, "no pixel rate control in subdev %s\n",
+                        pipe->external->name);
+               return -EPIPE;
+       }
+
+       pipe->external_rate = v4l2_ctrl_g_ctrl_int64(ctrl);
+
+       return 0;
+}
+
+/*
+ * Configure the bridge. Valid inputs are
+ *
+ * IPIPEIF_INPUT_CSI2A: CSI2a receiver
+ * IPIPEIF_INPUT_CSI2B: CSI2b receiver
+ *
+ * The bridge and lane shifter are configured according to the selected input
+ * and the ISP platform data.
+ */
+void omap4iss_configure_bridge(struct iss_device *iss,
+                              enum ipipeif_input_entity input)
+{
+       u32 issctrl_val;
+       u32 isp5ctrl_val;
+
+       issctrl_val  = readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_CTRL);
+       issctrl_val &= ~ISS_CTRL_INPUT_SEL_MASK;
+       issctrl_val &= ~ISS_CTRL_CLK_DIV_MASK;
+
+       isp5ctrl_val  = readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_CTRL);
+
+       switch (input) {
+       case IPIPEIF_INPUT_CSI2A:
+               issctrl_val |= ISS_CTRL_INPUT_SEL_CSI2A;
+               break;
+
+       case IPIPEIF_INPUT_CSI2B:
+               issctrl_val |= ISS_CTRL_INPUT_SEL_CSI2B;
+               break;
+
+       default:
+               return;
+       }
+
+       issctrl_val |= ISS_CTRL_SYNC_DETECT_VS_RAISING;
+
+       isp5ctrl_val |= ISP5_CTRL_VD_PULSE_EXT | ISP5_CTRL_PSYNC_CLK_SEL |
+                       ISP5_CTRL_SYNC_ENABLE;
+
+       writel(issctrl_val, iss->regs[OMAP4_ISS_MEM_TOP] + ISS_CTRL);
+       writel(isp5ctrl_val, iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_CTRL);
+}
+
+static inline void iss_isr_dbg(struct iss_device *iss, u32 irqstatus)
+{
+       static const char *name[] = {
+               "ISP_IRQ0",
+               "ISP_IRQ1",
+               "ISP_IRQ2",
+               "ISP_IRQ3",
+               "CSIA_IRQ",
+               "CSIB_IRQ",
+               "CCP2_IRQ0",
+               "CCP2_IRQ1",
+               "CCP2_IRQ2",
+               "CCP2_IRQ3",
+               "CBUFF_IRQ",
+               "BTE_IRQ",
+               "SIMCOP_IRQ0",
+               "SIMCOP_IRQ1",
+               "SIMCOP_IRQ2",
+               "SIMCOP_IRQ3",
+               "CCP2_IRQ8",
+               "HS_VS_IRQ",
+               "res18",
+               "res19",
+               "res20",
+               "res21",
+               "res22",
+               "res23",
+               "res24",
+               "res25",
+               "res26",
+               "res27",
+               "res28",
+               "res29",
+               "res30",
+               "res31",
+       };
+       int i;
+
+       dev_dbg(iss->dev, "ISS IRQ: ");
+
+       for (i = 0; i < ARRAY_SIZE(name); i++) {
+               if ((1 << i) & irqstatus)
+                       pr_cont("%s ", name[i]);
+       }
+       pr_cont("\n");
+}
+
+/*
+ * iss_isr - Interrupt Service Routine for ISS module.
+ * @irq: Not used currently.
+ * @_iss: Pointer to the OMAP4 ISS device
+ *
+ * Handles the corresponding callback if plugged in.
+ *
+ * Returns IRQ_HANDLED when IRQ was correctly handled, or IRQ_NONE when the
+ * IRQ wasn't handled.
+ */
+static irqreturn_t iss_isr(int irq, void *_iss)
+{
+       static const u32 ipipeif_events = ISP5_IRQ_IPIPEIF |
+                                         ISP5_IRQ_ISIF0;
+       static const u32 resizer_events = ISP5_IRQ_RSZ_FIFO_IN_BLK |
+                                         ISP5_IRQ_RSZ_FIFO_OVF |
+                                         ISP5_IRQ_RSZ_INT_DMA;
+       struct iss_device *iss = _iss;
+       u32 irqstatus;
+
+       irqstatus = readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_IRQSTATUS_5);
+       writel(irqstatus, iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_IRQSTATUS_5);
+
+       if (irqstatus & ISS_HL_IRQ_CSIA)
+               omap4iss_csi2_isr(&iss->csi2a);
+
+       if (irqstatus & ISS_HL_IRQ_CSIB)
+               omap4iss_csi2_isr(&iss->csi2b);
+
+       if (irqstatus & ISS_HL_IRQ_ISP(0)) {
+               u32 isp_irqstatus = readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] +
+                                         ISP5_IRQSTATUS(0));
+               writel(isp_irqstatus, iss->regs[OMAP4_ISS_MEM_ISP_SYS1] +
+                       ISP5_IRQSTATUS(0));
+
+               if (isp_irqstatus & ISP5_IRQ_OCP_ERR)
+                       dev_dbg(iss->dev, "ISP5 OCP Error!\n");
+
+               if (isp_irqstatus & ipipeif_events) {
+                       omap4iss_ipipeif_isr(&iss->ipipeif,
+                                            isp_irqstatus & ipipeif_events);
+               }
+
+               if (isp_irqstatus & resizer_events)
+                       omap4iss_resizer_isr(&iss->resizer,
+                                            isp_irqstatus & resizer_events);
+       }
+
+       omap4iss_flush(iss);
+
+#if defined(DEBUG) && defined(ISS_ISR_DEBUG)
+       iss_isr_dbg(iss, irqstatus);
+#endif
+
+       return IRQ_HANDLED;
+}
+
+/* -----------------------------------------------------------------------------
+ * Pipeline power management
+ *
+ * Entities must be powered up when part of a pipeline that contains at least
+ * one open video device node.
+ *
+ * To achieve this use the entity use_count field to track the number of users.
+ * For entities corresponding to video device nodes the use_count field stores
+ * the users count of the node. For entities corresponding to subdevs the
+ * use_count field stores the total number of users of all video device nodes
+ * in the pipeline.
+ *
+ * The omap4iss_pipeline_pm_use() function must be called in the open() and
+ * close() handlers of video device nodes. It increments or decrements the use
+ * count of all subdev entities in the pipeline.
+ *
+ * To react to link management on powered pipelines, the link setup notification
+ * callback updates the use count of all entities in the source and sink sides
+ * of the link.
+ */
+
+/*
+ * iss_pipeline_pm_use_count - Count the number of users of a pipeline
+ * @entity: The entity
+ *
+ * Return the total number of users of all video device nodes in the pipeline.
+ */
+static int iss_pipeline_pm_use_count(struct media_entity *entity)
+{
+       struct media_entity_graph graph;
+       int use = 0;
+
+       media_entity_graph_walk_start(&graph, entity);
+
+       while ((entity = media_entity_graph_walk_next(&graph))) {
+               if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+                       use += entity->use_count;
+       }
+
+       return use;
+}
+
+/*
+ * iss_pipeline_pm_power_one - Apply power change to an entity
+ * @entity: The entity
+ * @change: Use count change
+ *
+ * Change the entity use count by @change. If the entity is a subdev update its
+ * power state by calling the core::s_power operation when the use count goes
+ * from 0 to != 0 or from != 0 to 0.
+ *
+ * Return 0 on success or a negative error code on failure.
+ */
+static int iss_pipeline_pm_power_one(struct media_entity *entity, int change)
+{
+       struct v4l2_subdev *subdev;
+
+       subdev = media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV
+              ? media_entity_to_v4l2_subdev(entity) : NULL;
+
+       if (entity->use_count == 0 && change > 0 && subdev != NULL) {
+               int ret;
+
+               ret = v4l2_subdev_call(subdev, core, s_power, 1);
+               if (ret < 0 && ret != -ENOIOCTLCMD)
+                       return ret;
+       }
+
+       entity->use_count += change;
+       WARN_ON(entity->use_count < 0);
+
+       if (entity->use_count == 0 && change < 0 && subdev != NULL)
+               v4l2_subdev_call(subdev, core, s_power, 0);
+
+       return 0;
+}
+
+/*
+ * iss_pipeline_pm_power - Apply power change to all entities in a pipeline
+ * @entity: The entity
+ * @change: Use count change
+ *
+ * Walk the pipeline to update the use count and the power state of all non-node
+ * entities.
+ *
+ * Return 0 on success or a negative error code on failure.
+ */
+static int iss_pipeline_pm_power(struct media_entity *entity, int change)
+{
+       struct media_entity_graph graph;
+       struct media_entity *first = entity;
+       int ret = 0;
+
+       if (!change)
+               return 0;
+
+       media_entity_graph_walk_start(&graph, entity);
+
+       while (!ret && (entity = media_entity_graph_walk_next(&graph)))
+               if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+                       ret = iss_pipeline_pm_power_one(entity, change);
+
+       if (!ret)
+               return 0;
+
+       media_entity_graph_walk_start(&graph, first);
+
+       while ((first = media_entity_graph_walk_next(&graph))
+              && first != entity)
+               if (media_entity_type(first) != MEDIA_ENT_T_DEVNODE)
+                       iss_pipeline_pm_power_one(first, -change);
+
+       return ret;
+}
+
+/*
+ * omap4iss_pipeline_pm_use - Update the use count of an entity
+ * @entity: The entity
+ * @use: Use (1) or stop using (0) the entity
+ *
+ * Update the use count of all entities in the pipeline and power entities on or
+ * off accordingly.
+ *
+ * Return 0 on success or a negative error code on failure. Powering entities
+ * off is assumed to never fail. No failure can occur when the use parameter is
+ * set to 0.
+ */
+int omap4iss_pipeline_pm_use(struct media_entity *entity, int use)
+{
+       int change = use ? 1 : -1;
+       int ret;
+
+       mutex_lock(&entity->parent->graph_mutex);
+
+       /* Apply use count to node. */
+       entity->use_count += change;
+       WARN_ON(entity->use_count < 0);
+
+       /* Apply power change to connected non-nodes. */
+       ret = iss_pipeline_pm_power(entity, change);
+       if (ret < 0)
+               entity->use_count -= change;
+
+       mutex_unlock(&entity->parent->graph_mutex);
+
+       return ret;
+}
+
+/*
+ * iss_pipeline_link_notify - Link management notification callback
+ * @link: The link
+ * @flags: New link flags that will be applied
+ *
+ * React to link management on powered pipelines by updating the use count of
+ * all entities in the source and sink sides of the link. Entities are powered
+ * on or off accordingly.
+ *
+ * Return 0 on success or a negative error code on failure. Powering entities
+ * off is assumed to never fail. This function will not fail for disconnection
+ * events.
+ */
+static int iss_pipeline_link_notify(struct media_link *link, u32 flags,
+                                   unsigned int notification)
+{
+       struct media_entity *source = link->source->entity;
+       struct media_entity *sink = link->sink->entity;
+       int source_use = iss_pipeline_pm_use_count(source);
+       int sink_use = iss_pipeline_pm_use_count(sink);
+       int ret;
+
+       if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH &&
+           !(link->flags & MEDIA_LNK_FL_ENABLED)) {
+               /* Powering off entities is assumed to never fail. */
+               iss_pipeline_pm_power(source, -sink_use);
+               iss_pipeline_pm_power(sink, -source_use);
+               return 0;
+       }
+
+       if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH &&
+               (flags & MEDIA_LNK_FL_ENABLED)) {
+               ret = iss_pipeline_pm_power(source, sink_use);
+               if (ret < 0)
+                       return ret;
+
+               ret = iss_pipeline_pm_power(sink, source_use);
+               if (ret < 0)
+                       iss_pipeline_pm_power(source, -sink_use);
+
+               return ret;
+       }
+
+       return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Pipeline stream management
+ */
+
+/*
+ * iss_pipeline_enable - Enable streaming on a pipeline
+ * @pipe: ISS pipeline
+ * @mode: Stream mode (single shot or continuous)
+ *
+ * Walk the entities chain starting at the pipeline output video node and start
+ * all modules in the chain in the given mode.
+ *
+ * Return 0 if successful, or the return value of the failed video::s_stream
+ * operation otherwise.
+ */
+static int iss_pipeline_enable(struct iss_pipeline *pipe,
+                              enum iss_pipeline_stream_state mode)
+{
+       struct media_entity *entity;
+       struct media_pad *pad;
+       struct v4l2_subdev *subdev;
+       unsigned long flags;
+       int ret;
+
+       spin_lock_irqsave(&pipe->lock, flags);
+       pipe->state &= ~(ISS_PIPELINE_IDLE_INPUT | ISS_PIPELINE_IDLE_OUTPUT);
+       spin_unlock_irqrestore(&pipe->lock, flags);
+
+       pipe->do_propagation = false;
+
+       entity = &pipe->output->video.entity;
+       while (1) {
+               pad = &entity->pads[0];
+               if (!(pad->flags & MEDIA_PAD_FL_SINK))
+                       break;
+
+               pad = media_entity_remote_pad(pad);
+               if (pad == NULL ||
+                   media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+                       break;
+
+               entity = pad->entity;
+               subdev = media_entity_to_v4l2_subdev(entity);
+
+               ret = v4l2_subdev_call(subdev, video, s_stream, mode);
+               if (ret < 0 && ret != -ENOIOCTLCMD)
+                       return ret;
+       }
+       iss_print_status(pipe->output->iss);
+       return 0;
+}
+
+/*
+ * iss_pipeline_disable - Disable streaming on a pipeline
+ * @pipe: ISS pipeline
+ *
+ * Walk the entities chain starting at the pipeline output video node and stop
+ * all modules in the chain. Wait synchronously for the modules to be stopped if
+ * necessary.
+ */
+static int iss_pipeline_disable(struct iss_pipeline *pipe)
+{
+       struct media_entity *entity;
+       struct media_pad *pad;
+       struct v4l2_subdev *subdev;
+
+       entity = &pipe->output->video.entity;
+       while (1) {
+               pad = &entity->pads[0];
+               if (!(pad->flags & MEDIA_PAD_FL_SINK))
+                       break;
+
+               pad = media_entity_remote_pad(pad);
+               if (pad == NULL ||
+                   media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+                       break;
+
+               entity = pad->entity;
+               subdev = media_entity_to_v4l2_subdev(entity);
+
+               v4l2_subdev_call(subdev, video, s_stream, 0);
+       }
+
+       return 0;
+}
+
+/*
+ * omap4iss_pipeline_set_stream - Enable/disable streaming on a pipeline
+ * @pipe: ISS pipeline
+ * @state: Stream state (stopped, single shot or continuous)
+ *
+ * Set the pipeline to the given stream state. Pipelines can be started in
+ * single-shot or continuous mode.
+ *
+ * Return 0 if successful, or the return value of the failed video::s_stream
+ * operation otherwise. The pipeline state is not updated when the operation
+ * fails, except when stopping the pipeline.
+ */
+int omap4iss_pipeline_set_stream(struct iss_pipeline *pipe,
+                                enum iss_pipeline_stream_state state)
+{
+       int ret;
+
+       if (state == ISS_PIPELINE_STREAM_STOPPED)
+               ret = iss_pipeline_disable(pipe);
+       else
+               ret = iss_pipeline_enable(pipe, state);
+
+       if (ret == 0 || state == ISS_PIPELINE_STREAM_STOPPED)
+               pipe->stream_state = state;
+
+       return ret;
+}
+
+/*
+ * iss_pipeline_is_last - Verify if entity has an enabled link to the output
+ *                       video node
+ * @me: ISS module's media entity
+ *
+ * Returns 1 if the entity has an enabled link to the output video node or 0
+ * otherwise. It's true only while pipeline can have no more than one output
+ * node.
+ */
+static int iss_pipeline_is_last(struct media_entity *me)
+{
+       struct iss_pipeline *pipe;
+       struct media_pad *pad;
+
+       if (!me->pipe)
+               return 0;
+       pipe = to_iss_pipeline(me);
+       if (pipe->stream_state == ISS_PIPELINE_STREAM_STOPPED)
+               return 0;
+       pad = media_entity_remote_pad(&pipe->output->pad);
+       return pad->entity == me;
+}
+
+static int iss_reset(struct iss_device *iss)
+{
+       unsigned long timeout = 0;
+
+       writel(readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_SYSCONFIG) |
+               ISS_HL_SYSCONFIG_SOFTRESET,
+               iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_SYSCONFIG);
+
+       while (readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_SYSCONFIG) &
+                       ISS_HL_SYSCONFIG_SOFTRESET) {
+               if (timeout++ > 100) {
+                       dev_alert(iss->dev, "cannot reset ISS\n");
+                       return -ETIMEDOUT;
+               }
+               usleep_range(10, 10);
+       }
+
+       return 0;
+}
+
+static int iss_isp_reset(struct iss_device *iss)
+{
+       unsigned long timeout = 0;
+
+       /* Fist, ensure that the ISP is IDLE (no transactions happening) */
+       writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_SYSCONFIG) &
+               ~ISP5_SYSCONFIG_STANDBYMODE_MASK) |
+               ISP5_SYSCONFIG_STANDBYMODE_SMART,
+               iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_SYSCONFIG);
+
+       writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_CTRL) |
+               ISP5_CTRL_MSTANDBY,
+               iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_CTRL);
+
+       for (;;) {
+               if (readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_CTRL) &
+                               ISP5_CTRL_MSTANDBY_WAIT)
+                       break;
+               if (timeout++ > 1000) {
+                       dev_alert(iss->dev, "cannot set ISP5 to standby\n");
+                       return -ETIMEDOUT;
+               }
+               usleep_range(1000, 1500);
+       }
+
+       /* Now finally, do the reset */
+       writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_SYSCONFIG) |
+               ISP5_SYSCONFIG_SOFTRESET,
+               iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_SYSCONFIG);
+
+       timeout = 0;
+       while (readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_SYSCONFIG) &
+                       ISP5_SYSCONFIG_SOFTRESET) {
+               if (timeout++ > 1000) {
+                       dev_alert(iss->dev, "cannot reset ISP5\n");
+                       return -ETIMEDOUT;
+               }
+               usleep_range(1000, 1500);
+       }
+
+       return 0;
+}
+
+/*
+ * iss_module_sync_idle - Helper to sync module with its idle state
+ * @me: ISS submodule's media entity
+ * @wait: ISS submodule's wait queue for streamoff/interrupt synchronization
+ * @stopping: flag which tells module wants to stop
+ *
+ * This function checks if ISS submodule needs to wait for next interrupt. If
+ * yes, makes the caller to sleep while waiting for such event.
+ */
+int omap4iss_module_sync_idle(struct media_entity *me, wait_queue_head_t *wait,
+                             atomic_t *stopping)
+{
+       struct iss_pipeline *pipe = to_iss_pipeline(me);
+       struct iss_video *video = pipe->output;
+       unsigned long flags;
+
+       if (pipe->stream_state == ISS_PIPELINE_STREAM_STOPPED ||
+           (pipe->stream_state == ISS_PIPELINE_STREAM_SINGLESHOT &&
+            !iss_pipeline_ready(pipe)))
+               return 0;
+
+       /*
+        * atomic_set() doesn't include memory barrier on ARM platform for SMP
+        * scenario. We'll call it here to avoid race conditions.
+        */
+       atomic_set(stopping, 1);
+       smp_wmb();
+
+       /*
+        * If module is the last one, it's writing to memory. In this case,
+        * it's necessary to check if the module is already paused due to
+        * DMA queue underrun or if it has to wait for next interrupt to be
+        * idle.
+        * If it isn't the last one, the function won't sleep but *stopping
+        * will still be set to warn next submodule caller's interrupt the
+        * module wants to be idle.
+        */
+       if (!iss_pipeline_is_last(me))
+               return 0;
+
+       spin_lock_irqsave(&video->qlock, flags);
+       if (video->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_UNDERRUN) {
+               spin_unlock_irqrestore(&video->qlock, flags);
+               atomic_set(stopping, 0);
+               smp_wmb();
+               return 0;
+       }
+       spin_unlock_irqrestore(&video->qlock, flags);
+       if (!wait_event_timeout(*wait, !atomic_read(stopping),
+                               msecs_to_jiffies(1000))) {
+               atomic_set(stopping, 0);
+               smp_wmb();
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+/*
+ * omap4iss_module_sync_is_stopped - Helper to verify if module was stopping
+ * @wait: ISS submodule's wait queue for streamoff/interrupt synchronization
+ * @stopping: flag which tells module wants to stop
+ *
+ * This function checks if ISS submodule was stopping. In case of yes, it
+ * notices the caller by setting stopping to 0 and waking up the wait queue.
+ * Returns 1 if it was stopping or 0 otherwise.
+ */
+int omap4iss_module_sync_is_stopping(wait_queue_head_t *wait,
+                                    atomic_t *stopping)
+{
+       if (atomic_cmpxchg(stopping, 1, 0)) {
+               wake_up(wait);
+               return 1;
+       }
+
+       return 0;
+}
+
+/* --------------------------------------------------------------------------
+ * Clock management
+ */
+
+#define ISS_CLKCTRL_MASK       (ISS_CLKCTRL_CSI2_A |\
+                                ISS_CLKCTRL_CSI2_B |\
+                                ISS_CLKCTRL_ISP)
+
+static int __iss_subclk_update(struct iss_device *iss)
+{
+       u32 clk = 0;
+       int ret = 0, timeout = 1000;
+
+       if (iss->subclk_resources & OMAP4_ISS_SUBCLK_CSI2_A)
+               clk |= ISS_CLKCTRL_CSI2_A;
+
+       if (iss->subclk_resources & OMAP4_ISS_SUBCLK_CSI2_B)
+               clk |= ISS_CLKCTRL_CSI2_B;
+
+       if (iss->subclk_resources & OMAP4_ISS_SUBCLK_ISP)
+               clk |= ISS_CLKCTRL_ISP;
+
+       writel((readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_CLKCTRL) &
+               ~ISS_CLKCTRL_MASK) | clk,
+               iss->regs[OMAP4_ISS_MEM_TOP] + ISS_CLKCTRL);
+
+       /* Wait for HW assertion */
+       while (--timeout > 0) {
+               udelay(1);
+               if ((readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_CLKSTAT) &
+                    ISS_CLKCTRL_MASK) == clk)
+                       break;
+       }
+
+       if (!timeout)
+               ret = -EBUSY;
+
+       return ret;
+}
+
+int omap4iss_subclk_enable(struct iss_device *iss,
+                           enum iss_subclk_resource res)
+{
+       iss->subclk_resources |= res;
+
+       return __iss_subclk_update(iss);
+}
+
+int omap4iss_subclk_disable(struct iss_device *iss,
+                            enum iss_subclk_resource res)
+{
+       iss->subclk_resources &= ~res;
+
+       return __iss_subclk_update(iss);
+}
+
+#define ISS_ISP5_CLKCTRL_MASK  (ISP5_CTRL_BL_CLK_ENABLE |\
+                                ISP5_CTRL_ISIF_CLK_ENABLE |\
+                                ISP5_CTRL_H3A_CLK_ENABLE |\
+                                ISP5_CTRL_RSZ_CLK_ENABLE |\
+                                ISP5_CTRL_IPIPE_CLK_ENABLE |\
+                                ISP5_CTRL_IPIPEIF_CLK_ENABLE)
+
+static void __iss_isp_subclk_update(struct iss_device *iss)
+{
+       u32 clk = 0;
+
+       if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_ISIF)
+               clk |= ISP5_CTRL_ISIF_CLK_ENABLE;
+
+       if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_H3A)
+               clk |= ISP5_CTRL_H3A_CLK_ENABLE;
+
+       if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_RSZ)
+               clk |= ISP5_CTRL_RSZ_CLK_ENABLE;
+
+       if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_IPIPE)
+               clk |= ISP5_CTRL_IPIPE_CLK_ENABLE;
+
+       if (iss->isp_subclk_resources & OMAP4_ISS_ISP_SUBCLK_IPIPEIF)
+               clk |= ISP5_CTRL_IPIPEIF_CLK_ENABLE;
+
+       if (clk)
+               clk |= ISP5_CTRL_BL_CLK_ENABLE;
+
+       writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_CTRL) &
+               ~ISS_ISP5_CLKCTRL_MASK) | clk,
+               iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_CTRL);
+}
+
+void omap4iss_isp_subclk_enable(struct iss_device *iss,
+                               enum iss_isp_subclk_resource res)
+{
+       iss->isp_subclk_resources |= res;
+
+       __iss_isp_subclk_update(iss);
+}
+
+void omap4iss_isp_subclk_disable(struct iss_device *iss,
+                                enum iss_isp_subclk_resource res)
+{
+       iss->isp_subclk_resources &= ~res;
+
+       __iss_isp_subclk_update(iss);
+}
+
+/*
+ * iss_enable_clocks - Enable ISS clocks
+ * @iss: OMAP4 ISS device
+ *
+ * Return 0 if successful, or clk_enable return value if any of tthem fails.
+ */
+static int iss_enable_clocks(struct iss_device *iss)
+{
+       int ret;
+
+       ret = clk_enable(iss->iss_fck);
+       if (ret) {
+               dev_err(iss->dev, "clk_enable iss_fck failed\n");
+               return ret;
+       }
+
+       ret = clk_enable(iss->iss_ctrlclk);
+       if (ret) {
+               dev_err(iss->dev, "clk_enable iss_ctrlclk failed\n");
+               clk_disable(iss->iss_fck);
+               return ret;
+       }
+
+       return 0;
+}
+
+/*
+ * iss_disable_clocks - Disable ISS clocks
+ * @iss: OMAP4 ISS device
+ */
+static void iss_disable_clocks(struct iss_device *iss)
+{
+       clk_disable(iss->iss_ctrlclk);
+       clk_disable(iss->iss_fck);
+}
+
+static void iss_put_clocks(struct iss_device *iss)
+{
+       if (iss->iss_fck) {
+               clk_put(iss->iss_fck);
+               iss->iss_fck = NULL;
+       }
+
+       if (iss->iss_ctrlclk) {
+               clk_put(iss->iss_ctrlclk);
+               iss->iss_ctrlclk = NULL;
+       }
+}
+
+static int iss_get_clocks(struct iss_device *iss)
+{
+       iss->iss_fck = clk_get(iss->dev, "iss_fck");
+       if (IS_ERR(iss->iss_fck)) {
+               dev_err(iss->dev, "Unable to get iss_fck clock info\n");
+               iss_put_clocks(iss);
+               return PTR_ERR(iss->iss_fck);
+       }
+
+       iss->iss_ctrlclk = clk_get(iss->dev, "iss_ctrlclk");
+       if (IS_ERR(iss->iss_ctrlclk)) {
+               dev_err(iss->dev, "Unable to get iss_ctrlclk clock info\n");
+               iss_put_clocks(iss);
+               return PTR_ERR(iss->iss_fck);
+       }
+
+       return 0;
+}
+
+/*
+ * omap4iss_get - Acquire the ISS resource.
+ *
+ * Initializes the clocks for the first acquire.
+ *
+ * Increment the reference count on the ISS. If the first reference is taken,
+ * enable clocks and power-up all submodules.
+ *
+ * Return a pointer to the ISS device structure, or NULL if an error occurred.
+ */
+struct iss_device *omap4iss_get(struct iss_device *iss)
+{
+       struct iss_device *__iss = iss;
+
+       if (iss == NULL)
+               return NULL;
+
+       mutex_lock(&iss->iss_mutex);
+       if (iss->ref_count > 0)
+               goto out;
+
+       if (iss_enable_clocks(iss) < 0) {
+               __iss = NULL;
+               goto out;
+       }
+
+       iss_enable_interrupts(iss);
+
+out:
+       if (__iss != NULL)
+               iss->ref_count++;
+       mutex_unlock(&iss->iss_mutex);
+
+       return __iss;
+}
+
+/*
+ * omap4iss_put - Release the ISS
+ *
+ * Decrement the reference count on the ISS. If the last reference is released,
+ * power-down all submodules, disable clocks and free temporary buffers.
+ */
+void omap4iss_put(struct iss_device *iss)
+{
+       if (iss == NULL)
+               return;
+
+       mutex_lock(&iss->iss_mutex);
+       BUG_ON(iss->ref_count == 0);
+       if (--iss->ref_count == 0) {
+               iss_disable_interrupts(iss);
+               iss_disable_clocks(iss);
+       }
+       mutex_unlock(&iss->iss_mutex);
+}
+
+static int iss_map_mem_resource(struct platform_device *pdev,
+                               struct iss_device *iss,
+                               enum iss_mem_resources res)
+{
+       struct resource *mem;
+
+       /* request the mem region for the camera registers */
+
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, res);
+       if (!mem) {
+               dev_err(iss->dev, "no mem resource?\n");
+               return -ENODEV;
+       }
+
+       if (!request_mem_region(mem->start, resource_size(mem), pdev->name)) {
+               dev_err(iss->dev,
+                       "cannot reserve camera register I/O region\n");
+               return -ENODEV;
+       }
+       iss->res[res] = mem;
+
+       /* map the region */
+       iss->regs[res] = ioremap_nocache(mem->start, resource_size(mem));
+       if (!iss->regs[res]) {
+               dev_err(iss->dev, "cannot map camera register I/O region\n");
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static void iss_unregister_entities(struct iss_device *iss)
+{
+       omap4iss_resizer_unregister_entities(&iss->resizer);
+       omap4iss_ipipe_unregister_entities(&iss->ipipe);
+       omap4iss_ipipeif_unregister_entities(&iss->ipipeif);
+       omap4iss_csi2_unregister_entities(&iss->csi2a);
+       omap4iss_csi2_unregister_entities(&iss->csi2b);
+
+       v4l2_device_unregister(&iss->v4l2_dev);
+       media_device_unregister(&iss->media_dev);
+}
+
+/*
+ * iss_register_subdev_group - Register a group of subdevices
+ * @iss: OMAP4 ISS device
+ * @board_info: I2C subdevs board information array
+ *
+ * Register all I2C subdevices in the board_info array. The array must be
+ * terminated by a NULL entry, and the first entry must be the sensor.
+ *
+ * Return a pointer to the sensor media entity if it has been successfully
+ * registered, or NULL otherwise.
+ */
+static struct v4l2_subdev *
+iss_register_subdev_group(struct iss_device *iss,
+                    struct iss_subdev_i2c_board_info *board_info)
+{
+       struct v4l2_subdev *sensor = NULL;
+       unsigned int first;
+
+       if (board_info->board_info == NULL)
+               return NULL;
+
+       for (first = 1; board_info->board_info; ++board_info, first = 0) {
+               struct v4l2_subdev *subdev;
+               struct i2c_adapter *adapter;
+
+               adapter = i2c_get_adapter(board_info->i2c_adapter_id);
+               if (adapter == NULL) {
+                       dev_err(iss->dev, "%s: Unable to get I2C adapter %d for "
+                               "device %s\n", __func__,
+                               board_info->i2c_adapter_id,
+                               board_info->board_info->type);
+                       continue;
+               }
+
+               subdev = v4l2_i2c_new_subdev_board(&iss->v4l2_dev, adapter,
+                               board_info->board_info, NULL);
+               if (subdev == NULL) {
+                       dev_err(iss->dev, "%s: Unable to register subdev %s\n",
+                               __func__, board_info->board_info->type);
+                       continue;
+               }
+
+               if (first)
+                       sensor = subdev;
+       }
+
+       return sensor;
+}
+
+static int iss_register_entities(struct iss_device *iss)
+{
+       struct iss_platform_data *pdata = iss->pdata;
+       struct iss_v4l2_subdevs_group *subdevs;
+       int ret;
+
+       iss->media_dev.dev = iss->dev;
+       strlcpy(iss->media_dev.model, "TI OMAP4 ISS",
+               sizeof(iss->media_dev.model));
+       iss->media_dev.hw_revision = iss->revision;
+       iss->media_dev.link_notify = iss_pipeline_link_notify;
+       ret = media_device_register(&iss->media_dev);
+       if (ret < 0) {
+               printk(KERN_ERR "%s: Media device registration failed (%d)\n",
+                       __func__, ret);
+               return ret;
+       }
+
+       iss->v4l2_dev.mdev = &iss->media_dev;
+       ret = v4l2_device_register(iss->dev, &iss->v4l2_dev);
+       if (ret < 0) {
+               printk(KERN_ERR "%s: V4L2 device registration failed (%d)\n",
+                       __func__, ret);
+               goto done;
+       }
+
+       /* Register internal entities */
+       ret = omap4iss_csi2_register_entities(&iss->csi2a, &iss->v4l2_dev);
+       if (ret < 0)
+               goto done;
+
+       ret = omap4iss_csi2_register_entities(&iss->csi2b, &iss->v4l2_dev);
+       if (ret < 0)
+               goto done;
+
+       ret = omap4iss_ipipeif_register_entities(&iss->ipipeif, &iss->v4l2_dev);
+       if (ret < 0)
+               goto done;
+
+       ret = omap4iss_ipipe_register_entities(&iss->ipipe, &iss->v4l2_dev);
+       if (ret < 0)
+               goto done;
+
+       ret = omap4iss_resizer_register_entities(&iss->resizer, &iss->v4l2_dev);
+       if (ret < 0)
+               goto done;
+
+       /* Register external entities */
+       for (subdevs = pdata->subdevs; subdevs && subdevs->subdevs; ++subdevs) {
+               struct v4l2_subdev *sensor;
+               struct media_entity *input;
+               unsigned int flags;
+               unsigned int pad;
+
+               sensor = iss_register_subdev_group(iss, subdevs->subdevs);
+               if (sensor == NULL)
+                       continue;
+
+               sensor->host_priv = subdevs;
+
+               /* Connect the sensor to the correct interface module.
+                * CSI2a receiver through CSIPHY1, or
+                * CSI2b receiver through CSIPHY2
+                */
+               switch (subdevs->interface) {
+               case ISS_INTERFACE_CSI2A_PHY1:
+                       input = &iss->csi2a.subdev.entity;
+                       pad = CSI2_PAD_SINK;
+                       flags = MEDIA_LNK_FL_IMMUTABLE
+                             | MEDIA_LNK_FL_ENABLED;
+                       break;
+
+               case ISS_INTERFACE_CSI2B_PHY2:
+                       input = &iss->csi2b.subdev.entity;
+                       pad = CSI2_PAD_SINK;
+                       flags = MEDIA_LNK_FL_IMMUTABLE
+                             | MEDIA_LNK_FL_ENABLED;
+                       break;
+
+               default:
+                       printk(KERN_ERR "%s: invalid interface type %u\n",
+                              __func__, subdevs->interface);
+                       ret = -EINVAL;
+                       goto done;
+               }
+
+               ret = media_entity_create_link(&sensor->entity, 0, input, pad,
+                                              flags);
+               if (ret < 0)
+                       goto done;
+       }
+
+       ret = v4l2_device_register_subdev_nodes(&iss->v4l2_dev);
+
+done:
+       if (ret < 0)
+               iss_unregister_entities(iss);
+
+       return ret;
+}
+
+static void iss_cleanup_modules(struct iss_device *iss)
+{
+       omap4iss_csi2_cleanup(iss);
+       omap4iss_ipipeif_cleanup(iss);
+       omap4iss_ipipe_cleanup(iss);
+       omap4iss_resizer_cleanup(iss);
+}
+
+static int iss_initialize_modules(struct iss_device *iss)
+{
+       int ret;
+
+       ret = omap4iss_csiphy_init(iss);
+       if (ret < 0) {
+               dev_err(iss->dev, "CSI PHY initialization failed\n");
+               goto error_csiphy;
+       }
+
+       ret = omap4iss_csi2_init(iss);
+       if (ret < 0) {
+               dev_err(iss->dev, "CSI2 initialization failed\n");
+               goto error_csi2;
+       }
+
+       ret = omap4iss_ipipeif_init(iss);
+       if (ret < 0) {
+               dev_err(iss->dev, "ISP IPIPEIF initialization failed\n");
+               goto error_ipipeif;
+       }
+
+       ret = omap4iss_ipipe_init(iss);
+       if (ret < 0) {
+               dev_err(iss->dev, "ISP IPIPE initialization failed\n");
+               goto error_ipipe;
+       }
+
+       ret = omap4iss_resizer_init(iss);
+       if (ret < 0) {
+               dev_err(iss->dev, "ISP RESIZER initialization failed\n");
+               goto error_resizer;
+       }
+
+       /* Connect the submodules. */
+       ret = media_entity_create_link(
+                       &iss->csi2a.subdev.entity, CSI2_PAD_SOURCE,
+                       &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0);
+       if (ret < 0)
+               goto error_link;
+
+       ret = media_entity_create_link(
+                       &iss->csi2b.subdev.entity, CSI2_PAD_SOURCE,
+                       &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0);
+       if (ret < 0)
+               goto error_link;
+
+       ret = media_entity_create_link(
+                       &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP,
+                       &iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0);
+       if (ret < 0)
+               goto error_link;
+
+       ret = media_entity_create_link(
+                       &iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP,
+                       &iss->ipipe.subdev.entity, IPIPE_PAD_SINK, 0);
+       if (ret < 0)
+               goto error_link;
+
+       ret = media_entity_create_link(
+                       &iss->ipipe.subdev.entity, IPIPE_PAD_SOURCE_VP,
+                       &iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0);
+       if (ret < 0)
+               goto error_link;
+
+       return 0;
+
+error_link:
+       omap4iss_resizer_cleanup(iss);
+error_resizer:
+       omap4iss_ipipe_cleanup(iss);
+error_ipipe:
+       omap4iss_ipipeif_cleanup(iss);
+error_ipipeif:
+       omap4iss_csi2_cleanup(iss);
+error_csi2:
+error_csiphy:
+       return ret;
+}
+
+static int iss_probe(struct platform_device *pdev)
+{
+       struct iss_platform_data *pdata = pdev->dev.platform_data;
+       struct iss_device *iss;
+       unsigned int i;
+       int ret;
+
+       if (pdata == NULL)
+               return -EINVAL;
+
+       iss = kzalloc(sizeof(*iss), GFP_KERNEL);
+       if (!iss) {
+               dev_err(&pdev->dev, "Could not allocate memory\n");
+               return -ENOMEM;
+       }
+
+       mutex_init(&iss->iss_mutex);
+
+       iss->dev = &pdev->dev;
+       iss->pdata = pdata;
+
+       iss->raw_dmamask = DMA_BIT_MASK(32);
+       iss->dev->dma_mask = &iss->raw_dmamask;
+       iss->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+
+       platform_set_drvdata(pdev, iss);
+
+       /* Clocks */
+       ret = iss_map_mem_resource(pdev, iss, OMAP4_ISS_MEM_TOP);
+       if (ret < 0)
+               goto error;
+
+       ret = iss_get_clocks(iss);
+       if (ret < 0)
+               goto error;
+
+       if (omap4iss_get(iss) == NULL)
+               goto error;
+
+       ret = iss_reset(iss);
+       if (ret < 0)
+               goto error_iss;
+
+       iss->revision = readl(iss->regs[OMAP4_ISS_MEM_TOP] + ISS_HL_REVISION);
+       dev_info(iss->dev, "Revision %08x found\n", iss->revision);
+
+       for (i = 1; i < OMAP4_ISS_MEM_LAST; i++) {
+               ret = iss_map_mem_resource(pdev, iss, i);
+               if (ret)
+                       goto error_iss;
+       }
+
+       /* Configure BTE BW_LIMITER field to max recommended value (1 GB) */
+       writel((readl(iss->regs[OMAP4_ISS_MEM_BTE] + BTE_CTRL) & ~BTE_CTRL_BW_LIMITER_MASK) |
+               (18 << BTE_CTRL_BW_LIMITER_SHIFT),
+               iss->regs[OMAP4_ISS_MEM_BTE] + BTE_CTRL);
+
+       /* Perform ISP reset */
+       ret = omap4iss_subclk_enable(iss, OMAP4_ISS_SUBCLK_ISP);
+       if (ret < 0)
+               goto error_iss;
+
+       ret = iss_isp_reset(iss);
+       if (ret < 0)
+               goto error_iss;
+
+       dev_info(iss->dev, "ISP Revision %08x found\n",
+                readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_REVISION));
+
+       /* Interrupt */
+       iss->irq_num = platform_get_irq(pdev, 0);
+       if (iss->irq_num <= 0) {
+               dev_err(iss->dev, "No IRQ resource\n");
+               ret = -ENODEV;
+               goto error_iss;
+       }
+
+       if (request_irq(iss->irq_num, iss_isr, IRQF_SHARED, "OMAP4 ISS", iss)) {
+               dev_err(iss->dev, "Unable to request IRQ\n");
+               ret = -EINVAL;
+               goto error_iss;
+       }
+
+       /* Entities */
+       ret = iss_initialize_modules(iss);
+       if (ret < 0)
+               goto error_irq;
+
+       ret = iss_register_entities(iss);
+       if (ret < 0)
+               goto error_modules;
+
+       omap4iss_put(iss);
+
+       return 0;
+
+error_modules:
+       iss_cleanup_modules(iss);
+error_irq:
+       free_irq(iss->irq_num, iss);
+error_iss:
+       omap4iss_put(iss);
+error:
+       iss_put_clocks(iss);
+
+       for (i = 0; i < OMAP4_ISS_MEM_LAST; i++) {
+               if (iss->regs[i]) {
+                       iounmap(iss->regs[i]);
+                       iss->regs[i] = NULL;
+               }
+
+               if (iss->res[i]) {
+                       release_mem_region(iss->res[i]->start,
+                                          resource_size(iss->res[i]));
+                       iss->res[i] = NULL;
+               }
+       }
+       platform_set_drvdata(pdev, NULL);
+
+       mutex_destroy(&iss->iss_mutex);
+       kfree(iss);
+
+       return ret;
+}
+
+static int iss_remove(struct platform_device *pdev)
+{
+       struct iss_device *iss = platform_get_drvdata(pdev);
+       unsigned int i;
+
+       iss_unregister_entities(iss);
+       iss_cleanup_modules(iss);
+
+       free_irq(iss->irq_num, iss);
+       iss_put_clocks(iss);
+
+       for (i = 0; i < OMAP4_ISS_MEM_LAST; i++) {
+               if (iss->regs[i]) {
+                       iounmap(iss->regs[i]);
+                       iss->regs[i] = NULL;
+               }
+
+               if (iss->res[i]) {
+                       release_mem_region(iss->res[i]->start,
+                                          resource_size(iss->res[i]));
+                       iss->res[i] = NULL;
+               }
+       }
+
+       kfree(iss);
+
+       return 0;
+}
+
+static struct platform_device_id omap4iss_id_table[] = {
+       { "omap4iss", 0 },
+       { },
+};
+MODULE_DEVICE_TABLE(platform, omap4iss_id_table);
+
+static struct platform_driver iss_driver = {
+       .probe          = iss_probe,
+       .remove         = iss_remove,
+       .id_table       = omap4iss_id_table,
+       .driver = {
+               .owner  = THIS_MODULE,
+               .name   = "omap4iss",
+       },
+};
+
+module_platform_driver(iss_driver);
+
+MODULE_DESCRIPTION("TI OMAP4 ISS driver");
+MODULE_AUTHOR("Sergio Aguirre <sergio.a.aguirre@gmail.com>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(ISS_VIDEO_DRIVER_VERSION);
diff --git a/drivers/staging/media/omap4iss/iss.h b/drivers/staging/media/omap4iss/iss.h
new file mode 100644 (file)
index 0000000..f33664d
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * TI OMAP4 ISS V4L2 Driver
+ *
+ * Copyright (C) 2012 Texas Instruments.
+ *
+ * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef _OMAP4_ISS_H_
+#define _OMAP4_ISS_H_
+
+#include <media/v4l2-device.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/wait.h>
+
+#include <media/omap4iss.h>
+
+#include "iss_regs.h"
+#include "iss_csiphy.h"
+#include "iss_csi2.h"
+#include "iss_ipipeif.h"
+#include "iss_ipipe.h"
+#include "iss_resizer.h"
+
+#define to_iss_device(ptr_module)                              \
+       container_of(ptr_module, struct iss_device, ptr_module)
+#define to_device(ptr_module)                                          \
+       (to_iss_device(ptr_module)->dev)
+
+enum iss_mem_resources {
+       OMAP4_ISS_MEM_TOP,
+       OMAP4_ISS_MEM_CSI2_A_REGS1,
+       OMAP4_ISS_MEM_CAMERARX_CORE1,
+       OMAP4_ISS_MEM_CSI2_B_REGS1,
+       OMAP4_ISS_MEM_CAMERARX_CORE2,
+       OMAP4_ISS_MEM_BTE,
+       OMAP4_ISS_MEM_ISP_SYS1,
+       OMAP4_ISS_MEM_ISP_RESIZER,
+       OMAP4_ISS_MEM_ISP_IPIPE,
+       OMAP4_ISS_MEM_ISP_ISIF,
+       OMAP4_ISS_MEM_ISP_IPIPEIF,
+       OMAP4_ISS_MEM_LAST,
+};
+
+enum iss_subclk_resource {
+       OMAP4_ISS_SUBCLK_SIMCOP         = (1 << 0),
+       OMAP4_ISS_SUBCLK_ISP            = (1 << 1),
+       OMAP4_ISS_SUBCLK_CSI2_A         = (1 << 2),
+       OMAP4_ISS_SUBCLK_CSI2_B         = (1 << 3),
+       OMAP4_ISS_SUBCLK_CCP2           = (1 << 4),
+};
+
+enum iss_isp_subclk_resource {
+       OMAP4_ISS_ISP_SUBCLK_BL         = (1 << 0),
+       OMAP4_ISS_ISP_SUBCLK_ISIF       = (1 << 1),
+       OMAP4_ISS_ISP_SUBCLK_H3A        = (1 << 2),
+       OMAP4_ISS_ISP_SUBCLK_RSZ        = (1 << 3),
+       OMAP4_ISS_ISP_SUBCLK_IPIPE      = (1 << 4),
+       OMAP4_ISS_ISP_SUBCLK_IPIPEIF    = (1 << 5),
+};
+
+/*
+ * struct iss_reg - Structure for ISS register values.
+ * @reg: 32-bit Register address.
+ * @val: 32-bit Register value.
+ */
+struct iss_reg {
+       enum iss_mem_resources mmio_range;
+       u32 reg;
+       u32 val;
+};
+
+struct iss_device {
+       struct v4l2_device v4l2_dev;
+       struct media_device media_dev;
+       struct device *dev;
+       u32 revision;
+
+       /* platform HW resources */
+       struct iss_platform_data *pdata;
+       unsigned int irq_num;
+
+       struct resource *res[OMAP4_ISS_MEM_LAST];
+       void __iomem *regs[OMAP4_ISS_MEM_LAST];
+
+       u64 raw_dmamask;
+
+       struct mutex iss_mutex; /* For handling ref_count field */
+       int has_context;
+       int ref_count;
+
+       struct clk *iss_fck;
+       struct clk *iss_ctrlclk;
+
+       /* ISS modules */
+       struct iss_csi2_device csi2a;
+       struct iss_csi2_device csi2b;
+       struct iss_csiphy csiphy1;
+       struct iss_csiphy csiphy2;
+       struct iss_ipipeif_device ipipeif;
+       struct iss_ipipe_device ipipe;
+       struct iss_resizer_device resizer;
+
+       unsigned int subclk_resources;
+       unsigned int isp_subclk_resources;
+};
+
+#define v4l2_dev_to_iss_device(dev) \
+       container_of(dev, struct iss_device, v4l2_dev)
+
+int omap4iss_get_external_info(struct iss_pipeline *pipe,
+                              struct media_link *link);
+
+int omap4iss_module_sync_idle(struct media_entity *me, wait_queue_head_t *wait,
+                             atomic_t *stopping);
+
+int omap4iss_module_sync_is_stopping(wait_queue_head_t *wait,
+                                    atomic_t *stopping);
+
+int omap4iss_pipeline_set_stream(struct iss_pipeline *pipe,
+                                enum iss_pipeline_stream_state state);
+
+void omap4iss_configure_bridge(struct iss_device *iss,
+                              enum ipipeif_input_entity input);
+
+struct iss_device *omap4iss_get(struct iss_device *iss);
+void omap4iss_put(struct iss_device *iss);
+int omap4iss_subclk_enable(struct iss_device *iss,
+                          enum iss_subclk_resource res);
+int omap4iss_subclk_disable(struct iss_device *iss,
+                           enum iss_subclk_resource res);
+void omap4iss_isp_subclk_enable(struct iss_device *iss,
+                               enum iss_isp_subclk_resource res);
+void omap4iss_isp_subclk_disable(struct iss_device *iss,
+                                enum iss_isp_subclk_resource res);
+
+void omap4iss_isp_enable_interrupts(struct iss_device *iss);
+void omap4iss_isp_disable_interrupts(struct iss_device *iss);
+
+int omap4iss_pipeline_pm_use(struct media_entity *entity, int use);
+
+int omap4iss_register_entities(struct platform_device *pdev,
+                              struct v4l2_device *v4l2_dev);
+void omap4iss_unregister_entities(struct platform_device *pdev);
+
+#endif /* _OMAP4_ISS_H_ */
diff --git a/drivers/staging/media/omap4iss/iss_csi2.c b/drivers/staging/media/omap4iss/iss_csi2.c
new file mode 100644 (file)
index 0000000..0ee8381
--- /dev/null
@@ -0,0 +1,1368 @@
+/*
+ * TI OMAP4 ISS V4L2 Driver - CSI PHY module
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/delay.h>
+#include <media/v4l2-common.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/mm.h>
+
+#include "iss.h"
+#include "iss_regs.h"
+#include "iss_csi2.h"
+
+/*
+ * csi2_if_enable - Enable CSI2 Receiver interface.
+ * @enable: enable flag
+ *
+ */
+static void csi2_if_enable(struct iss_csi2_device *csi2, u8 enable)
+{
+       struct iss_csi2_ctrl_cfg *currctrl = &csi2->ctrl;
+
+       writel((readl(csi2->regs1 + CSI2_CTRL) & ~CSI2_CTRL_IF_EN) |
+               (enable ? CSI2_CTRL_IF_EN : 0),
+               csi2->regs1 + CSI2_CTRL);
+
+       currctrl->if_enable = enable;
+}
+
+/*
+ * csi2_recv_config - CSI2 receiver module configuration.
+ * @currctrl: iss_csi2_ctrl_cfg structure
+ *
+ */
+static void csi2_recv_config(struct iss_csi2_device *csi2,
+                            struct iss_csi2_ctrl_cfg *currctrl)
+{
+       u32 reg = 0;
+
+       if (currctrl->frame_mode)
+               reg |= CSI2_CTRL_FRAME;
+       else
+               reg &= ~CSI2_CTRL_FRAME;
+
+       if (currctrl->vp_clk_enable)
+               reg |= CSI2_CTRL_VP_CLK_EN;
+       else
+               reg &= ~CSI2_CTRL_VP_CLK_EN;
+
+       if (currctrl->vp_only_enable)
+               reg |= CSI2_CTRL_VP_ONLY_EN;
+       else
+               reg &= ~CSI2_CTRL_VP_ONLY_EN;
+
+       reg &= ~CSI2_CTRL_VP_OUT_CTRL_MASK;
+       reg |= currctrl->vp_out_ctrl << CSI2_CTRL_VP_OUT_CTRL_SHIFT;
+
+       if (currctrl->ecc_enable)
+               reg |= CSI2_CTRL_ECC_EN;
+       else
+               reg &= ~CSI2_CTRL_ECC_EN;
+
+       /*
+        * Set MFlag assertion boundaries to:
+        * Low: 4/8 of FIFO size
+        * High: 6/8 of FIFO size
+        */
+       reg &= ~(CSI2_CTRL_MFLAG_LEVH_MASK | CSI2_CTRL_MFLAG_LEVL_MASK);
+       reg |= (2 << CSI2_CTRL_MFLAG_LEVH_SHIFT) |
+              (4 << CSI2_CTRL_MFLAG_LEVL_SHIFT);
+
+       /* Generation of 16x64-bit bursts (Recommended) */
+       reg |= CSI2_CTRL_BURST_SIZE_EXPAND;
+
+       /* Do Non-Posted writes (Recommended) */
+       reg |= CSI2_CTRL_NON_POSTED_WRITE;
+
+       /*
+        * Enforce Little endian for all formats, including:
+        * YUV4:2:2 8-bit and YUV4:2:0 Legacy
+        */
+       reg |= CSI2_CTRL_ENDIANNESS;
+
+       writel(reg, csi2->regs1 + CSI2_CTRL);
+}
+
+static const unsigned int csi2_input_fmts[] = {
+       V4L2_MBUS_FMT_SGRBG10_1X10,
+       V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
+       V4L2_MBUS_FMT_SRGGB10_1X10,
+       V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8,
+       V4L2_MBUS_FMT_SBGGR10_1X10,
+       V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8,
+       V4L2_MBUS_FMT_SGBRG10_1X10,
+       V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8,
+       V4L2_MBUS_FMT_SBGGR8_1X8,
+       V4L2_MBUS_FMT_SGBRG8_1X8,
+       V4L2_MBUS_FMT_SGRBG8_1X8,
+       V4L2_MBUS_FMT_SRGGB8_1X8,
+       V4L2_MBUS_FMT_UYVY8_1X16,
+       V4L2_MBUS_FMT_YUYV8_1X16,
+};
+
+/* To set the format on the CSI2 requires a mapping function that takes
+ * the following inputs:
+ * - 3 different formats (at this time)
+ * - 2 destinations (mem, vp+mem) (vp only handled separately)
+ * - 2 decompression options (on, off)
+ * Output should be CSI2 frame format code
+ * Array indices as follows: [format][dest][decompr]
+ * Not all combinations are valid. 0 means invalid.
+ */
+static const u16 __csi2_fmt_map[][2][2] = {
+       /* RAW10 formats */
+       {
+               /* Output to memory */
+               {
+                       /* No DPCM decompression */
+                       CSI2_PIX_FMT_RAW10_EXP16,
+                       /* DPCM decompression */
+                       0,
+               },
+               /* Output to both */
+               {
+                       /* No DPCM decompression */
+                       CSI2_PIX_FMT_RAW10_EXP16_VP,
+                       /* DPCM decompression */
+                       0,
+               },
+       },
+       /* RAW10 DPCM8 formats */
+       {
+               /* Output to memory */
+               {
+                       /* No DPCM decompression */
+                       CSI2_USERDEF_8BIT_DATA1,
+                       /* DPCM decompression */
+                       CSI2_USERDEF_8BIT_DATA1_DPCM10,
+               },
+               /* Output to both */
+               {
+                       /* No DPCM decompression */
+                       CSI2_PIX_FMT_RAW8_VP,
+                       /* DPCM decompression */
+                       CSI2_USERDEF_8BIT_DATA1_DPCM10_VP,
+               },
+       },
+       /* RAW8 formats */
+       {
+               /* Output to memory */
+               {
+                       /* No DPCM decompression */
+                       CSI2_PIX_FMT_RAW8,
+                       /* DPCM decompression */
+                       0,
+               },
+               /* Output to both */
+               {
+                       /* No DPCM decompression */
+                       CSI2_PIX_FMT_RAW8_VP,
+                       /* DPCM decompression */
+                       0,
+               },
+       },
+       /* YUV422 formats */
+       {
+               /* Output to memory */
+               {
+                       /* No DPCM decompression */
+                       CSI2_PIX_FMT_YUV422_8BIT,
+                       /* DPCM decompression */
+                       0,
+               },
+               /* Output to both */
+               {
+                       /* No DPCM decompression */
+                       CSI2_PIX_FMT_YUV422_8BIT_VP16,
+                       /* DPCM decompression */
+                       0,
+               },
+       },
+};
+
+/*
+ * csi2_ctx_map_format - Map CSI2 sink media bus format to CSI2 format ID
+ * @csi2: ISS CSI2 device
+ *
+ * Returns CSI2 physical format id
+ */
+static u16 csi2_ctx_map_format(struct iss_csi2_device *csi2)
+{
+       const struct v4l2_mbus_framefmt *fmt = &csi2->formats[CSI2_PAD_SINK];
+       int fmtidx, destidx;
+
+       switch (fmt->code) {
+       case V4L2_MBUS_FMT_SGRBG10_1X10:
+       case V4L2_MBUS_FMT_SRGGB10_1X10:
+       case V4L2_MBUS_FMT_SBGGR10_1X10:
+       case V4L2_MBUS_FMT_SGBRG10_1X10:
+               fmtidx = 0;
+               break;
+       case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8:
+       case V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8:
+       case V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8:
+       case V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8:
+               fmtidx = 1;
+               break;
+       case V4L2_MBUS_FMT_SBGGR8_1X8:
+       case V4L2_MBUS_FMT_SGBRG8_1X8:
+       case V4L2_MBUS_FMT_SGRBG8_1X8:
+       case V4L2_MBUS_FMT_SRGGB8_1X8:
+               fmtidx = 2;
+               break;
+       case V4L2_MBUS_FMT_UYVY8_1X16:
+       case V4L2_MBUS_FMT_YUYV8_1X16:
+               fmtidx = 3;
+               break;
+       default:
+               WARN(1, KERN_ERR "CSI2: pixel format %08x unsupported!\n",
+                    fmt->code);
+               return 0;
+       }
+
+       if (!(csi2->output & CSI2_OUTPUT_IPIPEIF) &&
+           !(csi2->output & CSI2_OUTPUT_MEMORY)) {
+               /* Neither output enabled is a valid combination */
+               return CSI2_PIX_FMT_OTHERS;
+       }
+
+       /* If we need to skip frames at the beginning of the stream disable the
+        * video port to avoid sending the skipped frames to the IPIPEIF.
+        */
+       destidx = csi2->frame_skip ? 0 : !!(csi2->output & CSI2_OUTPUT_IPIPEIF);
+
+       return __csi2_fmt_map[fmtidx][destidx][csi2->dpcm_decompress];
+}
+
+/*
+ * csi2_set_outaddr - Set memory address to save output image
+ * @csi2: Pointer to ISS CSI2a device.
+ * @addr: 32-bit memory address aligned on 32 byte boundary.
+ *
+ * Sets the memory address where the output will be saved.
+ *
+ * Returns 0 if successful, or -EINVAL if the address is not in the 32 byte
+ * boundary.
+ */
+static void csi2_set_outaddr(struct iss_csi2_device *csi2, u32 addr)
+{
+       struct iss_csi2_ctx_cfg *ctx = &csi2->contexts[0];
+
+       ctx->ping_addr = addr;
+       ctx->pong_addr = addr;
+       writel(ctx->ping_addr,
+              csi2->regs1 + CSI2_CTX_PING_ADDR(ctx->ctxnum));
+       writel(ctx->pong_addr,
+              csi2->regs1 + CSI2_CTX_PONG_ADDR(ctx->ctxnum));
+}
+
+/*
+ * is_usr_def_mapping - Checks whether USER_DEF_MAPPING should
+ *                     be enabled by CSI2.
+ * @format_id: mapped format id
+ *
+ */
+static inline int is_usr_def_mapping(u32 format_id)
+{
+       return ((format_id & 0xF0) == 0x40) ? 1 : 0;
+}
+
+/*
+ * csi2_ctx_enable - Enable specified CSI2 context
+ * @ctxnum: Context number, valid between 0 and 7 values.
+ * @enable: enable
+ *
+ */
+static void csi2_ctx_enable(struct iss_csi2_device *csi2, u8 ctxnum, u8 enable)
+{
+       struct iss_csi2_ctx_cfg *ctx = &csi2->contexts[ctxnum];
+       u32 reg;
+
+       reg = readl(csi2->regs1 + CSI2_CTX_CTRL1(ctxnum));
+
+       if (enable) {
+               unsigned int skip = 0;
+
+               if (csi2->frame_skip)
+                       skip = csi2->frame_skip;
+               else if (csi2->output & CSI2_OUTPUT_MEMORY)
+                       skip = 1;
+
+               reg &= ~CSI2_CTX_CTRL1_COUNT_MASK;
+               reg |= CSI2_CTX_CTRL1_COUNT_UNLOCK
+                   |  (skip << CSI2_CTX_CTRL1_COUNT_SHIFT)
+                   |  CSI2_CTX_CTRL1_CTX_EN;
+       } else {
+               reg &= ~CSI2_CTX_CTRL1_CTX_EN;
+       }
+
+       writel(reg, csi2->regs1 + CSI2_CTX_CTRL1(ctxnum));
+       ctx->enabled = enable;
+}
+
+/*
+ * csi2_ctx_config - CSI2 context configuration.
+ * @ctx: context configuration
+ *
+ */
+static void csi2_ctx_config(struct iss_csi2_device *csi2,
+                           struct iss_csi2_ctx_cfg *ctx)
+{
+       u32 reg;
+
+       /* Set up CSI2_CTx_CTRL1 */
+       if (ctx->eof_enabled)
+               reg = CSI2_CTX_CTRL1_EOF_EN;
+
+       if (ctx->eol_enabled)
+               reg |= CSI2_CTX_CTRL1_EOL_EN;
+
+       if (ctx->checksum_enabled)
+               reg |= CSI2_CTX_CTRL1_CS_EN;
+
+       writel(reg, csi2->regs1 + CSI2_CTX_CTRL1(ctx->ctxnum));
+
+       /* Set up CSI2_CTx_CTRL2 */
+       reg = ctx->virtual_id << CSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT;
+       reg |= ctx->format_id << CSI2_CTX_CTRL2_FORMAT_SHIFT;
+
+       if (ctx->dpcm_decompress && ctx->dpcm_predictor)
+               reg |= CSI2_CTX_CTRL2_DPCM_PRED;
+
+       if (is_usr_def_mapping(ctx->format_id))
+               reg |= 2 << CSI2_CTX_CTRL2_USER_DEF_MAP_SHIFT;
+
+       writel(reg, csi2->regs1 + CSI2_CTX_CTRL2(ctx->ctxnum));
+
+       /* Set up CSI2_CTx_CTRL3 */
+       writel(ctx->alpha << CSI2_CTX_CTRL3_ALPHA_SHIFT,
+               csi2->regs1 + CSI2_CTX_CTRL3(ctx->ctxnum));
+
+       /* Set up CSI2_CTx_DAT_OFST */
+       reg = readl(csi2->regs1 + CSI2_CTX_DAT_OFST(ctx->ctxnum));
+       reg &= ~CSI2_CTX_DAT_OFST_MASK;
+       reg |= ctx->data_offset;
+       writel(reg, csi2->regs1 + CSI2_CTX_DAT_OFST(ctx->ctxnum));
+
+       writel(ctx->ping_addr,
+                      csi2->regs1 + CSI2_CTX_PING_ADDR(ctx->ctxnum));
+
+       writel(ctx->pong_addr,
+                      csi2->regs1 + CSI2_CTX_PONG_ADDR(ctx->ctxnum));
+}
+
+/*
+ * csi2_timing_config - CSI2 timing configuration.
+ * @timing: csi2_timing_cfg structure
+ */
+static void csi2_timing_config(struct iss_csi2_device *csi2,
+                              struct iss_csi2_timing_cfg *timing)
+{
+       u32 reg;
+
+       reg = readl(csi2->regs1 + CSI2_TIMING);
+
+       if (timing->force_rx_mode)
+               reg |= CSI2_TIMING_FORCE_RX_MODE_IO1;
+       else
+               reg &= ~CSI2_TIMING_FORCE_RX_MODE_IO1;
+
+       if (timing->stop_state_16x)
+               reg |= CSI2_TIMING_STOP_STATE_X16_IO1;
+       else
+               reg &= ~CSI2_TIMING_STOP_STATE_X16_IO1;
+
+       if (timing->stop_state_4x)
+               reg |= CSI2_TIMING_STOP_STATE_X4_IO1;
+       else
+               reg &= ~CSI2_TIMING_STOP_STATE_X4_IO1;
+
+       reg &= ~CSI2_TIMING_STOP_STATE_COUNTER_IO1_MASK;
+       reg |= timing->stop_state_counter <<
+              CSI2_TIMING_STOP_STATE_COUNTER_IO1_SHIFT;
+
+       writel(reg, csi2->regs1 + CSI2_TIMING);
+}
+
+/*
+ * csi2_irq_ctx_set - Enables CSI2 Context IRQs.
+ * @enable: Enable/disable CSI2 Context interrupts
+ */
+static void csi2_irq_ctx_set(struct iss_csi2_device *csi2, int enable)
+{
+       u32 reg = CSI2_CTX_IRQ_FE;
+       int i;
+
+       if (csi2->use_fs_irq)
+               reg |= CSI2_CTX_IRQ_FS;
+
+       for (i = 0; i < 8; i++) {
+               writel(reg, csi2->regs1 + CSI2_CTX_IRQSTATUS(i));
+               if (enable)
+                       writel(readl(csi2->regs1 + CSI2_CTX_IRQENABLE(i)) | reg,
+                               csi2->regs1 + CSI2_CTX_IRQENABLE(i));
+               else
+                       writel(readl(csi2->regs1 + CSI2_CTX_IRQENABLE(i)) &
+                               ~reg,
+                               csi2->regs1 + CSI2_CTX_IRQENABLE(i));
+       }
+}
+
+/*
+ * csi2_irq_complexio1_set - Enables CSI2 ComplexIO IRQs.
+ * @enable: Enable/disable CSI2 ComplexIO #1 interrupts
+ */
+static void csi2_irq_complexio1_set(struct iss_csi2_device *csi2, int enable)
+{
+       u32 reg;
+       reg = CSI2_COMPLEXIO_IRQ_STATEALLULPMEXIT |
+               CSI2_COMPLEXIO_IRQ_STATEALLULPMENTER |
+               CSI2_COMPLEXIO_IRQ_STATEULPM5 |
+               CSI2_COMPLEXIO_IRQ_ERRCONTROL5 |
+               CSI2_COMPLEXIO_IRQ_ERRESC5 |
+               CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS5 |
+               CSI2_COMPLEXIO_IRQ_ERRSOTHS5 |
+               CSI2_COMPLEXIO_IRQ_STATEULPM4 |
+               CSI2_COMPLEXIO_IRQ_ERRCONTROL4 |
+               CSI2_COMPLEXIO_IRQ_ERRESC4 |
+               CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS4 |
+               CSI2_COMPLEXIO_IRQ_ERRSOTHS4 |
+               CSI2_COMPLEXIO_IRQ_STATEULPM3 |
+               CSI2_COMPLEXIO_IRQ_ERRCONTROL3 |
+               CSI2_COMPLEXIO_IRQ_ERRESC3 |
+               CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS3 |
+               CSI2_COMPLEXIO_IRQ_ERRSOTHS3 |
+               CSI2_COMPLEXIO_IRQ_STATEULPM2 |
+               CSI2_COMPLEXIO_IRQ_ERRCONTROL2 |
+               CSI2_COMPLEXIO_IRQ_ERRESC2 |
+               CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS2 |
+               CSI2_COMPLEXIO_IRQ_ERRSOTHS2 |
+               CSI2_COMPLEXIO_IRQ_STATEULPM1 |
+               CSI2_COMPLEXIO_IRQ_ERRCONTROL1 |
+               CSI2_COMPLEXIO_IRQ_ERRESC1 |
+               CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS1 |
+               CSI2_COMPLEXIO_IRQ_ERRSOTHS1;
+       writel(reg, csi2->regs1 + CSI2_COMPLEXIO_IRQSTATUS);
+       if (enable)
+               reg |= readl(csi2->regs1 + CSI2_COMPLEXIO_IRQENABLE);
+       else
+               reg = 0;
+       writel(reg, csi2->regs1 + CSI2_COMPLEXIO_IRQENABLE);
+}
+
+/*
+ * csi2_irq_status_set - Enables CSI2 Status IRQs.
+ * @enable: Enable/disable CSI2 Status interrupts
+ */
+static void csi2_irq_status_set(struct iss_csi2_device *csi2, int enable)
+{
+       u32 reg;
+       reg = CSI2_IRQ_OCP_ERR |
+               CSI2_IRQ_SHORT_PACKET |
+               CSI2_IRQ_ECC_CORRECTION |
+               CSI2_IRQ_ECC_NO_CORRECTION |
+               CSI2_IRQ_COMPLEXIO_ERR |
+               CSI2_IRQ_FIFO_OVF |
+               CSI2_IRQ_CONTEXT0;
+       writel(reg, csi2->regs1 + CSI2_IRQSTATUS);
+       if (enable)
+               reg |= readl(csi2->regs1 + CSI2_IRQENABLE);
+       else
+               reg = 0;
+
+       writel(reg, csi2->regs1 + CSI2_IRQENABLE);
+}
+
+/*
+ * omap4iss_csi2_reset - Resets the CSI2 module.
+ *
+ * Must be called with the phy lock held.
+ *
+ * Returns 0 if successful, or -EBUSY if power command didn't respond.
+ */
+int omap4iss_csi2_reset(struct iss_csi2_device *csi2)
+{
+       u8 soft_reset_retries = 0;
+       u32 reg;
+       int i;
+
+       if (!csi2->available)
+               return -ENODEV;
+
+       if (csi2->phy->phy_in_use)
+               return -EBUSY;
+
+       writel(readl(csi2->regs1 + CSI2_SYSCONFIG) |
+               CSI2_SYSCONFIG_SOFT_RESET,
+               csi2->regs1 + CSI2_SYSCONFIG);
+
+       do {
+               reg = readl(csi2->regs1 + CSI2_SYSSTATUS) &
+                                   CSI2_SYSSTATUS_RESET_DONE;
+               if (reg == CSI2_SYSSTATUS_RESET_DONE)
+                       break;
+               soft_reset_retries++;
+               if (soft_reset_retries < 5)
+                       usleep_range(100, 100);
+       } while (soft_reset_retries < 5);
+
+       if (soft_reset_retries == 5) {
+               printk(KERN_ERR "CSI2: Soft reset try count exceeded!\n");
+               return -EBUSY;
+       }
+
+       writel(readl(csi2->regs1 + CSI2_COMPLEXIO_CFG) |
+               CSI2_COMPLEXIO_CFG_RESET_CTRL,
+               csi2->regs1 + CSI2_COMPLEXIO_CFG);
+
+       i = 100;
+       do {
+               reg = readl(csi2->phy->phy_regs + REGISTER1)
+                   & REGISTER1_RESET_DONE_CTRLCLK;
+               if (reg == REGISTER1_RESET_DONE_CTRLCLK)
+                       break;
+               usleep_range(100, 100);
+       } while (--i > 0);
+
+       if (i == 0) {
+               printk(KERN_ERR
+                      "CSI2: Reset for CSI2_96M_FCLK domain Failed!\n");
+               return -EBUSY;
+       }
+
+       writel((readl(csi2->regs1 + CSI2_SYSCONFIG) &
+               ~(CSI2_SYSCONFIG_MSTANDBY_MODE_MASK |
+                 CSI2_SYSCONFIG_AUTO_IDLE)) |
+               CSI2_SYSCONFIG_MSTANDBY_MODE_NO,
+               csi2->regs1 + CSI2_SYSCONFIG);
+
+       return 0;
+}
+
+static int csi2_configure(struct iss_csi2_device *csi2)
+{
+       const struct iss_v4l2_subdevs_group *pdata;
+       struct iss_csi2_timing_cfg *timing = &csi2->timing[0];
+       struct v4l2_subdev *sensor;
+       struct media_pad *pad;
+
+       /*
+        * CSI2 fields that can be updated while the context has
+        * been enabled or the interface has been enabled are not
+        * updated dynamically currently. So we do not allow to
+        * reconfigure if either has been enabled
+        */
+       if (csi2->contexts[0].enabled || csi2->ctrl.if_enable)
+               return -EBUSY;
+
+       pad = media_entity_remote_pad(&csi2->pads[CSI2_PAD_SINK]);
+       sensor = media_entity_to_v4l2_subdev(pad->entity);
+       pdata = sensor->host_priv;
+
+       csi2->frame_skip = 0;
+       v4l2_subdev_call(sensor, sensor, g_skip_frames, &csi2->frame_skip);
+
+       csi2->ctrl.vp_out_ctrl = pdata->bus.csi2.vpclk_div;
+       csi2->ctrl.frame_mode = ISS_CSI2_FRAME_IMMEDIATE;
+       csi2->ctrl.ecc_enable = pdata->bus.csi2.crc;
+
+       timing->force_rx_mode = 1;
+       timing->stop_state_16x = 1;
+       timing->stop_state_4x = 1;
+       timing->stop_state_counter = 0x1FF;
+
+       /*
+        * The CSI2 receiver can't do any format conversion except DPCM
+        * decompression, so every set_format call configures both pads
+        * and enables DPCM decompression as a special case:
+        */
+       if (csi2->formats[CSI2_PAD_SINK].code !=
+           csi2->formats[CSI2_PAD_SOURCE].code)
+               csi2->dpcm_decompress = true;
+       else
+               csi2->dpcm_decompress = false;
+
+       csi2->contexts[0].format_id = csi2_ctx_map_format(csi2);
+
+       if (csi2->video_out.bpl_padding == 0)
+               csi2->contexts[0].data_offset = 0;
+       else
+               csi2->contexts[0].data_offset = csi2->video_out.bpl_value;
+
+       /*
+        * Enable end of frame and end of line signals generation for
+        * context 0. These signals are generated from CSI2 receiver to
+        * qualify the last pixel of a frame and the last pixel of a line.
+        * Without enabling the signals CSI2 receiver writes data to memory
+        * beyond buffer size and/or data line offset is not handled correctly.
+        */
+       csi2->contexts[0].eof_enabled = 1;
+       csi2->contexts[0].eol_enabled = 1;
+
+       csi2_irq_complexio1_set(csi2, 1);
+       csi2_irq_ctx_set(csi2, 1);
+       csi2_irq_status_set(csi2, 1);
+
+       /* Set configuration (timings, format and links) */
+       csi2_timing_config(csi2, timing);
+       csi2_recv_config(csi2, &csi2->ctrl);
+       csi2_ctx_config(csi2, &csi2->contexts[0]);
+
+       return 0;
+}
+
+/*
+ * csi2_print_status - Prints CSI2 debug information.
+ */
+#define CSI2_PRINT_REGISTER(iss, regs, name)\
+       dev_dbg(iss->dev, "###CSI2 " #name "=0x%08x\n", \
+               readl(regs + CSI2_##name))
+
+static void csi2_print_status(struct iss_csi2_device *csi2)
+{
+       struct iss_device *iss = csi2->iss;
+
+       if (!csi2->available)
+               return;
+
+       dev_dbg(iss->dev, "-------------CSI2 Register dump-------------\n");
+
+       CSI2_PRINT_REGISTER(iss, csi2->regs1, SYSCONFIG);
+       CSI2_PRINT_REGISTER(iss, csi2->regs1, SYSSTATUS);
+       CSI2_PRINT_REGISTER(iss, csi2->regs1, IRQENABLE);
+       CSI2_PRINT_REGISTER(iss, csi2->regs1, IRQSTATUS);
+       CSI2_PRINT_REGISTER(iss, csi2->regs1, CTRL);
+       CSI2_PRINT_REGISTER(iss, csi2->regs1, DBG_H);
+       CSI2_PRINT_REGISTER(iss, csi2->regs1, COMPLEXIO_CFG);
+       CSI2_PRINT_REGISTER(iss, csi2->regs1, COMPLEXIO_IRQSTATUS);
+       CSI2_PRINT_REGISTER(iss, csi2->regs1, SHORT_PACKET);
+       CSI2_PRINT_REGISTER(iss, csi2->regs1, COMPLEXIO_IRQENABLE);
+       CSI2_PRINT_REGISTER(iss, csi2->regs1, DBG_P);
+       CSI2_PRINT_REGISTER(iss, csi2->regs1, TIMING);
+       CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_CTRL1(0));
+       CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_CTRL2(0));
+       CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_DAT_OFST(0));
+       CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_PING_ADDR(0));
+       CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_PONG_ADDR(0));
+       CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_IRQENABLE(0));
+       CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_IRQSTATUS(0));
+       CSI2_PRINT_REGISTER(iss, csi2->regs1, CTX_CTRL3(0));
+
+       dev_dbg(iss->dev, "--------------------------------------------\n");
+}
+
+/* -----------------------------------------------------------------------------
+ * Interrupt handling
+ */
+
+/*
+ * csi2_isr_buffer - Does buffer handling at end-of-frame
+ * when writing to memory.
+ */
+static void csi2_isr_buffer(struct iss_csi2_device *csi2)
+{
+       struct iss_buffer *buffer;
+
+       csi2_ctx_enable(csi2, 0, 0);
+
+       buffer = omap4iss_video_buffer_next(&csi2->video_out);
+
+       /*
+        * Let video queue operation restart engine if there is an underrun
+        * condition.
+        */
+       if (buffer == NULL)
+               return;
+
+       csi2_set_outaddr(csi2, buffer->iss_addr);
+       csi2_ctx_enable(csi2, 0, 1);
+}
+
+static void csi2_isr_ctx(struct iss_csi2_device *csi2,
+                        struct iss_csi2_ctx_cfg *ctx)
+{
+       unsigned int n = ctx->ctxnum;
+       u32 status;
+
+       status = readl(csi2->regs1 + CSI2_CTX_IRQSTATUS(n));
+       writel(status, csi2->regs1 + CSI2_CTX_IRQSTATUS(n));
+
+       /* Propagate frame number */
+       if (status & CSI2_CTX_IRQ_FS) {
+               struct iss_pipeline *pipe =
+                                    to_iss_pipeline(&csi2->subdev.entity);
+               if (pipe->do_propagation)
+                       atomic_inc(&pipe->frame_number);
+       }
+
+       if (!(status & CSI2_CTX_IRQ_FE))
+               return;
+
+       /* Skip interrupts until we reach the frame skip count. The CSI2 will be
+        * automatically disabled, as the frame skip count has been programmed
+        * in the CSI2_CTx_CTRL1::COUNT field, so reenable it.
+        *
+        * It would have been nice to rely on the FRAME_NUMBER interrupt instead
+        * but it turned out that the interrupt is only generated when the CSI2
+        * writes to memory (the CSI2_CTx_CTRL1::COUNT field is decreased
+        * correctly and reaches 0 when data is forwarded to the video port only
+        * but no interrupt arrives). Maybe a CSI2 hardware bug.
+        */
+       if (csi2->frame_skip) {
+               csi2->frame_skip--;
+               if (csi2->frame_skip == 0) {
+                       ctx->format_id = csi2_ctx_map_format(csi2);
+                       csi2_ctx_config(csi2, ctx);
+                       csi2_ctx_enable(csi2, n, 1);
+               }
+               return;
+       }
+
+       if (csi2->output & CSI2_OUTPUT_MEMORY)
+               csi2_isr_buffer(csi2);
+}
+
+/*
+ * omap4iss_csi2_isr - CSI2 interrupt handling.
+ */
+void omap4iss_csi2_isr(struct iss_csi2_device *csi2)
+{
+       struct iss_pipeline *pipe = to_iss_pipeline(&csi2->subdev.entity);
+       u32 csi2_irqstatus, cpxio1_irqstatus;
+       struct iss_device *iss = csi2->iss;
+
+       if (!csi2->available)
+               return;
+
+       csi2_irqstatus = readl(csi2->regs1 + CSI2_IRQSTATUS);
+       writel(csi2_irqstatus, csi2->regs1 + CSI2_IRQSTATUS);
+
+       /* Failure Cases */
+       if (csi2_irqstatus & CSI2_IRQ_COMPLEXIO_ERR) {
+               cpxio1_irqstatus = readl(csi2->regs1 +
+                                        CSI2_COMPLEXIO_IRQSTATUS);
+               writel(cpxio1_irqstatus,
+                       csi2->regs1 + CSI2_COMPLEXIO_IRQSTATUS);
+               dev_dbg(iss->dev, "CSI2: ComplexIO Error IRQ "
+                       "%x\n", cpxio1_irqstatus);
+               pipe->error = true;
+       }
+
+       if (csi2_irqstatus & (CSI2_IRQ_OCP_ERR |
+                             CSI2_IRQ_SHORT_PACKET |
+                             CSI2_IRQ_ECC_NO_CORRECTION |
+                             CSI2_IRQ_COMPLEXIO_ERR |
+                             CSI2_IRQ_FIFO_OVF)) {
+               dev_dbg(iss->dev, "CSI2 Err:"
+                       " OCP:%d,"
+                       " Short_pack:%d,"
+                       " ECC:%d,"
+                       " CPXIO:%d,"
+                       " FIFO_OVF:%d,"
+                       "\n",
+                       (csi2_irqstatus &
+                        CSI2_IRQ_OCP_ERR) ? 1 : 0,
+                       (csi2_irqstatus &
+                        CSI2_IRQ_SHORT_PACKET) ? 1 : 0,
+                       (csi2_irqstatus &
+                        CSI2_IRQ_ECC_NO_CORRECTION) ? 1 : 0,
+                       (csi2_irqstatus &
+                        CSI2_IRQ_COMPLEXIO_ERR) ? 1 : 0,
+                       (csi2_irqstatus &
+                        CSI2_IRQ_FIFO_OVF) ? 1 : 0);
+               pipe->error = true;
+       }
+
+       if (omap4iss_module_sync_is_stopping(&csi2->wait, &csi2->stopping))
+               return;
+
+       /* Successful cases */
+       if (csi2_irqstatus & CSI2_IRQ_CONTEXT0)
+               csi2_isr_ctx(csi2, &csi2->contexts[0]);
+
+       if (csi2_irqstatus & CSI2_IRQ_ECC_CORRECTION)
+               dev_dbg(iss->dev, "CSI2: ECC correction done\n");
+}
+
+/* -----------------------------------------------------------------------------
+ * ISS video operations
+ */
+
+/*
+ * csi2_queue - Queues the first buffer when using memory output
+ * @video: The video node
+ * @buffer: buffer to queue
+ */
+static int csi2_queue(struct iss_video *video, struct iss_buffer *buffer)
+{
+       struct iss_csi2_device *csi2 = container_of(video,
+                               struct iss_csi2_device, video_out);
+
+       csi2_set_outaddr(csi2, buffer->iss_addr);
+
+       /*
+        * If streaming was enabled before there was a buffer queued
+        * or underrun happened in the ISR, the hardware was not enabled
+        * and DMA queue flag ISS_VIDEO_DMAQUEUE_UNDERRUN is still set.
+        * Enable it now.
+        */
+       if (csi2->video_out.dmaqueue_flags & ISS_VIDEO_DMAQUEUE_UNDERRUN) {
+               /* Enable / disable context 0 and IRQs */
+               csi2_if_enable(csi2, 1);
+               csi2_ctx_enable(csi2, 0, 1);
+               iss_video_dmaqueue_flags_clr(&csi2->video_out);
+       }
+
+       return 0;
+}
+
+static const struct iss_video_operations csi2_issvideo_ops = {
+       .queue = csi2_queue,
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev operations
+ */
+
+static struct v4l2_mbus_framefmt *
+__csi2_get_format(struct iss_csi2_device *csi2, struct v4l2_subdev_fh *fh,
+                 unsigned int pad, enum v4l2_subdev_format_whence which)
+{
+       if (which == V4L2_SUBDEV_FORMAT_TRY)
+               return v4l2_subdev_get_try_format(fh, pad);
+       else
+               return &csi2->formats[pad];
+}
+
+static void
+csi2_try_format(struct iss_csi2_device *csi2, struct v4l2_subdev_fh *fh,
+               unsigned int pad, struct v4l2_mbus_framefmt *fmt,
+               enum v4l2_subdev_format_whence which)
+{
+       enum v4l2_mbus_pixelcode pixelcode;
+       struct v4l2_mbus_framefmt *format;
+       const struct iss_format_info *info;
+       unsigned int i;
+
+       switch (pad) {
+       case CSI2_PAD_SINK:
+               /* Clamp the width and height to valid range (1-8191). */
+               for (i = 0; i < ARRAY_SIZE(csi2_input_fmts); i++) {
+                       if (fmt->code == csi2_input_fmts[i])
+                               break;
+               }
+
+               /* If not found, use SGRBG10 as default */
+               if (i >= ARRAY_SIZE(csi2_input_fmts))
+                       fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
+
+               fmt->width = clamp_t(u32, fmt->width, 1, 8191);
+               fmt->height = clamp_t(u32, fmt->height, 1, 8191);
+               break;
+
+       case CSI2_PAD_SOURCE:
+               /* Source format same as sink format, except for DPCM
+                * compression.
+                */
+               pixelcode = fmt->code;
+               format = __csi2_get_format(csi2, fh, CSI2_PAD_SINK, which);
+               memcpy(fmt, format, sizeof(*fmt));
+
+               /*
+                * Only Allow DPCM decompression, and check that the
+                * pattern is preserved
+                */
+               info = omap4iss_video_format_info(fmt->code);
+               if (info->uncompressed == pixelcode)
+                       fmt->code = pixelcode;
+               break;
+       }
+
+       /* RGB, non-interlaced */
+       fmt->colorspace = V4L2_COLORSPACE_SRGB;
+       fmt->field = V4L2_FIELD_NONE;
+}
+
+/*
+ * csi2_enum_mbus_code - Handle pixel format enumeration
+ * @sd     : pointer to v4l2 subdev structure
+ * @fh     : V4L2 subdev file handle
+ * @code   : pointer to v4l2_subdev_mbus_code_enum structure
+ * return -EINVAL or zero on success
+ */
+static int csi2_enum_mbus_code(struct v4l2_subdev *sd,
+                              struct v4l2_subdev_fh *fh,
+                              struct v4l2_subdev_mbus_code_enum *code)
+{
+       struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd);
+       struct v4l2_mbus_framefmt *format;
+       const struct iss_format_info *info;
+
+       if (code->pad == CSI2_PAD_SINK) {
+               if (code->index >= ARRAY_SIZE(csi2_input_fmts))
+                       return -EINVAL;
+
+               code->code = csi2_input_fmts[code->index];
+       } else {
+               format = __csi2_get_format(csi2, fh, CSI2_PAD_SINK,
+                                          V4L2_SUBDEV_FORMAT_TRY);
+               switch (code->index) {
+               case 0:
+                       /* Passthrough sink pad code */
+                       code->code = format->code;
+                       break;
+               case 1:
+                       /* Uncompressed code */
+                       info = omap4iss_video_format_info(format->code);
+                       if (info->uncompressed == format->code)
+                               return -EINVAL;
+
+                       code->code = info->uncompressed;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+       }
+
+       return 0;
+}
+
+static int csi2_enum_frame_size(struct v4l2_subdev *sd,
+                               struct v4l2_subdev_fh *fh,
+                               struct v4l2_subdev_frame_size_enum *fse)
+{
+       struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd);
+       struct v4l2_mbus_framefmt format;
+
+       if (fse->index != 0)
+               return -EINVAL;
+
+       format.code = fse->code;
+       format.width = 1;
+       format.height = 1;
+       csi2_try_format(csi2, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
+       fse->min_width = format.width;
+       fse->min_height = format.height;
+
+       if (format.code != fse->code)
+               return -EINVAL;
+
+       format.code = fse->code;
+       format.width = -1;
+       format.height = -1;
+       csi2_try_format(csi2, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
+       fse->max_width = format.width;
+       fse->max_height = format.height;
+
+       return 0;
+}
+
+/*
+ * csi2_get_format - Handle get format by pads subdev method
+ * @sd : pointer to v4l2 subdev structure
+ * @fh : V4L2 subdev file handle
+ * @fmt: pointer to v4l2 subdev format structure
+ * return -EINVAL or zero on success
+ */
+static int csi2_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                          struct v4l2_subdev_format *fmt)
+{
+       struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd);
+       struct v4l2_mbus_framefmt *format;
+
+       format = __csi2_get_format(csi2, fh, fmt->pad, fmt->which);
+       if (format == NULL)
+               return -EINVAL;
+
+       fmt->format = *format;
+       return 0;
+}
+
+/*
+ * csi2_set_format - Handle set format by pads subdev method
+ * @sd : pointer to v4l2 subdev structure
+ * @fh : V4L2 subdev file handle
+ * @fmt: pointer to v4l2 subdev format structure
+ * return -EINVAL or zero on success
+ */
+static int csi2_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                          struct v4l2_subdev_format *fmt)
+{
+       struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd);
+       struct v4l2_mbus_framefmt *format;
+
+       format = __csi2_get_format(csi2, fh, fmt->pad, fmt->which);
+       if (format == NULL)
+               return -EINVAL;
+
+       csi2_try_format(csi2, fh, fmt->pad, &fmt->format, fmt->which);
+       *format = fmt->format;
+
+       /* Propagate the format from sink to source */
+       if (fmt->pad == CSI2_PAD_SINK) {
+               format = __csi2_get_format(csi2, fh, CSI2_PAD_SOURCE,
+                                          fmt->which);
+               *format = fmt->format;
+               csi2_try_format(csi2, fh, CSI2_PAD_SOURCE, format, fmt->which);
+       }
+
+       return 0;
+}
+
+static int csi2_link_validate(struct v4l2_subdev *sd, struct media_link *link,
+                             struct v4l2_subdev_format *source_fmt,
+                             struct v4l2_subdev_format *sink_fmt)
+{
+       struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd);
+       struct iss_pipeline *pipe = to_iss_pipeline(&csi2->subdev.entity);
+       int rval;
+
+       pipe->external = media_entity_to_v4l2_subdev(link->source->entity);
+       rval = omap4iss_get_external_info(pipe, link);
+       if (rval < 0)
+               return rval;
+
+       return v4l2_subdev_link_validate_default(sd, link, source_fmt,
+                                                sink_fmt);
+}
+
+/*
+ * csi2_init_formats - Initialize formats on all pads
+ * @sd: ISS CSI2 V4L2 subdevice
+ * @fh: V4L2 subdev file handle
+ *
+ * Initialize all pad formats with default values. If fh is not NULL, try
+ * formats are initialized on the file handle. Otherwise active formats are
+ * initialized on the device.
+ */
+static int csi2_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+       struct v4l2_subdev_format format;
+
+       memset(&format, 0, sizeof(format));
+       format.pad = CSI2_PAD_SINK;
+       format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+       format.format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
+       format.format.width = 4096;
+       format.format.height = 4096;
+       csi2_set_format(sd, fh, &format);
+
+       return 0;
+}
+
+/*
+ * csi2_set_stream - Enable/Disable streaming on the CSI2 module
+ * @sd: ISS CSI2 V4L2 subdevice
+ * @enable: ISS pipeline stream state
+ *
+ * Return 0 on success or a negative error code otherwise.
+ */
+static int csi2_set_stream(struct v4l2_subdev *sd, int enable)
+{
+       struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd);
+       struct iss_device *iss = csi2->iss;
+       struct iss_pipeline *pipe = to_iss_pipeline(&csi2->subdev.entity);
+       struct iss_video *video_out = &csi2->video_out;
+
+       if (csi2->state == ISS_PIPELINE_STREAM_STOPPED) {
+               if (enable == ISS_PIPELINE_STREAM_STOPPED)
+                       return 0;
+
+               if (csi2 == &iss->csi2a)
+                       omap4iss_subclk_enable(iss, OMAP4_ISS_SUBCLK_CSI2_A);
+               else if (csi2 == &iss->csi2b)
+                       omap4iss_subclk_enable(iss, OMAP4_ISS_SUBCLK_CSI2_B);
+       }
+
+       switch (enable) {
+       case ISS_PIPELINE_STREAM_CONTINUOUS: {
+               int ret;
+
+               ret = omap4iss_csiphy_config(iss, sd);
+               if (ret < 0)
+                       return ret;
+
+               if (omap4iss_csiphy_acquire(csi2->phy) < 0)
+                       return -ENODEV;
+               csi2->use_fs_irq = pipe->do_propagation;
+               csi2_configure(csi2);
+               csi2_print_status(csi2);
+
+               /*
+                * When outputting to memory with no buffer available, let the
+                * buffer queue handler start the hardware. A DMA queue flag
+                * ISS_VIDEO_DMAQUEUE_QUEUED will be set as soon as there is
+                * a buffer available.
+                */
+               if (csi2->output & CSI2_OUTPUT_MEMORY &&
+                   !(video_out->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_QUEUED))
+                       break;
+               /* Enable context 0 and IRQs */
+               atomic_set(&csi2->stopping, 0);
+               csi2_ctx_enable(csi2, 0, 1);
+               csi2_if_enable(csi2, 1);
+               iss_video_dmaqueue_flags_clr(video_out);
+               break;
+       }
+       case ISS_PIPELINE_STREAM_STOPPED:
+               if (csi2->state == ISS_PIPELINE_STREAM_STOPPED)
+                       return 0;
+               if (omap4iss_module_sync_idle(&sd->entity, &csi2->wait,
+                                             &csi2->stopping))
+                       dev_dbg(iss->dev, "%s: module stop timeout.\n",
+                               sd->name);
+               csi2_ctx_enable(csi2, 0, 0);
+               csi2_if_enable(csi2, 0);
+               csi2_irq_ctx_set(csi2, 0);
+               omap4iss_csiphy_release(csi2->phy);
+               if (csi2 == &iss->csi2a)
+                       omap4iss_subclk_disable(iss, OMAP4_ISS_SUBCLK_CSI2_A);
+               else if (csi2 == &iss->csi2b)
+                       omap4iss_subclk_disable(iss, OMAP4_ISS_SUBCLK_CSI2_B);
+               iss_video_dmaqueue_flags_clr(video_out);
+               break;
+       }
+
+       csi2->state = enable;
+       return 0;
+}
+
+/* subdev video operations */
+static const struct v4l2_subdev_video_ops csi2_video_ops = {
+       .s_stream = csi2_set_stream,
+};
+
+/* subdev pad operations */
+static const struct v4l2_subdev_pad_ops csi2_pad_ops = {
+       .enum_mbus_code = csi2_enum_mbus_code,
+       .enum_frame_size = csi2_enum_frame_size,
+       .get_fmt = csi2_get_format,
+       .set_fmt = csi2_set_format,
+       .link_validate = csi2_link_validate,
+};
+
+/* subdev operations */
+static const struct v4l2_subdev_ops csi2_ops = {
+       .video = &csi2_video_ops,
+       .pad = &csi2_pad_ops,
+};
+
+/* subdev internal operations */
+static const struct v4l2_subdev_internal_ops csi2_internal_ops = {
+       .open = csi2_init_formats,
+};
+
+/* -----------------------------------------------------------------------------
+ * Media entity operations
+ */
+
+/*
+ * csi2_link_setup - Setup CSI2 connections.
+ * @entity : Pointer to media entity structure
+ * @local  : Pointer to local pad array
+ * @remote : Pointer to remote pad array
+ * @flags  : Link flags
+ * return -EINVAL or zero on success
+ */
+static int csi2_link_setup(struct media_entity *entity,
+                          const struct media_pad *local,
+                          const struct media_pad *remote, u32 flags)
+{
+       struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
+       struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd);
+       struct iss_csi2_ctrl_cfg *ctrl = &csi2->ctrl;
+
+       /*
+        * The ISS core doesn't support pipelines with multiple video outputs.
+        * Revisit this when it will be implemented, and return -EBUSY for now.
+        */
+
+       switch (local->index | media_entity_type(remote->entity)) {
+       case CSI2_PAD_SOURCE | MEDIA_ENT_T_DEVNODE:
+               if (flags & MEDIA_LNK_FL_ENABLED) {
+                       if (csi2->output & ~CSI2_OUTPUT_MEMORY)
+                               return -EBUSY;
+                       csi2->output |= CSI2_OUTPUT_MEMORY;
+               } else {
+                       csi2->output &= ~CSI2_OUTPUT_MEMORY;
+               }
+               break;
+
+       case CSI2_PAD_SOURCE | MEDIA_ENT_T_V4L2_SUBDEV:
+               if (flags & MEDIA_LNK_FL_ENABLED) {
+                       if (csi2->output & ~CSI2_OUTPUT_IPIPEIF)
+                               return -EBUSY;
+                       csi2->output |= CSI2_OUTPUT_IPIPEIF;
+               } else {
+                       csi2->output &= ~CSI2_OUTPUT_IPIPEIF;
+               }
+               break;
+
+       default:
+               /* Link from camera to CSI2 is fixed... */
+               return -EINVAL;
+       }
+
+       ctrl->vp_only_enable =
+               (csi2->output & CSI2_OUTPUT_MEMORY) ? false : true;
+       ctrl->vp_clk_enable = !!(csi2->output & CSI2_OUTPUT_IPIPEIF);
+
+       return 0;
+}
+
+/* media operations */
+static const struct media_entity_operations csi2_media_ops = {
+       .link_setup = csi2_link_setup,
+       .link_validate = v4l2_subdev_link_validate,
+};
+
+void omap4iss_csi2_unregister_entities(struct iss_csi2_device *csi2)
+{
+       v4l2_device_unregister_subdev(&csi2->subdev);
+       omap4iss_video_unregister(&csi2->video_out);
+}
+
+int omap4iss_csi2_register_entities(struct iss_csi2_device *csi2,
+                                   struct v4l2_device *vdev)
+{
+       int ret;
+
+       /* Register the subdev and video nodes. */
+       ret = v4l2_device_register_subdev(vdev, &csi2->subdev);
+       if (ret < 0)
+               goto error;
+
+       ret = omap4iss_video_register(&csi2->video_out, vdev);
+       if (ret < 0)
+               goto error;
+
+       return 0;
+
+error:
+       omap4iss_csi2_unregister_entities(csi2);
+       return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * ISS CSI2 initialisation and cleanup
+ */
+
+/*
+ * csi2_init_entities - Initialize subdev and media entity.
+ * @csi2: Pointer to csi2 structure.
+ * return -ENOMEM or zero on success
+ */
+static int csi2_init_entities(struct iss_csi2_device *csi2, const char *subname)
+{
+       struct v4l2_subdev *sd = &csi2->subdev;
+       struct media_pad *pads = csi2->pads;
+       struct media_entity *me = &sd->entity;
+       int ret;
+       char name[V4L2_SUBDEV_NAME_SIZE];
+
+       v4l2_subdev_init(sd, &csi2_ops);
+       sd->internal_ops = &csi2_internal_ops;
+       sprintf(name, "CSI2%s", subname);
+       strlcpy(sd->name, "", sizeof(sd->name));
+       sprintf(sd->name, "OMAP4 ISS %s", name);
+
+       sd->grp_id = 1 << 16;   /* group ID for iss subdevs */
+       v4l2_set_subdevdata(sd, csi2);
+       sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+       pads[CSI2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+       pads[CSI2_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+
+       me->ops = &csi2_media_ops;
+       ret = media_entity_init(me, CSI2_PADS_NUM, pads, 0);
+       if (ret < 0)
+               return ret;
+
+       csi2_init_formats(sd, NULL);
+
+       /* Video device node */
+       csi2->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       csi2->video_out.ops = &csi2_issvideo_ops;
+       csi2->video_out.bpl_alignment = 32;
+       csi2->video_out.bpl_zero_padding = 1;
+       csi2->video_out.bpl_max = 0x1ffe0;
+       csi2->video_out.iss = csi2->iss;
+       csi2->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 3;
+
+       ret = omap4iss_video_init(&csi2->video_out, name);
+       if (ret < 0)
+               goto error_video;
+
+       /* Connect the CSI2 subdev to the video node. */
+       ret = media_entity_create_link(&csi2->subdev.entity, CSI2_PAD_SOURCE,
+                                      &csi2->video_out.video.entity, 0, 0);
+       if (ret < 0)
+               goto error_link;
+
+       return 0;
+
+error_link:
+       omap4iss_video_cleanup(&csi2->video_out);
+error_video:
+       media_entity_cleanup(&csi2->subdev.entity);
+       return ret;
+}
+
+/*
+ * omap4iss_csi2_init - Routine for module driver init
+ */
+int omap4iss_csi2_init(struct iss_device *iss)
+{
+       struct iss_csi2_device *csi2a = &iss->csi2a;
+       struct iss_csi2_device *csi2b = &iss->csi2b;
+       int ret;
+
+       csi2a->iss = iss;
+       csi2a->available = 1;
+       csi2a->regs1 = iss->regs[OMAP4_ISS_MEM_CSI2_A_REGS1];
+       csi2a->phy = &iss->csiphy1;
+       csi2a->state = ISS_PIPELINE_STREAM_STOPPED;
+       init_waitqueue_head(&csi2a->wait);
+
+       ret = csi2_init_entities(csi2a, "a");
+       if (ret < 0)
+               return ret;
+
+       csi2b->iss = iss;
+       csi2b->available = 1;
+       csi2b->regs1 = iss->regs[OMAP4_ISS_MEM_CSI2_B_REGS1];
+       csi2b->phy = &iss->csiphy2;
+       csi2b->state = ISS_PIPELINE_STREAM_STOPPED;
+       init_waitqueue_head(&csi2b->wait);
+
+       ret = csi2_init_entities(csi2b, "b");
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+/*
+ * omap4iss_csi2_cleanup - Routine for module driver cleanup
+ */
+void omap4iss_csi2_cleanup(struct iss_device *iss)
+{
+       struct iss_csi2_device *csi2a = &iss->csi2a;
+       struct iss_csi2_device *csi2b = &iss->csi2b;
+
+       omap4iss_video_cleanup(&csi2a->video_out);
+       media_entity_cleanup(&csi2a->subdev.entity);
+
+       omap4iss_video_cleanup(&csi2b->video_out);
+       media_entity_cleanup(&csi2b->subdev.entity);
+}
diff --git a/drivers/staging/media/omap4iss/iss_csi2.h b/drivers/staging/media/omap4iss/iss_csi2.h
new file mode 100644 (file)
index 0000000..d1d077b
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * TI OMAP4 ISS V4L2 Driver - CSI2 module
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef OMAP4_ISS_CSI2_H
+#define OMAP4_ISS_CSI2_H
+
+#include <linux/types.h>
+#include <linux/videodev2.h>
+
+#include "iss_video.h"
+
+struct iss_csiphy;
+
+/* This is not an exhaustive list */
+enum iss_csi2_pix_formats {
+       CSI2_PIX_FMT_OTHERS = 0,
+       CSI2_PIX_FMT_YUV422_8BIT = 0x1e,
+       CSI2_PIX_FMT_YUV422_8BIT_VP = 0x9e,
+       CSI2_PIX_FMT_YUV422_8BIT_VP16 = 0xde,
+       CSI2_PIX_FMT_RAW10_EXP16 = 0xab,
+       CSI2_PIX_FMT_RAW10_EXP16_VP = 0x12f,
+       CSI2_PIX_FMT_RAW8 = 0x2a,
+       CSI2_PIX_FMT_RAW8_DPCM10_EXP16 = 0x2aa,
+       CSI2_PIX_FMT_RAW8_DPCM10_VP = 0x32a,
+       CSI2_PIX_FMT_RAW8_VP = 0x12a,
+       CSI2_USERDEF_8BIT_DATA1_DPCM10_VP = 0x340,
+       CSI2_USERDEF_8BIT_DATA1_DPCM10 = 0x2c0,
+       CSI2_USERDEF_8BIT_DATA1 = 0x40,
+};
+
+enum iss_csi2_irqevents {
+       OCP_ERR_IRQ = 0x4000,
+       SHORT_PACKET_IRQ = 0x2000,
+       ECC_CORRECTION_IRQ = 0x1000,
+       ECC_NO_CORRECTION_IRQ = 0x800,
+       COMPLEXIO2_ERR_IRQ = 0x400,
+       COMPLEXIO1_ERR_IRQ = 0x200,
+       FIFO_OVF_IRQ = 0x100,
+       CONTEXT7 = 0x80,
+       CONTEXT6 = 0x40,
+       CONTEXT5 = 0x20,
+       CONTEXT4 = 0x10,
+       CONTEXT3 = 0x8,
+       CONTEXT2 = 0x4,
+       CONTEXT1 = 0x2,
+       CONTEXT0 = 0x1,
+};
+
+enum iss_csi2_ctx_irqevents {
+       CTX_ECC_CORRECTION = 0x100,
+       CTX_LINE_NUMBER = 0x80,
+       CTX_FRAME_NUMBER = 0x40,
+       CTX_CS = 0x20,
+       CTX_LE = 0x8,
+       CTX_LS = 0x4,
+       CTX_FE = 0x2,
+       CTX_FS = 0x1,
+};
+
+enum iss_csi2_frame_mode {
+       ISS_CSI2_FRAME_IMMEDIATE,
+       ISS_CSI2_FRAME_AFTERFEC,
+};
+
+#define ISS_CSI2_MAX_CTX_NUM   7
+
+struct iss_csi2_ctx_cfg {
+       u8 ctxnum;              /* context number 0 - 7 */
+       u8 dpcm_decompress;
+
+       /* Fields in CSI2_CTx_CTRL2 - locked by CSI2_CTx_CTRL1.CTX_EN */
+       u8 virtual_id;
+       u16 format_id;          /* as in CSI2_CTx_CTRL2[9:0] */
+       u8 dpcm_predictor;      /* 1: simple, 0: advanced */
+
+       /* Fields in CSI2_CTx_CTRL1/3 - Shadowed */
+       u16 alpha;
+       u16 data_offset;
+       u32 ping_addr;
+       u32 pong_addr;
+       u8 eof_enabled;
+       u8 eol_enabled;
+       u8 checksum_enabled;
+       u8 enabled;
+};
+
+struct iss_csi2_timing_cfg {
+       u8 ionum;                       /* IO1 or IO2 as in CSI2_TIMING */
+       unsigned force_rx_mode:1;
+       unsigned stop_state_16x:1;
+       unsigned stop_state_4x:1;
+       u16 stop_state_counter;
+};
+
+struct iss_csi2_ctrl_cfg {
+       bool vp_clk_enable;
+       bool vp_only_enable;
+       u8 vp_out_ctrl;
+       enum iss_csi2_frame_mode frame_mode;
+       bool ecc_enable;
+       bool if_enable;
+};
+
+#define CSI2_PAD_SINK          0
+#define CSI2_PAD_SOURCE                1
+#define CSI2_PADS_NUM          2
+
+#define CSI2_OUTPUT_IPIPEIF    (1 << 0)
+#define CSI2_OUTPUT_MEMORY     (1 << 1)
+
+struct iss_csi2_device {
+       struct v4l2_subdev subdev;
+       struct media_pad pads[CSI2_PADS_NUM];
+       struct v4l2_mbus_framefmt formats[CSI2_PADS_NUM];
+
+       struct iss_video video_out;
+       struct iss_device *iss;
+
+       u8 available;           /* Is the IP present on the silicon? */
+
+       /* Pointer to register remaps into kernel space */
+       void __iomem *regs1;
+       void __iomem *regs2;
+
+       u32 output; /* output to IPIPEIF, memory or both? */
+       bool dpcm_decompress;
+       unsigned int frame_skip;
+       bool use_fs_irq;
+
+       struct iss_csiphy *phy;
+       struct iss_csi2_ctx_cfg contexts[ISS_CSI2_MAX_CTX_NUM + 1];
+       struct iss_csi2_timing_cfg timing[2];
+       struct iss_csi2_ctrl_cfg ctrl;
+       enum iss_pipeline_stream_state state;
+       wait_queue_head_t wait;
+       atomic_t stopping;
+};
+
+void omap4iss_csi2_isr(struct iss_csi2_device *csi2);
+int omap4iss_csi2_reset(struct iss_csi2_device *csi2);
+int omap4iss_csi2_init(struct iss_device *iss);
+void omap4iss_csi2_cleanup(struct iss_device *iss);
+void omap4iss_csi2_unregister_entities(struct iss_csi2_device *csi2);
+int omap4iss_csi2_register_entities(struct iss_csi2_device *csi2,
+                                   struct v4l2_device *vdev);
+#endif /* OMAP4_ISS_CSI2_H */
diff --git a/drivers/staging/media/omap4iss/iss_csiphy.c b/drivers/staging/media/omap4iss/iss_csiphy.c
new file mode 100644 (file)
index 0000000..2afea98
--- /dev/null
@@ -0,0 +1,278 @@
+/*
+ * TI OMAP4 ISS V4L2 Driver - CSI PHY module
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+
+#include "../../../../arch/arm/mach-omap2/control.h"
+
+#include "iss.h"
+#include "iss_regs.h"
+#include "iss_csiphy.h"
+
+/*
+ * csiphy_lanes_config - Configuration of CSIPHY lanes.
+ *
+ * Updates HW configuration.
+ * Called with phy->mutex taken.
+ */
+static void csiphy_lanes_config(struct iss_csiphy *phy)
+{
+       unsigned int i;
+       u32 reg;
+
+       reg = readl(phy->cfg_regs + CSI2_COMPLEXIO_CFG);
+
+       for (i = 0; i < phy->max_data_lanes; i++) {
+               reg &= ~(CSI2_COMPLEXIO_CFG_DATA_POL(i + 1) |
+                        CSI2_COMPLEXIO_CFG_DATA_POSITION_MASK(i + 1));
+               reg |= (phy->lanes.data[i].pol ?
+                       CSI2_COMPLEXIO_CFG_DATA_POL(i + 1) : 0);
+               reg |= (phy->lanes.data[i].pos <<
+                       CSI2_COMPLEXIO_CFG_DATA_POSITION_SHIFT(i + 1));
+       }
+
+       reg &= ~(CSI2_COMPLEXIO_CFG_CLOCK_POL |
+                CSI2_COMPLEXIO_CFG_CLOCK_POSITION_MASK);
+       reg |= phy->lanes.clk.pol ? CSI2_COMPLEXIO_CFG_CLOCK_POL : 0;
+       reg |= phy->lanes.clk.pos << CSI2_COMPLEXIO_CFG_CLOCK_POSITION_SHIFT;
+
+       writel(reg, phy->cfg_regs + CSI2_COMPLEXIO_CFG);
+}
+
+/*
+ * csiphy_set_power
+ * @power: Power state to be set.
+ *
+ * Returns 0 if successful, or -EBUSY if the retry count is exceeded.
+ */
+static int csiphy_set_power(struct iss_csiphy *phy, u32 power)
+{
+       u32 reg;
+       u8 retry_count;
+
+       writel((readl(phy->cfg_regs + CSI2_COMPLEXIO_CFG) &
+               ~CSI2_COMPLEXIO_CFG_PWD_CMD_MASK) |
+               power,
+               phy->cfg_regs + CSI2_COMPLEXIO_CFG);
+
+       retry_count = 0;
+       do {
+               udelay(1);
+               reg = readl(phy->cfg_regs + CSI2_COMPLEXIO_CFG) &
+                               CSI2_COMPLEXIO_CFG_PWD_STATUS_MASK;
+
+               if (reg != power >> 2)
+                       retry_count++;
+
+       } while ((reg != power >> 2) && (retry_count < 250));
+
+       if (retry_count == 250) {
+               printk(KERN_ERR "CSI2 CIO set power failed!\n");
+               return -EBUSY;
+       }
+
+       return 0;
+}
+
+/*
+ * csiphy_dphy_config - Configure CSI2 D-PHY parameters.
+ *
+ * Called with phy->mutex taken.
+ */
+static void csiphy_dphy_config(struct iss_csiphy *phy)
+{
+       u32 reg;
+
+       /* Set up REGISTER0 */
+       reg = phy->dphy.ths_term << REGISTER0_THS_TERM_SHIFT;
+       reg |= phy->dphy.ths_settle << REGISTER0_THS_SETTLE_SHIFT;
+
+       writel(reg, phy->phy_regs + REGISTER0);
+
+       /* Set up REGISTER1 */
+       reg = phy->dphy.tclk_term << REGISTER1_TCLK_TERM_SHIFT;
+       reg |= phy->dphy.tclk_miss << REGISTER1_CTRLCLK_DIV_FACTOR_SHIFT;
+       reg |= phy->dphy.tclk_settle << REGISTER1_TCLK_SETTLE_SHIFT;
+       reg |= 0xB8 << REGISTER1_DPHY_HS_SYNC_PATTERN_SHIFT;
+
+       writel(reg, phy->phy_regs + REGISTER1);
+}
+
+/*
+ * TCLK values are OK at their reset values
+ */
+#define TCLK_TERM      0
+#define TCLK_MISS      1
+#define TCLK_SETTLE    14
+
+int omap4iss_csiphy_config(struct iss_device *iss,
+                          struct v4l2_subdev *csi2_subdev)
+{
+       struct iss_csi2_device *csi2 = v4l2_get_subdevdata(csi2_subdev);
+       struct iss_pipeline *pipe = to_iss_pipeline(&csi2_subdev->entity);
+       struct iss_v4l2_subdevs_group *subdevs = pipe->external->host_priv;
+       struct iss_csiphy_dphy_cfg csi2phy;
+       int csi2_ddrclk_khz;
+       struct iss_csiphy_lanes_cfg *lanes;
+       unsigned int used_lanes = 0;
+       u32 cam_rx_ctrl;
+       unsigned int i;
+
+       lanes = &subdevs->bus.csi2.lanecfg;
+
+       /*
+        * SCM.CONTROL_CAMERA_RX
+        * - bit [31] : CSIPHY2 lane 2 enable (4460+ only)
+        * - bit [30:29] : CSIPHY2 per-lane enable (1 to 0)
+        * - bit [28:24] : CSIPHY1 per-lane enable (4 to 0)
+        * - bit [21] : CSIPHY2 CTRLCLK enable
+        * - bit [20:19] : CSIPHY2 config: 00 d-phy, 01/10 ccp2
+        * - bit [18] : CSIPHY1 CTRLCLK enable
+        * - bit [17:16] : CSIPHY1 config: 00 d-phy, 01/10 ccp2
+        */
+       cam_rx_ctrl = omap4_ctrl_pad_readl(
+                       OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_CAMERA_RX);
+
+
+       if (subdevs->interface == ISS_INTERFACE_CSI2A_PHY1) {
+               cam_rx_ctrl &= ~(OMAP4_CAMERARX_CSI21_LANEENABLE_MASK |
+                               OMAP4_CAMERARX_CSI21_CAMMODE_MASK);
+               /* NOTE: Leave CSIPHY1 config to 0x0: D-PHY mode */
+               /* Enable all lanes for now */
+               cam_rx_ctrl |=
+                       0x1F << OMAP4_CAMERARX_CSI21_LANEENABLE_SHIFT;
+               /* Enable CTRLCLK */
+               cam_rx_ctrl |= OMAP4_CAMERARX_CSI21_CTRLCLKEN_MASK;
+       }
+
+       if (subdevs->interface == ISS_INTERFACE_CSI2B_PHY2) {
+               cam_rx_ctrl &= ~(OMAP4_CAMERARX_CSI22_LANEENABLE_MASK |
+                               OMAP4_CAMERARX_CSI22_CAMMODE_MASK);
+               /* NOTE: Leave CSIPHY2 config to 0x0: D-PHY mode */
+               /* Enable all lanes for now */
+               cam_rx_ctrl |=
+                       0x3 << OMAP4_CAMERARX_CSI22_LANEENABLE_SHIFT;
+               /* Enable CTRLCLK */
+               cam_rx_ctrl |= OMAP4_CAMERARX_CSI22_CTRLCLKEN_MASK;
+       }
+
+       omap4_ctrl_pad_writel(cam_rx_ctrl,
+                OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_CAMERA_RX);
+
+       /* Reset used lane count */
+       csi2->phy->used_data_lanes = 0;
+
+       /* Clock and data lanes verification */
+       for (i = 0; i < csi2->phy->max_data_lanes; i++) {
+               if (lanes->data[i].pos == 0)
+                       continue;
+
+               if (lanes->data[i].pol > 1 || lanes->data[i].pos > (csi2->phy->max_data_lanes + 1))
+                       return -EINVAL;
+
+               if (used_lanes & (1 << lanes->data[i].pos))
+                       return -EINVAL;
+
+               used_lanes |= 1 << lanes->data[i].pos;
+               csi2->phy->used_data_lanes++;
+       }
+
+       if (lanes->clk.pol > 1 || lanes->clk.pos > (csi2->phy->max_data_lanes + 1))
+               return -EINVAL;
+
+       if (lanes->clk.pos == 0 || used_lanes & (1 << lanes->clk.pos))
+               return -EINVAL;
+
+       csi2_ddrclk_khz = pipe->external_rate / 1000
+               / (2 * csi2->phy->used_data_lanes)
+               * pipe->external_bpp;
+
+       /*
+        * THS_TERM: Programmed value = ceil(12.5 ns/DDRClk period) - 1.
+        * THS_SETTLE: Programmed value = ceil(90 ns/DDRClk period) + 3.
+        */
+       csi2phy.ths_term = DIV_ROUND_UP(25 * csi2_ddrclk_khz, 2000000) - 1;
+       csi2phy.ths_settle = DIV_ROUND_UP(90 * csi2_ddrclk_khz, 1000000) + 3;
+       csi2phy.tclk_term = TCLK_TERM;
+       csi2phy.tclk_miss = TCLK_MISS;
+       csi2phy.tclk_settle = TCLK_SETTLE;
+
+       mutex_lock(&csi2->phy->mutex);
+       csi2->phy->dphy = csi2phy;
+       csi2->phy->lanes = *lanes;
+       mutex_unlock(&csi2->phy->mutex);
+
+       return 0;
+}
+
+int omap4iss_csiphy_acquire(struct iss_csiphy *phy)
+{
+       int rval;
+
+       mutex_lock(&phy->mutex);
+
+       rval = omap4iss_csi2_reset(phy->csi2);
+       if (rval)
+               goto done;
+
+       csiphy_dphy_config(phy);
+       csiphy_lanes_config(phy);
+
+       rval = csiphy_set_power(phy, CSI2_COMPLEXIO_CFG_PWD_CMD_ON);
+       if (rval)
+               goto done;
+
+       phy->phy_in_use = 1;
+
+done:
+       mutex_unlock(&phy->mutex);
+       return rval;
+}
+
+void omap4iss_csiphy_release(struct iss_csiphy *phy)
+{
+       mutex_lock(&phy->mutex);
+       if (phy->phy_in_use) {
+               csiphy_set_power(phy, CSI2_COMPLEXIO_CFG_PWD_CMD_OFF);
+               phy->phy_in_use = 0;
+       }
+       mutex_unlock(&phy->mutex);
+}
+
+/*
+ * omap4iss_csiphy_init - Initialize the CSI PHY frontends
+ */
+int omap4iss_csiphy_init(struct iss_device *iss)
+{
+       struct iss_csiphy *phy1 = &iss->csiphy1;
+       struct iss_csiphy *phy2 = &iss->csiphy2;
+
+       phy1->iss = iss;
+       phy1->csi2 = &iss->csi2a;
+       phy1->max_data_lanes = ISS_CSIPHY1_NUM_DATA_LANES;
+       phy1->used_data_lanes = 0;
+       phy1->cfg_regs = iss->regs[OMAP4_ISS_MEM_CSI2_A_REGS1];
+       phy1->phy_regs = iss->regs[OMAP4_ISS_MEM_CAMERARX_CORE1];
+       mutex_init(&phy1->mutex);
+
+       phy2->iss = iss;
+       phy2->csi2 = &iss->csi2b;
+       phy2->max_data_lanes = ISS_CSIPHY2_NUM_DATA_LANES;
+       phy2->used_data_lanes = 0;
+       phy2->cfg_regs = iss->regs[OMAP4_ISS_MEM_CSI2_B_REGS1];
+       phy2->phy_regs = iss->regs[OMAP4_ISS_MEM_CAMERARX_CORE2];
+       mutex_init(&phy2->mutex);
+
+       return 0;
+}
diff --git a/drivers/staging/media/omap4iss/iss_csiphy.h b/drivers/staging/media/omap4iss/iss_csiphy.h
new file mode 100644 (file)
index 0000000..df63eda
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * TI OMAP4 ISS V4L2 Driver - CSI PHY module
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef OMAP4_ISS_CSI_PHY_H
+#define OMAP4_ISS_CSI_PHY_H
+
+#include <media/omap4iss.h>
+
+struct iss_csi2_device;
+
+struct iss_csiphy_dphy_cfg {
+       u8 ths_term;
+       u8 ths_settle;
+       u8 tclk_term;
+       unsigned tclk_miss:1;
+       u8 tclk_settle;
+};
+
+struct iss_csiphy {
+       struct iss_device *iss;
+       struct mutex mutex;     /* serialize csiphy configuration */
+       u8 phy_in_use;
+       struct iss_csi2_device *csi2;
+
+       /* Pointer to register remaps into kernel space */
+       void __iomem *cfg_regs;
+       void __iomem *phy_regs;
+
+       u8 max_data_lanes;      /* number of CSI2 Data Lanes supported */
+       u8 used_data_lanes;     /* number of CSI2 Data Lanes used */
+       struct iss_csiphy_lanes_cfg lanes;
+       struct iss_csiphy_dphy_cfg dphy;
+};
+
+int omap4iss_csiphy_config(struct iss_device *iss,
+                          struct v4l2_subdev *csi2_subdev);
+int omap4iss_csiphy_acquire(struct iss_csiphy *phy);
+void omap4iss_csiphy_release(struct iss_csiphy *phy);
+int omap4iss_csiphy_init(struct iss_device *iss);
+
+#endif /* OMAP4_ISS_CSI_PHY_H */
diff --git a/drivers/staging/media/omap4iss/iss_ipipe.c b/drivers/staging/media/omap4iss/iss_ipipe.c
new file mode 100644 (file)
index 0000000..fc38a5c
--- /dev/null
@@ -0,0 +1,581 @@
+/*
+ * TI OMAP4 ISS V4L2 Driver - ISP IPIPE module
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+
+#include "iss.h"
+#include "iss_regs.h"
+#include "iss_ipipe.h"
+
+static struct v4l2_mbus_framefmt *
+__ipipe_get_format(struct iss_ipipe_device *ipipe, struct v4l2_subdev_fh *fh,
+                 unsigned int pad, enum v4l2_subdev_format_whence which);
+
+static const unsigned int ipipe_fmts[] = {
+       V4L2_MBUS_FMT_SGRBG10_1X10,
+       V4L2_MBUS_FMT_SRGGB10_1X10,
+       V4L2_MBUS_FMT_SBGGR10_1X10,
+       V4L2_MBUS_FMT_SGBRG10_1X10,
+};
+
+/*
+ * ipipe_print_status - Print current IPIPE Module register values.
+ * @ipipe: Pointer to ISS ISP IPIPE device.
+ *
+ * Also prints other debug information stored in the IPIPE module.
+ */
+#define IPIPE_PRINT_REGISTER(iss, name)\
+       dev_dbg(iss->dev, "###IPIPE " #name "=0x%08x\n", \
+               readl(iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_##name))
+
+static void ipipe_print_status(struct iss_ipipe_device *ipipe)
+{
+       struct iss_device *iss = to_iss_device(ipipe);
+
+       dev_dbg(iss->dev, "-------------IPIPE Register dump-------------\n");
+
+       IPIPE_PRINT_REGISTER(iss, SRC_EN);
+       IPIPE_PRINT_REGISTER(iss, SRC_MODE);
+       IPIPE_PRINT_REGISTER(iss, SRC_FMT);
+       IPIPE_PRINT_REGISTER(iss, SRC_COL);
+       IPIPE_PRINT_REGISTER(iss, SRC_VPS);
+       IPIPE_PRINT_REGISTER(iss, SRC_VSZ);
+       IPIPE_PRINT_REGISTER(iss, SRC_HPS);
+       IPIPE_PRINT_REGISTER(iss, SRC_HSZ);
+       IPIPE_PRINT_REGISTER(iss, GCK_MMR);
+       IPIPE_PRINT_REGISTER(iss, YUV_PHS);
+
+       dev_dbg(iss->dev, "-----------------------------------------------\n");
+}
+
+/*
+ * ipipe_enable - Enable/Disable IPIPE.
+ * @enable: enable flag
+ *
+ */
+static void ipipe_enable(struct iss_ipipe_device *ipipe, u8 enable)
+{
+       struct iss_device *iss = to_iss_device(ipipe);
+
+       writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_SRC_EN) &
+               ~IPIPE_SRC_EN_EN) |
+               enable ? IPIPE_SRC_EN_EN : 0,
+               iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_SRC_EN);
+}
+
+/* -----------------------------------------------------------------------------
+ * Format- and pipeline-related configuration helpers
+ */
+
+static void ipipe_configure(struct iss_ipipe_device *ipipe)
+{
+       struct iss_device *iss = to_iss_device(ipipe);
+       struct v4l2_mbus_framefmt *format;
+
+       /* IPIPE_PAD_SINK */
+       format = &ipipe->formats[IPIPE_PAD_SINK];
+
+       /* NOTE: Currently just supporting pipeline IN: RGB, OUT: YUV422 */
+       writel(IPIPE_SRC_FMT_RAW2YUV,
+               iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_SRC_FMT);
+
+       /* Enable YUV444 -> YUV422 conversion */
+       writel(IPIPE_YUV_PHS_LPF,
+               iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_YUV_PHS);
+
+       writel(0, iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_SRC_VPS);
+       writel(0, iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_SRC_HPS);
+       writel((format->height - 2) & IPIPE_SRC_VSZ_MASK,
+               iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_SRC_VSZ);
+       writel((format->width - 1) & IPIPE_SRC_HSZ_MASK,
+               iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_SRC_HSZ);
+
+       /* Ignore ipipeif_wrt signal, and operate on-the-fly.  */
+       writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_SRC_MODE) &
+               ~(IPIPE_SRC_MODE_WRT | IPIPE_SRC_MODE_OST),
+               iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_SRC_MODE);
+
+       /* HACK: Values tuned for Ducati SW (OV) */
+       writel(IPIPE_SRC_COL_EE_B |
+               IPIPE_SRC_COL_EO_GB |
+               IPIPE_SRC_COL_OE_GR |
+               IPIPE_SRC_COL_OO_R,
+               iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_SRC_COL);
+
+       /* IPIPE_PAD_SOURCE_VP */
+       format = &ipipe->formats[IPIPE_PAD_SOURCE_VP];
+       /* Do nothing? */
+
+       omap4iss_isp_enable_interrupts(iss);
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev operations
+ */
+
+/*
+ * ipipe_set_stream - Enable/Disable streaming on the IPIPE module
+ * @sd: ISP IPIPE V4L2 subdevice
+ * @enable: Enable/disable stream
+ */
+static int ipipe_set_stream(struct v4l2_subdev *sd, int enable)
+{
+       struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
+       struct iss_device *iss = to_iss_device(ipipe);
+       int ret = 0;
+
+       if (ipipe->state == ISS_PIPELINE_STREAM_STOPPED) {
+               if (enable == ISS_PIPELINE_STREAM_STOPPED)
+                       return 0;
+
+               omap4iss_isp_subclk_enable(iss, OMAP4_ISS_ISP_SUBCLK_IPIPE);
+
+               /* Enable clk_arm_g0 */
+               writel(IPIPE_GCK_MMR_REG,
+                       iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_GCK_MMR);
+
+               /* Enable clk_pix_g[3:0] */
+               writel(IPIPE_GCK_PIX_G3 |
+                       IPIPE_GCK_PIX_G2 |
+                       IPIPE_GCK_PIX_G1 |
+                       IPIPE_GCK_PIX_G0,
+                       iss->regs[OMAP4_ISS_MEM_ISP_IPIPE] + IPIPE_GCK_PIX);
+       }
+
+       switch (enable) {
+       case ISS_PIPELINE_STREAM_CONTINUOUS:
+
+               ipipe_configure(ipipe);
+               ipipe_print_status(ipipe);
+
+               atomic_set(&ipipe->stopping, 0);
+               ipipe_enable(ipipe, 1);
+               break;
+
+       case ISS_PIPELINE_STREAM_STOPPED:
+               if (ipipe->state == ISS_PIPELINE_STREAM_STOPPED)
+                       return 0;
+               if (omap4iss_module_sync_idle(&sd->entity, &ipipe->wait,
+                                             &ipipe->stopping))
+                       dev_dbg(iss->dev, "%s: module stop timeout.\n",
+                               sd->name);
+
+               ipipe_enable(ipipe, 0);
+               omap4iss_isp_disable_interrupts(iss);
+               omap4iss_isp_subclk_disable(iss, OMAP4_ISS_ISP_SUBCLK_IPIPE);
+               break;
+       }
+
+       ipipe->state = enable;
+       return ret;
+}
+
+static struct v4l2_mbus_framefmt *
+__ipipe_get_format(struct iss_ipipe_device *ipipe, struct v4l2_subdev_fh *fh,
+                 unsigned int pad, enum v4l2_subdev_format_whence which)
+{
+       if (which == V4L2_SUBDEV_FORMAT_TRY)
+               return v4l2_subdev_get_try_format(fh, pad);
+       else
+               return &ipipe->formats[pad];
+}
+
+/*
+ * ipipe_try_format - Try video format on a pad
+ * @ipipe: ISS IPIPE device
+ * @fh : V4L2 subdev file handle
+ * @pad: Pad number
+ * @fmt: Format
+ */
+static void
+ipipe_try_format(struct iss_ipipe_device *ipipe, struct v4l2_subdev_fh *fh,
+               unsigned int pad, struct v4l2_mbus_framefmt *fmt,
+               enum v4l2_subdev_format_whence which)
+{
+       struct v4l2_mbus_framefmt *format;
+       unsigned int width = fmt->width;
+       unsigned int height = fmt->height;
+       unsigned int i;
+
+       switch (pad) {
+       case IPIPE_PAD_SINK:
+               for (i = 0; i < ARRAY_SIZE(ipipe_fmts); i++) {
+                       if (fmt->code == ipipe_fmts[i])
+                               break;
+               }
+
+               /* If not found, use SGRBG10 as default */
+               if (i >= ARRAY_SIZE(ipipe_fmts))
+                       fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
+
+               /* Clamp the input size. */
+               fmt->width = clamp_t(u32, width, 1, 8192);
+               fmt->height = clamp_t(u32, height, 1, 8192);
+               fmt->colorspace = V4L2_COLORSPACE_SRGB;
+               break;
+
+       case IPIPE_PAD_SOURCE_VP:
+               format = __ipipe_get_format(ipipe, fh, IPIPE_PAD_SINK, which);
+               memcpy(fmt, format, sizeof(*fmt));
+
+               fmt->code = V4L2_MBUS_FMT_UYVY8_1X16;
+               fmt->width = clamp_t(u32, width, 32, fmt->width);
+               fmt->height = clamp_t(u32, height, 32, fmt->height);
+               fmt->colorspace = V4L2_COLORSPACE_JPEG;
+               break;
+       }
+
+       fmt->field = V4L2_FIELD_NONE;
+}
+
+/*
+ * ipipe_enum_mbus_code - Handle pixel format enumeration
+ * @sd     : pointer to v4l2 subdev structure
+ * @fh : V4L2 subdev file handle
+ * @code   : pointer to v4l2_subdev_mbus_code_enum structure
+ * return -EINVAL or zero on success
+ */
+static int ipipe_enum_mbus_code(struct v4l2_subdev *sd,
+                              struct v4l2_subdev_fh *fh,
+                              struct v4l2_subdev_mbus_code_enum *code)
+{
+       switch (code->pad) {
+       case IPIPE_PAD_SINK:
+               if (code->index >= ARRAY_SIZE(ipipe_fmts))
+                       return -EINVAL;
+
+               code->code = ipipe_fmts[code->index];
+               break;
+
+       case IPIPE_PAD_SOURCE_VP:
+               /* FIXME: Forced format conversion inside IPIPE ? */
+               if (code->index != 0)
+                       return -EINVAL;
+
+               code->code = V4L2_MBUS_FMT_UYVY8_1X16;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int ipipe_enum_frame_size(struct v4l2_subdev *sd,
+                               struct v4l2_subdev_fh *fh,
+                               struct v4l2_subdev_frame_size_enum *fse)
+{
+       struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
+       struct v4l2_mbus_framefmt format;
+
+       if (fse->index != 0)
+               return -EINVAL;
+
+       format.code = fse->code;
+       format.width = 1;
+       format.height = 1;
+       ipipe_try_format(ipipe, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
+       fse->min_width = format.width;
+       fse->min_height = format.height;
+
+       if (format.code != fse->code)
+               return -EINVAL;
+
+       format.code = fse->code;
+       format.width = -1;
+       format.height = -1;
+       ipipe_try_format(ipipe, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
+       fse->max_width = format.width;
+       fse->max_height = format.height;
+
+       return 0;
+}
+
+/*
+ * ipipe_get_format - Retrieve the video format on a pad
+ * @sd : ISP IPIPE V4L2 subdevice
+ * @fh : V4L2 subdev file handle
+ * @fmt: Format
+ *
+ * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
+ * to the format type.
+ */
+static int ipipe_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                          struct v4l2_subdev_format *fmt)
+{
+       struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
+       struct v4l2_mbus_framefmt *format;
+
+       format = __ipipe_get_format(ipipe, fh, fmt->pad, fmt->which);
+       if (format == NULL)
+               return -EINVAL;
+
+       fmt->format = *format;
+       return 0;
+}
+
+/*
+ * ipipe_set_format - Set the video format on a pad
+ * @sd : ISP IPIPE V4L2 subdevice
+ * @fh : V4L2 subdev file handle
+ * @fmt: Format
+ *
+ * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
+ * to the format type.
+ */
+static int ipipe_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                          struct v4l2_subdev_format *fmt)
+{
+       struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
+       struct v4l2_mbus_framefmt *format;
+
+       format = __ipipe_get_format(ipipe, fh, fmt->pad, fmt->which);
+       if (format == NULL)
+               return -EINVAL;
+
+       ipipe_try_format(ipipe, fh, fmt->pad, &fmt->format, fmt->which);
+       *format = fmt->format;
+
+       /* Propagate the format from sink to source */
+       if (fmt->pad == IPIPE_PAD_SINK) {
+               format = __ipipe_get_format(ipipe, fh, IPIPE_PAD_SOURCE_VP,
+                                          fmt->which);
+               *format = fmt->format;
+               ipipe_try_format(ipipe, fh, IPIPE_PAD_SOURCE_VP, format,
+                               fmt->which);
+       }
+
+       return 0;
+}
+
+static int ipipe_link_validate(struct v4l2_subdev *sd, struct media_link *link,
+                                struct v4l2_subdev_format *source_fmt,
+                                struct v4l2_subdev_format *sink_fmt)
+{
+       /* Check if the two ends match */
+       if (source_fmt->format.width != sink_fmt->format.width ||
+           source_fmt->format.height != sink_fmt->format.height)
+               return -EPIPE;
+
+       if (source_fmt->format.code != sink_fmt->format.code)
+               return -EPIPE;
+
+       return 0;
+}
+
+/*
+ * ipipe_init_formats - Initialize formats on all pads
+ * @sd: ISP IPIPE V4L2 subdevice
+ * @fh: V4L2 subdev file handle
+ *
+ * Initialize all pad formats with default values. If fh is not NULL, try
+ * formats are initialized on the file handle. Otherwise active formats are
+ * initialized on the device.
+ */
+static int ipipe_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+       struct v4l2_subdev_format format;
+
+       memset(&format, 0, sizeof(format));
+       format.pad = IPIPE_PAD_SINK;
+       format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+       format.format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
+       format.format.width = 4096;
+       format.format.height = 4096;
+       ipipe_set_format(sd, fh, &format);
+
+       return 0;
+}
+
+/* V4L2 subdev video operations */
+static const struct v4l2_subdev_video_ops ipipe_v4l2_video_ops = {
+       .s_stream = ipipe_set_stream,
+};
+
+/* V4L2 subdev pad operations */
+static const struct v4l2_subdev_pad_ops ipipe_v4l2_pad_ops = {
+       .enum_mbus_code = ipipe_enum_mbus_code,
+       .enum_frame_size = ipipe_enum_frame_size,
+       .get_fmt = ipipe_get_format,
+       .set_fmt = ipipe_set_format,
+       .link_validate = ipipe_link_validate,
+};
+
+/* V4L2 subdev operations */
+static const struct v4l2_subdev_ops ipipe_v4l2_ops = {
+       .video = &ipipe_v4l2_video_ops,
+       .pad = &ipipe_v4l2_pad_ops,
+};
+
+/* V4L2 subdev internal operations */
+static const struct v4l2_subdev_internal_ops ipipe_v4l2_internal_ops = {
+       .open = ipipe_init_formats,
+};
+
+/* -----------------------------------------------------------------------------
+ * Media entity operations
+ */
+
+/*
+ * ipipe_link_setup - Setup IPIPE connections
+ * @entity: IPIPE media entity
+ * @local: Pad at the local end of the link
+ * @remote: Pad at the remote end of the link
+ * @flags: Link flags
+ *
+ * return -EINVAL or zero on success
+ */
+static int ipipe_link_setup(struct media_entity *entity,
+                          const struct media_pad *local,
+                          const struct media_pad *remote, u32 flags)
+{
+       struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
+       struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
+       struct iss_device *iss = to_iss_device(ipipe);
+
+       switch (local->index | media_entity_type(remote->entity)) {
+       case IPIPE_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV:
+               /* Read from IPIPEIF. */
+               if (!(flags & MEDIA_LNK_FL_ENABLED)) {
+                       ipipe->input = IPIPE_INPUT_NONE;
+                       break;
+               }
+
+               if (ipipe->input != IPIPE_INPUT_NONE)
+                       return -EBUSY;
+
+               if (remote->entity == &iss->ipipeif.subdev.entity)
+                       ipipe->input = IPIPE_INPUT_IPIPEIF;
+
+               break;
+
+       case IPIPE_PAD_SOURCE_VP | MEDIA_ENT_T_V4L2_SUBDEV:
+               /* Send to RESIZER */
+               if (flags & MEDIA_LNK_FL_ENABLED) {
+                       if (ipipe->output & ~IPIPE_OUTPUT_VP)
+                               return -EBUSY;
+                       ipipe->output |= IPIPE_OUTPUT_VP;
+               } else {
+                       ipipe->output &= ~IPIPE_OUTPUT_VP;
+               }
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/* media operations */
+static const struct media_entity_operations ipipe_media_ops = {
+       .link_setup = ipipe_link_setup,
+       .link_validate = v4l2_subdev_link_validate,
+};
+
+/*
+ * ipipe_init_entities - Initialize V4L2 subdev and media entity
+ * @ipipe: ISS ISP IPIPE module
+ *
+ * Return 0 on success and a negative error code on failure.
+ */
+static int ipipe_init_entities(struct iss_ipipe_device *ipipe)
+{
+       struct v4l2_subdev *sd = &ipipe->subdev;
+       struct media_pad *pads = ipipe->pads;
+       struct media_entity *me = &sd->entity;
+       int ret;
+
+       ipipe->input = IPIPE_INPUT_NONE;
+
+       v4l2_subdev_init(sd, &ipipe_v4l2_ops);
+       sd->internal_ops = &ipipe_v4l2_internal_ops;
+       strlcpy(sd->name, "OMAP4 ISS ISP IPIPE", sizeof(sd->name));
+       sd->grp_id = 1 << 16;   /* group ID for iss subdevs */
+       v4l2_set_subdevdata(sd, ipipe);
+       sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+       pads[IPIPE_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+       pads[IPIPE_PAD_SOURCE_VP].flags = MEDIA_PAD_FL_SOURCE;
+
+       me->ops = &ipipe_media_ops;
+       ret = media_entity_init(me, IPIPE_PADS_NUM, pads, 0);
+       if (ret < 0)
+               return ret;
+
+       ipipe_init_formats(sd, NULL);
+
+       return 0;
+}
+
+void omap4iss_ipipe_unregister_entities(struct iss_ipipe_device *ipipe)
+{
+       media_entity_cleanup(&ipipe->subdev.entity);
+
+       v4l2_device_unregister_subdev(&ipipe->subdev);
+}
+
+int omap4iss_ipipe_register_entities(struct iss_ipipe_device *ipipe,
+       struct v4l2_device *vdev)
+{
+       int ret;
+
+       /* Register the subdev and video node. */
+       ret = v4l2_device_register_subdev(vdev, &ipipe->subdev);
+       if (ret < 0)
+               goto error;
+
+       return 0;
+
+error:
+       omap4iss_ipipe_unregister_entities(ipipe);
+       return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * ISP IPIPE initialisation and cleanup
+ */
+
+/*
+ * omap4iss_ipipe_init - IPIPE module initialization.
+ * @iss: Device pointer specific to the OMAP4 ISS.
+ *
+ * TODO: Get the initialisation values from platform data.
+ *
+ * Return 0 on success or a negative error code otherwise.
+ */
+int omap4iss_ipipe_init(struct iss_device *iss)
+{
+       struct iss_ipipe_device *ipipe = &iss->ipipe;
+
+       ipipe->state = ISS_PIPELINE_STREAM_STOPPED;
+       init_waitqueue_head(&ipipe->wait);
+
+       return ipipe_init_entities(ipipe);
+}
+
+/*
+ * omap4iss_ipipe_cleanup - IPIPE module cleanup.
+ * @iss: Device pointer specific to the OMAP4 ISS.
+ */
+void omap4iss_ipipe_cleanup(struct iss_device *iss)
+{
+       /* FIXME: are you sure there's nothing to do? */
+}
diff --git a/drivers/staging/media/omap4iss/iss_ipipe.h b/drivers/staging/media/omap4iss/iss_ipipe.h
new file mode 100644 (file)
index 0000000..c22d904
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * TI OMAP4 ISS V4L2 Driver - ISP IPIPE module
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef OMAP4_ISS_IPIPE_H
+#define OMAP4_ISS_IPIPE_H
+
+#include "iss_video.h"
+
+enum ipipe_input_entity {
+       IPIPE_INPUT_NONE,
+       IPIPE_INPUT_IPIPEIF,
+};
+
+#define IPIPE_OUTPUT_VP                (1 << 0)
+
+/* Sink and source IPIPE pads */
+#define IPIPE_PAD_SINK                         0
+#define IPIPE_PAD_SOURCE_VP                    1
+#define IPIPE_PADS_NUM                         2
+
+/*
+ * struct iss_ipipe_device - Structure for the IPIPE module to store its own
+ *                         information
+ * @subdev: V4L2 subdevice
+ * @pads: Sink and source media entity pads
+ * @formats: Active video formats
+ * @input: Active input
+ * @output: Active outputs
+ * @error: A hardware error occurred during capture
+ * @state: Streaming state
+ * @wait: Wait queue used to stop the module
+ * @stopping: Stopping state
+ */
+struct iss_ipipe_device {
+       struct v4l2_subdev subdev;
+       struct media_pad pads[IPIPE_PADS_NUM];
+       struct v4l2_mbus_framefmt formats[IPIPE_PADS_NUM];
+
+       enum ipipe_input_entity input;
+       unsigned int output;
+       unsigned int error;
+
+       enum iss_pipeline_stream_state state;
+       wait_queue_head_t wait;
+       atomic_t stopping;
+};
+
+struct iss_device;
+
+int omap4iss_ipipe_register_entities(struct iss_ipipe_device *ipipe,
+       struct v4l2_device *vdev);
+void omap4iss_ipipe_unregister_entities(struct iss_ipipe_device *ipipe);
+
+int omap4iss_ipipe_init(struct iss_device *iss);
+void omap4iss_ipipe_cleanup(struct iss_device *iss);
+
+#endif /* OMAP4_ISS_IPIPE_H */
diff --git a/drivers/staging/media/omap4iss/iss_ipipeif.c b/drivers/staging/media/omap4iss/iss_ipipeif.c
new file mode 100644 (file)
index 0000000..acc6005
--- /dev/null
@@ -0,0 +1,847 @@
+/*
+ * TI OMAP4 ISS V4L2 Driver - ISP IPIPEIF module
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+
+#include "iss.h"
+#include "iss_regs.h"
+#include "iss_ipipeif.h"
+
+static struct v4l2_mbus_framefmt *
+__ipipeif_get_format(struct iss_ipipeif_device *ipipeif, struct v4l2_subdev_fh *fh,
+                 unsigned int pad, enum v4l2_subdev_format_whence which);
+
+static const unsigned int ipipeif_fmts[] = {
+       V4L2_MBUS_FMT_SGRBG10_1X10,
+       V4L2_MBUS_FMT_SRGGB10_1X10,
+       V4L2_MBUS_FMT_SBGGR10_1X10,
+       V4L2_MBUS_FMT_SGBRG10_1X10,
+       V4L2_MBUS_FMT_UYVY8_1X16,
+       V4L2_MBUS_FMT_YUYV8_1X16,
+};
+
+/*
+ * ipipeif_print_status - Print current IPIPEIF Module register values.
+ * @ipipeif: Pointer to ISS ISP IPIPEIF device.
+ *
+ * Also prints other debug information stored in the IPIPEIF module.
+ */
+#define IPIPEIF_PRINT_REGISTER(iss, name)\
+       dev_dbg(iss->dev, "###IPIPEIF " #name "=0x%08x\n", \
+               readl(iss->regs[OMAP4_ISS_MEM_ISP_IPIPEIF] + IPIPEIF_##name))
+
+#define ISIF_PRINT_REGISTER(iss, name)\
+       dev_dbg(iss->dev, "###ISIF " #name "=0x%08x\n", \
+               readl(iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_##name))
+
+#define ISP5_PRINT_REGISTER(iss, name)\
+       dev_dbg(iss->dev, "###ISP5 " #name "=0x%08x\n", \
+               readl(iss->regs[OMAP4_ISS_MEM_ISP_SYS1] + ISP5_##name))
+
+static void ipipeif_print_status(struct iss_ipipeif_device *ipipeif)
+{
+       struct iss_device *iss = to_iss_device(ipipeif);
+
+       dev_dbg(iss->dev, "-------------IPIPEIF Register dump-------------\n");
+
+       IPIPEIF_PRINT_REGISTER(iss, CFG1);
+       IPIPEIF_PRINT_REGISTER(iss, CFG2);
+
+       ISIF_PRINT_REGISTER(iss, SYNCEN);
+       ISIF_PRINT_REGISTER(iss, CADU);
+       ISIF_PRINT_REGISTER(iss, CADL);
+       ISIF_PRINT_REGISTER(iss, MODESET);
+       ISIF_PRINT_REGISTER(iss, CCOLP);
+       ISIF_PRINT_REGISTER(iss, SPH);
+       ISIF_PRINT_REGISTER(iss, LNH);
+       ISIF_PRINT_REGISTER(iss, LNV);
+       ISIF_PRINT_REGISTER(iss, VDINT0);
+       ISIF_PRINT_REGISTER(iss, HSIZE);
+
+       ISP5_PRINT_REGISTER(iss, SYSCONFIG);
+       ISP5_PRINT_REGISTER(iss, CTRL);
+       ISP5_PRINT_REGISTER(iss, IRQSTATUS(0));
+       ISP5_PRINT_REGISTER(iss, IRQENABLE_SET(0));
+       ISP5_PRINT_REGISTER(iss, IRQENABLE_CLR(0));
+
+       dev_dbg(iss->dev, "-----------------------------------------------\n");
+}
+
+static void ipipeif_write_enable(struct iss_ipipeif_device *ipipeif, u8 enable)
+{
+       struct iss_device *iss = to_iss_device(ipipeif);
+
+       writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_SYNCEN) &
+               ~ISIF_SYNCEN_DWEN) |
+               enable ? ISIF_SYNCEN_DWEN : 0,
+               iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_SYNCEN);
+}
+
+/*
+ * ipipeif_enable - Enable/Disable IPIPEIF.
+ * @enable: enable flag
+ *
+ */
+static void ipipeif_enable(struct iss_ipipeif_device *ipipeif, u8 enable)
+{
+       struct iss_device *iss = to_iss_device(ipipeif);
+
+       writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_SYNCEN) &
+               ~ISIF_SYNCEN_SYEN) |
+               enable ? ISIF_SYNCEN_SYEN : 0,
+               iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_SYNCEN);
+}
+
+/* -----------------------------------------------------------------------------
+ * Format- and pipeline-related configuration helpers
+ */
+
+/*
+ * ipipeif_set_outaddr - Set memory address to save output image
+ * @ipipeif: Pointer to ISP IPIPEIF device.
+ * @addr: 32-bit memory address aligned on 32 byte boundary.
+ *
+ * Sets the memory address where the output will be saved.
+ */
+static void ipipeif_set_outaddr(struct iss_ipipeif_device *ipipeif, u32 addr)
+{
+       struct iss_device *iss = to_iss_device(ipipeif);
+
+       /* Save address splitted in Base Address H & L */
+       writel((addr >> (16 + 5)) & ISIF_CADU_MASK,
+               iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_CADU);
+       writel((addr >> 5) & ISIF_CADL_MASK,
+               iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_CADL);
+}
+
+static void ipipeif_configure(struct iss_ipipeif_device *ipipeif)
+{
+       struct iss_device *iss = to_iss_device(ipipeif);
+       struct v4l2_mbus_framefmt *format;
+       u32 isif_ccolp = 0;
+
+       omap4iss_configure_bridge(iss, ipipeif->input);
+
+       /* IPIPEIF_PAD_SINK */
+       format = &ipipeif->formats[IPIPEIF_PAD_SINK];
+
+       /* IPIPEIF with YUV422 input from ISIF */
+       writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_IPIPEIF] + IPIPEIF_CFG1) &
+               ~(IPIPEIF_CFG1_INPSRC1_MASK | IPIPEIF_CFG1_INPSRC2_MASK),
+               iss->regs[OMAP4_ISS_MEM_ISP_IPIPEIF] + IPIPEIF_CFG1);
+
+       /* Select ISIF/IPIPEIF input format */
+       switch (format->code) {
+       case V4L2_MBUS_FMT_UYVY8_1X16:
+       case V4L2_MBUS_FMT_YUYV8_1X16:
+               writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_MODESET) &
+                       ~(ISIF_MODESET_CCDMD |
+                         ISIF_MODESET_INPMOD_MASK |
+                         ISIF_MODESET_CCDW_MASK)) |
+                       ISIF_MODESET_INPMOD_YCBCR16,
+                       iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_MODESET);
+
+               writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_IPIPEIF] + IPIPEIF_CFG2) &
+                       ~IPIPEIF_CFG2_YUV8) |
+                       IPIPEIF_CFG2_YUV16,
+                       iss->regs[OMAP4_ISS_MEM_ISP_IPIPEIF] + IPIPEIF_CFG2);
+
+               break;
+       case V4L2_MBUS_FMT_SGRBG10_1X10:
+               isif_ccolp = ISIF_CCOLP_CP0_F0_GR |
+                       ISIF_CCOLP_CP1_F0_R |
+                       ISIF_CCOLP_CP2_F0_B |
+                       ISIF_CCOLP_CP3_F0_GB;
+               goto cont_raw;
+       case V4L2_MBUS_FMT_SRGGB10_1X10:
+               isif_ccolp = ISIF_CCOLP_CP0_F0_R |
+                       ISIF_CCOLP_CP1_F0_GR |
+                       ISIF_CCOLP_CP2_F0_GB |
+                       ISIF_CCOLP_CP3_F0_B;
+               goto cont_raw;
+       case V4L2_MBUS_FMT_SBGGR10_1X10:
+               isif_ccolp = ISIF_CCOLP_CP0_F0_B |
+                       ISIF_CCOLP_CP1_F0_GB |
+                       ISIF_CCOLP_CP2_F0_GR |
+                       ISIF_CCOLP_CP3_F0_R;
+               goto cont_raw;
+       case V4L2_MBUS_FMT_SGBRG10_1X10:
+               isif_ccolp = ISIF_CCOLP_CP0_F0_GB |
+                       ISIF_CCOLP_CP1_F0_B |
+                       ISIF_CCOLP_CP2_F0_R |
+                       ISIF_CCOLP_CP3_F0_GR;
+cont_raw:
+               writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_IPIPEIF] + IPIPEIF_CFG2) &
+                       ~IPIPEIF_CFG2_YUV16),
+                       iss->regs[OMAP4_ISS_MEM_ISP_IPIPEIF] + IPIPEIF_CFG2);
+
+               writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_MODESET) &
+                       ~(ISIF_MODESET_CCDMD |
+                         ISIF_MODESET_INPMOD_MASK |
+                         ISIF_MODESET_CCDW_MASK)) |
+                       ISIF_MODESET_INPMOD_RAW | ISIF_MODESET_CCDW_2BIT,
+                       iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_MODESET);
+
+               writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_CGAMMAWD) &
+                       ~ISIF_CGAMMAWD_GWDI_MASK) |
+                       ISIF_CGAMMAWD_GWDI_BIT11,
+                       iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_CGAMMAWD);
+
+               /* Set RAW Bayer pattern */
+               writel(isif_ccolp,
+                       iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_CCOLP);
+               break;
+       }
+
+       writel(0 & ISIF_SPH_MASK, iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_SPH);
+       writel((format->width - 1) & ISIF_LNH_MASK,
+               iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_LNH);
+       writel((format->height - 1) & ISIF_LNV_MASK,
+               iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_LNV);
+
+       /* Generate ISIF0 on the last line of the image */
+       writel(format->height - 1,
+               iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_VDINT0);
+
+       /* IPIPEIF_PAD_SOURCE_ISIF_SF */
+       format = &ipipeif->formats[IPIPEIF_PAD_SOURCE_ISIF_SF];
+
+       writel((ipipeif->video_out.bpl_value >> 5) & ISIF_HSIZE_HSIZE_MASK,
+               iss->regs[OMAP4_ISS_MEM_ISP_ISIF] + ISIF_HSIZE);
+
+       /* IPIPEIF_PAD_SOURCE_VP */
+       /* Do nothing? */
+
+       omap4iss_isp_enable_interrupts(iss);
+}
+
+/* -----------------------------------------------------------------------------
+ * Interrupt handling
+ */
+
+static void ipipeif_isr_buffer(struct iss_ipipeif_device *ipipeif)
+{
+       struct iss_buffer *buffer;
+
+       ipipeif_write_enable(ipipeif, 0);
+
+       buffer = omap4iss_video_buffer_next(&ipipeif->video_out);
+       if (buffer == NULL)
+               return;
+
+       ipipeif_set_outaddr(ipipeif, buffer->iss_addr);
+
+       ipipeif_write_enable(ipipeif, 1);
+}
+
+/*
+ * ipipeif_isif0_isr - Handle ISIF0 event
+ * @ipipeif: Pointer to ISP IPIPEIF device.
+ *
+ * Executes LSC deferred enablement before next frame starts.
+ */
+static void ipipeif_isif0_isr(struct iss_ipipeif_device *ipipeif)
+{
+       struct iss_pipeline *pipe =
+                            to_iss_pipeline(&ipipeif->subdev.entity);
+       if (pipe->do_propagation)
+               atomic_inc(&pipe->frame_number);
+
+       if (ipipeif->output & IPIPEIF_OUTPUT_MEMORY)
+               ipipeif_isr_buffer(ipipeif);
+}
+
+/*
+ * omap4iss_ipipeif_isr - Configure ipipeif during interframe time.
+ * @ipipeif: Pointer to ISP IPIPEIF device.
+ * @events: IPIPEIF events
+ */
+void omap4iss_ipipeif_isr(struct iss_ipipeif_device *ipipeif, u32 events)
+{
+       if (omap4iss_module_sync_is_stopping(&ipipeif->wait, &ipipeif->stopping))
+               return;
+
+       if (events & ISP5_IRQ_ISIF0)
+               ipipeif_isif0_isr(ipipeif);
+}
+
+/* -----------------------------------------------------------------------------
+ * ISP video operations
+ */
+
+static int ipipeif_video_queue(struct iss_video *video, struct iss_buffer *buffer)
+{
+       struct iss_ipipeif_device *ipipeif = container_of(video,
+                               struct iss_ipipeif_device, video_out);
+
+       if (!(ipipeif->output & IPIPEIF_OUTPUT_MEMORY))
+               return -ENODEV;
+
+       ipipeif_set_outaddr(ipipeif, buffer->iss_addr);
+
+       /*
+        * If streaming was enabled before there was a buffer queued
+        * or underrun happened in the ISR, the hardware was not enabled
+        * and DMA queue flag ISS_VIDEO_DMAQUEUE_UNDERRUN is still set.
+        * Enable it now.
+        */
+       if (video->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_UNDERRUN) {
+               if (ipipeif->output & IPIPEIF_OUTPUT_MEMORY)
+                       ipipeif_write_enable(ipipeif, 1);
+               ipipeif_enable(ipipeif, 1);
+               iss_video_dmaqueue_flags_clr(video);
+       }
+
+       return 0;
+}
+
+static const struct iss_video_operations ipipeif_video_ops = {
+       .queue = ipipeif_video_queue,
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev operations
+ */
+
+#define IPIPEIF_DRV_SUBCLK_MASK        (OMAP4_ISS_ISP_SUBCLK_IPIPEIF |\
+                                OMAP4_ISS_ISP_SUBCLK_ISIF)
+/*
+ * ipipeif_set_stream - Enable/Disable streaming on the IPIPEIF module
+ * @sd: ISP IPIPEIF V4L2 subdevice
+ * @enable: Enable/disable stream
+ */
+static int ipipeif_set_stream(struct v4l2_subdev *sd, int enable)
+{
+       struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
+       struct iss_device *iss = to_iss_device(ipipeif);
+       struct iss_video *video_out = &ipipeif->video_out;
+       int ret = 0;
+
+       if (ipipeif->state == ISS_PIPELINE_STREAM_STOPPED) {
+               if (enable == ISS_PIPELINE_STREAM_STOPPED)
+                       return 0;
+
+               omap4iss_isp_subclk_enable(iss, IPIPEIF_DRV_SUBCLK_MASK);
+       }
+
+       switch (enable) {
+       case ISS_PIPELINE_STREAM_CONTINUOUS:
+
+               ipipeif_configure(ipipeif);
+               ipipeif_print_status(ipipeif);
+
+               /*
+                * When outputting to memory with no buffer available, let the
+                * buffer queue handler start the hardware. A DMA queue flag
+                * ISS_VIDEO_DMAQUEUE_QUEUED will be set as soon as there is
+                * a buffer available.
+                */
+               if (ipipeif->output & IPIPEIF_OUTPUT_MEMORY &&
+                   !(video_out->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_QUEUED))
+                       break;
+
+               atomic_set(&ipipeif->stopping, 0);
+               if (ipipeif->output & IPIPEIF_OUTPUT_MEMORY)
+                       ipipeif_write_enable(ipipeif, 1);
+               ipipeif_enable(ipipeif, 1);
+               iss_video_dmaqueue_flags_clr(video_out);
+               break;
+
+       case ISS_PIPELINE_STREAM_STOPPED:
+               if (ipipeif->state == ISS_PIPELINE_STREAM_STOPPED)
+                       return 0;
+               if (omap4iss_module_sync_idle(&sd->entity, &ipipeif->wait,
+                                             &ipipeif->stopping))
+                       dev_dbg(iss->dev, "%s: module stop timeout.\n",
+                               sd->name);
+
+               if (ipipeif->output & IPIPEIF_OUTPUT_MEMORY)
+                       ipipeif_write_enable(ipipeif, 0);
+               ipipeif_enable(ipipeif, 0);
+               omap4iss_isp_disable_interrupts(iss);
+               omap4iss_isp_subclk_disable(iss, IPIPEIF_DRV_SUBCLK_MASK);
+               iss_video_dmaqueue_flags_clr(video_out);
+               break;
+       }
+
+       ipipeif->state = enable;
+       return ret;
+}
+
+static struct v4l2_mbus_framefmt *
+__ipipeif_get_format(struct iss_ipipeif_device *ipipeif, struct v4l2_subdev_fh *fh,
+                 unsigned int pad, enum v4l2_subdev_format_whence which)
+{
+       if (which == V4L2_SUBDEV_FORMAT_TRY)
+               return v4l2_subdev_get_try_format(fh, pad);
+       else
+               return &ipipeif->formats[pad];
+}
+
+/*
+ * ipipeif_try_format - Try video format on a pad
+ * @ipipeif: ISS IPIPEIF device
+ * @fh : V4L2 subdev file handle
+ * @pad: Pad number
+ * @fmt: Format
+ */
+static void
+ipipeif_try_format(struct iss_ipipeif_device *ipipeif, struct v4l2_subdev_fh *fh,
+               unsigned int pad, struct v4l2_mbus_framefmt *fmt,
+               enum v4l2_subdev_format_whence which)
+{
+       struct v4l2_mbus_framefmt *format;
+       unsigned int width = fmt->width;
+       unsigned int height = fmt->height;
+       unsigned int i;
+
+       switch (pad) {
+       case IPIPEIF_PAD_SINK:
+               /* TODO: If the IPIPEIF output formatter pad is connected directly
+                * to the resizer, only YUV formats can be used.
+                */
+               for (i = 0; i < ARRAY_SIZE(ipipeif_fmts); i++) {
+                       if (fmt->code == ipipeif_fmts[i])
+                               break;
+               }
+
+               /* If not found, use SGRBG10 as default */
+               if (i >= ARRAY_SIZE(ipipeif_fmts))
+                       fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
+
+               /* Clamp the input size. */
+               fmt->width = clamp_t(u32, width, 1, 8192);
+               fmt->height = clamp_t(u32, height, 1, 8192);
+               break;
+
+       case IPIPEIF_PAD_SOURCE_ISIF_SF:
+               format = __ipipeif_get_format(ipipeif, fh, IPIPEIF_PAD_SINK, which);
+               memcpy(fmt, format, sizeof(*fmt));
+
+               /* The data formatter truncates the number of horizontal output
+                * pixels to a multiple of 16. To avoid clipping data, allow
+                * callers to request an output size bigger than the input size
+                * up to the nearest multiple of 16.
+                */
+               fmt->width = clamp_t(u32, width, 32, (fmt->width + 15) & ~15);
+               fmt->width &= ~15;
+               fmt->height = clamp_t(u32, height, 32, fmt->height);
+               break;
+
+       case IPIPEIF_PAD_SOURCE_VP:
+               format = __ipipeif_get_format(ipipeif, fh, IPIPEIF_PAD_SINK, which);
+               memcpy(fmt, format, sizeof(*fmt));
+
+               fmt->width = clamp_t(u32, width, 32, fmt->width);
+               fmt->height = clamp_t(u32, height, 32, fmt->height);
+               break;
+       }
+
+       /* Data is written to memory unpacked, each 10-bit or 12-bit pixel is
+        * stored on 2 bytes.
+        */
+       fmt->colorspace = V4L2_COLORSPACE_SRGB;
+       fmt->field = V4L2_FIELD_NONE;
+}
+
+/*
+ * ipipeif_enum_mbus_code - Handle pixel format enumeration
+ * @sd     : pointer to v4l2 subdev structure
+ * @fh : V4L2 subdev file handle
+ * @code   : pointer to v4l2_subdev_mbus_code_enum structure
+ * return -EINVAL or zero on success
+ */
+static int ipipeif_enum_mbus_code(struct v4l2_subdev *sd,
+                              struct v4l2_subdev_fh *fh,
+                              struct v4l2_subdev_mbus_code_enum *code)
+{
+       struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
+       struct v4l2_mbus_framefmt *format;
+
+       switch (code->pad) {
+       case IPIPEIF_PAD_SINK:
+               if (code->index >= ARRAY_SIZE(ipipeif_fmts))
+                       return -EINVAL;
+
+               code->code = ipipeif_fmts[code->index];
+               break;
+
+       case IPIPEIF_PAD_SOURCE_ISIF_SF:
+       case IPIPEIF_PAD_SOURCE_VP:
+               /* No format conversion inside IPIPEIF */
+               if (code->index != 0)
+                       return -EINVAL;
+
+               format = __ipipeif_get_format(ipipeif, fh, IPIPEIF_PAD_SINK,
+                                             V4L2_SUBDEV_FORMAT_TRY);
+
+               code->code = format->code;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int ipipeif_enum_frame_size(struct v4l2_subdev *sd,
+                               struct v4l2_subdev_fh *fh,
+                               struct v4l2_subdev_frame_size_enum *fse)
+{
+       struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
+       struct v4l2_mbus_framefmt format;
+
+       if (fse->index != 0)
+               return -EINVAL;
+
+       format.code = fse->code;
+       format.width = 1;
+       format.height = 1;
+       ipipeif_try_format(ipipeif, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
+       fse->min_width = format.width;
+       fse->min_height = format.height;
+
+       if (format.code != fse->code)
+               return -EINVAL;
+
+       format.code = fse->code;
+       format.width = -1;
+       format.height = -1;
+       ipipeif_try_format(ipipeif, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
+       fse->max_width = format.width;
+       fse->max_height = format.height;
+
+       return 0;
+}
+
+/*
+ * ipipeif_get_format - Retrieve the video format on a pad
+ * @sd : ISP IPIPEIF V4L2 subdevice
+ * @fh : V4L2 subdev file handle
+ * @fmt: Format
+ *
+ * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
+ * to the format type.
+ */
+static int ipipeif_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                          struct v4l2_subdev_format *fmt)
+{
+       struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
+       struct v4l2_mbus_framefmt *format;
+
+       format = __ipipeif_get_format(ipipeif, fh, fmt->pad, fmt->which);
+       if (format == NULL)
+               return -EINVAL;
+
+       fmt->format = *format;
+       return 0;
+}
+
+/*
+ * ipipeif_set_format - Set the video format on a pad
+ * @sd : ISP IPIPEIF V4L2 subdevice
+ * @fh : V4L2 subdev file handle
+ * @fmt: Format
+ *
+ * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
+ * to the format type.
+ */
+static int ipipeif_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                          struct v4l2_subdev_format *fmt)
+{
+       struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
+       struct v4l2_mbus_framefmt *format;
+
+       format = __ipipeif_get_format(ipipeif, fh, fmt->pad, fmt->which);
+       if (format == NULL)
+               return -EINVAL;
+
+       ipipeif_try_format(ipipeif, fh, fmt->pad, &fmt->format, fmt->which);
+       *format = fmt->format;
+
+       /* Propagate the format from sink to source */
+       if (fmt->pad == IPIPEIF_PAD_SINK) {
+               format = __ipipeif_get_format(ipipeif, fh, IPIPEIF_PAD_SOURCE_ISIF_SF,
+                                          fmt->which);
+               *format = fmt->format;
+               ipipeif_try_format(ipipeif, fh, IPIPEIF_PAD_SOURCE_ISIF_SF, format,
+                               fmt->which);
+
+               format = __ipipeif_get_format(ipipeif, fh, IPIPEIF_PAD_SOURCE_VP,
+                                          fmt->which);
+               *format = fmt->format;
+               ipipeif_try_format(ipipeif, fh, IPIPEIF_PAD_SOURCE_VP, format,
+                               fmt->which);
+       }
+
+       return 0;
+}
+
+static int ipipeif_link_validate(struct v4l2_subdev *sd, struct media_link *link,
+                                struct v4l2_subdev_format *source_fmt,
+                                struct v4l2_subdev_format *sink_fmt)
+{
+       /* Check if the two ends match */
+       if (source_fmt->format.width != sink_fmt->format.width ||
+           source_fmt->format.height != sink_fmt->format.height)
+               return -EPIPE;
+
+       if (source_fmt->format.code != sink_fmt->format.code)
+               return -EPIPE;
+
+       return 0;
+}
+
+/*
+ * ipipeif_init_formats - Initialize formats on all pads
+ * @sd: ISP IPIPEIF V4L2 subdevice
+ * @fh: V4L2 subdev file handle
+ *
+ * Initialize all pad formats with default values. If fh is not NULL, try
+ * formats are initialized on the file handle. Otherwise active formats are
+ * initialized on the device.
+ */
+static int ipipeif_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+       struct v4l2_subdev_format format;
+
+       memset(&format, 0, sizeof(format));
+       format.pad = IPIPEIF_PAD_SINK;
+       format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+       format.format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
+       format.format.width = 4096;
+       format.format.height = 4096;
+       ipipeif_set_format(sd, fh, &format);
+
+       return 0;
+}
+
+/* V4L2 subdev video operations */
+static const struct v4l2_subdev_video_ops ipipeif_v4l2_video_ops = {
+       .s_stream = ipipeif_set_stream,
+};
+
+/* V4L2 subdev pad operations */
+static const struct v4l2_subdev_pad_ops ipipeif_v4l2_pad_ops = {
+       .enum_mbus_code = ipipeif_enum_mbus_code,
+       .enum_frame_size = ipipeif_enum_frame_size,
+       .get_fmt = ipipeif_get_format,
+       .set_fmt = ipipeif_set_format,
+       .link_validate = ipipeif_link_validate,
+};
+
+/* V4L2 subdev operations */
+static const struct v4l2_subdev_ops ipipeif_v4l2_ops = {
+       .video = &ipipeif_v4l2_video_ops,
+       .pad = &ipipeif_v4l2_pad_ops,
+};
+
+/* V4L2 subdev internal operations */
+static const struct v4l2_subdev_internal_ops ipipeif_v4l2_internal_ops = {
+       .open = ipipeif_init_formats,
+};
+
+/* -----------------------------------------------------------------------------
+ * Media entity operations
+ */
+
+/*
+ * ipipeif_link_setup - Setup IPIPEIF connections
+ * @entity: IPIPEIF media entity
+ * @local: Pad at the local end of the link
+ * @remote: Pad at the remote end of the link
+ * @flags: Link flags
+ *
+ * return -EINVAL or zero on success
+ */
+static int ipipeif_link_setup(struct media_entity *entity,
+                          const struct media_pad *local,
+                          const struct media_pad *remote, u32 flags)
+{
+       struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
+       struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
+       struct iss_device *iss = to_iss_device(ipipeif);
+
+       switch (local->index | media_entity_type(remote->entity)) {
+       case IPIPEIF_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV:
+               /* Read from the sensor CSI2a or CSI2b. */
+               if (!(flags & MEDIA_LNK_FL_ENABLED)) {
+                       ipipeif->input = IPIPEIF_INPUT_NONE;
+                       break;
+               }
+
+               if (ipipeif->input != IPIPEIF_INPUT_NONE)
+                       return -EBUSY;
+
+               if (remote->entity == &iss->csi2a.subdev.entity)
+                       ipipeif->input = IPIPEIF_INPUT_CSI2A;
+               else if (remote->entity == &iss->csi2b.subdev.entity)
+                       ipipeif->input = IPIPEIF_INPUT_CSI2B;
+
+               break;
+
+       case IPIPEIF_PAD_SOURCE_ISIF_SF | MEDIA_ENT_T_DEVNODE:
+               /* Write to memory */
+               if (flags & MEDIA_LNK_FL_ENABLED) {
+                       if (ipipeif->output & ~IPIPEIF_OUTPUT_MEMORY)
+                               return -EBUSY;
+                       ipipeif->output |= IPIPEIF_OUTPUT_MEMORY;
+               } else {
+                       ipipeif->output &= ~IPIPEIF_OUTPUT_MEMORY;
+               }
+               break;
+
+       case IPIPEIF_PAD_SOURCE_VP | MEDIA_ENT_T_V4L2_SUBDEV:
+               /* Send to IPIPE/RESIZER */
+               if (flags & MEDIA_LNK_FL_ENABLED) {
+                       if (ipipeif->output & ~IPIPEIF_OUTPUT_VP)
+                               return -EBUSY;
+                       ipipeif->output |= IPIPEIF_OUTPUT_VP;
+               } else {
+                       ipipeif->output &= ~IPIPEIF_OUTPUT_VP;
+               }
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/* media operations */
+static const struct media_entity_operations ipipeif_media_ops = {
+       .link_setup = ipipeif_link_setup,
+       .link_validate = v4l2_subdev_link_validate,
+};
+
+/*
+ * ipipeif_init_entities - Initialize V4L2 subdev and media entity
+ * @ipipeif: ISS ISP IPIPEIF module
+ *
+ * Return 0 on success and a negative error code on failure.
+ */
+static int ipipeif_init_entities(struct iss_ipipeif_device *ipipeif)
+{
+       struct v4l2_subdev *sd = &ipipeif->subdev;
+       struct media_pad *pads = ipipeif->pads;
+       struct media_entity *me = &sd->entity;
+       int ret;
+
+       ipipeif->input = IPIPEIF_INPUT_NONE;
+
+       v4l2_subdev_init(sd, &ipipeif_v4l2_ops);
+       sd->internal_ops = &ipipeif_v4l2_internal_ops;
+       strlcpy(sd->name, "OMAP4 ISS ISP IPIPEIF", sizeof(sd->name));
+       sd->grp_id = 1 << 16;   /* group ID for iss subdevs */
+       v4l2_set_subdevdata(sd, ipipeif);
+       sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+       pads[IPIPEIF_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+       pads[IPIPEIF_PAD_SOURCE_ISIF_SF].flags = MEDIA_PAD_FL_SOURCE;
+       pads[IPIPEIF_PAD_SOURCE_VP].flags = MEDIA_PAD_FL_SOURCE;
+
+       me->ops = &ipipeif_media_ops;
+       ret = media_entity_init(me, IPIPEIF_PADS_NUM, pads, 0);
+       if (ret < 0)
+               return ret;
+
+       ipipeif_init_formats(sd, NULL);
+
+       ipipeif->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       ipipeif->video_out.ops = &ipipeif_video_ops;
+       ipipeif->video_out.iss = to_iss_device(ipipeif);
+       ipipeif->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 3;
+       ipipeif->video_out.bpl_alignment = 32;
+       ipipeif->video_out.bpl_zero_padding = 1;
+       ipipeif->video_out.bpl_max = 0x1ffe0;
+
+       ret = omap4iss_video_init(&ipipeif->video_out, "ISP IPIPEIF");
+       if (ret < 0)
+               return ret;
+
+       /* Connect the IPIPEIF subdev to the video node. */
+       ret = media_entity_create_link(&ipipeif->subdev.entity, IPIPEIF_PAD_SOURCE_ISIF_SF,
+                       &ipipeif->video_out.video.entity, 0, 0);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+void omap4iss_ipipeif_unregister_entities(struct iss_ipipeif_device *ipipeif)
+{
+       media_entity_cleanup(&ipipeif->subdev.entity);
+
+       v4l2_device_unregister_subdev(&ipipeif->subdev);
+       omap4iss_video_unregister(&ipipeif->video_out);
+}
+
+int omap4iss_ipipeif_register_entities(struct iss_ipipeif_device *ipipeif,
+       struct v4l2_device *vdev)
+{
+       int ret;
+
+       /* Register the subdev and video node. */
+       ret = v4l2_device_register_subdev(vdev, &ipipeif->subdev);
+       if (ret < 0)
+               goto error;
+
+       ret = omap4iss_video_register(&ipipeif->video_out, vdev);
+       if (ret < 0)
+               goto error;
+
+       return 0;
+
+error:
+       omap4iss_ipipeif_unregister_entities(ipipeif);
+       return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * ISP IPIPEIF initialisation and cleanup
+ */
+
+/*
+ * omap4iss_ipipeif_init - IPIPEIF module initialization.
+ * @iss: Device pointer specific to the OMAP4 ISS.
+ *
+ * TODO: Get the initialisation values from platform data.
+ *
+ * Return 0 on success or a negative error code otherwise.
+ */
+int omap4iss_ipipeif_init(struct iss_device *iss)
+{
+       struct iss_ipipeif_device *ipipeif = &iss->ipipeif;
+
+       ipipeif->state = ISS_PIPELINE_STREAM_STOPPED;
+       init_waitqueue_head(&ipipeif->wait);
+
+       return ipipeif_init_entities(ipipeif);
+}
+
+/*
+ * omap4iss_ipipeif_cleanup - IPIPEIF module cleanup.
+ * @iss: Device pointer specific to the OMAP4 ISS.
+ */
+void omap4iss_ipipeif_cleanup(struct iss_device *iss)
+{
+       /* FIXME: are you sure there's nothing to do? */
+}
diff --git a/drivers/staging/media/omap4iss/iss_ipipeif.h b/drivers/staging/media/omap4iss/iss_ipipeif.h
new file mode 100644 (file)
index 0000000..cbdccb9
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * TI OMAP4 ISS V4L2 Driver - ISP IPIPEIF module
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef OMAP4_ISS_IPIPEIF_H
+#define OMAP4_ISS_IPIPEIF_H
+
+#include "iss_video.h"
+
+enum ipipeif_input_entity {
+       IPIPEIF_INPUT_NONE,
+       IPIPEIF_INPUT_CSI2A,
+       IPIPEIF_INPUT_CSI2B
+};
+
+#define IPIPEIF_OUTPUT_MEMORY          (1 << 0)
+#define IPIPEIF_OUTPUT_VP              (1 << 1)
+
+/* Sink and source IPIPEIF pads */
+#define IPIPEIF_PAD_SINK                       0
+#define IPIPEIF_PAD_SOURCE_ISIF_SF             1
+#define IPIPEIF_PAD_SOURCE_VP                  2
+#define IPIPEIF_PADS_NUM                       3
+
+/*
+ * struct iss_ipipeif_device - Structure for the IPIPEIF module to store its own
+ *                         information
+ * @subdev: V4L2 subdevice
+ * @pads: Sink and source media entity pads
+ * @formats: Active video formats
+ * @input: Active input
+ * @output: Active outputs
+ * @video_out: Output video node
+ * @error: A hardware error occurred during capture
+ * @alaw: A-law compression enabled (1) or disabled (0)
+ * @lpf: Low pass filter enabled (1) or disabled (0)
+ * @obclamp: Optical-black clamp enabled (1) or disabled (0)
+ * @fpc_en: Faulty pixels correction enabled (1) or disabled (0)
+ * @blcomp: Black level compensation configuration
+ * @clamp: Optical-black or digital clamp configuration
+ * @fpc: Faulty pixels correction configuration
+ * @lsc: Lens shading compensation configuration
+ * @update: Bitmask of controls to update during the next interrupt
+ * @shadow_update: Controls update in progress by userspace
+ * @syncif: Interface synchronization configuration
+ * @vpcfg: Video port configuration
+ * @underrun: A buffer underrun occurred and a new buffer has been queued
+ * @state: Streaming state
+ * @lock: Serializes shadow_update with interrupt handler
+ * @wait: Wait queue used to stop the module
+ * @stopping: Stopping state
+ * @ioctl_lock: Serializes ioctl calls and LSC requests freeing
+ */
+struct iss_ipipeif_device {
+       struct v4l2_subdev subdev;
+       struct media_pad pads[IPIPEIF_PADS_NUM];
+       struct v4l2_mbus_framefmt formats[IPIPEIF_PADS_NUM];
+
+       enum ipipeif_input_entity input;
+       unsigned int output;
+       struct iss_video video_out;
+       unsigned int error;
+
+       enum iss_pipeline_stream_state state;
+       wait_queue_head_t wait;
+       atomic_t stopping;
+};
+
+struct iss_device;
+
+int omap4iss_ipipeif_init(struct iss_device *iss);
+void omap4iss_ipipeif_cleanup(struct iss_device *iss);
+int omap4iss_ipipeif_register_entities(struct iss_ipipeif_device *ipipeif,
+       struct v4l2_device *vdev);
+void omap4iss_ipipeif_unregister_entities(struct iss_ipipeif_device *ipipeif);
+
+int omap4iss_ipipeif_busy(struct iss_ipipeif_device *ipipeif);
+void omap4iss_ipipeif_isr(struct iss_ipipeif_device *ipipeif, u32 events);
+void omap4iss_ipipeif_restore_context(struct iss_device *iss);
+void omap4iss_ipipeif_max_rate(struct iss_ipipeif_device *ipipeif,
+       unsigned int *max_rate);
+
+#endif /* OMAP4_ISS_IPIPEIF_H */
diff --git a/drivers/staging/media/omap4iss/iss_regs.h b/drivers/staging/media/omap4iss/iss_regs.h
new file mode 100644 (file)
index 0000000..7327d0c
--- /dev/null
@@ -0,0 +1,883 @@
+/*
+ * TI OMAP4 ISS V4L2 Driver - Register defines
+ *
+ * Copyright (C) 2012 Texas Instruments.
+ *
+ * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef _OMAP4_ISS_REGS_H_
+#define _OMAP4_ISS_REGS_H_
+
+/* ISS */
+#define ISS_HL_REVISION                                        0x0
+
+#define ISS_HL_SYSCONFIG                               0x10
+#define ISS_HL_SYSCONFIG_IDLEMODE_SHIFT                        2
+#define ISS_HL_SYSCONFIG_IDLEMODE_FORCEIDLE            0x0
+#define ISS_HL_SYSCONFIG_IDLEMODE_NOIDLE               0x1
+#define ISS_HL_SYSCONFIG_IDLEMODE_SMARTIDLE            0x2
+#define ISS_HL_SYSCONFIG_SOFTRESET                     (1 << 0)
+
+#define ISS_HL_IRQSTATUS_5                             (0x24 + (0x10 * 5))
+#define ISS_HL_IRQENABLE_5_SET                         (0x28 + (0x10 * 5))
+#define ISS_HL_IRQENABLE_5_CLR                         (0x2C + (0x10 * 5))
+
+#define ISS_HL_IRQ_BTE                                 (1 << 11)
+#define ISS_HL_IRQ_CBUFF                               (1 << 10)
+#define ISS_HL_IRQ_CSIB                                        (1 << 5)
+#define ISS_HL_IRQ_CSIA                                        (1 << 4)
+#define ISS_HL_IRQ_ISP(i)                              (1 << (i))
+
+#define ISS_CTRL                                       0x80
+#define ISS_CTRL_CLK_DIV_MASK                          (3 << 4)
+#define ISS_CTRL_INPUT_SEL_MASK                                (3 << 2)
+#define ISS_CTRL_INPUT_SEL_CSI2A                       (0 << 2)
+#define ISS_CTRL_INPUT_SEL_CSI2B                       (1 << 2)
+#define ISS_CTRL_SYNC_DETECT_VS_RAISING                        (3 << 0)
+
+#define ISS_CLKCTRL                                    0x84
+#define ISS_CLKCTRL_VPORT2_CLK                         (1 << 30)
+#define ISS_CLKCTRL_VPORT1_CLK                         (1 << 29)
+#define ISS_CLKCTRL_VPORT0_CLK                         (1 << 28)
+#define ISS_CLKCTRL_CCP2                               (1 << 4)
+#define ISS_CLKCTRL_CSI2_B                             (1 << 3)
+#define ISS_CLKCTRL_CSI2_A                             (1 << 2)
+#define ISS_CLKCTRL_ISP                                        (1 << 1)
+#define ISS_CLKCTRL_SIMCOP                             (1 << 0)
+
+#define ISS_CLKSTAT                                    0x88
+#define ISS_CLKSTAT_VPORT2_CLK                         (1 << 30)
+#define ISS_CLKSTAT_VPORT1_CLK                         (1 << 29)
+#define ISS_CLKSTAT_VPORT0_CLK                         (1 << 28)
+#define ISS_CLKSTAT_CCP2                               (1 << 4)
+#define ISS_CLKSTAT_CSI2_B                             (1 << 3)
+#define ISS_CLKSTAT_CSI2_A                             (1 << 2)
+#define ISS_CLKSTAT_ISP                                        (1 << 1)
+#define ISS_CLKSTAT_SIMCOP                             (1 << 0)
+
+#define ISS_PM_STATUS                                  0x8C
+#define ISS_PM_STATUS_CBUFF_PM_MASK                    (3 << 12)
+#define ISS_PM_STATUS_BTE_PM_MASK                      (3 << 10)
+#define ISS_PM_STATUS_SIMCOP_PM_MASK                   (3 << 8)
+#define ISS_PM_STATUS_ISP_PM_MASK                      (3 << 6)
+#define ISS_PM_STATUS_CCP2_PM_MASK                     (3 << 4)
+#define ISS_PM_STATUS_CSI2_B_PM_MASK                   (3 << 2)
+#define ISS_PM_STATUS_CSI2_A_PM_MASK                   (3 << 0)
+
+#define REGISTER0                                      0x0
+#define REGISTER0_HSCLOCKCONFIG                                (1 << 24)
+#define REGISTER0_THS_TERM_MASK                                (0xFF << 8)
+#define REGISTER0_THS_TERM_SHIFT                       8
+#define REGISTER0_THS_SETTLE_MASK                      (0xFF << 0)
+#define REGISTER0_THS_SETTLE_SHIFT                     0
+
+#define REGISTER1                                      0x4
+#define REGISTER1_RESET_DONE_CTRLCLK                   (1 << 29)
+#define REGISTER1_CLOCK_MISS_DETECTOR_STATUS           (1 << 25)
+#define REGISTER1_TCLK_TERM_MASK                       (0x3F << 18)
+#define REGISTER1_TCLK_TERM_SHIFT                      18
+#define REGISTER1_DPHY_HS_SYNC_PATTERN_SHIFT           10
+#define REGISTER1_CTRLCLK_DIV_FACTOR_MASK              (0x3 << 8)
+#define REGISTER1_CTRLCLK_DIV_FACTOR_SHIFT             8
+#define REGISTER1_TCLK_SETTLE_MASK                     (0xFF << 0)
+#define REGISTER1_TCLK_SETTLE_SHIFT                    0
+
+#define REGISTER2                                      0x8
+
+#define CSI2_SYSCONFIG                                 0x10
+#define CSI2_SYSCONFIG_MSTANDBY_MODE_MASK              (3 << 12)
+#define CSI2_SYSCONFIG_MSTANDBY_MODE_FORCE             (0 << 12)
+#define CSI2_SYSCONFIG_MSTANDBY_MODE_NO                        (1 << 12)
+#define CSI2_SYSCONFIG_MSTANDBY_MODE_SMART             (2 << 12)
+#define CSI2_SYSCONFIG_SOFT_RESET                      (1 << 1)
+#define CSI2_SYSCONFIG_AUTO_IDLE                       (1 << 0)
+
+#define CSI2_SYSSTATUS                                 0x14
+#define CSI2_SYSSTATUS_RESET_DONE                      (1 << 0)
+
+#define CSI2_IRQSTATUS                                 0x18
+#define CSI2_IRQENABLE                                 0x1C
+
+/* Shared bits across CSI2_IRQENABLE and IRQSTATUS */
+
+#define CSI2_IRQ_OCP_ERR                               (1 << 14)
+#define CSI2_IRQ_SHORT_PACKET                          (1 << 13)
+#define CSI2_IRQ_ECC_CORRECTION                                (1 << 12)
+#define CSI2_IRQ_ECC_NO_CORRECTION                     (1 << 11)
+#define CSI2_IRQ_COMPLEXIO_ERR                         (1 << 9)
+#define CSI2_IRQ_FIFO_OVF                              (1 << 8)
+#define CSI2_IRQ_CONTEXT0                              (1 << 0)
+
+#define CSI2_CTRL                                      0x40
+#define CSI2_CTRL_MFLAG_LEVH_MASK                      (7 << 20)
+#define CSI2_CTRL_MFLAG_LEVH_SHIFT                     20
+#define CSI2_CTRL_MFLAG_LEVL_MASK                      (7 << 17)
+#define CSI2_CTRL_MFLAG_LEVL_SHIFT                     17
+#define CSI2_CTRL_BURST_SIZE_EXPAND                    (1 << 16)
+#define CSI2_CTRL_VP_CLK_EN                            (1 << 15)
+#define CSI2_CTRL_NON_POSTED_WRITE                     (1 << 13)
+#define CSI2_CTRL_VP_ONLY_EN                           (1 << 11)
+#define CSI2_CTRL_VP_OUT_CTRL_MASK                     (3 << 8)
+#define CSI2_CTRL_VP_OUT_CTRL_SHIFT                    8
+#define CSI2_CTRL_DBG_EN                               (1 << 7)
+#define CSI2_CTRL_BURST_SIZE_MASK                      (3 << 5)
+#define CSI2_CTRL_ENDIANNESS                           (1 << 4)
+#define CSI2_CTRL_FRAME                                        (1 << 3)
+#define CSI2_CTRL_ECC_EN                               (1 << 2)
+#define CSI2_CTRL_IF_EN                                        (1 << 0)
+
+#define CSI2_DBG_H                                     0x44
+
+#define CSI2_COMPLEXIO_CFG                             0x50
+#define CSI2_COMPLEXIO_CFG_RESET_CTRL                  (1 << 30)
+#define CSI2_COMPLEXIO_CFG_RESET_DONE                  (1 << 29)
+#define CSI2_COMPLEXIO_CFG_PWD_CMD_MASK                        (3 << 27)
+#define CSI2_COMPLEXIO_CFG_PWD_CMD_OFF                 (0 << 27)
+#define CSI2_COMPLEXIO_CFG_PWD_CMD_ON                  (1 << 27)
+#define CSI2_COMPLEXIO_CFG_PWD_CMD_ULP                 (2 << 27)
+#define CSI2_COMPLEXIO_CFG_PWD_STATUS_MASK             (3 << 25)
+#define CSI2_COMPLEXIO_CFG_PWD_STATUS_OFF              (0 << 25)
+#define CSI2_COMPLEXIO_CFG_PWD_STATUS_ON               (1 << 25)
+#define CSI2_COMPLEXIO_CFG_PWD_STATUS_ULP              (2 << 25)
+#define CSI2_COMPLEXIO_CFG_PWR_AUTO                    (1 << 24)
+#define CSI2_COMPLEXIO_CFG_DATA_POL(i)                 (1 << (((i) * 4) + 3))
+#define CSI2_COMPLEXIO_CFG_DATA_POSITION_MASK(i)       (7 << ((i) * 4))
+#define CSI2_COMPLEXIO_CFG_DATA_POSITION_SHIFT(i)      ((i) * 4)
+#define CSI2_COMPLEXIO_CFG_CLOCK_POL                   (1 << 3)
+#define CSI2_COMPLEXIO_CFG_CLOCK_POSITION_MASK         (7 << 0)
+#define CSI2_COMPLEXIO_CFG_CLOCK_POSITION_SHIFT                0
+
+#define CSI2_COMPLEXIO_IRQSTATUS                       0x54
+
+#define CSI2_SHORT_PACKET                              0x5C
+
+#define CSI2_COMPLEXIO_IRQENABLE                       0x60
+
+/* Shared bits across CSI2_COMPLEXIO_IRQENABLE and IRQSTATUS */
+#define CSI2_COMPLEXIO_IRQ_STATEALLULPMEXIT            (1 << 26)
+#define CSI2_COMPLEXIO_IRQ_STATEALLULPMENTER           (1 << 25)
+#define CSI2_COMPLEXIO_IRQ_STATEULPM5                  (1 << 24)
+#define CSI2_COMPLEXIO_IRQ_STATEULPM4                  (1 << 23)
+#define CSI2_COMPLEXIO_IRQ_STATEULPM3                  (1 << 22)
+#define CSI2_COMPLEXIO_IRQ_STATEULPM2                  (1 << 21)
+#define CSI2_COMPLEXIO_IRQ_STATEULPM1                  (1 << 20)
+#define CSI2_COMPLEXIO_IRQ_ERRCONTROL5                 (1 << 19)
+#define CSI2_COMPLEXIO_IRQ_ERRCONTROL4                 (1 << 18)
+#define CSI2_COMPLEXIO_IRQ_ERRCONTROL3                 (1 << 17)
+#define CSI2_COMPLEXIO_IRQ_ERRCONTROL2                 (1 << 16)
+#define CSI2_COMPLEXIO_IRQ_ERRCONTROL1                 (1 << 15)
+#define CSI2_COMPLEXIO_IRQ_ERRESC5                     (1 << 14)
+#define CSI2_COMPLEXIO_IRQ_ERRESC4                     (1 << 13)
+#define CSI2_COMPLEXIO_IRQ_ERRESC3                     (1 << 12)
+#define CSI2_COMPLEXIO_IRQ_ERRESC2                     (1 << 11)
+#define CSI2_COMPLEXIO_IRQ_ERRESC1                     (1 << 10)
+#define CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS5               (1 << 9)
+#define CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS4               (1 << 8)
+#define CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS3               (1 << 7)
+#define CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS2               (1 << 6)
+#define CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS1               (1 << 5)
+#define CSI2_COMPLEXIO_IRQ_ERRSOTHS5                   (1 << 4)
+#define CSI2_COMPLEXIO_IRQ_ERRSOTHS4                   (1 << 3)
+#define CSI2_COMPLEXIO_IRQ_ERRSOTHS3                   (1 << 2)
+#define CSI2_COMPLEXIO_IRQ_ERRSOTHS2                   (1 << 1)
+#define CSI2_COMPLEXIO_IRQ_ERRSOTHS1                   (1 << 0)
+
+#define CSI2_DBG_P                                     0x68
+
+#define CSI2_TIMING                                    0x6C
+#define CSI2_TIMING_FORCE_RX_MODE_IO1                  (1 << 15)
+#define CSI2_TIMING_STOP_STATE_X16_IO1                 (1 << 14)
+#define CSI2_TIMING_STOP_STATE_X4_IO1                  (1 << 13)
+#define CSI2_TIMING_STOP_STATE_COUNTER_IO1_MASK                (0x1FFF << 0)
+#define CSI2_TIMING_STOP_STATE_COUNTER_IO1_SHIFT       0
+
+#define CSI2_CTX_CTRL1(i)                              (0x70 + (0x20 * i))
+#define CSI2_CTX_CTRL1_GENERIC                         (1 << 30)
+#define CSI2_CTX_CTRL1_TRANSCODE                       (0xF << 24)
+#define CSI2_CTX_CTRL1_FEC_NUMBER_MASK                 (0xFF << 16)
+#define CSI2_CTX_CTRL1_COUNT_MASK                      (0xFF << 8)
+#define CSI2_CTX_CTRL1_COUNT_SHIFT                     8
+#define CSI2_CTX_CTRL1_EOF_EN                          (1 << 7)
+#define CSI2_CTX_CTRL1_EOL_EN                          (1 << 6)
+#define CSI2_CTX_CTRL1_CS_EN                           (1 << 5)
+#define CSI2_CTX_CTRL1_COUNT_UNLOCK                    (1 << 4)
+#define CSI2_CTX_CTRL1_PING_PONG                       (1 << 3)
+#define CSI2_CTX_CTRL1_CTX_EN                          (1 << 0)
+
+#define CSI2_CTX_CTRL2(i)                              (0x74 + (0x20 * i))
+#define CSI2_CTX_CTRL2_USER_DEF_MAP_SHIFT              13
+#define CSI2_CTX_CTRL2_USER_DEF_MAP_MASK               \
+               (0x3 << CSI2_CTX_CTRL2_USER_DEF_MAP_SHIFT)
+#define CSI2_CTX_CTRL2_VIRTUAL_ID_MASK                 (3 << 11)
+#define CSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT                        11
+#define CSI2_CTX_CTRL2_DPCM_PRED                       (1 << 10)
+#define CSI2_CTX_CTRL2_FORMAT_MASK                     (0x3FF << 0)
+#define CSI2_CTX_CTRL2_FORMAT_SHIFT                    0
+
+#define CSI2_CTX_DAT_OFST(i)                           (0x78 + (0x20 * i))
+#define CSI2_CTX_DAT_OFST_MASK                         (0xFFF << 5)
+
+#define CSI2_CTX_PING_ADDR(i)                          (0x7C + (0x20 * i))
+#define CSI2_CTX_PING_ADDR_MASK                                0xFFFFFFE0
+
+#define CSI2_CTX_PONG_ADDR(i)                          (0x80 + (0x20 * i))
+#define CSI2_CTX_PONG_ADDR_MASK                                CSI2_CTX_PING_ADDR_MASK
+
+#define CSI2_CTX_IRQENABLE(i)                          (0x84 + (0x20 * i))
+#define CSI2_CTX_IRQSTATUS(i)                          (0x88 + (0x20 * i))
+
+#define CSI2_CTX_CTRL3(i)                              (0x8C + (0x20 * i))
+#define CSI2_CTX_CTRL3_ALPHA_SHIFT                     5
+#define CSI2_CTX_CTRL3_ALPHA_MASK                      \
+               (0x3fff << CSI2_CTX_CTRL3_ALPHA_SHIFT)
+
+/* Shared bits across CSI2_CTX_IRQENABLE and IRQSTATUS */
+#define CSI2_CTX_IRQ_ECC_CORRECTION                    (1 << 8)
+#define CSI2_CTX_IRQ_LINE_NUMBER                       (1 << 7)
+#define CSI2_CTX_IRQ_FRAME_NUMBER                      (1 << 6)
+#define CSI2_CTX_IRQ_CS                                        (1 << 5)
+#define CSI2_CTX_IRQ_LE                                        (1 << 3)
+#define CSI2_CTX_IRQ_LS                                        (1 << 2)
+#define CSI2_CTX_IRQ_FE                                        (1 << 1)
+#define CSI2_CTX_IRQ_FS                                        (1 << 0)
+
+/* ISS BTE */
+#define BTE_CTRL                                       (0x0030)
+#define BTE_CTRL_BW_LIMITER_MASK                       (0x3FF << 22)
+#define BTE_CTRL_BW_LIMITER_SHIFT                      22
+
+/* ISS ISP_SYS1 */
+#define ISP5_REVISION                                  (0x0000)
+#define ISP5_SYSCONFIG                                 (0x0010)
+#define ISP5_SYSCONFIG_STANDBYMODE_MASK                        (3 << 4)
+#define ISP5_SYSCONFIG_STANDBYMODE_FORCE               (0 << 4)
+#define ISP5_SYSCONFIG_STANDBYMODE_NO                  (1 << 4)
+#define ISP5_SYSCONFIG_STANDBYMODE_SMART               (2 << 4)
+#define ISP5_SYSCONFIG_SOFTRESET                       (1 << 1)
+
+#define ISP5_IRQSTATUS(i)                              (0x0028 + (0x10 * (i)))
+#define ISP5_IRQENABLE_SET(i)                          (0x002C + (0x10 * (i)))
+#define ISP5_IRQENABLE_CLR(i)                          (0x0030 + (0x10 * (i)))
+
+/* Bits shared for ISP5_IRQ* registers */
+#define ISP5_IRQ_OCP_ERR                               (1 << 31)
+#define ISP5_IRQ_RSZ_INT_EOF0                          (1 << 22)
+#define ISP5_IRQ_RSZ_FIFO_IN_BLK                       (1 << 19)
+#define ISP5_IRQ_RSZ_FIFO_OVF                          (1 << 18)
+#define ISP5_IRQ_RSZ_INT_CYC_RSZA                      (1 << 16)
+#define ISP5_IRQ_RSZ_INT_DMA                           (1 << 15)
+#define ISP5_IRQ_IPIPEIF                               (1 << 9)
+#define ISP5_IRQ_ISIF3                                 (1 << 3)
+#define ISP5_IRQ_ISIF2                                 (1 << 2)
+#define ISP5_IRQ_ISIF1                                 (1 << 1)
+#define ISP5_IRQ_ISIF0                                 (1 << 0)
+
+#define ISP5_CTRL                                      (0x006C)
+#define ISP5_CTRL_MSTANDBY                             (1 << 24)
+#define ISP5_CTRL_VD_PULSE_EXT                         (1 << 23)
+#define ISP5_CTRL_MSTANDBY_WAIT                                (1 << 20)
+#define ISP5_CTRL_BL_CLK_ENABLE                                (1 << 15)
+#define ISP5_CTRL_ISIF_CLK_ENABLE                      (1 << 14)
+#define ISP5_CTRL_H3A_CLK_ENABLE                       (1 << 13)
+#define ISP5_CTRL_RSZ_CLK_ENABLE                       (1 << 12)
+#define ISP5_CTRL_IPIPE_CLK_ENABLE                     (1 << 11)
+#define ISP5_CTRL_IPIPEIF_CLK_ENABLE                   (1 << 10)
+#define ISP5_CTRL_SYNC_ENABLE                          (1 << 9)
+#define ISP5_CTRL_PSYNC_CLK_SEL                                (1 << 8)
+
+/* ISS ISP ISIF register offsets */
+#define ISIF_SYNCEN                                    (0x0000)
+#define ISIF_SYNCEN_DWEN                               (1 << 1)
+#define ISIF_SYNCEN_SYEN                               (1 << 0)
+
+#define ISIF_MODESET                                   (0x0004)
+#define ISIF_MODESET_INPMOD_MASK                       (3 << 12)
+#define ISIF_MODESET_INPMOD_RAW                                (0 << 12)
+#define ISIF_MODESET_INPMOD_YCBCR16                    (1 << 12)
+#define ISIF_MODESET_INPMOD_YCBCR8                     (2 << 12)
+#define ISIF_MODESET_CCDW_MASK                         (7 << 8)
+#define ISIF_MODESET_CCDW_2BIT                         (2 << 8)
+#define ISIF_MODESET_CCDMD                             (1 << 7)
+#define ISIF_MODESET_SWEN                              (1 << 5)
+#define ISIF_MODESET_HDPOL                             (1 << 3)
+#define ISIF_MODESET_VDPOL                             (1 << 2)
+
+#define ISIF_SPH                                       (0x0018)
+#define ISIF_SPH_MASK                                  (0x7FFF)
+
+#define ISIF_LNH                                       (0x001C)
+#define ISIF_LNH_MASK                                  (0x7FFF)
+
+#define ISIF_LNV                                       (0x0028)
+#define ISIF_LNV_MASK                                  (0x7FFF)
+
+#define ISIF_HSIZE                                     (0x0034)
+#define ISIF_HSIZE_ADCR                                        (1 << 12)
+#define ISIF_HSIZE_HSIZE_MASK                          (0xFFF)
+
+#define ISIF_CADU                                      (0x003C)
+#define ISIF_CADU_MASK                                 (0x7FF)
+
+#define ISIF_CADL                                      (0x0040)
+#define ISIF_CADL_MASK                                 (0xFFFF)
+
+#define ISIF_CCOLP                                     (0x004C)
+#define ISIF_CCOLP_CP0_F0_R                            (0 << 6)
+#define ISIF_CCOLP_CP0_F0_GR                           (1 << 6)
+#define ISIF_CCOLP_CP0_F0_B                            (3 << 6)
+#define ISIF_CCOLP_CP0_F0_GB                           (2 << 6)
+#define ISIF_CCOLP_CP1_F0_R                            (0 << 4)
+#define ISIF_CCOLP_CP1_F0_GR                           (1 << 4)
+#define ISIF_CCOLP_CP1_F0_B                            (3 << 4)
+#define ISIF_CCOLP_CP1_F0_GB                           (2 << 4)
+#define ISIF_CCOLP_CP2_F0_R                            (0 << 2)
+#define ISIF_CCOLP_CP2_F0_GR                           (1 << 2)
+#define ISIF_CCOLP_CP2_F0_B                            (3 << 2)
+#define ISIF_CCOLP_CP2_F0_GB                           (2 << 2)
+#define ISIF_CCOLP_CP3_F0_R                            (0 << 0)
+#define ISIF_CCOLP_CP3_F0_GR                           (1 << 0)
+#define ISIF_CCOLP_CP3_F0_B                            (3 << 0)
+#define ISIF_CCOLP_CP3_F0_GB                           (2 << 0)
+
+#define ISIF_VDINT0                                    (0x0070)
+#define ISIF_VDINT0_MASK                               (0x7FFF)
+
+#define ISIF_CGAMMAWD                                  (0x0080)
+#define ISIF_CGAMMAWD_GWDI_MASK                                (0xF << 1)
+#define ISIF_CGAMMAWD_GWDI_BIT11                       (0x4 << 1)
+
+#define ISIF_CCDCFG                                    (0x0088)
+#define ISIF_CCDCFG_Y8POS                              (1 << 11)
+
+/* ISS ISP IPIPEIF register offsets */
+#define IPIPEIF_ENABLE                                 (0x0000)
+
+#define IPIPEIF_CFG1                                   (0x0004)
+#define IPIPEIF_CFG1_INPSRC1_MASK                      (3 << 14)
+#define IPIPEIF_CFG1_INPSRC1_VPORT_RAW                 (0 << 14)
+#define IPIPEIF_CFG1_INPSRC1_SDRAM_RAW                 (1 << 14)
+#define IPIPEIF_CFG1_INPSRC1_ISIF_DARKFM               (2 << 14)
+#define IPIPEIF_CFG1_INPSRC1_SDRAM_YUV                 (3 << 14)
+#define IPIPEIF_CFG1_INPSRC2_MASK                      (3 << 2)
+#define IPIPEIF_CFG1_INPSRC2_ISIF                      (0 << 2)
+#define IPIPEIF_CFG1_INPSRC2_SDRAM_RAW                 (1 << 2)
+#define IPIPEIF_CFG1_INPSRC2_ISIF_DARKFM               (2 << 2)
+#define IPIPEIF_CFG1_INPSRC2_SDRAM_YUV                 (3 << 2)
+
+#define IPIPEIF_CFG2                                   (0x0030)
+#define IPIPEIF_CFG2_YUV8P                             (1 << 7)
+#define IPIPEIF_CFG2_YUV8                              (1 << 6)
+#define IPIPEIF_CFG2_YUV16                             (1 << 3)
+#define IPIPEIF_CFG2_VDPOL                             (1 << 2)
+#define IPIPEIF_CFG2_HDPOL                             (1 << 1)
+#define IPIPEIF_CFG2_INTSW                             (1 << 0)
+
+#define IPIPEIF_CLKDIV                                 (0x0040)
+
+/* ISS ISP IPIPE register offsets */
+#define IPIPE_SRC_EN                                   (0x0000)
+#define IPIPE_SRC_EN_EN                                        (1 << 0)
+
+#define IPIPE_SRC_MODE                                 (0x0004)
+#define IPIPE_SRC_MODE_WRT                             (1 << 1)
+#define IPIPE_SRC_MODE_OST                             (1 << 0)
+
+#define IPIPE_SRC_FMT                                  (0x0008)
+#define IPIPE_SRC_FMT_RAW2YUV                          (0 << 0)
+#define IPIPE_SRC_FMT_RAW2RAW                          (1 << 0)
+#define IPIPE_SRC_FMT_RAW2STATS                                (2 << 0)
+#define IPIPE_SRC_FMT_YUV2YUV                          (3 << 0)
+
+#define IPIPE_SRC_COL                                  (0x000C)
+#define IPIPE_SRC_COL_OO_R                             (0 << 6)
+#define IPIPE_SRC_COL_OO_GR                            (1 << 6)
+#define IPIPE_SRC_COL_OO_B                             (3 << 6)
+#define IPIPE_SRC_COL_OO_GB                            (2 << 6)
+#define IPIPE_SRC_COL_OE_R                             (0 << 4)
+#define IPIPE_SRC_COL_OE_GR                            (1 << 4)
+#define IPIPE_SRC_COL_OE_B                             (3 << 4)
+#define IPIPE_SRC_COL_OE_GB                            (2 << 4)
+#define IPIPE_SRC_COL_EO_R                             (0 << 2)
+#define IPIPE_SRC_COL_EO_GR                            (1 << 2)
+#define IPIPE_SRC_COL_EO_B                             (3 << 2)
+#define IPIPE_SRC_COL_EO_GB                            (2 << 2)
+#define IPIPE_SRC_COL_EE_R                             (0 << 0)
+#define IPIPE_SRC_COL_EE_GR                            (1 << 0)
+#define IPIPE_SRC_COL_EE_B                             (3 << 0)
+#define IPIPE_SRC_COL_EE_GB                            (2 << 0)
+
+#define IPIPE_SRC_VPS                                  (0x0010)
+#define IPIPE_SRC_VPS_MASK                             (0xFFFF)
+
+#define IPIPE_SRC_VSZ                                  (0x0014)
+#define IPIPE_SRC_VSZ_MASK                             (0x1FFF)
+
+#define IPIPE_SRC_HPS                                  (0x0018)
+#define IPIPE_SRC_HPS_MASK                             (0xFFFF)
+
+#define IPIPE_SRC_HSZ                                  (0x001C)
+#define IPIPE_SRC_HSZ_MASK                             (0x1FFE)
+
+#define IPIPE_SEL_SBU                                  (0x0020)
+
+#define IPIPE_SRC_STA                                  (0x0024)
+
+#define IPIPE_GCK_MMR                                  (0x0028)
+#define IPIPE_GCK_MMR_REG                              (1 << 0)
+
+#define IPIPE_GCK_PIX                                  (0x002C)
+#define IPIPE_GCK_PIX_G3                               (1 << 3)
+#define IPIPE_GCK_PIX_G2                               (1 << 2)
+#define IPIPE_GCK_PIX_G1                               (1 << 1)
+#define IPIPE_GCK_PIX_G0                               (1 << 0)
+
+#define IPIPE_DPC_LUT_EN                               (0x0034)
+#define IPIPE_DPC_LUT_SEL                              (0x0038)
+#define IPIPE_DPC_LUT_ADR                              (0x003C)
+#define IPIPE_DPC_LUT_SIZ                              (0x0040)
+
+#define IPIPE_DPC_OTF_EN                               (0x0044)
+#define IPIPE_DPC_OTF_TYP                              (0x0048)
+#define IPIPE_DPC_OTF_2_D_THR_R                                (0x004C)
+#define IPIPE_DPC_OTF_2_D_THR_GR                       (0x0050)
+#define IPIPE_DPC_OTF_2_D_THR_GB                       (0x0054)
+#define IPIPE_DPC_OTF_2_D_THR_B                                (0x0058)
+#define IPIPE_DPC_OTF_2_C_THR_R                                (0x005C)
+#define IPIPE_DPC_OTF_2_C_THR_GR                       (0x0060)
+#define IPIPE_DPC_OTF_2_C_THR_GB                       (0x0064)
+#define IPIPE_DPC_OTF_2_C_THR_B                                (0x0068)
+#define IPIPE_DPC_OTF_3_SHF                            (0x006C)
+#define IPIPE_DPC_OTF_3_D_THR                          (0x0070)
+#define IPIPE_DPC_OTF_3_D_SPL                          (0x0074)
+#define IPIPE_DPC_OTF_3_D_MIN                          (0x0078)
+#define IPIPE_DPC_OTF_3_D_MAX                          (0x007C)
+#define IPIPE_DPC_OTF_3_C_THR                          (0x0080)
+#define IPIPE_DPC_OTF_3_C_SLP                          (0x0084)
+#define IPIPE_DPC_OTF_3_C_MIN                          (0x0088)
+#define IPIPE_DPC_OTF_3_C_MAX                          (0x008C)
+
+#define IPIPE_LSC_VOFT                                 (0x0090)
+#define IPIPE_LSC_VA2                                  (0x0094)
+#define IPIPE_LSC_VA1                                  (0x0098)
+#define IPIPE_LSC_VS                                   (0x009C)
+#define IPIPE_LSC_HOFT                                 (0x00A0)
+#define IPIPE_LSC_HA2                                  (0x00A4)
+#define IPIPE_LSC_HA1                                  (0x00A8)
+#define IPIPE_LSC_HS                                   (0x00AC)
+#define IPIPE_LSC_GAN_R                                        (0x00B0)
+#define IPIPE_LSC_GAN_GR                               (0x00B4)
+#define IPIPE_LSC_GAN_GB                               (0x00B8)
+#define IPIPE_LSC_GAN_B                                        (0x00BC)
+#define IPIPE_LSC_OFT_R                                        (0x00C0)
+#define IPIPE_LSC_OFT_GR                               (0x00C4)
+#define IPIPE_LSC_OFT_GB                               (0x00C8)
+#define IPIPE_LSC_OFT_B                                        (0x00CC)
+#define IPIPE_LSC_SHF                                  (0x00D0)
+#define IPIPE_LSC_MAX                                  (0x00D4)
+
+#define IPIPE_D2F_1ST_EN                               (0x00D8)
+#define IPIPE_D2F_1ST_TYP                              (0x00DC)
+#define IPIPE_D2F_1ST_THR_00                           (0x00E0)
+#define IPIPE_D2F_1ST_THR_01                           (0x00E4)
+#define IPIPE_D2F_1ST_THR_02                           (0x00E8)
+#define IPIPE_D2F_1ST_THR_03                           (0x00EC)
+#define IPIPE_D2F_1ST_THR_04                           (0x00F0)
+#define IPIPE_D2F_1ST_THR_05                           (0x00F4)
+#define IPIPE_D2F_1ST_THR_06                           (0x00F8)
+#define IPIPE_D2F_1ST_THR_07                           (0x00FC)
+#define IPIPE_D2F_1ST_STR_00                           (0x0100)
+#define IPIPE_D2F_1ST_STR_01                           (0x0104)
+#define IPIPE_D2F_1ST_STR_02                           (0x0108)
+#define IPIPE_D2F_1ST_STR_03                           (0x010C)
+#define IPIPE_D2F_1ST_STR_04                           (0x0110)
+#define IPIPE_D2F_1ST_STR_05                           (0x0114)
+#define IPIPE_D2F_1ST_STR_06                           (0x0118)
+#define IPIPE_D2F_1ST_STR_07                           (0x011C)
+#define IPIPE_D2F_1ST_SPR_00                           (0x0120)
+#define IPIPE_D2F_1ST_SPR_01                           (0x0124)
+#define IPIPE_D2F_1ST_SPR_02                           (0x0128)
+#define IPIPE_D2F_1ST_SPR_03                           (0x012C)
+#define IPIPE_D2F_1ST_SPR_04                           (0x0130)
+#define IPIPE_D2F_1ST_SPR_05                           (0x0134)
+#define IPIPE_D2F_1ST_SPR_06                           (0x0138)
+#define IPIPE_D2F_1ST_SPR_07                           (0x013C)
+#define IPIPE_D2F_1ST_EDG_MIN                          (0x0140)
+#define IPIPE_D2F_1ST_EDG_MAX                          (0x0144)
+#define IPIPE_D2F_2ND_EN                               (0x0148)
+#define IPIPE_D2F_2ND_TYP                              (0x014C)
+#define IPIPE_D2F_2ND_THR00                            (0x0150)
+#define IPIPE_D2F_2ND_THR01                            (0x0154)
+#define IPIPE_D2F_2ND_THR02                            (0x0158)
+#define IPIPE_D2F_2ND_THR03                            (0x015C)
+#define IPIPE_D2F_2ND_THR04                            (0x0160)
+#define IPIPE_D2F_2ND_THR05                            (0x0164)
+#define IPIPE_D2F_2ND_THR06                            (0x0168)
+#define IPIPE_D2F_2ND_THR07                            (0x016C)
+#define IPIPE_D2F_2ND_STR_00                           (0x0170)
+#define IPIPE_D2F_2ND_STR_01                           (0x0174)
+#define IPIPE_D2F_2ND_STR_02                           (0x0178)
+#define IPIPE_D2F_2ND_STR_03                           (0x017C)
+#define IPIPE_D2F_2ND_STR_04                           (0x0180)
+#define IPIPE_D2F_2ND_STR_05                           (0x0184)
+#define IPIPE_D2F_2ND_STR_06                           (0x0188)
+#define IPIPE_D2F_2ND_STR_07                           (0x018C)
+#define IPIPE_D2F_2ND_SPR_00                           (0x0190)
+#define IPIPE_D2F_2ND_SPR_01                           (0x0194)
+#define IPIPE_D2F_2ND_SPR_02                           (0x0198)
+#define IPIPE_D2F_2ND_SPR_03                           (0x019C)
+#define IPIPE_D2F_2ND_SPR_04                           (0x01A0)
+#define IPIPE_D2F_2ND_SPR_05                           (0x01A4)
+#define IPIPE_D2F_2ND_SPR_06                           (0x01A8)
+#define IPIPE_D2F_2ND_SPR_07                           (0x01AC)
+#define IPIPE_D2F_2ND_EDG_MIN                          (0x01B0)
+#define IPIPE_D2F_2ND_EDG_MAX                          (0x01B4)
+
+#define IPIPE_GIC_EN                                   (0x01B8)
+#define IPIPE_GIC_TYP                                  (0x01BC)
+#define IPIPE_GIC_GAN                                  (0x01C0)
+#define IPIPE_GIC_NFGAIN                               (0x01C4)
+#define IPIPE_GIC_THR                                  (0x01C8)
+#define IPIPE_GIC_SLP                                  (0x01CC)
+
+#define IPIPE_WB2_OFT_R                                        (0x01D0)
+#define IPIPE_WB2_OFT_GR                               (0x01D4)
+#define IPIPE_WB2_OFT_GB                               (0x01D8)
+#define IPIPE_WB2_OFT_B                                        (0x01DC)
+
+#define IPIPE_WB2_WGN_R                                        (0x01E0)
+#define IPIPE_WB2_WGN_GR                               (0x01E4)
+#define IPIPE_WB2_WGN_GB                               (0x01E8)
+#define IPIPE_WB2_WGN_B                                        (0x01EC)
+
+#define IPIPE_CFA_MODE                                 (0x01F0)
+#define IPIPE_CFA_2DIR_HPF_THR                         (0x01F4)
+#define IPIPE_CFA_2DIR_HPF_SLP                         (0x01F8)
+#define IPIPE_CFA_2DIR_MIX_THR                         (0x01FC)
+#define IPIPE_CFA_2DIR_MIX_SLP                         (0x0200)
+#define IPIPE_CFA_2DIR_DIR_TRH                         (0x0204)
+#define IPIPE_CFA_2DIR_DIR_SLP                         (0x0208)
+#define IPIPE_CFA_2DIR_NDWT                            (0x020C)
+#define IPIPE_CFA_MONO_HUE_FRA                         (0x0210)
+#define IPIPE_CFA_MONO_EDG_THR                         (0x0214)
+#define IPIPE_CFA_MONO_THR_MIN                         (0x0218)
+
+#define IPIPE_CFA_MONO_THR_SLP                         (0x021C)
+#define IPIPE_CFA_MONO_SLP_MIN                         (0x0220)
+#define IPIPE_CFA_MONO_SLP_SLP                         (0x0224)
+#define IPIPE_CFA_MONO_LPWT                            (0x0228)
+
+#define IPIPE_RGB1_MUL_RR                              (0x022C)
+#define IPIPE_RGB1_MUL_GR                              (0x0230)
+#define IPIPE_RGB1_MUL_BR                              (0x0234)
+#define IPIPE_RGB1_MUL_RG                              (0x0238)
+#define IPIPE_RGB1_MUL_GG                              (0x023C)
+#define IPIPE_RGB1_MUL_BG                              (0x0240)
+#define IPIPE_RGB1_MUL_RB                              (0x0244)
+#define IPIPE_RGB1_MUL_GB                              (0x0248)
+#define IPIPE_RGB1_MUL_BB                              (0x024C)
+#define IPIPE_RGB1_OFT_OR                              (0x0250)
+#define IPIPE_RGB1_OFT_OG                              (0x0254)
+#define IPIPE_RGB1_OFT_OB                              (0x0258)
+#define IPIPE_GMM_CFG                                  (0x025C)
+#define IPIPE_RGB2_MUL_RR                              (0x0260)
+#define IPIPE_RGB2_MUL_GR                              (0x0264)
+#define IPIPE_RGB2_MUL_BR                              (0x0268)
+#define IPIPE_RGB2_MUL_RG                              (0x026C)
+#define IPIPE_RGB2_MUL_GG                              (0x0270)
+#define IPIPE_RGB2_MUL_BG                              (0x0274)
+#define IPIPE_RGB2_MUL_RB                              (0x0278)
+#define IPIPE_RGB2_MUL_GB                              (0x027C)
+#define IPIPE_RGB2_MUL_BB                              (0x0280)
+#define IPIPE_RGB2_OFT_OR                              (0x0284)
+#define IPIPE_RGB2_OFT_OG                              (0x0288)
+#define IPIPE_RGB2_OFT_OB                              (0x028C)
+
+#define IPIPE_YUV_ADJ                                  (0x0294)
+#define IPIPE_YUV_MUL_RY                               (0x0298)
+#define IPIPE_YUV_MUL_GY                               (0x029C)
+#define IPIPE_YUV_MUL_BY                               (0x02A0)
+#define IPIPE_YUV_MUL_RCB                              (0x02A4)
+#define IPIPE_YUV_MUL_GCB                              (0x02A8)
+#define IPIPE_YUV_MUL_BCB                              (0x02AC)
+#define IPIPE_YUV_MUL_RCR                              (0x02B0)
+#define IPIPE_YUV_MUL_GCR                              (0x02B4)
+#define IPIPE_YUV_MUL_BCR                              (0x02B8)
+#define IPIPE_YUV_OFT_Y                                        (0x02BC)
+#define IPIPE_YUV_OFT_CB                               (0x02C0)
+#define IPIPE_YUV_OFT_CR                               (0x02C4)
+
+#define IPIPE_YUV_PHS                                  (0x02C8)
+#define IPIPE_YUV_PHS_LPF                              (1 << 1)
+#define IPIPE_YUV_PHS_POS                              (1 << 0)
+
+#define IPIPE_YEE_EN                                   (0x02D4)
+#define IPIPE_YEE_TYP                                  (0x02D8)
+#define IPIPE_YEE_SHF                                  (0x02DC)
+#define IPIPE_YEE_MUL_00                               (0x02E0)
+#define IPIPE_YEE_MUL_01                               (0x02E4)
+#define IPIPE_YEE_MUL_02                               (0x02E8)
+#define IPIPE_YEE_MUL_10                               (0x02EC)
+#define IPIPE_YEE_MUL_11                               (0x02F0)
+#define IPIPE_YEE_MUL_12                               (0x02F4)
+#define IPIPE_YEE_MUL_20                               (0x02F8)
+#define IPIPE_YEE_MUL_21                               (0x02FC)
+#define IPIPE_YEE_MUL_22                               (0x0300)
+#define IPIPE_YEE_THR                                  (0x0304)
+#define IPIPE_YEE_E_GAN                                        (0x0308)
+#define IPIPE_YEE_E_THR_1                              (0x030C)
+#define IPIPE_YEE_E_THR_2                              (0x0310)
+#define IPIPE_YEE_G_GAN                                        (0x0314)
+#define IPIPE_YEE_G_OFT                                        (0x0318)
+
+#define IPIPE_CAR_EN                                   (0x031C)
+#define IPIPE_CAR_TYP                                  (0x0320)
+#define IPIPE_CAR_SW                                   (0x0324)
+#define IPIPE_CAR_HPF_TYP                              (0x0328)
+#define IPIPE_CAR_HPF_SHF                              (0x032C)
+#define IPIPE_CAR_HPF_THR                              (0x0330)
+#define IPIPE_CAR_GN1_GAN                              (0x0334)
+#define IPIPE_CAR_GN1_SHF                              (0x0338)
+#define IPIPE_CAR_GN1_MIN                              (0x033C)
+#define IPIPE_CAR_GN2_GAN                              (0x0340)
+#define IPIPE_CAR_GN2_SHF                              (0x0344)
+#define IPIPE_CAR_GN2_MIN                              (0x0348)
+#define IPIPE_CGS_EN                                   (0x034C)
+#define IPIPE_CGS_GN1_L_THR                            (0x0350)
+#define IPIPE_CGS_GN1_L_GAIN                           (0x0354)
+#define IPIPE_CGS_GN1_L_SHF                            (0x0358)
+#define IPIPE_CGS_GN1_L_MIN                            (0x035C)
+#define IPIPE_CGS_GN1_H_THR                            (0x0360)
+#define IPIPE_CGS_GN1_H_GAIN                           (0x0364)
+#define IPIPE_CGS_GN1_H_SHF                            (0x0368)
+#define IPIPE_CGS_GN1_H_MIN                            (0x036C)
+#define IPIPE_CGS_GN2_L_THR                            (0x0370)
+#define IPIPE_CGS_GN2_L_GAIN                           (0x0374)
+#define IPIPE_CGS_GN2_L_SHF                            (0x0378)
+#define IPIPE_CGS_GN2_L_MIN                            (0x037C)
+
+#define IPIPE_BOX_EN                                   (0x0380)
+#define IPIPE_BOX_MODE                                 (0x0384)
+#define IPIPE_BOX_TYP                                  (0x0388)
+#define IPIPE_BOX_SHF                                  (0x038C)
+#define IPIPE_BOX_SDR_SAD_H                            (0x0390)
+#define IPIPE_BOX_SDR_SAD_L                            (0x0394)
+
+#define IPIPE_HST_EN                                   (0x039C)
+#define IPIPE_HST_MODE                                 (0x03A0)
+#define IPIPE_HST_SEL                                  (0x03A4)
+#define IPIPE_HST_PARA                                 (0x03A8)
+#define IPIPE_HST_0_VPS                                        (0x03AC)
+#define IPIPE_HST_0_VSZ                                        (0x03B0)
+#define IPIPE_HST_0_HPS                                        (0x03B4)
+#define IPIPE_HST_0_HSZ                                        (0x03B8)
+#define IPIPE_HST_1_VPS                                        (0x03BC)
+#define IPIPE_HST_1_VSZ                                        (0x03C0)
+#define IPIPE_HST_1_HPS                                        (0x03C4)
+#define IPIPE_HST_1_HSZ                                        (0x03C8)
+#define IPIPE_HST_2_VPS                                        (0x03CC)
+#define IPIPE_HST_2_VSZ                                        (0x03D0)
+#define IPIPE_HST_2_HPS                                        (0x03D4)
+#define IPIPE_HST_2_HSZ                                        (0x03D8)
+#define IPIPE_HST_3_VPS                                        (0x03DC)
+#define IPIPE_HST_3_VSZ                                        (0x03E0)
+#define IPIPE_HST_3_HPS                                        (0x03E4)
+#define IPIPE_HST_3_HSZ                                        (0x03E8)
+#define IPIPE_HST_TBL                                  (0x03EC)
+#define IPIPE_HST_MUL_R                                        (0x03F0)
+#define IPIPE_HST_MUL_GR                               (0x03F4)
+#define IPIPE_HST_MUL_GB                               (0x03F8)
+#define IPIPE_HST_MUL_B                                        (0x03FC)
+
+#define IPIPE_BSC_EN                                   (0x0400)
+#define IPIPE_BSC_MODE                                 (0x0404)
+#define IPIPE_BSC_TYP                                  (0x0408)
+#define IPIPE_BSC_ROW_VCT                              (0x040C)
+#define IPIPE_BSC_ROW_SHF                              (0x0410)
+#define IPIPE_BSC_ROW_VPO                              (0x0414)
+#define IPIPE_BSC_ROW_VNU                              (0x0418)
+#define IPIPE_BSC_ROW_VSKIP                            (0x041C)
+#define IPIPE_BSC_ROW_HPO                              (0x0420)
+#define IPIPE_BSC_ROW_HNU                              (0x0424)
+#define IPIPE_BSC_ROW_HSKIP                            (0x0428)
+#define IPIPE_BSC_COL_VCT                              (0x042C)
+#define IPIPE_BSC_COL_SHF                              (0x0430)
+#define IPIPE_BSC_COL_VPO                              (0x0434)
+#define IPIPE_BSC_COL_VNU                              (0x0438)
+#define IPIPE_BSC_COL_VSKIP                            (0x043C)
+#define IPIPE_BSC_COL_HPO                              (0x0440)
+#define IPIPE_BSC_COL_HNU                              (0x0444)
+#define IPIPE_BSC_COL_HSKIP                            (0x0448)
+
+#define IPIPE_BSC_EN                                   (0x0400)
+
+/* ISS ISP Resizer register offsets */
+#define RSZ_REVISION                                   (0x0000)
+#define RSZ_SYSCONFIG                                  (0x0004)
+#define RSZ_SYSCONFIG_RSZB_CLK_EN                      (1 << 9)
+#define RSZ_SYSCONFIG_RSZA_CLK_EN                      (1 << 8)
+
+#define RSZ_IN_FIFO_CTRL                               (0x000C)
+#define RSZ_IN_FIFO_CTRL_THRLD_LOW_MASK                        (0x1FF << 16)
+#define RSZ_IN_FIFO_CTRL_THRLD_LOW_SHIFT               16
+#define RSZ_IN_FIFO_CTRL_THRLD_HIGH_MASK               (0x1FF << 0)
+#define RSZ_IN_FIFO_CTRL_THRLD_HIGH_SHIFT              0
+
+#define RSZ_FRACDIV                                    (0x0008)
+#define RSZ_FRACDIV_MASK                               (0xFFFF)
+
+#define RSZ_SRC_EN                                     (0x0020)
+#define RSZ_SRC_EN_SRC_EN                              (1 << 0)
+
+#define RSZ_SRC_MODE                                   (0x0024)
+#define RSZ_SRC_MODE_OST                               (1 << 0)
+#define RSZ_SRC_MODE_WRT                               (1 << 1)
+
+#define RSZ_SRC_FMT0                                   (0x0028)
+#define RSZ_SRC_FMT0_BYPASS                            (1 << 1)
+#define RSZ_SRC_FMT0_SEL                               (1 << 0)
+
+#define RSZ_SRC_FMT1                                   (0x002C)
+#define RSZ_SRC_FMT1_IN420                             (1 << 1)
+
+#define RSZ_SRC_VPS                                    (0x0030)
+#define RSZ_SRC_VSZ                                    (0x0034)
+#define RSZ_SRC_HPS                                    (0x0038)
+#define RSZ_SRC_HSZ                                    (0x003C)
+#define RSZ_DMA_RZA                                    (0x0040)
+#define RSZ_DMA_RZB                                    (0x0044)
+#define RSZ_DMA_STA                                    (0x0048)
+#define RSZ_GCK_MMR                                    (0x004C)
+#define RSZ_GCK_MMR_MMR                                        (1 << 0)
+
+#define RSZ_GCK_SDR                                    (0x0054)
+#define RSZ_GCK_SDR_CORE                               (1 << 0)
+
+#define RSZ_IRQ_RZA                                    (0x0058)
+#define RSZ_IRQ_RZA_MASK                               (0x1FFF)
+
+#define RSZ_IRQ_RZB                                    (0x005C)
+#define RSZ_IRQ_RZB_MASK                               (0x1FFF)
+
+#define RSZ_YUV_Y_MIN                                  (0x0060)
+#define RSZ_YUV_Y_MAX                                  (0x0064)
+#define RSZ_YUV_C_MIN                                  (0x0068)
+#define RSZ_YUV_C_MAX                                  (0x006C)
+
+#define RSZ_SEQ                                                (0x0074)
+#define RSZ_SEQ_HRVB                                   (1 << 2)
+#define RSZ_SEQ_HRVA                                   (1 << 0)
+
+#define RZA_EN                                         (0x0078)
+#define RZA_MODE                                       (0x007C)
+#define RZA_MODE_ONE_SHOT                              (1 << 0)
+
+#define RZA_420                                                (0x0080)
+#define RZA_I_VPS                                      (0x0084)
+#define RZA_I_HPS                                      (0x0088)
+#define RZA_O_VSZ                                      (0x008C)
+#define RZA_O_HSZ                                      (0x0090)
+#define RZA_V_PHS_Y                                    (0x0094)
+#define RZA_V_PHS_C                                    (0x0098)
+#define RZA_V_DIF                                      (0x009C)
+#define RZA_V_TYP                                      (0x00A0)
+#define RZA_V_LPF                                      (0x00A4)
+#define RZA_H_PHS                                      (0x00A8)
+#define RZA_H_DIF                                      (0x00B0)
+#define RZA_H_TYP                                      (0x00B4)
+#define RZA_H_LPF                                      (0x00B8)
+#define RZA_DWN_EN                                     (0x00BC)
+#define RZA_SDR_Y_BAD_H                                        (0x00D0)
+#define RZA_SDR_Y_BAD_L                                        (0x00D4)
+#define RZA_SDR_Y_SAD_H                                        (0x00D8)
+#define RZA_SDR_Y_SAD_L                                        (0x00DC)
+#define RZA_SDR_Y_OFT                                  (0x00E0)
+#define RZA_SDR_Y_PTR_S                                        (0x00E4)
+#define RZA_SDR_Y_PTR_E                                        (0x00E8)
+#define RZA_SDR_C_BAD_H                                        (0x00EC)
+#define RZA_SDR_C_BAD_L                                        (0x00F0)
+#define RZA_SDR_C_SAD_H                                        (0x00F4)
+#define RZA_SDR_C_SAD_L                                        (0x00F8)
+#define RZA_SDR_C_OFT                                  (0x00FC)
+#define RZA_SDR_C_PTR_S                                        (0x0100)
+#define RZA_SDR_C_PTR_E                                        (0x0104)
+
+#define RZB_EN                                         (0x0108)
+#define RZB_MODE                                       (0x010C)
+#define RZB_420                                                (0x0110)
+#define RZB_I_VPS                                      (0x0114)
+#define RZB_I_HPS                                      (0x0118)
+#define RZB_O_VSZ                                      (0x011C)
+#define RZB_O_HSZ                                      (0x0120)
+
+#define RZB_V_DIF                                      (0x012C)
+#define RZB_V_TYP                                      (0x0130)
+#define RZB_V_LPF                                      (0x0134)
+
+#define RZB_H_DIF                                      (0x0140)
+#define RZB_H_TYP                                      (0x0144)
+#define RZB_H_LPF                                      (0x0148)
+
+#define RZB_SDR_Y_BAD_H                                        (0x0160)
+#define RZB_SDR_Y_BAD_L                                        (0x0164)
+#define RZB_SDR_Y_SAD_H                                        (0x0168)
+#define RZB_SDR_Y_SAD_L                                        (0x016C)
+#define RZB_SDR_Y_OFT                                  (0x0170)
+#define RZB_SDR_Y_PTR_S                                        (0x0174)
+#define RZB_SDR_Y_PTR_E                                        (0x0178)
+#define RZB_SDR_C_BAD_H                                        (0x017C)
+#define RZB_SDR_C_BAD_L                                        (0x0180)
+#define RZB_SDR_C_SAD_H                                        (0x0184)
+#define RZB_SDR_C_SAD_L                                        (0x0188)
+
+#define RZB_SDR_C_PTR_S                                        (0x0190)
+#define RZB_SDR_C_PTR_E                                        (0x0194)
+
+/* Shared Bitmasks between RZA & RZB */
+#define RSZ_EN_EN                                      (1 << 0)
+
+#define RSZ_420_CEN                                    (1 << 1)
+#define RSZ_420_YEN                                    (1 << 0)
+
+#define RSZ_I_VPS_MASK                                 (0x1FFF)
+
+#define RSZ_I_HPS_MASK                                 (0x1FFF)
+
+#define RSZ_O_VSZ_MASK                                 (0x1FFF)
+
+#define RSZ_O_HSZ_MASK                                 (0x1FFE)
+
+#define RSZ_V_PHS_Y_MASK                               (0x3FFF)
+
+#define RSZ_V_PHS_C_MASK                               (0x3FFF)
+
+#define RSZ_V_DIF_MASK                                 (0x3FFF)
+
+#define RSZ_V_TYP_C                                    (1 << 1)
+#define RSZ_V_TYP_Y                                    (1 << 0)
+
+#define RSZ_V_LPF_C_MASK                               (0x3F << 6)
+#define RSZ_V_LPF_C_SHIFT                              6
+#define RSZ_V_LPF_Y_MASK                               (0x3F << 0)
+#define RSZ_V_LPF_Y_SHIFT                              0
+
+#define RSZ_H_PHS_MASK                                 (0x3FFF)
+
+#define RSZ_H_DIF_MASK                                 (0x3FFF)
+
+#define RSZ_H_TYP_C                                    (1 << 1)
+#define RSZ_H_TYP_Y                                    (1 << 0)
+
+#define RSZ_H_LPF_C_MASK                               (0x3F << 6)
+#define RSZ_H_LPF_C_SHIFT                              6
+#define RSZ_H_LPF_Y_MASK                               (0x3F << 0)
+#define RSZ_H_LPF_Y_SHIFT                              0
+
+#define RSZ_DWN_EN_DWN_EN                              (1 << 0)
+
+#endif /* _OMAP4_ISS_REGS_H_ */
diff --git a/drivers/staging/media/omap4iss/iss_resizer.c b/drivers/staging/media/omap4iss/iss_resizer.c
new file mode 100644 (file)
index 0000000..cb5df52
--- /dev/null
@@ -0,0 +1,905 @@
+/*
+ * TI OMAP4 ISS V4L2 Driver - ISP RESIZER module
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+
+#include "iss.h"
+#include "iss_regs.h"
+#include "iss_resizer.h"
+
+static struct v4l2_mbus_framefmt *
+__resizer_get_format(struct iss_resizer_device *resizer, struct v4l2_subdev_fh *fh,
+                 unsigned int pad, enum v4l2_subdev_format_whence which);
+
+static const unsigned int resizer_fmts[] = {
+       V4L2_MBUS_FMT_UYVY8_1X16,
+       V4L2_MBUS_FMT_YUYV8_1X16,
+};
+
+/*
+ * resizer_print_status - Print current RESIZER Module register values.
+ * @resizer: Pointer to ISS ISP RESIZER device.
+ *
+ * Also prints other debug information stored in the RESIZER module.
+ */
+#define RSZ_PRINT_REGISTER(iss, name)\
+       dev_dbg(iss->dev, "###RSZ " #name "=0x%08x\n", \
+               readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_##name))
+
+#define RZA_PRINT_REGISTER(iss, name)\
+       dev_dbg(iss->dev, "###RZA " #name "=0x%08x\n", \
+               readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_##name))
+
+static void resizer_print_status(struct iss_resizer_device *resizer)
+{
+       struct iss_device *iss = to_iss_device(resizer);
+
+       dev_dbg(iss->dev, "-------------RESIZER Register dump-------------\n");
+
+       RSZ_PRINT_REGISTER(iss, SYSCONFIG);
+       RSZ_PRINT_REGISTER(iss, IN_FIFO_CTRL);
+       RSZ_PRINT_REGISTER(iss, FRACDIV);
+       RSZ_PRINT_REGISTER(iss, SRC_EN);
+       RSZ_PRINT_REGISTER(iss, SRC_MODE);
+       RSZ_PRINT_REGISTER(iss, SRC_FMT0);
+       RSZ_PRINT_REGISTER(iss, SRC_FMT1);
+       RSZ_PRINT_REGISTER(iss, SRC_VPS);
+       RSZ_PRINT_REGISTER(iss, SRC_VSZ);
+       RSZ_PRINT_REGISTER(iss, SRC_HPS);
+       RSZ_PRINT_REGISTER(iss, SRC_HSZ);
+       RSZ_PRINT_REGISTER(iss, DMA_RZA);
+       RSZ_PRINT_REGISTER(iss, DMA_RZB);
+       RSZ_PRINT_REGISTER(iss, DMA_STA);
+       RSZ_PRINT_REGISTER(iss, GCK_MMR);
+       RSZ_PRINT_REGISTER(iss, GCK_SDR);
+       RSZ_PRINT_REGISTER(iss, IRQ_RZA);
+       RSZ_PRINT_REGISTER(iss, IRQ_RZB);
+       RSZ_PRINT_REGISTER(iss, YUV_Y_MIN);
+       RSZ_PRINT_REGISTER(iss, YUV_Y_MAX);
+       RSZ_PRINT_REGISTER(iss, YUV_C_MIN);
+       RSZ_PRINT_REGISTER(iss, YUV_C_MAX);
+       RSZ_PRINT_REGISTER(iss, SEQ);
+
+       RZA_PRINT_REGISTER(iss, EN);
+       RZA_PRINT_REGISTER(iss, MODE);
+       RZA_PRINT_REGISTER(iss, 420);
+       RZA_PRINT_REGISTER(iss, I_VPS);
+       RZA_PRINT_REGISTER(iss, I_HPS);
+       RZA_PRINT_REGISTER(iss, O_VSZ);
+       RZA_PRINT_REGISTER(iss, O_HSZ);
+       RZA_PRINT_REGISTER(iss, V_PHS_Y);
+       RZA_PRINT_REGISTER(iss, V_PHS_C);
+       RZA_PRINT_REGISTER(iss, V_DIF);
+       RZA_PRINT_REGISTER(iss, V_TYP);
+       RZA_PRINT_REGISTER(iss, V_LPF);
+       RZA_PRINT_REGISTER(iss, H_PHS);
+       RZA_PRINT_REGISTER(iss, H_DIF);
+       RZA_PRINT_REGISTER(iss, H_TYP);
+       RZA_PRINT_REGISTER(iss, H_LPF);
+       RZA_PRINT_REGISTER(iss, DWN_EN);
+       RZA_PRINT_REGISTER(iss, SDR_Y_BAD_H);
+       RZA_PRINT_REGISTER(iss, SDR_Y_BAD_L);
+       RZA_PRINT_REGISTER(iss, SDR_Y_SAD_H);
+       RZA_PRINT_REGISTER(iss, SDR_Y_SAD_L);
+       RZA_PRINT_REGISTER(iss, SDR_Y_OFT);
+       RZA_PRINT_REGISTER(iss, SDR_Y_PTR_S);
+       RZA_PRINT_REGISTER(iss, SDR_Y_PTR_E);
+       RZA_PRINT_REGISTER(iss, SDR_C_BAD_H);
+       RZA_PRINT_REGISTER(iss, SDR_C_BAD_L);
+       RZA_PRINT_REGISTER(iss, SDR_C_SAD_H);
+       RZA_PRINT_REGISTER(iss, SDR_C_SAD_L);
+       RZA_PRINT_REGISTER(iss, SDR_C_OFT);
+       RZA_PRINT_REGISTER(iss, SDR_C_PTR_S);
+       RZA_PRINT_REGISTER(iss, SDR_C_PTR_E);
+
+       dev_dbg(iss->dev, "-----------------------------------------------\n");
+}
+
+/*
+ * resizer_enable - Enable/Disable RESIZER.
+ * @enable: enable flag
+ *
+ */
+static void resizer_enable(struct iss_resizer_device *resizer, u8 enable)
+{
+       struct iss_device *iss = to_iss_device(resizer);
+
+       writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_EN) &
+               ~RSZ_SRC_EN_SRC_EN) |
+               enable ? RSZ_SRC_EN_SRC_EN : 0,
+               iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_EN);
+
+       /* TODO: Enable RSZB */
+       writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_EN) &
+               ~RSZ_EN_EN) |
+               enable ? RSZ_EN_EN : 0,
+               iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_EN);
+}
+
+/* -----------------------------------------------------------------------------
+ * Format- and pipeline-related configuration helpers
+ */
+
+/*
+ * resizer_set_outaddr - Set memory address to save output image
+ * @resizer: Pointer to ISP RESIZER device.
+ * @addr: 32-bit memory address aligned on 32 byte boundary.
+ *
+ * Sets the memory address where the output will be saved.
+ */
+static void resizer_set_outaddr(struct iss_resizer_device *resizer, u32 addr)
+{
+       struct iss_device *iss = to_iss_device(resizer);
+       struct v4l2_mbus_framefmt *informat, *outformat;
+
+       informat = &resizer->formats[RESIZER_PAD_SINK];
+       outformat = &resizer->formats[RESIZER_PAD_SOURCE_MEM];
+
+       /* Save address splitted in Base Address H & L */
+       writel((addr >> 16) & 0xffff,
+               iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_Y_BAD_H);
+       writel(addr & 0xffff,
+               iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_Y_BAD_L);
+
+       /* SAD = BAD */
+       writel((addr >> 16) & 0xffff,
+               iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_Y_SAD_H);
+       writel(addr & 0xffff,
+               iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_Y_SAD_L);
+
+       /* Program UV buffer address... Hardcoded to be contiguous! */
+       if ((informat->code == V4L2_MBUS_FMT_UYVY8_1X16) &&
+           (outformat->code == V4L2_MBUS_FMT_YUYV8_1_5X8)) {
+               u32 c_addr = addr + (resizer->video_out.bpl_value *
+                                    (outformat->height - 1));
+
+               /* Ensure Y_BAD_L[6:0] = C_BAD_L[6:0]*/
+               if ((c_addr ^ addr) & 0x7f) {
+                       c_addr &= ~0x7f;
+                       c_addr += 0x80;
+                       c_addr |= addr & 0x7f;
+               }
+
+               /* Save address splitted in Base Address H & L */
+               writel((c_addr >> 16) & 0xffff,
+                       iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_C_BAD_H);
+               writel(c_addr & 0xffff,
+                       iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_C_BAD_L);
+
+               /* SAD = BAD */
+               writel((c_addr >> 16) & 0xffff,
+                       iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_C_SAD_H);
+               writel(c_addr & 0xffff,
+                       iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_C_SAD_L);
+       }
+}
+
+static void resizer_configure(struct iss_resizer_device *resizer)
+{
+       struct iss_device *iss = to_iss_device(resizer);
+       struct v4l2_mbus_framefmt *informat, *outformat;
+
+       informat = &resizer->formats[RESIZER_PAD_SINK];
+       outformat = &resizer->formats[RESIZER_PAD_SOURCE_MEM];
+
+       /* Make sure we don't bypass the resizer */
+       writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_FMT0) &
+               ~RSZ_SRC_FMT0_BYPASS,
+               iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_FMT0);
+
+       /* Select RSZ input */
+       writel((readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_FMT0) &
+               ~RSZ_SRC_FMT0_SEL) |
+               (resizer->input == RESIZER_INPUT_IPIPEIF) ? RSZ_SRC_FMT0_SEL : 0,
+               iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_FMT0);
+
+       /* RSZ ignores WEN signal from IPIPE/IPIPEIF */
+       writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_MODE) &
+               ~RSZ_SRC_MODE_WRT,
+               iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_MODE);
+
+       /* Set Resizer in free-running mode */
+       writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_MODE) &
+               ~RSZ_SRC_MODE_OST,
+               iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_MODE);
+
+       /* Init Resizer A */
+       writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_MODE) &
+               ~RZA_MODE_ONE_SHOT,
+               iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_MODE);
+
+       /* Set size related things now */
+       writel(0, iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_VPS);
+       writel(0, iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_HPS);
+       writel(informat->height - 2, iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_VSZ);
+       writel(informat->width - 1, iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SRC_HSZ);
+
+       writel(0, iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_I_VPS);
+       writel(0, iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_I_HPS);
+
+       writel(outformat->height - 2, iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_O_VSZ);
+       writel(outformat->width - 1, iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_O_HSZ);
+
+       writel(0x100, iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_V_DIF);
+       writel(0x100, iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_H_DIF);
+
+       /* Buffer output settings */
+       writel(0, iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_Y_PTR_S);
+       writel(outformat->height - 1,
+               iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_Y_PTR_E);
+
+       writel(resizer->video_out.bpl_value,
+               iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_Y_OFT);
+
+       /* UYVY -> NV12 conversion */
+       if ((informat->code == V4L2_MBUS_FMT_UYVY8_1X16) &&
+           (outformat->code == V4L2_MBUS_FMT_YUYV8_1_5X8)) {
+               writel(RSZ_420_CEN | RSZ_420_YEN,
+                       iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_420);
+
+               /* UV Buffer output settings */
+               writel(0, iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_C_PTR_S);
+               writel(outformat->height - 1,
+                       iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_C_PTR_E);
+
+               writel(resizer->video_out.bpl_value,
+                       iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_SDR_C_OFT);
+       } else {
+               writel(0,
+                       iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_420);
+       }
+
+       omap4iss_isp_enable_interrupts(iss);
+}
+
+/* -----------------------------------------------------------------------------
+ * Interrupt handling
+ */
+
+static void resizer_isr_buffer(struct iss_resizer_device *resizer)
+{
+       struct iss_device *iss = to_iss_device(resizer);
+       struct iss_buffer *buffer;
+
+       writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_EN) &
+               ~RSZ_EN_EN,
+               iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_EN);
+
+       buffer = omap4iss_video_buffer_next(&resizer->video_out);
+       if (buffer == NULL)
+               return;
+
+       resizer_set_outaddr(resizer, buffer->iss_addr);
+
+       writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_EN) |
+               RSZ_EN_EN,
+               iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RZA_EN);
+}
+
+/*
+ * resizer_isif0_isr - Handle ISIF0 event
+ * @resizer: Pointer to ISP RESIZER device.
+ *
+ * Executes LSC deferred enablement before next frame starts.
+ */
+static void resizer_int_dma_isr(struct iss_resizer_device *resizer)
+{
+       struct iss_pipeline *pipe =
+                            to_iss_pipeline(&resizer->subdev.entity);
+       if (pipe->do_propagation)
+               atomic_inc(&pipe->frame_number);
+
+       resizer_isr_buffer(resizer);
+}
+
+/*
+ * omap4iss_resizer_isr - Configure resizer during interframe time.
+ * @resizer: Pointer to ISP RESIZER device.
+ * @events: RESIZER events
+ */
+void omap4iss_resizer_isr(struct iss_resizer_device *resizer, u32 events)
+{
+       struct iss_device *iss = to_iss_device(resizer);
+       struct iss_pipeline *pipe =
+                            to_iss_pipeline(&resizer->subdev.entity);
+
+       if (events & (ISP5_IRQ_RSZ_FIFO_IN_BLK |
+                     ISP5_IRQ_RSZ_FIFO_OVF)) {
+               dev_dbg(iss->dev, "RSZ Err:"
+                       " FIFO_IN_BLK:%d,"
+                       " FIFO_OVF:%d,"
+                       "\n",
+                       (events &
+                        ISP5_IRQ_RSZ_FIFO_IN_BLK) ? 1 : 0,
+                       (events &
+                        ISP5_IRQ_RSZ_FIFO_OVF) ? 1 : 0);
+               pipe->error = true;
+       }
+
+       if (omap4iss_module_sync_is_stopping(&resizer->wait, &resizer->stopping))
+               return;
+
+       if (events & ISP5_IRQ_RSZ_INT_DMA)
+               resizer_int_dma_isr(resizer);
+}
+
+/* -----------------------------------------------------------------------------
+ * ISS video operations
+ */
+
+static int resizer_video_queue(struct iss_video *video, struct iss_buffer *buffer)
+{
+       struct iss_resizer_device *resizer = container_of(video,
+                               struct iss_resizer_device, video_out);
+
+       if (!(resizer->output & RESIZER_OUTPUT_MEMORY))
+               return -ENODEV;
+
+       resizer_set_outaddr(resizer, buffer->iss_addr);
+
+       /*
+        * If streaming was enabled before there was a buffer queued
+        * or underrun happened in the ISR, the hardware was not enabled
+        * and DMA queue flag ISS_VIDEO_DMAQUEUE_UNDERRUN is still set.
+        * Enable it now.
+        */
+       if (video->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_UNDERRUN) {
+               resizer_enable(resizer, 1);
+               iss_video_dmaqueue_flags_clr(video);
+       }
+
+       return 0;
+}
+
+static const struct iss_video_operations resizer_video_ops = {
+       .queue = resizer_video_queue,
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev operations
+ */
+
+/*
+ * resizer_set_stream - Enable/Disable streaming on the RESIZER module
+ * @sd: ISP RESIZER V4L2 subdevice
+ * @enable: Enable/disable stream
+ */
+static int resizer_set_stream(struct v4l2_subdev *sd, int enable)
+{
+       struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd);
+       struct iss_device *iss = to_iss_device(resizer);
+       struct iss_video *video_out = &resizer->video_out;
+       int ret = 0;
+
+       if (resizer->state == ISS_PIPELINE_STREAM_STOPPED) {
+               if (enable == ISS_PIPELINE_STREAM_STOPPED)
+                       return 0;
+
+               omap4iss_isp_subclk_enable(iss, OMAP4_ISS_ISP_SUBCLK_RSZ);
+
+               writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_GCK_MMR) |
+                       RSZ_GCK_MMR_MMR,
+                       iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_GCK_MMR);
+               writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_GCK_SDR) |
+                       RSZ_GCK_SDR_CORE,
+                       iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_GCK_SDR);
+
+               /* FIXME: Enable RSZB also */
+               writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SYSCONFIG) |
+                       RSZ_SYSCONFIG_RSZA_CLK_EN,
+                       iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SYSCONFIG);
+       }
+
+       switch (enable) {
+       case ISS_PIPELINE_STREAM_CONTINUOUS:
+
+               resizer_configure(resizer);
+               resizer_print_status(resizer);
+
+               /*
+                * When outputting to memory with no buffer available, let the
+                * buffer queue handler start the hardware. A DMA queue flag
+                * ISS_VIDEO_DMAQUEUE_QUEUED will be set as soon as there is
+                * a buffer available.
+                */
+               if (resizer->output & RESIZER_OUTPUT_MEMORY &&
+                   !(video_out->dmaqueue_flags & ISS_VIDEO_DMAQUEUE_QUEUED))
+                       break;
+
+               atomic_set(&resizer->stopping, 0);
+               resizer_enable(resizer, 1);
+               iss_video_dmaqueue_flags_clr(video_out);
+               break;
+
+       case ISS_PIPELINE_STREAM_STOPPED:
+               if (resizer->state == ISS_PIPELINE_STREAM_STOPPED)
+                       return 0;
+               if (omap4iss_module_sync_idle(&sd->entity, &resizer->wait,
+                                             &resizer->stopping))
+                       dev_dbg(iss->dev, "%s: module stop timeout.\n",
+                               sd->name);
+
+               resizer_enable(resizer, 0);
+               omap4iss_isp_disable_interrupts(iss);
+               writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SYSCONFIG) &
+                       ~RSZ_SYSCONFIG_RSZA_CLK_EN,
+                       iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_SYSCONFIG);
+               writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_GCK_SDR) &
+                       ~RSZ_GCK_SDR_CORE,
+                       iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_GCK_SDR);
+               writel(readl(iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_GCK_MMR) &
+                       ~RSZ_GCK_MMR_MMR,
+                       iss->regs[OMAP4_ISS_MEM_ISP_RESIZER] + RSZ_GCK_MMR);
+               omap4iss_isp_subclk_disable(iss, OMAP4_ISS_ISP_SUBCLK_RSZ);
+               iss_video_dmaqueue_flags_clr(video_out);
+               break;
+       }
+
+       resizer->state = enable;
+       return ret;
+}
+
+static struct v4l2_mbus_framefmt *
+__resizer_get_format(struct iss_resizer_device *resizer, struct v4l2_subdev_fh *fh,
+                 unsigned int pad, enum v4l2_subdev_format_whence which)
+{
+       if (which == V4L2_SUBDEV_FORMAT_TRY)
+               return v4l2_subdev_get_try_format(fh, pad);
+       else
+               return &resizer->formats[pad];
+}
+
+/*
+ * resizer_try_format - Try video format on a pad
+ * @resizer: ISS RESIZER device
+ * @fh : V4L2 subdev file handle
+ * @pad: Pad number
+ * @fmt: Format
+ */
+static void
+resizer_try_format(struct iss_resizer_device *resizer, struct v4l2_subdev_fh *fh,
+               unsigned int pad, struct v4l2_mbus_framefmt *fmt,
+               enum v4l2_subdev_format_whence which)
+{
+       enum v4l2_mbus_pixelcode pixelcode;
+       struct v4l2_mbus_framefmt *format;
+       unsigned int width = fmt->width;
+       unsigned int height = fmt->height;
+       unsigned int i;
+
+       switch (pad) {
+       case RESIZER_PAD_SINK:
+               for (i = 0; i < ARRAY_SIZE(resizer_fmts); i++) {
+                       if (fmt->code == resizer_fmts[i])
+                               break;
+               }
+
+               /* If not found, use UYVY as default */
+               if (i >= ARRAY_SIZE(resizer_fmts))
+                       fmt->code = V4L2_MBUS_FMT_UYVY8_1X16;
+
+               /* Clamp the input size. */
+               fmt->width = clamp_t(u32, width, 1, 8192);
+               fmt->height = clamp_t(u32, height, 1, 8192);
+               break;
+
+       case RESIZER_PAD_SOURCE_MEM:
+               pixelcode = fmt->code;
+               format = __resizer_get_format(resizer, fh, RESIZER_PAD_SINK, which);
+               memcpy(fmt, format, sizeof(*fmt));
+
+               if ((pixelcode == V4L2_MBUS_FMT_YUYV8_1_5X8) &&
+                   (fmt->code == V4L2_MBUS_FMT_UYVY8_1X16))
+                       fmt->code = pixelcode;
+
+               /* The data formatter truncates the number of horizontal output
+                * pixels to a multiple of 16. To avoid clipping data, allow
+                * callers to request an output size bigger than the input size
+                * up to the nearest multiple of 16.
+                */
+               fmt->width = clamp_t(u32, width, 32, (fmt->width + 15) & ~15);
+               fmt->width &= ~15;
+               fmt->height = clamp_t(u32, height, 32, fmt->height);
+               break;
+
+       }
+
+       fmt->colorspace = V4L2_COLORSPACE_JPEG;
+       fmt->field = V4L2_FIELD_NONE;
+}
+
+/*
+ * resizer_enum_mbus_code - Handle pixel format enumeration
+ * @sd     : pointer to v4l2 subdev structure
+ * @fh : V4L2 subdev file handle
+ * @code   : pointer to v4l2_subdev_mbus_code_enum structure
+ * return -EINVAL or zero on success
+ */
+static int resizer_enum_mbus_code(struct v4l2_subdev *sd,
+                              struct v4l2_subdev_fh *fh,
+                              struct v4l2_subdev_mbus_code_enum *code)
+{
+       struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd);
+       struct v4l2_mbus_framefmt *format;
+
+       switch (code->pad) {
+       case RESIZER_PAD_SINK:
+               if (code->index >= ARRAY_SIZE(resizer_fmts))
+                       return -EINVAL;
+
+               code->code = resizer_fmts[code->index];
+               break;
+
+       case RESIZER_PAD_SOURCE_MEM:
+               format = __resizer_get_format(resizer, fh, RESIZER_PAD_SINK,
+                                             V4L2_SUBDEV_FORMAT_TRY);
+
+               if (code->index == 0) {
+                       code->code = format->code;
+                       break;
+               }
+
+               switch (format->code) {
+               case V4L2_MBUS_FMT_UYVY8_1X16:
+                       if (code->index == 1)
+                               code->code = V4L2_MBUS_FMT_YUYV8_1_5X8;
+                       else
+                               return -EINVAL;
+                       break;
+               default:
+                       if (code->index != 0)
+                               return -EINVAL;
+               }
+
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int resizer_enum_frame_size(struct v4l2_subdev *sd,
+                               struct v4l2_subdev_fh *fh,
+                               struct v4l2_subdev_frame_size_enum *fse)
+{
+       struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd);
+       struct v4l2_mbus_framefmt format;
+
+       if (fse->index != 0)
+               return -EINVAL;
+
+       format.code = fse->code;
+       format.width = 1;
+       format.height = 1;
+       resizer_try_format(resizer, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
+       fse->min_width = format.width;
+       fse->min_height = format.height;
+
+       if (format.code != fse->code)
+               return -EINVAL;
+
+       format.code = fse->code;
+       format.width = -1;
+       format.height = -1;
+       resizer_try_format(resizer, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
+       fse->max_width = format.width;
+       fse->max_height = format.height;
+
+       return 0;
+}
+
+/*
+ * resizer_get_format - Retrieve the video format on a pad
+ * @sd : ISP RESIZER V4L2 subdevice
+ * @fh : V4L2 subdev file handle
+ * @fmt: Format
+ *
+ * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
+ * to the format type.
+ */
+static int resizer_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                          struct v4l2_subdev_format *fmt)
+{
+       struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd);
+       struct v4l2_mbus_framefmt *format;
+
+       format = __resizer_get_format(resizer, fh, fmt->pad, fmt->which);
+       if (format == NULL)
+               return -EINVAL;
+
+       fmt->format = *format;
+       return 0;
+}
+
+/*
+ * resizer_set_format - Set the video format on a pad
+ * @sd : ISP RESIZER V4L2 subdevice
+ * @fh : V4L2 subdev file handle
+ * @fmt: Format
+ *
+ * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
+ * to the format type.
+ */
+static int resizer_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                             struct v4l2_subdev_format *fmt)
+{
+       struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd);
+       struct v4l2_mbus_framefmt *format;
+
+       format = __resizer_get_format(resizer, fh, fmt->pad, fmt->which);
+       if (format == NULL)
+               return -EINVAL;
+
+       resizer_try_format(resizer, fh, fmt->pad, &fmt->format, fmt->which);
+       *format = fmt->format;
+
+       /* Propagate the format from sink to source */
+       if (fmt->pad == RESIZER_PAD_SINK) {
+               format = __resizer_get_format(resizer, fh, RESIZER_PAD_SOURCE_MEM,
+                                          fmt->which);
+               *format = fmt->format;
+               resizer_try_format(resizer, fh, RESIZER_PAD_SOURCE_MEM, format,
+                               fmt->which);
+       }
+
+       return 0;
+}
+
+static int resizer_link_validate(struct v4l2_subdev *sd, struct media_link *link,
+                                struct v4l2_subdev_format *source_fmt,
+                                struct v4l2_subdev_format *sink_fmt)
+{
+       /* Check if the two ends match */
+       if (source_fmt->format.width != sink_fmt->format.width ||
+           source_fmt->format.height != sink_fmt->format.height)
+               return -EPIPE;
+
+       if (source_fmt->format.code != sink_fmt->format.code)
+               return -EPIPE;
+
+       return 0;
+}
+
+/*
+ * resizer_init_formats - Initialize formats on all pads
+ * @sd: ISP RESIZER V4L2 subdevice
+ * @fh: V4L2 subdev file handle
+ *
+ * Initialize all pad formats with default values. If fh is not NULL, try
+ * formats are initialized on the file handle. Otherwise active formats are
+ * initialized on the device.
+ */
+static int resizer_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+       struct v4l2_subdev_format format;
+
+       memset(&format, 0, sizeof(format));
+       format.pad = RESIZER_PAD_SINK;
+       format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+       format.format.code = V4L2_MBUS_FMT_UYVY8_1X16;
+       format.format.width = 4096;
+       format.format.height = 4096;
+       resizer_set_format(sd, fh, &format);
+
+       return 0;
+}
+
+/* V4L2 subdev video operations */
+static const struct v4l2_subdev_video_ops resizer_v4l2_video_ops = {
+       .s_stream = resizer_set_stream,
+};
+
+/* V4L2 subdev pad operations */
+static const struct v4l2_subdev_pad_ops resizer_v4l2_pad_ops = {
+       .enum_mbus_code = resizer_enum_mbus_code,
+       .enum_frame_size = resizer_enum_frame_size,
+       .get_fmt = resizer_get_format,
+       .set_fmt = resizer_set_format,
+       .link_validate = resizer_link_validate,
+};
+
+/* V4L2 subdev operations */
+static const struct v4l2_subdev_ops resizer_v4l2_ops = {
+       .video = &resizer_v4l2_video_ops,
+       .pad = &resizer_v4l2_pad_ops,
+};
+
+/* V4L2 subdev internal operations */
+static const struct v4l2_subdev_internal_ops resizer_v4l2_internal_ops = {
+       .open = resizer_init_formats,
+};
+
+/* -----------------------------------------------------------------------------
+ * Media entity operations
+ */
+
+/*
+ * resizer_link_setup - Setup RESIZER connections
+ * @entity: RESIZER media entity
+ * @local: Pad at the local end of the link
+ * @remote: Pad at the remote end of the link
+ * @flags: Link flags
+ *
+ * return -EINVAL or zero on success
+ */
+static int resizer_link_setup(struct media_entity *entity,
+                          const struct media_pad *local,
+                          const struct media_pad *remote, u32 flags)
+{
+       struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
+       struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd);
+       struct iss_device *iss = to_iss_device(resizer);
+
+       switch (local->index | media_entity_type(remote->entity)) {
+       case RESIZER_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV:
+               /* Read from IPIPE or IPIPEIF. */
+               if (!(flags & MEDIA_LNK_FL_ENABLED)) {
+                       resizer->input = RESIZER_INPUT_NONE;
+                       break;
+               }
+
+               if (resizer->input != RESIZER_INPUT_NONE)
+                       return -EBUSY;
+
+               if (remote->entity == &iss->ipipeif.subdev.entity)
+                       resizer->input = RESIZER_INPUT_IPIPEIF;
+               else if (remote->entity == &iss->ipipe.subdev.entity)
+                       resizer->input = RESIZER_INPUT_IPIPE;
+
+
+               break;
+
+       case RESIZER_PAD_SOURCE_MEM | MEDIA_ENT_T_DEVNODE:
+               /* Write to memory */
+               if (flags & MEDIA_LNK_FL_ENABLED) {
+                       if (resizer->output & ~RESIZER_OUTPUT_MEMORY)
+                               return -EBUSY;
+                       resizer->output |= RESIZER_OUTPUT_MEMORY;
+               } else {
+                       resizer->output &= ~RESIZER_OUTPUT_MEMORY;
+               }
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/* media operations */
+static const struct media_entity_operations resizer_media_ops = {
+       .link_setup = resizer_link_setup,
+       .link_validate = v4l2_subdev_link_validate,
+};
+
+/*
+ * resizer_init_entities - Initialize V4L2 subdev and media entity
+ * @resizer: ISS ISP RESIZER module
+ *
+ * Return 0 on success and a negative error code on failure.
+ */
+static int resizer_init_entities(struct iss_resizer_device *resizer)
+{
+       struct v4l2_subdev *sd = &resizer->subdev;
+       struct media_pad *pads = resizer->pads;
+       struct media_entity *me = &sd->entity;
+       int ret;
+
+       resizer->input = RESIZER_INPUT_NONE;
+
+       v4l2_subdev_init(sd, &resizer_v4l2_ops);
+       sd->internal_ops = &resizer_v4l2_internal_ops;
+       strlcpy(sd->name, "OMAP4 ISS ISP resizer", sizeof(sd->name));
+       sd->grp_id = 1 << 16;   /* group ID for iss subdevs */
+       v4l2_set_subdevdata(sd, resizer);
+       sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+       pads[RESIZER_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+       pads[RESIZER_PAD_SOURCE_MEM].flags = MEDIA_PAD_FL_SOURCE;
+
+       me->ops = &resizer_media_ops;
+       ret = media_entity_init(me, RESIZER_PADS_NUM, pads, 0);
+       if (ret < 0)
+               return ret;
+
+       resizer_init_formats(sd, NULL);
+
+       resizer->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       resizer->video_out.ops = &resizer_video_ops;
+       resizer->video_out.iss = to_iss_device(resizer);
+       resizer->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 3;
+       resizer->video_out.bpl_alignment = 32;
+       resizer->video_out.bpl_zero_padding = 1;
+       resizer->video_out.bpl_max = 0x1ffe0;
+
+       ret = omap4iss_video_init(&resizer->video_out, "ISP resizer a");
+       if (ret < 0)
+               return ret;
+
+       /* Connect the RESIZER subdev to the video node. */
+       ret = media_entity_create_link(&resizer->subdev.entity, RESIZER_PAD_SOURCE_MEM,
+                       &resizer->video_out.video.entity, 0, 0);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+void omap4iss_resizer_unregister_entities(struct iss_resizer_device *resizer)
+{
+       media_entity_cleanup(&resizer->subdev.entity);
+
+       v4l2_device_unregister_subdev(&resizer->subdev);
+       omap4iss_video_unregister(&resizer->video_out);
+}
+
+int omap4iss_resizer_register_entities(struct iss_resizer_device *resizer,
+       struct v4l2_device *vdev)
+{
+       int ret;
+
+       /* Register the subdev and video node. */
+       ret = v4l2_device_register_subdev(vdev, &resizer->subdev);
+       if (ret < 0)
+               goto error;
+
+       ret = omap4iss_video_register(&resizer->video_out, vdev);
+       if (ret < 0)
+               goto error;
+
+       return 0;
+
+error:
+       omap4iss_resizer_unregister_entities(resizer);
+       return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * ISP RESIZER initialisation and cleanup
+ */
+
+/*
+ * omap4iss_resizer_init - RESIZER module initialization.
+ * @iss: Device pointer specific to the OMAP4 ISS.
+ *
+ * TODO: Get the initialisation values from platform data.
+ *
+ * Return 0 on success or a negative error code otherwise.
+ */
+int omap4iss_resizer_init(struct iss_device *iss)
+{
+       struct iss_resizer_device *resizer = &iss->resizer;
+
+       resizer->state = ISS_PIPELINE_STREAM_STOPPED;
+       init_waitqueue_head(&resizer->wait);
+
+       return resizer_init_entities(resizer);
+}
+
+/*
+ * omap4iss_resizer_cleanup - RESIZER module cleanup.
+ * @iss: Device pointer specific to the OMAP4 ISS.
+ */
+void omap4iss_resizer_cleanup(struct iss_device *iss)
+{
+       /* FIXME: are you sure there's nothing to do? */
+}
diff --git a/drivers/staging/media/omap4iss/iss_resizer.h b/drivers/staging/media/omap4iss/iss_resizer.h
new file mode 100644 (file)
index 0000000..3727498
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * TI OMAP4 ISS V4L2 Driver - ISP RESIZER module
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef OMAP4_ISS_RESIZER_H
+#define OMAP4_ISS_RESIZER_H
+
+#include "iss_video.h"
+
+enum resizer_input_entity {
+       RESIZER_INPUT_NONE,
+       RESIZER_INPUT_IPIPE,
+       RESIZER_INPUT_IPIPEIF
+};
+
+#define RESIZER_OUTPUT_MEMORY          (1 << 0)
+
+/* Sink and source RESIZER pads */
+#define RESIZER_PAD_SINK                       0
+#define RESIZER_PAD_SOURCE_MEM                 1
+#define RESIZER_PADS_NUM                       2
+
+/*
+ * struct iss_resizer_device - Structure for the RESIZER module to store its own
+ *                         information
+ * @subdev: V4L2 subdevice
+ * @pads: Sink and source media entity pads
+ * @formats: Active video formats
+ * @input: Active input
+ * @output: Active outputs
+ * @video_out: Output video node
+ * @error: A hardware error occurred during capture
+ * @state: Streaming state
+ * @wait: Wait queue used to stop the module
+ * @stopping: Stopping state
+ */
+struct iss_resizer_device {
+       struct v4l2_subdev subdev;
+       struct media_pad pads[RESIZER_PADS_NUM];
+       struct v4l2_mbus_framefmt formats[RESIZER_PADS_NUM];
+
+       enum resizer_input_entity input;
+       unsigned int output;
+       struct iss_video video_out;
+       unsigned int error;
+
+       enum iss_pipeline_stream_state state;
+       wait_queue_head_t wait;
+       atomic_t stopping;
+};
+
+struct iss_device;
+
+int omap4iss_resizer_init(struct iss_device *iss);
+void omap4iss_resizer_cleanup(struct iss_device *iss);
+int omap4iss_resizer_register_entities(struct iss_resizer_device *resizer,
+       struct v4l2_device *vdev);
+void omap4iss_resizer_unregister_entities(struct iss_resizer_device *resizer);
+
+int omap4iss_resizer_busy(struct iss_resizer_device *resizer);
+void omap4iss_resizer_isr(struct iss_resizer_device *resizer, u32 events);
+void omap4iss_resizer_restore_context(struct iss_device *iss);
+void omap4iss_resizer_max_rate(struct iss_resizer_device *resizer,
+       unsigned int *max_rate);
+
+#endif /* OMAP4_ISS_RESIZER_H */
diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c
new file mode 100644 (file)
index 0000000..766491e
--- /dev/null
@@ -0,0 +1,1128 @@
+/*
+ * TI OMAP4 ISS V4L2 Driver - Generic video node
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <asm/cacheflush.h>
+#include <linux/clk.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/module.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-ioctl.h>
+
+#include "iss_video.h"
+#include "iss.h"
+
+
+/* -----------------------------------------------------------------------------
+ * Helper functions
+ */
+
+static struct iss_format_info formats[] = {
+       { V4L2_MBUS_FMT_Y8_1X8, V4L2_MBUS_FMT_Y8_1X8,
+         V4L2_MBUS_FMT_Y8_1X8, V4L2_MBUS_FMT_Y8_1X8,
+         V4L2_PIX_FMT_GREY, 8, },
+       { V4L2_MBUS_FMT_Y10_1X10, V4L2_MBUS_FMT_Y10_1X10,
+         V4L2_MBUS_FMT_Y10_1X10, V4L2_MBUS_FMT_Y8_1X8,
+         V4L2_PIX_FMT_Y10, 10, },
+       { V4L2_MBUS_FMT_Y12_1X12, V4L2_MBUS_FMT_Y10_1X10,
+         V4L2_MBUS_FMT_Y12_1X12, V4L2_MBUS_FMT_Y8_1X8,
+         V4L2_PIX_FMT_Y12, 12, },
+       { V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_MBUS_FMT_SBGGR8_1X8,
+         V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_MBUS_FMT_SBGGR8_1X8,
+         V4L2_PIX_FMT_SBGGR8, 8, },
+       { V4L2_MBUS_FMT_SGBRG8_1X8, V4L2_MBUS_FMT_SGBRG8_1X8,
+         V4L2_MBUS_FMT_SGBRG8_1X8, V4L2_MBUS_FMT_SGBRG8_1X8,
+         V4L2_PIX_FMT_SGBRG8, 8, },
+       { V4L2_MBUS_FMT_SGRBG8_1X8, V4L2_MBUS_FMT_SGRBG8_1X8,
+         V4L2_MBUS_FMT_SGRBG8_1X8, V4L2_MBUS_FMT_SGRBG8_1X8,
+         V4L2_PIX_FMT_SGRBG8, 8, },
+       { V4L2_MBUS_FMT_SRGGB8_1X8, V4L2_MBUS_FMT_SRGGB8_1X8,
+         V4L2_MBUS_FMT_SRGGB8_1X8, V4L2_MBUS_FMT_SRGGB8_1X8,
+         V4L2_PIX_FMT_SRGGB8, 8, },
+       { V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8, V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
+         V4L2_MBUS_FMT_SGRBG10_1X10, 0,
+         V4L2_PIX_FMT_SGRBG10DPCM8, 8, },
+       { V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR10_1X10,
+         V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR8_1X8,
+         V4L2_PIX_FMT_SBGGR10, 10, },
+       { V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG10_1X10,
+         V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG8_1X8,
+         V4L2_PIX_FMT_SGBRG10, 10, },
+       { V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG10_1X10,
+         V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG8_1X8,
+         V4L2_PIX_FMT_SGRBG10, 10, },
+       { V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB10_1X10,
+         V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB8_1X8,
+         V4L2_PIX_FMT_SRGGB10, 10, },
+       { V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SBGGR10_1X10,
+         V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SBGGR8_1X8,
+         V4L2_PIX_FMT_SBGGR12, 12, },
+       { V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_MBUS_FMT_SGBRG10_1X10,
+         V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_MBUS_FMT_SGBRG8_1X8,
+         V4L2_PIX_FMT_SGBRG12, 12, },
+       { V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_MBUS_FMT_SGRBG10_1X10,
+         V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_MBUS_FMT_SGRBG8_1X8,
+         V4L2_PIX_FMT_SGRBG12, 12, },
+       { V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SRGGB10_1X10,
+         V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SRGGB8_1X8,
+         V4L2_PIX_FMT_SRGGB12, 12, },
+       { V4L2_MBUS_FMT_UYVY8_1X16, V4L2_MBUS_FMT_UYVY8_1X16,
+         V4L2_MBUS_FMT_UYVY8_1X16, 0,
+         V4L2_PIX_FMT_UYVY, 16, },
+       { V4L2_MBUS_FMT_YUYV8_1X16, V4L2_MBUS_FMT_YUYV8_1X16,
+         V4L2_MBUS_FMT_YUYV8_1X16, 0,
+         V4L2_PIX_FMT_YUYV, 16, },
+       { V4L2_MBUS_FMT_YUYV8_1_5X8, V4L2_MBUS_FMT_YUYV8_1_5X8,
+         V4L2_MBUS_FMT_YUYV8_1_5X8, 0,
+         V4L2_PIX_FMT_NV12, 8, },
+};
+
+const struct iss_format_info *
+omap4iss_video_format_info(enum v4l2_mbus_pixelcode code)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(formats); ++i) {
+               if (formats[i].code == code)
+                       return &formats[i];
+       }
+
+       return NULL;
+}
+
+/*
+ * iss_video_mbus_to_pix - Convert v4l2_mbus_framefmt to v4l2_pix_format
+ * @video: ISS video instance
+ * @mbus: v4l2_mbus_framefmt format (input)
+ * @pix: v4l2_pix_format format (output)
+ *
+ * Fill the output pix structure with information from the input mbus format.
+ * The bytesperline and sizeimage fields are computed from the requested bytes
+ * per line value in the pix format and information from the video instance.
+ *
+ * Return the number of padding bytes at end of line.
+ */
+static unsigned int iss_video_mbus_to_pix(const struct iss_video *video,
+                                         const struct v4l2_mbus_framefmt *mbus,
+                                         struct v4l2_pix_format *pix)
+{
+       unsigned int bpl = pix->bytesperline;
+       unsigned int min_bpl;
+       unsigned int i;
+
+       memset(pix, 0, sizeof(*pix));
+       pix->width = mbus->width;
+       pix->height = mbus->height;
+
+       /* Skip the last format in the loop so that it will be selected if no
+        * match is found.
+        */
+       for (i = 0; i < ARRAY_SIZE(formats) - 1; ++i) {
+               if (formats[i].code == mbus->code)
+                       break;
+       }
+
+       min_bpl = pix->width * ALIGN(formats[i].bpp, 8) / 8;
+
+       /* Clamp the requested bytes per line value. If the maximum bytes per
+        * line value is zero, the module doesn't support user configurable line
+        * sizes. Override the requested value with the minimum in that case.
+        */
+       if (video->bpl_max)
+               bpl = clamp(bpl, min_bpl, video->bpl_max);
+       else
+               bpl = min_bpl;
+
+       if (!video->bpl_zero_padding || bpl != min_bpl)
+               bpl = ALIGN(bpl, video->bpl_alignment);
+
+       pix->pixelformat = formats[i].pixelformat;
+       pix->bytesperline = bpl;
+       pix->sizeimage = pix->bytesperline * pix->height;
+       pix->colorspace = mbus->colorspace;
+       pix->field = mbus->field;
+
+       /* FIXME: Special case for NV12! We should make this nicer... */
+       if (pix->pixelformat == V4L2_PIX_FMT_NV12)
+               pix->sizeimage += (pix->bytesperline * pix->height) / 2;
+
+       return bpl - min_bpl;
+}
+
+static void iss_video_pix_to_mbus(const struct v4l2_pix_format *pix,
+                                 struct v4l2_mbus_framefmt *mbus)
+{
+       unsigned int i;
+
+       memset(mbus, 0, sizeof(*mbus));
+       mbus->width = pix->width;
+       mbus->height = pix->height;
+
+       for (i = 0; i < ARRAY_SIZE(formats); ++i) {
+               if (formats[i].pixelformat == pix->pixelformat)
+                       break;
+       }
+
+       if (WARN_ON(i == ARRAY_SIZE(formats)))
+               return;
+
+       mbus->code = formats[i].code;
+       mbus->colorspace = pix->colorspace;
+       mbus->field = pix->field;
+}
+
+static struct v4l2_subdev *
+iss_video_remote_subdev(struct iss_video *video, u32 *pad)
+{
+       struct media_pad *remote;
+
+       remote = media_entity_remote_pad(&video->pad);
+
+       if (remote == NULL ||
+           media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+               return NULL;
+
+       if (pad)
+               *pad = remote->index;
+
+       return media_entity_to_v4l2_subdev(remote->entity);
+}
+
+/* Return a pointer to the ISS video instance at the far end of the pipeline. */
+static struct iss_video *
+iss_video_far_end(struct iss_video *video)
+{
+       struct media_entity_graph graph;
+       struct media_entity *entity = &video->video.entity;
+       struct media_device *mdev = entity->parent;
+       struct iss_video *far_end = NULL;
+
+       mutex_lock(&mdev->graph_mutex);
+       media_entity_graph_walk_start(&graph, entity);
+
+       while ((entity = media_entity_graph_walk_next(&graph))) {
+               if (entity == &video->video.entity)
+                       continue;
+
+               if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+                       continue;
+
+               far_end = to_iss_video(media_entity_to_video_device(entity));
+               if (far_end->type != video->type)
+                       break;
+
+               far_end = NULL;
+       }
+
+       mutex_unlock(&mdev->graph_mutex);
+       return far_end;
+}
+
+static int
+__iss_video_get_format(struct iss_video *video, struct v4l2_format *format)
+{
+       struct v4l2_subdev_format fmt;
+       struct v4l2_subdev *subdev;
+       u32 pad;
+       int ret;
+
+       subdev = iss_video_remote_subdev(video, &pad);
+       if (subdev == NULL)
+               return -EINVAL;
+
+       fmt.pad = pad;
+       fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+
+       mutex_lock(&video->mutex);
+       ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
+       mutex_unlock(&video->mutex);
+
+       if (ret)
+               return ret;
+
+       format->type = video->type;
+       return iss_video_mbus_to_pix(video, &fmt.format, &format->fmt.pix);
+}
+
+static int
+iss_video_check_format(struct iss_video *video, struct iss_video_fh *vfh)
+{
+       struct v4l2_format format;
+       int ret;
+
+       memcpy(&format, &vfh->format, sizeof(format));
+       ret = __iss_video_get_format(video, &format);
+       if (ret < 0)
+               return ret;
+
+       if (vfh->format.fmt.pix.pixelformat != format.fmt.pix.pixelformat ||
+           vfh->format.fmt.pix.height != format.fmt.pix.height ||
+           vfh->format.fmt.pix.width != format.fmt.pix.width ||
+           vfh->format.fmt.pix.bytesperline != format.fmt.pix.bytesperline ||
+           vfh->format.fmt.pix.sizeimage != format.fmt.pix.sizeimage)
+               return -EINVAL;
+
+       return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * Video queue operations
+ */
+
+static int iss_video_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+                                unsigned int *count, unsigned int *num_planes,
+                                unsigned int sizes[], void *alloc_ctxs[])
+{
+       struct iss_video_fh *vfh = vb2_get_drv_priv(vq);
+       struct iss_video *video = vfh->video;
+
+       /* Revisit multi-planar support for NV12 */
+       *num_planes = 1;
+
+       sizes[0] = vfh->format.fmt.pix.sizeimage;
+       if (sizes[0] == 0)
+               return -EINVAL;
+
+       alloc_ctxs[0] = video->alloc_ctx;
+
+       *count = min(*count, (unsigned int)(video->capture_mem / PAGE_ALIGN(sizes[0])));
+
+       return 0;
+}
+
+static void iss_video_buf_cleanup(struct vb2_buffer *vb)
+{
+       struct iss_buffer *buffer = container_of(vb, struct iss_buffer, vb);
+
+       if (buffer->iss_addr)
+               buffer->iss_addr = 0;
+}
+
+static int iss_video_buf_prepare(struct vb2_buffer *vb)
+{
+       struct iss_video_fh *vfh = vb2_get_drv_priv(vb->vb2_queue);
+       struct iss_buffer *buffer = container_of(vb, struct iss_buffer, vb);
+       struct iss_video *video = vfh->video;
+       unsigned long size = vfh->format.fmt.pix.sizeimage;
+       dma_addr_t addr;
+
+       if (vb2_plane_size(vb, 0) < size)
+               return -ENOBUFS;
+
+       addr = vb2_dma_contig_plane_dma_addr(vb, 0);
+       if (!IS_ALIGNED(addr, 32)) {
+               dev_dbg(video->iss->dev, "Buffer address must be "
+                       "aligned to 32 bytes boundary.\n");
+               return -EINVAL;
+       }
+
+       vb2_set_plane_payload(vb, 0, size);
+       buffer->iss_addr = addr;
+       return 0;
+}
+
+static void iss_video_buf_queue(struct vb2_buffer *vb)
+{
+       struct iss_video_fh *vfh = vb2_get_drv_priv(vb->vb2_queue);
+       struct iss_video *video = vfh->video;
+       struct iss_buffer *buffer = container_of(vb, struct iss_buffer, vb);
+       struct iss_pipeline *pipe = to_iss_pipeline(&video->video.entity);
+       unsigned int empty;
+       unsigned long flags;
+
+       spin_lock_irqsave(&video->qlock, flags);
+       empty = list_empty(&video->dmaqueue);
+       list_add_tail(&buffer->list, &video->dmaqueue);
+       spin_unlock_irqrestore(&video->qlock, flags);
+
+       if (empty) {
+               enum iss_pipeline_state state;
+               unsigned int start;
+
+               if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+                       state = ISS_PIPELINE_QUEUE_OUTPUT;
+               else
+                       state = ISS_PIPELINE_QUEUE_INPUT;
+
+               spin_lock_irqsave(&pipe->lock, flags);
+               pipe->state |= state;
+               video->ops->queue(video, buffer);
+               video->dmaqueue_flags |= ISS_VIDEO_DMAQUEUE_QUEUED;
+
+               start = iss_pipeline_ready(pipe);
+               if (start)
+                       pipe->state |= ISS_PIPELINE_STREAM;
+               spin_unlock_irqrestore(&pipe->lock, flags);
+
+               if (start)
+                       omap4iss_pipeline_set_stream(pipe,
+                                               ISS_PIPELINE_STREAM_SINGLESHOT);
+       }
+}
+
+static struct vb2_ops iss_video_vb2ops = {
+       .queue_setup    = iss_video_queue_setup,
+       .buf_prepare    = iss_video_buf_prepare,
+       .buf_queue      = iss_video_buf_queue,
+       .buf_cleanup    = iss_video_buf_cleanup,
+};
+
+/*
+ * omap4iss_video_buffer_next - Complete the current buffer and return the next
+ * @video: ISS video object
+ *
+ * Remove the current video buffer from the DMA queue and fill its timestamp,
+ * field count and state fields before waking up its completion handler.
+ *
+ * For capture video nodes, the buffer state is set to VB2_BUF_STATE_DONE if no
+ * error has been flagged in the pipeline, or to VB2_BUF_STATE_ERROR otherwise.
+ *
+ * The DMA queue is expected to contain at least one buffer.
+ *
+ * Return a pointer to the next buffer in the DMA queue, or NULL if the queue is
+ * empty.
+ */
+struct iss_buffer *omap4iss_video_buffer_next(struct iss_video *video)
+{
+       struct iss_pipeline *pipe = to_iss_pipeline(&video->video.entity);
+       enum iss_pipeline_state state;
+       struct iss_buffer *buf;
+       unsigned long flags;
+       struct timespec ts;
+
+       spin_lock_irqsave(&video->qlock, flags);
+       if (WARN_ON(list_empty(&video->dmaqueue))) {
+               spin_unlock_irqrestore(&video->qlock, flags);
+               return NULL;
+       }
+
+       buf = list_first_entry(&video->dmaqueue, struct iss_buffer,
+                              list);
+       list_del(&buf->list);
+       spin_unlock_irqrestore(&video->qlock, flags);
+
+       ktime_get_ts(&ts);
+       buf->vb.v4l2_buf.timestamp.tv_sec = ts.tv_sec;
+       buf->vb.v4l2_buf.timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
+
+       /* Do frame number propagation only if this is the output video node.
+        * Frame number either comes from the CSI receivers or it gets
+        * incremented here if H3A is not active.
+        * Note: There is no guarantee that the output buffer will finish
+        * first, so the input number might lag behind by 1 in some cases.
+        */
+       if (video == pipe->output && !pipe->do_propagation)
+               buf->vb.v4l2_buf.sequence = atomic_inc_return(&pipe->frame_number);
+       else
+               buf->vb.v4l2_buf.sequence = atomic_read(&pipe->frame_number);
+
+       vb2_buffer_done(&buf->vb, pipe->error ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
+       pipe->error = false;
+
+       spin_lock_irqsave(&video->qlock, flags);
+       if (list_empty(&video->dmaqueue)) {
+               spin_unlock_irqrestore(&video->qlock, flags);
+               if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+                       state = ISS_PIPELINE_QUEUE_OUTPUT
+                             | ISS_PIPELINE_STREAM;
+               else
+                       state = ISS_PIPELINE_QUEUE_INPUT
+                             | ISS_PIPELINE_STREAM;
+
+               spin_lock_irqsave(&pipe->lock, flags);
+               pipe->state &= ~state;
+               if (video->pipe.stream_state == ISS_PIPELINE_STREAM_CONTINUOUS)
+                       video->dmaqueue_flags |= ISS_VIDEO_DMAQUEUE_UNDERRUN;
+               spin_unlock_irqrestore(&pipe->lock, flags);
+               return NULL;
+       }
+
+       if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && pipe->input != NULL) {
+               spin_lock_irqsave(&pipe->lock, flags);
+               pipe->state &= ~ISS_PIPELINE_STREAM;
+               spin_unlock_irqrestore(&pipe->lock, flags);
+       }
+
+       buf = list_first_entry(&video->dmaqueue, struct iss_buffer,
+                              list);
+       spin_unlock_irqrestore(&video->qlock, flags);
+       buf->vb.state = VB2_BUF_STATE_ACTIVE;
+       return buf;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 ioctls
+ */
+
+static int
+iss_video_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
+{
+       struct iss_video *video = video_drvdata(file);
+
+       strlcpy(cap->driver, ISS_VIDEO_DRIVER_NAME, sizeof(cap->driver));
+       strlcpy(cap->card, video->video.name, sizeof(cap->card));
+       strlcpy(cap->bus_info, "media", sizeof(cap->bus_info));
+
+       if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+       else
+               cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
+
+       cap->capabilities = V4L2_CAP_DEVICE_CAPS | V4L2_CAP_STREAMING
+                         | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT;
+
+       return 0;
+}
+
+static int
+iss_video_get_format(struct file *file, void *fh, struct v4l2_format *format)
+{
+       struct iss_video_fh *vfh = to_iss_video_fh(fh);
+       struct iss_video *video = video_drvdata(file);
+
+       if (format->type != video->type)
+               return -EINVAL;
+
+       mutex_lock(&video->mutex);
+       *format = vfh->format;
+       mutex_unlock(&video->mutex);
+
+       return 0;
+}
+
+static int
+iss_video_set_format(struct file *file, void *fh, struct v4l2_format *format)
+{
+       struct iss_video_fh *vfh = to_iss_video_fh(fh);
+       struct iss_video *video = video_drvdata(file);
+       struct v4l2_mbus_framefmt fmt;
+
+       if (format->type != video->type)
+               return -EINVAL;
+
+       mutex_lock(&video->mutex);
+
+       /* Fill the bytesperline and sizeimage fields by converting to media bus
+        * format and back to pixel format.
+        */
+       iss_video_pix_to_mbus(&format->fmt.pix, &fmt);
+       iss_video_mbus_to_pix(video, &fmt, &format->fmt.pix);
+
+       vfh->format = *format;
+
+       mutex_unlock(&video->mutex);
+       return 0;
+}
+
+static int
+iss_video_try_format(struct file *file, void *fh, struct v4l2_format *format)
+{
+       struct iss_video *video = video_drvdata(file);
+       struct v4l2_subdev_format fmt;
+       struct v4l2_subdev *subdev;
+       u32 pad;
+       int ret;
+
+       if (format->type != video->type)
+               return -EINVAL;
+
+       subdev = iss_video_remote_subdev(video, &pad);
+       if (subdev == NULL)
+               return -EINVAL;
+
+       iss_video_pix_to_mbus(&format->fmt.pix, &fmt.format);
+
+       fmt.pad = pad;
+       fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+       ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
+       if (ret)
+               return ret;
+
+       iss_video_mbus_to_pix(video, &fmt.format, &format->fmt.pix);
+       return 0;
+}
+
+static int
+iss_video_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cropcap)
+{
+       struct iss_video *video = video_drvdata(file);
+       struct v4l2_subdev *subdev;
+       int ret;
+
+       subdev = iss_video_remote_subdev(video, NULL);
+       if (subdev == NULL)
+               return -EINVAL;
+
+       mutex_lock(&video->mutex);
+       ret = v4l2_subdev_call(subdev, video, cropcap, cropcap);
+       mutex_unlock(&video->mutex);
+
+       return ret == -ENOIOCTLCMD ? -ENOTTY : ret;
+}
+
+static int
+iss_video_get_crop(struct file *file, void *fh, struct v4l2_crop *crop)
+{
+       struct iss_video *video = video_drvdata(file);
+       struct v4l2_subdev_format format;
+       struct v4l2_subdev *subdev;
+       u32 pad;
+       int ret;
+
+       subdev = iss_video_remote_subdev(video, &pad);
+       if (subdev == NULL)
+               return -EINVAL;
+
+       /* Try the get crop operation first and fallback to get format if not
+        * implemented.
+        */
+       ret = v4l2_subdev_call(subdev, video, g_crop, crop);
+       if (ret != -ENOIOCTLCMD)
+               return ret;
+
+       format.pad = pad;
+       format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+       ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &format);
+       if (ret < 0)
+               return ret == -ENOIOCTLCMD ? -ENOTTY : ret;
+
+       crop->c.left = 0;
+       crop->c.top = 0;
+       crop->c.width = format.format.width;
+       crop->c.height = format.format.height;
+
+       return 0;
+}
+
+static int
+iss_video_set_crop(struct file *file, void *fh, const struct v4l2_crop *crop)
+{
+       struct iss_video *video = video_drvdata(file);
+       struct v4l2_subdev *subdev;
+       int ret;
+
+       subdev = iss_video_remote_subdev(video, NULL);
+       if (subdev == NULL)
+               return -EINVAL;
+
+       mutex_lock(&video->mutex);
+       ret = v4l2_subdev_call(subdev, video, s_crop, crop);
+       mutex_unlock(&video->mutex);
+
+       return ret == -ENOIOCTLCMD ? -ENOTTY : ret;
+}
+
+static int
+iss_video_get_param(struct file *file, void *fh, struct v4l2_streamparm *a)
+{
+       struct iss_video_fh *vfh = to_iss_video_fh(fh);
+       struct iss_video *video = video_drvdata(file);
+
+       if (video->type != V4L2_BUF_TYPE_VIDEO_OUTPUT ||
+           video->type != a->type)
+               return -EINVAL;
+
+       memset(a, 0, sizeof(*a));
+       a->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+       a->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
+       a->parm.output.timeperframe = vfh->timeperframe;
+
+       return 0;
+}
+
+static int
+iss_video_set_param(struct file *file, void *fh, struct v4l2_streamparm *a)
+{
+       struct iss_video_fh *vfh = to_iss_video_fh(fh);
+       struct iss_video *video = video_drvdata(file);
+
+       if (video->type != V4L2_BUF_TYPE_VIDEO_OUTPUT ||
+           video->type != a->type)
+               return -EINVAL;
+
+       if (a->parm.output.timeperframe.denominator == 0)
+               a->parm.output.timeperframe.denominator = 1;
+
+       vfh->timeperframe = a->parm.output.timeperframe;
+
+       return 0;
+}
+
+static int
+iss_video_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *rb)
+{
+       struct iss_video_fh *vfh = to_iss_video_fh(fh);
+
+       return vb2_reqbufs(&vfh->queue, rb);
+}
+
+static int
+iss_video_querybuf(struct file *file, void *fh, struct v4l2_buffer *b)
+{
+       struct iss_video_fh *vfh = to_iss_video_fh(fh);
+
+       return vb2_querybuf(&vfh->queue, b);
+}
+
+static int
+iss_video_qbuf(struct file *file, void *fh, struct v4l2_buffer *b)
+{
+       struct iss_video_fh *vfh = to_iss_video_fh(fh);
+
+       return vb2_qbuf(&vfh->queue, b);
+}
+
+static int
+iss_video_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
+{
+       struct iss_video_fh *vfh = to_iss_video_fh(fh);
+
+       return vb2_dqbuf(&vfh->queue, b, file->f_flags & O_NONBLOCK);
+}
+
+/*
+ * Stream management
+ *
+ * Every ISS pipeline has a single input and a single output. The input can be
+ * either a sensor or a video node. The output is always a video node.
+ *
+ * As every pipeline has an output video node, the ISS video objects at the
+ * pipeline output stores the pipeline state. It tracks the streaming state of
+ * both the input and output, as well as the availability of buffers.
+ *
+ * In sensor-to-memory mode, frames are always available at the pipeline input.
+ * Starting the sensor usually requires I2C transfers and must be done in
+ * interruptible context. The pipeline is started and stopped synchronously
+ * to the stream on/off commands. All modules in the pipeline will get their
+ * subdev set stream handler called. The module at the end of the pipeline must
+ * delay starting the hardware until buffers are available at its output.
+ *
+ * In memory-to-memory mode, starting/stopping the stream requires
+ * synchronization between the input and output. ISS modules can't be stopped
+ * in the middle of a frame, and at least some of the modules seem to become
+ * busy as soon as they're started, even if they don't receive a frame start
+ * event. For that reason frames need to be processed in single-shot mode. The
+ * driver needs to wait until a frame is completely processed and written to
+ * memory before restarting the pipeline for the next frame. Pipelined
+ * processing might be possible but requires more testing.
+ *
+ * Stream start must be delayed until buffers are available at both the input
+ * and output. The pipeline must be started in the videobuf queue callback with
+ * the buffers queue spinlock held. The modules subdev set stream operation must
+ * not sleep.
+ */
+static int
+iss_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
+{
+       struct iss_video_fh *vfh = to_iss_video_fh(fh);
+       struct iss_video *video = video_drvdata(file);
+       enum iss_pipeline_state state;
+       struct iss_pipeline *pipe;
+       struct iss_video *far_end;
+       unsigned long flags;
+       int ret;
+
+       if (type != video->type)
+               return -EINVAL;
+
+       mutex_lock(&video->stream_lock);
+
+       /* Start streaming on the pipeline. No link touching an entity in the
+        * pipeline can be activated or deactivated once streaming is started.
+        */
+       pipe = video->video.entity.pipe
+            ? to_iss_pipeline(&video->video.entity) : &video->pipe;
+       pipe->external = NULL;
+       pipe->external_rate = 0;
+       pipe->external_bpp = 0;
+
+       if (video->iss->pdata->set_constraints)
+               video->iss->pdata->set_constraints(video->iss, true);
+
+       ret = media_entity_pipeline_start(&video->video.entity, &pipe->pipe);
+       if (ret < 0)
+               goto err_media_entity_pipeline_start;
+
+       /* Verify that the currently configured format matches the output of
+        * the connected subdev.
+        */
+       ret = iss_video_check_format(video, vfh);
+       if (ret < 0)
+               goto err_iss_video_check_format;
+
+       video->bpl_padding = ret;
+       video->bpl_value = vfh->format.fmt.pix.bytesperline;
+
+       /* Find the ISS video node connected at the far end of the pipeline and
+        * update the pipeline.
+        */
+       far_end = iss_video_far_end(video);
+
+       if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               state = ISS_PIPELINE_STREAM_OUTPUT | ISS_PIPELINE_IDLE_OUTPUT;
+               pipe->input = far_end;
+               pipe->output = video;
+       } else {
+               if (far_end == NULL) {
+                       ret = -EPIPE;
+                       goto err_iss_video_check_format;
+               }
+
+               state = ISS_PIPELINE_STREAM_INPUT | ISS_PIPELINE_IDLE_INPUT;
+               pipe->input = video;
+               pipe->output = far_end;
+       }
+
+       spin_lock_irqsave(&pipe->lock, flags);
+       pipe->state &= ~ISS_PIPELINE_STREAM;
+       pipe->state |= state;
+       spin_unlock_irqrestore(&pipe->lock, flags);
+
+       /* Set the maximum time per frame as the value requested by userspace.
+        * This is a soft limit that can be overridden if the hardware doesn't
+        * support the request limit.
+        */
+       if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+               pipe->max_timeperframe = vfh->timeperframe;
+
+       video->queue = &vfh->queue;
+       INIT_LIST_HEAD(&video->dmaqueue);
+       spin_lock_init(&video->qlock);
+       atomic_set(&pipe->frame_number, -1);
+
+       ret = vb2_streamon(&vfh->queue, type);
+       if (ret < 0)
+               goto err_iss_video_check_format;
+
+       /* In sensor-to-memory mode, the stream can be started synchronously
+        * to the stream on command. In memory-to-memory mode, it will be
+        * started when buffers are queued on both the input and output.
+        */
+       if (pipe->input == NULL) {
+               unsigned long flags;
+               ret = omap4iss_pipeline_set_stream(pipe,
+                                             ISS_PIPELINE_STREAM_CONTINUOUS);
+               if (ret < 0)
+                       goto err_omap4iss_set_stream;
+               spin_lock_irqsave(&video->qlock, flags);
+               if (list_empty(&video->dmaqueue))
+                       video->dmaqueue_flags |= ISS_VIDEO_DMAQUEUE_UNDERRUN;
+               spin_unlock_irqrestore(&video->qlock, flags);
+       }
+
+       mutex_unlock(&video->stream_lock);
+       return 0;
+
+err_omap4iss_set_stream:
+       vb2_streamoff(&vfh->queue, type);
+err_iss_video_check_format:
+       media_entity_pipeline_stop(&video->video.entity);
+err_media_entity_pipeline_start:
+       if (video->iss->pdata->set_constraints)
+               video->iss->pdata->set_constraints(video->iss, false);
+       video->queue = NULL;
+
+       mutex_unlock(&video->stream_lock);
+       return ret;
+}
+
+static int
+iss_video_streamoff(struct file *file, void *fh, enum v4l2_buf_type type)
+{
+       struct iss_video_fh *vfh = to_iss_video_fh(fh);
+       struct iss_video *video = video_drvdata(file);
+       struct iss_pipeline *pipe = to_iss_pipeline(&video->video.entity);
+       enum iss_pipeline_state state;
+       unsigned long flags;
+
+       if (type != video->type)
+               return -EINVAL;
+
+       mutex_lock(&video->stream_lock);
+
+       if (!vb2_is_streaming(&vfh->queue))
+               goto done;
+
+       /* Update the pipeline state. */
+       if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               state = ISS_PIPELINE_STREAM_OUTPUT
+                     | ISS_PIPELINE_QUEUE_OUTPUT;
+       else
+               state = ISS_PIPELINE_STREAM_INPUT
+                     | ISS_PIPELINE_QUEUE_INPUT;
+
+       spin_lock_irqsave(&pipe->lock, flags);
+       pipe->state &= ~state;
+       spin_unlock_irqrestore(&pipe->lock, flags);
+
+       /* Stop the stream. */
+       omap4iss_pipeline_set_stream(pipe, ISS_PIPELINE_STREAM_STOPPED);
+       vb2_streamoff(&vfh->queue, type);
+       video->queue = NULL;
+
+       if (video->iss->pdata->set_constraints)
+               video->iss->pdata->set_constraints(video->iss, false);
+       media_entity_pipeline_stop(&video->video.entity);
+
+done:
+       mutex_unlock(&video->stream_lock);
+       return 0;
+}
+
+static int
+iss_video_enum_input(struct file *file, void *fh, struct v4l2_input *input)
+{
+       if (input->index > 0)
+               return -EINVAL;
+
+       strlcpy(input->name, "camera", sizeof(input->name));
+       input->type = V4L2_INPUT_TYPE_CAMERA;
+
+       return 0;
+}
+
+static int
+iss_video_g_input(struct file *file, void *fh, unsigned int *input)
+{
+       *input = 0;
+
+       return 0;
+}
+
+static int
+iss_video_s_input(struct file *file, void *fh, unsigned int input)
+{
+       return input == 0 ? 0 : -EINVAL;
+}
+
+static const struct v4l2_ioctl_ops iss_video_ioctl_ops = {
+       .vidioc_querycap                = iss_video_querycap,
+       .vidioc_g_fmt_vid_cap           = iss_video_get_format,
+       .vidioc_s_fmt_vid_cap           = iss_video_set_format,
+       .vidioc_try_fmt_vid_cap         = iss_video_try_format,
+       .vidioc_g_fmt_vid_out           = iss_video_get_format,
+       .vidioc_s_fmt_vid_out           = iss_video_set_format,
+       .vidioc_try_fmt_vid_out         = iss_video_try_format,
+       .vidioc_cropcap                 = iss_video_cropcap,
+       .vidioc_g_crop                  = iss_video_get_crop,
+       .vidioc_s_crop                  = iss_video_set_crop,
+       .vidioc_g_parm                  = iss_video_get_param,
+       .vidioc_s_parm                  = iss_video_set_param,
+       .vidioc_reqbufs                 = iss_video_reqbufs,
+       .vidioc_querybuf                = iss_video_querybuf,
+       .vidioc_qbuf                    = iss_video_qbuf,
+       .vidioc_dqbuf                   = iss_video_dqbuf,
+       .vidioc_streamon                = iss_video_streamon,
+       .vidioc_streamoff               = iss_video_streamoff,
+       .vidioc_enum_input              = iss_video_enum_input,
+       .vidioc_g_input                 = iss_video_g_input,
+       .vidioc_s_input                 = iss_video_s_input,
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 file operations
+ */
+
+static int iss_video_open(struct file *file)
+{
+       struct iss_video *video = video_drvdata(file);
+       struct iss_video_fh *handle;
+       struct vb2_queue *q;
+       int ret = 0;
+
+       handle = kzalloc(sizeof(*handle), GFP_KERNEL);
+       if (handle == NULL)
+               return -ENOMEM;
+
+       v4l2_fh_init(&handle->vfh, &video->video);
+       v4l2_fh_add(&handle->vfh);
+
+       /* If this is the first user, initialise the pipeline. */
+       if (omap4iss_get(video->iss) == NULL) {
+               ret = -EBUSY;
+               goto done;
+       }
+
+       ret = omap4iss_pipeline_pm_use(&video->video.entity, 1);
+       if (ret < 0) {
+               omap4iss_put(video->iss);
+               goto done;
+       }
+
+       video->alloc_ctx = vb2_dma_contig_init_ctx(video->iss->dev);
+       if (IS_ERR(video->alloc_ctx)) {
+               ret = PTR_ERR(video->alloc_ctx);
+               omap4iss_put(video->iss);
+               goto done;
+       }
+
+       q = &handle->queue;
+
+       q->type = video->type;
+       q->io_modes = VB2_MMAP;
+       q->drv_priv = handle;
+       q->ops = &iss_video_vb2ops;
+       q->mem_ops = &vb2_dma_contig_memops;
+       q->buf_struct_size = sizeof(struct iss_buffer);
+       q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+
+       ret = vb2_queue_init(q);
+       if (ret) {
+               omap4iss_put(video->iss);
+               goto done;
+       }
+
+       memset(&handle->format, 0, sizeof(handle->format));
+       handle->format.type = video->type;
+       handle->timeperframe.denominator = 1;
+
+       handle->video = video;
+       file->private_data = &handle->vfh;
+
+done:
+       if (ret < 0) {
+               v4l2_fh_del(&handle->vfh);
+               kfree(handle);
+       }
+
+       return ret;
+}
+
+static int iss_video_release(struct file *file)
+{
+       struct iss_video *video = video_drvdata(file);
+       struct v4l2_fh *vfh = file->private_data;
+       struct iss_video_fh *handle = to_iss_video_fh(vfh);
+
+       /* Disable streaming and free the buffers queue resources. */
+       iss_video_streamoff(file, vfh, video->type);
+
+       omap4iss_pipeline_pm_use(&video->video.entity, 0);
+
+       /* Release the videobuf2 queue */
+       vb2_queue_release(&handle->queue);
+
+       /* Release the file handle. */
+       v4l2_fh_del(vfh);
+       kfree(handle);
+       file->private_data = NULL;
+
+       omap4iss_put(video->iss);
+
+       return 0;
+}
+
+static unsigned int iss_video_poll(struct file *file, poll_table *wait)
+{
+       struct iss_video_fh *vfh = to_iss_video_fh(file->private_data);
+
+       return vb2_poll(&vfh->queue, file, wait);
+}
+
+static int iss_video_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct iss_video_fh *vfh = to_iss_video_fh(file->private_data);
+
+       return vb2_mmap(&vfh->queue, vma);;
+}
+
+static struct v4l2_file_operations iss_video_fops = {
+       .owner = THIS_MODULE,
+       .unlocked_ioctl = video_ioctl2,
+       .open = iss_video_open,
+       .release = iss_video_release,
+       .poll = iss_video_poll,
+       .mmap = iss_video_mmap,
+};
+
+/* -----------------------------------------------------------------------------
+ * ISS video core
+ */
+
+static const struct iss_video_operations iss_video_dummy_ops = {
+};
+
+int omap4iss_video_init(struct iss_video *video, const char *name)
+{
+       const char *direction;
+       int ret;
+
+       switch (video->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               direction = "output";
+               video->pad.flags = MEDIA_PAD_FL_SINK;
+               break;
+       case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+               direction = "input";
+               video->pad.flags = MEDIA_PAD_FL_SOURCE;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       ret = media_entity_init(&video->video.entity, 1, &video->pad, 0);
+       if (ret < 0)
+               return ret;
+
+       mutex_init(&video->mutex);
+       atomic_set(&video->active, 0);
+
+       spin_lock_init(&video->pipe.lock);
+       mutex_init(&video->stream_lock);
+
+       /* Initialize the video device. */
+       if (video->ops == NULL)
+               video->ops = &iss_video_dummy_ops;
+
+       video->video.fops = &iss_video_fops;
+       snprintf(video->video.name, sizeof(video->video.name),
+                "OMAP4 ISS %s %s", name, direction);
+       video->video.vfl_type = VFL_TYPE_GRABBER;
+       video->video.release = video_device_release_empty;
+       video->video.ioctl_ops = &iss_video_ioctl_ops;
+       video->pipe.stream_state = ISS_PIPELINE_STREAM_STOPPED;
+
+       video_set_drvdata(&video->video, video);
+
+       return 0;
+}
+
+void omap4iss_video_cleanup(struct iss_video *video)
+{
+       media_entity_cleanup(&video->video.entity);
+       mutex_destroy(&video->stream_lock);
+       mutex_destroy(&video->mutex);
+}
+
+int omap4iss_video_register(struct iss_video *video, struct v4l2_device *vdev)
+{
+       int ret;
+
+       video->video.v4l2_dev = vdev;
+
+       ret = video_register_device(&video->video, VFL_TYPE_GRABBER, -1);
+       if (ret < 0)
+               printk(KERN_ERR "%s: could not register video device (%d)\n",
+                       __func__, ret);
+
+       return ret;
+}
+
+void omap4iss_video_unregister(struct iss_video *video)
+{
+       video_unregister_device(&video->video);
+}
diff --git a/drivers/staging/media/omap4iss/iss_video.h b/drivers/staging/media/omap4iss/iss_video.h
new file mode 100644 (file)
index 0000000..35f14d8
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * TI OMAP4 ISS V4L2 Driver - Generic video node
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef OMAP4_ISS_VIDEO_H
+#define OMAP4_ISS_VIDEO_H
+
+#include <linux/v4l2-mediabus.h>
+#include <media/media-entity.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-fh.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-dma-contig.h>
+
+#define ISS_VIDEO_DRIVER_NAME          "issvideo"
+#define ISS_VIDEO_DRIVER_VERSION       "0.0.2"
+
+struct iss_device;
+struct iss_video;
+struct v4l2_mbus_framefmt;
+struct v4l2_pix_format;
+
+/*
+ * struct iss_format_info - ISS media bus format information
+ * @code: V4L2 media bus format code
+ * @truncated: V4L2 media bus format code for the same format truncated to 10
+ *     bits. Identical to @code if the format is 10 bits wide or less.
+ * @uncompressed: V4L2 media bus format code for the corresponding uncompressed
+ *     format. Identical to @code if the format is not DPCM compressed.
+ * @flavor: V4L2 media bus format code for the same pixel layout but
+ *     shifted to be 8 bits per pixel. =0 if format is not shiftable.
+ * @pixelformat: V4L2 pixel format FCC identifier
+ * @bpp: Bits per pixel
+ */
+struct iss_format_info {
+       enum v4l2_mbus_pixelcode code;
+       enum v4l2_mbus_pixelcode truncated;
+       enum v4l2_mbus_pixelcode uncompressed;
+       enum v4l2_mbus_pixelcode flavor;
+       u32 pixelformat;
+       unsigned int bpp;
+};
+
+enum iss_pipeline_stream_state {
+       ISS_PIPELINE_STREAM_STOPPED = 0,
+       ISS_PIPELINE_STREAM_CONTINUOUS = 1,
+       ISS_PIPELINE_STREAM_SINGLESHOT = 2,
+};
+
+enum iss_pipeline_state {
+       /* The stream has been started on the input video node. */
+       ISS_PIPELINE_STREAM_INPUT = 1,
+       /* The stream has been started on the output video node. */
+       ISS_PIPELINE_STREAM_OUTPUT = (1 << 1),
+       /* At least one buffer is queued on the input video node. */
+       ISS_PIPELINE_QUEUE_INPUT = (1 << 2),
+       /* At least one buffer is queued on the output video node. */
+       ISS_PIPELINE_QUEUE_OUTPUT = (1 << 3),
+       /* The input entity is idle, ready to be started. */
+       ISS_PIPELINE_IDLE_INPUT = (1 << 4),
+       /* The output entity is idle, ready to be started. */
+       ISS_PIPELINE_IDLE_OUTPUT = (1 << 5),
+       /* The pipeline is currently streaming. */
+       ISS_PIPELINE_STREAM = (1 << 6),
+};
+
+/*
+ * struct iss_pipeline - An OMAP4 ISS hardware pipeline
+ * @error: A hardware error occurred during capture
+ */
+struct iss_pipeline {
+       struct media_pipeline pipe;
+       spinlock_t lock;                /* Pipeline state and queue flags */
+       unsigned int state;
+       enum iss_pipeline_stream_state stream_state;
+       struct iss_video *input;
+       struct iss_video *output;
+       atomic_t frame_number;
+       bool do_propagation; /* of frame number */
+       bool error;
+       struct v4l2_fract max_timeperframe;
+       struct v4l2_subdev *external;
+       unsigned int external_rate;
+       int external_bpp;
+};
+
+#define to_iss_pipeline(__e) \
+       container_of((__e)->pipe, struct iss_pipeline, pipe)
+
+static inline int iss_pipeline_ready(struct iss_pipeline *pipe)
+{
+       return pipe->state == (ISS_PIPELINE_STREAM_INPUT |
+                              ISS_PIPELINE_STREAM_OUTPUT |
+                              ISS_PIPELINE_QUEUE_INPUT |
+                              ISS_PIPELINE_QUEUE_OUTPUT |
+                              ISS_PIPELINE_IDLE_INPUT |
+                              ISS_PIPELINE_IDLE_OUTPUT);
+}
+
+/*
+ * struct iss_buffer - ISS buffer
+ * @buffer: ISS video buffer
+ * @iss_addr: Physical address of the buffer.
+ */
+struct iss_buffer {
+       /* common v4l buffer stuff -- must be first */
+       struct vb2_buffer       vb;
+       struct list_head        list;
+       dma_addr_t iss_addr;
+};
+
+#define to_iss_buffer(buf)     container_of(buf, struct iss_buffer, buffer)
+
+enum iss_video_dmaqueue_flags {
+       /* Set if DMA queue becomes empty when ISS_PIPELINE_STREAM_CONTINUOUS */
+       ISS_VIDEO_DMAQUEUE_UNDERRUN = (1 << 0),
+       /* Set when queuing buffer to an empty DMA queue */
+       ISS_VIDEO_DMAQUEUE_QUEUED = (1 << 1),
+};
+
+#define iss_video_dmaqueue_flags_clr(video)    \
+                       ({ (video)->dmaqueue_flags = 0; })
+
+/*
+ * struct iss_video_operations - ISS video operations
+ * @queue:     Resume streaming when a buffer is queued. Called on VIDIOC_QBUF
+ *             if there was no buffer previously queued.
+ */
+struct iss_video_operations {
+       int(*queue)(struct iss_video *video, struct iss_buffer *buffer);
+};
+
+struct iss_video {
+       struct video_device video;
+       enum v4l2_buf_type type;
+       struct media_pad pad;
+
+       struct mutex mutex;             /* format and crop settings */
+       atomic_t active;
+
+       struct iss_device *iss;
+
+       unsigned int capture_mem;
+       unsigned int bpl_alignment;     /* alignment value */
+       unsigned int bpl_zero_padding;  /* whether the alignment is optional */
+       unsigned int bpl_max;           /* maximum bytes per line value */
+       unsigned int bpl_value;         /* bytes per line value */
+       unsigned int bpl_padding;       /* padding at end of line */
+
+       /* Pipeline state */
+       struct iss_pipeline pipe;
+       struct mutex stream_lock;       /* pipeline and stream states */
+
+       /* Video buffers queue */
+       struct vb2_queue *queue;
+       spinlock_t qlock;       /* Spinlock for dmaqueue */
+       struct list_head dmaqueue;
+       enum iss_video_dmaqueue_flags dmaqueue_flags;
+       struct vb2_alloc_ctx *alloc_ctx;
+
+       const struct iss_video_operations *ops;
+};
+
+#define to_iss_video(vdev)     container_of(vdev, struct iss_video, video)
+
+struct iss_video_fh {
+       struct v4l2_fh vfh;
+       struct iss_video *video;
+       struct vb2_queue queue;
+       struct v4l2_format format;
+       struct v4l2_fract timeperframe;
+};
+
+#define to_iss_video_fh(fh)    container_of(fh, struct iss_video_fh, vfh)
+#define iss_video_queue_to_iss_video_fh(q) \
+                               container_of(q, struct iss_video_fh, queue)
+
+int omap4iss_video_init(struct iss_video *video, const char *name);
+void omap4iss_video_cleanup(struct iss_video *video);
+int omap4iss_video_register(struct iss_video *video,
+                           struct v4l2_device *vdev);
+void omap4iss_video_unregister(struct iss_video *video);
+struct iss_buffer *omap4iss_video_buffer_next(struct iss_video *video);
+struct media_pad *omap4iss_video_remote_pad(struct iss_video *video);
+
+const struct iss_format_info *
+omap4iss_video_format_info(enum v4l2_mbus_pixelcode code);
+
+#endif /* OMAP4_ISS_VIDEO_H */
index 49ea76b3435dcd19b9a9f8bbbfb561a92b0a53fe..bb152201e93d2292835571c838c01ebf58805ed1 100644 (file)
@@ -83,7 +83,7 @@ enum nvec_sleep_subcmds {
 
 static struct nvec_chip *nvec_power_handle;
 
-static struct mfd_cell nvec_devices[] = {
+static const struct mfd_cell nvec_devices[] = {
        {
                .name = "nvec-kbd",
                .id = 1,
index 9f6ebdb23740596f530e9ab5d52194ca3c9c438e..a85c3d68c462b1a14b8a517445521a6df61bf64e 100644 (file)
@@ -31,7 +31,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
 #include <linux/platform_device.h>
 #include <linux/input.h>
 
index 1aa4a3fd0f1ba3b023367974593897ba1077df18..56e355b3e7fa00b5dd6a8ca4929071cc5cdaca09 100644 (file)
@@ -258,7 +258,8 @@ err:
 /* This function maps kernel space memory to user space memory. */
 static int bridge_mmap(struct file *filp, struct vm_area_struct *vma)
 {
-       u32 status;
+       struct omap_dsp_platform_data *pdata =
+                                       omap_dspbridge_dev->dev.platform_data;
 
        /* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */
        vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
@@ -268,13 +269,9 @@ static int bridge_mmap(struct file *filp, struct vm_area_struct *vma)
                vma->vm_start, vma->vm_end, vma->vm_page_prot,
                vma->vm_flags);
 
-       status = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
-                                vma->vm_end - vma->vm_start,
-                                vma->vm_page_prot);
-       if (status != 0)
-               status = -EAGAIN;
-
-       return status;
+       return vm_iomap_memory(vma,
+                              pdata->phys_mempool_base,
+                              pdata->phys_mempool_size);
 }
 
 static const struct file_operations bridge_fops = {
index 3277d9838f4e928ab3555720a186e476e826a720..108f2733106d77c00b73003e106febe6aa8998cc 100644 (file)
@@ -171,13 +171,14 @@ static inline int valid_io_request(struct zram *zram, struct bio *bio)
        u64 start, end, bound;
 
        /* unaligned request */
-       if (unlikely(bio->bi_sector & (ZRAM_SECTOR_PER_LOGICAL_BLOCK - 1)))
+       if (unlikely(bio->bi_iter.bi_sector &
+                    (ZRAM_SECTOR_PER_LOGICAL_BLOCK - 1)))
                return 0;
-       if (unlikely(bio->bi_size & (ZRAM_LOGICAL_BLOCK_SIZE - 1)))
+       if (unlikely(bio->bi_iter.bi_size & (ZRAM_LOGICAL_BLOCK_SIZE - 1)))
                return 0;
 
-       start = bio->bi_sector;
-       end = start + (bio->bi_size >> SECTOR_SHIFT);
+       start = bio->bi_iter.bi_sector;
+       end = start + (bio->bi_iter.bi_size >> SECTOR_SHIFT);
        bound = zram->disksize >> SECTOR_SHIFT;
        /* out of range range */
        if (unlikely(start >= bound || end > bound || start > end))
@@ -680,9 +681,10 @@ out:
 
 static void __zram_make_request(struct zram *zram, struct bio *bio, int rw)
 {
-       int i, offset;
+       int offset;
        u32 index;
-       struct bio_vec *bvec;
+       struct bio_vec bvec;
+       struct bvec_iter iter;
 
        switch (rw) {
        case READ:
@@ -693,36 +695,37 @@ static void __zram_make_request(struct zram *zram, struct bio *bio, int rw)
                break;
        }
 
-       index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT;
-       offset = (bio->bi_sector & (SECTORS_PER_PAGE - 1)) << SECTOR_SHIFT;
+       index = bio->bi_iter.bi_sector >> SECTORS_PER_PAGE_SHIFT;
+       offset = (bio->bi_iter.bi_sector &
+                 (SECTORS_PER_PAGE - 1)) << SECTOR_SHIFT;
 
-       bio_for_each_segment(bvec, bio, i) {
+       bio_for_each_segment(bvec, bio, iter) {
                int max_transfer_size = PAGE_SIZE - offset;
 
-               if (bvec->bv_len > max_transfer_size) {
+               if (bvec.bv_len > max_transfer_size) {
                        /*
                         * zram_bvec_rw() can only make operation on a single
                         * zram page. Split the bio vector.
                         */
                        struct bio_vec bv;
 
-                       bv.bv_page = bvec->bv_page;
+                       bv.bv_page = bvec.bv_page;
                        bv.bv_len = max_transfer_size;
-                       bv.bv_offset = bvec->bv_offset;
+                       bv.bv_offset = bvec.bv_offset;
 
                        if (zram_bvec_rw(zram, &bv, index, offset, bio, rw) < 0)
                                goto out;
 
-                       bv.bv_len = bvec->bv_len - max_transfer_size;
+                       bv.bv_len = bvec.bv_len - max_transfer_size;
                        bv.bv_offset += max_transfer_size;
                        if (zram_bvec_rw(zram, &bv, index+1, 0, bio, rw) < 0)
                                goto out;
                } else
-                       if (zram_bvec_rw(zram, bvec, index, offset, bio, rw)
+                       if (zram_bvec_rw(zram, &bvec, index, offset, bio, rw)
                            < 0)
                                goto out;
 
-               update_position(&index, &offset, bvec);
+               update_position(&index, &offset, &bvec);
        }
 
        set_bit(BIO_UPTODATE, &bio->bi_flags);
index c87959f12760462ca76740737e7cc839bdd4fc58..2d29356d0c85a076e90db99bbda9f1a428f9c336 100644 (file)
@@ -319,7 +319,7 @@ iblock_get_bio(struct se_cmd *cmd, sector_t lba, u32 sg_num)
        bio->bi_bdev = ib_dev->ibd_bd;
        bio->bi_private = cmd;
        bio->bi_end_io = &iblock_bio_done;
-       bio->bi_sector = lba;
+       bio->bi_iter.bi_sector = lba;
 
        return bio;
 }
index 0f74945af624962266803ce242ef10509906a6a4..268b62768f2b41eab5f7db4d4c5c8b9111f248b6 100644 (file)
@@ -810,7 +810,8 @@ static void process_echoes(struct tty_struct *tty)
        struct n_tty_data *ldata = tty->disc_data;
        size_t echoed;
 
-       if (!L_ECHO(tty) || ldata->echo_commit == ldata->echo_tail)
+       if ((!L_ECHO(tty) && !L_ECHONL(tty)) ||
+           ldata->echo_commit == ldata->echo_tail)
                return;
 
        mutex_lock(&ldata->output_lock);
@@ -825,7 +826,8 @@ static void flush_echoes(struct tty_struct *tty)
 {
        struct n_tty_data *ldata = tty->disc_data;
 
-       if (!L_ECHO(tty) || ldata->echo_commit == ldata->echo_head)
+       if ((!L_ECHO(tty) && !L_ECHONL(tty)) ||
+           ldata->echo_commit == ldata->echo_head)
                return;
 
        mutex_lock(&ldata->output_lock);
index ec06505e3ae63704d73f44ad23252b3de7bc6656..97888f4900eced03ab3a656faa6de016c16d3851 100644 (file)
@@ -421,6 +421,7 @@ struct psc_fifoc {
 
 static struct psc_fifoc __iomem *psc_fifoc;
 static unsigned int psc_fifoc_irq;
+static struct clk *psc_fifoc_clk;
 
 static void mpc512x_psc_fifo_init(struct uart_port *port)
 {
@@ -568,36 +569,73 @@ static unsigned int mpc512x_psc_set_baudrate(struct uart_port *port,
 /* Init PSC FIFO Controller */
 static int __init mpc512x_psc_fifoc_init(void)
 {
+       int err;
        struct device_node *np;
+       struct clk *clk;
+
+       /* default error code, potentially overwritten by clock calls */
+       err = -ENODEV;
 
        np = of_find_compatible_node(NULL, NULL,
                                     "fsl,mpc5121-psc-fifo");
        if (!np) {
                pr_err("%s: Can't find FIFOC node\n", __func__);
-               return -ENODEV;
+               goto out_err;
        }
 
+       clk = of_clk_get(np, 0);
+       if (IS_ERR(clk)) {
+               /* backwards compat with device trees that lack clock specs */
+               clk = clk_get_sys(np->name, "ipg");
+       }
+       if (IS_ERR(clk)) {
+               pr_err("%s: Can't lookup FIFO clock\n", __func__);
+               err = PTR_ERR(clk);
+               goto out_ofnode_put;
+       }
+       if (clk_prepare_enable(clk)) {
+               pr_err("%s: Can't enable FIFO clock\n", __func__);
+               clk_put(clk);
+               goto out_ofnode_put;
+       }
+       psc_fifoc_clk = clk;
+
        psc_fifoc = of_iomap(np, 0);
        if (!psc_fifoc) {
                pr_err("%s: Can't map FIFOC\n", __func__);
-               of_node_put(np);
-               return -ENODEV;
+               goto out_clk_disable;
        }
 
        psc_fifoc_irq = irq_of_parse_and_map(np, 0);
-       of_node_put(np);
        if (psc_fifoc_irq == 0) {
                pr_err("%s: Can't get FIFOC irq\n", __func__);
-               iounmap(psc_fifoc);
-               return -ENODEV;
+               goto out_unmap;
        }
 
+       of_node_put(np);
        return 0;
+
+out_unmap:
+       iounmap(psc_fifoc);
+out_clk_disable:
+       clk_disable_unprepare(psc_fifoc_clk);
+       clk_put(psc_fifoc_clk);
+out_ofnode_put:
+       of_node_put(np);
+out_err:
+       return err;
 }
 
 static void __exit mpc512x_psc_fifoc_uninit(void)
 {
        iounmap(psc_fifoc);
+
+       /* disable the clock, errors are not fatal */
+       if (psc_fifoc_clk) {
+               clk_disable_unprepare(psc_fifoc_clk);
+               clk_put(psc_fifoc_clk);
+               psc_fifoc_clk = NULL;
+       }
 }
 
 /* 512x specific interrupt handler. The caller holds the port lock */
@@ -619,29 +657,55 @@ static irqreturn_t mpc512x_psc_handle_irq(struct uart_port *port)
 }
 
 static struct clk *psc_mclk_clk[MPC52xx_PSC_MAXNUM];
+static struct clk *psc_ipg_clk[MPC52xx_PSC_MAXNUM];
 
 /* called from within the .request_port() callback (allocation) */
 static int mpc512x_psc_alloc_clock(struct uart_port *port)
 {
        int psc_num;
-       char clk_name[16];
        struct clk *clk;
        int err;
 
        psc_num = (port->mapbase & 0xf00) >> 8;
-       snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
-       clk = devm_clk_get(port->dev, clk_name);
+
+       clk = devm_clk_get(port->dev, "mclk");
        if (IS_ERR(clk)) {
                dev_err(port->dev, "Failed to get MCLK!\n");
-               return PTR_ERR(clk);
+               err = PTR_ERR(clk);
+               goto out_err;
        }
        err = clk_prepare_enable(clk);
        if (err) {
                dev_err(port->dev, "Failed to enable MCLK!\n");
-               return err;
+               goto out_err;
        }
        psc_mclk_clk[psc_num] = clk;
+
+       clk = devm_clk_get(port->dev, "ipg");
+       if (IS_ERR(clk)) {
+               dev_err(port->dev, "Failed to get IPG clock!\n");
+               err = PTR_ERR(clk);
+               goto out_err;
+       }
+       err = clk_prepare_enable(clk);
+       if (err) {
+               dev_err(port->dev, "Failed to enable IPG clock!\n");
+               goto out_err;
+       }
+       psc_ipg_clk[psc_num] = clk;
+
        return 0;
+
+out_err:
+       if (psc_mclk_clk[psc_num]) {
+               clk_disable_unprepare(psc_mclk_clk[psc_num]);
+               psc_mclk_clk[psc_num] = NULL;
+       }
+       if (psc_ipg_clk[psc_num]) {
+               clk_disable_unprepare(psc_ipg_clk[psc_num]);
+               psc_ipg_clk[psc_num] = NULL;
+       }
+       return err;
 }
 
 /* called from within the .release_port() callback (release) */
@@ -656,6 +720,10 @@ static void mpc512x_psc_relse_clock(struct uart_port *port)
                clk_disable_unprepare(clk);
                psc_mclk_clk[psc_num] = NULL;
        }
+       if (psc_ipg_clk[psc_num]) {
+               clk_disable_unprepare(psc_ipg_clk[psc_num]);
+               psc_ipg_clk[psc_num] = NULL;
+       }
 }
 
 /* implementation of the .clock() callback (enable/disable) */
index 7d8103cd3e2ec56eacbb5a5d3f3f332597e190ff..e7e9cabb21fd2a4a6613f075632e6f16f3432a33 100644 (file)
@@ -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),
        },
 };
 
index 67beb84449304d987c68a544c02b9c6e428dce1a..f7beb6eb40c714ae71309807b94b55a643501a9f 100644 (file)
@@ -653,6 +653,8 @@ static int uio_mmap_physical(struct vm_area_struct *vma)
                return -EINVAL;
        mem = idev->info->mem + mi;
 
+       if (mem->addr & ~PAGE_MASK)
+               return -ENODEV;
        if (vma->vm_end - vma->vm_start > mem->size)
                return -EINVAL;
 
index 5d8981c5235e50e42776cfb9f672977c11a61ef0..6e73f8cd60e513ca44de8d6bd00fe69085e4453f 100644 (file)
@@ -642,6 +642,10 @@ static int ci_hdrc_probe(struct platform_device *pdev)
                        : CI_ROLE_GADGET;
        }
 
+       /* only update vbus status for peripheral */
+       if (ci->role == CI_ROLE_GADGET)
+               ci_handle_vbus_change(ci);
+
        ret = ci_role_start(ci, ci->role);
        if (ret) {
                dev_err(dev, "can't start %s role\n", ci_role(ci)->name);
index 59e6020ea7539e5e331364ac067c9a16f27855ba..526cd77563d8a89c29f5444901ee3ba366b1575a 100644 (file)
@@ -88,7 +88,8 @@ static int host_start(struct ci_hdrc *ci)
        return ret;
 
 disable_reg:
-       regulator_disable(ci->platdata->reg_vbus);
+       if (ci->platdata->reg_vbus)
+               regulator_disable(ci->platdata->reg_vbus);
 
 put_hcd:
        usb_put_hcd(hcd);
index b34c81969cba672a7e880f405f2445adf36b7e6f..69d20fbb38a26a32357cc9f5d7fc4f81efa08cca 100644 (file)
@@ -1795,9 +1795,6 @@ static int udc_start(struct ci_hdrc *ci)
        pm_runtime_no_callbacks(&ci->gadget.dev);
        pm_runtime_enable(&ci->gadget.dev);
 
-       /* Update ci->vbus_active */
-       ci_handle_vbus_change(ci);
-
        return retval;
 
 destroy_eps:
index 3e7560f004f86d7153ed3ea0eeabed09dabf6b47..e8404319ca68b93d7b1d05b881b4d1bed8d1ded8 100644 (file)
@@ -1515,6 +1515,8 @@ static int acm_reset_resume(struct usb_interface *intf)
 
 static const struct usb_device_id acm_ids[] = {
        /* quirky and broken devices */
+       { USB_DEVICE(0x17ef, 0x7000), /* Lenovo USB modem */
+       .driver_info = NO_UNION_NORMAL, },/* has no union descriptor */
        { USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */
        .driver_info = NO_UNION_NORMAL, /* has no union descriptor */
        },
index 4d387596f3f0a6e531caa1a9049a383d605091b4..0b23a8639311b182ee9e2afddcec1cb888269257 100644 (file)
@@ -854,13 +854,11 @@ static int wdm_manage_power(struct usb_interface *intf, int on)
 {
        /* need autopm_get/put here to ensure the usbcore sees the new value */
        int rv = usb_autopm_get_interface(intf);
-       if (rv < 0)
-               goto err;
 
        intf->needs_remote_wakeup = on;
-       usb_autopm_put_interface(intf);
-err:
-       return rv;
+       if (!rv)
+               usb_autopm_put_interface(intf);
+       return 0;
 }
 
 static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id)
index a7c04e24ca484deb233db5dcfd995b73427c4cc0..bd9dc3504b5149b2ff5091d67bb514a92cbc0a88 100644 (file)
@@ -4832,8 +4832,9 @@ static void hub_events(void)
                                        hub->ports[i - 1]->child;
 
                                dev_dbg(hub_dev, "warm reset port %d\n", i);
-                               if (!udev || !(portstatus &
-                                               USB_PORT_STAT_CONNECTION)) {
+                               if (!udev ||
+                                   !(portstatus & USB_PORT_STAT_CONNECTION) ||
+                                   udev->state == USB_STATE_NOTATTACHED) {
                                        status = hub_port_reset(hub, i,
                                                        NULL, HUB_BH_RESET_TIME,
                                                        true);
index 4e243c37f17f50ab197582a3ee5d4662e933d368..f0155a39aaa3b686f1b392c7d59781a8f76fda5d 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/acpi.h>
 #include <linux/pci.h>
 #include <linux/usb/hcd.h>
-#include <acpi/acpi_bus.h>
 
 #include "usb.h"
 
@@ -127,7 +126,7 @@ out:
        return ret;
 }
 
-static int usb_acpi_find_device(struct device *dev, acpi_handle *handle)
+static struct acpi_device *usb_acpi_find_companion(struct device *dev)
 {
        struct usb_device *udev;
        acpi_handle *parent_handle;
@@ -169,16 +168,15 @@ static int usb_acpi_find_device(struct device *dev, acpi_handle *handle)
                                break;
                        }
 
-                       return -ENODEV;
+                       return NULL;
                }
 
                /* root hub's parent is the usb hcd. */
-               parent_handle = ACPI_HANDLE(dev->parent);
-               *handle = acpi_get_child(parent_handle, udev->portnum);
-               if (!*handle)
-                       return -ENODEV;
-               return 0;
+               return acpi_find_child_device(ACPI_COMPANION(dev->parent),
+                                             udev->portnum, false);
        } else if (is_usb_port(dev)) {
+               struct acpi_device *adev = NULL;
+
                sscanf(dev_name(dev), "port%d", &port_num);
                /* Get the struct usb_device point of port's hub */
                udev = to_usb_device(dev->parent->parent);
@@ -194,26 +192,27 @@ static int usb_acpi_find_device(struct device *dev, acpi_handle *handle)
 
                        raw_port_num = usb_hcd_find_raw_port_number(hcd,
                                port_num);
-                       *handle = acpi_get_child(ACPI_HANDLE(&udev->dev),
-                               raw_port_num);
-                       if (!*handle)
-                               return -ENODEV;
+                       adev = acpi_find_child_device(ACPI_COMPANION(&udev->dev),
+                                                     raw_port_num, false);
+                       if (!adev)
+                               return NULL;
                } else {
                        parent_handle =
                                usb_get_hub_port_acpi_handle(udev->parent,
                                udev->portnum);
                        if (!parent_handle)
-                               return -ENODEV;
+                               return NULL;
 
-                       *handle = acpi_get_child(parent_handle, port_num);
-                       if (!*handle)
-                               return -ENODEV;
+                       acpi_bus_get_device(parent_handle, &adev);
+                       adev = acpi_find_child_device(adev, port_num, false);
+                       if (!adev)
+                               return NULL;
                }
-               usb_acpi_check_port_connect_type(udev, *handle, port_num);
-       } else
-               return -ENODEV;
+               usb_acpi_check_port_connect_type(udev, adev->handle, port_num);
+               return adev;
+       }
 
-       return 0;
+       return NULL;
 }
 
 static bool usb_acpi_bus_match(struct device *dev)
@@ -224,7 +223,7 @@ static bool usb_acpi_bus_match(struct device *dev)
 static struct acpi_bus_type usb_acpi_bus = {
        .name = "USB",
        .match = usb_acpi_bus_match,
-       .find_device = usb_acpi_find_device,
+       .find_companion = usb_acpi_find_companion,
 };
 
 int usb_acpi_register(void)
index 74f9cf02da070a6d1c23b643a56f76e3264fb8cd..a49217ae35333846bb76912666f0efa12bca6813 100644 (file)
@@ -455,9 +455,6 @@ static int dwc3_probe(struct platform_device *pdev)
        if (IS_ERR(regs))
                return PTR_ERR(regs);
 
-       usb_phy_set_suspend(dwc->usb2_phy, 0);
-       usb_phy_set_suspend(dwc->usb3_phy, 0);
-
        spin_lock_init(&dwc->lock);
        platform_set_drvdata(pdev, dwc);
 
@@ -488,6 +485,9 @@ static int dwc3_probe(struct platform_device *pdev)
                goto err0;
        }
 
+       usb_phy_set_suspend(dwc->usb2_phy, 0);
+       usb_phy_set_suspend(dwc->usb3_phy, 0);
+
        ret = dwc3_event_buffers_setup(dwc);
        if (ret) {
                dev_err(dwc->dev, "failed to setup event buffers\n");
@@ -569,6 +569,8 @@ err2:
        dwc3_event_buffers_cleanup(dwc);
 
 err1:
+       usb_phy_set_suspend(dwc->usb2_phy, 1);
+       usb_phy_set_suspend(dwc->usb3_phy, 1);
        dwc3_core_exit(dwc);
 
 err0:
index 95f7649c71a78745692a63bafd1527daacda52e3..21a352079bc25fdd0fe33ddba1a3191b29b812f0 100644 (file)
@@ -459,6 +459,8 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
                        dep = dwc3_wIndex_to_dep(dwc, wIndex);
                        if (!dep)
                                return -EINVAL;
+                       if (set == 0 && (dep->flags & DWC3_EP_WEDGE))
+                               break;
                        ret = __dwc3_gadget_ep_set_halt(dep, set);
                        if (ret)
                                return -EINVAL;
index 5452c0fce36074d4238e3553bb00d879d8df9ac3..02e44fcaf205e3eaf4a69e706c41d6e081c6c1e5 100644 (file)
@@ -1200,9 +1200,6 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value)
                else
                        dep->flags |= DWC3_EP_STALL;
        } else {
-               if (dep->flags & DWC3_EP_WEDGE)
-                       return 0;
-
                ret = dwc3_send_gadget_ep_cmd(dwc, dep->number,
                        DWC3_DEPCMD_CLEARSTALL, &params);
                if (ret)
@@ -1210,7 +1207,7 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value)
                                        value ? "set" : "clear",
                                        dep->name);
                else
-                       dep->flags &= ~DWC3_EP_STALL;
+                       dep->flags &= ~(DWC3_EP_STALL | DWC3_EP_WEDGE);
        }
 
        return ret;
index a91e6422f93021f912042298a99cdde36362b09b..f66d96ad1f51eb96d1806187dbb564675a02b8f0 100644 (file)
@@ -682,6 +682,7 @@ config USB_CONFIGFS_PHONET
 config USB_CONFIGFS_MASS_STORAGE
        boolean "Mass storage"
        depends on USB_CONFIGFS
+       depends on BLOCK
        select USB_F_MASS_STORAGE
        help
          The Mass Storage Gadget acts as a USB Mass Storage disk drive.
index 2cb52e0438df1b349a1feca20749e3290739a94a..9f71d9fdcc143206d8947b00e1c8d5cebb33297f 100644 (file)
@@ -326,7 +326,7 @@ static int vbus_is_present(struct usba_udc *udc)
 
 #if defined(CONFIG_ARCH_AT91SAM9RL)
 
-#include <mach/at91_pmc.h>
+#include <linux/clk/at91_pmc.h>
 
 static void toggle_bias(int is_on)
 {
index 3e7ae707f691c4b0cf4b701024d8df0af4a5bb69..2018ba1a2172d4bb26faea20c34e44653070e91f 100644 (file)
@@ -593,6 +593,7 @@ static void reset_config(struct usb_composite_dev *cdev)
                bitmap_zero(f->endpoints, 32);
        }
        cdev->config = NULL;
+       cdev->delayed_status = 0;
 }
 
 static int set_config(struct usb_composite_dev *cdev,
index 774e8b89cdb593bf951b5c82e97c169f921a6130..241fc873ffa4569fcc98a3a93ff98e3f07339d72 100644 (file)
@@ -1304,7 +1304,7 @@ static struct ffs_data *ffs_data_new(void)
 {
        struct ffs_data *ffs = kzalloc(sizeof *ffs, GFP_KERNEL);
        if (unlikely(!ffs))
-               return 0;
+               return NULL;
 
        ENTER();
 
index a03ba2c83589ee15f9c1880d17f1aa133eb47f29..b963939088606e7e9252ec1f55d42ff9fdd1dcd3 100644 (file)
@@ -523,7 +523,7 @@ static int fsg_setup(struct usb_function *f,
                 */
                DBG(fsg, "bulk reset request\n");
                raise_exception(fsg->common, FSG_STATE_RESET);
-               return DELAYED_STATUS;
+               return USB_GADGET_DELAYED_STATUS;
 
        case US_BULK_GET_MAX_LUN:
                if (ctrl->bRequestType !=
@@ -602,13 +602,14 @@ static bool start_out_transfer(struct fsg_common *common, struct fsg_buffhd *bh)
        return true;
 }
 
-static int sleep_thread(struct fsg_common *common)
+static int sleep_thread(struct fsg_common *common, bool can_freeze)
 {
        int     rc = 0;
 
        /* Wait until a signal arrives or we are woken up */
        for (;;) {
-               try_to_freeze();
+               if (can_freeze)
+                       try_to_freeze();
                set_current_state(TASK_INTERRUPTIBLE);
                if (signal_pending(current)) {
                        rc = -EINTR;
@@ -682,7 +683,7 @@ static int do_read(struct fsg_common *common)
                /* Wait for the next buffer to become available */
                bh = common->next_buffhd_to_fill;
                while (bh->state != BUF_STATE_EMPTY) {
-                       rc = sleep_thread(common);
+                       rc = sleep_thread(common, false);
                        if (rc)
                                return rc;
                }
@@ -937,7 +938,7 @@ static int do_write(struct fsg_common *common)
                }
 
                /* Wait for something to happen */
-               rc = sleep_thread(common);
+               rc = sleep_thread(common, false);
                if (rc)
                        return rc;
        }
@@ -1504,7 +1505,7 @@ static int throw_away_data(struct fsg_common *common)
                }
 
                /* Otherwise wait for something to happen */
-               rc = sleep_thread(common);
+               rc = sleep_thread(common, true);
                if (rc)
                        return rc;
        }
@@ -1625,7 +1626,7 @@ static int send_status(struct fsg_common *common)
        /* Wait for the next buffer to become available */
        bh = common->next_buffhd_to_fill;
        while (bh->state != BUF_STATE_EMPTY) {
-               rc = sleep_thread(common);
+               rc = sleep_thread(common, true);
                if (rc)
                        return rc;
        }
@@ -1828,7 +1829,7 @@ static int do_scsi_command(struct fsg_common *common)
        bh = common->next_buffhd_to_fill;
        common->next_buffhd_to_drain = bh;
        while (bh->state != BUF_STATE_EMPTY) {
-               rc = sleep_thread(common);
+               rc = sleep_thread(common, true);
                if (rc)
                        return rc;
        }
@@ -2174,7 +2175,7 @@ static int get_next_command(struct fsg_common *common)
        /* Wait for the next buffer to become available */
        bh = common->next_buffhd_to_fill;
        while (bh->state != BUF_STATE_EMPTY) {
-               rc = sleep_thread(common);
+               rc = sleep_thread(common, true);
                if (rc)
                        return rc;
        }
@@ -2193,7 +2194,7 @@ static int get_next_command(struct fsg_common *common)
 
        /* Wait for the CBW to arrive */
        while (bh->state != BUF_STATE_FULL) {
-               rc = sleep_thread(common);
+               rc = sleep_thread(common, true);
                if (rc)
                        return rc;
        }
@@ -2379,7 +2380,7 @@ static void handle_exception(struct fsg_common *common)
                        }
                        if (num_active == 0)
                                break;
-                       if (sleep_thread(common))
+                       if (sleep_thread(common, true))
                                return;
                }
 
@@ -2516,7 +2517,7 @@ static int fsg_main_thread(void *common_)
                }
 
                if (!common->running) {
-                       sleep_thread(common);
+                       sleep_thread(common, true);
                        continue;
                }
 
@@ -3111,7 +3112,7 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
                                          fsg->common->can_stall);
                if (ret)
                        return ret;
-               fsg_common_set_inquiry_string(fsg->common, 0, 0);
+               fsg_common_set_inquiry_string(fsg->common, NULL, NULL);
                ret = fsg_common_run_thread(fsg->common);
                if (ret)
                        return ret;
index 0ac6064aa3b86b6cd2376324ac9996f8ece1c0a0..409a3c45a36af1ec596ad4d9bf2c117c9f493444 100644 (file)
@@ -54,6 +54,7 @@
  */
 #ifdef CONFIG_ARCH_PXA
 #include <mach/pxa25x-udc.h>
+#include <mach/hardware.h>
 #endif
 
 #ifdef CONFIG_ARCH_LUBBOCK
index 9875d9c0823f7c554744a40acb0a70897dde0bc6..e20bc109fdd70f43eec9e1572d3fa8f75e6ba423 100644 (file)
@@ -1180,6 +1180,7 @@ static int s3c_hsotg_process_req_feature(struct s3c_hsotg *hsotg,
 }
 
 static void s3c_hsotg_enqueue_setup(struct s3c_hsotg *hsotg);
+static void s3c_hsotg_disconnect(struct s3c_hsotg *hsotg);
 
 /**
  * s3c_hsotg_process_control - process a control request
@@ -1221,6 +1222,7 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg,
        if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
                switch (ctrl->bRequest) {
                case USB_REQ_SET_ADDRESS:
+                       s3c_hsotg_disconnect(hsotg);
                        dcfg = readl(hsotg->regs + DCFG);
                        dcfg &= ~DCFG_DevAddr_MASK;
                        dcfg |= ctrl->wValue << DCFG_DevAddr_SHIFT;
@@ -1245,7 +1247,9 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg,
        /* as a fallback, try delivering it to the driver to deal with */
 
        if (ret == 0 && hsotg->driver) {
+               spin_unlock(&hsotg->lock);
                ret = hsotg->driver->setup(&hsotg->gadget, ctrl);
+               spin_lock(&hsotg->lock);
                if (ret < 0)
                        dev_dbg(hsotg->dev, "driver->setup() ret %d\n", ret);
        }
@@ -1308,10 +1312,12 @@ static void s3c_hsotg_complete_setup(struct usb_ep *ep,
                return;
        }
 
+       spin_lock(&hsotg->lock);
        if (req->actual == 0)
                s3c_hsotg_enqueue_setup(hsotg);
        else
                s3c_hsotg_process_control(hsotg, req->buf);
+       spin_unlock(&hsotg->lock);
 }
 
 /**
@@ -2533,7 +2539,6 @@ irq_retry:
                writel(GINTSTS_USBSusp, hsotg->regs + GINTSTS);
 
                call_gadget(hsotg, suspend);
-               s3c_hsotg_disconnect(hsotg);
        }
 
        if (gintsts & GINTSTS_WkUpInt) {
index c74c2fdbd56eda5683a13995a96b6221711c30ef..70c891469f574ebd1d7719fc05bcf838d1d6e3cb 100644 (file)
@@ -119,10 +119,6 @@ static inline bool fsg_lun_is_open(struct fsg_lun *curlun)
        return curlun->filp != NULL;
 }
 
-/* Big enough to hold our biggest descriptor */
-#define EP0_BUFSIZE    256
-#define DELAYED_STATUS (EP0_BUFSIZE + 999)     /* An impossibly large value */
-
 /* Default size of buffer length. */
 #define FSG_BUFLEN     ((u32)16384)
 
index 6c3d7950d2a9e56d5231938493127c0964f04221..0f8aad78b54f7095a26b6e413a22ff5ae1e016df 100644 (file)
@@ -370,7 +370,7 @@ err:
        return -ENOMEM;
 }
 
-void bot_cleanup_old_alt(struct f_uas *fu)
+static void bot_cleanup_old_alt(struct f_uas *fu)
 {
        if (!(fu->flags & USBG_ENABLED))
                return;
index 0dd07ae1555ddf066312e0ff4e8182a02f27a3d6..f49b0b61ecc8163941447e8ba5b719982951531e 100644 (file)
@@ -91,17 +91,17 @@ static struct usb_zero_options gzero_options = {
  * functional coverage for the "USBCV" test harness from USB-IF.
  * It's always set if OTG mode is enabled.
  */
-unsigned autoresume = DEFAULT_AUTORESUME;
+static unsigned autoresume = DEFAULT_AUTORESUME;
 module_param(autoresume, uint, S_IRUGO);
 MODULE_PARM_DESC(autoresume, "zero, or seconds before remote wakeup");
 
 /* Maximum Autoresume time */
-unsigned max_autoresume;
+static unsigned max_autoresume;
 module_param(max_autoresume, uint, S_IRUGO);
 MODULE_PARM_DESC(max_autoresume, "maximum seconds before remote wakeup");
 
 /* Interval between two remote wakeups */
-unsigned autoresume_interval_ms;
+static unsigned autoresume_interval_ms;
 module_param(autoresume_interval_ms, uint, S_IRUGO);
 MODULE_PARM_DESC(autoresume_interval_ms,
                "milliseconds to increase successive wakeup delays");
index abd5050a4899bdb4518294175477a418583c4e83..9162d1b6c0a348f9a6d028bf7c7eef9df0261240 100644 (file)
@@ -261,19 +261,8 @@ int fsl_usb2_mpc5121_init(struct platform_device *pdev)
        struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev);
        struct clk *clk;
        int err;
-       char clk_name[10];
-       int base, clk_num;
-
-       base = pdev->resource->start & 0xf000;
-       if (base == 0x3000)
-               clk_num = 1;
-       else if (base == 0x4000)
-               clk_num = 2;
-       else
-               return -ENODEV;
 
-       snprintf(clk_name, sizeof(clk_name), "usb%d_clk", clk_num);
-       clk = devm_clk_get(pdev->dev.parent, clk_name);
+       clk = devm_clk_get(pdev->dev.parent, "ipg");
        if (IS_ERR(clk)) {
                dev_err(&pdev->dev, "failed to get clk\n");
                return PTR_ERR(clk);
index e89ac4d4b87e5be4d4a134e389dbdfa20931eb9c..9b7435f0dcd6b432f0c7fa9fcc096817e7141712 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <linux/clk.h>
 #include <linux/device.h>
+#include <linux/dma-mapping.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
index 2ad004ae747c53b20f34fbeda0f54179408ce432..a2fdd85e0c919dc7aaac1baa48b0504c0baa708d 100644 (file)
@@ -95,7 +95,7 @@ static int r8a66597_clock_enable(struct r8a66597 *r8a66597)
        int i = 0;
 
        if (r8a66597->pdata->on_chip) {
-               clk_enable(r8a66597->clk);
+               clk_prepare_enable(r8a66597->clk);
                do {
                        r8a66597_write(r8a66597, SCKE, SYSCFG0);
                        tmp = r8a66597_read(r8a66597, SYSCFG0);
@@ -139,7 +139,7 @@ static void r8a66597_clock_disable(struct r8a66597 *r8a66597)
        udelay(1);
 
        if (r8a66597->pdata->on_chip) {
-               clk_disable(r8a66597->clk);
+               clk_disable_unprepare(r8a66597->clk);
        } else {
                r8a66597_bclr(r8a66597, PLLC, SYSCFG0);
                r8a66597_bclr(r8a66597, XCKE, SYSCFG0);
index b8dffd59eb256e52786328e5e4f1919846a80d9c..73f5208714a4a4d8270bd85acd1ec625fb9abf71 100644 (file)
@@ -128,7 +128,12 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
                 * any other sleep) on Haswell machines with LPT and LPT-LP
                 * with the new Intel BIOS
                 */
-               xhci->quirks |= XHCI_SPURIOUS_WAKEUP;
+               /* Limit the quirk to only known vendors, as this triggers
+                * yet another BIOS bug on some other machines
+                * https://bugzilla.kernel.org/show_bug.cgi?id=66171
+                */
+               if (pdev->subsystem_vendor == PCI_VENDOR_ID_HP)
+                       xhci->quirks |= XHCI_SPURIOUS_WAKEUP;
        }
        if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
                        pdev->device == PCI_DEVICE_ID_ASROCK_P67) {
index 1e2f3f4958436fb120b81d41632ad7e7c76fb5b5..53c2e296467fcabbb8139361f6b422829f97cae4 100644 (file)
@@ -2973,8 +2973,58 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
        }
 
        while (1) {
-               if (room_on_ring(xhci, ep_ring, num_trbs))
-                       break;
+               if (room_on_ring(xhci, ep_ring, num_trbs)) {
+                       union xhci_trb *trb = ep_ring->enqueue;
+                       unsigned int usable = ep_ring->enq_seg->trbs +
+                                       TRBS_PER_SEGMENT - 1 - trb;
+                       u32 nop_cmd;
+
+                       /*
+                        * Section 4.11.7.1 TD Fragments states that a link
+                        * TRB must only occur at the boundary between
+                        * data bursts (eg 512 bytes for 480M).
+                        * While it is possible to split a large fragment
+                        * we don't know the size yet.
+                        * Simplest solution is to fill the trb before the
+                        * LINK with nop commands.
+                        */
+                       if (num_trbs == 1 || num_trbs <= usable || usable == 0)
+                               break;
+
+                       if (ep_ring->type != TYPE_BULK)
+                               /*
+                                * While isoc transfers might have a buffer that
+                                * crosses a 64k boundary it is unlikely.
+                                * Since we can't add NOPs without generating
+                                * gaps in the traffic just hope it never
+                                * happens at the end of the ring.
+                                * This could be fixed by writing a LINK TRB
+                                * instead of the first NOP - however the
+                                * TRB_TYPE_LINK_LE32() calls would all need
+                                * changing to check the ring length.
+                                */
+                               break;
+
+                       if (num_trbs >= TRBS_PER_SEGMENT) {
+                               xhci_err(xhci, "Too many fragments %d, max %d\n",
+                                               num_trbs, TRBS_PER_SEGMENT - 1);
+                               return -ENOMEM;
+                       }
+
+                       nop_cmd = cpu_to_le32(TRB_TYPE(TRB_TR_NOOP) |
+                                       ep_ring->cycle_state);
+                       ep_ring->num_trbs_free -= usable;
+                       do {
+                               trb->generic.field[0] = 0;
+                               trb->generic.field[1] = 0;
+                               trb->generic.field[2] = 0;
+                               trb->generic.field[3] = nop_cmd;
+                               trb++;
+                       } while (--usable);
+                       ep_ring->enqueue = trb;
+                       if (room_on_ring(xhci, ep_ring, num_trbs))
+                               break;
+               }
 
                if (ep_ring == xhci->cmd_ring) {
                        xhci_err(xhci, "Do not support expand command ring\n");
index 0a43329569d178de72a5c8ee619e7206c360c51c..4d4499b8044971a8db410579f7965e9b6d862c38 100644 (file)
@@ -1809,7 +1809,6 @@ static void musb_free(struct musb *musb)
                        disable_irq_wake(musb->nIrq);
                free_irq(musb->nIrq, musb);
        }
-       cancel_work_sync(&musb->irq_work);
 
        musb_host_free(musb);
 }
@@ -1896,6 +1895,9 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
        musb_platform_disable(musb);
        musb_generic_disable(musb);
 
+       /* Init IRQ workqueue before request_irq */
+       INIT_WORK(&musb->irq_work, musb_irq_work);
+
        /* setup musb parts of the core (especially endpoints) */
        status = musb_core_init(plat->config->multipoint
                        ? MUSB_CONTROLLER_MHDRC
@@ -1905,9 +1907,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
 
        setup_timer(&musb->otg_timer, musb_otg_timer_func, (unsigned long) musb);
 
-       /* Init IRQ workqueue before request_irq */
-       INIT_WORK(&musb->irq_work, musb_irq_work);
-
        /* attach to the IRQ */
        if (request_irq(nIrq, musb->isr, 0, dev_name(dev), musb)) {
                dev_err(dev, "request_irq %d failed!\n", nIrq);
@@ -1981,6 +1980,7 @@ fail4:
        musb_host_cleanup(musb);
 
 fail3:
+       cancel_work_sync(&musb->irq_work);
        if (musb->dma_controller)
                dma_controller_destroy(musb->dma_controller);
 fail2_5:
@@ -2043,6 +2043,7 @@ static int musb_remove(struct platform_device *pdev)
        if (musb->dma_controller)
                dma_controller_destroy(musb->dma_controller);
 
+       cancel_work_sync(&musb->irq_work);
        musb_free(musb);
        device_init_wakeup(dev, 0);
        return 0;
index ff9d6de2b7465c949d54ae4801108a3800f4be3f..a12bd30401e076fe0e502789e300c05ecc770bb1 100644 (file)
@@ -38,6 +38,7 @@ struct cppi41_dma_channel {
        u32 prog_len;
        u32 transferred;
        u32 packet_sz;
+       struct list_head tx_check;
 };
 
 #define MUSB_DMA_NUM_CHANNELS 15
@@ -47,6 +48,8 @@ struct cppi41_dma_controller {
        struct cppi41_dma_channel rx_channel[MUSB_DMA_NUM_CHANNELS];
        struct cppi41_dma_channel tx_channel[MUSB_DMA_NUM_CHANNELS];
        struct musb *musb;
+       struct hrtimer early_tx;
+       struct list_head early_tx_list;
        u32 rx_mode;
        u32 tx_mode;
        u32 auto_req;
@@ -96,31 +99,27 @@ static void update_rx_toggle(struct cppi41_dma_channel *cppi41_channel)
        cppi41_channel->usb_toggle = toggle;
 }
 
-static void cppi41_dma_callback(void *private_data)
+static bool musb_is_tx_fifo_empty(struct musb_hw_ep *hw_ep)
 {
-       struct dma_channel *channel = private_data;
-       struct cppi41_dma_channel *cppi41_channel = channel->private_data;
-       struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
-       struct musb *musb = hw_ep->musb;
-       unsigned long flags;
-       struct dma_tx_state txstate;
-       u32 transferred;
+       u8              epnum = hw_ep->epnum;
+       struct musb     *musb = hw_ep->musb;
+       void __iomem    *epio = musb->endpoints[epnum].regs;
+       u16             csr;
 
-       spin_lock_irqsave(&musb->lock, flags);
+       csr = musb_readw(epio, MUSB_TXCSR);
+       if (csr & MUSB_TXCSR_TXPKTRDY)
+               return false;
+       return true;
+}
 
-       dmaengine_tx_status(cppi41_channel->dc, cppi41_channel->cookie,
-                       &txstate);
-       transferred = cppi41_channel->prog_len - txstate.residue;
-       cppi41_channel->transferred += transferred;
+static void cppi41_dma_callback(void *private_data);
 
-       dev_dbg(musb->controller, "DMA transfer done on hw_ep=%d bytes=%d/%d\n",
-               hw_ep->epnum, cppi41_channel->transferred,
-               cppi41_channel->total_len);
+static void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel)
+{
+       struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
+       struct musb *musb = hw_ep->musb;
 
-       update_rx_toggle(cppi41_channel);
-
-       if (cppi41_channel->transferred == cppi41_channel->total_len ||
-                       transferred < cppi41_channel->packet_sz) {
+       if (!cppi41_channel->prog_len) {
 
                /* done, complete */
                cppi41_channel->channel.actual_len =
@@ -150,13 +149,11 @@ static void cppi41_dma_callback(void *private_data)
                                remain_bytes,
                                direction,
                                DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-               if (WARN_ON(!dma_desc)) {
-                       spin_unlock_irqrestore(&musb->lock, flags);
+               if (WARN_ON(!dma_desc))
                        return;
-               }
 
                dma_desc->callback = cppi41_dma_callback;
-               dma_desc->callback_param = channel;
+               dma_desc->callback_param = &cppi41_channel->channel;
                cppi41_channel->cookie = dma_desc->tx_submit(dma_desc);
                dma_async_issue_pending(dc);
 
@@ -166,6 +163,117 @@ static void cppi41_dma_callback(void *private_data)
                        musb_writew(epio, MUSB_RXCSR, csr);
                }
        }
+}
+
+static enum hrtimer_restart cppi41_recheck_tx_req(struct hrtimer *timer)
+{
+       struct cppi41_dma_controller *controller;
+       struct cppi41_dma_channel *cppi41_channel, *n;
+       struct musb *musb;
+       unsigned long flags;
+       enum hrtimer_restart ret = HRTIMER_NORESTART;
+
+       controller = container_of(timer, struct cppi41_dma_controller,
+                       early_tx);
+       musb = controller->musb;
+
+       spin_lock_irqsave(&musb->lock, flags);
+       list_for_each_entry_safe(cppi41_channel, n, &controller->early_tx_list,
+                       tx_check) {
+               bool empty;
+               struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
+
+               empty = musb_is_tx_fifo_empty(hw_ep);
+               if (empty) {
+                       list_del_init(&cppi41_channel->tx_check);
+                       cppi41_trans_done(cppi41_channel);
+               }
+       }
+
+       if (!list_empty(&controller->early_tx_list)) {
+               ret = HRTIMER_RESTART;
+               hrtimer_forward_now(&controller->early_tx,
+                               ktime_set(0, 150 * NSEC_PER_USEC));
+       }
+
+       spin_unlock_irqrestore(&musb->lock, flags);
+       return ret;
+}
+
+static void cppi41_dma_callback(void *private_data)
+{
+       struct dma_channel *channel = private_data;
+       struct cppi41_dma_channel *cppi41_channel = channel->private_data;
+       struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
+       struct musb *musb = hw_ep->musb;
+       unsigned long flags;
+       struct dma_tx_state txstate;
+       u32 transferred;
+       bool empty;
+
+       spin_lock_irqsave(&musb->lock, flags);
+
+       dmaengine_tx_status(cppi41_channel->dc, cppi41_channel->cookie,
+                       &txstate);
+       transferred = cppi41_channel->prog_len - txstate.residue;
+       cppi41_channel->transferred += transferred;
+
+       dev_dbg(musb->controller, "DMA transfer done on hw_ep=%d bytes=%d/%d\n",
+               hw_ep->epnum, cppi41_channel->transferred,
+               cppi41_channel->total_len);
+
+       update_rx_toggle(cppi41_channel);
+
+       if (cppi41_channel->transferred == cppi41_channel->total_len ||
+                       transferred < cppi41_channel->packet_sz)
+               cppi41_channel->prog_len = 0;
+
+       empty = musb_is_tx_fifo_empty(hw_ep);
+       if (empty) {
+               cppi41_trans_done(cppi41_channel);
+       } else {
+               struct cppi41_dma_controller *controller;
+               /*
+                * On AM335x it has been observed that the TX interrupt fires
+                * too early that means the TXFIFO is not yet empty but the DMA
+                * engine says that it is done with the transfer. We don't
+                * receive a FIFO empty interrupt so the only thing we can do is
+                * to poll for the bit. On HS it usually takes 2us, on FS around
+                * 110us - 150us depending on the transfer size.
+                * We spin on HS (no longer than than 25us and setup a timer on
+                * FS to check for the bit and complete the transfer.
+                */
+               controller = cppi41_channel->controller;
+
+               if (musb->g.speed == USB_SPEED_HIGH) {
+                       unsigned wait = 25;
+
+                       do {
+                               empty = musb_is_tx_fifo_empty(hw_ep);
+                               if (empty)
+                                       break;
+                               wait--;
+                               if (!wait)
+                                       break;
+                               udelay(1);
+                       } while (1);
+
+                       empty = musb_is_tx_fifo_empty(hw_ep);
+                       if (empty) {
+                               cppi41_trans_done(cppi41_channel);
+                               goto out;
+                       }
+               }
+               list_add_tail(&cppi41_channel->tx_check,
+                               &controller->early_tx_list);
+               if (!hrtimer_active(&controller->early_tx)) {
+                       hrtimer_start_range_ns(&controller->early_tx,
+                               ktime_set(0, 140 * NSEC_PER_USEC),
+                               40 * NSEC_PER_USEC,
+                               HRTIMER_MODE_REL);
+               }
+       }
+out:
        spin_unlock_irqrestore(&musb->lock, flags);
 }
 
@@ -364,6 +472,8 @@ static int cppi41_is_compatible(struct dma_channel *channel, u16 maxpacket,
                WARN_ON(1);
                return 1;
        }
+       if (cppi41_channel->hw_ep->ep_in.type != USB_ENDPOINT_XFER_BULK)
+               return 0;
        if (cppi41_channel->is_tx)
                return 1;
        /* AM335x Advisory 1.0.13. No workaround for device RX mode */
@@ -388,6 +498,7 @@ static int cppi41_dma_channel_abort(struct dma_channel *channel)
        if (cppi41_channel->channel.status == MUSB_DMA_STATUS_FREE)
                return 0;
 
+       list_del_init(&cppi41_channel->tx_check);
        if (is_tx) {
                csr = musb_readw(epio, MUSB_TXCSR);
                csr &= ~MUSB_TXCSR_DMAENAB;
@@ -495,6 +606,7 @@ static int cppi41_dma_controller_start(struct cppi41_dma_controller *controller)
                cppi41_channel->controller = controller;
                cppi41_channel->port_num = port;
                cppi41_channel->is_tx = is_tx;
+               INIT_LIST_HEAD(&cppi41_channel->tx_check);
 
                musb_dma = &cppi41_channel->channel;
                musb_dma->private_data = cppi41_channel;
@@ -520,6 +632,7 @@ void dma_controller_destroy(struct dma_controller *c)
        struct cppi41_dma_controller *controller = container_of(c,
                        struct cppi41_dma_controller, controller);
 
+       hrtimer_cancel(&controller->early_tx);
        cppi41_dma_controller_stop(controller);
        kfree(controller);
 }
@@ -539,6 +652,9 @@ struct dma_controller *dma_controller_create(struct musb *musb,
        if (!controller)
                goto kzalloc_fail;
 
+       hrtimer_init(&controller->early_tx, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+       controller->early_tx.function = cppi41_recheck_tx_req;
+       INIT_LIST_HEAD(&controller->early_tx_list);
        controller->musb = musb;
 
        controller->controller.channel_alloc = cppi41_dma_channel_allocate;
index d2d3a173b31503b54f9071e9af48f4878567856f..32fb057c03f58e25f401bdb49755e2cdc2637e86 100644 (file)
@@ -1796,7 +1796,11 @@ int musb_gadget_setup(struct musb *musb)
 
        /* this "gadget" abstracts/virtualizes the controller */
        musb->g.name = musb_driver_name;
+#if IS_ENABLED(CONFIG_USB_MUSB_DUAL_ROLE)
        musb->g.is_otg = 1;
+#elif IS_ENABLED(CONFIG_USB_MUSB_GADGET)
+       musb->g.is_otg = 0;
+#endif
 
        musb_g_init_endpoints(musb);
 
index 6370e50649d7f732c640fd65879c26d82ec5f994..0e3c60cb669a63c7a1d1bb7bd673f212f854c425 100644 (file)
@@ -52,8 +52,7 @@ static int am335x_phy_probe(struct platform_device *pdev)
                return am_phy->id;
        }
 
-       ret = usb_phy_gen_create_phy(dev, &am_phy->usb_phy_gen,
-                       USB_PHY_TYPE_USB2, 0, false);
+       ret = usb_phy_gen_create_phy(dev, &am_phy->usb_phy_gen, NULL);
        if (ret)
                return ret;
 
@@ -66,8 +65,6 @@ static int am335x_phy_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, am_phy);
 
        return 0;
-
-       return ret;
 }
 
 static int am335x_phy_remove(struct platform_device *pdev)
index fce3a9e9bb5d282ff6b1a64492ad6a55c90e654f..aa6d37b3378ad65ff26e336031173a9ae52d2287 100644 (file)
@@ -48,8 +48,9 @@ void usb_nop_xceiv_register(void)
        if (pd)
                return;
        pd = platform_device_register_simple("usb_phy_gen_xceiv", -1, NULL, 0);
-       if (!pd) {
+       if (IS_ERR(pd)) {
                pr_err("Unable to register generic usb transceiver\n");
+               pd = NULL;
                return;
        }
 }
@@ -150,10 +151,40 @@ static int nop_set_host(struct usb_otg *otg, struct usb_bus *host)
 }
 
 int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop,
-               enum usb_phy_type type, u32 clk_rate, bool needs_vcc)
+               struct usb_phy_gen_xceiv_platform_data *pdata)
 {
+       enum usb_phy_type type = USB_PHY_TYPE_USB2;
        int err;
 
+       u32 clk_rate = 0;
+       bool needs_vcc = false;
+
+       nop->reset_active_low = true;   /* default behaviour */
+
+       if (dev->of_node) {
+               struct device_node *node = dev->of_node;
+               enum of_gpio_flags flags = 0;
+
+               if (of_property_read_u32(node, "clock-frequency", &clk_rate))
+                       clk_rate = 0;
+
+               needs_vcc = of_property_read_bool(node, "vcc-supply");
+               nop->gpio_reset = of_get_named_gpio_flags(node, "reset-gpios",
+                                                               0, &flags);
+               if (nop->gpio_reset == -EPROBE_DEFER)
+                       return -EPROBE_DEFER;
+
+               nop->reset_active_low = flags & OF_GPIO_ACTIVE_LOW;
+
+       } else if (pdata) {
+               type = pdata->type;
+               clk_rate = pdata->clk_rate;
+               needs_vcc = pdata->needs_vcc;
+               nop->gpio_reset = pdata->gpio_reset;
+       } else {
+               nop->gpio_reset = -1;
+       }
+
        nop->phy.otg = devm_kzalloc(dev, sizeof(*nop->phy.otg),
                        GFP_KERNEL);
        if (!nop->phy.otg)
@@ -218,43 +249,14 @@ EXPORT_SYMBOL_GPL(usb_phy_gen_create_phy);
 static int usb_phy_gen_xceiv_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
-       struct usb_phy_gen_xceiv_platform_data *pdata =
-                       dev_get_platdata(&pdev->dev);
        struct usb_phy_gen_xceiv        *nop;
-       enum usb_phy_type       type = USB_PHY_TYPE_USB2;
        int err;
-       u32 clk_rate = 0;
-       bool needs_vcc = false;
 
        nop = devm_kzalloc(dev, sizeof(*nop), GFP_KERNEL);
        if (!nop)
                return -ENOMEM;
 
-       nop->reset_active_low = true;   /* default behaviour */
-
-       if (dev->of_node) {
-               struct device_node *node = dev->of_node;
-               enum of_gpio_flags flags;
-
-               if (of_property_read_u32(node, "clock-frequency", &clk_rate))
-                       clk_rate = 0;
-
-               needs_vcc = of_property_read_bool(node, "vcc-supply");
-               nop->gpio_reset = of_get_named_gpio_flags(node, "reset-gpios",
-                                                               0, &flags);
-               if (nop->gpio_reset == -EPROBE_DEFER)
-                       return -EPROBE_DEFER;
-
-               nop->reset_active_low = flags & OF_GPIO_ACTIVE_LOW;
-
-       } else if (pdata) {
-               type = pdata->type;
-               clk_rate = pdata->clk_rate;
-               needs_vcc = pdata->needs_vcc;
-               nop->gpio_reset = pdata->gpio_reset;
-       }
-
-       err = usb_phy_gen_create_phy(dev, nop, type, clk_rate, needs_vcc);
+       err = usb_phy_gen_create_phy(dev, nop, dev_get_platdata(&pdev->dev));
        if (err)
                return err;
 
@@ -271,8 +273,6 @@ static int usb_phy_gen_xceiv_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, nop);
 
        return 0;
-
-       return err;
 }
 
 static int usb_phy_gen_xceiv_remove(struct platform_device *pdev)
index d2a220d81734ad5be296f56c3b416aa321bfb63e..38a81f307b8220bc5dfc81487a9fb420e397ccd1 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _PHY_GENERIC_H_
 #define _PHY_GENERIC_H_
 
+#include <linux/usb/usb_phy_gen_xceiv.h>
+
 struct usb_phy_gen_xceiv {
        struct usb_phy phy;
        struct device *dev;
@@ -14,6 +16,6 @@ int usb_gen_phy_init(struct usb_phy *phy);
 void usb_gen_phy_shutdown(struct usb_phy *phy);
 
 int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop,
-               enum usb_phy_type type, u32 clk_rate, bool needs_vcc);
+               struct usb_phy_gen_xceiv_platform_data *pdata);
 
 #endif
index fdd33b44dbd31b929eb13a2c0bd138570ccebc37..545844b7e7962f809f33812d9167f039b5fbc8d1 100644 (file)
@@ -164,7 +164,7 @@ static int mxs_phy_probe(struct platform_device *pdev)
 
        mxs_phy->clk = clk;
 
-       platform_set_drvdata(pdev, &mxs_phy->phy);
+       platform_set_drvdata(pdev, mxs_phy);
 
        ret = usb_add_phy_dev(&mxs_phy->phy);
        if (ret)
index a99a6953f11cc1988272b9ae2d4e917073eb458f..db3ab34cddb4cbc6be6df4e66596b11186235477 100644 (file)
@@ -107,10 +107,10 @@ static void __rcar_gen2_usb_phy_init(struct rcar_gen2_usb_phy_priv *priv)
        clk_prepare_enable(priv->clk);
 
        /* Set USB channels in the USBHS UGCTRL2 register */
-       val = ioread32(priv->base);
+       val = ioread32(priv->base + USBHS_UGCTRL2_REG);
        val &= ~(USBHS_UGCTRL2_USB0_HS | USBHS_UGCTRL2_USB2_SS);
        val |= priv->ugctrl2;
-       iowrite32(val, priv->base);
+       iowrite32(val, priv->base + USBHS_UGCTRL2_REG);
 }
 
 /* Shutdown USB channels */
index 82232acf1ab61b17cfbe9d084c3ed2188d554b18..bbe4f8e6e8d7492be10cc54cfe2f37e8001f2db6 100644 (file)
@@ -876,7 +876,7 @@ static int utmi_phy_probe(struct tegra_usb_phy *tegra_phy,
 
        tegra_phy->pad_regs = devm_ioremap(&pdev->dev, res->start,
                resource_size(res));
-       if (!tegra_phy->regs) {
+       if (!tegra_phy->pad_regs) {
                dev_err(&pdev->dev, "Failed to remap UTMI Pad regs\n");
                return -ENOMEM;
        }
index 30e8a61552d4d0526d999c0b49651593f04a5530..bad57ce77ba508e0f6ff8c07fa516e9477606a3c 100644 (file)
@@ -127,7 +127,8 @@ static inline int twl6030_writeb(struct twl6030_usb *twl, u8 module,
 
 static inline u8 twl6030_readb(struct twl6030_usb *twl, u8 module, u8 address)
 {
-       u8 data, ret = 0;
+       u8 data;
+       int ret;
 
        ret = twl_i2c_read_u8(module, &data, address);
        if (ret >= 0)
index 9ced8937a8f3a699dad340e1e9ea62c9d706dc69..fb0d537435eb221019babe694aafefd25b9e90cc 100644 (file)
@@ -2123,6 +2123,20 @@ static void ftdi_set_termios(struct tty_struct *tty,
                termios->c_cflag |= CRTSCTS;
        }
 
+       /*
+        * All FTDI UART chips are limited to CS7/8. We won't pretend to
+        * support CS5/6 and revert the CSIZE setting instead.
+        */
+       if ((C_CSIZE(tty) != CS8) && (C_CSIZE(tty) != CS7)) {
+               dev_warn(ddev, "requested CSIZE setting not supported\n");
+
+               termios->c_cflag &= ~CSIZE;
+               if (old_termios)
+                       termios->c_cflag |= old_termios->c_cflag & CSIZE;
+               else
+                       termios->c_cflag |= CS8;
+       }
+
        cflag = termios->c_cflag;
 
        if (!old_termios)
@@ -2159,19 +2173,16 @@ no_skip:
        } else {
                urb_value |= FTDI_SIO_SET_DATA_PARITY_NONE;
        }
-       if (cflag & CSIZE) {
-               switch (cflag & CSIZE) {
-               case CS7:
-                       urb_value |= 7;
-                       dev_dbg(ddev, "Setting CS7\n");
-                       break;
-               case CS8:
-                       urb_value |= 8;
-                       dev_dbg(ddev, "Setting CS8\n");
-                       break;
-               default:
-                       dev_err(ddev, "CSIZE was set but not CS7-CS8\n");
-               }
+       switch (cflag & CSIZE) {
+       case CS7:
+               urb_value |= 7;
+               dev_dbg(ddev, "Setting CS7\n");
+               break;
+       default:
+       case CS8:
+               urb_value |= 8;
+               dev_dbg(ddev, "Setting CS8\n");
+               break;
        }
 
        /* This is needed by the break command since it uses the same command
index 2b01ec8651c296e3f016bf2421040da6f1bbbc98..b63ce023f96f1ab7284e218ca68219da5f952440 100644 (file)
@@ -173,16 +173,8 @@ retry:
                clear_bit_unlock(USB_SERIAL_WRITE_BUSY, &port->flags);
                return result;
        }
-       /*
-        * Try sending off another urb, unless called from completion handler
-        * (in which case there will be no free urb or no data).
-        */
-       if (mem_flags != GFP_ATOMIC)
-               goto retry;
 
-       clear_bit_unlock(USB_SERIAL_WRITE_BUSY, &port->flags);
-
-       return 0;
+       goto retry;     /* try sending off another urb */
 }
 EXPORT_SYMBOL_GPL(usb_serial_generic_write_start);
 
@@ -208,7 +200,7 @@ int usb_serial_generic_write(struct tty_struct *tty,
                return 0;
 
        count = kfifo_in_locked(&port->write_fifo, buf, count, &port->lock);
-       result = usb_serial_generic_write_start(port, GFP_KERNEL);
+       result = usb_serial_generic_write_start(port, GFP_ATOMIC);
        if (result)
                return result;
 
index e5bdd987b9e8f7e260fc95c48b142742026999fa..a69da83604c03da3219c2340264cff08b456a404 100644 (file)
@@ -1813,25 +1813,25 @@ static void mos7840_change_port_settings(struct tty_struct *tty,
        iflag = tty->termios.c_iflag;
 
        /* Change the number of bits */
-       if (cflag & CSIZE) {
-               switch (cflag & CSIZE) {
-               case CS5:
-                       lData = LCR_BITS_5;
-                       break;
+       switch (cflag & CSIZE) {
+       case CS5:
+               lData = LCR_BITS_5;
+               break;
 
-               case CS6:
-                       lData = LCR_BITS_6;
-                       break;
+       case CS6:
+               lData = LCR_BITS_6;
+               break;
 
-               case CS7:
-                       lData = LCR_BITS_7;
-                       break;
-               default:
-               case CS8:
-                       lData = LCR_BITS_8;
-                       break;
-               }
+       case CS7:
+               lData = LCR_BITS_7;
+               break;
+
+       default:
+       case CS8:
+               lData = LCR_BITS_8;
+               break;
        }
+
        /* Change the Parity bit */
        if (cflag & PARENB) {
                if (cflag & PARODD) {
index c3d94853b4ab7a2dd13d8f6dea0009f55795ba56..cc7a24154490b29ebb39d4b9d3e72785c4320285 100644 (file)
@@ -85,6 +85,7 @@ static void option_instat_callback(struct urb *urb);
 #define HUAWEI_PRODUCT_K4505                   0x1464
 #define HUAWEI_PRODUCT_K3765                   0x1465
 #define HUAWEI_PRODUCT_K4605                   0x14C6
+#define HUAWEI_PRODUCT_E173S6                  0x1C07
 
 #define QUANTA_VENDOR_ID                       0x0408
 #define QUANTA_PRODUCT_Q101                    0xEA02
@@ -250,6 +251,7 @@ static void option_instat_callback(struct urb *urb);
 #define ZTE_PRODUCT_MF628                      0x0015
 #define ZTE_PRODUCT_MF626                      0x0031
 #define ZTE_PRODUCT_MC2718                     0xffe8
+#define ZTE_PRODUCT_AC2726                     0xfff1
 
 #define BENQ_VENDOR_ID                         0x04a5
 #define BENQ_PRODUCT_H10                       0x4068
@@ -572,6 +574,8 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c23, USB_CLASS_COMM, 0x02, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173, 0xff, 0xff, 0xff),
                .driver_info = (kernel_ulong_t) &net_intf1_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173S6, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t) &net_intf1_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1750, 0xff, 0xff, 0xff),
                .driver_info = (kernel_ulong_t) &net_intf2_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1441, USB_CLASS_COMM, 0x02, 0xff) },
@@ -634,6 +638,10 @@ static const struct usb_device_id option_ids[] = {
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6D) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6E) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6F) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x72) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x73) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x74) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x75) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x78) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x79) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x7A) },
@@ -688,6 +696,10 @@ static const struct usb_device_id option_ids[] = {
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6D) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6E) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6F) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x72) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x73) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x74) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x75) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x78) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x79) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7A) },
@@ -742,6 +754,10 @@ static const struct usb_device_id option_ids[] = {
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6D) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6E) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6F) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x72) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x73) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x74) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x75) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x78) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x79) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x7A) },
@@ -796,6 +812,10 @@ static const struct usb_device_id option_ids[] = {
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6D) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6E) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6F) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x72) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x73) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x74) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x75) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x78) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x79) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x7A) },
@@ -850,6 +870,10 @@ static const struct usb_device_id option_ids[] = {
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6D) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6E) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6F) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x72) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x73) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x74) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x75) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x78) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x79) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x7A) },
@@ -904,6 +928,10 @@ static const struct usb_device_id option_ids[] = {
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6D) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6E) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6F) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x72) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x73) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x74) },
+       { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x75) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x78) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x79) },
        { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x7A) },
@@ -1426,6 +1454,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x01) },
        { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x05) },
        { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x86, 0x10) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) },
 
        { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
        { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) },
index 1e6de4cd079d6a2c0e3b4b3c7679d6145bcf6f2c..1e3318dfa1cb569fcbd78ed2079ef026f33a8d16 100644 (file)
@@ -361,23 +361,21 @@ static void pl2303_set_termios(struct tty_struct *tty,
                            0, 0, buf, 7, 100);
        dev_dbg(&port->dev, "0xa1:0x21:0:0  %d - %7ph\n", i, buf);
 
-       if (C_CSIZE(tty)) {
-               switch (C_CSIZE(tty)) {
-               case CS5:
-                       buf[6] = 5;
-                       break;
-               case CS6:
-                       buf[6] = 6;
-                       break;
-               case CS7:
-                       buf[6] = 7;
-                       break;
-               default:
-               case CS8:
-                       buf[6] = 8;
-               }
-               dev_dbg(&port->dev, "data bits = %d\n", buf[6]);
+       switch (C_CSIZE(tty)) {
+       case CS5:
+               buf[6] = 5;
+               break;
+       case CS6:
+               buf[6] = 6;
+               break;
+       case CS7:
+               buf[6] = 7;
+               break;
+       default:
+       case CS8:
+               buf[6] = 8;
        }
+       dev_dbg(&port->dev, "data bits = %d\n", buf[6]);
 
        /* For reference buf[0]:buf[3] baud rate value */
        pl2303_encode_baudrate(tty, port, &buf[0]);
index 4abac28b5992a1f128005f5f7df103118a39b081..5b793c352267751ecd43cce1c7fae9e5a7fac624 100644 (file)
@@ -348,22 +348,20 @@ static void spcp8x5_set_termios(struct tty_struct *tty,
        }
 
        /* Set Data Length : 00:5bit, 01:6bit, 10:7bit, 11:8bit */
-       if (cflag & CSIZE) {
-               switch (cflag & CSIZE) {
-               case CS5:
-                       buf[1] |= SET_UART_FORMAT_SIZE_5;
-                       break;
-               case CS6:
-                       buf[1] |= SET_UART_FORMAT_SIZE_6;
-                       break;
-               case CS7:
-                       buf[1] |= SET_UART_FORMAT_SIZE_7;
-                       break;
-               default:
-               case CS8:
-                       buf[1] |= SET_UART_FORMAT_SIZE_8;
-                       break;
-               }
+       switch (cflag & CSIZE) {
+       case CS5:
+               buf[1] |= SET_UART_FORMAT_SIZE_5;
+               break;
+       case CS6:
+               buf[1] |= SET_UART_FORMAT_SIZE_6;
+               break;
+       case CS7:
+               buf[1] |= SET_UART_FORMAT_SIZE_7;
+               break;
+       default:
+       case CS8:
+               buf[1] |= SET_UART_FORMAT_SIZE_8;
+               break;
        }
 
        /* Set Stop bit2 : 0:1bit 1:2bit */
index fca4c752a4ed233199d82a787c0ebfbfff32e71c..eae2c873b39ff7dbb2ecd8d7624a1e2aec14e8ca 100644 (file)
@@ -281,8 +281,7 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x19d2, 0xfffd) },
        { USB_DEVICE(0x19d2, 0xfffc) },
        { USB_DEVICE(0x19d2, 0xfffb) },
-       /* AC2726, AC8710_V3 */
-       { USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0xfff1, 0xff, 0xff, 0xff) },
+       /* AC8710_V3 */
        { USB_DEVICE(0x19d2, 0xfff6) },
        { USB_DEVICE(0x19d2, 0xfff7) },
        { USB_DEVICE(0x19d2, 0xfff8) },
index e538b72c4e3af2d09153614952e12101eac03520..f14e7929ba2278dae601788ab4f07ae657e2e2bb 100644 (file)
@@ -97,18 +97,12 @@ static void wusbhc_devconnect_acked_work(struct work_struct *work);
 
 static void wusb_dev_free(struct wusb_dev *wusb_dev)
 {
-       if (wusb_dev) {
-               kfree(wusb_dev->set_gtk_req);
-               usb_free_urb(wusb_dev->set_gtk_urb);
-               kfree(wusb_dev);
-       }
+       kfree(wusb_dev);
 }
 
 static struct wusb_dev *wusb_dev_alloc(struct wusbhc *wusbhc)
 {
        struct wusb_dev *wusb_dev;
-       struct urb *urb;
-       struct usb_ctrlrequest *req;
 
        wusb_dev = kzalloc(sizeof(*wusb_dev), GFP_KERNEL);
        if (wusb_dev == NULL)
@@ -118,22 +112,6 @@ static struct wusb_dev *wusb_dev_alloc(struct wusbhc *wusbhc)
 
        INIT_WORK(&wusb_dev->devconnect_acked_work, wusbhc_devconnect_acked_work);
 
-       urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (urb == NULL)
-               goto err;
-       wusb_dev->set_gtk_urb = urb;
-
-       req = kmalloc(sizeof(*req), GFP_KERNEL);
-       if (req == NULL)
-               goto err;
-       wusb_dev->set_gtk_req = req;
-
-       req->bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE;
-       req->bRequest = USB_REQ_SET_DESCRIPTOR;
-       req->wValue = cpu_to_le16(USB_DT_KEY << 8 | wusbhc->gtk_index);
-       req->wIndex = 0;
-       req->wLength = cpu_to_le16(wusbhc->gtk.descr.bLength);
-
        return wusb_dev;
 err:
        wusb_dev_free(wusb_dev);
@@ -411,9 +389,6 @@ static void __wusbhc_dev_disconnect(struct wusbhc *wusbhc,
 /*
  * Refresh the list of keep alives to emit in the MMC
  *
- * Some devices don't respond to keep alives unless they've been
- * authenticated, so skip unauthenticated devices.
- *
  * We only publish the first four devices that have a coming timeout
  * condition. Then when we are done processing those, we go for the
  * next ones. We ignore the ones that have timed out already (they'll
@@ -448,7 +423,7 @@ static void __wusbhc_keep_alive(struct wusbhc *wusbhc)
 
                if (wusb_dev == NULL)
                        continue;
-               if (wusb_dev->usb_dev == NULL || !wusb_dev->usb_dev->authenticated)
+               if (wusb_dev->usb_dev == NULL)
                        continue;
 
                if (time_after(jiffies, wusb_dev->entry_ts + tt)) {
@@ -524,11 +499,19 @@ static struct wusb_dev *wusbhc_find_dev_by_addr(struct wusbhc *wusbhc, u8 addr)
  *
  * @wusbhc shall be referenced and unlocked
  */
-static void wusbhc_handle_dn_alive(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev)
+static void wusbhc_handle_dn_alive(struct wusbhc *wusbhc, u8 srcaddr)
 {
+       struct wusb_dev *wusb_dev;
+
        mutex_lock(&wusbhc->mutex);
-       wusb_dev->entry_ts = jiffies;
-       __wusbhc_keep_alive(wusbhc);
+       wusb_dev = wusbhc_find_dev_by_addr(wusbhc, srcaddr);
+       if (wusb_dev == NULL) {
+               dev_dbg(wusbhc->dev, "ignoring DN_Alive from unconnected device %02x\n",
+                       srcaddr);
+       } else {
+               wusb_dev->entry_ts = jiffies;
+               __wusbhc_keep_alive(wusbhc);
+       }
        mutex_unlock(&wusbhc->mutex);
 }
 
@@ -582,14 +565,22 @@ static void wusbhc_handle_dn_connect(struct wusbhc *wusbhc,
  *
  * @wusbhc shall be referenced and unlocked
  */
-static void wusbhc_handle_dn_disconnect(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev)
+static void wusbhc_handle_dn_disconnect(struct wusbhc *wusbhc, u8 srcaddr)
 {
        struct device *dev = wusbhc->dev;
-
-       dev_info(dev, "DN DISCONNECT: device 0x%02x going down\n", wusb_dev->addr);
+       struct wusb_dev *wusb_dev;
 
        mutex_lock(&wusbhc->mutex);
-       __wusbhc_dev_disconnect(wusbhc, wusb_port_by_idx(wusbhc, wusb_dev->port_idx));
+       wusb_dev = wusbhc_find_dev_by_addr(wusbhc, srcaddr);
+       if (wusb_dev == NULL) {
+               dev_dbg(dev, "ignoring DN DISCONNECT from unconnected device %02x\n",
+                       srcaddr);
+       } else {
+               dev_info(dev, "DN DISCONNECT: device 0x%02x going down\n",
+                       wusb_dev->addr);
+               __wusbhc_dev_disconnect(wusbhc, wusb_port_by_idx(wusbhc,
+                       wusb_dev->port_idx));
+       }
        mutex_unlock(&wusbhc->mutex);
 }
 
@@ -611,30 +602,21 @@ void wusbhc_handle_dn(struct wusbhc *wusbhc, u8 srcaddr,
                      struct wusb_dn_hdr *dn_hdr, size_t size)
 {
        struct device *dev = wusbhc->dev;
-       struct wusb_dev *wusb_dev;
 
        if (size < sizeof(struct wusb_dn_hdr)) {
                dev_err(dev, "DN data shorter than DN header (%d < %d)\n",
                        (int)size, (int)sizeof(struct wusb_dn_hdr));
                return;
        }
-
-       wusb_dev = wusbhc_find_dev_by_addr(wusbhc, srcaddr);
-       if (wusb_dev == NULL && dn_hdr->bType != WUSB_DN_CONNECT) {
-               dev_dbg(dev, "ignoring DN %d from unconnected device %02x\n",
-                       dn_hdr->bType, srcaddr);
-               return;
-       }
-
        switch (dn_hdr->bType) {
        case WUSB_DN_CONNECT:
                wusbhc_handle_dn_connect(wusbhc, dn_hdr, size);
                break;
        case WUSB_DN_ALIVE:
-               wusbhc_handle_dn_alive(wusbhc, wusb_dev);
+               wusbhc_handle_dn_alive(wusbhc, srcaddr);
                break;
        case WUSB_DN_DISCONNECT:
-               wusbhc_handle_dn_disconnect(wusbhc, wusb_dev);
+               wusbhc_handle_dn_disconnect(wusbhc, srcaddr);
                break;
        case WUSB_DN_MASAVAILCHANGED:
        case WUSB_DN_RWAKE:
index dd88441c8f7891e0d242e1107d6ff585a30999e4..4c40d0dbf53d45c35ae5b05798f1f09566ffc29e 100644 (file)
 #include <linux/export.h>
 #include "wusbhc.h"
 
-static void wusbhc_set_gtk_callback(struct urb *urb);
-static void wusbhc_gtk_rekey_done_work(struct work_struct *work);
+static void wusbhc_gtk_rekey_work(struct work_struct *work);
 
 int wusbhc_sec_create(struct wusbhc *wusbhc)
 {
        wusbhc->gtk.descr.bLength = sizeof(wusbhc->gtk.descr) + sizeof(wusbhc->gtk.data);
        wusbhc->gtk.descr.bDescriptorType = USB_DT_KEY;
        wusbhc->gtk.descr.bReserved = 0;
+       wusbhc->gtk_index = 0;
 
-       wusbhc->gtk_index = wusb_key_index(0, WUSB_KEY_INDEX_TYPE_GTK,
-                                          WUSB_KEY_INDEX_ORIGINATOR_HOST);
-
-       INIT_WORK(&wusbhc->gtk_rekey_done_work, wusbhc_gtk_rekey_done_work);
+       INIT_WORK(&wusbhc->gtk_rekey_work, wusbhc_gtk_rekey_work);
 
        return 0;
 }
@@ -113,7 +110,7 @@ int wusbhc_sec_start(struct wusbhc *wusbhc)
        wusbhc_generate_gtk(wusbhc);
 
        result = wusbhc->set_gtk(wusbhc, wusbhc->gtk_tkid,
-                                &wusbhc->gtk.descr.bKeyData, key_size);
+                               &wusbhc->gtk.descr.bKeyData, key_size);
        if (result < 0)
                dev_err(wusbhc->dev, "cannot set GTK for the host: %d\n",
                        result);
@@ -129,7 +126,7 @@ int wusbhc_sec_start(struct wusbhc *wusbhc)
  */
 void wusbhc_sec_stop(struct wusbhc *wusbhc)
 {
-       cancel_work_sync(&wusbhc->gtk_rekey_done_work);
+       cancel_work_sync(&wusbhc->gtk_rekey_work);
 }
 
 
@@ -185,12 +182,14 @@ static int wusb_dev_set_encryption(struct usb_device *usb_dev, int value)
 static int wusb_dev_set_gtk(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev)
 {
        struct usb_device *usb_dev = wusb_dev->usb_dev;
+       u8 key_index = wusb_key_index(wusbhc->gtk_index,
+               WUSB_KEY_INDEX_TYPE_GTK, WUSB_KEY_INDEX_ORIGINATOR_HOST);
 
        return usb_control_msg(
                usb_dev, usb_sndctrlpipe(usb_dev, 0),
                USB_REQ_SET_DESCRIPTOR,
                USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
-               USB_DT_KEY << 8 | wusbhc->gtk_index, 0,
+               USB_DT_KEY << 8 | key_index, 0,
                &wusbhc->gtk.descr, wusbhc->gtk.descr.bLength,
                1000);
 }
@@ -520,24 +519,55 @@ error_kzalloc:
  * Once all connected and authenticated devices have received the new
  * GTK, switch the host to using it.
  */
-static void wusbhc_gtk_rekey_done_work(struct work_struct *work)
+static void wusbhc_gtk_rekey_work(struct work_struct *work)
 {
-       struct wusbhc *wusbhc = container_of(work, struct wusbhc, gtk_rekey_done_work);
+       struct wusbhc *wusbhc = container_of(work,
+                                       struct wusbhc, gtk_rekey_work);
        size_t key_size = sizeof(wusbhc->gtk.data);
+       int port_idx;
+       struct wusb_dev *wusb_dev, *wusb_dev_next;
+       LIST_HEAD(rekey_list);
 
        mutex_lock(&wusbhc->mutex);
+       /* generate the new key */
+       wusbhc_generate_gtk(wusbhc);
+       /* roll the gtk index. */
+       wusbhc->gtk_index = (wusbhc->gtk_index + 1) % (WUSB_KEY_INDEX_MAX + 1);
+       /*
+        * Save all connected devices on a list while holding wusbhc->mutex and
+        * take a reference to each one.  Then submit the set key request to
+        * them after releasing the lock in order to avoid a deadlock.
+        */
+       for (port_idx = 0; port_idx < wusbhc->ports_max; port_idx++) {
+               wusb_dev = wusbhc->port[port_idx].wusb_dev;
+               if (!wusb_dev || !wusb_dev->usb_dev
+                       || !wusb_dev->usb_dev->authenticated)
+                       continue;
 
-       if (--wusbhc->pending_set_gtks == 0)
-               wusbhc->set_gtk(wusbhc, wusbhc->gtk_tkid, &wusbhc->gtk.descr.bKeyData, key_size);
-
+               wusb_dev_get(wusb_dev);
+               list_add_tail(&wusb_dev->rekey_node, &rekey_list);
+       }
        mutex_unlock(&wusbhc->mutex);
-}
 
-static void wusbhc_set_gtk_callback(struct urb *urb)
-{
-       struct wusbhc *wusbhc = urb->context;
+       /* Submit the rekey requests without holding wusbhc->mutex. */
+       list_for_each_entry_safe(wusb_dev, wusb_dev_next, &rekey_list,
+               rekey_node) {
+               list_del_init(&wusb_dev->rekey_node);
+               dev_dbg(&wusb_dev->usb_dev->dev, "%s: rekey device at port %d\n",
+                       __func__, wusb_dev->port_idx);
+
+               if (wusb_dev_set_gtk(wusbhc, wusb_dev) < 0) {
+                       dev_err(&wusb_dev->usb_dev->dev, "%s: rekey device at port %d failed\n",
+                               __func__, wusb_dev->port_idx);
+               }
+               wusb_dev_put(wusb_dev);
+       }
 
-       queue_work(wusbd, &wusbhc->gtk_rekey_done_work);
+       /* Switch the host controller to use the new GTK. */
+       mutex_lock(&wusbhc->mutex);
+       wusbhc->set_gtk(wusbhc, wusbhc->gtk_tkid,
+               &wusbhc->gtk.descr.bKeyData, key_size);
+       mutex_unlock(&wusbhc->mutex);
 }
 
 /**
@@ -553,26 +583,12 @@ static void wusbhc_set_gtk_callback(struct urb *urb)
  */
 void wusbhc_gtk_rekey(struct wusbhc *wusbhc)
 {
-       static const size_t key_size = sizeof(wusbhc->gtk.data);
-       int p;
-
-       wusbhc_generate_gtk(wusbhc);
-
-       for (p = 0; p < wusbhc->ports_max; p++) {
-               struct wusb_dev *wusb_dev;
-
-               wusb_dev = wusbhc->port[p].wusb_dev;
-               if (!wusb_dev || !wusb_dev->usb_dev || !wusb_dev->usb_dev->authenticated)
-                       continue;
-
-               usb_fill_control_urb(wusb_dev->set_gtk_urb, wusb_dev->usb_dev,
-                                    usb_sndctrlpipe(wusb_dev->usb_dev, 0),
-                                    (void *)wusb_dev->set_gtk_req,
-                                    &wusbhc->gtk.descr, wusbhc->gtk.descr.bLength,
-                                    wusbhc_set_gtk_callback, wusbhc);
-               if (usb_submit_urb(wusb_dev->set_gtk_urb, GFP_KERNEL) == 0)
-                       wusbhc->pending_set_gtks++;
-       }
-       if (wusbhc->pending_set_gtks == 0)
-               wusbhc->set_gtk(wusbhc, wusbhc->gtk_tkid, &wusbhc->gtk.descr.bKeyData, key_size);
+       /*
+        * We need to submit a URB to the downstream WUSB devices in order to
+        * change the group key.  This can't be done while holding the
+        * wusbhc->mutex since that is also taken in the urb_enqueue routine
+        * and will cause a deadlock.  Instead, queue a work item to do
+        * it when the lock is not held
+        */
+       queue_work(wusbd, &wusbhc->gtk_rekey_work);
 }
index 711b1952b114ab09322a2b11289cf7aa5fe0d433..6bd3b819a6b56b2c37f552ba5177f71df80cd626 100644 (file)
@@ -97,6 +97,7 @@ struct wusb_dev {
        struct kref refcnt;
        struct wusbhc *wusbhc;
        struct list_head cack_node;     /* Connect-Ack list */
+       struct list_head rekey_node;    /* GTK rekey list */
        u8 port_idx;
        u8 addr;
        u8 beacon_type:4;
@@ -107,8 +108,6 @@ struct wusb_dev {
        struct usb_wireless_cap_descriptor *wusb_cap_descr;
        struct uwb_mas_bm availability;
        struct work_struct devconnect_acked_work;
-       struct urb *set_gtk_urb;
-       struct usb_ctrlrequest *set_gtk_req;
        struct usb_device *usb_dev;
 };
 
@@ -296,8 +295,7 @@ struct wusbhc {
        } __attribute__((packed)) gtk;
        u8 gtk_index;
        u32 gtk_tkid;
-       struct work_struct gtk_rekey_done_work;
-       int pending_set_gtks;
+       struct work_struct gtk_rekey_work;
 
        struct usb_encryption_descriptor *ccm1_etd;
 };
index 831eb4fd197d4867f607a42b4ed76541159099ba..9a68409580d5b76d8d3972e42a33314dc22f16f8 100644 (file)
@@ -683,7 +683,7 @@ static int vhost_net_open(struct inode *inode, struct file *f)
        struct vhost_net *n = kmalloc(sizeof *n, GFP_KERNEL);
        struct vhost_dev *dev;
        struct vhost_virtqueue **vqs;
-       int r, i;
+       int i;
 
        if (!n)
                return -ENOMEM;
@@ -706,12 +706,7 @@ static int vhost_net_open(struct inode *inode, struct file *f)
                n->vqs[i].vhost_hlen = 0;
                n->vqs[i].sock_hlen = 0;
        }
-       r = vhost_dev_init(dev, vqs, VHOST_NET_VQ_MAX);
-       if (r < 0) {
-               kfree(n);
-               kfree(vqs);
-               return r;
-       }
+       vhost_dev_init(dev, vqs, VHOST_NET_VQ_MAX);
 
        vhost_poll_init(n->poll + VHOST_NET_VQ_TX, handle_tx_net, POLLOUT, dev);
        vhost_poll_init(n->poll + VHOST_NET_VQ_RX, handle_rx_net, POLLIN, dev);
index f175629513ed3dc0f5ad30eb3d8510506a894e1b..1e4c75c5b36bd3c9a394c755c39a291a0d2b831d 100644 (file)
@@ -1417,18 +1417,13 @@ static int vhost_scsi_open(struct inode *inode, struct file *f)
                vqs[i] = &vs->vqs[i].vq;
                vs->vqs[i].vq.handle_kick = vhost_scsi_handle_kick;
        }
-       r = vhost_dev_init(&vs->dev, vqs, VHOST_SCSI_MAX_VQ);
+       vhost_dev_init(&vs->dev, vqs, VHOST_SCSI_MAX_VQ);
 
        tcm_vhost_init_inflight(vs, NULL);
 
-       if (r < 0)
-               goto err_init;
-
        f->private_data = vs;
        return 0;
 
-err_init:
-       kfree(vqs);
 err_vqs:
        vhost_scsi_free(vs);
 err_vs:
index 339eae85859a58afbd6ea563b4b9fae3f667100c..c2a54fbf7f996e9065702a5aab1d284447c9785b 100644 (file)
@@ -104,7 +104,6 @@ static int vhost_test_open(struct inode *inode, struct file *f)
        struct vhost_test *n = kmalloc(sizeof *n, GFP_KERNEL);
        struct vhost_dev *dev;
        struct vhost_virtqueue **vqs;
-       int r;
 
        if (!n)
                return -ENOMEM;
@@ -117,12 +116,7 @@ static int vhost_test_open(struct inode *inode, struct file *f)
        dev = &n->dev;
        vqs[VHOST_TEST_VQ] = &n->vqs[VHOST_TEST_VQ];
        n->vqs[VHOST_TEST_VQ].handle_kick = handle_vq_kick;
-       r = vhost_dev_init(dev, vqs, VHOST_TEST_VQ_MAX);
-       if (r < 0) {
-               kfree(vqs);
-               kfree(n);
-               return r;
-       }
+       vhost_dev_init(dev, vqs, VHOST_TEST_VQ_MAX);
 
        f->private_data = n;
 
index 69068e0d8f31af183c075afe3026d60b09a0b55e..78987e481bc6a3e578f1ea5789802ae9b1ae7045 100644 (file)
@@ -290,7 +290,7 @@ static void vhost_dev_free_iovecs(struct vhost_dev *dev)
                vhost_vq_free_iovecs(dev->vqs[i]);
 }
 
-long vhost_dev_init(struct vhost_dev *dev,
+void vhost_dev_init(struct vhost_dev *dev,
                    struct vhost_virtqueue **vqs, int nvqs)
 {
        struct vhost_virtqueue *vq;
@@ -319,8 +319,6 @@ long vhost_dev_init(struct vhost_dev *dev,
                        vhost_poll_init(&vq->poll, vq->handle_kick,
                                        POLLIN, dev);
        }
-
-       return 0;
 }
 EXPORT_SYMBOL_GPL(vhost_dev_init);
 
index 4465ed5f316d6e9b36e1f43c05df1c980aa908ae..35eeb2a1badaf8e90e2af8215ff376b23a2e9853 100644 (file)
@@ -127,7 +127,7 @@ struct vhost_dev {
        struct task_struct *worker;
 };
 
-long vhost_dev_init(struct vhost_dev *, struct vhost_virtqueue **vqs, int nvqs);
+void vhost_dev_init(struct vhost_dev *, struct vhost_virtqueue **vqs, int nvqs);
 long vhost_dev_set_owner(struct vhost_dev *dev);
 bool vhost_dev_has_owner(struct vhost_dev *dev);
 long vhost_dev_check_owner(struct vhost_dev *);
index 0dac36ce09d6d74b7b33af1c15a70faffa72e792..518f790ef88a6d319e4d7fd806557c61741363dd 100644 (file)
@@ -3710,7 +3710,7 @@ default_chipset:
        if (!videomemory) {
                dev_warn(&pdev->dev,
                         "Unable to map videomem cached writethrough\n");
-               info->screen_base = (char *)ZTWO_VADDR(info->fix.smem_start);
+               info->screen_base = ZTWO_VADDR(info->fix.smem_start);
        } else
                info->screen_base = (char *)videomemory;
 
index 8521051cf946f0025a9cab15e4f8f880ac841016..cd961622f9c1aac941f33fb0053f192010cd6c09 100644 (file)
@@ -131,6 +131,7 @@ static const struct platform_device_id atmel_lcdfb_devtypes[] = {
                /* terminator */
        }
 };
+MODULE_DEVICE_TABLE(platform, atmel_lcdfb_devtypes);
 
 static struct atmel_lcdfb_config *
 atmel_lcdfb_get_config(struct platform_device *pdev)
index 5aab9b9dc2109be565005d77cbfed962046434b3..d992aa5eb3f0dc6557b23b4ec3e4868301c5ede8 100644 (file)
@@ -2256,7 +2256,7 @@ static int cirrusfb_zorro_register(struct zorro_dev *z,
 
        info->fix.mmio_start = regbase;
        cinfo->regbase = regbase > 16 * MB_ ? ioremap(regbase, 64 * 1024)
-                                           : (caddr_t)ZTWO_VADDR(regbase);
+                                           : ZTWO_VADDR(regbase);
        if (!cinfo->regbase) {
                dev_err(info->device, "Cannot map registers\n");
                error = -EIO;
@@ -2266,7 +2266,7 @@ static int cirrusfb_zorro_register(struct zorro_dev *z,
        info->fix.smem_start = rambase;
        info->screen_size = ramsize;
        info->screen_base = rambase > 16 * MB_ ? ioremap(rambase, ramsize)
-                                              : (caddr_t)ZTWO_VADDR(rambase);
+                                              : ZTWO_VADDR(rambase);
        if (!info->screen_base) {
                dev_err(info->device, "Cannot map video RAM\n");
                error = -EIO;
index 50c857477e4f1fff39527a4570fc4bf16a640c5e..65041e15fd598ec465c76369fe62cab480746655 100644 (file)
@@ -624,15 +624,15 @@ static int kyrofb_ioctl(struct fb_info *info,
                        return -EINVAL;
                }
        case KYRO_IOCTL_UVSTRIDE:
-               if (copy_to_user(argp, &deviceInfo.ulOverlayUVStride, sizeof(unsigned long)))
+               if (copy_to_user(argp, &deviceInfo.ulOverlayUVStride, sizeof(deviceInfo.ulOverlayUVStride)))
                        return -EFAULT;
                break;
        case KYRO_IOCTL_STRIDE:
-               if (copy_to_user(argp, &deviceInfo.ulOverlayStride, sizeof(unsigned long)))
+               if (copy_to_user(argp, &deviceInfo.ulOverlayStride, sizeof(deviceInfo.ulOverlayStride)))
                        return -EFAULT;
                break;
        case KYRO_IOCTL_OVERLAY_OFFSET:
-               if (copy_to_user(argp, &deviceInfo.ulOverlayOffset, sizeof(unsigned long)))
+               if (copy_to_user(argp, &deviceInfo.ulOverlayOffset, sizeof(deviceInfo.ulOverlayOffset)))
                        return -EFAULT;
                break;
        }
index 5bd2eb8d4f394b2122bf42bb1a1c42a71f440efe..cda7587cbc86ec0e2a6fa8a2ca90038ff71e155b 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/fb.h>
 
 #include <asm/setup.h>
-#include <asm/bootinfo.h>
 #include <asm/macintosh.h>
 #include <asm/io.h>
 
index 9dbea22234015b39845410dd1e651d61e06beb55..7d44d669d5b6decc8f986de2be5a120d408efb3a 100644 (file)
@@ -91,6 +91,15 @@ extern boot_infos_t *boot_infos;
 #define AVIVO_DC_LUTB_WHITE_OFFSET_GREEN        0x6cd4
 #define AVIVO_DC_LUTB_WHITE_OFFSET_RED          0x6cd8
 
+#define FB_RIGHT_POS(p, bpp)         (fb_be_math(p) ? 0 : (32 - (bpp)))
+
+static inline u32 offb_cmap_byteswap(struct fb_info *info, u32 value)
+{
+       u32 bpp = info->var.bits_per_pixel;
+
+       return cpu_to_be32(value) >> FB_RIGHT_POS(info, bpp);
+}
+
     /*
      *  Set a single color register. The values supplied are already
      *  rounded down to the hardware's capabilities (according to the
@@ -120,7 +129,7 @@ static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
                        mask <<= info->var.transp.offset;
                        value |= mask;
                }
-               pal[regno] = value;
+               pal[regno] = offb_cmap_byteswap(info, value);
                return 0;
        }
 
@@ -301,7 +310,7 @@ static struct fb_ops offb_ops = {
 static void __iomem *offb_map_reg(struct device_node *np, int index,
                                  unsigned long offset, unsigned long size)
 {
-       const u32 *addrp;
+       const __be32 *addrp;
        u64 asize, taddr;
        unsigned int flags;
 
@@ -369,7 +378,11 @@ static void offb_init_palette_hacks(struct fb_info *info, struct device_node *dp
                }
                of_node_put(pciparent);
        } else if (dp && of_device_is_compatible(dp, "qemu,std-vga")) {
-               const u32 io_of_addr[3] = { 0x01000000, 0x0, 0x0 };
+#ifdef __BIG_ENDIAN
+               const __be32 io_of_addr[3] = { 0x01000000, 0x0, 0x0 };
+#else
+               const __be32 io_of_addr[3] = { 0x00000001, 0x0, 0x0 };
+#endif
                u64 io_addr = of_translate_address(dp, io_of_addr);
                if (io_addr != OF_BAD_ADDR) {
                        par->cmap_adr = ioremap(io_addr + 0x3c8, 2);
@@ -535,7 +548,7 @@ static void __init offb_init_nodriver(struct device_node *dp, int no_real_node)
        unsigned int flags, rsize, addr_prop = 0;
        unsigned long max_size = 0;
        u64 rstart, address = OF_BAD_ADDR;
-       const u32 *pp, *addrp, *up;
+       const __be32 *pp, *addrp, *up;
        u64 asize;
        int foreign_endian = 0;
 
@@ -551,25 +564,25 @@ static void __init offb_init_nodriver(struct device_node *dp, int no_real_node)
        if (pp == NULL)
                pp = of_get_property(dp, "depth", &len);
        if (pp && len == sizeof(u32))
-               depth = *pp;
+               depth = be32_to_cpup(pp);
 
        pp = of_get_property(dp, "linux,bootx-width", &len);
        if (pp == NULL)
                pp = of_get_property(dp, "width", &len);
        if (pp && len == sizeof(u32))
-               width = *pp;
+               width = be32_to_cpup(pp);
 
        pp = of_get_property(dp, "linux,bootx-height", &len);
        if (pp == NULL)
                pp = of_get_property(dp, "height", &len);
        if (pp && len == sizeof(u32))
-               height = *pp;
+               height = be32_to_cpup(pp);
 
        pp = of_get_property(dp, "linux,bootx-linebytes", &len);
        if (pp == NULL)
                pp = of_get_property(dp, "linebytes", &len);
        if (pp && len == sizeof(u32) && (*pp != 0xffffffffu))
-               pitch = *pp;
+               pitch = be32_to_cpup(pp);
        else
                pitch = width * ((depth + 7) / 8);
 
index e6d56f714ae498ef896f77f1ece977cbf906c345..d94f35dbd5369e83a50265c78b421aac2ab300c7 100644 (file)
@@ -526,6 +526,8 @@ static int acx565akm_panel_power_on(struct omap_dss_device *dssdev)
        struct omap_dss_device *in = ddata->in;
        int r;
 
+       mutex_lock(&ddata->mutex);
+
        dev_dbg(&ddata->spi->dev, "%s\n", __func__);
 
        in->ops.sdi->set_timings(in, &ddata->videomode);
@@ -614,10 +616,7 @@ static int acx565akm_enable(struct omap_dss_device *dssdev)
        if (omapdss_device_is_enabled(dssdev))
                return 0;
 
-       mutex_lock(&ddata->mutex);
        r = acx565akm_panel_power_on(dssdev);
-       mutex_unlock(&ddata->mutex);
-
        if (r)
                return r;
 
index e0f098562a74b87eee790de505a8483a8a2024b7..a297de5cc859934209099e74fc54880a5f0620f3 100644 (file)
@@ -569,6 +569,7 @@ EXPORT_SYMBOL_GPL(sh_mobile_meram_cache_update);
  * Power management
  */
 
+#if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM_RUNTIME)
 static int sh_mobile_meram_suspend(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
@@ -611,6 +612,7 @@ static int sh_mobile_meram_resume(struct device *dev)
                meram_write_reg(priv->base, common_regs[i], priv->regs[i]);
        return 0;
 }
+#endif /* CONFIG_PM_SLEEP || CONFIG_PM_RUNTIME */
 
 static UNIVERSAL_DEV_PM_OPS(sh_mobile_meram_dev_pm_ops,
                            sh_mobile_meram_suspend,
index e287ebc47817da5e8dccd66ce40d028d92bb6c73..97cb9bd1d1ddb75f48abe8546c555f6160b7a0b1 100644 (file)
@@ -56,7 +56,6 @@
 #include <linux/cuda.h>
 #include <asm/io.h>
 #ifdef CONFIG_MAC
-#include <asm/bootinfo.h>
 #include <asm/macintosh.h>
 #else
 #include <asm/prom.h>
index b30e5a439d1f968679c4b0ce80eb918f7e1678b5..a8f2b280f796337df10aa430688f859bdf47b12f 100644 (file)
@@ -293,8 +293,7 @@ static int vt8500lcd_probe(struct platform_device *pdev)
                        + sizeof(u32) * 16, GFP_KERNEL);
        if (!fbi) {
                dev_err(&pdev->dev, "Failed to initialize framebuffer device\n");
-               ret = -ENOMEM;
-               goto failed;
+               return -ENOMEM;
        }
 
        strcpy(fbi->fb.fix.id, "VT8500 LCD");
@@ -327,15 +326,13 @@ static int vt8500lcd_probe(struct platform_device *pdev)
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (res == NULL) {
                dev_err(&pdev->dev, "no I/O memory resource defined\n");
-               ret = -ENODEV;
-               goto failed_fbi;
+               return -ENODEV;
        }
 
        res = request_mem_region(res->start, resource_size(res), "vt8500lcd");
        if (res == NULL) {
                dev_err(&pdev->dev, "failed to request I/O memory\n");
-               ret = -EBUSY;
-               goto failed_fbi;
+               return -EBUSY;
        }
 
        fbi->regbase = ioremap(res->start, resource_size(res));
@@ -346,17 +343,19 @@ static int vt8500lcd_probe(struct platform_device *pdev)
        }
 
        disp_timing = of_get_display_timings(pdev->dev.of_node);
-       if (!disp_timing)
-               return -EINVAL;
+       if (!disp_timing) {
+               ret = -EINVAL;
+               goto failed_free_io;
+       }
 
        ret = of_get_fb_videomode(pdev->dev.of_node, &of_mode,
                                                        OF_USE_NATIVE_MODE);
        if (ret)
-               return ret;
+               goto failed_free_io;
 
        ret = of_property_read_u32(pdev->dev.of_node, "bits-per-pixel", &bpp);
        if (ret)
-               return ret;
+               goto failed_free_io;
 
        /* try allocating the framebuffer */
        fb_mem_len = of_mode.xres * of_mode.yres * 2 * (bpp / 8);
@@ -364,7 +363,8 @@ static int vt8500lcd_probe(struct platform_device *pdev)
                                GFP_KERNEL);
        if (!fb_mem_virt) {
                pr_err("%s: Failed to allocate framebuffer\n", __func__);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto failed_free_io;
        }
 
        fbi->fb.fix.smem_start  = fb_mem_phys;
@@ -447,9 +447,6 @@ failed_free_io:
        iounmap(fbi->regbase);
 failed_free_res:
        release_mem_region(res->start, resource_size(res));
-failed_fbi:
-       kfree(fbi);
-failed:
        return ret;
 }
 
index c444654fc33fb6f7e858824eb8ed816186bf3bda..5c4a95b516cf9e576884c8f84e566f03b396facb 100644 (file)
@@ -285,7 +285,7 @@ static void update_balloon_size(struct virtio_balloon *vb)
 {
        __le32 actual = cpu_to_le32(vb->num_pages);
 
-       virtio_cwrite(vb->vdev, struct virtio_balloon_config, num_pages,
+       virtio_cwrite(vb->vdev, struct virtio_balloon_config, actual,
                      &actual);
 }
 
index a37c69941d30920649f6f25726ce72b038b752fd..a416f9b2a7f6ddf616e3a396e50b8a413962aff8 100644 (file)
@@ -742,7 +742,6 @@ static int virtio_pci_probe(struct pci_dev *pci_dev,
        return 0;
 
 out_set_drvdata:
-       pci_set_drvdata(pci_dev, NULL);
        pci_iounmap(pci_dev, vp_dev->ioaddr);
 out_req_regions:
        pci_release_regions(pci_dev);
@@ -760,7 +759,6 @@ static void virtio_pci_remove(struct pci_dev *pci_dev)
        unregister_virtio_device(&vp_dev->vdev);
 
        vp_del_vqs(&vp_dev->vdev);
-       pci_set_drvdata(pci_dev, NULL);
        pci_iounmap(pci_dev, vp_dev->ioaddr);
        pci_release_regions(pci_dev);
        pci_disable_device(pci_dev);
index fbb7b94cabfd5816e7532fe0093b579b831b63a8..3a17fbd39f8aed015f00ecafdbb5839a2e8296f4 100644 (file)
@@ -301,7 +301,7 @@ static int ali_notify_sys(struct notifier_block *this,
  *     want to register another driver on the same PCI id.
  */
 
-static DEFINE_PCI_DEVICE_TABLE(ali_pci_tbl) __used = {
+static const struct pci_device_id ali_pci_tbl[] __used = {
        { PCI_VENDOR_ID_AL, 0x1533, PCI_ANY_ID, PCI_ANY_ID,},
        { PCI_VENDOR_ID_AL, 0x1535, PCI_ANY_ID, PCI_ANY_ID,},
        { 0, },
index 12f0b762b528948b15e30fab605860a34c01ba57..996b2f7d330e94ec3143e6bebe0c86f74e162943 100644 (file)
@@ -414,7 +414,7 @@ err_out:
 module_init(alim7101_wdt_init);
 module_exit(alim7101_wdt_unload);
 
-static DEFINE_PCI_DEVICE_TABLE(alim7101_pci_tbl) __used = {
+static const struct pci_device_id alim7101_pci_tbl[] __used = {
        { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533) },
        { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) },
        { }
index a6a2cebb25879242b8408b1537838a67d932b2b3..cafa973c43be7af984fb9d39456b1d36b8913ea8 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/watchdog.h>
 #include <linux/platform_device.h>
 #include <linux/of_address.h>
-#include <linux/miscdevice.h>
 
 #define PM_RSTC                                0x1c
 #define PM_WDOG                                0x24
index 833e813118489216a8a27901f749f0765bd03e8f..d1d07f2f69df7cf61cd838feaa89650c22908098 100644 (file)
@@ -28,7 +28,6 @@
 
 #include <linux/platform_device.h>
 #include <linux/module.h>
-#include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/timer.h>
 #include <linux/io.h>
index 45b979d9dd13acf223ac4ede12262c51fe6e1e9d..4f1c3e0459ffe0dbe783a1c766252cc251b8a971 100644 (file)
@@ -55,7 +55,7 @@ static void __iomem *pci_mem_addr;            /* the PCI-memory address */
 static unsigned long __iomem *hpwdt_timer_reg;
 static unsigned long __iomem *hpwdt_timer_con;
 
-static DEFINE_PCI_DEVICE_TABLE(hpwdt_devices) = {
+static const struct pci_device_id hpwdt_devices[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xB203) },   /* iLO2 */
        { PCI_DEVICE(PCI_VENDOR_ID_HP, 0x3306) },       /* iLO3 */
        {0},                    /* terminate list */
index a72fe9361ddf028ef717959183cc5bdfc3ea0478..25a2bfdb4e9d2e41812b676e4b93b0c4219c47a9 100644 (file)
@@ -334,7 +334,7 @@ static struct miscdevice esb_miscdev = {
 /*
  * Data for PCI driver interface
  */
-static DEFINE_PCI_DEVICE_TABLE(esb_pci_tbl) = {
+static const struct pci_device_id esb_pci_tbl[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_9), },
        { 0, },                 /* End of list */
 };
index 70a240297c6d22f2a7d170a731f70320512f478a..07f88f54e5c03008159a5a276056340e65058086 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/watchdog.h>
-#include <linux/miscdevice.h>
 #include <linux/seq_file.h>
 #include <linux/debugfs.h>
 #include <linux/uaccess.h>
index 2de486a7eea18a058808cbb33a0ec0fa5f3a650b..3aa50cfa335fda1576950451a492a92336da41cd 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
index a1a3638c579c857c382ec9c253e5f69424e1dbbb..20dc73844737a99cf30aa6852f6bfceb06d04984 100644 (file)
@@ -26,7 +26,6 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/miscdevice.h>
 #include <linux/uaccess.h>
 #include <linux/watchdog.h>
 #include <linux/platform_device.h>
index 6d4f3998e1f6c08e7158fdf1068b3a94c3bad448..bdb3f4a5b27c760b5c7509f957213037e234e2be 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/init.h>
 #include <linux/bitops.h>
index 231e5b9d5c8e079ec424b9331aca90912f42efae..0b9ec61e131330524e417197304702baaebdf272 100644 (file)
@@ -289,7 +289,7 @@ static struct miscdevice nv_tco_miscdev = {
  * register a pci_driver, because someone else might one day
  * want to register another driver on the same PCI id.
  */
-static DEFINE_PCI_DEVICE_TABLE(tco_pci_tbl) = {
+static const struct pci_device_id tco_pci_tbl[] = {
        { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS,
          PCI_ANY_ID, PCI_ANY_ID, },
        { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS,
index 44edca66d564195a8e20b54f20c8b4cc389eca2c..f7722a42467632030b4d36dc608e1af7cf497002 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/miscdevice.h>
 #include <linux/platform_device.h>
 #include <linux/watchdog.h>
 #include <linux/init.h>
index b4864f254b48940b7fd9b7febb368b6608af4716..c0d07eef2640b9cb0f2469acda6a579e57a16d94 100644 (file)
@@ -801,7 +801,7 @@ static void pcipcwd_card_exit(struct pci_dev *pdev)
        cards_found--;
 }
 
-static DEFINE_PCI_DEVICE_TABLE(pcipcwd_pci_tbl) = {
+static const struct pci_device_id pcipcwd_pci_tbl[] = {
        { PCI_VENDOR_ID_QUICKLOGIC, PCI_DEVICE_ID_WATCHDOG_PCIPCWD,
                PCI_ANY_ID, PCI_ANY_ID, },
        { 0 },                  /* End of list */
index 1bdcc313e1d9f713dc24c8b4cf7e2f7e9c312574..5bec20f5dc2db29ec5294bbdf03ee7b8106cb21a 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
index 53d37fea183e1b5be5f2f18093a1c4021e632bc9..d92c2d5859ce9f67c4af0f2c61fcbe6c8c396e74 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/watchdog.h>
-#include <linux/miscdevice.h>
 #include <linux/moduleparam.h>
 #include <linux/platform_device.h>
 
index 3b9fff9dcf654ba6abfb09f970a7d288147d7083..131193a7acdfd0bb07660095e0ff57c500eed6cb 100644 (file)
@@ -409,8 +409,9 @@ static int __init sc1200wdt_init(void)
 #if defined CONFIG_PNP
        /* now that the user has specified an IO port and we haven't detected
         * any devices, disable pnp support */
+       if (isapnp)
+               pnp_unregister_driver(&scl200wdt_pnp_driver);
        isapnp = 0;
-       pnp_unregister_driver(&scl200wdt_pnp_driver);
 #endif
 
        if (!request_region(io, io_len, SC1200_MODULE_NAME)) {
index f9b8e06f355808e763ca7a1f7f2e4511fe33c88f..af3528f84d65469196d2a409dbcfc531a09e57c6 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/spinlock.h>
-#include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/pm_runtime.h>
 #include <linux/fs.h>
index ef2638fee4a8f7037c1f7c342ec1be1347ee3957..c04a1aa158e25762fcbe2b161052beaf56897d7f 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/timer.h>
-#include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/notifier.h>
 #include <linux/reboot.h>
index ce63a1bbf395fa94ea5833aa0eb98d84aaa5dc75..5cca9cddb87d188f19a33e8e3b6a2fc2851f8a36 100644 (file)
@@ -303,7 +303,7 @@ static struct miscdevice sp5100_tco_miscdev = {
  * register a pci_driver, because someone else might
  * want to register another driver on the same PCI id.
  */
-static DEFINE_PCI_DEVICE_TABLE(sp5100_tco_pci_tbl) = {
+static const struct pci_device_id sp5100_tco_pci_tbl[] = {
        { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS, PCI_ANY_ID,
          PCI_ANY_ID, },
        { 0, },                 /* End of list */
index d667f6b51d35f93aba02547f82653f3dbb189aa4..bb64ae3f47da58079ac816bde0d5c9abac5f0bff 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/platform_device.h>
 #include <linux/stmp3xxx_rtc_wdt.h>
index 0fd0e8ae62a833b462b29bd09f8f5e7666e437bf..6a447e321dd0c3cf076169d7eac3c7b887a4b96b 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
-#include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
index e029b5768f2c1379279f034dc24c892b52fc0ec3..5aed9d7ad47e6ee81e96b4f16b15aa653a6a9482 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/moduleparam.h>
-#include <linux/miscdevice.h>
 #include <linux/err.h>
 #include <linux/uaccess.h>
 #include <linux/watchdog.h>
index 1a68f760cf866a1da43ce6d6a9978daf7ec0d736..d2cd9f0bcb9a2df915472446f295139f04fc0ede 100644 (file)
@@ -239,7 +239,7 @@ static void wdt_remove(struct pci_dev *pdev)
        pci_disable_device(pdev);
 }
 
-static DEFINE_PCI_DEVICE_TABLE(wdt_pci_table) = {
+static const struct pci_device_id wdt_pci_table[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_CX700) },
        { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX800) },
        { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855) },
index ee89ba4dea63c932ecad137b49712191b9a9b799..3dc578e7121110bea28748b16c7a44b6817a566f 100644 (file)
@@ -720,7 +720,7 @@ static void wdtpci_remove_one(struct pci_dev *pdev)
 }
 
 
-static DEFINE_PCI_DEVICE_TABLE(wdtpci_pci_tbl) = {
+static const struct pci_device_id wdtpci_pci_tbl[] = {
        {
                .vendor    = PCI_VENDOR_ID_ACCESSIO,
                .device    = PCI_DEVICE_ID_ACCESSIO_WDG_CSM,
index c794ea1821402dc21e47af3d8b398c9d4f3209e6..12ba6db651427aa6bf11c9cc4e2d219157c03828 100644 (file)
@@ -222,7 +222,7 @@ config XEN_ACPI_PROCESSOR
 
          To do that the driver parses the Power Management data and uploads
          said information to the Xen hypervisor. Then the Xen hypervisor can
-         select the proper Cx and Pxx states. It also registers itslef as the
+         select the proper Cx and Pxx states. It also registers itself as the
          SMM so that other drivers (such as ACPI cpufreq scaling driver) will
          not load.
 
index 62ccf5424ba857e0fe11bb22187bb7dd5d3dad6c..028387192b608b04a9fd9483a9916404cb861f76 100644 (file)
@@ -930,9 +930,10 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
                ret = m2p_add_override(mfn, pages[i], kmap_ops ?
                                       &kmap_ops[i] : NULL);
                if (ret)
-                       return ret;
+                       goto out;
        }
 
+ out:
        if (lazy)
                arch_leave_lazy_mmu_mode();
 
@@ -969,9 +970,10 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
                ret = m2p_remove_override(pages[i], kmap_ops ?
                                       &kmap_ops[i] : NULL);
                if (ret)
-                       return ret;
+                       goto out;
        }
 
+ out:
        if (lazy)
                arch_leave_lazy_mmu_mode();
 
index a224bc74b6b9d34fa5c45f41408a3ed1138098f4..1eac0731c349f2067b42dea6e01f292453096d4b 100644 (file)
@@ -555,6 +555,11 @@ xen_swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
                                sg_dma_len(sgl) = 0;
                                return 0;
                        }
+                       xen_dma_map_page(hwdev, pfn_to_page(map >> PAGE_SHIFT),
+                                               map & ~PAGE_MASK,
+                                               sg->length,
+                                               dir,
+                                               attrs);
                        sg->dma_address = xen_phys_to_bus(map);
                } else {
                        /* we are not interested in the dma_addr returned by
index 8dae6c13063af5df3846d0c3a700876fe23eefe0..80875fb770ed931681c75db5aa4209c15acfc7a7 100644 (file)
 #include <linux/cpu.h>
 #include <linux/acpi.h>
 #include <linux/uaccess.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
 #include <acpi/processor.h>
-
 #include <xen/acpi.h>
 #include <xen/interface/platform.h>
 #include <asm/xen/hypercall.h>
@@ -269,7 +266,8 @@ static void acpi_processor_hotplug_notify(acpi_handle handle,
                if (!is_processor_present(handle))
                        break;
 
-               if (!acpi_bus_get_device(handle, &device))
+               acpi_bus_get_device(handle, &device);
+               if (acpi_device_enumerated(device))
                        break;
 
                result = acpi_bus_scan(handle);
@@ -277,8 +275,9 @@ static void acpi_processor_hotplug_notify(acpi_handle handle,
                        pr_err(PREFIX "Unable to add the device\n");
                        break;
                }
-               result = acpi_bus_get_device(handle, &device);
-               if (result) {
+               device = NULL;
+               acpi_bus_get_device(handle, &device);
+               if (!acpi_device_enumerated(device)) {
                        pr_err(PREFIX "Missing device object\n");
                        break;
                }
index 9083f1e474f801c07c1531551fa971b5e0e21b38..f8d18626969a48819ae5810f1d424dc4eacf3f31 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/acpi.h>
-#include <acpi/acpi_drivers.h>
 #include <xen/acpi.h>
 #include <xen/interface/platform.h>
 #include <asm/xen/hypercall.h>
@@ -169,7 +168,7 @@ static int acpi_memory_get_device(acpi_handle handle,
        acpi_scan_lock_acquire();
 
        acpi_bus_get_device(handle, &device);
-       if (device)
+       if (acpi_device_enumerated(device))
                goto end;
 
        /*
@@ -182,8 +181,9 @@ static int acpi_memory_get_device(acpi_handle handle,
                result = -EINVAL;
                goto out;
        }
-       result = acpi_bus_get_device(handle, &device);
-       if (result) {
+       device = NULL;
+       acpi_bus_get_device(handle, &device);
+       if (!acpi_device_enumerated(device)) {
                pr_warn(PREFIX "Missing device object\n");
                result = -EINVAL;
                goto out;
index 59708fdd068bdfed83976dab53a823115efeda29..40c4bc06b5fa0929af0b9b8ffddd9d59e6bcbc36 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
-#include <asm/xen/hypercall.h>
+#include <linux/acpi.h>
 #include <xen/interface/version.h>
 #include <xen/xen-ops.h>
+#include <asm/xen/hypercall.h>
 
 #define ACPI_PROCESSOR_AGGREGATOR_CLASS        "acpi_pad"
 #define ACPI_PROCESSOR_AGGREGATOR_DEVICE_NAME "Processor Aggregator"
index 13bc6c31c060bfc9821eb23eb467873b720c6f13..7231859119f1f126ac89e606ecc7c96c1a6a55c3 100644 (file)
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/syscore_ops.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
 #include <acpi/processor.h>
-
 #include <xen/xen.h>
 #include <xen/interface/platform.h>
 #include <asm/xen/hypercall.h>
index f62172603215ed433a32f7945603c95bf05783c2..7dc5332ff9842bfe1f119f4ff003056430959ec3 100644 (file)
@@ -2,8 +2,9 @@
 # Makefile for the Zorro bus specific drivers.
 #
 
-obj-$(CONFIG_ZORRO)    += zorro.o zorro-driver.o zorro-sysfs.o names.o
+obj-$(CONFIG_ZORRO)    += zorro.o zorro-driver.o zorro-sysfs.o
 obj-$(CONFIG_PROC_FS)  += proc.o
+obj-$(CONFIG_ZORRO_NAMES) +=  names.o
 
 hostprogs-y            := gen-devlist
 
index e8517c3d8e82df3d9b34f9049a29bdedd0a61b0e..6f3fd9903ac387f8d354c843ae88950b45bcfcfb 100644 (file)
@@ -15,8 +15,6 @@
 #include <linux/zorro.h>
 
 
-#ifdef CONFIG_ZORRO_NAMES
-
 struct zorro_prod_info {
        __u16 prod;
        unsigned short seen;
@@ -69,7 +67,6 @@ void __init zorro_name_device(struct zorro_dev *dev)
        } while (--i);
 
        /* Couldn't find either the manufacturer nor the product */
-       sprintf(name, "Zorro device %08x", dev->id);
        return;
 
        match_manuf: {
@@ -98,11 +95,3 @@ void __init zorro_name_device(struct zorro_dev *dev)
                }
        }
 }
-
-#else
-
-void __init zorro_name_device(struct zorro_dev *dev)
-{
-}
-
-#endif
index ea1ce822a8e0437120184a8e559bd0495860c7b7..6ac2579da0ebb1355450474204807701e47e2e08 100644 (file)
@@ -14,6 +14,8 @@
 #include <linux/seq_file.h>
 #include <linux/init.h>
 #include <linux/export.h>
+
+#include <asm/byteorder.h>
 #include <asm/uaccess.h>
 #include <asm/amigahw.h>
 #include <asm/setup.h>
@@ -41,10 +43,10 @@ proc_bus_zorro_read(struct file *file, char __user *buf, size_t nbytes, loff_t *
        /* Construct a ConfigDev */
        memset(&cd, 0, sizeof(cd));
        cd.cd_Rom = z->rom;
-       cd.cd_SlotAddr = z->slotaddr;
-       cd.cd_SlotSize = z->slotsize;
-       cd.cd_BoardAddr = (void *)zorro_resource_start(z);
-       cd.cd_BoardSize = zorro_resource_len(z);
+       cd.cd_SlotAddr = cpu_to_be16(z->slotaddr);
+       cd.cd_SlotSize = cpu_to_be16(z->slotsize);
+       cd.cd_BoardAddr = cpu_to_be32(zorro_resource_start(z));
+       cd.cd_BoardSize = cpu_to_be32(zorro_resource_len(z));
 
        if (copy_to_user(buf, (void *)&cd + pos, nbytes))
                return -EFAULT;
index ac1db7f1bcab7731e9366cfc4bce832c4258cd35..eacae1434b73fd7472e2d81b5b86ebc214f3e6af 100644 (file)
@@ -161,11 +161,12 @@ static int zorro_uevent(struct device *dev, struct kobj_uevent_env *env)
 }
 
 struct bus_type zorro_bus_type = {
-       .name   = "zorro",
-       .match  = zorro_bus_match,
-       .uevent = zorro_uevent,
-       .probe  = zorro_device_probe,
-       .remove = zorro_device_remove,
+       .name     = "zorro",
+       .dev_name = "zorro",
+       .match    = zorro_bus_match,
+       .uevent   = zorro_uevent,
+       .probe    = zorro_device_probe,
+       .remove   = zorro_device_remove,
 };
 EXPORT_SYMBOL(zorro_bus_type);
 
index 26f7184ef9e1a19cb47890bcbfaa124c6c34912b..36b210f9b6b29621fa9e410db063d3df53d7fb75 100644 (file)
@@ -16,6 +16,8 @@
 #include <linux/stat.h>
 #include <linux/string.h>
 
+#include <asm/byteorder.h>
+
 #include "zorro.h"
 
 
@@ -33,10 +35,20 @@ static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);
 
 zorro_config_attr(id, id, "0x%08x\n");
 zorro_config_attr(type, rom.er_Type, "0x%02x\n");
-zorro_config_attr(serial, rom.er_SerialNumber, "0x%08x\n");
 zorro_config_attr(slotaddr, slotaddr, "0x%04x\n");
 zorro_config_attr(slotsize, slotsize, "0x%04x\n");
 
+static ssize_t
+show_serial(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct zorro_dev *z;
+
+       z = to_zorro_dev(dev);
+       return sprintf(buf, "0x%08x\n", be32_to_cpu(z->rom.er_SerialNumber));
+}
+
+static DEVICE_ATTR(serial, S_IRUGO, show_serial, NULL);
+
 static ssize_t zorro_show_resource(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct zorro_dev *z = to_zorro_dev(dev);
@@ -60,10 +72,10 @@ static ssize_t zorro_read_config(struct file *filp, struct kobject *kobj,
        /* Construct a ConfigDev */
        memset(&cd, 0, sizeof(cd));
        cd.cd_Rom = z->rom;
-       cd.cd_SlotAddr = z->slotaddr;
-       cd.cd_SlotSize = z->slotsize;
-       cd.cd_BoardAddr = (void *)zorro_resource_start(z);
-       cd.cd_BoardSize = zorro_resource_len(z);
+       cd.cd_SlotAddr = cpu_to_be16(z->slotaddr);
+       cd.cd_SlotSize = cpu_to_be16(z->slotsize);
+       cd.cd_BoardAddr = cpu_to_be32(zorro_resource_start(z));
+       cd.cd_BoardSize = cpu_to_be32(zorro_resource_len(z));
 
        return memory_read_from_buffer(buf, count, &off, &cd, sizeof(cd));
 }
index 858c9714b2f390a26e1a1450f196d7abf6e14340..707c1a5a031703ba1b7e8de9f87e71103d217a18 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 
+#include <asm/byteorder.h>
 #include <asm/setup.h>
 #include <asm/amigahw.h>
 
@@ -29,7 +30,8 @@
      */
 
 unsigned int zorro_num_autocon;
-struct zorro_dev zorro_autocon[ZORRO_NUM_AUTO];
+struct zorro_dev_init zorro_autocon_init[ZORRO_NUM_AUTO] __initdata;
+struct zorro_dev *zorro_autocon;
 
 
     /*
@@ -38,6 +40,7 @@ struct zorro_dev zorro_autocon[ZORRO_NUM_AUTO];
 
 struct zorro_bus {
        struct device dev;
+       struct zorro_dev devices[0];
 };
 
 
@@ -125,18 +128,22 @@ static struct resource __init *zorro_find_parent_resource(
 static int __init amiga_zorro_probe(struct platform_device *pdev)
 {
        struct zorro_bus *bus;
+       struct zorro_dev_init *zi;
        struct zorro_dev *z;
        struct resource *r;
        unsigned int i;
        int error;
 
        /* Initialize the Zorro bus */
-       bus = kzalloc(sizeof(*bus), GFP_KERNEL);
+       bus = kzalloc(sizeof(*bus) +
+                     zorro_num_autocon * sizeof(bus->devices[0]),
+                     GFP_KERNEL);
        if (!bus)
                return -ENOMEM;
 
+       zorro_autocon = bus->devices;
        bus->dev.parent = &pdev->dev;
-       dev_set_name(&bus->dev, "zorro");
+       dev_set_name(&bus->dev, zorro_bus_type.name);
        error = device_register(&bus->dev);
        if (error) {
                pr_err("Zorro: Error registering zorro_bus\n");
@@ -151,15 +158,23 @@ static int __init amiga_zorro_probe(struct platform_device *pdev)
 
        /* First identify all devices ... */
        for (i = 0; i < zorro_num_autocon; i++) {
+               zi = &zorro_autocon_init[i];
                z = &zorro_autocon[i];
-               z->id = (z->rom.er_Manufacturer<<16) | (z->rom.er_Product<<8);
+
+               z->rom = zi->rom;
+               z->id = (be16_to_cpu(z->rom.er_Manufacturer) << 16) |
+                       (z->rom.er_Product << 8);
                if (z->id == ZORRO_PROD_GVP_EPC_BASE) {
                        /* GVP quirk */
-                       unsigned long magic = zorro_resource_start(z)+0x8000;
+                       unsigned long magic = zi->boardaddr + 0x8000;
                        z->id |= *(u16 *)ZTWO_VADDR(magic) & GVP_PRODMASK;
                }
+               z->slotaddr = zi->slotaddr;
+               z->slotsize = zi->slotsize;
                sprintf(z->name, "Zorro device %08x", z->id);
                zorro_name_device(z);
+               z->resource.start = zi->boardaddr;
+               z->resource.end = zi->boardaddr + zi->boardsize - 1;
                z->resource.name = z->name;
                r = zorro_find_parent_resource(pdev, z);
                error = request_resource(r, &z->resource);
@@ -167,9 +182,9 @@ static int __init amiga_zorro_probe(struct platform_device *pdev)
                        dev_err(&bus->dev,
                                "Address space collision on device %s %pR\n",
                                z->name, &z->resource);
-               dev_set_name(&z->dev, "%02x", i);
                z->dev.parent = &bus->dev;
                z->dev.bus = &zorro_bus_type;
+               z->dev.id = i;
        }
 
        /* ... then register them */
index b682d5ccd63f74b1be7aae6db188270318891f14..34119fb4e5601603edbd139563f539b3548963c9 100644 (file)
@@ -1,4 +1,9 @@
 
+#ifdef CONFIG_ZORRO_NAMES
 extern void zorro_name_device(struct zorro_dev *z);
+#else
+static inline void zorro_name_device(struct zorro_dev *dev) { }
+#endif
+
 extern int zorro_create_sysfs_dev_files(struct zorro_dev *z);
 
index 2b7a032c37bc7b087e0fdb3129436c0b735ba809..a69260f27555df85894618dc1647422971914dc4 100644 (file)
@@ -239,13 +239,12 @@ void v9fs_cache_inode_flush_cookie(struct inode *inode)
 void v9fs_cache_inode_set_cookie(struct inode *inode, struct file *filp)
 {
        struct v9fs_inode *v9inode = V9FS_I(inode);
-       struct p9_fid *fid;
 
        if (!v9inode->fscache)
                return;
 
        spin_lock(&v9inode->fscache_lock);
-       fid = filp->private_data;
+
        if ((filp->f_flags & O_ACCMODE) != O_RDONLY)
                v9fs_cache_inode_flush_cookie(inode);
        else
index a0df3e73c2b128e01ede3519b1c2aae2d8b09f28..27782bb7f4f9090c7c6330a1c071356b9c4baaf1 100644 (file)
@@ -461,14 +461,12 @@ v9fs_file_write_internal(struct inode *inode, struct p9_fid *fid,
        int n;
        loff_t i_size;
        size_t total = 0;
-       struct p9_client *clnt;
        loff_t origin = *offset;
        unsigned long pg_start, pg_end;
 
        p9_debug(P9_DEBUG_VFS, "data %p count %d offset %x\n",
                 data, (int)count, (int)*offset);
 
-       clnt = fid->clnt;
        do {
                n = p9_client_write(fid, NULL, data+total, origin+total, count);
                if (n <= 0)
index 4e65aa903345da5a7e63f5e49fb53f1204ee579e..af7d531bdecdedcc4e7cef7a99dc36347b1c1163 100644 (file)
@@ -779,7 +779,6 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
                                      unsigned int flags)
 {
        struct dentry *res;
-       struct super_block *sb;
        struct v9fs_session_info *v9ses;
        struct p9_fid *dfid, *fid;
        struct inode *inode;
@@ -791,7 +790,6 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
        if (dentry->d_name.len > NAME_MAX)
                return ERR_PTR(-ENAMETOOLONG);
 
-       sb = dir->i_sb;
        v9ses = v9fs_inode2v9ses(dir);
        /* We can walk d_parent because we hold the dir->i_mutex */
        dfid = v9fs_fid_lookup(dentry->d_parent);
@@ -863,7 +861,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
                return finish_no_open(file, res);
 
        err = 0;
-       fid = NULL;
+
        v9ses = v9fs_inode2v9ses(dir);
        perm = unixmode2p9mode(v9ses, mode);
        fid = v9fs_create(v9ses, dir, dentry, NULL, perm,
index 4c10edec26a04a5796f417da7151f3b5ae2b77fb..98013068f35bffa2e347b0ddb1b7ce44b366deb7 100644 (file)
@@ -473,13 +473,11 @@ static int
 v9fs_vfs_getattr_dotl(struct vfsmount *mnt, struct dentry *dentry,
                 struct kstat *stat)
 {
-       int err;
        struct v9fs_session_info *v9ses;
        struct p9_fid *fid;
        struct p9_stat_dotl *st;
 
        p9_debug(P9_DEBUG_VFS, "dentry: %p\n", dentry);
-       err = -EPERM;
        v9ses = v9fs_dentry2v9ses(dentry);
        if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
                generic_fillattr(dentry->d_inode, stat);
@@ -556,7 +554,6 @@ static int v9fs_mapped_iattr_valid(int iattr_valid)
 int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr)
 {
        int retval;
-       struct v9fs_session_info *v9ses;
        struct p9_fid *fid;
        struct p9_iattr_dotl p9attr;
        struct inode *inode = dentry->d_inode;
@@ -577,8 +574,6 @@ int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr)
        p9attr.mtime_sec = iattr->ia_mtime.tv_sec;
        p9attr.mtime_nsec = iattr->ia_mtime.tv_nsec;
 
-       retval = -EPERM;
-       v9ses = v9fs_dentry2v9ses(dentry);
        fid = v9fs_fid_lookup(dentry);
        if (IS_ERR(fid))
                return PTR_ERR(fid);
@@ -768,7 +763,6 @@ v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir,
                struct dentry *dentry)
 {
        int err;
-       char *name;
        struct dentry *dir_dentry;
        struct p9_fid *dfid, *oldfid;
        struct v9fs_session_info *v9ses;
@@ -786,8 +780,6 @@ v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir,
        if (IS_ERR(oldfid))
                return PTR_ERR(oldfid);
 
-       name = (char *) dentry->d_name.name;
-
        err = p9_client_link(dfid, oldfid, (char *)dentry->d_name.name);
 
        if (err < 0) {
index 3c28cdfb8c477b65269c1a26957cb4942d10344f..04133a1fd9cbea42585f530b56bb73f93b1bd1dc 100644 (file)
@@ -138,8 +138,7 @@ int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name,
        if (retval < 0) {
                p9_debug(P9_DEBUG_VFS, "p9_client_xattrcreate failed %d\n",
                         retval);
-               p9_client_clunk(fid);
-               return retval;
+               goto err;
        }
        msize = fid->clnt->msize;
        while (value_len) {
@@ -152,12 +151,15 @@ int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name,
                if (write_count < 0) {
                        /* error in xattr write */
                        retval = write_count;
-                       break;
+                       goto err;
                }
                offset += write_count;
                value_len -= write_count;
        }
-       return p9_client_clunk(fid);
+       retval = offset;
+err:
+       p9_client_clunk(fid);
+       return retval;
 }
 
 ssize_t v9fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
index 08159ed13649cacbec1825065e24b2b5b61be267..6efb7f6cb22e9ba5aabb5f111129ef69b7dac370 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -367,8 +367,10 @@ static int aio_setup_ring(struct kioctx *ctx)
        if (nr_pages > AIO_RING_PAGES) {
                ctx->ring_pages = kcalloc(nr_pages, sizeof(struct page *),
                                          GFP_KERNEL);
-               if (!ctx->ring_pages)
+               if (!ctx->ring_pages) {
+                       put_aio_ring_file(ctx);
                        return -ENOMEM;
+               }
        }
 
        ctx->mmap_size = nr_pages * PAGE_SIZE;
@@ -645,7 +647,7 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
            aio_nr + nr_events < aio_nr) {
                spin_unlock(&aio_nr_lock);
                err = -EAGAIN;
-               goto err;
+               goto err_ctx;
        }
        aio_nr += ctx->max_reqs;
        spin_unlock(&aio_nr_lock);
@@ -662,6 +664,8 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
 
 err_cleanup:
        aio_nr_sub(ctx->max_reqs);
+err_ctx:
+       aio_free_ring(ctx);
 err:
        free_percpu(ctx->cpu);
        free_percpu(ctx->reqs.pcpu_count);
index 267968d946739a2f3c17a20b4ffb5776e21ece75..5d4e59d56e854a158614302531cd15d1e8d0b5b6 100644 (file)
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -202,11 +202,6 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de
                        return -EPERM;
        }
 
-       if ((ia_valid & ATTR_SIZE) && IS_I_VERSION(inode)) {
-               if (attr->ia_size != inode->i_size)
-                       inode_inc_iversion(inode);
-       }
-
        if ((ia_valid & ATTR_MODE)) {
                umode_t amode = attr->ia_mode;
                /* Flag setting protected by i_mutex */
index fc60b31453eefbbdcc234c7df78c5504da655980..80d972d739e5d32236b0df186d6312dcab028f3f 100644 (file)
@@ -134,8 +134,7 @@ int bio_integrity_add_page(struct bio *bio, struct page *page,
                return 0;
        }
 
-       iv = bip_vec_idx(bip, bip->bip_vcnt);
-       BUG_ON(iv == NULL);
+       iv = bip->bip_vec + bip->bip_vcnt;
 
        iv->bv_page = page;
        iv->bv_len = len;
@@ -203,6 +202,12 @@ static inline unsigned int bio_integrity_hw_sectors(struct blk_integrity *bi,
        return sectors;
 }
 
+static inline unsigned int bio_integrity_bytes(struct blk_integrity *bi,
+                                              unsigned int sectors)
+{
+       return bio_integrity_hw_sectors(bi, sectors) * bi->tuple_size;
+}
+
 /**
  * bio_integrity_tag_size - Retrieve integrity tag space
  * @bio:       bio to inspect
@@ -215,9 +220,9 @@ unsigned int bio_integrity_tag_size(struct bio *bio)
 {
        struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
 
-       BUG_ON(bio->bi_size == 0);
+       BUG_ON(bio->bi_iter.bi_size == 0);
 
-       return bi->tag_size * (bio->bi_size / bi->sector_size);
+       return bi->tag_size * (bio->bi_iter.bi_size / bi->sector_size);
 }
 EXPORT_SYMBOL(bio_integrity_tag_size);
 
@@ -235,9 +240,9 @@ int bio_integrity_tag(struct bio *bio, void *tag_buf, unsigned int len, int set)
        nr_sectors = bio_integrity_hw_sectors(bi,
                                        DIV_ROUND_UP(len, bi->tag_size));
 
-       if (nr_sectors * bi->tuple_size > bip->bip_size) {
-               printk(KERN_ERR "%s: tag too big for bio: %u > %u\n",
-                      __func__, nr_sectors * bi->tuple_size, bip->bip_size);
+       if (nr_sectors * bi->tuple_size > bip->bip_iter.bi_size) {
+               printk(KERN_ERR "%s: tag too big for bio: %u > %u\n", __func__,
+                      nr_sectors * bi->tuple_size, bip->bip_iter.bi_size);
                return -1;
        }
 
@@ -299,29 +304,30 @@ static void bio_integrity_generate(struct bio *bio)
 {
        struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
        struct blk_integrity_exchg bix;
-       struct bio_vec *bv;
-       sector_t sector = bio->bi_sector;
-       unsigned int i, sectors, total;
+       struct bio_vec bv;
+       struct bvec_iter iter;
+       sector_t sector = bio->bi_iter.bi_sector;
+       unsigned int sectors, total;
        void *prot_buf = bio->bi_integrity->bip_buf;
 
        total = 0;
        bix.disk_name = bio->bi_bdev->bd_disk->disk_name;
        bix.sector_size = bi->sector_size;
 
-       bio_for_each_segment(bv, bio, i) {
-               void *kaddr = kmap_atomic(bv->bv_page);
-               bix.data_buf = kaddr + bv->bv_offset;
-               bix.data_size = bv->bv_len;
+       bio_for_each_segment(bv, bio, iter) {
+               void *kaddr = kmap_atomic(bv.bv_page);
+               bix.data_buf = kaddr + bv.bv_offset;
+               bix.data_size = bv.bv_len;
                bix.prot_buf = prot_buf;
                bix.sector = sector;
 
                bi->generate_fn(&bix);
 
-               sectors = bv->bv_len / bi->sector_size;
+               sectors = bv.bv_len / bi->sector_size;
                sector += sectors;
                prot_buf += sectors * bi->tuple_size;
                total += sectors * bi->tuple_size;
-               BUG_ON(total > bio->bi_integrity->bip_size);
+               BUG_ON(total > bio->bi_integrity->bip_iter.bi_size);
 
                kunmap_atomic(kaddr);
        }
@@ -386,8 +392,8 @@ int bio_integrity_prep(struct bio *bio)
 
        bip->bip_owns_buf = 1;
        bip->bip_buf = buf;
-       bip->bip_size = len;
-       bip->bip_sector = bio->bi_sector;
+       bip->bip_iter.bi_size = len;
+       bip->bip_iter.bi_sector = bio->bi_iter.bi_sector;
 
        /* Map it */
        offset = offset_in_page(buf);
@@ -441,19 +447,20 @@ static int bio_integrity_verify(struct bio *bio)
 {
        struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
        struct blk_integrity_exchg bix;
-       struct bio_vec *bv;
-       sector_t sector = bio->bi_integrity->bip_sector;
-       unsigned int i, sectors, total, ret;
+       struct bio_vec bv;
+       struct bvec_iter iter;
+       sector_t sector = bio->bi_integrity->bip_iter.bi_sector;
+       unsigned int sectors, total, ret;
        void *prot_buf = bio->bi_integrity->bip_buf;
 
        ret = total = 0;
        bix.disk_name = bio->bi_bdev->bd_disk->disk_name;
        bix.sector_size = bi->sector_size;
 
-       bio_for_each_segment(bv, bio, i) {
-               void *kaddr = kmap_atomic(bv->bv_page);
-               bix.data_buf = kaddr + bv->bv_offset;
-               bix.data_size = bv->bv_len;
+       bio_for_each_segment(bv, bio, iter) {
+               void *kaddr = kmap_atomic(bv.bv_page);
+               bix.data_buf = kaddr + bv.bv_offset;
+               bix.data_size = bv.bv_len;
                bix.prot_buf = prot_buf;
                bix.sector = sector;
 
@@ -464,11 +471,11 @@ static int bio_integrity_verify(struct bio *bio)
                        return ret;
                }
 
-               sectors = bv->bv_len / bi->sector_size;
+               sectors = bv.bv_len / bi->sector_size;
                sector += sectors;
                prot_buf += sectors * bi->tuple_size;
                total += sectors * bi->tuple_size;
-               BUG_ON(total > bio->bi_integrity->bip_size);
+               BUG_ON(total > bio->bi_integrity->bip_iter.bi_size);
 
                kunmap_atomic(kaddr);
        }
@@ -495,7 +502,7 @@ static void bio_integrity_verify_fn(struct work_struct *work)
 
        /* Restore original bio completion handler */
        bio->bi_end_io = bip->bip_end_io;
-       bio_endio(bio, error);
+       bio_endio_nodec(bio, error);
 }
 
 /**
@@ -532,56 +539,6 @@ void bio_integrity_endio(struct bio *bio, int error)
 }
 EXPORT_SYMBOL(bio_integrity_endio);
 
-/**
- * bio_integrity_mark_head - Advance bip_vec skip bytes
- * @bip:       Integrity vector to advance
- * @skip:      Number of bytes to advance it
- */
-void bio_integrity_mark_head(struct bio_integrity_payload *bip,
-                            unsigned int skip)
-{
-       struct bio_vec *iv;
-       unsigned int i;
-
-       bip_for_each_vec(iv, bip, i) {
-               if (skip == 0) {
-                       bip->bip_idx = i;
-                       return;
-               } else if (skip >= iv->bv_len) {
-                       skip -= iv->bv_len;
-               } else { /* skip < iv->bv_len) */
-                       iv->bv_offset += skip;
-                       iv->bv_len -= skip;
-                       bip->bip_idx = i;
-                       return;
-               }
-       }
-}
-
-/**
- * bio_integrity_mark_tail - Truncate bip_vec to be len bytes long
- * @bip:       Integrity vector to truncate
- * @len:       New length of integrity vector
- */
-void bio_integrity_mark_tail(struct bio_integrity_payload *bip,
-                            unsigned int len)
-{
-       struct bio_vec *iv;
-       unsigned int i;
-
-       bip_for_each_vec(iv, bip, i) {
-               if (len == 0) {
-                       bip->bip_vcnt = i;
-                       return;
-               } else if (len >= iv->bv_len) {
-                       len -= iv->bv_len;
-               } else { /* len < iv->bv_len) */
-                       iv->bv_len = len;
-                       len = 0;
-               }
-       }
-}
-
 /**
  * bio_integrity_advance - Advance integrity vector
  * @bio:       bio whose integrity vector to update
@@ -595,13 +552,9 @@ void bio_integrity_advance(struct bio *bio, unsigned int bytes_done)
 {
        struct bio_integrity_payload *bip = bio->bi_integrity;
        struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
-       unsigned int nr_sectors;
-
-       BUG_ON(bip == NULL);
-       BUG_ON(bi == NULL);
+       unsigned bytes = bio_integrity_bytes(bi, bytes_done >> 9);
 
-       nr_sectors = bio_integrity_hw_sectors(bi, bytes_done >> 9);
-       bio_integrity_mark_head(bip, nr_sectors * bi->tuple_size);
+       bvec_iter_advance(bip->bip_vec, &bip->bip_iter, bytes);
 }
 EXPORT_SYMBOL(bio_integrity_advance);
 
@@ -621,63 +574,12 @@ void bio_integrity_trim(struct bio *bio, unsigned int offset,
 {
        struct bio_integrity_payload *bip = bio->bi_integrity;
        struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
-       unsigned int nr_sectors;
 
-       BUG_ON(bip == NULL);
-       BUG_ON(bi == NULL);
-       BUG_ON(!bio_flagged(bio, BIO_CLONED));
-
-       nr_sectors = bio_integrity_hw_sectors(bi, sectors);
-       bip->bip_sector = bip->bip_sector + offset;
-       bio_integrity_mark_head(bip, offset * bi->tuple_size);
-       bio_integrity_mark_tail(bip, sectors * bi->tuple_size);
+       bio_integrity_advance(bio, offset << 9);
+       bip->bip_iter.bi_size = bio_integrity_bytes(bi, sectors);
 }
 EXPORT_SYMBOL(bio_integrity_trim);
 
-/**
- * bio_integrity_split - Split integrity metadata
- * @bio:       Protected bio
- * @bp:                Resulting bio_pair
- * @sectors:   Offset
- *
- * Description: Splits an integrity page into a bio_pair.
- */
-void bio_integrity_split(struct bio *bio, struct bio_pair *bp, int sectors)
-{
-       struct blk_integrity *bi;
-       struct bio_integrity_payload *bip = bio->bi_integrity;
-       unsigned int nr_sectors;
-
-       if (bio_integrity(bio) == 0)
-               return;
-
-       bi = bdev_get_integrity(bio->bi_bdev);
-       BUG_ON(bi == NULL);
-       BUG_ON(bip->bip_vcnt != 1);
-
-       nr_sectors = bio_integrity_hw_sectors(bi, sectors);
-
-       bp->bio1.bi_integrity = &bp->bip1;
-       bp->bio2.bi_integrity = &bp->bip2;
-
-       bp->iv1 = bip->bip_vec[bip->bip_idx];
-       bp->iv2 = bip->bip_vec[bip->bip_idx];
-
-       bp->bip1.bip_vec = &bp->iv1;
-       bp->bip2.bip_vec = &bp->iv2;
-
-       bp->iv1.bv_len = sectors * bi->tuple_size;
-       bp->iv2.bv_offset += sectors * bi->tuple_size;
-       bp->iv2.bv_len -= sectors * bi->tuple_size;
-
-       bp->bip1.bip_sector = bio->bi_integrity->bip_sector;
-       bp->bip2.bip_sector = bio->bi_integrity->bip_sector + nr_sectors;
-
-       bp->bip1.bip_vcnt = bp->bip2.bip_vcnt = 1;
-       bp->bip1.bip_idx = bp->bip2.bip_idx = 0;
-}
-EXPORT_SYMBOL(bio_integrity_split);
-
 /**
  * bio_integrity_clone - Callback for cloning bios with integrity metadata
  * @bio:       New bio
@@ -702,9 +604,8 @@ int bio_integrity_clone(struct bio *bio, struct bio *bio_src,
        memcpy(bip->bip_vec, bip_src->bip_vec,
               bip_src->bip_vcnt * sizeof(struct bio_vec));
 
-       bip->bip_sector = bip_src->bip_sector;
        bip->bip_vcnt = bip_src->bip_vcnt;
-       bip->bip_idx = bip_src->bip_idx;
+       bip->bip_iter = bip_src->bip_iter;
 
        return 0;
 }
index 33d79a4eb92d6e623aa90e2291af39b2b2689d83..75c49a38223969c1f7256868cb3b09fc7d3bd286 100644 (file)
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -38,8 +38,6 @@
  */
 #define BIO_INLINE_VECS                4
 
-static mempool_t *bio_split_pool __read_mostly;
-
 /*
  * if you change this list, also change bvec_alloc or things will
  * break badly! cannot be bigger than what you can fit into an
@@ -273,6 +271,7 @@ void bio_init(struct bio *bio)
 {
        memset(bio, 0, sizeof(*bio));
        bio->bi_flags = 1 << BIO_UPTODATE;
+       atomic_set(&bio->bi_remaining, 1);
        atomic_set(&bio->bi_cnt, 1);
 }
 EXPORT_SYMBOL(bio_init);
@@ -295,9 +294,35 @@ void bio_reset(struct bio *bio)
 
        memset(bio, 0, BIO_RESET_BYTES);
        bio->bi_flags = flags|(1 << BIO_UPTODATE);
+       atomic_set(&bio->bi_remaining, 1);
 }
 EXPORT_SYMBOL(bio_reset);
 
+static void bio_chain_endio(struct bio *bio, int error)
+{
+       bio_endio(bio->bi_private, error);
+       bio_put(bio);
+}
+
+/**
+ * bio_chain - chain bio completions
+ *
+ * The caller won't have a bi_end_io called when @bio completes - instead,
+ * @parent's bi_end_io won't be called until both @parent and @bio have
+ * completed; the chained bio will also be freed when it completes.
+ *
+ * The caller must not set bi_private or bi_end_io in @bio.
+ */
+void bio_chain(struct bio *bio, struct bio *parent)
+{
+       BUG_ON(bio->bi_private || bio->bi_end_io);
+
+       bio->bi_private = parent;
+       bio->bi_end_io  = bio_chain_endio;
+       atomic_inc(&parent->bi_remaining);
+}
+EXPORT_SYMBOL(bio_chain);
+
 static void bio_alloc_rescue(struct work_struct *work)
 {
        struct bio_set *bs = container_of(work, struct bio_set, rescue_work);
@@ -473,13 +498,13 @@ EXPORT_SYMBOL(bio_alloc_bioset);
 void zero_fill_bio(struct bio *bio)
 {
        unsigned long flags;
-       struct bio_vec *bv;
-       int i;
+       struct bio_vec bv;
+       struct bvec_iter iter;
 
-       bio_for_each_segment(bv, bio, i) {
-               char *data = bvec_kmap_irq(bv, &flags);
-               memset(data, 0, bv->bv_len);
-               flush_dcache_page(bv->bv_page);
+       bio_for_each_segment(bv, bio, iter) {
+               char *data = bvec_kmap_irq(&bv, &flags);
+               memset(data, 0, bv.bv_len);
+               flush_dcache_page(bv.bv_page);
                bvec_kunmap_irq(data, &flags);
        }
 }
@@ -515,51 +540,49 @@ inline int bio_phys_segments(struct request_queue *q, struct bio *bio)
 EXPORT_SYMBOL(bio_phys_segments);
 
 /**
- *     __bio_clone     -       clone a bio
+ *     __bio_clone_fast - clone a bio that shares the original bio's biovec
  *     @bio: destination bio
  *     @bio_src: bio to clone
  *
  *     Clone a &bio. Caller will own the returned bio, but not
  *     the actual data it points to. Reference count of returned
  *     bio will be one.
+ *
+ *     Caller must ensure that @bio_src is not freed before @bio.
  */
-void __bio_clone(struct bio *bio, struct bio *bio_src)
+void __bio_clone_fast(struct bio *bio, struct bio *bio_src)
 {
-       memcpy(bio->bi_io_vec, bio_src->bi_io_vec,
-               bio_src->bi_max_vecs * sizeof(struct bio_vec));
+       BUG_ON(bio->bi_pool && BIO_POOL_IDX(bio) != BIO_POOL_NONE);
 
        /*
         * most users will be overriding ->bi_bdev with a new target,
         * so we don't set nor calculate new physical/hw segment counts here
         */
-       bio->bi_sector = bio_src->bi_sector;
        bio->bi_bdev = bio_src->bi_bdev;
        bio->bi_flags |= 1 << BIO_CLONED;
        bio->bi_rw = bio_src->bi_rw;
-       bio->bi_vcnt = bio_src->bi_vcnt;
-       bio->bi_size = bio_src->bi_size;
-       bio->bi_idx = bio_src->bi_idx;
+       bio->bi_iter = bio_src->bi_iter;
+       bio->bi_io_vec = bio_src->bi_io_vec;
 }
-EXPORT_SYMBOL(__bio_clone);
+EXPORT_SYMBOL(__bio_clone_fast);
 
 /**
- *     bio_clone_bioset -      clone a bio
+ *     bio_clone_fast - clone a bio that shares the original bio's biovec
  *     @bio: bio to clone
  *     @gfp_mask: allocation priority
  *     @bs: bio_set to allocate from
  *
- *     Like __bio_clone, only also allocates the returned bio
+ *     Like __bio_clone_fast, only also allocates the returned bio
  */
-struct bio *bio_clone_bioset(struct bio *bio, gfp_t gfp_mask,
-                            struct bio_set *bs)
+struct bio *bio_clone_fast(struct bio *bio, gfp_t gfp_mask, struct bio_set *bs)
 {
        struct bio *b;
 
-       b = bio_alloc_bioset(gfp_mask, bio->bi_max_vecs, bs);
+       b = bio_alloc_bioset(gfp_mask, 0, bs);
        if (!b)
                return NULL;
 
-       __bio_clone(b, bio);
+       __bio_clone_fast(b, bio);
 
        if (bio_integrity(bio)) {
                int ret;
@@ -574,6 +597,74 @@ struct bio *bio_clone_bioset(struct bio *bio, gfp_t gfp_mask,
 
        return b;
 }
+EXPORT_SYMBOL(bio_clone_fast);
+
+/**
+ *     bio_clone_bioset - clone a bio
+ *     @bio_src: bio to clone
+ *     @gfp_mask: allocation priority
+ *     @bs: bio_set to allocate from
+ *
+ *     Clone bio. Caller will own the returned bio, but not the actual data it
+ *     points to. Reference count of returned bio will be one.
+ */
+struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask,
+                            struct bio_set *bs)
+{
+       unsigned nr_iovecs = 0;
+       struct bvec_iter iter;
+       struct bio_vec bv;
+       struct bio *bio;
+
+       /*
+        * Pre immutable biovecs, __bio_clone() used to just do a memcpy from
+        * bio_src->bi_io_vec to bio->bi_io_vec.
+        *
+        * We can't do that anymore, because:
+        *
+        *  - The point of cloning the biovec is to produce a bio with a biovec
+        *    the caller can modify: bi_idx and bi_bvec_done should be 0.
+        *
+        *  - The original bio could've had more than BIO_MAX_PAGES biovecs; if
+        *    we tried to clone the whole thing bio_alloc_bioset() would fail.
+        *    But the clone should succeed as long as the number of biovecs we
+        *    actually need to allocate is fewer than BIO_MAX_PAGES.
+        *
+        *  - Lastly, bi_vcnt should not be looked at or relied upon by code
+        *    that does not own the bio - reason being drivers don't use it for
+        *    iterating over the biovec anymore, so expecting it to be kept up
+        *    to date (i.e. for clones that share the parent biovec) is just
+        *    asking for trouble and would force extra work on
+        *    __bio_clone_fast() anyways.
+        */
+
+       bio_for_each_segment(bv, bio_src, iter)
+               nr_iovecs++;
+
+       bio = bio_alloc_bioset(gfp_mask, nr_iovecs, bs);
+       if (!bio)
+               return NULL;
+
+       bio->bi_bdev            = bio_src->bi_bdev;
+       bio->bi_rw              = bio_src->bi_rw;
+       bio->bi_iter.bi_sector  = bio_src->bi_iter.bi_sector;
+       bio->bi_iter.bi_size    = bio_src->bi_iter.bi_size;
+
+       bio_for_each_segment(bv, bio_src, iter)
+               bio->bi_io_vec[bio->bi_vcnt++] = bv;
+
+       if (bio_integrity(bio_src)) {
+               int ret;
+
+               ret = bio_integrity_clone(bio, bio_src, gfp_mask);
+               if (ret < 0) {
+                       bio_put(bio);
+                       return NULL;
+               }
+       }
+
+       return bio;
+}
 EXPORT_SYMBOL(bio_clone_bioset);
 
 /**
@@ -612,7 +703,7 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page
        if (unlikely(bio_flagged(bio, BIO_CLONED)))
                return 0;
 
-       if (((bio->bi_size + len) >> 9) > max_sectors)
+       if (((bio->bi_iter.bi_size + len) >> 9) > max_sectors)
                return 0;
 
        /*
@@ -635,8 +726,9 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page
                                           simulate merging updated prev_bvec
                                           as new bvec. */
                                        .bi_bdev = bio->bi_bdev,
-                                       .bi_sector = bio->bi_sector,
-                                       .bi_size = bio->bi_size - prev_bv_len,
+                                       .bi_sector = bio->bi_iter.bi_sector,
+                                       .bi_size = bio->bi_iter.bi_size -
+                                               prev_bv_len,
                                        .bi_rw = bio->bi_rw,
                                };
 
@@ -684,8 +776,8 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page
        if (q->merge_bvec_fn) {
                struct bvec_merge_data bvm = {
                        .bi_bdev = bio->bi_bdev,
-                       .bi_sector = bio->bi_sector,
-                       .bi_size = bio->bi_size,
+                       .bi_sector = bio->bi_iter.bi_sector,
+                       .bi_size = bio->bi_iter.bi_size,
                        .bi_rw = bio->bi_rw,
                };
 
@@ -708,7 +800,7 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page
        bio->bi_vcnt++;
        bio->bi_phys_segments++;
  done:
-       bio->bi_size += len;
+       bio->bi_iter.bi_size += len;
        return len;
 }
 
@@ -807,28 +899,7 @@ void bio_advance(struct bio *bio, unsigned bytes)
        if (bio_integrity(bio))
                bio_integrity_advance(bio, bytes);
 
-       bio->bi_sector += bytes >> 9;
-       bio->bi_size -= bytes;
-
-       if (bio->bi_rw & BIO_NO_ADVANCE_ITER_MASK)
-               return;
-
-       while (bytes) {
-               if (unlikely(bio->bi_idx >= bio->bi_vcnt)) {
-                       WARN_ONCE(1, "bio idx %d >= vcnt %d\n",
-                                 bio->bi_idx, bio->bi_vcnt);
-                       break;
-               }
-
-               if (bytes >= bio_iovec(bio)->bv_len) {
-                       bytes -= bio_iovec(bio)->bv_len;
-                       bio->bi_idx++;
-               } else {
-                       bio_iovec(bio)->bv_len -= bytes;
-                       bio_iovec(bio)->bv_offset += bytes;
-                       bytes = 0;
-               }
-       }
+       bio_advance_iter(bio, &bio->bi_iter, bytes);
 }
 EXPORT_SYMBOL(bio_advance);
 
@@ -874,117 +945,80 @@ EXPORT_SYMBOL(bio_alloc_pages);
  */
 void bio_copy_data(struct bio *dst, struct bio *src)
 {
-       struct bio_vec *src_bv, *dst_bv;
-       unsigned src_offset, dst_offset, bytes;
+       struct bvec_iter src_iter, dst_iter;
+       struct bio_vec src_bv, dst_bv;
        void *src_p, *dst_p;
+       unsigned bytes;
 
-       src_bv = bio_iovec(src);
-       dst_bv = bio_iovec(dst);
-
-       src_offset = src_bv->bv_offset;
-       dst_offset = dst_bv->bv_offset;
+       src_iter = src->bi_iter;
+       dst_iter = dst->bi_iter;
 
        while (1) {
-               if (src_offset == src_bv->bv_offset + src_bv->bv_len) {
-                       src_bv++;
-                       if (src_bv == bio_iovec_idx(src, src->bi_vcnt)) {
-                               src = src->bi_next;
-                               if (!src)
-                                       break;
-
-                               src_bv = bio_iovec(src);
-                       }
+               if (!src_iter.bi_size) {
+                       src = src->bi_next;
+                       if (!src)
+                               break;
 
-                       src_offset = src_bv->bv_offset;
+                       src_iter = src->bi_iter;
                }
 
-               if (dst_offset == dst_bv->bv_offset + dst_bv->bv_len) {
-                       dst_bv++;
-                       if (dst_bv == bio_iovec_idx(dst, dst->bi_vcnt)) {
-                               dst = dst->bi_next;
-                               if (!dst)
-                                       break;
-
-                               dst_bv = bio_iovec(dst);
-                       }
+               if (!dst_iter.bi_size) {
+                       dst = dst->bi_next;
+                       if (!dst)
+                               break;
 
-                       dst_offset = dst_bv->bv_offset;
+                       dst_iter = dst->bi_iter;
                }
 
-               bytes = min(dst_bv->bv_offset + dst_bv->bv_len - dst_offset,
-                           src_bv->bv_offset + src_bv->bv_len - src_offset);
+               src_bv = bio_iter_iovec(src, src_iter);
+               dst_bv = bio_iter_iovec(dst, dst_iter);
+
+               bytes = min(src_bv.bv_len, dst_bv.bv_len);
 
-               src_p = kmap_atomic(src_bv->bv_page);
-               dst_p = kmap_atomic(dst_bv->bv_page);
+               src_p = kmap_atomic(src_bv.bv_page);
+               dst_p = kmap_atomic(dst_bv.bv_page);
 
-               memcpy(dst_p + dst_offset,
-                      src_p + src_offset,
+               memcpy(dst_p + dst_bv.bv_offset,
+                      src_p + src_bv.bv_offset,
                       bytes);
 
                kunmap_atomic(dst_p);
                kunmap_atomic(src_p);
 
-               src_offset += bytes;
-               dst_offset += bytes;
+               bio_advance_iter(src, &src_iter, bytes);
+               bio_advance_iter(dst, &dst_iter, bytes);
        }
 }
 EXPORT_SYMBOL(bio_copy_data);
 
 struct bio_map_data {
-       struct bio_vec *iovecs;
-       struct sg_iovec *sgvecs;
        int nr_sgvecs;
        int is_our_pages;
+       struct sg_iovec sgvecs[];
 };
 
 static void bio_set_map_data(struct bio_map_data *bmd, struct bio *bio,
                             struct sg_iovec *iov, int iov_count,
                             int is_our_pages)
 {
-       memcpy(bmd->iovecs, bio->bi_io_vec, sizeof(struct bio_vec) * bio->bi_vcnt);
        memcpy(bmd->sgvecs, iov, sizeof(struct sg_iovec) * iov_count);
        bmd->nr_sgvecs = iov_count;
        bmd->is_our_pages = is_our_pages;
        bio->bi_private = bmd;
 }
 
-static void bio_free_map_data(struct bio_map_data *bmd)
-{
-       kfree(bmd->iovecs);
-       kfree(bmd->sgvecs);
-       kfree(bmd);
-}
-
 static struct bio_map_data *bio_alloc_map_data(int nr_segs,
                                               unsigned int iov_count,
                                               gfp_t gfp_mask)
 {
-       struct bio_map_data *bmd;
-
        if (iov_count > UIO_MAXIOV)
                return NULL;
 
-       bmd = kmalloc(sizeof(*bmd), gfp_mask);
-       if (!bmd)
-               return NULL;
-
-       bmd->iovecs = kmalloc(sizeof(struct bio_vec) * nr_segs, gfp_mask);
-       if (!bmd->iovecs) {
-               kfree(bmd);
-               return NULL;
-       }
-
-       bmd->sgvecs = kmalloc(sizeof(struct sg_iovec) * iov_count, gfp_mask);
-       if (bmd->sgvecs)
-               return bmd;
-
-       kfree(bmd->iovecs);
-       kfree(bmd);
-       return NULL;
+       return kmalloc(sizeof(struct bio_map_data) +
+                      sizeof(struct sg_iovec) * iov_count, gfp_mask);
 }
 
-static int __bio_copy_iov(struct bio *bio, struct bio_vec *iovecs,
-                         struct sg_iovec *iov, int iov_count,
+static int __bio_copy_iov(struct bio *bio, struct sg_iovec *iov, int iov_count,
                          int to_user, int from_user, int do_free_page)
 {
        int ret = 0, i;
@@ -994,7 +1028,7 @@ static int __bio_copy_iov(struct bio *bio, struct bio_vec *iovecs,
 
        bio_for_each_segment_all(bvec, bio, i) {
                char *bv_addr = page_address(bvec->bv_page);
-               unsigned int bv_len = iovecs[i].bv_len;
+               unsigned int bv_len = bvec->bv_len;
 
                while (bv_len && iov_idx < iov_count) {
                        unsigned int bytes;
@@ -1054,14 +1088,14 @@ int bio_uncopy_user(struct bio *bio)
                 * don't copy into a random user address space, just free.
                 */
                if (current->mm)
-                       ret = __bio_copy_iov(bio, bmd->iovecs, bmd->sgvecs,
-                                            bmd->nr_sgvecs, bio_data_dir(bio) == READ,
+                       ret = __bio_copy_iov(bio, bmd->sgvecs, bmd->nr_sgvecs,
+                                            bio_data_dir(bio) == READ,
                                             0, bmd->is_our_pages);
                else if (bmd->is_our_pages)
                        bio_for_each_segment_all(bvec, bio, i)
                                __free_page(bvec->bv_page);
        }
-       bio_free_map_data(bmd);
+       kfree(bmd);
        bio_put(bio);
        return ret;
 }
@@ -1175,7 +1209,7 @@ struct bio *bio_copy_user_iov(struct request_queue *q,
         */
        if ((!write_to_vm && (!map_data || !map_data->null_mapped)) ||
            (map_data && map_data->from_user)) {
-               ret = __bio_copy_iov(bio, bio->bi_io_vec, iov, iov_count, 0, 1, 0);
+               ret = __bio_copy_iov(bio, iov, iov_count, 0, 1, 0);
                if (ret)
                        goto cleanup;
        }
@@ -1189,7 +1223,7 @@ cleanup:
 
        bio_put(bio);
 out_bmd:
-       bio_free_map_data(bmd);
+       kfree(bmd);
        return ERR_PTR(ret);
 }
 
@@ -1485,7 +1519,7 @@ struct bio *bio_map_kern(struct request_queue *q, void *data, unsigned int len,
        if (IS_ERR(bio))
                return bio;
 
-       if (bio->bi_size == len)
+       if (bio->bi_iter.bi_size == len)
                return bio;
 
        /*
@@ -1506,16 +1540,15 @@ static void bio_copy_kern_endio(struct bio *bio, int err)
 
        bio_for_each_segment_all(bvec, bio, i) {
                char *addr = page_address(bvec->bv_page);
-               int len = bmd->iovecs[i].bv_len;
 
                if (read)
-                       memcpy(p, addr, len);
+                       memcpy(p, addr, bvec->bv_len);
 
                __free_page(bvec->bv_page);
-               p += len;
+               p += bvec->bv_len;
        }
 
-       bio_free_map_data(bmd);
+       kfree(bmd);
        bio_put(bio);
 }
 
@@ -1686,11 +1719,11 @@ void bio_check_pages_dirty(struct bio *bio)
 #if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE
 void bio_flush_dcache_pages(struct bio *bi)
 {
-       int i;
-       struct bio_vec *bvec;
+       struct bio_vec bvec;
+       struct bvec_iter iter;
 
-       bio_for_each_segment(bvec, bi, i)
-               flush_dcache_page(bvec->bv_page);
+       bio_for_each_segment(bvec, bi, iter)
+               flush_dcache_page(bvec.bv_page);
 }
 EXPORT_SYMBOL(bio_flush_dcache_pages);
 #endif
@@ -1711,96 +1744,86 @@ EXPORT_SYMBOL(bio_flush_dcache_pages);
  **/
 void bio_endio(struct bio *bio, int error)
 {
-       if (error)
-               clear_bit(BIO_UPTODATE, &bio->bi_flags);
-       else if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
-               error = -EIO;
+       while (bio) {
+               BUG_ON(atomic_read(&bio->bi_remaining) <= 0);
 
-       if (bio->bi_end_io)
-               bio->bi_end_io(bio, error);
-}
-EXPORT_SYMBOL(bio_endio);
+               if (error)
+                       clear_bit(BIO_UPTODATE, &bio->bi_flags);
+               else if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
+                       error = -EIO;
 
-void bio_pair_release(struct bio_pair *bp)
-{
-       if (atomic_dec_and_test(&bp->cnt)) {
-               struct bio *master = bp->bio1.bi_private;
+               if (!atomic_dec_and_test(&bio->bi_remaining))
+                       return;
 
-               bio_endio(master, bp->error);
-               mempool_free(bp, bp->bio2.bi_private);
+               /*
+                * Need to have a real endio function for chained bios,
+                * otherwise various corner cases will break (like stacking
+                * block devices that save/restore bi_end_io) - however, we want
+                * to avoid unbounded recursion and blowing the stack. Tail call
+                * optimization would handle this, but compiling with frame
+                * pointers also disables gcc's sibling call optimization.
+                */
+               if (bio->bi_end_io == bio_chain_endio) {
+                       struct bio *parent = bio->bi_private;
+                       bio_put(bio);
+                       bio = parent;
+               } else {
+                       if (bio->bi_end_io)
+                               bio->bi_end_io(bio, error);
+                       bio = NULL;
+               }
        }
 }
-EXPORT_SYMBOL(bio_pair_release);
+EXPORT_SYMBOL(bio_endio);
 
-static void bio_pair_end_1(struct bio *bi, int err)
+/**
+ * bio_endio_nodec - end I/O on a bio, without decrementing bi_remaining
+ * @bio:       bio
+ * @error:     error, if any
+ *
+ * For code that has saved and restored bi_end_io; thing hard before using this
+ * function, probably you should've cloned the entire bio.
+ **/
+void bio_endio_nodec(struct bio *bio, int error)
 {
-       struct bio_pair *bp = container_of(bi, struct bio_pair, bio1);
-
-       if (err)
-               bp->error = err;
-
-       bio_pair_release(bp);
+       atomic_inc(&bio->bi_remaining);
+       bio_endio(bio, error);
 }
+EXPORT_SYMBOL(bio_endio_nodec);
 
-static void bio_pair_end_2(struct bio *bi, int err)
-{
-       struct bio_pair *bp = container_of(bi, struct bio_pair, bio2);
-
-       if (err)
-               bp->error = err;
-
-       bio_pair_release(bp);
-}
-
-/*
- * split a bio - only worry about a bio with a single page in its iovec
+/**
+ * bio_split - split a bio
+ * @bio:       bio to split
+ * @sectors:   number of sectors to split from the front of @bio
+ * @gfp:       gfp mask
+ * @bs:                bio set to allocate from
+ *
+ * Allocates and returns a new bio which represents @sectors from the start of
+ * @bio, and updates @bio to represent the remaining sectors.
+ *
+ * The newly allocated bio will point to @bio's bi_io_vec; it is the caller's
+ * responsibility to ensure that @bio is not freed before the split.
  */
-struct bio_pair *bio_split(struct bio *bi, int first_sectors)
+struct bio *bio_split(struct bio *bio, int sectors,
+                     gfp_t gfp, struct bio_set *bs)
 {
-       struct bio_pair *bp = mempool_alloc(bio_split_pool, GFP_NOIO);
-
-       if (!bp)
-               return bp;
-
-       trace_block_split(bdev_get_queue(bi->bi_bdev), bi,
-                               bi->bi_sector + first_sectors);
-
-       BUG_ON(bio_segments(bi) > 1);
-       atomic_set(&bp->cnt, 3);
-       bp->error = 0;
-       bp->bio1 = *bi;
-       bp->bio2 = *bi;
-       bp->bio2.bi_sector += first_sectors;
-       bp->bio2.bi_size -= first_sectors << 9;
-       bp->bio1.bi_size = first_sectors << 9;
-
-       if (bi->bi_vcnt != 0) {
-               bp->bv1 = *bio_iovec(bi);
-               bp->bv2 = *bio_iovec(bi);
-
-               if (bio_is_rw(bi)) {
-                       bp->bv2.bv_offset += first_sectors << 9;
-                       bp->bv2.bv_len -= first_sectors << 9;
-                       bp->bv1.bv_len = first_sectors << 9;
-               }
+       struct bio *split = NULL;
 
-               bp->bio1.bi_io_vec = &bp->bv1;
-               bp->bio2.bi_io_vec = &bp->bv2;
+       BUG_ON(sectors <= 0);
+       BUG_ON(sectors >= bio_sectors(bio));
 
-               bp->bio1.bi_max_vecs = 1;
-               bp->bio2.bi_max_vecs = 1;
-       }
+       split = bio_clone_fast(bio, gfp, bs);
+       if (!split)
+               return NULL;
 
-       bp->bio1.bi_end_io = bio_pair_end_1;
-       bp->bio2.bi_end_io = bio_pair_end_2;
+       split->bi_iter.bi_size = sectors << 9;
 
-       bp->bio1.bi_private = bi;
-       bp->bio2.bi_private = bio_split_pool;
+       if (bio_integrity(split))
+               bio_integrity_trim(split, 0, sectors);
 
-       if (bio_integrity(bi))
-               bio_integrity_split(bi, bp, first_sectors);
+       bio_advance(bio, split->bi_iter.bi_size);
 
-       return bp;
+       return split;
 }
 EXPORT_SYMBOL(bio_split);
 
@@ -1814,80 +1837,20 @@ void bio_trim(struct bio *bio, int offset, int size)
 {
        /* 'bio' is a cloned bio which we need to trim to match
         * the given offset and size.
-        * This requires adjusting bi_sector, bi_size, and bi_io_vec
         */
-       int i;
-       struct bio_vec *bvec;
-       int sofar = 0;
 
        size <<= 9;
-       if (offset == 0 && size == bio->bi_size)
+       if (offset == 0 && size == bio->bi_iter.bi_size)
                return;
 
        clear_bit(BIO_SEG_VALID, &bio->bi_flags);
 
        bio_advance(bio, offset << 9);
 
-       bio->bi_size = size;
-
-       /* avoid any complications with bi_idx being non-zero*/
-       if (bio->bi_idx) {
-               memmove(bio->bi_io_vec, bio->bi_io_vec+bio->bi_idx,
-                       (bio->bi_vcnt - bio->bi_idx) * sizeof(struct bio_vec));
-               bio->bi_vcnt -= bio->bi_idx;
-               bio->bi_idx = 0;
-       }
-       /* Make sure vcnt and last bv are not too big */
-       bio_for_each_segment(bvec, bio, i) {
-               if (sofar + bvec->bv_len > size)
-                       bvec->bv_len = size - sofar;
-               if (bvec->bv_len == 0) {
-                       bio->bi_vcnt = i;
-                       break;
-               }
-               sofar += bvec->bv_len;
-       }
+       bio->bi_iter.bi_size = size;
 }
 EXPORT_SYMBOL_GPL(bio_trim);
 
-/**
- *      bio_sector_offset - Find hardware sector offset in bio
- *      @bio:           bio to inspect
- *      @index:         bio_vec index
- *      @offset:        offset in bv_page
- *
- *      Return the number of hardware sectors between beginning of bio
- *      and an end point indicated by a bio_vec index and an offset
- *      within that vector's page.
- */
-sector_t bio_sector_offset(struct bio *bio, unsigned short index,
-                          unsigned int offset)
-{
-       unsigned int sector_sz;
-       struct bio_vec *bv;
-       sector_t sectors;
-       int i;
-
-       sector_sz = queue_logical_block_size(bio->bi_bdev->bd_disk->queue);
-       sectors = 0;
-
-       if (index >= bio->bi_idx)
-               index = bio->bi_vcnt - 1;
-
-       bio_for_each_segment_all(bv, bio, i) {
-               if (i == index) {
-                       if (offset > bv->bv_offset)
-                               sectors += (offset - bv->bv_offset) / sector_sz;
-                       break;
-               }
-
-               sectors += bv->bv_len / sector_sz;
-       }
-
-       return sectors;
-}
-EXPORT_SYMBOL(bio_sector_offset);
-
 /*
  * create memory pools for biovec's in a bio_set.
  * use the global biovec slabs created for general use.
@@ -2065,11 +2028,6 @@ static int __init init_bio(void)
        if (bioset_integrity_create(fs_bio_set, BIO_POOL_SIZE))
                panic("bio: can't create integrity pool\n");
 
-       bio_split_pool = mempool_create_kmalloc_pool(BIO_SPLIT_ENTRIES,
-                                                    sizeof(struct bio_pair));
-       if (!bio_split_pool)
-               panic("bio: can't create split pool\n");
-
        return 0;
 }
 subsys_initcall(init_bio);
index b50764bef1410c2750b17d943ae3597899b3ee9e..cb05e1c842c5b8b84dee98d1a3f452eaa179417e 100644 (file)
@@ -333,7 +333,6 @@ static void btrfsic_release_block_ctx(struct btrfsic_block_data_ctx *block_ctx);
 static int btrfsic_read_block(struct btrfsic_state *state,
                              struct btrfsic_block_data_ctx *block_ctx);
 static void btrfsic_dump_database(struct btrfsic_state *state);
-static void btrfsic_complete_bio_end_io(struct bio *bio, int err);
 static int btrfsic_test_for_metadata(struct btrfsic_state *state,
                                     char **datav, unsigned int num_pages);
 static void btrfsic_process_written_block(struct btrfsic_dev_state *dev_state,
@@ -1687,7 +1686,6 @@ static int btrfsic_read_block(struct btrfsic_state *state,
        for (i = 0; i < num_pages;) {
                struct bio *bio;
                unsigned int j;
-               DECLARE_COMPLETION_ONSTACK(complete);
 
                bio = btrfs_io_bio_alloc(GFP_NOFS, num_pages - i);
                if (!bio) {
@@ -1697,9 +1695,7 @@ static int btrfsic_read_block(struct btrfsic_state *state,
                        return -1;
                }
                bio->bi_bdev = block_ctx->dev->bdev;
-               bio->bi_sector = dev_bytenr >> 9;
-               bio->bi_end_io = btrfsic_complete_bio_end_io;
-               bio->bi_private = &complete;
+               bio->bi_iter.bi_sector = dev_bytenr >> 9;
 
                for (j = i; j < num_pages; j++) {
                        ret = bio_add_page(bio, block_ctx->pagev[j],
@@ -1712,12 +1708,7 @@ static int btrfsic_read_block(struct btrfsic_state *state,
                               "btrfsic: error, failed to add a single page!\n");
                        return -1;
                }
-               submit_bio(READ, bio);
-
-               /* this will also unplug the queue */
-               wait_for_completion(&complete);
-
-               if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) {
+               if (submit_bio_wait(READ, bio)) {
                        printk(KERN_INFO
                               "btrfsic: read error at logical %llu dev %s!\n",
                               block_ctx->start, block_ctx->dev->name);
@@ -1740,11 +1731,6 @@ static int btrfsic_read_block(struct btrfsic_state *state,
        return block_ctx->len;
 }
 
-static void btrfsic_complete_bio_end_io(struct bio *bio, int err)
-{
-       complete((struct completion *)bio->bi_private);
-}
-
 static void btrfsic_dump_database(struct btrfsic_state *state)
 {
        struct list_head *elem_all;
@@ -3008,14 +2994,12 @@ int btrfsic_submit_bh(int rw, struct buffer_head *bh)
        return submit_bh(rw, bh);
 }
 
-void btrfsic_submit_bio(int rw, struct bio *bio)
+static void __btrfsic_submit_bio(int rw, struct bio *bio)
 {
        struct btrfsic_dev_state *dev_state;
 
-       if (!btrfsic_is_initialized) {
-               submit_bio(rw, bio);
+       if (!btrfsic_is_initialized)
                return;
-       }
 
        mutex_lock(&btrfsic_mutex);
        /* since btrfsic_submit_bio() is also called before
@@ -3029,7 +3013,7 @@ void btrfsic_submit_bio(int rw, struct bio *bio)
                int bio_is_patched;
                char **mapped_datav;
 
-               dev_bytenr = 512 * bio->bi_sector;
+               dev_bytenr = 512 * bio->bi_iter.bi_sector;
                bio_is_patched = 0;
                if (dev_state->state->print_mask &
                    BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH)
@@ -3037,8 +3021,8 @@ void btrfsic_submit_bio(int rw, struct bio *bio)
                               "submit_bio(rw=0x%x, bi_vcnt=%u,"
                               " bi_sector=%llu (bytenr %llu), bi_bdev=%p)\n",
                               rw, bio->bi_vcnt,
-                              (unsigned long long)bio->bi_sector, dev_bytenr,
-                              bio->bi_bdev);
+                              (unsigned long long)bio->bi_iter.bi_sector,
+                              dev_bytenr, bio->bi_bdev);
 
                mapped_datav = kmalloc(sizeof(*mapped_datav) * bio->bi_vcnt,
                                       GFP_NOFS);
@@ -3106,10 +3090,20 @@ void btrfsic_submit_bio(int rw, struct bio *bio)
        }
 leave:
        mutex_unlock(&btrfsic_mutex);
+}
 
+void btrfsic_submit_bio(int rw, struct bio *bio)
+{
+       __btrfsic_submit_bio(rw, bio);
        submit_bio(rw, bio);
 }
 
+int btrfsic_submit_bio_wait(int rw, struct bio *bio)
+{
+       __btrfsic_submit_bio(rw, bio);
+       return submit_bio_wait(rw, bio);
+}
+
 int btrfsic_mount(struct btrfs_root *root,
                  struct btrfs_fs_devices *fs_devices,
                  int including_extent_data, u32 print_mask)
index 8b59175cc50243c7bd525c91b265fa0f329f6af1..13b8566c97ab433f7455eeb6762942d5e623d16a 100644 (file)
 #ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
 int btrfsic_submit_bh(int rw, struct buffer_head *bh);
 void btrfsic_submit_bio(int rw, struct bio *bio);
+int btrfsic_submit_bio_wait(int rw, struct bio *bio);
 #else
 #define btrfsic_submit_bh submit_bh
 #define btrfsic_submit_bio submit_bio
+#define btrfsic_submit_bio_wait submit_bio_wait
 #endif
 
 int btrfsic_mount(struct btrfs_root *root,
index 1499b27b41863e7dfbbe7da134b1a7fb66dece34..f5cdeb4b553824744429cff1f4d8b57c17a27909 100644 (file)
@@ -172,7 +172,8 @@ static void end_compressed_bio_read(struct bio *bio, int err)
                goto out;
 
        inode = cb->inode;
-       ret = check_compressed_csum(inode, cb, (u64)bio->bi_sector << 9);
+       ret = check_compressed_csum(inode, cb,
+                                   (u64)bio->bi_iter.bi_sector << 9);
        if (ret)
                goto csum_failed;
 
@@ -201,18 +202,16 @@ csum_failed:
        if (cb->errors) {
                bio_io_error(cb->orig_bio);
        } else {
-               int bio_index = 0;
-               struct bio_vec *bvec = cb->orig_bio->bi_io_vec;
+               int i;
+               struct bio_vec *bvec;
 
                /*
                 * we have verified the checksum already, set page
                 * checked so the end_io handlers know about it
                 */
-               while (bio_index < cb->orig_bio->bi_vcnt) {
+               bio_for_each_segment_all(bvec, cb->orig_bio, i)
                        SetPageChecked(bvec->bv_page);
-                       bvec++;
-                       bio_index++;
-               }
+
                bio_endio(cb->orig_bio, 0);
        }
 
@@ -372,7 +371,7 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start,
        for (pg_index = 0; pg_index < cb->nr_pages; pg_index++) {
                page = compressed_pages[pg_index];
                page->mapping = inode->i_mapping;
-               if (bio->bi_size)
+               if (bio->bi_iter.bi_size)
                        ret = io_tree->ops->merge_bio_hook(WRITE, page, 0,
                                                           PAGE_CACHE_SIZE,
                                                           bio, 0);
@@ -506,7 +505,7 @@ static noinline int add_ra_bio_pages(struct inode *inode,
 
                if (!em || last_offset < em->start ||
                    (last_offset + PAGE_CACHE_SIZE > extent_map_end(em)) ||
-                   (em->block_start >> 9) != cb->orig_bio->bi_sector) {
+                   (em->block_start >> 9) != cb->orig_bio->bi_iter.bi_sector) {
                        free_extent_map(em);
                        unlock_extent(tree, last_offset, end);
                        unlock_page(page);
@@ -552,7 +551,7 @@ next:
  * in it.  We don't actually do IO on those pages but allocate new ones
  * to hold the compressed pages on disk.
  *
- * bio->bi_sector points to the compressed extent on disk
+ * bio->bi_iter.bi_sector points to the compressed extent on disk
  * bio->bi_io_vec points to all of the inode pages
  * bio->bi_vcnt is a count of pages
  *
@@ -573,7 +572,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
        struct page *page;
        struct block_device *bdev;
        struct bio *comp_bio;
-       u64 cur_disk_byte = (u64)bio->bi_sector << 9;
+       u64 cur_disk_byte = (u64)bio->bi_iter.bi_sector << 9;
        u64 em_len;
        u64 em_start;
        struct extent_map *em;
@@ -659,7 +658,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
                page->mapping = inode->i_mapping;
                page->index = em_start >> PAGE_CACHE_SHIFT;
 
-               if (comp_bio->bi_size)
+               if (comp_bio->bi_iter.bi_size)
                        ret = tree->ops->merge_bio_hook(READ, page, 0,
                                                        PAGE_CACHE_SIZE,
                                                        comp_bio, 0);
@@ -687,8 +686,8 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
                                                        comp_bio, sums);
                                BUG_ON(ret); /* -ENOMEM */
                        }
-                       sums += (comp_bio->bi_size + root->sectorsize - 1) /
-                               root->sectorsize;
+                       sums += (comp_bio->bi_iter.bi_size +
+                                root->sectorsize - 1) / root->sectorsize;
 
                        ret = btrfs_map_bio(root, READ, comp_bio,
                                            mirror_num, 0);
index 8072cfa8a3b16c075e5c381f481e7cb874d9c531..e71039ea66cf9d4bf8a56bdd984bc7e26597aa74 100644 (file)
@@ -842,20 +842,17 @@ int btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct inode *inode,
 
 static int btree_csum_one_bio(struct bio *bio)
 {
-       struct bio_vec *bvec = bio->bi_io_vec;
-       int bio_index = 0;
+       struct bio_vec *bvec;
        struct btrfs_root *root;
-       int ret = 0;
+       int i, ret = 0;
 
-       WARN_ON(bio->bi_vcnt <= 0);
-       while (bio_index < bio->bi_vcnt) {
+       bio_for_each_segment_all(bvec, bio, i) {
                root = BTRFS_I(bvec->bv_page->mapping->host)->root;
                ret = csum_dirty_buffer(root, bvec->bv_page);
                if (ret)
                        break;
-               bio_index++;
-               bvec++;
        }
+
        return ret;
 }
 
@@ -1695,7 +1692,7 @@ static void end_workqueue_fn(struct btrfs_work *work)
        bio->bi_private = end_io_wq->private;
        bio->bi_end_io = end_io_wq->end_io;
        kfree(end_io_wq);
-       bio_endio(bio, error);
+       bio_endio_nodec(bio, error);
 }
 
 static int cleaner_kthread(void *arg)
index 8e457fca0a0ba5c04afb84414ccd640821a640d1..bcb6f1b780d64512868303c04a7939060612e3e3 100644 (file)
@@ -1952,11 +1952,6 @@ static int free_io_failure(struct inode *inode, struct io_failure_record *rec,
        return err;
 }
 
-static void repair_io_failure_callback(struct bio *bio, int err)
-{
-       complete(bio->bi_private);
-}
-
 /*
  * this bypasses the standard btrfs submit functions deliberately, as
  * the standard behavior is to write all copies in a raid setup. here we only
@@ -1973,7 +1968,6 @@ int repair_io_failure(struct btrfs_fs_info *fs_info, u64 start,
 {
        struct bio *bio;
        struct btrfs_device *dev;
-       DECLARE_COMPLETION_ONSTACK(compl);
        u64 map_length = 0;
        u64 sector;
        struct btrfs_bio *bbio = NULL;
@@ -1990,9 +1984,7 @@ int repair_io_failure(struct btrfs_fs_info *fs_info, u64 start,
        bio = btrfs_io_bio_alloc(GFP_NOFS, 1);
        if (!bio)
                return -EIO;
-       bio->bi_private = &compl;
-       bio->bi_end_io = repair_io_failure_callback;
-       bio->bi_size = 0;
+       bio->bi_iter.bi_size = 0;
        map_length = length;
 
        ret = btrfs_map_block(fs_info, WRITE, logical,
@@ -2003,7 +1995,7 @@ int repair_io_failure(struct btrfs_fs_info *fs_info, u64 start,
        }
        BUG_ON(mirror_num != bbio->mirror_num);
        sector = bbio->stripes[mirror_num-1].physical >> 9;
-       bio->bi_sector = sector;
+       bio->bi_iter.bi_sector = sector;
        dev = bbio->stripes[mirror_num-1].dev;
        kfree(bbio);
        if (!dev || !dev->bdev || !dev->writeable) {
@@ -2012,10 +2004,8 @@ int repair_io_failure(struct btrfs_fs_info *fs_info, u64 start,
        }
        bio->bi_bdev = dev->bdev;
        bio_add_page(bio, page, length, start - page_offset(page));
-       btrfsic_submit_bio(WRITE_SYNC, bio);
-       wait_for_completion(&compl);
 
-       if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) {
+       if (btrfsic_submit_bio_wait(WRITE_SYNC, bio)) {
                /* try to remap that extent elsewhere? */
                bio_put(bio);
                btrfs_dev_stat_inc_and_print(dev, BTRFS_DEV_STAT_WRITE_ERRS);
@@ -2278,9 +2268,9 @@ static int bio_readpage_error(struct bio *failed_bio, u64 phy_offset,
                return -EIO;
        }
        bio->bi_end_io = failed_bio->bi_end_io;
-       bio->bi_sector = failrec->logical >> 9;
+       bio->bi_iter.bi_sector = failrec->logical >> 9;
        bio->bi_bdev = BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev;
-       bio->bi_size = 0;
+       bio->bi_iter.bi_size = 0;
 
        btrfs_failed_bio = btrfs_io_bio(failed_bio);
        if (btrfs_failed_bio->csum) {
@@ -2342,12 +2332,13 @@ int end_extent_writepage(struct page *page, int err, u64 start, u64 end)
  */
 static void end_bio_extent_writepage(struct bio *bio, int err)
 {
-       struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
+       struct bio_vec *bvec;
        struct extent_io_tree *tree;
        u64 start;
        u64 end;
+       int i;
 
-       do {
+       bio_for_each_segment_all(bvec, bio, i) {
                struct page *page = bvec->bv_page;
                tree = &BTRFS_I(page->mapping->host)->io_tree;
 
@@ -2365,14 +2356,11 @@ static void end_bio_extent_writepage(struct bio *bio, int err)
                start = page_offset(page);
                end = start + bvec->bv_offset + bvec->bv_len - 1;
 
-               if (--bvec >= bio->bi_io_vec)
-                       prefetchw(&bvec->bv_page->flags);
-
                if (end_extent_writepage(page, err, start, end))
                        continue;
 
                end_page_writeback(page);
-       } while (bvec >= bio->bi_io_vec);
+       }
 
        bio_put(bio);
 }
@@ -2402,9 +2390,8 @@ endio_readpage_release_extent(struct extent_io_tree *tree, u64 start, u64 len,
  */
 static void end_bio_extent_readpage(struct bio *bio, int err)
 {
+       struct bio_vec *bvec;
        int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
-       struct bio_vec *bvec_end = bio->bi_io_vec + bio->bi_vcnt - 1;
-       struct bio_vec *bvec = bio->bi_io_vec;
        struct btrfs_io_bio *io_bio = btrfs_io_bio(bio);
        struct extent_io_tree *tree;
        u64 offset = 0;
@@ -2415,16 +2402,17 @@ static void end_bio_extent_readpage(struct bio *bio, int err)
        u64 extent_len = 0;
        int mirror;
        int ret;
+       int i;
 
        if (err)
                uptodate = 0;
 
-       do {
+       bio_for_each_segment_all(bvec, bio, i) {
                struct page *page = bvec->bv_page;
                struct inode *inode = page->mapping->host;
 
                pr_debug("end_bio_extent_readpage: bi_sector=%llu, err=%d, "
-                        "mirror=%lu\n", (u64)bio->bi_sector, err,
+                        "mirror=%lu\n", (u64)bio->bi_iter.bi_sector, err,
                         io_bio->mirror_num);
                tree = &BTRFS_I(inode)->io_tree;
 
@@ -2443,9 +2431,6 @@ static void end_bio_extent_readpage(struct bio *bio, int err)
                end = start + bvec->bv_offset + bvec->bv_len - 1;
                len = bvec->bv_len;
 
-               if (++bvec <= bvec_end)
-                       prefetchw(&bvec->bv_page->flags);
-
                mirror = io_bio->mirror_num;
                if (likely(uptodate && tree->ops &&
                           tree->ops->readpage_end_io_hook)) {
@@ -2526,7 +2511,7 @@ readpage_ok:
                        extent_start = start;
                        extent_len = end + 1 - start;
                }
-       } while (bvec <= bvec_end);
+       }
 
        if (extent_len)
                endio_readpage_release_extent(tree, extent_start, extent_len,
@@ -2557,9 +2542,8 @@ btrfs_bio_alloc(struct block_device *bdev, u64 first_sector, int nr_vecs,
        }
 
        if (bio) {
-               bio->bi_size = 0;
                bio->bi_bdev = bdev;
-               bio->bi_sector = first_sector;
+               bio->bi_iter.bi_sector = first_sector;
                btrfs_bio = btrfs_io_bio(bio);
                btrfs_bio->csum = NULL;
                btrfs_bio->csum_allocated = NULL;
@@ -2653,7 +2637,7 @@ static int submit_extent_page(int rw, struct extent_io_tree *tree,
        if (bio_ret && *bio_ret) {
                bio = *bio_ret;
                if (old_compressed)
-                       contig = bio->bi_sector == sector;
+                       contig = bio->bi_iter.bi_sector == sector;
                else
                        contig = bio_end_sector(bio) == sector;
 
@@ -3420,20 +3404,18 @@ static void end_extent_buffer_writeback(struct extent_buffer *eb)
 
 static void end_bio_extent_buffer_writepage(struct bio *bio, int err)
 {
-       int uptodate = err == 0;
-       struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
+       struct bio_vec *bvec;
        struct extent_buffer *eb;
-       int done;
+       int i, done;
 
-       do {
+       bio_for_each_segment_all(bvec, bio, i) {
                struct page *page = bvec->bv_page;
 
-               bvec--;
                eb = (struct extent_buffer *)page->private;
                BUG_ON(!eb);
                done = atomic_dec_and_test(&eb->io_pages);
 
-               if (!uptodate || test_bit(EXTENT_BUFFER_IOERR, &eb->bflags)) {
+               if (err || test_bit(EXTENT_BUFFER_IOERR, &eb->bflags)) {
                        set_bit(EXTENT_BUFFER_IOERR, &eb->bflags);
                        ClearPageUptodate(page);
                        SetPageError(page);
@@ -3445,10 +3427,9 @@ static void end_bio_extent_buffer_writepage(struct bio *bio, int err)
                        continue;
 
                end_extent_buffer_writeback(eb);
-       } while (bvec >= bio->bi_io_vec);
+       }
 
        bio_put(bio);
-
 }
 
 static int write_one_eb(struct extent_buffer *eb,
index 6f384886028386f2f069756ef18e757b10ba9dbf..84a46a42d26269b94fbb0a823e1fec43439d5e69 100644 (file)
@@ -182,7 +182,7 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
        if (!path)
                return -ENOMEM;
 
-       nblocks = bio->bi_size >> inode->i_sb->s_blocksize_bits;
+       nblocks = bio->bi_iter.bi_size >> inode->i_sb->s_blocksize_bits;
        if (!dst) {
                if (nblocks * csum_size > BTRFS_BIO_INLINE_CSUM_SIZE) {
                        btrfs_bio->csum_allocated = kmalloc(nblocks * csum_size,
@@ -201,7 +201,7 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
                csum = (u8 *)dst;
        }
 
-       if (bio->bi_size > PAGE_CACHE_SIZE * 8)
+       if (bio->bi_iter.bi_size > PAGE_CACHE_SIZE * 8)
                path->reada = 2;
 
        WARN_ON(bio->bi_vcnt <= 0);
@@ -217,7 +217,7 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
                path->skip_locking = 1;
        }
 
-       disk_bytenr = (u64)bio->bi_sector << 9;
+       disk_bytenr = (u64)bio->bi_iter.bi_sector << 9;
        if (dio)
                offset = logical_offset;
        while (bio_index < bio->bi_vcnt) {
@@ -302,7 +302,7 @@ int btrfs_lookup_bio_sums_dio(struct btrfs_root *root, struct inode *inode,
                              struct btrfs_dio_private *dip, struct bio *bio,
                              u64 offset)
 {
-       int len = (bio->bi_sector << 9) - dip->disk_bytenr;
+       int len = (bio->bi_iter.bi_sector << 9) - dip->disk_bytenr;
        u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy);
        int ret;
 
@@ -447,11 +447,12 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode,
        u64 offset;
 
        WARN_ON(bio->bi_vcnt <= 0);
-       sums = kzalloc(btrfs_ordered_sum_size(root, bio->bi_size), GFP_NOFS);
+       sums = kzalloc(btrfs_ordered_sum_size(root, bio->bi_iter.bi_size),
+                      GFP_NOFS);
        if (!sums)
                return -ENOMEM;
 
-       sums->len = bio->bi_size;
+       sums->len = bio->bi_iter.bi_size;
        INIT_LIST_HEAD(&sums->list);
 
        if (contig)
@@ -461,7 +462,7 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode,
 
        ordered = btrfs_lookup_ordered_extent(inode, offset);
        BUG_ON(!ordered); /* Logic error */
-       sums->bytenr = (u64)bio->bi_sector << 9;
+       sums->bytenr = (u64)bio->bi_iter.bi_sector << 9;
        index = 0;
 
        while (bio_index < bio->bi_vcnt) {
@@ -476,7 +477,7 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode,
                        btrfs_add_ordered_sum(inode, ordered, sums);
                        btrfs_put_ordered_extent(ordered);
 
-                       bytes_left = bio->bi_size - total_bytes;
+                       bytes_left = bio->bi_iter.bi_size - total_bytes;
 
                        sums = kzalloc(btrfs_ordered_sum_size(root, bytes_left),
                                       GFP_NOFS);
@@ -484,7 +485,7 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode,
                        sums->len = bytes_left;
                        ordered = btrfs_lookup_ordered_extent(inode, offset);
                        BUG_ON(!ordered); /* Logic error */
-                       sums->bytenr = ((u64)bio->bi_sector << 9) +
+                       sums->bytenr = ((u64)bio->bi_iter.bi_sector << 9) +
                                       total_bytes;
                        index = 0;
                }
index f1a77449d032b1fbd481eb16cd232653e5bfbefa..39a5ea25fd2304757b6ef0996778b1ff0050cd51 100644 (file)
@@ -1577,7 +1577,7 @@ int btrfs_merge_bio_hook(int rw, struct page *page, unsigned long offset,
                         unsigned long bio_flags)
 {
        struct btrfs_root *root = BTRFS_I(page->mapping->host)->root;
-       u64 logical = (u64)bio->bi_sector << 9;
+       u64 logical = (u64)bio->bi_iter.bi_sector << 9;
        u64 length = 0;
        u64 map_length;
        int ret;
@@ -1585,7 +1585,7 @@ int btrfs_merge_bio_hook(int rw, struct page *page, unsigned long offset,
        if (bio_flags & EXTENT_BIO_COMPRESSED)
                return 0;
 
-       length = bio->bi_size;
+       length = bio->bi_iter.bi_size;
        map_length = length;
        ret = btrfs_map_block(root->fs_info, rw, logical,
                              &map_length, NULL, 0);
@@ -4354,8 +4354,12 @@ static int btrfs_setsize(struct inode *inode, struct iattr *attr)
         * these flags set.  For all other operations the VFS set these flags
         * explicitly if it wants a timestamp update.
         */
-       if (newsize != oldsize && (!(mask & (ATTR_CTIME | ATTR_MTIME))))
-               inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb);
+       if (newsize != oldsize) {
+               inode_inc_iversion(inode);
+               if (!(mask & (ATTR_CTIME | ATTR_MTIME)))
+                       inode->i_ctime = inode->i_mtime =
+                               current_fs_time(inode->i_sb);
+       }
 
        if (newsize > oldsize) {
                truncate_pagecache(inode, newsize);
@@ -6779,17 +6783,16 @@ unlock_err:
 static void btrfs_endio_direct_read(struct bio *bio, int err)
 {
        struct btrfs_dio_private *dip = bio->bi_private;
-       struct bio_vec *bvec_end = bio->bi_io_vec + bio->bi_vcnt - 1;
-       struct bio_vec *bvec = bio->bi_io_vec;
+       struct bio_vec *bvec;
        struct inode *inode = dip->inode;
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct bio *dio_bio;
        u32 *csums = (u32 *)dip->csum;
-       int index = 0;
        u64 start;
+       int i;
 
        start = dip->logical_offset;
-       do {
+       bio_for_each_segment_all(bvec, bio, i) {
                if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) {
                        struct page *page = bvec->bv_page;
                        char *kaddr;
@@ -6805,18 +6808,16 @@ static void btrfs_endio_direct_read(struct bio *bio, int err)
                        local_irq_restore(flags);
 
                        flush_dcache_page(bvec->bv_page);
-                       if (csum != csums[index]) {
+                       if (csum != csums[i]) {
                                btrfs_err(root->fs_info, "csum failed ino %llu off %llu csum %u expected csum %u",
                                          btrfs_ino(inode), start, csum,
-                                         csums[index]);
+                                         csums[i]);
                                err = -EIO;
                        }
                }
 
                start += bvec->bv_len;
-               bvec++;
-               index++;
-       } while (bvec <= bvec_end);
+       }
 
        unlock_extent(&BTRFS_I(inode)->io_tree, dip->logical_offset,
                      dip->logical_offset + dip->bytes - 1);
@@ -6897,7 +6898,8 @@ static void btrfs_end_dio_bio(struct bio *bio, int err)
                printk(KERN_ERR "btrfs direct IO failed ino %llu rw %lu "
                      "sector %#Lx len %u err no %d\n",
                      btrfs_ino(dip->inode), bio->bi_rw,
-                     (unsigned long long)bio->bi_sector, bio->bi_size, err);
+                     (unsigned long long)bio->bi_iter.bi_sector,
+                     bio->bi_iter.bi_size, err);
                dip->errors = 1;
 
                /*
@@ -6988,7 +6990,7 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
        struct bio *bio;
        struct bio *orig_bio = dip->orig_bio;
        struct bio_vec *bvec = orig_bio->bi_io_vec;
-       u64 start_sector = orig_bio->bi_sector;
+       u64 start_sector = orig_bio->bi_iter.bi_sector;
        u64 file_offset = dip->logical_offset;
        u64 submit_len = 0;
        u64 map_length;
@@ -6996,7 +6998,7 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
        int ret = 0;
        int async_submit = 0;
 
-       map_length = orig_bio->bi_size;
+       map_length = orig_bio->bi_iter.bi_size;
        ret = btrfs_map_block(root->fs_info, rw, start_sector << 9,
                              &map_length, NULL, 0);
        if (ret) {
@@ -7004,7 +7006,7 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
                return -EIO;
        }
 
-       if (map_length >= orig_bio->bi_size) {
+       if (map_length >= orig_bio->bi_iter.bi_size) {
                bio = orig_bio;
                goto submit;
        }
@@ -7056,7 +7058,7 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
                        bio->bi_private = dip;
                        bio->bi_end_io = btrfs_end_dio_bio;
 
-                       map_length = orig_bio->bi_size;
+                       map_length = orig_bio->bi_iter.bi_size;
                        ret = btrfs_map_block(root->fs_info, rw,
                                              start_sector << 9,
                                              &map_length, NULL, 0);
@@ -7114,7 +7116,8 @@ static void btrfs_submit_direct(int rw, struct bio *dio_bio,
 
        if (!skip_sum && !write) {
                csum_size = btrfs_super_csum_size(root->fs_info->super_copy);
-               sum_len = dio_bio->bi_size >> inode->i_sb->s_blocksize_bits;
+               sum_len = dio_bio->bi_iter.bi_size >>
+                       inode->i_sb->s_blocksize_bits;
                sum_len *= csum_size;
        } else {
                sum_len = 0;
@@ -7129,8 +7132,8 @@ static void btrfs_submit_direct(int rw, struct bio *dio_bio,
        dip->private = dio_bio->bi_private;
        dip->inode = inode;
        dip->logical_offset = file_offset;
-       dip->bytes = dio_bio->bi_size;
-       dip->disk_bytenr = (u64)dio_bio->bi_sector << 9;
+       dip->bytes = dio_bio->bi_iter.bi_size;
+       dip->disk_bytenr = (u64)dio_bio->bi_iter.bi_sector << 9;
        io_bio->bi_private = dip;
        dip->errors = 0;
        dip->orig_bio = io_bio;
index 24ac21840a9a0797cdb086a58e90e64a3c1481ad..9af0b25d991a8c64653b4fa20f4dc31c2794b943 100644 (file)
@@ -1032,8 +1032,8 @@ static int rbio_add_io_page(struct btrfs_raid_bio *rbio,
 
        /* see if we can add this page onto our existing bio */
        if (last) {
-               last_end = (u64)last->bi_sector << 9;
-               last_end += last->bi_size;
+               last_end = (u64)last->bi_iter.bi_sector << 9;
+               last_end += last->bi_iter.bi_size;
 
                /*
                 * we can't merge these if they are from different
@@ -1053,9 +1053,9 @@ static int rbio_add_io_page(struct btrfs_raid_bio *rbio,
        if (!bio)
                return -ENOMEM;
 
-       bio->bi_size = 0;
+       bio->bi_iter.bi_size = 0;
        bio->bi_bdev = stripe->dev->bdev;
-       bio->bi_sector = disk_start >> 9;
+       bio->bi_iter.bi_sector = disk_start >> 9;
        set_bit(BIO_UPTODATE, &bio->bi_flags);
 
        bio_add_page(bio, page, PAGE_CACHE_SIZE, 0);
@@ -1111,7 +1111,7 @@ static void index_rbio_pages(struct btrfs_raid_bio *rbio)
 
        spin_lock_irq(&rbio->bio_list_lock);
        bio_list_for_each(bio, &rbio->bio_list) {
-               start = (u64)bio->bi_sector << 9;
+               start = (u64)bio->bi_iter.bi_sector << 9;
                stripe_offset = start - rbio->raid_map[0];
                page_index = stripe_offset >> PAGE_CACHE_SHIFT;
 
@@ -1272,7 +1272,7 @@ cleanup:
 static int find_bio_stripe(struct btrfs_raid_bio *rbio,
                           struct bio *bio)
 {
-       u64 physical = bio->bi_sector;
+       u64 physical = bio->bi_iter.bi_sector;
        u64 stripe_start;
        int i;
        struct btrfs_bio_stripe *stripe;
@@ -1298,7 +1298,7 @@ static int find_bio_stripe(struct btrfs_raid_bio *rbio,
 static int find_logical_bio_stripe(struct btrfs_raid_bio *rbio,
                                   struct bio *bio)
 {
-       u64 logical = bio->bi_sector;
+       u64 logical = bio->bi_iter.bi_sector;
        u64 stripe_start;
        int i;
 
@@ -1602,8 +1602,8 @@ static int plug_cmp(void *priv, struct list_head *a, struct list_head *b)
                                                 plug_list);
        struct btrfs_raid_bio *rb = container_of(b, struct btrfs_raid_bio,
                                                 plug_list);
-       u64 a_sector = ra->bio_list.head->bi_sector;
-       u64 b_sector = rb->bio_list.head->bi_sector;
+       u64 a_sector = ra->bio_list.head->bi_iter.bi_sector;
+       u64 b_sector = rb->bio_list.head->bi_iter.bi_sector;
 
        if (a_sector < b_sector)
                return -1;
@@ -1691,7 +1691,7 @@ int raid56_parity_write(struct btrfs_root *root, struct bio *bio,
        if (IS_ERR(rbio))
                return PTR_ERR(rbio);
        bio_list_add(&rbio->bio_list, bio);
-       rbio->bio_list_bytes = bio->bi_size;
+       rbio->bio_list_bytes = bio->bi_iter.bi_size;
 
        /*
         * don't plug on full rbios, just get them out the door
@@ -2044,7 +2044,7 @@ int raid56_parity_recover(struct btrfs_root *root, struct bio *bio,
 
        rbio->read_rebuild = 1;
        bio_list_add(&rbio->bio_list, bio);
-       rbio->bio_list_bytes = bio->bi_size;
+       rbio->bio_list_bytes = bio->bi_iter.bi_size;
 
        rbio->faila = find_logical_bio_stripe(rbio, bio);
        if (rbio->faila == -1) {
index 561e2f16ba3e3ff3b0be72b12b4a052b86082d2a..bb9a928fa3a848c597d842a94fe2e49a48766cf0 100644 (file)
@@ -208,7 +208,6 @@ static void scrub_recheck_block_checksum(struct btrfs_fs_info *fs_info,
                                         int is_metadata, int have_csum,
                                         const u8 *csum, u64 generation,
                                         u16 csum_size);
-static void scrub_complete_bio_end_io(struct bio *bio, int err);
 static int scrub_repair_block_from_good_copy(struct scrub_block *sblock_bad,
                                             struct scrub_block *sblock_good,
                                             int force_write);
@@ -1294,7 +1293,6 @@ static void scrub_recheck_block(struct btrfs_fs_info *fs_info,
        for (page_num = 0; page_num < sblock->page_count; page_num++) {
                struct bio *bio;
                struct scrub_page *page = sblock->pagev[page_num];
-               DECLARE_COMPLETION_ONSTACK(complete);
 
                if (page->dev->bdev == NULL) {
                        page->io_error = 1;
@@ -1310,19 +1308,12 @@ static void scrub_recheck_block(struct btrfs_fs_info *fs_info,
                        continue;
                }
                bio->bi_bdev = page->dev->bdev;
-               bio->bi_sector = page->physical >> 9;
-               bio->bi_end_io = scrub_complete_bio_end_io;
-               bio->bi_private = &complete;
+               bio->bi_iter.bi_sector = page->physical >> 9;
 
                bio_add_page(bio, page->page, PAGE_SIZE, 0);
-               btrfsic_submit_bio(READ, bio);
-
-               /* this will also unplug the queue */
-               wait_for_completion(&complete);
-
-               page->io_error = !test_bit(BIO_UPTODATE, &bio->bi_flags);
-               if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
+               if (btrfsic_submit_bio_wait(READ, bio))
                        sblock->no_io_error_seen = 0;
+
                bio_put(bio);
        }
 
@@ -1391,11 +1382,6 @@ static void scrub_recheck_block_checksum(struct btrfs_fs_info *fs_info,
                sblock->checksum_error = 1;
 }
 
-static void scrub_complete_bio_end_io(struct bio *bio, int err)
-{
-       complete((struct completion *)bio->bi_private);
-}
-
 static int scrub_repair_block_from_good_copy(struct scrub_block *sblock_bad,
                                             struct scrub_block *sblock_good,
                                             int force_write)
@@ -1430,7 +1416,6 @@ static int scrub_repair_page_from_good_copy(struct scrub_block *sblock_bad,
            sblock_bad->checksum_error || page_bad->io_error) {
                struct bio *bio;
                int ret;
-               DECLARE_COMPLETION_ONSTACK(complete);
 
                if (!page_bad->dev->bdev) {
                        printk_ratelimited(KERN_WARNING
@@ -1442,20 +1427,15 @@ static int scrub_repair_page_from_good_copy(struct scrub_block *sblock_bad,
                if (!bio)
                        return -EIO;
                bio->bi_bdev = page_bad->dev->bdev;
-               bio->bi_sector = page_bad->physical >> 9;
-               bio->bi_end_io = scrub_complete_bio_end_io;
-               bio->bi_private = &complete;
+               bio->bi_iter.bi_sector = page_bad->physical >> 9;
 
                ret = bio_add_page(bio, page_good->page, PAGE_SIZE, 0);
                if (PAGE_SIZE != ret) {
                        bio_put(bio);
                        return -EIO;
                }
-               btrfsic_submit_bio(WRITE, bio);
 
-               /* this will also unplug the queue */
-               wait_for_completion(&complete);
-               if (!bio_flagged(bio, BIO_UPTODATE)) {
+               if (btrfsic_submit_bio_wait(WRITE, bio)) {
                        btrfs_dev_stat_inc_and_print(page_bad->dev,
                                BTRFS_DEV_STAT_WRITE_ERRS);
                        btrfs_dev_replace_stats_inc(
@@ -1540,7 +1520,7 @@ again:
                bio->bi_private = sbio;
                bio->bi_end_io = scrub_wr_bio_end_io;
                bio->bi_bdev = sbio->dev->bdev;
-               bio->bi_sector = sbio->physical >> 9;
+               bio->bi_iter.bi_sector = sbio->physical >> 9;
                sbio->err = 0;
        } else if (sbio->physical + sbio->page_count * PAGE_SIZE !=
                   spage->physical_for_dev_replace ||
@@ -1946,7 +1926,7 @@ again:
                bio->bi_private = sbio;
                bio->bi_end_io = scrub_bio_end_io;
                bio->bi_bdev = sbio->dev->bdev;
-               bio->bi_sector = sbio->physical >> 9;
+               bio->bi_iter.bi_sector = sbio->physical >> 9;
                sbio->err = 0;
        } else if (sbio->physical + sbio->page_count * PAGE_SIZE !=
                   spage->physical ||
@@ -3375,7 +3355,6 @@ static int write_page_nocow(struct scrub_ctx *sctx,
        struct bio *bio;
        struct btrfs_device *dev;
        int ret;
-       DECLARE_COMPLETION_ONSTACK(compl);
 
        dev = sctx->wr_ctx.tgtdev;
        if (!dev)
@@ -3392,10 +3371,8 @@ static int write_page_nocow(struct scrub_ctx *sctx,
                spin_unlock(&sctx->stat_lock);
                return -ENOMEM;
        }
-       bio->bi_private = &compl;
-       bio->bi_end_io = scrub_complete_bio_end_io;
-       bio->bi_size = 0;
-       bio->bi_sector = physical_for_dev_replace >> 9;
+       bio->bi_iter.bi_size = 0;
+       bio->bi_iter.bi_sector = physical_for_dev_replace >> 9;
        bio->bi_bdev = dev->bdev;
        ret = bio_add_page(bio, page, PAGE_CACHE_SIZE, 0);
        if (ret != PAGE_CACHE_SIZE) {
@@ -3404,10 +3381,8 @@ leave_with_eio:
                btrfs_dev_stat_inc_and_print(dev, BTRFS_DEV_STAT_WRITE_ERRS);
                return -EIO;
        }
-       btrfsic_submit_bio(WRITE_SYNC, bio);
-       wait_for_completion(&compl);
 
-       if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
+       if (btrfsic_submit_bio_wait(WRITE_SYNC, bio))
                goto leave_with_eio;
 
        bio_put(bio);
index 92303f42baaa92d5d845edddff1f8600fc46518e..37972d5db7375abd6d4022e3a1e6725ab357dd7c 100644 (file)
@@ -5297,6 +5297,8 @@ static void btrfs_end_bio(struct bio *bio, int err)
                if (!is_orig_bio) {
                        bio_put(bio);
                        bio = bbio->orig_bio;
+               } else {
+                       atomic_inc(&bio->bi_remaining);
                }
                bio->bi_private = bbio->private;
                bio->bi_end_io = bbio->end_io;
@@ -5411,7 +5413,7 @@ static int bio_size_ok(struct block_device *bdev, struct bio *bio,
        if (!q->merge_bvec_fn)
                return 1;
 
-       bvm.bi_size = bio->bi_size - prev->bv_len;
+       bvm.bi_size = bio->bi_iter.bi_size - prev->bv_len;
        if (q->merge_bvec_fn(q, &bvm, prev) < prev->bv_len)
                return 0;
        return 1;
@@ -5426,7 +5428,7 @@ static void submit_stripe_bio(struct btrfs_root *root, struct btrfs_bio *bbio,
        bio->bi_private = bbio;
        btrfs_io_bio(bio)->stripe_index = dev_nr;
        bio->bi_end_io = btrfs_end_bio;
-       bio->bi_sector = physical >> 9;
+       bio->bi_iter.bi_sector = physical >> 9;
 #ifdef DEBUG
        {
                struct rcu_string *name;
@@ -5464,7 +5466,7 @@ again:
        while (bvec <= (first_bio->bi_io_vec + first_bio->bi_vcnt - 1)) {
                if (bio_add_page(bio, bvec->bv_page, bvec->bv_len,
                                 bvec->bv_offset) < bvec->bv_len) {
-                       u64 len = bio->bi_size;
+                       u64 len = bio->bi_iter.bi_size;
 
                        atomic_inc(&bbio->stripes_pending);
                        submit_stripe_bio(root, bbio, bio, physical, dev_nr,
@@ -5486,7 +5488,7 @@ static void bbio_error(struct btrfs_bio *bbio, struct bio *bio, u64 logical)
                bio->bi_private = bbio->private;
                bio->bi_end_io = bbio->end_io;
                btrfs_io_bio(bio)->mirror_num = bbio->mirror_num;
-               bio->bi_sector = logical >> 9;
+               bio->bi_iter.bi_sector = logical >> 9;
                kfree(bbio);
                bio_endio(bio, -EIO);
        }
@@ -5497,7 +5499,7 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio,
 {
        struct btrfs_device *dev;
        struct bio *first_bio = bio;
-       u64 logical = (u64)bio->bi_sector << 9;
+       u64 logical = (u64)bio->bi_iter.bi_sector << 9;
        u64 length = 0;
        u64 map_length;
        u64 *raid_map = NULL;
@@ -5506,7 +5508,7 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio,
        int total_devs = 1;
        struct btrfs_bio *bbio = NULL;
 
-       length = bio->bi_size;
+       length = bio->bi_iter.bi_size;
        map_length = length;
 
        ret = __btrfs_map_block(root->fs_info, rw, logical, &map_length, &bbio,
index 6024877335caf2a9dfa6af1018c5da19b0e8a2ae..651dba10b9c2b5468af528ad3114166b90d8c067 100644 (file)
@@ -1312,7 +1312,7 @@ static void bh_lru_install(struct buffer_head *bh)
                }
                while (out < BH_LRU_SIZE)
                        bhs[out++] = NULL;
-               memcpy(__this_cpu_ptr(&bh_lrus.bhs), bhs, sizeof(bhs));
+               memcpy(this_cpu_ptr(&bh_lrus.bhs), bhs, sizeof(bhs));
        }
        bh_lru_unlock();
 
@@ -2982,11 +2982,11 @@ static void guard_bh_eod(int rw, struct bio *bio, struct buffer_head *bh)
         * let it through, and the IO layer will turn it into
         * an EIO.
         */
-       if (unlikely(bio->bi_sector >= maxsector))
+       if (unlikely(bio->bi_iter.bi_sector >= maxsector))
                return;
 
-       maxsector -= bio->bi_sector;
-       bytes = bio->bi_size;
+       maxsector -= bio->bi_iter.bi_sector;
+       bytes = bio->bi_iter.bi_size;
        if (likely((bytes >> 9) <= maxsector))
                return;
 
@@ -2994,7 +2994,7 @@ static void guard_bh_eod(int rw, struct bio *bio, struct buffer_head *bh)
        bytes = maxsector << 9;
 
        /* Truncate the bio.. */
-       bio->bi_size = bytes;
+       bio->bi_iter.bi_size = bytes;
        bio->bi_io_vec[0].bv_len = bytes;
 
        /* ..and clear the end of the buffer for reads */
@@ -3029,14 +3029,14 @@ int _submit_bh(int rw, struct buffer_head *bh, unsigned long bio_flags)
         */
        bio = bio_alloc(GFP_NOIO, 1);
 
-       bio->bi_sector = bh->b_blocknr * (bh->b_size >> 9);
+       bio->bi_iter.bi_sector = bh->b_blocknr * (bh->b_size >> 9);
        bio->bi_bdev = bh->b_bdev;
        bio->bi_io_vec[0].bv_page = bh->b_page;
        bio->bi_io_vec[0].bv_len = bh->b_size;
        bio->bi_io_vec[0].bv_offset = bh_offset(bh);
 
        bio->bi_vcnt = 1;
-       bio->bi_size = bh->b_size;
+       bio->bi_iter.bi_size = bh->b_size;
 
        bio->bi_end_io = end_bio_bh_io_sync;
        bio->bi_private = bh;
index 3de89829e2a162ab6bce2a58296b25aef9235c43..c4419e848a4f89eced64c8a156a560f62bc2cbdd 100644 (file)
@@ -408,51 +408,92 @@ more:
  *
  * If the read spans object boundary, just do multiple reads.
  */
-static ssize_t ceph_sync_read(struct file *file, char __user *data,
-                             unsigned len, loff_t *poff, int *checkeof)
+static ssize_t ceph_sync_read(struct kiocb *iocb, struct iov_iter *i,
+                               int *checkeof)
 {
+       struct file *file = iocb->ki_filp;
        struct inode *inode = file_inode(file);
        struct page **pages;
-       u64 off = *poff;
+       u64 off = iocb->ki_pos;
        int num_pages, ret;
+       size_t len = i->count;
 
-       dout("sync_read on file %p %llu~%u %s\n", file, off, len,
+       dout("sync_read on file %p %llu~%u %s\n", file, off,
+            (unsigned)len,
             (file->f_flags & O_DIRECT) ? "O_DIRECT" : "");
-
-       if (file->f_flags & O_DIRECT) {
-               num_pages = calc_pages_for((unsigned long)data, len);
-               pages = ceph_get_direct_page_vector(data, num_pages, true);
-       } else {
-               num_pages = calc_pages_for(off, len);
-               pages = ceph_alloc_page_vector(num_pages, GFP_NOFS);
-       }
-       if (IS_ERR(pages))
-               return PTR_ERR(pages);
-
        /*
         * flush any page cache pages in this range.  this
         * will make concurrent normal and sync io slow,
         * but it will at least behave sensibly when they are
         * in sequence.
         */
-       ret = filemap_write_and_wait(inode->i_mapping);
+       ret = filemap_write_and_wait_range(inode->i_mapping, off,
+                                               off + len);
        if (ret < 0)
-               goto done;
+               return ret;
 
-       ret = striped_read(inode, off, len, pages, num_pages, checkeof,
-                          file->f_flags & O_DIRECT,
-                          (unsigned long)data & ~PAGE_MASK);
+       if (file->f_flags & O_DIRECT) {
+               while (iov_iter_count(i)) {
+                       void __user *data = i->iov[0].iov_base + i->iov_offset;
+                       size_t len = i->iov[0].iov_len - i->iov_offset;
+
+                       num_pages = calc_pages_for((unsigned long)data, len);
+                       pages = ceph_get_direct_page_vector(data,
+                                                           num_pages, true);
+                       if (IS_ERR(pages))
+                               return PTR_ERR(pages);
+
+                       ret = striped_read(inode, off, len,
+                                          pages, num_pages, checkeof,
+                                          1, (unsigned long)data & ~PAGE_MASK);
+                       ceph_put_page_vector(pages, num_pages, true);
+
+                       if (ret <= 0)
+                               break;
+                       off += ret;
+                       iov_iter_advance(i, ret);
+                       if (ret < len)
+                               break;
+               }
+       } else {
+               num_pages = calc_pages_for(off, len);
+               pages = ceph_alloc_page_vector(num_pages, GFP_NOFS);
+               if (IS_ERR(pages))
+                       return PTR_ERR(pages);
+               ret = striped_read(inode, off, len, pages,
+                                       num_pages, checkeof, 0, 0);
+               if (ret > 0) {
+                       int l, k = 0;
+                       size_t left = len = ret;
+
+                       while (left) {
+                               void __user *data = i->iov[0].iov_base
+                                                       + i->iov_offset;
+                               l = min(i->iov[0].iov_len - i->iov_offset,
+                                       left);
+
+                               ret = ceph_copy_page_vector_to_user(&pages[k],
+                                                                   data, off,
+                                                                   l);
+                               if (ret > 0) {
+                                       iov_iter_advance(i, ret);
+                                       left -= ret;
+                                       off += ret;
+                                       k = calc_pages_for(iocb->ki_pos,
+                                                          len - left + 1) - 1;
+                                       BUG_ON(k >= num_pages && left);
+                               } else
+                                       break;
+                       }
+               }
+               ceph_release_page_vector(pages, num_pages);
+       }
 
-       if (ret >= 0 && (file->f_flags & O_DIRECT) == 0)
-               ret = ceph_copy_page_vector_to_user(pages, data, off, ret);
-       if (ret >= 0)
-               *poff = off + ret;
+       if (off > iocb->ki_pos) {
+               ret = off - iocb->ki_pos;
+               iocb->ki_pos = off;
+       }
 
-done:
-       if (file->f_flags & O_DIRECT)
-               ceph_put_page_vector(pages, num_pages, true);
-       else
-               ceph_release_page_vector(pages, num_pages);
        dout("sync_read result %d\n", ret);
        return ret;
 }
@@ -489,83 +530,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 = i.iov->iov_base + i.iov_offset;
+               u64 len = i.iov->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 +614,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;
 }
@@ -647,55 +799,84 @@ static ssize_t ceph_aio_read(struct kiocb *iocb, const struct iovec *iov,
 {
        struct file *filp = iocb->ki_filp;
        struct ceph_file_info *fi = filp->private_data;
-       loff_t *ppos = &iocb->ki_pos;
-       size_t len = iov->iov_len;
+       size_t len = iocb->ki_nbytes;
        struct inode *inode = file_inode(filp);
        struct ceph_inode_info *ci = ceph_inode(inode);
-       void __user *base = iov->iov_base;
        ssize_t ret;
        int want, got = 0;
        int checkeof = 0, read = 0;
 
-       dout("aio_read %p %llx.%llx %llu~%u trying to get caps on %p\n",
-            inode, ceph_vinop(inode), pos, (unsigned)len, inode);
 again:
+       dout("aio_read %p %llx.%llx %llu~%u trying to get caps on %p\n",
+            inode, ceph_vinop(inode), iocb->ki_pos, (unsigned)len, inode);
+
        if (fi->fmode & CEPH_FILE_MODE_LAZY)
                want = CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_LAZYIO;
        else
                want = CEPH_CAP_FILE_CACHE;
        ret = ceph_get_caps(ci, CEPH_CAP_FILE_RD, want, &got, -1);
        if (ret < 0)
-               goto out;
-       dout("aio_read %p %llx.%llx %llu~%u got cap refs on %s\n",
-            inode, ceph_vinop(inode), pos, (unsigned)len,
-            ceph_cap_string(got));
+               return ret;
 
        if ((got & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)) == 0 ||
            (iocb->ki_filp->f_flags & O_DIRECT) ||
-           (fi->flags & CEPH_F_SYNC))
+           (fi->flags & CEPH_F_SYNC)) {
+               struct iov_iter i;
+
+               dout("aio_sync_read %p %llx.%llx %llu~%u got cap refs on %s\n",
+                    inode, ceph_vinop(inode), iocb->ki_pos, (unsigned)len,
+                    ceph_cap_string(got));
+
+               if (!read) {
+                       ret = generic_segment_checks(iov, &nr_segs,
+                                                       &len, VERIFY_WRITE);
+                       if (ret)
+                               goto out;
+               }
+
+               iov_iter_init(&i, iov, nr_segs, len, read);
+
                /* hmm, this isn't really async... */
-               ret = ceph_sync_read(filp, base, len, ppos, &checkeof);
-       else
-               ret = generic_file_aio_read(iocb, iov, nr_segs, pos);
+               ret = ceph_sync_read(iocb, &i, &checkeof);
+       } else {
+               /*
+                * We can't modify the content of iov,
+                * so we only read from beginning.
+                */
+               if (read) {
+                       iocb->ki_pos = pos;
+                       len = iocb->ki_nbytes;
+                       read = 0;
+               }
+               dout("aio_read %p %llx.%llx %llu~%u got cap refs on %s\n",
+                    inode, ceph_vinop(inode), pos, (unsigned)len,
+                    ceph_cap_string(got));
 
+               ret = generic_file_aio_read(iocb, iov, nr_segs, pos);
+       }
 out:
        dout("aio_read %p %llx.%llx dropping cap refs on %s = %d\n",
             inode, ceph_vinop(inode), ceph_cap_string(got), (int)ret);
        ceph_put_cap_refs(ci, got);
 
        if (checkeof && ret >= 0) {
-               int statret = ceph_do_getattr(inode, CEPH_STAT_CAP_SIZE);
+               int statret = ceph_do_getattr(inode,
+                                             CEPH_STAT_CAP_SIZE);
 
                /* hit EOF or hole? */
-               if (statret == 0 && *ppos < inode->i_size) {
-                       dout("aio_read sync_read hit hole, ppos %lld < size %lld, reading more\n", *ppos, inode->i_size);
+               if (statret == 0 && iocb->ki_pos < inode->i_size &&
+                       ret < len) {
+                       dout("sync_read hit hole, ppos %lld < size %lld"
+                            ", reading more\n", iocb->ki_pos,
+                            inode->i_size);
+
                        read += ret;
-                       base += ret;
                        len -= ret;
                        checkeof = 0;
                        goto again;
                }
        }
+
        if (ret >= 0)
                ret += read;
 
@@ -772,11 +953,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",
index 9a8e396aed89a43a0c824c3b682f96ac817ebc1c..2ae1381de64a102c89d3fbe9b92dee3893fbbe7a 100644 (file)
@@ -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
index 6a0951e4304441a241ca8fe550aba36cc097c271..e58bd4a23bfb532bd2c119345bb4669be1d9336b 100644 (file)
@@ -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,
index ef4ac38bb614a911680668fe52f6e7fa272d94ce..8de94b564d670d28a033d6ccfc309a37f799ab57 100644 (file)
@@ -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);
index aa3397620342d20beba92abc732845273d3663ca..2c29db6a247e4788256461100bed11ac79648d26 100644 (file)
@@ -477,9 +477,10 @@ extern int CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
                        const int netfid, __u64 *pExtAttrBits, __u64 *pMask);
 extern void cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb);
 extern bool CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr);
-extern int CIFSCheckMFSymlink(struct cifs_fattr *fattr,
-               const unsigned char *path,
-               struct cifs_sb_info *cifs_sb, unsigned int xid);
+extern int CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon,
+                             struct cifs_sb_info *cifs_sb,
+                             struct cifs_fattr *fattr,
+                             const unsigned char *path);
 extern int mdfour(unsigned char *, unsigned char *, int);
 extern int E_md4hash(const unsigned char *passwd, unsigned char *p16,
                        const struct nls_table *codepage);
index 124aa0230c1b8738edb8d04ca5d764f0a6cc5b12..d707edb6b852695f0de3993c9ef9cd12a3f909f3 100644 (file)
@@ -4010,7 +4010,7 @@ QFileInfoRetry:
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
-               cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
+               cifs_dbg(FYI, "Send error in QFileInfo = %d", rc);
        } else {                /* decode response */
                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
@@ -4179,7 +4179,7 @@ UnixQFileInfoRetry:
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
-               cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
+               cifs_dbg(FYI, "Send error in UnixQFileInfo = %d", rc);
        } else {                /* decode response */
                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
@@ -4263,7 +4263,7 @@ UnixQPathInfoRetry:
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
-               cifs_dbg(FYI, "Send error in QPathInfo = %d\n", rc);
+               cifs_dbg(FYI, "Send error in UnixQPathInfo = %d", rc);
        } else {                /* decode response */
                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
index 36f9ebb93ceba676c363cdf7b973f3936a9dde8f..49719b8228e58bd44b373fd4b39d844be9e2043b 100644 (file)
@@ -383,7 +383,8 @@ int cifs_get_inode_info_unix(struct inode **pinode,
 
        /* check for Minshall+French symlinks */
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
-               int tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid);
+               int tmprc = CIFSCheckMFSymlink(xid, tcon, cifs_sb, &fattr,
+                                              full_path);
                if (tmprc)
                        cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc);
        }
@@ -799,7 +800,8 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
 
        /* check for Minshall+French symlinks */
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
-               tmprc = CIFSCheckMFSymlink(&fattr, full_path, cifs_sb, xid);
+               tmprc = CIFSCheckMFSymlink(xid, tcon, cifs_sb, &fattr,
+                                          full_path);
                if (tmprc)
                        cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc);
        }
index cc0234710ddbb780cae5037b717a93d8a7d3d54d..92aee08483a52e100011fb05e1fcfc5255b340ac 100644 (file)
@@ -354,34 +354,30 @@ open_query_close_cifs_symlink(const unsigned char *path, char *pbuf,
 
 
 int
-CIFSCheckMFSymlink(struct cifs_fattr *fattr,
-                  const unsigned char *path,
-                  struct cifs_sb_info *cifs_sb, unsigned int xid)
+CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon,
+                  struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
+                  const unsigned char *path)
 {
-       int rc = 0;
+       int rc;
        u8 *buf = NULL;
        unsigned int link_len = 0;
        unsigned int bytes_read = 0;
-       struct cifs_tcon *ptcon;
 
        if (!CIFSCouldBeMFSymlink(fattr))
                /* it's not a symlink */
                return 0;
 
        buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
-       if (!buf) {
-               rc = -ENOMEM;
-               goto out;
-       }
+       if (!buf)
+               return -ENOMEM;
 
-       ptcon = tlink_tcon(cifs_sb_tlink(cifs_sb));
-       if ((ptcon->ses) && (ptcon->ses->server->ops->query_mf_symlink))
-               rc = ptcon->ses->server->ops->query_mf_symlink(path, buf,
-                                                &bytes_read, cifs_sb, xid);
+       if (tcon->ses->server->ops->query_mf_symlink)
+               rc = tcon->ses->server->ops->query_mf_symlink(path, buf,
+                                               &bytes_read, cifs_sb, xid);
        else
-               goto out;
+               rc = -ENOSYS;
 
-       if (rc != 0)
+       if (rc)
                goto out;
 
        if (bytes_read == 0) /* not a symlink */
index 0e04142d5962312fcb055738479247b2364a252e..160a5489a93936372c85683ee8cfd6da5185007b 100644 (file)
@@ -375,7 +375,7 @@ dio_bio_alloc(struct dio *dio, struct dio_submit *sdio,
        bio = bio_alloc(GFP_KERNEL, nr_vecs);
 
        bio->bi_bdev = bdev;
-       bio->bi_sector = first_sector;
+       bio->bi_iter.bi_sector = first_sector;
        if (dio->is_async)
                bio->bi_end_io = dio_bio_end_aio;
        else
@@ -719,7 +719,7 @@ static inline int dio_send_cur_page(struct dio *dio, struct dio_submit *sdio,
        if (sdio->bio) {
                loff_t cur_offset = sdio->cur_page_fs_offset;
                loff_t bio_next_offset = sdio->logical_offset_in_bio +
-                       sdio->bio->bi_size;
+                       sdio->bio->bi_iter.bi_size;
 
                /*
                 * See whether this new request is contiguous with the old.
index d90909ec6aa6bc5dd846b0545773b8cee0bee7d8..9c2bceeb4fe91a94981a69616c6a87760533e3da 100644 (file)
@@ -649,6 +649,7 @@ static void process_sctp_notification(struct connection *con,
                                      struct msghdr *msg, char *buf)
 {
        union sctp_notification *sn = (union sctp_notification *)buf;
+       struct linger linger;
 
        switch (sn->sn_header.sn_type) {
        case SCTP_SEND_FAILED:
@@ -727,6 +728,13 @@ static void process_sctp_notification(struct connection *con,
                        }
                        add_sock(new_con->sock, new_con);
 
+                       linger.l_onoff = 1;
+                       linger.l_linger = 0;
+                       ret = sock_setsockopt(new_con->sock, SOL_SOCKET, SO_LINGER,
+                                             (char *)&linger, sizeof(linger));
+                       if (ret < 0)
+                               log_print("set socket option SO_LINGER failed");
+
                        log_print("connecting to %d sctp association %d",
                                 nodeid, (int)sn->sn_assoc_change.sac_assoc_id);
 
index 79b65c3b9e876f1087ccbcf7908a47c18efbbad9..8b5e2584c840903bc9aeffab1a31aa0a2149b595 100644 (file)
@@ -1852,8 +1852,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
                goto error_tgt_fput;
 
        /* Check if EPOLLWAKEUP is allowed */
-       if ((epds.events & EPOLLWAKEUP) && !capable(CAP_BLOCK_SUSPEND))
-               epds.events &= ~EPOLLWAKEUP;
+       ep_take_care_of_epollwakeup(&epds);
 
        /*
         * We have to check that the file structure underneath the file descriptor
index 288534920fe5cc4960f99ae636777344c5d42db6..20d6697bd6386560a679dda5e8b8592a65d63798 100644 (file)
@@ -1493,6 +1493,7 @@ static ssize_t ext2_quota_write(struct super_block *sb, int type,
                                sb->s_blocksize - offset : towrite;
 
                tmp_bh.b_state = 0;
+               tmp_bh.b_size = sb->s_blocksize;
                err = ext2_get_block(inode, blk, &tmp_bh, 1);
                if (err < 0)
                        goto out;
index 17ac112ab1012bd88ff32d145f27a29f025efdde..3fe29de832c825e390b8d59d818b5ec37a8eb61f 100644 (file)
@@ -259,6 +259,15 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
                if (WARN_ON_ONCE(err)) {
                        ext4_journal_abort_handle(where, line, __func__, bh,
                                                  handle, err);
+                       ext4_error_inode(inode, where, line,
+                                        bh->b_blocknr,
+                                        "journal_dirty_metadata failed: "
+                                        "handle type %u started at line %u, "
+                                        "credits %u/%u, errcode %d",
+                                        handle->h_type,
+                                        handle->h_line_no,
+                                        handle->h_requested_credits,
+                                        handle->h_buffer_credits, err);
                }
        } else {
                if (inode)
index 35f65cf4f318d72bce4e79995ddbc85d0e4bbfa3..267c9fb53bf9f0bdbf07d779c6880cb936c8c3fa 100644 (file)
@@ -360,8 +360,10 @@ static int ext4_valid_extent(struct inode *inode, struct ext4_extent *ext)
 {
        ext4_fsblk_t block = ext4_ext_pblock(ext);
        int len = ext4_ext_get_actual_len(ext);
+       ext4_lblk_t lblock = le32_to_cpu(ext->ee_block);
+       ext4_lblk_t last = lblock + len - 1;
 
-       if (len == 0)
+       if (lblock > last)
                return 0;
        return ext4_data_block_valid(EXT4_SB(inode->i_sb), block, len);
 }
@@ -387,11 +389,26 @@ static int ext4_valid_extent_entries(struct inode *inode,
        if (depth == 0) {
                /* leaf entries */
                struct ext4_extent *ext = EXT_FIRST_EXTENT(eh);
+               struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
+               ext4_fsblk_t pblock = 0;
+               ext4_lblk_t lblock = 0;
+               ext4_lblk_t prev = 0;
+               int len = 0;
                while (entries) {
                        if (!ext4_valid_extent(inode, ext))
                                return 0;
+
+                       /* Check for overlapping extents */
+                       lblock = le32_to_cpu(ext->ee_block);
+                       len = ext4_ext_get_actual_len(ext);
+                       if ((lblock <= prev) && prev) {
+                               pblock = ext4_ext_pblock(ext);
+                               es->s_last_error_block = cpu_to_le64(pblock);
+                               return 0;
+                       }
                        ext++;
                        entries--;
+                       prev = lblock + len - 1;
                }
        } else {
                struct ext4_extent_idx *ext_idx = EXT_FIRST_INDEX(eh);
index 0757634741187a568cc2255187bcd2cf250d852b..bd47404c4eae04e8c776bb67a451098da331b429 100644 (file)
@@ -3513,11 +3513,6 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
        if (!S_ISREG(inode->i_mode))
                return -EOPNOTSUPP;
 
-       if (EXT4_SB(sb)->s_cluster_ratio > 1) {
-               /* TODO: Add support for bigalloc file systems */
-               return -EOPNOTSUPP;
-       }
-
        trace_ext4_punch_hole(inode, offset, length);
 
        /*
@@ -4598,6 +4593,10 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
                        if (attr->ia_size > sbi->s_bitmap_maxbytes)
                                return -EFBIG;
                }
+
+               if (IS_I_VERSION(inode) && attr->ia_size != inode->i_size)
+                       inode_inc_iversion(inode);
+
                if (S_ISREG(inode->i_mode) &&
                    (attr->ia_size < inode->i_size)) {
                        if (ext4_should_order_data(inode)) {
index 4d113efa024c8439f4000a0fa59ed643f2489166..04766d9a29cd66dd74166a5c1243c2c29405382f 100644 (file)
@@ -3442,6 +3442,9 @@ static void ext4_mb_pa_callback(struct rcu_head *head)
 {
        struct ext4_prealloc_space *pa;
        pa = container_of(head, struct ext4_prealloc_space, u.pa_rcu);
+
+       BUG_ON(atomic_read(&pa->pa_count));
+       BUG_ON(pa->pa_deleted == 0);
        kmem_cache_free(ext4_pspace_cachep, pa);
 }
 
@@ -3455,11 +3458,13 @@ static void ext4_mb_put_pa(struct ext4_allocation_context *ac,
        ext4_group_t grp;
        ext4_fsblk_t grp_blk;
 
-       if (!atomic_dec_and_test(&pa->pa_count) || pa->pa_free != 0)
-               return;
-
        /* in this short window concurrent discard can set pa_deleted */
        spin_lock(&pa->pa_lock);
+       if (!atomic_dec_and_test(&pa->pa_count) || pa->pa_free != 0) {
+               spin_unlock(&pa->pa_lock);
+               return;
+       }
+
        if (pa->pa_deleted == 1) {
                spin_unlock(&pa->pa_lock);
                return;
index d488f80ee32df1137e91df0aed72bef2f61b49ac..ab95508e3d4018eab92647c6d2308e98524080d1 100644 (file)
@@ -65,9 +65,9 @@ static void ext4_finish_bio(struct bio *bio)
 {
        int i;
        int error = !test_bit(BIO_UPTODATE, &bio->bi_flags);
+       struct bio_vec *bvec;
 
-       for (i = 0; i < bio->bi_vcnt; i++) {
-               struct bio_vec *bvec = &bio->bi_io_vec[i];
+       bio_for_each_segment_all(bvec, bio, i) {
                struct page *page = bvec->bv_page;
                struct buffer_head *bh, *head;
                unsigned bio_start = bvec->bv_offset;
@@ -298,7 +298,7 @@ ext4_io_end_t *ext4_get_io_end(ext4_io_end_t *io_end)
 static void ext4_end_bio(struct bio *bio, int error)
 {
        ext4_io_end_t *io_end = bio->bi_private;
-       sector_t bi_sector = bio->bi_sector;
+       sector_t bi_sector = bio->bi_iter.bi_sector;
 
        BUG_ON(!io_end);
        bio->bi_end_io = NULL;
@@ -366,7 +366,7 @@ static int io_submit_init_bio(struct ext4_io_submit *io,
        bio = bio_alloc(GFP_NOIO, min(nvecs, BIO_MAX_PAGES));
        if (!bio)
                return -ENOMEM;
-       bio->bi_sector = bh->b_blocknr * (bh->b_size >> 9);
+       bio->bi_iter.bi_sector = bh->b_blocknr * (bh->b_size >> 9);
        bio->bi_bdev = bh->b_bdev;
        bio->bi_end_io = ext4_end_bio;
        bio->bi_private = ext4_get_io_end(io->io_end);
index c977f4e4e63be6c4cf3b477f628e4fc7d323d1f5..1f7784de05b6c6afad4d7437202ceb6efeec3399 100644 (file)
@@ -792,7 +792,7 @@ static void ext4_put_super(struct super_block *sb)
        }
 
        ext4_es_unregister_shrinker(sbi);
-       del_timer(&sbi->s_err_report);
+       del_timer_sync(&sbi->s_err_report);
        ext4_release_system_zone(sb);
        ext4_mb_release(sb);
        ext4_ext_release(sb);
@@ -3316,10 +3316,18 @@ int ext4_calculate_overhead(struct super_block *sb)
 }
 
 
-static ext4_fsblk_t ext4_calculate_resv_clusters(struct ext4_sb_info *sbi)
+static ext4_fsblk_t ext4_calculate_resv_clusters(struct super_block *sb)
 {
        ext4_fsblk_t resv_clusters;
 
+       /*
+        * There's no need to reserve anything when we aren't using extents.
+        * The space estimates are exact, there are no unwritten extents,
+        * hole punching doesn't need new metadata... This is needed especially
+        * to keep ext2/3 backward compatibility.
+        */
+       if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS))
+               return 0;
        /*
         * By default we reserve 2% or 4096 clusters, whichever is smaller.
         * This should cover the situations where we can not afford to run
@@ -3328,7 +3336,8 @@ static ext4_fsblk_t ext4_calculate_resv_clusters(struct ext4_sb_info *sbi)
         * allocation would require 1, or 2 blocks, higher numbers are
         * very rare.
         */
-       resv_clusters = ext4_blocks_count(sbi->s_es) >> sbi->s_cluster_bits;
+       resv_clusters = ext4_blocks_count(EXT4_SB(sb)->s_es) >>
+                       EXT4_SB(sb)->s_cluster_bits;
 
        do_div(resv_clusters, 50);
        resv_clusters = min_t(ext4_fsblk_t, resv_clusters, 4096);
@@ -4071,10 +4080,10 @@ no_journal:
                         "available");
        }
 
-       err = ext4_reserve_clusters(sbi, ext4_calculate_resv_clusters(sbi));
+       err = ext4_reserve_clusters(sbi, ext4_calculate_resv_clusters(sb));
        if (err) {
                ext4_msg(sb, KERN_ERR, "failed to reserve %llu clusters for "
-                        "reserved pool", ext4_calculate_resv_clusters(sbi));
+                        "reserved pool", ext4_calculate_resv_clusters(sb));
                goto failed_mount4a;
        }
 
@@ -4184,7 +4193,7 @@ failed_mount_wq:
        }
 failed_mount3:
        ext4_es_unregister_shrinker(sbi);
-       del_timer(&sbi->s_err_report);
+       del_timer_sync(&sbi->s_err_report);
        if (sbi->s_flex_groups)
                ext4_kvfree(sbi->s_flex_groups);
        percpu_counter_destroy(&sbi->s_freeclusters_counter);
index 5716e5eb4e8ec7ab2c63c69079259e2c5d772918..f8c074961e0a96126caf33ac08c29a4212033e2b 100644 (file)
@@ -61,11 +61,12 @@ repeat:
        if (PageUptodate(page))
                goto out;
 
-       if (f2fs_readpage(sbi, page, index, READ_SYNC))
+       if (f2fs_submit_page_bio(sbi, page, index,
+                               READ_SYNC | REQ_META | REQ_PRIO))
                goto repeat;
 
        lock_page(page);
-       if (page->mapping != mapping) {
+       if (unlikely(page->mapping != mapping)) {
                f2fs_put_page(page, 1);
                goto repeat;
        }
@@ -81,13 +82,12 @@ static int f2fs_write_meta_page(struct page *page,
        struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
 
        /* Should not write any meta pages, if any IO error was occurred */
-       if (wbc->for_reclaim || sbi->por_doing ||
-                       is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ERROR_FLAG)) {
-               dec_page_count(sbi, F2FS_DIRTY_META);
-               wbc->pages_skipped++;
-               set_page_dirty(page);
-               return AOP_WRITEPAGE_ACTIVATE;
-       }
+       if (unlikely(sbi->por_doing ||
+                       is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ERROR_FLAG)))
+               goto redirty_out;
+
+       if (wbc->for_reclaim)
+               goto redirty_out;
 
        wait_on_page_writeback(page);
 
@@ -95,6 +95,12 @@ static int f2fs_write_meta_page(struct page *page,
        dec_page_count(sbi, F2FS_DIRTY_META);
        unlock_page(page);
        return 0;
+
+redirty_out:
+       dec_page_count(sbi, F2FS_DIRTY_META);
+       wbc->pages_skipped++;
+       set_page_dirty(page);
+       return AOP_WRITEPAGE_ACTIVATE;
 }
 
 static int f2fs_write_meta_pages(struct address_space *mapping,
@@ -136,7 +142,7 @@ long sync_meta_pages(struct f2fs_sb_info *sbi, enum page_type type,
                nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
                                PAGECACHE_TAG_DIRTY,
                                min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1);
-               if (nr_pages == 0)
+               if (unlikely(nr_pages == 0))
                        break;
 
                for (i = 0; i < nr_pages; i++) {
@@ -149,7 +155,8 @@ long sync_meta_pages(struct f2fs_sb_info *sbi, enum page_type type,
                                unlock_page(page);
                                break;
                        }
-                       if (nwritten++ >= nr_to_write)
+                       nwritten++;
+                       if (unlikely(nwritten >= nr_to_write))
                                break;
                }
                pagevec_release(&pvec);
@@ -157,7 +164,7 @@ long sync_meta_pages(struct f2fs_sb_info *sbi, enum page_type type,
        }
 
        if (nwritten)
-               f2fs_submit_bio(sbi, type, nr_to_write == LONG_MAX);
+               f2fs_submit_merged_bio(sbi, type, WRITE);
 
        return nwritten;
 }
@@ -190,14 +197,15 @@ int acquire_orphan_inode(struct f2fs_sb_info *sbi)
        int err = 0;
 
        /*
-        * considering 512 blocks in a segment 5 blocks are needed for cp
+        * considering 512 blocks in a segment 8 blocks are needed for cp
         * and log segment summaries. Remaining blocks are used to keep
         * orphan entries with the limitation one reserved segment
-        * for cp pack we can have max 1020*507 orphan entries
+        * for cp pack we can have max 1020*504 orphan entries
         */
-       max_orphans = (sbi->blocks_per_seg - 5) * F2FS_ORPHANS_PER_BLOCK;
+       max_orphans = (sbi->blocks_per_seg - 2 - NR_CURSEG_TYPE)
+                               * F2FS_ORPHANS_PER_BLOCK;
        mutex_lock(&sbi->orphan_inode_mutex);
-       if (sbi->n_orphans >= max_orphans)
+       if (unlikely(sbi->n_orphans >= max_orphans))
                err = -ENOSPC;
        else
                sbi->n_orphans++;
@@ -270,12 +278,12 @@ static void recover_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
        iput(inode);
 }
 
-int recover_orphan_inodes(struct f2fs_sb_info *sbi)
+void recover_orphan_inodes(struct f2fs_sb_info *sbi)
 {
        block_t start_blk, orphan_blkaddr, i, j;
 
        if (!is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ORPHAN_PRESENT_FLAG))
-               return 0;
+               return;
 
        sbi->por_doing = true;
        start_blk = __start_cp_addr(sbi) + 1;
@@ -295,17 +303,18 @@ int recover_orphan_inodes(struct f2fs_sb_info *sbi)
        /* clear Orphan Flag */
        clear_ckpt_flags(F2FS_CKPT(sbi), CP_ORPHAN_PRESENT_FLAG);
        sbi->por_doing = false;
-       return 0;
+       return;
 }
 
 static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk)
 {
-       struct list_head *head, *this, *next;
+       struct list_head *head;
        struct f2fs_orphan_block *orphan_blk = NULL;
        struct page *page = NULL;
        unsigned int nentries = 0;
        unsigned short index = 1;
        unsigned short orphan_blocks;
+       struct orphan_inode_entry *orphan = NULL;
 
        orphan_blocks = (unsigned short)((sbi->n_orphans +
                (F2FS_ORPHANS_PER_BLOCK - 1)) / F2FS_ORPHANS_PER_BLOCK);
@@ -314,10 +323,15 @@ static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk)
        head = &sbi->orphan_inode_list;
 
        /* loop for each orphan inode entry and write them in Jornal block */
-       list_for_each_safe(this, next, head) {
-               struct orphan_inode_entry *orphan;
+       list_for_each_entry(orphan, head, list) {
+               if (!page) {
+                       page = grab_meta_page(sbi, start_blk);
+                       orphan_blk =
+                               (struct f2fs_orphan_block *)page_address(page);
+                       memset(orphan_blk, 0, sizeof(*orphan_blk));
+               }
 
-               orphan = list_entry(this, struct orphan_inode_entry, list);
+               orphan_blk->ino[nentries++] = cpu_to_le32(orphan->ino);
 
                if (nentries == F2FS_ORPHANS_PER_BLOCK) {
                        /*
@@ -335,24 +349,16 @@ static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk)
                        nentries = 0;
                        page = NULL;
                }
-               if (page)
-                       goto page_exist;
+       }
 
-               page = grab_meta_page(sbi, start_blk);
-               orphan_blk = (struct f2fs_orphan_block *)page_address(page);
-               memset(orphan_blk, 0, sizeof(*orphan_blk));
-page_exist:
-               orphan_blk->ino[nentries++] = cpu_to_le32(orphan->ino);
+       if (page) {
+               orphan_blk->blk_addr = cpu_to_le16(index);
+               orphan_blk->blk_count = cpu_to_le16(orphan_blocks);
+               orphan_blk->entry_count = cpu_to_le32(nentries);
+               set_page_dirty(page);
+               f2fs_put_page(page, 1);
        }
-       if (!page)
-               goto end;
 
-       orphan_blk->blk_addr = cpu_to_le16(index);
-       orphan_blk->blk_count = cpu_to_le16(orphan_blocks);
-       orphan_blk->entry_count = cpu_to_le32(nentries);
-       set_page_dirty(page);
-       f2fs_put_page(page, 1);
-end:
        mutex_unlock(&sbi->orphan_inode_mutex);
 }
 
@@ -428,7 +434,8 @@ int get_valid_checkpoint(struct f2fs_sb_info *sbi)
        cp1 = validate_checkpoint(sbi, cp_start_blk_no, &cp1_version);
 
        /* The second checkpoint pack should start at the next segment */
-       cp_start_blk_no += 1 << le32_to_cpu(fsb->log_blocks_per_seg);
+       cp_start_blk_no += ((unsigned long long)1) <<
+                               le32_to_cpu(fsb->log_blocks_per_seg);
        cp2 = validate_checkpoint(sbi, cp_start_blk_no, &cp2_version);
 
        if (cp1 && cp2) {
@@ -465,7 +472,7 @@ static int __add_dirty_inode(struct inode *inode, struct dir_inode_entry *new)
        list_for_each(this, head) {
                struct dir_inode_entry *entry;
                entry = list_entry(this, struct dir_inode_entry, list);
-               if (entry->inode == inode)
+               if (unlikely(entry->inode == inode))
                        return -EEXIST;
        }
        list_add_tail(&new->list, head);
@@ -513,8 +520,8 @@ void add_dirty_dir_inode(struct inode *inode)
 void remove_dirty_dir_inode(struct inode *inode)
 {
        struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
-       struct list_head *head = &sbi->dir_inode_list;
-       struct list_head *this;
+
+       struct list_head *this, *head;
 
        if (!S_ISDIR(inode->i_mode))
                return;
@@ -525,6 +532,7 @@ void remove_dirty_dir_inode(struct inode *inode)
                return;
        }
 
+       head = &sbi->dir_inode_list;
        list_for_each(this, head) {
                struct dir_inode_entry *entry;
                entry = list_entry(this, struct dir_inode_entry, list);
@@ -546,11 +554,13 @@ void remove_dirty_dir_inode(struct inode *inode)
 
 struct inode *check_dirty_dir_inode(struct f2fs_sb_info *sbi, nid_t ino)
 {
-       struct list_head *head = &sbi->dir_inode_list;
-       struct list_head *this;
+
+       struct list_head *this, *head;
        struct inode *inode = NULL;
 
        spin_lock(&sbi->dir_inode_lock);
+
+       head = &sbi->dir_inode_list;
        list_for_each(this, head) {
                struct dir_inode_entry *entry;
                entry = list_entry(this, struct dir_inode_entry, list);
@@ -565,11 +575,13 @@ struct inode *check_dirty_dir_inode(struct f2fs_sb_info *sbi, nid_t ino)
 
 void sync_dirty_dir_inodes(struct f2fs_sb_info *sbi)
 {
-       struct list_head *head = &sbi->dir_inode_list;
+       struct list_head *head;
        struct dir_inode_entry *entry;
        struct inode *inode;
 retry:
        spin_lock(&sbi->dir_inode_lock);
+
+       head = &sbi->dir_inode_list;
        if (list_empty(head)) {
                spin_unlock(&sbi->dir_inode_lock);
                return;
@@ -585,7 +597,7 @@ retry:
                 * We should submit bio, since it exists several
                 * wribacking dentry pages in the freeing inode.
                 */
-               f2fs_submit_bio(sbi, DATA, true);
+               f2fs_submit_merged_bio(sbi, DATA, WRITE);
        }
        goto retry;
 }
@@ -770,7 +782,7 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
        /* Here, we only have one bio having CP pack */
        sync_meta_pages(sbi, META_FLUSH, LONG_MAX);
 
-       if (!is_set_ckpt_flags(ckpt, CP_ERROR_FLAG)) {
+       if (unlikely(!is_set_ckpt_flags(ckpt, CP_ERROR_FLAG))) {
                clear_prefree_segments(sbi);
                F2FS_RESET_SB_DIRT(sbi);
        }
@@ -791,9 +803,9 @@ void write_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
 
        trace_f2fs_write_checkpoint(sbi->sb, is_umount, "finish block_ops");
 
-       f2fs_submit_bio(sbi, DATA, true);
-       f2fs_submit_bio(sbi, NODE, true);
-       f2fs_submit_bio(sbi, META, true);
+       f2fs_submit_merged_bio(sbi, DATA, WRITE);
+       f2fs_submit_merged_bio(sbi, NODE, WRITE);
+       f2fs_submit_merged_bio(sbi, META, WRITE);
 
        /*
         * update checkpoint pack index
@@ -827,11 +839,11 @@ int __init create_checkpoint_caches(void)
 {
        orphan_entry_slab = f2fs_kmem_cache_create("f2fs_orphan_entry",
                        sizeof(struct orphan_inode_entry), NULL);
-       if (unlikely(!orphan_entry_slab))
+       if (!orphan_entry_slab)
                return -ENOMEM;
        inode_entry_slab = f2fs_kmem_cache_create("f2fs_dirty_dir_entry",
                        sizeof(struct dir_inode_entry), NULL);
-       if (unlikely(!inode_entry_slab)) {
+       if (!inode_entry_slab) {
                kmem_cache_destroy(orphan_entry_slab);
                return -ENOMEM;
        }
index aa3438c571fa9a2dfaf3e1ab61bd4328f580b0d6..6d91cb071b57847e61b9f14c0db2aeb5956984fc 100644 (file)
 #include "segment.h"
 #include <trace/events/f2fs.h>
 
+/*
+ * Low-level block read/write IO operations.
+ */
+static struct bio *__bio_alloc(struct block_device *bdev, int npages)
+{
+       struct bio *bio;
+
+       /* No failure on bio allocation */
+       bio = bio_alloc(GFP_NOIO, npages);
+       bio->bi_bdev = bdev;
+       bio->bi_private = NULL;
+       return bio;
+}
+
+static void f2fs_read_end_io(struct bio *bio, int err)
+{
+       struct bio_vec *bvec;
+       int i;
+
+       bio_for_each_segment_all(bvec, bio, i) {
+               struct page *page = bvec->bv_page;
+
+               if (unlikely(err)) {
+                       ClearPageUptodate(page);
+                       SetPageError(page);
+               } else {
+                       SetPageUptodate(page);
+               }
+               unlock_page(page);
+       }
+
+       bio_put(bio);
+}
+
+static void f2fs_write_end_io(struct bio *bio, int err)
+{
+       struct f2fs_sb_info *sbi = NULL;
+       struct bio_vec *bvec;
+       int i;
+
+       bio_for_each_segment_all(bvec, bio, i) {
+               struct page *page = bvec->bv_page;
+
+               if (!sbi)
+                       sbi = F2FS_SB(bvec->bv_page->mapping->host->i_sb);
+               if (unlikely(err)) {
+                       SetPageError(page);
+                       set_bit(AS_EIO, &page->mapping->flags);
+                       set_ckpt_flags(sbi->ckpt, CP_ERROR_FLAG);
+                       sbi->sb->s_flags |= MS_RDONLY;
+               }
+               end_page_writeback(page);
+               dec_page_count(sbi, F2FS_WRITEBACK);
+       }
+
+       if (bio->bi_private)
+               complete(bio->bi_private);
+
+       if (!get_pages(sbi, F2FS_WRITEBACK) &&
+                       !list_empty(&sbi->cp_wait.task_list))
+               wake_up(&sbi->cp_wait);
+
+       bio_put(bio);
+}
+
+static void __submit_merged_bio(struct f2fs_bio_info *io)
+{
+       struct f2fs_io_info *fio = &io->fio;
+       int rw;
+
+       if (!io->bio)
+               return;
+
+       rw = fio->rw | fio->rw_flag;
+
+       if (is_read_io(rw)) {
+               trace_f2fs_submit_read_bio(io->sbi->sb, rw, fio->type, io->bio);
+               submit_bio(rw, io->bio);
+               io->bio = NULL;
+               return;
+       }
+       trace_f2fs_submit_write_bio(io->sbi->sb, rw, fio->type, io->bio);
+
+       /*
+        * META_FLUSH is only from the checkpoint procedure, and we should wait
+        * this metadata bio for FS consistency.
+        */
+       if (fio->type == META_FLUSH) {
+               DECLARE_COMPLETION_ONSTACK(wait);
+               io->bio->bi_private = &wait;
+               submit_bio(rw, io->bio);
+               wait_for_completion(&wait);
+       } else {
+               submit_bio(rw, io->bio);
+       }
+       io->bio = NULL;
+}
+
+void f2fs_submit_merged_bio(struct f2fs_sb_info *sbi,
+                               enum page_type type, int rw)
+{
+       enum page_type btype = PAGE_TYPE_OF_BIO(type);
+       struct f2fs_bio_info *io;
+
+       io = is_read_io(rw) ? &sbi->read_io : &sbi->write_io[btype];
+
+       mutex_lock(&io->io_mutex);
+
+       /* change META to META_FLUSH in the checkpoint procedure */
+       if (type >= META_FLUSH) {
+               io->fio.type = META_FLUSH;
+               io->fio.rw = WRITE_FLUSH_FUA;
+       }
+       __submit_merged_bio(io);
+       mutex_unlock(&io->io_mutex);
+}
+
+/*
+ * Fill the locked page with data located in the block address.
+ * Return unlocked page.
+ */
+int f2fs_submit_page_bio(struct f2fs_sb_info *sbi, struct page *page,
+                                       block_t blk_addr, int rw)
+{
+       struct block_device *bdev = sbi->sb->s_bdev;
+       struct bio *bio;
+
+       trace_f2fs_submit_page_bio(page, blk_addr, rw);
+
+       /* Allocate a new bio */
+       bio = __bio_alloc(bdev, 1);
+
+       /* Initialize the bio */
+       bio->bi_iter.bi_sector = SECTOR_FROM_BLOCK(sbi, blk_addr);
+       bio->bi_end_io = is_read_io(rw) ? f2fs_read_end_io : f2fs_write_end_io;
+
+       if (bio_add_page(bio, page, PAGE_CACHE_SIZE, 0) < PAGE_CACHE_SIZE) {
+               bio_put(bio);
+               f2fs_put_page(page, 1);
+               return -EFAULT;
+       }
+
+       submit_bio(rw, bio);
+       return 0;
+}
+
+void f2fs_submit_page_mbio(struct f2fs_sb_info *sbi, struct page *page,
+                       block_t blk_addr, struct f2fs_io_info *fio)
+{
+       enum page_type btype = PAGE_TYPE_OF_BIO(fio->type);
+       struct block_device *bdev = sbi->sb->s_bdev;
+       struct f2fs_bio_info *io;
+       int bio_blocks;
+
+       io = is_read_io(fio->rw) ? &sbi->read_io : &sbi->write_io[btype];
+
+       verify_block_addr(sbi, blk_addr);
+
+       mutex_lock(&io->io_mutex);
+
+       if (!is_read_io(fio->rw))
+               inc_page_count(sbi, F2FS_WRITEBACK);
+
+       if (io->bio && (io->last_block_in_bio != blk_addr - 1 ||
+                                               io->fio.rw != fio->rw))
+               __submit_merged_bio(io);
+alloc_new:
+       if (io->bio == NULL) {
+               bio_blocks = MAX_BIO_BLOCKS(max_hw_blocks(sbi));
+               io->bio = __bio_alloc(bdev, bio_blocks);
+               io->bio->bi_iter.bi_sector = SECTOR_FROM_BLOCK(sbi, blk_addr);
+               io->bio->bi_end_io = is_read_io(fio->rw) ? f2fs_read_end_io :
+                                                       f2fs_write_end_io;
+               io->fio = *fio;
+               /*
+                * The end_io will be assigned at the sumbission phase.
+                * Until then, let bio_add_page() merge consecutive IOs as much
+                * as possible.
+                */
+       }
+
+       if (bio_add_page(io->bio, page, PAGE_CACHE_SIZE, 0) <
+                                                       PAGE_CACHE_SIZE) {
+               __submit_merged_bio(io);
+               goto alloc_new;
+       }
+
+       io->last_block_in_bio = blk_addr;
+
+       mutex_unlock(&io->io_mutex);
+       trace_f2fs_submit_page_mbio(page, fio->rw, fio->type, blk_addr);
+}
+
 /*
  * Lock ordering for the change of data block address:
  * ->data_page
@@ -51,9 +244,9 @@ int reserve_new_block(struct dnode_of_data *dn)
 {
        struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
 
-       if (is_inode_flag_set(F2FS_I(dn->inode), FI_NO_ALLOC))
+       if (unlikely(is_inode_flag_set(F2FS_I(dn->inode), FI_NO_ALLOC)))
                return -EPERM;
-       if (!inc_valid_block_count(sbi, dn->inode, 1))
+       if (unlikely(!inc_valid_block_count(sbi, dn->inode, 1)))
                return -ENOSPC;
 
        trace_f2fs_reserve_new_block(dn->inode, dn->nid, dn->ofs_in_node);
@@ -64,6 +257,22 @@ int reserve_new_block(struct dnode_of_data *dn)
        return 0;
 }
 
+int f2fs_reserve_block(struct dnode_of_data *dn, pgoff_t index)
+{
+       bool need_put = dn->inode_page ? false : true;
+       int err;
+
+       err = get_dnode_of_data(dn, index, ALLOC_NODE);
+       if (err)
+               return err;
+       if (dn->data_blkaddr == NULL_ADDR)
+               err = reserve_new_block(dn);
+
+       if (need_put)
+               f2fs_put_dnode(dn);
+       return err;
+}
+
 static int check_extent_cache(struct inode *inode, pgoff_t pgofs,
                                        struct buffer_head *bh_result)
 {
@@ -71,6 +280,9 @@ static int check_extent_cache(struct inode *inode, pgoff_t pgofs,
        pgoff_t start_fofs, end_fofs;
        block_t start_blkaddr;
 
+       if (is_inode_flag_set(fi, FI_NO_EXTENT))
+               return 0;
+
        read_lock(&fi->ext.ext_lock);
        if (fi->ext.len == 0) {
                read_unlock(&fi->ext.ext_lock);
@@ -109,6 +321,7 @@ void update_extent_cache(block_t blk_addr, struct dnode_of_data *dn)
        struct f2fs_inode_info *fi = F2FS_I(dn->inode);
        pgoff_t fofs, start_fofs, end_fofs;
        block_t start_blkaddr, end_blkaddr;
+       int need_update = true;
 
        f2fs_bug_on(blk_addr == NEW_ADDR);
        fofs = start_bidx_of_node(ofs_of_node(dn->node_page), fi) +
@@ -117,6 +330,9 @@ void update_extent_cache(block_t blk_addr, struct dnode_of_data *dn)
        /* Update the page address in the parent node */
        __set_data_blkaddr(dn, blk_addr);
 
+       if (is_inode_flag_set(fi, FI_NO_EXTENT))
+               return;
+
        write_lock(&fi->ext.ext_lock);
 
        start_fofs = fi->ext.fofs;
@@ -163,14 +379,21 @@ void update_extent_cache(block_t blk_addr, struct dnode_of_data *dn)
                                        fofs - start_fofs + 1;
                        fi->ext.len -= fofs - start_fofs + 1;
                }
-               goto end_update;
+       } else {
+               need_update = false;
        }
-       write_unlock(&fi->ext.ext_lock);
-       return;
 
+       /* Finally, if the extent is very fragmented, let's drop the cache. */
+       if (fi->ext.len < F2FS_MIN_EXTENT_LEN) {
+               fi->ext.len = 0;
+               set_inode_flag(fi, FI_NO_EXTENT);
+               need_update = true;
+       }
 end_update:
        write_unlock(&fi->ext.ext_lock);
-       sync_inode_page(dn);
+       if (need_update)
+               sync_inode_page(dn);
+       return;
 }
 
 struct page *find_data_page(struct inode *inode, pgoff_t index, bool sync)
@@ -196,7 +419,7 @@ struct page *find_data_page(struct inode *inode, pgoff_t index, bool sync)
                return ERR_PTR(-ENOENT);
 
        /* By fallocate(), there is no cached page, but with NEW_ADDR */
-       if (dn.data_blkaddr == NEW_ADDR)
+       if (unlikely(dn.data_blkaddr == NEW_ADDR))
                return ERR_PTR(-EINVAL);
 
        page = grab_cache_page_write_begin(mapping, index, AOP_FLAG_NOFS);
@@ -208,11 +431,14 @@ struct page *find_data_page(struct inode *inode, pgoff_t index, bool sync)
                return page;
        }
 
-       err = f2fs_readpage(sbi, page, dn.data_blkaddr,
+       err = f2fs_submit_page_bio(sbi, page, dn.data_blkaddr,
                                        sync ? READ_SYNC : READA);
+       if (err)
+               return ERR_PTR(err);
+
        if (sync) {
                wait_on_page_locked(page);
-               if (!PageUptodate(page)) {
+               if (unlikely(!PageUptodate(page))) {
                        f2fs_put_page(page, 0);
                        return ERR_PTR(-EIO);
                }
@@ -246,7 +472,7 @@ repeat:
        }
        f2fs_put_dnode(&dn);
 
-       if (dn.data_blkaddr == NULL_ADDR) {
+       if (unlikely(dn.data_blkaddr == NULL_ADDR)) {
                f2fs_put_page(page, 1);
                return ERR_PTR(-ENOENT);
        }
@@ -266,16 +492,16 @@ repeat:
                return page;
        }
 
-       err = f2fs_readpage(sbi, page, dn.data_blkaddr, READ_SYNC);
+       err = f2fs_submit_page_bio(sbi, page, dn.data_blkaddr, READ_SYNC);
        if (err)
                return ERR_PTR(err);
 
        lock_page(page);
-       if (!PageUptodate(page)) {
+       if (unlikely(!PageUptodate(page))) {
                f2fs_put_page(page, 1);
                return ERR_PTR(-EIO);
        }
-       if (page->mapping != mapping) {
+       if (unlikely(page->mapping != mapping)) {
                f2fs_put_page(page, 1);
                goto repeat;
        }
@@ -300,19 +526,9 @@ struct page *get_new_data_page(struct inode *inode,
        int err;
 
        set_new_dnode(&dn, inode, npage, npage, 0);
-       err = get_dnode_of_data(&dn, index, ALLOC_NODE);
+       err = f2fs_reserve_block(&dn, index);
        if (err)
                return ERR_PTR(err);
-
-       if (dn.data_blkaddr == NULL_ADDR) {
-               if (reserve_new_block(&dn)) {
-                       if (!npage)
-                               f2fs_put_dnode(&dn);
-                       return ERR_PTR(-ENOSPC);
-               }
-       }
-       if (!npage)
-               f2fs_put_dnode(&dn);
 repeat:
        page = grab_cache_page(mapping, index);
        if (!page)
@@ -325,15 +541,16 @@ repeat:
                zero_user_segment(page, 0, PAGE_CACHE_SIZE);
                SetPageUptodate(page);
        } else {
-               err = f2fs_readpage(sbi, page, dn.data_blkaddr, READ_SYNC);
+               err = f2fs_submit_page_bio(sbi, page, dn.data_blkaddr,
+                                                               READ_SYNC);
                if (err)
                        return ERR_PTR(err);
                lock_page(page);
-               if (!PageUptodate(page)) {
+               if (unlikely(!PageUptodate(page))) {
                        f2fs_put_page(page, 1);
                        return ERR_PTR(-EIO);
                }
-               if (page->mapping != mapping) {
+               if (unlikely(page->mapping != mapping)) {
                        f2fs_put_page(page, 1);
                        goto repeat;
                }
@@ -349,61 +566,6 @@ repeat:
        return page;
 }
 
-static void read_end_io(struct bio *bio, int err)
-{
-       const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
-       struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
-
-       do {
-               struct page *page = bvec->bv_page;
-
-               if (--bvec >= bio->bi_io_vec)
-                       prefetchw(&bvec->bv_page->flags);
-
-               if (uptodate) {
-                       SetPageUptodate(page);
-               } else {
-                       ClearPageUptodate(page);
-                       SetPageError(page);
-               }
-               unlock_page(page);
-       } while (bvec >= bio->bi_io_vec);
-       bio_put(bio);
-}
-
-/*
- * Fill the locked page with data located in the block address.
- * Return unlocked page.
- */
-int f2fs_readpage(struct f2fs_sb_info *sbi, struct page *page,
-                                       block_t blk_addr, int type)
-{
-       struct block_device *bdev = sbi->sb->s_bdev;
-       struct bio *bio;
-
-       trace_f2fs_readpage(page, blk_addr, type);
-
-       down_read(&sbi->bio_sem);
-
-       /* Allocate a new bio */
-       bio = f2fs_bio_alloc(bdev, 1);
-
-       /* Initialize the bio */
-       bio->bi_sector = SECTOR_FROM_BLOCK(sbi, blk_addr);
-       bio->bi_end_io = read_end_io;
-
-       if (bio_add_page(bio, page, PAGE_CACHE_SIZE, 0) < PAGE_CACHE_SIZE) {
-               bio_put(bio);
-               up_read(&sbi->bio_sem);
-               f2fs_put_page(page, 1);
-               return -EFAULT;
-       }
-
-       submit_bio(type, bio);
-       up_read(&sbi->bio_sem);
-       return 0;
-}
-
 /*
  * This function should be used by the data read flow only where it
  * does not check the "create" flag that indicates block allocation.
@@ -455,7 +617,7 @@ static int get_data_block_ro(struct inode *inode, sector_t iblock,
                                != (dn.data_blkaddr + i)) || maxblocks == i)
                                break;
                map_bh(bh_result, inode->i_sb, dn.data_blkaddr);
-               bh_result->b_size = (i << blkbits);
+               bh_result->b_size = (((size_t)i) << blkbits);
        }
        f2fs_put_dnode(&dn);
        trace_f2fs_get_data_block(inode, iblock, bh_result, 0);
@@ -474,10 +636,10 @@ static int f2fs_read_data_pages(struct file *file,
        return mpage_readpages(mapping, pages, nr_pages, get_data_block_ro);
 }
 
-int do_write_data_page(struct page *page)
+int do_write_data_page(struct page *page, struct f2fs_io_info *fio)
 {
        struct inode *inode = page->mapping->host;
-       block_t old_blk_addr, new_blk_addr;
+       block_t old_blkaddr, new_blkaddr;
        struct dnode_of_data dn;
        int err = 0;
 
@@ -486,10 +648,10 @@ int do_write_data_page(struct page *page)
        if (err)
                return err;
 
-       old_blk_addr = dn.data_blkaddr;
+       old_blkaddr = dn.data_blkaddr;
 
        /* This page is already truncated */
-       if (old_blk_addr == NULL_ADDR)
+       if (old_blkaddr == NULL_ADDR)
                goto out_writepage;
 
        set_page_writeback(page);
@@ -498,15 +660,13 @@ int do_write_data_page(struct page *page)
         * If current allocation needs SSR,
         * it had better in-place writes for updated data.
         */
-       if (unlikely(old_blk_addr != NEW_ADDR &&
+       if (unlikely(old_blkaddr != NEW_ADDR &&
                        !is_cold_data(page) &&
                        need_inplace_update(inode))) {
-               rewrite_data_page(F2FS_SB(inode->i_sb), page,
-                                               old_blk_addr);
+               rewrite_data_page(page, old_blkaddr, fio);
        } else {
-               write_data_page(inode, page, &dn,
-                               old_blk_addr, &new_blk_addr);
-               update_extent_cache(new_blk_addr, &dn);
+               write_data_page(page, &dn, &new_blkaddr, fio);
+               update_extent_cache(new_blkaddr, &dn);
        }
 out_writepage:
        f2fs_put_dnode(&dn);
@@ -524,6 +684,11 @@ static int f2fs_write_data_page(struct page *page,
        unsigned offset;
        bool need_balance_fs = false;
        int err = 0;
+       struct f2fs_io_info fio = {
+               .type = DATA,
+               .rw = (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC: WRITE,
+               .rw_flag = 0,
+       };
 
        if (page->index < end_index)
                goto write;
@@ -543,7 +708,7 @@ static int f2fs_write_data_page(struct page *page,
 
        zero_user_segment(page, offset, PAGE_CACHE_SIZE);
 write:
-       if (sbi->por_doing) {
+       if (unlikely(sbi->por_doing)) {
                err = AOP_WRITEPAGE_ACTIVATE;
                goto redirty_out;
        }
@@ -552,10 +717,10 @@ write:
        if (S_ISDIR(inode->i_mode)) {
                dec_page_count(sbi, F2FS_DIRTY_DENTS);
                inode_dec_dirty_dents(inode);
-               err = do_write_data_page(page);
+               err = do_write_data_page(page, &fio);
        } else {
                f2fs_lock_op(sbi);
-               err = do_write_data_page(page);
+               err = do_write_data_page(page, &fio);
                f2fs_unlock_op(sbi);
                need_balance_fs = true;
        }
@@ -565,7 +730,7 @@ write:
                goto redirty_out;
 
        if (wbc->for_reclaim)
-               f2fs_submit_bio(sbi, DATA, true);
+               f2fs_submit_merged_bio(sbi, DATA, WRITE);
 
        clear_cold_data(page);
 out:
@@ -617,7 +782,8 @@ static int f2fs_write_data_pages(struct address_space *mapping,
        ret = write_cache_pages(mapping, wbc, __f2fs_writepage, mapping);
        if (locked)
                mutex_unlock(&sbi->writepages);
-       f2fs_submit_bio(sbi, DATA, (wbc->sync_mode == WB_SYNC_ALL));
+
+       f2fs_submit_merged_bio(sbi, DATA, WRITE);
 
        remove_dirty_dir_inode(inode);
 
@@ -644,21 +810,15 @@ repeat:
        *pagep = page;
 
        f2fs_lock_op(sbi);
-
        set_new_dnode(&dn, inode, NULL, NULL, 0);
-       err = get_dnode_of_data(&dn, index, ALLOC_NODE);
-       if (err)
-               goto err;
-
-       if (dn.data_blkaddr == NULL_ADDR)
-               err = reserve_new_block(&dn);
-
-       f2fs_put_dnode(&dn);
-       if (err)
-               goto err;
-
+       err = f2fs_reserve_block(&dn, index);
        f2fs_unlock_op(sbi);
 
+       if (err) {
+               f2fs_put_page(page, 1);
+               return err;
+       }
+
        if ((len == PAGE_CACHE_SIZE) || PageUptodate(page))
                return 0;
 
@@ -674,15 +834,16 @@ repeat:
        if (dn.data_blkaddr == NEW_ADDR) {
                zero_user_segment(page, 0, PAGE_CACHE_SIZE);
        } else {
-               err = f2fs_readpage(sbi, page, dn.data_blkaddr, READ_SYNC);
+               err = f2fs_submit_page_bio(sbi, page, dn.data_blkaddr,
+                                                       READ_SYNC);
                if (err)
                        return err;
                lock_page(page);
-               if (!PageUptodate(page)) {
+               if (unlikely(!PageUptodate(page))) {
                        f2fs_put_page(page, 1);
                        return -EIO;
                }
-               if (page->mapping != mapping) {
+               if (unlikely(page->mapping != mapping)) {
                        f2fs_put_page(page, 1);
                        goto repeat;
                }
@@ -691,11 +852,6 @@ out:
        SetPageUptodate(page);
        clear_cold_data(page);
        return 0;
-
-err:
-       f2fs_unlock_op(sbi);
-       f2fs_put_page(page, 1);
-       return err;
 }
 
 static int f2fs_write_end(struct file *file,
@@ -714,8 +870,7 @@ static int f2fs_write_end(struct file *file,
                update_inode_page(inode);
        }
 
-       unlock_page(page);
-       page_cache_release(page);
+       f2fs_put_page(page, 1);
        return copied;
 }
 
index a84b0a8e6854cd6e2faba8a84124d350378343f1..61adbcbe9b87cda2b20c0e698dc509163ee8b226 100644 (file)
@@ -24,7 +24,7 @@
 #include "gc.h"
 
 static LIST_HEAD(f2fs_stat_list);
-static struct dentry *debugfs_root;
+static struct dentry *f2fs_debugfs_root;
 static DEFINE_MUTEX(f2fs_stat_mutex);
 
 static void update_general_status(struct f2fs_sb_info *sbi)
@@ -340,14 +340,32 @@ void f2fs_destroy_stats(struct f2fs_sb_info *sbi)
 
 void __init f2fs_create_root_stats(void)
 {
-       debugfs_root = debugfs_create_dir("f2fs", NULL);
-       if (debugfs_root)
-               debugfs_create_file("status", S_IRUGO, debugfs_root,
-                                        NULL, &stat_fops);
+       struct dentry *file;
+
+       f2fs_debugfs_root = debugfs_create_dir("f2fs", NULL);
+       if (!f2fs_debugfs_root)
+               goto bail;
+
+       file = debugfs_create_file("status", S_IRUGO, f2fs_debugfs_root,
+                       NULL, &stat_fops);
+       if (!file)
+               goto free_debugfs_dir;
+
+       return;
+
+free_debugfs_dir:
+       debugfs_remove(f2fs_debugfs_root);
+
+bail:
+       f2fs_debugfs_root = NULL;
+       return;
 }
 
 void f2fs_destroy_root_stats(void)
 {
-       debugfs_remove_recursive(debugfs_root);
-       debugfs_root = NULL;
+       if (!f2fs_debugfs_root)
+               return;
+
+       debugfs_remove_recursive(f2fs_debugfs_root);
+       f2fs_debugfs_root = NULL;
 }
index 594fc1bb64ef44f1ea734ec7222b710a670b37fe..0cc26ba07c3b2c1f7ba96868164758cdec421e7e 100644 (file)
@@ -190,7 +190,7 @@ struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir,
        unsigned int max_depth;
        unsigned int level;
 
-       if (namelen > F2FS_NAME_LEN)
+       if (unlikely(namelen > F2FS_NAME_LEN))
                return NULL;
 
        if (npages == 0)
@@ -461,7 +461,7 @@ int __f2fs_add_link(struct inode *dir, const struct qstr *name, struct inode *in
        }
 
 start:
-       if (current_depth == MAX_DIR_HASH_DEPTH)
+       if (unlikely(current_depth == MAX_DIR_HASH_DEPTH))
                return -ENOSPC;
 
        /* Increase the depth, if required */
index 89dc7508faf2edf173441a9e25cad8a9ff4856aa..022ce324b1660add5617faae8241d1564949e401 100644 (file)
 
 #ifdef CONFIG_F2FS_CHECK_FS
 #define f2fs_bug_on(condition) BUG_ON(condition)
+#define f2fs_down_write(x, y)  down_write_nest_lock(x, y)
 #else
 #define f2fs_bug_on(condition)
+#define f2fs_down_write(x, y)  down_write(x)
 #endif
 
 /*
@@ -37,6 +39,7 @@
 #define F2FS_MOUNT_POSIX_ACL           0x00000020
 #define F2FS_MOUNT_DISABLE_EXT_IDENTIFY        0x00000040
 #define F2FS_MOUNT_INLINE_XATTR                0x00000080
+#define F2FS_MOUNT_INLINE_DATA         0x00000100
 
 #define clear_opt(sbi, option) (sbi->mount_opt.opt &= ~F2FS_MOUNT_##option)
 #define set_opt(sbi, option)   (sbi->mount_opt.opt |= F2FS_MOUNT_##option)
@@ -97,6 +100,13 @@ struct dir_inode_entry {
        struct inode *inode;    /* vfs inode pointer */
 };
 
+/* for the list of blockaddresses to be discarded */
+struct discard_entry {
+       struct list_head list;  /* list head */
+       block_t blkaddr;        /* block address to be discarded */
+       int len;                /* # of consecutive blocks of the discard */
+};
+
 /* for the list of fsync inodes, used only during recovery */
 struct fsync_inode_entry {
        struct list_head list;  /* list head */
@@ -162,6 +172,8 @@ enum {
 #define F2FS_LINK_MAX          32000   /* maximum link count per file */
 
 /* for in-memory extent cache entry */
+#define F2FS_MIN_EXTENT_LEN    16      /* minimum extent length */
+
 struct extent_info {
        rwlock_t ext_lock;      /* rwlock for consistency */
        unsigned int fofs;      /* start offset in a file */
@@ -308,6 +320,11 @@ struct f2fs_sm_info {
 
        /* a threshold to reclaim prefree segments */
        unsigned int rec_prefree_segments;
+
+       /* for small discard management */
+       struct list_head discard_list;          /* 4KB discard list */
+       int nr_discards;                        /* # of discards in the list */
+       int max_discards;                       /* max. discards to be issued */
 };
 
 /*
@@ -338,6 +355,7 @@ enum count_type {
  *                     with waiting the bio's completion
  * ...                 Only can be used with META.
  */
+#define PAGE_TYPE_OF_BIO(type) ((type) > META ? META : (type))
 enum page_type {
        DATA,
        NODE,
@@ -346,6 +364,21 @@ enum page_type {
        META_FLUSH,
 };
 
+struct f2fs_io_info {
+       enum page_type type;            /* contains DATA/NODE/META/META_FLUSH */
+       int rw;                         /* contains R/RS/W/WS */
+       int rw_flag;                    /* contains REQ_META/REQ_PRIO */
+};
+
+#define is_read_io(rw) (((rw) & 1) == READ)
+struct f2fs_bio_info {
+       struct f2fs_sb_info *sbi;       /* f2fs superblock */
+       struct bio *bio;                /* bios to merge */
+       sector_t last_block_in_bio;     /* last block number */
+       struct f2fs_io_info fio;        /* store buffered io info. */
+       struct mutex io_mutex;          /* mutex for bio */
+};
+
 struct f2fs_sb_info {
        struct super_block *sb;                 /* pointer to VFS super block */
        struct proc_dir_entry *s_proc;          /* proc entry */
@@ -359,9 +392,10 @@ struct f2fs_sb_info {
 
        /* for segment-related operations */
        struct f2fs_sm_info *sm_info;           /* segment manager */
-       struct bio *bio[NR_PAGE_TYPE];          /* bios to merge */
-       sector_t last_block_in_bio[NR_PAGE_TYPE];       /* last block number */
-       struct rw_semaphore bio_sem;            /* IO semaphore */
+
+       /* for bio operations */
+       struct f2fs_bio_info read_io;                   /* for read bios */
+       struct f2fs_bio_info write_io[NR_PAGE_TYPE];    /* for write bios */
 
        /* for checkpoint */
        struct f2fs_checkpoint *ckpt;           /* raw checkpoint pointer */
@@ -534,7 +568,7 @@ static inline void f2fs_unlock_op(struct f2fs_sb_info *sbi)
 
 static inline void f2fs_lock_all(struct f2fs_sb_info *sbi)
 {
-       down_write_nest_lock(&sbi->cp_rwsem, &sbi->cp_mutex);
+       f2fs_down_write(&sbi->cp_rwsem, &sbi->cp_mutex);
 }
 
 static inline void f2fs_unlock_all(struct f2fs_sb_info *sbi)
@@ -548,7 +582,7 @@ static inline void f2fs_unlock_all(struct f2fs_sb_info *sbi)
 static inline int check_nid_range(struct f2fs_sb_info *sbi, nid_t nid)
 {
        WARN_ON((nid >= NM_I(sbi)->max_nid));
-       if (nid >= NM_I(sbi)->max_nid)
+       if (unlikely(nid >= NM_I(sbi)->max_nid))
                return -EINVAL;
        return 0;
 }
@@ -574,7 +608,7 @@ static inline bool inc_valid_block_count(struct f2fs_sb_info *sbi,
        spin_lock(&sbi->stat_lock);
        valid_block_count =
                sbi->total_valid_block_count + (block_t)count;
-       if (valid_block_count > sbi->user_block_count) {
+       if (unlikely(valid_block_count > sbi->user_block_count)) {
                spin_unlock(&sbi->stat_lock);
                return false;
        }
@@ -585,7 +619,7 @@ static inline bool inc_valid_block_count(struct f2fs_sb_info *sbi,
        return true;
 }
 
-static inline int dec_valid_block_count(struct f2fs_sb_info *sbi,
+static inline void dec_valid_block_count(struct f2fs_sb_info *sbi,
                                                struct inode *inode,
                                                blkcnt_t count)
 {
@@ -595,7 +629,6 @@ static inline int dec_valid_block_count(struct f2fs_sb_info *sbi,
        inode->i_blocks -= count;
        sbi->total_valid_block_count -= (block_t)count;
        spin_unlock(&sbi->stat_lock);
-       return 0;
 }
 
 static inline void inc_page_count(struct f2fs_sb_info *sbi, int count_type)
@@ -686,50 +719,48 @@ static inline block_t __start_sum_addr(struct f2fs_sb_info *sbi)
 }
 
 static inline bool inc_valid_node_count(struct f2fs_sb_info *sbi,
-                                               struct inode *inode,
-                                               unsigned int count)
+                                               struct inode *inode)
 {
        block_t valid_block_count;
        unsigned int valid_node_count;
 
        spin_lock(&sbi->stat_lock);
 
-       valid_block_count = sbi->total_valid_block_count + (block_t)count;
-       sbi->alloc_valid_block_count += (block_t)count;
-       valid_node_count = sbi->total_valid_node_count + count;
-
-       if (valid_block_count > sbi->user_block_count) {
+       valid_block_count = sbi->total_valid_block_count + 1;
+       if (unlikely(valid_block_count > sbi->user_block_count)) {
                spin_unlock(&sbi->stat_lock);
                return false;
        }
 
-       if (valid_node_count > sbi->total_node_count) {
+       valid_node_count = sbi->total_valid_node_count + 1;
+       if (unlikely(valid_node_count > sbi->total_node_count)) {
                spin_unlock(&sbi->stat_lock);
                return false;
        }
 
        if (inode)
-               inode->i_blocks += count;
-       sbi->total_valid_node_count = valid_node_count;
-       sbi->total_valid_block_count = valid_block_count;
+               inode->i_blocks++;
+
+       sbi->alloc_valid_block_count++;
+       sbi->total_valid_node_count++;
+       sbi->total_valid_block_count++;
        spin_unlock(&sbi->stat_lock);
 
        return true;
 }
 
 static inline void dec_valid_node_count(struct f2fs_sb_info *sbi,
-                                               struct inode *inode,
-                                               unsigned int count)
+                                               struct inode *inode)
 {
        spin_lock(&sbi->stat_lock);
 
-       f2fs_bug_on(sbi->total_valid_block_count < count);
-       f2fs_bug_on(sbi->total_valid_node_count < count);
-       f2fs_bug_on(inode->i_blocks < count);
+       f2fs_bug_on(!sbi->total_valid_block_count);
+       f2fs_bug_on(!sbi->total_valid_node_count);
+       f2fs_bug_on(!inode->i_blocks);
 
-       inode->i_blocks -= count;
-       sbi->total_valid_node_count -= count;
-       sbi->total_valid_block_count -= (block_t)count;
+       inode->i_blocks--;
+       sbi->total_valid_node_count--;
+       sbi->total_valid_block_count--;
 
        spin_unlock(&sbi->stat_lock);
 }
@@ -751,13 +782,12 @@ static inline void inc_valid_inode_count(struct f2fs_sb_info *sbi)
        spin_unlock(&sbi->stat_lock);
 }
 
-static inline int dec_valid_inode_count(struct f2fs_sb_info *sbi)
+static inline void dec_valid_inode_count(struct f2fs_sb_info *sbi)
 {
        spin_lock(&sbi->stat_lock);
        f2fs_bug_on(!sbi->total_valid_inode_count);
        sbi->total_valid_inode_count--;
        spin_unlock(&sbi->stat_lock);
-       return 0;
 }
 
 static inline unsigned int valid_inode_count(struct f2fs_sb_info *sbi)
@@ -771,7 +801,7 @@ static inline unsigned int valid_inode_count(struct f2fs_sb_info *sbi)
 
 static inline void f2fs_put_page(struct page *page, int unlock)
 {
-       if (!page || IS_ERR(page))
+       if (!page)
                return;
 
        if (unlock) {
@@ -876,7 +906,9 @@ enum {
        FI_NO_ALLOC,            /* should not allocate any blocks */
        FI_UPDATE_DIR,          /* should update inode block for consistency */
        FI_DELAY_IPUT,          /* used for the recovery */
+       FI_NO_EXTENT,           /* not to use the extent cache */
        FI_INLINE_XATTR,        /* used for inline xattr */
+       FI_INLINE_DATA,         /* used for inline data*/
 };
 
 static inline void set_inode_flag(struct f2fs_inode_info *fi, int flag)
@@ -914,6 +946,8 @@ static inline void get_inline_info(struct f2fs_inode_info *fi,
 {
        if (ri->i_inline & F2FS_INLINE_XATTR)
                set_inode_flag(fi, FI_INLINE_XATTR);
+       if (ri->i_inline & F2FS_INLINE_DATA)
+               set_inode_flag(fi, FI_INLINE_DATA);
 }
 
 static inline void set_raw_inline(struct f2fs_inode_info *fi,
@@ -923,6 +957,8 @@ static inline void set_raw_inline(struct f2fs_inode_info *fi,
 
        if (is_inode_flag_set(fi, FI_INLINE_XATTR))
                ri->i_inline |= F2FS_INLINE_XATTR;
+       if (is_inode_flag_set(fi, FI_INLINE_DATA))
+               ri->i_inline |= F2FS_INLINE_DATA;
 }
 
 static inline unsigned int addrs_per_inode(struct f2fs_inode_info *fi)
@@ -948,6 +984,13 @@ static inline int inline_xattr_size(struct inode *inode)
                return 0;
 }
 
+static inline void *inline_data_addr(struct page *page)
+{
+       struct f2fs_inode *ri;
+       ri = (struct f2fs_inode *)page_address(page);
+       return (void *)&(ri->i_addr[1]);
+}
+
 static inline int f2fs_readonly(struct super_block *sb)
 {
        return sb->s_flags & MS_RDONLY;
@@ -1027,7 +1070,7 @@ int get_dnode_of_data(struct dnode_of_data *, pgoff_t, int);
 int truncate_inode_blocks(struct inode *, pgoff_t);
 int truncate_xattr_node(struct inode *, struct page *);
 int wait_on_node_pages_writeback(struct f2fs_sb_info *, nid_t);
-int remove_inode_page(struct inode *);
+void remove_inode_page(struct inode *);
 struct page *new_inode_page(struct inode *, const struct qstr *);
 struct page *new_node_page(struct dnode_of_data *, unsigned int, struct page *);
 void ra_node_page(struct f2fs_sb_info *, nid_t);
@@ -1059,19 +1102,17 @@ void clear_prefree_segments(struct f2fs_sb_info *);
 int npages_for_summary_flush(struct f2fs_sb_info *);
 void allocate_new_segments(struct f2fs_sb_info *);
 struct page *get_sum_page(struct f2fs_sb_info *, unsigned int);
-struct bio *f2fs_bio_alloc(struct block_device *, int);
-void f2fs_submit_bio(struct f2fs_sb_info *, enum page_type, bool);
-void f2fs_wait_on_page_writeback(struct page *, enum page_type, bool);
 void write_meta_page(struct f2fs_sb_info *, struct page *);
 void write_node_page(struct f2fs_sb_info *, struct page *, unsigned int,
                                        block_t, block_t *);
-void write_data_page(struct inode *, struct page *, struct dnode_of_data*,
-                                       block_t, block_t *);
-void rewrite_data_page(struct f2fs_sb_info *, struct page *, block_t);
+void write_data_page(struct page *, struct dnode_of_data *, block_t *,
+                                       struct f2fs_io_info *);
+void rewrite_data_page(struct page *, block_t, struct f2fs_io_info *);
 void recover_data_page(struct f2fs_sb_info *, struct page *,
                                struct f2fs_summary *, block_t, block_t);
 void rewrite_node_page(struct f2fs_sb_info *, struct page *,
                                struct f2fs_summary *, block_t, block_t);
+void f2fs_wait_on_page_writeback(struct page *, enum page_type, bool);
 void write_data_summaries(struct f2fs_sb_info *, block_t);
 void write_node_summaries(struct f2fs_sb_info *, block_t);
 int lookup_journal_in_cursum(struct f2fs_summary_block *,
@@ -1079,6 +1120,8 @@ int lookup_journal_in_cursum(struct f2fs_summary_block *,
 void flush_sit_entries(struct f2fs_sb_info *);
 int build_segment_manager(struct f2fs_sb_info *);
 void destroy_segment_manager(struct f2fs_sb_info *);
+int __init create_segment_manager_caches(void);
+void destroy_segment_manager_caches(void);
 
 /*
  * checkpoint.c
@@ -1090,7 +1133,7 @@ int acquire_orphan_inode(struct f2fs_sb_info *);
 void release_orphan_inode(struct f2fs_sb_info *);
 void add_orphan_inode(struct f2fs_sb_info *, nid_t);
 void remove_orphan_inode(struct f2fs_sb_info *, nid_t);
-int recover_orphan_inodes(struct f2fs_sb_info *);
+void recover_orphan_inodes(struct f2fs_sb_info *);
 int get_valid_checkpoint(struct f2fs_sb_info *);
 void set_dirty_dir_page(struct inode *, struct page *);
 void add_dirty_dir_inode(struct inode *);
@@ -1105,13 +1148,17 @@ void destroy_checkpoint_caches(void);
 /*
  * data.c
  */
+void f2fs_submit_merged_bio(struct f2fs_sb_info *, enum page_type, int);
+int f2fs_submit_page_bio(struct f2fs_sb_info *, struct page *, block_t, int);
+void f2fs_submit_page_mbio(struct f2fs_sb_info *, struct page *, block_t,
+                                               struct f2fs_io_info *);
 int reserve_new_block(struct dnode_of_data *);
+int f2fs_reserve_block(struct dnode_of_data *, pgoff_t);
 void update_extent_cache(block_t, struct dnode_of_data *);
 struct page *find_data_page(struct inode *, pgoff_t, bool);
 struct page *get_lock_data_page(struct inode *, pgoff_t);
 struct page *get_new_data_page(struct inode *, struct page *, pgoff_t, bool);
-int f2fs_readpage(struct f2fs_sb_info *, struct page *, block_t, int);
-int do_write_data_page(struct page *);
+int do_write_data_page(struct page *, struct f2fs_io_info *);
 
 /*
  * gc.c
@@ -1238,4 +1285,5 @@ extern const struct address_space_operations f2fs_meta_aops;
 extern const struct inode_operations f2fs_dir_inode_operations;
 extern const struct inode_operations f2fs_symlink_inode_operations;
 extern const struct inode_operations f2fs_special_inode_operations;
+
 #endif
index 7d714f4972d59505e04576306dfd99a363f3b7d4..5accc964368d9834dbca324df30ba00f09f0f271 100644 (file)
@@ -33,7 +33,6 @@ static int f2fs_vm_page_mkwrite(struct vm_area_struct *vma,
        struct page *page = vmf->page;
        struct inode *inode = file_inode(vma->vm_file);
        struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
-       block_t old_blk_addr;
        struct dnode_of_data dn;
        int err;
 
@@ -44,30 +43,16 @@ static int f2fs_vm_page_mkwrite(struct vm_area_struct *vma,
        /* block allocation */
        f2fs_lock_op(sbi);
        set_new_dnode(&dn, inode, NULL, NULL, 0);
-       err = get_dnode_of_data(&dn, page->index, ALLOC_NODE);
-       if (err) {
-               f2fs_unlock_op(sbi);
-               goto out;
-       }
-
-       old_blk_addr = dn.data_blkaddr;
-
-       if (old_blk_addr == NULL_ADDR) {
-               err = reserve_new_block(&dn);
-               if (err) {
-                       f2fs_put_dnode(&dn);
-                       f2fs_unlock_op(sbi);
-                       goto out;
-               }
-       }
-       f2fs_put_dnode(&dn);
+       err = f2fs_reserve_block(&dn, page->index);
        f2fs_unlock_op(sbi);
+       if (err)
+               goto out;
 
        file_update_time(vma->vm_file);
        lock_page(page);
-       if (page->mapping != inode->i_mapping ||
+       if (unlikely(page->mapping != inode->i_mapping ||
                        page_offset(page) > i_size_read(inode) ||
-                       !PageUptodate(page)) {
+                       !PageUptodate(page))) {
                unlock_page(page);
                err = -EFAULT;
                goto out;
@@ -135,7 +120,7 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
                .for_reclaim = 0,
        };
 
-       if (f2fs_readonly(inode->i_sb))
+       if (unlikely(f2fs_readonly(inode->i_sb)))
                return 0;
 
        trace_f2fs_sync_file_enter(inode);
@@ -256,7 +241,7 @@ static void truncate_partial_data_page(struct inode *inode, u64 from)
                return;
 
        lock_page(page);
-       if (page->mapping != inode->i_mapping) {
+       if (unlikely(page->mapping != inode->i_mapping)) {
                f2fs_put_page(page, 1);
                return;
        }
@@ -459,7 +444,7 @@ int truncate_hole(struct inode *inode, pgoff_t pg_start, pgoff_t pg_end)
        return 0;
 }
 
-static int punch_hole(struct inode *inode, loff_t offset, loff_t len, int mode)
+static int punch_hole(struct inode *inode, loff_t offset, loff_t len)
 {
        pgoff_t pg_start, pg_end;
        loff_t off_start, off_end;
@@ -499,12 +484,6 @@ static int punch_hole(struct inode *inode, loff_t offset, loff_t len, int mode)
                }
        }
 
-       if (!(mode & FALLOC_FL_KEEP_SIZE) &&
-               i_size_read(inode) <= (offset + len)) {
-               i_size_write(inode, offset);
-               mark_inode_dirty(inode);
-       }
-
        return ret;
 }
 
@@ -532,22 +511,10 @@ static int expand_inode_data(struct inode *inode, loff_t offset,
 
                f2fs_lock_op(sbi);
                set_new_dnode(&dn, inode, NULL, NULL, 0);
-               ret = get_dnode_of_data(&dn, index, ALLOC_NODE);
-               if (ret) {
-                       f2fs_unlock_op(sbi);
-                       break;
-               }
-
-               if (dn.data_blkaddr == NULL_ADDR) {
-                       ret = reserve_new_block(&dn);
-                       if (ret) {
-                               f2fs_put_dnode(&dn);
-                               f2fs_unlock_op(sbi);
-                               break;
-                       }
-               }
-               f2fs_put_dnode(&dn);
+               ret = f2fs_reserve_block(&dn, index);
                f2fs_unlock_op(sbi);
+               if (ret)
+                       break;
 
                if (pg_start == pg_end)
                        new_size = offset + len;
@@ -578,7 +545,7 @@ static long f2fs_fallocate(struct file *file, int mode,
                return -EOPNOTSUPP;
 
        if (mode & FALLOC_FL_PUNCH_HOLE)
-               ret = punch_hole(inode, offset, len, mode);
+               ret = punch_hole(inode, offset, len);
        else
                ret = expand_inode_data(inode, offset, len, mode);
 
index b7ad1ec7e4ccb50227d1b48ce6d9ee7d26796f07..69c18e399014b8884cb60e28c37f146d3aeef78d 100644 (file)
@@ -119,7 +119,6 @@ int start_gc_thread(struct f2fs_sb_info *sbi)
                kfree(gc_th);
                sbi->gc_thread = NULL;
        }
-
 out:
        return err;
 }
@@ -521,6 +520,12 @@ static int check_dnode(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
 
 static void move_data_page(struct inode *inode, struct page *page, int gc_type)
 {
+       struct f2fs_io_info fio = {
+               .type = DATA,
+               .rw = WRITE_SYNC,
+               .rw_flag = 0,
+       };
+
        if (gc_type == BG_GC) {
                if (PageWriteback(page))
                        goto out;
@@ -537,7 +542,7 @@ static void move_data_page(struct inode *inode, struct page *page, int gc_type)
                        inode_dec_dirty_dents(inode);
                }
                set_cold_data(page);
-               do_write_data_page(page);
+               do_write_data_page(page, &fio);
                clear_cold_data(page);
        }
 out:
@@ -631,7 +636,7 @@ next_iput:
                goto next_step;
 
        if (gc_type == FG_GC) {
-               f2fs_submit_bio(sbi, DATA, true);
+               f2fs_submit_merged_bio(sbi, DATA, WRITE);
 
                /*
                 * In the case of FG_GC, it'd be better to reclaim this victim
@@ -664,8 +669,6 @@ static void do_garbage_collect(struct f2fs_sb_info *sbi, unsigned int segno,
 
        /* read segment summary of victim */
        sum_page = get_sum_page(sbi, segno);
-       if (IS_ERR(sum_page))
-               return;
 
        blk_start_plug(&plug);
 
@@ -697,7 +700,7 @@ int f2fs_gc(struct f2fs_sb_info *sbi)
 
        INIT_LIST_HEAD(&ilist);
 gc_more:
-       if (!(sbi->sb->s_flags & MS_ACTIVE))
+       if (unlikely(!(sbi->sb->s_flags & MS_ACTIVE)))
                goto stop;
 
        if (gc_type == BG_GC && has_not_enough_free_secs(sbi, nfree)) {
index 4ac4150d421dc05e6c20812d5fd36dcc910a938a..3565caf97005c1f25a35bc499184f710343fa766 100644 (file)
@@ -89,15 +89,18 @@ static void ra_nat_pages(struct f2fs_sb_info *sbi, int nid)
 {
        struct address_space *mapping = sbi->meta_inode->i_mapping;
        struct f2fs_nm_info *nm_i = NM_I(sbi);
-       struct blk_plug plug;
        struct page *page;
        pgoff_t index;
        int i;
+       struct f2fs_io_info fio = {
+               .type = META,
+               .rw = READ_SYNC,
+               .rw_flag = REQ_META | REQ_PRIO
+       };
 
-       blk_start_plug(&plug);
 
        for (i = 0; i < FREE_NID_PAGES; i++, nid += NAT_ENTRY_PER_BLOCK) {
-               if (nid >= nm_i->max_nid)
+               if (unlikely(nid >= nm_i->max_nid))
                        nid = 0;
                index = current_nat_addr(sbi, nid);
 
@@ -105,15 +108,15 @@ static void ra_nat_pages(struct f2fs_sb_info *sbi, int nid)
                if (!page)
                        continue;
                if (PageUptodate(page)) {
+                       mark_page_accessed(page);
                        f2fs_put_page(page, 1);
                        continue;
                }
-               if (f2fs_readpage(sbi, page, index, READ))
-                       continue;
-
+               f2fs_submit_page_mbio(sbi, page, index, &fio);
+               mark_page_accessed(page);
                f2fs_put_page(page, 0);
        }
-       blk_finish_plug(&plug);
+       f2fs_submit_merged_bio(sbi, META, READ);
 }
 
 static struct nat_entry *__lookup_nat_cache(struct f2fs_nm_info *nm_i, nid_t n)
@@ -502,7 +505,7 @@ static void truncate_node(struct dnode_of_data *dn)
 
        /* Deallocate node address */
        invalidate_blocks(sbi, ni.blk_addr);
-       dec_valid_node_count(sbi, dn->inode, 1);
+       dec_valid_node_count(sbi, dn->inode);
        set_node_addr(sbi, &ni, NULL_ADDR);
 
        if (dn->nid == dn->inode->i_ino) {
@@ -753,7 +756,7 @@ skip_partial:
                if (offset[1] == 0 &&
                                rn->i.i_nid[offset[0] - NODE_DIR1_BLOCK]) {
                        lock_page(page);
-                       if (page->mapping != node_mapping) {
+                       if (unlikely(page->mapping != node_mapping)) {
                                f2fs_put_page(page, 1);
                                goto restart;
                        }
@@ -794,7 +797,7 @@ int truncate_xattr_node(struct inode *inode, struct page *page)
        set_new_dnode(&dn, inode, page, npage, nid);
 
        if (page)
-               dn.inode_page_locked = 1;
+               dn.inode_page_locked = true;
        truncate_node(&dn);
        return 0;
 }
@@ -803,29 +806,25 @@ int truncate_xattr_node(struct inode *inode, struct page *page)
  * Caller should grab and release a mutex by calling mutex_lock_op() and
  * mutex_unlock_op().
  */
-int remove_inode_page(struct inode *inode)
+void remove_inode_page(struct inode *inode)
 {
        struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
        struct page *page;
        nid_t ino = inode->i_ino;
        struct dnode_of_data dn;
-       int err;
 
        page = get_node_page(sbi, ino);
        if (IS_ERR(page))
-               return PTR_ERR(page);
+               return;
 
-       err = truncate_xattr_node(inode, page);
-       if (err) {
+       if (truncate_xattr_node(inode, page)) {
                f2fs_put_page(page, 1);
-               return err;
+               return;
        }
-
        /* 0 is possible, after f2fs_new_inode() is failed */
        f2fs_bug_on(inode->i_blocks != 0 && inode->i_blocks != 1);
        set_new_dnode(&dn, inode, page, page, ino);
        truncate_node(&dn);
-       return 0;
 }
 
 struct page *new_inode_page(struct inode *inode, const struct qstr *name)
@@ -848,14 +847,14 @@ struct page *new_node_page(struct dnode_of_data *dn,
        struct page *page;
        int err;
 
-       if (is_inode_flag_set(F2FS_I(dn->inode), FI_NO_ALLOC))
+       if (unlikely(is_inode_flag_set(F2FS_I(dn->inode), FI_NO_ALLOC)))
                return ERR_PTR(-EPERM);
 
        page = grab_cache_page(mapping, dn->nid);
        if (!page)
                return ERR_PTR(-ENOMEM);
 
-       if (!inc_valid_node_count(sbi, dn->inode, 1)) {
+       if (unlikely(!inc_valid_node_count(sbi, dn->inode))) {
                err = -ENOSPC;
                goto fail;
        }
@@ -898,14 +897,14 @@ fail:
  * LOCKED_PAGE: f2fs_put_page(page, 1)
  * error: nothing
  */
-static int read_node_page(struct page *page, int type)
+static int read_node_page(struct page *page, int rw)
 {
        struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb);
        struct node_info ni;
 
        get_node_info(sbi, page->index, &ni);
 
-       if (ni.blk_addr == NULL_ADDR) {
+       if (unlikely(ni.blk_addr == NULL_ADDR)) {
                f2fs_put_page(page, 1);
                return -ENOENT;
        }
@@ -913,7 +912,7 @@ static int read_node_page(struct page *page, int type)
        if (PageUptodate(page))
                return LOCKED_PAGE;
 
-       return f2fs_readpage(sbi, page, ni.blk_addr, type);
+       return f2fs_submit_page_bio(sbi, page, ni.blk_addr, rw);
 }
 
 /*
@@ -960,11 +959,11 @@ repeat:
                goto got_it;
 
        lock_page(page);
-       if (!PageUptodate(page)) {
+       if (unlikely(!PageUptodate(page))) {
                f2fs_put_page(page, 1);
                return ERR_PTR(-EIO);
        }
-       if (page->mapping != mapping) {
+       if (unlikely(page->mapping != mapping)) {
                f2fs_put_page(page, 1);
                goto repeat;
        }
@@ -1017,12 +1016,12 @@ repeat:
        blk_finish_plug(&plug);
 
        lock_page(page);
-       if (page->mapping != mapping) {
+       if (unlikely(page->mapping != mapping)) {
                f2fs_put_page(page, 1);
                goto repeat;
        }
 page_hit:
-       if (!PageUptodate(page)) {
+       if (unlikely(!PageUptodate(page))) {
                f2fs_put_page(page, 1);
                return ERR_PTR(-EIO);
        }
@@ -1143,8 +1142,7 @@ continue_unlock:
        }
 
        if (wrote)
-               f2fs_submit_bio(sbi, NODE, wbc->sync_mode == WB_SYNC_ALL);
-
+               f2fs_submit_merged_bio(sbi, NODE, WRITE);
        return nwritten;
 }
 
@@ -1167,7 +1165,7 @@ int wait_on_node_pages_writeback(struct f2fs_sb_info *sbi, nid_t ino)
                        struct page *page = pvec.pages[i];
 
                        /* until radix tree lookup accepts end_index */
-                       if (page->index > end)
+                       if (unlikely(page->index > end))
                                continue;
 
                        if (ino && ino_of_node(page) == ino) {
@@ -1180,9 +1178,9 @@ int wait_on_node_pages_writeback(struct f2fs_sb_info *sbi, nid_t ino)
                cond_resched();
        }
 
-       if (test_and_clear_bit(AS_ENOSPC, &mapping->flags))
+       if (unlikely(test_and_clear_bit(AS_ENOSPC, &mapping->flags)))
                ret2 = -ENOSPC;
-       if (test_and_clear_bit(AS_EIO, &mapping->flags))
+       if (unlikely(test_and_clear_bit(AS_EIO, &mapping->flags)))
                ret2 = -EIO;
        if (!ret)
                ret = ret2;
@@ -1197,7 +1195,7 @@ static int f2fs_write_node_page(struct page *page,
        block_t new_addr;
        struct node_info ni;
 
-       if (sbi->por_doing)
+       if (unlikely(sbi->por_doing))
                goto redirty_out;
 
        wait_on_page_writeback(page);
@@ -1209,7 +1207,7 @@ static int f2fs_write_node_page(struct page *page,
        get_node_info(sbi, nid, &ni);
 
        /* This page is already truncated */
-       if (ni.blk_addr == NULL_ADDR) {
+       if (unlikely(ni.blk_addr == NULL_ADDR)) {
                dec_page_count(sbi, F2FS_DIRTY_NODES);
                unlock_page(page);
                return 0;
@@ -1333,7 +1331,7 @@ static int add_free_nid(struct f2fs_nm_info *nm_i, nid_t nid, bool build)
                return -1;
 
        /* 0 nid should not be used */
-       if (nid == 0)
+       if (unlikely(nid == 0))
                return 0;
 
        if (build) {
@@ -1386,7 +1384,7 @@ static void scan_nat_page(struct f2fs_nm_info *nm_i,
 
        for (; i < NAT_ENTRY_PER_BLOCK; i++, start_nid++) {
 
-               if (start_nid >= nm_i->max_nid)
+               if (unlikely(start_nid >= nm_i->max_nid))
                        break;
 
                blk_addr = le32_to_cpu(nat_blk->entries[i].block_addr);
@@ -1420,7 +1418,7 @@ static void build_free_nids(struct f2fs_sb_info *sbi)
                f2fs_put_page(page, 1);
 
                nid += (NAT_ENTRY_PER_BLOCK - (nid % NAT_ENTRY_PER_BLOCK));
-               if (nid >= nm_i->max_nid)
+               if (unlikely(nid >= nm_i->max_nid))
                        nid = 0;
 
                if (i++ == FREE_NID_PAGES)
@@ -1454,7 +1452,7 @@ bool alloc_nid(struct f2fs_sb_info *sbi, nid_t *nid)
        struct free_nid *i = NULL;
        struct list_head *this;
 retry:
-       if (sbi->total_valid_node_count + 1 >= nm_i->max_nid)
+       if (unlikely(sbi->total_valid_node_count + 1 >= nm_i->max_nid))
                return false;
 
        spin_lock(&nm_i->free_nid_list_lock);
@@ -1564,7 +1562,7 @@ int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page)
        new_ni = old_ni;
        new_ni.ino = ino;
 
-       if (!inc_valid_node_count(sbi, NULL, 1))
+       if (unlikely(!inc_valid_node_count(sbi, NULL)))
                WARN_ON(1);
        set_node_addr(sbi, &new_ni, NEW_ADDR);
        inc_valid_inode_count(sbi);
@@ -1572,47 +1570,89 @@ int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page)
        return 0;
 }
 
+/*
+ * ra_sum_pages() merge contiguous pages into one bio and submit.
+ * these pre-readed pages are linked in pages list.
+ */
+static int ra_sum_pages(struct f2fs_sb_info *sbi, struct list_head *pages,
+                               int start, int nrpages)
+{
+       struct page *page;
+       int page_idx = start;
+       struct f2fs_io_info fio = {
+               .type = META,
+               .rw = READ_SYNC,
+               .rw_flag = REQ_META | REQ_PRIO
+       };
+
+       for (; page_idx < start + nrpages; page_idx++) {
+               /* alloc temporal page for read node summary info*/
+               page = alloc_page(GFP_F2FS_ZERO);
+               if (!page) {
+                       struct page *tmp;
+                       list_for_each_entry_safe(page, tmp, pages, lru) {
+                               list_del(&page->lru);
+                               unlock_page(page);
+                               __free_pages(page, 0);
+                       }
+                       return -ENOMEM;
+               }
+
+               lock_page(page);
+               page->index = page_idx;
+               list_add_tail(&page->lru, pages);
+       }
+
+       list_for_each_entry(page, pages, lru)
+               f2fs_submit_page_mbio(sbi, page, page->index, &fio);
+
+       f2fs_submit_merged_bio(sbi, META, READ);
+       return 0;
+}
+
 int restore_node_summary(struct f2fs_sb_info *sbi,
                        unsigned int segno, struct f2fs_summary_block *sum)
 {
        struct f2fs_node *rn;
        struct f2fs_summary *sum_entry;
-       struct page *page;
+       struct page *page, *tmp;
        block_t addr;
-       int i, last_offset;
-
-       /* alloc temporal page for read node */
-       page = alloc_page(GFP_NOFS | __GFP_ZERO);
-       if (!page)
-               return -ENOMEM;
-       lock_page(page);
+       int bio_blocks = MAX_BIO_BLOCKS(max_hw_blocks(sbi));
+       int i, last_offset, nrpages, err = 0;
+       LIST_HEAD(page_list);
 
        /* scan the node segment */
        last_offset = sbi->blocks_per_seg;
        addr = START_BLOCK(sbi, segno);
        sum_entry = &sum->entries[0];
 
-       for (i = 0; i < last_offset; i++, sum_entry++) {
-               /*
-                * In order to read next node page,
-                * we must clear PageUptodate flag.
-                */
-               ClearPageUptodate(page);
+       for (i = 0; i < last_offset; i += nrpages, addr += nrpages) {
+               nrpages = min(last_offset - i, bio_blocks);
 
-               if (f2fs_readpage(sbi, page, addr, READ_SYNC))
-                       goto out;
+               /* read ahead node pages */
+               err = ra_sum_pages(sbi, &page_list, addr, nrpages);
+               if (err)
+                       return err;
 
-               lock_page(page);
-               rn = F2FS_NODE(page);
-               sum_entry->nid = rn->footer.nid;
-               sum_entry->version = 0;
-               sum_entry->ofs_in_node = 0;
-               addr++;
+               list_for_each_entry_safe(page, tmp, &page_list, lru) {
+
+                       lock_page(page);
+                       if (unlikely(!PageUptodate(page))) {
+                               err = -EIO;
+                       } else {
+                               rn = F2FS_NODE(page);
+                               sum_entry->nid = rn->footer.nid;
+                               sum_entry->version = 0;
+                               sum_entry->ofs_in_node = 0;
+                               sum_entry++;
+                       }
+
+                       list_del(&page->lru);
+                       unlock_page(page);
+                       __free_pages(page, 0);
+               }
        }
-       unlock_page(page);
-out:
-       __free_pages(page, 0);
-       return 0;
+       return err;
 }
 
 static bool flush_nats_in_journal(struct f2fs_sb_info *sbi)
index fdc81161f2543a4818e371946ba691515aa9f3c4..a3f4542160cf1abb099a94419afe2bb19bfd56b9 100644 (file)
@@ -143,9 +143,9 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head)
        while (1) {
                struct fsync_inode_entry *entry;
 
-               err = f2fs_readpage(sbi, page, blkaddr, READ_SYNC);
+               err = f2fs_submit_page_bio(sbi, page, blkaddr, READ_SYNC);
                if (err)
-                       goto out;
+                       return err;
 
                lock_page(page);
 
@@ -191,9 +191,10 @@ next:
                /* check next segment */
                blkaddr = next_blkaddr_of_node(page);
        }
+
        unlock_page(page);
-out:
        __free_pages(page, 0);
+
        return err;
 }
 
@@ -377,7 +378,7 @@ static int recover_data(struct f2fs_sb_info *sbi,
        blkaddr = NEXT_FREE_BLKADDR(sbi, curseg);
 
        /* read node page */
-       page = alloc_page(GFP_NOFS | __GFP_ZERO);
+       page = alloc_page(GFP_F2FS_ZERO);
        if (!page)
                return -ENOMEM;
 
@@ -386,9 +387,9 @@ static int recover_data(struct f2fs_sb_info *sbi,
        while (1) {
                struct fsync_inode_entry *entry;
 
-               err = f2fs_readpage(sbi, page, blkaddr, READ_SYNC);
+               err = f2fs_submit_page_bio(sbi, page, blkaddr, READ_SYNC);
                if (err)
-                       goto out;
+                       return err;
 
                lock_page(page);
 
@@ -412,8 +413,8 @@ next:
                /* check next segment */
                blkaddr = next_blkaddr_of_node(page);
        }
+
        unlock_page(page);
-out:
        __free_pages(page, 0);
 
        if (!err)
@@ -429,7 +430,7 @@ int recover_fsync_data(struct f2fs_sb_info *sbi)
 
        fsync_entry_slab = f2fs_kmem_cache_create("f2fs_fsync_inode_entry",
                        sizeof(struct fsync_inode_entry), NULL);
-       if (unlikely(!fsync_entry_slab))
+       if (!fsync_entry_slab)
                return -ENOMEM;
 
        INIT_LIST_HEAD(&inode_list);
index fa284d397199faed53f1c8ffb4de611440ad2e73..0b2e8ceec9832cd46c8d2b74dfadb19d9ba47291 100644 (file)
 #include <linux/blkdev.h>
 #include <linux/prefetch.h>
 #include <linux/vmalloc.h>
+#include <linux/swap.h>
 
 #include "f2fs.h"
 #include "segment.h"
 #include "node.h"
 #include <trace/events/f2fs.h>
 
+#define __reverse_ffz(x) __reverse_ffs(~(x))
+
+static struct kmem_cache *discard_entry_slab;
+
+/*
+ * __reverse_ffs is copied from include/asm-generic/bitops/__ffs.h since
+ * MSB and LSB are reversed in a byte by f2fs_set_bit.
+ */
+static inline unsigned long __reverse_ffs(unsigned long word)
+{
+       int num = 0;
+
+#if BITS_PER_LONG == 64
+       if ((word & 0xffffffff) == 0) {
+               num += 32;
+               word >>= 32;
+       }
+#endif
+       if ((word & 0xffff) == 0) {
+               num += 16;
+               word >>= 16;
+       }
+       if ((word & 0xff) == 0) {
+               num += 8;
+               word >>= 8;
+       }
+       if ((word & 0xf0) == 0)
+               num += 4;
+       else
+               word >>= 4;
+       if ((word & 0xc) == 0)
+               num += 2;
+       else
+               word >>= 2;
+       if ((word & 0x2) == 0)
+               num += 1;
+       return num;
+}
+
+/*
+ * __find_rev_next(_zero)_bit is copied from lib/find_next_bit.c becasue
+ * f2fs_set_bit makes MSB and LSB reversed in a byte.
+ * Example:
+ *                             LSB <--> MSB
+ *   f2fs_set_bit(0, bitmap) => 0000 0001
+ *   f2fs_set_bit(7, bitmap) => 1000 0000
+ */
+static unsigned long __find_rev_next_bit(const unsigned long *addr,
+                       unsigned long size, unsigned long offset)
+{
+       const unsigned long *p = addr + BIT_WORD(offset);
+       unsigned long result = offset & ~(BITS_PER_LONG - 1);
+       unsigned long tmp;
+       unsigned long mask, submask;
+       unsigned long quot, rest;
+
+       if (offset >= size)
+               return size;
+
+       size -= result;
+       offset %= BITS_PER_LONG;
+       if (!offset)
+               goto aligned;
+
+       tmp = *(p++);
+       quot = (offset >> 3) << 3;
+       rest = offset & 0x7;
+       mask = ~0UL << quot;
+       submask = (unsigned char)(0xff << rest) >> rest;
+       submask <<= quot;
+       mask &= submask;
+       tmp &= mask;
+       if (size < BITS_PER_LONG)
+               goto found_first;
+       if (tmp)
+               goto found_middle;
+
+       size -= BITS_PER_LONG;
+       result += BITS_PER_LONG;
+aligned:
+       while (size & ~(BITS_PER_LONG-1)) {
+               tmp = *(p++);
+               if (tmp)
+                       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 == 0UL)         /* Are any bits set? */
+               return result + size;   /* Nope. */
+found_middle:
+       return result + __reverse_ffs(tmp);
+}
+
+static unsigned long __find_rev_next_zero_bit(const unsigned long *addr,
+                       unsigned long size, unsigned long offset)
+{
+       const unsigned long *p = addr + BIT_WORD(offset);
+       unsigned long result = offset & ~(BITS_PER_LONG - 1);
+       unsigned long tmp;
+       unsigned long mask, submask;
+       unsigned long quot, rest;
+
+       if (offset >= size)
+               return size;
+
+       size -= result;
+       offset %= BITS_PER_LONG;
+       if (!offset)
+               goto aligned;
+
+       tmp = *(p++);
+       quot = (offset >> 3) << 3;
+       rest = offset & 0x7;
+       mask = ~(~0UL << quot);
+       submask = (unsigned char)~((unsigned char)(0xff << rest) >> rest);
+       submask <<= quot;
+       mask += submask;
+       tmp |= mask;
+       if (size < BITS_PER_LONG)
+               goto found_first;
+       if (~tmp)
+               goto found_middle;
+
+       size -= BITS_PER_LONG;
+       result += BITS_PER_LONG;
+aligned:
+       while (size & ~(BITS_PER_LONG - 1)) {
+               tmp = *(p++);
+               if (~tmp)
+                       goto found_middle;
+               result += BITS_PER_LONG;
+               size -= BITS_PER_LONG;
+       }
+       if (!size)
+               return result;
+       tmp = *p;
+
+found_first:
+       tmp |= ~0UL << size;
+       if (tmp == ~0UL)        /* Are any bits zero? */
+               return result + size;   /* Nope. */
+found_middle:
+       return result + __reverse_ffz(tmp);
+}
+
 /*
  * This function balances dirty node and dentry pages.
  * In addition, it controls garbage collection.
@@ -116,6 +267,56 @@ static void locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno)
        mutex_unlock(&dirty_i->seglist_lock);
 }
 
+static void f2fs_issue_discard(struct f2fs_sb_info *sbi,
+                               block_t blkstart, block_t blklen)
+{
+       sector_t start = SECTOR_FROM_BLOCK(sbi, blkstart);
+       sector_t len = SECTOR_FROM_BLOCK(sbi, blklen);
+       blkdev_issue_discard(sbi->sb->s_bdev, start, len, GFP_NOFS, 0);
+       trace_f2fs_issue_discard(sbi->sb, blkstart, blklen);
+}
+
+static void add_discard_addrs(struct f2fs_sb_info *sbi,
+                       unsigned int segno, struct seg_entry *se)
+{
+       struct list_head *head = &SM_I(sbi)->discard_list;
+       struct discard_entry *new;
+       int entries = SIT_VBLOCK_MAP_SIZE / sizeof(unsigned long);
+       int max_blocks = sbi->blocks_per_seg;
+       unsigned long *cur_map = (unsigned long *)se->cur_valid_map;
+       unsigned long *ckpt_map = (unsigned long *)se->ckpt_valid_map;
+       unsigned long dmap[entries];
+       unsigned int start = 0, end = -1;
+       int i;
+
+       if (!test_opt(sbi, DISCARD))
+               return;
+
+       /* zero block will be discarded through the prefree list */
+       if (!se->valid_blocks || se->valid_blocks == max_blocks)
+               return;
+
+       /* SIT_VBLOCK_MAP_SIZE should be multiple of sizeof(unsigned long) */
+       for (i = 0; i < entries; i++)
+               dmap[i] = (cur_map[i] ^ ckpt_map[i]) & ckpt_map[i];
+
+       while (SM_I(sbi)->nr_discards <= SM_I(sbi)->max_discards) {
+               start = __find_rev_next_bit(dmap, max_blocks, end + 1);
+               if (start >= max_blocks)
+                       break;
+
+               end = __find_rev_next_zero_bit(dmap, max_blocks, start + 1);
+
+               new = f2fs_kmem_cache_alloc(discard_entry_slab, GFP_NOFS);
+               INIT_LIST_HEAD(&new->list);
+               new->blkaddr = START_BLOCK(sbi, segno) + start;
+               new->len = end - start;
+
+               list_add_tail(&new->list, head);
+               SM_I(sbi)->nr_discards += end - start;
+       }
+}
+
 /*
  * Should call clear_prefree_segments after checkpoint is done.
  */
@@ -138,6 +339,9 @@ static void set_prefree_as_free_segments(struct f2fs_sb_info *sbi)
 
 void clear_prefree_segments(struct f2fs_sb_info *sbi)
 {
+       struct list_head *head = &(SM_I(sbi)->discard_list);
+       struct list_head *this, *next;
+       struct discard_entry *entry;
        struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
        unsigned long *prefree_map = dirty_i->dirty_segmap[PRE];
        unsigned int total_segs = TOTAL_SEGS(sbi);
@@ -160,14 +364,19 @@ void clear_prefree_segments(struct f2fs_sb_info *sbi)
                if (!test_opt(sbi, DISCARD))
                        continue;
 
-               blkdev_issue_discard(sbi->sb->s_bdev,
-                               START_BLOCK(sbi, start) <<
-                               sbi->log_sectors_per_block,
-                               (1 << (sbi->log_sectors_per_block +
-                               sbi->log_blocks_per_seg)) * (end - start),
-                               GFP_NOFS, 0);
+               f2fs_issue_discard(sbi, START_BLOCK(sbi, start),
+                               (end - start) << sbi->log_blocks_per_seg);
        }
        mutex_unlock(&dirty_i->seglist_lock);
+
+       /* send small discards */
+       list_for_each_safe(this, next, head) {
+               entry = list_entry(this, struct discard_entry, list);
+               f2fs_issue_discard(sbi, entry->blkaddr, entry->len);
+               list_del(&entry->list);
+               SM_I(sbi)->nr_discards -= entry->len;
+               kmem_cache_free(discard_entry_slab, entry);
+       }
 }
 
 static void __mark_sit_entry_dirty(struct f2fs_sb_info *sbi, unsigned int segno)
@@ -459,13 +668,18 @@ static void __next_free_blkoff(struct f2fs_sb_info *sbi,
                        struct curseg_info *seg, block_t start)
 {
        struct seg_entry *se = get_seg_entry(sbi, seg->segno);
-       block_t ofs;
-       for (ofs = start; ofs < sbi->blocks_per_seg; ofs++) {
-               if (!f2fs_test_bit(ofs, se->ckpt_valid_map)
-                       && !f2fs_test_bit(ofs, se->cur_valid_map))
-                       break;
-       }
-       seg->next_blkoff = ofs;
+       int entries = SIT_VBLOCK_MAP_SIZE / sizeof(unsigned long);
+       unsigned long target_map[entries];
+       unsigned long *ckpt_map = (unsigned long *)se->ckpt_valid_map;
+       unsigned long *cur_map = (unsigned long *)se->cur_valid_map;
+       int i, pos;
+
+       for (i = 0; i < entries; i++)
+               target_map[i] = ckpt_map[i] | cur_map[i];
+
+       pos = __find_rev_next_zero_bit(target_map, sbi->blocks_per_seg, start);
+
+       seg->next_blkoff = pos;
 }
 
 /*
@@ -573,148 +787,6 @@ static const struct segment_allocation default_salloc_ops = {
        .allocate_segment = allocate_segment_by_default,
 };
 
-static void f2fs_end_io_write(struct bio *bio, int err)
-{
-       const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
-       struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
-       struct bio_private *p = bio->bi_private;
-
-       do {
-               struct page *page = bvec->bv_page;
-
-               if (--bvec >= bio->bi_io_vec)
-                       prefetchw(&bvec->bv_page->flags);
-               if (!uptodate) {
-                       SetPageError(page);
-                       if (page->mapping)
-                               set_bit(AS_EIO, &page->mapping->flags);
-                       set_ckpt_flags(p->sbi->ckpt, CP_ERROR_FLAG);
-                       p->sbi->sb->s_flags |= MS_RDONLY;
-               }
-               end_page_writeback(page);
-               dec_page_count(p->sbi, F2FS_WRITEBACK);
-       } while (bvec >= bio->bi_io_vec);
-
-       if (p->is_sync)
-               complete(p->wait);
-
-       if (!get_pages(p->sbi, F2FS_WRITEBACK) &&
-                       !list_empty(&p->sbi->cp_wait.task_list))
-               wake_up(&p->sbi->cp_wait);
-
-       kfree(p);
-       bio_put(bio);
-}
-
-struct bio *f2fs_bio_alloc(struct block_device *bdev, int npages)
-{
-       struct bio *bio;
-
-       /* No failure on bio allocation */
-       bio = bio_alloc(GFP_NOIO, npages);
-       bio->bi_bdev = bdev;
-       bio->bi_private = NULL;
-
-       return bio;
-}
-
-static void do_submit_bio(struct f2fs_sb_info *sbi,
-                               enum page_type type, bool sync)
-{
-       int rw = sync ? WRITE_SYNC : WRITE;
-       enum page_type btype = type > META ? META : type;
-
-       if (type >= META_FLUSH)
-               rw = WRITE_FLUSH_FUA;
-
-       if (btype == META)
-               rw |= REQ_META;
-
-       if (sbi->bio[btype]) {
-               struct bio_private *p = sbi->bio[btype]->bi_private;
-               p->sbi = sbi;
-               sbi->bio[btype]->bi_end_io = f2fs_end_io_write;
-
-               trace_f2fs_do_submit_bio(sbi->sb, btype, sync, sbi->bio[btype]);
-
-               if (type == META_FLUSH) {
-                       DECLARE_COMPLETION_ONSTACK(wait);
-                       p->is_sync = true;
-                       p->wait = &wait;
-                       submit_bio(rw, sbi->bio[btype]);
-                       wait_for_completion(&wait);
-               } else {
-                       p->is_sync = false;
-                       submit_bio(rw, sbi->bio[btype]);
-               }
-               sbi->bio[btype] = NULL;
-       }
-}
-
-void f2fs_submit_bio(struct f2fs_sb_info *sbi, enum page_type type, bool sync)
-{
-       down_write(&sbi->bio_sem);
-       do_submit_bio(sbi, type, sync);
-       up_write(&sbi->bio_sem);
-}
-
-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);
-
-       down_write(&sbi->bio_sem);
-
-       inc_page_count(sbi, F2FS_WRITEBACK);
-
-       if (sbi->bio[type] && sbi->last_block_in_bio[type] != blk_addr - 1)
-               do_submit_bio(sbi, type, false);
-alloc_new:
-       if (sbi->bio[type] == NULL) {
-               struct bio_private *priv;
-retry:
-               priv = kmalloc(sizeof(struct bio_private), GFP_NOFS);
-               if (!priv) {
-                       cond_resched();
-                       goto retry;
-               }
-
-               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;
-               /*
-                * The end_io will be assigned at the sumbission phase.
-                * Until then, let bio_add_page() merge consecutive IOs as much
-                * as possible.
-                */
-       }
-
-       if (bio_add_page(sbi->bio[type], page, PAGE_CACHE_SIZE, 0) <
-                                                       PAGE_CACHE_SIZE) {
-               do_submit_bio(sbi, type, false);
-               goto alloc_new;
-       }
-
-       sbi->last_block_in_bio[type] = blk_addr;
-
-       up_write(&sbi->bio_sem);
-       trace_f2fs_submit_write_page(page, blk_addr, type);
-}
-
-void f2fs_wait_on_page_writeback(struct page *page,
-                               enum page_type type, bool sync)
-{
-       struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb);
-       if (PageWriteback(page)) {
-               f2fs_submit_bio(sbi, type, sync);
-               wait_on_page_writeback(page);
-       }
-}
-
 static bool __has_curseg_space(struct f2fs_sb_info *sbi, int type)
 {
        struct curseg_info *curseg = CURSEG_I(sbi, type);
@@ -784,14 +856,14 @@ static int __get_segment_type(struct page *page, enum page_type p_type)
 
 static void do_write_page(struct f2fs_sb_info *sbi, struct page *page,
                        block_t old_blkaddr, block_t *new_blkaddr,
-                       struct f2fs_summary *sum, enum page_type p_type)
+                       struct f2fs_summary *sum, struct f2fs_io_info *fio)
 {
        struct sit_info *sit_i = SIT_I(sbi);
        struct curseg_info *curseg;
        unsigned int old_cursegno;
        int type;
 
-       type = __get_segment_type(page, p_type);
+       type = __get_segment_type(page, fio->type);
        curseg = CURSEG_I(sbi, type);
 
        mutex_lock(&curseg->curseg_mutex);
@@ -824,49 +896,60 @@ static void do_write_page(struct f2fs_sb_info *sbi, struct page *page,
        locate_dirty_segment(sbi, GET_SEGNO(sbi, old_blkaddr));
        mutex_unlock(&sit_i->sentry_lock);
 
-       if (p_type == NODE)
+       if (fio->type == NODE)
                fill_node_footer_blkaddr(page, NEXT_FREE_BLKADDR(sbi, curseg));
 
        /* writeout dirty page into bdev */
-       submit_write_page(sbi, page, *new_blkaddr, p_type);
+       f2fs_submit_page_mbio(sbi, page, *new_blkaddr, fio);
 
        mutex_unlock(&curseg->curseg_mutex);
 }
 
 void write_meta_page(struct f2fs_sb_info *sbi, struct page *page)
 {
+       struct f2fs_io_info fio = {
+               .type = META,
+               .rw = WRITE_SYNC,
+               .rw_flag = REQ_META | REQ_PRIO
+       };
+
        set_page_writeback(page);
-       submit_write_page(sbi, page, page->index, META);
+       f2fs_submit_page_mbio(sbi, page, page->index, &fio);
 }
 
 void write_node_page(struct f2fs_sb_info *sbi, struct page *page,
                unsigned int nid, block_t old_blkaddr, block_t *new_blkaddr)
 {
        struct f2fs_summary sum;
+       struct f2fs_io_info fio = {
+               .type = NODE,
+               .rw = WRITE_SYNC,
+               .rw_flag = 0
+       };
+
        set_summary(&sum, nid, 0, 0);
-       do_write_page(sbi, page, old_blkaddr, new_blkaddr, &sum, NODE);
+       do_write_page(sbi, page, old_blkaddr, new_blkaddr, &sum, &fio);
 }
 
-void write_data_page(struct inode *inode, struct page *page,
-               struct dnode_of_data *dn, block_t old_blkaddr,
-               block_t *new_blkaddr)
+void write_data_page(struct page *page, struct dnode_of_data *dn,
+               block_t *new_blkaddr, struct f2fs_io_info *fio)
 {
-       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
        struct f2fs_summary sum;
        struct node_info ni;
 
-       f2fs_bug_on(old_blkaddr == NULL_ADDR);
+       f2fs_bug_on(dn->data_blkaddr == NULL_ADDR);
        get_node_info(sbi, dn->nid, &ni);
        set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version);
 
-       do_write_page(sbi, page, old_blkaddr,
-                       new_blkaddr, &sum, DATA);
+       do_write_page(sbi, page, dn->data_blkaddr, new_blkaddr, &sum, fio);
 }
 
-void rewrite_data_page(struct f2fs_sb_info *sbi, struct page *page,
-                                       block_t old_blk_addr)
+void rewrite_data_page(struct page *page, block_t old_blkaddr, struct f2fs_io_info *fio)
 {
-       submit_write_page(sbi, page, old_blk_addr, DATA);
+       struct inode *inode = page->mapping->host;
+       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       f2fs_submit_page_mbio(sbi, page, old_blkaddr, fio);
 }
 
 void recover_data_page(struct f2fs_sb_info *sbi,
@@ -925,6 +1008,11 @@ void rewrite_node_page(struct f2fs_sb_info *sbi,
        unsigned int segno, old_cursegno;
        block_t next_blkaddr = next_blkaddr_of_node(page);
        unsigned int next_segno = GET_SEGNO(sbi, next_blkaddr);
+       struct f2fs_io_info fio = {
+               .type = NODE,
+               .rw = WRITE_SYNC,
+               .rw_flag = 0
+       };
 
        curseg = CURSEG_I(sbi, type);
 
@@ -953,8 +1041,8 @@ void rewrite_node_page(struct f2fs_sb_info *sbi,
 
        /* rewrite node page */
        set_page_writeback(page);
-       submit_write_page(sbi, page, new_blkaddr, NODE);
-       f2fs_submit_bio(sbi, NODE, true);
+       f2fs_submit_page_mbio(sbi, page, new_blkaddr, &fio);
+       f2fs_submit_merged_bio(sbi, NODE, WRITE);
        refresh_sit_entry(sbi, old_blkaddr, new_blkaddr);
 
        locate_dirty_segment(sbi, old_cursegno);
@@ -964,6 +1052,16 @@ void rewrite_node_page(struct f2fs_sb_info *sbi,
        mutex_unlock(&curseg->curseg_mutex);
 }
 
+void f2fs_wait_on_page_writeback(struct page *page,
+                               enum page_type type, bool sync)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb);
+       if (PageWriteback(page)) {
+               f2fs_submit_merged_bio(sbi, type, WRITE);
+               wait_on_page_writeback(page);
+       }
+}
+
 static int read_compacted_summaries(struct f2fs_sb_info *sbi)
 {
        struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
@@ -1314,6 +1412,10 @@ void flush_sit_entries(struct f2fs_sb_info *sbi)
 
                sit_offset = SIT_ENTRY_OFFSET(sit_i, segno);
 
+               /* add discard candidates */
+               if (SM_I(sbi)->nr_discards < SM_I(sbi)->max_discards)
+                       add_discard_addrs(sbi, segno, se);
+
                if (flushed)
                        goto to_sit_page;
 
@@ -1480,41 +1582,94 @@ static int build_curseg(struct f2fs_sb_info *sbi)
        return restore_curseg_summaries(sbi);
 }
 
+static int ra_sit_pages(struct f2fs_sb_info *sbi, int start, int nrpages)
+{
+       struct address_space *mapping = sbi->meta_inode->i_mapping;
+       struct page *page;
+       block_t blk_addr, prev_blk_addr = 0;
+       int sit_blk_cnt = SIT_BLK_CNT(sbi);
+       int blkno = start;
+       struct f2fs_io_info fio = {
+               .type = META,
+               .rw = READ_SYNC,
+               .rw_flag = REQ_META | REQ_PRIO
+       };
+
+       for (; blkno < start + nrpages && blkno < sit_blk_cnt; blkno++) {
+
+               blk_addr = current_sit_addr(sbi, blkno * SIT_ENTRY_PER_BLOCK);
+
+               if (blkno != start && prev_blk_addr + 1 != blk_addr)
+                       break;
+               prev_blk_addr = blk_addr;
+repeat:
+               page = grab_cache_page(mapping, blk_addr);
+               if (!page) {
+                       cond_resched();
+                       goto repeat;
+               }
+               if (PageUptodate(page)) {
+                       mark_page_accessed(page);
+                       f2fs_put_page(page, 1);
+                       continue;
+               }
+
+               f2fs_submit_page_mbio(sbi, page, blk_addr, &fio);
+
+               mark_page_accessed(page);
+               f2fs_put_page(page, 0);
+       }
+
+       f2fs_submit_merged_bio(sbi, META, READ);
+       return blkno - start;
+}
+
 static void build_sit_entries(struct f2fs_sb_info *sbi)
 {
        struct sit_info *sit_i = SIT_I(sbi);
        struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA);
        struct f2fs_summary_block *sum = curseg->sum_blk;
-       unsigned int start;
+       int sit_blk_cnt = SIT_BLK_CNT(sbi);
+       unsigned int i, start, end;
+       unsigned int readed, start_blk = 0;
+       int nrpages = MAX_BIO_BLOCKS(max_hw_blocks(sbi));
 
-       for (start = 0; start < TOTAL_SEGS(sbi); start++) {
-               struct seg_entry *se = &sit_i->sentries[start];
-               struct f2fs_sit_block *sit_blk;
-               struct f2fs_sit_entry sit;
-               struct page *page;
-               int i;
-
-               mutex_lock(&curseg->curseg_mutex);
-               for (i = 0; i < sits_in_cursum(sum); i++) {
-                       if (le32_to_cpu(segno_in_journal(sum, i)) == start) {
-                               sit = sit_in_journal(sum, i);
-                               mutex_unlock(&curseg->curseg_mutex);
-                               goto got_it;
+       do {
+               readed = ra_sit_pages(sbi, start_blk, nrpages);
+
+               start = start_blk * sit_i->sents_per_block;
+               end = (start_blk + readed) * sit_i->sents_per_block;
+
+               for (; start < end && start < TOTAL_SEGS(sbi); start++) {
+                       struct seg_entry *se = &sit_i->sentries[start];
+                       struct f2fs_sit_block *sit_blk;
+                       struct f2fs_sit_entry sit;
+                       struct page *page;
+
+                       mutex_lock(&curseg->curseg_mutex);
+                       for (i = 0; i < sits_in_cursum(sum); i++) {
+                               if (le32_to_cpu(segno_in_journal(sum, i)) == start) {
+                                       sit = sit_in_journal(sum, i);
+                                       mutex_unlock(&curseg->curseg_mutex);
+                                       goto got_it;
+                               }
                        }
-               }
-               mutex_unlock(&curseg->curseg_mutex);
-               page = get_current_sit_page(sbi, start);
-               sit_blk = (struct f2fs_sit_block *)page_address(page);
-               sit = sit_blk->entries[SIT_ENTRY_OFFSET(sit_i, start)];
-               f2fs_put_page(page, 1);
+                       mutex_unlock(&curseg->curseg_mutex);
+
+                       page = get_current_sit_page(sbi, start);
+                       sit_blk = (struct f2fs_sit_block *)page_address(page);
+                       sit = sit_blk->entries[SIT_ENTRY_OFFSET(sit_i, start)];
+                       f2fs_put_page(page, 1);
 got_it:
-               check_block_count(sbi, start, &sit);
-               seg_info_from_raw_sit(se, &sit);
-               if (sbi->segs_per_sec > 1) {
-                       struct sec_entry *e = get_sec_entry(sbi, start);
-                       e->valid_blocks += se->valid_blocks;
+                       check_block_count(sbi, start, &sit);
+                       seg_info_from_raw_sit(se, &sit);
+                       if (sbi->segs_per_sec > 1) {
+                               struct sec_entry *e = get_sec_entry(sbi, start);
+                               e->valid_blocks += se->valid_blocks;
+                       }
                }
-       }
+               start_blk += readed;
+       } while (start_blk < sit_blk_cnt);
 }
 
 static void init_free_segmap(struct f2fs_sb_info *sbi)
@@ -1645,6 +1800,10 @@ int build_segment_manager(struct f2fs_sb_info *sbi)
        sm_info->ssa_blkaddr = le32_to_cpu(raw_super->ssa_blkaddr);
        sm_info->rec_prefree_segments = DEF_RECLAIM_PREFREE_SEGMENTS;
 
+       INIT_LIST_HEAD(&sm_info->discard_list);
+       sm_info->nr_discards = 0;
+       sm_info->max_discards = 0;
+
        err = build_sit_info(sbi);
        if (err)
                return err;
@@ -1760,3 +1919,17 @@ void destroy_segment_manager(struct f2fs_sb_info *sbi)
        sbi->sm_info = NULL;
        kfree(sm_info);
 }
+
+int __init create_segment_manager_caches(void)
+{
+       discard_entry_slab = f2fs_kmem_cache_create("discard_entry",
+                       sizeof(struct discard_entry), NULL);
+       if (!discard_entry_slab)
+               return -ENOMEM;
+       return 0;
+}
+
+void destroy_segment_manager_caches(void)
+{
+       kmem_cache_destroy(discard_entry_slab);
+}
index 269f690b4e2492c65bf1a59e9d10302d87725a4e..ea563760f4b748e2827b543c4fc7a6a869abe8f0 100644 (file)
 #define GET_L2R_SEGNO(free_i, segno)   (segno - free_i->start_segno)
 #define GET_R2L_SEGNO(free_i, segno)   (segno + free_i->start_segno)
 
-#define IS_DATASEG(t)                                                  \
-       ((t == CURSEG_HOT_DATA) || (t == CURSEG_COLD_DATA) ||           \
-       (t == CURSEG_WARM_DATA))
-
-#define IS_NODESEG(t)                                                  \
-       ((t == CURSEG_HOT_NODE) || (t == CURSEG_COLD_NODE) ||           \
-       (t == CURSEG_WARM_NODE))
+#define IS_DATASEG(t)  (t <= CURSEG_COLD_DATA)
+#define IS_NODESEG(t)  (t >= CURSEG_HOT_NODE)
 
 #define IS_CURSEG(sbi, seg)                                            \
        ((seg == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno) ||      \
        (segno / SIT_ENTRY_PER_BLOCK)
 #define        START_SEGNO(sit_i, segno)               \
        (SIT_BLOCK_OFFSET(sit_i, segno) * SIT_ENTRY_PER_BLOCK)
+#define SIT_BLK_CNT(sbi)                       \
+       ((TOTAL_SEGS(sbi) + SIT_ENTRY_PER_BLOCK - 1) / SIT_ENTRY_PER_BLOCK)
 #define f2fs_bitmap_size(nr)                   \
        (BITS_TO_LONGS(nr) * sizeof(unsigned long))
 #define TOTAL_SEGS(sbi)        (SM_I(sbi)->main_segments)
 #define TOTAL_SECS(sbi)        (sbi->total_sections)
 
 #define SECTOR_FROM_BLOCK(sbi, blk_addr)                               \
-       (blk_addr << ((sbi)->log_blocksize - F2FS_LOG_SECTOR_SIZE))
+       (((sector_t)blk_addr) << (sbi)->log_sectors_per_block)
 #define SECTOR_TO_BLOCK(sbi, sectors)                                  \
-       (sectors >> ((sbi)->log_blocksize - F2FS_LOG_SECTOR_SIZE))
+       (sectors >> (sbi)->log_sectors_per_block)
 #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 {
-       struct f2fs_sb_info *sbi;
-       bool is_sync;
-       void *wait;
-};
-
 /*
  * indicate a block allocation direction: RIGHT and LEFT.
  * RIGHT means allocating new sections towards the end of volume.
@@ -467,7 +457,7 @@ static inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi, int freed)
        int node_secs = get_blocktype_secs(sbi, F2FS_DIRTY_NODES);
        int dent_secs = get_blocktype_secs(sbi, F2FS_DIRTY_DENTS);
 
-       if (sbi->por_doing)
+       if (unlikely(sbi->por_doing))
                return false;
 
        return ((free_sections(sbi) + freed) <= (node_secs + 2 * dent_secs +
index bafff72de8e841afba9d609a8001c71af67f42fc..5c574fa1143cd7bc5b9e3c11c0e49793526263fa 100644 (file)
@@ -50,6 +50,7 @@ enum {
        Opt_active_logs,
        Opt_disable_ext_identify,
        Opt_inline_xattr,
+       Opt_inline_data,
        Opt_err,
 };
 
@@ -65,6 +66,7 @@ static match_table_t f2fs_tokens = {
        {Opt_active_logs, "active_logs=%u"},
        {Opt_disable_ext_identify, "disable_ext_identify"},
        {Opt_inline_xattr, "inline_xattr"},
+       {Opt_inline_data, "inline_data"},
        {Opt_err, NULL},
 };
 
@@ -175,6 +177,7 @@ F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_max_sleep_time, max_sleep_time);
 F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_no_gc_sleep_time, no_gc_sleep_time);
 F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_idle, gc_idle);
 F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, reclaim_segments, rec_prefree_segments);
+F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, max_small_discards, max_discards);
 
 #define ATTR_LIST(name) (&f2fs_attr_##name.attr)
 static struct attribute *f2fs_attrs[] = {
@@ -183,6 +186,7 @@ static struct attribute *f2fs_attrs[] = {
        ATTR_LIST(gc_no_gc_sleep_time),
        ATTR_LIST(gc_idle),
        ATTR_LIST(reclaim_segments),
+       ATTR_LIST(max_small_discards),
        NULL,
 };
 
@@ -311,6 +315,9 @@ static int parse_options(struct super_block *sb, char *options)
                case Opt_disable_ext_identify:
                        set_opt(sbi, DISABLE_EXT_IDENTIFY);
                        break;
+               case Opt_inline_data:
+                       set_opt(sbi, INLINE_DATA);
+                       break;
                default:
                        f2fs_msg(sb, KERN_ERR,
                                "Unrecognized mount option \"%s\" or missing value",
@@ -325,7 +332,7 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb)
 {
        struct f2fs_inode_info *fi;
 
-       fi = kmem_cache_alloc(f2fs_inode_cachep, GFP_NOFS | __GFP_ZERO);
+       fi = kmem_cache_alloc(f2fs_inode_cachep, GFP_F2FS_ZERO);
        if (!fi)
                return NULL;
 
@@ -508,7 +515,8 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
 #endif
        if (test_opt(sbi, DISABLE_EXT_IDENTIFY))
                seq_puts(seq, ",disable_ext_identify");
-
+       if (test_opt(sbi, INLINE_DATA))
+               seq_puts(seq, ",inline_data");
        seq_printf(seq, ",active_logs=%u", sbi->active_logs);
 
        return 0;
@@ -618,7 +626,7 @@ static struct inode *f2fs_nfs_get_inode(struct super_block *sb,
        struct f2fs_sb_info *sbi = F2FS_SB(sb);
        struct inode *inode;
 
-       if (ino < F2FS_ROOT_INO(sbi))
+       if (unlikely(ino < F2FS_ROOT_INO(sbi)))
                return ERR_PTR(-ESTALE);
 
        /*
@@ -629,7 +637,7 @@ static struct inode *f2fs_nfs_get_inode(struct super_block *sb,
        inode = f2fs_iget(sb, ino);
        if (IS_ERR(inode))
                return ERR_CAST(inode);
-       if (generation && inode->i_generation != generation) {
+       if (unlikely(generation && inode->i_generation != generation)) {
                /* we didn't find the right inode.. */
                iput(inode);
                return ERR_PTR(-ESTALE);
@@ -732,10 +740,10 @@ static int sanity_check_ckpt(struct f2fs_sb_info *sbi)
        fsmeta += le32_to_cpu(ckpt->rsvd_segment_count);
        fsmeta += le32_to_cpu(raw_super->segment_count_ssa);
 
-       if (fsmeta >= total)
+       if (unlikely(fsmeta >= total))
                return 1;
 
-       if (is_set_ckpt_flags(ckpt, CP_ERROR_FLAG)) {
+       if (unlikely(is_set_ckpt_flags(ckpt, CP_ERROR_FLAG))) {
                f2fs_msg(sbi->sb, KERN_ERR, "A bug case: need to run fsck");
                return 1;
        }
@@ -800,7 +808,7 @@ retry:
                brelse(*raw_super_buf);
                f2fs_msg(sb, KERN_ERR, "Can't find a valid F2FS filesystem "
                                "in %dth superblock", block + 1);
-               if(block == 0) {
+               if (block == 0) {
                        block++;
                        goto retry;
                } else {
@@ -818,6 +826,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
        struct buffer_head *raw_super_buf;
        struct inode *root;
        long err = -EINVAL;
+       int i;
 
        /* allocate memory for f2fs-specific super block info */
        sbi = kzalloc(sizeof(struct f2fs_sb_info), GFP_KERNEL);
@@ -825,7 +834,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
                return -ENOMEM;
 
        /* set a block size */
-       if (!sb_set_blocksize(sb, F2FS_BLKSIZE)) {
+       if (unlikely(!sb_set_blocksize(sb, F2FS_BLKSIZE))) {
                f2fs_msg(sb, KERN_ERR, "unable to set blocksize");
                goto free_sbi;
        }
@@ -874,7 +883,16 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
        mutex_init(&sbi->node_write);
        sbi->por_doing = false;
        spin_lock_init(&sbi->stat_lock);
-       init_rwsem(&sbi->bio_sem);
+
+       mutex_init(&sbi->read_io.io_mutex);
+       sbi->read_io.sbi = sbi;
+       sbi->read_io.bio = NULL;
+       for (i = 0; i < NR_PAGE_TYPE; i++) {
+               mutex_init(&sbi->write_io[i].io_mutex);
+               sbi->write_io[i].sbi = sbi;
+               sbi->write_io[i].bio = NULL;
+       }
+
        init_rwsem(&sbi->cp_rwsem);
        init_waitqueue_head(&sbi->cp_wait);
        init_sb_info(sbi);
@@ -939,9 +957,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
        }
 
        /* if there are nt orphan nodes free them */
-       err = -EINVAL;
-       if (recover_orphan_inodes(sbi))
-               goto free_node_inode;
+       recover_orphan_inodes(sbi);
 
        /* read root inode and dentry */
        root = f2fs_iget(sb, F2FS_ROOT_INO(sbi));
@@ -950,8 +966,10 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
                err = PTR_ERR(root);
                goto free_node_inode;
        }
-       if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size)
+       if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) {
+               err = -EINVAL;
                goto free_root_inode;
+       }
 
        sb->s_root = d_make_root(root); /* allocate root dentry */
        if (!sb->s_root) {
@@ -1053,7 +1071,7 @@ static int __init init_inodecache(void)
 {
        f2fs_inode_cachep = f2fs_kmem_cache_create("f2fs_inode_cache",
                        sizeof(struct f2fs_inode_info), NULL);
-       if (f2fs_inode_cachep == NULL)
+       if (!f2fs_inode_cachep)
                return -ENOMEM;
        return 0;
 }
@@ -1078,9 +1096,12 @@ static int __init init_f2fs_fs(void)
        err = create_node_manager_caches();
        if (err)
                goto free_inodecache;
-       err = create_gc_caches();
+       err = create_segment_manager_caches();
        if (err)
                goto free_node_manager_caches;
+       err = create_gc_caches();
+       if (err)
+               goto free_segment_manager_caches;
        err = create_checkpoint_caches();
        if (err)
                goto free_gc_caches;
@@ -1102,6 +1123,8 @@ free_checkpoint_caches:
        destroy_checkpoint_caches();
 free_gc_caches:
        destroy_gc_caches();
+free_segment_manager_caches:
+       destroy_segment_manager_caches();
 free_node_manager_caches:
        destroy_node_manager_caches();
 free_inodecache:
@@ -1117,6 +1140,7 @@ static void __exit exit_f2fs_fs(void)
        unregister_filesystem(&f2fs_fs_type);
        destroy_checkpoint_caches();
        destroy_gc_caches();
+       destroy_segment_manager_caches();
        destroy_node_manager_caches();
        destroy_inodecache();
        kset_unregister(f2fs_kset);
index aa7a3f139fe5336130d10dcfbe9813fa7ca95698..b0fb8a27f3da6fe3b810eca732361953aeebc030 100644 (file)
@@ -522,7 +522,7 @@ static int __f2fs_setxattr(struct inode *inode, int name_index,
                if (found)
                        free = free + ENTRY_SIZE(here);
 
-               if (free < newsize) {
+               if (unlikely(free < newsize)) {
                        error = -ENOSPC;
                        goto exit;
                }
index 7f5c658af755f9b43296c1dacfab5def788c4a1c..b4730cf52aec9172727816820174fb53d7e001b8 100644 (file)
@@ -755,6 +755,7 @@ static void fscache_write_op(struct fscache_operation *_op)
        struct fscache_object *object = op->op.object;
        struct fscache_cookie *cookie;
        struct page *page;
+       pgoff_t index;
        unsigned n;
        void *results[1];
        int ret;
@@ -803,7 +804,7 @@ static void fscache_write_op(struct fscache_operation *_op)
        _debug("gang %d [%lx]", n, page->index);
        if (page->index > op->store_limit) {
                fscache_stat(&fscache_n_store_pages_over_limit);
-               goto superseded;
+               goto page_beyond_limit;
        }
 
        radix_tree_tag_set(&cookie->stores, page->index,
@@ -829,6 +830,40 @@ static void fscache_write_op(struct fscache_operation *_op)
        _leave("");
        return;
 
+page_beyond_limit:
+       spin_unlock(&object->lock);
+
+page_beyond_limit_unlocked:
+       /* pages that are now beyond the end of the storage object must have
+        * their pending storage records cleared.
+        */
+       index = page->index;
+       radix_tree_tag_clear(&cookie->stores, page->index,
+                            FSCACHE_COOKIE_PENDING_TAG);
+       if (!radix_tree_tag_get(&cookie->stores, page->index,
+                               FSCACHE_COOKIE_STORING_TAG)) {
+               fscache_stat(&fscache_n_store_radix_deletes);
+               radix_tree_delete(&cookie->stores, page->index);
+               page_cache_release(page);
+       }
+       if (!need_resched()) {
+               n = radix_tree_gang_lookup_tag(&cookie->stores, results,
+                                              index + 1, 1,
+                                              FSCACHE_COOKIE_PENDING_TAG);
+               if (n == 1) {
+                       page = results[0];
+                       goto page_beyond_limit_unlocked;
+               }
+               spin_unlock(&cookie->stores_lock);
+               wake_up_bit(&cookie->flags, 0);
+       } else {
+               spin_unlock(&cookie->stores_lock);
+       }
+
+       fscache_enqueue_operation(&op->op);
+       _leave("");
+       return;
+
 superseded:
        /* this writer is going away and there aren't any more things to
         * write */
index b7fc035a6943cc40f649f1cca7be5858fbcf1cbc..028281303beacc580992411ac11e2816d2ad76ad 100644 (file)
@@ -1050,30 +1050,22 @@ int gfs2_releasepage(struct page *page, gfp_t gfp_mask)
                bh = bh->b_this_page;
        } while(bh != head);
        spin_unlock(&sdp->sd_ail_lock);
-       gfs2_log_unlock(sdp);
 
        head = bh = page_buffers(page);
        do {
-               gfs2_log_lock(sdp);
                bd = bh->b_private;
                if (bd) {
                        gfs2_assert_warn(sdp, bd->bd_bh == bh);
-                       if (!list_empty(&bd->bd_list)) {
-                               if (!buffer_pinned(bh))
-                                       list_del_init(&bd->bd_list);
-                               else
-                                       bd = NULL;
-                       }
-                       if (bd)
-                               bd->bd_bh = NULL;
+                       if (!list_empty(&bd->bd_list))
+                               list_del_init(&bd->bd_list);
+                       bd->bd_bh = NULL;
                        bh->b_private = NULL;
-               }
-               gfs2_log_unlock(sdp);
-               if (bd)
                        kmem_cache_free(gfs2_bufdata_cachep, bd);
+               }
 
                bh = bh->b_this_page;
        } while (bh != head);
+       gfs2_log_unlock(sdp);
 
        return try_to_free_buffers(page);
 
index db908f697139cfffbca462d3a7528e13139576b5..3a81f1e7de116ce64b1e6d23f0f0cffd7e69ec8b 100644 (file)
@@ -133,7 +133,8 @@ void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
 
 static void rgrp_go_sync(struct gfs2_glock *gl)
 {
-       struct address_space *metamapping = gfs2_glock2aspace(gl);
+       struct gfs2_sbd *sdp = gl->gl_sbd;
+       struct address_space *mapping = &sdp->sd_aspace;
        struct gfs2_rgrpd *rgd;
        int error;
 
@@ -141,10 +142,10 @@ static void rgrp_go_sync(struct gfs2_glock *gl)
                return;
        GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_EXCLUSIVE);
 
-       gfs2_log_flush(gl->gl_sbd, gl);
-       filemap_fdatawrite(metamapping);
-       error = filemap_fdatawait(metamapping);
-        mapping_set_error(metamapping, error);
+       gfs2_log_flush(sdp, gl);
+       filemap_fdatawrite_range(mapping, gl->gl_vm.start, gl->gl_vm.end);
+       error = filemap_fdatawait_range(mapping, gl->gl_vm.start, gl->gl_vm.end);
+       mapping_set_error(mapping, error);
        gfs2_ail_empty_gl(gl);
 
        spin_lock(&gl->gl_spin);
@@ -166,11 +167,12 @@ static void rgrp_go_sync(struct gfs2_glock *gl)
 
 static void rgrp_go_inval(struct gfs2_glock *gl, int flags)
 {
-       struct address_space *mapping = gfs2_glock2aspace(gl);
+       struct gfs2_sbd *sdp = gl->gl_sbd;
+       struct address_space *mapping = &sdp->sd_aspace;
 
        WARN_ON_ONCE(!(flags & DIO_METADATA));
-       gfs2_assert_withdraw(gl->gl_sbd, !atomic_read(&gl->gl_ail_count));
-       truncate_inode_pages(mapping, 0);
+       gfs2_assert_withdraw(sdp, !atomic_read(&gl->gl_ail_count));
+       truncate_inode_pages_range(mapping, gl->gl_vm.start, gl->gl_vm.end);
 
        if (gl->gl_object) {
                struct gfs2_rgrpd *rgd = (struct gfs2_rgrpd *)gl->gl_object;
@@ -552,7 +554,7 @@ const struct gfs2_glock_operations gfs2_rgrp_glops = {
        .go_unlock = gfs2_rgrp_go_unlock,
        .go_dump = gfs2_rgrp_dump,
        .go_type = LM_TYPE_RGRP,
-       .go_flags = GLOF_ASPACE | GLOF_LVB,
+       .go_flags = GLOF_LVB,
 };
 
 const struct gfs2_glock_operations gfs2_trans_glops = {
index ba1ea67f4eeb1c99e826f54be8b9b6d8d57909f8..a99f60c98845db04ccc733feb1a6c0a4e09d4d6e 100644 (file)
@@ -93,6 +93,7 @@ struct gfs2_rgrpd {
        struct gfs2_rgrp_lvb *rd_rgl;
        u32 rd_last_alloc;
        u32 rd_flags;
+       u32 rd_extfail_pt;              /* extent failure point */
 #define GFS2_RDF_CHECK         0x10000000 /* check for unlinked inodes */
 #define GFS2_RDF_UPTODATE      0x20000000 /* rg is up to date */
 #define GFS2_RDF_ERROR         0x40000000 /* error in rg */
@@ -350,7 +351,15 @@ struct gfs2_glock {
        atomic_t gl_ail_count;
        atomic_t gl_revokes;
        struct delayed_work gl_work;
-       struct work_struct gl_delete;
+       union {
+               /* For inode and iopen glocks only */
+               struct work_struct gl_delete;
+               /* For rgrp glocks only */
+               struct {
+                       loff_t start;
+                       loff_t end;
+               } gl_vm;
+       };
        struct rcu_head gl_rcu;
 };
 
@@ -727,6 +736,8 @@ struct gfs2_sbd {
 
        /* Log stuff */
 
+       struct address_space sd_aspace;
+
        spinlock_t sd_log_lock;
 
        struct gfs2_trans *sd_log_tr;
index 610613fb65b552dccfdf9853ac96d2f667bd36d4..9dcb9777a5f80eb32bcfce88aca3a8026776f047 100644 (file)
@@ -551,10 +551,10 @@ void gfs2_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
        struct buffer_head *bh = bd->bd_bh;
        struct gfs2_glock *gl = bd->bd_gl;
 
-       gfs2_remove_from_ail(bd);
-       bd->bd_bh = NULL;
        bh->b_private = NULL;
        bd->bd_blkno = bh->b_blocknr;
+       gfs2_remove_from_ail(bd); /* drops ref on bh */
+       bd->bd_bh = NULL;
        bd->bd_ops = &gfs2_revoke_lops;
        sdp->sd_log_num_revoke++;
        atomic_inc(&gl->gl_revokes);
index 010b9fb9fec6e781cb80a6982d746896ba6cffdb..76693793ceddfe7f936c360a6c3494d1882a849a 100644 (file)
@@ -83,6 +83,7 @@ static void maybe_release_space(struct gfs2_bufdata *bd)
               bd->bd_bh->b_data + bi->bi_offset, bi->bi_len);
        clear_bit(GBF_FULL, &bi->bi_flags);
        rgd->rd_free_clone = rgd->rd_free;
+       rgd->rd_extfail_pt = rgd->rd_free;
 }
 
 /**
@@ -272,7 +273,7 @@ static struct bio *gfs2_log_alloc_bio(struct gfs2_sbd *sdp, u64 blkno)
                nrvecs = max(nrvecs/2, 1U);
        }
 
-       bio->bi_sector = blkno * (sb->s_blocksize >> 9);
+       bio->bi_iter.bi_sector = blkno * (sb->s_blocksize >> 9);
        bio->bi_bdev = sb->s_bdev;
        bio->bi_end_io = gfs2_end_log_write;
        bio->bi_private = sdp;
@@ -588,8 +589,12 @@ static int buf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start,
 static void gfs2_meta_sync(struct gfs2_glock *gl)
 {
        struct address_space *mapping = gfs2_glock2aspace(gl);
+       struct gfs2_sbd *sdp = gl->gl_sbd;
        int error;
 
+       if (mapping == NULL)
+               mapping = &sdp->sd_aspace;
+
        filemap_fdatawrite(mapping);
        error = filemap_fdatawait(mapping);
 
index 932415050540e2a1bdefc6d957e68ef7a0d82d01..e57f6081e7e5cf8043148f4782d0a68459b802fd 100644 (file)
@@ -116,6 +116,9 @@ struct buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno, int create)
        unsigned long index;
        unsigned int bufnum;
 
+       if (mapping == NULL)
+               mapping = &sdp->sd_aspace;
+
        shift = PAGE_CACHE_SHIFT - sdp->sd_sb.sb_bsize_shift;
        index = blkno >> shift;             /* convert block to page */
        bufnum = blkno - (index << shift);  /* block buf index within page */
index 82303b4749582cd3c00d402a9f42b9972b1de677..716d40391b2393c4b41b6667711a95a1b8ad2deb 100644 (file)
@@ -36,6 +36,7 @@
 #include "log.h"
 #include "quota.h"
 #include "dir.h"
+#include "meta_io.h"
 #include "trace_gfs2.h"
 
 #define DO 0
@@ -62,6 +63,7 @@ static void gfs2_tune_init(struct gfs2_tune *gt)
 static struct gfs2_sbd *init_sbd(struct super_block *sb)
 {
        struct gfs2_sbd *sdp;
+       struct address_space *mapping;
 
        sdp = kzalloc(sizeof(struct gfs2_sbd), GFP_KERNEL);
        if (!sdp)
@@ -98,6 +100,16 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
        INIT_LIST_HEAD(&sdp->sd_trunc_list);
        spin_lock_init(&sdp->sd_trunc_lock);
 
+       mapping = &sdp->sd_aspace;
+
+       mapping->a_ops = &gfs2_meta_aops;
+       mapping->host = sb->s_bdev->bd_inode;
+       mapping->flags = 0;
+       mapping_set_gfp_mask(mapping, GFP_NOFS);
+       mapping->private_data = NULL;
+       mapping->backing_dev_info = sb->s_bdi;
+       mapping->writeback_index = 0;
+
        spin_lock_init(&sdp->sd_log_lock);
        atomic_set(&sdp->sd_log_pinned, 0);
        INIT_LIST_HEAD(&sdp->sd_log_le_buf);
@@ -224,7 +236,7 @@ static int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector, int silent)
        lock_page(page);
 
        bio = bio_alloc(GFP_NOFS, 1);
-       bio->bi_sector = sector * (sb->s_blocksize >> 9);
+       bio->bi_iter.bi_sector = sector * (sb->s_blocksize >> 9);
        bio->bi_bdev = sb->s_bdev;
        bio_add_page(bio, page, PAGE_SIZE, 0);
 
@@ -1366,8 +1378,18 @@ static struct dentry *gfs2_mount(struct file_system_type *fs_type, int flags,
        if (IS_ERR(s))
                goto error_bdev;
 
-       if (s->s_root)
+       if (s->s_root) {
+               /*
+                * s_umount nests inside bd_mutex during
+                * __invalidate_device().  blkdev_put() acquires
+                * bd_mutex and can't be called under s_umount.  Drop
+                * s_umount temporarily.  This is safe as we're
+                * holding an active reference.
+                */
+               up_write(&s->s_umount);
                blkdev_put(bdev, mode);
+               down_write(&s->s_umount);
+       }
 
        memset(&args, 0, sizeof(args));
        args.ar_quota = GFS2_QUOTA_DEFAULT;
index 98236d0df3cae7ce7666a10dc7fc907590b873b0..1b6b3675ee1d546b15b78bdf5dc1ee9fb5823b0d 100644 (file)
 #include "inode.h"
 #include "util.h"
 
-struct gfs2_quota_change_host {
-       u64 qc_change;
-       u32 qc_flags; /* GFS2_QCF_... */
-       struct kqid qc_id;
-};
-
 /* Lock order: qd_lock -> qd->lockref.lock -> lru lock */
 static DEFINE_SPINLOCK(qd_lock);
 struct list_lru gfs2_qd_lru;
@@ -1214,17 +1208,6 @@ int gfs2_quota_refresh(struct gfs2_sbd *sdp, struct kqid qid)
        return error;
 }
 
-static void gfs2_quota_change_in(struct gfs2_quota_change_host *qc, const void *buf)
-{
-       const struct gfs2_quota_change *str = buf;
-
-       qc->qc_change = be64_to_cpu(str->qc_change);
-       qc->qc_flags = be32_to_cpu(str->qc_flags);
-       qc->qc_id = make_kqid(&init_user_ns,
-                             (qc->qc_flags & GFS2_QCF_USER)?USRQUOTA:GRPQUOTA,
-                             be32_to_cpu(str->qc_id));
-}
-
 int gfs2_quota_init(struct gfs2_sbd *sdp)
 {
        struct gfs2_inode *ip = GFS2_I(sdp->sd_qc_inode);
@@ -1257,6 +1240,7 @@ int gfs2_quota_init(struct gfs2_sbd *sdp)
 
        for (x = 0; x < blocks; x++) {
                struct buffer_head *bh;
+               const struct gfs2_quota_change *qc;
                unsigned int y;
 
                if (!extlen) {
@@ -1274,25 +1258,28 @@ int gfs2_quota_init(struct gfs2_sbd *sdp)
                        goto fail;
                }
 
+               qc = (const struct gfs2_quota_change *)(bh->b_data + sizeof(struct gfs2_meta_header));
                for (y = 0; y < sdp->sd_qc_per_block && slot < sdp->sd_quota_slots;
                     y++, slot++) {
-                       struct gfs2_quota_change_host qc;
                        struct gfs2_quota_data *qd;
-
-                       gfs2_quota_change_in(&qc, bh->b_data +
-                                         sizeof(struct gfs2_meta_header) +
-                                         y * sizeof(struct gfs2_quota_change));
-                       if (!qc.qc_change)
+                       s64 qc_change = be64_to_cpu(qc->qc_change);
+                       u32 qc_flags = be32_to_cpu(qc->qc_flags);
+                       enum quota_type qtype = (qc_flags & GFS2_QCF_USER) ?
+                                               USRQUOTA : GRPQUOTA;
+                       struct kqid qc_id = make_kqid(&init_user_ns, qtype,
+                                                     be32_to_cpu(qc->qc_id));
+                       qc++;
+                       if (!qc_change)
                                continue;
 
-                       error = qd_alloc(sdp, qc.qc_id, &qd);
+                       error = qd_alloc(sdp, qc_id, &qd);
                        if (error) {
                                brelse(bh);
                                goto fail;
                        }
 
                        set_bit(QDF_CHANGE, &qd->qd_flags);
-                       qd->qd_change = qc.qc_change;
+                       qd->qd_change = qc_change;
                        qd->qd_slot = slot;
                        qd->qd_slot_count = 1;
 
index c8d6161bd682bd6cbd05247e2f0efc8274afe0b9..183cf0f0052d9c7fa78d8b369c7b4a7d8b0c452c 100644 (file)
  * 3 = Used (metadata)
  */
 
+struct gfs2_extent {
+       struct gfs2_rbm rbm;
+       u32 len;
+};
+
 static const char valid_change[16] = {
                /* current */
        /* n */ 0, 1, 1, 1,
@@ -65,8 +70,9 @@ static const char valid_change[16] = {
                1, 0, 0, 0
 };
 
-static int gfs2_rbm_find(struct gfs2_rbm *rbm, u8 state, u32 minext,
-                         const struct gfs2_inode *ip, bool nowrap);
+static int gfs2_rbm_find(struct gfs2_rbm *rbm, u8 state, u32 *minext,
+                        const struct gfs2_inode *ip, bool nowrap,
+                        const struct gfs2_alloc_parms *ap);
 
 
 /**
@@ -635,9 +641,13 @@ static void __rs_deltree(struct gfs2_blkreserv *rs)
                /* 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;
+               /* The rgrp extent failure point is likely not to increase;
+                  it will only do so if the freed blocks are somehow
+                  contiguous with a span of free blocks that follows. Still,
+                  it will force the number to be recalculated later. */
+               rgd->rd_extfail_pt += rs->rs_free;
                rs->rs_free = 0;
                clear_bit(GBF_FULL, &bi->bi_flags);
-               smp_mb__after_clear_bit();
        }
 }
 
@@ -876,6 +886,7 @@ static int rgd_insert(struct gfs2_rgrpd *rgd)
 static int read_rindex_entry(struct gfs2_inode *ip)
 {
        struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+       const unsigned bsize = sdp->sd_sb.sb_bsize;
        loff_t pos = sdp->sd_rgrps * sizeof(struct gfs2_rindex);
        struct gfs2_rindex buf;
        int error;
@@ -913,6 +924,8 @@ static int read_rindex_entry(struct gfs2_inode *ip)
                goto fail;
 
        rgd->rd_gl->gl_object = rgd;
+       rgd->rd_gl->gl_vm.start = rgd->rd_addr * bsize;
+       rgd->rd_gl->gl_vm.end = rgd->rd_gl->gl_vm.start + (rgd->rd_length * bsize) - 1;
        rgd->rd_rgl = (struct gfs2_rgrp_lvb *)rgd->rd_gl->gl_lksb.sb_lvbptr;
        rgd->rd_flags &= ~GFS2_RDF_UPTODATE;
        if (rgd->rd_data > sdp->sd_max_rg_data)
@@ -1126,6 +1139,8 @@ int gfs2_rgrp_bh_get(struct gfs2_rgrpd *rgd)
                gfs2_rgrp_in(rgd, (rgd->rd_bits[0].bi_bh)->b_data);
                rgd->rd_flags |= (GFS2_RDF_UPTODATE | GFS2_RDF_CHECK);
                rgd->rd_free_clone = rgd->rd_free;
+               /* max out the rgrp allocation failure point */
+               rgd->rd_extfail_pt = rgd->rd_free;
        }
        if (cpu_to_be32(GFS2_MAGIC) != rgd->rd_rgl->rl_magic) {
                rgd->rd_rgl->rl_unlinked = cpu_to_be32(count_unlinked(rgd));
@@ -1455,7 +1470,7 @@ static void rg_mblk_search(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip,
        if (WARN_ON(gfs2_rbm_from_block(&rbm, goal)))
                return;
 
-       ret = gfs2_rbm_find(&rbm, GFS2_BLKST_FREE, extlen, ip, true);
+       ret = gfs2_rbm_find(&rbm, GFS2_BLKST_FREE, &extlen, ip, true, ap);
        if (ret == 0) {
                rs->rs_rbm = rbm;
                rs->rs_free = extlen;
@@ -1520,6 +1535,7 @@ static u64 gfs2_next_unreserved_block(struct gfs2_rgrpd *rgd, u64 block,
  * @rbm: The current position in the resource group
  * @ip: The inode for which we are searching for blocks
  * @minext: The minimum extent length
+ * @maxext: A pointer to the maximum extent structure
  *
  * This checks the current position in the rgrp to see whether there is
  * a reservation covering this block. If not then this function is a
@@ -1532,7 +1548,8 @@ static u64 gfs2_next_unreserved_block(struct gfs2_rgrpd *rgd, u64 block,
 
 static int gfs2_reservation_check_and_update(struct gfs2_rbm *rbm,
                                             const struct gfs2_inode *ip,
-                                            u32 minext)
+                                            u32 minext,
+                                            struct gfs2_extent *maxext)
 {
        u64 block = gfs2_rbm_to_block(rbm);
        u32 extlen = 1;
@@ -1545,8 +1562,7 @@ static int gfs2_reservation_check_and_update(struct gfs2_rbm *rbm,
         */
        if (minext) {
                extlen = gfs2_free_extlen(rbm, minext);
-               nblock = block + extlen;
-               if (extlen < minext)
+               if (extlen <= maxext->len)
                        goto fail;
        }
 
@@ -1555,9 +1571,17 @@ static int gfs2_reservation_check_and_update(struct gfs2_rbm *rbm,
         * and skip if parts of it are already reserved
         */
        nblock = gfs2_next_unreserved_block(rbm->rgd, block, extlen, ip);
-       if (nblock == block)
-               return 0;
+       if (nblock == block) {
+               if (!minext || extlen >= minext)
+                       return 0;
+
+               if (extlen > maxext->len) {
+                       maxext->len = extlen;
+                       maxext->rbm = *rbm;
+               }
 fail:
+               nblock = block + extlen;
+       }
        ret = gfs2_rbm_from_block(rbm, nblock);
        if (ret < 0)
                return ret;
@@ -1568,30 +1592,38 @@ fail:
  * gfs2_rbm_find - Look for blocks of a particular state
  * @rbm: Value/result starting position and final position
  * @state: The state which we want to find
- * @minext: The requested extent length (0 for a single block)
+ * @minext: Pointer to the requested extent length (NULL for a single block)
+ *          This is updated to be the actual reservation size.
  * @ip: If set, check for reservations
  * @nowrap: Stop looking at the end of the rgrp, rather than wrapping
  *          around until we've reached the starting point.
+ * @ap: the allocation parameters
  *
  * Side effects:
  * - If looking for free blocks, we set GBF_FULL on each bitmap which
  *   has no free blocks in it.
+ * - If looking for free blocks, we set rd_extfail_pt on each rgrp which
+ *   has come up short on a free block search.
  *
  * Returns: 0 on success, -ENOSPC if there is no block of the requested state
  */
 
-static int gfs2_rbm_find(struct gfs2_rbm *rbm, u8 state, u32 minext,
-                        const struct gfs2_inode *ip, bool nowrap)
+static int gfs2_rbm_find(struct gfs2_rbm *rbm, u8 state, u32 *minext,
+                        const struct gfs2_inode *ip, bool nowrap,
+                        const struct gfs2_alloc_parms *ap)
 {
        struct buffer_head *bh;
        int initial_bii;
        u32 initial_offset;
+       int first_bii = rbm->bii;
+       u32 first_offset = rbm->offset;
        u32 offset;
        u8 *buffer;
        int n = 0;
        int iters = rbm->rgd->rd_length;
        int ret;
        struct gfs2_bitmap *bi;
+       struct gfs2_extent maxext = { .rbm.rgd = rbm->rgd, };
 
        /* 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
@@ -1620,7 +1652,9 @@ static int gfs2_rbm_find(struct gfs2_rbm *rbm, u8 state, u32 minext,
                        return 0;
 
                initial_bii = rbm->bii;
-               ret = gfs2_reservation_check_and_update(rbm, ip, minext);
+               ret = gfs2_reservation_check_and_update(rbm, ip,
+                                                       minext ? *minext : 0,
+                                                       &maxext);
                if (ret == 0)
                        return 0;
                if (ret > 0) {
@@ -1655,6 +1689,24 @@ next_iter:
                        break;
        }
 
+       if (minext == NULL || state != GFS2_BLKST_FREE)
+               return -ENOSPC;
+
+       /* If the extent was too small, and it's smaller than the smallest
+          to have failed before, remember for future reference that it's
+          useless to search this rgrp again for this amount or more. */
+       if ((first_offset == 0) && (first_bii == 0) &&
+           (*minext < rbm->rgd->rd_extfail_pt))
+               rbm->rgd->rd_extfail_pt = *minext;
+
+       /* If the maximum extent we found is big enough to fulfill the
+          minimum requirements, use it anyway. */
+       if (maxext.len) {
+               *rbm = maxext.rbm;
+               *minext = maxext.len;
+               return 0;
+       }
+
        return -ENOSPC;
 }
 
@@ -1680,7 +1732,8 @@ static void try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, u64 skip
 
        while (1) {
                down_write(&sdp->sd_log_flush_lock);
-               error = gfs2_rbm_find(&rbm, GFS2_BLKST_UNLINKED, 0, NULL, true);
+               error = gfs2_rbm_find(&rbm, GFS2_BLKST_UNLINKED, NULL, NULL,
+                                     true, NULL);
                up_write(&sdp->sd_log_flush_lock);
                if (error == -ENOSPC)
                        break;
@@ -1891,7 +1944,9 @@ int gfs2_inplace_reserve(struct gfs2_inode *ip, const struct gfs2_alloc_parms *a
                }
 
                /* Skip unuseable resource groups */
-               if (rs->rs_rbm.rgd->rd_flags & (GFS2_RGF_NOALLOC | GFS2_RDF_ERROR))
+               if ((rs->rs_rbm.rgd->rd_flags & (GFS2_RGF_NOALLOC |
+                                                GFS2_RDF_ERROR)) ||
+                   (ap->target > rs->rs_rbm.rgd->rd_extfail_pt))
                        goto skip_rgrp;
 
                if (sdp->sd_args.ar_rgrplvb)
@@ -1911,15 +1966,16 @@ int gfs2_inplace_reserve(struct gfs2_inode *ip, const struct gfs2_alloc_parms *a
                        return 0;
                }
 
-               /* Drop reservation, if we couldn't use reserved rgrp */
-               if (gfs2_rs_active(rs))
-                       gfs2_rs_deltree(rs);
 check_rgrp:
                /* Check for unlinked inodes which can be reclaimed */
                if (rs->rs_rbm.rgd->rd_flags & GFS2_RDF_CHECK)
                        try_rgrp_unlink(rs->rs_rbm.rgd, &last_unlinked,
                                        ip->i_no_addr);
 skip_rgrp:
+               /* Drop reservation, if we couldn't use reserved rgrp */
+               if (gfs2_rs_active(rs))
+                       gfs2_rs_deltree(rs);
+
                /* Unlock rgrp if required */
                if (!rg_locked)
                        gfs2_glock_dq_uninit(&rs->rs_rgd_gh);
@@ -2072,10 +2128,10 @@ int gfs2_rgrp_dump(struct seq_file *seq, const struct gfs2_glock *gl)
 
        if (rgd == NULL)
                return 0;
-       gfs2_print_dbg(seq, " R: n:%llu f:%02x b:%u/%u i:%u r:%u\n",
+       gfs2_print_dbg(seq, " R: n:%llu f:%02x b:%u/%u i:%u r:%u e:%u\n",
                       (unsigned long long)rgd->rd_addr, rgd->rd_flags,
                       rgd->rd_free, rgd->rd_free_clone, rgd->rd_dinodes,
-                      rgd->rd_reserved);
+                      rgd->rd_reserved, rgd->rd_extfail_pt);
        spin_lock(&rgd->rd_rsspin);
        for (n = rb_first(&rgd->rd_rstree); n; n = rb_next(&trs->rs_node)) {
                trs = rb_entry(n, struct gfs2_blkreserv, rs_node);
@@ -2184,18 +2240,20 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks,
        int error;
 
        gfs2_set_alloc_start(&rbm, ip, dinode);
-       error = gfs2_rbm_find(&rbm, GFS2_BLKST_FREE, 0, ip, false);
+       error = gfs2_rbm_find(&rbm, GFS2_BLKST_FREE, NULL, ip, false, NULL);
 
        if (error == -ENOSPC) {
                gfs2_set_alloc_start(&rbm, ip, dinode);
-               error = gfs2_rbm_find(&rbm, GFS2_BLKST_FREE, 0, NULL, false);
+               error = gfs2_rbm_find(&rbm, GFS2_BLKST_FREE, NULL, NULL, false,
+                                     NULL);
        }
 
        /* Since all blocks are reserved in advance, this shouldn't happen */
        if (error) {
-               fs_warn(sdp, "inum=%llu error=%d, nblocks=%u, full=%d\n",
+               fs_warn(sdp, "inum=%llu error=%d, nblocks=%u, full=%d fail_pt=%d\n",
                        (unsigned long long)ip->i_no_addr, error, *nblocks,
-                       test_bit(GBF_FULL, &rbm.rgd->rd_bits->bi_flags));
+                       test_bit(GBF_FULL, &rbm.rgd->rd_bits->bi_flags),
+                       rbm.rgd->rd_extfail_pt);
                goto rgrp_error;
        }
 
index b51a6079108d1d4fa4a696b222a63c6634b0a36c..3f999649587ff8185ebd326c3672acee83542de4 100644 (file)
@@ -24,13 +24,6 @@ struct hfsplus_wd {
        u16 embed_count;
 };
 
-static void hfsplus_end_io_sync(struct bio *bio, int err)
-{
-       if (err)
-               clear_bit(BIO_UPTODATE, &bio->bi_flags);
-       complete(bio->bi_private);
-}
-
 /*
  * hfsplus_submit_bio - Perfrom block I/O
  * @sb: super block of volume for I/O
@@ -53,7 +46,6 @@ static void hfsplus_end_io_sync(struct bio *bio, int err)
 int hfsplus_submit_bio(struct super_block *sb, sector_t sector,
                void *buf, void **data, int rw)
 {
-       DECLARE_COMPLETION_ONSTACK(wait);
        struct bio *bio;
        int ret = 0;
        u64 io_size;
@@ -71,10 +63,8 @@ int hfsplus_submit_bio(struct super_block *sb, sector_t sector,
        sector &= ~((io_size >> HFSPLUS_SECTOR_SHIFT) - 1);
 
        bio = bio_alloc(GFP_NOIO, 1);
-       bio->bi_sector = sector;
+       bio->bi_iter.bi_sector = sector;
        bio->bi_bdev = sb->s_bdev;
-       bio->bi_end_io = hfsplus_end_io_sync;
-       bio->bi_private = &wait;
 
        if (!(rw & WRITE) && data)
                *data = (u8 *)buf + offset;
@@ -93,12 +83,7 @@ int hfsplus_submit_bio(struct super_block *sb, sector_t sector,
                buf = (u8 *)buf + len;
        }
 
-       submit_bio(rw, bio);
-       wait_for_completion(&wait);
-
-       if (!bio_flagged(bio, BIO_UPTODATE))
-               ret = -EIO;
-
+       ret = submit_bio_wait(rw, bio);
 out:
        bio_put(bio);
        return ret < 0 ? ret : 0;
index 52032647dd4a32f7c8efaea95227634071f8d7d3..5fa344afb49ae8642be889ce2b3f69d176af548e 100644 (file)
@@ -702,7 +702,7 @@ int jbd2_log_wait_commit(journal_t *journal, tid_t tid)
        read_lock(&journal->j_state_lock);
 #ifdef CONFIG_JBD2_DEBUG
        if (!tid_geq(journal->j_commit_request, tid)) {
-               printk(KERN_EMERG
+               printk(KERN_ERR
                       "%s: error: j_commit_request=%d, tid=%d\n",
                       __func__, journal->j_commit_request, tid);
        }
@@ -718,10 +718,8 @@ int jbd2_log_wait_commit(journal_t *journal, tid_t tid)
        }
        read_unlock(&journal->j_state_lock);
 
-       if (unlikely(is_journal_aborted(journal))) {
-               printk(KERN_EMERG "journal commit I/O error\n");
+       if (unlikely(is_journal_aborted(journal)))
                err = -EIO;
-       }
        return err;
 }
 
@@ -1527,13 +1525,13 @@ static int journal_get_superblock(journal_t *journal)
        if (JBD2_HAS_COMPAT_FEATURE(journal, JBD2_FEATURE_COMPAT_CHECKSUM) &&
            JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) {
                /* Can't have checksum v1 and v2 on at the same time! */
-               printk(KERN_ERR "JBD: Can't enable checksumming v1 and v2 "
+               printk(KERN_ERR "JBD2: Can't enable checksumming v1 and v2 "
                       "at the same time!\n");
                goto out;
        }
 
        if (!jbd2_verify_csum_type(journal, sb)) {
-               printk(KERN_ERR "JBD: Unknown checksum type\n");
+               printk(KERN_ERR "JBD2: Unknown checksum type\n");
                goto out;
        }
 
@@ -1541,7 +1539,7 @@ static int journal_get_superblock(journal_t *journal)
        if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) {
                journal->j_chksum_driver = crypto_alloc_shash("crc32c", 0, 0);
                if (IS_ERR(journal->j_chksum_driver)) {
-                       printk(KERN_ERR "JBD: Cannot load crc32c driver.\n");
+                       printk(KERN_ERR "JBD2: Cannot load crc32c driver.\n");
                        err = PTR_ERR(journal->j_chksum_driver);
                        journal->j_chksum_driver = NULL;
                        goto out;
@@ -1550,7 +1548,7 @@ static int journal_get_superblock(journal_t *journal)
 
        /* Check superblock checksum */
        if (!jbd2_superblock_csum_verify(journal, sb)) {
-               printk(KERN_ERR "JBD: journal checksum error\n");
+               printk(KERN_ERR "JBD2: journal checksum error\n");
                goto out;
        }
 
@@ -1836,7 +1834,7 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat,
                        journal->j_chksum_driver = crypto_alloc_shash("crc32c",
                                                                      0, 0);
                        if (IS_ERR(journal->j_chksum_driver)) {
-                               printk(KERN_ERR "JBD: Cannot load crc32c "
+                               printk(KERN_ERR "JBD2: Cannot load crc32c "
                                       "driver.\n");
                                journal->j_chksum_driver = NULL;
                                return 0;
@@ -2645,7 +2643,7 @@ static void __exit journal_exit(void)
 #ifdef CONFIG_JBD2_DEBUG
        int n = atomic_read(&nr_journal_heads);
        if (n)
-               printk(KERN_EMERG "JBD2: leaked %d journal_heads!\n", n);
+               printk(KERN_ERR "JBD2: leaked %d journal_heads!\n", n);
 #endif
        jbd2_remove_jbd_stats_proc_entry();
        jbd2_journal_destroy_caches();
index 3929c50428b1a289d4024fcbe673276f63ff97c0..3b6bb19d60b17abceadec4c38df5d3570c0fcba9 100644 (file)
@@ -594,7 +594,7 @@ static int do_one_pass(journal_t *journal,
                                                be32_to_cpu(tmp->h_sequence))) {
                                                brelse(obh);
                                                success = -EIO;
-                                               printk(KERN_ERR "JBD: Invalid "
+                                               printk(KERN_ERR "JBD2: Invalid "
                                                       "checksum recovering "
                                                       "block %llu in log\n",
                                                       blocknr);
index 7aa9a32573bba885d166e484c367bffc06bcd9e2..8360674c85bcb98af88d6aaff3ee4c46fe6f31bf 100644 (file)
@@ -932,7 +932,7 @@ repeat:
                                        jbd2_alloc(jh2bh(jh)->b_size,
                                                         GFP_NOFS);
                                if (!frozen_buffer) {
-                                       printk(KERN_EMERG
+                                       printk(KERN_ERR
                                               "%s: OOM for frozen_buffer\n",
                                               __func__);
                                        JBUFFER_TRACE(jh, "oom!");
@@ -1166,7 +1166,7 @@ repeat:
        if (!jh->b_committed_data) {
                committed_data = jbd2_alloc(jh2bh(jh)->b_size, GFP_NOFS);
                if (!committed_data) {
-                       printk(KERN_EMERG "%s: No memory for committed data\n",
+                       printk(KERN_ERR "%s: No memory for committed data\n",
                                __func__);
                        err = -ENOMEM;
                        goto out;
@@ -1290,7 +1290,10 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
                 * once a transaction -bzzz
                 */
                jh->b_modified = 1;
-               J_ASSERT_JH(jh, handle->h_buffer_credits > 0);
+               if (handle->h_buffer_credits <= 0) {
+                       ret = -ENOSPC;
+                       goto out_unlock_bh;
+               }
                handle->h_buffer_credits--;
        }
 
@@ -1305,7 +1308,7 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
                JBUFFER_TRACE(jh, "fastpath");
                if (unlikely(jh->b_transaction !=
                             journal->j_running_transaction)) {
-                       printk(KERN_EMERG "JBD: %s: "
+                       printk(KERN_ERR "JBD2: %s: "
                               "jh->b_transaction (%llu, %p, %u) != "
                               "journal->j_running_transaction (%p, %u)",
                               journal->j_devname,
@@ -1332,7 +1335,7 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
                JBUFFER_TRACE(jh, "already on other transaction");
                if (unlikely(jh->b_transaction !=
                             journal->j_committing_transaction)) {
-                       printk(KERN_EMERG "JBD: %s: "
+                       printk(KERN_ERR "JBD2: %s: "
                               "jh->b_transaction (%llu, %p, %u) != "
                               "journal->j_committing_transaction (%p, %u)",
                               journal->j_devname,
@@ -1345,7 +1348,7 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
                        ret = -EINVAL;
                }
                if (unlikely(jh->b_next_transaction != transaction)) {
-                       printk(KERN_EMERG "JBD: %s: "
+                       printk(KERN_ERR "JBD2: %s: "
                               "jh->b_next_transaction (%llu, %p, %u) != "
                               "transaction (%p, %u)",
                               journal->j_devname,
@@ -1373,7 +1376,6 @@ out_unlock_bh:
        jbd2_journal_put_journal_head(jh);
 out:
        JBUFFER_TRACE(jh, "exit");
-       WARN_ON(ret);   /* All errors are bugs, so dump the stack */
        return ret;
 }
 
index 4f47aa24b5562001cf8983d6c7634c373d50206b..b8fd651307a42e2fce3d15dfcc1976e2526932ab 100644 (file)
@@ -288,6 +288,8 @@ struct jffs2_xattr_datum *jffs2_alloc_xattr_datum(void)
        struct jffs2_xattr_datum *xd;
        xd = kmem_cache_zalloc(xattr_datum_cache, GFP_KERNEL);
        dbg_memalloc("%p\n", xd);
+       if (!xd)
+               return NULL;
 
        xd->class = RAWNODE_CLASS_XATTR_DATUM;
        xd->node = (void *)xd;
@@ -306,6 +308,8 @@ struct jffs2_xattr_ref *jffs2_alloc_xattr_ref(void)
        struct jffs2_xattr_ref *ref;
        ref = kmem_cache_zalloc(xattr_ref_cache, GFP_KERNEL);
        dbg_memalloc("%p\n", ref);
+       if (!ref)
+               return NULL;
 
        ref->class = RAWNODE_CLASS_XATTR_REF;
        ref->node = (void *)ref;
index 360d27c488873825fed5c04f8bb2320a51a39d62..8d811e02b4b92bb26d28367c727fcbe909fa95d5 100644 (file)
@@ -1998,20 +1998,20 @@ static int lbmRead(struct jfs_log * log, int pn, struct lbuf ** bpp)
 
        bio = bio_alloc(GFP_NOFS, 1);
 
-       bio->bi_sector = bp->l_blkno << (log->l2bsize - 9);
+       bio->bi_iter.bi_sector = bp->l_blkno << (log->l2bsize - 9);
        bio->bi_bdev = log->bdev;
        bio->bi_io_vec[0].bv_page = bp->l_page;
        bio->bi_io_vec[0].bv_len = LOGPSIZE;
        bio->bi_io_vec[0].bv_offset = bp->l_offset;
 
        bio->bi_vcnt = 1;
-       bio->bi_size = LOGPSIZE;
+       bio->bi_iter.bi_size = LOGPSIZE;
 
        bio->bi_end_io = lbmIODone;
        bio->bi_private = bp;
        /*check if journaling to disk has been disabled*/
        if (log->no_integrity) {
-               bio->bi_size = 0;
+               bio->bi_iter.bi_size = 0;
                lbmIODone(bio, 0);
        } else {
                submit_bio(READ_SYNC, bio);
@@ -2144,21 +2144,21 @@ static void lbmStartIO(struct lbuf * bp)
        jfs_info("lbmStartIO\n");
 
        bio = bio_alloc(GFP_NOFS, 1);
-       bio->bi_sector = bp->l_blkno << (log->l2bsize - 9);
+       bio->bi_iter.bi_sector = bp->l_blkno << (log->l2bsize - 9);
        bio->bi_bdev = log->bdev;
        bio->bi_io_vec[0].bv_page = bp->l_page;
        bio->bi_io_vec[0].bv_len = LOGPSIZE;
        bio->bi_io_vec[0].bv_offset = bp->l_offset;
 
        bio->bi_vcnt = 1;
-       bio->bi_size = LOGPSIZE;
+       bio->bi_iter.bi_size = LOGPSIZE;
 
        bio->bi_end_io = lbmIODone;
        bio->bi_private = bp;
 
        /* check if journaling to disk has been disabled */
        if (log->no_integrity) {
-               bio->bi_size = 0;
+               bio->bi_iter.bi_size = 0;
                lbmIODone(bio, 0);
        } else {
                submit_bio(WRITE_SYNC, bio);
index d165cde0c68dda885c2f5bb512f48465f521c4a1..49ba7ff1bbb9a15d8939128df2021354f2db6c52 100644 (file)
@@ -416,7 +416,7 @@ static int metapage_writepage(struct page *page, struct writeback_control *wbc)
                         * count from hitting zero before we're through
                         */
                        inc_io(page);
-                       if (!bio->bi_size)
+                       if (!bio->bi_iter.bi_size)
                                goto dump_bio;
                        submit_bio(WRITE, bio);
                        nr_underway++;
@@ -438,7 +438,7 @@ static int metapage_writepage(struct page *page, struct writeback_control *wbc)
 
                bio = bio_alloc(GFP_NOFS, 1);
                bio->bi_bdev = inode->i_sb->s_bdev;
-               bio->bi_sector = pblock << (inode->i_blkbits - 9);
+               bio->bi_iter.bi_sector = pblock << (inode->i_blkbits - 9);
                bio->bi_end_io = metapage_write_end_io;
                bio->bi_private = page;
 
@@ -452,7 +452,7 @@ static int metapage_writepage(struct page *page, struct writeback_control *wbc)
        if (bio) {
                if (bio_add_page(bio, page, bio_bytes, bio_offset) < bio_bytes)
                                goto add_failed;
-               if (!bio->bi_size)
+               if (!bio->bi_iter.bi_size)
                        goto dump_bio;
 
                submit_bio(WRITE, bio);
@@ -517,7 +517,8 @@ static int metapage_readpage(struct file *fp, struct page *page)
 
                        bio = bio_alloc(GFP_NOFS, 1);
                        bio->bi_bdev = inode->i_sb->s_bdev;
-                       bio->bi_sector = pblock << (inode->i_blkbits - 9);
+                       bio->bi_iter.bi_sector =
+                               pblock << (inode->i_blkbits - 9);
                        bio->bi_end_io = metapage_read_end_io;
                        bio->bi_private = page;
                        len = xlen << inode->i_blkbits;
index 550475ca6a0e0ec35c82d90b10372f2e4434fe90..76279e11982d854c9b22312cf51b3bd3a97e256d 100644 (file)
 
 #define PAGE_OFS(ofs) ((ofs) & (PAGE_SIZE-1))
 
-static void request_complete(struct bio *bio, int err)
-{
-       complete((struct completion *)bio->bi_private);
-}
-
 static int sync_request(struct page *page, struct block_device *bdev, int rw)
 {
        struct bio bio;
        struct bio_vec bio_vec;
-       struct completion complete;
 
        bio_init(&bio);
        bio.bi_max_vecs = 1;
@@ -32,16 +26,11 @@ static int sync_request(struct page *page, struct block_device *bdev, int rw)
        bio_vec.bv_len = PAGE_SIZE;
        bio_vec.bv_offset = 0;
        bio.bi_vcnt = 1;
-       bio.bi_size = PAGE_SIZE;
        bio.bi_bdev = bdev;
-       bio.bi_sector = page->index * (PAGE_SIZE >> 9);
-       init_completion(&complete);
-       bio.bi_private = &complete;
-       bio.bi_end_io = request_complete;
-
-       submit_bio(rw, &bio);
-       wait_for_completion(&complete);
-       return test_bit(BIO_UPTODATE, &bio.bi_flags) ? 0 : -EIO;
+       bio.bi_iter.bi_sector = page->index * (PAGE_SIZE >> 9);
+       bio.bi_iter.bi_size = PAGE_SIZE;
+
+       return submit_bio_wait(rw, &bio);
 }
 
 static int bdev_readpage(void *_sb, struct page *page)
@@ -67,22 +56,18 @@ static DECLARE_WAIT_QUEUE_HEAD(wq);
 static void writeseg_end_io(struct bio *bio, int err)
 {
        const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
-       struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
+       struct bio_vec *bvec;
+       int i;
        struct super_block *sb = bio->bi_private;
        struct logfs_super *super = logfs_super(sb);
-       struct page *page;
 
        BUG_ON(!uptodate); /* FIXME: Retry io or write elsewhere */
        BUG_ON(err);
-       BUG_ON(bio->bi_vcnt == 0);
-       do {
-               page = bvec->bv_page;
-               if (--bvec >= bio->bi_io_vec)
-                       prefetchw(&bvec->bv_page->flags);
-
-               end_page_writeback(page);
-               page_cache_release(page);
-       } while (bvec >= bio->bi_io_vec);
+
+       bio_for_each_segment_all(bvec, bio, i) {
+               end_page_writeback(bvec->bv_page);
+               page_cache_release(bvec->bv_page);
+       }
        bio_put(bio);
        if (atomic_dec_and_test(&super->s_pending_writes))
                wake_up(&wq);
@@ -107,9 +92,9 @@ static int __bdev_writeseg(struct super_block *sb, u64 ofs, pgoff_t index,
                if (i >= max_pages) {
                        /* Block layer cannot split bios :( */
                        bio->bi_vcnt = i;
-                       bio->bi_size = i * PAGE_SIZE;
+                       bio->bi_iter.bi_size = i * PAGE_SIZE;
                        bio->bi_bdev = super->s_bdev;
-                       bio->bi_sector = ofs >> 9;
+                       bio->bi_iter.bi_sector = ofs >> 9;
                        bio->bi_private = sb;
                        bio->bi_end_io = writeseg_end_io;
                        atomic_inc(&super->s_pending_writes);
@@ -134,9 +119,9 @@ static int __bdev_writeseg(struct super_block *sb, u64 ofs, pgoff_t index,
                unlock_page(page);
        }
        bio->bi_vcnt = nr_pages;
-       bio->bi_size = nr_pages * PAGE_SIZE;
+       bio->bi_iter.bi_size = nr_pages * PAGE_SIZE;
        bio->bi_bdev = super->s_bdev;
-       bio->bi_sector = ofs >> 9;
+       bio->bi_iter.bi_sector = ofs >> 9;
        bio->bi_private = sb;
        bio->bi_end_io = writeseg_end_io;
        atomic_inc(&super->s_pending_writes);
@@ -199,9 +184,9 @@ static int do_erase(struct super_block *sb, u64 ofs, pgoff_t index,
                if (i >= max_pages) {
                        /* Block layer cannot split bios :( */
                        bio->bi_vcnt = i;
-                       bio->bi_size = i * PAGE_SIZE;
+                       bio->bi_iter.bi_size = i * PAGE_SIZE;
                        bio->bi_bdev = super->s_bdev;
-                       bio->bi_sector = ofs >> 9;
+                       bio->bi_iter.bi_sector = ofs >> 9;
                        bio->bi_private = sb;
                        bio->bi_end_io = erase_end_io;
                        atomic_inc(&super->s_pending_writes);
@@ -220,9 +205,9 @@ static int do_erase(struct super_block *sb, u64 ofs, pgoff_t index,
                bio->bi_io_vec[i].bv_offset = 0;
        }
        bio->bi_vcnt = nr_pages;
-       bio->bi_size = nr_pages * PAGE_SIZE;
+       bio->bi_iter.bi_size = nr_pages * PAGE_SIZE;
        bio->bi_bdev = super->s_bdev;
-       bio->bi_sector = ofs >> 9;
+       bio->bi_iter.bi_sector = ofs >> 9;
        bio->bi_private = sb;
        bio->bi_end_io = erase_end_io;
        atomic_inc(&super->s_pending_writes);
index 9c501449450dc9be6891e5d9c1a035ca31b5687b..427bb73e298f197d4cfc73b17baeffdd1c848c5d 100644 (file)
@@ -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;
 }
 
index 54360293bcb5cd0680c3042e6f0b9b87e342c649..b256c0690e5b66f5b16a2b81be033cc3b345dec6 100644 (file)
@@ -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);
index 0face1c4d4c6bd4ea33cb60e45b8c7fad8235acf..4979ffa60aaabfd36839adec6feafcb17a876d98 100644 (file)
  */
 static void mpage_end_io(struct bio *bio, int err)
 {
-       const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
-       struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
+       struct bio_vec *bv;
+       int i;
 
-       do {
-               struct page *page = bvec->bv_page;
+       bio_for_each_segment_all(bv, bio, i) {
+               struct page *page = bv->bv_page;
 
-               if (--bvec >= bio->bi_io_vec)
-                       prefetchw(&bvec->bv_page->flags);
                if (bio_data_dir(bio) == READ) {
-                       if (uptodate) {
+                       if (!err) {
                                SetPageUptodate(page);
                        } else {
                                ClearPageUptodate(page);
@@ -60,14 +58,15 @@ static void mpage_end_io(struct bio *bio, int err)
                        }
                        unlock_page(page);
                } else { /* bio_data_dir(bio) == WRITE */
-                       if (!uptodate) {
+                       if (err) {
                                SetPageError(page);
                                if (page->mapping)
                                        set_bit(AS_EIO, &page->mapping->flags);
                        }
                        end_page_writeback(page);
                }
-       } while (bvec >= bio->bi_io_vec);
+       }
+
        bio_put(bio);
 }
 
@@ -94,7 +93,7 @@ mpage_alloc(struct block_device *bdev,
 
        if (bio) {
                bio->bi_bdev = bdev;
-               bio->bi_sector = first_sector;
+               bio->bi_iter.bi_sector = first_sector;
        }
        return bio;
 }
index e242bbf729723d1d45ae0cac7370952167b026cd..56ff823ca82e0979f08355f80aaf75ae4a019393 100644 (file)
@@ -134,8 +134,8 @@ bl_submit_bio(int rw, struct bio *bio)
        if (bio) {
                get_parallel(bio->bi_private);
                dprintk("%s submitting %s bio %u@%llu\n", __func__,
-                       rw == READ ? "read" : "write",
-                       bio->bi_size, (unsigned long long)bio->bi_sector);
+                       rw == READ ? "read" : "write", bio->bi_iter.bi_size,
+                       (unsigned long long)bio->bi_iter.bi_sector);
                submit_bio(rw, bio);
        }
        return NULL;
@@ -156,7 +156,8 @@ static struct bio *bl_alloc_init_bio(int npg, sector_t isect,
        }
 
        if (bio) {
-               bio->bi_sector = isect - be->be_f_offset + be->be_v_offset;
+               bio->bi_iter.bi_sector = isect - be->be_f_offset +
+                       be->be_v_offset;
                bio->bi_bdev = be->be_mdev;
                bio->bi_end_io = end_io;
                bio->bi_private = par;
@@ -201,18 +202,14 @@ static struct bio *bl_add_page_to_bio(struct bio *bio, int npg, int rw,
 static void bl_end_io_read(struct bio *bio, int err)
 {
        struct parallel_io *par = bio->bi_private;
-       const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
-       struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
+       struct bio_vec *bvec;
+       int i;
 
-       do {
-               struct page *page = bvec->bv_page;
+       if (!err)
+               bio_for_each_segment_all(bvec, bio, i)
+                       SetPageUptodate(bvec->bv_page);
 
-               if (--bvec >= bio->bi_io_vec)
-                       prefetchw(&bvec->bv_page->flags);
-               if (uptodate)
-                       SetPageUptodate(page);
-       } while (bvec >= bio->bi_io_vec);
-       if (!uptodate) {
+       if (err) {
                struct nfs_read_data *rdata = par->data;
                struct nfs_pgio_header *header = rdata->header;
 
@@ -383,20 +380,16 @@ static void mark_extents_written(struct pnfs_block_layout *bl,
 static void bl_end_io_write_zero(struct bio *bio, int err)
 {
        struct parallel_io *par = bio->bi_private;
-       const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
-       struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
-
-       do {
-               struct page *page = bvec->bv_page;
+       struct bio_vec *bvec;
+       int i;
 
-               if (--bvec >= bio->bi_io_vec)
-                       prefetchw(&bvec->bv_page->flags);
+       bio_for_each_segment_all(bvec, bio, i) {
                /* This is the zeroing page we added */
-               end_page_writeback(page);
-               page_cache_release(page);
-       } while (bvec >= bio->bi_io_vec);
+               end_page_writeback(bvec->bv_page);
+               page_cache_release(bvec->bv_page);
+       }
 
-       if (unlikely(!uptodate)) {
+       if (unlikely(err)) {
                struct nfs_write_data *data = par->data;
                struct nfs_pgio_header *header = data->header;
 
@@ -519,7 +512,7 @@ bl_do_readpage_sync(struct page *page, struct pnfs_block_extent *be,
        isect = (page->index << PAGE_CACHE_SECTOR_SHIFT) +
                (offset / SECTOR_SIZE);
 
-       bio->bi_sector = isect - be->be_f_offset + be->be_v_offset;
+       bio->bi_iter.bi_sector = isect - be->be_f_offset + be->be_v_offset;
        bio->bi_bdev = be->be_mdev;
        bio->bi_end_io = bl_read_single_end_io;
 
index 8485978993e85bcbda9772b55a2ed26f5442a228..9838fb020473c935817b34da4a1127b4c75af3fe 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/nfs_fs.h>
 #include <linux/sunrpc/rpc_pipe_fs.h>
 
+#include "../nfs4_fs.h"
 #include "../pnfs.h"
 #include "../netns.h"
 
index 9c3e117c3ed1f04c5dd1650f70a3aa4ca2fd7d8c..4d01614425658adade20f579ec7f10e44c5d5a15 100644 (file)
@@ -44,7 +44,7 @@
 static inline sector_t normalize(sector_t s, int base)
 {
        sector_t tmp = s; /* Since do_div modifies its argument */
-       return s - do_div(tmp, base);
+       return s - sector_div(tmp, base);
 }
 
 static inline sector_t normalize_up(sector_t s, int base)
index fc0f95ec73587f9fbcfa7fca24438da29012b5b9..d25f10fb4926b09dc39ac3f6f62a433d4bcdc58b 100644 (file)
@@ -46,7 +46,9 @@ ssize_t nfs_dns_resolve_name(struct net *net, char *name, size_t namelen,
 #include <linux/sunrpc/cache.h>
 #include <linux/sunrpc/svcauth.h>
 #include <linux/sunrpc/rpc_pipe_fs.h>
+#include <linux/nfs_fs.h>
 
+#include "nfs4_fs.h"
 #include "dns_resolve.h"
 #include "cache_lib.h"
 #include "netns.h"
index 18ab2da4eeb65dbf7c8f7d7b578a35fc5251b0b6..00ad1c2b217ded2338c0ac4154681f83963581ab 100644 (file)
@@ -312,7 +312,7 @@ struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags)
 }
 EXPORT_SYMBOL_GPL(nfs4_label_alloc);
 #else
-void inline nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr,
+void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr,
                                        struct nfs4_label *label)
 {
 }
index bca6a3e3c49ce58e9cdfa1552e25afce2158584e..8b5cc04a86115e05f0a2e98e9b02a0b307b1b910 100644 (file)
@@ -269,6 +269,21 @@ extern const u32 nfs41_maxgetdevinfo_overhead;
 extern struct rpc_procinfo nfs4_procedures[];
 #endif
 
+#ifdef CONFIG_NFS_V4_SECURITY_LABEL
+extern struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags);
+static inline void nfs4_label_free(struct nfs4_label *label)
+{
+       if (label) {
+               kfree(label->label);
+               kfree(label);
+       }
+       return;
+}
+#else
+static inline struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags) { return NULL; }
+static inline void nfs4_label_free(void *label) {}
+#endif /* CONFIG_NFS_V4_SECURITY_LABEL */
+
 /* proc.c */
 void nfs_close_context(struct nfs_open_context *ctx, int is_sync);
 extern struct nfs_client *nfs_init_client(struct nfs_client *clp,
index 3ce79b04522eb19b2ecee294c3a59a2b0c49b4b9..5609edc742a0fc42568c73e7d26b4c2feb336c33 100644 (file)
@@ -9,6 +9,14 @@
 #ifndef __LINUX_FS_NFS_NFS4_FS_H
 #define __LINUX_FS_NFS_NFS4_FS_H
 
+#if defined(CONFIG_NFS_V4_2)
+#define NFS4_MAX_MINOR_VERSION 2
+#elif defined(CONFIG_NFS_V4_1)
+#define NFS4_MAX_MINOR_VERSION 1
+#else
+#define NFS4_MAX_MINOR_VERSION 0
+#endif
+
 #if IS_ENABLED(CONFIG_NFS_V4)
 
 #define NFS4_MAX_LOOP_ON_RECOVER (10)
index b4a160a405ce2b60f64255433c1555a4284c61e9..c1b7a80b6704850bde97a9573d8dcde01c813366 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/sunrpc/auth.h>
 #include <linux/sunrpc/xprt.h>
 #include <linux/sunrpc/bc_xprt.h>
+#include <linux/sunrpc/rpc_pipe_fs.h>
 #include "internal.h"
 #include "callback.h"
 #include "delegation.h"
@@ -370,7 +371,11 @@ struct nfs_client *nfs4_init_client(struct nfs_client *clp,
                __set_bit(NFS_CS_INFINITE_SLOTS, &clp->cl_flags);
        __set_bit(NFS_CS_DISCRTRY, &clp->cl_flags);
        __set_bit(NFS_CS_NO_RETRANS_TIMEOUT, &clp->cl_flags);
-       error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_GSS_KRB5I);
+
+       error = -EINVAL;
+       if (gssd_running(clp->cl_net))
+               error = nfs_create_rpc_client(clp, timeparms,
+                                             RPC_AUTH_GSS_KRB5I);
        if (error == -EINVAL)
                error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_UNIX);
        if (error < 0)
index 659990c0109e3173298b92385d585be566e161de..15052b81df4245e4f797adb0d0b2e523338b23cc 100644 (file)
@@ -2518,9 +2518,8 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
                                                     calldata->roc_barrier);
                        nfs_set_open_stateid(state, &calldata->res.stateid, 0);
                        renew_lease(server, calldata->timestamp);
-                       nfs4_close_clear_stateid_flags(state,
-                                       calldata->arg.fmode);
                        break;
+               case -NFS4ERR_ADMIN_REVOKED:
                case -NFS4ERR_STALE_STATEID:
                case -NFS4ERR_OLD_STATEID:
                case -NFS4ERR_BAD_STATEID:
@@ -2528,9 +2527,13 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
                        if (calldata->arg.fmode == 0)
                                break;
                default:
-                       if (nfs4_async_handle_error(task, server, state) == -EAGAIN)
+                       if (nfs4_async_handle_error(task, server, state) == -EAGAIN) {
                                rpc_restart_call_prepare(task);
+                               goto out_release;
+                       }
        }
+       nfs4_close_clear_stateid_flags(state, calldata->arg.fmode);
+out_release:
        nfs_release_seqid(calldata->arg.seqid);
        nfs_refresh_inode(calldata->inode, calldata->res.fattr);
        dprintk("%s: done, ret = %d!\n", __func__, task->tk_status);
@@ -4802,7 +4805,7 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
                        dprintk("%s ERROR %d, Reset session\n", __func__,
                                task->tk_status);
                        nfs4_schedule_session_recovery(clp->cl_session, task->tk_status);
-                       goto restart_call;
+                       goto wait_on_recovery;
 #endif /* CONFIG_NFS_V4_1 */
                case -NFS4ERR_DELAY:
                        nfs_inc_server_stats(server, NFSIOS_DELAY);
@@ -4987,11 +4990,17 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
 
        trace_nfs4_delegreturn_exit(&data->args, &data->res, task->tk_status);
        switch (task->tk_status) {
-       case -NFS4ERR_STALE_STATEID:
-       case -NFS4ERR_EXPIRED:
        case 0:
                renew_lease(data->res.server, data->timestamp);
                break;
+       case -NFS4ERR_ADMIN_REVOKED:
+       case -NFS4ERR_DELEG_REVOKED:
+       case -NFS4ERR_BAD_STATEID:
+       case -NFS4ERR_OLD_STATEID:
+       case -NFS4ERR_STALE_STATEID:
+       case -NFS4ERR_EXPIRED:
+               task->tk_status = 0;
+               break;
        default:
                if (nfs4_async_handle_error(task, data->res.server, NULL) ==
                                -EAGAIN) {
@@ -7589,7 +7598,14 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
                return;
 
        server = NFS_SERVER(lrp->args.inode);
-       if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) {
+       switch (task->tk_status) {
+       default:
+               task->tk_status = 0;
+       case 0:
+               break;
+       case -NFS4ERR_DELAY:
+               if (nfs4_async_handle_error(task, server, NULL) != -EAGAIN)
+                       break;
                rpc_restart_call_prepare(task);
                return;
        }
index 5be2868c02f15e63c33eaea848f077e1e7b3d889..8c21d69a9dc114c8781dc8ae3171f17f67fb4a8d 100644 (file)
@@ -3097,7 +3097,8 @@ out_overflow:
        return -EIO;
 }
 
-static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected)
+static bool __decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected,
+               int *nfs_retval)
 {
        __be32 *p;
        uint32_t opnum;
@@ -3107,19 +3108,32 @@ static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected)
        if (unlikely(!p))
                goto out_overflow;
        opnum = be32_to_cpup(p++);
-       if (opnum != expected) {
-               dprintk("nfs: Server returned operation"
-                       " %d but we issued a request for %d\n",
-                               opnum, expected);
-               return -EIO;
-       }
+       if (unlikely(opnum != expected))
+               goto out_bad_operation;
        nfserr = be32_to_cpup(p);
-       if (nfserr != NFS_OK)
-               return nfs4_stat_to_errno(nfserr);
-       return 0;
+       if (nfserr == NFS_OK)
+               *nfs_retval = 0;
+       else
+               *nfs_retval = nfs4_stat_to_errno(nfserr);
+       return true;
+out_bad_operation:
+       dprintk("nfs: Server returned operation"
+               " %d but we issued a request for %d\n",
+                       opnum, expected);
+       *nfs_retval = -EREMOTEIO;
+       return false;
 out_overflow:
        print_overflow_msg(__func__, xdr);
-       return -EIO;
+       *nfs_retval = -EIO;
+       return false;
+}
+
+static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected)
+{
+       int retval;
+
+       __decode_op_hdr(xdr, expected, &retval);
+       return retval;
 }
 
 /* Dummy routine */
@@ -5001,11 +5015,12 @@ static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
        uint32_t savewords, bmlen, i;
        int status;
 
-       status = decode_op_hdr(xdr, OP_OPEN);
-       if (status != -EIO)
-               nfs_increment_open_seqid(status, res->seqid);
-       if (!status)
-               status = decode_stateid(xdr, &res->stateid);
+       if (!__decode_op_hdr(xdr, OP_OPEN, &status))
+               return status;
+       nfs_increment_open_seqid(status, res->seqid);
+       if (status)
+               return status;
+       status = decode_stateid(xdr, &res->stateid);
        if (unlikely(status))
                return status;
 
index 14d9ecb96cff0ba476549467fbc321f94ea55ff3..1ee6baec5fa167961583737028cefd9e797fcc7f 100644 (file)
@@ -168,7 +168,7 @@ encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
              struct kstat *stat)
 {
        *p++ = htonl(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]);
-       *p++ = htonl((u32) stat->mode);
+       *p++ = htonl((u32) (stat->mode & S_IALLUGO));
        *p++ = htonl((u32) stat->nlink);
        *p++ = htonl((u32) from_kuid(&init_user_ns, stat->uid));
        *p++ = htonl((u32) from_kgid(&init_user_ns, stat->gid));
index ee7237f99f54cd413dba6375dbc344084d0ece56..79754139ccdf51a6775aa9d5ee227dad675ff9e0 100644 (file)
@@ -190,6 +190,15 @@ static int zero_clientid(clientid_t *clid)
        return (clid->cl_boot == 0) && (clid->cl_id == 0);
 }
 
+/**
+ * defer_free - mark an allocation as deferred freed
+ * @argp: NFSv4 compound argument structure to be freed with
+ * @release: release callback to free @p, typically kfree()
+ * @p: pointer to be freed
+ *
+ * Marks @p to be freed when processing the compound operation
+ * described in @argp finishes.
+ */
 static int
 defer_free(struct nfsd4_compoundargs *argp,
                void (*release)(const void *), void *p)
@@ -206,6 +215,16 @@ defer_free(struct nfsd4_compoundargs *argp,
        return 0;
 }
 
+/**
+ * savemem - duplicate a chunk of memory for later processing
+ * @argp: NFSv4 compound argument structure to be freed with
+ * @p: pointer to be duplicated
+ * @nbytes: length to be duplicated
+ *
+ * Returns a pointer to a copy of @nbytes bytes of memory at @p
+ * that are preserved until processing of the NFSv4 compound
+ * operation described by @argp finishes.
+ */
 static char *savemem(struct nfsd4_compoundargs *argp, __be32 *p, int nbytes)
 {
        if (p == argp->tmp) {
index 9186c7ce0b141b187a8b127a6608005a05ad53d1..f8f060ffbf4f173888db46dc0c000ce8c1ea34c6 100644 (file)
@@ -409,22 +409,8 @@ nfsd_cache_lookup(struct svc_rqst *rqstp)
 
        /*
         * Since the common case is a cache miss followed by an insert,
-        * preallocate an entry. First, try to reuse the first entry on the LRU
-        * if it works, then go ahead and prune the LRU list.
+        * preallocate an entry.
         */
-       spin_lock(&cache_lock);
-       if (!list_empty(&lru_head)) {
-               rp = list_first_entry(&lru_head, struct svc_cacherep, c_lru);
-               if (nfsd_cache_entry_expired(rp) ||
-                   num_drc_entries >= max_drc_entries) {
-                       lru_put_end(rp);
-                       prune_cache_entries();
-                       goto search_cache;
-               }
-       }
-
-       /* No expired ones available, allocate a new one. */
-       spin_unlock(&cache_lock);
        rp = nfsd_reply_cache_alloc();
        spin_lock(&cache_lock);
        if (likely(rp)) {
@@ -432,7 +418,9 @@ nfsd_cache_lookup(struct svc_rqst *rqstp)
                drc_mem_usage += sizeof(*rp);
        }
 
-search_cache:
+       /* go ahead and prune the cache */
+       prune_cache_entries();
+
        found = nfsd_cache_search(rqstp, csum);
        if (found) {
                if (likely(rp))
@@ -446,15 +434,6 @@ search_cache:
                goto out;
        }
 
-       /*
-        * We're keeping the one we just allocated. Are we now over the
-        * limit? Prune one off the tip of the LRU in trade for the one we
-        * just allocated if so.
-        */
-       if (num_drc_entries >= max_drc_entries)
-               nfsd_reply_cache_free_locked(list_first_entry(&lru_head,
-                                               struct svc_cacherep, c_lru));
-
        nfsdstats.rcmisses++;
        rqstp->rq_cacherep = rp;
        rp->c_state = RC_INPROG;
index 9c769a47ac5ab7efc9a2b939305ffbad45ed988f..b17d93214d0153b426282b1f23e3414768fb6ca0 100644 (file)
@@ -152,7 +152,7 @@ encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
        type = (stat->mode & S_IFMT);
 
        *p++ = htonl(nfs_ftypes[type >> 12]);
-       *p++ = htonl((u32) stat->mode);
+       *p++ = htonl((u32) (stat->mode & S_IALLUGO));
        *p++ = htonl((u32) stat->nlink);
        *p++ = htonl((u32) from_kuid(&init_user_ns, stat->uid));
        *p++ = htonl((u32) from_kgid(&init_user_ns, stat->gid));
index 2d8be51f90dc9257bf74cad77b719d17f781c739..dc3a9efdaab87751e47edcf9ef3a807fed4573db 100644 (file)
@@ -416,7 +416,8 @@ static struct bio *nilfs_alloc_seg_bio(struct the_nilfs *nilfs, sector_t start,
        }
        if (likely(bio)) {
                bio->bi_bdev = nilfs->ns_bdev;
-               bio->bi_sector = start << (nilfs->ns_blocksize_bits - 9);
+               bio->bi_iter.bi_sector =
+                       start << (nilfs->ns_blocksize_bits - 9);
        }
        return bio;
 }
index 73920ffda05b331c85ef1760d97083d1590a4a16..bf482dfed14fecf17406a6aa2d517929d6834800 100644 (file)
@@ -413,7 +413,7 @@ static struct bio *o2hb_setup_one_bio(struct o2hb_region *reg,
        }
 
        /* Must put everything in 512 byte sectors for the bio... */
-       bio->bi_sector = (reg->hr_start_block + cs) << (bits - 9);
+       bio->bi_iter.bi_sector = (reg->hr_start_block + cs) << (bits - 9);
        bio->bi_bdev = reg->hr_bdev;
        bio->bi_private = wc;
        bio->bi_end_io = o2hb_bio_end_io;
index d2c45e14e6d8126e41bc6c463a509e68946e9fa4..0e0752ef27159f6183dabc1749e49fca8494319a 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -726,11 +726,25 @@ pipe_poll(struct file *filp, poll_table *wait)
        return mask;
 }
 
+static void put_pipe_info(struct inode *inode, struct pipe_inode_info *pipe)
+{
+       int kill = 0;
+
+       spin_lock(&inode->i_lock);
+       if (!--pipe->files) {
+               inode->i_pipe = NULL;
+               kill = 1;
+       }
+       spin_unlock(&inode->i_lock);
+
+       if (kill)
+               free_pipe_info(pipe);
+}
+
 static int
 pipe_release(struct inode *inode, struct file *file)
 {
-       struct pipe_inode_info *pipe = inode->i_pipe;
-       int kill = 0;
+       struct pipe_inode_info *pipe = file->private_data;
 
        __pipe_lock(pipe);
        if (file->f_mode & FMODE_READ)
@@ -743,17 +757,9 @@ pipe_release(struct inode *inode, struct file *file)
                kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
                kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
        }
-       spin_lock(&inode->i_lock);
-       if (!--pipe->files) {
-               inode->i_pipe = NULL;
-               kill = 1;
-       }
-       spin_unlock(&inode->i_lock);
        __pipe_unlock(pipe);
 
-       if (kill)
-               free_pipe_info(pipe);
-
+       put_pipe_info(inode, pipe);
        return 0;
 }
 
@@ -1014,7 +1020,6 @@ static int fifo_open(struct inode *inode, struct file *filp)
 {
        struct pipe_inode_info *pipe;
        bool is_pipe = inode->i_sb->s_magic == PIPEFS_MAGIC;
-       int kill = 0;
        int ret;
 
        filp->f_version = 0;
@@ -1130,15 +1135,9 @@ err_wr:
        goto err;
 
 err:
-       spin_lock(&inode->i_lock);
-       if (!--pipe->files) {
-               inode->i_pipe = NULL;
-               kill = 1;
-       }
-       spin_unlock(&inode->i_lock);
        __pipe_unlock(pipe);
-       if (kill)
-               free_pipe_info(pipe);
+
+       put_pipe_info(inode, pipe);
        return ret;
 }
 
index 2943b2bfae482ac83d352f317af4c074ce6597ae..62a0de6632e1aa3c8de599e19db3f8d7e2a383e2 100644 (file)
@@ -84,6 +84,9 @@ int squashfs_readpage_block(struct page *target_page, u64 block, int bsize)
                 */
                res = squashfs_read_cache(target_page, block, bsize, pages,
                                                                page);
+               if (res < 0)
+                       goto mark_errored;
+
                goto out;
        }
 
@@ -119,7 +122,7 @@ mark_errored:
         * dealt with by the caller
         */
        for (i = 0; i < pages; i++) {
-               if (page[i] == target_page)
+               if (page[i] == NULL || page[i] == target_page)
                        continue;
                flush_dcache_page(page[i]);
                SetPageError(page[i]);
index b94f93685093edb4f2d189238989d3024fffa246..35e7d08fe629dfcb79553bcdcdf39af03b5e4960 100644 (file)
@@ -609,7 +609,7 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
        struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
        struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
        struct sysfs_open_file *of;
-       bool has_read, has_write, has_mmap;
+       bool has_read, has_write;
        int error = -EACCES;
 
        /* need attr_sd for attr and ops, its parent for kobj */
@@ -621,7 +621,6 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
 
                has_read = battr->read || battr->mmap;
                has_write = battr->write || battr->mmap;
-               has_mmap = battr->mmap;
        } else {
                const struct sysfs_ops *ops = sysfs_file_ops(attr_sd);
 
@@ -633,7 +632,6 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
 
                has_read = ops->show;
                has_write = ops->store;
-               has_mmap = false;
        }
 
        /* check perms and supported operations */
@@ -661,9 +659,9 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
         * open file has a separate mutex, it's okay as long as those don't
         * happen on the same file.  At this point, we can't easily give
         * each file a separate locking class.  Let's differentiate on
-        * whether the file has mmap or not for now.
+        * whether the file is bin or not for now.
         */
-       if (has_mmap)
+       if (sysfs_is_bin(attr_sd))
                mutex_init(&of->mutex);
        else
                mutex_init(&of->mutex);
index 71c8c9d2b8826a0ed22d886fb3327d2ff0784fc3..1b19b9cd692ad8ff4d73259f7353b1e6a86477ad 100644 (file)
@@ -407,7 +407,7 @@ xfs_alloc_ioend_bio(
        struct bio              *bio = bio_alloc(GFP_NOIO, nvecs);
 
        ASSERT(bio->bi_private == NULL);
-       bio->bi_sector = bh->b_blocknr * (bh->b_size >> 9);
+       bio->bi_iter.bi_sector = bh->b_blocknr * (bh->b_size >> 9);
        bio->bi_bdev = bh->b_bdev;
        return bio;
 }
index 3ef11b22e7505c380feb6597113d5b150f7b1afb..8401f11f378f989ea2a2ed70a9f744b8b89ced69 100644 (file)
@@ -1635,7 +1635,7 @@ xfs_bmap_last_extent(
  * blocks at the end of the file which do not start at the previous data block,
  * we will try to align the new blocks at stripe unit boundaries.
  *
- * Returns 0 in bma->aeof if the file (fork) is empty as any new write will be
+ * Returns 1 in bma->aeof if the file (fork) is empty as any new write will be
  * at, or past the EOF.
  */
 STATIC int
@@ -1650,9 +1650,14 @@ xfs_bmap_isaeof(
        bma->aeof = 0;
        error = xfs_bmap_last_extent(NULL, bma->ip, whichfork, &rec,
                                     &is_empty);
-       if (error || is_empty)
+       if (error)
                return error;
 
+       if (is_empty) {
+               bma->aeof = 1;
+               return 0;
+       }
+
        /*
         * Check if we are allocation or past the last extent, or at least into
         * the last delayed allocated extent.
index c7f0b77dcb0090046b84eda27c68d870af25d45a..dc17c89128ba70082e852303430f4ad9c9512c0a 100644 (file)
@@ -1255,7 +1255,7 @@ next_chunk:
 
        bio = bio_alloc(GFP_NOIO, nr_pages);
        bio->bi_bdev = bp->b_target->bt_bdev;
-       bio->bi_sector = sector;
+       bio->bi_iter.bi_sector = sector;
        bio->bi_end_io = xfs_buf_bio_end_io;
        bio->bi_private = bp;
 
@@ -1277,7 +1277,7 @@ next_chunk:
                total_nr_pages--;
        }
 
-       if (likely(bio->bi_size)) {
+       if (likely(bio->bi_iter.bi_size)) {
                if (xfs_buf_is_vmapped(bp)) {
                        flush_kernel_vmap_range(bp->b_addr,
                                                xfs_buf_vmap_len(bp));
@@ -1602,12 +1602,11 @@ xfs_free_buftarg(
        kmem_free(btp);
 }
 
-STATIC int
-xfs_setsize_buftarg_flags(
+int
+xfs_setsize_buftarg(
        xfs_buftarg_t           *btp,
        unsigned int            blocksize,
-       unsigned int            sectorsize,
-       int                     verbose)
+       unsigned int            sectorsize)
 {
        btp->bt_bsize = blocksize;
        btp->bt_sshift = ffs(sectorsize) - 1;
@@ -1628,26 +1627,17 @@ xfs_setsize_buftarg_flags(
 }
 
 /*
- *     When allocating the initial buffer target we have not yet
- *     read in the superblock, so don't know what sized sectors
- *     are being used at this early stage.  Play safe.
+ * When allocating the initial buffer target we have not yet
+ * read in the superblock, so don't know what sized sectors
+ * are being used at this early stage.  Play safe.
  */
 STATIC int
 xfs_setsize_buftarg_early(
        xfs_buftarg_t           *btp,
        struct block_device     *bdev)
 {
-       return xfs_setsize_buftarg_flags(btp,
-                       PAGE_SIZE, bdev_logical_block_size(bdev), 0);
-}
-
-int
-xfs_setsize_buftarg(
-       xfs_buftarg_t           *btp,
-       unsigned int            blocksize,
-       unsigned int            sectorsize)
-{
-       return xfs_setsize_buftarg_flags(btp, blocksize, sectorsize, 1);
+       return xfs_setsize_buftarg(btp, PAGE_SIZE,
+                                  bdev_logical_block_size(bdev));
 }
 
 xfs_buftarg_t *
index 56369d4509d5603cff44adeb17902324a547f48b..48c7d18f68c3fb23a89a31a955fc9250fbd63108 100644 (file)
@@ -2067,12 +2067,12 @@ xfs_dir2_node_lookup(
  */
 int                                            /* error */
 xfs_dir2_node_removename(
-       xfs_da_args_t           *args)          /* operation arguments */
+       struct xfs_da_args      *args)          /* operation arguments */
 {
-       xfs_da_state_blk_t      *blk;           /* leaf block */
+       struct xfs_da_state_blk *blk;           /* leaf block */
        int                     error;          /* error return value */
        int                     rval;           /* operation return value */
-       xfs_da_state_t          *state;         /* btree cursor */
+       struct xfs_da_state     *state;         /* btree cursor */
 
        trace_xfs_dir2_node_removename(args);
 
@@ -2084,19 +2084,18 @@ xfs_dir2_node_removename(
        state->mp = args->dp->i_mount;
        state->blocksize = state->mp->m_dirblksize;
        state->node_ents = state->mp->m_dir_node_ents;
-       /*
-        * Look up the entry we're deleting, set up the cursor.
-        */
+
+       /* Look up the entry we're deleting, set up the cursor. */
        error = xfs_da3_node_lookup_int(state, &rval);
        if (error)
-               rval = error;
-       /*
-        * Didn't find it, upper layer screwed up.
-        */
+               goto out_free;
+
+       /* Didn't find it, upper layer screwed up. */
        if (rval != EEXIST) {
-               xfs_da_state_free(state);
-               return rval;
+               error = rval;
+               goto out_free;
        }
+
        blk = &state->path.blk[state->path.active - 1];
        ASSERT(blk->magic == XFS_DIR2_LEAFN_MAGIC);
        ASSERT(state->extravalid);
@@ -2107,7 +2106,7 @@ xfs_dir2_node_removename(
        error = xfs_dir2_leafn_remove(args, blk->bp, blk->index,
                &state->extrablk, &rval);
        if (error)
-               return error;
+               goto out_free;
        /*
         * Fix the hash values up the btree.
         */
@@ -2122,6 +2121,7 @@ xfs_dir2_node_removename(
         */
        if (!error)
                error = xfs_dir2_node_to_leaf(state);
+out_free:
        xfs_da_state_free(state);
        return error;
 }
index aafc6e46cb5803620998399bea5da520aa720f83..3725fb1b902b8becf5f594524fd8143026aee03e 100644 (file)
@@ -170,6 +170,7 @@ xfs_dir2_block_to_sf(
        char                    *ptr;           /* current data pointer */
        xfs_dir2_sf_entry_t     *sfep;          /* shortform entry */
        xfs_dir2_sf_hdr_t       *sfp;           /* shortform directory header */
+       xfs_dir2_sf_hdr_t       *dst;           /* temporary data buffer */
 
        trace_xfs_dir2_block_to_sf(args);
 
@@ -177,35 +178,20 @@ xfs_dir2_block_to_sf(
        mp = dp->i_mount;
 
        /*
-        * Make a copy of the block data, so we can shrink the inode
-        * and add local data.
+        * allocate a temporary destination buffer the size of the inode
+        * to format the data into. Once we have formatted the data, we
+        * can free the block and copy the formatted data into the inode literal
+        * area.
         */
-       hdr = kmem_alloc(mp->m_dirblksize, KM_SLEEP);
-       memcpy(hdr, bp->b_addr, mp->m_dirblksize);
-       logflags = XFS_ILOG_CORE;
-       if ((error = xfs_dir2_shrink_inode(args, mp->m_dirdatablk, bp))) {
-               ASSERT(error != ENOSPC);
-               goto out;
-       }
+       dst = kmem_alloc(mp->m_sb.sb_inodesize, KM_SLEEP);
+       hdr = bp->b_addr;
 
-       /*
-        * The buffer is now unconditionally gone, whether
-        * xfs_dir2_shrink_inode worked or not.
-        *
-        * Convert the inode to local format.
-        */
-       dp->i_df.if_flags &= ~XFS_IFEXTENTS;
-       dp->i_df.if_flags |= XFS_IFINLINE;
-       dp->i_d.di_format = XFS_DINODE_FMT_LOCAL;
-       ASSERT(dp->i_df.if_bytes == 0);
-       xfs_idata_realloc(dp, size, XFS_DATA_FORK);
-       logflags |= XFS_ILOG_DDATA;
        /*
         * Copy the header into the newly allocate local space.
         */
-       sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
+       sfp = (xfs_dir2_sf_hdr_t *)dst;
        memcpy(sfp, sfhp, xfs_dir2_sf_hdr_size(sfhp->i8count));
-       dp->i_d.di_size = size;
+
        /*
         * Set up to loop over the block's entries.
         */
@@ -258,10 +244,34 @@ xfs_dir2_block_to_sf(
                ptr += dp->d_ops->data_entsize(dep->namelen);
        }
        ASSERT((char *)sfep - (char *)sfp == size);
+
+       /* now we are done with the block, we can shrink the inode */
+       logflags = XFS_ILOG_CORE;
+       error = xfs_dir2_shrink_inode(args, mp->m_dirdatablk, bp);
+       if (error) {
+               ASSERT(error != ENOSPC);
+               goto out;
+       }
+
+       /*
+        * The buffer is now unconditionally gone, whether
+        * xfs_dir2_shrink_inode worked or not.
+        *
+        * Convert the inode to local format and copy the data in.
+        */
+       dp->i_df.if_flags &= ~XFS_IFEXTENTS;
+       dp->i_df.if_flags |= XFS_IFINLINE;
+       dp->i_d.di_format = XFS_DINODE_FMT_LOCAL;
+       ASSERT(dp->i_df.if_bytes == 0);
+       xfs_idata_realloc(dp, size, XFS_DATA_FORK);
+
+       logflags |= XFS_ILOG_DDATA;
+       memcpy(dp->i_df.if_u1.if_data, dst, size);
+       dp->i_d.di_size = size;
        xfs_dir2_sf_check(args);
 out:
        xfs_trans_log_inode(args->trans, dp, logflags);
-       kmem_free(hdr);
+       kmem_free(dst);
        return error;
 }
 
index 8367d6dc18c9df7f51cd565e11395cba24929a53..4f11ef0111395bbb7775407e9039e92cad0a932d 100644 (file)
@@ -157,7 +157,7 @@ xfs_ioc_trim(
        struct xfs_mount                *mp,
        struct fstrim_range __user      *urange)
 {
-       struct request_queue    *q = mp->m_ddev_targp->bt_bdev->bd_disk->queue;
+       struct request_queue    *q = bdev_get_queue(mp->m_ddev_targp->bt_bdev);
        unsigned int            granularity = q->limits.discard_granularity;
        struct fstrim_range     range;
        xfs_daddr_t             start, end, minlen;
@@ -180,7 +180,8 @@ xfs_ioc_trim(
         * matter as trimming blocks is an advisory interface.
         */
        if (range.start >= XFS_FSB_TO_B(mp, mp->m_sb.sb_dblocks) ||
-           range.minlen > XFS_FSB_TO_B(mp, XFS_ALLOC_AG_MAX_USABLE(mp)))
+           range.minlen > XFS_FSB_TO_B(mp, XFS_ALLOC_AG_MAX_USABLE(mp)) ||
+           range.len < mp->m_sb.sb_blocksize)
                return -XFS_ERROR(EINVAL);
 
        start = BTOBB(range.start);
index a6e54b3319bd0f5deb573623f332486590fbe165..02fb943cbf22b36b4e6da8c66b03be8839dc03d4 100644 (file)
@@ -220,6 +220,8 @@ xfs_growfs_data_private(
         */
        nfree = 0;
        for (agno = nagcount - 1; agno >= oagcount; agno--, new -= agsize) {
+               __be32  *agfl_bno;
+
                /*
                 * AG freespace header block
                 */
@@ -279,8 +281,10 @@ xfs_growfs_data_private(
                        agfl->agfl_seqno = cpu_to_be32(agno);
                        uuid_copy(&agfl->agfl_uuid, &mp->m_sb.sb_uuid);
                }
+
+               agfl_bno = XFS_BUF_TO_AGFL_BNO(mp, bp);
                for (bucket = 0; bucket < XFS_AGFL_SIZE(mp); bucket++)
-                       agfl->agfl_bno[bucket] = cpu_to_be32(NULLAGBLOCK);
+                       agfl_bno[bucket] = cpu_to_be32(NULLAGBLOCK);
 
                error = xfs_bwrite(bp);
                xfs_buf_relse(bp);
index e87719c5bebe128988a0993c4dc0f703cd3733ca..7a728f9fc0be97d98aeb3a4908716a03d27dbe57 100644 (file)
@@ -1229,7 +1229,7 @@ xfs_difree(
                }
 
                xfs_bmap_add_free(XFS_AGB_TO_FSB(mp,
-                               agno, XFS_INO_TO_AGBNO(mp,rec.ir_startino)),
+                               agno, XFS_AGINO_TO_AGBNO(mp, rec.ir_startino)),
                                XFS_IALLOC_BLOCKS(mp), flist, mp);
        } else {
                *delete = 0;
index 4d613401a5e056a08dd2f8b21b77833bfe14cbc6..33ad9a77791f7ebbf3f8762e0c9df1af637c5328 100644 (file)
@@ -442,7 +442,8 @@ xfs_attrlist_by_handle(
                return -XFS_ERROR(EPERM);
        if (copy_from_user(&al_hreq, arg, sizeof(xfs_fsop_attrlist_handlereq_t)))
                return -XFS_ERROR(EFAULT);
-       if (al_hreq.buflen > XATTR_LIST_MAX)
+       if (al_hreq.buflen < sizeof(struct attrlist) ||
+           al_hreq.buflen > XATTR_LIST_MAX)
                return -XFS_ERROR(EINVAL);
 
        /*
index e8fb1231db8124dc08b2ffbcc551d6bfa1bc21f5..a7992f8de9d3fa53a63ab2d3250f0c4933caded9 100644 (file)
@@ -356,7 +356,8 @@ xfs_compat_attrlist_by_handle(
        if (copy_from_user(&al_hreq, arg,
                           sizeof(compat_xfs_fsop_attrlist_handlereq_t)))
                return -XFS_ERROR(EFAULT);
-       if (al_hreq.buflen > XATTR_LIST_MAX)
+       if (al_hreq.buflen < sizeof(struct attrlist) ||
+           al_hreq.buflen > XATTR_LIST_MAX)
                return -XFS_ERROR(EINVAL);
 
        /*
index 27e0e544e9635ba47281279c68670f7e568a7a58..0ce1d759156e48ae092d566d30e713d7e597f29c 100644 (file)
@@ -459,14 +459,12 @@ xfs_vn_getattr(
 
 static void
 xfs_setattr_mode(
-       struct xfs_trans        *tp,
        struct xfs_inode        *ip,
        struct iattr            *iattr)
 {
-       struct inode    *inode = VFS_I(ip);
-       umode_t         mode = iattr->ia_mode;
+       struct inode            *inode = VFS_I(ip);
+       umode_t                 mode = iattr->ia_mode;
 
-       ASSERT(tp);
        ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
 
        ip->i_d.di_mode &= S_IFMT;
@@ -476,6 +474,32 @@ xfs_setattr_mode(
        inode->i_mode |= mode & ~S_IFMT;
 }
 
+static void
+xfs_setattr_time(
+       struct xfs_inode        *ip,
+       struct iattr            *iattr)
+{
+       struct inode            *inode = VFS_I(ip);
+
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+
+       if (iattr->ia_valid & ATTR_ATIME) {
+               inode->i_atime = iattr->ia_atime;
+               ip->i_d.di_atime.t_sec = iattr->ia_atime.tv_sec;
+               ip->i_d.di_atime.t_nsec = iattr->ia_atime.tv_nsec;
+       }
+       if (iattr->ia_valid & ATTR_CTIME) {
+               inode->i_ctime = iattr->ia_ctime;
+               ip->i_d.di_ctime.t_sec = iattr->ia_ctime.tv_sec;
+               ip->i_d.di_ctime.t_nsec = iattr->ia_ctime.tv_nsec;
+       }
+       if (iattr->ia_valid & ATTR_MTIME) {
+               inode->i_mtime = iattr->ia_mtime;
+               ip->i_d.di_mtime.t_sec = iattr->ia_mtime.tv_sec;
+               ip->i_d.di_mtime.t_nsec = iattr->ia_mtime.tv_nsec;
+       }
+}
+
 int
 xfs_setattr_nonsize(
        struct xfs_inode        *ip,
@@ -618,7 +642,8 @@ xfs_setattr_nonsize(
                }
                if (!gid_eq(igid, gid)) {
                        if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_GQUOTA_ON(mp)) {
-                               ASSERT(!XFS_IS_PQUOTA_ON(mp));
+                               ASSERT(xfs_sb_version_has_pquotino(&mp->m_sb) ||
+                                      !XFS_IS_PQUOTA_ON(mp));
                                ASSERT(mask & ATTR_GID);
                                ASSERT(gdqp);
                                olddquot2 = xfs_qm_vop_chown(tp, ip,
@@ -629,30 +654,10 @@ xfs_setattr_nonsize(
                }
        }
 
-       /*
-        * Change file access modes.
-        */
        if (mask & ATTR_MODE)
-               xfs_setattr_mode(tp, ip, iattr);
-
-       /*
-        * Change file access or modified times.
-        */
-       if (mask & ATTR_ATIME) {
-               inode->i_atime = iattr->ia_atime;
-               ip->i_d.di_atime.t_sec = iattr->ia_atime.tv_sec;
-               ip->i_d.di_atime.t_nsec = iattr->ia_atime.tv_nsec;
-       }
-       if (mask & ATTR_CTIME) {
-               inode->i_ctime = iattr->ia_ctime;
-               ip->i_d.di_ctime.t_sec = iattr->ia_ctime.tv_sec;
-               ip->i_d.di_ctime.t_nsec = iattr->ia_ctime.tv_nsec;
-       }
-       if (mask & ATTR_MTIME) {
-               inode->i_mtime = iattr->ia_mtime;
-               ip->i_d.di_mtime.t_sec = iattr->ia_mtime.tv_sec;
-               ip->i_d.di_mtime.t_nsec = iattr->ia_mtime.tv_nsec;
-       }
+               xfs_setattr_mode(ip, iattr);
+       if (mask & (ATTR_ATIME|ATTR_CTIME|ATTR_MTIME))
+               xfs_setattr_time(ip, iattr);
 
        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 
@@ -867,22 +872,10 @@ xfs_setattr_size(
                xfs_inode_clear_eofblocks_tag(ip);
        }
 
-       /*
-        * Change file access modes.
-        */
        if (mask & ATTR_MODE)
-               xfs_setattr_mode(tp, ip, iattr);
-
-       if (mask & ATTR_CTIME) {
-               inode->i_ctime = iattr->ia_ctime;
-               ip->i_d.di_ctime.t_sec = iattr->ia_ctime.tv_sec;
-               ip->i_d.di_ctime.t_nsec = iattr->ia_ctime.tv_nsec;
-       }
-       if (mask & ATTR_MTIME) {
-               inode->i_mtime = iattr->ia_mtime;
-               ip->i_d.di_mtime.t_sec = iattr->ia_mtime.tv_sec;
-               ip->i_d.di_mtime.t_nsec = iattr->ia_mtime.tv_nsec;
-       }
+               xfs_setattr_mode(ip, iattr);
+       if (mask & (ATTR_ATIME|ATTR_CTIME|ATTR_MTIME))
+               xfs_setattr_time(ip, iattr);
 
        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 
index b6b669df40f3ab335e75cd3a67903601be0128a4..07ab52ca8aba5786b9df50719be58457542d4db4 100644 (file)
@@ -1651,6 +1651,7 @@ xlog_recover_reorder_trans(
        int                     pass)
 {
        xlog_recover_item_t     *item, *n;
+       int                     error = 0;
        LIST_HEAD(sort_list);
        LIST_HEAD(cancel_list);
        LIST_HEAD(buffer_list);
@@ -1692,9 +1693,17 @@ xlog_recover_reorder_trans(
                                "%s: unrecognized type of log operation",
                                __func__);
                        ASSERT(0);
-                       return XFS_ERROR(EIO);
+                       /*
+                        * return the remaining items back to the transaction
+                        * item list so they can be freed in caller.
+                        */
+                       if (!list_empty(&sort_list))
+                               list_splice_init(&sort_list, &trans->r_itemq);
+                       error = XFS_ERROR(EIO);
+                       goto out;
                }
        }
+out:
        ASSERT(list_empty(&sort_list));
        if (!list_empty(&buffer_list))
                list_splice(&buffer_list, &trans->r_itemq);
@@ -1704,7 +1713,7 @@ xlog_recover_reorder_trans(
                list_splice_tail(&inode_buffer_list, &trans->r_itemq);
        if (!list_empty(&cancel_list))
                list_splice_tail(&cancel_list, &trans->r_itemq);
-       return 0;
+       return error;
 }
 
 /*
@@ -3608,8 +3617,10 @@ xlog_recover_process_data(
                                error = XFS_ERROR(EIO);
                                break;
                        }
-                       if (error)
+                       if (error) {
+                               xlog_recover_free_trans(trans);
                                return error;
+                       }
                }
                dp += be32_to_cpu(ohead->oh_len);
                num_logops--;
index 14a4996cfec6cb4fbeaa1d3f8432548ebb57d48b..dd88f0e27bd8ce1119d2606c256117d4d2488b9c 100644 (file)
@@ -134,8 +134,6 @@ xfs_qm_dqpurge(
 {
        struct xfs_mount        *mp = dqp->q_mount;
        struct xfs_quotainfo    *qi = mp->m_quotainfo;
-       struct xfs_dquot        *gdqp = NULL;
-       struct xfs_dquot        *pdqp = NULL;
 
        xfs_dqlock(dqp);
        if ((dqp->dq_flags & XFS_DQ_FREEING) || dqp->q_nrefs != 0) {
@@ -143,21 +141,6 @@ xfs_qm_dqpurge(
                return EAGAIN;
        }
 
-       /*
-        * If this quota has a hint attached, prepare for releasing it now.
-        */
-       gdqp = dqp->q_gdquot;
-       if (gdqp) {
-               xfs_dqlock(gdqp);
-               dqp->q_gdquot = NULL;
-       }
-
-       pdqp = dqp->q_pdquot;
-       if (pdqp) {
-               xfs_dqlock(pdqp);
-               dqp->q_pdquot = NULL;
-       }
-
        dqp->dq_flags |= XFS_DQ_FREEING;
 
        xfs_dqflock(dqp);
@@ -206,11 +189,47 @@ xfs_qm_dqpurge(
        XFS_STATS_DEC(xs_qm_dquot_unused);
 
        xfs_qm_dqdestroy(dqp);
+       return 0;
+}
+
+/*
+ * Release the group or project dquot pointers the user dquots maybe carrying
+ * around as a hint, and proceed to purge the user dquot cache if requested.
+*/
+STATIC int
+xfs_qm_dqpurge_hints(
+       struct xfs_dquot        *dqp,
+       void                    *data)
+{
+       struct xfs_dquot        *gdqp = NULL;
+       struct xfs_dquot        *pdqp = NULL;
+       uint                    flags = *((uint *)data);
+
+       xfs_dqlock(dqp);
+       if (dqp->dq_flags & XFS_DQ_FREEING) {
+               xfs_dqunlock(dqp);
+               return EAGAIN;
+       }
+
+       /* If this quota has a hint attached, prepare for releasing it now */
+       gdqp = dqp->q_gdquot;
+       if (gdqp)
+               dqp->q_gdquot = NULL;
+
+       pdqp = dqp->q_pdquot;
+       if (pdqp)
+               dqp->q_pdquot = NULL;
+
+       xfs_dqunlock(dqp);
 
        if (gdqp)
-               xfs_qm_dqput(gdqp);
+               xfs_qm_dqrele(gdqp);
        if (pdqp)
-               xfs_qm_dqput(pdqp);
+               xfs_qm_dqrele(pdqp);
+
+       if (flags & XFS_QMOPT_UQUOTA)
+               return xfs_qm_dqpurge(dqp, NULL);
+
        return 0;
 }
 
@@ -222,8 +241,18 @@ xfs_qm_dqpurge_all(
        struct xfs_mount        *mp,
        uint                    flags)
 {
-       if (flags & XFS_QMOPT_UQUOTA)
-               xfs_qm_dquot_walk(mp, XFS_DQ_USER, xfs_qm_dqpurge, NULL);
+       /*
+        * We have to release group/project dquot hint(s) from the user dquot
+        * at first if they are there, otherwise we would run into an infinite
+        * loop while walking through radix tree to purge other type of dquots
+        * since their refcount is not zero if the user dquot refers to them
+        * as hint.
+        *
+        * Call the special xfs_qm_dqpurge_hints() will end up go through the
+        * general xfs_qm_dqpurge() against user dquot cache if requested.
+        */
+       xfs_qm_dquot_walk(mp, XFS_DQ_USER, xfs_qm_dqpurge_hints, &flags);
+
        if (flags & XFS_QMOPT_GQUOTA)
                xfs_qm_dquot_walk(mp, XFS_DQ_GROUP, xfs_qm_dqpurge, NULL);
        if (flags & XFS_QMOPT_PQUOTA)
@@ -2082,24 +2111,21 @@ xfs_qm_vop_create_dqattach(
        ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
        ASSERT(XFS_IS_QUOTA_RUNNING(mp));
 
-       if (udqp) {
+       if (udqp && XFS_IS_UQUOTA_ON(mp)) {
                ASSERT(ip->i_udquot == NULL);
-               ASSERT(XFS_IS_UQUOTA_ON(mp));
                ASSERT(ip->i_d.di_uid == be32_to_cpu(udqp->q_core.d_id));
 
                ip->i_udquot = xfs_qm_dqhold(udqp);
                xfs_trans_mod_dquot(tp, udqp, XFS_TRANS_DQ_ICOUNT, 1);
        }
-       if (gdqp) {
+       if (gdqp && XFS_IS_GQUOTA_ON(mp)) {
                ASSERT(ip->i_gdquot == NULL);
-               ASSERT(XFS_IS_GQUOTA_ON(mp));
                ASSERT(ip->i_d.di_gid == be32_to_cpu(gdqp->q_core.d_id));
                ip->i_gdquot = xfs_qm_dqhold(gdqp);
                xfs_trans_mod_dquot(tp, gdqp, XFS_TRANS_DQ_ICOUNT, 1);
        }
-       if (pdqp) {
+       if (pdqp && XFS_IS_PQUOTA_ON(mp)) {
                ASSERT(ip->i_pdquot == NULL);
-               ASSERT(XFS_IS_PQUOTA_ON(mp));
                ASSERT(xfs_get_projid(ip) == be32_to_cpu(pdqp->q_core.d_id));
 
                ip->i_pdquot = xfs_qm_dqhold(pdqp);
index a788b66a5cb1c7e73898c877b0c3629eeb8e17a7..797fd4636273657992a1124bff8e5865fe36ba28 100644 (file)
 
 #include "xfs_dquot_item.h"
 #include "xfs_dquot.h"
-#include "xfs_quota_priv.h"
 
 struct xfs_inode;
 
 extern struct kmem_zone        *xfs_qm_dqtrxzone;
 
+/*
+ * Number of bmaps that we ask from bmapi when doing a quotacheck.
+ * We make this restriction to keep the memory usage to a minimum.
+ */
+#define XFS_DQITER_MAP_SIZE    10
+
+#define XFS_IS_DQUOT_UNINITIALIZED(dqp) ( \
+       !dqp->q_core.d_blk_hardlimit && \
+       !dqp->q_core.d_blk_softlimit && \
+       !dqp->q_core.d_rtb_hardlimit && \
+       !dqp->q_core.d_rtb_softlimit && \
+       !dqp->q_core.d_ino_hardlimit && \
+       !dqp->q_core.d_ino_softlimit && \
+       !dqp->q_core.d_bcount && \
+       !dqp->q_core.d_rtbcount && \
+       !dqp->q_core.d_icount)
+
 /*
  * This defines the unit of allocation of dquots.
  * Currently, it is just one file system block, and a 4K blk contains 30
index 437c9198031a49a940aecaa441dc305de0e9a145..3daf5ea1eb8d73989a4e199aaee4dd2364a98290 100644 (file)
@@ -278,7 +278,7 @@ xfs_qm_scall_trunc_qfiles(
        xfs_mount_t     *mp,
        uint            flags)
 {
-       int             error = 0, error2 = 0;
+       int             error;
 
        if (!xfs_sb_version_hasquota(&mp->m_sb) || flags == 0) {
                xfs_debug(mp, "%s: flags=%x m_qflags=%x",
@@ -286,14 +286,20 @@ xfs_qm_scall_trunc_qfiles(
                return XFS_ERROR(EINVAL);
        }
 
-       if (flags & XFS_DQ_USER)
+       if (flags & XFS_DQ_USER) {
                error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_uquotino);
-       if (flags & XFS_DQ_GROUP)
-               error2 = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_gquotino);
+               if (error)
+                       return error;
+       }
+       if (flags & XFS_DQ_GROUP) {
+               error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_gquotino);
+               if (error)
+                       return error;
+       }
        if (flags & XFS_DQ_PROJ)
-               error2 = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_pquotino);
+               error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_pquotino);
 
-       return error ? error : error2;
+       return error;
 }
 
 /*
diff --git a/fs/xfs/xfs_quota_priv.h b/fs/xfs/xfs_quota_priv.h
deleted file mode 100644 (file)
index 6d86219..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would 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 the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#ifndef __XFS_QUOTA_PRIV_H__
-#define __XFS_QUOTA_PRIV_H__
-
-/*
- * Number of bmaps that we ask from bmapi when doing a quotacheck.
- * We make this restriction to keep the memory usage to a minimum.
- */
-#define XFS_DQITER_MAP_SIZE    10
-
-#define XFS_IS_DQUOT_UNINITIALIZED(dqp) ( \
-       !dqp->q_core.d_blk_hardlimit && \
-       !dqp->q_core.d_blk_softlimit && \
-       !dqp->q_core.d_rtb_hardlimit && \
-       !dqp->q_core.d_rtb_softlimit && \
-       !dqp->q_core.d_ino_hardlimit && \
-       !dqp->q_core.d_ino_softlimit && \
-       !dqp->q_core.d_bcount && \
-       !dqp->q_core.d_rtbcount && \
-       !dqp->q_core.d_icount)
-
-#define DQFLAGTO_TYPESTR(d)    (((d)->dq_flags & XFS_DQ_USER) ? "USR" : \
-                                (((d)->dq_flags & XFS_DQ_GROUP) ? "GRP" : \
-                                (((d)->dq_flags & XFS_DQ_PROJ) ? "PRJ":"???")))
-
-#endif /* __XFS_QUOTA_PRIV_H__ */
index cd2a10e15d3ac5520661ed2877f2e5c9cdac48d9..41172861e857bf8c487f7adf3037aad0214b1681 100644 (file)
@@ -295,8 +295,8 @@ xfs_trans_mod_dquot(
 /*
  * Given an array of dqtrx structures, lock all the dquots associated and join
  * them to the transaction, provided they have been modified.  We know that the
- * highest number of dquots of one type - usr, grp OR prj - involved in a
- * transaction is 2 so we don't need to make this very generic.
+ * highest number of dquots of one type - usr, grp and prj - involved in a
+ * transaction is 3 so we don't need to make this very generic.
  */
 STATIC void
 xfs_trans_dqlockedjoin(
index 3e8e797c6d110ce01b0964a2e3845d8a59defd0b..e8a77383c0d5af630f4c154fa48e4d9ee345d95c 100644 (file)
@@ -34,15 +34,6 @@ struct attrlist_cursor_kern;
        { IO_ISDIRECT,  "DIRECT" }, \
        { IO_INVIS,     "INVIS"}
 
-/*
- * Flush/Invalidate options for vop_toss/flush/flushinval_pages.
- */
-#define FI_NONE                        0       /* none */
-#define FI_REMAPF              1       /* Do a remapf prior to the operation */
-#define FI_REMAPF_LOCKED       2       /* Do a remapf prior to the operation.
-                                          Prevent VM access to the pages until
-                                          the operation completes. */
-
 /*
  * Some useful predicates.
  */
index c602c7718421ded2f2bbe50f1e76edc39ac2b6f2..7135fe3d6daa6ee76bca6238a63a1ba6be949d5b 100644 (file)
@@ -28,8 +28,6 @@
 
 #include <linux/device.h>
 
-#include <acpi/acpi.h>
-
 /* TBD: Make dynamic */
 #define ACPI_MAX_HANDLES       10
 struct acpi_handle_list {
@@ -91,17 +89,10 @@ struct acpi_device;
  * -----------------
  */
 
-enum acpi_hotplug_mode {
-       AHM_GENERIC = 0,
-       AHM_CONTAINER,
-       AHM_COUNT
-};
-
 struct acpi_hotplug_profile {
        struct kobject kobj;
        bool enabled:1;
-       bool ignore:1;
-       enum acpi_hotplug_mode mode;
+       int (*scan_dependent)(struct acpi_device *adev);
 };
 
 static inline struct acpi_hotplug_profile *to_acpi_hotplug_profile(
@@ -169,7 +160,9 @@ struct acpi_device_flags {
        u32 ejectable:1;
        u32 power_manageable:1;
        u32 match_driver:1;
-       u32 reserved:27;
+       u32 initialized:1;
+       u32 visited:1;
+       u32 reserved:25;
 };
 
 /* File System */
@@ -299,6 +292,7 @@ struct acpi_device {
        struct list_head children;
        struct list_head node;
        struct list_head wakeup_list;
+       struct list_head del_list;
        struct acpi_device_status status;
        struct acpi_device_flags flags;
        struct acpi_device_pnp pnp;
@@ -324,6 +318,11 @@ static inline void *acpi_driver_data(struct acpi_device *d)
 #define to_acpi_device(d)      container_of(d, struct acpi_device, dev)
 #define to_acpi_driver(d)      container_of(d, struct acpi_driver, drv)
 
+static inline void acpi_set_device_status(struct acpi_device *adev, u32 sta)
+{
+       *((u32 *)&adev->status) = sta;
+}
+
 /* acpi_device.dev.bus == &acpi_bus_type */
 extern struct bus_type acpi_bus_type;
 
@@ -385,6 +384,11 @@ int acpi_match_device_ids(struct acpi_device *device,
 int acpi_create_dir(struct acpi_device *);
 void acpi_remove_dir(struct acpi_device *);
 
+static inline bool acpi_device_enumerated(struct acpi_device *adev)
+{
+       return adev && adev->flags.initialized && adev->flags.visited;
+}
+
 typedef void (*acpi_hp_callback)(void *data, u32 src);
 
 acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src);
@@ -408,7 +412,7 @@ struct acpi_bus_type {
        struct list_head list;
        const char *name;
        bool (*match)(struct device *dev);
-       int (*find_device) (struct device *, acpi_handle *);
+       struct acpi_device * (*find_companion)(struct device *);
        void (*setup)(struct device *);
        void (*cleanup)(struct device *);
 };
@@ -427,12 +431,9 @@ struct acpi_pci_root {
 };
 
 /* helper */
-acpi_handle acpi_find_child(acpi_handle, u64, bool);
-static inline acpi_handle acpi_get_child(acpi_handle handle, u64 addr)
-{
-       return acpi_find_child(handle, addr, false);
-}
-void acpi_preset_companion(struct device *dev, acpi_handle parent, u64 addr);
+
+struct acpi_device *acpi_find_child_device(struct acpi_device *parent,
+                                          u64 address, bool check_children);
 int acpi_is_root_bridge(acpi_handle);
 struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle);
 
index 1cedfcb1bd8878ff7466e4ab6d9285e3a811a90a..b124fdb260469bfa07dbc14fa511cb7dbd0240e2 100644 (file)
@@ -26,9 +26,6 @@
 #ifndef __ACPI_DRIVERS_H__
 #define __ACPI_DRIVERS_H__
 
-#include <linux/acpi.h>
-#include <acpi/acpi_bus.h>
-
 #define ACPI_MAX_STRING                        80
 
 /*
index 13621cc8cf4c454f546a6fbb33fb5e85e8b1b1aa..6a626a507b8ca2d9c1a167b0758c7d7d3604013e 100644 (file)
@@ -36,6 +36,7 @@ static inline void scatterwalk_sg_chain(struct scatterlist *sg1, int num,
 {
        sg_set_page(&sg1[num - 1], (void *)sg2, 0, 0);
        sg1[num - 1].page_link &= ~0x02;
+       sg1[num - 1].page_link |= 0x01;
 }
 
 static inline struct scatterlist *scatterwalk_sg_next(struct scatterlist *sg)
@@ -43,7 +44,7 @@ static inline struct scatterlist *scatterwalk_sg_next(struct scatterlist *sg)
        if (sg_is_last(sg))
                return NULL;
 
-       return (++sg)->length ? sg : (void *)sg_page(sg);
+       return (++sg)->length ? sg : sg_chain_ptr(sg);
 }
 
 static inline void scatterwalk_crypto_chain(struct scatterlist *head,
diff --git a/include/dt-bindings/clk/at91.h b/include/dt-bindings/clk/at91.h
new file mode 100644 (file)
index 0000000..0b4cb99
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * This header provides constants for AT91 pmc status.
+ *
+ * The constants defined in this header are being used in dts.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#ifndef _DT_BINDINGS_CLK_AT91_H
+#define _DT_BINDINGS_CLK_AT91_H
+
+#define AT91_PMC_MOSCS         0               /* MOSCS Flag */
+#define AT91_PMC_LOCKA         1               /* PLLA Lock */
+#define AT91_PMC_LOCKB         2               /* PLLB Lock */
+#define AT91_PMC_MCKRDY                3               /* Master Clock */
+#define AT91_PMC_LOCKU         6               /* UPLL Lock */
+#define AT91_PMC_PCKRDY(id)    (8 + (id))      /* Programmable Clock */
+#define AT91_PMC_MOSCSELS      16              /* Main Oscillator Selection */
+#define AT91_PMC_MOSCRCS       17              /* Main On-Chip RC */
+#define AT91_PMC_CFDEV         18              /* Clock Failure Detector Event */
+
+#endif
diff --git a/include/dt-bindings/clock/imx5-clock.h b/include/dt-bindings/clock/imx5-clock.h
new file mode 100644 (file)
index 0000000..5f2667e
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2013 Lucas Stach, Pengutronix <l.stach@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_IMX5_H
+#define __DT_BINDINGS_CLOCK_IMX5_H
+
+#define IMX5_CLK_DUMMY                 0
+#define IMX5_CLK_CKIL                  1
+#define IMX5_CLK_OSC                   2
+#define IMX5_CLK_CKIH1                 3
+#define IMX5_CLK_CKIH2                 4
+#define IMX5_CLK_AHB                   5
+#define IMX5_CLK_IPG                   6
+#define IMX5_CLK_AXI_A                 7
+#define IMX5_CLK_AXI_B                 8
+#define IMX5_CLK_UART_PRED             9
+#define IMX5_CLK_UART_ROOT             10
+#define IMX5_CLK_ESDHC_A_PRED          11
+#define IMX5_CLK_ESDHC_B_PRED          12
+#define IMX5_CLK_ESDHC_C_SEL           13
+#define IMX5_CLK_ESDHC_D_SEL           14
+#define IMX5_CLK_EMI_SEL               15
+#define IMX5_CLK_EMI_SLOW_PODF         16
+#define IMX5_CLK_NFC_PODF              17
+#define IMX5_CLK_ECSPI_PRED            18
+#define IMX5_CLK_ECSPI_PODF            19
+#define IMX5_CLK_USBOH3_PRED           20
+#define IMX5_CLK_USBOH3_PODF           21
+#define IMX5_CLK_USB_PHY_PRED          22
+#define IMX5_CLK_USB_PHY_PODF          23
+#define IMX5_CLK_CPU_PODF              24
+#define IMX5_CLK_DI_PRED               25
+#define IMX5_CLK_TVE_SEL               27
+#define IMX5_CLK_UART1_IPG_GATE                28
+#define IMX5_CLK_UART1_PER_GATE                29
+#define IMX5_CLK_UART2_IPG_GATE                30
+#define IMX5_CLK_UART2_PER_GATE                31
+#define IMX5_CLK_UART3_IPG_GATE                32
+#define IMX5_CLK_UART3_PER_GATE                33
+#define IMX5_CLK_I2C1_GATE             34
+#define IMX5_CLK_I2C2_GATE             35
+#define IMX5_CLK_GPT_IPG_GATE          36
+#define IMX5_CLK_PWM1_IPG_GATE         37
+#define IMX5_CLK_PWM1_HF_GATE          38
+#define IMX5_CLK_PWM2_IPG_GATE         39
+#define IMX5_CLK_PWM2_HF_GATE          40
+#define IMX5_CLK_GPT_HF_GATE           41
+#define IMX5_CLK_FEC_GATE              42
+#define IMX5_CLK_USBOH3_PER_GATE       43
+#define IMX5_CLK_ESDHC1_IPG_GATE       44
+#define IMX5_CLK_ESDHC2_IPG_GATE       45
+#define IMX5_CLK_ESDHC3_IPG_GATE       46
+#define IMX5_CLK_ESDHC4_IPG_GATE       47
+#define IMX5_CLK_SSI1_IPG_GATE         48
+#define IMX5_CLK_SSI2_IPG_GATE         49
+#define IMX5_CLK_SSI3_IPG_GATE         50
+#define IMX5_CLK_ECSPI1_IPG_GATE       51
+#define IMX5_CLK_ECSPI1_PER_GATE       52
+#define IMX5_CLK_ECSPI2_IPG_GATE       53
+#define IMX5_CLK_ECSPI2_PER_GATE       54
+#define IMX5_CLK_CSPI_IPG_GATE         55
+#define IMX5_CLK_SDMA_GATE             56
+#define IMX5_CLK_EMI_SLOW_GATE         57
+#define IMX5_CLK_IPU_SEL               58
+#define IMX5_CLK_IPU_GATE              59
+#define IMX5_CLK_NFC_GATE              60
+#define IMX5_CLK_IPU_DI1_GATE          61
+#define IMX5_CLK_VPU_SEL               62
+#define IMX5_CLK_VPU_GATE              63
+#define IMX5_CLK_VPU_REFERENCE_GATE    64
+#define IMX5_CLK_UART4_IPG_GATE                65
+#define IMX5_CLK_UART4_PER_GATE                66
+#define IMX5_CLK_UART5_IPG_GATE                67
+#define IMX5_CLK_UART5_PER_GATE                68
+#define IMX5_CLK_TVE_GATE              69
+#define IMX5_CLK_TVE_PRED              70
+#define IMX5_CLK_ESDHC1_PER_GATE       71
+#define IMX5_CLK_ESDHC2_PER_GATE       72
+#define IMX5_CLK_ESDHC3_PER_GATE       73
+#define IMX5_CLK_ESDHC4_PER_GATE       74
+#define IMX5_CLK_USB_PHY_GATE          75
+#define IMX5_CLK_HSI2C_GATE            76
+#define IMX5_CLK_MIPI_HSC1_GATE                77
+#define IMX5_CLK_MIPI_HSC2_GATE                78
+#define IMX5_CLK_MIPI_ESC_GATE         79
+#define IMX5_CLK_MIPI_HSP_GATE         80
+#define IMX5_CLK_LDB_DI1_DIV_3_5       81
+#define IMX5_CLK_LDB_DI1_DIV           82
+#define IMX5_CLK_LDB_DI0_DIV_3_5       83
+#define IMX5_CLK_LDB_DI0_DIV           84
+#define IMX5_CLK_LDB_DI1_GATE          85
+#define IMX5_CLK_CAN2_SERIAL_GATE      86
+#define IMX5_CLK_CAN2_IPG_GATE         87
+#define IMX5_CLK_I2C3_GATE             88
+#define IMX5_CLK_LP_APM                        89
+#define IMX5_CLK_PERIPH_APM            90
+#define IMX5_CLK_MAIN_BUS              91
+#define IMX5_CLK_AHB_MAX               92
+#define IMX5_CLK_AIPS_TZ1              93
+#define IMX5_CLK_AIPS_TZ2              94
+#define IMX5_CLK_TMAX1                 95
+#define IMX5_CLK_TMAX2                 96
+#define IMX5_CLK_TMAX3                 97
+#define IMX5_CLK_SPBA                  98
+#define IMX5_CLK_UART_SEL              99
+#define IMX5_CLK_ESDHC_A_SEL           100
+#define IMX5_CLK_ESDHC_B_SEL           101
+#define IMX5_CLK_ESDHC_A_PODF          102
+#define IMX5_CLK_ESDHC_B_PODF          103
+#define IMX5_CLK_ECSPI_SEL             104
+#define IMX5_CLK_USBOH3_SEL            105
+#define IMX5_CLK_USB_PHY_SEL           106
+#define IMX5_CLK_IIM_GATE              107
+#define IMX5_CLK_USBOH3_GATE           108
+#define IMX5_CLK_EMI_FAST_GATE         109
+#define IMX5_CLK_IPU_DI0_GATE          110
+#define IMX5_CLK_GPC_DVFS              111
+#define IMX5_CLK_PLL1_SW               112
+#define IMX5_CLK_PLL2_SW               113
+#define IMX5_CLK_PLL3_SW               114
+#define IMX5_CLK_IPU_DI0_SEL           115
+#define IMX5_CLK_IPU_DI1_SEL           116
+#define IMX5_CLK_TVE_EXT_SEL           117
+#define IMX5_CLK_MX51_MIPI             118
+#define IMX5_CLK_PLL4_SW               119
+#define IMX5_CLK_LDB_DI1_SEL           120
+#define IMX5_CLK_DI_PLL4_PODF          121
+#define IMX5_CLK_LDB_DI0_SEL           122
+#define IMX5_CLK_LDB_DI0_GATE          123
+#define IMX5_CLK_USB_PHY1_GATE         124
+#define IMX5_CLK_USB_PHY2_GATE         125
+#define IMX5_CLK_PER_LP_APM            126
+#define IMX5_CLK_PER_PRED1             127
+#define IMX5_CLK_PER_PRED2             128
+#define IMX5_CLK_PER_PODF              129
+#define IMX5_CLK_PER_ROOT              130
+#define IMX5_CLK_SSI_APM               131
+#define IMX5_CLK_SSI1_ROOT_SEL         132
+#define IMX5_CLK_SSI2_ROOT_SEL         133
+#define IMX5_CLK_SSI3_ROOT_SEL         134
+#define IMX5_CLK_SSI_EXT1_SEL          135
+#define IMX5_CLK_SSI_EXT2_SEL          136
+#define IMX5_CLK_SSI_EXT1_COM_SEL      137
+#define IMX5_CLK_SSI_EXT2_COM_SEL      138
+#define IMX5_CLK_SSI1_ROOT_PRED                139
+#define IMX5_CLK_SSI1_ROOT_PODF                140
+#define IMX5_CLK_SSI2_ROOT_PRED                141
+#define IMX5_CLK_SSI2_ROOT_PODF                142
+#define IMX5_CLK_SSI_EXT1_PRED         143
+#define IMX5_CLK_SSI_EXT1_PODF         144
+#define IMX5_CLK_SSI_EXT2_PRED         145
+#define IMX5_CLK_SSI_EXT2_PODF         146
+#define IMX5_CLK_SSI1_ROOT_GATE                147
+#define IMX5_CLK_SSI2_ROOT_GATE                148
+#define IMX5_CLK_SSI3_ROOT_GATE                149
+#define IMX5_CLK_SSI_EXT1_GATE         150
+#define IMX5_CLK_SSI_EXT2_GATE         151
+#define IMX5_CLK_EPIT1_IPG_GATE                152
+#define IMX5_CLK_EPIT1_HF_GATE         153
+#define IMX5_CLK_EPIT2_IPG_GATE                154
+#define IMX5_CLK_EPIT2_HF_GATE         155
+#define IMX5_CLK_CAN_SEL               156
+#define IMX5_CLK_CAN1_SERIAL_GATE      157
+#define IMX5_CLK_CAN1_IPG_GATE         158
+#define IMX5_CLK_OWIRE_GATE            159
+#define IMX5_CLK_GPU3D_SEL             160
+#define IMX5_CLK_GPU2D_SEL             161
+#define IMX5_CLK_GPU3D_GATE            162
+#define IMX5_CLK_GPU2D_GATE            163
+#define IMX5_CLK_GARB_GATE             164
+#define IMX5_CLK_CKO1_SEL              165
+#define IMX5_CLK_CKO1_PODF             166
+#define IMX5_CLK_CKO1                  167
+#define IMX5_CLK_CKO2_SEL              168
+#define IMX5_CLK_CKO2_PODF             169
+#define IMX5_CLK_CKO2                  170
+#define IMX5_CLK_SRTC_GATE             171
+#define IMX5_CLK_PATA_GATE             172
+#define IMX5_CLK_SATA_GATE             173
+#define IMX5_CLK_SPDIF_XTAL_SEL                174
+#define IMX5_CLK_SPDIF0_SEL            175
+#define IMX5_CLK_SPDIF1_SEL            176
+#define IMX5_CLK_SPDIF0_PRED           177
+#define IMX5_CLK_SPDIF0_PODF           178
+#define IMX5_CLK_SPDIF1_PRED           179
+#define IMX5_CLK_SPDIF1_PODF           180
+#define IMX5_CLK_SPDIF0_COM_SEL                181
+#define IMX5_CLK_SPDIF1_COM_SEL                182
+#define IMX5_CLK_SPDIF0_GATE           183
+#define IMX5_CLK_SPDIF1_GATE           184
+#define IMX5_CLK_SPDIF_IPG_GATE                185
+#define IMX5_CLK_OCRAM                 186
+#define IMX5_CLK_SAHARA_IPG_GATE       187
+#define IMX5_CLK_SATA_REF              188
+#define IMX5_CLK_END                   189
+
+#endif /* __DT_BINDINGS_CLOCK_IMX5_H */
index 7fcdf90879f25b23e9dadd28399dd7e8112022e9..46f7495ae3870c12a511b558b7970b8b4151e538 100644 (file)
 #define IMX6SL_CLK_USDHC2              130
 #define IMX6SL_CLK_USDHC3              131
 #define IMX6SL_CLK_USDHC4              132
-#define IMX6SL_CLK_CLK_END             133
+#define IMX6SL_CLK_END                 133
 
 #endif /* __DT_BINDINGS_CLOCK_IMX6SL_H */
diff --git a/include/dt-bindings/clock/mpc512x-clock.h b/include/dt-bindings/clock/mpc512x-clock.h
new file mode 100644 (file)
index 0000000..9e81b3b
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * This header provides constants for MPC512x clock specs in DT bindings.
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_MPC512x_CLOCK_H
+#define _DT_BINDINGS_CLOCK_MPC512x_CLOCK_H
+
+#define MPC512x_CLK_DUMMY              0
+#define MPC512x_CLK_REF                        1
+#define MPC512x_CLK_SYS                        2
+#define MPC512x_CLK_DIU                        3
+#define MPC512x_CLK_VIU                        4
+#define MPC512x_CLK_CSB                        5
+#define MPC512x_CLK_E300               6
+#define MPC512x_CLK_IPS                        7
+#define MPC512x_CLK_FEC                        8
+#define MPC512x_CLK_SATA               9
+#define MPC512x_CLK_PATA               10
+#define MPC512x_CLK_NFC                        11
+#define MPC512x_CLK_LPC                        12
+#define MPC512x_CLK_MBX_BUS            13
+#define MPC512x_CLK_MBX                        14
+#define MPC512x_CLK_MBX_3D             15
+#define MPC512x_CLK_AXE                        16
+#define MPC512x_CLK_USB1               17
+#define MPC512x_CLK_USB2               18
+#define MPC512x_CLK_I2C                        19
+#define MPC512x_CLK_MSCAN0_MCLK                20
+#define MPC512x_CLK_MSCAN1_MCLK                21
+#define MPC512x_CLK_MSCAN2_MCLK                22
+#define MPC512x_CLK_MSCAN3_MCLK                23
+#define MPC512x_CLK_BDLC               24
+#define MPC512x_CLK_SDHC               25
+#define MPC512x_CLK_PCI                        26
+#define MPC512x_CLK_PSC_MCLK_IN                27
+#define MPC512x_CLK_SPDIF_TX           28
+#define MPC512x_CLK_SPDIF_RX           29
+#define MPC512x_CLK_SPDIF_MCLK         30
+#define MPC512x_CLK_SPDIF              31
+#define MPC512x_CLK_AC97               32
+#define MPC512x_CLK_PSC0_MCLK          33
+#define MPC512x_CLK_PSC1_MCLK          34
+#define MPC512x_CLK_PSC2_MCLK          35
+#define MPC512x_CLK_PSC3_MCLK          36
+#define MPC512x_CLK_PSC4_MCLK          37
+#define MPC512x_CLK_PSC5_MCLK          38
+#define MPC512x_CLK_PSC6_MCLK          39
+#define MPC512x_CLK_PSC7_MCLK          40
+#define MPC512x_CLK_PSC8_MCLK          41
+#define MPC512x_CLK_PSC9_MCLK          42
+#define MPC512x_CLK_PSC10_MCLK         43
+#define MPC512x_CLK_PSC11_MCLK         44
+#define MPC512x_CLK_PSC_FIFO           45
+#define MPC512x_CLK_PSC0               46
+#define MPC512x_CLK_PSC1               47
+#define MPC512x_CLK_PSC2               48
+#define MPC512x_CLK_PSC3               49
+#define MPC512x_CLK_PSC4               50
+#define MPC512x_CLK_PSC5               51
+#define MPC512x_CLK_PSC6               52
+#define MPC512x_CLK_PSC7               53
+#define MPC512x_CLK_PSC8               54
+#define MPC512x_CLK_PSC9               55
+#define MPC512x_CLK_PSC10              56
+#define MPC512x_CLK_PSC11              57
+
+#define MPC512x_CLK_LAST_PUBLIC                57
+
+#endif
index 4aa2b48cd15183e457a3eb96288dca81039cef37..a91602951d3d3c018218c37889b7ae9338191948 100644 (file)
 #define VF610_CLK_GPU2D                        147
 #define VF610_CLK_ENET0                        148
 #define VF610_CLK_ENET1                        149
-#define VF610_CLK_END                  150
+#define VF610_CLK_DMAMUX0              150
+#define VF610_CLK_DMAMUX1              151
+#define VF610_CLK_DMAMUX2              152
+#define VF610_CLK_DMAMUX3              153
+#define VF610_CLK_END                  154
 
 #endif /* __DT_BINDINGS_CLOCK_VF610_H */
index 4d179c00f081f8e5a137a6562b8fb7c8e9b0faaf..197dc28b676ef8a53641eee4f0735e1231728765 100644 (file)
@@ -43,6 +43,7 @@
 #define TEGRA_GPIO_BANK_ID_CC 28
 #define TEGRA_GPIO_BANK_ID_DD 29
 #define TEGRA_GPIO_BANK_ID_EE 30
+#define TEGRA_GPIO_BANK_ID_FF 31
 
 #define TEGRA_GPIO(bank, offset) \
        ((TEGRA_GPIO_BANK_ID_##bank * 8) + offset)
index d9099b15b4726404343308a39e5e55d39a16aa05..115c610324d1ec6b9ecc8aa3a67d839636ca35bf 100644 (file)
@@ -53,6 +53,12 @@ static inline acpi_handle acpi_device_handle(struct acpi_device *adev)
 #define ACPI_COMPANION_SET(dev, adev)  ACPI_COMPANION(dev) = (adev)
 #define ACPI_HANDLE(dev)               acpi_device_handle(ACPI_COMPANION(dev))
 
+static inline void acpi_preset_companion(struct device *dev,
+                                        struct acpi_device *parent, u64 addr)
+{
+       ACPI_COMPANION_SET(dev, acpi_find_child_device(parent, addr, NULL));
+}
+
 static inline const char *acpi_dev_name(struct acpi_device *adev)
 {
        return dev_name(&adev->dev);
index b0ffa219993ec2be82a01854718d5e1269ef05bb..2a5a1391ce727b17d165298a416608841d266d63 100644 (file)
@@ -2,7 +2,7 @@
 #define _ACPI_IO_H_
 
 #include <linux/io.h>
-#include <acpi/acpi.h>
+#include <acpi/acpi.h> /* FIXME: inclusion should be removed */
 
 static inline void __iomem *acpi_os_ioremap(acpi_physical_address phys,
                                            acpi_size size)
index fcdd81bd531493645930cf2d2e19661f4ed63f0f..8598f8eacb20e175aacb638edd41e514afc7f9d8 100644 (file)
@@ -32,6 +32,8 @@ struct ath9k_platform_data {
        u32 gpio_val;
 
        bool is_clk_25mhz;
+       bool tx_gain_buffalo;
+
        int (*get_mac_revision)(void);
        int (*external_reset)(void);
 };
index 060ff695085c596f2ddcd2166e7825290d75bd3d..70654521dab69fb03443723550e9b9f8c64a6533 100644 (file)
  * various member access, note that bio_data should of course not be used
  * on highmem page vectors
  */
-#define bio_iovec_idx(bio, idx)        (&((bio)->bi_io_vec[(idx)]))
-#define bio_iovec(bio)         bio_iovec_idx((bio), (bio)->bi_idx)
-#define bio_page(bio)          bio_iovec((bio))->bv_page
-#define bio_offset(bio)                bio_iovec((bio))->bv_offset
-#define bio_segments(bio)      ((bio)->bi_vcnt - (bio)->bi_idx)
-#define bio_sectors(bio)       ((bio)->bi_size >> 9)
-#define bio_end_sector(bio)    ((bio)->bi_sector + bio_sectors((bio)))
+#define __bvec_iter_bvec(bvec, iter)   (&(bvec)[(iter).bi_idx])
+
+#define bvec_iter_page(bvec, iter)                             \
+       (__bvec_iter_bvec((bvec), (iter))->bv_page)
+
+#define bvec_iter_len(bvec, iter)                              \
+       min((iter).bi_size,                                     \
+           __bvec_iter_bvec((bvec), (iter))->bv_len - (iter).bi_bvec_done)
+
+#define bvec_iter_offset(bvec, iter)                           \
+       (__bvec_iter_bvec((bvec), (iter))->bv_offset + (iter).bi_bvec_done)
+
+#define bvec_iter_bvec(bvec, iter)                             \
+((struct bio_vec) {                                            \
+       .bv_page        = bvec_iter_page((bvec), (iter)),       \
+       .bv_len         = bvec_iter_len((bvec), (iter)),        \
+       .bv_offset      = bvec_iter_offset((bvec), (iter)),     \
+})
+
+#define bio_iter_iovec(bio, iter)                              \
+       bvec_iter_bvec((bio)->bi_io_vec, (iter))
+
+#define bio_iter_page(bio, iter)                               \
+       bvec_iter_page((bio)->bi_io_vec, (iter))
+#define bio_iter_len(bio, iter)                                        \
+       bvec_iter_len((bio)->bi_io_vec, (iter))
+#define bio_iter_offset(bio, iter)                             \
+       bvec_iter_offset((bio)->bi_io_vec, (iter))
+
+#define bio_page(bio)          bio_iter_page((bio), (bio)->bi_iter)
+#define bio_offset(bio)                bio_iter_offset((bio), (bio)->bi_iter)
+#define bio_iovec(bio)         bio_iter_iovec((bio), (bio)->bi_iter)
+
+#define bio_multiple_segments(bio)                             \
+       ((bio)->bi_iter.bi_size != bio_iovec(bio).bv_len)
+#define bio_sectors(bio)       ((bio)->bi_iter.bi_size >> 9)
+#define bio_end_sector(bio)    ((bio)->bi_iter.bi_sector + bio_sectors((bio)))
+
+/*
+ * Check whether this bio carries any data or not. A NULL bio is allowed.
+ */
+static inline bool bio_has_data(struct bio *bio)
+{
+       if (bio &&
+           bio->bi_iter.bi_size &&
+           !(bio->bi_rw & REQ_DISCARD))
+               return true;
+
+       return false;
+}
+
+static inline bool bio_is_rw(struct bio *bio)
+{
+       if (!bio_has_data(bio))
+               return false;
+
+       if (bio->bi_rw & BIO_NO_ADVANCE_ITER_MASK)
+               return false;
+
+       return true;
+}
+
+static inline bool bio_mergeable(struct bio *bio)
+{
+       if (bio->bi_rw & REQ_NOMERGE_FLAGS)
+               return false;
+
+       return true;
+}
 
 static inline unsigned int bio_cur_bytes(struct bio *bio)
 {
-       if (bio->bi_vcnt)
-               return bio_iovec(bio)->bv_len;
+       if (bio_has_data(bio))
+               return bio_iovec(bio).bv_len;
        else /* dataless requests such as discard */
-               return bio->bi_size;
+               return bio->bi_iter.bi_size;
 }
 
 static inline void *bio_data(struct bio *bio)
 {
-       if (bio->bi_vcnt)
+       if (bio_has_data(bio))
                return page_address(bio_page(bio)) + bio_offset(bio);
 
        return NULL;
@@ -97,19 +159,16 @@ static inline void *bio_data(struct bio *bio)
  * permanent PIO fall back, user is probably better off disabling highmem
  * I/O completely on that queue (see ide-dma for example)
  */
-#define __bio_kmap_atomic(bio, idx)                            \
-       (kmap_atomic(bio_iovec_idx((bio), (idx))->bv_page) +    \
-               bio_iovec_idx((bio), (idx))->bv_offset)
+#define __bio_kmap_atomic(bio, iter)                           \
+       (kmap_atomic(bio_iter_iovec((bio), (iter)).bv_page) +   \
+               bio_iter_iovec((bio), (iter)).bv_offset)
 
-#define __bio_kunmap_atomic(addr) kunmap_atomic(addr)
+#define __bio_kunmap_atomic(addr)      kunmap_atomic(addr)
 
 /*
  * merge helpers etc
  */
 
-#define __BVEC_END(bio)                bio_iovec_idx((bio), (bio)->bi_vcnt - 1)
-#define __BVEC_START(bio)      bio_iovec_idx((bio), (bio)->bi_idx)
-
 /* Default implementation of BIOVEC_PHYS_MERGEABLE */
 #define __BIOVEC_PHYS_MERGEABLE(vec1, vec2)    \
        ((bvec_to_phys((vec1)) + (vec1)->bv_len) == bvec_to_phys((vec2)))
@@ -126,33 +185,76 @@ static inline void *bio_data(struct bio *bio)
        (((addr1) | (mask)) == (((addr2) - 1) | (mask)))
 #define BIOVEC_SEG_BOUNDARY(q, b1, b2) \
        __BIO_SEG_BOUNDARY(bvec_to_phys((b1)), bvec_to_phys((b2)) + (b2)->bv_len, queue_segment_boundary((q)))
-#define BIO_SEG_BOUNDARY(q, b1, b2) \
-       BIOVEC_SEG_BOUNDARY((q), __BVEC_END((b1)), __BVEC_START((b2)))
 
 #define bio_io_error(bio) bio_endio((bio), -EIO)
 
-/*
- * drivers should not use the __ version unless they _really_ know what
- * they're doing
- */
-#define __bio_for_each_segment(bvl, bio, i, start_idx)                 \
-       for (bvl = bio_iovec_idx((bio), (start_idx)), i = (start_idx);  \
-            i < (bio)->bi_vcnt;                                        \
-            bvl++, i++)
-
 /*
  * drivers should _never_ use the all version - the bio may have been split
  * before it got to the driver and the driver won't own all of it
  */
 #define bio_for_each_segment_all(bvl, bio, i)                          \
-       for (i = 0;                                                     \
-            bvl = bio_iovec_idx((bio), (i)), i < (bio)->bi_vcnt;       \
-            i++)
+       for (i = 0, bvl = (bio)->bi_io_vec; i < (bio)->bi_vcnt; i++, bvl++)
+
+static inline void bvec_iter_advance(struct bio_vec *bv, struct bvec_iter *iter,
+                                    unsigned bytes)
+{
+       WARN_ONCE(bytes > iter->bi_size,
+                 "Attempted to advance past end of bvec iter\n");
+
+       while (bytes) {
+               unsigned len = min(bytes, bvec_iter_len(bv, *iter));
+
+               bytes -= len;
+               iter->bi_size -= len;
+               iter->bi_bvec_done += len;
+
+               if (iter->bi_bvec_done == __bvec_iter_bvec(bv, *iter)->bv_len) {
+                       iter->bi_bvec_done = 0;
+                       iter->bi_idx++;
+               }
+       }
+}
+
+#define for_each_bvec(bvl, bio_vec, iter, start)                       \
+       for ((iter) = start;                                            \
+            (bvl) = bvec_iter_bvec((bio_vec), (iter)),                 \
+               (iter).bi_size;                                         \
+            bvec_iter_advance((bio_vec), &(iter), (bvl).bv_len))
+
+
+static inline void bio_advance_iter(struct bio *bio, struct bvec_iter *iter,
+                                   unsigned bytes)
+{
+       iter->bi_sector += bytes >> 9;
+
+       if (bio->bi_rw & BIO_NO_ADVANCE_ITER_MASK)
+               iter->bi_size -= bytes;
+       else
+               bvec_iter_advance(bio->bi_io_vec, iter, bytes);
+}
 
-#define bio_for_each_segment(bvl, bio, i)                              \
-       for (i = (bio)->bi_idx;                                         \
-            bvl = bio_iovec_idx((bio), (i)), i < (bio)->bi_vcnt;       \
-            i++)
+#define __bio_for_each_segment(bvl, bio, iter, start)                  \
+       for (iter = (start);                                            \
+            (iter).bi_size &&                                          \
+               ((bvl = bio_iter_iovec((bio), (iter))), 1);             \
+            bio_advance_iter((bio), &(iter), (bvl).bv_len))
+
+#define bio_for_each_segment(bvl, bio, iter)                           \
+       __bio_for_each_segment(bvl, bio, iter, (bio)->bi_iter)
+
+#define bio_iter_last(bvec, iter) ((iter).bi_size == (bvec).bv_len)
+
+static inline unsigned bio_segments(struct bio *bio)
+{
+       unsigned segs = 0;
+       struct bio_vec bv;
+       struct bvec_iter iter;
+
+       bio_for_each_segment(bv, bio, iter)
+               segs++;
+
+       return segs;
+}
 
 /*
  * get a reference to a bio, so it won't disappear. the intended use is
@@ -177,16 +279,15 @@ static inline void *bio_data(struct bio *bio)
 struct bio_integrity_payload {
        struct bio              *bip_bio;       /* parent bio */
 
-       sector_t                bip_sector;     /* virtual start sector */
+       struct bvec_iter        bip_iter;
 
+       /* kill - should just use bip_vec */
        void                    *bip_buf;       /* generated integrity data */
-       bio_end_io_t            *bip_end_io;    /* saved I/O completion fn */
 
-       unsigned int            bip_size;
+       bio_end_io_t            *bip_end_io;    /* saved I/O completion fn */
 
        unsigned short          bip_slab;       /* slab the bip came from */
        unsigned short          bip_vcnt;       /* # of integrity bio_vecs */
-       unsigned short          bip_idx;        /* current bip_vec index */
        unsigned                bip_owns_buf:1; /* should free bip_buf */
 
        struct work_struct      bip_work;       /* I/O completion */
@@ -196,29 +297,28 @@ struct bio_integrity_payload {
 };
 #endif /* CONFIG_BLK_DEV_INTEGRITY */
 
-/*
- * A bio_pair is used when we need to split a bio.
- * This can only happen for a bio that refers to just one
- * page of data, and in the unusual situation when the
- * page crosses a chunk/device boundary
+extern void bio_trim(struct bio *bio, int offset, int size);
+extern struct bio *bio_split(struct bio *bio, int sectors,
+                            gfp_t gfp, struct bio_set *bs);
+
+/**
+ * bio_next_split - get next @sectors from a bio, splitting if necessary
+ * @bio:       bio to split
+ * @sectors:   number of sectors to split from the front of @bio
+ * @gfp:       gfp mask
+ * @bs:                bio set to allocate from
  *
- * The address of the master bio is stored in bio1.bi_private
- * The address of the pool the pair was allocated from is stored
- *   in bio2.bi_private
+ * Returns a bio representing the next @sectors of @bio - if the bio is smaller
+ * than @sectors, returns the original bio unchanged.
  */
-struct bio_pair {
-       struct bio                      bio1, bio2;
-       struct bio_vec                  bv1, bv2;
-#if defined(CONFIG_BLK_DEV_INTEGRITY)
-       struct bio_integrity_payload    bip1, bip2;
-       struct bio_vec                  iv1, iv2;
-#endif
-       atomic_t                        cnt;
-       int                             error;
-};
-extern struct bio_pair *bio_split(struct bio *bi, int first_sectors);
-extern void bio_pair_release(struct bio_pair *dbio);
-extern void bio_trim(struct bio *bio, int offset, int size);
+static inline struct bio *bio_next_split(struct bio *bio, int sectors,
+                                        gfp_t gfp, struct bio_set *bs)
+{
+       if (sectors >= bio_sectors(bio))
+               return bio;
+
+       return bio_split(bio, sectors, gfp, bs);
+}
 
 extern struct bio_set *bioset_create(unsigned int, unsigned int);
 extern void bioset_free(struct bio_set *);
@@ -227,7 +327,8 @@ extern mempool_t *biovec_create_pool(struct bio_set *bs, int pool_entries);
 extern struct bio *bio_alloc_bioset(gfp_t, int, struct bio_set *);
 extern void bio_put(struct bio *);
 
-extern void __bio_clone(struct bio *, struct bio *);
+extern void __bio_clone_fast(struct bio *, struct bio *);
+extern struct bio *bio_clone_fast(struct bio *, gfp_t, struct bio_set *);
 extern struct bio *bio_clone_bioset(struct bio *, gfp_t, struct bio_set *bs);
 
 extern struct bio_set *fs_bio_set;
@@ -254,6 +355,7 @@ static inline struct bio *bio_clone_kmalloc(struct bio *bio, gfp_t gfp_mask)
 }
 
 extern void bio_endio(struct bio *, int);
+extern void bio_endio_nodec(struct bio *, int);
 struct request_queue;
 extern int bio_phys_segments(struct request_queue *, struct bio *);
 
@@ -262,12 +364,12 @@ extern void bio_advance(struct bio *, unsigned);
 
 extern void bio_init(struct bio *);
 extern void bio_reset(struct bio *);
+void bio_chain(struct bio *, struct bio *);
 
 extern int bio_add_page(struct bio *, struct page *, unsigned int,unsigned int);
 extern int bio_add_pc_page(struct request_queue *, struct bio *, struct page *,
                           unsigned int, unsigned int);
 extern int bio_get_nr_vecs(struct block_device *);
-extern sector_t bio_sector_offset(struct bio *, unsigned short, unsigned int);
 extern struct bio *bio_map_user(struct request_queue *, struct block_device *,
                                unsigned long, unsigned int, int, gfp_t);
 struct sg_iovec;
@@ -357,47 +459,17 @@ static inline void bvec_kunmap_irq(char *buffer, unsigned long *flags)
 }
 #endif
 
-static inline char *__bio_kmap_irq(struct bio *bio, unsigned short idx,
+static inline char *__bio_kmap_irq(struct bio *bio, struct bvec_iter iter,
                                   unsigned long *flags)
 {
-       return bvec_kmap_irq(bio_iovec_idx(bio, idx), flags);
+       return bvec_kmap_irq(&bio_iter_iovec(bio, iter), flags);
 }
 #define __bio_kunmap_irq(buf, flags)   bvec_kunmap_irq(buf, flags)
 
 #define bio_kmap_irq(bio, flags) \
-       __bio_kmap_irq((bio), (bio)->bi_idx, (flags))
+       __bio_kmap_irq((bio), (bio)->bi_iter, (flags))
 #define bio_kunmap_irq(buf,flags)      __bio_kunmap_irq(buf, flags)
 
-/*
- * Check whether this bio carries any data or not. A NULL bio is allowed.
- */
-static inline bool bio_has_data(struct bio *bio)
-{
-       if (bio && bio->bi_vcnt)
-               return true;
-
-       return false;
-}
-
-static inline bool bio_is_rw(struct bio *bio)
-{
-       if (!bio_has_data(bio))
-               return false;
-
-       if (bio->bi_rw & REQ_WRITE_SAME)
-               return false;
-
-       return true;
-}
-
-static inline bool bio_mergeable(struct bio *bio)
-{
-       if (bio->bi_rw & REQ_NOMERGE_FLAGS)
-               return false;
-
-       return true;
-}
-
 /*
  * BIO list management for use by remapping drivers (e.g. DM or MD) and loop.
  *
@@ -559,16 +631,12 @@ struct biovec_slab {
 
 #if defined(CONFIG_BLK_DEV_INTEGRITY)
 
-#define bip_vec_idx(bip, idx)  (&(bip->bip_vec[(idx)]))
-#define bip_vec(bip)           bip_vec_idx(bip, 0)
 
-#define __bip_for_each_vec(bvl, bip, i, start_idx)                     \
-       for (bvl = bip_vec_idx((bip), (start_idx)), i = (start_idx);    \
-            i < (bip)->bip_vcnt;                                       \
-            bvl++, i++)
 
-#define bip_for_each_vec(bvl, bip, i)                                  \
-       __bip_for_each_vec(bvl, bip, i, (bip)->bip_idx)
+#define bip_vec_idx(bip, idx)  (&(bip->bip_vec[(idx)]))
+
+#define bip_for_each_vec(bvl, bip, iter)                               \
+       for_each_bvec(bvl, (bip)->bip_vec, iter, (bip)->bip_iter)
 
 #define bio_for_each_integrity_vec(_bvl, _bio, _iter)                  \
        for_each_bio(_bio)                                              \
@@ -586,7 +654,6 @@ extern int bio_integrity_prep(struct bio *);
 extern void bio_integrity_endio(struct bio *, int);
 extern void bio_integrity_advance(struct bio *, unsigned int);
 extern void bio_integrity_trim(struct bio *, unsigned int, unsigned int);
-extern void bio_integrity_split(struct bio *, struct bio_pair *, int);
 extern int bio_integrity_clone(struct bio *, struct bio *, gfp_t);
 extern int bioset_integrity_create(struct bio_set *, int);
 extern void bioset_integrity_free(struct bio_set *);
@@ -630,12 +697,6 @@ static inline int bio_integrity_clone(struct bio *bio, struct bio *bio_src,
        return 0;
 }
 
-static inline void bio_integrity_split(struct bio *bio, struct bio_pair *bp,
-                                      int sectors)
-{
-       return;
-}
-
 static inline void bio_integrity_advance(struct bio *bio,
                                         unsigned int bytes_done)
 {
index 238ef0ed62f85f18085b6446bc681d8c18d674dc..bbc3a6c88fce3410b954b6c91c407297e2f03e7f 100644 (file)
@@ -28,13 +28,22 @@ struct bio_vec {
        unsigned int    bv_offset;
 };
 
+struct bvec_iter {
+       sector_t                bi_sector;      /* device address in 512 byte
+                                                  sectors */
+       unsigned int            bi_size;        /* residual I/O count */
+
+       unsigned int            bi_idx;         /* current index into bvl_vec */
+
+       unsigned int            bi_bvec_done;   /* number of bytes completed in
+                                                  current bvec */
+};
+
 /*
  * main unit of I/O for the block layer and lower layers (ie drivers and
  * stacking drivers)
  */
 struct bio {
-       sector_t                bi_sector;      /* device address in 512 byte
-                                                  sectors */
        struct bio              *bi_next;       /* request queue link */
        struct block_device     *bi_bdev;
        unsigned long           bi_flags;       /* status, command, etc */
@@ -42,16 +51,13 @@ struct bio {
                                                 * top bits priority
                                                 */
 
-       unsigned short          bi_vcnt;        /* how many bio_vec's */
-       unsigned short          bi_idx;         /* current index into bvl_vec */
+       struct bvec_iter        bi_iter;
 
        /* Number of segments in this BIO after
         * physical address coalescing is performed.
         */
        unsigned int            bi_phys_segments;
 
-       unsigned int            bi_size;        /* residual I/O count */
-
        /*
         * To keep track of the max segment size, we account for the
         * sizes of the first and last mergeable segments in this bio.
@@ -59,6 +65,8 @@ struct bio {
        unsigned int            bi_seg_front_size;
        unsigned int            bi_seg_back_size;
 
+       atomic_t                bi_remaining;
+
        bio_end_io_t            *bi_end_io;
 
        void                    *bi_private;
@@ -74,11 +82,13 @@ struct bio {
        struct bio_integrity_payload *bi_integrity;  /* data integrity */
 #endif
 
+       unsigned short          bi_vcnt;        /* how many bio_vec's */
+
        /*
         * Everything starting with bi_max_vecs will be preserved by bio_reset()
         */
 
-       unsigned int            bi_max_vecs;    /* max bvl_vecs we can hold */
+       unsigned short          bi_max_vecs;    /* max bvl_vecs we can hold */
 
        atomic_t                bi_cnt;         /* pin count */
 
index 1b135d49b27985d3243cdbf92d6002ce5eea8597..02cb6f0ea71d52a09c3b2147f2bbc91997904650 100644 (file)
@@ -735,7 +735,7 @@ struct rq_map_data {
 };
 
 struct req_iterator {
-       int i;
+       struct bvec_iter iter;
        struct bio *bio;
 };
 
@@ -748,10 +748,11 @@ struct req_iterator {
 
 #define rq_for_each_segment(bvl, _rq, _iter)                   \
        __rq_for_each_bio(_iter.bio, _rq)                       \
-               bio_for_each_segment(bvl, _iter.bio, _iter.i)
+               bio_for_each_segment(bvl, _iter.bio, _iter.iter)
 
-#define rq_iter_last(rq, _iter)                                        \
-               (_iter.bio->bi_next == NULL && _iter.i == _iter.bio->bi_vcnt-1)
+#define rq_iter_last(bvec, _iter)                              \
+               (_iter.bio->bi_next == NULL &&                  \
+                bio_iter_last(bvec, _iter.iter))
 
 #ifndef ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE
 # error        "You should define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE for your platform"
diff --git a/include/linux/ccp.h b/include/linux/ccp.h
new file mode 100644 (file)
index 0000000..e8c2349
--- /dev/null
@@ -0,0 +1,525 @@
+/*
+ * AMD Cryptographic Coprocessor (CCP) driver
+ *
+ * Copyright (C) 2013 Advanced Micro Devices, Inc.
+ *
+ * Author: Tom Lendacky <thomas.lendacky@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __CPP_H__
+#define __CPP_H__
+
+#include <linux/scatterlist.h>
+#include <linux/workqueue.h>
+#include <linux/list.h>
+#include <crypto/aes.h>
+#include <crypto/sha.h>
+
+
+struct ccp_device;
+struct ccp_cmd;
+
+/**
+ * ccp_enqueue_cmd - queue an operation for processing by the CCP
+ *
+ * @cmd: ccp_cmd struct to be processed
+ *
+ * Refer to the ccp_cmd struct below for required fields.
+ *
+ * Queue a cmd to be processed by the CCP. If queueing the cmd
+ * would exceed the defined length of the cmd queue the cmd will
+ * only be queued if the CCP_CMD_MAY_BACKLOG flag is set and will
+ * result in a return code of -EBUSY.
+ *
+ * The callback routine specified in the ccp_cmd struct will be
+ * called to notify the caller of completion (if the cmd was not
+ * backlogged) or advancement out of the backlog. If the cmd has
+ * advanced out of the backlog the "err" value of the callback
+ * will be -EINPROGRESS. Any other "err" value during callback is
+ * the result of the operation.
+ *
+ * The cmd has been successfully queued if:
+ *   the return code is -EINPROGRESS or
+ *   the return code is -EBUSY and CCP_CMD_MAY_BACKLOG flag is set
+ */
+int ccp_enqueue_cmd(struct ccp_cmd *cmd);
+
+
+/***** AES engine *****/
+/**
+ * ccp_aes_type - AES key size
+ *
+ * @CCP_AES_TYPE_128: 128-bit key
+ * @CCP_AES_TYPE_192: 192-bit key
+ * @CCP_AES_TYPE_256: 256-bit key
+ */
+enum ccp_aes_type {
+       CCP_AES_TYPE_128 = 0,
+       CCP_AES_TYPE_192,
+       CCP_AES_TYPE_256,
+       CCP_AES_TYPE__LAST,
+};
+
+/**
+ * ccp_aes_mode - AES operation mode
+ *
+ * @CCP_AES_MODE_ECB: ECB mode
+ * @CCP_AES_MODE_CBC: CBC mode
+ * @CCP_AES_MODE_OFB: OFB mode
+ * @CCP_AES_MODE_CFB: CFB mode
+ * @CCP_AES_MODE_CTR: CTR mode
+ * @CCP_AES_MODE_CMAC: CMAC mode
+ */
+enum ccp_aes_mode {
+       CCP_AES_MODE_ECB = 0,
+       CCP_AES_MODE_CBC,
+       CCP_AES_MODE_OFB,
+       CCP_AES_MODE_CFB,
+       CCP_AES_MODE_CTR,
+       CCP_AES_MODE_CMAC,
+       CCP_AES_MODE__LAST,
+};
+
+/**
+ * ccp_aes_mode - AES operation mode
+ *
+ * @CCP_AES_ACTION_DECRYPT: AES decrypt operation
+ * @CCP_AES_ACTION_ENCRYPT: AES encrypt operation
+ */
+enum ccp_aes_action {
+       CCP_AES_ACTION_DECRYPT = 0,
+       CCP_AES_ACTION_ENCRYPT,
+       CCP_AES_ACTION__LAST,
+};
+
+/**
+ * struct ccp_aes_engine - CCP AES operation
+ * @type: AES operation key size
+ * @mode: AES operation mode
+ * @action: AES operation (decrypt/encrypt)
+ * @key: key to be used for this AES operation
+ * @key_len: length in bytes of key
+ * @iv: IV to be used for this AES operation
+ * @iv_len: length in bytes of iv
+ * @src: data to be used for this operation
+ * @dst: data produced by this operation
+ * @src_len: length in bytes of data used for this operation
+ * @cmac_final: indicates final operation when running in CMAC mode
+ * @cmac_key: K1/K2 key used in final CMAC operation
+ * @cmac_key_len: length in bytes of cmac_key
+ *
+ * Variables required to be set when calling ccp_enqueue_cmd():
+ *   - type, mode, action, key, key_len, src, dst, src_len
+ *   - iv, iv_len for any mode other than ECB
+ *   - cmac_final for CMAC mode
+ *   - cmac_key, cmac_key_len for CMAC mode if cmac_final is non-zero
+ *
+ * The iv variable is used as both input and output. On completion of the
+ * AES operation the new IV overwrites the old IV.
+ */
+struct ccp_aes_engine {
+       enum ccp_aes_type type;
+       enum ccp_aes_mode mode;
+       enum ccp_aes_action action;
+
+       struct scatterlist *key;
+       u32 key_len;            /* In bytes */
+
+       struct scatterlist *iv;
+       u32 iv_len;             /* In bytes */
+
+       struct scatterlist *src, *dst;
+       u32 src_len;            /* In bytes */
+
+       u32 cmac_final;         /* Indicates final cmac cmd */
+       struct scatterlist *cmac_key;   /* K1/K2 cmac key required for
+                                        * final cmac cmd */
+       u32 cmac_key_len;       /* In bytes */
+};
+
+/***** XTS-AES engine *****/
+/**
+ * ccp_xts_aes_unit_size - XTS unit size
+ *
+ * @CCP_XTS_AES_UNIT_SIZE_16: Unit size of 16 bytes
+ * @CCP_XTS_AES_UNIT_SIZE_512: Unit size of 512 bytes
+ * @CCP_XTS_AES_UNIT_SIZE_1024: Unit size of 1024 bytes
+ * @CCP_XTS_AES_UNIT_SIZE_2048: Unit size of 2048 bytes
+ * @CCP_XTS_AES_UNIT_SIZE_4096: Unit size of 4096 bytes
+ */
+enum ccp_xts_aes_unit_size {
+       CCP_XTS_AES_UNIT_SIZE_16 = 0,
+       CCP_XTS_AES_UNIT_SIZE_512,
+       CCP_XTS_AES_UNIT_SIZE_1024,
+       CCP_XTS_AES_UNIT_SIZE_2048,
+       CCP_XTS_AES_UNIT_SIZE_4096,
+       CCP_XTS_AES_UNIT_SIZE__LAST,
+};
+
+/**
+ * struct ccp_xts_aes_engine - CCP XTS AES operation
+ * @action: AES operation (decrypt/encrypt)
+ * @unit_size: unit size of the XTS operation
+ * @key: key to be used for this XTS AES operation
+ * @key_len: length in bytes of key
+ * @iv: IV to be used for this XTS AES operation
+ * @iv_len: length in bytes of iv
+ * @src: data to be used for this operation
+ * @dst: data produced by this operation
+ * @src_len: length in bytes of data used for this operation
+ * @final: indicates final XTS operation
+ *
+ * Variables required to be set when calling ccp_enqueue_cmd():
+ *   - action, unit_size, key, key_len, iv, iv_len, src, dst, src_len, final
+ *
+ * The iv variable is used as both input and output. On completion of the
+ * AES operation the new IV overwrites the old IV.
+ */
+struct ccp_xts_aes_engine {
+       enum ccp_aes_action action;
+       enum ccp_xts_aes_unit_size unit_size;
+
+       struct scatterlist *key;
+       u32 key_len;            /* In bytes */
+
+       struct scatterlist *iv;
+       u32 iv_len;             /* In bytes */
+
+       struct scatterlist *src, *dst;
+       u32 src_len;            /* In bytes */
+
+       u32 final;
+};
+
+/***** SHA engine *****/
+#define CCP_SHA_BLOCKSIZE               SHA256_BLOCK_SIZE
+#define CCP_SHA_CTXSIZE                 SHA256_DIGEST_SIZE
+
+/**
+ * ccp_sha_type - type of SHA operation
+ *
+ * @CCP_SHA_TYPE_1: SHA-1 operation
+ * @CCP_SHA_TYPE_224: SHA-224 operation
+ * @CCP_SHA_TYPE_256: SHA-256 operation
+ */
+enum ccp_sha_type {
+       CCP_SHA_TYPE_1 = 1,
+       CCP_SHA_TYPE_224,
+       CCP_SHA_TYPE_256,
+       CCP_SHA_TYPE__LAST,
+};
+
+/**
+ * struct ccp_sha_engine - CCP SHA operation
+ * @type: Type of SHA operation
+ * @ctx: current hash value
+ * @ctx_len: length in bytes of hash value
+ * @src: data to be used for this operation
+ * @src_len: length in bytes of data used for this operation
+ * @final: indicates final SHA operation
+ * @msg_bits: total length of the message in bits used in final SHA operation
+ *
+ * Variables required to be set when calling ccp_enqueue_cmd():
+ *   - type, ctx, ctx_len, src, src_len, final
+ *   - msg_bits if final is non-zero
+ *
+ * The ctx variable is used as both input and output. On completion of the
+ * SHA operation the new hash value overwrites the old hash value.
+ */
+struct ccp_sha_engine {
+       enum ccp_sha_type type;
+
+       struct scatterlist *ctx;
+       u32 ctx_len;            /* In bytes */
+
+       struct scatterlist *src;
+       u32 src_len;            /* In bytes */
+
+       u32 final;              /* Indicates final sha cmd */
+       u64 msg_bits;           /* Message length in bits required for
+                                * final sha cmd */
+};
+
+/***** RSA engine *****/
+/**
+ * struct ccp_rsa_engine - CCP RSA operation
+ * @key_size: length in bits of RSA key
+ * @exp: RSA exponent
+ * @exp_len: length in bytes of exponent
+ * @mod: RSA modulus
+ * @mod_len: length in bytes of modulus
+ * @src: data to be used for this operation
+ * @dst: data produced by this operation
+ * @src_len: length in bytes of data used for this operation
+ *
+ * Variables required to be set when calling ccp_enqueue_cmd():
+ *   - key_size, exp, exp_len, mod, mod_len, src, dst, src_len
+ */
+struct ccp_rsa_engine {
+       u32 key_size;           /* In bits */
+
+       struct scatterlist *exp;
+       u32 exp_len;            /* In bytes */
+
+       struct scatterlist *mod;
+       u32 mod_len;            /* In bytes */
+
+       struct scatterlist *src, *dst;
+       u32 src_len;            /* In bytes */
+};
+
+/***** Passthru engine *****/
+/**
+ * ccp_passthru_bitwise - type of bitwise passthru operation
+ *
+ * @CCP_PASSTHRU_BITWISE_NOOP: no bitwise operation performed
+ * @CCP_PASSTHRU_BITWISE_AND: perform bitwise AND of src with mask
+ * @CCP_PASSTHRU_BITWISE_OR: perform bitwise OR of src with mask
+ * @CCP_PASSTHRU_BITWISE_XOR: perform bitwise XOR of src with mask
+ * @CCP_PASSTHRU_BITWISE_MASK: overwrite with mask
+ */
+enum ccp_passthru_bitwise {
+       CCP_PASSTHRU_BITWISE_NOOP = 0,
+       CCP_PASSTHRU_BITWISE_AND,
+       CCP_PASSTHRU_BITWISE_OR,
+       CCP_PASSTHRU_BITWISE_XOR,
+       CCP_PASSTHRU_BITWISE_MASK,
+       CCP_PASSTHRU_BITWISE__LAST,
+};
+
+/**
+ * ccp_passthru_byteswap - type of byteswap passthru operation
+ *
+ * @CCP_PASSTHRU_BYTESWAP_NOOP: no byte swapping performed
+ * @CCP_PASSTHRU_BYTESWAP_32BIT: swap bytes within 32-bit words
+ * @CCP_PASSTHRU_BYTESWAP_256BIT: swap bytes within 256-bit words
+ */
+enum ccp_passthru_byteswap {
+       CCP_PASSTHRU_BYTESWAP_NOOP = 0,
+       CCP_PASSTHRU_BYTESWAP_32BIT,
+       CCP_PASSTHRU_BYTESWAP_256BIT,
+       CCP_PASSTHRU_BYTESWAP__LAST,
+};
+
+/**
+ * struct ccp_passthru_engine - CCP pass-through operation
+ * @bit_mod: bitwise operation to perform
+ * @byte_swap: byteswap operation to perform
+ * @mask: mask to be applied to data
+ * @mask_len: length in bytes of mask
+ * @src: data to be used for this operation
+ * @dst: data produced by this operation
+ * @src_len: length in bytes of data used for this operation
+ * @final: indicate final pass-through operation
+ *
+ * Variables required to be set when calling ccp_enqueue_cmd():
+ *   - bit_mod, byte_swap, src, dst, src_len
+ *   - mask, mask_len if bit_mod is not CCP_PASSTHRU_BITWISE_NOOP
+ */
+struct ccp_passthru_engine {
+       enum ccp_passthru_bitwise bit_mod;
+       enum ccp_passthru_byteswap byte_swap;
+
+       struct scatterlist *mask;
+       u32 mask_len;           /* In bytes */
+
+       struct scatterlist *src, *dst;
+       u32 src_len;            /* In bytes */
+
+       u32 final;
+};
+
+/***** ECC engine *****/
+#define CCP_ECC_MODULUS_BYTES  48      /* 384-bits */
+#define CCP_ECC_MAX_OPERANDS   6
+#define CCP_ECC_MAX_OUTPUTS    3
+
+/**
+ * ccp_ecc_function - type of ECC function
+ *
+ * @CCP_ECC_FUNCTION_MMUL_384BIT: 384-bit modular multiplication
+ * @CCP_ECC_FUNCTION_MADD_384BIT: 384-bit modular addition
+ * @CCP_ECC_FUNCTION_MINV_384BIT: 384-bit multiplicative inverse
+ * @CCP_ECC_FUNCTION_PADD_384BIT: 384-bit point addition
+ * @CCP_ECC_FUNCTION_PMUL_384BIT: 384-bit point multiplication
+ * @CCP_ECC_FUNCTION_PDBL_384BIT: 384-bit point doubling
+ */
+enum ccp_ecc_function {
+       CCP_ECC_FUNCTION_MMUL_384BIT = 0,
+       CCP_ECC_FUNCTION_MADD_384BIT,
+       CCP_ECC_FUNCTION_MINV_384BIT,
+       CCP_ECC_FUNCTION_PADD_384BIT,
+       CCP_ECC_FUNCTION_PMUL_384BIT,
+       CCP_ECC_FUNCTION_PDBL_384BIT,
+};
+
+/**
+ * struct ccp_ecc_modular_math - CCP ECC modular math parameters
+ * @operand_1: first operand for the modular math operation
+ * @operand_1_len: length of the first operand
+ * @operand_2: second operand for the modular math operation
+ *            (not used for CCP_ECC_FUNCTION_MINV_384BIT)
+ * @operand_2_len: length of the second operand
+ *            (not used for CCP_ECC_FUNCTION_MINV_384BIT)
+ * @result: result of the modular math operation
+ * @result_len: length of the supplied result buffer
+ */
+struct ccp_ecc_modular_math {
+       struct scatterlist *operand_1;
+       unsigned int operand_1_len;     /* In bytes */
+
+       struct scatterlist *operand_2;
+       unsigned int operand_2_len;     /* In bytes */
+
+       struct scatterlist *result;
+       unsigned int result_len;        /* In bytes */
+};
+
+/**
+ * struct ccp_ecc_point - CCP ECC point definition
+ * @x: the x coordinate of the ECC point
+ * @x_len: the length of the x coordinate
+ * @y: the y coordinate of the ECC point
+ * @y_len: the length of the y coordinate
+ */
+struct ccp_ecc_point {
+       struct scatterlist *x;
+       unsigned int x_len;     /* In bytes */
+
+       struct scatterlist *y;
+       unsigned int y_len;     /* In bytes */
+};
+
+/**
+ * struct ccp_ecc_point_math - CCP ECC point math parameters
+ * @point_1: the first point of the ECC point math operation
+ * @point_2: the second point of the ECC point math operation
+ *          (only used for CCP_ECC_FUNCTION_PADD_384BIT)
+ * @domain_a: the a parameter of the ECC curve
+ * @domain_a_len: the length of the a parameter
+ * @scalar: the scalar parameter for the point match operation
+ *         (only used for CCP_ECC_FUNCTION_PMUL_384BIT)
+ * @scalar_len: the length of the scalar parameter
+ *             (only used for CCP_ECC_FUNCTION_PMUL_384BIT)
+ * @result: the point resulting from the point math operation
+ */
+struct ccp_ecc_point_math {
+       struct ccp_ecc_point point_1;
+       struct ccp_ecc_point point_2;
+
+       struct scatterlist *domain_a;
+       unsigned int domain_a_len;      /* In bytes */
+
+       struct scatterlist *scalar;
+       unsigned int scalar_len;        /* In bytes */
+
+       struct ccp_ecc_point result;
+};
+
+/**
+ * struct ccp_ecc_engine - CCP ECC operation
+ * @function: ECC function to perform
+ * @mod: ECC modulus
+ * @mod_len: length in bytes of modulus
+ * @mm: module math parameters
+ * @pm: point math parameters
+ * @ecc_result: result of the ECC operation
+ *
+ * Variables required to be set when calling ccp_enqueue_cmd():
+ *   - function, mod, mod_len
+ *   - operand, operand_len, operand_count, output, output_len, output_count
+ *   - ecc_result
+ */
+struct ccp_ecc_engine {
+       enum ccp_ecc_function function;
+
+       struct scatterlist *mod;
+       u32 mod_len;            /* In bytes */
+
+       union {
+               struct ccp_ecc_modular_math mm;
+               struct ccp_ecc_point_math pm;
+       } u;
+
+       u16 ecc_result;
+};
+
+
+/**
+ * ccp_engine - CCP operation identifiers
+ *
+ * @CCP_ENGINE_AES: AES operation
+ * @CCP_ENGINE_XTS_AES: 128-bit XTS AES operation
+ * @CCP_ENGINE_RSVD1: unused
+ * @CCP_ENGINE_SHA: SHA operation
+ * @CCP_ENGINE_RSA: RSA operation
+ * @CCP_ENGINE_PASSTHRU: pass-through operation
+ * @CCP_ENGINE_ZLIB_DECOMPRESS: unused
+ * @CCP_ENGINE_ECC: ECC operation
+ */
+enum ccp_engine {
+       CCP_ENGINE_AES = 0,
+       CCP_ENGINE_XTS_AES_128,
+       CCP_ENGINE_RSVD1,
+       CCP_ENGINE_SHA,
+       CCP_ENGINE_RSA,
+       CCP_ENGINE_PASSTHRU,
+       CCP_ENGINE_ZLIB_DECOMPRESS,
+       CCP_ENGINE_ECC,
+       CCP_ENGINE__LAST,
+};
+
+/* Flag values for flags member of ccp_cmd */
+#define CCP_CMD_MAY_BACKLOG    0x00000001
+
+/**
+ * struct ccp_cmd - CPP operation request
+ * @entry: list element (ccp driver use only)
+ * @work: work element used for callbacks (ccp driver use only)
+ * @ccp: CCP device to be run on (ccp driver use only)
+ * @ret: operation return code (ccp driver use only)
+ * @flags: cmd processing flags
+ * @engine: CCP operation to perform
+ * @engine_error: CCP engine return code
+ * @u: engine specific structures, refer to specific engine struct below
+ * @callback: operation completion callback function
+ * @data: parameter value to be supplied to the callback function
+ *
+ * Variables required to be set when calling ccp_enqueue_cmd():
+ *   - engine, callback
+ *   - See the operation structures below for what is required for each
+ *     operation.
+ */
+struct ccp_cmd {
+       /* The list_head, work_struct, ccp and ret variables are for use
+        * by the CCP driver only.
+        */
+       struct list_head entry;
+       struct work_struct work;
+       struct ccp_device *ccp;
+       int ret;
+
+       u32 flags;
+
+       enum ccp_engine engine;
+       u32 engine_error;
+
+       union {
+               struct ccp_aes_engine aes;
+               struct ccp_xts_aes_engine xts;
+               struct ccp_sha_engine sha;
+               struct ccp_rsa_engine rsa;
+               struct ccp_passthru_engine passthru;
+               struct ccp_ecc_engine ecc;
+       } u;
+
+       /* Completion callback support */
+       void (*callback)(void *data, int err);
+       void *data;
+};
+
+#endif
index 7c1420bb1dcef40e6f8e4cc571ef5ea2c25df913..091fdb600d55bbde721ef15d06cbb5494e322ebc 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef __FS_CEPH_MESSENGER_H
 #define __FS_CEPH_MESSENGER_H
 
+#include <linux/blk_types.h>
 #include <linux/kref.h>
 #include <linux/mutex.h>
 #include <linux/net.h>
@@ -119,8 +120,7 @@ struct ceph_msg_data_cursor {
 #ifdef CONFIG_BLOCK
                struct {                                /* bio */
                        struct bio      *bio;           /* bio from list */
-                       unsigned int    vector_index;   /* vector from bio */
-                       unsigned int    vector_offset;  /* bytes from vector */
+                       struct bvec_iter bvec_iter;
                };
 #endif /* CONFIG_BLOCK */
                struct {                                /* pages */
index 39c1d946967778d29df5399d5ad222ff7a2ee2b8..cfaf416492dd69fd6a1ecaf857d6218a7a6e0201 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/xattr.h>
 #include <linux/fs.h>
 #include <linux/percpu-refcount.h>
+#include <linux/seq_file.h>
 
 #ifdef CONFIG_CGROUPS
 
@@ -29,7 +30,6 @@ struct cgroup_subsys;
 struct inode;
 struct cgroup;
 struct css_id;
-struct eventfd_ctx;
 
 extern int cgroup_init_early(void);
 extern int cgroup_init(void);
@@ -239,10 +239,6 @@ struct cgroup {
        struct rcu_head rcu_head;
        struct work_struct destroy_work;
 
-       /* List of events which userspace want to receive */
-       struct list_head event_list;
-       spinlock_t event_list_lock;
-
        /* directory xattrs */
        struct simple_xattrs xattrs;
 };
@@ -280,6 +276,9 @@ enum {
         * - "tasks" is removed.  Everything should be at process
         *   granularity.  Use "cgroup.procs" instead.
         *
+        * - "cgroup.procs" is not sorted.  pids will be unique unless they
+        *   got recycled inbetween reads.
+        *
         * - "release_agent" and "notify_on_release" are removed.
         *   Replacement notification mechanism will be implemented.
         *
@@ -320,9 +319,6 @@ struct cgroupfs_root {
        /* Unique id for this hierarchy. */
        int hierarchy_id;
 
-       /* A list running through the attached subsystems */
-       struct list_head subsys_list;
-
        /* The root cgroup for this hierarchy */
        struct cgroup top_cgroup;
 
@@ -388,16 +384,6 @@ struct css_set {
        struct rcu_head rcu_head;
 };
 
-/*
- * cgroup_map_cb is an abstract callback API for reporting map-valued
- * control files
- */
-
-struct cgroup_map_cb {
-       int (*fill)(struct cgroup_map_cb *cb, const char *key, u64 value);
-       void *state;
-};
-
 /*
  * struct cftype: handler definitions for cgroup control files
  *
@@ -445,10 +431,6 @@ struct cftype {
         */
        struct cgroup_subsys *ss;
 
-       int (*open)(struct inode *inode, struct file *file);
-       ssize_t (*read)(struct cgroup_subsys_state *css, struct cftype *cft,
-                       struct file *file,
-                       char __user *buf, size_t nbytes, loff_t *ppos);
        /*
         * read_u64() is a shortcut for the common case of returning a
         * single integer. Use it in place of read()
@@ -458,24 +440,14 @@ struct cftype {
         * read_s64() is a signed version of read_u64()
         */
        s64 (*read_s64)(struct cgroup_subsys_state *css, struct cftype *cft);
-       /*
-        * read_map() is used for defining a map of key/value
-        * pairs. It should call cb->fill(cb, key, value) for each
-        * entry. The key/value pairs (and their ordering) should not
-        * change between reboots.
-        */
-       int (*read_map)(struct cgroup_subsys_state *css, struct cftype *cft,
-                       struct cgroup_map_cb *cb);
-       /*
-        * read_seq_string() is used for outputting a simple sequence
-        * using seqfile.
-        */
-       int (*read_seq_string)(struct cgroup_subsys_state *css,
-                              struct cftype *cft, struct seq_file *m);
 
-       ssize_t (*write)(struct cgroup_subsys_state *css, struct cftype *cft,
-                        struct file *file,
-                        const char __user *buf, size_t nbytes, loff_t *ppos);
+       /* generic seq_file read interface */
+       int (*seq_show)(struct seq_file *sf, void *v);
+
+       /* optional ops, implement all or none */
+       void *(*seq_start)(struct seq_file *sf, loff_t *ppos);
+       void *(*seq_next)(struct seq_file *sf, void *v, loff_t *ppos);
+       void (*seq_stop)(struct seq_file *sf, void *v);
 
        /*
         * write_u64() is a shortcut for the common case of accepting
@@ -504,27 +476,6 @@ struct cftype {
         * kick type for multiplexing.
         */
        int (*trigger)(struct cgroup_subsys_state *css, unsigned int event);
-
-       int (*release)(struct inode *inode, struct file *file);
-
-       /*
-        * register_event() callback will be used to add new userspace
-        * waiter for changes related to the cftype. Implement it if
-        * you want to provide this functionality. Use eventfd_signal()
-        * on eventfd to send notification to userspace.
-        */
-       int (*register_event)(struct cgroup_subsys_state *css,
-                             struct cftype *cft, struct eventfd_ctx *eventfd,
-                             const char *args);
-       /*
-        * unregister_event() callback will be called when userspace
-        * closes the eventfd or on cgroup removing.
-        * This callback must be implemented, if you want provide
-        * notification functionality.
-        */
-       void (*unregister_event)(struct cgroup_subsys_state *css,
-                                struct cftype *cft,
-                                struct eventfd_ctx *eventfd);
 };
 
 /*
@@ -537,6 +488,26 @@ struct cftype_set {
        struct cftype                   *cfts;
 };
 
+/*
+ * cgroupfs file entry, pointed to from leaf dentry->d_fsdata.  Don't
+ * access directly.
+ */
+struct cfent {
+       struct list_head                node;
+       struct dentry                   *dentry;
+       struct cftype                   *type;
+       struct cgroup_subsys_state      *css;
+
+       /* file xattrs */
+       struct simple_xattrs            xattrs;
+};
+
+/* seq_file->private points to the following, only ->priv is public */
+struct cgroup_open_file {
+       struct cfent                    *cfe;
+       void                            *priv;
+};
+
 /*
  * See the comment above CGRP_ROOT_SANE_BEHAVIOR for details.  This
  * function can be called as long as @cgrp is accessible.
@@ -552,6 +523,18 @@ static inline const char *cgroup_name(const struct cgroup *cgrp)
        return rcu_dereference(cgrp->name)->name;
 }
 
+static inline struct cgroup_subsys_state *seq_css(struct seq_file *seq)
+{
+       struct cgroup_open_file *of = seq->private;
+       return of->cfe->css;
+}
+
+static inline struct cftype *seq_cft(struct seq_file *seq)
+{
+       struct cgroup_open_file *of = seq->private;
+       return of->cfe->type;
+}
+
 int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts);
 int cgroup_rm_cftypes(struct cftype *cfts);
 
@@ -631,12 +614,8 @@ struct cgroup_subsys {
 #define MAX_CGROUP_TYPE_NAMELEN 32
        const char *name;
 
-       /*
-        * Link to parent, and list entry in parent's children.
-        * Protected by cgroup_lock()
-        */
+       /* link to parent, protected by cgroup_lock() */
        struct cgroupfs_root *root;
-       struct list_head sibling;
 
        /* list of cftype_sets */
        struct list_head cftsets;
index 7e59253b86036b5d897a7b8e741c0ea3f5e4fdf4..534dc618f2d73314ef5374aff6b0eb27c89225a1 100644 (file)
@@ -512,6 +512,20 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
  * for improved portability across platforms
  */
 
+#if IS_ENABLED(CONFIG_PPC)
+
+static inline u32 clk_readl(u32 __iomem *reg)
+{
+       return ioread32be(reg);
+}
+
+static inline void clk_writel(u32 val, u32 __iomem *reg)
+{
+       iowrite32be(val, reg);
+}
+
+#else  /* platform dependent I/O accessors */
+
 static inline u32 clk_readl(u32 __iomem *reg)
 {
        return readl(reg);
@@ -522,5 +536,7 @@ static inline void clk_writel(u32 val, u32 __iomem *reg)
        writel(val, reg);
 }
 
+#endif /* platform dependent I/O accessors */
+
 #endif /* CONFIG_COMMON_CLK */
 #endif /* CLK_PROVIDER_H */
similarity index 98%
rename from arch/arm/mach-at91/include/mach/at91_pmc.h
rename to include/linux/clk/at91_pmc.h
index c604cc69acb5d790d0c1b1970e6dd8cffc7ad7e7..a6911ebbd02a024f3dffd028dc3d67fc13c0ef58 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * arch/arm/mach-at91/include/mach/at91_pmc.h
+ * include/linux/clk/at91_pmc.h
  *
  * Copyright (C) 2005 Ivan Kokshaysky
  * Copyright (C) SAN People
@@ -164,6 +164,8 @@ extern void __iomem *at91_pmc_base;
 #define                AT91_PMC_CFDEV          (1 << 18)               /* Clock Failure Detector Event [some SAM9] */
 #define        AT91_PMC_IMR            0x6c                    /* Interrupt Mask Register */
 
+#define AT91_PMC_PLLICPR       0x80                    /* PLL Charge Pump Current Register */
+
 #define AT91_PMC_PROT          0xe4                    /* Write Protect Mode Register [some SAM9] */
 #define                AT91_PMC_WPEN           (0x1  <<  0)            /* Write Protect Enable */
 #define                AT91_PMC_WPKEY          (0xffffff << 8)         /* Write Protect Key */
index 24545cd90a252b8dea0a9eec462b97a03b86adaa..02ae99e8e6d38a49ba59e76ecb722fce64376a51 100644 (file)
@@ -37,6 +37,9 @@
     __asm__ ("" : "=r"(__ptr) : "0"(ptr));             \
     (typeof(ptr)) (__ptr + (off)); })
 
+/* Make the optimizer believe the variable can be manipulated arbitrarily. */
+#define OPTIMIZER_HIDE_VAR(var) __asm__ ("" : "=r" (var) : "0" (var))
+
 #ifdef __CHECKER__
 #define __must_be_array(arr) 0
 #else
index 973ce10c40b651faa5d9e06f41eb49fefa492eab..e784f57077497f87e707f66f2718cfc2bba3dd84 100644 (file)
@@ -15,6 +15,7 @@
  */
 #undef barrier
 #undef RELOC_HIDE
+#undef OPTIMIZER_HIDE_VAR
 
 #define barrier() __memory_barrier()
 
      __ptr = (unsigned long) (ptr);                            \
     (typeof(ptr)) (__ptr + (off)); })
 
+/* This should act as an optimization barrier on var.
+ * Given that this compiler does not have inline assembly, a compiler barrier
+ * is the best we can do.
+ */
+#define OPTIMIZER_HIDE_VAR(var) barrier()
+
 /* Intel ECC compiler doesn't support __builtin_types_compatible_p() */
 #define __must_be_array(a) 0
 
index 92669cd182a6daca2550e2de8e4b8c7e2fd65a59..a2329c5e62062fee5157754b3cd3cce6494d661d 100644 (file)
@@ -170,6 +170,10 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect);
     (typeof(ptr)) (__ptr + (off)); })
 #endif
 
+#ifndef OPTIMIZER_HIDE_VAR
+#define OPTIMIZER_HIDE_VAR(var) barrier()
+#endif
+
 /* Not-quite-unique ID. */
 #ifndef __UNIQUE_ID
 # define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __LINE__)
index f4b0aa3126f5deae8ff8908375a9da1eca790ecf..a68cbe59e6ad190023e410cb32784b1fb6a67d2a 100644 (file)
@@ -29,7 +29,7 @@ typedef void (*io_notify_fn)(unsigned long error, void *context);
 
 enum dm_io_mem_type {
        DM_IO_PAGE_LIST,/* Page list */
-       DM_IO_BVEC,     /* Bio vector */
+       DM_IO_BIO,      /* Bio vector */
        DM_IO_VMA,      /* Virtual memory area */
        DM_IO_KMEM,     /* Kernel memory */
 };
@@ -41,7 +41,7 @@ struct dm_io_memory {
 
        union {
                struct page_list *pl;
-               struct bio_vec *bvec;
+               struct bio *bio;
                void *vma;
                void *addr;
        } ptr;
index 41cf0c399288e022edf32f7e65c6f151004829d9..bae1568416f81bb5037cd2c3d1ef88ed564a28e8 100644 (file)
@@ -22,6 +22,7 @@
 #define LINUX_DMAENGINE_H
 
 #include <linux/device.h>
+#include <linux/err.h>
 #include <linux/uio.h>
 #include <linux/bug.h>
 #include <linux/scatterlist.h>
@@ -1040,6 +1041,8 @@ enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx);
 void dma_issue_pending_all(void);
 struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask,
                                        dma_filter_fn fn, void *fn_param);
+struct dma_chan *dma_request_slave_channel_reason(struct device *dev,
+                                                 const char *name);
 struct dma_chan *dma_request_slave_channel(struct device *dev, const char *name);
 void dma_release_channel(struct dma_chan *chan);
 #else
@@ -1063,6 +1066,11 @@ static inline struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask,
 {
        return NULL;
 }
+static inline struct dma_chan *dma_request_slave_channel_reason(
+                                       struct device *dev, const char *name)
+{
+       return ERR_PTR(-ENODEV);
+}
 static inline struct dma_chan *dma_request_slave_channel(struct device *dev,
                                                         const char *name)
 {
@@ -1079,6 +1087,7 @@ int dma_async_device_register(struct dma_device *device);
 void dma_async_device_unregister(struct dma_device *device);
 void dma_run_dependencies(struct dma_async_tx_descriptor *tx);
 struct dma_chan *dma_get_slave_channel(struct dma_chan *chan);
+struct dma_chan *dma_get_any_slave_channel(struct dma_device *device);
 struct dma_chan *net_dma_find_channel(void);
 #define dma_request_channel(mask, x, y) __dma_request_channel(&(mask), x, y)
 #define dma_request_slave_channel_compat(mask, x, y, dev, name) \
index bc5687d0f3157c9d8d39342d4e69db1734baff16..49ece2ca3c570a2f589ef94588e031bbeb6654ce 100644 (file)
@@ -653,6 +653,7 @@ extern int __init efi_setup_pcdp_console(char *);
 #define EFI_RUNTIME_SERVICES   3       /* Can we use runtime services? */
 #define EFI_MEMMAP             4       /* Can we use EFI memory map? */
 #define EFI_64BIT              5       /* Is the firmware 64-bit? */
+#define EFI_ARCH_1             6       /* First arch-specific bit */
 
 #ifdef CONFIG_EFI
 # ifdef CONFIG_X86
@@ -801,6 +802,8 @@ struct efivar_entry {
        struct efi_variable var;
        struct list_head list;
        struct kobject kobj;
+       bool scanning;
+       bool deleting;
 };
 
 
@@ -866,6 +869,8 @@ void efivar_run_worker(void);
 #if defined(CONFIG_EFI_VARS) || defined(CONFIG_EFI_VARS_MODULE)
 int efivars_sysfs_init(void);
 
+#define EFIVARS_DATA_SIZE_MAX 1024
+
 #endif /* CONFIG_EFI_VARS */
 
 #endif /* _LINUX_EFI_H */
index fc4a9aa7dd82c7a26e69ac21cce27bdc399dc9b1..f344ac04f858bc7fa8789827fed9d02770b12fab 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/netdevice.h>
 #include <linux/random.h>
 #include <asm/unaligned.h>
+#include <asm/bitsperlong.h>
 
 #ifdef __KERNEL__
 __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev);
@@ -60,6 +61,8 @@ static const u8 eth_reserved_addr_base[ETH_ALEN] __aligned(2) =
  *
  * Return true if address is link local reserved addr (01:80:c2:00:00:0X) per
  * IEEE 802.1Q 8.6.3 Frame filtering.
+ *
+ * Please note: addr must be aligned to u16.
  */
 static inline bool is_link_local_ether_addr(const u8 *addr)
 {
@@ -67,7 +70,12 @@ static inline bool is_link_local_ether_addr(const u8 *addr)
        static const __be16 *b = (const __be16 *)eth_reserved_addr_base;
        static const __be16 m = cpu_to_be16(0xfff0);
 
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
+       return (((*(const u32 *)addr) ^ (*(const u32 *)b)) |
+               ((a[2] ^ b[2]) & m)) == 0;
+#else
        return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | ((a[2] ^ b[2]) & m)) == 0;
+#endif
 }
 
 /**
@@ -75,10 +83,18 @@ static inline bool is_link_local_ether_addr(const u8 *addr)
  * @addr: Pointer to a six-byte array containing the Ethernet address
  *
  * Return true if the address is all zeroes.
+ *
+ * Please note: addr must be aligned to u16.
  */
 static inline bool is_zero_ether_addr(const u8 *addr)
 {
-       return !(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]);
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
+       return ((*(const u32 *)addr) | (*(const u16 *)(addr + 4))) == 0;
+#else
+       return (*(const u16 *)(addr + 0) |
+               *(const u16 *)(addr + 2) |
+               *(const u16 *)(addr + 4)) == 0;
+#endif
 }
 
 /**
@@ -109,10 +125,14 @@ static inline bool is_local_ether_addr(const u8 *addr)
  * @addr: Pointer to a six-byte array containing the Ethernet address
  *
  * Return true if the address is the broadcast address.
+ *
+ * Please note: addr must be aligned to u16.
  */
 static inline bool is_broadcast_ether_addr(const u8 *addr)
 {
-       return (addr[0] & addr[1] & addr[2] & addr[3] & addr[4] & addr[5]) == 0xff;
+       return (*(const u16 *)(addr + 0) &
+               *(const u16 *)(addr + 2) &
+               *(const u16 *)(addr + 4)) == 0xffff;
 }
 
 /**
@@ -134,6 +154,8 @@ static inline bool is_unicast_ether_addr(const u8 *addr)
  * a multicast address, and is not FF:FF:FF:FF:FF:FF.
  *
  * Return true if the address is valid.
+ *
+ * Please note: addr must be aligned to u16.
  */
 static inline bool is_valid_ether_addr(const u8 *addr)
 {
@@ -210,41 +232,27 @@ static inline void eth_hw_addr_inherit(struct net_device *dst,
        memcpy(dst->dev_addr, src->dev_addr, ETH_ALEN);
 }
 
-/**
- * compare_ether_addr - Compare two Ethernet addresses
- * @addr1: Pointer to a six-byte array containing the Ethernet address
- * @addr2: Pointer other six-byte array containing the Ethernet address
- *
- * Compare two Ethernet addresses, returns 0 if equal, non-zero otherwise.
- * Unlike memcmp(), it doesn't return a value suitable for sorting.
- */
-static inline unsigned compare_ether_addr(const u8 *addr1, const u8 *addr2)
-{
-       const u16 *a = (const u16 *) addr1;
-       const u16 *b = (const u16 *) addr2;
-
-       BUILD_BUG_ON(ETH_ALEN != 6);
-       return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) != 0;
-}
-
 /**
  * ether_addr_equal - Compare two Ethernet addresses
  * @addr1: Pointer to a six-byte array containing the Ethernet address
  * @addr2: Pointer other six-byte array containing the Ethernet address
  *
  * Compare two Ethernet addresses, returns true if equal
+ *
+ * Please note: addr1 & addr2 must both be aligned to u16.
  */
 static inline bool ether_addr_equal(const u8 *addr1, const u8 *addr2)
 {
-       return !compare_ether_addr(addr1, addr2);
-}
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
+       u32 fold = ((*(const u32 *)addr1) ^ (*(const u32 *)addr2)) |
+                  ((*(const u16 *)(addr1 + 4)) ^ (*(const u16 *)(addr2 + 4)));
 
-static inline unsigned long zap_last_2bytes(unsigned long value)
-{
-#ifdef __BIG_ENDIAN
-       return value >> 16;
+       return fold == 0;
 #else
-       return value << 16;
+       const u16 *a = (const u16 *)addr1;
+       const u16 *b = (const u16 *)addr2;
+
+       return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) == 0;
 #endif
 }
 
@@ -265,21 +273,37 @@ static inline unsigned long zap_last_2bytes(unsigned long value)
 static inline bool ether_addr_equal_64bits(const u8 addr1[6+2],
                                           const u8 addr2[6+2])
 {
-#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
-       unsigned long fold = ((*(unsigned long *)addr1) ^
-                             (*(unsigned long *)addr2));
-
-       if (sizeof(fold) == 8)
-               return zap_last_2bytes(fold) == 0;
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
+       u64 fold = (*(const u64 *)addr1) ^ (*(const u64 *)addr2);
 
-       fold |= zap_last_2bytes((*(unsigned long *)(addr1 + 4)) ^
-                               (*(unsigned long *)(addr2 + 4)));
-       return fold == 0;
+#ifdef __BIG_ENDIAN
+       return (fold >> 16) == 0;
+#else
+       return (fold << 16) == 0;
+#endif
 #else
        return ether_addr_equal(addr1, addr2);
 #endif
 }
 
+/**
+ * ether_addr_equal_unaligned - Compare two not u16 aligned Ethernet addresses
+ * @addr1: Pointer to a six-byte array containing the Ethernet address
+ * @addr2: Pointer other six-byte array containing the Ethernet address
+ *
+ * Compare two Ethernet addresses, returns true if equal
+ *
+ * Please note: Use only when any Ethernet address may not be u16 aligned.
+ */
+static inline bool ether_addr_equal_unaligned(const u8 *addr1, const u8 *addr2)
+{
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
+       return ether_addr_equal(addr1, addr2);
+#else
+       return memcmp(addr1, addr2, ETH_ALEN) == 0;
+#endif
+}
+
 /**
  * is_etherdev_addr - Tell if given Ethernet address belongs to the device.
  * @dev: Pointer to a device structure
index bb942f6d5702912218abfc43134660dc0b4ea21f..aea5eedbb1ca042314fc9c422b420324bacdf063 100644 (file)
@@ -153,6 +153,14 @@ struct f2fs_extent {
 #define        NODE_DIND_BLOCK         (DEF_ADDRS_PER_INODE + 5)
 
 #define F2FS_INLINE_XATTR      0x01    /* file inline xattr flag */
+#define F2FS_INLINE_DATA       0x02    /* file inline data flag */
+
+
+#define MAX_INLINE_DATA                (sizeof(__le32) * (DEF_ADDRS_PER_INODE - \
+                                               F2FS_INLINE_XATTR_ADDRS - 1))
+
+#define INLINE_DATA_OFFSET     (PAGE_CACHE_SIZE - sizeof(struct node_footer) \
+                               - sizeof(__le32)*(DEF_ADDRS_PER_INODE + 5 - 1))
 
 struct f2fs_inode {
        __le16 i_mode;                  /* file mode */
index 9abbe630c456775b19cc999f36887efa94bbdd41..8c9b7a1c4138b87a79833bc400370a13e94cf270 100644 (file)
@@ -248,6 +248,9 @@ struct ftrace_event_call {
 #ifdef CONFIG_PERF_EVENTS
        int                             perf_refcount;
        struct hlist_head __percpu      *perf_events;
+
+       int     (*perf_perm)(struct ftrace_event_call *,
+                            struct perf_event *);
 #endif
 };
 
@@ -317,6 +320,19 @@ struct ftrace_event_file {
        }                                                               \
        early_initcall(trace_init_flags_##name);
 
+#define __TRACE_EVENT_PERF_PERM(name, expr...)                         \
+       static int perf_perm_##name(struct ftrace_event_call *tp_event, \
+                                   struct perf_event *p_event)         \
+       {                                                               \
+               return ({ expr; });                                     \
+       }                                                               \
+       static int __init trace_init_perf_perm_##name(void)             \
+       {                                                               \
+               event_##name.perf_perm = &perf_perm_##name;             \
+               return 0;                                               \
+       }                                                               \
+       early_initcall(trace_init_perf_perm_##name);
+
 #define PERF_MAX_TRACE_SIZE    2048
 
 #define MAX_FILTER_STR_VAL     256     /* Should handle KSYM_SYMBOL_LEN */
index 82eac610ce1a77ba944ee99d4afe6c921690b3c5..3ea2cf6b0e6ce444f732e489fbf97c8a44969515 100644 (file)
@@ -2,9 +2,12 @@
 #define __LINUX_GPIO_DRIVER_H
 
 #include <linux/types.h>
+#include <linux/module.h>
 
 struct device;
 struct gpio_desc;
+struct of_phandle_args;
+struct device_node;
 struct seq_file;
 
 /**
index 206a2af6b62b176fbbb16e2cca923053edc5877a..b914ca3f57ba4469264034cd521bf2cdc43b0cfb 100644 (file)
@@ -42,6 +42,8 @@ struct hid_sensor_hub_attribute_info {
        s32 units;
        s32 unit_expo;
        s32 size;
+       s32 logical_minimum;
+       s32 logical_maximum;
 };
 
 /**
index 4f945d3ed49fc7a511affdc307ea84aff60565cb..8323775ac21d0a86d2bda5a9ee93d2cfad181f78 100644 (file)
 #define HID_USAGE_SENSOR_PROP_REPORT_STATE                     0x200316
 #define HID_USAGE_SENSOR_PROY_POWER_STATE                      0x200319
 
+/* Power state enumerations */
+#define HID_USAGE_SENSOR_PROP_POWER_STATE_UNDEFINED_ENUM               0x00
+#define HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM           0x01
+#define HID_USAGE_SENSOR_PROP_POWER_STATE_D1_LOW_POWER_ENUM            0x02
+#define HID_USAGE_SENSOR_PROP_POWER_STATE_D2_STANDBY_WITH_WAKE_ENUM    0x03
+#define HID_USAGE_SENSOR_PROP_POWER_STATE_D3_SLEEP_WITH_WAKE_ENUM      0x04
+#define HID_USAGE_SENSOR_PROP_POWER_STATE_D4_POWER_OFF_ENUM            0x05
+
+/* Report State enumerations */
+#define HID_USAGE_SENSOR_PROP_REPORTING_STATE_NO_EVENTS_ENUM           0x00
+#define HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM          0x01
+
 #endif
index 506a9f7af51e6a5dc4766f62d19dda5279d06e7e..4f35b6ad3889fac069910379c48b149dea413358 100644 (file)
@@ -7,16 +7,14 @@ struct tsc2007_platform_data {
        u16     model;                          /* 2007. */
        u16     x_plate_ohms;   /* must be non-zero value */
        u16     max_rt; /* max. resistance above which samples are ignored */
-       unsigned long poll_delay; /* delay (in ms) after pen-down event
-                                    before polling starts */
        unsigned long poll_period; /* time (in ms) between samples */
        int     fuzzx; /* fuzz factor for X, Y and pressure axes */
        int     fuzzy;
        int     fuzzz;
 
-       int     (*get_pendown_state)(void);
-       void    (*clear_penirq)(void);          /* If needed, clear 2nd level
-                                                  interrupt source */
+       int     (*get_pendown_state)(struct device *);
+       /* If needed, clear 2nd level interrupt source */
+       void    (*clear_penirq)(void);
        int     (*init_platform_hw)(void);
        void    (*exit_platform_hw)(void);
 };
index 46a14229a162cf2bc5cc5e5b096c10c120766d8d..93b5ca754b5b4c4931aa2b3f66cf246312cedbd8 100644 (file)
 #include <linux/completion.h>
 #include <linux/pm.h>
 #include <linux/mutex.h>
-#ifdef CONFIG_BLK_DEV_IDEACPI
-#include <acpi/acpi.h>
-#endif
-#include <asm/byteorder.h>
-#include <asm/io.h>
-
 /* for request_sense */
 #include <linux/cdrom.h>
+#include <asm/byteorder.h>
+#include <asm/io.h>
 
 #if defined(CONFIG_CRIS) || defined(CONFIG_FRV) || defined(CONFIG_MN10300)
 # define SUPPORT_VLB_SYNC 0
index 8c3b26a215745b755a5018764e4c0ca1f1bd52b7..776cbb80d098d37e90c0bf0e8c37736ab961f338 100644 (file)
@@ -1411,8 +1411,12 @@ struct ieee80211_vht_operation {
 #define IEEE80211_VHT_CAP_RXSTBC_MASK                          0x00000700
 #define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE                        0x00000800
 #define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE                        0x00001000
-#define IEEE80211_VHT_CAP_BEAMFORMEE_STS_MAX                   0x0000e000
-#define IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MAX              0x00070000
+#define IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT                  13
+#define IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK                  \
+               (7 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT)
+#define IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT            16
+#define IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK             \
+               (7 << IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT)
 #define IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE                        0x00080000
 #define IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE                        0x00100000
 #define IEEE80211_VHT_CAP_VHT_TXOP_PS                          0x00200000
index 0d678aefe69df6155b683ce039a42e4b7c4a1cab..0068708161ffa6954f320d7de7d4ebb86dd2a889 100644 (file)
@@ -136,8 +136,8 @@ struct in_ifaddr {
        __be32                  ifa_mask;
        __be32                  ifa_broadcast;
        unsigned char           ifa_scope;
-       unsigned char           ifa_flags;
        unsigned char           ifa_prefixlen;
+       __u32                   ifa_flags;
        char                    ifa_label[IFNAMSIZ];
 
        /* In seconds, relative to tstamp. Expiry is at tstamp + HZ * lft. */
@@ -164,11 +164,10 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *);
 void devinet_init(void);
 struct in_device *inetdev_by_index(struct net *, int);
 __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope);
-__be32 inet_confirm_addr(struct in_device *in_dev, __be32 dst, __be32 local,
-                        int scope);
+__be32 inet_confirm_addr(struct net *net, struct in_device *in_dev, __be32 dst,
+                        __be32 local, int scope);
 struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, __be32 prefix,
                                    __be32 mask);
-
 static __inline__ int inet_ifa_match(__be32 addr, struct in_ifaddr *ifa)
 {
        return !((addr^ifa->ifa_address)&ifa->ifa_mask);
@@ -220,6 +219,13 @@ static inline struct in_device *__in_dev_get_rtnl(const struct net_device *dev)
        return rtnl_dereference(dev->ip_ptr);
 }
 
+static inline struct neigh_parms *__in_dev_arp_parms_get_rcu(const struct net_device *dev)
+{
+       struct in_device *in_dev = __in_dev_get_rcu(dev);
+
+       return in_dev ? in_dev->arp_parms : NULL;
+}
+
 void in_dev_finish_destroy(struct in_device *idev);
 
 static inline void in_dev_put(struct in_device *idev)
index 5d89d1b808a6cc896f22332c477126c3d2f2b563..3fde066455535ca98044c8548660e5e6a2279a9d 100644 (file)
@@ -4,6 +4,7 @@
 #include <uapi/linux/ipv6.h>
 
 #define ipv6_optlen(p)  (((p)->hdrlen+1) << 3)
+#define ipv6_authlen(p) (((p)->hdrlen+2) << 2)
 /*
  * This structure contains configuration options per IPv6 link.
  */
@@ -199,7 +200,7 @@ struct ipv6_pinfo {
                                dontfrag:1;
        __u8                    min_hopcount;
        __u8                    tclass;
-       __u8                    rcv_tclass;
+       __be32                  rcv_flowinfo;
 
        __u32                   dst_cookie;
        __u32                   rx_dst_cookie;
diff --git a/include/linux/irqchip/xtensa-mx.h b/include/linux/irqchip/xtensa-mx.h
new file mode 100644 (file)
index 0000000..9c3b6ec
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Xtensa MX interrupt distributor
+ *
+ * Copyright (C) 2002 - 2013 Tensilica, Inc.
+ *
+ * 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 __LINUX_IRQCHIP_XTENSA_MX_H
+#define __LINUX_IRQCHIP_XTENSA_MX_H
+
+struct device_node;
+int xtensa_mx_init_legacy(struct device_node *interrupt_parent);
+
+#endif /* __LINUX_IRQCHIP_XTENSA_MX_H */
diff --git a/include/linux/irqchip/xtensa-pic.h b/include/linux/irqchip/xtensa-pic.h
new file mode 100644 (file)
index 0000000..48718ae
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Xtensa built-in interrupt controller
+ *
+ * Copyright (C) 2002 - 2013 Tensilica, Inc.
+ * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
+ *
+ * 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 __LINUX_IRQCHIP_XTENSA_PIC_H
+#define __LINUX_IRQCHIP_XTENSA_PIC_H
+
+struct device_node;
+int xtensa_pic_init_legacy(struct device_node *interrupt_parent);
+
+#endif /* __LINUX_IRQCHIP_XTENSA_PIC_H */
index 714ba08dc09265922fe8ab81dee1caadc12a9100..e374e369fb2f4c9eb5ace48679376550d5ee633c 100644 (file)
@@ -14,6 +14,6 @@ enum irqreturn {
 };
 
 typedef enum irqreturn irqreturn_t;
-#define IRQ_RETVAL(x)  ((x) != IRQ_NONE)
+#define IRQ_RETVAL(x)  ((x) ? IRQ_HANDLED : IRQ_NONE)
 
 #endif
index 8ba7e5b9d62cb466f60cced5c8340261acf9fc4f..82f9673c2527c842dbd28f12a0bc6b0f7af96ed0 100644 (file)
@@ -21,7 +21,7 @@
 #ifndef ISCSI_IBFT_H
 #define ISCSI_IBFT_H
 
-#include <acpi/acpi.h>
+#include <acpi/acpi.h> /* FIXME: inclusion should be removed */
 
 /*
  * Logical location of iSCSI Boot Format Table.
index d4e98d13eff4bda01b08313986b63135cc80ee2b..2ac02772a86e3c1db0be81c7fb68d331aba02977 100644 (file)
@@ -393,6 +393,15 @@ extern int panic_on_oops;
 extern int panic_on_unrecovered_nmi;
 extern int panic_on_io_nmi;
 extern int sysctl_panic_on_stackoverflow;
+/*
+ * Only to be used by arch init code. If the user over-wrote the default
+ * CONFIG_PANIC_TIMEOUT, honor it.
+ */
+static inline void set_arch_panic_timeout(int timeout, int arch_default_timeout)
+{
+       if (panic_timeout == arch_default_timeout)
+               panic_timeout = timeout;
+}
 extern const char *print_tainted(void);
 enum lockdep_ok {
        LOCKDEP_STILL_OK,
index d78d28a733b15afdc25a620ca5925f6619f82a2c..5fd33dc1fe3ad265d352ed48f3a8cdeec0ca646e 100644 (file)
@@ -198,6 +198,9 @@ extern u32 vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4];
 extern size_t vmcoreinfo_size;
 extern size_t vmcoreinfo_max_size;
 
+/* flag to track if kexec reboot is in progress */
+extern bool kexec_in_progress;
+
 int __init parse_crashkernel(char *cmdline, unsigned long long system_ram,
                unsigned long long *crash_size, unsigned long long *crash_base);
 int parse_crashkernel_high(char *cmdline, unsigned long long system_ram,
diff --git a/include/linux/mfd/abx500/ab8500-gpio.h b/include/linux/mfd/abx500/ab8500-gpio.h
deleted file mode 100644 (file)
index 172b2f2..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright ST-Ericsson 2010.
- *
- * Author: Bibek Basu <bibek.basu@stericsson.com>
- * Licensed under GPLv2.
- */
-
-#ifndef _AB8500_GPIO_H
-#define _AB8500_GPIO_H
-
-/*
- * Platform data to register a block: only the initial gpio/irq number.
- * Array sizes are large enough to contain all AB8500 and AB9540 GPIO
- * registers.
- */
-
-struct abx500_gpio_platform_data {
-       int gpio_base;
-};
-
-enum abx500_gpio_pull_updown {
-       ABX500_GPIO_PULL_DOWN = 0x0,
-       ABX500_GPIO_PULL_NONE = 0x1,
-       ABX500_GPIO_PULL_UP = 0x3,
-};
-
-enum abx500_gpio_vinsel {
-       ABX500_GPIO_VINSEL_VBAT = 0x0,
-       ABX500_GPIO_VINSEL_VIN_1V8 = 0x1,
-       ABX500_GPIO_VINSEL_VDD_BIF = 0x2,
-};
-
-#endif /* _AB8500_GPIO_H */
index f4acd898dac974e40ef8ee2f71972a91009d2277..a86ca1406fb87ca11a656c72047b073a22c23e1b 100644 (file)
@@ -368,7 +368,6 @@ struct ab8500 {
 };
 
 struct ab8500_regulator_platform_data;
-struct ab8500_gpio_platform_data;
 struct ab8500_codec_platform_data;
 struct ab8500_sysctrl_platform_data;
 
@@ -382,7 +381,6 @@ struct ab8500_platform_data {
        int irq_base;
        void (*init) (struct ab8500 *);
        struct ab8500_regulator_platform_data *regulator;
-       struct abx500_gpio_platform_data *gpio;
        struct ab8500_codec_platform_data *codec;
        struct ab8500_sysctrl_platform_data *sysctrl;
 };
index cb49417f8ba9261ba436fef11851274f9df977d0..89878149a43f60d78de29c23de76ca47f8b5a006 100644 (file)
 #define ARIZONA_INPUT_ENABLES_STATUS             0x301
 #define ARIZONA_INPUT_RATE                       0x308
 #define ARIZONA_INPUT_VOLUME_RAMP                0x309
+#define ARIZONA_HPF_CONTROL                      0x30C
 #define ARIZONA_IN1L_CONTROL                     0x310
 #define ARIZONA_ADC_DIGITAL_VOLUME_1L            0x311
 #define ARIZONA_DMIC1L_CONTROL                   0x312
 #define ARIZONA_IN4L_CONTROL                     0x328
 #define ARIZONA_ADC_DIGITAL_VOLUME_4L            0x329
 #define ARIZONA_DMIC4L_CONTROL                   0x32A
+#define ARIZONA_IN4R_CONTROL                     0x32C
 #define ARIZONA_ADC_DIGITAL_VOLUME_4R            0x32D
 #define ARIZONA_DMIC4R_CONTROL                   0x32E
 #define ARIZONA_OUTPUT_ENABLES_1                 0x400
 #define ARIZONA_AIF2TX2MIX_INPUT_3_VOLUME        0x74D
 #define ARIZONA_AIF2TX2MIX_INPUT_4_SOURCE        0x74E
 #define ARIZONA_AIF2TX2MIX_INPUT_4_VOLUME        0x74F
+#define ARIZONA_AIF2TX3MIX_INPUT_1_SOURCE        0x750
+#define ARIZONA_AIF2TX3MIX_INPUT_1_VOLUME        0x751
+#define ARIZONA_AIF2TX3MIX_INPUT_2_SOURCE        0x752
+#define ARIZONA_AIF2TX3MIX_INPUT_2_VOLUME        0x753
+#define ARIZONA_AIF2TX3MIX_INPUT_3_SOURCE        0x754
+#define ARIZONA_AIF2TX3MIX_INPUT_3_VOLUME        0x755
+#define ARIZONA_AIF2TX3MIX_INPUT_4_SOURCE        0x756
+#define ARIZONA_AIF2TX3MIX_INPUT_4_VOLUME        0x757
+#define ARIZONA_AIF2TX4MIX_INPUT_1_SOURCE        0x758
+#define ARIZONA_AIF2TX4MIX_INPUT_1_VOLUME        0x759
+#define ARIZONA_AIF2TX4MIX_INPUT_2_SOURCE        0x75A
+#define ARIZONA_AIF2TX4MIX_INPUT_2_VOLUME        0x75B
+#define ARIZONA_AIF2TX4MIX_INPUT_3_SOURCE        0x75C
+#define ARIZONA_AIF2TX4MIX_INPUT_3_VOLUME        0x75D
+#define ARIZONA_AIF2TX4MIX_INPUT_4_SOURCE        0x75E
+#define ARIZONA_AIF2TX4MIX_INPUT_4_VOLUME        0x75F
+#define ARIZONA_AIF2TX5MIX_INPUT_1_SOURCE        0x760
+#define ARIZONA_AIF2TX5MIX_INPUT_1_VOLUME        0x761
+#define ARIZONA_AIF2TX5MIX_INPUT_2_SOURCE        0x762
+#define ARIZONA_AIF2TX5MIX_INPUT_2_VOLUME        0x763
+#define ARIZONA_AIF2TX5MIX_INPUT_3_SOURCE        0x764
+#define ARIZONA_AIF2TX5MIX_INPUT_3_VOLUME        0x765
+#define ARIZONA_AIF2TX5MIX_INPUT_4_SOURCE        0x766
+#define ARIZONA_AIF2TX5MIX_INPUT_4_VOLUME        0x767
+#define ARIZONA_AIF2TX6MIX_INPUT_1_SOURCE        0x768
+#define ARIZONA_AIF2TX6MIX_INPUT_1_VOLUME        0x769
+#define ARIZONA_AIF2TX6MIX_INPUT_2_SOURCE        0x76A
+#define ARIZONA_AIF2TX6MIX_INPUT_2_VOLUME        0x76B
+#define ARIZONA_AIF2TX6MIX_INPUT_3_SOURCE        0x76C
+#define ARIZONA_AIF2TX6MIX_INPUT_3_VOLUME        0x76D
+#define ARIZONA_AIF2TX6MIX_INPUT_4_SOURCE        0x76E
+#define ARIZONA_AIF2TX6MIX_INPUT_4_VOLUME        0x76F
 #define ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE        0x780
 #define ARIZONA_AIF3TX1MIX_INPUT_1_VOLUME        0x781
 #define ARIZONA_AIF3TX1MIX_INPUT_2_SOURCE        0x782
 #define ARIZONA_IN_VI_RAMP_SHIFT                      0  /* IN_VI_RAMP - [2:0] */
 #define ARIZONA_IN_VI_RAMP_WIDTH                      3  /* IN_VI_RAMP - [2:0] */
 
+/*
+ * R780 (0x30C) - HPF Control
+ */
+#define ARIZONA_IN_HPF_CUT_MASK                  0x0007  /* IN_HPF_CUT [2:0] */
+#define ARIZONA_IN_HPF_CUT_SHIFT                      0  /* IN_HPF_CUT [2:0] */
+#define ARIZONA_IN_HPF_CUT_WIDTH                      3  /* IN_HPF_CUT [2:0] */
+
 /*
  * R784 (0x310) - IN1L Control
  */
+#define ARIZONA_IN1L_HPF_MASK                    0x8000  /* IN1L_HPF - [15] */
+#define ARIZONA_IN1L_HPF_SHIFT                       15  /* IN1L_HPF - [15] */
+#define ARIZONA_IN1L_HPF_WIDTH                        1  /* IN1L_HPF - [15] */
 #define ARIZONA_IN1_OSR_MASK                     0x6000  /* IN1_OSR - [14:13] */
 #define ARIZONA_IN1_OSR_SHIFT                        13  /* IN1_OSR - [14:13] */
 #define ARIZONA_IN1_OSR_WIDTH                         2  /* IN1_OSR - [14:13] */
 /*
  * R788 (0x314) - IN1R Control
  */
+#define ARIZONA_IN1R_HPF_MASK                    0x8000  /* IN1R_HPF - [15] */
+#define ARIZONA_IN1R_HPF_SHIFT                       15  /* IN1R_HPF - [15] */
+#define ARIZONA_IN1R_HPF_WIDTH                        1  /* IN1R_HPF - [15] */
 #define ARIZONA_IN1R_PGA_VOL_MASK                0x00FE  /* IN1R_PGA_VOL - [7:1] */
 #define ARIZONA_IN1R_PGA_VOL_SHIFT                    1  /* IN1R_PGA_VOL - [7:1] */
 #define ARIZONA_IN1R_PGA_VOL_WIDTH                    7  /* IN1R_PGA_VOL - [7:1] */
 /*
  * R792 (0x318) - IN2L Control
  */
+#define ARIZONA_IN2L_HPF_MASK                    0x8000  /* IN2L_HPF - [15] */
+#define ARIZONA_IN2L_HPF_SHIFT                       15  /* IN2L_HPF - [15] */
+#define ARIZONA_IN2L_HPF_WIDTH                        1  /* IN2L_HPF - [15] */
 #define ARIZONA_IN2_OSR_MASK                     0x6000  /* IN2_OSR - [14:13] */
 #define ARIZONA_IN2_OSR_SHIFT                        13  /* IN2_OSR - [14:13] */
 #define ARIZONA_IN2_OSR_WIDTH                         2  /* IN2_OSR - [14:13] */
 /*
  * R796 (0x31C) - IN2R Control
  */
+#define ARIZONA_IN2R_HPF_MASK                    0x8000  /* IN2R_HPF - [15] */
+#define ARIZONA_IN2R_HPF_SHIFT                       15  /* IN2R_HPF - [15] */
+#define ARIZONA_IN2R_HPF_WIDTH                        1  /* IN2R_HPF - [15] */
 #define ARIZONA_IN2R_PGA_VOL_MASK                0x00FE  /* IN2R_PGA_VOL - [7:1] */
 #define ARIZONA_IN2R_PGA_VOL_SHIFT                    1  /* IN2R_PGA_VOL - [7:1] */
 #define ARIZONA_IN2R_PGA_VOL_WIDTH                    7  /* IN2R_PGA_VOL - [7:1] */
 /*
  * R800 (0x320) - IN3L Control
  */
+#define ARIZONA_IN3L_HPF_MASK                    0x8000  /* IN3L_HPF - [15] */
+#define ARIZONA_IN3L_HPF_SHIFT                       15  /* IN3L_HPF - [15] */
+#define ARIZONA_IN3L_HPF_WIDTH                        1  /* IN3L_HPF - [15] */
 #define ARIZONA_IN3_OSR_MASK                     0x6000  /* IN3_OSR - [14:13] */
 #define ARIZONA_IN3_OSR_SHIFT                        13  /* IN3_OSR - [14:13] */
 #define ARIZONA_IN3_OSR_WIDTH                         2  /* IN3_OSR - [14:13] */
 /*
  * R804 (0x324) - IN3R Control
  */
+#define ARIZONA_IN3R_HPF_MASK                    0x8000  /* IN3R_HPF - [15] */
+#define ARIZONA_IN3R_HPF_SHIFT                       15  /* IN3R_HPF - [15] */
+#define ARIZONA_IN3R_HPF_WIDTH                        1  /* IN3R_HPF - [15] */
 #define ARIZONA_IN3R_PGA_VOL_MASK                0x00FE  /* IN3R_PGA_VOL - [7:1] */
 #define ARIZONA_IN3R_PGA_VOL_SHIFT                    1  /* IN3R_PGA_VOL - [7:1] */
 #define ARIZONA_IN3R_PGA_VOL_WIDTH                    7  /* IN3R_PGA_VOL - [7:1] */
 /*
  * R808 (0x328) - IN4 Control
  */
+#define ARIZONA_IN4L_HPF_MASK                    0x8000  /* IN4L_HPF - [15] */
+#define ARIZONA_IN4L_HPF_SHIFT                       15  /* IN4L_HPF - [15] */
+#define ARIZONA_IN4L_HPF_WIDTH                        1  /* IN4L_HPF - [15] */
 #define ARIZONA_IN4_OSR_MASK                     0x6000  /* IN4_OSR - [14:13] */
 #define ARIZONA_IN4_OSR_SHIFT                        13  /* IN4_OSR - [14:13] */
 #define ARIZONA_IN4_OSR_WIDTH                         2  /* IN4_OSR - [14:13] */
 #define ARIZONA_IN4L_DMIC_DLY_SHIFT                   0  /* IN4L_DMIC_DLY - [5:0] */
 #define ARIZONA_IN4L_DMIC_DLY_WIDTH                   6  /* IN4L_DMIC_DLY - [5:0] */
 
+/*
+ * R812 (0x32C) - IN4R Control
+ */
+#define ARIZONA_IN4R_HPF_MASK                    0x8000  /* IN4R_HPF - [15] */
+#define ARIZONA_IN4R_HPF_SHIFT                       15  /* IN4R_HPF - [15] */
+#define ARIZONA_IN4R_HPF_WIDTH                        1  /* IN4R_HPF - [15] */
+
 /*
  * R813 (0x32D) - ADC Digital Volume 4R
  */
 #define ARIZONA_AIF2TX2_SLOT_SHIFT                    0  /* AIF2TX2_SLOT - [5:0] */
 #define ARIZONA_AIF2TX2_SLOT_WIDTH                    6  /* AIF2TX2_SLOT - [5:0] */
 
+/*
+ * R1355 (0x54B) - AIF2 Frame Ctrl 5
+ */
+#define ARIZONA_AIF2TX3_SLOT_MASK                0x003F  /* AIF2TX3_SLOT - [5:0] */
+#define ARIZONA_AIF2TX3_SLOT_SHIFT                    0  /* AIF2TX3_SLOT - [5:0] */
+#define ARIZONA_AIF2TX3_SLOT_WIDTH                    6  /* AIF2TX3_SLOT - [5:0] */
+
+/*
+ * R1356 (0x54C) - AIF2 Frame Ctrl 6
+ */
+#define ARIZONA_AIF2TX4_SLOT_MASK                0x003F  /* AIF2TX4_SLOT - [5:0] */
+#define ARIZONA_AIF2TX4_SLOT_SHIFT                    0  /* AIF2TX4_SLOT - [5:0] */
+#define ARIZONA_AIF2TX4_SLOT_WIDTH                    6  /* AIF2TX4_SLOT - [5:0] */
+
+
+/*
+ * R1357 (0x54D) - AIF2 Frame Ctrl 7
+ */
+#define ARIZONA_AIF2TX5_SLOT_MASK                0x003F  /* AIF2TX5_SLOT - [5:0] */
+#define ARIZONA_AIF2TX5_SLOT_SHIFT                    0  /* AIF2TX5_SLOT - [5:0] */
+#define ARIZONA_AIF2TX5_SLOT_WIDTH                    6  /* AIF2TX5_SLOT - [5:0] */
+
+/*
+ * R1358 (0x54E) - AIF2 Frame Ctrl 8
+ */
+#define ARIZONA_AIF2TX6_SLOT_MASK                0x003F  /* AIF2TX6_SLOT - [5:0] */
+#define ARIZONA_AIF2TX6_SLOT_SHIFT                    0  /* AIF2TX6_SLOT - [5:0] */
+#define ARIZONA_AIF2TX6_SLOT_WIDTH                    6  /* AIF2TX6_SLOT - [5:0] */
+
 /*
  * R1361 (0x551) - AIF2 Frame Ctrl 11
  */
 #define ARIZONA_AIF2RX2_SLOT_SHIFT                    0  /* AIF2RX2_SLOT - [5:0] */
 #define ARIZONA_AIF2RX2_SLOT_WIDTH                    6  /* AIF2RX2_SLOT - [5:0] */
 
+/*
+ * R1363 (0x553) - AIF2 Frame Ctrl 13
+ */
+#define ARIZONA_AIF2RX3_SLOT_MASK                0x003F  /* AIF2RX3_SLOT - [5:0] */
+#define ARIZONA_AIF2RX3_SLOT_SHIFT                    0  /* AIF2RX3_SLOT - [5:0] */
+#define ARIZONA_AIF2RX3_SLOT_WIDTH                    6  /* AIF2RX3_SLOT - [5:0] */
+
+/*
+ * R1364 (0x554) - AIF2 Frame Ctrl 14
+ */
+#define ARIZONA_AIF2RX4_SLOT_MASK                0x003F  /* AIF2RX4_SLOT - [5:0] */
+#define ARIZONA_AIF2RX4_SLOT_SHIFT                    0  /* AIF2RX4_SLOT - [5:0] */
+#define ARIZONA_AIF2RX4_SLOT_WIDTH                    6  /* AIF2RX4_SLOT - [5:0] */
+
+/*
+ * R1365 (0x555) - AIF2 Frame Ctrl 15
+ */
+#define ARIZONA_AIF2RX5_SLOT_MASK                0x003F  /* AIF2RX5_SLOT - [5:0] */
+#define ARIZONA_AIF2RX5_SLOT_SHIFT                    0  /* AIF2RX5_SLOT - [5:0] */
+#define ARIZONA_AIF2RX5_SLOT_WIDTH                    6  /* AIF2RX5_SLOT - [5:0] */
+
+/*
+ * R1366 (0x556) - AIF2 Frame Ctrl 16
+ */
+#define ARIZONA_AIF2RX6_SLOT_MASK                0x003F  /* AIF2RX6_SLOT - [5:0] */
+#define ARIZONA_AIF2RX6_SLOT_SHIFT                    0  /* AIF2RX6_SLOT - [5:0] */
+#define ARIZONA_AIF2RX6_SLOT_WIDTH                    6  /* AIF2RX6_SLOT - [5:0] */
+
 /*
  * R1369 (0x559) - AIF2 Tx Enables
  */
+#define ARIZONA_AIF2TX6_ENA                      0x0020  /* AIF2TX6_ENA */
+#define ARIZONA_AIF2TX6_ENA_MASK                 0x0020  /* AIF2TX6_ENA */
+#define ARIZONA_AIF2TX6_ENA_SHIFT                     5  /* AIF2TX6_ENA */
+#define ARIZONA_AIF2TX6_ENA_WIDTH                     1  /* AIF2TX6_ENA */
+#define ARIZONA_AIF2TX5_ENA                      0x0010  /* AIF2TX5_ENA */
+#define ARIZONA_AIF2TX5_ENA_MASK                 0x0010  /* AIF2TX5_ENA */
+#define ARIZONA_AIF2TX5_ENA_SHIFT                     4  /* AIF2TX5_ENA */
+#define ARIZONA_AIF2TX5_ENA_WIDTH                     1  /* AIF2TX5_ENA */
+#define ARIZONA_AIF2TX4_ENA                      0x0008  /* AIF2TX4_ENA */
+#define ARIZONA_AIF2TX4_ENA_MASK                 0x0008  /* AIF2TX4_ENA */
+#define ARIZONA_AIF2TX4_ENA_SHIFT                     3  /* AIF2TX4_ENA */
+#define ARIZONA_AIF2TX4_ENA_WIDTH                     1  /* AIF2TX4_ENA */
+#define ARIZONA_AIF2TX3_ENA                      0x0004  /* AIF2TX3_ENA */
+#define ARIZONA_AIF2TX3_ENA_MASK                 0x0004  /* AIF2TX3_ENA */
+#define ARIZONA_AIF2TX3_ENA_SHIFT                     2  /* AIF2TX3_ENA */
+#define ARIZONA_AIF2TX3_ENA_WIDTH                     1  /* AIF2TX3_ENA */
 #define ARIZONA_AIF2TX2_ENA                      0x0002  /* AIF2TX2_ENA */
 #define ARIZONA_AIF2TX2_ENA_MASK                 0x0002  /* AIF2TX2_ENA */
 #define ARIZONA_AIF2TX2_ENA_SHIFT                     1  /* AIF2TX2_ENA */
 /*
  * R1370 (0x55A) - AIF2 Rx Enables
  */
+#define ARIZONA_AIF2RX6_ENA                      0x0020  /* AIF2RX6_ENA */
+#define ARIZONA_AIF2RX6_ENA_MASK                 0x0020  /* AIF2RX6_ENA */
+#define ARIZONA_AIF2RX6_ENA_SHIFT                     5  /* AIF2RX6_ENA */
+#define ARIZONA_AIF2RX6_ENA_WIDTH                     1  /* AIF2RX6_ENA */
+#define ARIZONA_AIF2RX5_ENA                      0x0010  /* AIF2RX5_ENA */
+#define ARIZONA_AIF2RX5_ENA_MASK                 0x0010  /* AIF2RX5_ENA */
+#define ARIZONA_AIF2RX5_ENA_SHIFT                     4  /* AIF2RX5_ENA */
+#define ARIZONA_AIF2RX5_ENA_WIDTH                     1  /* AIF2RX5_ENA */
+#define ARIZONA_AIF2RX4_ENA                      0x0008  /* AIF2RX4_ENA */
+#define ARIZONA_AIF2RX4_ENA_MASK                 0x0008  /* AIF2RX4_ENA */
+#define ARIZONA_AIF2RX4_ENA_SHIFT                     3  /* AIF2RX4_ENA */
+#define ARIZONA_AIF2RX4_ENA_WIDTH                     1  /* AIF2RX4_ENA */
+#define ARIZONA_AIF2RX3_ENA                      0x0004  /* AIF2RX3_ENA */
+#define ARIZONA_AIF2RX3_ENA_MASK                 0x0004  /* AIF2RX3_ENA */
+#define ARIZONA_AIF2RX3_ENA_SHIFT                     2  /* AIF2RX3_ENA */
+#define ARIZONA_AIF2RX3_ENA_WIDTH                     1  /* AIF2RX3_ENA */
 #define ARIZONA_AIF2RX2_ENA                      0x0002  /* AIF2RX2_ENA */
 #define ARIZONA_AIF2RX2_ENA_MASK                 0x0002  /* AIF2RX2_ENA */
 #define ARIZONA_AIF2RX2_ENA_SHIFT                     1  /* AIF2RX2_ENA */
diff --git a/include/linux/mfd/lp3943.h b/include/linux/mfd/lp3943.h
new file mode 100644 (file)
index 0000000..3490db7
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * TI/National Semiconductor LP3943 Device
+ *
+ * Copyright 2013 Texas Instruments
+ *
+ * Author: Milo Kim <milo.kim@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __MFD_LP3943_H__
+#define __MFD_LP3943_H__
+
+#include <linux/gpio.h>
+#include <linux/pwm.h>
+#include <linux/regmap.h>
+
+/* Registers */
+#define LP3943_REG_GPIO_A              0x00
+#define LP3943_REG_GPIO_B              0x01
+#define LP3943_REG_PRESCALE0           0x02
+#define LP3943_REG_PWM0                        0x03
+#define LP3943_REG_PRESCALE1           0x04
+#define LP3943_REG_PWM1                        0x05
+#define LP3943_REG_MUX0                        0x06
+#define LP3943_REG_MUX1                        0x07
+#define LP3943_REG_MUX2                        0x08
+#define LP3943_REG_MUX3                        0x09
+
+/* Bit description for LP3943_REG_MUX0 ~ 3 */
+#define LP3943_GPIO_IN                 0x00
+#define LP3943_GPIO_OUT_HIGH           0x00
+#define LP3943_GPIO_OUT_LOW            0x01
+#define LP3943_DIM_PWM0                        0x02
+#define LP3943_DIM_PWM1                        0x03
+
+#define LP3943_NUM_PWMS                        2
+
+enum lp3943_pwm_output {
+       LP3943_PWM_OUT0,
+       LP3943_PWM_OUT1,
+       LP3943_PWM_OUT2,
+       LP3943_PWM_OUT3,
+       LP3943_PWM_OUT4,
+       LP3943_PWM_OUT5,
+       LP3943_PWM_OUT6,
+       LP3943_PWM_OUT7,
+       LP3943_PWM_OUT8,
+       LP3943_PWM_OUT9,
+       LP3943_PWM_OUT10,
+       LP3943_PWM_OUT11,
+       LP3943_PWM_OUT12,
+       LP3943_PWM_OUT13,
+       LP3943_PWM_OUT14,
+       LP3943_PWM_OUT15,
+};
+
+/*
+ * struct lp3943_pwm_map
+ * @output: Output pins which are mapped to each PWM channel
+ * @num_outputs: Number of outputs
+ */
+struct lp3943_pwm_map {
+       enum lp3943_pwm_output *output;
+       int num_outputs;
+};
+
+/*
+ * struct lp3943_platform_data
+ * @pwms: Output channel definitions for PWM channel 0 and 1
+ */
+struct lp3943_platform_data {
+       struct lp3943_pwm_map *pwms[LP3943_NUM_PWMS];
+};
+
+/*
+ * struct lp3943_reg_cfg
+ * @reg: Register address
+ * @mask: Register bit mask to be updated
+ * @shift: Register bit shift
+ */
+struct lp3943_reg_cfg {
+       u8 reg;
+       u8 mask;
+       u8 shift;
+};
+
+/*
+ * struct lp3943
+ * @dev: Parent device pointer
+ * @regmap: Used for I2C communication on accessing registers
+ * @pdata: LP3943 platform specific data
+ * @mux_cfg: Register configuration for pin MUX
+ * @pin_used: Bit mask for output pin used.
+ *           This bitmask is used for pin assignment management.
+ *           1 = pin used, 0 = available.
+ *           Only LSB 16 bits are used, but it is unsigned long type
+ *           for atomic bitwise operations.
+ */
+struct lp3943 {
+       struct device *dev;
+       struct regmap *regmap;
+       struct lp3943_platform_data *pdata;
+       const struct lp3943_reg_cfg *mux_cfg;
+       unsigned long pin_used;
+};
+
+int lp3943_read_byte(struct lp3943 *lp3943, u8 reg, u8 *read);
+int lp3943_write_byte(struct lp3943 *lp3943, u8 reg, u8 data);
+int lp3943_update_bits(struct lp3943 *lp3943, u8 reg, u8 mask, u8 data);
+#endif
diff --git a/include/linux/mfd/max14577-private.h b/include/linux/mfd/max14577-private.h
new file mode 100644 (file)
index 0000000..a3d0185
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+ * max14577-private.h - Common API for the Maxim 14577 internal sub chip
+ *
+ * Copyright (C) 2013 Samsung Electrnoics
+ * Chanwoo Choi <cw00.choi@samsung.com>
+ * Krzysztof Kozlowski <k.kozlowski@samsung.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.
+ */
+
+#ifndef __MAX14577_PRIVATE_H__
+#define __MAX14577_PRIVATE_H__
+
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+
+#define MAX14577_REG_INVALID           (0xff)
+
+/* Slave addr = 0x4A: Interrupt */
+enum max14577_reg {
+       MAX14577_REG_DEVICEID           = 0x00,
+       MAX14577_REG_INT1               = 0x01,
+       MAX14577_REG_INT2               = 0x02,
+       MAX14577_REG_INT3               = 0x03,
+       MAX14577_REG_STATUS1            = 0x04,
+       MAX14577_REG_STATUS2            = 0x05,
+       MAX14577_REG_STATUS3            = 0x06,
+       MAX14577_REG_INTMASK1           = 0x07,
+       MAX14577_REG_INTMASK2           = 0x08,
+       MAX14577_REG_INTMASK3           = 0x09,
+       MAX14577_REG_CDETCTRL1          = 0x0A,
+       MAX14577_REG_RFU                = 0x0B,
+       MAX14577_REG_CONTROL1           = 0x0C,
+       MAX14577_REG_CONTROL2           = 0x0D,
+       MAX14577_REG_CONTROL3           = 0x0E,
+       MAX14577_REG_CHGCTRL1           = 0x0F,
+       MAX14577_REG_CHGCTRL2           = 0x10,
+       MAX14577_REG_CHGCTRL3           = 0x11,
+       MAX14577_REG_CHGCTRL4           = 0x12,
+       MAX14577_REG_CHGCTRL5           = 0x13,
+       MAX14577_REG_CHGCTRL6           = 0x14,
+       MAX14577_REG_CHGCTRL7           = 0x15,
+
+       MAX14577_REG_END,
+};
+
+/* Slave addr = 0x4A: MUIC */
+enum max14577_muic_reg {
+       MAX14577_MUIC_REG_STATUS1       = 0x04,
+       MAX14577_MUIC_REG_STATUS2       = 0x05,
+       MAX14577_MUIC_REG_CONTROL1      = 0x0C,
+       MAX14577_MUIC_REG_CONTROL3      = 0x0E,
+
+       MAX14577_MUIC_REG_END,
+};
+
+enum max14577_muic_charger_type {
+       MAX14577_CHARGER_TYPE_NONE = 0,
+       MAX14577_CHARGER_TYPE_USB,
+       MAX14577_CHARGER_TYPE_DOWNSTREAM_PORT,
+       MAX14577_CHARGER_TYPE_DEDICATED_CHG,
+       MAX14577_CHARGER_TYPE_SPECIAL_500MA,
+       MAX14577_CHARGER_TYPE_SPECIAL_1A,
+       MAX14577_CHARGER_TYPE_RESERVED,
+       MAX14577_CHARGER_TYPE_DEAD_BATTERY = 7,
+};
+
+/* MAX14577 interrupts */
+#define INT1_ADC_MASK                  (0x1 << 0)
+#define INT1_ADCLOW_MASK               (0x1 << 1)
+#define INT1_ADCERR_MASK               (0x1 << 2)
+
+#define INT2_CHGTYP_MASK               (0x1 << 0)
+#define INT2_CHGDETRUN_MASK            (0x1 << 1)
+#define INT2_DCDTMR_MASK               (0x1 << 2)
+#define INT2_DBCHG_MASK                        (0x1 << 3)
+#define INT2_VBVOLT_MASK               (0x1 << 4)
+
+#define INT3_EOC_MASK                  (0x1 << 0)
+#define INT3_CGMBC_MASK                        (0x1 << 1)
+#define INT3_OVP_MASK                  (0x1 << 2)
+#define INT3_MBCCHGERR_MASK            (0x1 << 3)
+
+/* MAX14577 DEVICE ID register */
+#define DEVID_VENDORID_SHIFT           0
+#define DEVID_DEVICEID_SHIFT           3
+#define DEVID_VENDORID_MASK            (0x07 << DEVID_VENDORID_SHIFT)
+#define DEVID_DEVICEID_MASK            (0x1f << DEVID_DEVICEID_SHIFT)
+
+/* MAX14577 STATUS1 register */
+#define STATUS1_ADC_SHIFT              0
+#define STATUS1_ADCLOW_SHIFT           5
+#define STATUS1_ADCERR_SHIFT           6
+#define STATUS1_ADC_MASK               (0x1f << STATUS1_ADC_SHIFT)
+#define STATUS1_ADCLOW_MASK            (0x1 << STATUS1_ADCLOW_SHIFT)
+#define STATUS1_ADCERR_MASK            (0x1 << STATUS1_ADCERR_SHIFT)
+
+/* MAX14577 STATUS2 register */
+#define STATUS2_CHGTYP_SHIFT           0
+#define STATUS2_CHGDETRUN_SHIFT                3
+#define STATUS2_DCDTMR_SHIFT           4
+#define STATUS2_DBCHG_SHIFT            5
+#define STATUS2_VBVOLT_SHIFT           6
+#define STATUS2_CHGTYP_MASK            (0x7 << STATUS2_CHGTYP_SHIFT)
+#define STATUS2_CHGDETRUN_MASK         (0x1 << STATUS2_CHGDETRUN_SHIFT)
+#define STATUS2_DCDTMR_MASK            (0x1 << STATUS2_DCDTMR_SHIFT)
+#define STATUS2_DBCHG_MASK             (0x1 << STATUS2_DBCHG_SHIFT)
+#define STATUS2_VBVOLT_MASK            (0x1 << STATUS2_VBVOLT_SHIFT)
+
+/* MAX14577 CONTROL1 register */
+#define COMN1SW_SHIFT                  0
+#define COMP2SW_SHIFT                  3
+#define MICEN_SHIFT                    6
+#define IDBEN_SHIFT                    7
+#define COMN1SW_MASK                   (0x7 << COMN1SW_SHIFT)
+#define COMP2SW_MASK                   (0x7 << COMP2SW_SHIFT)
+#define MICEN_MASK                     (0x1 << MICEN_SHIFT)
+#define IDBEN_MASK                     (0x1 << IDBEN_SHIFT)
+#define CLEAR_IDBEN_MICEN_MASK         (COMN1SW_MASK | COMP2SW_MASK)
+#define CTRL1_SW_USB                   ((1 << COMP2SW_SHIFT) \
+                                               | (1 << COMN1SW_SHIFT))
+#define CTRL1_SW_AUDIO                 ((2 << COMP2SW_SHIFT) \
+                                               | (2 << COMN1SW_SHIFT))
+#define CTRL1_SW_UART                  ((3 << COMP2SW_SHIFT) \
+                                               | (3 << COMN1SW_SHIFT))
+#define CTRL1_SW_OPEN                  ((0 << COMP2SW_SHIFT) \
+                                               | (0 << COMN1SW_SHIFT))
+
+/* MAX14577 CONTROL2 register */
+#define CTRL2_LOWPWR_SHIFT             (0)
+#define CTRL2_ADCEN_SHIFT              (1)
+#define CTRL2_CPEN_SHIFT               (2)
+#define CTRL2_SFOUTASRT_SHIFT          (3)
+#define CTRL2_SFOUTORD_SHIFT           (4)
+#define CTRL2_ACCDET_SHIFT             (5)
+#define CTRL2_USBCPINT_SHIFT           (6)
+#define CTRL2_RCPS_SHIFT               (7)
+#define CTRL2_LOWPWR_MASK              (0x1 << CTRL2_LOWPWR_SHIFT)
+#define CTRL2_ADCEN_MASK               (0x1 << CTRL2_ADCEN_SHIFT)
+#define CTRL2_CPEN_MASK                        (0x1 << CTRL2_CPEN_SHIFT)
+#define CTRL2_SFOUTASRT_MASK           (0x1 << CTRL2_SFOUTASRT_SHIFT)
+#define CTRL2_SFOUTORD_MASK            (0x1 << CTRL2_SFOUTORD_SHIFT)
+#define CTRL2_ACCDET_MASK              (0x1 << CTRL2_ACCDET_SHIFT)
+#define CTRL2_USBCPINT_MASK            (0x1 << CTRL2_USBCPINT_SHIFT)
+#define CTRL2_RCPS_MASK                        (0x1 << CTR2_RCPS_SHIFT)
+
+#define CTRL2_CPEN1_LOWPWR0 ((1 << CTRL2_CPEN_SHIFT) | \
+                               (0 << CTRL2_LOWPWR_SHIFT))
+#define CTRL2_CPEN0_LOWPWR1 ((0 << CTRL2_CPEN_SHIFT) | \
+                               (1 << CTRL2_LOWPWR_SHIFT))
+
+/* MAX14577 CONTROL3 register */
+#define CTRL3_JIGSET_SHIFT             0
+#define CTRL3_BOOTSET_SHIFT            2
+#define CTRL3_ADCDBSET_SHIFT           4
+#define CTRL3_JIGSET_MASK              (0x3 << CTRL3_JIGSET_SHIFT)
+#define CTRL3_BOOTSET_MASK             (0x3 << CTRL3_BOOTSET_SHIFT)
+#define CTRL3_ADCDBSET_MASK            (0x3 << CTRL3_ADCDBSET_SHIFT)
+
+/* Slave addr = 0x4A: Charger */
+enum max14577_charger_reg {
+       MAX14577_CHG_REG_STATUS3        = 0x06,
+       MAX14577_CHG_REG_CHG_CTRL1      = 0x0F,
+       MAX14577_CHG_REG_CHG_CTRL2      = 0x10,
+       MAX14577_CHG_REG_CHG_CTRL3      = 0x11,
+       MAX14577_CHG_REG_CHG_CTRL4      = 0x12,
+       MAX14577_CHG_REG_CHG_CTRL5      = 0x13,
+       MAX14577_CHG_REG_CHG_CTRL6      = 0x14,
+       MAX14577_CHG_REG_CHG_CTRL7      = 0x15,
+
+       MAX14577_CHG_REG_END,
+};
+
+/* MAX14577 STATUS3 register */
+#define STATUS3_EOC_SHIFT              0
+#define STATUS3_CGMBC_SHIFT            1
+#define STATUS3_OVP_SHIFT              2
+#define STATUS3_MBCCHGERR_SHIFT                3
+#define STATUS3_EOC_MASK               (0x1 << STATUS3_EOC_SHIFT)
+#define STATUS3_CGMBC_MASK             (0x1 << STATUS3_CGMBC_SHIFT)
+#define STATUS3_OVP_MASK               (0x1 << STATUS3_OVP_SHIFT)
+#define STATUS3_MBCCHGERR_MASK         (0x1 << STATUS3_MBCCHGERR_SHIFT)
+
+/* MAX14577 CDETCTRL1 register */
+#define CDETCTRL1_CHGDETEN_SHIFT       0
+#define CDETCTRL1_CHGTYPMAN_SHIFT      1
+#define CDETCTRL1_DCDEN_SHIFT          2
+#define CDETCTRL1_DCD2SCT_SHIFT                3
+#define CDETCTRL1_DCHKTM_SHIFT         4
+#define CDETCTRL1_DBEXIT_SHIFT         5
+#define CDETCTRL1_DBIDLE_SHIFT         6
+#define CDETCTRL1_CDPDET_SHIFT         7
+#define CDETCTRL1_CHGDETEN_MASK                (0x1 << CDETCTRL1_CHGDETEN_SHIFT)
+#define CDETCTRL1_CHGTYPMAN_MASK       (0x1 << CDETCTRL1_CHGTYPMAN_SHIFT)
+#define CDETCTRL1_DCDEN_MASK           (0x1 << CDETCTRL1_DCDEN_SHIFT)
+#define CDETCTRL1_DCD2SCT_MASK         (0x1 << CDETCTRL1_DCD2SCT_SHIFT)
+#define CDETCTRL1_DCHKTM_MASK          (0x1 << CDETCTRL1_DCHKTM_SHIFT)
+#define CDETCTRL1_DBEXIT_MASK          (0x1 << CDETCTRL1_DBEXIT_SHIFT)
+#define CDETCTRL1_DBIDLE_MASK          (0x1 << CDETCTRL1_DBIDLE_SHIFT)
+#define CDETCTRL1_CDPDET_MASK          (0x1 << CDETCTRL1_CDPDET_SHIFT)
+
+/* MAX14577 CHGCTRL1 register */
+#define CHGCTRL1_TCHW_SHIFT            4
+#define CHGCTRL1_TCHW_MASK             (0x7 << CHGCTRL1_TCHW_SHIFT)
+
+/* MAX14577 CHGCTRL2 register */
+#define CHGCTRL2_MBCHOSTEN_SHIFT       6
+#define CHGCTRL2_MBCHOSTEN_MASK                (0x1 << CHGCTRL2_MBCHOSTEN_SHIFT)
+#define CHGCTRL2_VCHGR_RC_SHIFT                7
+#define CHGCTRL2_VCHGR_RC_MASK         (0x1 << CHGCTRL2_VCHGR_RC_SHIFT)
+
+/* MAX14577 CHGCTRL3 register */
+#define CHGCTRL3_MBCCVWRC_SHIFT                0
+#define CHGCTRL3_MBCCVWRC_MASK         (0xf << CHGCTRL3_MBCCVWRC_SHIFT)
+
+/* MAX14577 CHGCTRL4 register */
+#define CHGCTRL4_MBCICHWRCH_SHIFT      0
+#define CHGCTRL4_MBCICHWRCH_MASK       (0xf << CHGCTRL4_MBCICHWRCH_SHIFT)
+#define CHGCTRL4_MBCICHWRCL_SHIFT      4
+#define CHGCTRL4_MBCICHWRCL_MASK       (0x1 << CHGCTRL4_MBCICHWRCL_SHIFT)
+
+/* MAX14577 CHGCTRL5 register */
+#define CHGCTRL5_EOCS_SHIFT            0
+#define CHGCTRL5_EOCS_MASK             (0xf << CHGCTRL5_EOCS_SHIFT)
+
+/* MAX14577 CHGCTRL6 register */
+#define CHGCTRL6_AUTOSTOP_SHIFT                5
+#define CHGCTRL6_AUTOSTOP_MASK         (0x1 << CHGCTRL6_AUTOSTOP_SHIFT)
+
+/* MAX14577 CHGCTRL7 register */
+#define CHGCTRL7_OTPCGHCVS_SHIFT       0
+#define CHGCTRL7_OTPCGHCVS_MASK                (0x3 << CHGCTRL7_OTPCGHCVS_SHIFT)
+
+/* MAX14577 regulator current limits (as in CHGCTRL4 register), uA */
+#define MAX14577_REGULATOR_CURRENT_LIMIT_MIN            90000
+#define MAX14577_REGULATOR_CURRENT_LIMIT_HIGH_START    200000
+#define MAX14577_REGULATOR_CURRENT_LIMIT_HIGH_STEP      50000
+#define MAX14577_REGULATOR_CURRENT_LIMIT_MAX           950000
+
+/* MAX14577 regulator SFOUT LDO voltage, fixed, uV */
+#define MAX14577_REGULATOR_SAFEOUT_VOLTAGE             4900000
+
+enum max14577_irq_source {
+       MAX14577_IRQ_INT1 = 0,
+       MAX14577_IRQ_INT2,
+       MAX14577_IRQ_INT3,
+
+       MAX14577_IRQ_REGS_NUM,
+};
+
+enum max14577_irq {
+       /* INT1 */
+       MAX14577_IRQ_INT1_ADC,
+       MAX14577_IRQ_INT1_ADCLOW,
+       MAX14577_IRQ_INT1_ADCERR,
+
+       /* INT2 */
+       MAX14577_IRQ_INT2_CHGTYP,
+       MAX14577_IRQ_INT2_CHGDETRUN,
+       MAX14577_IRQ_INT2_DCDTMR,
+       MAX14577_IRQ_INT2_DBCHG,
+       MAX14577_IRQ_INT2_VBVOLT,
+
+       /* INT3 */
+       MAX14577_IRQ_INT3_EOC,
+       MAX14577_IRQ_INT3_CGMBC,
+       MAX14577_IRQ_INT3_OVP,
+       MAX14577_IRQ_INT3_MBCCHGERR,
+
+       MAX14577_IRQ_NUM,
+};
+
+struct max14577 {
+       struct device *dev;
+       struct i2c_client *i2c; /* Slave addr = 0x4A */
+
+       struct regmap *regmap;
+
+       struct regmap_irq_chip_data *irq_data;
+       int irq;
+
+       /* Device ID */
+       u8 vendor_id;   /* Vendor Identification */
+       u8 device_id;   /* Chip Version */
+};
+
+/* MAX14577 shared regmap API function */
+static inline int max14577_read_reg(struct regmap *map, u8 reg, u8 *dest)
+{
+       unsigned int val;
+       int ret;
+
+       ret = regmap_read(map, reg, &val);
+       *dest = val;
+
+       return ret;
+}
+
+static inline int max14577_bulk_read(struct regmap *map, u8 reg, u8 *buf,
+               int count)
+{
+       return regmap_bulk_read(map, reg, buf, count);
+}
+
+static inline int max14577_write_reg(struct regmap *map, u8 reg, u8 value)
+{
+       return regmap_write(map, reg, value);
+}
+
+static inline int max14577_bulk_write(struct regmap *map, u8 reg, u8 *buf,
+               int count)
+{
+       return regmap_bulk_write(map, reg, buf, count);
+}
+
+static inline int max14577_update_reg(struct regmap *map, u8 reg, u8 mask,
+               u8 val)
+{
+       return regmap_update_bits(map, reg, mask, val);
+}
+
+#endif /* __MAX14577_PRIVATE_H__ */
diff --git a/include/linux/mfd/max14577.h b/include/linux/mfd/max14577.h
new file mode 100644 (file)
index 0000000..247b021
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * max14577.h - Driver for the Maxim 14577
+ *
+ * Copyright (C) 2013 Samsung Electrnoics
+ * Chanwoo Choi <cw00.choi@samsung.com>
+ * Krzysztof Kozlowski <k.kozlowski@samsung.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.
+ *
+ * This driver is based on max8997.h
+ *
+ * MAX14577 has MUIC, Charger devices.
+ * The devices share the same I2C bus and interrupt line
+ * included in this mfd driver.
+ */
+
+#ifndef __MAX14577_H__
+#define __MAX14577_H__
+
+#include <linux/mfd/max14577-private.h>
+#include <linux/regulator/consumer.h>
+
+/*
+ * MAX14577 Regulator
+ */
+
+/* MAX14577 regulator IDs */
+enum max14577_regulators {
+       MAX14577_SAFEOUT = 0,
+       MAX14577_CHARGER,
+
+       MAX14577_REG_MAX,
+};
+
+struct max14577_regulator_platform_data {
+       int id;
+       struct regulator_init_data *initdata;
+       struct device_node *of_node;
+};
+
+/*
+ * MAX14577 MFD platform data
+ */
+struct max14577_platform_data {
+       /* IRQ */
+       int irq_base;
+
+       /* current control GPIOs */
+       int gpio_pogo_vbatt_en;
+       int gpio_pogo_vbus_en;
+
+       /* current control GPIO control function */
+       int (*set_gpio_pogo_vbatt_en) (int gpio_val);
+       int (*set_gpio_pogo_vbus_en) (int gpio_val);
+
+       int (*set_gpio_pogo_cb) (int new_dev);
+
+       struct max14577_regulator_platform_data *regulators;
+};
+
+#endif /* __MAX14577_H__ */
index 87994542573ba713580b4e6e518a76b39243b78b..cbecec2e353a3df0d931da2c86d5c206c84ea3eb 100644 (file)
 #define TPS6586X_SLEW_RATE_SET         0x08
 #define TPS6586X_SLEW_RATE_MASK         0x07
 
+/* VERSION CRC */
+#define TPS658621A     0x15
+#define TPS658621CD    0x2c
+#define TPS658623      0x1b
+#define TPS658643      0x03
+
 enum {
        TPS6586X_ID_SYS,
        TPS6586X_ID_SM_0,
@@ -97,5 +103,6 @@ extern int tps6586x_clr_bits(struct device *dev, int reg, uint8_t bit_mask);
 extern int tps6586x_update(struct device *dev, int reg, uint8_t val,
                           uint8_t mask);
 extern int tps6586x_irq_get_virq(struct device *dev, int irq);
+extern int tps6586x_get_version(struct device *dev);
 
 #endif /*__LINUX_MFD_TPS6586X_H */
index ad05ce60c1c97a052c11713f18532836829831cc..2e5b194b9b1900b9d5304cbdb52f14aac576b85e 100644 (file)
@@ -22,6 +22,8 @@
 #define PHY_ID_KSZ8021         0x00221555
 #define PHY_ID_KSZ8031         0x00221556
 #define PHY_ID_KSZ8041         0x00221510
+/* undocumented */
+#define PHY_ID_KSZ8041RNLI     0x00221537
 #define PHY_ID_KSZ8051         0x00221550
 /* same id: ks8001 Rev. A/B, and ks8721 Rev 3. */
 #define PHY_ID_KSZ8001         0x0022161A
index 1cedd000cf293f4486575b87086b01e2ee1b26e5..a7b4e310bf42524338ee2504d21843cdd0abeab9 100644 (file)
@@ -1842,7 +1842,7 @@ static inline pgprot_t vm_get_page_prot(unsigned long vm_flags)
 }
 #endif
 
-#ifdef CONFIG_ARCH_USES_NUMA_PROT_NONE
+#ifdef CONFIG_NUMA_BALANCING
 unsigned long change_prot_numa(struct vm_area_struct *vma,
                        unsigned long start, unsigned long end);
 #endif
index 15cd6b1b211e731c5c133dabd0d26e890a56e135..46e548fd502a0157c40869789ae128a323ff1aa6 100644 (file)
@@ -451,7 +451,7 @@ int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,
 
 extern void __module_put_and_exit(struct module *mod, long code)
        __attribute__((noreturn));
-#define module_put_and_exit(code) __module_put_and_exit(THIS_MODULE, code);
+#define module_put_and_exit(code) __module_put_and_exit(THIS_MODULE, code)
 
 #ifdef CONFIG_MODULE_UNLOAD
 unsigned long module_refcount(struct module *mod);
index 9e6c8f9f306e016923a0c32d3ae0e2d9f0ce0d1f..f3ea8daf08eef7e30794c7c93a7f2fb54b43f355 100644 (file)
@@ -279,7 +279,7 @@ struct nand_onfi_params {
        __le16 io_pin_capacitance_typ;
        __le16 input_pin_capacitance_typ;
        u8 input_pin_capacitance_max;
-       u8 driver_strenght_support;
+       u8 driver_strength_support;
        __le16 t_int_r;
        __le16 t_ald;
        u8 reserved4[7];
index 1f8d24bdafdac2bc28789c777315068311368765..6a35e6de5da174fc7b9f82f67be421f4d74a1cc3 100644 (file)
@@ -37,7 +37,7 @@
  */
 
 struct mtd_partition {
-       char *name;                     /* identifier string */
+       const char *name;               /* identifier string */
        uint64_t size;                  /* partition size */
        uint64_t offset;                /* offset within the master MTD space */
        uint32_t mask_flags;            /* master MTD flags to mask out for this partition */
@@ -76,11 +76,11 @@ struct mtd_part_parser {
                        struct mtd_part_parser_data *);
 };
 
-extern int register_mtd_parser(struct mtd_part_parser *parser);
-extern int deregister_mtd_parser(struct mtd_part_parser *parser);
+extern void register_mtd_parser(struct mtd_part_parser *parser);
+extern void deregister_mtd_parser(struct mtd_part_parser *parser);
 
 int mtd_is_partition(const struct mtd_info *mtd);
-int mtd_add_partition(struct mtd_info *master, char *name,
+int mtd_add_partition(struct mtd_info *master, const char *name,
                      long long offset, long long length);
 int mtd_del_partition(struct mtd_info *master, int partno);
 uint64_t mtd_get_device_size(const struct mtd_info *mtd);
index 4bcee94cef9314c44dfaa94fb17d3c905fefee08..69be3e6079c8c9320cff6598b8ba33ff1cdfb1f8 100644 (file)
@@ -181,7 +181,7 @@ struct proto_ops {
                                      int offset, size_t size, int flags);
        ssize_t         (*splice_read)(struct socket *sock,  loff_t *ppos,
                                       struct pipe_inode_info *pipe, size_t len, unsigned int flags);
-       void            (*set_peek_off)(struct sock *sk, int val);
+       int             (*set_peek_off)(struct sock *sk, int val);
 };
 
 #define DECLARE_SOCKADDR(type, dst, src)       \
index 7f0ed423a3606f1cc13e09a00d332dc4a45f924b..0ca8100f9fbcaf406298114990fbf5db57f073f6 100644 (file)
@@ -1282,6 +1282,9 @@ struct net_device {
 #endif
 #if IS_ENABLED(CONFIG_NET_DSA)
        struct dsa_switch_tree  *dsa_ptr;       /* dsa specific data */
+#endif
+#if IS_ENABLED(CONFIG_TIPC)
+       struct tipc_bearer __rcu *tipc_ptr;     /* TIPC specific data */
 #endif
        void                    *atalk_ptr;     /* AppleTalk link       */
        struct in_device __rcu  *ip_ptr;        /* IPv4 specific data   */
@@ -2368,17 +2371,52 @@ static inline int netif_copy_real_num_queues(struct net_device *to_dev,
 #define DEFAULT_MAX_NUM_RSS_QUEUES     (8)
 int netif_get_num_default_rss_queues(void);
 
-/* Use this variant when it is known for sure that it
- * is executing from hardware interrupt context or with hardware interrupts
- * disabled.
- */
-void dev_kfree_skb_irq(struct sk_buff *skb);
+enum skb_free_reason {
+       SKB_REASON_CONSUMED,
+       SKB_REASON_DROPPED,
+};
 
-/* Use this variant in places where it could be invoked
- * from either hardware interrupt or other context, with hardware interrupts
- * either disabled or enabled.
+void __dev_kfree_skb_irq(struct sk_buff *skb, enum skb_free_reason reason);
+void __dev_kfree_skb_any(struct sk_buff *skb, enum skb_free_reason reason);
+
+/*
+ * It is not allowed to call kfree_skb() or consume_skb() from hardware
+ * interrupt context or with hardware interrupts being disabled.
+ * (in_irq() || irqs_disabled())
+ *
+ * We provide four helpers that can be used in following contexts :
+ *
+ * dev_kfree_skb_irq(skb) when caller drops a packet from irq context,
+ *  replacing kfree_skb(skb)
+ *
+ * dev_consume_skb_irq(skb) when caller consumes a packet from irq context.
+ *  Typically used in place of consume_skb(skb) in TX completion path
+ *
+ * dev_kfree_skb_any(skb) when caller doesn't know its current irq context,
+ *  replacing kfree_skb(skb)
+ *
+ * dev_consume_skb_any(skb) when caller doesn't know its current irq context,
+ *  and consumed a packet. Used in place of consume_skb(skb)
  */
-void dev_kfree_skb_any(struct sk_buff *skb);
+static inline void dev_kfree_skb_irq(struct sk_buff *skb)
+{
+       __dev_kfree_skb_irq(skb, SKB_REASON_DROPPED);
+}
+
+static inline void dev_consume_skb_irq(struct sk_buff *skb)
+{
+       __dev_kfree_skb_irq(skb, SKB_REASON_CONSUMED);
+}
+
+static inline void dev_kfree_skb_any(struct sk_buff *skb)
+{
+       __dev_kfree_skb_any(skb, SKB_REASON_DROPPED);
+}
+
+static inline void dev_consume_skb_any(struct sk_buff *skb)
+{
+       __dev_kfree_skb_any(skb, SKB_REASON_CONSUMED);
+}
 
 int netif_rx(struct sk_buff *skb);
 int netif_rx_ni(struct sk_buff *skb);
index c1637062c1ce138129a87dd571a5ea7cd2b53abd..12c2cb947df579bca8e55c46c5a58cf449f084fb 100644 (file)
@@ -413,16 +413,6 @@ enum lock_type4 {
 #define NFS4_VERSION 4
 #define NFS4_MINOR_VERSION 0
 
-#if defined(CONFIG_NFS_V4_2)
-#define NFS4_MAX_MINOR_VERSION 2
-#else
-#if defined(CONFIG_NFS_V4_1)
-#define NFS4_MAX_MINOR_VERSION 1
-#else
-#define NFS4_MAX_MINOR_VERSION 0
-#endif /* CONFIG_NFS_V4_1 */
-#endif /* CONFIG_NFS_V4_2 */
-
 #define NFS4_DEBUG 1
 
 /* Index of predefined Linux client operations */
index 14a48207a304ec65dda6ac8af22e0e0825b8fa6b..48997374eaf04eac0d52b8bf8d60c61c35944df3 100644 (file)
@@ -506,24 +506,6 @@ extern const struct inode_operations nfs_referral_inode_operations;
 extern int nfs_mountpoint_expiry_timeout;
 extern void nfs_release_automount_timer(void);
 
-/*
- * linux/fs/nfs/nfs4proc.c
- */
-#ifdef CONFIG_NFS_V4_SECURITY_LABEL
-extern struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags);
-static inline void nfs4_label_free(struct nfs4_label *label)
-{
-       if (label) {
-               kfree(label->label);
-               kfree(label);
-       }
-       return;
-}
-#else
-static inline struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags) { return NULL; }
-static inline void nfs4_label_free(void *label) {}
-#endif
-
 /*
  * linux/fs/nfs/unlink.c
  */
index 6f10e938ff7e74d4db19b991a55193f5073946e7..cb32d9c1e8dc83502e39143a8c25913bab3193d5 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef __LINUX_OF_MTD_H
-#define __LINUX_OF_NET_H
+#define __LINUX_OF_MTD_H
 
 #ifdef CONFIG_OF_MTD
 
index 1084a15175e04ff0bc715e3e429aab7027d279f8..a13d6825e586972835ba2b3d53ac4ab504ba5369 100644 (file)
@@ -960,6 +960,7 @@ void pci_update_resource(struct pci_dev *dev, int resno);
 int __must_check pci_assign_resource(struct pci_dev *dev, int i);
 int __must_check pci_reassign_resource(struct pci_dev *dev, int i, resource_size_t add_size, resource_size_t align);
 int pci_select_bars(struct pci_dev *dev, unsigned long flags);
+bool pci_device_is_present(struct pci_dev *pdev);
 
 /* ROM control related routines */
 int pci_enable_rom(struct pci_dev *pdev);
@@ -1567,65 +1568,65 @@ enum pci_fixup_pass {
 /* Anonymous variables would be nice... */
 #define DECLARE_PCI_FIXUP_SECTION(section, name, vendor, device, class,        \
                                  class_shift, hook)                    \
-       static const struct pci_fixup __pci_fixup_##name __used         \
+       static const struct pci_fixup __PASTE(__pci_fixup_##name,__LINE__) __used       \
        __attribute__((__section__(#section), aligned((sizeof(void *)))))    \
                = { vendor, device, class, class_shift, hook };
 
 #define DECLARE_PCI_FIXUP_CLASS_EARLY(vendor, device, class,           \
                                         class_shift, hook)             \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_early,                     \
-               vendor##device##hook, vendor, device, class, class_shift, hook)
+               hook, vendor, device, class, class_shift, hook)
 #define DECLARE_PCI_FIXUP_CLASS_HEADER(vendor, device, class,          \
                                         class_shift, hook)             \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_header,                    \
-               vendor##device##hook, vendor, device, class, class_shift, hook)
+               hook, vendor, device, class, class_shift, hook)
 #define DECLARE_PCI_FIXUP_CLASS_FINAL(vendor, device, class,           \
                                         class_shift, hook)             \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_final,                     \
-               vendor##device##hook, vendor, device, class, class_shift, hook)
+               hook, vendor, device, class, class_shift, hook)
 #define DECLARE_PCI_FIXUP_CLASS_ENABLE(vendor, device, class,          \
                                         class_shift, hook)             \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_enable,                    \
-               vendor##device##hook, vendor, device, class, class_shift, hook)
+               hook, vendor, device, class, class_shift, hook)
 #define DECLARE_PCI_FIXUP_CLASS_RESUME(vendor, device, class,          \
                                         class_shift, hook)             \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_resume,                    \
-               resume##vendor##device##hook, vendor, device, class,    \
+               resume##hook, vendor, device, class,    \
                class_shift, hook)
 #define DECLARE_PCI_FIXUP_CLASS_RESUME_EARLY(vendor, device, class,    \
                                         class_shift, hook)             \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_resume_early,              \
-               resume_early##vendor##device##hook, vendor, device,     \
+               resume_early##hook, vendor, device,     \
                class, class_shift, hook)
 #define DECLARE_PCI_FIXUP_CLASS_SUSPEND(vendor, device, class,         \
                                         class_shift, hook)             \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_suspend,                   \
-               suspend##vendor##device##hook, vendor, device, class,   \
+               suspend##hook, vendor, device, class,   \
                class_shift, hook)
 
 #define DECLARE_PCI_FIXUP_EARLY(vendor, device, hook)                  \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_early,                     \
-               vendor##device##hook, vendor, device, PCI_ANY_ID, 0, hook)
+               hook, vendor, device, PCI_ANY_ID, 0, hook)
 #define DECLARE_PCI_FIXUP_HEADER(vendor, device, hook)                 \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_header,                    \
-               vendor##device##hook, vendor, device, PCI_ANY_ID, 0, hook)
+               hook, vendor, device, PCI_ANY_ID, 0, hook)
 #define DECLARE_PCI_FIXUP_FINAL(vendor, device, hook)                  \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_final,                     \
-               vendor##device##hook, vendor, device, PCI_ANY_ID, 0, hook)
+               hook, vendor, device, PCI_ANY_ID, 0, hook)
 #define DECLARE_PCI_FIXUP_ENABLE(vendor, device, hook)                 \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_enable,                    \
-               vendor##device##hook, vendor, device, PCI_ANY_ID, 0, hook)
+               hook, vendor, device, PCI_ANY_ID, 0, hook)
 #define DECLARE_PCI_FIXUP_RESUME(vendor, device, hook)                 \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_resume,                    \
-               resume##vendor##device##hook, vendor, device,           \
+               resume##hook, vendor, device,           \
                PCI_ANY_ID, 0, hook)
 #define DECLARE_PCI_FIXUP_RESUME_EARLY(vendor, device, hook)           \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_resume_early,              \
-               resume_early##vendor##device##hook, vendor, device,     \
+               resume_early##hook, vendor, device,     \
                PCI_ANY_ID, 0, hook)
 #define DECLARE_PCI_FIXUP_SUSPEND(vendor, device, hook)                        \
        DECLARE_PCI_FIXUP_SECTION(.pci_fixup_suspend,                   \
-               suspend##vendor##device##hook, vendor, device,          \
+               suspend##hook, vendor, device,          \
                PCI_ANY_ID, 0, hook)
 
 #ifdef CONFIG_PCI_QUIRKS
index a2e2f1d17e164c00b190d6515ec90950ef288e17..5f2e559af6b0a7a6ea07247ab405ea48407d4e72 100644 (file)
@@ -175,8 +175,7 @@ struct hotplug_params {
 };
 
 #ifdef CONFIG_ACPI
-#include <acpi/acpi.h>
-#include <acpi/acpi_bus.h>
+#include <linux/acpi.h>
 int pci_get_hp_params(struct pci_dev *dev, struct hotplug_params *hpp);
 int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags);
 int acpi_pci_check_ejectable(struct pci_bus *pbus, acpi_handle handle);
index 2e069d1288df5f04e6982243d7cac0f7455cd31d..8f4a70f2eca8bd0a3f55c572ad967ca516a2d8e1 100644 (file)
@@ -319,7 +319,10 @@ struct perf_event {
         */
        struct list_head                migrate_entry;
 
-       struct hlist_node               hlist_entry;
+       union {
+               struct hlist_node       hlist_entry;
+               struct list_head        active_entry;
+       };
        int                             nr_siblings;
        int                             group_flags;
        struct perf_event               *group_leader;
index 48a4dc3cb8cf26b91af2bd2cb147bf6879956695..90a666e0884b9ecdf612da8dff6d7f3e53151933 100644 (file)
 
 #include <linux/atomic.h>
 
-#define PHY_BASIC_FEATURES     (SUPPORTED_10baseT_Half | \
-                                SUPPORTED_10baseT_Full | \
-                                SUPPORTED_100baseT_Half | \
-                                SUPPORTED_100baseT_Full | \
-                                SUPPORTED_Autoneg | \
+#define PHY_DEFAULT_FEATURES   (SUPPORTED_Autoneg | \
                                 SUPPORTED_TP | \
                                 SUPPORTED_MII)
 
-#define PHY_GBIT_FEATURES      (PHY_BASIC_FEATURES | \
-                                SUPPORTED_1000baseT_Half | \
+#define PHY_10BT_FEATURES      (SUPPORTED_10baseT_Half | \
+                                SUPPORTED_10baseT_Full)
+
+#define PHY_100BT_FEATURES     (SUPPORTED_100baseT_Half | \
+                                SUPPORTED_100baseT_Full)
+
+#define PHY_1000BT_FEATURES    (SUPPORTED_1000baseT_Half | \
                                 SUPPORTED_1000baseT_Full)
 
+#define PHY_BASIC_FEATURES     (PHY_10BT_FEATURES | \
+                                PHY_100BT_FEATURES | \
+                                PHY_DEFAULT_FEATURES)
+
+#define PHY_GBIT_FEATURES      (PHY_BASIC_FEATURES | \
+                                PHY_1000BT_FEATURES)
+
+
 /*
  * Set phydev->irq to PHY_POLL if interrupts are not supported,
  * or not desired for this PHY.  Set to PHY_IGNORE_INTERRUPT if
@@ -278,8 +287,8 @@ struct phy_c45_device_ids {
  * adjust_state: Callback for the enet driver to respond to
  * changes in the state machine.
  *
- * speed, duplex, pause, supported, advertising, and
- * autoneg are used like in mii_if_info
+ * speed, duplex, pause, supported, advertising, lp_advertising,
+ * and autoneg are used like in mii_if_info
  *
  * interrupts currently only supports enabled or disabled,
  * but could be changed in the future to support enabling
@@ -331,6 +340,7 @@ struct phy_device {
        /* See mii.h for more info */
        u32 supported;
        u32 advertising;
+       u32 lp_advertising;
 
        int autoneg;
 
diff --git a/include/linux/platform_data/clocksource-nomadik-mtu.h b/include/linux/platform_data/clocksource-nomadik-mtu.h
deleted file mode 100644 (file)
index 8008897..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __PLAT_MTU_H
-#define __PLAT_MTU_H
-
-void nmdk_timer_init(void __iomem *base, int irq);
-void nmdk_clkevt_reset(void);
-void nmdk_clksrc_reset(void);
-
-#endif /* __PLAT_MTU_H */
-
index 689a856b86f90e1329515cf1ad9b80d3e2e7cdf5..5245992b036734dd4c96f1c544539e070d058b64 100644 (file)
@@ -92,6 +92,7 @@ enum {
        MCASP_VERSION_1 = 0,    /* DM646x */
        MCASP_VERSION_2,        /* DA8xx/OMAPL1x */
        MCASP_VERSION_3,        /* TI81xx/AM33xx */
+       MCASP_VERSION_4,        /* DRA7xxx */
 };
 
 enum mcbsp_clk_input_pin {
index 3a3942823c209163501b1dcd49a550d1664c56da..eabac4e2fc993b114ae940b1be960f04015ade0f 100644 (file)
@@ -43,6 +43,11 @@ struct sdma_script_start_addrs {
        s32 dptc_dvfs_addr;
        s32 utra_addr;
        s32 ram_code_start_addr;
+       /* End of v1 array */
+       s32 mcu_2_ssish_addr;
+       s32 ssish_2_mcu_addr;
+       s32 hdmi_dma_addr;
+       /* End of v2 array */
 };
 
 /**
index beac6b8b6a7b3846cf3925cab343da187fc686e1..bcbc6c3c14c0da82547b861e7108ccee41351f71 100644 (file)
@@ -39,6 +39,7 @@ enum sdma_peripheral_type {
        IMX_DMATYPE_IPU_MEMORY, /* IPU Memory */
        IMX_DMATYPE_ASRC,       /* ASRC */
        IMX_DMATYPE_ESAI,       /* ESAI */
+       IMX_DMATYPE_SSI_DUAL,   /* SSI Dual FIFO */
 };
 
 enum imx_dma_prio {
index ffb801998e5dfa10c450f99b2dbb943e8f7a05d4..a941471249299c842a7cfea12de9a4091d2e44e2 100644 (file)
@@ -55,6 +55,9 @@ struct pxa3xx_nand_platform_data {
        /* indicate how many chip selects will be used */
        int     num_cs;
 
+       /* use an flash-based bad block table */
+       bool    flash_bbt;
+
        const struct mtd_partition              *parts[NUM_CHIP_SELECT];
        unsigned int                            nr_parts[NUM_CHIP_SELECT];
 
diff --git a/include/linux/platform_data/pinctrl-nomadik.h b/include/linux/platform_data/pinctrl-nomadik.h
deleted file mode 100644 (file)
index abf5bed..0000000
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Structures and registers for GPIO access in the Nomadik SoC
- *
- * Copyright (C) 2008 STMicroelectronics
- *     Author: Prafulla WADASKAR <prafulla.wadaskar@st.com>
- * Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it>
- *
- * 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 __PLAT_NOMADIK_GPIO
-#define __PLAT_NOMADIK_GPIO
-
-/*
- * pin configurations are represented by 32-bit integers:
- *
- *     bit  0.. 8 - Pin Number (512 Pins Maximum)
- *     bit  9..10 - Alternate Function Selection
- *     bit 11..12 - Pull up/down state
- *     bit     13 - Sleep mode behaviour
- *     bit     14 - Direction
- *     bit     15 - Value (if output)
- *     bit 16..18 - SLPM pull up/down state
- *     bit 19..20 - SLPM direction
- *     bit 21..22 - SLPM Value (if output)
- *     bit 23..25 - PDIS value (if input)
- *     bit     26 - Gpio mode
- *     bit     27 - Sleep mode
- *
- * to facilitate the definition, the following macros are provided
- *
- * PIN_CFG_DEFAULT - default config (0):
- *                  pull up/down = disabled
- *                  sleep mode = input/wakeup
- *                  direction = input
- *                  value = low
- *                  SLPM direction = same as normal
- *                  SLPM pull = same as normal
- *                  SLPM value = same as normal
- *
- * PIN_CFG        - default config with alternate function
- */
-
-typedef unsigned long pin_cfg_t;
-
-#define PIN_NUM_MASK           0x1ff
-#define PIN_NUM(x)             ((x) & PIN_NUM_MASK)
-
-#define PIN_ALT_SHIFT          9
-#define PIN_ALT_MASK           (0x3 << PIN_ALT_SHIFT)
-#define PIN_ALT(x)             (((x) & PIN_ALT_MASK) >> PIN_ALT_SHIFT)
-#define PIN_GPIO               (NMK_GPIO_ALT_GPIO << PIN_ALT_SHIFT)
-#define PIN_ALT_A              (NMK_GPIO_ALT_A << PIN_ALT_SHIFT)
-#define PIN_ALT_B              (NMK_GPIO_ALT_B << PIN_ALT_SHIFT)
-#define PIN_ALT_C              (NMK_GPIO_ALT_C << PIN_ALT_SHIFT)
-
-#define PIN_PULL_SHIFT         11
-#define PIN_PULL_MASK          (0x3 << PIN_PULL_SHIFT)
-#define PIN_PULL(x)            (((x) & PIN_PULL_MASK) >> PIN_PULL_SHIFT)
-#define PIN_PULL_NONE          (NMK_GPIO_PULL_NONE << PIN_PULL_SHIFT)
-#define PIN_PULL_UP            (NMK_GPIO_PULL_UP << PIN_PULL_SHIFT)
-#define PIN_PULL_DOWN          (NMK_GPIO_PULL_DOWN << PIN_PULL_SHIFT)
-
-#define PIN_SLPM_SHIFT         13
-#define PIN_SLPM_MASK          (0x1 << PIN_SLPM_SHIFT)
-#define PIN_SLPM(x)            (((x) & PIN_SLPM_MASK) >> PIN_SLPM_SHIFT)
-#define PIN_SLPM_MAKE_INPUT    (NMK_GPIO_SLPM_INPUT << PIN_SLPM_SHIFT)
-#define PIN_SLPM_NOCHANGE      (NMK_GPIO_SLPM_NOCHANGE << PIN_SLPM_SHIFT)
-/* These two replace the above in DB8500v2+ */
-#define PIN_SLPM_WAKEUP_ENABLE (NMK_GPIO_SLPM_WAKEUP_ENABLE << PIN_SLPM_SHIFT)
-#define PIN_SLPM_WAKEUP_DISABLE        (NMK_GPIO_SLPM_WAKEUP_DISABLE << PIN_SLPM_SHIFT)
-#define PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP PIN_SLPM_WAKEUP_DISABLE
-
-#define PIN_SLPM_GPIO  PIN_SLPM_WAKEUP_ENABLE /* In SLPM, pin is a gpio */
-#define PIN_SLPM_ALTFUNC PIN_SLPM_WAKEUP_DISABLE /* In SLPM, pin is altfunc */
-
-#define PIN_DIR_SHIFT          14
-#define PIN_DIR_MASK           (0x1 << PIN_DIR_SHIFT)
-#define PIN_DIR(x)             (((x) & PIN_DIR_MASK) >> PIN_DIR_SHIFT)
-#define PIN_DIR_INPUT          (0 << PIN_DIR_SHIFT)
-#define PIN_DIR_OUTPUT         (1 << PIN_DIR_SHIFT)
-
-#define PIN_VAL_SHIFT          15
-#define PIN_VAL_MASK           (0x1 << PIN_VAL_SHIFT)
-#define PIN_VAL(x)             (((x) & PIN_VAL_MASK) >> PIN_VAL_SHIFT)
-#define PIN_VAL_LOW            (0 << PIN_VAL_SHIFT)
-#define PIN_VAL_HIGH           (1 << PIN_VAL_SHIFT)
-
-#define PIN_SLPM_PULL_SHIFT    16
-#define PIN_SLPM_PULL_MASK     (0x7 << PIN_SLPM_PULL_SHIFT)
-#define PIN_SLPM_PULL(x)       \
-       (((x) & PIN_SLPM_PULL_MASK) >> PIN_SLPM_PULL_SHIFT)
-#define PIN_SLPM_PULL_NONE     \
-       ((1 + NMK_GPIO_PULL_NONE) << PIN_SLPM_PULL_SHIFT)
-#define PIN_SLPM_PULL_UP       \
-       ((1 + NMK_GPIO_PULL_UP) << PIN_SLPM_PULL_SHIFT)
-#define PIN_SLPM_PULL_DOWN     \
-       ((1 + NMK_GPIO_PULL_DOWN) << PIN_SLPM_PULL_SHIFT)
-
-#define PIN_SLPM_DIR_SHIFT     19
-#define PIN_SLPM_DIR_MASK      (0x3 << PIN_SLPM_DIR_SHIFT)
-#define PIN_SLPM_DIR(x)                \
-       (((x) & PIN_SLPM_DIR_MASK) >> PIN_SLPM_DIR_SHIFT)
-#define PIN_SLPM_DIR_INPUT     ((1 + 0) << PIN_SLPM_DIR_SHIFT)
-#define PIN_SLPM_DIR_OUTPUT    ((1 + 1) << PIN_SLPM_DIR_SHIFT)
-
-#define PIN_SLPM_VAL_SHIFT     21
-#define PIN_SLPM_VAL_MASK      (0x3 << PIN_SLPM_VAL_SHIFT)
-#define PIN_SLPM_VAL(x)                \
-       (((x) & PIN_SLPM_VAL_MASK) >> PIN_SLPM_VAL_SHIFT)
-#define PIN_SLPM_VAL_LOW       ((1 + 0) << PIN_SLPM_VAL_SHIFT)
-#define PIN_SLPM_VAL_HIGH      ((1 + 1) << PIN_SLPM_VAL_SHIFT)
-
-#define PIN_SLPM_PDIS_SHIFT            23
-#define PIN_SLPM_PDIS_MASK             (0x3 << PIN_SLPM_PDIS_SHIFT)
-#define PIN_SLPM_PDIS(x)       \
-       (((x) & PIN_SLPM_PDIS_MASK) >> PIN_SLPM_PDIS_SHIFT)
-#define PIN_SLPM_PDIS_NO_CHANGE                (0 << PIN_SLPM_PDIS_SHIFT)
-#define PIN_SLPM_PDIS_DISABLED         (1 << PIN_SLPM_PDIS_SHIFT)
-#define PIN_SLPM_PDIS_ENABLED          (2 << PIN_SLPM_PDIS_SHIFT)
-
-#define PIN_LOWEMI_SHIFT       25
-#define PIN_LOWEMI_MASK                (0x1 << PIN_LOWEMI_SHIFT)
-#define PIN_LOWEMI(x)          (((x) & PIN_LOWEMI_MASK) >> PIN_LOWEMI_SHIFT)
-#define PIN_LOWEMI_DISABLED    (0 << PIN_LOWEMI_SHIFT)
-#define PIN_LOWEMI_ENABLED     (1 << PIN_LOWEMI_SHIFT)
-
-#define PIN_GPIOMODE_SHIFT     26
-#define PIN_GPIOMODE_MASK      (0x1 << PIN_GPIOMODE_SHIFT)
-#define PIN_GPIOMODE(x)                (((x) & PIN_GPIOMODE_MASK) >> PIN_GPIOMODE_SHIFT)
-#define PIN_GPIOMODE_DISABLED  (0 << PIN_GPIOMODE_SHIFT)
-#define PIN_GPIOMODE_ENABLED   (1 << PIN_GPIOMODE_SHIFT)
-
-#define PIN_SLEEPMODE_SHIFT    27
-#define PIN_SLEEPMODE_MASK     (0x1 << PIN_SLEEPMODE_SHIFT)
-#define PIN_SLEEPMODE(x)       (((x) & PIN_SLEEPMODE_MASK) >> PIN_SLEEPMODE_SHIFT)
-#define PIN_SLEEPMODE_DISABLED (0 << PIN_SLEEPMODE_SHIFT)
-#define PIN_SLEEPMODE_ENABLED  (1 << PIN_SLEEPMODE_SHIFT)
-
-
-/* Shortcuts.  Use these instead of separate DIR, PULL, and VAL.  */
-#define PIN_INPUT_PULLDOWN     (PIN_DIR_INPUT | PIN_PULL_DOWN)
-#define PIN_INPUT_PULLUP       (PIN_DIR_INPUT | PIN_PULL_UP)
-#define PIN_INPUT_NOPULL       (PIN_DIR_INPUT | PIN_PULL_NONE)
-#define PIN_OUTPUT_LOW         (PIN_DIR_OUTPUT | PIN_VAL_LOW)
-#define PIN_OUTPUT_HIGH                (PIN_DIR_OUTPUT | PIN_VAL_HIGH)
-
-#define PIN_SLPM_INPUT_PULLDOWN        (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_DOWN)
-#define PIN_SLPM_INPUT_PULLUP  (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_UP)
-#define PIN_SLPM_INPUT_NOPULL  (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_NONE)
-#define PIN_SLPM_OUTPUT_LOW    (PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_LOW)
-#define PIN_SLPM_OUTPUT_HIGH   (PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_HIGH)
-
-#define PIN_CFG_DEFAULT                (0)
-
-#define PIN_CFG(num, alt)              \
-       (PIN_CFG_DEFAULT |\
-        (PIN_NUM(num) | PIN_##alt))
-
-#define PIN_CFG_INPUT(num, alt, pull)          \
-       (PIN_CFG_DEFAULT |\
-        (PIN_NUM(num) | PIN_##alt | PIN_INPUT_##pull))
-
-#define PIN_CFG_OUTPUT(num, alt, val)          \
-       (PIN_CFG_DEFAULT |\
-        (PIN_NUM(num) | PIN_##alt | PIN_OUTPUT_##val))
-
-/*
- * "nmk_gpio" and "NMK_GPIO" stand for "Nomadik GPIO", leaving
- * the "gpio" namespace for generic and cross-machine functions
- */
-
-#define GPIO_BLOCK_SHIFT 5
-#define NMK_GPIO_PER_CHIP (1 << GPIO_BLOCK_SHIFT)
-
-/* Register in the logic block */
-#define NMK_GPIO_DAT   0x00
-#define NMK_GPIO_DATS  0x04
-#define NMK_GPIO_DATC  0x08
-#define NMK_GPIO_PDIS  0x0c
-#define NMK_GPIO_DIR   0x10
-#define NMK_GPIO_DIRS  0x14
-#define NMK_GPIO_DIRC  0x18
-#define NMK_GPIO_SLPC  0x1c
-#define NMK_GPIO_AFSLA 0x20
-#define NMK_GPIO_AFSLB 0x24
-#define NMK_GPIO_LOWEMI        0x28
-
-#define NMK_GPIO_RIMSC 0x40
-#define NMK_GPIO_FIMSC 0x44
-#define NMK_GPIO_IS    0x48
-#define NMK_GPIO_IC    0x4c
-#define NMK_GPIO_RWIMSC        0x50
-#define NMK_GPIO_FWIMSC        0x54
-#define NMK_GPIO_WKS   0x58
-/* These appear in DB8540 and later ASICs */
-#define NMK_GPIO_EDGELEVEL 0x5C
-#define NMK_GPIO_LEVEL 0x60
-
-/* Alternate functions: function C is set in hw by setting both A and B */
-#define NMK_GPIO_ALT_GPIO      0
-#define NMK_GPIO_ALT_A 1
-#define NMK_GPIO_ALT_B 2
-#define NMK_GPIO_ALT_C (NMK_GPIO_ALT_A | NMK_GPIO_ALT_B)
-
-#define NMK_GPIO_ALT_CX_SHIFT 2
-#define NMK_GPIO_ALT_C1        ((1<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
-#define NMK_GPIO_ALT_C2        ((2<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
-#define NMK_GPIO_ALT_C3        ((3<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
-#define NMK_GPIO_ALT_C4        ((4<<NMK_GPIO_ALT_CX_SHIFT) | NMK_GPIO_ALT_C)
-
-/* Pull up/down values */
-enum nmk_gpio_pull {
-       NMK_GPIO_PULL_NONE,
-       NMK_GPIO_PULL_UP,
-       NMK_GPIO_PULL_DOWN,
-};
-
-/* Sleep mode */
-enum nmk_gpio_slpm {
-       NMK_GPIO_SLPM_INPUT,
-       NMK_GPIO_SLPM_WAKEUP_ENABLE = NMK_GPIO_SLPM_INPUT,
-       NMK_GPIO_SLPM_NOCHANGE,
-       NMK_GPIO_SLPM_WAKEUP_DISABLE = NMK_GPIO_SLPM_NOCHANGE,
-};
-
-/*
- * Platform data to register a block: only the initial gpio/irq number.
- */
-struct nmk_gpio_platform_data {
-       char *name;
-       int first_gpio;
-       int first_irq;
-       int num_gpio;
-       u32 (*get_secondary_status)(unsigned int bank);
-       void (*set_ioforce)(bool enable);
-       bool supports_sleepmode;
-};
-
-#endif /* __PLAT_NOMADIK_GPIO */
index 713bfd7033429c91f80400086222ec927a615865..5ce1ab983f44d1c0191fe0a29f403cb5f6482507 100644 (file)
@@ -16,8 +16,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef _PN544_H_
index 5c2600630dc99ace79f3d001416db6d37f568806..3e28fe188d171a11f224fcdc36975a031c7146b2 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/workqueue.h>
 #include <linux/leds.h>
 #include <linux/spinlock.h>
+#include <linux/notifier.h>
 
 struct device;
 
@@ -158,6 +159,10 @@ enum power_supply_type {
        POWER_SUPPLY_TYPE_USB_ACA,      /* Accessory Charger Adapters */
 };
 
+enum power_supply_notifier_events {
+       PSY_EVENT_PROP_CHANGED,
+};
+
 union power_supply_propval {
        int intval;
        const char *strval;
@@ -235,6 +240,9 @@ struct power_supply_info {
        int use_for_apm;
 };
 
+extern struct atomic_notifier_head power_supply_notifier;
+extern int power_supply_reg_notifier(struct notifier_block *nb);
+extern void power_supply_unreg_notifier(struct notifier_block *nb);
 extern struct power_supply *power_supply_get_by_name(const char *name);
 extern void power_supply_changed(struct power_supply *psy);
 extern int power_supply_am_i_supplied(struct power_supply *psy);
index 7e35d4b9e14a45cba37fd8a7f234e5a3a50ec4b5..bf14c215af1e820eb2395950701fc5b5831aa2c8 100644 (file)
@@ -168,7 +168,6 @@ extern char ___assert_task_state[1 - 2*!!(
 
 #define task_is_traced(task)   ((task->state & __TASK_TRACED) != 0)
 #define task_is_stopped(task)  ((task->state & __TASK_STOPPED) != 0)
-#define task_is_dead(task)     ((task)->exit_state != 0)
 #define task_is_stopped_or_traced(task)        \
                        ((task->state & (__TASK_STOPPED | __TASK_TRACED)) != 0)
 #define task_contributes_to_load(task) \
@@ -831,8 +830,6 @@ struct sched_domain {
        unsigned int balance_interval;  /* initialise to 1. units in ms. */
        unsigned int nr_balance_failed; /* initialise to 0 */
 
-       u64 last_update;
-
        /* idle_balance() stats */
        u64 max_newidle_lb_cost;
        unsigned long next_decay_max_lb_cost;
index 3bfe8d6ee248e8e38df18e9b0462678ee76d479f..c4c5eba26d9f4cc5711de1141e313613db19b205 100644 (file)
@@ -23,9 +23,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
index 50fe651da965933f416b3cc6a5a0080942ac107e..3dbdf7e53dcc0942153be0a59cdeebd73caa0973 100644 (file)
 #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)
index 631af63af42ddbaaabf6f8debcda035821cc71dc..2cfcb7944a493432d7e44088e0b9ccd13b16aafa 100644 (file)
@@ -60,7 +60,7 @@
 #define _LINUX_SFI_ACPI_H
 
 #ifdef CONFIG_SFI
-#include <acpi/acpi.h>         /* struct acpi_table_header */
+#include <acpi/acpi.h> /* FIXME: inclusion should be removed */
 
 extern int sfi_acpi_table_parse(char *signature, char *oem_id,
                                char *oem_table_id,
index bec1cc7d5e3c41efbc4939ab742eeb955b64b7f0..77c7aae1c6b20d7d72baff3fa0f6de05851b44ba 100644 (file)
@@ -2263,6 +2263,24 @@ static inline void skb_postpull_rcsum(struct sk_buff *skb,
 
 unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len);
 
+/**
+ *     pskb_trim_rcsum - trim received skb and update checksum
+ *     @skb: buffer to trim
+ *     @len: new length
+ *
+ *     This is exactly the same as pskb_trim except that it ensures the
+ *     checksum of received packets are still valid after the operation.
+ */
+
+static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len)
+{
+       if (likely(len >= skb->len))
+               return 0;
+       if (skb->ip_summed == CHECKSUM_COMPLETE)
+               skb->ip_summed = CHECKSUM_NONE;
+       return __pskb_trim(skb, len);
+}
+
 #define skb_queue_walk(queue, skb) \
                for (skb = (queue)->next;                                       \
                     skb != (struct sk_buff *)(queue);                          \
@@ -2360,27 +2378,6 @@ __wsum __skb_checksum(const struct sk_buff *skb, int offset, int len,
 __wsum skb_checksum(const struct sk_buff *skb, int offset, int len,
                    __wsum csum);
 
-/**
- *     pskb_trim_rcsum - trim received skb and update checksum
- *     @skb: buffer to trim
- *     @len: new length
- *
- *     This is exactly the same as pskb_trim except that it ensures the
- *     checksum of received packets are still valid after the operation.
- */
-
-static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len)
-{
-       if (likely(len >= skb->len))
-               return 0;
-       if (skb->ip_summed == CHECKSUM_COMPLETE) {
-               __wsum adj = skb_checksum(skb, len, skb->len - len, 0);
-
-               skb->csum = csum_sub(skb->csum, adj);
-       }
-       return __pskb_trim(skb, len);
-}
-
 static inline void *skb_header_pointer(const struct sk_buff *skb, int offset,
                                       int len, void *buffer)
 {
@@ -2395,6 +2392,24 @@ static inline void *skb_header_pointer(const struct sk_buff *skb, int offset,
        return buffer;
 }
 
+/**
+ *     skb_needs_linearize - check if we need to linearize a given skb
+ *                           depending on the given device features.
+ *     @skb: socket buffer to check
+ *     @features: net device features
+ *
+ *     Returns true if either:
+ *     1. skb has frag_list and the device doesn't support FRAGLIST, or
+ *     2. skb is fragmented and the device does not support SG.
+ */
+static inline bool skb_needs_linearize(struct sk_buff *skb,
+                                      netdev_features_t features)
+{
+       return skb_is_nonlinear(skb) &&
+              ((skb_has_frag_list(skb) && !(features & NETIF_F_FRAGLIST)) ||
+               (skb_shinfo(skb)->nr_frags && !(features & NETIF_F_SG)));
+}
+
 static inline void skb_copy_from_linear_data(const struct sk_buff *skb,
                                             void *to,
                                             const unsigned int len)
index a353e0300b54b97a63cf4b87baf28cacf91428b8..7f490bef9e99f9838294bbb674e3014a7128185b 100644 (file)
@@ -84,7 +84,8 @@ enum {
 
 extern struct dentry *rpc_d_lookup_sb(const struct super_block *sb,
                                      const unsigned char *dir_name);
-extern void rpc_pipefs_init_net(struct net *net);
+extern int rpc_pipefs_init_net(struct net *net);
+extern void rpc_pipefs_exit_net(struct net *net);
 extern struct super_block *rpc_get_sb_net(const struct net *net);
 extern void rpc_put_sb_net(const struct net *net);
 
@@ -130,5 +131,7 @@ extern int rpc_unlink(struct dentry *);
 extern int register_rpc_pipefs(void);
 extern void unregister_rpc_pipefs(void);
 
+extern bool gssd_running(struct net *net);
+
 #endif
 #endif
index 6eecfc2e4f989b8e9511719cee900f75e057850c..b631642318c517a71cce7db9ba56c0743f0c6900 100644 (file)
@@ -368,7 +368,7 @@ struct svc_program {
        struct svc_program *    pg_next;        /* other programs (same xprt) */
        u32                     pg_prog;        /* program number */
        unsigned int            pg_lovers;      /* lowest version */
-       unsigned int            pg_hivers;      /* lowest version */
+       unsigned int            pg_hivers;      /* highest version */
        unsigned int            pg_nvers;       /* number of versions */
        struct svc_version **   pg_vers;        /* version array */
        char *                  pg_name;        /* service name */
index c75128bed5fa39116952fd148ff01374993b8f44..9a54b331f938fcfc02d66a22873b8d735369d8ad 100644 (file)
@@ -34,7 +34,7 @@ enum {
 };
 
 #ifdef CONFIG_INTEL_TXT
-#include <acpi/acpi.h>
+#include <linux/acpi.h>
 /* used to communicate between tboot and the launched kernel */
 
 #define TB_KEY_SIZE             64   /* 512 bits */
index ebeab360d851c1ece4952b3f5f4f294aa9673db0..accc497f8d729160b0234756e96d99607cf67f33 100644 (file)
@@ -267,6 +267,8 @@ static inline void tracepoint_synchronize_unregister(void)
 
 #define TRACE_EVENT_FLAGS(event, flag)
 
+#define TRACE_EVENT_PERF_PERM(event, expr...)
+
 #endif /* DECLARE_TRACE */
 
 #ifndef TRACE_EVENT
@@ -274,7 +276,7 @@ static inline void tracepoint_synchronize_unregister(void)
  * For use with the TRACE_EVENT macro:
  *
  * We define a tracepoint, its arguments, its printk format
- * and its 'fast binay record' layout.
+ * and its 'fast binary record' layout.
  *
  * Firstly, name your tracepoint via TRACE_EVENT(name : the
  * 'subsystem_event' notation is fine.
@@ -399,4 +401,6 @@ static inline void tracepoint_synchronize_unregister(void)
 
 #define TRACE_EVENT_FLAGS(event, flag)
 
+#define TRACE_EVENT_PERF_PERM(event, expr...)
+
 #endif /* ifdef TRACE_EVENT (see note above) */
index 319eae70fe8415f774e57c4861b98688fb81bb4c..e32251e00e62f0b2629c0ef7658d1445e6647586 100644 (file)
 
 #include <linux/errno.h>
 #include <linux/rbtree.h>
+#include <linux/types.h>
 
 struct vm_area_struct;
 struct mm_struct;
 struct inode;
 struct notifier_block;
 
-#ifdef CONFIG_ARCH_SUPPORTS_UPROBES
-# include <asm/uprobes.h>
-#endif
-
 #define UPROBE_HANDLER_REMOVE          1
 #define UPROBE_HANDLER_MASK            1
 
@@ -60,6 +57,8 @@ struct uprobe_consumer {
 };
 
 #ifdef CONFIG_UPROBES
+#include <asm/uprobes.h>
+
 enum uprobe_task_state {
        UTASK_RUNNING,
        UTASK_SSTEP,
@@ -72,35 +71,28 @@ enum uprobe_task_state {
  */
 struct uprobe_task {
        enum uprobe_task_state          state;
-       struct arch_uprobe_task         autask;
 
-       struct return_instance          *return_instances;
-       unsigned int                    depth;
-       struct uprobe                   *active_uprobe;
+       union {
+               struct {
+                       struct arch_uprobe_task autask;
+                       unsigned long           vaddr;
+               };
 
+               struct {
+                       struct callback_head    dup_xol_work;
+                       unsigned long           dup_xol_addr;
+               };
+       };
+
+       struct uprobe                   *active_uprobe;
        unsigned long                   xol_vaddr;
-       unsigned long                   vaddr;
-};
 
-/*
- * On a breakpoint hit, thread contests for a slot.  It frees the
- * slot after singlestep. Currently a fixed number of slots are
- * allocated.
- */
-struct xol_area {
-       wait_queue_head_t       wq;             /* if all slots are busy */
-       atomic_t                slot_count;     /* number of in-use slots */
-       unsigned long           *bitmap;        /* 0 = free slot */
-       struct page             *page;
-
-       /*
-        * We keep the vma's vm_start rather than a pointer to the vma
-        * itself.  The probed process or a naughty kernel module could make
-        * the vma go away, and we must handle that reasonably gracefully.
-        */
-       unsigned long           vaddr;          /* Page(s) of instruction slots */
+       struct return_instance          *return_instances;
+       unsigned int                    depth;
 };
 
+struct xol_area;
+
 struct uprobes_state {
        struct xol_area         *xol_area;
 };
@@ -109,6 +101,7 @@ extern int __weak set_swbp(struct arch_uprobe *aup, struct mm_struct *mm, unsign
 extern int __weak set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr);
 extern bool __weak is_swbp_insn(uprobe_opcode_t *insn);
 extern bool __weak is_trap_insn(uprobe_opcode_t *insn);
+extern unsigned long __weak uprobe_get_swbp_addr(struct pt_regs *regs);
 extern int uprobe_write_opcode(struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_t);
 extern int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc);
 extern int uprobe_apply(struct inode *inode, loff_t offset, struct uprobe_consumer *uc, bool);
@@ -120,7 +113,6 @@ extern void uprobe_end_dup_mmap(void);
 extern void uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm);
 extern void uprobe_free_utask(struct task_struct *t);
 extern void uprobe_copy_process(struct task_struct *t, unsigned long flags);
-extern unsigned long __weak uprobe_get_swbp_addr(struct pt_regs *regs);
 extern int uprobe_post_sstep_notifier(struct pt_regs *regs);
 extern int uprobe_pre_sstep_notifier(struct pt_regs *regs);
 extern void uprobe_notify_resume(struct pt_regs *regs);
@@ -176,10 +168,6 @@ static inline bool uprobe_deny_signal(void)
 {
        return false;
 }
-static inline unsigned long uprobe_get_swbp_addr(struct pt_regs *regs)
-{
-       return 0;
-}
 static inline void uprobe_free_utask(struct task_struct *t)
 {
 }
index 7454865ad14834f50a05dc9baf7f6d78ea3de7b8..512ab162832ccc0bb4b30f6210d083d762573b78 100644 (file)
@@ -1264,6 +1264,8 @@ typedef void (*usb_complete_t)(struct urb *);
  * @sg: scatter gather buffer list, the buffer size of each element in
  *     the list (except the last) must be divisible by the endpoint's
  *     max packet size if no_sg_constraint isn't set in 'struct usb_bus'
+ *     (FIXME: scatter-gather under xHCI is broken for periodic transfers.
+ *     Do not use urb->sg for interrupt endpoints for now, only bulk.)
  * @num_mapped_sgs: (internal) number of mapped sg entries
  * @num_sgs: number of entries in the sg list
  * @transfer_buffer_length: How big is transfer_buffer.  The transfer may
index 0c4d4ca370ec9ba2e88c90b5d9a34b1efc9bc557..eeb28329fa3c9a17087834e2bb2f4d054757a005 100644 (file)
@@ -271,6 +271,8 @@ static inline u8 wusb_key_index(int index, int type, int originator)
 #define WUSB_KEY_INDEX_TYPE_GTK                        2
 #define WUSB_KEY_INDEX_ORIGINATOR_HOST         0
 #define WUSB_KEY_INDEX_ORIGINATOR_DEVICE       1
+/* bits 0-3 used for the key index. */
+#define WUSB_KEY_INDEX_MAX                     15
 
 /* A CCM Nonce, defined in WUSB1.0[6.4.1] */
 struct aes_ccm_nonce {
index 3f3788d4936292ce150a6cb4b56036a58c541128..3e4535876d37493e590d43a687aa980646dab0c4 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/gfp.h>
 #include <linux/types.h>
 #include <linux/cgroup.h>
+#include <linux/eventfd.h>
 
 struct vmpressure {
        unsigned long scanned;
@@ -33,13 +34,10 @@ extern void vmpressure_init(struct vmpressure *vmpr);
 extern void vmpressure_cleanup(struct vmpressure *vmpr);
 extern struct vmpressure *memcg_to_vmpressure(struct mem_cgroup *memcg);
 extern struct cgroup_subsys_state *vmpressure_to_css(struct vmpressure *vmpr);
-extern struct vmpressure *css_to_vmpressure(struct cgroup_subsys_state *css);
-extern int vmpressure_register_event(struct cgroup_subsys_state *css,
-                                    struct cftype *cft,
+extern int vmpressure_register_event(struct mem_cgroup *memcg,
                                     struct eventfd_ctx *eventfd,
                                     const char *args);
-extern void vmpressure_unregister_event(struct cgroup_subsys_state *css,
-                                       struct cftype *cft,
+extern void vmpressure_unregister_event(struct mem_cgroup *memcg,
                                        struct eventfd_ctx *eventfd);
 #else
 static inline void vmpressure(gfp_t gfp, struct mem_cgroup *memcg,
index dff42025649b32cb03f84d359c0c213ec5617569..63fbba0740c2c2bfb35b4a29f6c146b0137f695d 100644 (file)
 #ifndef _LINUX_ZORRO_H
 #define _LINUX_ZORRO_H
 
-#include <linux/device.h>
-
-
-    /*
-     *  Each Zorro board has a 32-bit ID of the form
-     *
-     *      mmmmmmmmmmmmmmmmppppppppeeeeeeee
-     *
-     *  with
-     *
-     *      mmmmmmmmmmmmmmmm   16-bit Manufacturer ID (assigned by CBM (sigh))
-     *      pppppppp           8-bit Product ID (assigned by manufacturer)
-     *      eeeeeeee           8-bit Extended Product ID (currently only used
-     *                         for some GVP boards)
-     */
-
-
-#define ZORRO_MANUF(id)                ((id) >> 16)
-#define ZORRO_PROD(id)         (((id) >> 8) & 0xff)
-#define ZORRO_EPC(id)          ((id) & 0xff)
-
-#define ZORRO_ID(manuf, prod, epc) \
-    ((ZORRO_MANUF_##manuf << 16) | ((prod) << 8) | (epc))
-
-typedef __u32 zorro_id;
-
-
-/* Include the ID list */
-#include <linux/zorro_ids.h>
-
 
-    /*
-     *  GVP identifies most of its products through the 'extended product code'
-     *  (epc). The epc has to be ANDed with the GVP_PRODMASK before the
-     *  identification.
-     */
-
-#define GVP_PRODMASK                   (0xf8)
-#define GVP_SCSICLKMASK                        (0x01)
-
-enum GVP_flags {
-    GVP_IO             = 0x01,
-    GVP_ACCEL          = 0x02,
-    GVP_SCSI           = 0x04,
-    GVP_24BITDMA       = 0x08,
-    GVP_25BITDMA       = 0x10,
-    GVP_NOBANK         = 0x20,
-    GVP_14MHZ          = 0x40,
-};
-
-
-struct Node {
-    struct  Node *ln_Succ;     /* Pointer to next (successor) */
-    struct  Node *ln_Pred;     /* Pointer to previous (predecessor) */
-    __u8    ln_Type;
-    __s8    ln_Pri;            /* Priority, for sorting */
-    __s8    *ln_Name;          /* ID string, null terminated */
-} __attribute__ ((packed));
-
-struct ExpansionRom {
-    /* -First 16 bytes of the expansion ROM */
-    __u8  er_Type;             /* Board type, size and flags */
-    __u8  er_Product;          /* Product number, assigned by manufacturer */
-    __u8  er_Flags;            /* Flags */
-    __u8  er_Reserved03;       /* Must be zero ($ff inverted) */
-    __u16 er_Manufacturer;     /* Unique ID, ASSIGNED BY COMMODORE-AMIGA! */
-    __u32 er_SerialNumber;     /* Available for use by manufacturer */
-    __u16 er_InitDiagVec;      /* Offset to optional "DiagArea" structure */
-    __u8  er_Reserved0c;
-    __u8  er_Reserved0d;
-    __u8  er_Reserved0e;
-    __u8  er_Reserved0f;
-} __attribute__ ((packed));
-
-/* er_Type board type bits */
-#define ERT_TYPEMASK   0xc0
-#define ERT_ZORROII    0xc0
-#define ERT_ZORROIII   0x80
-
-/* other bits defined in er_Type */
-#define ERTB_MEMLIST   5               /* Link RAM into free memory list */
-#define ERTF_MEMLIST   (1<<5)
-
-struct ConfigDev {
-    struct Node                cd_Node;
-    __u8               cd_Flags;       /* (read/write) */
-    __u8               cd_Pad;         /* reserved */
-    struct ExpansionRom cd_Rom;                /* copy of board's expansion ROM */
-    void               *cd_BoardAddr;  /* where in memory the board was placed */
-    __u32              cd_BoardSize;   /* size of board in bytes */
-    __u16              cd_SlotAddr;    /* which slot number (PRIVATE) */
-    __u16              cd_SlotSize;    /* number of slots (PRIVATE) */
-    void               *cd_Driver;     /* pointer to node of driver */
-    struct ConfigDev   *cd_NextCD;     /* linked list of drivers to config */
-    __u32              cd_Unused[4];   /* for whatever the driver wants */
-} __attribute__ ((packed));
-
-#define ZORRO_NUM_AUTO         16
-
-#ifdef __KERNEL__
+#include <uapi/linux/zorro.h>
 
+#include <linux/device.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/mod_devicetable.h>
@@ -175,7 +78,23 @@ static inline struct zorro_driver *zorro_dev_driver(const struct zorro_dev *z)
 
 
 extern unsigned int zorro_num_autocon; /* # of autoconfig devices found */
-extern struct zorro_dev zorro_autocon[ZORRO_NUM_AUTO];
+extern struct zorro_dev *zorro_autocon;
+
+
+    /*
+     * Minimal information about a Zorro device, passed from bootinfo
+     * Only available temporarily, i.e. until initmem has been freed!
+     */
+
+struct zorro_dev_init {
+       struct ExpansionRom rom;
+       u16 slotaddr;
+       u16 slotsize;
+       u32 boardaddr;
+       u32 boardsize;
+};
+
+extern struct zorro_dev_init zorro_autocon_init[ZORRO_NUM_AUTO] __initdata;
 
 
     /*
@@ -229,6 +148,4 @@ extern DECLARE_BITMAP(zorro_unused_z2ram, 128);
 #define Z2RAM_CHUNKSHIFT       (16)
 
 
-#endif /* __KERNEL__ */
-
 #endif /* _LINUX_ZORRO_H */
diff --git a/include/media/omap4iss.h b/include/media/omap4iss.h
new file mode 100644 (file)
index 0000000..0d7620d
--- /dev/null
@@ -0,0 +1,65 @@
+#ifndef ARCH_ARM_PLAT_OMAP4_ISS_H
+#define ARCH_ARM_PLAT_OMAP4_ISS_H
+
+#include <linux/i2c.h>
+
+struct iss_device;
+
+enum iss_interface_type {
+       ISS_INTERFACE_CSI2A_PHY1,
+       ISS_INTERFACE_CSI2B_PHY2,
+};
+
+/**
+ * struct iss_csiphy_lane: CSI2 lane position and polarity
+ * @pos: position of the lane
+ * @pol: polarity of the lane
+ */
+struct iss_csiphy_lane {
+       u8 pos;
+       u8 pol;
+};
+
+#define ISS_CSIPHY1_NUM_DATA_LANES     4
+#define ISS_CSIPHY2_NUM_DATA_LANES     1
+
+/**
+ * struct iss_csiphy_lanes_cfg - CSI2 lane configuration
+ * @data: Configuration of one or two data lanes
+ * @clk: Clock lane configuration
+ */
+struct iss_csiphy_lanes_cfg {
+       struct iss_csiphy_lane data[ISS_CSIPHY1_NUM_DATA_LANES];
+       struct iss_csiphy_lane clk;
+};
+
+/**
+ * struct iss_csi2_platform_data - CSI2 interface platform data
+ * @crc: Enable the cyclic redundancy check
+ * @vpclk_div: Video port output clock control
+ */
+struct iss_csi2_platform_data {
+       unsigned crc:1;
+       unsigned vpclk_div:2;
+       struct iss_csiphy_lanes_cfg lanecfg;
+};
+
+struct iss_subdev_i2c_board_info {
+       struct i2c_board_info *board_info;
+       int i2c_adapter_id;
+};
+
+struct iss_v4l2_subdevs_group {
+       struct iss_subdev_i2c_board_info *subdevs;
+       enum iss_interface_type interface;
+       union {
+               struct iss_csi2_platform_data csi2;
+       } bus; /* gcc < 4.6.0 chokes on anonymous union initializers */
+};
+
+struct iss_platform_data {
+       struct iss_v4l2_subdevs_group *subdevs;
+       void (*set_constraints)(struct iss_device *iss, bool enable);
+};
+
+#endif
index 528cdaf622e192aa572ade990b60acf949e74109..803516775162d184d4dbe8cf78e427ec3452e23c 100644 (file)
@@ -45,6 +45,10 @@ struct v4l2_fh {
        struct list_head        available; /* Dequeueable event */
        unsigned int            navailable;
        u32                     sequence;
+
+#if IS_ENABLED(CONFIG_V4L2_MEM2MEM_DEV)
+       struct v4l2_m2m_ctx     *m2m_ctx;
+#endif
 };
 
 /*
index 44542a20ab8126cdcd851a3d369f2b2b956c96ac..12ea5a6a4331c7036341f6bc0ff4cbe48d767a01 100644 (file)
@@ -64,6 +64,9 @@ struct v4l2_m2m_queue_ctx {
 };
 
 struct v4l2_m2m_ctx {
+       /* optional cap/out vb2 queues lock */
+       struct mutex                    *q_lock;
+
 /* private: internal use only */
        struct v4l2_m2m_dev             *m2m_dev;
 
@@ -229,5 +232,26 @@ static inline void *v4l2_m2m_dst_buf_remove(struct v4l2_m2m_ctx *m2m_ctx)
        return v4l2_m2m_buf_remove(&m2m_ctx->cap_q_ctx);
 }
 
+/* v4l2 ioctl helpers */
+
+int v4l2_m2m_ioctl_reqbufs(struct file *file, void *priv,
+                               struct v4l2_requestbuffers *rb);
+int v4l2_m2m_ioctl_create_bufs(struct file *file, void *fh,
+                               struct v4l2_create_buffers *create);
+int v4l2_m2m_ioctl_querybuf(struct file *file, void *fh,
+                               struct v4l2_buffer *buf);
+int v4l2_m2m_ioctl_expbuf(struct file *file, void *fh,
+                               struct v4l2_exportbuffer *eb);
+int v4l2_m2m_ioctl_qbuf(struct file *file, void *fh,
+                               struct v4l2_buffer *buf);
+int v4l2_m2m_ioctl_dqbuf(struct file *file, void *fh,
+                               struct v4l2_buffer *buf);
+int v4l2_m2m_ioctl_streamon(struct file *file, void *fh,
+                               enum v4l2_buf_type type);
+int v4l2_m2m_ioctl_streamoff(struct file *file, void *fh,
+                               enum v4l2_buf_type type);
+int v4l2_m2m_fop_mmap(struct file *file, struct vm_area_struct *vma);
+unsigned int v4l2_m2m_fop_poll(struct file *file, poll_table *wait);
+
 #endif /* _MEDIA_V4L2_MEM2MEM_H */
 
index bd8218b15009a810af8abd5df5a4bcad31dfdb20..0ae974ee8894d1d040e0d7a527d4e3ab187abf03 100644 (file)
@@ -83,7 +83,7 @@ struct vb2_fileio_data;
 struct vb2_mem_ops {
        void            *(*alloc)(void *alloc_ctx, unsigned long size, gfp_t gfp_flags);
        void            (*put)(void *buf_priv);
-       struct dma_buf *(*get_dmabuf)(void *buf_priv);
+       struct dma_buf *(*get_dmabuf)(void *buf_priv, unsigned long flags);
 
        void            *(*get_userptr)(void *alloc_ctx, unsigned long vaddr,
                                        unsigned long size, int write);
@@ -491,6 +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);
+int _vb2_fop_release(struct file *file, struct mutex *lock);
 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,
index 86505bfa5d2c4829698d21ce81ba47575b504941..66c4a44d8f5cb22a6a9aca1454d422775fc67034 100644 (file)
@@ -81,9 +81,9 @@ int ipv6_dev_get_saddr(struct net *net, const struct net_device *dev,
                       const struct in6_addr *daddr, unsigned int srcprefs,
                       struct in6_addr *saddr);
 int __ipv6_get_lladdr(struct inet6_dev *idev, struct in6_addr *addr,
-                     unsigned char banned_flags);
+                     u32 banned_flags);
 int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr,
-                   unsigned char banned_flags);
+                   u32 banned_flags);
 int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2);
 void addrconf_join_solict(struct net_device *dev, const struct in6_addr *addr);
 void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr);
@@ -248,6 +248,13 @@ static inline struct inet6_dev *in6_dev_get(const struct net_device *dev)
        return idev;
 }
 
+static inline struct neigh_parms *__in6_dev_nd_parms_get_rcu(const struct net_device *dev)
+{
+       struct inet6_dev *idev = __in6_dev_get(dev);
+
+       return idev ? idev->nd_parms : NULL;
+}
+
 void in6_dev_finish_destroy(struct inet6_dev *idev);
 
 static inline void in6_dev_put(struct inet6_dev *idev)
index 2a628b28249ffd00f8b4bd36d4e024583599ad67..f4f9ee466791a9b9fc0b0d7f74f22e2cf3660ac2 100644 (file)
@@ -115,6 +115,9 @@ struct bt_voice {
 #define BT_VOICE_TRANSPARENT                   0x0003
 #define BT_VOICE_CVSD_16BIT                    0x0060
 
+#define BT_SNDMTU              12
+#define BT_RCVMTU              13
+
 __printf(1, 2)
 int bt_info(const char *fmt, ...);
 __printf(1, 2)
index 1784c48699f04dd425027d2e51d0aabc3fd87f4a..5dc3d90726502db224c5b7160e173ecb3e059b64 100644 (file)
@@ -131,6 +131,7 @@ enum {
        HCI_PERIODIC_INQ,
        HCI_FAST_CONNECTABLE,
        HCI_BREDR_ENABLED,
+       HCI_6LOWPAN_ENABLED,
 };
 
 /* A mask for the flags that are supposed to remain when a reset happens
@@ -275,6 +276,12 @@ enum {
 #define LMP_EXTFEATURES        0x80
 
 /* Extended LMP features */
+#define LMP_CSB_MASTER 0x01
+#define LMP_CSB_SLAVE  0x02
+#define LMP_SYNC_TRAIN 0x04
+#define LMP_SYNC_SCAN  0x08
+
+/* Host features */
 #define LMP_HOST_SSP           0x01
 #define LMP_HOST_LE            0x02
 #define LMP_HOST_LE_BREDR      0x04
index f8555ad7b10485925b07393019579c1ee706b2b0..f2f0cf5865c40a9b92f7a98eb4c53c6834a34d29 100644 (file)
@@ -448,6 +448,7 @@ enum {
        HCI_CONN_SSP_ENABLED,
        HCI_CONN_POWER_SAVE,
        HCI_CONN_REMOTE_OOB,
+       HCI_CONN_6LOWPAN,
 };
 
 static inline bool hci_conn_ssp_enabled(struct hci_conn *conn)
@@ -798,6 +799,12 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
 #define lmp_transp_capable(dev)    ((dev)->features[0][2] & LMP_TRANSPARENT)
 
 /* ----- Extended LMP capabilities ----- */
+#define lmp_csb_master_capable(dev) ((dev)->features[2][0] & LMP_CSB_MASTER)
+#define lmp_csb_slave_capable(dev)  ((dev)->features[2][0] & LMP_CSB_SLAVE)
+#define lmp_sync_train_capable(dev) ((dev)->features[2][0] & LMP_SYNC_TRAIN)
+#define lmp_sync_scan_capable(dev)  ((dev)->features[2][0] & LMP_SYNC_SCAN)
+
+/* ----- Host capabilities ----- */
 #define lmp_host_ssp_capable(dev)  ((dev)->features[1][0] & LMP_HOST_SSP)
 #define lmp_host_le_capable(dev)   (!!((dev)->features[1][0] & LMP_HOST_LE))
 #define lmp_host_le_br_capable(dev) (!!((dev)->features[1][0] & LMP_HOST_LE_BREDR))
index c853b16de4efde38a501440ce58ca260a379e5da..dbc4a89984ca67287715a8279b2d9793e7d2eebe 100644 (file)
@@ -112,6 +112,9 @@ struct l2cap_conninfo {
 #define L2CAP_MOVE_CHAN_CFM_RSP        0x11
 #define L2CAP_CONN_PARAM_UPDATE_REQ    0x12
 #define L2CAP_CONN_PARAM_UPDATE_RSP    0x13
+#define L2CAP_LE_CONN_REQ      0x14
+#define L2CAP_LE_CONN_RSP      0x15
+#define L2CAP_LE_CREDITS       0x16
 
 /* L2CAP extended feature mask */
 #define L2CAP_FEAT_FLOWCTL     0x00000001
@@ -133,6 +136,7 @@ struct l2cap_conninfo {
 #define L2CAP_FC_L2CAP         0x02
 #define L2CAP_FC_CONNLESS      0x04
 #define L2CAP_FC_A2MP          0x08
+#define L2CAP_FC_6LOWPAN        0x3e /* reserved and temporary value */
 
 /* L2CAP Control Field bit masks */
 #define L2CAP_CTRL_SAR                 0xC000
@@ -249,6 +253,7 @@ struct l2cap_conn_rsp {
 #define L2CAP_CID_SMP          0x0006
 #define L2CAP_CID_DYN_START    0x0040
 #define L2CAP_CID_DYN_END      0xffff
+#define L2CAP_CID_LE_DYN_END   0x007f
 
 /* connect/create channel results */
 #define L2CAP_CR_SUCCESS       0x0000
@@ -257,6 +262,10 @@ struct l2cap_conn_rsp {
 #define L2CAP_CR_SEC_BLOCK     0x0003
 #define L2CAP_CR_NO_MEM                0x0004
 #define L2CAP_CR_BAD_AMP       0x0005
+#define L2CAP_CR_AUTHENTICATION        0x0005
+#define L2CAP_CR_AUTHORIZATION 0x0006
+#define L2CAP_CR_BAD_KEY_SIZE  0x0007
+#define L2CAP_CR_ENCRYPTION    0x0008
 
 /* connect/create channel status */
 #define L2CAP_CS_NO_INFO       0x0000
@@ -321,6 +330,12 @@ struct l2cap_conf_rfc {
 #define L2CAP_MODE_ERTM                0x03
 #define L2CAP_MODE_STREAMING   0x04
 
+/* Unlike the above this one doesn't actually map to anything that would
+ * ever be sent over the air. Therefore, use a value that's unlikely to
+ * ever be used in the BR/EDR configuration phase.
+ */
+#define L2CAP_MODE_LE_FLOWCTL  0x80
+
 struct l2cap_conf_efs {
        __u8    id;
        __u8    stype;
@@ -423,6 +438,30 @@ struct l2cap_conn_param_update_rsp {
 #define L2CAP_CONN_PARAM_ACCEPTED      0x0000
 #define L2CAP_CONN_PARAM_REJECTED      0x0001
 
+#define L2CAP_LE_MAX_CREDITS           10
+#define L2CAP_LE_DEFAULT_MPS           230
+
+struct l2cap_le_conn_req {
+       __le16     psm;
+       __le16     scid;
+       __le16     mtu;
+       __le16     mps;
+       __le16     credits;
+} __packed;
+
+struct l2cap_le_conn_rsp {
+       __le16     dcid;
+       __le16     mtu;
+       __le16     mps;
+       __le16     credits;
+       __le16     result;
+} __packed;
+
+struct l2cap_le_credits {
+       __le16     cid;
+       __le16     credits;
+} __packed;
+
 /* ----- L2CAP channels and connections ----- */
 struct l2cap_seq_list {
        __u16   head;
@@ -477,6 +516,9 @@ struct l2cap_chan {
        __u16           monitor_timeout;
        __u16           mps;
 
+       __u16           tx_credits;
+       __u16           rx_credits;
+
        __u8            tx_state;
        __u8            rx_state;
 
@@ -553,6 +595,7 @@ struct l2cap_ops {
        void                    (*ready) (struct l2cap_chan *chan);
        void                    (*defer) (struct l2cap_chan *chan);
        void                    (*resume) (struct l2cap_chan *chan);
+       void                    (*suspend) (struct l2cap_chan *chan);
        void                    (*set_shutdown) (struct l2cap_chan *chan);
        long                    (*get_sndtimeo) (struct l2cap_chan *chan);
        struct sk_buff          *(*alloc_skb) (struct l2cap_chan *chan,
@@ -654,6 +697,7 @@ enum {
        FLAG_EXT_CTRL,
        FLAG_EFS_ENABLE,
        FLAG_DEFER_SETUP,
+       FLAG_LE_CONN_REQ_SENT,
 };
 
 enum {
@@ -809,11 +853,13 @@ static inline long l2cap_chan_no_get_sndtimeo(struct l2cap_chan *chan)
 }
 
 extern bool disable_ertm;
+extern bool enable_lecoc;
 
 int l2cap_init_sockets(void);
 void l2cap_cleanup_sockets(void);
 bool l2cap_is_socket(struct socket *sock);
 
+void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan);
 void __l2cap_connect_rsp_defer(struct l2cap_chan *chan);
 
 int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm);
index 3eae46cb1acfecadbff979ee17e17aeab40971e7..e9abc7b536cdebb5434caae1cbd487378ad0dfe1 100644 (file)
@@ -91,9 +91,8 @@ enum ieee80211_band {
  * Channel flags set by the regulatory control code.
  *
  * @IEEE80211_CHAN_DISABLED: This channel is disabled.
- * @IEEE80211_CHAN_PASSIVE_SCAN: Only passive scanning is permitted
- *     on this channel.
- * @IEEE80211_CHAN_NO_IBSS: IBSS is not allowed on this channel.
+ * @IEEE80211_CHAN_NO_IR: do not initiate radiation, this includes
+ *     sending probe requests or beaconing.
  * @IEEE80211_CHAN_RADAR: Radar detection is required on this channel.
  * @IEEE80211_CHAN_NO_HT40PLUS: extension channel above this channel
  *     is not permitted.
@@ -113,8 +112,8 @@ enum ieee80211_band {
  */
 enum ieee80211_channel_flags {
        IEEE80211_CHAN_DISABLED         = 1<<0,
-       IEEE80211_CHAN_PASSIVE_SCAN     = 1<<1,
-       IEEE80211_CHAN_NO_IBSS          = 1<<2,
+       IEEE80211_CHAN_NO_IR            = 1<<1,
+       /* hole at 1<<2 */
        IEEE80211_CHAN_RADAR            = 1<<3,
        IEEE80211_CHAN_NO_HT40PLUS      = 1<<4,
        IEEE80211_CHAN_NO_HT40MINUS     = 1<<5,
@@ -1944,6 +1943,29 @@ struct cfg80211_update_ft_ies_params {
        size_t ie_len;
 };
 
+/**
+ * struct cfg80211_mgmt_tx_params - mgmt tx parameters
+ *
+ * This structure provides information needed to transmit a mgmt frame
+ *
+ * @chan: channel to use
+ * @offchan: indicates wether off channel operation is required
+ * @wait: duration for ROC
+ * @buf: buffer to transmit
+ * @len: buffer length
+ * @no_cck: don't use cck rates for this frame
+ * @dont_wait_for_ack: tells the low level not to wait for an ack
+ */
+struct cfg80211_mgmt_tx_params {
+       struct ieee80211_channel *chan;
+       bool offchan;
+       unsigned int wait;
+       const u8 *buf;
+       size_t len;
+       bool no_cck;
+       bool dont_wait_for_ack;
+};
+
 /**
  * struct cfg80211_ops - backend description for wireless configuration
  *
@@ -2342,9 +2364,8 @@ struct cfg80211_ops {
                                            u64 cookie);
 
        int     (*mgmt_tx)(struct wiphy *wiphy, struct wireless_dev *wdev,
-                         struct ieee80211_channel *chan, bool offchan,
-                         unsigned int wait, const u8 *buf, size_t len,
-                         bool no_cck, bool dont_wait_for_ack, u64 *cookie);
+                          struct cfg80211_mgmt_tx_params *params,
+                          u64 *cookie);
        int     (*mgmt_tx_cancel_wait)(struct wiphy *wiphy,
                                       struct wireless_dev *wdev,
                                       u64 cookie);
@@ -2438,27 +2459,6 @@ struct cfg80211_ops {
 /**
  * enum wiphy_flags - wiphy capability flags
  *
- * @WIPHY_FLAG_CUSTOM_REGULATORY:  tells us the driver for this device
- *     has its own custom regulatory domain and cannot identify the
- *     ISO / IEC 3166 alpha2 it belongs to. When this is enabled
- *     we will disregard the first regulatory hint (when the
- *     initiator is %REGDOM_SET_BY_CORE).
- * @WIPHY_FLAG_STRICT_REGULATORY: tells us the driver for this device will
- *     ignore regulatory domain settings until it gets its own regulatory
- *     domain via its regulatory_hint() unless the regulatory hint is
- *     from a country IE. After its gets its own regulatory domain it will
- *     only allow further regulatory domain settings to further enhance
- *     compliance. For example if channel 13 and 14 are disabled by this
- *     regulatory domain no user regulatory domain can enable these channels
- *     at a later time. This can be used for devices which do not have
- *     calibration information guaranteed for frequencies or settings
- *     outside of its regulatory domain. If used in combination with
- *     WIPHY_FLAG_CUSTOM_REGULATORY the inspected country IE power settings
- *     will be followed.
- * @WIPHY_FLAG_DISABLE_BEACON_HINTS: enable this if your driver needs to ensure
- *     that passive scan flags and beaconing flags may not be lifted by
- *     cfg80211 due to regulatory beacon hints. For more information on beacon
- *     hints read the documenation for regulatory_hint_found_beacon()
  * @WIPHY_FLAG_NETNS_OK: if not set, do not allow changing the netns of this
  *     wiphy at all
  * @WIPHY_FLAG_PS_ON_BY_DEFAULT: if set to true, powersave will be enabled
@@ -2497,9 +2497,9 @@ struct cfg80211_ops {
  *     beaconing mode (AP, IBSS, Mesh, ...).
  */
 enum wiphy_flags {
-       WIPHY_FLAG_CUSTOM_REGULATORY            = BIT(0),
-       WIPHY_FLAG_STRICT_REGULATORY            = BIT(1),
-       WIPHY_FLAG_DISABLE_BEACON_HINTS         = BIT(2),
+       /* use hole at 0 */
+       /* use hole at 1 */
+       /* use hole at 2 */
        WIPHY_FLAG_NETNS_OK                     = BIT(3),
        WIPHY_FLAG_PS_ON_BY_DEFAULT             = BIT(4),
        WIPHY_FLAG_4ADDR_AP                     = BIT(5),
@@ -2721,6 +2721,8 @@ struct wiphy_coalesce_support {
  * @software_iftypes: bitmask of software interface types, these are not
  *     subject to any restrictions since they are purely managed in SW.
  * @flags: wiphy flags, see &enum wiphy_flags
+ * @regulatory_flags: wiphy regulatory flags, see
+ *     &enum ieee80211_regulatory_flags
  * @features: features advertised to nl80211, see &enum nl80211_feature_flags.
  * @bss_priv_size: each BSS struct has private data allocated with it,
  *     this variable determines its size
@@ -2809,7 +2811,7 @@ struct wiphy {
 
        u16 max_acl_mac_addrs;
 
-       u32 flags, features;
+       u32 flags, regulatory_flags, features;
 
        u32 ap_sme_capa;
 
@@ -3472,6 +3474,9 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2);
  * custom regulatory domain will be trusted completely and as such previous
  * default channel settings will be disregarded. If no rule is found for a
  * channel on the regulatory domain the channel will be disabled.
+ * Drivers using this for a wiphy should also set the wiphy flag
+ * WIPHY_FLAG_CUSTOM_REGULATORY or cfg80211 will set it for the wiphy
+ * that called this helper.
  */
 void wiphy_apply_custom_regulatory(struct wiphy *wiphy,
                                   const struct ieee80211_regdomain *regd);
@@ -4146,6 +4151,7 @@ void cfg80211_radar_event(struct wiphy *wiphy,
 /**
  * cfg80211_cac_event - Channel availability check (CAC) event
  * @netdev: network device
+ * @chandef: chandef for the current channel
  * @event: type of event
  * @gfp: context flags
  *
@@ -4154,6 +4160,7 @@ void cfg80211_radar_event(struct wiphy *wiphy,
  * also by full-MAC drivers.
  */
 void cfg80211_cac_event(struct net_device *netdev,
+                       const struct cfg80211_chan_def *chandef,
                        enum nl80211_radar_event event, gfp_t gfp);
 
 
@@ -4279,7 +4286,8 @@ bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
  * @dev: the device which switched channels
  * @chandef: the new channel definition
  *
- * Acquires wdev_lock, so must only be called from sleepable driver context!
+ * Caller must acquire wdev_lock, therefore must only be called from sleepable
+ * driver context!
  */
 void cfg80211_ch_switch_notify(struct net_device *dev,
                               struct cfg80211_chan_def *chandef);
index a8c2ef6d3b932abbb42e28be158d472effd02513..a6fd939f202d39b0745e0a48ac350cbe9e795648 100644 (file)
@@ -26,8 +26,7 @@
  * 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
+ * along with this program;  if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
@@ -304,7 +303,7 @@ static inline int cipso_v4_validate(const struct sk_buff *skb,
 
        for (opt_iter = 6; opt_iter < opt_len;) {
                tag_len = opt[opt_iter + 1];
-               if ((tag_len == 0) || (opt[opt_iter + 1] > (opt_len - opt_iter))) {
+               if ((tag_len == 0) || (tag_len > (opt_len - opt_iter))) {
                        err_offset = opt_iter + 1;
                        goto out;
                }
index d2f3041c0dfaa685b2f32a633ee0931bad036329..aec07c8a660a4fa28fd9ef59f78fa3b26a5526b5 100644 (file)
@@ -11,8 +11,7 @@
  * 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.
+ * this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * Author: John Fastabend <john.r.fastabend@intel.com>
  */
index fc5d5dcebb00e88447444cf95ff525e57363a940..a975edf21b22c3678194972db693645e48dd46e6 100644 (file)
@@ -11,8 +11,7 @@
  * 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.
+ * this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * Author: Lucy Liu <lucy.liu@intel.com>
  */
index 20b5ab06032d35dc1f5f3175d9b88d59db2e2232..197886cd7bddad9a5099ce590c64569fdd619753 100644 (file)
@@ -9,7 +9,7 @@ struct dn_ifaddr {
        struct dn_dev    *ifa_dev;
        __le16            ifa_local;
        __le16            ifa_address;
-       __u             ifa_flags;
+       __u32             ifa_flags;
        __u8              ifa_scope;
        char              ifa_label[IFNAMSIZ];
        struct rcu_head   rcu;
index 65ce471d2ab577f81cc62040018aff980ea82f65..d23e7fa2042e0dd79b9d23867d5237f164ff3782 100644 (file)
@@ -20,8 +20,7 @@ struct flowi_common {
        __u8    flowic_proto;
        __u8    flowic_flags;
 #define FLOWI_FLAG_ANYSRC              0x01
-#define FLOWI_FLAG_CAN_SLEEP           0x02
-#define FLOWI_FLAG_KNOWN_NH            0x04
+#define FLOWI_FLAG_KNOWN_NH            0x02
        __u32   flowic_secid;
 };
 
index 76d54270f2e27c175836b137f363014381e91687..b58c36c1c3f6bfc820ca0988d91064b0a0a39af8 100644 (file)
@@ -50,8 +50,8 @@ struct inet6_ifaddr {
 
        int                     state;
 
+       __u32                   flags;
        __u8                    dad_probes;
-       __u8                    flags;
 
        __u16                   scope;
 
index 217bc5bfc6c6e99cf52117312ceda95c98f005a6..5a25f36fe3a7cb50a388e309df9b5905f013b6b4 100644 (file)
@@ -473,7 +473,7 @@ int compat_ip_getsockopt(struct sock *sk, int level, int optname,
 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);
+int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_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,
index 2a5f668cd6836fae6ff45e551f8dacfd93dacd8e..e600b89811aa055edf8b6bf571a30b1d7b918c09 100644 (file)
@@ -110,7 +110,8 @@ struct frag_hdr {
        __be32  identification;
 };
 
-#define        IP6_MF  0x0001
+#define        IP6_MF          0x0001
+#define        IP6_OFFSET      0xFFF8
 
 #include <net/sock.h>
 
@@ -237,6 +238,7 @@ struct ip6_flowlabel {
 
 #define IPV6_FLOWINFO_MASK     cpu_to_be32(0x0FFFFFFF)
 #define IPV6_FLOWLABEL_MASK    cpu_to_be32(0x000FFFFF)
+#define IPV6_TCLASS_MASK (IPV6_FLOWINFO_MASK & ~IPV6_FLOWLABEL_MASK)
 
 struct ipv6_fl_socklist {
        struct ipv6_fl_socklist __rcu   *next;
@@ -677,6 +679,11 @@ static inline __be32 ip6_flowinfo(const struct ipv6hdr *hdr)
        return *(__be32 *)hdr & IPV6_FLOWINFO_MASK;
 }
 
+static inline __be32 ip6_flowlabel(const struct ipv6hdr *hdr)
+{
+       return *(__be32 *)hdr & IPV6_FLOWLABEL_MASK;
+}
+
 /*
  *     Prototypes exported by ipv6
  */
@@ -711,11 +718,9 @@ 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);
+                                     const struct in6_addr *final_dst);
 struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6,
-                                        const struct in6_addr *final_dst,
-                                        bool can_sleep);
+                                        const struct in6_addr *final_dst);
 struct dst_entry *ip6_blackhole_route(struct net *net,
                                      struct dst_entry *orig_dst);
 
@@ -776,8 +781,10 @@ int compat_ipv6_getsockopt(struct sock *sk, int level, int optname,
 
 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);
+int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len,
+                   int *addr_len);
+int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len,
+                    int *addr_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);
index 0ce93398720d1763fd4f740ded67d47b799e6bc3..63ae325305671495f565aadcf91b9ced74f0a531 100644 (file)
@@ -23,9 +23,7 @@
  *     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
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  *     
  ********************************************************************/
 
index 69b610acd2df9f1aefd9edd81c9cb07b8e4cca56..2a580ce9edad884fe112277e9936d5e9e8b1a482 100644 (file)
@@ -22,9 +22,7 @@
  *     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
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  *     
  ********************************************************************/
 
index bc0c6f31f1c6204d41f983c1ce3434d7f8d77258..5bbc32998d577e43990d72c56b2ac727d7e765a0 100644 (file)
@@ -22,9 +22,7 @@
  *     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
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  *     
  ********************************************************************/
 
index ae02106be59000d54c5089a313ace02a2e393bf7..5042a5021a0428c72a32c10f2120e0138e4930cd 100644 (file)
@@ -22,9 +22,7 @@
  *     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
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  *     
  ********************************************************************/
 
index e6678800c41ff27a09b59863581ba84d7c63c1cf..1f67432321c49a38394adf81e5fdc58c014b2672 100644 (file)
@@ -22,9 +22,7 @@
  *     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
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  *     
  ********************************************************************/
 
index 403081ed725ca0cffc2453cf66a19185398a5287..c5627288bca30002666df5b63cb5a73187948257 100644 (file)
@@ -22,9 +22,7 @@
  *     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
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  *     
  ********************************************************************/
 
index 0224402260a77a3653a276e0c33f2e9281601f80..8d4f588974bce7943659779b22386230a780892a 100644 (file)
@@ -22,9 +22,7 @@
  *     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
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  *     
  ********************************************************************/
 
index 0a63bbb972d7152c1daa9c9d0d058e58954cf0ad..20dcbdf258cf22c6c2e58e5bc7809be4cfdca186 100644 (file)
@@ -22,9 +22,7 @@
  *     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
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  *     
  ********************************************************************/
 
index 11417475a6c31059aa28d5db55ce90c2a536a703..664bf8178412e11c62a637ebc812d33f0861bcce 100644 (file)
@@ -24,9 +24,7 @@
  *     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
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  *     
  ********************************************************************/
 
index f9d88da97af2c15844caf5b9ba875cffb8a5f8c3..e4325fee1267621526959b40a53a6b66acd87ffd 100644 (file)
@@ -25,9 +25,7 @@
  *     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
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  *     
  ********************************************************************/
 
index 57173ae398aed4096dd8b2cc7374bd4645edc3e7..cbc12a926e5f7c554a38c9e51d06834d9b35923a 100644 (file)
@@ -24,9 +24,7 @@
  *     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
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  *     
  ********************************************************************/
 
index c0d938847bd3ba8fbd2e3d0b163074e25977a64b..42713c931d1fee497f000b242204c7b14416ae1d 100644 (file)
@@ -22,9 +22,7 @@
  *     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
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  *     Michel Dänzer <daenzer@debian.org>, 10/2001
  *     - simplify irda_pv_t to avoid endianness issues
index cc577dc0a0efb08d689c13e9685cc30a33cece43..05a5a249956f8b18bee66e0b2bf22202a125d36b 100644 (file)
@@ -22,9 +22,7 @@
  *     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
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  *     
  ********************************************************************/
 
index 7ceed99a05bc79218a841352a454a980df48741b..3cd408b326de7400b00e6284be2524955beefe27 100644 (file)
@@ -154,12 +154,14 @@ struct ieee80211_low_level_stats {
  * @IEEE80211_CHANCTX_CHANGE_RADAR: radar detection flag changed
  * @IEEE80211_CHANCTX_CHANGE_CHANNEL: switched to another operating channel,
  *     this is used only with channel switching with CSA
+ * @IEEE80211_CHANCTX_CHANGE_MIN_WIDTH: The min required channel width changed
  */
 enum ieee80211_chanctx_change {
        IEEE80211_CHANCTX_CHANGE_WIDTH          = BIT(0),
        IEEE80211_CHANCTX_CHANGE_RX_CHAINS      = BIT(1),
        IEEE80211_CHANCTX_CHANGE_RADAR          = BIT(2),
        IEEE80211_CHANCTX_CHANGE_CHANNEL        = BIT(3),
+       IEEE80211_CHANCTX_CHANGE_MIN_WIDTH      = BIT(4),
 };
 
 /**
@@ -169,6 +171,7 @@ enum ieee80211_chanctx_change {
  * that contains it is visible in mac80211 only.
  *
  * @def: the channel definition
+ * @min_def: the minimum channel definition currently required.
  * @rx_chains_static: The number of RX chains that must always be
  *     active on the channel to receive MIMO transmissions
  * @rx_chains_dynamic: The number of RX chains that must be enabled
@@ -180,6 +183,7 @@ enum ieee80211_chanctx_change {
  */
 struct ieee80211_chanctx_conf {
        struct cfg80211_chan_def def;
+       struct cfg80211_chan_def min_def;
 
        u8 rx_chains_static, rx_chains_dynamic;
 
@@ -1228,6 +1232,36 @@ struct ieee80211_key_conf {
        u8 key[0];
 };
 
+/**
+ * struct ieee80211_cipher_scheme - cipher scheme
+ *
+ * This structure contains a cipher scheme information defining
+ * the secure packet crypto handling.
+ *
+ * @cipher: a cipher suite selector
+ * @iftype: a cipher iftype bit mask indicating an allowed cipher usage
+ * @hdr_len: a length of a security header used the cipher
+ * @pn_len: a length of a packet number in the security header
+ * @pn_off: an offset of pn from the beginning of the security header
+ * @key_idx_off: an offset of key index byte in the security header
+ * @key_idx_mask: a bit mask of key_idx bits
+ * @key_idx_shift: a bit shift needed to get key_idx
+ *     key_idx value calculation:
+ *      (sec_header_base[key_idx_off] & key_idx_mask) >> key_idx_shift
+ * @mic_len: a mic length in bytes
+ */
+struct ieee80211_cipher_scheme {
+       u32 cipher;
+       u16 iftype;
+       u8 hdr_len;
+       u8 pn_len;
+       u8 pn_off;
+       u8 key_idx_off;
+       u8 key_idx_mask;
+       u8 key_idx_shift;
+       u8 mic_len;
+};
+
 /**
  * enum set_key_cmd - key command
  *
@@ -1636,6 +1670,10 @@ enum ieee80211_hw_flags {
  * @uapsd_max_sp_len: maximum number of total buffered frames the WMM AP may
  *     deliver to a WMM STA during any Service Period triggered by the WMM STA.
  *     Use IEEE80211_WMM_IE_STA_QOSINFO_SP_* for correct values.
+ *
+ * @n_cipher_schemes: a size of an array of cipher schemes definitions.
+ * @cipher_schemes: a pointer to an array of cipher scheme definitions
+ *     supported by HW.
  */
 struct ieee80211_hw {
        struct ieee80211_conf conf;
@@ -1663,6 +1701,8 @@ struct ieee80211_hw {
        netdev_features_t netdev_features;
        u8 uapsd_queues;
        u8 uapsd_max_sp_len;
+       u8 n_cipher_schemes;
+       const struct ieee80211_cipher_scheme *cipher_schemes;
 };
 
 /**
index 26ba99b5a4b139cadb746c95294be3f6789f4c1b..0386b618908c8b789319ed579ba265e2a1ab5ae6 100644 (file)
@@ -13,8 +13,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 /*
  * Authors:
index 536501a3e58d861211656b87ec2e0e9b0e4f9a47..4c09bd23b8329bd2abad4c6e317d54ebba92d8bb 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/skbuff.h>
 #include <linux/rcupdate.h>
 #include <linux/seq_file.h>
+#include <linux/bitmap.h>
 
 #include <linux/err.h>
 #include <linux/sysctl.h>
 
 struct neighbour;
 
+enum {
+       NEIGH_VAR_MCAST_PROBES,
+       NEIGH_VAR_UCAST_PROBES,
+       NEIGH_VAR_APP_PROBES,
+       NEIGH_VAR_RETRANS_TIME,
+       NEIGH_VAR_BASE_REACHABLE_TIME,
+       NEIGH_VAR_DELAY_PROBE_TIME,
+       NEIGH_VAR_GC_STALETIME,
+       NEIGH_VAR_QUEUE_LEN_BYTES,
+       NEIGH_VAR_PROXY_QLEN,
+       NEIGH_VAR_ANYCAST_DELAY,
+       NEIGH_VAR_PROXY_DELAY,
+       NEIGH_VAR_LOCKTIME,
+#define NEIGH_VAR_DATA_MAX (NEIGH_VAR_LOCKTIME + 1)
+       /* Following are used as a second way to access one of the above */
+       NEIGH_VAR_QUEUE_LEN, /* same data as NEIGH_VAR_QUEUE_LEN_BYTES */
+       NEIGH_VAR_RETRANS_TIME_MS, /* same data as NEIGH_VAR_RETRANS_TIME */
+       NEIGH_VAR_BASE_REACHABLE_TIME_MS, /* same data as NEIGH_VAR_BASE_REACHABLE_TIME */
+       /* Following are used by "default" only */
+       NEIGH_VAR_GC_INTERVAL,
+       NEIGH_VAR_GC_THRESH1,
+       NEIGH_VAR_GC_THRESH2,
+       NEIGH_VAR_GC_THRESH3,
+       NEIGH_VAR_MAX
+};
+
 struct neigh_parms {
 #ifdef CONFIG_NET_NS
        struct net *net;
@@ -53,22 +80,30 @@ struct neigh_parms {
        atomic_t refcnt;
        struct rcu_head rcu_head;
 
-       int     base_reachable_time;
-       int     retrans_time;
-       int     gc_staletime;
        int     reachable_time;
-       int     delay_probe_time;
-
-       int     queue_len_bytes;
-       int     ucast_probes;
-       int     app_probes;
-       int     mcast_probes;
-       int     anycast_delay;
-       int     proxy_delay;
-       int     proxy_qlen;
-       int     locktime;
+       int     data[NEIGH_VAR_DATA_MAX];
+       DECLARE_BITMAP(data_state, NEIGH_VAR_DATA_MAX);
 };
 
+static inline void neigh_var_set(struct neigh_parms *p, int index, int val)
+{
+       set_bit(index, p->data_state);
+       p->data[index] = val;
+}
+
+#define NEIGH_VAR(p, attr) ((p)->data[NEIGH_VAR_ ## attr])
+#define NEIGH_VAR_SET(p, attr, val) neigh_var_set(p, NEIGH_VAR_ ## attr, val)
+
+static inline void neigh_parms_data_state_setall(struct neigh_parms *p)
+{
+       bitmap_fill(p->data_state, NEIGH_VAR_DATA_MAX);
+}
+
+static inline void neigh_parms_data_state_cleanall(struct neigh_parms *p)
+{
+       bitmap_zero(p->data_state, NEIGH_VAR_DATA_MAX);
+}
+
 struct neigh_statistics {
        unsigned long allocs;           /* number of allocated neighs */
        unsigned long destroys;         /* number of destroyed neighs */
@@ -180,6 +215,11 @@ struct neigh_table {
        struct pneigh_entry     **phash_buckets;
 };
 
+static inline int neigh_parms_family(struct neigh_parms *p)
+{
+       return p->tbl->family;
+}
+
 #define NEIGH_PRIV_ALIGN       sizeof(long long)
 #define NEIGH_ENTRY_SIZE(size) ALIGN((size), NEIGH_PRIV_ALIGN)
 
@@ -212,6 +252,7 @@ static inline struct neighbour *neigh_create(struct neigh_table *tbl,
 void neigh_destroy(struct neighbour *neigh);
 int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb);
 int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, u32 flags);
+void __neigh_set_probe_once(struct neighbour *neigh);
 void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev);
 int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev);
 int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb);
@@ -274,8 +315,17 @@ void *neigh_seq_start(struct seq_file *, loff_t *, struct neigh_table *,
 void *neigh_seq_next(struct seq_file *, void *, loff_t *);
 void neigh_seq_stop(struct seq_file *, void *);
 
+int neigh_proc_dointvec(struct ctl_table *ctl, int write,
+                       void __user *buffer, size_t *lenp, loff_t *ppos);
+int neigh_proc_dointvec_jiffies(struct ctl_table *ctl, int write,
+                               void __user *buffer,
+                               size_t *lenp, loff_t *ppos);
+int neigh_proc_dointvec_ms_jiffies(struct ctl_table *ctl, int write,
+                                  void __user *buffer,
+                                  size_t *lenp, loff_t *ppos);
+
 int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
-                         char *p_name, proc_handler *proc_handler);
+                         proc_handler *proc_handler);
 void neigh_sysctl_unregister(struct neigh_parms *p);
 
 static inline void __neigh_parms_put(struct neigh_parms *parms)
index 2c95d55f79149173d3a1f5f27bb1213dd24a323b..24948bedb64cf8cc055976e31646a204ec090683 100644 (file)
@@ -22,8 +22,7 @@
  * 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
+ * along with this program;  if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 5299e69a32afd91a6bd577ee2f7427d8c37bdf3b..1006a265beb393a0ab917eb8315f0fb258c39e0a 100644 (file)
@@ -33,8 +33,6 @@ struct netns_xfrm {
        struct hlist_head       state_gc_list;
        struct work_struct      state_gc_work;
 
-       wait_queue_head_t       km_waitq;
-
        struct list_head        policy_all;
        struct hlist_head       *policy_byidx;
        unsigned int            policy_idx_hmask;
@@ -59,6 +57,10 @@ struct netns_xfrm {
 #if IS_ENABLED(CONFIG_IPV6)
        struct dst_ops          xfrm6_dst_ops;
 #endif
+       spinlock_t xfrm_state_lock;
+       spinlock_t xfrm_policy_sk_bundle_lock;
+       rwlock_t xfrm_policy_lock;
+       struct mutex xfrm_cfg_mutex;
 };
 
 #endif
index 2eca2960ca9c54116bd187b6e1e18b70060f0282..03c4650b548ca7b01c24ba0f95317139949c7cdb 100644 (file)
@@ -12,9 +12,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef __NET_HCI_H
index 400ab7ae749db0f673791108c1134135bdf8bff1..c25fbdee0d61068f69416bbec68ecc54e2d366c2 100644 (file)
@@ -13,9 +13,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef __NFC_LLC_H_
index e5aa5acafea0e0e176e83ce50d58d33529be4669..fbfa4e471abb7f62cf31508da0f5ac3e2686fec9 100644 (file)
@@ -20,8 +20,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 6126f1f992b40068923771cf0a7967395f88017e..0ff070e8f8de656d09f94919da587f3be1ffb938 100644 (file)
@@ -21,8 +21,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 82fc4e43fc6e9ec156e19e18dddc4d3ec1fbe037..e80894bca1d042201c01c854df897ccc2607b72e 100644 (file)
@@ -16,9 +16,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef __NET_NFC_H
index 3f67704f3747281b3ad0852fd5d69dcd49c9b01c..90f48417b03dac91259aefe18d79c63145a23849 100644 (file)
@@ -31,7 +31,8 @@
 
 /* Compatibility glue so we can support IPv6 when it's compiled as a module */
 struct pingv6_ops {
-       int (*ipv6_recv_error)(struct sock *sk, struct msghdr *msg, int len);
+       int (*ipv6_recv_error)(struct sock *sk, struct msghdr *msg, int len,
+                              int *addr_len);
        int (*ip6_datagram_recv_ctl)(struct sock *sk, struct msghdr *msg,
                                     struct sk_buff *skb);
        int (*icmpv6_err_convert)(u8 type, u8 code, int *err);
index 59ec3cd15d681c04230b3cccd386c045140c0645..891d80d2c4d2a98cfdad75deee1c28bdce9c9f9f 100644 (file)
@@ -88,6 +88,7 @@ int unregister_qdisc(struct Qdisc_ops *qops);
 void qdisc_get_default(char *id, size_t len);
 int qdisc_set_default(const char *id);
 
+void qdisc_list_add(struct Qdisc *q);
 void qdisc_list_del(struct Qdisc *q);
 struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle);
 struct Qdisc *qdisc_lookup_class(struct net_device *dev, u32 handle);
index f17ed590d64a35b314c8c9c42dc7dc153e0f1619..c96a0b86f342cc1093dee253f070f9ff225b0ba6 100644 (file)
@@ -38,17 +38,17 @@ enum environment_cap {
  *
  * @rcu_head: RCU head struct used to free the request
  * @wiphy_idx: this is set if this request's initiator is
- *     %REGDOM_SET_BY_COUNTRY_IE or %REGDOM_SET_BY_DRIVER. This
- *     can be used by the wireless core to deal with conflicts
- *     and potentially inform users of which devices specifically
- *     cased the conflicts.
+ *     %REGDOM_SET_BY_COUNTRY_IE or %REGDOM_SET_BY_DRIVER. This
+ *     can be used by the wireless core to deal with conflicts
+ *     and potentially inform users of which devices specifically
+ *     cased the conflicts.
  * @initiator: indicates who sent this request, could be any of
- *     of those set in nl80211_reg_initiator (%NL80211_REGDOM_SET_BY_*)
+ *     of those set in nl80211_reg_initiator (%NL80211_REGDOM_SET_BY_*)
  * @alpha2: the ISO / IEC 3166 alpha2 country code of the requested
- *     regulatory domain. We have a few special codes:
- *     00 - World regulatory domain
- *     99 - built by driver but a specific alpha2 cannot be determined
- *     98 - result of an intersection between two regulatory domains
+ *     regulatory domain. We have a few special codes:
+ *     00 - World regulatory domain
+ *     99 - built by driver but a specific alpha2 cannot be determined
+ *     98 - result of an intersection between two regulatory domains
  *     97 - regulatory domain has not yet been configured
  * @dfs_region: If CRDA responded with a regulatory domain that requires
  *     DFS master operation on a known DFS region (NL80211_DFS_*),
@@ -59,8 +59,8 @@ enum environment_cap {
  *     of hint passed. This could be any of the %NL80211_USER_REG_HINT_*
  *     types.
  * @intersect: indicates whether the wireless core should intersect
- *     the requested regulatory domain with the presently set regulatory
- *     domain.
+ *     the requested regulatory domain with the presently set regulatory
+ *     domain.
  * @processed: indicates whether or not this requests has already been
  *     processed. When the last request is processed it means that the
  *     currently regulatory domain set on cfg80211 is updated from
@@ -68,9 +68,9 @@ enum environment_cap {
  *     the last request is not yet processed we must yield until it
  *     is processed before processing any new requests.
  * @country_ie_checksum: checksum of the last processed and accepted
- *     country IE
+ *     country IE
  * @country_ie_env: lets us know if the AP is telling us we are outdoor,
- *     indoor, or if it doesn't matter
+ *     indoor, or if it doesn't matter
  * @list: used to insert into the reg_requests_list linked list
  */
 struct regulatory_request {
@@ -79,13 +79,63 @@ struct regulatory_request {
        enum nl80211_reg_initiator initiator;
        enum nl80211_user_reg_hint_type user_reg_hint_type;
        char alpha2[2];
-       u8 dfs_region;
+       enum nl80211_dfs_regions dfs_region;
        bool intersect;
        bool processed;
        enum environment_cap country_ie_env;
        struct list_head list;
 };
 
+/**
+ * enum ieee80211_regulatory_flags - device regulatory flags
+ *
+ * @REGULATORY_CUSTOM_REG: tells us the driver for this device
+ *     has its own custom regulatory domain and cannot identify the
+ *     ISO / IEC 3166 alpha2 it belongs to. When this is enabled
+ *     we will disregard the first regulatory hint (when the
+ *     initiator is %REGDOM_SET_BY_CORE). Drivers that use
+ *     wiphy_apply_custom_regulatory() should have this flag set
+ *     or the regulatory core will set it for the wiphy.
+ * @REGULATORY_STRICT_REG: tells us that the wiphy for this device
+ *     has regulatory domain that it wishes to be considered as the
+ *     superset for regulatory rules. After this device gets its regulatory
+ *     domain programmed further regulatory hints shall only be considered
+ *     for this device to enhance regulatory compliance, forcing the
+ *     device to only possibly use subsets of the original regulatory
+ *     rules. For example if channel 13 and 14 are disabled by this
+ *     device's regulatory domain no user specified regulatory hint which
+ *     has these channels enabled would enable them for this wiphy,
+ *     the device's original regulatory domain will be trusted as the
+ *     base. You can program the superset of regulatory rules for this
+ *     wiphy with regulatory_hint() for cards programmed with an
+ *     ISO3166-alpha2 country code. wiphys that use regulatory_hint()
+ *     will have their wiphy->regd programmed once the regulatory
+ *     domain is set, and all other regulatory hints will be ignored
+ *     until their own regulatory domain gets programmed.
+ * @REGULATORY_DISABLE_BEACON_HINTS: enable this if your driver needs to
+ *     ensure that passive scan flags and beaconing flags may not be lifted by
+ *     cfg80211 due to regulatory beacon hints. For more information on beacon
+ *     hints read the documenation for regulatory_hint_found_beacon()
+ * @REGULATORY_COUNTRY_IE_FOLLOW_POWER:  for devices that have a preference
+ *     that even though they may have programmed their own custom power
+ *     setting prior to wiphy registration, they want to ensure their channel
+ *     power settings are updated for this connection with the power settings
+ *     derived from the regulatory domain. The regulatory domain used will be
+ *     based on the ISO3166-alpha2 from country IE provided through
+ *     regulatory_hint_country_ie()
+ * @REGULATORY_COUNTRY_IE_IGNORE: for devices that have a preference to ignore
+ *     all country IE information processed by the regulatory core. This will
+ *     override %REGULATORY_COUNTRY_IE_FOLLOW_POWER as all country IEs will
+ *     be ignored.
+ */
+enum ieee80211_regulatory_flags {
+       REGULATORY_CUSTOM_REG                   = BIT(0),
+       REGULATORY_STRICT_REG                   = BIT(1),
+       REGULATORY_DISABLE_BEACON_HINTS         = BIT(2),
+       REGULATORY_COUNTRY_IE_FOLLOW_POWER      = BIT(3),
+       REGULATORY_COUNTRY_IE_IGNORE            = BIT(4),
+};
+
 struct ieee80211_freq_range {
        u32 start_freq_khz;
        u32 end_freq_khz;
@@ -107,7 +157,7 @@ struct ieee80211_regdomain {
        struct rcu_head rcu_head;
        u32 n_reg_rules;
        char alpha2[2];
-       u8 dfs_region;
+       enum nl80211_dfs_regions dfs_region;
        struct ieee80211_reg_rule reg_rules[];
 };
 
index f68c167280a7f6138036f626cb8f82e68faf4f36..638e3ebf76f33443ac3c218912c7b7646a4f7846 100644 (file)
@@ -239,14 +239,12 @@ static inline char rt_tos2priority(u8 tos)
 static inline void ip_route_connect_init(struct flowi4 *fl4, __be32 dst, __be32 src,
                                         u32 tos, int oif, u8 protocol,
                                         __be16 sport, __be16 dport,
-                                        struct sock *sk, bool can_sleep)
+                                        struct sock *sk)
 {
        __u8 flow_flags = 0;
 
        if (inet_sk(sk)->transparent)
                flow_flags |= FLOWI_FLAG_ANYSRC;
-       if (can_sleep)
-               flow_flags |= FLOWI_FLAG_CAN_SLEEP;
 
        flowi4_init_output(fl4, oif, sk->sk_mark, tos, RT_SCOPE_UNIVERSE,
                           protocol, flow_flags, dst, src, dport, sport);
@@ -256,13 +254,13 @@ static inline struct rtable *ip_route_connect(struct flowi4 *fl4,
                                              __be32 dst, __be32 src, u32 tos,
                                              int oif, u8 protocol,
                                              __be16 sport, __be16 dport,
-                                             struct sock *sk, bool can_sleep)
+                                             struct sock *sk)
 {
        struct net *net = sock_net(sk);
        struct rtable *rt;
 
        ip_route_connect_init(fl4, dst, src, tos, oif, protocol,
-                             sport, dport, sk, can_sleep);
+                             sport, dport, sk);
 
        if (!dst || !src) {
                rt = __ip_route_output_key(net, fl4);
index aa80bef3c9d5392b8cf472013c4f1da8f7de87f4..f2d58aa37a6fef8438d0ea0ea1ebce870a2a31bb 100644 (file)
@@ -16,9 +16,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
index 6bd44fe94c26382e1130b9b989d1ed6efb68b349..4a5b9a306c69b4139c8811138204410bb791e79b 100644 (file)
@@ -19,9 +19,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
index 832f2191489c946bebd68ce8b6cdfa92c0086979..4b7cd695e43187c39eeae537bdc031d44ba63abc 100644 (file)
@@ -19,9 +19,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
index 2f0a565a0fd57ee6914b60512d531fb057729d83..307728f622efa6b2b3cbb58b99d77f62c9941437 100644 (file)
@@ -19,9 +19,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
index c5fe80697f8d442d9c52cb4aabc9b4edfff85223..610a8c8738fa63d48b7200272b289585e61a1405 100644 (file)
@@ -21,9 +21,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
index 4ef75af340b633c7e8a5fabeb34dd88cdbd73ef2..7f4eeb340a54af17cd1e4a97631f3b86ede9214d 100644 (file)
@@ -21,9 +21,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email addresses:
index 2174d8da0770a5285d3d937a1174eb9e52dd2a27..88480b818830c4d3b2abbee23178fd6f48750e59 100644 (file)
@@ -19,9 +19,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email addresses:
@@ -629,6 +628,7 @@ struct sctp_chunk {
 #define SCTP_NEED_FRTX 0x1
 #define SCTP_DONT_FRTX 0x2
        __u16   rtt_in_progress:1,      /* This chunk used for RTT calc? */
+               resent:1,               /* Has this chunk ever been resent. */
                has_tsn:1,              /* Does this chunk have a TSN yet? */
                has_ssn:1,              /* Does this chunk have a SSN yet? */
                singleton:1,            /* Only chunk in the packet? */
@@ -1725,12 +1725,6 @@ struct sctp_association {
        /* How many duplicated TSNs have we seen?  */
        int numduptsns;
 
-       /* Number of seconds of idle time before an association is closed.
-        * In the association context, this is really used as a boolean
-        * since the real timeout is stored in the timeouts array
-        */
-       __u32 autoclose;
-
        /* These are to support
         * "SCTP Extensions for Dynamic Reconfiguration of IP Addresses
         *  and Enforcement of Flow and Message Limits"
index 54bbbe547303cc8d37c88d736e9e95894e054a69..31b8dbaad45a62f438f89069f0d22ec4fef19deb 100644 (file)
@@ -22,9 +22,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
index 27b9f5c90153610e75d9a7023b808e5b61174c33..daacb32b55b576359443cb57d184a8c6639d4956 100644 (file)
@@ -25,9 +25,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
index b0cf5d54d717a553a9135044237c2db563253b23..e0dce07b87947ca11a1af9b2c8fec10036746633 100644 (file)
@@ -24,9 +24,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email addresses:
index e3a18ff0c38b58aec20413489bf7237c54a14a77..2ef3c3eca47aacaa28ee25aecd236897d276845a 100644 (file)
@@ -1035,7 +1035,6 @@ enum cg_proto_flags {
 };
 
 struct cg_proto {
-       void                    (*enter_memory_pressure)(struct sock *sk);
        struct res_counter      memory_allocated;       /* Current allocated memory. */
        struct percpu_counter   sockets_allocated;      /* Current number of sockets. */
        int                     memory_pressure;
@@ -1155,8 +1154,7 @@ static inline void sk_leave_memory_pressure(struct sock *sk)
                struct proto *prot = sk->sk_prot;
 
                for (; cg_proto; cg_proto = parent_cg_proto(prot, cg_proto))
-                       if (cg_proto->memory_pressure)
-                               cg_proto->memory_pressure = 0;
+                       cg_proto->memory_pressure = 0;
        }
 
 }
@@ -1171,7 +1169,7 @@ static inline void sk_enter_memory_pressure(struct sock *sk)
                struct proto *prot = sk->sk_prot;
 
                for (; cg_proto; cg_proto = parent_cg_proto(prot, cg_proto))
-                       cg_proto->enter_memory_pressure(sk);
+                       cg_proto->memory_pressure = 1;
        }
 
        sk->sk_prot->enter_memory_pressure(sk);
index e103fe02f37571aa0436878897f1fd98a872aa09..dd5d86fab030c8fb8d16d6acad7eefebcab375b9 100644 (file)
@@ -11,8 +11,7 @@
  * 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.
+ * this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * Author: Alexander Duyck <alexander.h.duyck@intel.com>
  */
index 70e55d200610ec6596f7c90715bff4749b462f6e..f7e1ab2139efe7f6208836c1797a2db6fb603749 100644 (file)
@@ -282,6 +282,7 @@ extern int sysctl_tcp_limit_output_bytes;
 extern int sysctl_tcp_challenge_ack_limit;
 extern unsigned int sysctl_tcp_notsent_lowat;
 extern int sysctl_tcp_min_tso_segs;
+extern int sysctl_tcp_autocorking;
 
 extern atomic_long_t tcp_memory_allocated;
 extern struct percpu_counter tcp_sockets_allocated;
index 6b82fdf4ba716898ea53fb0cf2e66690a66d1479..59f5d0a6c7f8529bcc2fcee079fce9234e5a9be0 100644 (file)
@@ -53,7 +53,6 @@
 #define XFRM_INC_STATS_USER(net, field)        ((void)(net))
 #endif
 
-extern struct mutex xfrm_cfg_mutex;
 
 /* Organization of SPD aka "XFRM rules"
    ------------------------------------
@@ -1409,7 +1408,7 @@ static inline void xfrm_sysctl_fini(struct net *net)
 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);
+void xfrm_state_walk_done(struct xfrm_state_walk *walk, struct net *net);
 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,
@@ -1436,12 +1435,12 @@ struct xfrm_state *xfrm_state_lookup_byaddr(struct net *net, u32 mark,
                                            unsigned short family);
 #ifdef CONFIG_XFRM_SUB_POLICY
 int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n,
-                  unsigned short family);
+                  unsigned short family, struct net *net);
 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)
+                                int n, unsigned short family, struct net *net)
 {
        return -ENOSYS;
 }
@@ -1553,7 +1552,7 @@ 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);
+void xfrm_policy_walk_done(struct xfrm_policy_walk *walk, struct net *net);
 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,
@@ -1576,12 +1575,12 @@ int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
 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_migrate_state_find(struct xfrm_migrate *m, struct net *net);
 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);
+                struct xfrm_kmaddress *k, struct net *net);
 #endif
 
 int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport);
index 546084964d554fc8e463e9244558fce4e4eb8563..fe3b58e836c881b7598d37c46d56cbd6d1b81b6e 100644 (file)
@@ -475,6 +475,9 @@ struct scsi_host_template {
         */
        unsigned ordered_tag:1;
 
+       /* True if the controller does not support WRITE SAME */
+       unsigned no_write_same:1;
+
        /*
         * Countdown for host blocking with no commands outstanding.
         */
@@ -677,6 +680,9 @@ struct Scsi_Host {
        /* Don't resume host in EH */
        unsigned eh_noresume:1;
 
+       /* The controller does not support WRITE SAME */
+       unsigned no_write_same:1;
+
        /*
         * Optional work queue to be utilized by the transport
         */
index 7c2be4a51894484e8a05fe08d11751c1cc7e04ab..bbabf84bdb443114fcd33d4b3a4bbc3172385a8b 100644 (file)
@@ -16,17 +16,11 @@ struct cs42l52_platform_data {
        /* MICBIAS Level. Check datasheet Pg48 */
        unsigned int micbias_lvl;
 
-       /* MICA mode selection 0=Single 1=Differential */
-       unsigned int mica_cfg;
+       /* MICA mode selection Differential or Single-ended */
+       bool mica_diff_cfg;
 
-       /* MICB mode selection 0=Single 1=Differential */
-       unsigned int micb_cfg;
-
-       /* MICA Select 0=MIC1A 1=MIC2A */
-       unsigned int mica_sel;
-
-       /* MICB Select 0=MIC2A 1=MIC2B */
-       unsigned int micb_sel;
+       /* MICB mode selection Differential or Single-ended */
+       bool micb_diff_cfg;
 
        /* Charge Pump Freq. Check datasheet Pg73 */
        unsigned int chgfreq;
index 15017311f2e9f0c9c2dba9bf41c00f01763cee0f..eb73a3a39ec2fbb9a3b4aef39ff65e21af9d51b4 100644 (file)
@@ -114,6 +114,10 @@ void snd_dmaengine_pcm_set_config_from_dai_data(
  * @compat_filter_fn: Will be used as the filter function when requesting a
  *  channel for platforms which do not use devicetree. The filter parameter
  *  will be the DAI's DMA data.
+ * @dma_dev: If set, request DMA channel on this device rather than the DAI
+ *  device.
+ * @chan_names: If set, these custom DMA channel names will be requested at
+ *  registration time.
  * @pcm_hardware: snd_pcm_hardware struct to be used for the PCM.
  * @prealloc_buffer_size: Size of the preallocated audio buffer.
  *
@@ -130,6 +134,8 @@ struct snd_dmaengine_pcm_config {
                        struct snd_soc_pcm_runtime *rtd,
                        struct snd_pcm_substream *substream);
        dma_filter_fn compat_filter_fn;
+       struct device *dma_dev;
+       const char *chan_names[SNDRV_PCM_STREAM_LAST + 1];
 
        const struct snd_pcm_hardware *pcm_hardware;
        unsigned int prealloc_buffer_size;
@@ -140,6 +146,10 @@ int snd_dmaengine_pcm_register(struct device *dev,
        unsigned int flags);
 void snd_dmaengine_pcm_unregister(struct device *dev);
 
+int devm_snd_dmaengine_pcm_register(struct device *dev,
+       const struct snd_dmaengine_pcm_config *config,
+       unsigned int flags);
+
 int snd_dmaengine_pcm_prepare_slave_config(struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *params,
        struct dma_slave_config *slave_config);
diff --git a/include/sound/hda_verbs.h b/include/sound/hda_verbs.h
new file mode 100644 (file)
index 0000000..d0509db
--- /dev/null
@@ -0,0 +1,554 @@
+/*
+ * HD-audio codec verbs
+ */
+
+#ifndef __SOUND_HDA_VERBS_H
+#define __SOUND_HDA_VERBS_H
+
+/*
+ * nodes
+ */
+#define        AC_NODE_ROOT            0x00
+
+/*
+ * function group types
+ */
+enum {
+       AC_GRP_AUDIO_FUNCTION = 0x01,
+       AC_GRP_MODEM_FUNCTION = 0x02,
+};
+
+/*
+ * widget types
+ */
+enum {
+       AC_WID_AUD_OUT,         /* Audio Out */
+       AC_WID_AUD_IN,          /* Audio In */
+       AC_WID_AUD_MIX,         /* Audio Mixer */
+       AC_WID_AUD_SEL,         /* Audio Selector */
+       AC_WID_PIN,             /* Pin Complex */
+       AC_WID_POWER,           /* Power */
+       AC_WID_VOL_KNB,         /* Volume Knob */
+       AC_WID_BEEP,            /* Beep Generator */
+       AC_WID_VENDOR = 0x0f    /* Vendor specific */
+};
+
+/*
+ * GET verbs
+ */
+#define AC_VERB_GET_STREAM_FORMAT              0x0a00
+#define AC_VERB_GET_AMP_GAIN_MUTE              0x0b00
+#define AC_VERB_GET_PROC_COEF                  0x0c00
+#define AC_VERB_GET_COEF_INDEX                 0x0d00
+#define AC_VERB_PARAMETERS                     0x0f00
+#define AC_VERB_GET_CONNECT_SEL                        0x0f01
+#define AC_VERB_GET_CONNECT_LIST               0x0f02
+#define AC_VERB_GET_PROC_STATE                 0x0f03
+#define AC_VERB_GET_SDI_SELECT                 0x0f04
+#define AC_VERB_GET_POWER_STATE                        0x0f05
+#define AC_VERB_GET_CONV                       0x0f06
+#define AC_VERB_GET_PIN_WIDGET_CONTROL         0x0f07
+#define AC_VERB_GET_UNSOLICITED_RESPONSE       0x0f08
+#define AC_VERB_GET_PIN_SENSE                  0x0f09
+#define AC_VERB_GET_BEEP_CONTROL               0x0f0a
+#define AC_VERB_GET_EAPD_BTLENABLE             0x0f0c
+#define AC_VERB_GET_DIGI_CONVERT_1             0x0f0d
+#define AC_VERB_GET_DIGI_CONVERT_2             0x0f0e /* unused */
+#define AC_VERB_GET_VOLUME_KNOB_CONTROL                0x0f0f
+/* f10-f1a: GPIO */
+#define AC_VERB_GET_GPIO_DATA                  0x0f15
+#define AC_VERB_GET_GPIO_MASK                  0x0f16
+#define AC_VERB_GET_GPIO_DIRECTION             0x0f17
+#define AC_VERB_GET_GPIO_WAKE_MASK             0x0f18
+#define AC_VERB_GET_GPIO_UNSOLICITED_RSP_MASK  0x0f19
+#define AC_VERB_GET_GPIO_STICKY_MASK           0x0f1a
+#define AC_VERB_GET_CONFIG_DEFAULT             0x0f1c
+/* f20: AFG/MFG */
+#define AC_VERB_GET_SUBSYSTEM_ID               0x0f20
+#define AC_VERB_GET_CVT_CHAN_COUNT             0x0f2d
+#define AC_VERB_GET_HDMI_DIP_SIZE              0x0f2e
+#define AC_VERB_GET_HDMI_ELDD                  0x0f2f
+#define AC_VERB_GET_HDMI_DIP_INDEX             0x0f30
+#define AC_VERB_GET_HDMI_DIP_DATA              0x0f31
+#define AC_VERB_GET_HDMI_DIP_XMIT              0x0f32
+#define AC_VERB_GET_HDMI_CP_CTRL               0x0f33
+#define AC_VERB_GET_HDMI_CHAN_SLOT             0x0f34
+#define AC_VERB_GET_DEVICE_SEL                 0xf35
+#define AC_VERB_GET_DEVICE_LIST                        0xf36
+
+/*
+ * SET verbs
+ */
+#define AC_VERB_SET_STREAM_FORMAT              0x200
+#define AC_VERB_SET_AMP_GAIN_MUTE              0x300
+#define AC_VERB_SET_PROC_COEF                  0x400
+#define AC_VERB_SET_COEF_INDEX                 0x500
+#define AC_VERB_SET_CONNECT_SEL                        0x701
+#define AC_VERB_SET_PROC_STATE                 0x703
+#define AC_VERB_SET_SDI_SELECT                 0x704
+#define AC_VERB_SET_POWER_STATE                        0x705
+#define AC_VERB_SET_CHANNEL_STREAMID           0x706
+#define AC_VERB_SET_PIN_WIDGET_CONTROL         0x707
+#define AC_VERB_SET_UNSOLICITED_ENABLE         0x708
+#define AC_VERB_SET_PIN_SENSE                  0x709
+#define AC_VERB_SET_BEEP_CONTROL               0x70a
+#define AC_VERB_SET_EAPD_BTLENABLE             0x70c
+#define AC_VERB_SET_DIGI_CONVERT_1             0x70d
+#define AC_VERB_SET_DIGI_CONVERT_2             0x70e
+#define AC_VERB_SET_VOLUME_KNOB_CONTROL                0x70f
+#define AC_VERB_SET_GPIO_DATA                  0x715
+#define AC_VERB_SET_GPIO_MASK                  0x716
+#define AC_VERB_SET_GPIO_DIRECTION             0x717
+#define AC_VERB_SET_GPIO_WAKE_MASK             0x718
+#define AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK  0x719
+#define AC_VERB_SET_GPIO_STICKY_MASK           0x71a
+#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_0     0x71c
+#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_1     0x71d
+#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_2     0x71e
+#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_3     0x71f
+#define AC_VERB_SET_EAPD                               0x788
+#define AC_VERB_SET_CODEC_RESET                        0x7ff
+#define AC_VERB_SET_CVT_CHAN_COUNT             0x72d
+#define AC_VERB_SET_HDMI_DIP_INDEX             0x730
+#define AC_VERB_SET_HDMI_DIP_DATA              0x731
+#define AC_VERB_SET_HDMI_DIP_XMIT              0x732
+#define AC_VERB_SET_HDMI_CP_CTRL               0x733
+#define AC_VERB_SET_HDMI_CHAN_SLOT             0x734
+#define AC_VERB_SET_DEVICE_SEL                 0x735
+
+/*
+ * Parameter IDs
+ */
+#define AC_PAR_VENDOR_ID               0x00
+#define AC_PAR_SUBSYSTEM_ID            0x01
+#define AC_PAR_REV_ID                  0x02
+#define AC_PAR_NODE_COUNT              0x04
+#define AC_PAR_FUNCTION_TYPE           0x05
+#define AC_PAR_AUDIO_FG_CAP            0x08
+#define AC_PAR_AUDIO_WIDGET_CAP                0x09
+#define AC_PAR_PCM                     0x0a
+#define AC_PAR_STREAM                  0x0b
+#define AC_PAR_PIN_CAP                 0x0c
+#define AC_PAR_AMP_IN_CAP              0x0d
+#define AC_PAR_CONNLIST_LEN            0x0e
+#define AC_PAR_POWER_STATE             0x0f
+#define AC_PAR_PROC_CAP                        0x10
+#define AC_PAR_GPIO_CAP                        0x11
+#define AC_PAR_AMP_OUT_CAP             0x12
+#define AC_PAR_VOL_KNB_CAP             0x13
+#define AC_PAR_DEVLIST_LEN             0x15
+#define AC_PAR_HDMI_LPCM_CAP           0x20
+
+/*
+ * AC_VERB_PARAMETERS results (32bit)
+ */
+
+/* Function Group Type */
+#define AC_FGT_TYPE                    (0xff<<0)
+#define AC_FGT_TYPE_SHIFT              0
+#define AC_FGT_UNSOL_CAP               (1<<8)
+
+/* Audio Function Group Capabilities */
+#define AC_AFG_OUT_DELAY               (0xf<<0)
+#define AC_AFG_IN_DELAY                        (0xf<<8)
+#define AC_AFG_BEEP_GEN                        (1<<16)
+
+/* Audio Widget Capabilities */
+#define AC_WCAP_STEREO                 (1<<0)  /* stereo I/O */
+#define AC_WCAP_IN_AMP                 (1<<1)  /* AMP-in present */
+#define AC_WCAP_OUT_AMP                        (1<<2)  /* AMP-out present */
+#define AC_WCAP_AMP_OVRD               (1<<3)  /* AMP-parameter override */
+#define AC_WCAP_FORMAT_OVRD            (1<<4)  /* format override */
+#define AC_WCAP_STRIPE                 (1<<5)  /* stripe */
+#define AC_WCAP_PROC_WID               (1<<6)  /* Proc Widget */
+#define AC_WCAP_UNSOL_CAP              (1<<7)  /* Unsol capable */
+#define AC_WCAP_CONN_LIST              (1<<8)  /* connection list */
+#define AC_WCAP_DIGITAL                        (1<<9)  /* digital I/O */
+#define AC_WCAP_POWER                  (1<<10) /* power control */
+#define AC_WCAP_LR_SWAP                        (1<<11) /* L/R swap */
+#define AC_WCAP_CP_CAPS                        (1<<12) /* content protection */
+#define AC_WCAP_CHAN_CNT_EXT           (7<<13) /* channel count ext */
+#define AC_WCAP_DELAY                  (0xf<<16)
+#define AC_WCAP_DELAY_SHIFT            16
+#define AC_WCAP_TYPE                   (0xf<<20)
+#define AC_WCAP_TYPE_SHIFT             20
+
+/* supported PCM rates and bits */
+#define AC_SUPPCM_RATES                        (0xfff << 0)
+#define AC_SUPPCM_BITS_8               (1<<16)
+#define AC_SUPPCM_BITS_16              (1<<17)
+#define AC_SUPPCM_BITS_20              (1<<18)
+#define AC_SUPPCM_BITS_24              (1<<19)
+#define AC_SUPPCM_BITS_32              (1<<20)
+
+/* supported PCM stream format */
+#define AC_SUPFMT_PCM                  (1<<0)
+#define AC_SUPFMT_FLOAT32              (1<<1)
+#define AC_SUPFMT_AC3                  (1<<2)
+
+/* GP I/O count */
+#define AC_GPIO_IO_COUNT               (0xff<<0)
+#define AC_GPIO_O_COUNT                        (0xff<<8)
+#define AC_GPIO_O_COUNT_SHIFT          8
+#define AC_GPIO_I_COUNT                        (0xff<<16)
+#define AC_GPIO_I_COUNT_SHIFT          16
+#define AC_GPIO_UNSOLICITED            (1<<30)
+#define AC_GPIO_WAKE                   (1<<31)
+
+/* Converter stream, channel */
+#define AC_CONV_CHANNEL                        (0xf<<0)
+#define AC_CONV_STREAM                 (0xf<<4)
+#define AC_CONV_STREAM_SHIFT           4
+
+/* Input converter SDI select */
+#define AC_SDI_SELECT                  (0xf<<0)
+
+/* stream format id */
+#define AC_FMT_CHAN_SHIFT              0
+#define AC_FMT_CHAN_MASK               (0x0f << 0)
+#define AC_FMT_BITS_SHIFT              4
+#define AC_FMT_BITS_MASK               (7 << 4)
+#define AC_FMT_BITS_8                  (0 << 4)
+#define AC_FMT_BITS_16                 (1 << 4)
+#define AC_FMT_BITS_20                 (2 << 4)
+#define AC_FMT_BITS_24                 (3 << 4)
+#define AC_FMT_BITS_32                 (4 << 4)
+#define AC_FMT_DIV_SHIFT               8
+#define AC_FMT_DIV_MASK                        (7 << 8)
+#define AC_FMT_MULT_SHIFT              11
+#define AC_FMT_MULT_MASK               (7 << 11)
+#define AC_FMT_BASE_SHIFT              14
+#define AC_FMT_BASE_48K                        (0 << 14)
+#define AC_FMT_BASE_44K                        (1 << 14)
+#define AC_FMT_TYPE_SHIFT              15
+#define AC_FMT_TYPE_PCM                        (0 << 15)
+#define AC_FMT_TYPE_NON_PCM            (1 << 15)
+
+/* Unsolicited response control */
+#define AC_UNSOL_TAG                   (0x3f<<0)
+#define AC_UNSOL_ENABLED               (1<<7)
+#define AC_USRSP_EN                    AC_UNSOL_ENABLED
+
+/* Unsolicited responses */
+#define AC_UNSOL_RES_TAG               (0x3f<<26)
+#define AC_UNSOL_RES_TAG_SHIFT         26
+#define AC_UNSOL_RES_SUBTAG            (0x1f<<21)
+#define AC_UNSOL_RES_SUBTAG_SHIFT      21
+#define AC_UNSOL_RES_DE                        (0x3f<<15)  /* Device Entry
+                                                    * (for DP1.2 MST)
+                                                    */
+#define AC_UNSOL_RES_DE_SHIFT          15
+#define AC_UNSOL_RES_IA                        (1<<2)  /* Inactive (for DP1.2 MST) */
+#define AC_UNSOL_RES_ELDV              (1<<1)  /* ELD Data valid (for HDMI) */
+#define AC_UNSOL_RES_PD                        (1<<0)  /* pinsense detect */
+#define AC_UNSOL_RES_CP_STATE          (1<<1)  /* content protection */
+#define AC_UNSOL_RES_CP_READY          (1<<0)  /* content protection */
+
+/* Pin widget capabilies */
+#define AC_PINCAP_IMP_SENSE            (1<<0)  /* impedance sense capable */
+#define AC_PINCAP_TRIG_REQ             (1<<1)  /* trigger required */
+#define AC_PINCAP_PRES_DETECT          (1<<2)  /* presence detect capable */
+#define AC_PINCAP_HP_DRV               (1<<3)  /* headphone drive capable */
+#define AC_PINCAP_OUT                  (1<<4)  /* output capable */
+#define AC_PINCAP_IN                   (1<<5)  /* input capable */
+#define AC_PINCAP_BALANCE              (1<<6)  /* balanced I/O capable */
+/* Note: This LR_SWAP pincap is defined in the Realtek ALC883 specification,
+ *       but is marked reserved in the Intel HDA specification.
+ */
+#define AC_PINCAP_LR_SWAP              (1<<7)  /* L/R swap */
+/* Note: The same bit as LR_SWAP is newly defined as HDMI capability
+ *       in HD-audio specification
+ */
+#define AC_PINCAP_HDMI                 (1<<7)  /* HDMI pin */
+#define AC_PINCAP_DP                   (1<<24) /* DisplayPort pin, can
+                                                * coexist with AC_PINCAP_HDMI
+                                                */
+#define AC_PINCAP_VREF                 (0x37<<8)
+#define AC_PINCAP_VREF_SHIFT           8
+#define AC_PINCAP_EAPD                 (1<<16) /* EAPD capable */
+#define AC_PINCAP_HBR                  (1<<27) /* High Bit Rate */
+/* Vref status (used in pin cap) */
+#define AC_PINCAP_VREF_HIZ             (1<<0)  /* Hi-Z */
+#define AC_PINCAP_VREF_50              (1<<1)  /* 50% */
+#define AC_PINCAP_VREF_GRD             (1<<2)  /* ground */
+#define AC_PINCAP_VREF_80              (1<<4)  /* 80% */
+#define AC_PINCAP_VREF_100             (1<<5)  /* 100% */
+
+/* Amplifier capabilities */
+#define AC_AMPCAP_OFFSET               (0x7f<<0)  /* 0dB offset */
+#define AC_AMPCAP_OFFSET_SHIFT         0
+#define AC_AMPCAP_NUM_STEPS            (0x7f<<8)  /* number of steps */
+#define AC_AMPCAP_NUM_STEPS_SHIFT      8
+#define AC_AMPCAP_STEP_SIZE            (0x7f<<16) /* step size 0-32dB
+                                                   * in 0.25dB
+                                                   */
+#define AC_AMPCAP_STEP_SIZE_SHIFT      16
+#define AC_AMPCAP_MUTE                 (1<<31)    /* mute capable */
+#define AC_AMPCAP_MUTE_SHIFT           31
+
+/* driver-specific amp-caps: using bits 24-30 */
+#define AC_AMPCAP_MIN_MUTE             (1 << 30) /* min-volume = mute */
+
+/* Connection list */
+#define AC_CLIST_LENGTH                        (0x7f<<0)
+#define AC_CLIST_LONG                  (1<<7)
+
+/* Supported power status */
+#define AC_PWRST_D0SUP                 (1<<0)
+#define AC_PWRST_D1SUP                 (1<<1)
+#define AC_PWRST_D2SUP                 (1<<2)
+#define AC_PWRST_D3SUP                 (1<<3)
+#define AC_PWRST_D3COLDSUP             (1<<4)
+#define AC_PWRST_S3D3COLDSUP           (1<<29)
+#define AC_PWRST_CLKSTOP               (1<<30)
+#define AC_PWRST_EPSS                  (1U<<31)
+
+/* Power state values */
+#define AC_PWRST_SETTING               (0xf<<0)
+#define AC_PWRST_ACTUAL                        (0xf<<4)
+#define AC_PWRST_ACTUAL_SHIFT          4
+#define AC_PWRST_D0                    0x00
+#define AC_PWRST_D1                    0x01
+#define AC_PWRST_D2                    0x02
+#define AC_PWRST_D3                    0x03
+#define AC_PWRST_ERROR                  (1<<8)
+#define AC_PWRST_CLK_STOP_OK            (1<<9)
+#define AC_PWRST_SETTING_RESET          (1<<10)
+
+/* Processing capabilies */
+#define AC_PCAP_BENIGN                 (1<<0)
+#define AC_PCAP_NUM_COEF               (0xff<<8)
+#define AC_PCAP_NUM_COEF_SHIFT         8
+
+/* Volume knobs capabilities */
+#define AC_KNBCAP_NUM_STEPS            (0x7f<<0)
+#define AC_KNBCAP_DELTA                        (1<<7)
+
+/* HDMI LPCM capabilities */
+#define AC_LPCMCAP_48K_CP_CHNS         (0x0f<<0) /* max channels w/ CP-on */
+#define AC_LPCMCAP_48K_NO_CHNS         (0x0f<<4) /* max channels w/o CP-on */
+#define AC_LPCMCAP_48K_20BIT           (1<<8)  /* 20b bitrate supported */
+#define AC_LPCMCAP_48K_24BIT           (1<<9)  /* 24b bitrate supported */
+#define AC_LPCMCAP_96K_CP_CHNS         (0x0f<<10) /* max channels w/ CP-on */
+#define AC_LPCMCAP_96K_NO_CHNS         (0x0f<<14) /* max channels w/o CP-on */
+#define AC_LPCMCAP_96K_20BIT           (1<<18) /* 20b bitrate supported */
+#define AC_LPCMCAP_96K_24BIT           (1<<19) /* 24b bitrate supported */
+#define AC_LPCMCAP_192K_CP_CHNS                (0x0f<<20) /* max channels w/ CP-on */
+#define AC_LPCMCAP_192K_NO_CHNS                (0x0f<<24) /* max channels w/o CP-on */
+#define AC_LPCMCAP_192K_20BIT          (1<<28) /* 20b bitrate supported */
+#define AC_LPCMCAP_192K_24BIT          (1<<29) /* 24b bitrate supported */
+#define AC_LPCMCAP_44K                 (1<<30) /* 44.1kHz support */
+#define AC_LPCMCAP_44K_MS              (1<<31) /* 44.1kHz-multiplies support */
+
+/* Display pin's device list length */
+#define AC_DEV_LIST_LEN_MASK           0x3f
+#define AC_MAX_DEV_LIST_LEN            64
+
+/*
+ * Control Parameters
+ */
+
+/* Amp gain/mute */
+#define AC_AMP_MUTE                    (1<<7)
+#define AC_AMP_GAIN                    (0x7f)
+#define AC_AMP_GET_INDEX               (0xf<<0)
+
+#define AC_AMP_GET_LEFT                        (1<<13)
+#define AC_AMP_GET_RIGHT               (0<<13)
+#define AC_AMP_GET_OUTPUT              (1<<15)
+#define AC_AMP_GET_INPUT               (0<<15)
+
+#define AC_AMP_SET_INDEX               (0xf<<8)
+#define AC_AMP_SET_INDEX_SHIFT         8
+#define AC_AMP_SET_RIGHT               (1<<12)
+#define AC_AMP_SET_LEFT                        (1<<13)
+#define AC_AMP_SET_INPUT               (1<<14)
+#define AC_AMP_SET_OUTPUT              (1<<15)
+
+/* DIGITAL1 bits */
+#define AC_DIG1_ENABLE                 (1<<0)
+#define AC_DIG1_V                      (1<<1)
+#define AC_DIG1_VCFG                   (1<<2)
+#define AC_DIG1_EMPHASIS               (1<<3)
+#define AC_DIG1_COPYRIGHT              (1<<4)
+#define AC_DIG1_NONAUDIO               (1<<5)
+#define AC_DIG1_PROFESSIONAL           (1<<6)
+#define AC_DIG1_LEVEL                  (1<<7)
+
+/* DIGITAL2 bits */
+#define AC_DIG2_CC                     (0x7f<<0)
+
+/* DIGITAL3 bits */
+#define AC_DIG3_ICT                    (0xf<<0)
+#define AC_DIG3_KAE                    (1<<7)
+
+/* Pin widget control - 8bit */
+#define AC_PINCTL_EPT                  (0x3<<0)
+#define AC_PINCTL_EPT_NATIVE           0
+#define AC_PINCTL_EPT_HBR              3
+#define AC_PINCTL_VREFEN               (0x7<<0)
+#define AC_PINCTL_VREF_HIZ             0       /* Hi-Z */
+#define AC_PINCTL_VREF_50              1       /* 50% */
+#define AC_PINCTL_VREF_GRD             2       /* ground */
+#define AC_PINCTL_VREF_80              4       /* 80% */
+#define AC_PINCTL_VREF_100             5       /* 100% */
+#define AC_PINCTL_IN_EN                        (1<<5)
+#define AC_PINCTL_OUT_EN               (1<<6)
+#define AC_PINCTL_HP_EN                        (1<<7)
+
+/* Pin sense - 32bit */
+#define AC_PINSENSE_IMPEDANCE_MASK     (0x7fffffff)
+#define AC_PINSENSE_PRESENCE           (1<<31)
+#define AC_PINSENSE_ELDV               (1<<30) /* ELD valid (HDMI) */
+
+/* EAPD/BTL enable - 32bit */
+#define AC_EAPDBTL_BALANCED            (1<<0)
+#define AC_EAPDBTL_EAPD                        (1<<1)
+#define AC_EAPDBTL_LR_SWAP             (1<<2)
+
+/* HDMI ELD data */
+#define AC_ELDD_ELD_VALID              (1<<31)
+#define AC_ELDD_ELD_DATA               0xff
+
+/* HDMI DIP size */
+#define AC_DIPSIZE_ELD_BUF             (1<<3) /* ELD buf size of packet size */
+#define AC_DIPSIZE_PACK_IDX            (0x07<<0) /* packet index */
+
+/* HDMI DIP index */
+#define AC_DIPIDX_PACK_IDX             (0x07<<5) /* packet idnex */
+#define AC_DIPIDX_BYTE_IDX             (0x1f<<0) /* byte index */
+
+/* HDMI DIP xmit (transmit) control */
+#define AC_DIPXMIT_MASK                        (0x3<<6)
+#define AC_DIPXMIT_DISABLE             (0x0<<6) /* disable xmit */
+#define AC_DIPXMIT_ONCE                        (0x2<<6) /* xmit once then disable */
+#define AC_DIPXMIT_BEST                        (0x3<<6) /* best effort */
+
+/* HDMI content protection (CP) control */
+#define AC_CPCTRL_CES                  (1<<9) /* current encryption state */
+#define AC_CPCTRL_READY                        (1<<8) /* ready bit */
+#define AC_CPCTRL_SUBTAG               (0x1f<<3) /* subtag for unsol-resp */
+#define AC_CPCTRL_STATE                        (3<<0) /* current CP request state */
+
+/* Converter channel <-> HDMI slot mapping */
+#define AC_CVTMAP_HDMI_SLOT            (0xf<<0) /* HDMI slot number */
+#define AC_CVTMAP_CHAN                 (0xf<<4) /* converter channel number */
+
+/* configuration default - 32bit */
+#define AC_DEFCFG_SEQUENCE             (0xf<<0)
+#define AC_DEFCFG_DEF_ASSOC            (0xf<<4)
+#define AC_DEFCFG_ASSOC_SHIFT          4
+#define AC_DEFCFG_MISC                 (0xf<<8)
+#define AC_DEFCFG_MISC_SHIFT           8
+#define AC_DEFCFG_MISC_NO_PRESENCE     (1<<0)
+#define AC_DEFCFG_COLOR                        (0xf<<12)
+#define AC_DEFCFG_COLOR_SHIFT          12
+#define AC_DEFCFG_CONN_TYPE            (0xf<<16)
+#define AC_DEFCFG_CONN_TYPE_SHIFT      16
+#define AC_DEFCFG_DEVICE               (0xf<<20)
+#define AC_DEFCFG_DEVICE_SHIFT         20
+#define AC_DEFCFG_LOCATION             (0x3f<<24)
+#define AC_DEFCFG_LOCATION_SHIFT       24
+#define AC_DEFCFG_PORT_CONN            (0x3<<30)
+#define AC_DEFCFG_PORT_CONN_SHIFT      30
+
+/* Display pin's device list entry */
+#define AC_DE_PD                       (1<<0)
+#define AC_DE_ELDV                     (1<<1)
+#define AC_DE_IA                       (1<<2)
+
+/* device device types (0x0-0xf) */
+enum {
+       AC_JACK_LINE_OUT,
+       AC_JACK_SPEAKER,
+       AC_JACK_HP_OUT,
+       AC_JACK_CD,
+       AC_JACK_SPDIF_OUT,
+       AC_JACK_DIG_OTHER_OUT,
+       AC_JACK_MODEM_LINE_SIDE,
+       AC_JACK_MODEM_HAND_SIDE,
+       AC_JACK_LINE_IN,
+       AC_JACK_AUX,
+       AC_JACK_MIC_IN,
+       AC_JACK_TELEPHONY,
+       AC_JACK_SPDIF_IN,
+       AC_JACK_DIG_OTHER_IN,
+       AC_JACK_OTHER = 0xf,
+};
+
+/* jack connection types (0x0-0xf) */
+enum {
+       AC_JACK_CONN_UNKNOWN,
+       AC_JACK_CONN_1_8,
+       AC_JACK_CONN_1_4,
+       AC_JACK_CONN_ATAPI,
+       AC_JACK_CONN_RCA,
+       AC_JACK_CONN_OPTICAL,
+       AC_JACK_CONN_OTHER_DIGITAL,
+       AC_JACK_CONN_OTHER_ANALOG,
+       AC_JACK_CONN_DIN,
+       AC_JACK_CONN_XLR,
+       AC_JACK_CONN_RJ11,
+       AC_JACK_CONN_COMB,
+       AC_JACK_CONN_OTHER = 0xf,
+};
+
+/* jack colors (0x0-0xf) */
+enum {
+       AC_JACK_COLOR_UNKNOWN,
+       AC_JACK_COLOR_BLACK,
+       AC_JACK_COLOR_GREY,
+       AC_JACK_COLOR_BLUE,
+       AC_JACK_COLOR_GREEN,
+       AC_JACK_COLOR_RED,
+       AC_JACK_COLOR_ORANGE,
+       AC_JACK_COLOR_YELLOW,
+       AC_JACK_COLOR_PURPLE,
+       AC_JACK_COLOR_PINK,
+       AC_JACK_COLOR_WHITE = 0xe,
+       AC_JACK_COLOR_OTHER,
+};
+
+/* Jack location (0x0-0x3f) */
+/* common case */
+enum {
+       AC_JACK_LOC_NONE,
+       AC_JACK_LOC_REAR,
+       AC_JACK_LOC_FRONT,
+       AC_JACK_LOC_LEFT,
+       AC_JACK_LOC_RIGHT,
+       AC_JACK_LOC_TOP,
+       AC_JACK_LOC_BOTTOM,
+};
+/* bits 4-5 */
+enum {
+       AC_JACK_LOC_EXTERNAL = 0x00,
+       AC_JACK_LOC_INTERNAL = 0x10,
+       AC_JACK_LOC_SEPARATE = 0x20,
+       AC_JACK_LOC_OTHER    = 0x30,
+};
+enum {
+       /* external on primary chasis */
+       AC_JACK_LOC_REAR_PANEL = 0x07,
+       AC_JACK_LOC_DRIVE_BAY,
+       /* internal */
+       AC_JACK_LOC_RISER = 0x17,
+       AC_JACK_LOC_HDMI,
+       AC_JACK_LOC_ATAPI,
+       /* others */
+       AC_JACK_LOC_MOBILE_IN = 0x37,
+       AC_JACK_LOC_MOBILE_OUT,
+};
+
+/* Port connectivity (0-3) */
+enum {
+       AC_JACK_PORT_COMPLEX,
+       AC_JACK_PORT_NONE,
+       AC_JACK_PORT_FIXED,
+       AC_JACK_PORT_BOTH,
+};
+
+/* max. codec address */
+#define HDA_MAX_CODEC_ADDRESS  0x0f
+
+#endif /* __SOUND_HDA_VERBS_H */
index af998397041768a82ee347665e7040a9a4e44b9c..5f73785f5977e5f3c1b1a443c8f4a8f194b5f2b2 100644 (file)
@@ -108,7 +108,7 @@ static inline dma_addr_t snd_sgbuf_get_addr(struct snd_dma_buffer *dmab,
 {
        struct snd_sg_buf *sgbuf = dmab->private_data;
        dma_addr_t addr = sgbuf->table[offset >> PAGE_SHIFT].addr;
-       addr &= PAGE_MASK;
+       addr &= ~((dma_addr_t)PAGE_SIZE - 1);
        return addr + offset % PAGE_SIZE;
 }
 
index 12afab18945d056709df7495b75b0da6c0155426..8f639e03b76a45ac387e1092ca74aa19473c5002 100644 (file)
@@ -18,7 +18,7 @@
 #define RSND_GEN1_ADG  1
 #define RSND_GEN1_SSI  2
 
-#define RSND_GEN2_SRU  0
+#define RSND_GEN2_SCU  0
 #define RSND_GEN2_ADG  1
 #define RSND_GEN2_SSIU 2
 #define RSND_GEN2_SSI  3
@@ -34,7 +34,6 @@
  * B : SSI direction
  */
 #define RSND_SSI_CLK_PIN_SHARE         (1 << 31)
-#define RSND_SSI_CLK_FROM_ADG          (1 << 30) /* clock parent is master */
 #define RSND_SSI_SYNC                  (1 << 29) /* SSI34_sync etc */
 
 #define RSND_SSI_PLAY                  (1 << 24)
index 800c101bb096fd6f5c1170ebbdce1ab06cead062..243d3b689699791ae257b5edc48f5c6bb9f34bfd 100644 (file)
@@ -220,6 +220,8 @@ struct snd_soc_dai_driver {
        struct snd_soc_pcm_stream capture;
        struct snd_soc_pcm_stream playback;
        unsigned int symmetric_rates:1;
+       unsigned int symmetric_channels:1;
+       unsigned int symmetric_samplebits:1;
 
        /* probe ordering - for components with runtime dependencies */
        int probe_order;
@@ -244,6 +246,8 @@ struct snd_soc_dai {
        unsigned int capture_active:1;          /* stream is in use */
        unsigned int playback_active:1;         /* stream is in use */
        unsigned int symmetric_rates:1;
+       unsigned int symmetric_channels:1;
+       unsigned int symmetric_samplebits:1;
        struct snd_pcm_runtime *runtime;
        unsigned int active;
        unsigned char probed:1;
@@ -258,6 +262,8 @@ struct snd_soc_dai {
 
        /* Symmetry data - only valid if symmetry is being enforced */
        unsigned int rate;
+       unsigned int channels;
+       unsigned int sample_bits;
 
        /* parent platform/codec */
        struct snd_soc_platform *platform;
index 2037c45adfe648e907fa86290f7dfea847989c20..56ebdfca627375b1a7ec7d5ce5606bc124ecdf42 100644 (file)
@@ -104,7 +104,8 @@ struct device;
        SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
        .kcontrol_news = wcontrols, .num_kcontrols = 1}
 #define SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols) \
-{      .id = snd_soc_dapm_mux, .name = wname, .reg = wreg, \
+{      .id = snd_soc_dapm_mux, .name = wname, \
+       SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
        .kcontrol_news = wcontrols, .num_kcontrols = 1}
 #define SND_SOC_DAPM_VIRT_MUX(wname, wreg, wshift, winvert, wcontrols) \
 {      .id = snd_soc_dapm_virt_mux, .name = wname, \
index 1f741cb24f337c3e4662c2ff2cd45f78985c54c1..5a049d969c59cd0712940501974e4b23292f0b9c 100644 (file)
@@ -334,9 +334,7 @@ struct snd_soc_jack_pin;
 #include <sound/soc-dapm.h>
 #include <sound/soc-dpcm.h>
 
-#ifdef CONFIG_GPIOLIB
 struct snd_soc_jack_gpio;
-#endif
 
 typedef int (*hw_write_t)(void *,const char* ,int);
 
@@ -446,6 +444,17 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
                        struct snd_soc_jack_gpio *gpios);
 void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count,
                        struct snd_soc_jack_gpio *gpios);
+#else
+static inline int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
+                                        struct snd_soc_jack_gpio *gpios)
+{
+       return 0;
+}
+
+static inline void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count,
+                                          struct snd_soc_jack_gpio *gpios)
+{
+}
 #endif
 
 /* codec register bit access */
@@ -580,7 +589,6 @@ struct snd_soc_jack_zone {
  *                    to provide more complex checks (eg, reading an
  *                    ADC).
  */
-#ifdef CONFIG_GPIOLIB
 struct snd_soc_jack_gpio {
        unsigned int gpio;
        const char *name;
@@ -594,7 +602,6 @@ struct snd_soc_jack_gpio {
 
        int (*jack_status_check)(void);
 };
-#endif
 
 struct snd_soc_jack {
        struct mutex mutex;
@@ -879,6 +886,8 @@ struct snd_soc_dai_link {
 
        /* Symmetry requirements */
        unsigned int symmetric_rates:1;
+       unsigned int symmetric_channels:1;
+       unsigned int symmetric_samplebits:1;
 
        /* Do not create a PCM for this DAI link (Backend link) */
        unsigned int no_pcm:1;
index e2b9576d00e24772580a601a268e42bdc46e349e..095c6e4fe1e87ea02e3c6d9eeecdb66ddc1a1367 100644 (file)
@@ -24,10 +24,10 @@ DECLARE_EVENT_CLASS(bcache_request,
                __entry->dev            = bio->bi_bdev->bd_dev;
                __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;
-               blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_size);
+               __entry->sector         = bio->bi_iter.bi_sector;
+               __entry->orig_sector    = bio->bi_iter.bi_sector - 16;
+               __entry->nr_sector      = bio->bi_iter.bi_size >> 9;
+               blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_iter.bi_size);
        ),
 
        TP_printk("%d,%d %s %llu + %u (from %d,%d @ %llu)",
@@ -99,9 +99,9 @@ DECLARE_EVENT_CLASS(bcache_bio,
 
        TP_fast_assign(
                __entry->dev            = bio->bi_bdev->bd_dev;
-               __entry->sector         = bio->bi_sector;
-               __entry->nr_sector      = bio->bi_size >> 9;
-               blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_size);
+               __entry->sector         = bio->bi_iter.bi_sector;
+               __entry->nr_sector      = bio->bi_iter.bi_size >> 9;
+               blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_iter.bi_size);
        ),
 
        TP_printk("%d,%d  %s %llu + %u",
@@ -134,9 +134,9 @@ TRACE_EVENT(bcache_read,
 
        TP_fast_assign(
                __entry->dev            = bio->bi_bdev->bd_dev;
-               __entry->sector         = bio->bi_sector;
-               __entry->nr_sector      = bio->bi_size >> 9;
-               blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_size);
+               __entry->sector         = bio->bi_iter.bi_sector;
+               __entry->nr_sector      = bio->bi_iter.bi_size >> 9;
+               blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_iter.bi_size);
                __entry->cache_hit = hit;
                __entry->bypass = bypass;
        ),
@@ -162,9 +162,9 @@ TRACE_EVENT(bcache_write,
 
        TP_fast_assign(
                __entry->dev            = bio->bi_bdev->bd_dev;
-               __entry->sector         = bio->bi_sector;
-               __entry->nr_sector      = bio->bi_size >> 9;
-               blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_size);
+               __entry->sector         = bio->bi_iter.bi_sector;
+               __entry->nr_sector      = bio->bi_iter.bi_size >> 9;
+               blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_iter.bi_size);
                __entry->writeback = writeback;
                __entry->bypass = bypass;
        ),
index 4c2301d2ef1aa979ea0d6594ad1b6404368b920b..e76ae19a8d6fe65705e48104bb8212ed8bddb546 100644 (file)
@@ -243,9 +243,9 @@ TRACE_EVENT(block_bio_bounce,
        TP_fast_assign(
                __entry->dev            = bio->bi_bdev ?
                                          bio->bi_bdev->bd_dev : 0;
-               __entry->sector         = bio->bi_sector;
+               __entry->sector         = bio->bi_iter.bi_sector;
                __entry->nr_sector      = bio_sectors(bio);
-               blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_size);
+               blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_iter.bi_size);
                memcpy(__entry->comm, current->comm, TASK_COMM_LEN);
        ),
 
@@ -280,10 +280,10 @@ TRACE_EVENT(block_bio_complete,
 
        TP_fast_assign(
                __entry->dev            = bio->bi_bdev->bd_dev;
-               __entry->sector         = bio->bi_sector;
+               __entry->sector         = bio->bi_iter.bi_sector;
                __entry->nr_sector      = bio_sectors(bio);
                __entry->error          = error;
-               blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_size);
+               blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_iter.bi_size);
        ),
 
        TP_printk("%d,%d %s %llu + %u [%d]",
@@ -308,9 +308,9 @@ DECLARE_EVENT_CLASS(block_bio_merge,
 
        TP_fast_assign(
                __entry->dev            = bio->bi_bdev->bd_dev;
-               __entry->sector         = bio->bi_sector;
+               __entry->sector         = bio->bi_iter.bi_sector;
                __entry->nr_sector      = bio_sectors(bio);
-               blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_size);
+               blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_iter.bi_size);
                memcpy(__entry->comm, current->comm, TASK_COMM_LEN);
        ),
 
@@ -375,9 +375,9 @@ TRACE_EVENT(block_bio_queue,
 
        TP_fast_assign(
                __entry->dev            = bio->bi_bdev->bd_dev;
-               __entry->sector         = bio->bi_sector;
+               __entry->sector         = bio->bi_iter.bi_sector;
                __entry->nr_sector      = bio_sectors(bio);
-               blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_size);
+               blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_iter.bi_size);
                memcpy(__entry->comm, current->comm, TASK_COMM_LEN);
        ),
 
@@ -403,7 +403,7 @@ DECLARE_EVENT_CLASS(block_get_rq,
 
        TP_fast_assign(
                __entry->dev            = bio ? bio->bi_bdev->bd_dev : 0;
-               __entry->sector         = bio ? bio->bi_sector : 0;
+               __entry->sector         = bio ? bio->bi_iter.bi_sector : 0;
                __entry->nr_sector      = bio ? bio_sectors(bio) : 0;
                blk_fill_rwbs(__entry->rwbs,
                              bio ? bio->bi_rw : 0, __entry->nr_sector);
@@ -538,9 +538,9 @@ TRACE_EVENT(block_split,
 
        TP_fast_assign(
                __entry->dev            = bio->bi_bdev->bd_dev;
-               __entry->sector         = bio->bi_sector;
+               __entry->sector         = bio->bi_iter.bi_sector;
                __entry->new_sector     = new_sector;
-               blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_size);
+               blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_iter.bi_size);
                memcpy(__entry->comm, current->comm, TASK_COMM_LEN);
        ),
 
@@ -579,11 +579,11 @@ TRACE_EVENT(block_bio_remap,
 
        TP_fast_assign(
                __entry->dev            = bio->bi_bdev->bd_dev;
-               __entry->sector         = bio->bi_sector;
+               __entry->sector         = bio->bi_iter.bi_sector;
                __entry->nr_sector      = bio_sectors(bio);
                __entry->old_dev        = dev;
                __entry->old_sector     = from;
-               blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_size);
+               blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_iter.bi_size);
        ),
 
        TP_printk("%d,%d %s %llu + %u <- (%d,%d) %llu",
index e0dc355fa3179658a2b99660fd6fca0ca0a80937..67f38faac589ad52ac5850e5af602799753b8d29 100644 (file)
                { META,         "META" },                               \
                { META_FLUSH,   "META_FLUSH" })
 
-#define show_bio_type(type)                                            \
-       __print_symbolic(type,                                          \
-               { READ,         "READ" },                               \
-               { READA,        "READAHEAD" },                          \
-               { READ_SYNC,    "READ_SYNC" },                          \
-               { WRITE,        "WRITE" },                              \
-               { WRITE_SYNC,   "WRITE_SYNC" },                         \
-               { WRITE_FLUSH,  "WRITE_FLUSH" },                        \
-               { WRITE_FUA,    "WRITE_FUA" })
+#define F2FS_BIO_MASK(t)       (t & (READA | WRITE_FLUSH_FUA))
+#define F2FS_BIO_EXTRA_MASK(t) (t & (REQ_META | REQ_PRIO))
+
+#define show_bio_type(type)    show_bio_base(type), show_bio_extra(type)
+
+#define show_bio_base(type)                                            \
+       __print_symbolic(F2FS_BIO_MASK(type),                           \
+               { READ,                 "READ" },                       \
+               { READA,                "READAHEAD" },                  \
+               { READ_SYNC,            "READ_SYNC" },                  \
+               { WRITE,                "WRITE" },                      \
+               { WRITE_SYNC,           "WRITE_SYNC" },                 \
+               { WRITE_FLUSH,          "WRITE_FLUSH" },                \
+               { WRITE_FUA,            "WRITE_FUA" },                  \
+               { WRITE_FLUSH_FUA,      "WRITE_FLUSH_FUA" })
+
+#define show_bio_extra(type)                                           \
+       __print_symbolic(F2FS_BIO_EXTRA_MASK(type),                     \
+               { REQ_META,             "(M)" },                        \
+               { REQ_PRIO,             "(P)" },                        \
+               { REQ_META | REQ_PRIO,  "(MP)" },                       \
+               { 0, " \b" })
 
 #define show_data_type(type)                                           \
        __print_symbolic(type,                                          \
@@ -421,7 +434,7 @@ TRACE_EVENT(f2fs_truncate_partial_nodes,
                __entry->err)
 );
 
-TRACE_EVENT_CONDITION(f2fs_readpage,
+TRACE_EVENT_CONDITION(f2fs_submit_page_bio,
 
        TP_PROTO(struct page *page, sector_t blkaddr, int type),
 
@@ -446,7 +459,7 @@ TRACE_EVENT_CONDITION(f2fs_readpage,
        ),
 
        TP_printk("dev = (%d,%d), ino = %lu, page_index = 0x%lx, "
-               "blkaddr = 0x%llx, bio_type = %s",
+               "blkaddr = 0x%llx, bio_type = %s%s",
                show_dev_ino(__entry),
                (unsigned long)__entry->index,
                (unsigned long long)__entry->blkaddr,
@@ -598,36 +611,54 @@ TRACE_EVENT(f2fs_reserve_new_block,
                __entry->ofs_in_node)
 );
 
-TRACE_EVENT(f2fs_do_submit_bio,
+DECLARE_EVENT_CLASS(f2fs__submit_bio,
 
-       TP_PROTO(struct super_block *sb, int btype, bool sync, struct bio *bio),
+       TP_PROTO(struct super_block *sb, int rw, int type, struct bio *bio),
 
-       TP_ARGS(sb, btype, sync, bio),
+       TP_ARGS(sb, rw, type, bio),
 
        TP_STRUCT__entry(
                __field(dev_t,  dev)
-               __field(int,    btype)
-               __field(bool,   sync)
+               __field(int,    rw)
+               __field(int,    type)
                __field(sector_t,       sector)
                __field(unsigned int,   size)
        ),
 
        TP_fast_assign(
                __entry->dev            = sb->s_dev;
-               __entry->btype          = btype;
-               __entry->sync           = sync;
-               __entry->sector         = bio->bi_sector;
-               __entry->size           = bio->bi_size;
+               __entry->rw             = rw;
+               __entry->type           = type;
+               __entry->sector         = bio->bi_iter.bi_sector;
+               __entry->size           = bio->bi_iter.bi_size;
        ),
 
-       TP_printk("dev = (%d,%d), type = %s, io = %s, sector = %lld, size = %u",
+       TP_printk("dev = (%d,%d), %s%s, %s, sector = %lld, size = %u",
                show_dev(__entry),
-               show_block_type(__entry->btype),
-               __entry->sync ? "sync" : "no sync",
+               show_bio_type(__entry->rw),
+               show_block_type(__entry->type),
                (unsigned long long)__entry->sector,
                __entry->size)
 );
 
+DEFINE_EVENT_CONDITION(f2fs__submit_bio, f2fs_submit_write_bio,
+
+       TP_PROTO(struct super_block *sb, int rw, int type, struct bio *bio),
+
+       TP_ARGS(sb, rw, type, bio),
+
+       TP_CONDITION(bio)
+);
+
+DEFINE_EVENT_CONDITION(f2fs__submit_bio, f2fs_submit_read_bio,
+
+       TP_PROTO(struct super_block *sb, int rw, int type, struct bio *bio),
+
+       TP_ARGS(sb, rw, type, bio),
+
+       TP_CONDITION(bio)
+);
+
 DECLARE_EVENT_CLASS(f2fs__page,
 
        TP_PROTO(struct page *page, int type),
@@ -674,15 +705,16 @@ DEFINE_EVENT(f2fs__page, f2fs_vm_page_mkwrite,
        TP_ARGS(page, type)
 );
 
-TRACE_EVENT(f2fs_submit_write_page,
+TRACE_EVENT(f2fs_submit_page_mbio,
 
-       TP_PROTO(struct page *page, block_t blk_addr, int type),
+       TP_PROTO(struct page *page, int rw, int type, block_t blk_addr),
 
-       TP_ARGS(page, blk_addr, type),
+       TP_ARGS(page, rw, type, blk_addr),
 
        TP_STRUCT__entry(
                __field(dev_t,  dev)
                __field(ino_t,  ino)
+               __field(int, rw)
                __field(int, type)
                __field(pgoff_t, index)
                __field(block_t, block)
@@ -691,13 +723,15 @@ TRACE_EVENT(f2fs_submit_write_page,
        TP_fast_assign(
                __entry->dev    = page->mapping->host->i_sb->s_dev;
                __entry->ino    = page->mapping->host->i_ino;
+               __entry->rw     = rw;
                __entry->type   = type;
                __entry->index  = page->index;
                __entry->block  = blk_addr;
        ),
 
-       TP_printk("dev = (%d,%d), ino = %lu, %s, index = %lu, blkaddr = 0x%llx",
+       TP_printk("dev = (%d,%d), ino = %lu, %s%s, %s, index = %lu, blkaddr = 0x%llx",
                show_dev_ino(__entry),
+               show_bio_type(__entry->rw),
                show_block_type(__entry->type),
                (unsigned long)__entry->index,
                (unsigned long long)__entry->block)
@@ -727,6 +761,29 @@ TRACE_EVENT(f2fs_write_checkpoint,
                __entry->msg)
 );
 
+TRACE_EVENT(f2fs_issue_discard,
+
+       TP_PROTO(struct super_block *sb, block_t blkstart, block_t blklen),
+
+       TP_ARGS(sb, blkstart, blklen),
+
+       TP_STRUCT__entry(
+               __field(dev_t,  dev)
+               __field(block_t, blkstart)
+               __field(block_t, blklen)
+       ),
+
+       TP_fast_assign(
+               __entry->dev    = sb->s_dev;
+               __entry->blkstart = blkstart;
+               __entry->blklen = blklen;
+       ),
+
+       TP_printk("dev = (%d,%d), blkstart = 0x%llx, blklen = 0x%llx",
+               show_dev(__entry),
+               (unsigned long long)__entry->blkstart,
+               (unsigned long long)__entry->blklen)
+);
 #endif /* _TRACE_F2FS_H */
 
  /* This part must be outside protection */
index d17a35c6537e615a384e2cd006f37b4a2828a55a..5c38606613d89a06c361a56054e97031c391c2d3 100644 (file)
 #define TRACE_EVENT_FLAGS(name, value)                                 \
        __TRACE_EVENT_FLAGS(name, value)
 
+#undef TRACE_EVENT_PERF_PERM
+#define TRACE_EVENT_PERF_PERM(name, expr...)                           \
+       __TRACE_EVENT_PERF_PERM(name, expr)
+
 #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
 
 
 #undef TRACE_EVENT_FLAGS
 #define TRACE_EVENT_FLAGS(event, flag)
 
+#undef TRACE_EVENT_PERF_PERM
+#define TRACE_EVENT_PERF_PERM(event, expr...)
+
 #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
 
 /*
index 3a4e97bd860771b6ad8e3b5d026a35200fcad4d3..52aed893710a126e979cec558239e55c76cb2c59 100644 (file)
@@ -222,6 +222,7 @@ typedef struct _drm_i915_sarea {
 #define DRM_I915_GEM_SET_CACHING       0x2f
 #define DRM_I915_GEM_GET_CACHING       0x30
 #define DRM_I915_REG_READ              0x31
+#define DRM_I915_GET_RESET_STATS       0x32
 
 #define DRM_IOCTL_I915_INIT            DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
 #define DRM_IOCTL_I915_FLUSH           DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -271,6 +272,7 @@ typedef struct _drm_i915_sarea {
 #define DRM_IOCTL_I915_GEM_CONTEXT_CREATE      DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE, struct drm_i915_gem_context_create)
 #define DRM_IOCTL_I915_GEM_CONTEXT_DESTROY     DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_DESTROY, struct drm_i915_gem_context_destroy)
 #define DRM_IOCTL_I915_REG_READ                        DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_REG_READ, struct drm_i915_reg_read)
+#define DRM_IOCTL_I915_GET_RESET_STATS         DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GET_RESET_STATS, struct drm_i915_reset_stats)
 
 /* Allow drivers to submit batchbuffers directly to hardware, relying
  * on the security mechanisms provided by hardware.
@@ -1030,4 +1032,21 @@ struct drm_i915_reg_read {
        __u64 offset;
        __u64 val; /* Return value */
 };
+
+struct drm_i915_reset_stats {
+       __u32 ctx_id;
+       __u32 flags;
+
+       /* All resets since boot/module reload, for all contexts */
+       __u32 reset_count;
+
+       /* Number of batches lost when active in GPU, for this context */
+       __u32 batch_active;
+
+       /* Number of batches lost pending for execution, for this context */
+       __u32 batch_pending;
+
+       __u32 pad;
+};
+
 #endif /* _UAPI_I915_DRM_H_ */
index 33d2b8fe166dafcd8dd39c5b7a092b8b3d5befa6..3ce25b5d75a9facfd047a526d3c3af618169e488 100644 (file)
@@ -426,3 +426,5 @@ header-y += x25.h
 header-y += xattr.h
 header-y += xfrm.h
 header-y += hw_breakpoint.h
+header-y += zorro.h
+header-y += zorro_ids.h
index 2c267bcbb85c1c4e31b676127db7686d8d027e09..bc81fb2e1f0e19d363d3c8095c85b971c521d12a 100644 (file)
@@ -61,5 +61,16 @@ struct epoll_event {
        __u64 data;
 } EPOLL_PACKED;
 
-
+#ifdef CONFIG_PM_SLEEP
+static inline void ep_take_care_of_epollwakeup(struct epoll_event *epev)
+{
+       if ((epev->events & EPOLLWAKEUP) && !capable(CAP_BLOCK_SUSPEND))
+               epev->events &= ~EPOLLWAKEUP;
+}
+#else
+static inline void ep_take_care_of_epollwakeup(struct epoll_event *epev)
+{
+       epev->events &= ~EPOLLWAKEUP;
+}
+#endif
 #endif /* _UAPI_LINUX_EVENTPOLL_H */
index 1af72d8228e04db8c1d6de05cacfa1bfd4a577b7..c3363ba1ae057f66dc5b878ee9fde7899857c450 100644 (file)
@@ -28,6 +28,7 @@ struct genlmsghdr {
 #define GENL_ID_GENERATE       0
 #define GENL_ID_CTRL           NLMSG_MIN_TYPE
 #define GENL_ID_VFS_DQUOT      (NLMSG_MIN_TYPE + 1)
+#define GENL_ID_PMCRAID                (NLMSG_MIN_TYPE + 2)
 
 /**************************************************************************
  * Controller
index 23357ab81a7743942766c4ebb701b71cd9e99a84..cfed10be7529c5f540220789eb0f9025165157f3 100644 (file)
@@ -18,6 +18,9 @@ struct ifaddrmsg {
  * It makes no difference for normally configured broadcast interfaces,
  * but for point-to-point IFA_ADDRESS is DESTINATION address,
  * local address is supplied in IFA_LOCAL attribute.
+ *
+ * IFA_FLAGS is a u32 attribute that extends the u8 field ifa_flags.
+ * If present, the value from struct ifaddrmsg will be ignored.
  */
 enum {
        IFA_UNSPEC,
@@ -28,6 +31,7 @@ enum {
        IFA_ANYCAST,
        IFA_CACHEINFO,
        IFA_MULTICAST,
+       IFA_FLAGS,
        __IFA_MAX,
 };
 
@@ -44,6 +48,7 @@ enum {
 #define IFA_F_DEPRECATED       0x20
 #define IFA_F_TENTATIVE                0x40
 #define IFA_F_PERMANENT                0x80
+#define IFA_F_MANAGETEMPADDR   0x100
 
 struct ifa_cacheinfo {
        __u32   ifa_prefered;
index d7fea3496f323078739fc6c6148be125f79797c3..4d024d75d64ba8b7831cdb1d61384e47ac14ef33 100644 (file)
@@ -94,6 +94,7 @@
 #define ARPHRD_CAIF    822             /* CAIF media type              */
 #define ARPHRD_IP6GRE  823             /* GRE over IPv6                */
 #define ARPHRD_NETLINK 824             /* Netlink header               */
+#define ARPHRD_6LOWPAN 825             /* IPv6 over LoWPAN             */
 
 #define ARPHRD_VOID      0xFFFF        /* Void type, nothing is known */
 #define ARPHRD_NONE      0xFFFE        /* zero header length */
index b78566f59abaa54528ed86acf85eb7e7b3f305fa..6db460121f84845d4026420cdc2fd12fc4f1497e 100644 (file)
@@ -488,7 +488,9 @@ enum {
        IFLA_HSR_UNSPEC,
        IFLA_HSR_SLAVE1,
        IFLA_HSR_SLAVE2,
-       IFLA_HSR_MULTICAST_SPEC,
+       IFLA_HSR_MULTICAST_SPEC,        /* Last byte of supervision addr */
+       IFLA_HSR_SUPERVISION_ADDR,      /* Supervision frame multicast addr */
+       IFLA_HSR_SEQ_NR,
        __IFLA_HSR_MAX,
 };
 
index dbf06667394b1185fb1dc769a5da198636164a45..1e24aa701cbd3d2f45c4348ebcd2c00fae9e8bda 100644 (file)
@@ -51,6 +51,7 @@ struct sockaddr_ll {
 #define PACKET_TIMESTAMP               17
 #define PACKET_FANOUT                  18
 #define PACKET_TX_HAS_OFF              19
+#define PACKET_QDISC_BYPASS            20
 
 #define PACKET_FANOUT_HASH             0
 #define PACKET_FANOUT_LB               1
index a3726275876dc509bfa99a01b8113385c1fb2d2f..ecc88592ecbe94acfbacd1eda9b5907a832470da 100644 (file)
@@ -719,6 +719,8 @@ struct input_keymap_entry {
 #define BTN_DPAD_LEFT          0x222
 #define BTN_DPAD_RIGHT         0x223
 
+#define KEY_ALS_TOGGLE         0x230   /* Ambient light sensor */
+
 #define BTN_TRIGGER_HAPPY              0x2c0
 #define BTN_TRIGGER_HAPPY1             0x2c0
 #define BTN_TRIGGER_HAPPY2             0x2c1
@@ -856,6 +858,7 @@ struct input_keymap_entry {
 #define SW_FRONT_PROXIMITY     0x0b  /* set = front proximity sensor active */
 #define SW_ROTATE_LOCK         0x0c  /* set = rotate locked/disabled */
 #define SW_LINEIN_INSERT       0x0d  /* set = inserted */
+#define SW_MUTE_DEVICE         0x0e  /* set = device disabled */
 #define SW_MAX                 0x0f
 #define SW_CNT                 (SW_MAX+1)
 
index 104838f65bc184cf46531e3335492668a822789e..d6629d49a2433745d205cb3685dadeaffaeab61a 100644 (file)
@@ -18,6 +18,7 @@
  */
 #define KEXEC_ARCH_DEFAULT ( 0 << 16)
 #define KEXEC_ARCH_386     ( 3 << 16)
+#define KEXEC_ARCH_68K     ( 4 << 16)
 #define KEXEC_ARCH_X86_64  (62 << 16)
 #define KEXEC_ARCH_PPC     (20 << 16)
 #define KEXEC_ARCH_PPC64   (21 << 16)
index ed49574ad7573cc446e9ee722554998d3b3c8c34..d847c760e8f09c49fec028cbe3a7b599cee2e60f 100644 (file)
@@ -98,6 +98,7 @@ struct media_entity_desc {
 
 #define MEDIA_PAD_FL_SINK              (1 << 0)
 #define MEDIA_PAD_FL_SOURCE            (1 << 1)
+#define MEDIA_PAD_FL_MUST_CONNECT      (1 << 2)
 
 struct media_pad_desc {
        __u32 entity;           /* entity ID */
index 17e7d95e4f536b883cf98ebe363ed3734e9db958..6eb40244e0194110ce6c7e3878f738227ddfb013 100644 (file)
 
 #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)
+#define __mic_align(a, x) (((a) + (x) - 1) & ~((x) - 1))
 
 /**
  * struct mic_device_desc: Virtio device information shared between the
@@ -48,8 +43,8 @@ struct mic_device_desc {
        __u8 feature_len;
        __u8 config_len;
        __u8 status;
-       __u64 config[0];
-} __aligned(8);
+       __le64 config[0];
+} __attribute__ ((aligned(8)));
 
 /**
  * struct mic_device_ctrl: Per virtio device information in the device page
@@ -66,7 +61,7 @@ struct mic_device_desc {
  * @h2c_vdev_db: The doorbell number to be used by host. Set by guest.
  */
 struct mic_device_ctrl {
-       __u64 vdev;
+       __le64 vdev;
        __u8 config_change;
        __u8 vdev_reset;
        __u8 guest_ack;
@@ -74,7 +69,7 @@ struct mic_device_ctrl {
        __u8 used_address_updated;
        __s8 c2h_vdev_db;
        __s8 h2c_vdev_db;
-} __aligned(8);
+} __attribute__ ((aligned(8)));
 
 /**
  * struct mic_bootparam: Virtio device independent information in device page
@@ -87,13 +82,13 @@ struct mic_device_ctrl {
  * @shutdown_card: Set to 1 by the host when a card shutdown is initiated
  */
 struct mic_bootparam {
-       __u32 magic;
+       __le32 magic;
        __s8 c2h_shutdown_db;
        __s8 h2c_shutdown_db;
        __s8 h2c_config_db;
        __u8 shutdown_status;
        __u8 shutdown_card;
-} __aligned(8);
+} __attribute__ ((aligned(8)));
 
 /**
  * struct mic_device_page: High level representation of the device page
@@ -116,10 +111,10 @@ struct mic_device_page {
  * @num: The number of entries in the virtio_ring
  */
 struct mic_vqconfig {
-       __u64 address;
-       __u64 used_address;
-       __u16 num;
-} __aligned(8);
+       __le64 address;
+       __le64 used_address;
+       __le16 num;
+} __attribute__ ((aligned(8)));
 
 /*
  * The alignment to use between consumer and producer parts of vring.
@@ -154,7 +149,7 @@ struct mic_vqconfig {
  */
 struct _mic_vring_info {
        __u16 avail_idx;
-       int magic;
+       __le32 magic;
 };
 
 /**
@@ -173,15 +168,13 @@ struct mic_vring {
        int len;
 };
 
-#define mic_aligned_desc_size(d) ALIGN(mic_desc_size(d), 8)
+#define mic_aligned_desc_size(d) __mic_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;
+       return sizeof(*desc) + desc->num_vq * sizeof(struct mic_vqconfig)
+               + desc->feature_len * 2 + desc->config_len;
 }
 
 static inline struct mic_vqconfig *
@@ -201,8 +194,7 @@ static inline __u8 *mic_vq_configspace(const struct mic_device_desc *desc)
 }
 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);
+       return mic_aligned_desc_size(desc) + sizeof(struct mic_device_ctrl);
 }
 #endif
 
index ae5df122e42f9108d27430e26a23fa12e5a98d23..f53879c0f590f6a10c891f3716dfc060aefe4bc2 100644 (file)
@@ -26,17 +26,17 @@ enum {
 };
 
 /**
- * struct hwtstamp_config - %SIOCSHWTSTAMP parameter
+ * struct hwtstamp_config - %SIOCGHWTSTAMP and %SIOCSHWTSTAMP parameter
  *
- * @flags:     no flags defined right now, must be zero
+ * @flags:     no flags defined right now, must be zero for %SIOCSHWTSTAMP
  * @tx_type:   one of HWTSTAMP_TX_*
- * @rx_type:   one of one of HWTSTAMP_FILTER_*
+ * @rx_filter: one of HWTSTAMP_FILTER_*
  *
- * %SIOCSHWTSTAMP expects a &struct ifreq with a ifr_data pointer to
- * this structure. dev_ifsioc() in the kernel takes care of the
- * translation between 32 bit userspace and 64 bit kernel. The
- * structure is intentionally chosen so that it has the same layout on
- * 32 and 64 bit systems, don't break this!
+ * %SIOCGHWTSTAMP and %SIOCSHWTSTAMP expect a &struct ifreq with a
+ * ifr_data pointer to this structure.  For %SIOCSHWTSTAMP, if the
+ * driver or hardware does not support the requested @rx_filter value,
+ * the driver may use a more general filter mode.  In this case
+ * @rx_filter will indicate the actual mode on return.
  */
 struct hwtstamp_config {
        int flags;
index 18afa495f9737b9915732b953729ee7f2dd91459..5d66caeba3eec38b725e2a7b37edaa3450713e3a 100644 (file)
@@ -13,8 +13,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef _XT_OSF_H
index 4e31db4eea412dcfc3c56364d734b420f36afaef..f2159d30d1f5a24c76d6e939318603e72faa2637 100644 (file)
@@ -33,6 +33,7 @@ struct netlink_diag_ring {
 };
 
 enum {
+       /* NETLINK_DIAG_NONE, standard nl API requires this attribute!  */
        NETLINK_DIAG_MEMINFO,
        NETLINK_DIAG_GROUPS,
        NETLINK_DIAG_RX_RING,
index f752e9821e717ee68066f4d8467775a8bee2fd78..129b7b08714848279f3638019892a4dc0e9e6d65 100644 (file)
  *     operation, %NL80211_ATTR_MAC contains the peer MAC address, and
  *     %NL80211_ATTR_REASON_CODE the reason code to be used (only with
  *     %NL80211_TDLS_TEARDOWN).
- * @NL80211_CMD_TDLS_MGMT: Send a TDLS management frame.
+ * @NL80211_CMD_TDLS_MGMT: Send a TDLS management frame. The
+ *     %NL80211_ATTR_TDLS_ACTION attribute determines the type of frame to be
+ *     sent. Public Action codes (802.11-2012 8.1.5.1) will be sent as
+ *     802.11 management frames, while TDLS action codes (802.11-2012
+ *     8.5.13.1) will be encapsulated and sent as data frames. The currently
+ *     supported Public Action code is %WLAN_PUB_ACTION_TDLS_DISCOVER_RES
+ *     and the currently supported TDLS actions codes are given in
+ *     &enum ieee80211_tdls_actioncode.
  *
  * @NL80211_CMD_UNEXPECTED_FRAME: Used by an application controlling an AP
  *     (or GO) interface (i.e. hostapd) to ask for unexpected frames to
@@ -1508,6 +1515,11 @@ enum nl80211_commands {
  *     to react to radar events, e.g. initiate a channel switch or leave the
  *     IBSS network.
  *
+ * @NL80211_ATTR_SUPPORT_5_MHZ: A flag indicating that the device supports
+ *     5 MHz channel bandwidth.
+ * @NL80211_ATTR_SUPPORT_10_MHZ: A flag indicating that the device supports
+ *     10 MHz channel bandwidth.
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -1824,6 +1836,9 @@ enum nl80211_attrs {
 
        NL80211_ATTR_HANDLE_DFS,
 
+       NL80211_ATTR_SUPPORT_5_MHZ,
+       NL80211_ATTR_SUPPORT_10_MHZ,
+
        /* add attributes here, update the policy in nl80211.c */
 
        __NL80211_ATTR_AFTER_LAST,
@@ -2224,10 +2239,9 @@ enum nl80211_band_attr {
  * @NL80211_FREQUENCY_ATTR_FREQ: Frequency in MHz
  * @NL80211_FREQUENCY_ATTR_DISABLED: Channel is disabled in current
  *     regulatory domain.
- * @NL80211_FREQUENCY_ATTR_PASSIVE_SCAN: Only passive scanning is
- *     permitted on this channel in current regulatory domain.
- * @NL80211_FREQUENCY_ATTR_NO_IBSS: IBSS networks are not permitted
- *     on this channel in current regulatory domain.
+ * @NL80211_FREQUENCY_ATTR_NO_IR: no mechanisms that initiate radiation
+ *     are permitted on this channel, this includes sending probe
+ *     requests, or modes of operation that require beaconing.
  * @NL80211_FREQUENCY_ATTR_RADAR: Radar detection is mandatory
  *     on this channel in current regulatory domain.
  * @NL80211_FREQUENCY_ATTR_MAX_TX_POWER: Maximum transmission power in mBm
@@ -2254,8 +2268,8 @@ enum nl80211_frequency_attr {
        __NL80211_FREQUENCY_ATTR_INVALID,
        NL80211_FREQUENCY_ATTR_FREQ,
        NL80211_FREQUENCY_ATTR_DISABLED,
-       NL80211_FREQUENCY_ATTR_PASSIVE_SCAN,
-       NL80211_FREQUENCY_ATTR_NO_IBSS,
+       NL80211_FREQUENCY_ATTR_NO_IR,
+       __NL80211_FREQUENCY_ATTR_NO_IBSS,
        NL80211_FREQUENCY_ATTR_RADAR,
        NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
        NL80211_FREQUENCY_ATTR_DFS_STATE,
@@ -2271,6 +2285,9 @@ enum nl80211_frequency_attr {
 };
 
 #define NL80211_FREQUENCY_ATTR_MAX_TX_POWER NL80211_FREQUENCY_ATTR_MAX_TX_POWER
+#define NL80211_FREQUENCY_ATTR_PASSIVE_SCAN    NL80211_FREQUENCY_ATTR_NO_IR
+#define NL80211_FREQUENCY_ATTR_NO_IBSS         NL80211_FREQUENCY_ATTR_NO_IR
+#define NL80211_FREQUENCY_ATTR_NO_IR           NL80211_FREQUENCY_ATTR_NO_IR
 
 /**
  * enum nl80211_bitrate_attr - bitrate attributes
@@ -2413,8 +2430,9 @@ enum nl80211_sched_scan_match_attr {
  * @NL80211_RRF_DFS: DFS support is required to be used
  * @NL80211_RRF_PTP_ONLY: this is only for Point To Point links
  * @NL80211_RRF_PTMP_ONLY: this is only for Point To Multi Point links
- * @NL80211_RRF_PASSIVE_SCAN: passive scan is required
- * @NL80211_RRF_NO_IBSS: no IBSS is allowed
+ * @NL80211_RRF_NO_IR: no mechanisms that initiate radiation are allowed,
+ *     this includes probe requests or modes of operation that require
+ *     beaconing.
  */
 enum nl80211_reg_rule_flags {
        NL80211_RRF_NO_OFDM             = 1<<0,
@@ -2424,10 +2442,17 @@ enum nl80211_reg_rule_flags {
        NL80211_RRF_DFS                 = 1<<4,
        NL80211_RRF_PTP_ONLY            = 1<<5,
        NL80211_RRF_PTMP_ONLY           = 1<<6,
-       NL80211_RRF_PASSIVE_SCAN        = 1<<7,
-       NL80211_RRF_NO_IBSS             = 1<<8,
+       NL80211_RRF_NO_IR               = 1<<7,
+       __NL80211_RRF_NO_IBSS           = 1<<8,
 };
 
+#define NL80211_RRF_PASSIVE_SCAN       NL80211_RRF_NO_IR
+#define NL80211_RRF_NO_IBSS            NL80211_RRF_NO_IR
+#define NL80211_RRF_NO_IR              NL80211_RRF_NO_IR
+
+/* For backport compatibility with older userspace */
+#define NL80211_RRF_NO_IR_ALL          (NL80211_RRF_NO_IR | __NL80211_RRF_NO_IBSS)
+
 /**
  * enum nl80211_dfs_regions - regulatory DFS regions
  *
index b2cc0cd9c4d9782433b4203e24480267257071ce..d08c63f3dd6ff47c7cf090927e91f27cfc0d767f 100644 (file)
@@ -29,6 +29,7 @@ struct packet_diag_msg {
 };
 
 enum {
+       /* PACKET_DIAG_NONE, standard nl API requires this attribute!  */
        PACKET_DIAG_INFO,
        PACKET_DIAG_MCLIST,
        PACKET_DIAG_RX_RING,
index ca451e99b28b92f5a5e1d8fde7d99446e2df06cf..266022a2be4acae990ed56c3efe783766d667d6e 100644 (file)
@@ -22,9 +22,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
index 1bdb4a39d1e1512da2091f1c4e897c5e03527554..bbaba22f2d1bcfa25517acb1bf19fc8eb648c480 100644 (file)
@@ -258,6 +258,7 @@ enum
        LINUX_MIB_TCPFASTOPENCOOKIEREQD,        /* TCPFastOpenCookieReqd */
        LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES, /* TCPSpuriousRtxHostQueues */
        LINUX_MIB_BUSYPOLLRXPACKETS,            /* BusyPollRxPackets */
+       LINUX_MIB_TCPAUTOCORKING,               /* TCPAutoCorking */
        __LINUX_MIB_MAX
 };
 
index 7997a506ad4105fb145a9ddc120286a8431a1502..e888b1aed69f84c27dd38546ca110f65eaad2c6e 100644 (file)
 #define SIOCBRDELIF    0x89a3          /* remove interface from bridge */
 
 /* hardware time stamping: parameters in linux/net_tstamp.h */
-#define SIOCSHWTSTAMP   0x89b0
+#define SIOCSHWTSTAMP  0x89b0          /* set and get config           */
+#define SIOCGHWTSTAMP  0x89b1          /* get config                   */
 
 /* Device private ioctl calls */
 
index b9e2a6a7446f077e528dd15fac8e8d97f0d9a232..1eb0b8dd18308481313b9d13b284f897a56188aa 100644 (file)
@@ -31,6 +31,7 @@ struct unix_diag_msg {
 };
 
 enum {
+       /* UNIX_DIAG_NONE, standard nl API requires this attribute!  */
        UNIX_DIAG_NAME,
        UNIX_DIAG_VFS,
        UNIX_DIAG_PEER,
diff --git a/include/uapi/linux/zorro.h b/include/uapi/linux/zorro.h
new file mode 100644 (file)
index 0000000..59d021b
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ *  linux/zorro.h -- Amiga AutoConfig (Zorro) Bus Definitions
+ *
+ *  Copyright (C) 1995--2003 Geert Uytterhoeven
+ *
+ *  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 _UAPI_LINUX_ZORRO_H
+#define _UAPI_LINUX_ZORRO_H
+
+#include <linux/types.h>
+
+
+    /*
+     *  Each Zorro board has a 32-bit ID of the form
+     *
+     *      mmmmmmmmmmmmmmmmppppppppeeeeeeee
+     *
+     *  with
+     *
+     *      mmmmmmmmmmmmmmmm   16-bit Manufacturer ID (assigned by CBM (sigh))
+     *      pppppppp           8-bit Product ID (assigned by manufacturer)
+     *      eeeeeeee           8-bit Extended Product ID (currently only used
+     *                         for some GVP boards)
+     */
+
+
+#define ZORRO_MANUF(id)                ((id) >> 16)
+#define ZORRO_PROD(id)         (((id) >> 8) & 0xff)
+#define ZORRO_EPC(id)          ((id) & 0xff)
+
+#define ZORRO_ID(manuf, prod, epc) \
+       ((ZORRO_MANUF_##manuf << 16) | ((prod) << 8) | (epc))
+
+typedef __u32 zorro_id;
+
+
+/* Include the ID list */
+#include <linux/zorro_ids.h>
+
+
+    /*
+     *  GVP identifies most of its products through the 'extended product code'
+     *  (epc). The epc has to be ANDed with the GVP_PRODMASK before the
+     *  identification.
+     */
+
+#define GVP_PRODMASK           (0xf8)
+#define GVP_SCSICLKMASK                (0x01)
+
+enum GVP_flags {
+       GVP_IO                  = 0x01,
+       GVP_ACCEL               = 0x02,
+       GVP_SCSI                = 0x04,
+       GVP_24BITDMA            = 0x08,
+       GVP_25BITDMA            = 0x10,
+       GVP_NOBANK              = 0x20,
+       GVP_14MHZ               = 0x40,
+};
+
+
+struct Node {
+       __be32 ln_Succ;         /* Pointer to next (successor) */
+       __be32 ln_Pred;         /* Pointer to previous (predecessor) */
+       __u8   ln_Type;
+       __s8   ln_Pri;          /* Priority, for sorting */
+       __be32 ln_Name;         /* ID string, null terminated */
+} __packed;
+
+struct ExpansionRom {
+       /* -First 16 bytes of the expansion ROM */
+       __u8   er_Type;         /* Board type, size and flags */
+       __u8   er_Product;      /* Product number, assigned by manufacturer */
+       __u8   er_Flags;                /* Flags */
+       __u8   er_Reserved03;   /* Must be zero ($ff inverted) */
+       __be16 er_Manufacturer; /* Unique ID, ASSIGNED BY COMMODORE-AMIGA! */
+       __be32 er_SerialNumber; /* Available for use by manufacturer */
+       __be16 er_InitDiagVec;  /* Offset to optional "DiagArea" structure */
+       __u8   er_Reserved0c;
+       __u8   er_Reserved0d;
+       __u8   er_Reserved0e;
+       __u8   er_Reserved0f;
+} __packed;
+
+/* er_Type board type bits */
+#define ERT_TYPEMASK   0xc0
+#define ERT_ZORROII    0xc0
+#define ERT_ZORROIII   0x80
+
+/* other bits defined in er_Type */
+#define ERTB_MEMLIST   5               /* Link RAM into free memory list */
+#define ERTF_MEMLIST   (1<<5)
+
+struct ConfigDev {
+       struct Node     cd_Node;
+       __u8            cd_Flags;       /* (read/write) */
+       __u8            cd_Pad;         /* reserved */
+       struct ExpansionRom cd_Rom;     /* copy of board's expansion ROM */
+       __be32          cd_BoardAddr;   /* where in memory the board was placed */
+       __be32          cd_BoardSize;   /* size of board in bytes */
+       __be16          cd_SlotAddr;    /* which slot number (PRIVATE) */
+       __be16          cd_SlotSize;    /* number of slots (PRIVATE) */
+       __be32          cd_Driver;      /* pointer to node of driver */
+       __be32          cd_NextCD;      /* linked list of drivers to config */
+       __be32          cd_Unused[4];   /* for whatever the driver wants */
+} __packed;
+
+#define ZORRO_NUM_AUTO         16
+
+#endif /* _UAPI_LINUX_ZORRO_H */
index d630163b9a2e6d46f079b00357be501d3b5335fc..5759810e1c1b9768f67f8e703c625b7ce9d76e94 100644 (file)
@@ -30,7 +30,7 @@
 #include <sound/compress_params.h>
 
 
-#define SNDRV_COMPRESS_VERSION SNDRV_PROTOCOL_VERSION(0, 1, 1)
+#define SNDRV_COMPRESS_VERSION SNDRV_PROTOCOL_VERSION(0, 1, 2)
 /**
  * struct snd_compressed_buffer: compressed buffer
  * @fragment_size: size of buffer fragment in bytes
@@ -67,8 +67,8 @@ struct snd_compr_params {
 struct snd_compr_tstamp {
        __u32 byte_offset;
        __u32 copied_total;
-       snd_pcm_uframes_t pcm_frames;
-       snd_pcm_uframes_t pcm_io_frames;
+       __u32 pcm_frames;
+       __u32 pcm_io_frames;
        __u32 sampling_rate;
 };
 
index 79383d3aa5dc5f7fe64abdcaf7d511144ca016e5..c3562ca534d46062bdfca6c21d12ff5e8ed0ddaf 100644 (file)
@@ -532,7 +532,7 @@ config CONTEXT_TRACKING_FORCE
          dynticks subsystem by forcing the context tracking on all
          CPUs in the system.
 
-         Say Y only if you're working on the developpement of an
+         Say Y only if you're working on the development of an
          architecture backend for the context tracking.
 
          Say N otherwise, this option brings an overhead that you
@@ -848,7 +848,6 @@ config NUMA_BALANCING
 
 menuconfig CGROUPS
        boolean "Control Group support"
-       depends on EVENTFD
        help
          This option adds support for grouping sets of processes together, for
          use with process control subsystems such as Cpusets, CFS, memory
@@ -915,6 +914,7 @@ config MEMCG
        bool "Memory Resource Controller for Control Groups"
        depends on RESOURCE_COUNTERS
        select MM_OWNER
+       select EVENTFD
        help
          Provides a memory resource controller that manages both anonymous
          memory and page cache. (See Documentation/cgroups/memory.txt)
@@ -1154,7 +1154,6 @@ config UIDGID_STRICT_TYPE_CHECKS
 
 config SCHED_AUTOGROUP
        bool "Automatic process group scheduling"
-       select EVENTFD
        select CGROUPS
        select CGROUP_SCHED
        select FAIR_GROUP_SCHED
index 8b729c278b649c7c016786f6dac9886290ce794f..fb1193bec4affe1666e98fe3e7a98cb06e16b63a 100644 (file)
@@ -41,7 +41,6 @@
 #include <linux/rcupdate.h>
 #include <linux/sched.h>
 #include <linux/backing-dev.h>
-#include <linux/seq_file.h>
 #include <linux/slab.h>
 #include <linux/magic.h>
 #include <linux/spinlock.h>
 #include <linux/pid_namespace.h>
 #include <linux/idr.h>
 #include <linux/vmalloc.h> /* TODO: replace with more sophisticated array */
-#include <linux/eventfd.h>
-#include <linux/poll.h>
 #include <linux/flex_array.h> /* used in cgroup_attach_task */
 #include <linux/kthread.h>
-#include <linux/file.h>
 
 #include <linux/atomic.h>
 
+/*
+ * pidlists linger the following amount before being destroyed.  The goal
+ * is avoiding frequent destruction in the middle of consecutive read calls
+ * Expiring in the middle is a performance problem not a correctness one.
+ * 1 sec should be enough.
+ */
+#define CGROUP_PIDLIST_DESTROY_DELAY   HZ
+
 /*
  * cgroup_mutex is the master lock.  Any modification to cgroup or its
  * hierarchy must be performed while holding it.
@@ -89,6 +93,19 @@ static DEFINE_MUTEX(cgroup_mutex);
 
 static DEFINE_MUTEX(cgroup_root_mutex);
 
+#define cgroup_assert_mutex_or_rcu_locked()                            \
+       rcu_lockdep_assert(rcu_read_lock_held() ||                      \
+                          lockdep_is_held(&cgroup_mutex),              \
+                          "cgroup_mutex or RCU read lock required");
+
+#ifdef CONFIG_LOCKDEP
+#define cgroup_assert_mutex_or_root_locked()                           \
+       WARN_ON_ONCE(debug_locks && (!lockdep_is_held(&cgroup_mutex) && \
+                                    !lockdep_is_held(&cgroup_root_mutex)))
+#else
+#define cgroup_assert_mutex_or_root_locked()   do { } while (0)
+#endif
+
 /*
  * cgroup destruction makes heavy use of work items and there can be a lot
  * of concurrent destructions.  Use a separate workqueue so that cgroup
@@ -97,6 +114,12 @@ static DEFINE_MUTEX(cgroup_root_mutex);
  */
 static struct workqueue_struct *cgroup_destroy_wq;
 
+/*
+ * pidlist destructions need to be flushed on cgroup destruction.  Use a
+ * separate workqueue as flush domain.
+ */
+static struct workqueue_struct *cgroup_pidlist_destroy_wq;
+
 /*
  * Generate an array of cgroup subsystem pointers. At boot time, this is
  * populated with the built in subsystems, and modular subsystems are
@@ -119,49 +142,6 @@ static struct cgroupfs_root cgroup_dummy_root;
 /* dummy_top is a shorthand for the dummy hierarchy's top cgroup */
 static struct cgroup * const cgroup_dummy_top = &cgroup_dummy_root.top_cgroup;
 
-/*
- * cgroupfs file entry, pointed to from leaf dentry->d_fsdata.
- */
-struct cfent {
-       struct list_head                node;
-       struct dentry                   *dentry;
-       struct cftype                   *type;
-       struct cgroup_subsys_state      *css;
-
-       /* file xattrs */
-       struct simple_xattrs            xattrs;
-};
-
-/*
- * cgroup_event represents events which userspace want to receive.
- */
-struct cgroup_event {
-       /*
-        * css which the event belongs to.
-        */
-       struct cgroup_subsys_state *css;
-       /*
-        * Control file which the event associated.
-        */
-       struct cftype *cft;
-       /*
-        * eventfd to signal userspace about the event.
-        */
-       struct eventfd_ctx *eventfd;
-       /*
-        * Each of these stored in a list by the cgroup.
-        */
-       struct list_head list;
-       /*
-        * All fields below needed to unregister event when
-        * userspace closes eventfd.
-        */
-       poll_table pt;
-       wait_queue_head_t *wqh;
-       wait_queue_t wait;
-       struct work_struct remove;
-};
-
 /* The list of hierarchy roots */
 
 static LIST_HEAD(cgroup_roots);
@@ -200,6 +180,7 @@ static int cgroup_destroy_locked(struct cgroup *cgrp);
 static int cgroup_addrm_files(struct cgroup *cgrp, struct cftype cfts[],
                              bool is_add);
 static int cgroup_file_release(struct inode *inode, struct file *file);
+static void cgroup_pidlist_destroy_all(struct cgroup *cgrp);
 
 /**
  * cgroup_css - obtain a cgroup's css for the specified subsystem
@@ -261,17 +242,33 @@ static int notify_on_release(const struct cgroup *cgrp)
        return test_bit(CGRP_NOTIFY_ON_RELEASE, &cgrp->flags);
 }
 
+/**
+ * for_each_css - iterate all css's of a cgroup
+ * @css: the iteration cursor
+ * @ssid: the index of the subsystem, CGROUP_SUBSYS_COUNT after reaching the end
+ * @cgrp: the target cgroup to iterate css's of
+ *
+ * Should be called under cgroup_mutex.
+ */
+#define for_each_css(css, ssid, cgrp)                                  \
+       for ((ssid) = 0; (ssid) < CGROUP_SUBSYS_COUNT; (ssid)++)        \
+               if (!((css) = rcu_dereference_check(                    \
+                               (cgrp)->subsys[(ssid)],                 \
+                               lockdep_is_held(&cgroup_mutex)))) { }   \
+               else
+
 /**
  * for_each_subsys - iterate all loaded cgroup subsystems
  * @ss: the iteration cursor
- * @i: the index of @ss, CGROUP_SUBSYS_COUNT after reaching the end
+ * @ssid: the index of @ss, CGROUP_SUBSYS_COUNT after reaching the end
  *
- * Should be called under cgroup_mutex.
+ * Iterates through all loaded subsystems.  Should be called under
+ * cgroup_mutex or cgroup_root_mutex.
  */
-#define for_each_subsys(ss, i)                                         \
-       for ((i) = 0; (i) < CGROUP_SUBSYS_COUNT; (i)++)                 \
-               if (({ lockdep_assert_held(&cgroup_mutex);              \
-                      !((ss) = cgroup_subsys[i]); })) { }              \
+#define for_each_subsys(ss, ssid)                                      \
+       for (({ cgroup_assert_mutex_or_root_locked(); (ssid) = 0; });   \
+            (ssid) < CGROUP_SUBSYS_COUNT; (ssid)++)                    \
+               if (!((ss) = cgroup_subsys[(ssid)])) { }                \
                else
 
 /**
@@ -286,10 +283,6 @@ static int notify_on_release(const struct cgroup *cgrp)
        for ((i) = 0; (i) < CGROUP_BUILTIN_SUBSYS_COUNT &&              \
             (((ss) = cgroup_subsys[i]) || true); (i)++)
 
-/* iterate each subsystem attached to a hierarchy */
-#define for_each_root_subsys(root, ss)                                 \
-       list_for_each_entry((ss), &(root)->subsys_list, sibling)
-
 /* iterate across the active hierarchies */
 #define for_each_active_root(root)                                     \
        list_for_each_entry((root), &cgroup_roots, root_list)
@@ -863,11 +856,7 @@ static void cgroup_free_fn(struct work_struct *work)
         */
        deactivate_super(cgrp->root->sb);
 
-       /*
-        * if we're getting rid of the cgroup, refcount should ensure
-        * that there are no pidlists left.
-        */
-       BUG_ON(!list_empty(&cgrp->pidlists));
+       cgroup_pidlist_destroy_all(cgrp);
 
        simple_xattrs_free(&cgrp->xattrs);
 
@@ -1040,7 +1029,6 @@ static int rebind_subsystems(struct cgroupfs_root *root,
                                           cgroup_css(cgroup_dummy_top, ss));
                        cgroup_css(cgrp, ss)->cgroup = cgrp;
 
-                       list_move(&ss->sibling, &root->subsys_list);
                        ss->root = root;
                        if (ss->bind)
                                ss->bind(cgroup_css(cgrp, ss));
@@ -1059,7 +1047,6 @@ static int rebind_subsystems(struct cgroupfs_root *root,
                        RCU_INIT_POINTER(cgrp->subsys[i], NULL);
 
                        cgroup_subsys[i]->root = &cgroup_dummy_root;
-                       list_move(&ss->sibling, &cgroup_dummy_root.subsys_list);
 
                        /* subsystem is now free - drop reference on module */
                        module_put(ss->module);
@@ -1086,10 +1073,12 @@ static int cgroup_show_options(struct seq_file *seq, struct dentry *dentry)
 {
        struct cgroupfs_root *root = dentry->d_sb->s_fs_info;
        struct cgroup_subsys *ss;
+       int ssid;
 
        mutex_lock(&cgroup_root_mutex);
-       for_each_root_subsys(root, ss)
-               seq_printf(seq, ",%s", ss->name);
+       for_each_subsys(ss, ssid)
+               if (root->subsys_mask & (1 << ssid))
+                       seq_printf(seq, ",%s", ss->name);
        if (root->flags & CGRP_ROOT_SANE_BEHAVIOR)
                seq_puts(seq, ",sane_behavior");
        if (root->flags & CGRP_ROOT_NOPREFIX)
@@ -1352,8 +1341,6 @@ static void init_cgroup_housekeeping(struct cgroup *cgrp)
        INIT_LIST_HEAD(&cgrp->pidlists);
        mutex_init(&cgrp->pidlist_mutex);
        cgrp->dummy_css.cgroup = cgrp;
-       INIT_LIST_HEAD(&cgrp->event_list);
-       spin_lock_init(&cgrp->event_list_lock);
        simple_xattrs_init(&cgrp->xattrs);
 }
 
@@ -1361,7 +1348,6 @@ static void init_cgroup_root(struct cgroupfs_root *root)
 {
        struct cgroup *cgrp = &root->top_cgroup;
 
-       INIT_LIST_HEAD(&root->subsys_list);
        INIT_LIST_HEAD(&root->root_list);
        root->number_of_cgroups = 1;
        cgrp->root = root;
@@ -1966,8 +1952,8 @@ static int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk,
                              bool threadgroup)
 {
        int retval, i, group_size;
-       struct cgroup_subsys *ss, *failed_ss = NULL;
        struct cgroupfs_root *root = cgrp->root;
+       struct cgroup_subsys_state *css, *failed_css = NULL;
        /* threadgroup list cursor and array */
        struct task_struct *leader = tsk;
        struct task_and_cgroup *tc;
@@ -2040,13 +2026,11 @@ static int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk,
        /*
         * step 1: check that we can legitimately attach to the cgroup.
         */
-       for_each_root_subsys(root, ss) {
-               struct cgroup_subsys_state *css = cgroup_css(cgrp, ss);
-
-               if (ss->can_attach) {
-                       retval = ss->can_attach(css, &tset);
+       for_each_css(css, i, cgrp) {
+               if (css->ss->can_attach) {
+                       retval = css->ss->can_attach(css, &tset);
                        if (retval) {
-                               failed_ss = ss;
+                               failed_css = css;
                                goto out_cancel_attach;
                        }
                }
@@ -2082,12 +2066,9 @@ static int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk,
        /*
         * step 4: do subsystem attach callbacks.
         */
-       for_each_root_subsys(root, ss) {
-               struct cgroup_subsys_state *css = cgroup_css(cgrp, ss);
-
-               if (ss->attach)
-                       ss->attach(css, &tset);
-       }
+       for_each_css(css, i, cgrp)
+               if (css->ss->attach)
+                       css->ss->attach(css, &tset);
 
        /*
         * step 5: success! and cleanup
@@ -2104,13 +2085,11 @@ out_put_css_set_refs:
        }
 out_cancel_attach:
        if (retval) {
-               for_each_root_subsys(root, ss) {
-                       struct cgroup_subsys_state *css = cgroup_css(cgrp, ss);
-
-                       if (ss == failed_ss)
+               for_each_css(css, i, cgrp) {
+                       if (css == failed_css)
                                break;
-                       if (ss->cancel_attach)
-                               ss->cancel_attach(css, &tset);
+                       if (css->ss->cancel_attach)
+                               css->ss->cancel_attach(css, &tset);
                }
        }
 out_free_group_list:
@@ -2250,10 +2229,9 @@ static int cgroup_release_agent_write(struct cgroup_subsys_state *css,
        return 0;
 }
 
-static int cgroup_release_agent_show(struct cgroup_subsys_state *css,
-                                    struct cftype *cft, struct seq_file *seq)
+static int cgroup_release_agent_show(struct seq_file *seq, void *v)
 {
-       struct cgroup *cgrp = css->cgroup;
+       struct cgroup *cgrp = seq_css(seq)->cgroup;
 
        if (!cgroup_lock_live_group(cgrp))
                return -ENODEV;
@@ -2263,174 +2241,129 @@ static int cgroup_release_agent_show(struct cgroup_subsys_state *css,
        return 0;
 }
 
-static int cgroup_sane_behavior_show(struct cgroup_subsys_state *css,
-                                    struct cftype *cft, struct seq_file *seq)
+static int cgroup_sane_behavior_show(struct seq_file *seq, void *v)
 {
-       seq_printf(seq, "%d\n", cgroup_sane_behavior(css->cgroup));
+       struct cgroup *cgrp = seq_css(seq)->cgroup;
+
+       seq_printf(seq, "%d\n", cgroup_sane_behavior(cgrp));
        return 0;
 }
 
 /* A buffer size big enough for numbers or short strings */
 #define CGROUP_LOCAL_BUFFER_SIZE 64
 
-static ssize_t cgroup_write_X64(struct cgroup_subsys_state *css,
-                               struct cftype *cft, struct file *file,
-                               const char __user *userbuf, size_t nbytes,
-                               loff_t *unused_ppos)
+static ssize_t cgroup_file_write(struct file *file, const char __user *userbuf,
+                                size_t nbytes, loff_t *ppos)
 {
-       char buffer[CGROUP_LOCAL_BUFFER_SIZE];
-       int retval = 0;
-       char *end;
+       struct cfent *cfe = __d_cfe(file->f_dentry);
+       struct cftype *cft = __d_cft(file->f_dentry);
+       struct cgroup_subsys_state *css = cfe->css;
+       size_t max_bytes = cft->max_write_len ?: CGROUP_LOCAL_BUFFER_SIZE - 1;
+       char *buf;
+       int ret;
 
-       if (!nbytes)
-               return -EINVAL;
-       if (nbytes >= sizeof(buffer))
+       if (nbytes >= max_bytes)
                return -E2BIG;
-       if (copy_from_user(buffer, userbuf, nbytes))
-               return -EFAULT;
 
-       buffer[nbytes] = 0;     /* nul-terminate */
-       if (cft->write_u64) {
-               u64 val = simple_strtoull(strstrip(buffer), &end, 0);
-               if (*end)
-                       return -EINVAL;
-               retval = cft->write_u64(css, cft, val);
+       buf = kmalloc(nbytes + 1, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       if (copy_from_user(buf, userbuf, nbytes)) {
+               ret = -EFAULT;
+               goto out_free;
+       }
+
+       buf[nbytes] = '\0';
+
+       if (cft->write_string) {
+               ret = cft->write_string(css, cft, strstrip(buf));
+       } else if (cft->write_u64) {
+               unsigned long long v;
+               ret = kstrtoull(buf, 0, &v);
+               if (!ret)
+                       ret = cft->write_u64(css, cft, v);
+       } else if (cft->write_s64) {
+               long long v;
+               ret = kstrtoll(buf, 0, &v);
+               if (!ret)
+                       ret = cft->write_s64(css, cft, v);
+       } else if (cft->trigger) {
+               ret = cft->trigger(css, (unsigned int)cft->private);
        } else {
-               s64 val = simple_strtoll(strstrip(buffer), &end, 0);
-               if (*end)
-                       return -EINVAL;
-               retval = cft->write_s64(css, cft, val);
+               ret = -EINVAL;
        }
-       if (!retval)
-               retval = nbytes;
-       return retval;
+out_free:
+       kfree(buf);
+       return ret ?: nbytes;
 }
 
-static ssize_t cgroup_write_string(struct cgroup_subsys_state *css,
-                                  struct cftype *cft, struct file *file,
-                                  const char __user *userbuf, size_t nbytes,
-                                  loff_t *unused_ppos)
+/*
+ * seqfile ops/methods for returning structured data. Currently just
+ * supports string->u64 maps, but can be extended in future.
+ */
+
+static void *cgroup_seqfile_start(struct seq_file *seq, loff_t *ppos)
 {
-       char local_buffer[CGROUP_LOCAL_BUFFER_SIZE];
-       int retval = 0;
-       size_t max_bytes = cft->max_write_len;
-       char *buffer = local_buffer;
+       struct cftype *cft = seq_cft(seq);
 
-       if (!max_bytes)
-               max_bytes = sizeof(local_buffer) - 1;
-       if (nbytes >= max_bytes)
-               return -E2BIG;
-       /* Allocate a dynamic buffer if we need one */
-       if (nbytes >= sizeof(local_buffer)) {
-               buffer = kmalloc(nbytes + 1, GFP_KERNEL);
-               if (buffer == NULL)
-                       return -ENOMEM;
-       }
-       if (nbytes && copy_from_user(buffer, userbuf, nbytes)) {
-               retval = -EFAULT;
-               goto out;
+       if (cft->seq_start) {
+               return cft->seq_start(seq, ppos);
+       } else {
+               /*
+                * The same behavior and code as single_open().  Returns
+                * !NULL if pos is at the beginning; otherwise, NULL.
+                */
+               return NULL + !*ppos;
        }
-
-       buffer[nbytes] = 0;     /* nul-terminate */
-       retval = cft->write_string(css, cft, strstrip(buffer));
-       if (!retval)
-               retval = nbytes;
-out:
-       if (buffer != local_buffer)
-               kfree(buffer);
-       return retval;
 }
 
-static ssize_t cgroup_file_write(struct file *file, const char __user *buf,
-                                size_t nbytes, loff_t *ppos)
+static void *cgroup_seqfile_next(struct seq_file *seq, void *v, loff_t *ppos)
 {
-       struct cfent *cfe = __d_cfe(file->f_dentry);
-       struct cftype *cft = __d_cft(file->f_dentry);
-       struct cgroup_subsys_state *css = cfe->css;
+       struct cftype *cft = seq_cft(seq);
 
-       if (cft->write)
-               return cft->write(css, cft, file, buf, nbytes, ppos);
-       if (cft->write_u64 || cft->write_s64)
-               return cgroup_write_X64(css, cft, file, buf, nbytes, ppos);
-       if (cft->write_string)
-               return cgroup_write_string(css, cft, file, buf, nbytes, ppos);
-       if (cft->trigger) {
-               int ret = cft->trigger(css, (unsigned int)cft->private);
-               return ret ? ret : nbytes;
+       if (cft->seq_next) {
+               return cft->seq_next(seq, v, ppos);
+       } else {
+               /*
+                * The same behavior and code as single_open(), always
+                * terminate after the initial read.
+                */
+               ++*ppos;
+               return NULL;
        }
-       return -EINVAL;
 }
 
-static ssize_t cgroup_read_u64(struct cgroup_subsys_state *css,
-                              struct cftype *cft, struct file *file,
-                              char __user *buf, size_t nbytes, loff_t *ppos)
+static void cgroup_seqfile_stop(struct seq_file *seq, void *v)
 {
-       char tmp[CGROUP_LOCAL_BUFFER_SIZE];
-       u64 val = cft->read_u64(css, cft);
-       int len = sprintf(tmp, "%llu\n", (unsigned long long) val);
+       struct cftype *cft = seq_cft(seq);
 
-       return simple_read_from_buffer(buf, nbytes, ppos, tmp, len);
+       if (cft->seq_stop)
+               cft->seq_stop(seq, v);
 }
 
-static ssize_t cgroup_read_s64(struct cgroup_subsys_state *css,
-                              struct cftype *cft, struct file *file,
-                              char __user *buf, size_t nbytes, loff_t *ppos)
+static int cgroup_seqfile_show(struct seq_file *m, void *arg)
 {
-       char tmp[CGROUP_LOCAL_BUFFER_SIZE];
-       s64 val = cft->read_s64(css, cft);
-       int len = sprintf(tmp, "%lld\n", (long long) val);
+       struct cftype *cft = seq_cft(m);
+       struct cgroup_subsys_state *css = seq_css(m);
 
-       return simple_read_from_buffer(buf, nbytes, ppos, tmp, len);
-}
-
-static ssize_t cgroup_file_read(struct file *file, char __user *buf,
-                               size_t nbytes, loff_t *ppos)
-{
-       struct cfent *cfe = __d_cfe(file->f_dentry);
-       struct cftype *cft = __d_cft(file->f_dentry);
-       struct cgroup_subsys_state *css = cfe->css;
+       if (cft->seq_show)
+               return cft->seq_show(m, arg);
 
-       if (cft->read)
-               return cft->read(css, cft, file, buf, nbytes, ppos);
        if (cft->read_u64)
-               return cgroup_read_u64(css, cft, file, buf, nbytes, ppos);
-       if (cft->read_s64)
-               return cgroup_read_s64(css, cft, file, buf, nbytes, ppos);
-       return -EINVAL;
-}
-
-/*
- * seqfile ops/methods for returning structured data. Currently just
- * supports string->u64 maps, but can be extended in future.
- */
-
-static int cgroup_map_add(struct cgroup_map_cb *cb, const char *key, u64 value)
-{
-       struct seq_file *sf = cb->state;
-       return seq_printf(sf, "%s %llu\n", key, (unsigned long long)value);
-}
-
-static int cgroup_seqfile_show(struct seq_file *m, void *arg)
-{
-       struct cfent *cfe = m->private;
-       struct cftype *cft = cfe->type;
-       struct cgroup_subsys_state *css = cfe->css;
-
-       if (cft->read_map) {
-               struct cgroup_map_cb cb = {
-                       .fill = cgroup_map_add,
-                       .state = m,
-               };
-               return cft->read_map(css, cft, &cb);
-       }
-       return cft->read_seq_string(css, cft, m);
+               seq_printf(m, "%llu\n", cft->read_u64(css, cft));
+       else if (cft->read_s64)
+               seq_printf(m, "%lld\n", cft->read_s64(css, cft));
+       else
+               return -EINVAL;
+       return 0;
 }
 
-static const struct file_operations cgroup_seqfile_operations = {
-       .read = seq_read,
-       .write = cgroup_file_write,
-       .llseek = seq_lseek,
-       .release = cgroup_file_release,
+static struct seq_operations cgroup_seq_operations = {
+       .start          = cgroup_seqfile_start,
+       .next           = cgroup_seqfile_next,
+       .stop           = cgroup_seqfile_stop,
+       .show           = cgroup_seqfile_show,
 };
 
 static int cgroup_file_open(struct inode *inode, struct file *file)
@@ -2439,6 +2372,7 @@ static int cgroup_file_open(struct inode *inode, struct file *file)
        struct cftype *cft = __d_cft(file->f_dentry);
        struct cgroup *cgrp = __d_cgrp(cfe->dentry->d_parent);
        struct cgroup_subsys_state *css;
+       struct cgroup_open_file *of;
        int err;
 
        err = generic_file_open(inode, file);
@@ -2468,32 +2402,26 @@ static int cgroup_file_open(struct inode *inode, struct file *file)
        WARN_ON_ONCE(cfe->css && cfe->css != css);
        cfe->css = css;
 
-       if (cft->read_map || cft->read_seq_string) {
-               file->f_op = &cgroup_seqfile_operations;
-               err = single_open(file, cgroup_seqfile_show, cfe);
-       } else if (cft->open) {
-               err = cft->open(inode, file);
+       of = __seq_open_private(file, &cgroup_seq_operations,
+                               sizeof(struct cgroup_open_file));
+       if (of) {
+               of->cfe = cfe;
+               return 0;
        }
 
-       if (css->ss && err)
+       if (css->ss)
                css_put(css);
-       return err;
+       return -ENOMEM;
 }
 
 static int cgroup_file_release(struct inode *inode, struct file *file)
 {
        struct cfent *cfe = __d_cfe(file->f_dentry);
-       struct cftype *cft = __d_cft(file->f_dentry);
        struct cgroup_subsys_state *css = cfe->css;
-       int ret = 0;
 
-       if (cft->release)
-               ret = cft->release(inode, file);
        if (css->ss)
                css_put(css);
-       if (file->f_op == &cgroup_seqfile_operations)
-               single_release(inode, file);
-       return ret;
+       return seq_release_private(inode, file);
 }
 
 /*
@@ -2604,7 +2532,7 @@ static ssize_t cgroup_listxattr(struct dentry *dentry, char *buf, size_t size)
 }
 
 static const struct file_operations cgroup_file_operations = {
-       .read = cgroup_file_read,
+       .read = seq_read,
        .write = cgroup_file_write,
        .llseek = generic_file_llseek,
        .open = cgroup_file_open,
@@ -2629,16 +2557,6 @@ static const struct inode_operations cgroup_dir_inode_operations = {
        .removexattr = cgroup_removexattr,
 };
 
-/*
- * Check if a file is a control file
- */
-static inline struct cftype *__file_cft(struct file *file)
-{
-       if (file_inode(file)->i_fop != &cgroup_file_operations)
-               return ERR_PTR(-EINVAL);
-       return __d_cft(file->f_dentry);
-}
-
 static int cgroup_create_file(struct dentry *dentry, umode_t mode,
                                struct super_block *sb)
 {
@@ -2696,12 +2614,11 @@ static umode_t cgroup_file_mode(const struct cftype *cft)
        if (cft->mode)
                return cft->mode;
 
-       if (cft->read || cft->read_u64 || cft->read_s64 ||
-           cft->read_map || cft->read_seq_string)
+       if (cft->read_u64 || cft->read_s64 || cft->seq_show)
                mode |= S_IRUGO;
 
-       if (cft->write || cft->write_u64 || cft->write_s64 ||
-           cft->write_string || cft->trigger)
+       if (cft->write_u64 || cft->write_s64 || cft->write_string ||
+           cft->trigger)
                mode |= S_IWUSR;
 
        return mode;
@@ -2997,9 +2914,9 @@ static void cgroup_enable_task_cg_lists(void)
  * @parent_css: css whose children to walk
  *
  * This function returns the next child of @parent_css and should be called
- * under RCU read lock.  The only requirement is that @parent_css and
- * @pos_css are accessible.  The next sibling is guaranteed to be returned
- * regardless of their states.
+ * under either cgroup_mutex or RCU read lock.  The only requirement is
+ * that @parent_css and @pos_css are accessible.  The next sibling is
+ * guaranteed to be returned regardless of their states.
  */
 struct cgroup_subsys_state *
 css_next_child(struct cgroup_subsys_state *pos_css,
@@ -3009,7 +2926,7 @@ css_next_child(struct cgroup_subsys_state *pos_css,
        struct cgroup *cgrp = parent_css->cgroup;
        struct cgroup *next;
 
-       WARN_ON_ONCE(!rcu_read_lock_held());
+       cgroup_assert_mutex_or_rcu_locked();
 
        /*
         * @pos could already have been removed.  Once a cgroup is removed,
@@ -3056,10 +2973,10 @@ EXPORT_SYMBOL_GPL(css_next_child);
  * to visit for pre-order traversal of @root's descendants.  @root is
  * included in the iteration and the first node to be visited.
  *
- * While this function requires RCU read locking, it doesn't require the
- * whole traversal to be contained in a single RCU critical section.  This
- * function will return the correct next descendant as long as both @pos
- * and @root are accessible and @pos is a descendant of @root.
+ * While this function requires cgroup_mutex or RCU read locking, it
+ * doesn't require the whole traversal to be contained in a single critical
+ * section.  This function will return the correct next descendant as long
+ * as both @pos and @root are accessible and @pos is a descendant of @root.
  */
 struct cgroup_subsys_state *
 css_next_descendant_pre(struct cgroup_subsys_state *pos,
@@ -3067,7 +2984,7 @@ css_next_descendant_pre(struct cgroup_subsys_state *pos,
 {
        struct cgroup_subsys_state *next;
 
-       WARN_ON_ONCE(!rcu_read_lock_held());
+       cgroup_assert_mutex_or_rcu_locked();
 
        /* if first iteration, visit @root */
        if (!pos)
@@ -3098,17 +3015,17 @@ EXPORT_SYMBOL_GPL(css_next_descendant_pre);
  * is returned.  This can be used during pre-order traversal to skip
  * subtree of @pos.
  *
- * While this function requires RCU read locking, it doesn't require the
- * whole traversal to be contained in a single RCU critical section.  This
- * function will return the correct rightmost descendant as long as @pos is
- * accessible.
+ * While this function requires cgroup_mutex or RCU read locking, it
+ * doesn't require the whole traversal to be contained in a single critical
+ * section.  This function will return the correct rightmost descendant as
+ * long as @pos is accessible.
  */
 struct cgroup_subsys_state *
 css_rightmost_descendant(struct cgroup_subsys_state *pos)
 {
        struct cgroup_subsys_state *last, *tmp;
 
-       WARN_ON_ONCE(!rcu_read_lock_held());
+       cgroup_assert_mutex_or_rcu_locked();
 
        do {
                last = pos;
@@ -3144,10 +3061,11 @@ css_leftmost_descendant(struct cgroup_subsys_state *pos)
  * to visit for post-order traversal of @root's descendants.  @root is
  * included in the iteration and the last node to be visited.
  *
- * While this function requires RCU read locking, it doesn't require the
- * whole traversal to be contained in a single RCU critical section.  This
- * function will return the correct next descendant as long as both @pos
- * and @cgroup are accessible and @pos is a descendant of @cgroup.
+ * While this function requires cgroup_mutex or RCU read locking, it
+ * doesn't require the whole traversal to be contained in a single critical
+ * section.  This function will return the correct next descendant as long
+ * as both @pos and @cgroup are accessible and @pos is a descendant of
+ * @cgroup.
  */
 struct cgroup_subsys_state *
 css_next_descendant_post(struct cgroup_subsys_state *pos,
@@ -3155,7 +3073,7 @@ css_next_descendant_post(struct cgroup_subsys_state *pos,
 {
        struct cgroup_subsys_state *next;
 
-       WARN_ON_ONCE(!rcu_read_lock_held());
+       cgroup_assert_mutex_or_rcu_locked();
 
        /* if first iteration, visit leftmost descendant which may be @root */
        if (!pos)
@@ -3494,14 +3412,12 @@ struct cgroup_pidlist {
        pid_t *list;
        /* how many elements the above list has */
        int length;
-       /* how many files are using the current array */
-       int use_count;
        /* each of these stored in a list by its cgroup */
        struct list_head links;
        /* pointer to the cgroup we belong to, for list removal purposes */
        struct cgroup *owner;
-       /* protects the other fields */
-       struct rw_semaphore rwsem;
+       /* for delayed destruction */
+       struct delayed_work destroy_dwork;
 };
 
 /*
@@ -3517,6 +3433,7 @@ static void *pidlist_allocate(int count)
        else
                return kmalloc(count * sizeof(pid_t), GFP_KERNEL);
 }
+
 static void pidlist_free(void *p)
 {
        if (is_vmalloc_addr(p))
@@ -3525,6 +3442,47 @@ static void pidlist_free(void *p)
                kfree(p);
 }
 
+/*
+ * Used to destroy all pidlists lingering waiting for destroy timer.  None
+ * should be left afterwards.
+ */
+static void cgroup_pidlist_destroy_all(struct cgroup *cgrp)
+{
+       struct cgroup_pidlist *l, *tmp_l;
+
+       mutex_lock(&cgrp->pidlist_mutex);
+       list_for_each_entry_safe(l, tmp_l, &cgrp->pidlists, links)
+               mod_delayed_work(cgroup_pidlist_destroy_wq, &l->destroy_dwork, 0);
+       mutex_unlock(&cgrp->pidlist_mutex);
+
+       flush_workqueue(cgroup_pidlist_destroy_wq);
+       BUG_ON(!list_empty(&cgrp->pidlists));
+}
+
+static void cgroup_pidlist_destroy_work_fn(struct work_struct *work)
+{
+       struct delayed_work *dwork = to_delayed_work(work);
+       struct cgroup_pidlist *l = container_of(dwork, struct cgroup_pidlist,
+                                               destroy_dwork);
+       struct cgroup_pidlist *tofree = NULL;
+
+       mutex_lock(&l->owner->pidlist_mutex);
+
+       /*
+        * Destroy iff we didn't get queued again.  The state won't change
+        * as destroy_dwork can only be queued while locked.
+        */
+       if (!delayed_work_pending(dwork)) {
+               list_del(&l->links);
+               pidlist_free(l->list);
+               put_pid_ns(l->key.ns);
+               tofree = l;
+       }
+
+       mutex_unlock(&l->owner->pidlist_mutex);
+       kfree(tofree);
+}
+
 /*
  * pidlist_uniq - given a kmalloc()ed list, strip out all duplicate entries
  * Returns the number of unique elements.
@@ -3555,52 +3513,92 @@ after:
        return dest;
 }
 
+/*
+ * The two pid files - task and cgroup.procs - guaranteed that the result
+ * is sorted, which forced this whole pidlist fiasco.  As pid order is
+ * different per namespace, each namespace needs differently sorted list,
+ * making it impossible to use, for example, single rbtree of member tasks
+ * sorted by task pointer.  As pidlists can be fairly large, allocating one
+ * per open file is dangerous, so cgroup had to implement shared pool of
+ * pidlists keyed by cgroup and namespace.
+ *
+ * All this extra complexity was caused by the original implementation
+ * committing to an entirely unnecessary property.  In the long term, we
+ * want to do away with it.  Explicitly scramble sort order if
+ * sane_behavior so that no such expectation exists in the new interface.
+ *
+ * Scrambling is done by swapping every two consecutive bits, which is
+ * non-identity one-to-one mapping which disturbs sort order sufficiently.
+ */
+static pid_t pid_fry(pid_t pid)
+{
+       unsigned a = pid & 0x55555555;
+       unsigned b = pid & 0xAAAAAAAA;
+
+       return (a << 1) | (b >> 1);
+}
+
+static pid_t cgroup_pid_fry(struct cgroup *cgrp, pid_t pid)
+{
+       if (cgroup_sane_behavior(cgrp))
+               return pid_fry(pid);
+       else
+               return pid;
+}
+
 static int cmppid(const void *a, const void *b)
 {
        return *(pid_t *)a - *(pid_t *)b;
 }
 
+static int fried_cmppid(const void *a, const void *b)
+{
+       return pid_fry(*(pid_t *)a) - pid_fry(*(pid_t *)b);
+}
+
+static struct cgroup_pidlist *cgroup_pidlist_find(struct cgroup *cgrp,
+                                                 enum cgroup_filetype type)
+{
+       struct cgroup_pidlist *l;
+       /* don't need task_nsproxy() if we're looking at ourself */
+       struct pid_namespace *ns = task_active_pid_ns(current);
+
+       lockdep_assert_held(&cgrp->pidlist_mutex);
+
+       list_for_each_entry(l, &cgrp->pidlists, links)
+               if (l->key.type == type && l->key.ns == ns)
+                       return l;
+       return NULL;
+}
+
 /*
  * find the appropriate pidlist for our purpose (given procs vs tasks)
  * returns with the lock on that pidlist already held, and takes care
  * of the use count, or returns NULL with no locks held if we're out of
  * memory.
  */
-static struct cgroup_pidlist *cgroup_pidlist_find(struct cgroup *cgrp,
-                                                 enum cgroup_filetype type)
+static struct cgroup_pidlist *cgroup_pidlist_find_create(struct cgroup *cgrp,
+                                               enum cgroup_filetype type)
 {
        struct cgroup_pidlist *l;
-       /* don't need task_nsproxy() if we're looking at ourself */
-       struct pid_namespace *ns = task_active_pid_ns(current);
 
-       /*
-        * We can't drop the pidlist_mutex before taking the l->rwsem in case
-        * the last ref-holder is trying to remove l from the list at the same
-        * time. Holding the pidlist_mutex precludes somebody taking whichever
-        * list we find out from under us - compare release_pid_array().
-        */
-       mutex_lock(&cgrp->pidlist_mutex);
-       list_for_each_entry(l, &cgrp->pidlists, links) {
-               if (l->key.type == type && l->key.ns == ns) {
-                       /* make sure l doesn't vanish out from under us */
-                       down_write(&l->rwsem);
-                       mutex_unlock(&cgrp->pidlist_mutex);
-                       return l;
-               }
-       }
+       lockdep_assert_held(&cgrp->pidlist_mutex);
+
+       l = cgroup_pidlist_find(cgrp, type);
+       if (l)
+               return l;
+
        /* entry not found; create a new one */
        l = kzalloc(sizeof(struct cgroup_pidlist), GFP_KERNEL);
-       if (!l) {
-               mutex_unlock(&cgrp->pidlist_mutex);
+       if (!l)
                return l;
-       }
-       init_rwsem(&l->rwsem);
-       down_write(&l->rwsem);
+
+       INIT_DELAYED_WORK(&l->destroy_dwork, cgroup_pidlist_destroy_work_fn);
        l->key.type = type;
-       l->key.ns = get_pid_ns(ns);
+       /* don't need task_nsproxy() if we're looking at ourself */
+       l->key.ns = get_pid_ns(task_active_pid_ns(current));
        l->owner = cgrp;
        list_add(&l->links, &cgrp->pidlists);
-       mutex_unlock(&cgrp->pidlist_mutex);
        return l;
 }
 
@@ -3617,6 +3615,8 @@ static int pidlist_array_load(struct cgroup *cgrp, enum cgroup_filetype type,
        struct task_struct *tsk;
        struct cgroup_pidlist *l;
 
+       lockdep_assert_held(&cgrp->pidlist_mutex);
+
        /*
         * If cgroup gets more users after we read count, we won't have
         * enough space - tough.  This race is indistinguishable to the
@@ -3643,20 +3643,24 @@ static int pidlist_array_load(struct cgroup *cgrp, enum cgroup_filetype type,
        css_task_iter_end(&it);
        length = n;
        /* now sort & (if procs) strip out duplicates */
-       sort(array, length, sizeof(pid_t), cmppid, NULL);
+       if (cgroup_sane_behavior(cgrp))
+               sort(array, length, sizeof(pid_t), fried_cmppid, NULL);
+       else
+               sort(array, length, sizeof(pid_t), cmppid, NULL);
        if (type == CGROUP_FILE_PROCS)
                length = pidlist_uniq(array, length);
-       l = cgroup_pidlist_find(cgrp, type);
+
+       l = cgroup_pidlist_find_create(cgrp, type);
        if (!l) {
+               mutex_unlock(&cgrp->pidlist_mutex);
                pidlist_free(array);
                return -ENOMEM;
        }
-       /* store array, freeing old if necessary - lock already held */
+
+       /* store array, freeing old if necessary */
        pidlist_free(l->list);
        l->list = array;
        l->length = length;
-       l->use_count++;
-       up_write(&l->rwsem);
        *lp = l;
        return 0;
 }
@@ -3730,20 +3734,45 @@ static void *cgroup_pidlist_start(struct seq_file *s, loff_t *pos)
         * after a seek to the start). Use a binary-search to find the
         * next pid to display, if any
         */
-       struct cgroup_pidlist *l = s->private;
+       struct cgroup_open_file *of = s->private;
+       struct cgroup *cgrp = seq_css(s)->cgroup;
+       struct cgroup_pidlist *l;
+       enum cgroup_filetype type = seq_cft(s)->private;
        int index = 0, pid = *pos;
-       int *iter;
+       int *iter, ret;
+
+       mutex_lock(&cgrp->pidlist_mutex);
+
+       /*
+        * !NULL @of->priv indicates that this isn't the first start()
+        * after open.  If the matching pidlist is around, we can use that.
+        * Look for it.  Note that @of->priv can't be used directly.  It
+        * could already have been destroyed.
+        */
+       if (of->priv)
+               of->priv = cgroup_pidlist_find(cgrp, type);
+
+       /*
+        * Either this is the first start() after open or the matching
+        * pidlist has been destroyed inbetween.  Create a new one.
+        */
+       if (!of->priv) {
+               ret = pidlist_array_load(cgrp, type,
+                                        (struct cgroup_pidlist **)&of->priv);
+               if (ret)
+                       return ERR_PTR(ret);
+       }
+       l = of->priv;
 
-       down_read(&l->rwsem);
        if (pid) {
                int end = l->length;
 
                while (index < end) {
                        int mid = (index + end) / 2;
-                       if (l->list[mid] == pid) {
+                       if (cgroup_pid_fry(cgrp, l->list[mid]) == pid) {
                                index = mid;
                                break;
-                       } else if (l->list[mid] <= pid)
+                       } else if (cgroup_pid_fry(cgrp, l->list[mid]) <= pid)
                                index = mid + 1;
                        else
                                end = mid;
@@ -3754,19 +3783,25 @@ static void *cgroup_pidlist_start(struct seq_file *s, loff_t *pos)
                return NULL;
        /* Update the abstract position to be the actual pid that we found */
        iter = l->list + index;
-       *pos = *iter;
+       *pos = cgroup_pid_fry(cgrp, *iter);
        return iter;
 }
 
 static void cgroup_pidlist_stop(struct seq_file *s, void *v)
 {
-       struct cgroup_pidlist *l = s->private;
-       up_read(&l->rwsem);
+       struct cgroup_open_file *of = s->private;
+       struct cgroup_pidlist *l = of->priv;
+
+       if (l)
+               mod_delayed_work(cgroup_pidlist_destroy_wq, &l->destroy_dwork,
+                                CGROUP_PIDLIST_DESTROY_DELAY);
+       mutex_unlock(&seq_css(s)->cgroup->pidlist_mutex);
 }
 
 static void *cgroup_pidlist_next(struct seq_file *s, void *v, loff_t *pos)
 {
-       struct cgroup_pidlist *l = s->private;
+       struct cgroup_open_file *of = s->private;
+       struct cgroup_pidlist *l = of->priv;
        pid_t *p = v;
        pid_t *end = l->list + l->length;
        /*
@@ -3777,7 +3812,7 @@ static void *cgroup_pidlist_next(struct seq_file *s, void *v, loff_t *pos)
        if (p >= end) {
                return NULL;
        } else {
-               *pos = *p;
+               *pos = cgroup_pid_fry(seq_css(s)->cgroup, *p);
                return p;
        }
 }
@@ -3798,92 +3833,6 @@ static const struct seq_operations cgroup_pidlist_seq_operations = {
        .show = cgroup_pidlist_show,
 };
 
-static void cgroup_release_pid_array(struct cgroup_pidlist *l)
-{
-       /*
-        * the case where we're the last user of this particular pidlist will
-        * have us remove it from the cgroup's list, which entails taking the
-        * mutex. since in pidlist_find the pidlist->lock depends on cgroup->
-        * pidlist_mutex, we have to take pidlist_mutex first.
-        */
-       mutex_lock(&l->owner->pidlist_mutex);
-       down_write(&l->rwsem);
-       BUG_ON(!l->use_count);
-       if (!--l->use_count) {
-               /* we're the last user if refcount is 0; remove and free */
-               list_del(&l->links);
-               mutex_unlock(&l->owner->pidlist_mutex);
-               pidlist_free(l->list);
-               put_pid_ns(l->key.ns);
-               up_write(&l->rwsem);
-               kfree(l);
-               return;
-       }
-       mutex_unlock(&l->owner->pidlist_mutex);
-       up_write(&l->rwsem);
-}
-
-static int cgroup_pidlist_release(struct inode *inode, struct file *file)
-{
-       struct cgroup_pidlist *l;
-       if (!(file->f_mode & FMODE_READ))
-               return 0;
-       /*
-        * the seq_file will only be initialized if the file was opened for
-        * reading; hence we check if it's not null only in that case.
-        */
-       l = ((struct seq_file *)file->private_data)->private;
-       cgroup_release_pid_array(l);
-       return seq_release(inode, file);
-}
-
-static const struct file_operations cgroup_pidlist_operations = {
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .write = cgroup_file_write,
-       .release = cgroup_pidlist_release,
-};
-
-/*
- * The following functions handle opens on a file that displays a pidlist
- * (tasks or procs). Prepare an array of the process/thread IDs of whoever's
- * in the cgroup.
- */
-/* helper function for the two below it */
-static int cgroup_pidlist_open(struct file *file, enum cgroup_filetype type)
-{
-       struct cgroup *cgrp = __d_cgrp(file->f_dentry->d_parent);
-       struct cgroup_pidlist *l;
-       int retval;
-
-       /* Nothing to do for write-only files */
-       if (!(file->f_mode & FMODE_READ))
-               return 0;
-
-       /* have the array populated */
-       retval = pidlist_array_load(cgrp, type, &l);
-       if (retval)
-               return retval;
-       /* configure file information */
-       file->f_op = &cgroup_pidlist_operations;
-
-       retval = seq_open(file, &cgroup_pidlist_seq_operations);
-       if (retval) {
-               cgroup_release_pid_array(l);
-               return retval;
-       }
-       ((struct seq_file *)file->private_data)->private = l;
-       return 0;
-}
-static int cgroup_tasks_open(struct inode *unused, struct file *file)
-{
-       return cgroup_pidlist_open(file, CGROUP_FILE_TASKS);
-}
-static int cgroup_procs_open(struct inode *unused, struct file *file)
-{
-       return cgroup_pidlist_open(file, CGROUP_FILE_PROCS);
-}
-
 static u64 cgroup_read_notify_on_release(struct cgroup_subsys_state *css,
                                         struct cftype *cft)
 {
@@ -3918,202 +3867,6 @@ static void cgroup_dput(struct cgroup *cgrp)
        deactivate_super(sb);
 }
 
-/*
- * Unregister event and free resources.
- *
- * Gets called from workqueue.
- */
-static void cgroup_event_remove(struct work_struct *work)
-{
-       struct cgroup_event *event = container_of(work, struct cgroup_event,
-                       remove);
-       struct cgroup_subsys_state *css = event->css;
-
-       remove_wait_queue(event->wqh, &event->wait);
-
-       event->cft->unregister_event(css, event->cft, event->eventfd);
-
-       /* Notify userspace the event is going away. */
-       eventfd_signal(event->eventfd, 1);
-
-       eventfd_ctx_put(event->eventfd);
-       kfree(event);
-       css_put(css);
-}
-
-/*
- * Gets called on POLLHUP on eventfd when user closes it.
- *
- * Called with wqh->lock held and interrupts disabled.
- */
-static int cgroup_event_wake(wait_queue_t *wait, unsigned mode,
-               int sync, void *key)
-{
-       struct cgroup_event *event = container_of(wait,
-                       struct cgroup_event, wait);
-       struct cgroup *cgrp = event->css->cgroup;
-       unsigned long flags = (unsigned long)key;
-
-       if (flags & POLLHUP) {
-               /*
-                * If the event has been detached at cgroup removal, we
-                * can simply return knowing the other side will cleanup
-                * for us.
-                *
-                * We can't race against event freeing since the other
-                * side will require wqh->lock via remove_wait_queue(),
-                * which we hold.
-                */
-               spin_lock(&cgrp->event_list_lock);
-               if (!list_empty(&event->list)) {
-                       list_del_init(&event->list);
-                       /*
-                        * We are in atomic context, but cgroup_event_remove()
-                        * may sleep, so we have to call it in workqueue.
-                        */
-                       schedule_work(&event->remove);
-               }
-               spin_unlock(&cgrp->event_list_lock);
-       }
-
-       return 0;
-}
-
-static void cgroup_event_ptable_queue_proc(struct file *file,
-               wait_queue_head_t *wqh, poll_table *pt)
-{
-       struct cgroup_event *event = container_of(pt,
-                       struct cgroup_event, pt);
-
-       event->wqh = wqh;
-       add_wait_queue(wqh, &event->wait);
-}
-
-/*
- * Parse input and register new cgroup event handler.
- *
- * Input must be in format '<event_fd> <control_fd> <args>'.
- * Interpretation of args is defined by control file implementation.
- */
-static int cgroup_write_event_control(struct cgroup_subsys_state *dummy_css,
-                                     struct cftype *cft, const char *buffer)
-{
-       struct cgroup *cgrp = dummy_css->cgroup;
-       struct cgroup_event *event;
-       struct cgroup_subsys_state *cfile_css;
-       unsigned int efd, cfd;
-       struct fd efile;
-       struct fd cfile;
-       char *endp;
-       int ret;
-
-       efd = simple_strtoul(buffer, &endp, 10);
-       if (*endp != ' ')
-               return -EINVAL;
-       buffer = endp + 1;
-
-       cfd = simple_strtoul(buffer, &endp, 10);
-       if ((*endp != ' ') && (*endp != '\0'))
-               return -EINVAL;
-       buffer = endp + 1;
-
-       event = kzalloc(sizeof(*event), GFP_KERNEL);
-       if (!event)
-               return -ENOMEM;
-
-       INIT_LIST_HEAD(&event->list);
-       init_poll_funcptr(&event->pt, cgroup_event_ptable_queue_proc);
-       init_waitqueue_func_entry(&event->wait, cgroup_event_wake);
-       INIT_WORK(&event->remove, cgroup_event_remove);
-
-       efile = fdget(efd);
-       if (!efile.file) {
-               ret = -EBADF;
-               goto out_kfree;
-       }
-
-       event->eventfd = eventfd_ctx_fileget(efile.file);
-       if (IS_ERR(event->eventfd)) {
-               ret = PTR_ERR(event->eventfd);
-               goto out_put_efile;
-       }
-
-       cfile = fdget(cfd);
-       if (!cfile.file) {
-               ret = -EBADF;
-               goto out_put_eventfd;
-       }
-
-       /* the process need read permission on control file */
-       /* AV: shouldn't we check that it's been opened for read instead? */
-       ret = inode_permission(file_inode(cfile.file), MAY_READ);
-       if (ret < 0)
-               goto out_put_cfile;
-
-       event->cft = __file_cft(cfile.file);
-       if (IS_ERR(event->cft)) {
-               ret = PTR_ERR(event->cft);
-               goto out_put_cfile;
-       }
-
-       if (!event->cft->ss) {
-               ret = -EBADF;
-               goto out_put_cfile;
-       }
-
-       /*
-        * Determine the css of @cfile, verify it belongs to the same
-        * cgroup as cgroup.event_control, and associate @event with it.
-        * Remaining events are automatically removed on cgroup destruction
-        * but the removal is asynchronous, so take an extra ref.
-        */
-       rcu_read_lock();
-
-       ret = -EINVAL;
-       event->css = cgroup_css(cgrp, event->cft->ss);
-       cfile_css = css_from_dir(cfile.file->f_dentry->d_parent, event->cft->ss);
-       if (event->css && event->css == cfile_css && css_tryget(event->css))
-               ret = 0;
-
-       rcu_read_unlock();
-       if (ret)
-               goto out_put_cfile;
-
-       if (!event->cft->register_event || !event->cft->unregister_event) {
-               ret = -EINVAL;
-               goto out_put_css;
-       }
-
-       ret = event->cft->register_event(event->css, event->cft,
-                       event->eventfd, buffer);
-       if (ret)
-               goto out_put_css;
-
-       efile.file->f_op->poll(efile.file, &event->pt);
-
-       spin_lock(&cgrp->event_list_lock);
-       list_add(&event->list, &cgrp->event_list);
-       spin_unlock(&cgrp->event_list_lock);
-
-       fdput(cfile);
-       fdput(efile);
-
-       return 0;
-
-out_put_css:
-       css_put(event->css);
-out_put_cfile:
-       fdput(cfile);
-out_put_eventfd:
-       eventfd_ctx_put(event->eventfd);
-out_put_efile:
-       fdput(efile);
-out_kfree:
-       kfree(event);
-
-       return ret;
-}
-
 static u64 cgroup_clone_children_read(struct cgroup_subsys_state *css,
                                      struct cftype *cft)
 {
@@ -4133,16 +3886,14 @@ static int cgroup_clone_children_write(struct cgroup_subsys_state *css,
 static struct cftype cgroup_base_files[] = {
        {
                .name = "cgroup.procs",
-               .open = cgroup_procs_open,
+               .seq_start = cgroup_pidlist_start,
+               .seq_next = cgroup_pidlist_next,
+               .seq_stop = cgroup_pidlist_stop,
+               .seq_show = cgroup_pidlist_show,
+               .private = CGROUP_FILE_PROCS,
                .write_u64 = cgroup_procs_write,
-               .release = cgroup_pidlist_release,
                .mode = S_IRUGO | S_IWUSR,
        },
-       {
-               .name = "cgroup.event_control",
-               .write_string = cgroup_write_event_control,
-               .mode = S_IWUGO,
-       },
        {
                .name = "cgroup.clone_children",
                .flags = CFTYPE_INSANE,
@@ -4152,7 +3903,7 @@ static struct cftype cgroup_base_files[] = {
        {
                .name = "cgroup.sane_behavior",
                .flags = CFTYPE_ONLY_ON_ROOT,
-               .read_seq_string = cgroup_sane_behavior_show,
+               .seq_show = cgroup_sane_behavior_show,
        },
 
        /*
@@ -4163,9 +3914,12 @@ static struct cftype cgroup_base_files[] = {
        {
                .name = "tasks",
                .flags = CFTYPE_INSANE,         /* use "procs" instead */
-               .open = cgroup_tasks_open,
+               .seq_start = cgroup_pidlist_start,
+               .seq_next = cgroup_pidlist_next,
+               .seq_stop = cgroup_pidlist_stop,
+               .seq_show = cgroup_pidlist_show,
+               .private = CGROUP_FILE_TASKS,
                .write_u64 = cgroup_tasks_write,
-               .release = cgroup_pidlist_release,
                .mode = S_IRUGO | S_IWUSR,
        },
        {
@@ -4177,7 +3931,7 @@ static struct cftype cgroup_base_files[] = {
        {
                .name = "release_agent",
                .flags = CFTYPE_INSANE | CFTYPE_ONLY_ON_ROOT,
-               .read_seq_string = cgroup_release_agent_show,
+               .seq_show = cgroup_release_agent_show,
                .write_string = cgroup_release_agent_write,
                .max_write_len = PATH_MAX,
        },
@@ -4322,6 +4076,62 @@ static void offline_css(struct cgroup_subsys_state *css)
        RCU_INIT_POINTER(css->cgroup->subsys[ss->subsys_id], css);
 }
 
+/**
+ * create_css - create a cgroup_subsys_state
+ * @cgrp: the cgroup new css will be associated with
+ * @ss: the subsys of new css
+ *
+ * Create a new css associated with @cgrp - @ss pair.  On success, the new
+ * css is online and installed in @cgrp with all interface files created.
+ * Returns 0 on success, -errno on failure.
+ */
+static int create_css(struct cgroup *cgrp, struct cgroup_subsys *ss)
+{
+       struct cgroup *parent = cgrp->parent;
+       struct cgroup_subsys_state *css;
+       int err;
+
+       lockdep_assert_held(&cgrp->dentry->d_inode->i_mutex);
+       lockdep_assert_held(&cgroup_mutex);
+
+       css = ss->css_alloc(cgroup_css(parent, ss));
+       if (IS_ERR(css))
+               return PTR_ERR(css);
+
+       err = percpu_ref_init(&css->refcnt, css_release);
+       if (err)
+               goto err_free;
+
+       init_css(css, ss, cgrp);
+
+       err = cgroup_populate_dir(cgrp, 1 << ss->subsys_id);
+       if (err)
+               goto err_free;
+
+       err = online_css(css);
+       if (err)
+               goto err_free;
+
+       dget(cgrp->dentry);
+       css_get(css->parent);
+
+       if (ss->broken_hierarchy && !ss->warned_broken_hierarchy &&
+           parent->parent) {
+               pr_warning("cgroup: %s (%d) created nested cgroup for controller \"%s\" which has incomplete hierarchy support. Nested cgroups may change behavior in the future.\n",
+                          current->comm, current->pid, ss->name);
+               if (!strcmp(ss->name, "memory"))
+                       pr_warning("cgroup: \"memory\" requires setting use_hierarchy to 1 on the root.\n");
+               ss->warned_broken_hierarchy = true;
+       }
+
+       return 0;
+
+err_free:
+       percpu_ref_cancel_init(&css->refcnt);
+       ss->css_free(css);
+       return err;
+}
+
 /*
  * cgroup_create - create a cgroup
  * @parent: cgroup that will be parent of the new cgroup
@@ -4333,11 +4143,10 @@ static void offline_css(struct cgroup_subsys_state *css)
 static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
                             umode_t mode)
 {
-       struct cgroup_subsys_state *css_ar[CGROUP_SUBSYS_COUNT] = { };
        struct cgroup *cgrp;
        struct cgroup_name *name;
        struct cgroupfs_root *root = parent->root;
-       int err = 0;
+       int ssid, err = 0;
        struct cgroup_subsys *ss;
        struct super_block *sb = root->sb;
 
@@ -4393,23 +4202,6 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
        if (test_bit(CGRP_CPUSET_CLONE_CHILDREN, &parent->flags))
                set_bit(CGRP_CPUSET_CLONE_CHILDREN, &cgrp->flags);
 
-       for_each_root_subsys(root, ss) {
-               struct cgroup_subsys_state *css;
-
-               css = ss->css_alloc(cgroup_css(parent, ss));
-               if (IS_ERR(css)) {
-                       err = PTR_ERR(css);
-                       goto err_free_all;
-               }
-               css_ar[ss->subsys_id] = css;
-
-               err = percpu_ref_init(&css->refcnt, css_release);
-               if (err)
-                       goto err_free_all;
-
-               init_css(css, ss, cgrp);
-       }
-
        /*
         * Create directory.  cgroup_create_file() returns with the new
         * directory locked on success so that it can be populated without
@@ -4417,7 +4209,7 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
         */
        err = cgroup_create_file(dentry, S_IFDIR | mode, sb);
        if (err < 0)
-               goto err_free_all;
+               goto err_unlock;
        lockdep_assert_held(&dentry->d_inode->i_mutex);
 
        cgrp->serial_nr = cgroup_serial_nr_next++;
@@ -4426,59 +4218,34 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
        list_add_tail_rcu(&cgrp->sibling, &cgrp->parent->children);
        root->number_of_cgroups++;
 
-       /* each css holds a ref to the cgroup's dentry and the parent css */
-       for_each_root_subsys(root, ss) {
-               struct cgroup_subsys_state *css = css_ar[ss->subsys_id];
-
-               dget(dentry);
-               css_get(css->parent);
-       }
-
        /* hold a ref to the parent's dentry */
        dget(parent->dentry);
 
-       /* creation succeeded, notify subsystems */
-       for_each_root_subsys(root, ss) {
-               struct cgroup_subsys_state *css = css_ar[ss->subsys_id];
-
-               err = online_css(css);
-               if (err)
-                       goto err_destroy;
-
-               if (ss->broken_hierarchy && !ss->warned_broken_hierarchy &&
-                   parent->parent) {
-                       pr_warning("cgroup: %s (%d) created nested cgroup for controller \"%s\" which has incomplete hierarchy support. Nested cgroups may change behavior in the future.\n",
-                                  current->comm, current->pid, ss->name);
-                       if (!strcmp(ss->name, "memory"))
-                               pr_warning("cgroup: \"memory\" requires setting use_hierarchy to 1 on the root.\n");
-                       ss->warned_broken_hierarchy = true;
-               }
-       }
-
+       /*
+        * @cgrp is now fully operational.  If something fails after this
+        * point, it'll be released via the normal destruction path.
+        */
        idr_replace(&root->cgroup_idr, cgrp, cgrp->id);
 
        err = cgroup_addrm_files(cgrp, cgroup_base_files, true);
        if (err)
                goto err_destroy;
 
-       err = cgroup_populate_dir(cgrp, root->subsys_mask);
-       if (err)
-               goto err_destroy;
+       /* let's create and online css's */
+       for_each_subsys(ss, ssid) {
+               if (root->subsys_mask & (1 << ssid)) {
+                       err = create_css(cgrp, ss);
+                       if (err)
+                               goto err_destroy;
+               }
+       }
 
        mutex_unlock(&cgroup_mutex);
        mutex_unlock(&cgrp->dentry->d_inode->i_mutex);
 
        return 0;
 
-err_free_all:
-       for_each_root_subsys(root, ss) {
-               struct cgroup_subsys_state *css = css_ar[ss->subsys_id];
-
-               if (css) {
-                       percpu_ref_cancel_init(&css->refcnt);
-                       ss->css_free(css);
-               }
-       }
+err_unlock:
        mutex_unlock(&cgroup_mutex);
        /* Release the reference count that we took on the superblock */
        deactivate_super(sb);
@@ -4613,10 +4380,10 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
        __releases(&cgroup_mutex) __acquires(&cgroup_mutex)
 {
        struct dentry *d = cgrp->dentry;
-       struct cgroup_event *event, *tmp;
-       struct cgroup_subsys *ss;
+       struct cgroup_subsys_state *css;
        struct cgroup *child;
        bool empty;
+       int ssid;
 
        lockdep_assert_held(&d->d_inode->i_mutex);
        lockdep_assert_held(&cgroup_mutex);
@@ -4652,8 +4419,8 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
         * will be invoked to perform the rest of destruction once the
         * percpu refs of all css's are confirmed to be killed.
         */
-       for_each_root_subsys(cgrp->root, ss)
-               kill_css(cgroup_css(cgrp, ss));
+       for_each_css(css, ssid, cgrp)
+               kill_css(css);
 
        /*
         * Mark @cgrp dead.  This prevents further task migration and child
@@ -4688,18 +4455,6 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
        dget(d);
        cgroup_d_remove_dir(d);
 
-       /*
-        * Unregister events and notify userspace.
-        * Notify userspace about cgroup removing only after rmdir of cgroup
-        * directory to avoid race between userspace and kernelspace.
-        */
-       spin_lock(&cgrp->event_list_lock);
-       list_for_each_entry_safe(event, tmp, &cgrp->event_list, list) {
-               list_del_init(&event->list);
-               schedule_work(&event->remove);
-       }
-       spin_unlock(&cgrp->event_list_lock);
-
        return 0;
 };
 
@@ -4778,7 +4533,6 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss)
        cgroup_init_cftsets(ss);
 
        /* Create the top cgroup state for this subsystem */
-       list_add(&ss->sibling, &cgroup_dummy_root.subsys_list);
        ss->root = &cgroup_dummy_root;
        css = ss->css_alloc(cgroup_css(cgroup_dummy_top, ss));
        /* We don't handle early failures gracefully */
@@ -4852,6 +4606,7 @@ int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss)
        cgroup_init_cftsets(ss);
 
        mutex_lock(&cgroup_mutex);
+       mutex_lock(&cgroup_root_mutex);
        cgroup_subsys[ss->subsys_id] = ss;
 
        /*
@@ -4867,7 +4622,6 @@ int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss)
                return PTR_ERR(css);
        }
 
-       list_add(&ss->sibling, &cgroup_dummy_root.subsys_list);
        ss->root = &cgroup_dummy_root;
 
        /* our new subsystem will be attached to the dummy hierarchy. */
@@ -4901,10 +4655,12 @@ int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss)
                goto err_unload;
 
        /* success! */
+       mutex_unlock(&cgroup_root_mutex);
        mutex_unlock(&cgroup_mutex);
        return 0;
 
 err_unload:
+       mutex_unlock(&cgroup_root_mutex);
        mutex_unlock(&cgroup_mutex);
        /* @ss can't be mounted here as try_module_get() would fail */
        cgroup_unload_subsys(ss);
@@ -4934,15 +4690,13 @@ void cgroup_unload_subsys(struct cgroup_subsys *ss)
        BUG_ON(ss->root != &cgroup_dummy_root);
 
        mutex_lock(&cgroup_mutex);
+       mutex_lock(&cgroup_root_mutex);
 
        offline_css(cgroup_css(cgroup_dummy_top, ss));
 
        /* deassign the subsys_id */
        cgroup_subsys[ss->subsys_id] = NULL;
 
-       /* remove subsystem from the dummy root's list of subsystems */
-       list_del_init(&ss->sibling);
-
        /*
         * disentangle the css from all css_sets attached to the dummy
         * top. as in loading, we need to pay our respects to the hashtable
@@ -4968,6 +4722,7 @@ void cgroup_unload_subsys(struct cgroup_subsys *ss)
        ss->css_free(cgroup_css(cgroup_dummy_top, ss));
        RCU_INIT_POINTER(cgroup_dummy_top->subsys[ss->subsys_id], NULL);
 
+       mutex_unlock(&cgroup_root_mutex);
        mutex_unlock(&cgroup_mutex);
 }
 EXPORT_SYMBOL_GPL(cgroup_unload_subsys);
@@ -5086,6 +4841,15 @@ static int __init cgroup_wq_init(void)
         */
        cgroup_destroy_wq = alloc_workqueue("cgroup_destroy", 0, 1);
        BUG_ON(!cgroup_destroy_wq);
+
+       /*
+        * Used to destroy pidlists and separate to serve as flush domain.
+        * Cap @max_active to 1 too.
+        */
+       cgroup_pidlist_destroy_wq = alloc_workqueue("cgroup_pidlist_destroy",
+                                                   0, 1);
+       BUG_ON(!cgroup_pidlist_destroy_wq);
+
        return 0;
 }
 core_initcall(cgroup_wq_init);
@@ -5129,11 +4893,12 @@ int proc_cgroup_show(struct seq_file *m, void *v)
        for_each_active_root(root) {
                struct cgroup_subsys *ss;
                struct cgroup *cgrp;
-               int count = 0;
+               int ssid, count = 0;
 
                seq_printf(m, "%d:", root->hierarchy_id);
-               for_each_root_subsys(root, ss)
-                       seq_printf(m, "%s%s", count++ ? "," : "", ss->name);
+               for_each_subsys(ss, ssid)
+                       if (root->subsys_mask & (1 << ssid))
+                               seq_printf(m, "%s%s", count++ ? "," : "", ss->name);
                if (strlen(root->name))
                        seq_printf(m, "%sname=%s", count ? "," : "",
                                   root->name);
@@ -5474,16 +5239,16 @@ __setup("cgroup_disable=", cgroup_disable);
  * @dentry: directory dentry of interest
  * @ss: subsystem of interest
  *
- * Must be called under RCU read lock.  The caller is responsible for
- * pinning the returned css if it needs to be accessed outside the RCU
- * critical section.
+ * Must be called under cgroup_mutex or RCU read lock.  The caller is
+ * responsible for pinning the returned css if it needs to be accessed
+ * outside the critical section.
  */
 struct cgroup_subsys_state *css_from_dir(struct dentry *dentry,
                                         struct cgroup_subsys *ss)
 {
        struct cgroup *cgrp;
 
-       WARN_ON_ONCE(!rcu_read_lock_held());
+       cgroup_assert_mutex_or_rcu_locked();
 
        /* is @dentry a cgroup dir? */
        if (!dentry->d_inode ||
@@ -5506,9 +5271,7 @@ struct cgroup_subsys_state *css_from_id(int id, struct cgroup_subsys *ss)
 {
        struct cgroup *cgrp;
 
-       rcu_lockdep_assert(rcu_read_lock_held() ||
-                          lockdep_is_held(&cgroup_mutex),
-                          "css_from_id() needs proper protection");
+       cgroup_assert_mutex_or_rcu_locked();
 
        cgrp = idr_find(&ss->root->cgroup_idr, id);
        if (cgrp)
@@ -5556,9 +5319,7 @@ static u64 current_css_set_refcount_read(struct cgroup_subsys_state *css,
        return count;
 }
 
-static int current_css_set_cg_links_read(struct cgroup_subsys_state *css,
-                                        struct cftype *cft,
-                                        struct seq_file *seq)
+static int current_css_set_cg_links_read(struct seq_file *seq, void *v)
 {
        struct cgrp_cset_link *link;
        struct css_set *cset;
@@ -5583,9 +5344,9 @@ static int current_css_set_cg_links_read(struct cgroup_subsys_state *css,
 }
 
 #define MAX_TASKS_SHOWN_PER_CSS 25
-static int cgroup_css_links_read(struct cgroup_subsys_state *css,
-                                struct cftype *cft, struct seq_file *seq)
+static int cgroup_css_links_read(struct seq_file *seq, void *v)
 {
+       struct cgroup_subsys_state *css = seq_css(seq);
        struct cgrp_cset_link *link;
 
        read_lock(&css_set_lock);
@@ -5631,12 +5392,12 @@ static struct cftype debug_files[] =  {
 
        {
                .name = "current_css_set_cg_links",
-               .read_seq_string = current_css_set_cg_links_read,
+               .seq_show = current_css_set_cg_links_read,
        },
 
        {
                .name = "cgroup_css_links",
-               .read_seq_string = cgroup_css_links_read,
+               .seq_show = cgroup_css_links_read,
        },
 
        {
index f0ff64d0ebaaf5c8f5d108f3f3ea4ed6cdc114fd..6c3154e477f601deb7588317b9cbc6d7267cbed2 100644 (file)
@@ -301,10 +301,9 @@ out_unlock:
        spin_unlock_irq(&freezer->lock);
 }
 
-static int freezer_read(struct cgroup_subsys_state *css, struct cftype *cft,
-                       struct seq_file *m)
+static int freezer_read(struct seq_file *m, void *v)
 {
-       struct cgroup_subsys_state *pos;
+       struct cgroup_subsys_state *css = seq_css(m), *pos;
 
        rcu_read_lock();
 
@@ -458,7 +457,7 @@ static struct cftype files[] = {
        {
                .name = "state",
                .flags = CFTYPE_NOT_ON_ROOT,
-               .read_seq_string = freezer_read,
+               .seq_show = freezer_read,
                .write_string = freezer_write,
        },
        {
index 4772034b4b17062a4506bc4f437c599b8d5f2ac3..4410ac6a55f1d9ae410976e3a8e7315acf88a61b 100644 (file)
@@ -1731,66 +1731,41 @@ out_unlock:
  * used, list of ranges of sequential numbers, is variable length,
  * and since these maps can change value dynamically, one could read
  * gibberish by doing partial reads while a list was changing.
- * A single large read to a buffer that crosses a page boundary is
- * ok, because the result being copied to user land is not recomputed
- * across a page fault.
  */
-
-static size_t cpuset_sprintf_cpulist(char *page, struct cpuset *cs)
+static int cpuset_common_seq_show(struct seq_file *sf, void *v)
 {
-       size_t count;
-
-       mutex_lock(&callback_mutex);
-       count = cpulist_scnprintf(page, PAGE_SIZE, cs->cpus_allowed);
-       mutex_unlock(&callback_mutex);
+       struct cpuset *cs = css_cs(seq_css(sf));
+       cpuset_filetype_t type = seq_cft(sf)->private;
+       ssize_t count;
+       char *buf, *s;
+       int ret = 0;
 
-       return count;
-}
-
-static size_t cpuset_sprintf_memlist(char *page, struct cpuset *cs)
-{
-       size_t count;
+       count = seq_get_buf(sf, &buf);
+       s = buf;
 
        mutex_lock(&callback_mutex);
-       count = nodelist_scnprintf(page, PAGE_SIZE, cs->mems_allowed);
-       mutex_unlock(&callback_mutex);
-
-       return count;
-}
-
-static ssize_t cpuset_common_file_read(struct cgroup_subsys_state *css,
-                                      struct cftype *cft, struct file *file,
-                                      char __user *buf, size_t nbytes,
-                                      loff_t *ppos)
-{
-       struct cpuset *cs = css_cs(css);
-       cpuset_filetype_t type = cft->private;
-       char *page;
-       ssize_t retval = 0;
-       char *s;
-
-       if (!(page = (char *)__get_free_page(GFP_TEMPORARY)))
-               return -ENOMEM;
-
-       s = page;
 
        switch (type) {
        case FILE_CPULIST:
-               s += cpuset_sprintf_cpulist(s, cs);
+               s += cpulist_scnprintf(s, count, cs->cpus_allowed);
                break;
        case FILE_MEMLIST:
-               s += cpuset_sprintf_memlist(s, cs);
+               s += nodelist_scnprintf(s, count, cs->mems_allowed);
                break;
        default:
-               retval = -EINVAL;
-               goto out;
+               ret = -EINVAL;
+               goto out_unlock;
        }
-       *s++ = '\n';
 
-       retval = simple_read_from_buffer(buf, nbytes, ppos, page, s - page);
-out:
-       free_page((unsigned long)page);
-       return retval;
+       if (s < buf + count - 1) {
+               *s++ = '\n';
+               seq_commit(sf, s - buf);
+       } else {
+               seq_commit(sf, -1);
+       }
+out_unlock:
+       mutex_unlock(&callback_mutex);
+       return ret;
 }
 
 static u64 cpuset_read_u64(struct cgroup_subsys_state *css, struct cftype *cft)
@@ -1847,7 +1822,7 @@ static s64 cpuset_read_s64(struct cgroup_subsys_state *css, struct cftype *cft)
 static struct cftype files[] = {
        {
                .name = "cpus",
-               .read = cpuset_common_file_read,
+               .seq_show = cpuset_common_seq_show,
                .write_string = cpuset_write_resmask,
                .max_write_len = (100U + 6 * NR_CPUS),
                .private = FILE_CPULIST,
@@ -1855,7 +1830,7 @@ static struct cftype files[] = {
 
        {
                .name = "mems",
-               .read = cpuset_common_file_read,
+               .seq_show = cpuset_common_seq_show,
                .write_string = cpuset_write_resmask,
                .max_write_len = (100U + 6 * MAX_NUMNODES),
                .private = FILE_MEMLIST,
index d724e7757cd1ec2df7a9c2ac9be1b0c23f6e4e71..403b781daafb694ef9baa94e5a176212a23678e1 100644 (file)
@@ -5680,11 +5680,6 @@ static void swevent_hlist_put(struct perf_event *event)
 {
        int cpu;
 
-       if (event->cpu != -1) {
-               swevent_hlist_put_cpu(event, event->cpu);
-               return;
-       }
-
        for_each_possible_cpu(cpu)
                swevent_hlist_put_cpu(event, cpu);
 }
@@ -5718,9 +5713,6 @@ static int swevent_hlist_get(struct perf_event *event)
        int err;
        int cpu, failed_cpu;
 
-       if (event->cpu != -1)
-               return swevent_hlist_get_cpu(event, event->cpu);
-
        get_online_cpus();
        for_each_possible_cpu(cpu) {
                err = swevent_hlist_get_cpu(event, cpu);
@@ -6663,6 +6655,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
        INIT_LIST_HEAD(&event->event_entry);
        INIT_LIST_HEAD(&event->sibling_list);
        INIT_LIST_HEAD(&event->rb_entry);
+       INIT_LIST_HEAD(&event->active_entry);
 
        init_waitqueue_head(&event->waitq);
        init_irq_work(&event->pending, perf_pending_event);
index 24b7d6ca871b632f2e35912e720bfc0162c939c5..b886a5e7d4ff4a5d1c7b240a63aed39538926de4 100644 (file)
@@ -73,6 +73,17 @@ struct uprobe {
        struct inode            *inode;         /* Also hold a ref to inode */
        loff_t                  offset;
        unsigned long           flags;
+
+       /*
+        * The generic code assumes that it has two members of unknown type
+        * owned by the arch-specific code:
+        *
+        *      insn -  copy_insn() saves the original instruction here for
+        *              arch_uprobe_analyze_insn().
+        *
+        *      ixol -  potentially modified instruction to execute out of
+        *              line, copied to xol_area by xol_get_insn_slot().
+        */
        struct arch_uprobe      arch;
 };
 
@@ -85,6 +96,29 @@ struct return_instance {
        struct return_instance  *next;          /* keep as stack */
 };
 
+/*
+ * Execute out of line area: anonymous executable mapping installed
+ * by the probed task to execute the copy of the original instruction
+ * mangled by set_swbp().
+ *
+ * On a breakpoint hit, thread contests for a slot.  It frees the
+ * slot after singlestep. Currently a fixed number of slots are
+ * allocated.
+ */
+struct xol_area {
+       wait_queue_head_t       wq;             /* if all slots are busy */
+       atomic_t                slot_count;     /* number of in-use slots */
+       unsigned long           *bitmap;        /* 0 = free slot */
+       struct page             *page;
+
+       /*
+        * We keep the vma's vm_start rather than a pointer to the vma
+        * itself.  The probed process or a naughty kernel module could make
+        * the vma go away, and we must handle that reasonably gracefully.
+        */
+       unsigned long           vaddr;          /* Page(s) of instruction slots */
+};
+
 /*
  * valid_vma: Verify if the specified vma is an executable vma
  * Relax restrictions while unregistering: vm_flags might have
@@ -330,7 +364,7 @@ int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned
 int __weak
 set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr)
 {
-       return uprobe_write_opcode(mm, vaddr, *(uprobe_opcode_t *)auprobe->insn);
+       return uprobe_write_opcode(mm, vaddr, *(uprobe_opcode_t *)&auprobe->insn);
 }
 
 static int match_uprobe(struct uprobe *l, struct uprobe *r)
@@ -529,8 +563,8 @@ static int copy_insn(struct uprobe *uprobe, struct file *filp)
 {
        struct address_space *mapping = uprobe->inode->i_mapping;
        loff_t offs = uprobe->offset;
-       void *insn = uprobe->arch.insn;
-       int size = MAX_UINSN_BYTES;
+       void *insn = &uprobe->arch.insn;
+       int size = sizeof(uprobe->arch.insn);
        int len, err = -EIO;
 
        /* Copy only available bytes, -EIO if nothing was read */
@@ -569,7 +603,7 @@ static int prepare_uprobe(struct uprobe *uprobe, struct file *file,
                goto out;
 
        ret = -ENOTSUPP;
-       if (is_trap_insn((uprobe_opcode_t *)uprobe->arch.insn))
+       if (is_trap_insn((uprobe_opcode_t *)&uprobe->arch.insn))
                goto out;
 
        ret = arch_uprobe_analyze_insn(&uprobe->arch, mm, vaddr);
@@ -1264,7 +1298,7 @@ static unsigned long xol_get_insn_slot(struct uprobe *uprobe)
 
        /* Initialize the slot */
        copy_to_page(area->page, xol_vaddr,
-                       uprobe->arch.ixol, sizeof(uprobe->arch.ixol));
+                       &uprobe->arch.ixol, sizeof(uprobe->arch.ixol));
        /*
         * We probably need flush_icache_user_range() but it needs vma.
         * This should work on supported architectures too.
@@ -1403,12 +1437,10 @@ static void uprobe_warn(struct task_struct *t, const char *msg)
 
 static void dup_xol_work(struct callback_head *work)
 {
-       kfree(work);
-
        if (current->flags & PF_EXITING)
                return;
 
-       if (!__create_xol_area(current->utask->vaddr))
+       if (!__create_xol_area(current->utask->dup_xol_addr))
                uprobe_warn(current, "dup xol area");
 }
 
@@ -1419,7 +1451,6 @@ void uprobe_copy_process(struct task_struct *t, unsigned long flags)
 {
        struct uprobe_task *utask = current->utask;
        struct mm_struct *mm = current->mm;
-       struct callback_head *work;
        struct xol_area *area;
 
        t->utask = NULL;
@@ -1441,14 +1472,9 @@ void uprobe_copy_process(struct task_struct *t, unsigned long flags)
        if (mm == t->mm)
                return;
 
-       /* TODO: move it into the union in uprobe_task */
-       work = kmalloc(sizeof(*work), GFP_KERNEL);
-       if (!work)
-               return uprobe_warn(t, "dup xol area");
-
-       t->utask->vaddr = area->vaddr;
-       init_task_work(work, dup_xol_work);
-       task_work_add(t, work, true);
+       t->utask->dup_xol_addr = area->vaddr;
+       init_task_work(&t->utask->dup_xol_work, dup_xol_work);
+       task_work_add(t, &t->utask->dup_xol_work, true);
 }
 
 /*
index 728d5be9548ce61913c85e14303248363eae0a31..b3080823a24d08d875da78af3f05b8d6cd72456a 100644 (file)
@@ -1402,13 +1402,11 @@ static struct task_struct *copy_process(unsigned long clone_flags,
                p->tgid = p->pid;
        }
 
-       p->pdeath_signal = 0;
-       p->exit_state = 0;
-
        p->nr_dirtied = 0;
        p->nr_dirtied_pause = 128 >> (PAGE_SHIFT - 10);
        p->dirty_paused_when = 0;
 
+       p->pdeath_signal = 0;
        INIT_LIST_HEAD(&p->thread_group);
        p->task_works = NULL;
 
index cb228bf217603d6e841c1028dd610598ae133bff..abcd6ca86cb76b56e5979613a1964c0db743b5d0 100644 (file)
@@ -50,7 +50,7 @@ static void resume_irqs(bool want_early)
                bool is_early = desc->action &&
                        desc->action->flags & IRQF_EARLY_RESUME;
 
-               if (is_early != want_early)
+               if (!is_early && want_early)
                        continue;
 
                raw_spin_lock_irqsave(&desc->lock, flags);
index 490afc03627e52e34e51d69e0a15693b7716b17a..d0d8fca54065d72a248b0f8b76346bb72c6e2441 100644 (file)
@@ -47,6 +47,9 @@ u32 vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4];
 size_t vmcoreinfo_size;
 size_t vmcoreinfo_max_size = sizeof(vmcoreinfo_data);
 
+/* Flag to indicate we are going to kexec a new kernel */
+bool kexec_in_progress = false;
+
 /* Location of the reserved area for the crash kernel */
 struct resource crashk_res = {
        .name  = "Crash kernel",
@@ -1675,6 +1678,7 @@ int kernel_kexec(void)
        } else
 #endif
        {
+               kexec_in_progress = true;
                kernel_restart_prepare(NULL);
                printk(KERN_EMERG "Starting new kernel\n");
                machine_shutdown();
index 576ba756a32d9c80948c72e31700738bcfc5ee06..eb8a54783fa0f47bb9b51568ec9dfed3d51cc48d 100644 (file)
@@ -590,6 +590,7 @@ static int very_verbose(struct lock_class *class)
 /*
  * Is this the address of a static object:
  */
+#ifdef __KERNEL__
 static int static_obj(void *obj)
 {
        unsigned long start = (unsigned long) &_stext,
@@ -616,6 +617,7 @@ static int static_obj(void *obj)
         */
        return is_module_address(addr) || is_module_percpu_address(addr);
 }
+#endif
 
 /*
  * To make lock name printouts unique, we calculate a unique
@@ -4115,6 +4117,7 @@ void debug_check_no_locks_held(void)
 }
 EXPORT_SYMBOL_GPL(debug_check_no_locks_held);
 
+#ifdef __KERNEL__
 void debug_show_all_locks(void)
 {
        struct task_struct *g, *p;
@@ -4172,6 +4175,7 @@ retry:
                read_unlock(&tasklist_lock);
 }
 EXPORT_SYMBOL_GPL(debug_show_all_locks);
+#endif
 
 /*
  * Careful: only use this function if you are sure that
index 2abd25d79cc87bfc171f491c595d500e161f2de3..161402f0b517c9f483f166585bd61d61bac2e3f3 100644 (file)
@@ -112,7 +112,7 @@ int padata_do_parallel(struct padata_instance *pinst,
 
        rcu_read_lock_bh();
 
-       pd = rcu_dereference(pinst->pd);
+       pd = rcu_dereference_bh(pinst->pd);
 
        err = -EINVAL;
        if (!(pinst->flags & PADATA_INIT) || pinst->flags & PADATA_INVALID)
index c00b4ceb39e8b151aab790e6b498247ea53a4aa6..6d6300375090e7b2345353174d85ed09f6f35ce4 100644 (file)
@@ -33,7 +33,7 @@ static int pause_on_oops;
 static int pause_on_oops_flag;
 static DEFINE_SPINLOCK(pause_on_oops_lock);
 
-int panic_timeout;
+int panic_timeout = CONFIG_PANIC_TIMEOUT;
 EXPORT_SYMBOL_GPL(panic_timeout);
 
 ATOMIC_NOTIFIER_HEAD(panic_notifier_list);
index c00d5b502aa487de0f09117c21dfa12eb8923e0c..b00142e7f3ba18d52f41e19427f145eb6e95cf2d 100644 (file)
@@ -227,17 +227,10 @@ int parse_args(const char *doing,
 }
 
 /* Lazy bastard, eh? */
-#define STANDARD_PARAM_DEF(name, type, format, tmptype, strtolfn)              \
+#define STANDARD_PARAM_DEF(name, type, format, strtolfn)               \
        int param_set_##name(const char *val, const struct kernel_param *kp) \
        {                                                               \
-               tmptype l;                                              \
-               int ret;                                                \
-                                                                       \
-               ret = strtolfn(val, 0, &l);                             \
-               if (ret < 0 || ((type)l != l))                          \
-                       return ret < 0 ? ret : -EINVAL;                 \
-               *((type *)kp->arg) = l;                                 \
-               return 0;                                               \
+               return strtolfn(val, 0, (type *)kp->arg);               \
        }                                                               \
        int param_get_##name(char *buffer, const struct kernel_param *kp) \
        {                                                               \
@@ -253,13 +246,13 @@ int parse_args(const char *doing,
        EXPORT_SYMBOL(param_ops_##name)
 
 
-STANDARD_PARAM_DEF(byte, unsigned char, "%hhu", unsigned long, kstrtoul);
-STANDARD_PARAM_DEF(short, short, "%hi", long, kstrtol);
-STANDARD_PARAM_DEF(ushort, unsigned short, "%hu", unsigned long, kstrtoul);
-STANDARD_PARAM_DEF(int, int, "%i", long, kstrtol);
-STANDARD_PARAM_DEF(uint, unsigned int, "%u", unsigned long, kstrtoul);
-STANDARD_PARAM_DEF(long, long, "%li", long, kstrtol);
-STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", unsigned long, kstrtoul);
+STANDARD_PARAM_DEF(byte, unsigned char, "%hhu", kstrtou8);
+STANDARD_PARAM_DEF(short, short, "%hi", kstrtos16);
+STANDARD_PARAM_DEF(ushort, unsigned short, "%hu", kstrtou16);
+STANDARD_PARAM_DEF(int, int, "%i", kstrtoint);
+STANDARD_PARAM_DEF(uint, unsigned int, "%u", kstrtouint);
+STANDARD_PARAM_DEF(long, long, "%li", kstrtol);
+STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", kstrtoul);
 
 int param_set_charp(const char *val, const struct kernel_param *kp)
 {
index d09dd10c5a5efc2c206a85bd31a431268e37cc7f..9a58bc2588105900d79ec27c46bdcb8374c32cbc 100644 (file)
@@ -32,7 +32,7 @@ static int submit(int rw, struct block_device *bdev, sector_t sector,
        struct bio *bio;
 
        bio = bio_alloc(__GFP_WAIT | __GFP_HIGH, 1);
-       bio->bi_sector = sector;
+       bio->bi_iter.bi_sector = sector;
        bio->bi_bdev = bdev;
        bio->bi_end_io = end_swap_bio_read;
 
index 0121dab83f43d82ddfb620f7423d6c9728f8b01b..bc13d087ea14e3a69074ba67f00d68cb9a8ba4d2 100644 (file)
@@ -82,6 +82,7 @@ void hibernation_set_ops(const struct platform_hibernation_ops *ops)
 
        unlock_system_sleep();
 }
+EXPORT_SYMBOL_GPL(hibernation_set_ops);
 
 static bool entering_platform_hibernation;
 
index 6abb03dff5c053f44ef5dbc28f7bf754e5669e78..08a7652324321b132e3fca0f27f7285a609660dc 100644 (file)
@@ -1632,7 +1632,7 @@ module_param(rcu_idle_gp_delay, int, 0644);
 static int rcu_idle_lazy_gp_delay = RCU_IDLE_LAZY_GP_DELAY;
 module_param(rcu_idle_lazy_gp_delay, int, 0644);
 
-extern int tick_nohz_enabled;
+extern int tick_nohz_active;
 
 /*
  * Try to advance callbacks for all flavors of RCU on the current CPU, but
@@ -1729,7 +1729,7 @@ static void rcu_prepare_for_idle(int cpu)
        int tne;
 
        /* Handle nohz enablement switches conservatively. */
-       tne = ACCESS_ONCE(tick_nohz_enabled);
+       tne = ACCESS_ONCE(tick_nohz_active);
        if (tne != rdtp->tick_nohz_enabled_snap) {
                if (rcu_cpu_has_callbacks(cpu, NULL))
                        invoke_rcu_core(); /* force nohz to see update. */
index c1808606ee5f0f4e48e2fc51380369ba248bd9fe..bbadf7b2f1e9d2758f6ecd60dafbce49bfb26936 100644 (file)
@@ -2003,6 +2003,9 @@ static void finish_task_switch(struct rq *rq, struct task_struct *prev)
        if (unlikely(prev_state == TASK_DEAD)) {
                task_numa_free(prev);
 
+               if (prev->sched_class->task_dead)
+                       prev->sched_class->task_dead(prev);
+
                /*
                 * Remove function-return probe instances associated with this
                 * task and put them back on the free list.
@@ -2414,10 +2417,10 @@ static inline void schedule_debug(struct task_struct *prev)
 {
        /*
         * Test if we are atomic. Since do_exit() needs to call into
-        * schedule() atomically, we ignore that path for now.
-        * Otherwise, whine if we are scheduling when we should not be.
+        * schedule() atomically, we ignore that path. Otherwise whine
+        * if we are scheduling when we should not.
         */
-       if (unlikely(in_atomic_preempt_off() && !prev->exit_state))
+       if (unlikely(in_atomic_preempt_off() && prev->state != TASK_DEAD))
                __schedule_bug(prev);
        rcu_sleep_check();
 
@@ -2660,6 +2663,7 @@ asmlinkage void __sched notrace preempt_schedule(void)
        } while (need_resched());
 }
 EXPORT_SYMBOL(preempt_schedule);
+#endif /* CONFIG_PREEMPT */
 
 /*
  * this is the entry point to schedule() from kernel preemption
@@ -2693,8 +2697,6 @@ asmlinkage void __sched preempt_schedule_irq(void)
        exception_exit(prev_state);
 }
 
-#endif /* CONFIG_PREEMPT */
-
 int default_wake_function(wait_queue_t *curr, unsigned mode, int wake_flags,
                          void *key)
 {
@@ -3654,7 +3656,7 @@ again:
        }
 
        double_rq_lock(rq, p_rq);
-       while (task_rq(p) != p_rq) {
+       if (task_rq(p) != p_rq) {
                double_rq_unlock(rq, p_rq);
                goto again;
        }
@@ -4762,7 +4764,7 @@ static void rq_attach_root(struct rq *rq, struct root_domain *rd)
                cpumask_clear_cpu(rq->cpu, old_rd->span);
 
                /*
-                * If we dont want to free the old_rt yet then
+                * If we dont want to free the old_rd yet then
                 * set old_rd to NULL to skip the freeing later
                 * in this function:
                 */
@@ -4910,8 +4912,9 @@ static void update_top_cache_domain(int cpu)
        if (sd) {
                id = cpumask_first(sched_domain_span(sd));
                size = cpumask_weight(sched_domain_span(sd));
-               rcu_assign_pointer(per_cpu(sd_busy, cpu), sd->parent);
+               sd = sd->parent; /* sd_busy */
        }
+       rcu_assign_pointer(per_cpu(sd_busy, cpu), sd);
 
        rcu_assign_pointer(per_cpu(sd_llc, cpu), sd);
        per_cpu(sd_llc_size, cpu) = size;
@@ -7256,15 +7259,14 @@ static int __cfs_schedulable(struct task_group *tg, u64 period, u64 quota)
        return ret;
 }
 
-static int cpu_stats_show(struct cgroup_subsys_state *css, struct cftype *cft,
-               struct cgroup_map_cb *cb)
+static int cpu_stats_show(struct seq_file *sf, void *v)
 {
-       struct task_group *tg = css_tg(css);
+       struct task_group *tg = css_tg(seq_css(sf));
        struct cfs_bandwidth *cfs_b = &tg->cfs_bandwidth;
 
-       cb->fill(cb, "nr_periods", cfs_b->nr_periods);
-       cb->fill(cb, "nr_throttled", cfs_b->nr_throttled);
-       cb->fill(cb, "throttled_time", cfs_b->throttled_time);
+       seq_printf(sf, "nr_periods %d\n", cfs_b->nr_periods);
+       seq_printf(sf, "nr_throttled %d\n", cfs_b->nr_throttled);
+       seq_printf(sf, "throttled_time %llu\n", cfs_b->throttled_time);
 
        return 0;
 }
@@ -7318,7 +7320,7 @@ static struct cftype cpu_files[] = {
        },
        {
                .name = "stat",
-               .read_map = cpu_stats_show,
+               .seq_show = cpu_stats_show,
        },
 #endif
 #ifdef CONFIG_RT_GROUP_SCHED
index f64722ff029907b1cbcc6ed57cbc8c1f2b013534..622e0818f9054cf4d5d60a7543441b2c0abd9ebc 100644 (file)
@@ -163,10 +163,9 @@ out:
        return err;
 }
 
-static int cpuacct_percpu_seq_read(struct cgroup_subsys_state *css,
-                                  struct cftype *cft, struct seq_file *m)
+static int cpuacct_percpu_seq_show(struct seq_file *m, void *V)
 {
-       struct cpuacct *ca = css_ca(css);
+       struct cpuacct *ca = css_ca(seq_css(m));
        u64 percpu;
        int i;
 
@@ -183,10 +182,9 @@ static const char * const cpuacct_stat_desc[] = {
        [CPUACCT_STAT_SYSTEM] = "system",
 };
 
-static int cpuacct_stats_show(struct cgroup_subsys_state *css,
-                             struct cftype *cft, struct cgroup_map_cb *cb)
+static int cpuacct_stats_show(struct seq_file *sf, void *v)
 {
-       struct cpuacct *ca = css_ca(css);
+       struct cpuacct *ca = css_ca(seq_css(sf));
        int cpu;
        s64 val = 0;
 
@@ -196,7 +194,7 @@ static int cpuacct_stats_show(struct cgroup_subsys_state *css,
                val += kcpustat->cpustat[CPUTIME_NICE];
        }
        val = cputime64_to_clock_t(val);
-       cb->fill(cb, cpuacct_stat_desc[CPUACCT_STAT_USER], val);
+       seq_printf(sf, "%s %lld\n", cpuacct_stat_desc[CPUACCT_STAT_USER], val);
 
        val = 0;
        for_each_online_cpu(cpu) {
@@ -207,7 +205,7 @@ static int cpuacct_stats_show(struct cgroup_subsys_state *css,
        }
 
        val = cputime64_to_clock_t(val);
-       cb->fill(cb, cpuacct_stat_desc[CPUACCT_STAT_SYSTEM], val);
+       seq_printf(sf, "%s %lld\n", cpuacct_stat_desc[CPUACCT_STAT_SYSTEM], val);
 
        return 0;
 }
@@ -220,11 +218,11 @@ static struct cftype files[] = {
        },
        {
                .name = "usage_percpu",
-               .read_seq_string = cpuacct_percpu_seq_read,
+               .seq_show = cpuacct_percpu_seq_show,
        },
        {
                .name = "stat",
-               .read_map = cpuacct_stats_show,
+               .seq_show = cpuacct_stats_show,
        },
        { }     /* terminate */
 };
index e8b652ebe027c481e87122f629a300058cf82679..0de52f4f7717ad71d863ed82ecdba61c13e77766 100644 (file)
@@ -4110,12 +4110,16 @@ static int wake_affine(struct sched_domain *sd, struct task_struct *p, int sync)
  */
 static struct sched_group *
 find_idlest_group(struct sched_domain *sd, struct task_struct *p,
-                 int this_cpu, int load_idx)
+                 int this_cpu, int sd_flag)
 {
        struct sched_group *idlest = NULL, *group = sd->groups;
        unsigned long min_load = ULONG_MAX, this_load = 0;
+       int load_idx = sd->forkexec_idx;
        int imbalance = 100 + (sd->imbalance_pct-100)/2;
 
+       if (sd_flag & SD_BALANCE_WAKE)
+               load_idx = sd->wake_idx;
+
        do {
                unsigned long load, avg_load;
                int local_group;
@@ -4283,7 +4287,6 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_f
        }
 
        while (sd) {
-               int load_idx = sd->forkexec_idx;
                struct sched_group *group;
                int weight;
 
@@ -4292,10 +4295,7 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_f
                        continue;
                }
 
-               if (sd_flag & SD_BALANCE_WAKE)
-                       load_idx = sd->wake_idx;
-
-               group = find_idlest_group(sd, p, cpu, load_idx);
+               group = find_idlest_group(sd, p, cpu, sd_flag);
                if (!group) {
                        sd = sd->child;
                        continue;
@@ -5379,10 +5379,31 @@ void update_group_power(struct sched_domain *sd, int cpu)
                 */
 
                for_each_cpu(cpu, sched_group_cpus(sdg)) {
-                       struct sched_group *sg = cpu_rq(cpu)->sd->groups;
+                       struct sched_group_power *sgp;
+                       struct rq *rq = cpu_rq(cpu);
 
-                       power_orig += sg->sgp->power_orig;
-                       power += sg->sgp->power;
+                       /*
+                        * build_sched_domains() -> init_sched_groups_power()
+                        * gets here before we've attached the domains to the
+                        * runqueues.
+                        *
+                        * Use power_of(), which is set irrespective of domains
+                        * in update_cpu_power().
+                        *
+                        * This avoids power/power_orig from being 0 and
+                        * causing divide-by-zero issues on boot.
+                        *
+                        * Runtime updates will correct power_orig.
+                        */
+                       if (unlikely(!rq->sd)) {
+                               power_orig += power_of(cpu);
+                               power += power_of(cpu);
+                               continue;
+                       }
+
+                       sgp = rq->sd->groups->sgp;
+                       power_orig += sgp->power_orig;
+                       power += sgp->power;
                }
        } else  {
                /*
@@ -5500,7 +5521,6 @@ 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)
 {
-       unsigned long nr_running;
        unsigned long load;
        int i;
 
@@ -5509,8 +5529,6 @@ static inline void update_sg_lb_stats(struct lb_env *env,
        for_each_cpu_and(i, sched_group_cpus(group), env->cpus) {
                struct rq *rq = cpu_rq(i);
 
-               nr_running = rq->nr_running;
-
                /* Bias balancing toward cpus of our domain */
                if (local_group)
                        load = target_load(i, load_idx);
@@ -5518,7 +5536,7 @@ static inline void update_sg_lb_stats(struct lb_env *env,
                        load = source_load(i, load_idx);
 
                sgs->group_load += load;
-               sgs->sum_nr_running += nr_running;
+               sgs->sum_nr_running += rq->nr_running;
 #ifdef CONFIG_NUMA_BALANCING
                sgs->nr_numa_running += rq->nr_numa_running;
                sgs->nr_preferred_running += rq->nr_preferred_running;
index 88c85b21d63346f4ba82e00962486445c9fdb410..b3b4a4953efcdae925c77e44fcf2798c69edd040 100644 (file)
@@ -1023,6 +1023,7 @@ struct sched_class {
        void (*set_curr_task) (struct rq *rq);
        void (*task_tick) (struct rq *rq, struct task_struct *p, int queued);
        void (*task_fork) (struct task_struct *p);
+       void (*task_dead) (struct task_struct *p);
 
        void (*switched_from) (struct rq *this_rq, struct task_struct *task);
        void (*switched_to) (struct rq *this_rq, struct task_struct *task);
index 11025ccc06dd1e2211ca62dcbcea7ce1b05418dd..9a4500e4c1893ec22e17c4ac98a1d34cc6a0b6cf 100644 (file)
@@ -211,14 +211,48 @@ EXPORT_SYMBOL(local_bh_enable_ip);
 #define MAX_SOFTIRQ_TIME  msecs_to_jiffies(2)
 #define MAX_SOFTIRQ_RESTART 10
 
+#ifdef CONFIG_TRACE_IRQFLAGS
+/*
+ * When we run softirqs from irq_exit() and thus on the hardirq stack we need
+ * to keep the lockdep irq context tracking as tight as possible in order to
+ * not miss-qualify lock contexts and miss possible deadlocks.
+ */
+
+static inline bool lockdep_softirq_start(void)
+{
+       bool in_hardirq = false;
+
+       if (trace_hardirq_context(current)) {
+               in_hardirq = true;
+               trace_hardirq_exit();
+       }
+
+       lockdep_softirq_enter();
+
+       return in_hardirq;
+}
+
+static inline void lockdep_softirq_end(bool in_hardirq)
+{
+       lockdep_softirq_exit();
+
+       if (in_hardirq)
+               trace_hardirq_enter();
+}
+#else
+static inline bool lockdep_softirq_start(void) { return false; }
+static inline void lockdep_softirq_end(bool in_hardirq) { }
+#endif
+
 asmlinkage void __do_softirq(void)
 {
-       struct softirq_action *h;
-       __u32 pending;
        unsigned long end = jiffies + MAX_SOFTIRQ_TIME;
-       int cpu;
        unsigned long old_flags = current->flags;
        int max_restart = MAX_SOFTIRQ_RESTART;
+       struct softirq_action *h;
+       bool in_hardirq;
+       __u32 pending;
+       int cpu;
 
        /*
         * Mask out PF_MEMALLOC s current task context is borrowed for the
@@ -231,7 +265,7 @@ asmlinkage void __do_softirq(void)
        account_irq_enter_time(current);
 
        __local_bh_disable(_RET_IP_, SOFTIRQ_OFFSET);
-       lockdep_softirq_enter();
+       in_hardirq = lockdep_softirq_start();
 
        cpu = smp_processor_id();
 restart:
@@ -278,16 +312,13 @@ restart:
                wakeup_softirqd();
        }
 
-       lockdep_softirq_exit();
-
+       lockdep_softirq_end(in_hardirq);
        account_irq_exit_time(current);
        __local_bh_enable(SOFTIRQ_OFFSET);
        WARN_ON_ONCE(in_interrupt());
        tsk_restore_flags(current, old_flags, PF_MEMALLOC);
 }
 
-
-
 asmlinkage void do_softirq(void)
 {
        __u32 pending;
@@ -375,13 +406,13 @@ void irq_exit(void)
 #endif
 
        account_irq_exit_time(current);
-       trace_hardirq_exit();
        preempt_count_sub(HARDIRQ_OFFSET);
        if (!in_interrupt() && local_softirq_pending())
                invoke_softirq();
 
        tick_irq_exit();
        rcu_irq_exit();
+       trace_hardirq_exit(); /* must be last! */
 }
 
 /*
index 64522ecdfe0e868420acdd7b47a65de99b847748..162b03ab0ad2ed16e3654f7006aae6f88c1886cf 100644 (file)
@@ -33,6 +33,21 @@ DEFINE_PER_CPU(struct tick_device, tick_cpu_device);
  */
 ktime_t tick_next_period;
 ktime_t tick_period;
+
+/*
+ * tick_do_timer_cpu is a timer core internal variable which holds the CPU NR
+ * which is responsible for calling do_timer(), i.e. the timekeeping stuff. This
+ * variable has two functions:
+ *
+ * 1) Prevent a thundering herd issue of a gazillion of CPUs trying to grab the
+ *    timekeeping lock all at once. Only the CPU which is assigned to do the
+ *    update is handling it.
+ *
+ * 2) Hand off the duty in the NOHZ idle case by setting the value to
+ *    TICK_DO_TIMER_NONE, i.e. a non existing CPU. So the next cpu which looks
+ *    at it will take over and keep the time keeping alive.  The handover
+ *    procedure also covers cpu hotplug.
+ */
 int tick_do_timer_cpu __read_mostly = TICK_DO_TIMER_BOOT;
 
 /*
index 3612fc77f834372c0d5d674f3bc5ae609dd64635..ea20f7d1ac2c4f91af4dd8dd4db3b01b5c6ae4b7 100644 (file)
@@ -361,8 +361,8 @@ void __init tick_nohz_init(void)
 /*
  * NO HZ enabled ?
  */
-int tick_nohz_enabled __read_mostly  = 1;
-
+static int tick_nohz_enabled __read_mostly  = 1;
+int tick_nohz_active  __read_mostly;
 /*
  * Enable / Disable tickless mode
  */
@@ -465,7 +465,7 @@ u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time)
        struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
        ktime_t now, idle;
 
-       if (!tick_nohz_enabled)
+       if (!tick_nohz_active)
                return -1;
 
        now = ktime_get();
@@ -506,7 +506,7 @@ u64 get_cpu_iowait_time_us(int cpu, u64 *last_update_time)
        struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
        ktime_t now, iowait;
 
-       if (!tick_nohz_enabled)
+       if (!tick_nohz_active)
                return -1;
 
        now = ktime_get();
@@ -711,8 +711,10 @@ static bool can_stop_idle_tick(int cpu, struct tick_sched *ts)
                return false;
        }
 
-       if (unlikely(ts->nohz_mode == NOHZ_MODE_INACTIVE))
+       if (unlikely(ts->nohz_mode == NOHZ_MODE_INACTIVE)) {
+               ts->sleep_length = (ktime_t) { .tv64 = NSEC_PER_SEC/HZ };
                return false;
+       }
 
        if (need_resched())
                return false;
@@ -799,11 +801,6 @@ void tick_nohz_idle_enter(void)
        local_irq_disable();
 
        ts = &__get_cpu_var(tick_cpu_sched);
-       /*
-        * set ts->inidle unconditionally. even if the system did not
-        * switch to nohz mode the cpu frequency governers rely on the
-        * update of the idle time accounting in tick_nohz_start_idle().
-        */
        ts->inidle = 1;
        __tick_nohz_idle_enter(ts);
 
@@ -973,7 +970,7 @@ static void tick_nohz_switch_to_nohz(void)
        struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
        ktime_t next;
 
-       if (!tick_nohz_enabled)
+       if (!tick_nohz_active)
                return;
 
        local_irq_disable();
@@ -981,7 +978,7 @@ static void tick_nohz_switch_to_nohz(void)
                local_irq_enable();
                return;
        }
-
+       tick_nohz_active = 1;
        ts->nohz_mode = NOHZ_MODE_LOWRES;
 
        /*
@@ -1139,8 +1136,10 @@ void tick_setup_sched_timer(void)
        }
 
 #ifdef CONFIG_NO_HZ_COMMON
-       if (tick_nohz_enabled)
+       if (tick_nohz_enabled) {
                ts->nohz_mode = NOHZ_MODE_HIGHRES;
+               tick_nohz_active = 1;
+       }
 #endif
 }
 #endif /* HIGH_RES_TIMERS */
index 3abf53418b67c6ee92c16522299a8821856b749d..87b4f00284c9e21f420d0865af937b03eb286f33 100644 (file)
@@ -1347,7 +1347,7 @@ static inline void old_vsyscall_fixup(struct timekeeper *tk)
        tk->xtime_nsec -= remainder;
        tk->xtime_nsec += 1ULL << tk->shift;
        tk->ntp_error += remainder << tk->ntp_error_shift;
-
+       tk->ntp_error -= (1ULL << tk->shift) << tk->ntp_error_shift;
 }
 #else
 #define old_vsyscall_fixup(tk)
index 6582b82fa966d6ba503a7361f8f89f699f4de04d..accfd241b9e5d5c67040407dfa4f3d8603851de2 100644 (file)
@@ -1518,9 +1518,8 @@ static int init_timers_cpu(int cpu)
                        /*
                         * The APs use this path later in boot
                         */
-                       base = kmalloc_node(sizeof(*base),
-                                               GFP_KERNEL | __GFP_ZERO,
-                                               cpu_to_node(cpu));
+                       base = kzalloc_node(sizeof(*base), GFP_KERNEL,
+                                           cpu_to_node(cpu));
                        if (!base)
                                return -ENOMEM;
 
index f785aef65799cdb0068f0016bb0183a3bfe312a6..b418cb0d72424ab454e66e3cde881784ce1f0fad 100644 (file)
@@ -781,8 +781,8 @@ static void blk_add_trace_bio(struct request_queue *q, struct bio *bio,
        if (!error && !bio_flagged(bio, BIO_UPTODATE))
                error = EIO;
 
-       __blk_add_trace(bt, bio->bi_sector, bio->bi_size, bio->bi_rw, what,
-                       error, 0, NULL);
+       __blk_add_trace(bt, bio->bi_iter.bi_sector, bio->bi_iter.bi_size,
+                       bio->bi_rw, what, error, 0, NULL);
 }
 
 static void blk_add_trace_bio_bounce(void *ignore,
@@ -885,8 +885,9 @@ static void blk_add_trace_split(void *ignore,
        if (bt) {
                __be64 rpdu = cpu_to_be64(pdu);
 
-               __blk_add_trace(bt, bio->bi_sector, bio->bi_size, bio->bi_rw,
-                               BLK_TA_SPLIT, !bio_flagged(bio, BIO_UPTODATE),
+               __blk_add_trace(bt, bio->bi_iter.bi_sector,
+                               bio->bi_iter.bi_size, bio->bi_rw, BLK_TA_SPLIT,
+                               !bio_flagged(bio, BIO_UPTODATE),
                                sizeof(rpdu), &rpdu);
        }
 }
@@ -918,9 +919,9 @@ static void blk_add_trace_bio_remap(void *ignore,
        r.device_to   = cpu_to_be32(bio->bi_bdev->bd_dev);
        r.sector_from = cpu_to_be64(from);
 
-       __blk_add_trace(bt, bio->bi_sector, bio->bi_size, bio->bi_rw,
-                       BLK_TA_REMAP, !bio_flagged(bio, BIO_UPTODATE),
-                       sizeof(r), &r);
+       __blk_add_trace(bt, bio->bi_iter.bi_sector, bio->bi_iter.bi_size,
+                       bio->bi_rw, BLK_TA_REMAP,
+                       !bio_flagged(bio, BIO_UPTODATE), sizeof(r), &r);
 }
 
 /**
index 78e27e3b52ac2ee0b9e86f544b77a45e12865d95..e854f420e033eb65a2bca233bb8df2e42778faf7 100644 (file)
@@ -24,6 +24,12 @@ static int   total_ref_count;
 static int perf_trace_event_perm(struct ftrace_event_call *tp_event,
                                 struct perf_event *p_event)
 {
+       if (tp_event->perf_perm) {
+               int ret = tp_event->perf_perm(tp_event, p_event);
+               if (ret)
+                       return ret;
+       }
+
        /* The ftrace function trace is allowed only for root. */
        if (ftrace_event_is_function(tp_event) &&
            perf_paranoid_tracepoint_raw() && !capable(CAP_SYS_ADMIN))
@@ -173,7 +179,7 @@ static int perf_trace_event_init(struct ftrace_event_call *tp_event,
 int perf_trace_init(struct perf_event *p_event)
 {
        struct ftrace_event_call *tp_event;
-       int event_id = p_event->attr.config;
+       u64 event_id = p_event->attr.config;
        int ret = -EINVAL;
 
        mutex_lock(&event_mutex);
index f919a2e21bf30e68ad6a99ee627d63f5bb6cb44c..a11800ae96de5d1f098153aaacdb715ba5098493 100644 (file)
@@ -2314,6 +2314,9 @@ int event_trace_del_tracer(struct trace_array *tr)
        /* Disable any running events */
        __ftrace_set_clr_event_nolock(tr, NULL, NULL, NULL, 0);
 
+       /* Access to events are within rcu_read_lock_sched() */
+       synchronize_sched();
+
        down_write(&trace_event_sem);
        __trace_remove_event_dirs(tr);
        debugfs_remove_recursive(tr->event_dir);
index e4b6d11bdf78f35a2a6d8e831cd3ec21d97d9c00..ea90eb5f6f1730dce05ca992c19ebb533d7085db 100644 (file)
@@ -431,11 +431,6 @@ static void unreg_event_syscall_enter(struct ftrace_event_file *file,
        if (!tr->sys_refcount_enter)
                unregister_trace_sys_enter(ftrace_syscall_enter, tr);
        mutex_unlock(&syscall_trace_lock);
-       /*
-        * Callers expect the event to be completely disabled on
-        * return, so wait for current handlers to finish.
-        */
-       synchronize_sched();
 }
 
 static int reg_event_syscall_exit(struct ftrace_event_file *file,
@@ -474,11 +469,6 @@ static void unreg_event_syscall_exit(struct ftrace_event_file *file,
        if (!tr->sys_refcount_exit)
                unregister_trace_sys_exit(ftrace_syscall_exit, tr);
        mutex_unlock(&syscall_trace_lock);
-       /*
-        * Callers expect the event to be completely disabled on
-        * return, so wait for current handlers to finish.
-        */
-       synchronize_sched();
 }
 
 static int __init init_syscall_trace(struct ftrace_event_call *call)
index c66912be990fbda0f61e7a58fdbc52cf304566c2..b010eac595d20eece261310cc4acb629ad70b92b 100644 (file)
@@ -2851,19 +2851,6 @@ already_gone:
        return false;
 }
 
-static bool __flush_work(struct work_struct *work)
-{
-       struct wq_barrier barr;
-
-       if (start_flush_work(work, &barr)) {
-               wait_for_completion(&barr.done);
-               destroy_work_on_stack(&barr.work);
-               return true;
-       } else {
-               return false;
-       }
-}
-
 /**
  * flush_work - wait for a work to finish executing the last queueing instance
  * @work: the work to flush
@@ -2877,10 +2864,18 @@ static bool __flush_work(struct work_struct *work)
  */
 bool flush_work(struct work_struct *work)
 {
+       struct wq_barrier barr;
+
        lock_map_acquire(&work->lockdep_map);
        lock_map_release(&work->lockdep_map);
 
-       return __flush_work(work);
+       if (start_flush_work(work, &barr)) {
+               wait_for_completion(&barr.done);
+               destroy_work_on_stack(&barr.work);
+               return true;
+       } else {
+               return false;
+       }
 }
 EXPORT_SYMBOL_GPL(flush_work);
 
@@ -4832,14 +4827,7 @@ long work_on_cpu(int cpu, long (*fn)(void *), void *arg)
 
        INIT_WORK_ONSTACK(&wfc.work, work_for_cpu_fn);
        schedule_work_on(cpu, &wfc.work);
-
-       /*
-        * The work item is on-stack and can't lead to deadlock through
-        * flushing.  Use __flush_work() to avoid spurious lockdep warnings
-        * when work_on_cpu()s are nested.
-        */
-       __flush_work(&wfc.work);
-
+       flush_work(&wfc.work);
        return wfc.ret;
 }
 EXPORT_SYMBOL_GPL(work_on_cpu);
index db25707aa41bc021b8174391091178b85258d466..6982094a7e74aa8c5daea87f90878174a8d746c1 100644 (file)
@@ -761,6 +761,15 @@ config PANIC_ON_OOPS_VALUE
        default 0 if !PANIC_ON_OOPS
        default 1 if PANIC_ON_OOPS
 
+config PANIC_TIMEOUT
+       int "panic timeout"
+       default 0
+       help
+         Set the timeout value (in seconds) until a reboot occurs when the
+         the kernel panics. If n = 0, then we wait forever. A timeout
+         value n > 0 will wait n seconds before rebooting, while a timeout
+         value n < 0 will reboot immediately.
+
 config SCHED_DEBUG
        bool "Collect scheduler debugging info"
        depends on DEBUG_KERNEL && PROC_FS
index 5a7d58fb883bfa1c4917e48d251cd132c8d9baf9..523918b8c6dcbef6968c37e2fa38ee87a3b2518c 100644 (file)
@@ -98,27 +98,24 @@ int init_emergency_isa_pool(void)
 static void copy_to_high_bio_irq(struct bio *to, struct bio *from)
 {
        unsigned char *vfrom;
-       struct bio_vec *tovec, *fromvec;
-       int i;
-
-       bio_for_each_segment(tovec, to, i) {
-               fromvec = from->bi_io_vec + i;
-
-               /*
-                * not bounced
-                */
-               if (tovec->bv_page == fromvec->bv_page)
-                       continue;
-
-               /*
-                * fromvec->bv_offset and fromvec->bv_len might have been
-                * modified by the block layer, so use the original copy,
-                * bounce_copy_vec already uses tovec->bv_len
-                */
-               vfrom = page_address(fromvec->bv_page) + tovec->bv_offset;
+       struct bio_vec tovec, *fromvec = from->bi_io_vec;
+       struct bvec_iter iter;
+
+       bio_for_each_segment(tovec, to, iter) {
+               if (tovec.bv_page != fromvec->bv_page) {
+                       /*
+                        * fromvec->bv_offset and fromvec->bv_len might have
+                        * been modified by the block layer, so use the original
+                        * copy, bounce_copy_vec already uses tovec->bv_len
+                        */
+                       vfrom = page_address(fromvec->bv_page) +
+                               tovec.bv_offset;
+
+                       bounce_copy_vec(&tovec, vfrom);
+                       flush_dcache_page(tovec.bv_page);
+               }
 
-               bounce_copy_vec(tovec, vfrom);
-               flush_dcache_page(tovec->bv_page);
+               fromvec++;
        }
 }
 
@@ -201,13 +198,14 @@ static void __blk_queue_bounce(struct request_queue *q, struct bio **bio_orig,
 {
        struct bio *bio;
        int rw = bio_data_dir(*bio_orig);
-       struct bio_vec *to, *from;
+       struct bio_vec *to, from;
+       struct bvec_iter iter;
        unsigned i;
 
        if (force)
                goto bounce;
-       bio_for_each_segment(from, *bio_orig, i)
-               if (page_to_pfn(from->bv_page) > queue_bounce_pfn(q))
+       bio_for_each_segment(from, *bio_orig, iter)
+               if (page_to_pfn(from.bv_page) > queue_bounce_pfn(q))
                        goto bounce;
 
        return;
index bda8e44f6fdee72c31d805aa5ae4164a0e01a952..d747a84e09b088e4e585a56089ce7e6c6302a3a5 100644 (file)
@@ -242,22 +242,16 @@ void hugetlb_cgroup_uncharge_cgroup(int idx, unsigned long nr_pages,
        return;
 }
 
-static ssize_t hugetlb_cgroup_read(struct cgroup_subsys_state *css,
-                                  struct cftype *cft, struct file *file,
-                                  char __user *buf, size_t nbytes,
-                                  loff_t *ppos)
+static u64 hugetlb_cgroup_read_u64(struct cgroup_subsys_state *css,
+                                  struct cftype *cft)
 {
-       u64 val;
-       char str[64];
-       int idx, name, len;
+       int idx, name;
        struct hugetlb_cgroup *h_cg = hugetlb_cgroup_from_css(css);
 
        idx = MEMFILE_IDX(cft->private);
        name = MEMFILE_ATTR(cft->private);
 
-       val = res_counter_read_u64(&h_cg->hugepage[idx], name);
-       len = scnprintf(str, sizeof(str), "%llu\n", (unsigned long long)val);
-       return simple_read_from_buffer(buf, nbytes, ppos, str, len);
+       return res_counter_read_u64(&h_cg->hugepage[idx], name);
 }
 
 static int hugetlb_cgroup_write(struct cgroup_subsys_state *css,
@@ -337,28 +331,28 @@ static void __init __hugetlb_cgroup_file_init(int idx)
        cft = &h->cgroup_files[0];
        snprintf(cft->name, MAX_CFTYPE_NAME, "%s.limit_in_bytes", buf);
        cft->private = MEMFILE_PRIVATE(idx, RES_LIMIT);
-       cft->read = hugetlb_cgroup_read;
+       cft->read_u64 = hugetlb_cgroup_read_u64;
        cft->write_string = hugetlb_cgroup_write;
 
        /* Add the usage file */
        cft = &h->cgroup_files[1];
        snprintf(cft->name, MAX_CFTYPE_NAME, "%s.usage_in_bytes", buf);
        cft->private = MEMFILE_PRIVATE(idx, RES_USAGE);
-       cft->read = hugetlb_cgroup_read;
+       cft->read_u64 = hugetlb_cgroup_read_u64;
 
        /* Add the MAX usage file */
        cft = &h->cgroup_files[2];
        snprintf(cft->name, MAX_CFTYPE_NAME, "%s.max_usage_in_bytes", buf);
        cft->private = MEMFILE_PRIVATE(idx, RES_MAX_USAGE);
        cft->trigger = hugetlb_cgroup_reset;
-       cft->read = hugetlb_cgroup_read;
+       cft->read_u64 = hugetlb_cgroup_read_u64;
 
        /* Add the failcntfile */
        cft = &h->cgroup_files[3];
        snprintf(cft->name, MAX_CFTYPE_NAME, "%s.failcnt", buf);
        cft->private  = MEMFILE_PRIVATE(idx, RES_FAILCNT);
        cft->trigger  = hugetlb_cgroup_reset;
-       cft->read = hugetlb_cgroup_read;
+       cft->read_u64 = hugetlb_cgroup_read_u64;
 
        /* NULL terminate the last cft */
        cft = &h->cgroup_files[4];
index f1a0ae6e11b86b3020c90d7241ba12d47d2bbaa8..9252219376ccb521770edbb1ed0c8ae036421abf 100644 (file)
@@ -45,6 +45,7 @@
 #include <linux/swapops.h>
 #include <linux/spinlock.h>
 #include <linux/eventfd.h>
+#include <linux/poll.h>
 #include <linux/sort.h>
 #include <linux/fs.h>
 #include <linux/seq_file.h>
@@ -55,6 +56,7 @@
 #include <linux/cpu.h>
 #include <linux/oom.h>
 #include <linux/lockdep.h>
+#include <linux/file.h>
 #include "internal.h"
 #include <net/sock.h>
 #include <net/ip.h>
@@ -227,6 +229,46 @@ struct mem_cgroup_eventfd_list {
        struct eventfd_ctx *eventfd;
 };
 
+/*
+ * cgroup_event represents events which userspace want to receive.
+ */
+struct mem_cgroup_event {
+       /*
+        * memcg which the event belongs to.
+        */
+       struct mem_cgroup *memcg;
+       /*
+        * eventfd to signal userspace about the event.
+        */
+       struct eventfd_ctx *eventfd;
+       /*
+        * Each of these stored in a list by the cgroup.
+        */
+       struct list_head list;
+       /*
+        * register_event() callback will be used to add new userspace
+        * waiter for changes related to this event.  Use eventfd_signal()
+        * on eventfd to send notification to userspace.
+        */
+       int (*register_event)(struct mem_cgroup *memcg,
+                             struct eventfd_ctx *eventfd, const char *args);
+       /*
+        * unregister_event() callback will be called when userspace closes
+        * the eventfd or on cgroup removing.  This callback must be set,
+        * if you want provide notification functionality.
+        */
+       void (*unregister_event)(struct mem_cgroup *memcg,
+                                struct eventfd_ctx *eventfd);
+       /*
+        * All fields below needed to unregister event when
+        * userspace closes eventfd.
+        */
+       poll_table pt;
+       wait_queue_head_t *wqh;
+       wait_queue_t wait;
+       struct work_struct remove;
+};
+
 static void mem_cgroup_threshold(struct mem_cgroup *memcg);
 static void mem_cgroup_oom_notify(struct mem_cgroup *memcg);
 
@@ -331,6 +373,10 @@ struct mem_cgroup {
        atomic_t        numainfo_updating;
 #endif
 
+       /* List of events which userspace want to receive */
+       struct list_head event_list;
+       spinlock_t event_list_lock;
+
        struct mem_cgroup_per_node *nodeinfo[0];
        /* WARNING: nodeinfo must be the last member here */
 };
@@ -490,11 +536,6 @@ struct cgroup_subsys_state *vmpressure_to_css(struct vmpressure *vmpr)
        return &container_of(vmpr, struct mem_cgroup, vmpressure)->css;
 }
 
-struct vmpressure *css_to_vmpressure(struct cgroup_subsys_state *css)
-{
-       return &mem_cgroup_from_css(css)->vmpressure;
-}
-
 static inline bool mem_cgroup_is_root(struct mem_cgroup *memcg)
 {
        return (memcg == root_mem_cgroup);
@@ -2973,10 +3014,9 @@ static struct kmem_cache *memcg_params_to_cache(struct memcg_cache_params *p)
 }
 
 #ifdef CONFIG_SLABINFO
-static int mem_cgroup_slabinfo_read(struct cgroup_subsys_state *css,
-                                   struct cftype *cft, struct seq_file *m)
+static int mem_cgroup_slabinfo_read(struct seq_file *m, void *v)
 {
-       struct mem_cgroup *memcg = mem_cgroup_from_css(css);
+       struct mem_cgroup *memcg = mem_cgroup_from_css(seq_css(m));
        struct memcg_cache_params *params;
 
        if (!memcg_can_account_kmem(memcg))
@@ -5109,14 +5149,12 @@ static inline u64 mem_cgroup_usage(struct mem_cgroup *memcg, bool swap)
        return val << PAGE_SHIFT;
 }
 
-static ssize_t mem_cgroup_read(struct cgroup_subsys_state *css,
-                              struct cftype *cft, struct file *file,
-                              char __user *buf, size_t nbytes, loff_t *ppos)
+static u64 mem_cgroup_read_u64(struct cgroup_subsys_state *css,
+                                  struct cftype *cft)
 {
        struct mem_cgroup *memcg = mem_cgroup_from_css(css);
-       char str[64];
        u64 val;
-       int name, len;
+       int name;
        enum res_type type;
 
        type = MEMFILE_TYPE(cft->private);
@@ -5142,8 +5180,7 @@ static ssize_t mem_cgroup_read(struct cgroup_subsys_state *css,
                BUG();
        }
 
-       len = scnprintf(str, sizeof(str), "%llu\n", (unsigned long long)val);
-       return simple_read_from_buffer(buf, nbytes, ppos, str, len);
+       return val;
 }
 
 static int memcg_update_kmem_limit(struct cgroup_subsys_state *css, u64 val)
@@ -5380,8 +5417,7 @@ static int mem_cgroup_move_charge_write(struct cgroup_subsys_state *css,
 #endif
 
 #ifdef CONFIG_NUMA
-static int memcg_numa_stat_show(struct cgroup_subsys_state *css,
-                               struct cftype *cft, struct seq_file *m)
+static int memcg_numa_stat_show(struct seq_file *m, void *v)
 {
        struct numa_stat {
                const char *name;
@@ -5397,7 +5433,7 @@ static int memcg_numa_stat_show(struct cgroup_subsys_state *css,
        const struct numa_stat *stat;
        int nid;
        unsigned long nr;
-       struct mem_cgroup *memcg = mem_cgroup_from_css(css);
+       struct mem_cgroup *memcg = mem_cgroup_from_css(seq_css(m));
 
        for (stat = stats; stat < stats + ARRAY_SIZE(stats); stat++) {
                nr = mem_cgroup_nr_lru_pages(memcg, stat->lru_mask);
@@ -5436,10 +5472,9 @@ static inline void mem_cgroup_lru_names_not_uptodate(void)
        BUILD_BUG_ON(ARRAY_SIZE(mem_cgroup_lru_names) != NR_LRU_LISTS);
 }
 
-static int memcg_stat_show(struct cgroup_subsys_state *css, struct cftype *cft,
-                                struct seq_file *m)
+static int memcg_stat_show(struct seq_file *m, void *v)
 {
-       struct mem_cgroup *memcg = mem_cgroup_from_css(css);
+       struct mem_cgroup *memcg = mem_cgroup_from_css(seq_css(m));
        struct mem_cgroup *mi;
        unsigned int i;
 
@@ -5648,13 +5683,11 @@ static void mem_cgroup_oom_notify(struct mem_cgroup *memcg)
                mem_cgroup_oom_notify_cb(iter);
 }
 
-static int mem_cgroup_usage_register_event(struct cgroup_subsys_state *css,
-       struct cftype *cft, struct eventfd_ctx *eventfd, const char *args)
+static int __mem_cgroup_usage_register_event(struct mem_cgroup *memcg,
+       struct eventfd_ctx *eventfd, const char *args, enum res_type type)
 {
-       struct mem_cgroup *memcg = mem_cgroup_from_css(css);
        struct mem_cgroup_thresholds *thresholds;
        struct mem_cgroup_threshold_ary *new;
-       enum res_type type = MEMFILE_TYPE(cft->private);
        u64 threshold, usage;
        int i, size, ret;
 
@@ -5731,13 +5764,23 @@ unlock:
        return ret;
 }
 
-static void mem_cgroup_usage_unregister_event(struct cgroup_subsys_state *css,
-       struct cftype *cft, struct eventfd_ctx *eventfd)
+static int mem_cgroup_usage_register_event(struct mem_cgroup *memcg,
+       struct eventfd_ctx *eventfd, const char *args)
+{
+       return __mem_cgroup_usage_register_event(memcg, eventfd, args, _MEM);
+}
+
+static int memsw_cgroup_usage_register_event(struct mem_cgroup *memcg,
+       struct eventfd_ctx *eventfd, const char *args)
+{
+       return __mem_cgroup_usage_register_event(memcg, eventfd, args, _MEMSWAP);
+}
+
+static void __mem_cgroup_usage_unregister_event(struct mem_cgroup *memcg,
+       struct eventfd_ctx *eventfd, enum res_type type)
 {
-       struct mem_cgroup *memcg = mem_cgroup_from_css(css);
        struct mem_cgroup_thresholds *thresholds;
        struct mem_cgroup_threshold_ary *new;
-       enum res_type type = MEMFILE_TYPE(cft->private);
        u64 usage;
        int i, j, size;
 
@@ -5810,14 +5853,23 @@ unlock:
        mutex_unlock(&memcg->thresholds_lock);
 }
 
-static int mem_cgroup_oom_register_event(struct cgroup_subsys_state *css,
-       struct cftype *cft, struct eventfd_ctx *eventfd, const char *args)
+static void mem_cgroup_usage_unregister_event(struct mem_cgroup *memcg,
+       struct eventfd_ctx *eventfd)
+{
+       return __mem_cgroup_usage_unregister_event(memcg, eventfd, _MEM);
+}
+
+static void memsw_cgroup_usage_unregister_event(struct mem_cgroup *memcg,
+       struct eventfd_ctx *eventfd)
+{
+       return __mem_cgroup_usage_unregister_event(memcg, eventfd, _MEMSWAP);
+}
+
+static int mem_cgroup_oom_register_event(struct mem_cgroup *memcg,
+       struct eventfd_ctx *eventfd, const char *args)
 {
-       struct mem_cgroup *memcg = mem_cgroup_from_css(css);
        struct mem_cgroup_eventfd_list *event;
-       enum res_type type = MEMFILE_TYPE(cft->private);
 
-       BUG_ON(type != _OOM_TYPE);
        event = kmalloc(sizeof(*event), GFP_KERNEL);
        if (!event)
                return -ENOMEM;
@@ -5835,14 +5887,10 @@ static int mem_cgroup_oom_register_event(struct cgroup_subsys_state *css,
        return 0;
 }
 
-static void mem_cgroup_oom_unregister_event(struct cgroup_subsys_state *css,
-       struct cftype *cft, struct eventfd_ctx *eventfd)
+static void mem_cgroup_oom_unregister_event(struct mem_cgroup *memcg,
+       struct eventfd_ctx *eventfd)
 {
-       struct mem_cgroup *memcg = mem_cgroup_from_css(css);
        struct mem_cgroup_eventfd_list *ev, *tmp;
-       enum res_type type = MEMFILE_TYPE(cft->private);
-
-       BUG_ON(type != _OOM_TYPE);
 
        spin_lock(&memcg_oom_lock);
 
@@ -5856,17 +5904,12 @@ static void mem_cgroup_oom_unregister_event(struct cgroup_subsys_state *css,
        spin_unlock(&memcg_oom_lock);
 }
 
-static int mem_cgroup_oom_control_read(struct cgroup_subsys_state *css,
-       struct cftype *cft,  struct cgroup_map_cb *cb)
+static int mem_cgroup_oom_control_read(struct seq_file *sf, void *v)
 {
-       struct mem_cgroup *memcg = mem_cgroup_from_css(css);
-
-       cb->fill(cb, "oom_kill_disable", memcg->oom_kill_disable);
+       struct mem_cgroup *memcg = mem_cgroup_from_css(seq_css(sf));
 
-       if (atomic_read(&memcg->under_oom))
-               cb->fill(cb, "under_oom", 1);
-       else
-               cb->fill(cb, "under_oom", 0);
+       seq_printf(sf, "oom_kill_disable %d\n", memcg->oom_kill_disable);
+       seq_printf(sf, "under_oom %d\n", (bool)atomic_read(&memcg->under_oom));
        return 0;
 }
 
@@ -5959,41 +6002,261 @@ static void kmem_cgroup_css_offline(struct mem_cgroup *memcg)
 }
 #endif
 
+/*
+ * DO NOT USE IN NEW FILES.
+ *
+ * "cgroup.event_control" implementation.
+ *
+ * This is way over-engineered.  It tries to support fully configurable
+ * events for each user.  Such level of flexibility is completely
+ * unnecessary especially in the light of the planned unified hierarchy.
+ *
+ * Please deprecate this and replace with something simpler if at all
+ * possible.
+ */
+
+/*
+ * Unregister event and free resources.
+ *
+ * Gets called from workqueue.
+ */
+static void memcg_event_remove(struct work_struct *work)
+{
+       struct mem_cgroup_event *event =
+               container_of(work, struct mem_cgroup_event, remove);
+       struct mem_cgroup *memcg = event->memcg;
+
+       remove_wait_queue(event->wqh, &event->wait);
+
+       event->unregister_event(memcg, event->eventfd);
+
+       /* Notify userspace the event is going away. */
+       eventfd_signal(event->eventfd, 1);
+
+       eventfd_ctx_put(event->eventfd);
+       kfree(event);
+       css_put(&memcg->css);
+}
+
+/*
+ * Gets called on POLLHUP on eventfd when user closes it.
+ *
+ * Called with wqh->lock held and interrupts disabled.
+ */
+static int memcg_event_wake(wait_queue_t *wait, unsigned mode,
+                           int sync, void *key)
+{
+       struct mem_cgroup_event *event =
+               container_of(wait, struct mem_cgroup_event, wait);
+       struct mem_cgroup *memcg = event->memcg;
+       unsigned long flags = (unsigned long)key;
+
+       if (flags & POLLHUP) {
+               /*
+                * If the event has been detached at cgroup removal, we
+                * can simply return knowing the other side will cleanup
+                * for us.
+                *
+                * We can't race against event freeing since the other
+                * side will require wqh->lock via remove_wait_queue(),
+                * which we hold.
+                */
+               spin_lock(&memcg->event_list_lock);
+               if (!list_empty(&event->list)) {
+                       list_del_init(&event->list);
+                       /*
+                        * We are in atomic context, but cgroup_event_remove()
+                        * may sleep, so we have to call it in workqueue.
+                        */
+                       schedule_work(&event->remove);
+               }
+               spin_unlock(&memcg->event_list_lock);
+       }
+
+       return 0;
+}
+
+static void memcg_event_ptable_queue_proc(struct file *file,
+               wait_queue_head_t *wqh, poll_table *pt)
+{
+       struct mem_cgroup_event *event =
+               container_of(pt, struct mem_cgroup_event, pt);
+
+       event->wqh = wqh;
+       add_wait_queue(wqh, &event->wait);
+}
+
+/*
+ * DO NOT USE IN NEW FILES.
+ *
+ * Parse input and register new cgroup event handler.
+ *
+ * Input must be in format '<event_fd> <control_fd> <args>'.
+ * Interpretation of args is defined by control file implementation.
+ */
+static int memcg_write_event_control(struct cgroup_subsys_state *css,
+                                    struct cftype *cft, const char *buffer)
+{
+       struct mem_cgroup *memcg = mem_cgroup_from_css(css);
+       struct mem_cgroup_event *event;
+       struct cgroup_subsys_state *cfile_css;
+       unsigned int efd, cfd;
+       struct fd efile;
+       struct fd cfile;
+       const char *name;
+       char *endp;
+       int ret;
+
+       efd = simple_strtoul(buffer, &endp, 10);
+       if (*endp != ' ')
+               return -EINVAL;
+       buffer = endp + 1;
+
+       cfd = simple_strtoul(buffer, &endp, 10);
+       if ((*endp != ' ') && (*endp != '\0'))
+               return -EINVAL;
+       buffer = endp + 1;
+
+       event = kzalloc(sizeof(*event), GFP_KERNEL);
+       if (!event)
+               return -ENOMEM;
+
+       event->memcg = memcg;
+       INIT_LIST_HEAD(&event->list);
+       init_poll_funcptr(&event->pt, memcg_event_ptable_queue_proc);
+       init_waitqueue_func_entry(&event->wait, memcg_event_wake);
+       INIT_WORK(&event->remove, memcg_event_remove);
+
+       efile = fdget(efd);
+       if (!efile.file) {
+               ret = -EBADF;
+               goto out_kfree;
+       }
+
+       event->eventfd = eventfd_ctx_fileget(efile.file);
+       if (IS_ERR(event->eventfd)) {
+               ret = PTR_ERR(event->eventfd);
+               goto out_put_efile;
+       }
+
+       cfile = fdget(cfd);
+       if (!cfile.file) {
+               ret = -EBADF;
+               goto out_put_eventfd;
+       }
+
+       /* the process need read permission on control file */
+       /* AV: shouldn't we check that it's been opened for read instead? */
+       ret = inode_permission(file_inode(cfile.file), MAY_READ);
+       if (ret < 0)
+               goto out_put_cfile;
+
+       /*
+        * Determine the event callbacks and set them in @event.  This used
+        * to be done via struct cftype but cgroup core no longer knows
+        * about these events.  The following is crude but the whole thing
+        * is for compatibility anyway.
+        *
+        * DO NOT ADD NEW FILES.
+        */
+       name = cfile.file->f_dentry->d_name.name;
+
+       if (!strcmp(name, "memory.usage_in_bytes")) {
+               event->register_event = mem_cgroup_usage_register_event;
+               event->unregister_event = mem_cgroup_usage_unregister_event;
+       } else if (!strcmp(name, "memory.oom_control")) {
+               event->register_event = mem_cgroup_oom_register_event;
+               event->unregister_event = mem_cgroup_oom_unregister_event;
+       } else if (!strcmp(name, "memory.pressure_level")) {
+               event->register_event = vmpressure_register_event;
+               event->unregister_event = vmpressure_unregister_event;
+       } else if (!strcmp(name, "memory.memsw.usage_in_bytes")) {
+               event->register_event = memsw_cgroup_usage_register_event;
+               event->unregister_event = memsw_cgroup_usage_unregister_event;
+       } else {
+               ret = -EINVAL;
+               goto out_put_cfile;
+       }
+
+       /*
+        * Verify @cfile should belong to @css.  Also, remaining events are
+        * automatically removed on cgroup destruction but the removal is
+        * asynchronous, so take an extra ref on @css.
+        */
+       rcu_read_lock();
+
+       ret = -EINVAL;
+       cfile_css = css_from_dir(cfile.file->f_dentry->d_parent,
+                                &mem_cgroup_subsys);
+       if (cfile_css == css && css_tryget(css))
+               ret = 0;
+
+       rcu_read_unlock();
+       if (ret)
+               goto out_put_cfile;
+
+       ret = event->register_event(memcg, event->eventfd, buffer);
+       if (ret)
+               goto out_put_css;
+
+       efile.file->f_op->poll(efile.file, &event->pt);
+
+       spin_lock(&memcg->event_list_lock);
+       list_add(&event->list, &memcg->event_list);
+       spin_unlock(&memcg->event_list_lock);
+
+       fdput(cfile);
+       fdput(efile);
+
+       return 0;
+
+out_put_css:
+       css_put(css);
+out_put_cfile:
+       fdput(cfile);
+out_put_eventfd:
+       eventfd_ctx_put(event->eventfd);
+out_put_efile:
+       fdput(efile);
+out_kfree:
+       kfree(event);
+
+       return ret;
+}
+
 static struct cftype mem_cgroup_files[] = {
        {
                .name = "usage_in_bytes",
                .private = MEMFILE_PRIVATE(_MEM, RES_USAGE),
-               .read = mem_cgroup_read,
-               .register_event = mem_cgroup_usage_register_event,
-               .unregister_event = mem_cgroup_usage_unregister_event,
+               .read_u64 = mem_cgroup_read_u64,
        },
        {
                .name = "max_usage_in_bytes",
                .private = MEMFILE_PRIVATE(_MEM, RES_MAX_USAGE),
                .trigger = mem_cgroup_reset,
-               .read = mem_cgroup_read,
+               .read_u64 = mem_cgroup_read_u64,
        },
        {
                .name = "limit_in_bytes",
                .private = MEMFILE_PRIVATE(_MEM, RES_LIMIT),
                .write_string = mem_cgroup_write,
-               .read = mem_cgroup_read,
+               .read_u64 = mem_cgroup_read_u64,
        },
        {
                .name = "soft_limit_in_bytes",
                .private = MEMFILE_PRIVATE(_MEM, RES_SOFT_LIMIT),
                .write_string = mem_cgroup_write,
-               .read = mem_cgroup_read,
+               .read_u64 = mem_cgroup_read_u64,
        },
        {
                .name = "failcnt",
                .private = MEMFILE_PRIVATE(_MEM, RES_FAILCNT),
                .trigger = mem_cgroup_reset,
-               .read = mem_cgroup_read,
+               .read_u64 = mem_cgroup_read_u64,
        },
        {
                .name = "stat",
-               .read_seq_string = memcg_stat_show,
+               .seq_show = memcg_stat_show,
        },
        {
                .name = "force_empty",
@@ -6005,6 +6268,12 @@ static struct cftype mem_cgroup_files[] = {
                .write_u64 = mem_cgroup_hierarchy_write,
                .read_u64 = mem_cgroup_hierarchy_read,
        },
+       {
+               .name = "cgroup.event_control",         /* XXX: for compat */
+               .write_string = memcg_write_event_control,
+               .flags = CFTYPE_NO_PREFIX,
+               .mode = S_IWUGO,
+       },
        {
                .name = "swappiness",
                .read_u64 = mem_cgroup_swappiness_read,
@@ -6017,21 +6286,17 @@ static struct cftype mem_cgroup_files[] = {
        },
        {
                .name = "oom_control",
-               .read_map = mem_cgroup_oom_control_read,
+               .seq_show = mem_cgroup_oom_control_read,
                .write_u64 = mem_cgroup_oom_control_write,
-               .register_event = mem_cgroup_oom_register_event,
-               .unregister_event = mem_cgroup_oom_unregister_event,
                .private = MEMFILE_PRIVATE(_OOM_TYPE, OOM_CONTROL),
        },
        {
                .name = "pressure_level",
-               .register_event = vmpressure_register_event,
-               .unregister_event = vmpressure_unregister_event,
        },
 #ifdef CONFIG_NUMA
        {
                .name = "numa_stat",
-               .read_seq_string = memcg_numa_stat_show,
+               .seq_show = memcg_numa_stat_show,
        },
 #endif
 #ifdef CONFIG_MEMCG_KMEM
@@ -6039,29 +6304,29 @@ static struct cftype mem_cgroup_files[] = {
                .name = "kmem.limit_in_bytes",
                .private = MEMFILE_PRIVATE(_KMEM, RES_LIMIT),
                .write_string = mem_cgroup_write,
-               .read = mem_cgroup_read,
+               .read_u64 = mem_cgroup_read_u64,
        },
        {
                .name = "kmem.usage_in_bytes",
                .private = MEMFILE_PRIVATE(_KMEM, RES_USAGE),
-               .read = mem_cgroup_read,
+               .read_u64 = mem_cgroup_read_u64,
        },
        {
                .name = "kmem.failcnt",
                .private = MEMFILE_PRIVATE(_KMEM, RES_FAILCNT),
                .trigger = mem_cgroup_reset,
-               .read = mem_cgroup_read,
+               .read_u64 = mem_cgroup_read_u64,
        },
        {
                .name = "kmem.max_usage_in_bytes",
                .private = MEMFILE_PRIVATE(_KMEM, RES_MAX_USAGE),
                .trigger = mem_cgroup_reset,
-               .read = mem_cgroup_read,
+               .read_u64 = mem_cgroup_read_u64,
        },
 #ifdef CONFIG_SLABINFO
        {
                .name = "kmem.slabinfo",
-               .read_seq_string = mem_cgroup_slabinfo_read,
+               .seq_show = mem_cgroup_slabinfo_read,
        },
 #endif
 #endif
@@ -6073,27 +6338,25 @@ static struct cftype memsw_cgroup_files[] = {
        {
                .name = "memsw.usage_in_bytes",
                .private = MEMFILE_PRIVATE(_MEMSWAP, RES_USAGE),
-               .read = mem_cgroup_read,
-               .register_event = mem_cgroup_usage_register_event,
-               .unregister_event = mem_cgroup_usage_unregister_event,
+               .read_u64 = mem_cgroup_read_u64,
        },
        {
                .name = "memsw.max_usage_in_bytes",
                .private = MEMFILE_PRIVATE(_MEMSWAP, RES_MAX_USAGE),
                .trigger = mem_cgroup_reset,
-               .read = mem_cgroup_read,
+               .read_u64 = mem_cgroup_read_u64,
        },
        {
                .name = "memsw.limit_in_bytes",
                .private = MEMFILE_PRIVATE(_MEMSWAP, RES_LIMIT),
                .write_string = mem_cgroup_write,
-               .read = mem_cgroup_read,
+               .read_u64 = mem_cgroup_read_u64,
        },
        {
                .name = "memsw.failcnt",
                .private = MEMFILE_PRIVATE(_MEMSWAP, RES_FAILCNT),
                .trigger = mem_cgroup_reset,
-               .read = mem_cgroup_read,
+               .read_u64 = mem_cgroup_read_u64,
        },
        { },    /* terminate */
 };
@@ -6265,6 +6528,8 @@ mem_cgroup_css_alloc(struct cgroup_subsys_state *parent_css)
        mutex_init(&memcg->thresholds_lock);
        spin_lock_init(&memcg->move_lock);
        vmpressure_init(&memcg->vmpressure);
+       INIT_LIST_HEAD(&memcg->event_list);
+       spin_lock_init(&memcg->event_list_lock);
 
        return &memcg->css;
 
@@ -6340,6 +6605,19 @@ static void mem_cgroup_invalidate_reclaim_iterators(struct mem_cgroup *memcg)
 static void mem_cgroup_css_offline(struct cgroup_subsys_state *css)
 {
        struct mem_cgroup *memcg = mem_cgroup_from_css(css);
+       struct mem_cgroup_event *event, *tmp;
+
+       /*
+        * Unregister events and notify userspace.
+        * Notify userspace about cgroup removing only after rmdir of cgroup
+        * directory to avoid race between userspace and kernelspace.
+        */
+       spin_lock(&memcg->event_list_lock);
+       list_for_each_entry_safe(event, tmp, &memcg->event_list, list) {
+               list_del_init(&event->list);
+               schedule_work(&event->remove);
+       }
+       spin_unlock(&memcg->event_list_lock);
 
        kmem_cgroup_css_offline(memcg);
 
index eca4a3129129751208b41cfe808e9e31e5dc7b5f..9f73b29d304d3f0ced5da23358fecc92de7983b7 100644 (file)
@@ -613,7 +613,7 @@ static inline int queue_pages_pgd_range(struct vm_area_struct *vma,
        return 0;
 }
 
-#ifdef CONFIG_ARCH_USES_NUMA_PROT_NONE
+#ifdef CONFIG_NUMA_BALANCING
 /*
  * This is used to mark a range of virtual addresses to be inaccessible.
  * These are later cleared by a NUMA hinting fault. Depending on these
@@ -627,7 +627,6 @@ unsigned long change_prot_numa(struct vm_area_struct *vma,
                        unsigned long addr, unsigned long end)
 {
        int nr_updated;
-       BUILD_BUG_ON(_PAGE_NUMA != _PAGE_PROTNONE);
 
        nr_updated = change_protection(vma, addr, end, vma->vm_page_prot, 0, 1);
        if (nr_updated)
@@ -641,7 +640,7 @@ static unsigned long change_prot_numa(struct vm_area_struct *vma,
 {
        return 0;
 }
-#endif /* CONFIG_ARCH_USES_NUMA_PROT_NONE */
+#endif /* CONFIG_NUMA_BALANCING */
 
 /*
  * Walk through page tables and collect pages to be migrated.
index 8c79a4764be0c99a1d573d174e2d247e90079519..f14eded987fac8276e3e3da5ff11d260a8ba44cf 100644 (file)
@@ -31,13 +31,13 @@ static struct bio *get_swap_bio(gfp_t gfp_flags,
 
        bio = bio_alloc(gfp_flags, 1);
        if (bio) {
-               bio->bi_sector = map_swap_page(page, &bio->bi_bdev);
-               bio->bi_sector <<= PAGE_SHIFT - 9;
+               bio->bi_iter.bi_sector = map_swap_page(page, &bio->bi_bdev);
+               bio->bi_iter.bi_sector <<= PAGE_SHIFT - 9;
                bio->bi_io_vec[0].bv_page = page;
                bio->bi_io_vec[0].bv_len = PAGE_SIZE;
                bio->bi_io_vec[0].bv_offset = 0;
                bio->bi_vcnt = 1;
-               bio->bi_size = PAGE_SIZE;
+               bio->bi_iter.bi_size = PAGE_SIZE;
                bio->bi_end_io = end_io;
        }
        return bio;
@@ -62,7 +62,7 @@ void end_swap_bio_write(struct bio *bio, int err)
                printk(KERN_ALERT "Write-error on swap-device (%u:%u:%Lu)\n",
                                imajor(bio->bi_bdev->bd_inode),
                                iminor(bio->bi_bdev->bd_inode),
-                               (unsigned long long)bio->bi_sector);
+                               (unsigned long long)bio->bi_iter.bi_sector);
                ClearPageReclaim(page);
        }
        end_page_writeback(page);
@@ -80,7 +80,7 @@ void end_swap_bio_read(struct bio *bio, int err)
                printk(KERN_ALERT "Read-error on swap-device (%u:%u:%Lu)\n",
                                imajor(bio->bi_bdev->bd_inode),
                                iminor(bio->bi_bdev->bd_inode),
-                               (unsigned long long)bio->bi_sector);
+                               (unsigned long long)bio->bi_iter.bi_sector);
                goto out;
        }
 
index e0f62837c3f4873ea2d54c14845c30cb888a386b..196970a4541f0c07108eff49b7cb8d12fd930b06 100644 (file)
@@ -278,8 +278,7 @@ void vmpressure_prio(gfp_t gfp, struct mem_cgroup *memcg, int prio)
 
 /**
  * vmpressure_register_event() - Bind vmpressure notifications to an eventfd
- * @css:       css that is interested in vmpressure notifications
- * @cft:       cgroup control files handle
+ * @memcg:     memcg that is interested in vmpressure notifications
  * @eventfd:   eventfd context to link notifications with
  * @args:      event arguments (used to set up a pressure level threshold)
  *
@@ -289,15 +288,12 @@ void vmpressure_prio(gfp_t gfp, struct mem_cgroup *memcg, int prio)
  * threshold (one of vmpressure_str_levels, i.e. "low", "medium", or
  * "critical").
  *
- * This function should not be used directly, just pass it to (struct
- * cftype).register_event, and then cgroup core will handle everything by
- * itself.
+ * To be used as memcg event method.
  */
-int vmpressure_register_event(struct cgroup_subsys_state *css,
-                             struct cftype *cft, struct eventfd_ctx *eventfd,
-                             const char *args)
+int vmpressure_register_event(struct mem_cgroup *memcg,
+                             struct eventfd_ctx *eventfd, const char *args)
 {
-       struct vmpressure *vmpr = css_to_vmpressure(css);
+       struct vmpressure *vmpr = memcg_to_vmpressure(memcg);
        struct vmpressure_event *ev;
        int level;
 
@@ -325,23 +321,19 @@ int vmpressure_register_event(struct cgroup_subsys_state *css,
 
 /**
  * vmpressure_unregister_event() - Unbind eventfd from vmpressure
- * @css:       css handle
- * @cft:       cgroup control files handle
+ * @memcg:     memcg handle
  * @eventfd:   eventfd context that was used to link vmpressure with the @cg
  *
  * This function does internal manipulations to detach the @eventfd from
  * the vmpressure notifications, and then frees internal resources
  * associated with the @eventfd (but the @eventfd itself is not freed).
  *
- * This function should not be used directly, just pass it to (struct
- * cftype).unregister_event, and then cgroup core will handle everything
- * by itself.
+ * To be used as memcg event method.
  */
-void vmpressure_unregister_event(struct cgroup_subsys_state *css,
-                                struct cftype *cft,
+void vmpressure_unregister_event(struct mem_cgroup *memcg,
                                 struct eventfd_ctx *eventfd)
 {
-       struct vmpressure *vmpr = css_to_vmpressure(css);
+       struct vmpressure *vmpr = memcg_to_vmpressure(memcg);
        struct vmpressure_event *ev;
 
        mutex_lock(&vmpr->events_lock);
index 51a1f530417d35f9d99e18abf7152934cdea1e77..a97a3bde77bb8b8d6a83c7c5407343553db36f7f 100644 (file)
@@ -172,14 +172,14 @@ EXPORT_SYMBOL(hippi_mac_addr);
 int hippi_neigh_setup_dev(struct net_device *dev, struct neigh_parms *p)
 {
        /* Never send broadcast/multicast ARP messages */
-       p->mcast_probes = 0;
+       NEIGH_VAR_SET(p, MCAST_PROBES, 0);
 
        /* In IPv6 unicast probes are valid even on NBMA,
        * because they are encapsulated in normal IPv6 protocol.
        * Should be a generic flag.
        */
        if (p->tbl->family != AF_INET6)
-               p->ucast_probes = 0;
+               NEIGH_VAR_SET(p, UCAST_PROBES, 0);
        return 0;
 }
 EXPORT_SYMBOL(hippi_neigh_setup_dev);
index ee8fd6bd4035b28697db6dacaf3453a3d94a72a3..a5e4d2dcb03e8c98eae243e1dd1b82cea68bd227 100644 (file)
@@ -1011,9 +1011,6 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
        if (err < 0)
                goto destroy_tagpool;
 
-       if (!clnt->trans_mod)
-               clnt->trans_mod = v9fs_get_trans_by_name("virtio");
-
        if (!clnt->trans_mod)
                clnt->trans_mod = v9fs_get_default_trans();
 
index 9321a77630675dacbca66949e7e2e0f75d25deed..b7bd7f2961bf60f49258bd60a702eadd8d651773 100644 (file)
@@ -1048,7 +1048,7 @@ p9_fd_create(struct p9_client *client, const char *addr, char *args)
 static struct p9_trans_module p9_tcp_trans = {
        .name = "tcp",
        .maxsize = MAX_SOCK_BUF,
-       .def = 1,
+       .def = 0,
        .create = p9_fd_create_tcp,
        .close = p9_fd_close,
        .request = p9_fd_request,
index 9c5a1aa34d1253c725af29889d83759946af37c3..cd1e1ede73a45c2516091263c937f45024616c4e 100644 (file)
@@ -698,7 +698,7 @@ static struct p9_trans_module p9_virtio_trans = {
         * page in zero copy.
         */
        .maxsize = PAGE_SIZE * (VIRTQUEUE_NUM - 3),
-       .def = 0,
+       .def = 1,
        .owner = THIS_MODULE,
 };
 
index f94f287b867083e755bd62dcc56af88f30837b33..322dd7323732cf724f1bedbdc0f7d246bff1bb20 100644 (file)
@@ -266,7 +266,7 @@ static inline void batadv_dbg(int type __always_unused,
  */
 static inline int batadv_compare_eth(const void *data1, const void *data2)
 {
-       return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
+       return ether_addr_equal_unaligned(data1, data2);
 }
 
 /**
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
new file mode 100644 (file)
index 0000000..ba840fe
--- /dev/null
@@ -0,0 +1,886 @@
+/*
+   Copyright (c) 2013 Intel Corp.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License version 2 and
+   only version 2 as published by the Free Software Foundation.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+*/
+
+#include <linux/version.h>
+#include <linux/if_arp.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+#include <net/ipv6.h>
+#include <net/ip6_route.h>
+#include <net/addrconf.h>
+
+#include <net/af_ieee802154.h> /* to get the address type */
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+#include <net/bluetooth/l2cap.h>
+
+#include "../ieee802154/6lowpan.h" /* for the compression support */
+
+#define IFACE_NAME_TEMPLATE "bt%d"
+#define EUI64_ADDR_LEN 8
+
+struct skb_cb {
+       struct in6_addr addr;
+       struct l2cap_conn *conn;
+};
+#define lowpan_cb(skb) ((struct skb_cb *)((skb)->cb))
+
+/* The devices list contains those devices that we are acting
+ * as a proxy. The BT 6LoWPAN device is a virtual device that
+ * connects to the Bluetooth LE device. The real connection to
+ * BT device is done via l2cap layer. There exists one
+ * virtual device / one BT 6LoWPAN network (=hciX device).
+ * The list contains struct lowpan_dev elements.
+ */
+static LIST_HEAD(bt_6lowpan_devices);
+static DEFINE_RWLOCK(devices_lock);
+
+struct lowpan_peer {
+       struct list_head list;
+       struct l2cap_conn *conn;
+
+       /* peer addresses in various formats */
+       unsigned char eui64_addr[EUI64_ADDR_LEN];
+       struct in6_addr peer_addr;
+};
+
+struct lowpan_dev {
+       struct list_head list;
+
+       struct hci_dev *hdev;
+       struct net_device *netdev;
+       struct list_head peers;
+       atomic_t peer_count; /* number of items in peers list */
+
+       struct work_struct delete_netdev;
+       struct delayed_work notify_peers;
+};
+
+static inline struct lowpan_dev *lowpan_dev(const struct net_device *netdev)
+{
+       return netdev_priv(netdev);
+}
+
+static inline void peer_add(struct lowpan_dev *dev, struct lowpan_peer *peer)
+{
+       list_add(&peer->list, &dev->peers);
+       atomic_inc(&dev->peer_count);
+}
+
+static inline bool peer_del(struct lowpan_dev *dev, struct lowpan_peer *peer)
+{
+       list_del(&peer->list);
+
+       if (atomic_dec_and_test(&dev->peer_count)) {
+               BT_DBG("last peer");
+               return true;
+       }
+
+       return false;
+}
+
+static inline struct lowpan_peer *peer_lookup_ba(struct lowpan_dev *dev,
+                                                bdaddr_t *ba, __u8 type)
+{
+       struct lowpan_peer *peer, *tmp;
+
+       BT_DBG("peers %d addr %pMR type %d", atomic_read(&dev->peer_count),
+              ba, type);
+
+       list_for_each_entry_safe(peer, tmp, &dev->peers, list) {
+               BT_DBG("addr %pMR type %d",
+                      &peer->conn->hcon->dst, peer->conn->hcon->dst_type);
+
+               if (bacmp(&peer->conn->hcon->dst, ba))
+                       continue;
+
+               if (type == peer->conn->hcon->dst_type)
+                       return peer;
+       }
+
+       return NULL;
+}
+
+static inline struct lowpan_peer *peer_lookup_conn(struct lowpan_dev *dev,
+                                                  struct l2cap_conn *conn)
+{
+       struct lowpan_peer *peer, *tmp;
+
+       list_for_each_entry_safe(peer, tmp, &dev->peers, list) {
+               if (peer->conn == conn)
+                       return peer;
+       }
+
+       return NULL;
+}
+
+static struct lowpan_peer *lookup_peer(struct l2cap_conn *conn)
+{
+       struct lowpan_dev *entry, *tmp;
+       struct lowpan_peer *peer = NULL;
+       unsigned long flags;
+
+       read_lock_irqsave(&devices_lock, flags);
+
+       list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, list) {
+               peer = peer_lookup_conn(entry, conn);
+               if (peer)
+                       break;
+       }
+
+       read_unlock_irqrestore(&devices_lock, flags);
+
+       return peer;
+}
+
+static struct lowpan_dev *lookup_dev(struct l2cap_conn *conn)
+{
+       struct lowpan_dev *entry, *tmp;
+       struct lowpan_dev *dev = NULL;
+       unsigned long flags;
+
+       read_lock_irqsave(&devices_lock, flags);
+
+       list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, list) {
+               if (conn->hcon->hdev == entry->hdev) {
+                       dev = entry;
+                       break;
+               }
+       }
+
+       read_unlock_irqrestore(&devices_lock, flags);
+
+       return dev;
+}
+
+/* print data in line */
+static inline void raw_dump_inline(const char *caller, char *msg,
+                                  unsigned char *buf, int len)
+{
+       if (msg)
+               pr_debug("%s():%s: ", caller, msg);
+
+       print_hex_dump_debug("", DUMP_PREFIX_NONE,
+                            16, 1, buf, len, false);
+}
+
+/* print data in a table format:
+ *
+ * addr: xx xx xx xx xx xx
+ * addr: xx xx xx xx xx xx
+ * ...
+ */
+static inline void raw_dump_table(const char *caller, char *msg,
+                                 unsigned char *buf, int len)
+{
+       if (msg)
+               pr_debug("%s():%s:\n", caller, msg);
+
+       print_hex_dump_debug("\t", DUMP_PREFIX_OFFSET,
+                            16, 1, buf, len, false);
+}
+
+static int give_skb_to_upper(struct sk_buff *skb, struct net_device *dev)
+{
+       struct sk_buff *skb_cp;
+       int ret;
+
+       skb_cp = skb_copy(skb, GFP_ATOMIC);
+       if (!skb_cp)
+               return -ENOMEM;
+
+       ret = netif_rx(skb_cp);
+
+       BT_DBG("receive skb %d", ret);
+       if (ret < 0)
+               return NET_RX_DROP;
+
+       return ret;
+}
+
+static int process_data(struct sk_buff *skb, struct net_device *netdev,
+                       struct l2cap_conn *conn)
+{
+       const u8 *saddr, *daddr;
+       u8 iphc0, iphc1;
+       struct lowpan_dev *dev;
+       struct lowpan_peer *peer;
+       unsigned long flags;
+
+       dev = lowpan_dev(netdev);
+
+       read_lock_irqsave(&devices_lock, flags);
+       peer = peer_lookup_conn(dev, conn);
+       read_unlock_irqrestore(&devices_lock, flags);
+       if (!peer)
+               goto drop;
+
+       saddr = peer->eui64_addr;
+       daddr = dev->netdev->dev_addr;
+
+       /* at least two bytes will be used for the encoding */
+       if (skb->len < 2)
+               goto drop;
+
+       if (lowpan_fetch_skb_u8(skb, &iphc0))
+               goto drop;
+
+       if (lowpan_fetch_skb_u8(skb, &iphc1))
+               goto drop;
+
+       return lowpan_process_data(skb, netdev,
+                                  saddr, IEEE802154_ADDR_LONG, EUI64_ADDR_LEN,
+                                  daddr, IEEE802154_ADDR_LONG, EUI64_ADDR_LEN,
+                                  iphc0, iphc1, give_skb_to_upper);
+
+drop:
+       kfree_skb(skb);
+       return -EINVAL;
+}
+
+static int recv_pkt(struct sk_buff *skb, struct net_device *dev,
+                   struct l2cap_conn *conn)
+{
+       struct sk_buff *local_skb;
+       int ret;
+
+       if (!netif_running(dev))
+               goto drop;
+
+       if (dev->type != ARPHRD_6LOWPAN)
+               goto drop;
+
+       /* check that it's our buffer */
+       if (skb->data[0] == LOWPAN_DISPATCH_IPV6) {
+               /* Copy the packet so that the IPv6 header is
+                * properly aligned.
+                */
+               local_skb = skb_copy_expand(skb, NET_SKB_PAD - 1,
+                                           skb_tailroom(skb), GFP_ATOMIC);
+               if (!local_skb)
+                       goto drop;
+
+               local_skb->protocol = htons(ETH_P_IPV6);
+               local_skb->pkt_type = PACKET_HOST;
+
+               skb_reset_network_header(local_skb);
+               skb_set_transport_header(local_skb, sizeof(struct ipv6hdr));
+
+               if (give_skb_to_upper(local_skb, dev) != NET_RX_SUCCESS) {
+                       kfree_skb(local_skb);
+                       goto drop;
+               }
+
+               dev->stats.rx_bytes += skb->len;
+               dev->stats.rx_packets++;
+
+               kfree_skb(local_skb);
+               kfree_skb(skb);
+       } else {
+               switch (skb->data[0] & 0xe0) {
+               case LOWPAN_DISPATCH_IPHC:      /* ipv6 datagram */
+                       local_skb = skb_clone(skb, GFP_ATOMIC);
+                       if (!local_skb)
+                               goto drop;
+
+                       ret = process_data(local_skb, dev, conn);
+                       if (ret != NET_RX_SUCCESS)
+                               goto drop;
+
+                       dev->stats.rx_bytes += skb->len;
+                       dev->stats.rx_packets++;
+
+                       kfree_skb(skb);
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       return NET_RX_SUCCESS;
+
+drop:
+       kfree_skb(skb);
+       return NET_RX_DROP;
+}
+
+/* Packet from BT LE device */
+int bt_6lowpan_recv(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+       struct lowpan_dev *dev;
+       struct lowpan_peer *peer;
+       int err;
+
+       peer = lookup_peer(conn);
+       if (!peer)
+               return -ENOENT;
+
+       dev = lookup_dev(conn);
+       if (dev && !dev->netdev)
+               return -ENOENT;
+
+       err = recv_pkt(skb, dev->netdev, conn);
+       BT_DBG("recv pkt %d", err);
+
+       return err;
+}
+
+static inline int skbuff_copy(void *msg, int len, int count, int mtu,
+                             struct sk_buff *skb, struct net_device *dev)
+{
+       struct sk_buff **frag;
+       int sent = 0;
+
+       memcpy(skb_put(skb, count), msg, count);
+
+       sent += count;
+       msg  += count;
+       len  -= count;
+
+       dev->stats.tx_bytes += count;
+       dev->stats.tx_packets++;
+
+       raw_dump_table(__func__, "Sending", skb->data, skb->len);
+
+       /* Continuation fragments (no L2CAP header) */
+       frag = &skb_shinfo(skb)->frag_list;
+       while (len > 0) {
+               struct sk_buff *tmp;
+
+               count = min_t(unsigned int, mtu, len);
+
+               tmp = bt_skb_alloc(count, GFP_ATOMIC);
+               if (IS_ERR(tmp))
+                       return PTR_ERR(tmp);
+
+               *frag = tmp;
+
+               memcpy(skb_put(*frag, count), msg, count);
+
+               raw_dump_table(__func__, "Sending fragment",
+                              (*frag)->data, count);
+
+               (*frag)->priority = skb->priority;
+
+               sent += count;
+               msg  += count;
+               len  -= count;
+
+               skb->len += (*frag)->len;
+               skb->data_len += (*frag)->len;
+
+               frag = &(*frag)->next;
+
+               dev->stats.tx_bytes += count;
+               dev->stats.tx_packets++;
+       }
+
+       return sent;
+}
+
+static struct sk_buff *create_pdu(struct l2cap_conn *conn, void *msg,
+                                 size_t len, u32 priority,
+                                 struct net_device *dev)
+{
+       struct sk_buff *skb;
+       int err, count;
+       struct l2cap_hdr *lh;
+
+       /* FIXME: This mtu check should be not needed and atm is only used for
+        * testing purposes
+        */
+       if (conn->mtu > (L2CAP_LE_MIN_MTU + L2CAP_HDR_SIZE))
+               conn->mtu = L2CAP_LE_MIN_MTU + L2CAP_HDR_SIZE;
+
+       count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len);
+
+       BT_DBG("conn %p len %zu mtu %d count %d", conn, len, conn->mtu, count);
+
+       skb = bt_skb_alloc(count + L2CAP_HDR_SIZE, GFP_ATOMIC);
+       if (IS_ERR(skb))
+               return skb;
+
+       skb->priority = priority;
+
+       lh = (struct l2cap_hdr *)skb_put(skb, L2CAP_HDR_SIZE);
+       lh->cid = cpu_to_le16(L2CAP_FC_6LOWPAN);
+       lh->len = cpu_to_le16(len);
+
+       err = skbuff_copy(msg, len, count, conn->mtu, skb, dev);
+       if (unlikely(err < 0)) {
+               kfree_skb(skb);
+               BT_DBG("skbuff copy %d failed", err);
+               return ERR_PTR(err);
+       }
+
+       return skb;
+}
+
+static int conn_send(struct l2cap_conn *conn,
+                    void *msg, size_t len, u32 priority,
+                    struct net_device *dev)
+{
+       struct sk_buff *skb;
+
+       skb = create_pdu(conn, msg, len, priority, dev);
+       if (IS_ERR(skb))
+               return -EINVAL;
+
+       BT_DBG("conn %p skb %p len %d priority %u", conn, skb, skb->len,
+              skb->priority);
+
+       hci_send_acl(conn->hchan, skb, ACL_START);
+
+       return 0;
+}
+
+static void get_dest_bdaddr(struct in6_addr *ip6_daddr,
+                           bdaddr_t *addr, u8 *addr_type)
+{
+       u8 *eui64;
+
+       eui64 = ip6_daddr->s6_addr + 8;
+
+       addr->b[0] = eui64[7];
+       addr->b[1] = eui64[6];
+       addr->b[2] = eui64[5];
+       addr->b[3] = eui64[2];
+       addr->b[4] = eui64[1];
+       addr->b[5] = eui64[0];
+
+       addr->b[5] ^= 2;
+
+       /* Set universal/local bit to 0 */
+       if (addr->b[5] & 1) {
+               addr->b[5] &= ~1;
+               *addr_type = BDADDR_LE_PUBLIC;
+       } else {
+               *addr_type = BDADDR_LE_RANDOM;
+       }
+}
+
+static int header_create(struct sk_buff *skb, struct net_device *netdev,
+                        unsigned short type, const void *_daddr,
+                        const void *_saddr, unsigned int len)
+{
+       struct ipv6hdr *hdr;
+       struct lowpan_dev *dev;
+       struct lowpan_peer *peer;
+       bdaddr_t addr, *any = BDADDR_ANY;
+       u8 *saddr, *daddr = any->b;
+       u8 addr_type;
+
+       if (type != ETH_P_IPV6)
+               return -EINVAL;
+
+       hdr = ipv6_hdr(skb);
+
+       dev = lowpan_dev(netdev);
+
+       if (ipv6_addr_is_multicast(&hdr->daddr)) {
+               memcpy(&lowpan_cb(skb)->addr, &hdr->daddr,
+                      sizeof(struct in6_addr));
+               lowpan_cb(skb)->conn = NULL;
+       } else {
+               unsigned long flags;
+
+               /* Get destination BT device from skb.
+                * If there is no such peer then discard the packet.
+                */
+               get_dest_bdaddr(&hdr->daddr, &addr, &addr_type);
+
+               BT_DBG("dest addr %pMR type %d", &addr, addr_type);
+
+               read_lock_irqsave(&devices_lock, flags);
+               peer = peer_lookup_ba(dev, &addr, addr_type);
+               read_unlock_irqrestore(&devices_lock, flags);
+
+               if (!peer) {
+                       BT_DBG("no such peer %pMR found", &addr);
+                       return -ENOENT;
+               }
+
+               daddr = peer->eui64_addr;
+
+               memcpy(&lowpan_cb(skb)->addr, &hdr->daddr,
+                      sizeof(struct in6_addr));
+               lowpan_cb(skb)->conn = peer->conn;
+       }
+
+       saddr = dev->netdev->dev_addr;
+
+       return lowpan_header_compress(skb, netdev, type, daddr, saddr, len);
+}
+
+/* Packet to BT LE device */
+static int send_pkt(struct l2cap_conn *conn, const void *saddr,
+                   const void *daddr, struct sk_buff *skb,
+                   struct net_device *netdev)
+{
+       raw_dump_table(__func__, "raw skb data dump before fragmentation",
+                      skb->data, skb->len);
+
+       return conn_send(conn, skb->data, skb->len, 0, netdev);
+}
+
+static void send_mcast_pkt(struct sk_buff *skb, struct net_device *netdev)
+{
+       struct sk_buff *local_skb;
+       struct lowpan_dev *entry, *tmp;
+       unsigned long flags;
+
+       read_lock_irqsave(&devices_lock, flags);
+
+       list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, list) {
+               struct lowpan_peer *pentry, *ptmp;
+               struct lowpan_dev *dev;
+
+               if (entry->netdev != netdev)
+                       continue;
+
+               dev = lowpan_dev(entry->netdev);
+
+               list_for_each_entry_safe(pentry, ptmp, &dev->peers, list) {
+                       local_skb = skb_clone(skb, GFP_ATOMIC);
+
+                       send_pkt(pentry->conn, netdev->dev_addr,
+                                pentry->eui64_addr, local_skb, netdev);
+
+                       kfree_skb(local_skb);
+               }
+       }
+
+       read_unlock_irqrestore(&devices_lock, flags);
+}
+
+static netdev_tx_t bt_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+       int err = 0;
+       unsigned char *eui64_addr;
+       struct lowpan_dev *dev;
+       struct lowpan_peer *peer;
+       bdaddr_t addr;
+       u8 addr_type;
+
+       if (ipv6_addr_is_multicast(&lowpan_cb(skb)->addr)) {
+               /* We need to send the packet to every device
+                * behind this interface.
+                */
+               send_mcast_pkt(skb, netdev);
+       } else {
+               unsigned long flags;
+
+               get_dest_bdaddr(&lowpan_cb(skb)->addr, &addr, &addr_type);
+               eui64_addr = lowpan_cb(skb)->addr.s6_addr + 8;
+               dev = lowpan_dev(netdev);
+
+               read_lock_irqsave(&devices_lock, flags);
+               peer = peer_lookup_ba(dev, &addr, addr_type);
+               read_unlock_irqrestore(&devices_lock, flags);
+
+               BT_DBG("xmit from %s to %pMR (%pI6c) peer %p", netdev->name,
+                      &addr, &lowpan_cb(skb)->addr, peer);
+
+               if (peer && peer->conn)
+                       err = send_pkt(peer->conn, netdev->dev_addr,
+                                      eui64_addr, skb, netdev);
+       }
+       dev_kfree_skb(skb);
+
+       if (err)
+               BT_DBG("ERROR: xmit failed (%d)", err);
+
+       return (err < 0) ? NET_XMIT_DROP : err;
+}
+
+static const struct net_device_ops netdev_ops = {
+       .ndo_start_xmit         = bt_xmit,
+};
+
+static struct header_ops header_ops = {
+       .create = header_create,
+};
+
+static void netdev_setup(struct net_device *dev)
+{
+       dev->addr_len           = EUI64_ADDR_LEN;
+       dev->type               = ARPHRD_6LOWPAN;
+
+       dev->hard_header_len    = 0;
+       dev->needed_tailroom    = 0;
+       dev->mtu                = IPV6_MIN_MTU;
+       dev->tx_queue_len       = 0;
+       dev->flags              = IFF_RUNNING | IFF_POINTOPOINT;
+       dev->watchdog_timeo     = 0;
+
+       dev->netdev_ops         = &netdev_ops;
+       dev->header_ops         = &header_ops;
+       dev->destructor         = free_netdev;
+}
+
+static struct device_type bt_type = {
+       .name   = "bluetooth",
+};
+
+static void set_addr(u8 *eui, u8 *addr, u8 addr_type)
+{
+       /* addr is the BT address in little-endian format */
+       eui[0] = addr[5];
+       eui[1] = addr[4];
+       eui[2] = addr[3];
+       eui[3] = 0xFF;
+       eui[4] = 0xFE;
+       eui[5] = addr[2];
+       eui[6] = addr[1];
+       eui[7] = addr[0];
+
+       eui[0] ^= 2;
+
+       /* Universal/local bit set, RFC 4291 */
+       if (addr_type == BDADDR_LE_PUBLIC)
+               eui[0] |= 1;
+       else
+               eui[0] &= ~1;
+}
+
+static void set_dev_addr(struct net_device *netdev, bdaddr_t *addr,
+                        u8 addr_type)
+{
+       netdev->addr_assign_type = NET_ADDR_PERM;
+       set_addr(netdev->dev_addr, addr->b, addr_type);
+       netdev->dev_addr[0] ^= 2;
+}
+
+static void ifup(struct net_device *netdev)
+{
+       int err;
+
+       rtnl_lock();
+       err = dev_open(netdev);
+       if (err < 0)
+               BT_INFO("iface %s cannot be opened (%d)", netdev->name, err);
+       rtnl_unlock();
+}
+
+static void do_notify_peers(struct work_struct *work)
+{
+       struct lowpan_dev *dev = container_of(work, struct lowpan_dev,
+                                             notify_peers.work);
+
+       netdev_notify_peers(dev->netdev); /* send neighbour adv at startup */
+}
+
+static bool is_bt_6lowpan(struct hci_conn *hcon)
+{
+       if (hcon->type != LE_LINK)
+               return false;
+
+       return test_bit(HCI_CONN_6LOWPAN, &hcon->flags);
+}
+
+static int add_peer_conn(struct l2cap_conn *conn, struct lowpan_dev *dev)
+{
+       struct lowpan_peer *peer;
+       unsigned long flags;
+
+       peer = kzalloc(sizeof(*peer), GFP_ATOMIC);
+       if (!peer)
+               return -ENOMEM;
+
+       peer->conn = conn;
+       memset(&peer->peer_addr, 0, sizeof(struct in6_addr));
+
+       /* RFC 2464 ch. 5 */
+       peer->peer_addr.s6_addr[0] = 0xFE;
+       peer->peer_addr.s6_addr[1] = 0x80;
+       set_addr((u8 *)&peer->peer_addr.s6_addr + 8, conn->hcon->dst.b,
+                conn->hcon->dst_type);
+
+       memcpy(&peer->eui64_addr, (u8 *)&peer->peer_addr.s6_addr + 8,
+              EUI64_ADDR_LEN);
+       peer->eui64_addr[0] ^= 2; /* second bit-flip (Universe/Local)
+                                  * is done according RFC2464
+                                  */
+
+       raw_dump_inline(__func__, "peer IPv6 address",
+                       (unsigned char *)&peer->peer_addr, 16);
+       raw_dump_inline(__func__, "peer EUI64 address", peer->eui64_addr, 8);
+
+       write_lock_irqsave(&devices_lock, flags);
+       INIT_LIST_HEAD(&peer->list);
+       peer_add(dev, peer);
+       write_unlock_irqrestore(&devices_lock, flags);
+
+       /* Notifying peers about us needs to be done without locks held */
+       INIT_DELAYED_WORK(&dev->notify_peers, do_notify_peers);
+       schedule_delayed_work(&dev->notify_peers, msecs_to_jiffies(100));
+
+       return 0;
+}
+
+/* This gets called when BT LE 6LoWPAN device is connected. We then
+ * create network device that acts as a proxy between BT LE device
+ * and kernel network stack.
+ */
+int bt_6lowpan_add_conn(struct l2cap_conn *conn)
+{
+       struct lowpan_peer *peer = NULL;
+       struct lowpan_dev *dev;
+       struct net_device *netdev;
+       int err = 0;
+       unsigned long flags;
+
+       if (!is_bt_6lowpan(conn->hcon))
+               return 0;
+
+       peer = lookup_peer(conn);
+       if (peer)
+               return -EEXIST;
+
+       dev = lookup_dev(conn);
+       if (dev)
+               return add_peer_conn(conn, dev);
+
+       netdev = alloc_netdev(sizeof(*dev), IFACE_NAME_TEMPLATE, netdev_setup);
+       if (!netdev)
+               return -ENOMEM;
+
+       set_dev_addr(netdev, &conn->hcon->src, conn->hcon->src_type);
+
+       netdev->netdev_ops = &netdev_ops;
+       SET_NETDEV_DEV(netdev, &conn->hcon->dev);
+       SET_NETDEV_DEVTYPE(netdev, &bt_type);
+
+       err = register_netdev(netdev);
+       if (err < 0) {
+               BT_INFO("register_netdev failed %d", err);
+               free_netdev(netdev);
+               goto out;
+       }
+
+       BT_DBG("ifindex %d peer bdaddr %pMR my addr %pMR",
+              netdev->ifindex, &conn->hcon->dst, &conn->hcon->src);
+       set_bit(__LINK_STATE_PRESENT, &netdev->state);
+
+       dev = netdev_priv(netdev);
+       dev->netdev = netdev;
+       dev->hdev = conn->hcon->hdev;
+       INIT_LIST_HEAD(&dev->peers);
+
+       write_lock_irqsave(&devices_lock, flags);
+       INIT_LIST_HEAD(&dev->list);
+       list_add(&dev->list, &bt_6lowpan_devices);
+       write_unlock_irqrestore(&devices_lock, flags);
+
+       ifup(netdev);
+
+       return add_peer_conn(conn, dev);
+
+out:
+       return err;
+}
+
+static void delete_netdev(struct work_struct *work)
+{
+       struct lowpan_dev *entry = container_of(work, struct lowpan_dev,
+                                               delete_netdev);
+
+       unregister_netdev(entry->netdev);
+
+       /* The entry pointer is deleted in device_event() */
+}
+
+int bt_6lowpan_del_conn(struct l2cap_conn *conn)
+{
+       struct lowpan_dev *entry, *tmp;
+       struct lowpan_dev *dev = NULL;
+       struct lowpan_peer *peer;
+       int err = -ENOENT;
+       unsigned long flags;
+       bool last = false;
+
+       if (!is_bt_6lowpan(conn->hcon))
+               return 0;
+
+       write_lock_irqsave(&devices_lock, flags);
+
+       list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, list) {
+               dev = lowpan_dev(entry->netdev);
+               peer = peer_lookup_conn(dev, conn);
+               if (peer) {
+                       last = peer_del(dev, peer);
+                       err = 0;
+                       break;
+               }
+       }
+
+       if (!err && last && dev && !atomic_read(&dev->peer_count)) {
+               write_unlock_irqrestore(&devices_lock, flags);
+
+               cancel_delayed_work_sync(&dev->notify_peers);
+
+               /* bt_6lowpan_del_conn() is called with hci dev lock held which
+                * means that we must delete the netdevice in worker thread.
+                */
+               INIT_WORK(&entry->delete_netdev, delete_netdev);
+               schedule_work(&entry->delete_netdev);
+       } else {
+               write_unlock_irqrestore(&devices_lock, flags);
+       }
+
+       return err;
+}
+
+static int device_event(struct notifier_block *unused,
+                       unsigned long event, void *ptr)
+{
+       struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
+       struct lowpan_dev *entry, *tmp;
+       unsigned long flags;
+
+       if (netdev->type != ARPHRD_6LOWPAN)
+               return NOTIFY_DONE;
+
+       switch (event) {
+       case NETDEV_UNREGISTER:
+               write_lock_irqsave(&devices_lock, flags);
+               list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices,
+                                        list) {
+                       if (entry->netdev == netdev) {
+                               list_del(&entry->list);
+                               kfree(entry);
+                               break;
+                       }
+               }
+               write_unlock_irqrestore(&devices_lock, flags);
+               break;
+       }
+
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block bt_6lowpan_dev_notifier = {
+       .notifier_call = device_event,
+};
+
+int bt_6lowpan_init(void)
+{
+       return register_netdevice_notifier(&bt_6lowpan_dev_notifier);
+}
+
+void bt_6lowpan_cleanup(void)
+{
+       unregister_netdevice_notifier(&bt_6lowpan_dev_notifier);
+}
diff --git a/net/bluetooth/6lowpan.h b/net/bluetooth/6lowpan.h
new file mode 100644 (file)
index 0000000..680eac8
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+   Copyright (c) 2013 Intel Corp.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License version 2 and
+   only version 2 as published by the Free Software Foundation.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+*/
+
+#ifndef __6LOWPAN_H
+#define __6LOWPAN_H
+
+#include <linux/skbuff.h>
+#include <net/bluetooth/l2cap.h>
+
+int bt_6lowpan_recv(struct l2cap_conn *conn, struct sk_buff *skb);
+int bt_6lowpan_add_conn(struct l2cap_conn *conn);
+int bt_6lowpan_del_conn(struct l2cap_conn *conn);
+int bt_6lowpan_init(void);
+void bt_6lowpan_cleanup(void);
+
+#endif /* __6LOWPAN_H */
index 6a791e73e39d936f0d9958d506c540c5a2805727..cc6827e2ce68b093be549a1be17b7159b23c1ddc 100644 (file)
@@ -10,6 +10,10 @@ obj-$(CONFIG_BT_HIDP)        += hidp/
 
 bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \
        hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o sco.o lib.o \
-       a2mp.o amp.o
+       a2mp.o amp.o 6lowpan.o
+
+ifeq ($(CONFIG_IEEE802154_6LOWPAN),)
+  bluetooth-y +=  ../ieee802154/6lowpan_iphc.o
+endif
 
 subdir-ccflags-y += -D__CHECK_ENDIAN__
index 56ca494621c66e76465aaada6be27d5f6820e33e..0c5866bb49b6fc8933b01d0e5ed0c9d3f8564c63 100644 (file)
@@ -31,7 +31,7 @@
 #include <net/bluetooth/bluetooth.h>
 #include <linux/proc_fs.h>
 
-#define VERSION "2.17"
+#define VERSION "2.18"
 
 /* Bluetooth sockets */
 #define BT_MAX_PROTO   8
index e7ee5314f39a1e6a611dd3f0bd59c10c012ae699..5a5b16f365e9baae89f345b22930f1109e5f0b4c 100644 (file)
@@ -12,8 +12,7 @@
   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
+  along with this program; if not, see <http://www.gnu.org/licenses/>.
 */
 
 #ifndef _BNEP_H
index 6ccc4eb9e55e4958f3eb070894a7668b05c98b5b..b23d40385f18aefb0de5fb4cce337e5f7a3e1bda 100644 (file)
@@ -636,6 +636,49 @@ static int conn_max_interval_get(void *data, u64 *val)
 DEFINE_SIMPLE_ATTRIBUTE(conn_max_interval_fops, conn_max_interval_get,
                        conn_max_interval_set, "%llu\n");
 
+static ssize_t lowpan_read(struct file *file, char __user *user_buf,
+                          size_t count, loff_t *ppos)
+{
+       struct hci_dev *hdev = file->private_data;
+       char buf[3];
+
+       buf[0] = test_bit(HCI_6LOWPAN_ENABLED, &hdev->dev_flags) ? 'Y' : 'N';
+       buf[1] = '\n';
+       buf[2] = '\0';
+       return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
+}
+
+static ssize_t lowpan_write(struct file *fp, const char __user *user_buffer,
+                           size_t count, loff_t *position)
+{
+       struct hci_dev *hdev = fp->private_data;
+       bool enable;
+       char buf[32];
+       size_t buf_size = min(count, (sizeof(buf)-1));
+
+       if (copy_from_user(buf, user_buffer, buf_size))
+               return -EFAULT;
+
+       buf[buf_size] = '\0';
+
+       if (strtobool(buf, &enable) < 0)
+               return -EINVAL;
+
+       if (enable == test_bit(HCI_6LOWPAN_ENABLED, &hdev->dev_flags))
+               return -EALREADY;
+
+       change_bit(HCI_6LOWPAN_ENABLED, &hdev->dev_flags);
+
+       return count;
+}
+
+static const struct file_operations lowpan_debugfs_fops = {
+       .open           = simple_open,
+       .read           = lowpan_read,
+       .write          = lowpan_write,
+       .llseek         = default_llseek,
+};
+
 /* ---- HCI requests ---- */
 
 static void hci_req_sync_complete(struct hci_dev *hdev, u8 result)
@@ -1228,7 +1271,7 @@ static void hci_set_event_mask_page_2(struct hci_request *req)
        /* If Connectionless Slave Broadcast master role is supported
         * enable all necessary events for it.
         */
-       if (hdev->features[2][0] & 0x01) {
+       if (lmp_csb_master_capable(hdev)) {
                events[1] |= 0x40;      /* Triggered Clock Capture */
                events[1] |= 0x80;      /* Synchronization Train Complete */
                events[2] |= 0x10;      /* Slave Page Response Timeout */
@@ -1238,7 +1281,7 @@ static void hci_set_event_mask_page_2(struct hci_request *req)
        /* If Connectionless Slave Broadcast slave role is supported
         * enable all necessary events for it.
         */
-       if (hdev->features[2][0] & 0x02) {
+       if (lmp_csb_slave_capable(hdev)) {
                events[2] |= 0x01;      /* Synchronization Train Received */
                events[2] |= 0x02;      /* CSB Receive */
                events[2] |= 0x04;      /* CSB Timeout */
@@ -1275,15 +1318,17 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt)
                hci_setup_link_policy(req);
 
        if (lmp_le_capable(hdev)) {
-               /* If the controller has a public BD_ADDR, then by
-                * default use that one. If this is a LE only
-                * controller without one, default to the random
-                * address.
-                */
-               if (bacmp(&hdev->bdaddr, BDADDR_ANY))
-                       hdev->own_addr_type = ADDR_LE_DEV_PUBLIC;
-               else
-                       hdev->own_addr_type = ADDR_LE_DEV_RANDOM;
+               if (test_bit(HCI_SETUP, &hdev->dev_flags)) {
+                       /* If the controller has a public BD_ADDR, then
+                        * by default use that one. If this is a LE only
+                        * controller without a public address, default
+                        * to the random address.
+                        */
+                       if (bacmp(&hdev->bdaddr, BDADDR_ANY))
+                               hdev->own_addr_type = ADDR_LE_DEV_PUBLIC;
+                       else
+                               hdev->own_addr_type = ADDR_LE_DEV_RANDOM;
+               }
 
                hci_set_le_support(req);
        }
@@ -1307,7 +1352,7 @@ static void hci_init4_req(struct hci_request *req, unsigned long opt)
                hci_set_event_mask_page_2(req);
 
        /* Check for Synchronization Train support */
-       if (hdev->features[2][0] & 0x04)
+       if (lmp_sync_train_capable(hdev))
                hci_req_add(req, HCI_OP_READ_SYNC_TRAIN_PARAMS, 0, NULL);
 }
 
@@ -1404,6 +1449,8 @@ static int __hci_init(struct hci_dev *hdev)
                                    hdev, &conn_min_interval_fops);
                debugfs_create_file("conn_max_interval", 0644, hdev->debugfs,
                                    hdev, &conn_max_interval_fops);
+               debugfs_create_file("6lowpan", 0644, hdev->debugfs, hdev,
+                                   &lowpan_debugfs_fops);
        }
 
        return 0;
index 5935f748c0f9a6fe71cb3c0fe8baeaedb7019c37..5f812455a4504260927cb2dd5a3bdc018e0e20d4 100644 (file)
@@ -486,7 +486,10 @@ static void hci_cc_read_local_commands(struct hci_dev *hdev,
 
        BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
 
-       if (!rp->status)
+       if (rp->status)
+               return;
+
+       if (test_bit(HCI_SETUP, &hdev->dev_flags))
                memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
 }
 
@@ -538,12 +541,6 @@ static void hci_cc_read_local_features(struct hci_dev *hdev,
 
        if (hdev->features[0][5] & LMP_EDR_3S_ESCO)
                hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
-
-       BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name,
-              hdev->features[0][0], hdev->features[0][1],
-              hdev->features[0][2], hdev->features[0][3],
-              hdev->features[0][4], hdev->features[0][5],
-              hdev->features[0][6], hdev->features[0][7]);
 }
 
 static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
@@ -1782,7 +1779,9 @@ static u8 hci_to_mgmt_reason(u8 err)
 static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
        struct hci_ev_disconn_complete *ev = (void *) skb->data;
+       u8 reason = hci_to_mgmt_reason(ev->reason);
        struct hci_conn *conn;
+       u8 type;
 
        BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
 
@@ -1792,43 +1791,38 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
        if (!conn)
                goto unlock;
 
-       if (ev->status == 0)
-               conn->state = BT_CLOSED;
+       if (ev->status) {
+               mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
+                                      conn->dst_type, ev->status);
+               goto unlock;
+       }
 
-       if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
-           (conn->type == ACL_LINK || conn->type == LE_LINK)) {
-               if (ev->status) {
-                       mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
-                                              conn->dst_type, ev->status);
-               } else {
-                       u8 reason = hci_to_mgmt_reason(ev->reason);
+       conn->state = BT_CLOSED;
 
-                       mgmt_device_disconnected(hdev, &conn->dst, conn->type,
-                                                conn->dst_type, reason);
-               }
-       }
+       if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
+               mgmt_device_disconnected(hdev, &conn->dst, conn->type,
+                                        conn->dst_type, reason);
 
-       if (ev->status == 0) {
-               u8 type = conn->type;
+       if (conn->type == ACL_LINK && conn->flush_key)
+               hci_remove_link_key(hdev, &conn->dst);
 
-               if (type == ACL_LINK && conn->flush_key)
-                       hci_remove_link_key(hdev, &conn->dst);
-               hci_proto_disconn_cfm(conn, ev->reason);
-               hci_conn_del(conn);
+       type = conn->type;
 
-               /* Re-enable advertising if necessary, since it might
-                * have been disabled by the connection. From the
-                * HCI_LE_Set_Advertise_Enable command description in
-                * the core specification (v4.0):
-                * "The Controller shall continue advertising until the Host
-                * issues an LE_Set_Advertise_Enable command with
-                * Advertising_Enable set to 0x00 (Advertising is disabled)
-                * or until a connection is created or until the Advertising
-                * is timed out due to Directed Advertising."
-                */
-               if (type == LE_LINK)
-                       mgmt_reenable_advertising(hdev);
-       }
+       hci_proto_disconn_cfm(conn, ev->reason);
+       hci_conn_del(conn);
+
+       /* Re-enable advertising if necessary, since it might
+        * have been disabled by the connection. From the
+        * HCI_LE_Set_Advertise_Enable command description in
+        * the core specification (v4.0):
+        * "The Controller shall continue advertising until the Host
+        * issues an LE_Set_Advertise_Enable command with
+        * Advertising_Enable set to 0x00 (Advertising is disabled)
+        * or until a connection is created or until the Advertising
+        * is timed out due to Directed Advertising."
+        */
+       if (type == LE_LINK)
+               mgmt_reenable_advertising(hdev);
 
 unlock:
        hci_dev_unlock(hdev);
@@ -3539,6 +3533,9 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
        conn->handle = __le16_to_cpu(ev->handle);
        conn->state = BT_CONNECTED;
 
+       if (test_bit(HCI_6LOWPAN_ENABLED, &hdev->dev_flags))
+               set_bit(HCI_CONN_6LOWPAN, &conn->flags);
+
        hci_conn_add_sysfs(conn);
 
        hci_proto_connect_cfm(conn, ev->status);
index 4af3821df880f70dd17cd36161eff766c3e49334..b0ad2c752d738039cff8ec32c028dd109a10388b 100644 (file)
@@ -40,6 +40,7 @@
 #include "smp.h"
 #include "a2mp.h"
 #include "amp.h"
+#include "6lowpan.h"
 
 bool disable_ertm;
 
@@ -49,6 +50,9 @@ static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP | L2CAP_FC_CONNLESS, };
 static LIST_HEAD(chan_list);
 static DEFINE_RWLOCK(chan_list_lock);
 
+static u16 le_max_credits = L2CAP_LE_MAX_CREDITS;
+static u16 le_default_mps = L2CAP_LE_DEFAULT_MPS;
+
 static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
                                       u8 code, u8 ident, u16 dlen, void *data);
 static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
@@ -213,9 +217,14 @@ int l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid)
 
 static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
 {
-       u16 cid = L2CAP_CID_DYN_START;
+       u16 cid, dyn_end;
+
+       if (conn->hcon->type == LE_LINK)
+               dyn_end = L2CAP_CID_LE_DYN_END;
+       else
+               dyn_end = L2CAP_CID_DYN_END;
 
-       for (; cid < L2CAP_CID_DYN_END; cid++) {
+       for (cid = L2CAP_CID_DYN_START; cid < dyn_end; cid++) {
                if (!__l2cap_get_chan_by_scid(conn, cid))
                        return cid;
        }
@@ -490,6 +499,18 @@ void l2cap_chan_set_defaults(struct l2cap_chan *chan)
        set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
 }
 
+static void l2cap_le_flowctl_init(struct l2cap_chan *chan)
+{
+       chan->sdu = NULL;
+       chan->sdu_last_frag = NULL;
+       chan->sdu_len = 0;
+       chan->tx_credits = 0;
+       chan->rx_credits = le_max_credits;
+       chan->mps = min_t(u16, chan->imtu, L2CAP_LE_DEFAULT_MPS);
+
+       skb_queue_head_init(&chan->tx_q);
+}
+
 void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
 {
        BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
@@ -502,12 +523,12 @@ void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
        switch (chan->chan_type) {
        case L2CAP_CHAN_CONN_ORIENTED:
                if (conn->hcon->type == LE_LINK) {
-                       /* LE connection */
-                       chan->omtu = L2CAP_DEFAULT_MTU;
-                       if (chan->dcid == L2CAP_CID_ATT)
+                       if (chan->dcid == L2CAP_CID_ATT) {
+                               chan->omtu = L2CAP_DEFAULT_MTU;
                                chan->scid = L2CAP_CID_ATT;
-                       else
+                       } else {
                                chan->scid = l2cap_alloc_cid(conn);
+                       }
                } else {
                        /* Alloc CID for connection-oriented socket */
                        chan->scid = l2cap_alloc_cid(conn);
@@ -597,6 +618,10 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
        case L2CAP_MODE_BASIC:
                break;
 
+       case L2CAP_MODE_LE_FLOWCTL:
+               skb_queue_purge(&chan->tx_q);
+               break;
+
        case L2CAP_MODE_ERTM:
                __clear_retrans_timer(chan);
                __clear_monitor_timer(chan);
@@ -617,6 +642,50 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
        return;
 }
 
+static void l2cap_chan_le_connect_reject(struct l2cap_chan *chan)
+{
+       struct l2cap_conn *conn = chan->conn;
+       struct l2cap_le_conn_rsp rsp;
+       u16 result;
+
+       if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
+               result = L2CAP_CR_AUTHORIZATION;
+       else
+               result = L2CAP_CR_BAD_PSM;
+
+       l2cap_state_change(chan, BT_DISCONN);
+
+       rsp.dcid    = cpu_to_le16(chan->scid);
+       rsp.mtu     = cpu_to_le16(chan->imtu);
+       rsp.mps     = cpu_to_le16(chan->mps);
+       rsp.credits = cpu_to_le16(chan->rx_credits);
+       rsp.result  = cpu_to_le16(result);
+
+       l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
+                      &rsp);
+}
+
+static void l2cap_chan_connect_reject(struct l2cap_chan *chan)
+{
+       struct l2cap_conn *conn = chan->conn;
+       struct l2cap_conn_rsp rsp;
+       u16 result;
+
+       if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
+               result = L2CAP_CR_SEC_BLOCK;
+       else
+               result = L2CAP_CR_BAD_PSM;
+
+       l2cap_state_change(chan, BT_DISCONN);
+
+       rsp.scid   = cpu_to_le16(chan->dcid);
+       rsp.dcid   = cpu_to_le16(chan->scid);
+       rsp.result = cpu_to_le16(result);
+       rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
+
+       l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
+}
+
 void l2cap_chan_close(struct l2cap_chan *chan, int reason)
 {
        struct l2cap_conn *conn = chan->conn;
@@ -630,8 +699,10 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason)
 
        case BT_CONNECTED:
        case BT_CONFIG:
-               if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
-                   conn->hcon->type == ACL_LINK) {
+               /* ATT uses L2CAP_CHAN_CONN_ORIENTED so we must also
+                * check for chan->psm.
+                */
+               if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && chan->psm) {
                        __set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
                        l2cap_send_disconn_req(chan, reason);
                } else
@@ -639,24 +710,11 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason)
                break;
 
        case BT_CONNECT2:
-               if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
-                   conn->hcon->type == ACL_LINK) {
-                       struct l2cap_conn_rsp rsp;
-                       __u16 result;
-
-                       if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
-                               result = L2CAP_CR_SEC_BLOCK;
-                       else
-                               result = L2CAP_CR_BAD_PSM;
-
-                       l2cap_state_change(chan, BT_DISCONN);
-
-                       rsp.scid   = cpu_to_le16(chan->dcid);
-                       rsp.dcid   = cpu_to_le16(chan->scid);
-                       rsp.result = cpu_to_le16(result);
-                       rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
-                       l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
-                                      sizeof(rsp), &rsp);
+               if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
+                       if (conn->hcon->type == ACL_LINK)
+                               l2cap_chan_connect_reject(chan);
+                       else if (conn->hcon->type == LE_LINK)
+                               l2cap_chan_le_connect_reject(chan);
                }
 
                l2cap_chan_del(chan, reason);
@@ -726,6 +784,9 @@ int l2cap_chan_check_security(struct l2cap_chan *chan)
        struct l2cap_conn *conn = chan->conn;
        __u8 auth_type;
 
+       if (conn->hcon->type == LE_LINK)
+               return smp_conn_security(conn->hcon, chan->sec_level);
+
        auth_type = l2cap_get_auth_type(chan);
 
        return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
@@ -1152,16 +1213,57 @@ static void l2cap_chan_ready(struct l2cap_chan *chan)
        chan->conf_state = 0;
        __clear_chan_timer(chan);
 
+       if (chan->mode == L2CAP_MODE_LE_FLOWCTL && !chan->tx_credits)
+               chan->ops->suspend(chan);
+
        chan->state = BT_CONNECTED;
 
        chan->ops->ready(chan);
 }
 
+static void l2cap_le_connect(struct l2cap_chan *chan)
+{
+       struct l2cap_conn *conn = chan->conn;
+       struct l2cap_le_conn_req req;
+
+       if (test_and_set_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags))
+               return;
+
+       req.psm     = chan->psm;
+       req.scid    = cpu_to_le16(chan->scid);
+       req.mtu     = cpu_to_le16(chan->imtu);
+       req.mps     = cpu_to_le16(chan->mps);
+       req.credits = cpu_to_le16(chan->rx_credits);
+
+       chan->ident = l2cap_get_ident(conn);
+
+       l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_REQ,
+                      sizeof(req), &req);
+}
+
+static void l2cap_le_start(struct l2cap_chan *chan)
+{
+       struct l2cap_conn *conn = chan->conn;
+
+       if (!smp_conn_security(conn->hcon, chan->sec_level))
+               return;
+
+       if (!chan->psm) {
+               l2cap_chan_ready(chan);
+               return;
+       }
+
+       if (chan->state == BT_CONNECT)
+               l2cap_le_connect(chan);
+}
+
 static void l2cap_start_connection(struct l2cap_chan *chan)
 {
        if (__amp_capable(chan)) {
                BT_DBG("chan %p AMP capable: discover AMPs", chan);
                a2mp_discover_amp(chan);
+       } else if (chan->conn->hcon->type == LE_LINK) {
+               l2cap_le_start(chan);
        } else {
                l2cap_send_conn_req(chan);
        }
@@ -1172,7 +1274,7 @@ static void l2cap_do_start(struct l2cap_chan *chan)
        struct l2cap_conn *conn = chan->conn;
 
        if (conn->hcon->type == LE_LINK) {
-               l2cap_chan_ready(chan);
+               l2cap_le_start(chan);
                return;
        }
 
@@ -1367,6 +1469,8 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
 
        BT_DBG("");
 
+       bt_6lowpan_add_conn(conn);
+
        /* Check if we have socket listening on cid */
        pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_ATT,
                                          &hcon->src, &hcon->dst);
@@ -1430,9 +1534,7 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
                }
 
                if (hcon->type == LE_LINK) {
-                       if (smp_conn_security(hcon, chan->sec_level))
-                               l2cap_chan_ready(chan);
-
+                       l2cap_le_start(chan);
                } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
                        l2cap_chan_ready(chan);
 
@@ -1703,7 +1805,8 @@ EXPORT_SYMBOL(l2cap_conn_put);
  */
 static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
                                                   bdaddr_t *src,
-                                                  bdaddr_t *dst)
+                                                  bdaddr_t *dst,
+                                                  u8 link_type)
 {
        struct l2cap_chan *c, *c1 = NULL;
 
@@ -1713,6 +1816,12 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
                if (state && c->state != state)
                        continue;
 
+               if (link_type == ACL_LINK && c->src_type != BDADDR_BREDR)
+                       continue;
+
+               if (link_type == LE_LINK && c->src_type == BDADDR_BREDR)
+                       continue;
+
                if (c->psm == psm) {
                        int src_match, dst_match;
                        int src_any, dst_any;
@@ -1739,6 +1848,18 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
        return c1;
 }
 
+static bool is_valid_psm(u16 psm, u8 dst_type)
+{
+       if (!psm)
+               return false;
+
+       if (bdaddr_type_is_le(dst_type))
+               return (psm <= 0x00ff);
+
+       /* PSM must be odd and lsb of upper byte must be 0 */
+       return ((psm & 0x0101) == 0x0001);
+}
+
 int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
                       bdaddr_t *dst, u8 dst_type)
 {
@@ -1759,8 +1880,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
 
        l2cap_chan_lock(chan);
 
-       /* PSM must be odd and lsb of upper byte must be 0 */
-       if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid &&
+       if (!is_valid_psm(__le16_to_cpu(psm), dst_type) && !cid &&
            chan->chan_type != L2CAP_CHAN_RAW) {
                err = -EINVAL;
                goto done;
@@ -1774,6 +1894,9 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
        switch (chan->mode) {
        case L2CAP_MODE_BASIC:
                break;
+       case L2CAP_MODE_LE_FLOWCTL:
+               l2cap_le_flowctl_init(chan);
+               break;
        case L2CAP_MODE_ERTM:
        case L2CAP_MODE_STREAMING:
                if (!disable_ertm)
@@ -2432,6 +2555,89 @@ static int l2cap_segment_sdu(struct l2cap_chan *chan,
        return 0;
 }
 
+static struct sk_buff *l2cap_create_le_flowctl_pdu(struct l2cap_chan *chan,
+                                                  struct msghdr *msg,
+                                                  size_t len, u16 sdulen)
+{
+       struct l2cap_conn *conn = chan->conn;
+       struct sk_buff *skb;
+       int err, count, hlen;
+       struct l2cap_hdr *lh;
+
+       BT_DBG("chan %p len %zu", chan, len);
+
+       if (!conn)
+               return ERR_PTR(-ENOTCONN);
+
+       hlen = L2CAP_HDR_SIZE;
+
+       if (sdulen)
+               hlen += L2CAP_SDULEN_SIZE;
+
+       count = min_t(unsigned int, (conn->mtu - hlen), len);
+
+       skb = chan->ops->alloc_skb(chan, count + hlen,
+                                  msg->msg_flags & MSG_DONTWAIT);
+       if (IS_ERR(skb))
+               return skb;
+
+       /* Create L2CAP header */
+       lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
+       lh->cid = cpu_to_le16(chan->dcid);
+       lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
+
+       if (sdulen)
+               put_unaligned_le16(sdulen, skb_put(skb, L2CAP_SDULEN_SIZE));
+
+       err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb);
+       if (unlikely(err < 0)) {
+               kfree_skb(skb);
+               return ERR_PTR(err);
+       }
+
+       return skb;
+}
+
+static int l2cap_segment_le_sdu(struct l2cap_chan *chan,
+                               struct sk_buff_head *seg_queue,
+                               struct msghdr *msg, size_t len)
+{
+       struct sk_buff *skb;
+       size_t pdu_len;
+       u16 sdu_len;
+
+       BT_DBG("chan %p, msg %p, len %zu", chan, msg, len);
+
+       pdu_len = chan->conn->mtu - L2CAP_HDR_SIZE;
+
+       pdu_len = min_t(size_t, pdu_len, chan->remote_mps);
+
+       sdu_len = len;
+       pdu_len -= L2CAP_SDULEN_SIZE;
+
+       while (len > 0) {
+               if (len <= pdu_len)
+                       pdu_len = len;
+
+               skb = l2cap_create_le_flowctl_pdu(chan, msg, pdu_len, sdu_len);
+               if (IS_ERR(skb)) {
+                       __skb_queue_purge(seg_queue);
+                       return PTR_ERR(skb);
+               }
+
+               __skb_queue_tail(seg_queue, skb);
+
+               len -= pdu_len;
+
+               if (sdu_len) {
+                       sdu_len = 0;
+                       pdu_len += L2CAP_SDULEN_SIZE;
+               }
+       }
+
+       return 0;
+}
+
 int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
                    u32 priority)
 {
@@ -2453,6 +2659,40 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
        }
 
        switch (chan->mode) {
+       case L2CAP_MODE_LE_FLOWCTL:
+               /* Check outgoing MTU */
+               if (len > chan->omtu)
+                       return -EMSGSIZE;
+
+               if (!chan->tx_credits)
+                       return -EAGAIN;
+
+               __skb_queue_head_init(&seg_queue);
+
+               err = l2cap_segment_le_sdu(chan, &seg_queue, msg, len);
+
+               if (chan->state != BT_CONNECTED) {
+                       __skb_queue_purge(&seg_queue);
+                       err = -ENOTCONN;
+               }
+
+               if (err)
+                       return err;
+
+               skb_queue_splice_tail_init(&seg_queue, &chan->tx_q);
+
+               while (chan->tx_credits && !skb_queue_empty(&chan->tx_q)) {
+                       l2cap_do_send(chan, skb_dequeue(&chan->tx_q));
+                       chan->tx_credits--;
+               }
+
+               if (!chan->tx_credits)
+                       chan->ops->suspend(chan);
+
+               err = len;
+
+               break;
+
        case L2CAP_MODE_BASIC:
                /* Check outgoing MTU */
                if (len > chan->omtu)
@@ -3592,6 +3832,23 @@ static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data,
        return ptr - data;
 }
 
+void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan)
+{
+       struct l2cap_le_conn_rsp rsp;
+       struct l2cap_conn *conn = chan->conn;
+
+       BT_DBG("chan %p", chan);
+
+       rsp.dcid    = cpu_to_le16(chan->scid);
+       rsp.mtu     = cpu_to_le16(chan->imtu);
+       rsp.mps     = cpu_to_le16(chan->mps);
+       rsp.credits = cpu_to_le16(chan->rx_credits);
+       rsp.result  = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
+
+       l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
+                      &rsp);
+}
+
 void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
 {
        struct l2cap_conn_rsp rsp;
@@ -3713,7 +3970,7 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
 
        /* Check if we have socket listening on psm */
        pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
-                                        &conn->hcon->dst);
+                                        &conn->hcon->dst, ACL_LINK);
        if (!pchan) {
                result = L2CAP_CR_BAD_PSM;
                goto sendresp;
@@ -5155,18 +5412,17 @@ static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
 
 static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
                                              struct l2cap_cmd_hdr *cmd,
-                                             u8 *data)
+                                             u16 cmd_len, u8 *data)
 {
        struct hci_conn *hcon = conn->hcon;
        struct l2cap_conn_param_update_req *req;
        struct l2cap_conn_param_update_rsp rsp;
-       u16 min, max, latency, to_multiplier, cmd_len;
+       u16 min, max, latency, to_multiplier;
        int err;
 
        if (!(hcon->link_mode & HCI_LM_MASTER))
                return -EINVAL;
 
-       cmd_len = __le16_to_cpu(cmd->len);
        if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
                return -EPROTO;
 
@@ -5196,6 +5452,65 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
        return 0;
 }
 
+static int l2cap_le_connect_rsp(struct l2cap_conn *conn,
+                               struct l2cap_cmd_hdr *cmd, u16 cmd_len,
+                               u8 *data)
+{
+       struct l2cap_le_conn_rsp *rsp = (struct l2cap_le_conn_rsp *) data;
+       u16 dcid, mtu, mps, credits, result;
+       struct l2cap_chan *chan;
+       int err;
+
+       if (cmd_len < sizeof(*rsp))
+               return -EPROTO;
+
+       dcid    = __le16_to_cpu(rsp->dcid);
+       mtu     = __le16_to_cpu(rsp->mtu);
+       mps     = __le16_to_cpu(rsp->mps);
+       credits = __le16_to_cpu(rsp->credits);
+       result  = __le16_to_cpu(rsp->result);
+
+       if (result == L2CAP_CR_SUCCESS && (mtu < 23 || mps < 23))
+               return -EPROTO;
+
+       BT_DBG("dcid 0x%4.4x mtu %u mps %u credits %u result 0x%2.2x",
+              dcid, mtu, mps, credits, result);
+
+       mutex_lock(&conn->chan_lock);
+
+       chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
+       if (!chan) {
+               err = -EBADSLT;
+               goto unlock;
+       }
+
+       err = 0;
+
+       l2cap_chan_lock(chan);
+
+       switch (result) {
+       case L2CAP_CR_SUCCESS:
+               chan->ident = 0;
+               chan->dcid = dcid;
+               chan->omtu = mtu;
+               chan->remote_mps = mps;
+               chan->tx_credits = credits;
+               l2cap_chan_ready(chan);
+               break;
+
+       default:
+               l2cap_chan_del(chan, ECONNREFUSED);
+               break;
+       }
+
+       l2cap_chan_unlock(chan);
+
+unlock:
+       mutex_unlock(&conn->chan_lock);
+
+       return err;
+}
+
 static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
                                      struct l2cap_cmd_hdr *cmd, u16 cmd_len,
                                      u8 *data)
@@ -5276,23 +5591,235 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
        return err;
 }
 
+static int l2cap_le_connect_req(struct l2cap_conn *conn,
+                               struct l2cap_cmd_hdr *cmd, u16 cmd_len,
+                               u8 *data)
+{
+       struct l2cap_le_conn_req *req = (struct l2cap_le_conn_req *) data;
+       struct l2cap_le_conn_rsp rsp;
+       struct l2cap_chan *chan, *pchan;
+       u16 dcid, scid, credits, mtu, mps;
+       __le16 psm;
+       u8 result;
+
+       if (cmd_len != sizeof(*req))
+               return -EPROTO;
+
+       scid = __le16_to_cpu(req->scid);
+       mtu  = __le16_to_cpu(req->mtu);
+       mps  = __le16_to_cpu(req->mps);
+       psm  = req->psm;
+       dcid = 0;
+       credits = 0;
+
+       if (mtu < 23 || mps < 23)
+               return -EPROTO;
+
+       BT_DBG("psm 0x%2.2x scid 0x%4.4x mtu %u mps %u", __le16_to_cpu(psm),
+              scid, mtu, mps);
+
+       /* Check if we have socket listening on psm */
+       pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
+                                        &conn->hcon->dst, LE_LINK);
+       if (!pchan) {
+               result = L2CAP_CR_BAD_PSM;
+               chan = NULL;
+               goto response;
+       }
+
+       mutex_lock(&conn->chan_lock);
+       l2cap_chan_lock(pchan);
+
+       if (!smp_sufficient_security(conn->hcon, pchan->sec_level)) {
+               result = L2CAP_CR_AUTHENTICATION;
+               chan = NULL;
+               goto response_unlock;
+       }
+
+       /* Check if we already have channel with that dcid */
+       if (__l2cap_get_chan_by_dcid(conn, scid)) {
+               result = L2CAP_CR_NO_MEM;
+               chan = NULL;
+               goto response_unlock;
+       }
+
+       chan = pchan->ops->new_connection(pchan);
+       if (!chan) {
+               result = L2CAP_CR_NO_MEM;
+               goto response_unlock;
+       }
+
+       l2cap_le_flowctl_init(chan);
+
+       bacpy(&chan->src, &conn->hcon->src);
+       bacpy(&chan->dst, &conn->hcon->dst);
+       chan->src_type = bdaddr_type(conn->hcon, conn->hcon->src_type);
+       chan->dst_type = bdaddr_type(conn->hcon, conn->hcon->dst_type);
+       chan->psm  = psm;
+       chan->dcid = scid;
+       chan->omtu = mtu;
+       chan->remote_mps = mps;
+       chan->tx_credits = __le16_to_cpu(req->credits);
+
+       __l2cap_chan_add(conn, chan);
+       dcid = chan->scid;
+       credits = chan->rx_credits;
+
+       __set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
+
+       chan->ident = cmd->ident;
+
+       if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
+               l2cap_state_change(chan, BT_CONNECT2);
+               result = L2CAP_CR_PEND;
+               chan->ops->defer(chan);
+       } else {
+               l2cap_chan_ready(chan);
+               result = L2CAP_CR_SUCCESS;
+       }
+
+response_unlock:
+       l2cap_chan_unlock(pchan);
+       mutex_unlock(&conn->chan_lock);
+
+       if (result == L2CAP_CR_PEND)
+               return 0;
+
+response:
+       if (chan) {
+               rsp.mtu = cpu_to_le16(chan->imtu);
+               rsp.mps = cpu_to_le16(chan->mps);
+       } else {
+               rsp.mtu = 0;
+               rsp.mps = 0;
+       }
+
+       rsp.dcid    = cpu_to_le16(dcid);
+       rsp.credits = cpu_to_le16(credits);
+       rsp.result  = cpu_to_le16(result);
+
+       l2cap_send_cmd(conn, cmd->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), &rsp);
+
+       return 0;
+}
+
+static inline int l2cap_le_credits(struct l2cap_conn *conn,
+                                  struct l2cap_cmd_hdr *cmd, u16 cmd_len,
+                                  u8 *data)
+{
+       struct l2cap_le_credits *pkt;
+       struct l2cap_chan *chan;
+       u16 cid, credits;
+
+       if (cmd_len != sizeof(*pkt))
+               return -EPROTO;
+
+       pkt = (struct l2cap_le_credits *) data;
+       cid     = __le16_to_cpu(pkt->cid);
+       credits = __le16_to_cpu(pkt->credits);
+
+       BT_DBG("cid 0x%4.4x credits 0x%4.4x", cid, credits);
+
+       chan = l2cap_get_chan_by_dcid(conn, cid);
+       if (!chan)
+               return -EBADSLT;
+
+       chan->tx_credits += credits;
+
+       while (chan->tx_credits && !skb_queue_empty(&chan->tx_q)) {
+               l2cap_do_send(chan, skb_dequeue(&chan->tx_q));
+               chan->tx_credits--;
+       }
+
+       if (chan->tx_credits)
+               chan->ops->resume(chan);
+
+       l2cap_chan_unlock(chan);
+
+       return 0;
+}
+
+static inline int l2cap_le_command_rej(struct l2cap_conn *conn,
+                                      struct l2cap_cmd_hdr *cmd, u16 cmd_len,
+                                      u8 *data)
+{
+       struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
+       struct l2cap_chan *chan;
+
+       if (cmd_len < sizeof(*rej))
+               return -EPROTO;
+
+       mutex_lock(&conn->chan_lock);
+
+       chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
+       if (!chan)
+               goto done;
+
+       l2cap_chan_lock(chan);
+       l2cap_chan_del(chan, ECONNREFUSED);
+       l2cap_chan_unlock(chan);
+
+done:
+       mutex_unlock(&conn->chan_lock);
+       return 0;
+}
+
 static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
-                                  struct l2cap_cmd_hdr *cmd, u8 *data)
+                                  struct l2cap_cmd_hdr *cmd, u16 cmd_len,
+                                  u8 *data)
 {
+       int err = 0;
+
+       if (!enable_lecoc) {
+               switch (cmd->code) {
+               case L2CAP_LE_CONN_REQ:
+               case L2CAP_LE_CONN_RSP:
+               case L2CAP_LE_CREDITS:
+               case L2CAP_DISCONN_REQ:
+               case L2CAP_DISCONN_RSP:
+                       return -EINVAL;
+               }
+       }
+
        switch (cmd->code) {
        case L2CAP_COMMAND_REJ:
-               return 0;
+               l2cap_le_command_rej(conn, cmd, cmd_len, data);
+               break;
 
        case L2CAP_CONN_PARAM_UPDATE_REQ:
-               return l2cap_conn_param_update_req(conn, cmd, data);
+               err = l2cap_conn_param_update_req(conn, cmd, cmd_len, data);
+               break;
 
        case L2CAP_CONN_PARAM_UPDATE_RSP:
-               return 0;
+               break;
+
+       case L2CAP_LE_CONN_RSP:
+               l2cap_le_connect_rsp(conn, cmd, cmd_len, data);
+               break;
+
+       case L2CAP_LE_CONN_REQ:
+               err = l2cap_le_connect_req(conn, cmd, cmd_len, data);
+               break;
+
+       case L2CAP_LE_CREDITS:
+               err = l2cap_le_credits(conn, cmd, cmd_len, data);
+               break;
+
+       case L2CAP_DISCONN_REQ:
+               err = l2cap_disconnect_req(conn, cmd, cmd_len, data);
+               break;
+
+       case L2CAP_DISCONN_RSP:
+               l2cap_disconnect_rsp(conn, cmd, cmd_len, data);
+               break;
 
        default:
                BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
-               return -EINVAL;
+               err = -EINVAL;
+               break;
        }
+
+       return err;
 }
 
 static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,
@@ -5321,7 +5848,7 @@ static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,
                goto drop;
        }
 
-       err = l2cap_le_sig_cmd(conn, cmd, skb->data);
+       err = l2cap_le_sig_cmd(conn, cmd, len, skb->data);
        if (err) {
                struct l2cap_cmd_rej_unk rej;
 
@@ -6312,6 +6839,121 @@ drop:
        return 0;
 }
 
+static void l2cap_chan_le_send_credits(struct l2cap_chan *chan)
+{
+       struct l2cap_conn *conn = chan->conn;
+       struct l2cap_le_credits pkt;
+       u16 return_credits;
+
+       /* We return more credits to the sender only after the amount of
+        * credits falls below half of the initial amount.
+        */
+       if (chan->rx_credits >= (le_max_credits + 1) / 2)
+               return;
+
+       return_credits = le_max_credits - chan->rx_credits;
+
+       BT_DBG("chan %p returning %u credits to sender", chan, return_credits);
+
+       chan->rx_credits += return_credits;
+
+       pkt.cid     = cpu_to_le16(chan->scid);
+       pkt.credits = cpu_to_le16(return_credits);
+
+       chan->ident = l2cap_get_ident(conn);
+
+       l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CREDITS, sizeof(pkt), &pkt);
+}
+
+static int l2cap_le_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
+{
+       int err;
+
+       if (!chan->rx_credits) {
+               BT_ERR("No credits to receive LE L2CAP data");
+               return -ENOBUFS;
+       }
+
+       if (chan->imtu < skb->len) {
+               BT_ERR("Too big LE L2CAP PDU");
+               return -ENOBUFS;
+       }
+
+       chan->rx_credits--;
+       BT_DBG("rx_credits %u -> %u", chan->rx_credits + 1, chan->rx_credits);
+
+       l2cap_chan_le_send_credits(chan);
+
+       err = 0;
+
+       if (!chan->sdu) {
+               u16 sdu_len;
+
+               sdu_len = get_unaligned_le16(skb->data);
+               skb_pull(skb, L2CAP_SDULEN_SIZE);
+
+               BT_DBG("Start of new SDU. sdu_len %u skb->len %u imtu %u",
+                      sdu_len, skb->len, chan->imtu);
+
+               if (sdu_len > chan->imtu) {
+                       BT_ERR("Too big LE L2CAP SDU length received");
+                       err = -EMSGSIZE;
+                       goto failed;
+               }
+
+               if (skb->len > sdu_len) {
+                       BT_ERR("Too much LE L2CAP data received");
+                       err = -EINVAL;
+                       goto failed;
+               }
+
+               if (skb->len == sdu_len)
+                       return chan->ops->recv(chan, skb);
+
+               chan->sdu = skb;
+               chan->sdu_len = sdu_len;
+               chan->sdu_last_frag = skb;
+
+               return 0;
+       }
+
+       BT_DBG("SDU fragment. chan->sdu->len %u skb->len %u chan->sdu_len %u",
+              chan->sdu->len, skb->len, chan->sdu_len);
+
+       if (chan->sdu->len + skb->len > chan->sdu_len) {
+               BT_ERR("Too much LE L2CAP data received");
+               err = -EINVAL;
+               goto failed;
+       }
+
+       append_skb_frag(chan->sdu, skb, &chan->sdu_last_frag);
+       skb = NULL;
+
+       if (chan->sdu->len == chan->sdu_len) {
+               err = chan->ops->recv(chan, chan->sdu);
+               if (!err) {
+                       chan->sdu = NULL;
+                       chan->sdu_last_frag = NULL;
+                       chan->sdu_len = 0;
+               }
+       }
+
+failed:
+       if (err) {
+               kfree_skb(skb);
+               kfree_skb(chan->sdu);
+               chan->sdu = NULL;
+               chan->sdu_last_frag = NULL;
+               chan->sdu_len = 0;
+       }
+
+       /* We can't return an error here since we took care of the skb
+        * freeing internally. An error return would cause the caller to
+        * do a double-free of the skb.
+        */
+       return 0;
+}
+
 static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid,
                               struct sk_buff *skb)
 {
@@ -6341,6 +6983,12 @@ static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid,
                goto drop;
 
        switch (chan->mode) {
+       case L2CAP_MODE_LE_FLOWCTL:
+               if (l2cap_le_data_rcv(chan, skb) < 0)
+                       goto drop;
+
+               goto done;
+
        case L2CAP_MODE_BASIC:
                /* If socket recv buffers overflows we drop data here
                 * which is *bad* because L2CAP has to be reliable.
@@ -6380,7 +7028,8 @@ static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm,
        if (hcon->type != ACL_LINK)
                goto drop;
 
-       chan = l2cap_global_chan_by_psm(0, psm, &hcon->src, &hcon->dst);
+       chan = l2cap_global_chan_by_psm(0, psm, &hcon->src, &hcon->dst,
+                                       ACL_LINK);
        if (!chan)
                goto drop;
 
@@ -6473,6 +7122,10 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
                        l2cap_conn_del(conn->hcon, EACCES);
                break;
 
+       case L2CAP_FC_6LOWPAN:
+               bt_6lowpan_recv(conn, skb);
+               break;
+
        default:
                l2cap_data_channel(conn, cid, skb);
                break;
@@ -6540,6 +7193,8 @@ void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
 {
        BT_DBG("hcon %p reason %d", hcon, reason);
 
+       bt_6lowpan_del_conn(hcon->l2cap_data);
+
        l2cap_conn_del(hcon, bt_to_errno(reason));
 }
 
@@ -6612,11 +7267,10 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
                }
 
                if (chan->state == BT_CONNECT) {
-                       if (!status) {
+                       if (!status)
                                l2cap_start_connection(chan);
-                       } else {
+                       else
                                __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
-                       }
                } else if (chan->state == BT_CONNECT2) {
                        struct l2cap_conn_rsp rsp;
                        __u16 res, stat;
@@ -6817,11 +7471,19 @@ int __init l2cap_init(void)
        l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs,
                                            NULL, &l2cap_debugfs_fops);
 
+       debugfs_create_u16("l2cap_le_max_credits", 0466, bt_debugfs,
+                          &le_max_credits);
+       debugfs_create_u16("l2cap_le_default_mps", 0466, bt_debugfs,
+                          &le_default_mps);
+
+       bt_6lowpan_init();
+
        return 0;
 }
 
 void l2cap_exit(void)
 {
+       bt_6lowpan_cleanup();
        debugfs_remove(l2cap_debugfs);
        l2cap_cleanup_sockets();
 }
index 7cc24d263caaab45af9d8bbe5be09ebda20e87a4..e7806e6d282c29af9c64f92aaee4632b50a6c8b6 100644 (file)
@@ -27,6 +27,7 @@
 
 /* Bluetooth L2CAP sockets. */
 
+#include <linux/module.h>
 #include <linux/export.h>
 
 #include <net/bluetooth/bluetooth.h>
@@ -35,6 +36,8 @@
 
 #include "smp.h"
 
+bool enable_lecoc;
+
 static struct bt_sock_list l2cap_sk_list = {
        .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock)
 };
@@ -50,6 +53,32 @@ bool l2cap_is_socket(struct socket *sock)
 }
 EXPORT_SYMBOL(l2cap_is_socket);
 
+static int l2cap_validate_bredr_psm(u16 psm)
+{
+       /* PSM must be odd and lsb of upper byte must be 0 */
+       if ((psm & 0x0101) != 0x0001)
+               return -EINVAL;
+
+       /* Restrict usage of well-known PSMs */
+       if (psm < 0x1001 && !capable(CAP_NET_BIND_SERVICE))
+               return -EACCES;
+
+       return 0;
+}
+
+static int l2cap_validate_le_psm(u16 psm)
+{
+       /* Valid LE_PSM ranges are defined only until 0x00ff */
+       if (psm > 0x00ff)
+               return -EINVAL;
+
+       /* Restrict fixed, SIG assigned PSM values to CAP_NET_BIND_SERVICE */
+       if (psm <= 0x007f && !capable(CAP_NET_BIND_SERVICE))
+               return -EACCES;
+
+       return 0;
+}
+
 static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
 {
        struct sock *sk = sock->sk;
@@ -73,11 +102,11 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
                return -EINVAL;
 
        if (bdaddr_type_is_le(la.l2_bdaddr_type)) {
-               /* Connection oriented channels are not supported on LE */
-               if (la.l2_psm)
+               if (!enable_lecoc && la.l2_psm)
                        return -EINVAL;
                /* We only allow ATT user space socket */
-               if (la.l2_cid != __constant_cpu_to_le16(L2CAP_CID_ATT))
+               if (la.l2_cid &&
+                   la.l2_cid != __constant_cpu_to_le16(L2CAP_CID_ATT))
                        return -EINVAL;
        }
 
@@ -91,17 +120,13 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
        if (la.l2_psm) {
                __u16 psm = __le16_to_cpu(la.l2_psm);
 
-               /* PSM must be odd and lsb of upper byte must be 0 */
-               if ((psm & 0x0101) != 0x0001) {
-                       err = -EINVAL;
-                       goto done;
-               }
+               if (la.l2_bdaddr_type == BDADDR_BREDR)
+                       err = l2cap_validate_bredr_psm(psm);
+               else
+                       err = l2cap_validate_le_psm(psm);
 
-               /* Restrict usage of well-known PSMs */
-               if (psm < 0x1001 && !capable(CAP_NET_BIND_SERVICE)) {
-                       err = -EACCES;
+               if (err)
                        goto done;
-               }
        }
 
        if (la.l2_cid)
@@ -127,6 +152,9 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
        bacpy(&chan->src, &la.l2_bdaddr);
        chan->src_type = la.l2_bdaddr_type;
 
+       if (chan->psm && bdaddr_type_is_le(chan->src_type))
+               chan->mode = L2CAP_MODE_LE_FLOWCTL;
+
        chan->state = BT_BOUND;
        sk->sk_state = BT_BOUND;
 
@@ -189,14 +217,17 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr,
                return -EINVAL;
 
        if (bdaddr_type_is_le(la.l2_bdaddr_type)) {
-               /* Connection oriented channels are not supported on LE */
-               if (la.l2_psm)
+               if (!enable_lecoc && la.l2_psm)
                        return -EINVAL;
                /* We only allow ATT user space socket */
-               if (la.l2_cid != __constant_cpu_to_le16(L2CAP_CID_ATT))
+               if (la.l2_cid &&
+                   la.l2_cid != __constant_cpu_to_le16(L2CAP_CID_ATT))
                        return -EINVAL;
        }
 
+       if (chan->psm && bdaddr_type_is_le(chan->src_type))
+               chan->mode = L2CAP_MODE_LE_FLOWCTL;
+
        err = l2cap_chan_connect(chan, la.l2_psm, __le16_to_cpu(la.l2_cid),
                                 &la.l2_bdaddr, la.l2_bdaddr_type);
        if (err)
@@ -234,6 +265,7 @@ static int l2cap_sock_listen(struct socket *sock, int backlog)
 
        switch (chan->mode) {
        case L2CAP_MODE_BASIC:
+       case L2CAP_MODE_LE_FLOWCTL:
                break;
        case L2CAP_MODE_ERTM:
        case L2CAP_MODE_STREAMING:
@@ -360,6 +392,16 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
 
        switch (optname) {
        case L2CAP_OPTIONS:
+               /* LE sockets should use BT_SNDMTU/BT_RCVMTU, but since
+                * legacy ATT code depends on getsockopt for
+                * L2CAP_OPTIONS we need to let this pass.
+                */
+               if (bdaddr_type_is_le(chan->src_type) &&
+                   chan->scid != L2CAP_CID_ATT) {
+                       err = -EINVAL;
+                       break;
+               }
+
                memset(&opts, 0, sizeof(opts));
                opts.imtu     = chan->imtu;
                opts.omtu     = chan->omtu;
@@ -514,6 +556,41 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname,
                        err = -EFAULT;
                break;
 
+       case BT_SNDMTU:
+               if (!enable_lecoc) {
+                       err = -EPROTONOSUPPORT;
+                       break;
+               }
+
+               if (!bdaddr_type_is_le(chan->src_type)) {
+                       err = -EINVAL;
+                       break;
+               }
+
+               if (sk->sk_state != BT_CONNECTED) {
+                       err = -ENOTCONN;
+                       break;
+               }
+
+               if (put_user(chan->omtu, (u16 __user *) optval))
+                       err = -EFAULT;
+               break;
+
+       case BT_RCVMTU:
+               if (!enable_lecoc) {
+                       err = -EPROTONOSUPPORT;
+                       break;
+               }
+
+               if (!bdaddr_type_is_le(chan->src_type)) {
+                       err = -EINVAL;
+                       break;
+               }
+
+               if (put_user(chan->imtu, (u16 __user *) optval))
+                       err = -EFAULT;
+               break;
+
        default:
                err = -ENOPROTOOPT;
                break;
@@ -554,6 +631,11 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
 
        switch (optname) {
        case L2CAP_OPTIONS:
+               if (bdaddr_type_is_le(chan->src_type)) {
+                       err = -EINVAL;
+                       break;
+               }
+
                if (sk->sk_state == BT_CONNECTED) {
                        err = -EINVAL;
                        break;
@@ -585,6 +667,8 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
 
                chan->mode = opts.mode;
                switch (chan->mode) {
+               case L2CAP_MODE_LE_FLOWCTL:
+                       break;
                case L2CAP_MODE_BASIC:
                        clear_bit(CONF_STATE2_DEVICE, &chan->conf_state);
                        break;
@@ -807,6 +891,47 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
 
                break;
 
+       case BT_SNDMTU:
+               if (!enable_lecoc) {
+                       err = -EPROTONOSUPPORT;
+                       break;
+               }
+
+               if (!bdaddr_type_is_le(chan->src_type)) {
+                       err = -EINVAL;
+                       break;
+               }
+
+               /* Setting is not supported as it's the remote side that
+                * decides this.
+                */
+               err = -EPERM;
+               break;
+
+       case BT_RCVMTU:
+               if (!enable_lecoc) {
+                       err = -EPROTONOSUPPORT;
+                       break;
+               }
+
+               if (!bdaddr_type_is_le(chan->src_type)) {
+                       err = -EINVAL;
+                       break;
+               }
+
+               if (sk->sk_state == BT_CONNECTED) {
+                       err = -EISCONN;
+                       break;
+               }
+
+               if (get_user(opt, (u32 __user *) optval)) {
+                       err = -EFAULT;
+                       break;
+               }
+
+               chan->imtu = opt;
+               break;
+
        default:
                err = -ENOPROTOOPT;
                break;
@@ -859,10 +984,16 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
 
        if (sk->sk_state == BT_CONNECT2 && test_bit(BT_SK_DEFER_SETUP,
                                                    &bt_sk(sk)->flags)) {
-               sk->sk_state = BT_CONFIG;
-               pi->chan->state = BT_CONFIG;
+               if (bdaddr_type_is_le(pi->chan->src_type)) {
+                       sk->sk_state = BT_CONNECTED;
+                       pi->chan->state = BT_CONNECTED;
+                       __l2cap_le_connect_rsp_defer(pi->chan);
+               } else {
+                       sk->sk_state = BT_CONFIG;
+                       pi->chan->state = BT_CONFIG;
+                       __l2cap_connect_rsp_defer(pi->chan);
+               }
 
-               __l2cap_connect_rsp_defer(pi->chan);
                err = 0;
                goto done;
        }
@@ -1236,6 +1367,14 @@ static long l2cap_sock_get_sndtimeo_cb(struct l2cap_chan *chan)
        return sk->sk_sndtimeo;
 }
 
+static void l2cap_sock_suspend_cb(struct l2cap_chan *chan)
+{
+       struct sock *sk = chan->data;
+
+       set_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags);
+       sk->sk_state_change(sk);
+}
+
 static struct l2cap_ops l2cap_chan_ops = {
        .name           = "L2CAP Socket Interface",
        .new_connection = l2cap_sock_new_connection_cb,
@@ -1246,6 +1385,7 @@ static struct l2cap_ops l2cap_chan_ops = {
        .ready          = l2cap_sock_ready_cb,
        .defer          = l2cap_sock_defer_cb,
        .resume         = l2cap_sock_resume_cb,
+       .suspend        = l2cap_sock_suspend_cb,
        .set_shutdown   = l2cap_sock_set_shutdown_cb,
        .get_sndtimeo   = l2cap_sock_get_sndtimeo_cb,
        .alloc_skb      = l2cap_sock_alloc_skb_cb,
@@ -1303,6 +1443,8 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent)
                chan->tx_win_max = pchan->tx_win_max;
                chan->sec_level = pchan->sec_level;
                chan->flags = pchan->flags;
+               chan->tx_credits = pchan->tx_credits;
+               chan->rx_credits = pchan->rx_credits;
 
                security_sk_clone(parent, sk);
        } else {
@@ -1469,3 +1611,6 @@ void l2cap_cleanup_sockets(void)
        bt_sock_unregister(BTPROTO_L2CAP);
        proto_unregister(&l2cap_proto);
 }
+
+module_param(enable_lecoc, bool, 0644);
+MODULE_PARM_DESC(enable_lecoc, "Enable support for LE CoC");
index 074d83690a414c8e668499d7f7e7c86215c563ea..a03ca3ca91bfa77e2663a09f90ce2271addb2331 100644 (file)
@@ -1264,7 +1264,7 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
 
                if (cp->val == 0x02) {
                        /* Limited discoverable mode */
-                       hci_cp.num_iac = 2;
+                       hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
                        hci_cp.iac_lap[0] = 0x00;       /* LIAC */
                        hci_cp.iac_lap[1] = 0x8b;
                        hci_cp.iac_lap[2] = 0x9e;
@@ -4595,6 +4595,9 @@ void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
        struct mgmt_ev_device_disconnected ev;
        struct sock *sk = NULL;
 
+       if (link_type != ACL_LINK && link_type != LE_LINK)
+               return;
+
        mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
 
        bacpy(&ev.addr.bdaddr, bdaddr);
@@ -4613,6 +4616,8 @@ void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
 void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
                            u8 link_type, u8 addr_type, u8 status)
 {
+       u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
+       struct mgmt_cp_disconnect *cp;
        struct mgmt_rp_disconnect rp;
        struct pending_cmd *cmd;
 
@@ -4623,8 +4628,16 @@ void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
        if (!cmd)
                return;
 
+       cp = cmd->param;
+
+       if (bacmp(bdaddr, &cp->addr.bdaddr))
+               return;
+
+       if (cp->addr.type != bdaddr_type)
+               return;
+
        bacpy(&rp.addr.bdaddr, bdaddr);
-       rp.addr.type = link_to_bdaddr(link_type, addr_type);
+       rp.addr.type = bdaddr_type;
 
        cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
                     mgmt_status(status), &rp, sizeof(rp));
index 4b07acb8293c3df3542e2a1661a6ae07bcfa6596..45007362683b4e4cdfcf8131d79ff38aa95f5733 100644 (file)
@@ -53,8 +53,7 @@ static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
 {
        struct blkcipher_desc desc;
        struct scatterlist sg;
-       int err, iv_len;
-       unsigned char iv[128];
+       int err;
 
        if (tfm == NULL) {
                BT_ERR("tfm %p", tfm);
@@ -72,12 +71,6 @@ static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
 
        sg_init_one(&sg, r, 16);
 
-       iv_len = crypto_blkcipher_ivsize(tfm);
-       if (iv_len) {
-               memset(&iv, 0xff, iv_len);
-               crypto_blkcipher_set_iv(tfm, iv, iv_len);
-       }
-
        err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16);
        if (err)
                BT_ERR("Encrypt data error %d", err);
@@ -143,13 +136,6 @@ static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16], u8 r1[16],
        return err;
 }
 
-static int smp_rand(u8 *buf)
-{
-       get_random_bytes(buf, 16);
-
-       return 0;
-}
-
 static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
                                     u16 dlen, void *data)
 {
@@ -257,11 +243,11 @@ static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
        return 0;
 }
 
-static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send)
+static void smp_failure(struct l2cap_conn *conn, u8 reason)
 {
        struct hci_conn *hcon = conn->hcon;
 
-       if (send)
+       if (reason)
                smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
                             &reason);
 
@@ -406,7 +392,7 @@ static void confirm_work(struct work_struct *work)
        return;
 
 error:
-       smp_failure(conn, reason, 1);
+       smp_failure(conn, reason);
 }
 
 static void random_work(struct work_struct *work)
@@ -490,7 +476,7 @@ static void random_work(struct work_struct *work)
        return;
 
 error:
-       smp_failure(conn, reason, 1);
+       smp_failure(conn, reason);
 }
 
 static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
@@ -555,10 +541,10 @@ int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
                break;
        case MGMT_OP_USER_PASSKEY_NEG_REPLY:
        case MGMT_OP_USER_CONFIRM_NEG_REPLY:
-               smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1);
+               smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED);
                return 0;
        default:
-               smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1);
+               smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED);
                return -EOPNOTSUPP;
        }
 
@@ -606,9 +592,7 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
        if (check_enc_key_size(conn, key_size))
                return SMP_ENC_KEY_SIZE;
 
-       ret = smp_rand(smp->prnd);
-       if (ret)
-               return SMP_UNSPECIFIED;
+       get_random_bytes(smp->prnd, sizeof(smp->prnd));
 
        smp->prsp[0] = SMP_CMD_PAIRING_RSP;
        memcpy(&smp->prsp[1], &rsp, sizeof(rsp));
@@ -644,9 +628,7 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
        if (check_enc_key_size(conn, key_size))
                return SMP_ENC_KEY_SIZE;
 
-       ret = smp_rand(smp->prnd);
-       if (ret)
-               return SMP_UNSPECIFIED;
+       get_random_bytes(smp->prnd, sizeof(smp->prnd));
 
        smp->prsp[0] = SMP_CMD_PAIRING_RSP;
        memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
@@ -768,6 +750,17 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
        return 0;
 }
 
+bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level)
+{
+       if (sec_level == BT_SECURITY_LOW)
+               return true;
+
+       if (hcon->sec_level >= sec_level)
+               return true;
+
+       return false;
+}
+
 int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
 {
        struct l2cap_conn *conn = hcon->l2cap_data;
@@ -779,10 +772,7 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
        if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags))
                return 1;
 
-       if (sec_level == BT_SECURITY_LOW)
-               return 1;
-
-       if (hcon->sec_level >= sec_level)
+       if (smp_sufficient_security(hcon, sec_level))
                return 1;
 
        if (hcon->link_mode & HCI_LM_MASTER)
@@ -895,7 +885,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
                break;
 
        case SMP_CMD_PAIRING_FAIL:
-               smp_failure(conn, skb->data[0], 0);
+               smp_failure(conn, 0);
                reason = 0;
                err = -EPERM;
                break;
@@ -941,7 +931,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
 
 done:
        if (reason)
-               smp_failure(conn, reason, 1);
+               smp_failure(conn, reason);
 
        kfree_skb(skb);
        return err;
index f8ba07f3e5fa19427573128f07764e8733977b29..a700bcb490d7bedb24c55b0b97b58bc6280c5552 100644 (file)
@@ -136,6 +136,7 @@ struct smp_chan {
 };
 
 /* SMP Commands */
+bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level);
 int smp_conn_security(struct hci_conn *hcon, __u8 sec_level);
 int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb);
 int smp_distribute_keys(struct l2cap_conn *conn, __u8 force);
index f75d92e4f96b33cec6fd46fc37151224f86ed018..c2fd6bc5f08013325b25424e03bf684a56717897 100644 (file)
@@ -373,7 +373,7 @@ int br_setlink(struct net_device *dev, struct nlmsghdr *nlh)
 
        p = br_port_get_rtnl(dev);
        /* We want to accept dev as bridge itself if the AF_SPEC
-        * is set to see if someone is setting vlan info on the brigde
+        * is set to see if someone is setting vlan info on the bridge
         */
        if (!p && !afspec)
                return -EINVAL;
@@ -389,7 +389,7 @@ int br_setlink(struct net_device *dev, struct nlmsghdr *nlh)
                        err = br_setport(p, tb);
                        spin_unlock_bh(&p->br->lock);
                } else {
-                       /* Binary compatability with old RSTP */
+                       /* Binary compatibility with old RSTP */
                        if (nla_len(protinfo) < sizeof(u8))
                                return -EINVAL;
 
index 229d820bdf0b06453cb43058020d54e33f210297..045d56eaeca2b777973bf1450d7b410a09d2d9f1 100644 (file)
@@ -426,6 +426,16 @@ netdev_features_t br_features_recompute(struct net_bridge *br,
 int br_handle_frame_finish(struct sk_buff *skb);
 rx_handler_result_t br_handle_frame(struct sk_buff **pskb);
 
+static inline bool br_rx_handler_check_rcu(const struct net_device *dev)
+{
+       return rcu_dereference(dev->rx_handler) == br_handle_frame;
+}
+
+static inline struct net_bridge_port *br_port_get_check_rcu(const struct net_device *dev)
+{
+       return br_rx_handler_check_rcu(dev) ? br_port_get_rcu(dev) : NULL;
+}
+
 /* br_ioctl.c */
 int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd,
index 8660ea3be7054571defa59bcfbfc0cd0dd7ab99e..bdb459d21ad8e2d5191023c5b096de39b6a78c90 100644 (file)
@@ -153,7 +153,7 @@ void br_stp_rcv(const struct stp_proto *proto, struct sk_buff *skb,
        if (buf[0] != 0 || buf[1] != 0 || buf[2] != 0)
                goto err;
 
-       p = br_port_get_rcu(dev);
+       p = br_port_get_check_rcu(dev);
        if (!p)
                goto err;
 
index eae67bf0446c8023b6e3895562e48912b6c29330..8d3f8c7651f0dcec64bc7cac84a7f9c3d8953352 100644 (file)
@@ -14,8 +14,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/if_ether.h>
index 4a5df7b1cc9ff5652185e0248cf5a4df4006effd..18c039b95c22459f8d669ee2598c411c1b615141 100644 (file)
@@ -777,13 +777,12 @@ static void ceph_msg_data_bio_cursor_init(struct ceph_msg_data_cursor *cursor,
 
        bio = data->bio;
        BUG_ON(!bio);
-       BUG_ON(!bio->bi_vcnt);
 
        cursor->resid = min(length, data->bio_length);
        cursor->bio = bio;
-       cursor->vector_index = 0;
-       cursor->vector_offset = 0;
-       cursor->last_piece = length <= bio->bi_io_vec[0].bv_len;
+       cursor->bvec_iter = bio->bi_iter;
+       cursor->last_piece =
+               cursor->resid <= bio_iter_len(bio, cursor->bvec_iter);
 }
 
 static struct page *ceph_msg_data_bio_next(struct ceph_msg_data_cursor *cursor,
@@ -792,71 +791,63 @@ static struct page *ceph_msg_data_bio_next(struct ceph_msg_data_cursor *cursor,
 {
        struct ceph_msg_data *data = cursor->data;
        struct bio *bio;
-       struct bio_vec *bio_vec;
-       unsigned int index;
+       struct bio_vec bio_vec;
 
        BUG_ON(data->type != CEPH_MSG_DATA_BIO);
 
        bio = cursor->bio;
        BUG_ON(!bio);
 
-       index = cursor->vector_index;
-       BUG_ON(index >= (unsigned int) bio->bi_vcnt);
+       bio_vec = bio_iter_iovec(bio, cursor->bvec_iter);
 
-       bio_vec = &bio->bi_io_vec[index];
-       BUG_ON(cursor->vector_offset >= bio_vec->bv_len);
-       *page_offset = (size_t) (bio_vec->bv_offset + cursor->vector_offset);
+       *page_offset = (size_t) bio_vec.bv_offset;
        BUG_ON(*page_offset >= PAGE_SIZE);
        if (cursor->last_piece) /* pagelist offset is always 0 */
                *length = cursor->resid;
        else
-               *length = (size_t) (bio_vec->bv_len - cursor->vector_offset);
+               *length = (size_t) bio_vec.bv_len;
        BUG_ON(*length > cursor->resid);
        BUG_ON(*page_offset + *length > PAGE_SIZE);
 
-       return bio_vec->bv_page;
+       return bio_vec.bv_page;
 }
 
 static bool ceph_msg_data_bio_advance(struct ceph_msg_data_cursor *cursor,
                                        size_t bytes)
 {
        struct bio *bio;
-       struct bio_vec *bio_vec;
-       unsigned int index;
+       struct bio_vec bio_vec;
 
        BUG_ON(cursor->data->type != CEPH_MSG_DATA_BIO);
 
        bio = cursor->bio;
        BUG_ON(!bio);
 
-       index = cursor->vector_index;
-       BUG_ON(index >= (unsigned int) bio->bi_vcnt);
-       bio_vec = &bio->bi_io_vec[index];
+       bio_vec = bio_iter_iovec(bio, cursor->bvec_iter);
 
        /* Advance the cursor offset */
 
        BUG_ON(cursor->resid < bytes);
        cursor->resid -= bytes;
-       cursor->vector_offset += bytes;
-       if (cursor->vector_offset < bio_vec->bv_len)
+
+       bio_advance_iter(bio, &cursor->bvec_iter, bytes);
+
+       if (bytes < bio_vec.bv_len)
                return false;   /* more bytes to process in this segment */
-       BUG_ON(cursor->vector_offset != bio_vec->bv_len);
 
        /* Move on to the next segment, and possibly the next bio */
 
-       if (++index == (unsigned int) bio->bi_vcnt) {
+       if (!cursor->bvec_iter.bi_size) {
                bio = bio->bi_next;
-               index = 0;
+               cursor->bvec_iter = bio->bi_iter;
        }
        cursor->bio = bio;
-       cursor->vector_index = index;
-       cursor->vector_offset = 0;
 
        if (!cursor->last_piece) {
                BUG_ON(!cursor->resid);
                BUG_ON(!bio);
                /* A short read is OK, so use <= rather than == */
-               if (cursor->resid <= bio->bi_io_vec[index].bv_len)
+               if (cursor->resid <= bio_iter_len(bio, cursor->bvec_iter))
                        cursor->last_piece = true;
        }
 
index 618c6a8a911b65c9a406ba5d7d0e221cb124960e..dd32e34c1e2c9481aa2db3c37437ef0d85ba5277 100644 (file)
@@ -72,7 +72,7 @@ int get_compat_msghdr(struct msghdr *kmsg, struct compat_msghdr __user *umsg)
            __get_user(kmsg->msg_flags, &umsg->msg_flags))
                return -EFAULT;
        if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
-               return -EINVAL;
+               kmsg->msg_namelen = sizeof(struct sockaddr_storage);
        kmsg->msg_name = compat_ptr(tmp1);
        kmsg->msg_iov = compat_ptr(tmp2);
        kmsg->msg_control = compat_ptr(tmp3);
index ba3b7ea5ebb3139cca38e82ac6f5f5e346f4a4e0..5bb32e798d941fb21ce608abbb7574109b8f7d60 100644 (file)
@@ -2145,30 +2145,42 @@ void __netif_schedule(struct Qdisc *q)
 }
 EXPORT_SYMBOL(__netif_schedule);
 
-void dev_kfree_skb_irq(struct sk_buff *skb)
+struct dev_kfree_skb_cb {
+       enum skb_free_reason reason;
+};
+
+static struct dev_kfree_skb_cb *get_kfree_skb_cb(const struct sk_buff *skb)
+{
+       return (struct dev_kfree_skb_cb *)skb->cb;
+}
+
+void __dev_kfree_skb_irq(struct sk_buff *skb, enum skb_free_reason reason)
 {
-       if (atomic_dec_and_test(&skb->users)) {
-               struct softnet_data *sd;
-               unsigned long flags;
+       unsigned long flags;
 
-               local_irq_save(flags);
-               sd = &__get_cpu_var(softnet_data);
-               skb->next = sd->completion_queue;
-               sd->completion_queue = skb;
-               raise_softirq_irqoff(NET_TX_SOFTIRQ);
-               local_irq_restore(flags);
+       if (likely(atomic_read(&skb->users) == 1)) {
+               smp_rmb();
+               atomic_set(&skb->users, 0);
+       } else if (likely(!atomic_dec_and_test(&skb->users))) {
+               return;
        }
+       get_kfree_skb_cb(skb)->reason = reason;
+       local_irq_save(flags);
+       skb->next = __this_cpu_read(softnet_data.completion_queue);
+       __this_cpu_write(softnet_data.completion_queue, skb);
+       raise_softirq_irqoff(NET_TX_SOFTIRQ);
+       local_irq_restore(flags);
 }
-EXPORT_SYMBOL(dev_kfree_skb_irq);
+EXPORT_SYMBOL(__dev_kfree_skb_irq);
 
-void dev_kfree_skb_any(struct sk_buff *skb)
+void __dev_kfree_skb_any(struct sk_buff *skb, enum skb_free_reason reason)
 {
        if (in_irq() || irqs_disabled())
-               dev_kfree_skb_irq(skb);
+               __dev_kfree_skb_irq(skb, reason);
        else
                dev_kfree_skb(skb);
 }
-EXPORT_SYMBOL(dev_kfree_skb_any);
+EXPORT_SYMBOL(__dev_kfree_skb_any);
 
 
 /**
@@ -2523,21 +2535,6 @@ netdev_features_t netif_skb_features(struct sk_buff *skb)
 }
 EXPORT_SYMBOL(netif_skb_features);
 
-/*
- * Returns true if either:
- *     1. skb has frag_list and the device doesn't support FRAGLIST, or
- *     2. skb is fragmented and the device does not support SG.
- */
-static inline int skb_needs_linearize(struct sk_buff *skb,
-                                     netdev_features_t features)
-{
-       return skb_is_nonlinear(skb) &&
-                       ((skb_has_frag_list(skb) &&
-                               !(features & NETIF_F_FRAGLIST)) ||
-                       (skb_shinfo(skb)->nr_frags &&
-                               !(features & NETIF_F_SG)));
-}
-
 int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
                        struct netdev_queue *txq, void *accel_priv)
 {
@@ -3306,7 +3303,10 @@ static void net_tx_action(struct softirq_action *h)
                        clist = clist->next;
 
                        WARN_ON(atomic_read(&skb->users));
-                       trace_kfree_skb(skb, net_tx_action);
+                       if (likely(get_kfree_skb_cb(skb)->reason == SKB_REASON_CONSUMED))
+                               trace_consume_skb(skb);
+                       else
+                               trace_kfree_skb(skb, net_tx_action);
                        __kfree_skb(skb);
                }
        }
@@ -3981,8 +3981,7 @@ struct sk_buff *napi_get_frags(struct napi_struct *napi)
 
        if (!skb) {
                skb = netdev_alloc_skb_ip_align(napi->dev, GRO_MAX_HEAD);
-               if (skb)
-                       napi->skb = skb;
+               napi->skb = skb;
        }
        return skb;
 }
@@ -6224,7 +6223,7 @@ void netdev_freemem(struct net_device *dev)
  *     @rxqs:          the number of RX subqueues to allocate
  *
  *     Allocates a struct net_device with private data area for driver use
- *     and performs basic initialization.  Also allocates subquue structs
+ *     and performs basic initialization.  Also allocates subqueue structs
  *     for each queue on the device.
  */
 struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
index 5b7d0e1d0664b1b00d5f30a30248f88fbacde2fd..cf999e09bcd2c23654826b8c7e7b3d3dde2a7a59 100644 (file)
@@ -327,6 +327,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
                    cmd == SIOCBRADDIF ||
                    cmd == SIOCBRDELIF ||
                    cmd == SIOCSHWTSTAMP ||
+                   cmd == SIOCGHWTSTAMP ||
                    cmd == SIOCWANDEV) {
                        err = -EOPNOTSUPP;
                        if (ops->ndo_do_ioctl) {
@@ -546,6 +547,7 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
         */
        default:
                if (cmd == SIOCWANDEV ||
+                   cmd == SIOCGHWTSTAMP ||
                    (cmd >= SIOCDEVPRIVATE &&
                     cmd <= SIOCDEVPRIVATE + 15)) {
                        dev_load(net, ifr.ifr_name);
index 95897183226e18882bdbe16d8e9ba3a111ffae71..e70301eb7a4a0472d1ade5bd3d318fe453bd2b8b 100644 (file)
@@ -64,7 +64,6 @@ static struct genl_family net_drop_monitor_family = {
        .hdrsize        = 0,
        .name           = "NET_DM",
        .version        = 2,
-       .maxattr        = NET_DM_CMD_MAX,
 };
 
 static DEFINE_PER_CPU(struct per_cpu_dm_data, dm_cpu_data);
index ca15f32821fb8d536586354108488050b7cc6a0e..bf6f404c04aa5d0c951f3d7322fe89b00f3b1ec4 100644 (file)
@@ -38,6 +38,8 @@
 #include <linux/random.h>
 #include <linux/string.h>
 #include <linux/log2.h>
+#include <linux/inetdevice.h>
+#include <net/addrconf.h>
 
 #define DEBUG
 #define NEIGH_DEBUG 1
@@ -497,7 +499,7 @@ struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey,
                goto out_neigh_release;
        }
 
-       n->confirmed = jiffies - (n->parms->base_reachable_time << 1);
+       n->confirmed = jiffies - (NEIGH_VAR(n->parms, BASE_REACHABLE_TIME) << 1);
 
        write_lock_bh(&tbl->lock);
        nht = rcu_dereference_protected(tbl->nht,
@@ -776,7 +778,7 @@ static void neigh_periodic_work(struct work_struct *work)
                tbl->last_rand = jiffies;
                for (p = &tbl->parms; p; p = p->next)
                        p->reachable_time =
-                               neigh_rand_reach_time(p->base_reachable_time);
+                               neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
        }
 
        for (i = 0 ; i < (1 << nht->hash_shift); i++) {
@@ -799,7 +801,7 @@ static void neigh_periodic_work(struct work_struct *work)
 
                        if (atomic_read(&n->refcnt) == 1 &&
                            (state == NUD_FAILED ||
-                            time_after(jiffies, n->used + n->parms->gc_staletime))) {
+                            time_after(jiffies, n->used + NEIGH_VAR(n->parms, GC_STALETIME)))) {
                                *np = n->next;
                                n->dead = 1;
                                write_unlock(&n->lock);
@@ -822,12 +824,12 @@ next_elt:
                                                lockdep_is_held(&tbl->lock));
        }
 out:
-       /* Cycle through all hash buckets every base_reachable_time/2 ticks.
-        * ARP entry timeouts range from 1/2 base_reachable_time to 3/2
-        * base_reachable_time.
+       /* Cycle through all hash buckets every BASE_REACHABLE_TIME/2 ticks.
+        * ARP entry timeouts range from 1/2 BASE_REACHABLE_TIME to 3/2
+        * BASE_REACHABLE_TIME.
         */
        schedule_delayed_work(&tbl->gc_work,
-                             tbl->parms.base_reachable_time >> 1);
+                             NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME) >> 1);
        write_unlock_bh(&tbl->lock);
 }
 
@@ -835,8 +837,9 @@ static __inline__ int neigh_max_probes(struct neighbour *n)
 {
        struct neigh_parms *p = n->parms;
        return (n->nud_state & NUD_PROBE) ?
-               p->ucast_probes :
-               p->ucast_probes + p->app_probes + p->mcast_probes;
+               NEIGH_VAR(p, UCAST_PROBES) :
+               NEIGH_VAR(p, UCAST_PROBES) + NEIGH_VAR(p, APP_PROBES) +
+               NEIGH_VAR(p, MCAST_PROBES);
 }
 
 static void neigh_invalidate(struct neighbour *neigh)
@@ -901,12 +904,13 @@ static void neigh_timer_handler(unsigned long arg)
                        neigh_dbg(2, "neigh %p is still alive\n", neigh);
                        next = neigh->confirmed + neigh->parms->reachable_time;
                } else if (time_before_eq(now,
-                                         neigh->used + neigh->parms->delay_probe_time)) {
+                                         neigh->used +
+                                         NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
                        neigh_dbg(2, "neigh %p is delayed\n", neigh);
                        neigh->nud_state = NUD_DELAY;
                        neigh->updated = jiffies;
                        neigh_suspect(neigh);
-                       next = now + neigh->parms->delay_probe_time;
+                       next = now + NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME);
                } else {
                        neigh_dbg(2, "neigh %p is suspected\n", neigh);
                        neigh->nud_state = NUD_STALE;
@@ -916,7 +920,8 @@ static void neigh_timer_handler(unsigned long arg)
                }
        } else if (state & NUD_DELAY) {
                if (time_before_eq(now,
-                                  neigh->confirmed + neigh->parms->delay_probe_time)) {
+                                  neigh->confirmed +
+                                  NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
                        neigh_dbg(2, "neigh %p is now reachable\n", neigh);
                        neigh->nud_state = NUD_REACHABLE;
                        neigh->updated = jiffies;
@@ -928,11 +933,11 @@ static void neigh_timer_handler(unsigned long arg)
                        neigh->nud_state = NUD_PROBE;
                        neigh->updated = jiffies;
                        atomic_set(&neigh->probes, 0);
-                       next = now + neigh->parms->retrans_time;
+                       next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
                }
        } else {
                /* NUD_PROBE|NUD_INCOMPLETE */
-               next = now + neigh->parms->retrans_time;
+               next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
        }
 
        if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) &&
@@ -973,13 +978,16 @@ int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
                goto out_unlock_bh;
 
        if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) {
-               if (neigh->parms->mcast_probes + neigh->parms->app_probes) {
+               if (NEIGH_VAR(neigh->parms, MCAST_PROBES) +
+                   NEIGH_VAR(neigh->parms, APP_PROBES)) {
                        unsigned long next, now = jiffies;
 
-                       atomic_set(&neigh->probes, neigh->parms->ucast_probes);
+                       atomic_set(&neigh->probes,
+                                  NEIGH_VAR(neigh->parms, UCAST_PROBES));
                        neigh->nud_state     = NUD_INCOMPLETE;
                        neigh->updated = now;
-                       next = now + max(neigh->parms->retrans_time, HZ/2);
+                       next = now + max(NEIGH_VAR(neigh->parms, RETRANS_TIME),
+                                        HZ/2);
                        neigh_add_timer(neigh, next);
                        immediate_probe = true;
                } else {
@@ -994,14 +1002,14 @@ int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
                neigh_dbg(2, "neigh %p is delayed\n", neigh);
                neigh->nud_state = NUD_DELAY;
                neigh->updated = jiffies;
-               neigh_add_timer(neigh,
-                               jiffies + neigh->parms->delay_probe_time);
+               neigh_add_timer(neigh, jiffies +
+                               NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME));
        }
 
        if (neigh->nud_state == NUD_INCOMPLETE) {
                if (skb) {
                        while (neigh->arp_queue_len_bytes + skb->truesize >
-                              neigh->parms->queue_len_bytes) {
+                              NEIGH_VAR(neigh->parms, QUEUE_LEN_BYTES)) {
                                struct sk_buff *buff;
 
                                buff = __skb_dequeue(&neigh->arp_queue);
@@ -1170,7 +1178,7 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
                neigh_update_hhs(neigh);
                if (!(new & NUD_CONNECTED))
                        neigh->confirmed = jiffies -
-                                     (neigh->parms->base_reachable_time << 1);
+                                     (NEIGH_VAR(neigh->parms, BASE_REACHABLE_TIME) << 1);
                notify = 1;
        }
        if (new == old)
@@ -1230,6 +1238,21 @@ out:
 }
 EXPORT_SYMBOL(neigh_update);
 
+/* Update the neigh to listen temporarily for probe responses, even if it is
+ * in a NUD_FAILED state. The caller has to hold neigh->lock for writing.
+ */
+void __neigh_set_probe_once(struct neighbour *neigh)
+{
+       neigh->updated = jiffies;
+       if (!(neigh->nud_state & NUD_FAILED))
+               return;
+       neigh->nud_state = NUD_PROBE;
+       atomic_set(&neigh->probes, NEIGH_VAR(neigh->parms, UCAST_PROBES));
+       neigh_add_timer(neigh,
+                       jiffies + NEIGH_VAR(neigh->parms, RETRANS_TIME));
+}
+EXPORT_SYMBOL(__neigh_set_probe_once);
+
 struct neighbour *neigh_event_ns(struct neigh_table *tbl,
                                 u8 *lladdr, void *saddr,
                                 struct net_device *dev)
@@ -1391,9 +1414,10 @@ void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
                    struct sk_buff *skb)
 {
        unsigned long now = jiffies;
-       unsigned long sched_next = now + (net_random() % p->proxy_delay);
+       unsigned long sched_next = now + (net_random() %
+                                         NEIGH_VAR(p, PROXY_DELAY));
 
-       if (tbl->proxy_queue.qlen > p->proxy_qlen) {
+       if (tbl->proxy_queue.qlen > NEIGH_VAR(p, PROXY_QLEN)) {
                kfree_skb(skb);
                return;
        }
@@ -1440,7 +1464,7 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
                p->tbl            = tbl;
                atomic_set(&p->refcnt, 1);
                p->reachable_time =
-                               neigh_rand_reach_time(p->base_reachable_time);
+                               neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
                dev_hold(dev);
                p->dev = dev;
                write_pnet(&p->net, hold_net(net));
@@ -1457,6 +1481,8 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
                p->next         = tbl->parms.next;
                tbl->parms.next = p;
                write_unlock_bh(&tbl->lock);
+
+               neigh_parms_data_state_cleanall(p);
        }
        return p;
 }
@@ -1509,7 +1535,7 @@ static void neigh_table_init_no_netlink(struct neigh_table *tbl)
        write_pnet(&tbl->parms.net, &init_net);
        atomic_set(&tbl->parms.refcnt, 1);
        tbl->parms.reachable_time =
-                         neigh_rand_reach_time(tbl->parms.base_reachable_time);
+                         neigh_rand_reach_time(NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME));
 
        tbl->stats = alloc_percpu(struct neigh_statistics);
        if (!tbl->stats)
@@ -1777,24 +1803,32 @@ static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
        if ((parms->dev &&
             nla_put_u32(skb, NDTPA_IFINDEX, parms->dev->ifindex)) ||
            nla_put_u32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt)) ||
-           nla_put_u32(skb, NDTPA_QUEUE_LENBYTES, parms->queue_len_bytes) ||
+           nla_put_u32(skb, NDTPA_QUEUE_LENBYTES,
+                       NEIGH_VAR(parms, QUEUE_LEN_BYTES)) ||
            /* approximative value for deprecated QUEUE_LEN (in packets) */
            nla_put_u32(skb, NDTPA_QUEUE_LEN,
-                       parms->queue_len_bytes / SKB_TRUESIZE(ETH_FRAME_LEN)) ||
-           nla_put_u32(skb, NDTPA_PROXY_QLEN, parms->proxy_qlen) ||
-           nla_put_u32(skb, NDTPA_APP_PROBES, parms->app_probes) ||
-           nla_put_u32(skb, NDTPA_UCAST_PROBES, parms->ucast_probes) ||
-           nla_put_u32(skb, NDTPA_MCAST_PROBES, parms->mcast_probes) ||
+                       NEIGH_VAR(parms, QUEUE_LEN_BYTES) / SKB_TRUESIZE(ETH_FRAME_LEN)) ||
+           nla_put_u32(skb, NDTPA_PROXY_QLEN, NEIGH_VAR(parms, PROXY_QLEN)) ||
+           nla_put_u32(skb, NDTPA_APP_PROBES, NEIGH_VAR(parms, APP_PROBES)) ||
+           nla_put_u32(skb, NDTPA_UCAST_PROBES,
+                       NEIGH_VAR(parms, UCAST_PROBES)) ||
+           nla_put_u32(skb, NDTPA_MCAST_PROBES,
+                       NEIGH_VAR(parms, MCAST_PROBES)) ||
            nla_put_msecs(skb, NDTPA_REACHABLE_TIME, parms->reachable_time) ||
            nla_put_msecs(skb, NDTPA_BASE_REACHABLE_TIME,
-                         parms->base_reachable_time) ||
-           nla_put_msecs(skb, NDTPA_GC_STALETIME, parms->gc_staletime) ||
+                         NEIGH_VAR(parms, BASE_REACHABLE_TIME)) ||
+           nla_put_msecs(skb, NDTPA_GC_STALETIME,
+                         NEIGH_VAR(parms, GC_STALETIME)) ||
            nla_put_msecs(skb, NDTPA_DELAY_PROBE_TIME,
-                         parms->delay_probe_time) ||
-           nla_put_msecs(skb, NDTPA_RETRANS_TIME, parms->retrans_time) ||
-           nla_put_msecs(skb, NDTPA_ANYCAST_DELAY, parms->anycast_delay) ||
-           nla_put_msecs(skb, NDTPA_PROXY_DELAY, parms->proxy_delay) ||
-           nla_put_msecs(skb, NDTPA_LOCKTIME, parms->locktime))
+                         NEIGH_VAR(parms, DELAY_PROBE_TIME)) ||
+           nla_put_msecs(skb, NDTPA_RETRANS_TIME,
+                         NEIGH_VAR(parms, RETRANS_TIME)) ||
+           nla_put_msecs(skb, NDTPA_ANYCAST_DELAY,
+                         NEIGH_VAR(parms, ANYCAST_DELAY)) ||
+           nla_put_msecs(skb, NDTPA_PROXY_DELAY,
+                         NEIGH_VAR(parms, PROXY_DELAY)) ||
+           nla_put_msecs(skb, NDTPA_LOCKTIME,
+                         NEIGH_VAR(parms, LOCKTIME)))
                goto nla_put_failure;
        return nla_nest_end(skb, nest);
 
@@ -2010,44 +2044,54 @@ static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh)
 
                        switch (i) {
                        case NDTPA_QUEUE_LEN:
-                               p->queue_len_bytes = nla_get_u32(tbp[i]) *
-                                                    SKB_TRUESIZE(ETH_FRAME_LEN);
+                               NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
+                                             nla_get_u32(tbp[i]) *
+                                             SKB_TRUESIZE(ETH_FRAME_LEN));
                                break;
                        case NDTPA_QUEUE_LENBYTES:
-                               p->queue_len_bytes = nla_get_u32(tbp[i]);
+                               NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
+                                             nla_get_u32(tbp[i]));
                                break;
                        case NDTPA_PROXY_QLEN:
-                               p->proxy_qlen = nla_get_u32(tbp[i]);
+                               NEIGH_VAR_SET(p, PROXY_QLEN,
+                                             nla_get_u32(tbp[i]));
                                break;
                        case NDTPA_APP_PROBES:
-                               p->app_probes = nla_get_u32(tbp[i]);
+                               NEIGH_VAR_SET(p, APP_PROBES,
+                                             nla_get_u32(tbp[i]));
                                break;
                        case NDTPA_UCAST_PROBES:
-                               p->ucast_probes = nla_get_u32(tbp[i]);
+                               NEIGH_VAR_SET(p, UCAST_PROBES,
+                                             nla_get_u32(tbp[i]));
                                break;
                        case NDTPA_MCAST_PROBES:
-                               p->mcast_probes = nla_get_u32(tbp[i]);
+                               NEIGH_VAR_SET(p, MCAST_PROBES,
+                                             nla_get_u32(tbp[i]));
                                break;
                        case NDTPA_BASE_REACHABLE_TIME:
-                               p->base_reachable_time = nla_get_msecs(tbp[i]);
+                               NEIGH_VAR_SET(p, BASE_REACHABLE_TIME,
+                                             nla_get_msecs(tbp[i]));
                                break;
                        case NDTPA_GC_STALETIME:
-                               p->gc_staletime = nla_get_msecs(tbp[i]);
+                               NEIGH_VAR_SET(p, GC_STALETIME,
+                                             nla_get_msecs(tbp[i]));
                                break;
                        case NDTPA_DELAY_PROBE_TIME:
-                               p->delay_probe_time = nla_get_msecs(tbp[i]);
+                               NEIGH_VAR_SET(p, DELAY_PROBE_TIME,
+                                             nla_get_msecs(tbp[i]));
                                break;
                        case NDTPA_RETRANS_TIME:
-                               p->retrans_time = nla_get_msecs(tbp[i]);
+                               NEIGH_VAR_SET(p, RETRANS_TIME,
+                                             nla_get_msecs(tbp[i]));
                                break;
                        case NDTPA_ANYCAST_DELAY:
-                               p->anycast_delay = nla_get_msecs(tbp[i]);
+                               NEIGH_VAR_SET(p, ANYCAST_DELAY, nla_get_msecs(tbp[i]));
                                break;
                        case NDTPA_PROXY_DELAY:
-                               p->proxy_delay = nla_get_msecs(tbp[i]);
+                               NEIGH_VAR_SET(p, PROXY_DELAY, nla_get_msecs(tbp[i]));
                                break;
                        case NDTPA_LOCKTIME:
-                               p->locktime = nla_get_msecs(tbp[i]);
+                               NEIGH_VAR_SET(p, LOCKTIME, nla_get_msecs(tbp[i]));
                                break;
                        }
                }
@@ -2788,133 +2832,167 @@ static int proc_unres_qlen(struct ctl_table *ctl, int write,
        return ret;
 }
 
-enum {
-       NEIGH_VAR_MCAST_PROBE,
-       NEIGH_VAR_UCAST_PROBE,
-       NEIGH_VAR_APP_PROBE,
-       NEIGH_VAR_RETRANS_TIME,
-       NEIGH_VAR_BASE_REACHABLE_TIME,
-       NEIGH_VAR_DELAY_PROBE_TIME,
-       NEIGH_VAR_GC_STALETIME,
-       NEIGH_VAR_QUEUE_LEN,
-       NEIGH_VAR_QUEUE_LEN_BYTES,
-       NEIGH_VAR_PROXY_QLEN,
-       NEIGH_VAR_ANYCAST_DELAY,
-       NEIGH_VAR_PROXY_DELAY,
-       NEIGH_VAR_LOCKTIME,
-       NEIGH_VAR_RETRANS_TIME_MS,
-       NEIGH_VAR_BASE_REACHABLE_TIME_MS,
-       NEIGH_VAR_GC_INTERVAL,
-       NEIGH_VAR_GC_THRESH1,
-       NEIGH_VAR_GC_THRESH2,
-       NEIGH_VAR_GC_THRESH3,
-       NEIGH_VAR_MAX
-};
+static struct neigh_parms *neigh_get_dev_parms_rcu(struct net_device *dev,
+                                                  int family)
+{
+       switch (family) {
+       case AF_INET:
+               return __in_dev_arp_parms_get_rcu(dev);
+       case AF_INET6:
+               return __in6_dev_nd_parms_get_rcu(dev);
+       }
+       return NULL;
+}
+
+static void neigh_copy_dflt_parms(struct net *net, struct neigh_parms *p,
+                                 int index)
+{
+       struct net_device *dev;
+       int family = neigh_parms_family(p);
+
+       rcu_read_lock();
+       for_each_netdev_rcu(net, dev) {
+               struct neigh_parms *dst_p =
+                               neigh_get_dev_parms_rcu(dev, family);
+
+               if (dst_p && !test_bit(index, dst_p->data_state))
+                       dst_p->data[index] = p->data[index];
+       }
+       rcu_read_unlock();
+}
+
+static void neigh_proc_update(struct ctl_table *ctl, int write)
+{
+       struct net_device *dev = ctl->extra1;
+       struct neigh_parms *p = ctl->extra2;
+       struct net *net = neigh_parms_net(p);
+       int index = (int *) ctl->data - p->data;
+
+       if (!write)
+               return;
+
+       set_bit(index, p->data_state);
+       if (!dev) /* NULL dev means this is default value */
+               neigh_copy_dflt_parms(net, p, index);
+}
+
+static int neigh_proc_dointvec_zero_intmax(struct ctl_table *ctl, int write,
+                                          void __user *buffer,
+                                          size_t *lenp, loff_t *ppos)
+{
+       struct ctl_table tmp = *ctl;
+       int ret;
+
+       tmp.extra1 = &zero;
+       tmp.extra2 = &int_max;
+
+       ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
+       neigh_proc_update(ctl, write);
+       return ret;
+}
+
+int neigh_proc_dointvec(struct ctl_table *ctl, int write,
+                       void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
+
+       neigh_proc_update(ctl, write);
+       return ret;
+}
+EXPORT_SYMBOL(neigh_proc_dointvec);
+
+int neigh_proc_dointvec_jiffies(struct ctl_table *ctl, int write,
+                               void __user *buffer,
+                               size_t *lenp, loff_t *ppos)
+{
+       int ret = proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
+
+       neigh_proc_update(ctl, write);
+       return ret;
+}
+EXPORT_SYMBOL(neigh_proc_dointvec_jiffies);
+
+static int neigh_proc_dointvec_userhz_jiffies(struct ctl_table *ctl, int write,
+                                             void __user *buffer,
+                                             size_t *lenp, loff_t *ppos)
+{
+       int ret = proc_dointvec_userhz_jiffies(ctl, write, buffer, lenp, ppos);
+
+       neigh_proc_update(ctl, write);
+       return ret;
+}
+
+int neigh_proc_dointvec_ms_jiffies(struct ctl_table *ctl, int write,
+                                  void __user *buffer,
+                                  size_t *lenp, loff_t *ppos)
+{
+       int ret = proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
+
+       neigh_proc_update(ctl, write);
+       return ret;
+}
+EXPORT_SYMBOL(neigh_proc_dointvec_ms_jiffies);
+
+static int neigh_proc_dointvec_unres_qlen(struct ctl_table *ctl, int write,
+                                         void __user *buffer,
+                                         size_t *lenp, loff_t *ppos)
+{
+       int ret = proc_unres_qlen(ctl, write, buffer, lenp, ppos);
+
+       neigh_proc_update(ctl, write);
+       return ret;
+}
+
+#define NEIGH_PARMS_DATA_OFFSET(index) \
+       (&((struct neigh_parms *) 0)->data[index])
+
+#define NEIGH_SYSCTL_ENTRY(attr, data_attr, name, mval, proc) \
+       [NEIGH_VAR_ ## attr] = { \
+               .procname       = name, \
+               .data           = NEIGH_PARMS_DATA_OFFSET(NEIGH_VAR_ ## data_attr), \
+               .maxlen         = sizeof(int), \
+               .mode           = mval, \
+               .proc_handler   = proc, \
+       }
+
+#define NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(attr, name) \
+       NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_zero_intmax)
+
+#define NEIGH_SYSCTL_JIFFIES_ENTRY(attr, name) \
+       NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_jiffies)
+
+#define NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(attr, name) \
+       NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_userhz_jiffies)
+
+#define NEIGH_SYSCTL_MS_JIFFIES_ENTRY(attr, name) \
+       NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
+
+#define NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(attr, data_attr, name) \
+       NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
+
+#define NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(attr, data_attr, name) \
+       NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_unres_qlen)
 
 static struct neigh_sysctl_table {
        struct ctl_table_header *sysctl_header;
        struct ctl_table neigh_vars[NEIGH_VAR_MAX + 1];
 } neigh_sysctl_template __read_mostly = {
        .neigh_vars = {
-               [NEIGH_VAR_MCAST_PROBE] = {
-                       .procname       = "mcast_solicit",
-                       .maxlen         = sizeof(int),
-                       .mode           = 0644,
-                       .extra1         = &zero,
-                       .extra2         = &int_max,
-                       .proc_handler   = proc_dointvec_minmax,
-               },
-               [NEIGH_VAR_UCAST_PROBE] = {
-                       .procname       = "ucast_solicit",
-                       .maxlen         = sizeof(int),
-                       .mode           = 0644,
-                       .extra1         = &zero,
-                       .extra2         = &int_max,
-                       .proc_handler   = proc_dointvec_minmax,
-               },
-               [NEIGH_VAR_APP_PROBE] = {
-                       .procname       = "app_solicit",
-                       .maxlen         = sizeof(int),
-                       .mode           = 0644,
-                       .extra1         = &zero,
-                       .extra2         = &int_max,
-                       .proc_handler   = proc_dointvec_minmax,
-               },
-               [NEIGH_VAR_RETRANS_TIME] = {
-                       .procname       = "retrans_time",
-                       .maxlen         = sizeof(int),
-                       .mode           = 0644,
-                       .proc_handler   = proc_dointvec_userhz_jiffies,
-               },
-               [NEIGH_VAR_BASE_REACHABLE_TIME] = {
-                       .procname       = "base_reachable_time",
-                       .maxlen         = sizeof(int),
-                       .mode           = 0644,
-                       .proc_handler   = proc_dointvec_jiffies,
-               },
-               [NEIGH_VAR_DELAY_PROBE_TIME] = {
-                       .procname       = "delay_first_probe_time",
-                       .maxlen         = sizeof(int),
-                       .mode           = 0644,
-                       .proc_handler   = proc_dointvec_jiffies,
-               },
-               [NEIGH_VAR_GC_STALETIME] = {
-                       .procname       = "gc_stale_time",
-                       .maxlen         = sizeof(int),
-                       .mode           = 0644,
-                       .proc_handler   = proc_dointvec_jiffies,
-               },
-               [NEIGH_VAR_QUEUE_LEN] = {
-                       .procname       = "unres_qlen",
-                       .maxlen         = sizeof(int),
-                       .mode           = 0644,
-                       .proc_handler   = proc_unres_qlen,
-               },
-               [NEIGH_VAR_QUEUE_LEN_BYTES] = {
-                       .procname       = "unres_qlen_bytes",
-                       .maxlen         = sizeof(int),
-                       .mode           = 0644,
-                       .extra1         = &zero,
-                       .proc_handler   = proc_dointvec_minmax,
-               },
-               [NEIGH_VAR_PROXY_QLEN] = {
-                       .procname       = "proxy_qlen",
-                       .maxlen         = sizeof(int),
-                       .mode           = 0644,
-                       .extra1         = &zero,
-                       .extra2         = &int_max,
-                       .proc_handler   = proc_dointvec_minmax,
-               },
-               [NEIGH_VAR_ANYCAST_DELAY] = {
-                       .procname       = "anycast_delay",
-                       .maxlen         = sizeof(int),
-                       .mode           = 0644,
-                       .proc_handler   = proc_dointvec_userhz_jiffies,
-               },
-               [NEIGH_VAR_PROXY_DELAY] = {
-                       .procname       = "proxy_delay",
-                       .maxlen         = sizeof(int),
-                       .mode           = 0644,
-                       .proc_handler   = proc_dointvec_userhz_jiffies,
-               },
-               [NEIGH_VAR_LOCKTIME] = {
-                       .procname       = "locktime",
-                       .maxlen         = sizeof(int),
-                       .mode           = 0644,
-                       .proc_handler   = proc_dointvec_userhz_jiffies,
-               },
-               [NEIGH_VAR_RETRANS_TIME_MS] = {
-                       .procname       = "retrans_time_ms",
-                       .maxlen         = sizeof(int),
-                       .mode           = 0644,
-                       .proc_handler   = proc_dointvec_ms_jiffies,
-               },
-               [NEIGH_VAR_BASE_REACHABLE_TIME_MS] = {
-                       .procname       = "base_reachable_time_ms",
-                       .maxlen         = sizeof(int),
-                       .mode           = 0644,
-                       .proc_handler   = proc_dointvec_ms_jiffies,
-               },
+               NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_PROBES, "mcast_solicit"),
+               NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(UCAST_PROBES, "ucast_solicit"),
+               NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(APP_PROBES, "app_solicit"),
+               NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(RETRANS_TIME, "retrans_time"),
+               NEIGH_SYSCTL_JIFFIES_ENTRY(BASE_REACHABLE_TIME, "base_reachable_time"),
+               NEIGH_SYSCTL_JIFFIES_ENTRY(DELAY_PROBE_TIME, "delay_first_probe_time"),
+               NEIGH_SYSCTL_JIFFIES_ENTRY(GC_STALETIME, "gc_stale_time"),
+               NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(QUEUE_LEN_BYTES, "unres_qlen_bytes"),
+               NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(PROXY_QLEN, "proxy_qlen"),
+               NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(ANYCAST_DELAY, "anycast_delay"),
+               NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(PROXY_DELAY, "proxy_delay"),
+               NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(LOCKTIME, "locktime"),
+               NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(QUEUE_LEN, QUEUE_LEN_BYTES, "unres_qlen"),
+               NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(RETRANS_TIME_MS, RETRANS_TIME, "retrans_time_ms"),
+               NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(BASE_REACHABLE_TIME_MS, BASE_REACHABLE_TIME, "base_reachable_time_ms"),
                [NEIGH_VAR_GC_INTERVAL] = {
                        .procname       = "gc_interval",
                        .maxlen         = sizeof(int),
@@ -2950,31 +3028,23 @@ static struct neigh_sysctl_table {
 };
 
 int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
-                         char *p_name, proc_handler *handler)
+                         proc_handler *handler)
 {
+       int i;
        struct neigh_sysctl_table *t;
-       const char *dev_name_source = NULL;
+       const char *dev_name_source;
        char neigh_path[ sizeof("net//neigh/") + IFNAMSIZ + IFNAMSIZ ];
+       char *p_name;
 
        t = kmemdup(&neigh_sysctl_template, sizeof(*t), GFP_KERNEL);
        if (!t)
                goto err;
 
-       t->neigh_vars[NEIGH_VAR_MCAST_PROBE].data  = &p->mcast_probes;
-       t->neigh_vars[NEIGH_VAR_UCAST_PROBE].data  = &p->ucast_probes;
-       t->neigh_vars[NEIGH_VAR_APP_PROBE].data  = &p->app_probes;
-       t->neigh_vars[NEIGH_VAR_RETRANS_TIME].data  = &p->retrans_time;
-       t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].data  = &p->base_reachable_time;
-       t->neigh_vars[NEIGH_VAR_DELAY_PROBE_TIME].data  = &p->delay_probe_time;
-       t->neigh_vars[NEIGH_VAR_GC_STALETIME].data  = &p->gc_staletime;
-       t->neigh_vars[NEIGH_VAR_QUEUE_LEN].data  = &p->queue_len_bytes;
-       t->neigh_vars[NEIGH_VAR_QUEUE_LEN_BYTES].data  = &p->queue_len_bytes;
-       t->neigh_vars[NEIGH_VAR_PROXY_QLEN].data  = &p->proxy_qlen;
-       t->neigh_vars[NEIGH_VAR_ANYCAST_DELAY].data  = &p->anycast_delay;
-       t->neigh_vars[NEIGH_VAR_PROXY_DELAY].data = &p->proxy_delay;
-       t->neigh_vars[NEIGH_VAR_LOCKTIME].data = &p->locktime;
-       t->neigh_vars[NEIGH_VAR_RETRANS_TIME_MS].data  = &p->retrans_time;
-       t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].data  = &p->base_reachable_time;
+       for (i = 0; i < ARRAY_SIZE(t->neigh_vars); i++) {
+               t->neigh_vars[i].data += (long) p;
+               t->neigh_vars[i].extra1 = dev;
+               t->neigh_vars[i].extra2 = p;
+       }
 
        if (dev) {
                dev_name_source = dev->name;
@@ -2989,26 +3059,32 @@ int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
                t->neigh_vars[NEIGH_VAR_GC_THRESH3].data = (int *)(p + 1) + 3;
        }
 
-
        if (handler) {
                /* RetransTime */
                t->neigh_vars[NEIGH_VAR_RETRANS_TIME].proc_handler = handler;
-               t->neigh_vars[NEIGH_VAR_RETRANS_TIME].extra1 = dev;
                /* ReachableTime */
                t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler = handler;
-               t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].extra1 = dev;
                /* RetransTime (in milliseconds)*/
                t->neigh_vars[NEIGH_VAR_RETRANS_TIME_MS].proc_handler = handler;
-               t->neigh_vars[NEIGH_VAR_RETRANS_TIME_MS].extra1 = dev;
                /* ReachableTime (in milliseconds) */
                t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler = handler;
-               t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].extra1 = dev;
        }
 
        /* Don't export sysctls to unprivileged users */
        if (neigh_parms_net(p)->user_ns != &init_user_ns)
                t->neigh_vars[0].procname = NULL;
 
+       switch (neigh_parms_family(p)) {
+       case AF_INET:
+             p_name = "ipv4";
+             break;
+       case AF_INET6:
+             p_name = "ipv6";
+             break;
+       default:
+             BUG();
+       }
+
        snprintf(neigh_path, sizeof(neigh_path), "net/%s/neigh/%s",
                p_name, dev_name_source);
        t->sysctl_header =
index f3edf9635e029bb47c028cd2336dbeccb803c846..1a7b7b1df0d197febe3fecadca653dbe6d2c8a5b 100644 (file)
@@ -676,8 +676,8 @@ static ssize_t store_rps_dev_flow_table_cnt(struct netdev_rx_queue *queue,
                while ((mask | (mask >> 1)) != mask)
                        mask |= (mask >> 1);
                /* On 64 bit arches, must check mask fits in table->mask (u32),
-                * and on 32bit arches, must check RPS_DEV_FLOW_TABLE_SIZE(mask + 1)
-                * doesnt overflow.
+                * and on 32bit arches, must check
+                * RPS_DEV_FLOW_TABLE_SIZE(mask + 1) doesn't overflow.
                 */
 #if BITS_PER_LONG > 32
                if (mask > (unsigned long)(u32)mask)
index 9b7cf6c85f82447d3e03f33cd2c599de13ed3644..9043caedcd083bf48836d0a970d48d8c533f86ee 100644 (file)
@@ -30,7 +30,7 @@
 #define PRIOMAP_MIN_SZ         128
 
 /*
- * Extend @dev->priomap so that it's large enough to accomodate
+ * Extend @dev->priomap so that it's large enough to accommodate
  * @target_idx.  @dev->priomap.priomap_len > @target_idx after successful
  * return.  Must be called under rtnl lock.
  */
@@ -173,14 +173,14 @@ static u64 read_prioidx(struct cgroup_subsys_state *css, struct cftype *cft)
        return css->cgroup->id;
 }
 
-static int read_priomap(struct cgroup_subsys_state *css, struct cftype *cft,
-                       struct cgroup_map_cb *cb)
+static int read_priomap(struct seq_file *sf, void *v)
 {
        struct net_device *dev;
 
        rcu_read_lock();
        for_each_netdev_rcu(&init_net, dev)
-               cb->fill(cb, dev->name, netprio_prio(css, dev));
+               seq_printf(sf, "%s %u\n", dev->name,
+                          netprio_prio(seq_css(sf), dev));
        rcu_read_unlock();
        return 0;
 }
@@ -238,7 +238,7 @@ static struct cftype ss_files[] = {
        },
        {
                .name = "ifpriomap",
-               .read_map = read_priomap,
+               .seq_show = read_priomap,
                .write_string = write_priomap,
        },
        { }     /* terminate */
index 261357a663001ccf98a92ba5f6d0f6ad141c7ce3..a797fff7f22213f3e5d1be6f97ab632a791079a4 100644 (file)
@@ -2527,6 +2527,8 @@ static int process_ipsec(struct pktgen_dev *pkt_dev,
                if (x) {
                        int ret;
                        __u8 *eth;
+                       struct iphdr *iph;
+
                        nhead = x->props.header_len - skb_headroom(skb);
                        if (nhead > 0) {
                                ret = pskb_expand_head(skb, nhead, 0, GFP_ATOMIC);
@@ -2548,6 +2550,11 @@ static int process_ipsec(struct pktgen_dev *pkt_dev,
                        eth = (__u8 *) skb_push(skb, ETH_HLEN);
                        memcpy(eth, pkt_dev->hh, 12);
                        *(u16 *) &eth[12] = protocol;
+
+                       /* Update IPv4 header len as well as checksum value */
+                       iph = ip_hdr(skb);
+                       iph->tot_len = htons(skb->len - ETH_HLEN);
+                       ip_send_check(iph);
                }
        }
        return 1;
index 2718fed53d8cf5b81a06c82f8cdf8ed96632185a..06e72d3cdf60dbd96a3ad4829cfcc2baec0a80e8 100644 (file)
@@ -3584,6 +3584,7 @@ void skb_scrub_packet(struct sk_buff *skb, bool xnet)
        skb->tstamp.tv64 = 0;
        skb->pkt_type = PACKET_HOST;
        skb->skb_iif = 0;
+       skb->local_df = 0;
        skb_dst_drop(skb);
        skb->mark = 0;
        secpath_reset(skb);
index ab20ed9b0f31da64cb118cf645fa88f5787b5571..5393b4b719d71de2e3126664e3dcd5882c0c99d9 100644 (file)
@@ -882,7 +882,7 @@ set_rcvbuf:
 
        case SO_PEEK_OFF:
                if (sock->ops->set_peek_off)
-                       sock->ops->set_peek_off(sk, val);
+                       ret = sock->ops->set_peek_off(sk, val);
                else
                        ret = -EOPNOTSUPP;
                break;
index 4f72fc40bf029b6e18f2828c57d666ab6ba0bf44..a520d8004d895d421ee1f99bb78e4cf83bd858c5 100644 (file)
@@ -11,8 +11,7 @@
  * 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.
+ * this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * Author: John Fastabend <john.r.fastabend@intel.com>
  */
index 40d5829ed36aaa6945c9c4c2056325b68ab64c03..66fbe1948fb5d290a867a8517ffd0e70e85038e4 100644 (file)
@@ -11,8 +11,7 @@
  * 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.
+ * this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * Author: Lucy Liu <lucy.liu@intel.com>
  */
index d9f65fc66db5ea28773962387c008597d0f99269..88299c29101db7f8b52dba800ec19087b495f7dd 100644 (file)
@@ -75,7 +75,7 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        rt = ip_route_connect(fl4, nexthop, inet->inet_saddr,
                              RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
                              IPPROTO_DCCP,
-                             orig_sport, orig_dport, sk, true);
+                             orig_sport, orig_dport, sk);
        if (IS_ERR(rt))
                return PTR_ERR(rt);
 
index 4ac71ff7c2e47c4a3bcec19206845c8afd7ce9e8..3873fdb2143dbf1e1a26920fbafd70ed31badf92 100644 (file)
@@ -237,7 +237,7 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req)
 
        final_p = fl6_update_dst(&fl6, np->opt, &final);
 
-       dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false);
+       dst = ip6_dst_lookup_flow(sk, &fl6, final_p);
        if (IS_ERR(dst)) {
                err = PTR_ERR(dst);
                dst = NULL;
@@ -301,7 +301,7 @@ static void dccp_v6_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb)
        security_skb_classify_flow(rxskb, flowi6_to_flowi(&fl6));
 
        /* sk = NULL, but it is safe for now. RST socket required. */
-       dst = ip6_dst_lookup_flow(ctl_sk, &fl6, NULL, false);
+       dst = ip6_dst_lookup_flow(ctl_sk, &fl6, NULL);
        if (!IS_ERR(dst)) {
                skb_dst_set(skb, dst);
                ip6_xmit(ctl_sk, skb, &fl6, NULL, 0);
@@ -512,7 +512,7 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk,
                fl6.fl6_sport = htons(ireq->ir_num);
                security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
 
-               dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false);
+               dst = ip6_dst_lookup_flow(sk, &fl6, final_p);
                if (IS_ERR(dst))
                        goto out;
        }
@@ -851,7 +851,6 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
                        flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
                        if (flowlabel == NULL)
                                return -EINVAL;
-                       usin->sin6_addr = flowlabel->dst;
                        fl6_sock_release(flowlabel);
                }
        }
@@ -932,7 +931,7 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
 
        final_p = fl6_update_dst(&fl6, np->opt, &final);
 
-       dst = ip6_dst_lookup_flow(sk, &fl6, final_p, true);
+       dst = ip6_dst_lookup_flow(sk, &fl6, final_p);
        if (IS_ERR(dst)) {
                err = PTR_ERR(dst);
                goto failure;
index dd0dfb25f4b1c6945ab07a5190e7393abb42a3cc..a603823a3e279c850d1641e5f4d59be983400488 100644 (file)
@@ -561,6 +561,7 @@ static const struct nla_policy dn_ifa_policy[IFA_MAX+1] = {
        [IFA_LOCAL]             = { .type = NLA_U16 },
        [IFA_LABEL]             = { .type = NLA_STRING,
                                    .len = IFNAMSIZ - 1 },
+       [IFA_FLAGS]             = { .type = NLA_U32 },
 };
 
 static int dn_nl_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh)
@@ -648,7 +649,8 @@ static int dn_nl_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh)
 
        ifa->ifa_local = nla_get_le16(tb[IFA_LOCAL]);
        ifa->ifa_address = nla_get_le16(tb[IFA_ADDRESS]);
-       ifa->ifa_flags = ifm->ifa_flags;
+       ifa->ifa_flags = tb[IFA_FLAGS] ? nla_get_u32(tb[IFA_FLAGS]) :
+                                        ifm->ifa_flags;
        ifa->ifa_scope = ifm->ifa_scope;
        ifa->ifa_dev = dn_db;
 
@@ -669,7 +671,8 @@ static inline size_t dn_ifaddr_nlmsg_size(void)
        return NLMSG_ALIGN(sizeof(struct ifaddrmsg))
               + nla_total_size(IFNAMSIZ) /* IFA_LABEL */
               + nla_total_size(2) /* IFA_ADDRESS */
-              + nla_total_size(2); /* IFA_LOCAL */
+              + nla_total_size(2) /* IFA_LOCAL */
+              + nla_total_size(4); /* IFA_FLAGS */
 }
 
 static int dn_nl_fill_ifaddr(struct sk_buff *skb, struct dn_ifaddr *ifa,
@@ -677,6 +680,7 @@ static int dn_nl_fill_ifaddr(struct sk_buff *skb, struct dn_ifaddr *ifa,
 {
        struct ifaddrmsg *ifm;
        struct nlmsghdr *nlh;
+       u32 ifa_flags = ifa->ifa_flags | IFA_F_PERMANENT;
 
        nlh = nlmsg_put(skb, portid, seq, event, sizeof(*ifm), flags);
        if (nlh == NULL)
@@ -685,7 +689,7 @@ static int dn_nl_fill_ifaddr(struct sk_buff *skb, struct dn_ifaddr *ifa,
        ifm = nlmsg_data(nlh);
        ifm->ifa_family = AF_DECnet;
        ifm->ifa_prefixlen = 16;
-       ifm->ifa_flags = ifa->ifa_flags | IFA_F_PERMANENT;
+       ifm->ifa_flags = ifa_flags;
        ifm->ifa_scope = ifa->ifa_scope;
        ifm->ifa_index = ifa->ifa_dev->dev->ifindex;
 
@@ -694,7 +698,8 @@ static int dn_nl_fill_ifaddr(struct sk_buff *skb, struct dn_ifaddr *ifa,
            (ifa->ifa_local &&
             nla_put_le16(skb, IFA_LOCAL, ifa->ifa_local)) ||
            (ifa->ifa_label[0] &&
-            nla_put_string(skb, IFA_LABEL, ifa->ifa_label)))
+            nla_put_string(skb, IFA_LABEL, ifa->ifa_label)) ||
+            nla_put_u32(skb, IFA_FLAGS, ifa_flags))
                goto nla_put_failure;
        return nlmsg_end(skb, nlh);
 
index f8637f93d318fcfd568d088172e6dab664ccce84..c8121ceddb9e65a87830a710ced847de02dda358 100644 (file)
@@ -102,19 +102,21 @@ struct neigh_table dn_neigh_table = {
        .id =                           "dn_neigh_cache",
        .parms ={
                .tbl =                  &dn_neigh_table,
-               .base_reachable_time =  30 * HZ,
-               .retrans_time = 1 * HZ,
-               .gc_staletime = 60 * HZ,
-               .reachable_time =               30 * HZ,
-               .delay_probe_time =     5 * HZ,
-               .queue_len_bytes =      64*1024,
-               .ucast_probes = 0,
-               .app_probes =           0,
-               .mcast_probes = 0,
-               .anycast_delay =        0,
-               .proxy_delay =          0,
-               .proxy_qlen =           0,
-               .locktime =             1 * HZ,
+               .reachable_time =       30 * HZ,
+               .data = {
+                       [NEIGH_VAR_MCAST_PROBES] = 0,
+                       [NEIGH_VAR_UCAST_PROBES] = 0,
+                       [NEIGH_VAR_APP_PROBES] = 0,
+                       [NEIGH_VAR_RETRANS_TIME] = 1 * HZ,
+                       [NEIGH_VAR_BASE_REACHABLE_TIME] = 30 * HZ,
+                       [NEIGH_VAR_DELAY_PROBE_TIME] = 5 * HZ,
+                       [NEIGH_VAR_GC_STALETIME] = 60 * HZ,
+                       [NEIGH_VAR_QUEUE_LEN_BYTES] = 64*1024,
+                       [NEIGH_VAR_PROXY_QLEN] = 0,
+                       [NEIGH_VAR_ANYCAST_DELAY] = 0,
+                       [NEIGH_VAR_PROXY_DELAY] = 0,
+                       [NEIGH_VAR_LOCKTIME] = 1 * HZ,
+               },
        },
        .gc_interval =                  30 * HZ,
        .gc_thresh1 =                   128,
index fe32388ea24f7cc6811ea17ee3fb8d9f47042ee7..ad2efa5b861b5bd14bee8c8c69a7f909e8ddfbb9 100644 (file)
@@ -1288,8 +1288,6 @@ int dn_route_output_sock(struct dst_entry __rcu **pprt, struct flowidn *fl, stru
 
        err = __dn_route_output_key(pprt, fl, flags & MSG_TRYHARD);
        if (err == 0 && fl->flowidn_proto) {
-               if (!(flags & MSG_DONTWAIT))
-                       fl->flowidn_flags |= FLOWI_FLAG_CAN_SLEEP;
                *pprt = xfrm_lookup(&init_net, *pprt,
                                    flowidn_to_flowi(fl), sk, 0);
                if (IS_ERR(*pprt)) {
index f347a2ca7d7e6c5c1f6feae5e8edae91b487500e..bf85843390488d7768e3b3457c7e9e1139e50c19 100644 (file)
@@ -19,8 +19,7 @@
  *   the GNU Lesser General Public License for more details.
  *
  *   You should have received a copy of the GNU Lesser General Public License
- *   along with this library; if not, write to the Free Software
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *   along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 #include <linux/module.h>
 #include <linux/moduleparam.h>
index c32be292c7e382c4a2c600e9e3c559906ff9784b..e7b6d53eef88d250d6a93e3a75f26c3a6cad4cba 100644 (file)
@@ -32,8 +32,7 @@
  *   the GNU Lesser General Public License for more details.
  *
  *   You should have received a copy of the GNU Lesser General Public License
- *   along with this library; if not, write to the Free Software
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *   along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/module.h>
index 17c7886b5b3a2a35807a6f4aad4ce52a0f0f3468..7af1ed39c0091de232f5b487ac557ba76e3e9b59 100644 (file)
@@ -15,8 +15,7 @@
  *   the GNU Lesser General Public License for more details.
  *
  *   You should have received a copy of the GNU Lesser General Public License
- *   along with this library; if not, write to the Free Software
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *   along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/compiler.h>
index 003f5bb3acd25f4dc696255c56ac1985eae58a62..4bdab152187826f364f0acff43dca1db8d0dc938 100644 (file)
@@ -288,7 +288,8 @@ void hsr_addr_subst_dest(struct hsr_priv *hsr_priv, struct ethhdr *ethhdr,
 static bool seq_nr_after(u16 a, u16 b)
 {
        /* Remove inconsistency where
-        * seq_nr_after(a, b) == seq_nr_before(a, b) */
+        * seq_nr_after(a, b) == seq_nr_before(a, b)
+        */
        if ((int) b - a == 32768)
                return false;
 
index 5325af85eea670f5c865367fc991eaf9b907cd98..01a5261ac7a5520230fb0d2e147ffd3cf0a930ec 100644 (file)
@@ -23,6 +23,8 @@ static const struct nla_policy hsr_policy[IFLA_HSR_MAX + 1] = {
        [IFLA_HSR_SLAVE1]               = { .type = NLA_U32 },
        [IFLA_HSR_SLAVE2]               = { .type = NLA_U32 },
        [IFLA_HSR_MULTICAST_SPEC]       = { .type = NLA_U8 },
+       [IFLA_HSR_SUPERVISION_ADDR]     = { .type = NLA_BINARY, .len = ETH_ALEN },
+       [IFLA_HSR_SEQ_NR]               = { .type = NLA_U16 },
 };
 
 
@@ -59,6 +61,31 @@ static int hsr_newlink(struct net *src_net, struct net_device *dev,
        return hsr_dev_finalize(dev, link, multicast_spec);
 }
 
+static int hsr_fill_info(struct sk_buff *skb, const struct net_device *dev)
+{
+       struct hsr_priv *hsr_priv;
+
+       hsr_priv = netdev_priv(dev);
+
+       if (hsr_priv->slave[0])
+               if (nla_put_u32(skb, IFLA_HSR_SLAVE1, hsr_priv->slave[0]->ifindex))
+                       goto nla_put_failure;
+
+       if (hsr_priv->slave[1])
+               if (nla_put_u32(skb, IFLA_HSR_SLAVE2, hsr_priv->slave[1]->ifindex))
+                       goto nla_put_failure;
+
+       if (nla_put(skb, IFLA_HSR_SUPERVISION_ADDR, ETH_ALEN,
+                   hsr_priv->sup_multicast_addr) ||
+           nla_put_u16(skb, IFLA_HSR_SEQ_NR, hsr_priv->sequence_nr))
+               goto nla_put_failure;
+
+       return 0;
+
+nla_put_failure:
+       return -EMSGSIZE;
+}
+
 static struct rtnl_link_ops hsr_link_ops __read_mostly = {
        .kind           = "hsr",
        .maxtype        = IFLA_HSR_MAX,
@@ -66,6 +93,7 @@ static struct rtnl_link_ops hsr_link_ops __read_mostly = {
        .priv_size      = sizeof(struct hsr_priv),
        .setup          = hsr_dev_setup,
        .newlink        = hsr_newlink,
+       .fill_info      = hsr_fill_info,
 };
 
 
index 459e200c08a40e4e737798582524cd973064b143..53d0bd58ed8db9ab9107087e10ecf789cd7bb6d5 100644 (file)
@@ -62,9 +62,6 @@
 
 #include "6lowpan.h"
 
-/* TTL uncompression values */
-static const u8 lowpan_ttl_values[] = {0, 1, 64, 255};
-
 static LIST_HEAD(lowpan_devices);
 
 /* private device info */
@@ -135,347 +132,14 @@ static inline void lowpan_raw_dump_table(const char *caller, char *msg,
 #endif /* DEBUG */
 }
 
-static u8
-lowpan_compress_addr_64(u8 **hc06_ptr, u8 shift, const struct in6_addr *ipaddr,
-                const unsigned char *lladdr)
-{
-       u8 val = 0;
-
-       if (is_addr_mac_addr_based(ipaddr, lladdr))
-               val = 3; /* 0-bits */
-       else if (lowpan_is_iid_16_bit_compressable(ipaddr)) {
-               /* compress IID to 16 bits xxxx::XXXX */
-               memcpy(*hc06_ptr, &ipaddr->s6_addr16[7], 2);
-               *hc06_ptr += 2;
-               val = 2; /* 16-bits */
-       } else {
-               /* do not compress IID => xxxx::IID */
-               memcpy(*hc06_ptr, &ipaddr->s6_addr16[4], 8);
-               *hc06_ptr += 8;
-               val = 1; /* 64-bits */
-       }
-
-       return rol8(val, shift);
-}
-
-/*
- * Uncompress address function for source and
- * destination address(non-multicast).
- *
- * address_mode is sam value or dam value.
- */
-static int
-lowpan_uncompress_addr(struct sk_buff *skb,
-               struct in6_addr *ipaddr,
-               const u8 address_mode,
-               const struct ieee802154_addr *lladdr)
-{
-       bool fail;
-
-       switch (address_mode) {
-       case LOWPAN_IPHC_ADDR_00:
-               /* for global link addresses */
-               fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16);
-               break;
-       case LOWPAN_IPHC_ADDR_01:
-               /* fe:80::XXXX:XXXX:XXXX:XXXX */
-               ipaddr->s6_addr[0] = 0xFE;
-               ipaddr->s6_addr[1] = 0x80;
-               fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[8], 8);
-               break;
-       case LOWPAN_IPHC_ADDR_02:
-               /* fe:80::ff:fe00:XXXX */
-               ipaddr->s6_addr[0] = 0xFE;
-               ipaddr->s6_addr[1] = 0x80;
-               ipaddr->s6_addr[11] = 0xFF;
-               ipaddr->s6_addr[12] = 0xFE;
-               fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[14], 2);
-               break;
-       case LOWPAN_IPHC_ADDR_03:
-               fail = false;
-               switch (lladdr->addr_type) {
-               case IEEE802154_ADDR_LONG:
-                       /* fe:80::XXXX:XXXX:XXXX:XXXX
-                        *        \_________________/
-                        *              hwaddr
-                        */
-                       ipaddr->s6_addr[0] = 0xFE;
-                       ipaddr->s6_addr[1] = 0x80;
-                       memcpy(&ipaddr->s6_addr[8], lladdr->hwaddr,
-                                       IEEE802154_ADDR_LEN);
-                       /* second bit-flip (Universe/Local)
-                        * is done according RFC2464
-                        */
-                       ipaddr->s6_addr[8] ^= 0x02;
-                       break;
-               case IEEE802154_ADDR_SHORT:
-                       /* fe:80::ff:fe00:XXXX
-                        *                \__/
-                        *             short_addr
-                        *
-                        * Universe/Local bit is zero.
-                        */
-                       ipaddr->s6_addr[0] = 0xFE;
-                       ipaddr->s6_addr[1] = 0x80;
-                       ipaddr->s6_addr[11] = 0xFF;
-                       ipaddr->s6_addr[12] = 0xFE;
-                       ipaddr->s6_addr16[7] = htons(lladdr->short_addr);
-                       break;
-               default:
-                       pr_debug("Invalid addr_type set\n");
-                       return -EINVAL;
-               }
-               break;
-       default:
-               pr_debug("Invalid address mode value: 0x%x\n", address_mode);
-               return -EINVAL;
-       }
-
-       if (fail) {
-               pr_debug("Failed to fetch skb data\n");
-               return -EIO;
-       }
-
-       lowpan_raw_dump_inline(NULL, "Reconstructed ipv6 addr is:\n",
-                       ipaddr->s6_addr, 16);
-
-       return 0;
-}
-
-/* Uncompress address function for source context
- * based address(non-multicast).
- */
-static int
-lowpan_uncompress_context_based_src_addr(struct sk_buff *skb,
-               struct in6_addr *ipaddr,
-               const u8 sam)
-{
-       switch (sam) {
-       case LOWPAN_IPHC_ADDR_00:
-               /* unspec address ::
-                * Do nothing, address is already ::
-                */
-               break;
-       case LOWPAN_IPHC_ADDR_01:
-               /* TODO */
-       case LOWPAN_IPHC_ADDR_02:
-               /* TODO */
-       case LOWPAN_IPHC_ADDR_03:
-               /* TODO */
-               netdev_warn(skb->dev, "SAM value 0x%x not supported\n", sam);
-               return -EINVAL;
-       default:
-               pr_debug("Invalid sam value: 0x%x\n", sam);
-               return -EINVAL;
-       }
-
-       lowpan_raw_dump_inline(NULL,
-                       "Reconstructed context based ipv6 src addr is:\n",
-                       ipaddr->s6_addr, 16);
-
-       return 0;
-}
-
-/* Uncompress function for multicast destination address,
- * when M bit is set.
- */
-static int
-lowpan_uncompress_multicast_daddr(struct sk_buff *skb,
-               struct in6_addr *ipaddr,
-               const u8 dam)
-{
-       bool fail;
-
-       switch (dam) {
-       case LOWPAN_IPHC_DAM_00:
-               /* 00:  128 bits.  The full address
-                * is carried in-line.
-                */
-               fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16);
-               break;
-       case LOWPAN_IPHC_DAM_01:
-               /* 01:  48 bits.  The address takes
-                * the form ffXX::00XX:XXXX:XXXX.
-                */
-               ipaddr->s6_addr[0] = 0xFF;
-               fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1);
-               fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[11], 5);
-               break;
-       case LOWPAN_IPHC_DAM_10:
-               /* 10:  32 bits.  The address takes
-                * the form ffXX::00XX:XXXX.
-                */
-               ipaddr->s6_addr[0] = 0xFF;
-               fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1);
-               fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[13], 3);
-               break;
-       case LOWPAN_IPHC_DAM_11:
-               /* 11:  8 bits.  The address takes
-                * the form ff02::00XX.
-                */
-               ipaddr->s6_addr[0] = 0xFF;
-               ipaddr->s6_addr[1] = 0x02;
-               fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[15], 1);
-               break;
-       default:
-               pr_debug("DAM value has a wrong value: 0x%x\n", dam);
-               return -EINVAL;
-       }
-
-       if (fail) {
-               pr_debug("Failed to fetch skb data\n");
-               return -EIO;
-       }
-
-       lowpan_raw_dump_inline(NULL, "Reconstructed ipv6 multicast addr is:\n",
-                       ipaddr->s6_addr, 16);
-
-       return 0;
-}
-
-static void
-lowpan_compress_udp_header(u8 **hc06_ptr, struct sk_buff *skb)
-{
-       struct udphdr *uh = udp_hdr(skb);
-
-       if (((uh->source & LOWPAN_NHC_UDP_4BIT_MASK) ==
-                               LOWPAN_NHC_UDP_4BIT_PORT) &&
-           ((uh->dest & LOWPAN_NHC_UDP_4BIT_MASK) ==
-                               LOWPAN_NHC_UDP_4BIT_PORT)) {
-               pr_debug("UDP header: both ports compression to 4 bits\n");
-               **hc06_ptr = LOWPAN_NHC_UDP_CS_P_11;
-               **(hc06_ptr + 1) = /* subtraction is faster */
-                  (u8)((uh->dest - LOWPAN_NHC_UDP_4BIT_PORT) +
-                      ((uh->source & LOWPAN_NHC_UDP_4BIT_PORT) << 4));
-               *hc06_ptr += 2;
-       } else if ((uh->dest & LOWPAN_NHC_UDP_8BIT_MASK) ==
-                       LOWPAN_NHC_UDP_8BIT_PORT) {
-               pr_debug("UDP header: remove 8 bits of dest\n");
-               **hc06_ptr = LOWPAN_NHC_UDP_CS_P_01;
-               memcpy(*hc06_ptr + 1, &uh->source, 2);
-               **(hc06_ptr + 3) = (u8)(uh->dest - LOWPAN_NHC_UDP_8BIT_PORT);
-               *hc06_ptr += 4;
-       } else if ((uh->source & LOWPAN_NHC_UDP_8BIT_MASK) ==
-                       LOWPAN_NHC_UDP_8BIT_PORT) {
-               pr_debug("UDP header: remove 8 bits of source\n");
-               **hc06_ptr = LOWPAN_NHC_UDP_CS_P_10;
-               memcpy(*hc06_ptr + 1, &uh->dest, 2);
-               **(hc06_ptr + 3) = (u8)(uh->source - LOWPAN_NHC_UDP_8BIT_PORT);
-               *hc06_ptr += 4;
-       } else {
-               pr_debug("UDP header: can't compress\n");
-               **hc06_ptr = LOWPAN_NHC_UDP_CS_P_00;
-               memcpy(*hc06_ptr + 1, &uh->source, 2);
-               memcpy(*hc06_ptr + 3, &uh->dest, 2);
-               *hc06_ptr += 5;
-       }
-
-       /* checksum is always inline */
-       memcpy(*hc06_ptr, &uh->check, 2);
-       *hc06_ptr += 2;
-
-       /* skip the UDP header */
-       skb_pull(skb, sizeof(struct udphdr));
-}
-
-static inline int lowpan_fetch_skb_u8(struct sk_buff *skb, u8 *val)
-{
-       if (unlikely(!pskb_may_pull(skb, 1)))
-               return -EINVAL;
-
-       *val = skb->data[0];
-       skb_pull(skb, 1);
-
-       return 0;
-}
-
-static inline int lowpan_fetch_skb_u16(struct sk_buff *skb, u16 *val)
-{
-       if (unlikely(!pskb_may_pull(skb, 2)))
-               return -EINVAL;
-
-       *val = (skb->data[0] << 8) | skb->data[1];
-       skb_pull(skb, 2);
-
-       return 0;
-}
-
-static int
-lowpan_uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh)
-{
-       u8 tmp;
-
-       if (!uh)
-               goto err;
-
-       if (lowpan_fetch_skb_u8(skb, &tmp))
-               goto err;
-
-       if ((tmp & LOWPAN_NHC_UDP_MASK) == LOWPAN_NHC_UDP_ID) {
-               pr_debug("UDP header uncompression\n");
-               switch (tmp & LOWPAN_NHC_UDP_CS_P_11) {
-               case LOWPAN_NHC_UDP_CS_P_00:
-                       memcpy(&uh->source, &skb->data[0], 2);
-                       memcpy(&uh->dest, &skb->data[2], 2);
-                       skb_pull(skb, 4);
-                       break;
-               case LOWPAN_NHC_UDP_CS_P_01:
-                       memcpy(&uh->source, &skb->data[0], 2);
-                       uh->dest =
-                          skb->data[2] + LOWPAN_NHC_UDP_8BIT_PORT;
-                       skb_pull(skb, 3);
-                       break;
-               case LOWPAN_NHC_UDP_CS_P_10:
-                       uh->source = skb->data[0] + LOWPAN_NHC_UDP_8BIT_PORT;
-                       memcpy(&uh->dest, &skb->data[1], 2);
-                       skb_pull(skb, 3);
-                       break;
-               case LOWPAN_NHC_UDP_CS_P_11:
-                       uh->source =
-                          LOWPAN_NHC_UDP_4BIT_PORT + (skb->data[0] >> 4);
-                       uh->dest =
-                          LOWPAN_NHC_UDP_4BIT_PORT + (skb->data[0] & 0x0f);
-                       skb_pull(skb, 1);
-                       break;
-               default:
-                       pr_debug("ERROR: unknown UDP format\n");
-                       goto err;
-               }
-
-               pr_debug("uncompressed UDP ports: src = %d, dst = %d\n",
-                        uh->source, uh->dest);
-
-               /* copy checksum */
-               memcpy(&uh->check, &skb->data[0], 2);
-               skb_pull(skb, 2);
-
-               /*
-                * UDP lenght needs to be infered from the lower layers
-                * here, we obtain the hint from the remaining size of the
-                * frame
-                */
-               uh->len = htons(skb->len + sizeof(struct udphdr));
-               pr_debug("uncompressed UDP length: src = %d", uh->len);
-       } else {
-               pr_debug("ERROR: unsupported NH format\n");
-               goto err;
-       }
-
-       return 0;
-err:
-       return -EINVAL;
-}
-
 static int lowpan_header_create(struct sk_buff *skb,
                           struct net_device *dev,
                           unsigned short type, const void *_daddr,
                           const void *_saddr, unsigned int len)
 {
-       u8 tmp, iphc0, iphc1, *hc06_ptr;
        struct ipv6hdr *hdr;
        const u8 *saddr = _saddr;
        const u8 *daddr = _daddr;
-       u8 head[100];
        struct ieee802154_addr sa, da;
 
        /* TODO:
@@ -485,181 +149,14 @@ static int lowpan_header_create(struct sk_buff *skb,
                return 0;
 
        hdr = ipv6_hdr(skb);
-       hc06_ptr = head + 2;
-
-       pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength  = %d\n"
-                "\tnexthdr = 0x%02x\n\thop_lim = %d\n", hdr->version,
-                ntohs(hdr->payload_len), hdr->nexthdr, hdr->hop_limit);
-
-       lowpan_raw_dump_table(__func__, "raw skb network header dump",
-               skb_network_header(skb), sizeof(struct ipv6hdr));
 
        if (!saddr)
                saddr = dev->dev_addr;
 
        lowpan_raw_dump_inline(__func__, "saddr", (unsigned char *)saddr, 8);
-
-       /*
-        * As we copy some bit-length fields, in the IPHC encoding bytes,
-        * we sometimes use |=
-        * If the field is 0, and the current bit value in memory is 1,
-        * this does not work. We therefore reset the IPHC encoding here
-        */
-       iphc0 = LOWPAN_DISPATCH_IPHC;
-       iphc1 = 0;
-
-       /* TODO: context lookup */
-
        lowpan_raw_dump_inline(__func__, "daddr", (unsigned char *)daddr, 8);
 
-       /*
-        * Traffic class, flow label
-        * If flow label is 0, compress it. If traffic class is 0, compress it
-        * We have to process both in the same time as the offset of traffic
-        * class depends on the presence of version and flow label
-        */
-
-       /* hc06 format of TC is ECN | DSCP , original one is DSCP | ECN */
-       tmp = (hdr->priority << 4) | (hdr->flow_lbl[0] >> 4);
-       tmp = ((tmp & 0x03) << 6) | (tmp >> 2);
-
-       if (((hdr->flow_lbl[0] & 0x0F) == 0) &&
-            (hdr->flow_lbl[1] == 0) && (hdr->flow_lbl[2] == 0)) {
-               /* flow label can be compressed */
-               iphc0 |= LOWPAN_IPHC_FL_C;
-               if ((hdr->priority == 0) &&
-                  ((hdr->flow_lbl[0] & 0xF0) == 0)) {
-                       /* compress (elide) all */
-                       iphc0 |= LOWPAN_IPHC_TC_C;
-               } else {
-                       /* compress only the flow label */
-                       *hc06_ptr = tmp;
-                       hc06_ptr += 1;
-               }
-       } else {
-               /* Flow label cannot be compressed */
-               if ((hdr->priority == 0) &&
-                  ((hdr->flow_lbl[0] & 0xF0) == 0)) {
-                       /* compress only traffic class */
-                       iphc0 |= LOWPAN_IPHC_TC_C;
-                       *hc06_ptr = (tmp & 0xc0) | (hdr->flow_lbl[0] & 0x0F);
-                       memcpy(hc06_ptr + 1, &hdr->flow_lbl[1], 2);
-                       hc06_ptr += 3;
-               } else {
-                       /* compress nothing */
-                       memcpy(hc06_ptr, &hdr, 4);
-                       /* replace the top byte with new ECN | DSCP format */
-                       *hc06_ptr = tmp;
-                       hc06_ptr += 4;
-               }
-       }
-
-       /* NOTE: payload length is always compressed */
-
-       /* Next Header is compress if UDP */
-       if (hdr->nexthdr == UIP_PROTO_UDP)
-               iphc0 |= LOWPAN_IPHC_NH_C;
-
-       if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) {
-               *hc06_ptr = hdr->nexthdr;
-               hc06_ptr += 1;
-       }
-
-       /*
-        * Hop limit
-        * if 1:   compress, encoding is 01
-        * if 64:  compress, encoding is 10
-        * if 255: compress, encoding is 11
-        * else do not compress
-        */
-       switch (hdr->hop_limit) {
-       case 1:
-               iphc0 |= LOWPAN_IPHC_TTL_1;
-               break;
-       case 64:
-               iphc0 |= LOWPAN_IPHC_TTL_64;
-               break;
-       case 255:
-               iphc0 |= LOWPAN_IPHC_TTL_255;
-               break;
-       default:
-               *hc06_ptr = hdr->hop_limit;
-               hc06_ptr += 1;
-               break;
-       }
-
-       /* source address compression */
-       if (is_addr_unspecified(&hdr->saddr)) {
-               pr_debug("source address is unspecified, setting SAC\n");
-               iphc1 |= LOWPAN_IPHC_SAC;
-       /* TODO: context lookup */
-       } else if (is_addr_link_local(&hdr->saddr)) {
-               pr_debug("source address is link-local\n");
-               iphc1 |= lowpan_compress_addr_64(&hc06_ptr,
-                               LOWPAN_IPHC_SAM_BIT, &hdr->saddr, saddr);
-       } else {
-               pr_debug("send the full source address\n");
-               memcpy(hc06_ptr, &hdr->saddr.s6_addr16[0], 16);
-               hc06_ptr += 16;
-       }
-
-       /* destination address compression */
-       if (is_addr_mcast(&hdr->daddr)) {
-               pr_debug("destination address is multicast: ");
-               iphc1 |= LOWPAN_IPHC_M;
-               if (lowpan_is_mcast_addr_compressable8(&hdr->daddr)) {
-                       pr_debug("compressed to 1 octet\n");
-                       iphc1 |= LOWPAN_IPHC_DAM_11;
-                       /* use last byte */
-                       *hc06_ptr = hdr->daddr.s6_addr[15];
-                       hc06_ptr += 1;
-               } else if (lowpan_is_mcast_addr_compressable32(&hdr->daddr)) {
-                       pr_debug("compressed to 4 octets\n");
-                       iphc1 |= LOWPAN_IPHC_DAM_10;
-                       /* second byte + the last three */
-                       *hc06_ptr = hdr->daddr.s6_addr[1];
-                       memcpy(hc06_ptr + 1, &hdr->daddr.s6_addr[13], 3);
-                       hc06_ptr += 4;
-               } else if (lowpan_is_mcast_addr_compressable48(&hdr->daddr)) {
-                       pr_debug("compressed to 6 octets\n");
-                       iphc1 |= LOWPAN_IPHC_DAM_01;
-                       /* second byte + the last five */
-                       *hc06_ptr = hdr->daddr.s6_addr[1];
-                       memcpy(hc06_ptr + 1, &hdr->daddr.s6_addr[11], 5);
-                       hc06_ptr += 6;
-               } else {
-                       pr_debug("using full address\n");
-                       iphc1 |= LOWPAN_IPHC_DAM_00;
-                       memcpy(hc06_ptr, &hdr->daddr.s6_addr[0], 16);
-                       hc06_ptr += 16;
-               }
-       } else {
-               /* TODO: context lookup */
-               if (is_addr_link_local(&hdr->daddr)) {
-                       pr_debug("dest address is unicast and link-local\n");
-                       iphc1 |= lowpan_compress_addr_64(&hc06_ptr,
-                               LOWPAN_IPHC_DAM_BIT, &hdr->daddr, daddr);
-               } else {
-                       pr_debug("dest address is unicast: using full one\n");
-                       memcpy(hc06_ptr, &hdr->daddr.s6_addr16[0], 16);
-                       hc06_ptr += 16;
-               }
-       }
-
-       /* UDP header compression */
-       if (hdr->nexthdr == UIP_PROTO_UDP)
-               lowpan_compress_udp_header(&hc06_ptr, skb);
-
-       head[0] = iphc0;
-       head[1] = iphc1;
-
-       skb_pull(skb, sizeof(struct ipv6hdr));
-       skb_reset_transport_header(skb);
-       memcpy(skb_push(skb, hc06_ptr - head), head, hc06_ptr - head);
-       skb_reset_network_header(skb);
-
-       lowpan_raw_dump_table(__func__, "raw skb data dump", skb->data,
-                               skb->len);
+       lowpan_header_compress(skb, dev, type, daddr, saddr, len);
 
        /*
         * NOTE1: I'm still unsure about the fact that compression and WPAN
@@ -671,39 +168,38 @@ static int lowpan_header_create(struct sk_buff *skb,
         * from MAC subif of the 'dev' and 'real_dev' network devices, but
         * this isn't implemented in mainline yet, so currently we assign 0xff
         */
-       {
-               mac_cb(skb)->flags = IEEE802154_FC_TYPE_DATA;
-               mac_cb(skb)->seq = ieee802154_mlme_ops(dev)->get_dsn(dev);
+       mac_cb(skb)->flags = IEEE802154_FC_TYPE_DATA;
+       mac_cb(skb)->seq = ieee802154_mlme_ops(dev)->get_dsn(dev);
 
-               /* prepare wpan address data */
-               sa.addr_type = IEEE802154_ADDR_LONG;
-               sa.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);
+       /* prepare wpan address data */
+       sa.addr_type = IEEE802154_ADDR_LONG;
+       sa.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);
 
-               memcpy(&(sa.hwaddr), saddr, 8);
-               /* intra-PAN communications */
-               da.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);
+       memcpy(&(sa.hwaddr), saddr, 8);
+       /* intra-PAN communications */
+       da.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);
 
-               /*
-                * if the destination address is the broadcast address, use the
-                * corresponding short address
-                */
-               if (lowpan_is_addr_broadcast(daddr)) {
-                       da.addr_type = IEEE802154_ADDR_SHORT;
-                       da.short_addr = IEEE802154_ADDR_BROADCAST;
-               } else {
-                       da.addr_type = IEEE802154_ADDR_LONG;
-                       memcpy(&(da.hwaddr), daddr, IEEE802154_ADDR_LEN);
-
-                       /* request acknowledgment */
-                       mac_cb(skb)->flags |= MAC_CB_FLAG_ACKREQ;
-               }
+       /*
+        * if the destination address is the broadcast address, use the
+        * corresponding short address
+        */
+       if (lowpan_is_addr_broadcast(daddr)) {
+               da.addr_type = IEEE802154_ADDR_SHORT;
+               da.short_addr = IEEE802154_ADDR_BROADCAST;
+       } else {
+               da.addr_type = IEEE802154_ADDR_LONG;
+               memcpy(&(da.hwaddr), daddr, IEEE802154_ADDR_LEN);
 
-               return dev_hard_header(skb, lowpan_dev_info(dev)->real_dev,
-                               type, (void *)&da, (void *)&sa, skb->len);
+               /* request acknowledgment */
+               mac_cb(skb)->flags |= MAC_CB_FLAG_ACKREQ;
        }
+
+       return dev_hard_header(skb, lowpan_dev_info(dev)->real_dev,
+                       type, (void *)&da, (void *)&sa, skb->len);
 }
 
-static int lowpan_give_skb_to_devices(struct sk_buff *skb)
+static int lowpan_give_skb_to_devices(struct sk_buff *skb,
+                                       struct net_device *dev)
 {
        struct lowpan_dev_record *entry;
        struct sk_buff *skb_cp;
@@ -726,31 +222,6 @@ static int lowpan_give_skb_to_devices(struct sk_buff *skb)
        return stat;
 }
 
-static int lowpan_skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr)
-{
-       struct sk_buff *new;
-       int stat = NET_RX_SUCCESS;
-
-       new = skb_copy_expand(skb, sizeof(struct ipv6hdr), skb_tailroom(skb),
-                                                               GFP_ATOMIC);
-       kfree_skb(skb);
-
-       if (!new)
-               return -ENOMEM;
-
-       skb_push(new, sizeof(struct ipv6hdr));
-       skb_copy_to_linear_data(new, hdr, sizeof(struct ipv6hdr));
-
-       new->protocol = htons(ETH_P_IPV6);
-       new->pkt_type = PACKET_HOST;
-
-       stat = lowpan_give_skb_to_devices(new);
-
-       kfree_skb(new);
-
-       return stat;
-}
-
 static void lowpan_fragment_timer_expired(unsigned long entry_addr)
 {
        struct lowpan_fragment *entry = (struct lowpan_fragment *)entry_addr;
@@ -814,13 +285,10 @@ frame_err:
        return NULL;
 }
 
-static int
-lowpan_process_data(struct sk_buff *skb)
+static int process_data(struct sk_buff *skb)
 {
-       struct ipv6hdr hdr = {};
-       u8 tmp, iphc0, iphc1, num_context = 0;
+       u8 iphc0, iphc1;
        const struct ieee802154_addr *_saddr, *_daddr;
-       int err;
 
        lowpan_raw_dump_table(__func__, "raw skb data dump", skb->data,
                                skb->len);
@@ -925,162 +393,11 @@ lowpan_process_data(struct sk_buff *skb)
        _saddr = &mac_cb(skb)->sa;
        _daddr = &mac_cb(skb)->da;
 
-       pr_debug("iphc0 = %02x, iphc1 = %02x\n", iphc0, iphc1);
-
-       /* another if the CID flag is set */
-       if (iphc1 & LOWPAN_IPHC_CID) {
-               pr_debug("CID flag is set, increase header with one\n");
-               if (lowpan_fetch_skb_u8(skb, &num_context))
-                       goto drop;
-       }
-
-       hdr.version = 6;
-
-       /* Traffic Class and Flow Label */
-       switch ((iphc0 & LOWPAN_IPHC_TF) >> 3) {
-       /*
-        * Traffic Class and FLow Label carried in-line
-        * ECN + DSCP + 4-bit Pad + Flow Label (4 bytes)
-        */
-       case 0: /* 00b */
-               if (lowpan_fetch_skb_u8(skb, &tmp))
-                       goto drop;
-
-               memcpy(&hdr.flow_lbl, &skb->data[0], 3);
-               skb_pull(skb, 3);
-               hdr.priority = ((tmp >> 2) & 0x0f);
-               hdr.flow_lbl[0] = ((tmp >> 2) & 0x30) | (tmp << 6) |
-                                       (hdr.flow_lbl[0] & 0x0f);
-               break;
-       /*
-        * Traffic class carried in-line
-        * ECN + DSCP (1 byte), Flow Label is elided
-        */
-       case 2: /* 10b */
-               if (lowpan_fetch_skb_u8(skb, &tmp))
-                       goto drop;
-
-               hdr.priority = ((tmp >> 2) & 0x0f);
-               hdr.flow_lbl[0] = ((tmp << 6) & 0xC0) | ((tmp >> 2) & 0x30);
-               break;
-       /*
-        * Flow Label carried in-line
-        * ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided
-        */
-       case 1: /* 01b */
-               if (lowpan_fetch_skb_u8(skb, &tmp))
-                       goto drop;
-
-               hdr.flow_lbl[0] = (skb->data[0] & 0x0F) | ((tmp >> 2) & 0x30);
-               memcpy(&hdr.flow_lbl[1], &skb->data[0], 2);
-               skb_pull(skb, 2);
-               break;
-       /* Traffic Class and Flow Label are elided */
-       case 3: /* 11b */
-               break;
-       default:
-               break;
-       }
-
-       /* Next Header */
-       if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) {
-               /* Next header is carried inline */
-               if (lowpan_fetch_skb_u8(skb, &(hdr.nexthdr)))
-                       goto drop;
-
-               pr_debug("NH flag is set, next header carried inline: %02x\n",
-                        hdr.nexthdr);
-       }
-
-       /* Hop Limit */
-       if ((iphc0 & 0x03) != LOWPAN_IPHC_TTL_I)
-               hdr.hop_limit = lowpan_ttl_values[iphc0 & 0x03];
-       else {
-               if (lowpan_fetch_skb_u8(skb, &(hdr.hop_limit)))
-                       goto drop;
-       }
-
-       /* Extract SAM to the tmp variable */
-       tmp = ((iphc1 & LOWPAN_IPHC_SAM) >> LOWPAN_IPHC_SAM_BIT) & 0x03;
-
-       if (iphc1 & LOWPAN_IPHC_SAC) {
-               /* Source address context based uncompression */
-               pr_debug("SAC bit is set. Handle context based source address.\n");
-               err = lowpan_uncompress_context_based_src_addr(
-                               skb, &hdr.saddr, tmp);
-       } else {
-               /* Source address uncompression */
-               pr_debug("source address stateless compression\n");
-               err = lowpan_uncompress_addr(skb, &hdr.saddr, tmp, _saddr);
-       }
-
-       /* Check on error of previous branch */
-       if (err)
-               goto drop;
-
-       /* Extract DAM to the tmp variable */
-       tmp = ((iphc1 & LOWPAN_IPHC_DAM_11) >> LOWPAN_IPHC_DAM_BIT) & 0x03;
-
-       /* check for Multicast Compression */
-       if (iphc1 & LOWPAN_IPHC_M) {
-               if (iphc1 & LOWPAN_IPHC_DAC) {
-                       pr_debug("dest: context-based mcast compression\n");
-                       /* TODO: implement this */
-               } else {
-                       err = lowpan_uncompress_multicast_daddr(
-                                       skb, &hdr.daddr, tmp);
-                       if (err)
-                               goto drop;
-               }
-       } else {
-               pr_debug("dest: stateless compression\n");
-               err = lowpan_uncompress_addr(skb, &hdr.daddr, tmp, _daddr);
-               if (err)
-                       goto drop;
-       }
-
-       /* UDP data uncompression */
-       if (iphc0 & LOWPAN_IPHC_NH_C) {
-               struct udphdr uh;
-               struct sk_buff *new;
-               if (lowpan_uncompress_udp_header(skb, &uh))
-                       goto drop;
-
-               /*
-                * replace the compressed UDP head by the uncompressed UDP
-                * header
-                */
-               new = skb_copy_expand(skb, sizeof(struct udphdr),
-                                     skb_tailroom(skb), GFP_ATOMIC);
-               kfree_skb(skb);
-
-               if (!new)
-                       return -ENOMEM;
-
-               skb = new;
-
-               skb_push(skb, sizeof(struct udphdr));
-               skb_copy_to_linear_data(skb, &uh, sizeof(struct udphdr));
-
-               lowpan_raw_dump_table(__func__, "raw UDP header dump",
-                                     (u8 *)&uh, sizeof(uh));
-
-               hdr.nexthdr = UIP_PROTO_UDP;
-       }
-
-       /* Not fragmented package */
-       hdr.payload_len = htons(skb->len);
-
-       pr_debug("skb headroom size = %d, data length = %d\n",
-                skb_headroom(skb), skb->len);
-
-       pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength  = %d\n\t"
-                "nexthdr = 0x%02x\n\thop_lim = %d\n", hdr.version,
-                ntohs(hdr.payload_len), hdr.nexthdr, hdr.hop_limit);
-
-       lowpan_raw_dump_table(__func__, "raw header dump", (u8 *)&hdr,
-                                                       sizeof(hdr));
-       return lowpan_skb_deliver(skb, &hdr);
+       return lowpan_process_data(skb, skb->dev, (u8 *)_saddr->hwaddr,
+                               _saddr->addr_type, IEEE802154_ADDR_LEN,
+                               (u8 *)_daddr->hwaddr, _daddr->addr_type,
+                               IEEE802154_ADDR_LEN, iphc0, iphc1,
+                               lowpan_give_skb_to_devices);
 
 unlock_and_drop:
        spin_unlock_bh(&flist_lock);
@@ -1316,7 +633,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
                /* Pull off the 1-byte of 6lowpan header. */
                skb_pull(local_skb, 1);
 
-               lowpan_give_skb_to_devices(local_skb);
+               lowpan_give_skb_to_devices(local_skb, NULL);
 
                kfree_skb(local_skb);
                kfree_skb(skb);
@@ -1328,7 +645,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
                        local_skb = skb_clone(skb, GFP_ATOMIC);
                        if (!local_skb)
                                goto drop;
-                       lowpan_process_data(local_skb);
+                       process_data(local_skb);
 
                        kfree_skb(skb);
                        break;
index 2869c0526dad698b574ddd05f3f2175d5fb69455..535606d45c390a69f1fead2388c471946a062c23 100644 (file)
                                        dest = 16 bit inline */
 #define LOWPAN_NHC_UDP_CS_P_11 0xF3 /* source & dest = 0xF0B + 4bit inline */
 
+static inline int lowpan_fetch_skb_u8(struct sk_buff *skb, u8 *val)
+{
+       if (unlikely(!pskb_may_pull(skb, 1)))
+               return -EINVAL;
+
+       *val = skb->data[0];
+       skb_pull(skb, 1);
+
+       return 0;
+}
+
+static inline int lowpan_fetch_skb_u16(struct sk_buff *skb, u16 *val)
+{
+       if (unlikely(!pskb_may_pull(skb, 2)))
+               return -EINVAL;
+
+       *val = (skb->data[0] << 8) | skb->data[1];
+       skb_pull(skb, 2);
+
+       return 0;
+}
+
 static inline bool lowpan_fetch_skb(struct sk_buff *skb,
                void *data, const unsigned int len)
 {
@@ -244,4 +266,14 @@ static inline bool lowpan_fetch_skb(struct sk_buff *skb,
        return false;
 }
 
+typedef int (*skb_delivery_cb)(struct sk_buff *skb, struct net_device *dev);
+
+int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
+               const u8 *saddr, const u8 saddr_type, const u8 saddr_len,
+               const u8 *daddr, const u8 daddr_type, const u8 daddr_len,
+               u8 iphc0, u8 iphc1, skb_delivery_cb skb_deliver);
+int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
+                       unsigned short type, const void *_daddr,
+                       const void *_saddr, unsigned int len);
+
 #endif /* __6LOWPAN_H__ */
diff --git a/net/ieee802154/6lowpan_iphc.c b/net/ieee802154/6lowpan_iphc.c
new file mode 100644 (file)
index 0000000..57c0b7a
--- /dev/null
@@ -0,0 +1,807 @@
+/*
+ * Copyright 2011, Siemens AG
+ * written by Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
+ */
+
+/*
+ * Based on patches from Jon Smirl <jonsmirl@gmail.com>
+ * Copyright (c) 2011 Jon Smirl <jonsmirl@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.
+ *
+ * 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.
+ */
+
+/* Jon's code is based on 6lowpan implementation for Contiki which is:
+ * Copyright (c) 2008, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <linux/bitops.h>
+#include <linux/if_arp.h>
+#include <linux/netdevice.h>
+#include <net/ipv6.h>
+#include <net/af_ieee802154.h>
+
+#include "6lowpan.h"
+
+/* print data in line */
+static inline void raw_dump_inline(const char *caller, char *msg,
+                                  unsigned char *buf, int len)
+{
+       if (msg)
+               pr_debug("%s():%s: ", caller, msg);
+       print_hex_dump_debug("", DUMP_PREFIX_NONE,
+                      16, 1, buf, len, false);
+}
+
+/*
+ * print data in a table format:
+ *
+ * addr: xx xx xx xx xx xx
+ * addr: xx xx xx xx xx xx
+ * ...
+ */
+static inline void raw_dump_table(const char *caller, char *msg,
+                               unsigned char *buf, int len)
+{
+       if (msg)
+               pr_debug("%s():%s:\n", caller, msg);
+       print_hex_dump_debug("\t", DUMP_PREFIX_OFFSET,
+                      16, 1, buf, len, false);
+}
+
+/*
+ * Uncompress address function for source and
+ * destination address(non-multicast).
+ *
+ * address_mode is sam value or dam value.
+ */
+static int uncompress_addr(struct sk_buff *skb,
+                               struct in6_addr *ipaddr, const u8 address_mode,
+                               const u8 *lladdr, const u8 addr_type,
+                               const u8 addr_len)
+{
+       bool fail;
+
+       switch (address_mode) {
+       case LOWPAN_IPHC_ADDR_00:
+               /* for global link addresses */
+               fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16);
+               break;
+       case LOWPAN_IPHC_ADDR_01:
+               /* fe:80::XXXX:XXXX:XXXX:XXXX */
+               ipaddr->s6_addr[0] = 0xFE;
+               ipaddr->s6_addr[1] = 0x80;
+               fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[8], 8);
+               break;
+       case LOWPAN_IPHC_ADDR_02:
+               /* fe:80::ff:fe00:XXXX */
+               ipaddr->s6_addr[0] = 0xFE;
+               ipaddr->s6_addr[1] = 0x80;
+               ipaddr->s6_addr[11] = 0xFF;
+               ipaddr->s6_addr[12] = 0xFE;
+               fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[14], 2);
+               break;
+       case LOWPAN_IPHC_ADDR_03:
+               fail = false;
+               switch (addr_type) {
+               case IEEE802154_ADDR_LONG:
+                       /* fe:80::XXXX:XXXX:XXXX:XXXX
+                        *        \_________________/
+                        *              hwaddr
+                        */
+                       ipaddr->s6_addr[0] = 0xFE;
+                       ipaddr->s6_addr[1] = 0x80;
+                       memcpy(&ipaddr->s6_addr[8], lladdr, addr_len);
+                       /* second bit-flip (Universe/Local)
+                        * is done according RFC2464
+                        */
+                       ipaddr->s6_addr[8] ^= 0x02;
+                       break;
+               case IEEE802154_ADDR_SHORT:
+                       /* fe:80::ff:fe00:XXXX
+                        *                \__/
+                        *             short_addr
+                        *
+                        * Universe/Local bit is zero.
+                        */
+                       ipaddr->s6_addr[0] = 0xFE;
+                       ipaddr->s6_addr[1] = 0x80;
+                       ipaddr->s6_addr[11] = 0xFF;
+                       ipaddr->s6_addr[12] = 0xFE;
+                       ipaddr->s6_addr16[7] = htons(*((u16 *)lladdr));
+                       break;
+               default:
+                       pr_debug("Invalid addr_type set\n");
+                       return -EINVAL;
+               }
+               break;
+       default:
+               pr_debug("Invalid address mode value: 0x%x\n", address_mode);
+               return -EINVAL;
+       }
+
+       if (fail) {
+               pr_debug("Failed to fetch skb data\n");
+               return -EIO;
+       }
+
+       raw_dump_inline(NULL, "Reconstructed ipv6 addr is",
+                       ipaddr->s6_addr, 16);
+
+       return 0;
+}
+
+/*
+ * Uncompress address function for source context
+ * based address(non-multicast).
+ */
+static int uncompress_context_based_src_addr(struct sk_buff *skb,
+                                               struct in6_addr *ipaddr,
+                                               const u8 sam)
+{
+       switch (sam) {
+       case LOWPAN_IPHC_ADDR_00:
+               /* unspec address ::
+                * Do nothing, address is already ::
+                */
+               break;
+       case LOWPAN_IPHC_ADDR_01:
+               /* TODO */
+       case LOWPAN_IPHC_ADDR_02:
+               /* TODO */
+       case LOWPAN_IPHC_ADDR_03:
+               /* TODO */
+               netdev_warn(skb->dev, "SAM value 0x%x not supported\n", sam);
+               return -EINVAL;
+       default:
+               pr_debug("Invalid sam value: 0x%x\n", sam);
+               return -EINVAL;
+       }
+
+       raw_dump_inline(NULL,
+                       "Reconstructed context based ipv6 src addr is",
+                       ipaddr->s6_addr, 16);
+
+       return 0;
+}
+
+static int skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr,
+               struct net_device *dev, skb_delivery_cb deliver_skb)
+{
+       struct sk_buff *new;
+       int stat;
+
+       new = skb_copy_expand(skb, sizeof(struct ipv6hdr), skb_tailroom(skb),
+                                                               GFP_ATOMIC);
+       kfree_skb(skb);
+
+       if (!new)
+               return -ENOMEM;
+
+       skb_push(new, sizeof(struct ipv6hdr));
+       skb_reset_network_header(new);
+       skb_copy_to_linear_data(new, hdr, sizeof(struct ipv6hdr));
+
+       new->protocol = htons(ETH_P_IPV6);
+       new->pkt_type = PACKET_HOST;
+       new->dev = dev;
+
+       raw_dump_table(__func__, "raw skb data dump before receiving",
+                       new->data, new->len);
+
+       stat = deliver_skb(new, dev);
+
+       kfree_skb(new);
+
+       return stat;
+}
+
+/* Uncompress function for multicast destination address,
+ * when M bit is set.
+ */
+static int
+lowpan_uncompress_multicast_daddr(struct sk_buff *skb,
+               struct in6_addr *ipaddr,
+               const u8 dam)
+{
+       bool fail;
+
+       switch (dam) {
+       case LOWPAN_IPHC_DAM_00:
+               /* 00:  128 bits.  The full address
+                * is carried in-line.
+                */
+               fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16);
+               break;
+       case LOWPAN_IPHC_DAM_01:
+               /* 01:  48 bits.  The address takes
+                * the form ffXX::00XX:XXXX:XXXX.
+                */
+               ipaddr->s6_addr[0] = 0xFF;
+               fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1);
+               fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[11], 5);
+               break;
+       case LOWPAN_IPHC_DAM_10:
+               /* 10:  32 bits.  The address takes
+                * the form ffXX::00XX:XXXX.
+                */
+               ipaddr->s6_addr[0] = 0xFF;
+               fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1);
+               fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[13], 3);
+               break;
+       case LOWPAN_IPHC_DAM_11:
+               /* 11:  8 bits.  The address takes
+                * the form ff02::00XX.
+                */
+               ipaddr->s6_addr[0] = 0xFF;
+               ipaddr->s6_addr[1] = 0x02;
+               fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[15], 1);
+               break;
+       default:
+               pr_debug("DAM value has a wrong value: 0x%x\n", dam);
+               return -EINVAL;
+       }
+
+       if (fail) {
+               pr_debug("Failed to fetch skb data\n");
+               return -EIO;
+       }
+
+       raw_dump_inline(NULL, "Reconstructed ipv6 multicast addr is",
+                               ipaddr->s6_addr, 16);
+
+       return 0;
+}
+
+static int
+uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh)
+{
+       u8 tmp;
+
+       if (!uh)
+               goto err;
+
+       if (lowpan_fetch_skb_u8(skb, &tmp))
+               goto err;
+
+       if ((tmp & LOWPAN_NHC_UDP_MASK) == LOWPAN_NHC_UDP_ID) {
+               pr_debug("UDP header uncompression\n");
+               switch (tmp & LOWPAN_NHC_UDP_CS_P_11) {
+               case LOWPAN_NHC_UDP_CS_P_00:
+                       memcpy(&uh->source, &skb->data[0], 2);
+                       memcpy(&uh->dest, &skb->data[2], 2);
+                       skb_pull(skb, 4);
+                       break;
+               case LOWPAN_NHC_UDP_CS_P_01:
+                       memcpy(&uh->source, &skb->data[0], 2);
+                       uh->dest =
+                          skb->data[2] + LOWPAN_NHC_UDP_8BIT_PORT;
+                       skb_pull(skb, 3);
+                       break;
+               case LOWPAN_NHC_UDP_CS_P_10:
+                       uh->source = skb->data[0] + LOWPAN_NHC_UDP_8BIT_PORT;
+                       memcpy(&uh->dest, &skb->data[1], 2);
+                       skb_pull(skb, 3);
+                       break;
+               case LOWPAN_NHC_UDP_CS_P_11:
+                       uh->source =
+                          LOWPAN_NHC_UDP_4BIT_PORT + (skb->data[0] >> 4);
+                       uh->dest =
+                          LOWPAN_NHC_UDP_4BIT_PORT + (skb->data[0] & 0x0f);
+                       skb_pull(skb, 1);
+                       break;
+               default:
+                       pr_debug("ERROR: unknown UDP format\n");
+                       goto err;
+                       break;
+               }
+
+               pr_debug("uncompressed UDP ports: src = %d, dst = %d\n",
+                        uh->source, uh->dest);
+
+               /* copy checksum */
+               memcpy(&uh->check, &skb->data[0], 2);
+               skb_pull(skb, 2);
+
+               /*
+                * UDP lenght needs to be infered from the lower layers
+                * here, we obtain the hint from the remaining size of the
+                * frame
+                */
+               uh->len = htons(skb->len + sizeof(struct udphdr));
+               pr_debug("uncompressed UDP length: src = %d", uh->len);
+       } else {
+               pr_debug("ERROR: unsupported NH format\n");
+               goto err;
+       }
+
+       return 0;
+err:
+       return -EINVAL;
+}
+
+/* TTL uncompression values */
+static const u8 lowpan_ttl_values[] = { 0, 1, 64, 255 };
+
+int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
+               const u8 *saddr, const u8 saddr_type, const u8 saddr_len,
+               const u8 *daddr, const u8 daddr_type, const u8 daddr_len,
+               u8 iphc0, u8 iphc1, skb_delivery_cb deliver_skb)
+{
+       struct ipv6hdr hdr = {};
+       u8 tmp, num_context = 0;
+       int err;
+
+       raw_dump_table(__func__, "raw skb data dump uncompressed",
+                               skb->data, skb->len);
+
+       /* another if the CID flag is set */
+       if (iphc1 & LOWPAN_IPHC_CID) {
+               pr_debug("CID flag is set, increase header with one\n");
+               if (lowpan_fetch_skb_u8(skb, &num_context))
+                       goto drop;
+       }
+
+       hdr.version = 6;
+
+       /* Traffic Class and Flow Label */
+       switch ((iphc0 & LOWPAN_IPHC_TF) >> 3) {
+       /*
+        * Traffic Class and FLow Label carried in-line
+        * ECN + DSCP + 4-bit Pad + Flow Label (4 bytes)
+        */
+       case 0: /* 00b */
+               if (lowpan_fetch_skb_u8(skb, &tmp))
+                       goto drop;
+
+               memcpy(&hdr.flow_lbl, &skb->data[0], 3);
+               skb_pull(skb, 3);
+               hdr.priority = ((tmp >> 2) & 0x0f);
+               hdr.flow_lbl[0] = ((tmp >> 2) & 0x30) | (tmp << 6) |
+                                       (hdr.flow_lbl[0] & 0x0f);
+               break;
+       /*
+        * Traffic class carried in-line
+        * ECN + DSCP (1 byte), Flow Label is elided
+        */
+       case 2: /* 10b */
+               if (lowpan_fetch_skb_u8(skb, &tmp))
+                       goto drop;
+
+               hdr.priority = ((tmp >> 2) & 0x0f);
+               hdr.flow_lbl[0] = ((tmp << 6) & 0xC0) | ((tmp >> 2) & 0x30);
+               break;
+       /*
+        * Flow Label carried in-line
+        * ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided
+        */
+       case 1: /* 01b */
+               if (lowpan_fetch_skb_u8(skb, &tmp))
+                       goto drop;
+
+               hdr.flow_lbl[0] = (skb->data[0] & 0x0F) | ((tmp >> 2) & 0x30);
+               memcpy(&hdr.flow_lbl[1], &skb->data[0], 2);
+               skb_pull(skb, 2);
+               break;
+       /* Traffic Class and Flow Label are elided */
+       case 3: /* 11b */
+               break;
+       default:
+               break;
+       }
+
+       /* Next Header */
+       if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) {
+               /* Next header is carried inline */
+               if (lowpan_fetch_skb_u8(skb, &(hdr.nexthdr)))
+                       goto drop;
+
+               pr_debug("NH flag is set, next header carried inline: %02x\n",
+                        hdr.nexthdr);
+       }
+
+       /* Hop Limit */
+       if ((iphc0 & 0x03) != LOWPAN_IPHC_TTL_I)
+               hdr.hop_limit = lowpan_ttl_values[iphc0 & 0x03];
+       else {
+               if (lowpan_fetch_skb_u8(skb, &(hdr.hop_limit)))
+                       goto drop;
+       }
+
+       /* Extract SAM to the tmp variable */
+       tmp = ((iphc1 & LOWPAN_IPHC_SAM) >> LOWPAN_IPHC_SAM_BIT) & 0x03;
+
+       if (iphc1 & LOWPAN_IPHC_SAC) {
+               /* Source address context based uncompression */
+               pr_debug("SAC bit is set. Handle context based source address.\n");
+               err = uncompress_context_based_src_addr(
+                               skb, &hdr.saddr, tmp);
+       } else {
+               /* Source address uncompression */
+               pr_debug("source address stateless compression\n");
+               err = uncompress_addr(skb, &hdr.saddr, tmp, saddr,
+                                       saddr_type, saddr_len);
+       }
+
+       /* Check on error of previous branch */
+       if (err)
+               goto drop;
+
+       /* Extract DAM to the tmp variable */
+       tmp = ((iphc1 & LOWPAN_IPHC_DAM_11) >> LOWPAN_IPHC_DAM_BIT) & 0x03;
+
+       /* check for Multicast Compression */
+       if (iphc1 & LOWPAN_IPHC_M) {
+               if (iphc1 & LOWPAN_IPHC_DAC) {
+                       pr_debug("dest: context-based mcast compression\n");
+                       /* TODO: implement this */
+               } else {
+                       err = lowpan_uncompress_multicast_daddr(
+                                               skb, &hdr.daddr, tmp);
+                       if (err)
+                               goto drop;
+               }
+       } else {
+               err = uncompress_addr(skb, &hdr.daddr, tmp, daddr,
+                                       daddr_type, daddr_len);
+               pr_debug("dest: stateless compression mode %d dest %pI6c\n",
+                       tmp, &hdr.daddr);
+               if (err)
+                       goto drop;
+       }
+
+       /* UDP data uncompression */
+       if (iphc0 & LOWPAN_IPHC_NH_C) {
+               struct udphdr uh;
+               struct sk_buff *new;
+               if (uncompress_udp_header(skb, &uh))
+                       goto drop;
+
+               /*
+                * replace the compressed UDP head by the uncompressed UDP
+                * header
+                */
+               new = skb_copy_expand(skb, sizeof(struct udphdr),
+                                     skb_tailroom(skb), GFP_ATOMIC);
+               kfree_skb(skb);
+
+               if (!new)
+                       return -ENOMEM;
+
+               skb = new;
+
+               skb_push(skb, sizeof(struct udphdr));
+               skb_reset_transport_header(skb);
+               skb_copy_to_linear_data(skb, &uh, sizeof(struct udphdr));
+
+               raw_dump_table(__func__, "raw UDP header dump",
+                                     (u8 *)&uh, sizeof(uh));
+
+               hdr.nexthdr = UIP_PROTO_UDP;
+       }
+
+       hdr.payload_len = htons(skb->len);
+
+       pr_debug("skb headroom size = %d, data length = %d\n",
+                skb_headroom(skb), skb->len);
+
+       pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength  = %d\n\t"
+                "nexthdr = 0x%02x\n\thop_lim = %d\n\tdest    = %pI6c\n",
+               hdr.version, ntohs(hdr.payload_len), hdr.nexthdr,
+               hdr.hop_limit, &hdr.daddr);
+
+       raw_dump_table(__func__, "raw header dump", (u8 *)&hdr,
+                                                       sizeof(hdr));
+
+       return skb_deliver(skb, &hdr, dev, deliver_skb);
+
+drop:
+       kfree_skb(skb);
+       return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(lowpan_process_data);
+
+static u8 lowpan_compress_addr_64(u8 **hc06_ptr, u8 shift,
+                               const struct in6_addr *ipaddr,
+                               const unsigned char *lladdr)
+{
+       u8 val = 0;
+
+       if (is_addr_mac_addr_based(ipaddr, lladdr)) {
+               val = 3; /* 0-bits */
+               pr_debug("address compression 0 bits\n");
+       } else if (lowpan_is_iid_16_bit_compressable(ipaddr)) {
+               /* compress IID to 16 bits xxxx::XXXX */
+               memcpy(*hc06_ptr, &ipaddr->s6_addr16[7], 2);
+               *hc06_ptr += 2;
+               val = 2; /* 16-bits */
+               raw_dump_inline(NULL, "Compressed ipv6 addr is (16 bits)",
+                       *hc06_ptr - 2, 2);
+       } else {
+               /* do not compress IID => xxxx::IID */
+               memcpy(*hc06_ptr, &ipaddr->s6_addr16[4], 8);
+               *hc06_ptr += 8;
+               val = 1; /* 64-bits */
+               raw_dump_inline(NULL, "Compressed ipv6 addr is (64 bits)",
+                       *hc06_ptr - 8, 8);
+       }
+
+       return rol8(val, shift);
+}
+
+static void compress_udp_header(u8 **hc06_ptr, struct sk_buff *skb)
+{
+       struct udphdr *uh = udp_hdr(skb);
+
+       if (((uh->source & LOWPAN_NHC_UDP_4BIT_MASK) ==
+                               LOWPAN_NHC_UDP_4BIT_PORT) &&
+           ((uh->dest & LOWPAN_NHC_UDP_4BIT_MASK) ==
+                               LOWPAN_NHC_UDP_4BIT_PORT)) {
+               pr_debug("UDP header: both ports compression to 4 bits\n");
+               **hc06_ptr = LOWPAN_NHC_UDP_CS_P_11;
+               **(hc06_ptr + 1) = /* subtraction is faster */
+                  (u8)((uh->dest - LOWPAN_NHC_UDP_4BIT_PORT) +
+                      ((uh->source & LOWPAN_NHC_UDP_4BIT_PORT) << 4));
+               *hc06_ptr += 2;
+       } else if ((uh->dest & LOWPAN_NHC_UDP_8BIT_MASK) ==
+                       LOWPAN_NHC_UDP_8BIT_PORT) {
+               pr_debug("UDP header: remove 8 bits of dest\n");
+               **hc06_ptr = LOWPAN_NHC_UDP_CS_P_01;
+               memcpy(*hc06_ptr + 1, &uh->source, 2);
+               **(hc06_ptr + 3) = (u8)(uh->dest - LOWPAN_NHC_UDP_8BIT_PORT);
+               *hc06_ptr += 4;
+       } else if ((uh->source & LOWPAN_NHC_UDP_8BIT_MASK) ==
+                       LOWPAN_NHC_UDP_8BIT_PORT) {
+               pr_debug("UDP header: remove 8 bits of source\n");
+               **hc06_ptr = LOWPAN_NHC_UDP_CS_P_10;
+               memcpy(*hc06_ptr + 1, &uh->dest, 2);
+               **(hc06_ptr + 3) = (u8)(uh->source - LOWPAN_NHC_UDP_8BIT_PORT);
+               *hc06_ptr += 4;
+       } else {
+               pr_debug("UDP header: can't compress\n");
+               **hc06_ptr = LOWPAN_NHC_UDP_CS_P_00;
+               memcpy(*hc06_ptr + 1, &uh->source, 2);
+               memcpy(*hc06_ptr + 3, &uh->dest, 2);
+               *hc06_ptr += 5;
+       }
+
+       /* checksum is always inline */
+       memcpy(*hc06_ptr, &uh->check, 2);
+       *hc06_ptr += 2;
+
+       /* skip the UDP header */
+       skb_pull(skb, sizeof(struct udphdr));
+}
+
+int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
+                       unsigned short type, const void *_daddr,
+                       const void *_saddr, unsigned int len)
+{
+       u8 tmp, iphc0, iphc1, *hc06_ptr;
+       struct ipv6hdr *hdr;
+       u8 head[100] = {};
+
+       if (type != ETH_P_IPV6)
+               return -EINVAL;
+
+       hdr = ipv6_hdr(skb);
+       hc06_ptr = head + 2;
+
+       pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength  = %d\n"
+                "\tnexthdr = 0x%02x\n\thop_lim = %d\n\tdest    = %pI6c\n",
+               hdr->version, ntohs(hdr->payload_len), hdr->nexthdr,
+               hdr->hop_limit, &hdr->daddr);
+
+       raw_dump_table(__func__, "raw skb network header dump",
+               skb_network_header(skb), sizeof(struct ipv6hdr));
+
+       /*
+        * As we copy some bit-length fields, in the IPHC encoding bytes,
+        * we sometimes use |=
+        * If the field is 0, and the current bit value in memory is 1,
+        * this does not work. We therefore reset the IPHC encoding here
+        */
+       iphc0 = LOWPAN_DISPATCH_IPHC;
+       iphc1 = 0;
+
+       /* TODO: context lookup */
+
+       raw_dump_inline(__func__, "saddr",
+                       (unsigned char *)_saddr, IEEE802154_ADDR_LEN);
+       raw_dump_inline(__func__, "daddr",
+                       (unsigned char *)_daddr, IEEE802154_ADDR_LEN);
+
+       raw_dump_table(__func__,
+                       "sending raw skb network uncompressed packet",
+                       skb->data, skb->len);
+
+       /*
+        * Traffic class, flow label
+        * If flow label is 0, compress it. If traffic class is 0, compress it
+        * We have to process both in the same time as the offset of traffic
+        * class depends on the presence of version and flow label
+        */
+
+       /* hc06 format of TC is ECN | DSCP , original one is DSCP | ECN */
+       tmp = (hdr->priority << 4) | (hdr->flow_lbl[0] >> 4);
+       tmp = ((tmp & 0x03) << 6) | (tmp >> 2);
+
+       if (((hdr->flow_lbl[0] & 0x0F) == 0) &&
+            (hdr->flow_lbl[1] == 0) && (hdr->flow_lbl[2] == 0)) {
+               /* flow label can be compressed */
+               iphc0 |= LOWPAN_IPHC_FL_C;
+               if ((hdr->priority == 0) &&
+                  ((hdr->flow_lbl[0] & 0xF0) == 0)) {
+                       /* compress (elide) all */
+                       iphc0 |= LOWPAN_IPHC_TC_C;
+               } else {
+                       /* compress only the flow label */
+                       *hc06_ptr = tmp;
+                       hc06_ptr += 1;
+               }
+       } else {
+               /* Flow label cannot be compressed */
+               if ((hdr->priority == 0) &&
+                  ((hdr->flow_lbl[0] & 0xF0) == 0)) {
+                       /* compress only traffic class */
+                       iphc0 |= LOWPAN_IPHC_TC_C;
+                       *hc06_ptr = (tmp & 0xc0) | (hdr->flow_lbl[0] & 0x0F);
+                       memcpy(hc06_ptr + 1, &hdr->flow_lbl[1], 2);
+                       hc06_ptr += 3;
+               } else {
+                       /* compress nothing */
+                       memcpy(hc06_ptr, &hdr, 4);
+                       /* replace the top byte with new ECN | DSCP format */
+                       *hc06_ptr = tmp;
+                       hc06_ptr += 4;
+               }
+       }
+
+       /* NOTE: payload length is always compressed */
+
+       /* Next Header is compress if UDP */
+       if (hdr->nexthdr == UIP_PROTO_UDP)
+               iphc0 |= LOWPAN_IPHC_NH_C;
+
+       if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) {
+               *hc06_ptr = hdr->nexthdr;
+               hc06_ptr += 1;
+       }
+
+       /*
+        * Hop limit
+        * if 1:   compress, encoding is 01
+        * if 64:  compress, encoding is 10
+        * if 255: compress, encoding is 11
+        * else do not compress
+        */
+       switch (hdr->hop_limit) {
+       case 1:
+               iphc0 |= LOWPAN_IPHC_TTL_1;
+               break;
+       case 64:
+               iphc0 |= LOWPAN_IPHC_TTL_64;
+               break;
+       case 255:
+               iphc0 |= LOWPAN_IPHC_TTL_255;
+               break;
+       default:
+               *hc06_ptr = hdr->hop_limit;
+               hc06_ptr += 1;
+               break;
+       }
+
+       /* source address compression */
+       if (is_addr_unspecified(&hdr->saddr)) {
+               pr_debug("source address is unspecified, setting SAC\n");
+               iphc1 |= LOWPAN_IPHC_SAC;
+       /* TODO: context lookup */
+       } else if (is_addr_link_local(&hdr->saddr)) {
+               iphc1 |= lowpan_compress_addr_64(&hc06_ptr,
+                               LOWPAN_IPHC_SAM_BIT, &hdr->saddr, _saddr);
+               pr_debug("source address unicast link-local %pI6c "
+                       "iphc1 0x%02x\n", &hdr->saddr, iphc1);
+       } else {
+               pr_debug("send the full source address\n");
+               memcpy(hc06_ptr, &hdr->saddr.s6_addr16[0], 16);
+               hc06_ptr += 16;
+       }
+
+       /* destination address compression */
+       if (is_addr_mcast(&hdr->daddr)) {
+               pr_debug("destination address is multicast: ");
+               iphc1 |= LOWPAN_IPHC_M;
+               if (lowpan_is_mcast_addr_compressable8(&hdr->daddr)) {
+                       pr_debug("compressed to 1 octet\n");
+                       iphc1 |= LOWPAN_IPHC_DAM_11;
+                       /* use last byte */
+                       *hc06_ptr = hdr->daddr.s6_addr[15];
+                       hc06_ptr += 1;
+               } else if (lowpan_is_mcast_addr_compressable32(&hdr->daddr)) {
+                       pr_debug("compressed to 4 octets\n");
+                       iphc1 |= LOWPAN_IPHC_DAM_10;
+                       /* second byte + the last three */
+                       *hc06_ptr = hdr->daddr.s6_addr[1];
+                       memcpy(hc06_ptr + 1, &hdr->daddr.s6_addr[13], 3);
+                       hc06_ptr += 4;
+               } else if (lowpan_is_mcast_addr_compressable48(&hdr->daddr)) {
+                       pr_debug("compressed to 6 octets\n");
+                       iphc1 |= LOWPAN_IPHC_DAM_01;
+                       /* second byte + the last five */
+                       *hc06_ptr = hdr->daddr.s6_addr[1];
+                       memcpy(hc06_ptr + 1, &hdr->daddr.s6_addr[11], 5);
+                       hc06_ptr += 6;
+               } else {
+                       pr_debug("using full address\n");
+                       iphc1 |= LOWPAN_IPHC_DAM_00;
+                       memcpy(hc06_ptr, &hdr->daddr.s6_addr[0], 16);
+                       hc06_ptr += 16;
+               }
+       } else {
+               /* TODO: context lookup */
+               if (is_addr_link_local(&hdr->daddr)) {
+                       iphc1 |= lowpan_compress_addr_64(&hc06_ptr,
+                               LOWPAN_IPHC_DAM_BIT, &hdr->daddr, _daddr);
+                       pr_debug("dest address unicast link-local %pI6c "
+                               "iphc1 0x%02x\n", &hdr->daddr, iphc1);
+               } else {
+                       pr_debug("dest address unicast %pI6c\n", &hdr->daddr);
+                       memcpy(hc06_ptr, &hdr->daddr.s6_addr16[0], 16);
+                       hc06_ptr += 16;
+               }
+       }
+
+       /* UDP header compression */
+       if (hdr->nexthdr == UIP_PROTO_UDP)
+               compress_udp_header(&hc06_ptr, skb);
+
+       head[0] = iphc0;
+       head[1] = iphc1;
+
+       skb_pull(skb, sizeof(struct ipv6hdr));
+       skb_reset_transport_header(skb);
+       memcpy(skb_push(skb, hc06_ptr - head), head, hc06_ptr - head);
+       skb_reset_network_header(skb);
+
+       pr_debug("header len %d skb %u\n", (int)(hc06_ptr - head), skb->len);
+
+       raw_dump_table(__func__, "raw skb data dump compressed",
+                               skb->data, skb->len);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(lowpan_header_compress);
index d7716d64c6bb2c38848695378d6634bfa958afd6..951a83ee8af4fb35c8dabc459c5c2d257f452eb7 100644 (file)
@@ -1,5 +1,5 @@
 obj-$(CONFIG_IEEE802154) += ieee802154.o af_802154.o
-obj-$(CONFIG_IEEE802154_6LOWPAN) += 6lowpan.o
+obj-$(CONFIG_IEEE802154_6LOWPAN) += 6lowpan.o 6lowpan_iphc.o
 
 ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o wpan-class.o
 af_802154-y := af_ieee802154.o raw.o dgram.o
index 70011e029ac13718d72d7172776ac8cb76798ced..4f6d50bda0933f1ca89db8b73b46e781e6b06044 100644 (file)
@@ -1133,7 +1133,7 @@ static int inet_sk_reselect_saddr(struct sock *sk)
        fl4 = &inet->cork.fl.u.ip4;
        rt = ip_route_connect(fl4, daddr, 0, RT_CONN_FLAGS(sk),
                              sk->sk_bound_dev_if, sk->sk_protocol,
-                             inet->inet_sport, inet->inet_dport, sk, false);
+                             inet->inet_sport, inet->inet_dport, sk);
        if (IS_ERR(rt))
                return PTR_ERR(rt);
 
index 7808093cede6c448eb52351f7db0a36ec3fdcf95..b67cf805910e1f962755cbc26f793be6a01a4c6a 100644 (file)
@@ -166,18 +166,20 @@ struct neigh_table arp_tbl = {
        .id             = "arp_cache",
        .parms          = {
                .tbl                    = &arp_tbl,
-               .base_reachable_time    = 30 * HZ,
-               .retrans_time           = 1 * HZ,
-               .gc_staletime           = 60 * HZ,
                .reachable_time         = 30 * HZ,
-               .delay_probe_time       = 5 * HZ,
-               .queue_len_bytes        = 64*1024,
-               .ucast_probes           = 3,
-               .mcast_probes           = 3,
-               .anycast_delay          = 1 * HZ,
-               .proxy_delay            = (8 * HZ) / 10,
-               .proxy_qlen             = 64,
-               .locktime               = 1 * HZ,
+               .data   = {
+                       [NEIGH_VAR_MCAST_PROBES] = 3,
+                       [NEIGH_VAR_UCAST_PROBES] = 3,
+                       [NEIGH_VAR_RETRANS_TIME] = 1 * HZ,
+                       [NEIGH_VAR_BASE_REACHABLE_TIME] = 30 * HZ,
+                       [NEIGH_VAR_DELAY_PROBE_TIME] = 5 * HZ,
+                       [NEIGH_VAR_GC_STALETIME] = 60 * HZ,
+                       [NEIGH_VAR_QUEUE_LEN_BYTES] = 64 * 1024,
+                       [NEIGH_VAR_PROXY_QLEN] = 64,
+                       [NEIGH_VAR_ANYCAST_DELAY] = 1 * HZ,
+                       [NEIGH_VAR_PROXY_DELAY] = (8 * HZ) / 10,
+                       [NEIGH_VAR_LOCKTIME] = 1 * HZ,
+               },
        },
        .gc_interval    = 30 * HZ,
        .gc_thresh1     = 128,
@@ -359,14 +361,14 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
        if (!saddr)
                saddr = inet_select_addr(dev, target, RT_SCOPE_LINK);
 
-       probes -= neigh->parms->ucast_probes;
+       probes -= NEIGH_VAR(neigh->parms, UCAST_PROBES);
        if (probes < 0) {
                if (!(neigh->nud_state & NUD_VALID))
                        pr_debug("trying to ucast probe in NUD_INVALID\n");
                neigh_ha_snapshot(dst_ha, neigh, dev);
                dst_hw = dst_ha;
        } else {
-               probes -= neigh->parms->app_probes;
+               probes -= NEIGH_VAR(neigh->parms, APP_PROBES);
                if (probes < 0) {
                        neigh_app_ns(neigh);
                        return;
@@ -379,6 +381,7 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
 
 static int arp_ignore(struct in_device *in_dev, __be32 sip, __be32 tip)
 {
+       struct net *net = dev_net(in_dev->dev);
        int scope;
 
        switch (IN_DEV_ARP_IGNORE(in_dev)) {
@@ -397,6 +400,7 @@ static int arp_ignore(struct in_device *in_dev, __be32 sip, __be32 tip)
        case 3: /* Do not reply for scope host addresses */
                sip = 0;
                scope = RT_SCOPE_LINK;
+               in_dev = NULL;
                break;
        case 4: /* Reserved */
        case 5:
@@ -408,7 +412,7 @@ static int arp_ignore(struct in_device *in_dev, __be32 sip, __be32 tip)
        default:
                return 0;
        }
-       return !inet_confirm_addr(in_dev, sip, tip, scope);
+       return !inet_confirm_addr(net, in_dev, sip, tip, scope);
 }
 
 static int arp_filter(__be32 sip, __be32 tip, struct net_device *dev)
@@ -871,7 +875,7 @@ static int arp_process(struct sk_buff *skb)
 
                                if (NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED ||
                                    skb->pkt_type == PACKET_HOST ||
-                                   in_dev->arp_parms->proxy_delay == 0) {
+                                   NEIGH_VAR(in_dev->arp_parms, PROXY_DELAY) == 0) {
                                        arp_send(ARPOP_REPLY, ETH_P_ARP, sip,
                                                 dev, tip, sha, dev->dev_addr,
                                                 sha);
@@ -910,7 +914,8 @@ static int arp_process(struct sk_buff *skb)
                   agents are active. Taking the first reply prevents
                   arp trashing and chooses the fastest router.
                 */
-               override = time_after(jiffies, n->updated + n->parms->locktime);
+               override = time_after(jiffies, n->updated +
+                                              NEIGH_VAR(n->parms, LOCKTIME));
 
                /* Broadcast replies and request packets
                   do not assert neighbour reachability.
@@ -1284,7 +1289,7 @@ void __init arp_init(void)
        dev_add_pack(&arp_packet_type);
        arp_proc_init();
 #ifdef CONFIG_SYSCTL
-       neigh_sysctl_register(NULL, &arp_tbl.parms, "ipv4", NULL);
+       neigh_sysctl_register(NULL, &arp_tbl.parms, NULL);
 #endif
        register_netdevice_notifier(&arp_netdev_notifier);
 }
index 667c1d4ca9847c627127dc633e19c7c94f354188..4b59b6e488d3e61ec919a263a0e1c347d9335e43 100644 (file)
@@ -31,8 +31,7 @@
  * 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
+ * along with this program;  if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 19e36376d2a083b5c8b307208ebd17ade086dcaa..8b5134c582f147a94938c34a01dd0691c288bb78 100644 (file)
@@ -53,7 +53,7 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        rt = ip_route_connect(fl4, usin->sin_addr.s_addr, saddr,
                              RT_CONN_FLAGS(sk), oif,
                              sk->sk_protocol,
-                             inet->inet_sport, usin->sin_port, sk, true);
+                             inet->inet_sport, usin->sin_port, sk);
        if (IS_ERR(rt)) {
                err = PTR_ERR(rt);
                if (err == -ENETUNREACH)
index a1b5bcbd04ae01e358d1542c354fac083c9f8582..84956f5f01352a8684101fa3eb2528740f7f5934 100644 (file)
@@ -99,6 +99,7 @@ static const struct nla_policy ifa_ipv4_policy[IFA_MAX+1] = {
        [IFA_BROADCAST]         = { .type = NLA_U32 },
        [IFA_LABEL]             = { .type = NLA_STRING, .len = IFNAMSIZ - 1 },
        [IFA_CACHEINFO]         = { .len = sizeof(struct ifa_cacheinfo) },
+       [IFA_FLAGS]             = { .type = NLA_U32 },
 };
 
 #define IN4_ADDR_HSIZE_SHIFT   8
@@ -500,6 +501,7 @@ static int inet_set_ifa(struct net_device *dev, struct in_ifaddr *ifa)
                return -ENOBUFS;
        }
        ipv4_devconf_setall(in_dev);
+       neigh_parms_data_state_setall(in_dev->arp_parms);
        if (ifa->ifa_dev != in_dev) {
                WARN_ON(ifa->ifa_dev);
                in_dev_hold(in_dev);
@@ -747,6 +749,7 @@ static struct in_ifaddr *rtm_to_ifaddr(struct net *net, struct nlmsghdr *nlh,
                goto errout;
 
        ipv4_devconf_setall(in_dev);
+       neigh_parms_data_state_setall(in_dev->arp_parms);
        in_dev_hold(in_dev);
 
        if (tb[IFA_ADDRESS] == NULL)
@@ -755,7 +758,8 @@ static struct in_ifaddr *rtm_to_ifaddr(struct net *net, struct nlmsghdr *nlh,
        INIT_HLIST_NODE(&ifa->hash);
        ifa->ifa_prefixlen = ifm->ifa_prefixlen;
        ifa->ifa_mask = inet_make_mask(ifm->ifa_prefixlen);
-       ifa->ifa_flags = ifm->ifa_flags;
+       ifa->ifa_flags = tb[IFA_FLAGS] ? nla_get_u32(tb[IFA_FLAGS]) :
+                                        ifm->ifa_flags;
        ifa->ifa_scope = ifm->ifa_scope;
        ifa->ifa_dev = in_dev;
 
@@ -1236,22 +1240,21 @@ static __be32 confirm_addr_indev(struct in_device *in_dev, __be32 dst,
 
 /*
  * Confirm that local IP address exists using wildcards:
- * - in_dev: only on this interface, 0=any interface
+ * - net: netns to check, cannot be NULL
+ * - in_dev: only on this interface, NULL=any interface
  * - dst: only in the same subnet as dst, 0=any dst
  * - local: address, 0=autoselect the local address
  * - scope: maximum allowed scope value for the local address
  */
-__be32 inet_confirm_addr(struct in_device *in_dev,
+__be32 inet_confirm_addr(struct net *net, struct in_device *in_dev,
                         __be32 dst, __be32 local, int scope)
 {
        __be32 addr = 0;
        struct net_device *dev;
-       struct net *net;
 
-       if (scope != RT_SCOPE_LINK)
+       if (in_dev != NULL)
                return confirm_addr_indev(in_dev, dst, local, scope);
 
-       net = dev_net(in_dev->dev);
        rcu_read_lock();
        for_each_netdev_rcu(net, dev) {
                in_dev = __in_dev_get_rcu(dev);
@@ -1435,7 +1438,8 @@ static size_t inet_nlmsg_size(void)
               + nla_total_size(4) /* IFA_ADDRESS */
               + nla_total_size(4) /* IFA_LOCAL */
               + nla_total_size(4) /* IFA_BROADCAST */
-              + nla_total_size(IFNAMSIZ); /* IFA_LABEL */
+              + nla_total_size(IFNAMSIZ) /* IFA_LABEL */
+              + nla_total_size(4);  /* IFA_FLAGS */
 }
 
 static inline u32 cstamp_delta(unsigned long cstamp)
@@ -1503,6 +1507,7 @@ static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,
             nla_put_be32(skb, IFA_BROADCAST, ifa->ifa_broadcast)) ||
            (ifa->ifa_label[0] &&
             nla_put_string(skb, IFA_LABEL, ifa->ifa_label)) ||
+           nla_put_u32(skb, IFA_FLAGS, ifa->ifa_flags) ||
            put_cacheinfo(skb, ifa->ifa_cstamp, ifa->ifa_tstamp,
                          preferred, valid))
                goto nla_put_failure;
@@ -2160,7 +2165,7 @@ static void __devinet_sysctl_unregister(struct ipv4_devconf *cnf)
 
 static void devinet_sysctl_register(struct in_device *idev)
 {
-       neigh_sysctl_register(idev->dev, idev->arp_parms, "ipv4", NULL);
+       neigh_sysctl_register(idev->dev, idev->arp_parms, NULL);
        __devinet_sysctl_register(dev_net(idev->dev), idev->dev->name,
                                        &idev->cnf);
 }
index 523be38e37de82736a28bc9aa229f1911d2eaa31..f2e15738534d316ed0c50b8be2e1976fa03052c5 100644 (file)
@@ -104,7 +104,10 @@ errout:
 static bool fib4_rule_suppress(struct fib_rule *rule, struct fib_lookup_arg *arg)
 {
        struct fib_result *result = (struct fib_result *) arg->result;
-       struct net_device *dev = result->fi->fib_dev;
+       struct net_device *dev = NULL;
+
+       if (result->fi)
+               dev = result->fi->fib_dev;
 
        /* do not accept result if the route does
         * not meet the required prefix length
index 3f858266fa7e33a0941a135ec8a36b36278fdfce..a9fc435dc89f5d372f42890d44df5cb362f080fc 100644 (file)
@@ -386,7 +386,7 @@ void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 port, u32 inf
 /*
  *     Handle MSG_ERRQUEUE
  */
-int ip_recv_error(struct sock *sk, struct msghdr *msg, int len)
+int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
 {
        struct sock_exterr_skb *serr;
        struct sk_buff *skb, *skb2;
@@ -423,6 +423,7 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len)
                                                   serr->addr_offset);
                sin->sin_port = serr->port;
                memset(&sin->sin_zero, 0, sizeof(sin->sin_zero));
+               *addr_len = sizeof(*sin);
        }
 
        memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err));
@@ -1050,7 +1051,7 @@ e_inval:
  *
  * To support IP_CMSG_PKTINFO option, we store rt_iif and specific
  * destination in skb->cb[] before dst drop.
- * This way, receiver doesnt make cache line misses to read rtable.
+ * This way, receiver doesn't make cache line misses to read rtable.
  */
 void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb)
 {
index 62212c772a4b95961dafe1efce3fd06f146ccbb6..421a24934ffd13a06e97d99b8235c2cd915a4fe7 100644 (file)
@@ -425,6 +425,7 @@ struct net_device *ipmr_new_tunnel(struct net *net, struct vifctl *v)
                                goto failure;
 
                        ipv4_devconf_setall(in_dev);
+                       neigh_parms_data_state_setall(in_dev->arp_parms);
                        IPV4_DEVCONF(in_dev->cnf, RP_FILTER) = 0;
 
                        if (dev_open(dev))
@@ -517,6 +518,7 @@ static struct net_device *ipmr_reg_vif(struct net *net, struct mr_table *mrt)
        }
 
        ipv4_devconf_setall(in_dev);
+       neigh_parms_data_state_setall(in_dev->arp_parms);
        IPV4_DEVCONF(in_dev->cnf, RP_FILTER) = 0;
        rcu_read_unlock();
 
index 5f011cc89cd979742844febe4cc6117a9332d5c9..61a942265e8abd963e169cb990d7a3e008b06e04 100644 (file)
@@ -34,8 +34,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * Author: James Morris <jmorris@intercode.com.au>
  *
index 876c6ca2d8f9e77a28f1e629aa6523df1ee8f42f..242e7f4ed6f44ff5765966388618152e2721fa87 100644 (file)
@@ -772,7 +772,7 @@ int ping_v4_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                err = PTR_ERR(rt);
                rt = NULL;
                if (err == -ENETUNREACH)
-                       IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES);
+                       IP_INC_STATS(net, IPSTATS_MIB_OUTNOROUTES);
                goto out;
        }
 
@@ -841,10 +841,11 @@ int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 
        if (flags & MSG_ERRQUEUE) {
                if (family == AF_INET) {
-                       return ip_recv_error(sk, msg, len);
+                       return ip_recv_error(sk, msg, len, addr_len);
 #if IS_ENABLED(CONFIG_IPV6)
                } else if (family == AF_INET6) {
-                       return pingv6_ops.ipv6_recv_error(sk, msg, len);
+                       return pingv6_ops.ipv6_recv_error(sk, msg, len,
+                                                         addr_len);
 #endif
                }
        }
index 4a0335854b89c305442e257057ca560811159df8..8ecd7ad959b4c9a1e29d6cf68501c7ba26f0bdf1 100644 (file)
@@ -279,6 +279,7 @@ static const struct snmp_mib snmp4_net_list[] = {
        SNMP_MIB_ITEM("TCPFastOpenCookieReqd", LINUX_MIB_TCPFASTOPENCOOKIEREQD),
        SNMP_MIB_ITEM("TCPSpuriousRtxHostQueues", LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES),
        SNMP_MIB_ITEM("BusyPollRxPackets", LINUX_MIB_BUSYPOLLRXPACKETS),
+       SNMP_MIB_ITEM("TCPAutoCorking", LINUX_MIB_TCPAUTOCORKING),
        SNMP_MIB_SENTINEL
 };
 
index ce848461acbb07f6b758dc900225c7aff16ac690..46d6a1c923a8741776fa1de1cdd727b6cba72294 100644 (file)
 const struct net_protocol __rcu *inet_protos[MAX_INET_PROTOS] __read_mostly;
 const struct net_offload __rcu *inet_offloads[MAX_INET_PROTOS] __read_mostly;
 
-/*
- *     Add a protocol handler to the hash tables
- */
-
 int inet_add_protocol(const struct net_protocol *prot, unsigned char protocol)
 {
        if (!prot->netns_ok) {
@@ -55,10 +51,6 @@ int inet_add_offload(const struct net_offload *prot, unsigned char protocol)
 }
 EXPORT_SYMBOL(inet_add_offload);
 
-/*
- *     Remove a protocol from the hash tables.
- */
-
 int inet_del_protocol(const struct net_protocol *prot, unsigned char protocol)
 {
        int ret;
index 5cb8ddb505ee8911461ec92a5c74feef0b441e00..81e6cfd5a365826a75dc5f22813fe2268b431213 100644 (file)
@@ -575,7 +575,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos,
                           RT_SCOPE_UNIVERSE,
                           inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol,
-                          inet_sk_flowi_flags(sk) | FLOWI_FLAG_CAN_SLEEP |
+                          inet_sk_flowi_flags(sk) |
                            (inet->hdrincl ? FLOWI_FLAG_KNOWN_NH : 0),
                           daddr, saddr, 0, 0);
 
@@ -697,7 +697,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                goto out;
 
        if (flags & MSG_ERRQUEUE) {
-               err = ip_recv_error(sk, msg, len);
+               err = ip_recv_error(sk, msg, len, addr_len);
                goto out;
        }
 
index 3d69ec8dac578ee101e2c4b9467b3be83a430ac6..38c8ec90ff680001656f9ab53ee838b85827f9ea 100644 (file)
@@ -732,6 +732,15 @@ static struct ctl_table ipv4_table[] = {
                .extra1         = &zero,
                .extra2         = &gso_max_segs,
        },
+       {
+               .procname       = "tcp_autocorking",
+               .data           = &sysctl_tcp_autocorking,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec_minmax,
+               .extra1         = &zero,
+               .extra2         = &one,
+       },
        {
                .procname       = "udp_mem",
                .data           = &sysctl_udp_mem,
index c4638e6f023843bedbceb91f1bef3c424ad3b666..0ca87547becbe939c19e93c6f68983c40087da86 100644 (file)
@@ -285,6 +285,8 @@ int sysctl_tcp_fin_timeout __read_mostly = TCP_FIN_TIMEOUT;
 
 int sysctl_tcp_min_tso_segs __read_mostly = 2;
 
+int sysctl_tcp_autocorking __read_mostly = 1;
+
 struct percpu_counter tcp_orphan_count;
 EXPORT_SYMBOL_GPL(tcp_orphan_count);
 
@@ -619,19 +621,52 @@ static inline void tcp_mark_urg(struct tcp_sock *tp, int flags)
                tp->snd_up = tp->write_seq;
 }
 
-static inline void tcp_push(struct sock *sk, int flags, int mss_now,
-                           int nonagle)
+/* If a not yet filled skb is pushed, do not send it if
+ * we have packets in Qdisc or NIC queues :
+ * Because TX completion will happen shortly, it gives a chance
+ * to coalesce future sendmsg() payload into this skb, without
+ * need for a timer, and with no latency trade off.
+ * As packets containing data payload have a bigger truesize
+ * than pure acks (dataless) packets, the last check prevents
+ * autocorking if we only have an ACK in Qdisc/NIC queues.
+ */
+static bool tcp_should_autocork(struct sock *sk, struct sk_buff *skb,
+                               int size_goal)
 {
-       if (tcp_send_head(sk)) {
-               struct tcp_sock *tp = tcp_sk(sk);
+       return skb->len < size_goal &&
+              sysctl_tcp_autocorking &&
+              atomic_read(&sk->sk_wmem_alloc) > skb->truesize;
+}
+
+static void tcp_push(struct sock *sk, int flags, int mss_now,
+                    int nonagle, int size_goal)
+{
+       struct tcp_sock *tp = tcp_sk(sk);
+       struct sk_buff *skb;
 
-               if (!(flags & MSG_MORE) || forced_push(tp))
-                       tcp_mark_push(tp, tcp_write_queue_tail(sk));
+       if (!tcp_send_head(sk))
+               return;
+
+       skb = tcp_write_queue_tail(sk);
+       if (!(flags & MSG_MORE) || forced_push(tp))
+               tcp_mark_push(tp, skb);
+
+       tcp_mark_urg(tp, flags);
+
+       if (tcp_should_autocork(sk, skb, size_goal)) {
 
-               tcp_mark_urg(tp, flags);
-               __tcp_push_pending_frames(sk, mss_now,
-                                         (flags & MSG_MORE) ? TCP_NAGLE_CORK : nonagle);
+               /* avoid atomic op if TSQ_THROTTLED bit is already set */
+               if (!test_bit(TSQ_THROTTLED, &tp->tsq_flags)) {
+                       NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPAUTOCORKING);
+                       set_bit(TSQ_THROTTLED, &tp->tsq_flags);
+               }
+               return;
        }
+
+       if (flags & MSG_MORE)
+               nonagle = TCP_NAGLE_CORK;
+
+       __tcp_push_pending_frames(sk, mss_now, nonagle);
 }
 
 static int tcp_splice_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
@@ -934,7 +969,8 @@ new_segment:
 wait_for_sndbuf:
                set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
 wait_for_memory:
-               tcp_push(sk, flags & ~MSG_MORE, mss_now, TCP_NAGLE_PUSH);
+               tcp_push(sk, flags & ~MSG_MORE, mss_now,
+                        TCP_NAGLE_PUSH, size_goal);
 
                if ((err = sk_stream_wait_memory(sk, &timeo)) != 0)
                        goto do_error;
@@ -944,7 +980,7 @@ wait_for_memory:
 
 out:
        if (copied && !(flags & MSG_SENDPAGE_NOTLAST))
-               tcp_push(sk, flags, mss_now, tp->nonagle);
+               tcp_push(sk, flags, mss_now, tp->nonagle, size_goal);
        return copied;
 
 do_error:
@@ -1225,7 +1261,8 @@ wait_for_sndbuf:
                        set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
 wait_for_memory:
                        if (copied)
-                               tcp_push(sk, flags & ~MSG_MORE, mss_now, TCP_NAGLE_PUSH);
+                               tcp_push(sk, flags & ~MSG_MORE, mss_now,
+                                        TCP_NAGLE_PUSH, size_goal);
 
                        if ((err = sk_stream_wait_memory(sk, &timeo)) != 0)
                                goto do_error;
@@ -1236,7 +1273,7 @@ wait_for_memory:
 
 out:
        if (copied)
-               tcp_push(sk, flags, mss_now, tp->nonagle);
+               tcp_push(sk, flags, mss_now, tp->nonagle, size_goal);
        release_sock(sk);
        return copied + copied_syn;
 
index 59a6f8b90cd9d7c9ca51bbcd2cc424153d6571df..bbaf8cb45eb2ef60f3ad57cb5af6b04a8edf96bf 100644 (file)
@@ -173,11 +173,11 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        rt = ip_route_connect(fl4, nexthop, inet->inet_saddr,
                              RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
                              IPPROTO_TCP,
-                             orig_sport, orig_dport, sk, true);
+                             orig_sport, orig_dport, sk);
        if (IS_ERR(rt)) {
                err = PTR_ERR(rt);
                if (err == -ENETUNREACH)
-                       IP_INC_STATS_BH(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
+                       IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
                return err;
        }
 
index 03e9154f7e687efef63c91878e33427672bc4036..f7e522c558ba2eb43165f85d46c2ba3a91ce42eb 100644 (file)
@@ -6,13 +6,6 @@
 #include <linux/memcontrol.h>
 #include <linux/module.h>
 
-static void memcg_tcp_enter_memory_pressure(struct sock *sk)
-{
-       if (sk->sk_cgrp->memory_pressure)
-               sk->sk_cgrp->memory_pressure = 1;
-}
-EXPORT_SYMBOL(memcg_tcp_enter_memory_pressure);
-
 int tcp_init_cgroup(struct mem_cgroup *memcg, struct cgroup_subsys *ss)
 {
        /*
@@ -60,7 +53,6 @@ EXPORT_SYMBOL(tcp_destroy_cgroup);
 static int tcp_update_limit(struct mem_cgroup *memcg, u64 val)
 {
        struct cg_proto *cg_proto;
-       u64 old_lim;
        int i;
        int ret;
 
@@ -71,7 +63,6 @@ static int tcp_update_limit(struct mem_cgroup *memcg, u64 val)
        if (val > RES_COUNTER_MAX)
                val = RES_COUNTER_MAX;
 
-       old_lim = res_counter_read_u64(&cg_proto->memory_allocated, RES_LIMIT);
        ret = res_counter_set_limit(&cg_proto->memory_allocated, val);
        if (ret)
                return ret;
index a2b68a108eae69170c8d915be778c9aeebf0f371..05606353c7e7cb026096acaf598a8685b84b85c9 100644 (file)
@@ -274,33 +274,32 @@ static struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff *
 {
        const struct iphdr *iph = skb_gro_network_header(skb);
        __wsum wsum;
-       __sum16 sum;
+
+       /* Don't bother verifying checksum if we're going to flush anyway. */
+       if (NAPI_GRO_CB(skb)->flush)
+               goto skip_csum;
+
+       wsum = skb->csum;
 
        switch (skb->ip_summed) {
+       case CHECKSUM_NONE:
+               wsum = skb_checksum(skb, skb_gro_offset(skb), skb_gro_len(skb),
+                                   0);
+
+               /* fall through */
+
        case CHECKSUM_COMPLETE:
                if (!tcp_v4_check(skb_gro_len(skb), iph->saddr, iph->daddr,
-                                 skb->csum)) {
+                                 wsum)) {
                        skb->ip_summed = CHECKSUM_UNNECESSARY;
                        break;
                }
-flush:
+
                NAPI_GRO_CB(skb)->flush = 1;
                return NULL;
-
-       case CHECKSUM_NONE:
-               wsum = csum_tcpudp_nofold(iph->saddr, iph->daddr,
-                                         skb_gro_len(skb), IPPROTO_TCP, 0);
-               sum = csum_fold(skb_checksum(skb,
-                                            skb_gro_offset(skb),
-                                            skb_gro_len(skb),
-                                            wsum));
-               if (sum)
-                       goto flush;
-
-               skb->ip_summed = CHECKSUM_UNNECESSARY;
-               break;
        }
 
+skip_csum:
        return tcp_gro_receive(head, skb);
 }
 
index 7820f3a7dd704bd6375c5cdc858e71b7be4261ed..2a69f42e51cab1b544a8ef7ebe6b7599a59d8934 100644 (file)
@@ -363,15 +363,17 @@ static inline void TCP_ECN_send(struct sock *sk, struct sk_buff *skb,
  */
 static void tcp_init_nondata_skb(struct sk_buff *skb, u32 seq, u8 flags)
 {
+       struct skb_shared_info *shinfo = skb_shinfo(skb);
+
        skb->ip_summed = CHECKSUM_PARTIAL;
        skb->csum = 0;
 
        TCP_SKB_CB(skb)->tcp_flags = flags;
        TCP_SKB_CB(skb)->sacked = 0;
 
-       skb_shinfo(skb)->gso_segs = 1;
-       skb_shinfo(skb)->gso_size = 0;
-       skb_shinfo(skb)->gso_type = 0;
+       shinfo->gso_segs = 1;
+       shinfo->gso_size = 0;
+       shinfo->gso_type = 0;
 
        TCP_SKB_CB(skb)->seq = seq;
        if (flags & (TCPHDR_SYN | TCPHDR_FIN))
@@ -406,7 +408,7 @@ struct tcp_out_options {
  * Beware: Something in the Internet is very sensitive to the ordering of
  * TCP options, we learned this through the hard way, so be careful here.
  * Luckily we can at least blame others for their non-compliance but from
- * inter-operatibility perspective it seems that we're somewhat stuck with
+ * inter-operability perspective it seems that we're somewhat stuck with
  * the ordering which we have been using if we want to keep working with
  * those broken things (not that it currently hurts anybody as there isn't
  * particular reason why the ordering would need to be changed).
@@ -679,7 +681,7 @@ static unsigned int tcp_established_options(struct sock *sk, struct sk_buff *skb
  *
  * Its important tcp_wfree() can be replaced by sock_wfree() in the event skb
  * needs to be reallocated in a driver.
- * The invariant being skb->truesize substracted from sk->sk_wmem_alloc
+ * The invariant being skb->truesize subtracted from sk->sk_wmem_alloc
  *
  * Since transmit from skb destructor is forbidden, we use a tasklet
  * to process all sockets that eventually need to send more skbs.
@@ -699,9 +701,9 @@ static void tcp_tsq_handler(struct sock *sk)
                tcp_write_xmit(sk, tcp_current_mss(sk), 0, 0, GFP_ATOMIC);
 }
 /*
- * One tasklest per cpu tries to send more skbs.
+ * One tasklet per cpu tries to send more skbs.
  * We run in tasklet context but need to disable irqs when
- * transfering tsq->head because tcp_wfree() might
+ * transferring tsq->head because tcp_wfree() might
  * interrupt us (non NAPI drivers)
  */
 static void tcp_tasklet_func(unsigned long data)
@@ -795,7 +797,7 @@ void __init tcp_tasklet_init(void)
 
 /*
  * Write buffer destructor automatically called from kfree_skb.
- * We cant xmit new skbs from this context, as we might already
+ * We can't xmit new skbs from this context, as we might already
  * hold qdisc lock.
  */
 void tcp_wfree(struct sk_buff *skb)
@@ -986,6 +988,8 @@ static void tcp_queue_skb(struct sock *sk, struct sk_buff *skb)
 static void tcp_set_skb_tso_segs(const struct sock *sk, struct sk_buff *skb,
                                 unsigned int mss_now)
 {
+       struct skb_shared_info *shinfo = skb_shinfo(skb);
+
        /* Make sure we own this skb before messing gso_size/gso_segs */
        WARN_ON_ONCE(skb_cloned(skb));
 
@@ -993,13 +997,13 @@ static void tcp_set_skb_tso_segs(const struct sock *sk, struct sk_buff *skb,
                /* Avoid the costly divide in the normal
                 * non-TSO case.
                 */
-               skb_shinfo(skb)->gso_segs = 1;
-               skb_shinfo(skb)->gso_size = 0;
-               skb_shinfo(skb)->gso_type = 0;
+               shinfo->gso_segs = 1;
+               shinfo->gso_size = 0;
+               shinfo->gso_type = 0;
        } else {
-               skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss_now);
-               skb_shinfo(skb)->gso_size = mss_now;
-               skb_shinfo(skb)->gso_type = sk->sk_gso_type;
+               shinfo->gso_segs = DIV_ROUND_UP(skb->len, mss_now);
+               shinfo->gso_size = mss_now;
+               shinfo->gso_type = sk->sk_gso_type;
        }
 }
 
@@ -1146,6 +1150,7 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len,
  */
 static void __pskb_trim_head(struct sk_buff *skb, int len)
 {
+       struct skb_shared_info *shinfo;
        int i, k, eat;
 
        eat = min_t(int, len, skb_headlen(skb));
@@ -1157,23 +1162,24 @@ static void __pskb_trim_head(struct sk_buff *skb, int len)
        }
        eat = len;
        k = 0;
-       for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-               int size = skb_frag_size(&skb_shinfo(skb)->frags[i]);
+       shinfo = skb_shinfo(skb);
+       for (i = 0; i < shinfo->nr_frags; i++) {
+               int size = skb_frag_size(&shinfo->frags[i]);
 
                if (size <= eat) {
                        skb_frag_unref(skb, i);
                        eat -= size;
                } else {
-                       skb_shinfo(skb)->frags[k] = skb_shinfo(skb)->frags[i];
+                       shinfo->frags[k] = shinfo->frags[i];
                        if (eat) {
-                               skb_shinfo(skb)->frags[k].page_offset += eat;
-                               skb_frag_size_sub(&skb_shinfo(skb)->frags[k], eat);
+                               shinfo->frags[k].page_offset += eat;
+                               skb_frag_size_sub(&shinfo->frags[k], eat);
                                eat = 0;
                        }
                        k++;
                }
        }
-       skb_shinfo(skb)->nr_frags = k;
+       shinfo->nr_frags = k;
 
        skb_reset_tail_pointer(skb);
        skb->data_len -= len;
index 5944d7d668dd91da21e945eac748bbbbbb11d67a..62681082fdfedb22328cd2e3e8ed1f3f52d69ba6 100644 (file)
@@ -560,15 +560,11 @@ static inline struct sock *__udp4_lib_lookup_skb(struct sk_buff *skb,
                                                 __be16 sport, __be16 dport,
                                                 struct udp_table *udptable)
 {
-       struct sock *sk;
        const struct iphdr *iph = ip_hdr(skb);
 
-       if (unlikely(sk = skb_steal_sock(skb)))
-               return sk;
-       else
-               return __udp4_lib_lookup(dev_net(skb_dst(skb)->dev), iph->saddr, sport,
-                                        iph->daddr, dport, inet_iif(skb),
-                                        udptable);
+       return __udp4_lib_lookup(dev_net(skb_dst(skb)->dev), iph->saddr, sport,
+                                iph->daddr, dport, inet_iif(skb),
+                                udptable);
 }
 
 struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
@@ -990,7 +986,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                fl4 = &fl4_stack;
                flowi4_init_output(fl4, ipc.oif, sk->sk_mark, tos,
                                   RT_SCOPE_UNIVERSE, sk->sk_protocol,
-                                  inet_sk_flowi_flags(sk)|FLOWI_FLAG_CAN_SLEEP,
+                                  inet_sk_flowi_flags(sk),
                                   faddr, saddr, dport, inet->inet_sport);
 
                security_sk_classify_flow(sk, flowi4_to_flowi(fl4));
@@ -999,7 +995,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                        err = PTR_ERR(rt);
                        rt = NULL;
                        if (err == -ENETUNREACH)
-                               IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES);
+                               IP_INC_STATS(net, IPSTATS_MIB_OUTNOROUTES);
                        goto out;
                }
 
@@ -1098,6 +1094,9 @@ int udp_sendpage(struct sock *sk, struct page *page, int offset,
        struct udp_sock *up = udp_sk(sk);
        int ret;
 
+       if (flags & MSG_SENDPAGE_NOTLAST)
+               flags |= MSG_MORE;
+
        if (!up->pending) {
                struct msghdr msg = {   .msg_flags = flags|MSG_MORE };
 
@@ -1236,7 +1235,7 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        bool slow;
 
        if (flags & MSG_ERRQUEUE)
-               return ip_recv_error(sk, msg, len);
+               return ip_recv_error(sk, msg, len, addr_len);
 
 try_again:
        skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0),
@@ -1736,15 +1735,15 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
        if (udp4_csum_init(skb, uh, proto))
                goto csum_error;
 
-       if (skb->sk) {
+       sk = skb_steal_sock(skb);
+       if (sk) {
                int ret;
-               sk = skb->sk;
 
                if (unlikely(sk->sk_rx_dst == NULL))
                        udp_sk_rx_dst_set(sk, skb);
 
                ret = udp_queue_rcv_skb(sk, skb);
-
+               sock_put(sk);
                /* a return value > 0 means to resubmit the input, but
                 * it wants the return to be -protocol, or 0
                 */
@@ -1910,17 +1909,20 @@ static struct sock *__udp4_lib_demux_lookup(struct net *net,
 
 void udp_v4_early_demux(struct sk_buff *skb)
 {
-       const struct iphdr *iph = ip_hdr(skb);
-       const struct udphdr *uh = udp_hdr(skb);
+       struct net *net = dev_net(skb->dev);
+       const struct iphdr *iph;
+       const struct udphdr *uh;
        struct sock *sk;
        struct dst_entry *dst;
-       struct net *net = dev_net(skb->dev);
        int dif = skb->dev->ifindex;
 
        /* validate the packet */
        if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct udphdr)))
                return;
 
+       iph = ip_hdr(skb);
+       uh = udp_hdr(skb);
+
        if (skb->pkt_type == PACKET_BROADCAST ||
            skb->pkt_type == PACKET_MULTICAST)
                sk = __udp4_lib_mcast_demux_lookup(net, uh->dest, iph->daddr,
index 12c97d8aa6bbb31ff1519459b89b7b9fb33817f5..96a5cb781c63df31f90db8084224f0223b168bd1 100644 (file)
@@ -834,6 +834,8 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
                goto out;
        }
 
+       neigh_parms_data_state_setall(idev->nd_parms);
+
        ifa->addr = *addr;
        if (peer_addr)
                ifa->peer_addr = *peer_addr;
@@ -1024,7 +1026,7 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i
        u32 addr_flags;
        unsigned long now = jiffies;
 
-       write_lock(&idev->lock);
+       write_lock_bh(&idev->lock);
        if (ift) {
                spin_lock_bh(&ift->lock);
                memcpy(&addr.s6_addr[8], &ift->addr.s6_addr[8], 8);
@@ -1036,7 +1038,7 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i
 retry:
        in6_dev_hold(idev);
        if (idev->cnf.use_tempaddr <= 0) {
-               write_unlock(&idev->lock);
+               write_unlock_bh(&idev->lock);
                pr_info("%s: use_tempaddr is disabled\n", __func__);
                in6_dev_put(idev);
                ret = -1;
@@ -1046,7 +1048,7 @@ retry:
        if (ifp->regen_count++ >= idev->cnf.regen_max_retry) {
                idev->cnf.use_tempaddr = -1;    /*XXX*/
                spin_unlock_bh(&ifp->lock);
-               write_unlock(&idev->lock);
+               write_unlock_bh(&idev->lock);
                pr_warn("%s: regeneration time exceeded - disabled temporary address support\n",
                        __func__);
                in6_dev_put(idev);
@@ -1071,8 +1073,8 @@ retry:
 
        regen_advance = idev->cnf.regen_max_retry *
                        idev->cnf.dad_transmits *
-                       idev->nd_parms->retrans_time / HZ;
-       write_unlock(&idev->lock);
+                       NEIGH_VAR(idev->nd_parms, RETRANS_TIME) / HZ;
+       write_unlock_bh(&idev->lock);
 
        /* A temporary address is created only if this calculated Preferred
         * Lifetime is greater than REGEN_ADVANCE time units.  In particular,
@@ -1099,7 +1101,7 @@ retry:
                in6_dev_put(idev);
                pr_info("%s: retry temporary address regeneration\n", __func__);
                tmpaddr = &addr;
-               write_lock(&idev->lock);
+               write_lock_bh(&idev->lock);
                goto retry;
        }
 
@@ -1407,7 +1409,7 @@ try_nextdev:
 EXPORT_SYMBOL(ipv6_dev_get_saddr);
 
 int __ipv6_get_lladdr(struct inet6_dev *idev, struct in6_addr *addr,
-                     unsigned char banned_flags)
+                     u32 banned_flags)
 {
        struct inet6_ifaddr *ifp;
        int err = -EADDRNOTAVAIL;
@@ -1424,7 +1426,7 @@ int __ipv6_get_lladdr(struct inet6_dev *idev, struct in6_addr *addr,
 }
 
 int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr,
-                   unsigned char banned_flags)
+                   u32 banned_flags)
 {
        struct inet6_dev *idev;
        int err = -EADDRNOTAVAIL;
@@ -1816,6 +1818,7 @@ static int ipv6_generate_eui64(u8 *eui, struct net_device *dev)
                return addrconf_ifid_sit(eui, dev);
        case ARPHRD_IPGRE:
                return addrconf_ifid_gre(eui, dev);
+       case ARPHRD_6LOWPAN:
        case ARPHRD_IEEE802154:
                return addrconf_ifid_eui64(eui, dev);
        case ARPHRD_IEEE1394:
@@ -1888,7 +1891,8 @@ static void ipv6_regen_rndid(unsigned long data)
 
        expires = jiffies +
                idev->cnf.temp_prefered_lft * HZ -
-               idev->cnf.regen_max_retry * idev->cnf.dad_transmits * idev->nd_parms->retrans_time -
+               idev->cnf.regen_max_retry * idev->cnf.dad_transmits *
+               NEIGH_VAR(idev->nd_parms, RETRANS_TIME) -
                idev->cnf.max_desync_factor * HZ;
        if (time_before(expires, jiffies)) {
                pr_warn("%s: too short regeneration interval; timer disabled for %s\n",
@@ -2016,6 +2020,73 @@ static struct inet6_dev *addrconf_add_dev(struct net_device *dev)
        return idev;
 }
 
+static void manage_tempaddrs(struct inet6_dev *idev,
+                            struct inet6_ifaddr *ifp,
+                            __u32 valid_lft, __u32 prefered_lft,
+                            bool create, unsigned long now)
+{
+       u32 flags;
+       struct inet6_ifaddr *ift;
+
+       read_lock_bh(&idev->lock);
+       /* update all temporary addresses in the list */
+       list_for_each_entry(ift, &idev->tempaddr_list, tmp_list) {
+               int age, max_valid, max_prefered;
+
+               if (ifp != ift->ifpub)
+                       continue;
+
+               /* RFC 4941 section 3.3:
+                * If a received option will extend the lifetime of a public
+                * address, the lifetimes of temporary addresses should
+                * be extended, subject to the overall constraint that no
+                * temporary addresses should ever remain "valid" or "preferred"
+                * for a time longer than (TEMP_VALID_LIFETIME) or
+                * (TEMP_PREFERRED_LIFETIME - DESYNC_FACTOR), respectively.
+                */
+               age = (now - ift->cstamp) / HZ;
+               max_valid = idev->cnf.temp_valid_lft - age;
+               if (max_valid < 0)
+                       max_valid = 0;
+
+               max_prefered = idev->cnf.temp_prefered_lft -
+                              idev->cnf.max_desync_factor - age;
+               if (max_prefered < 0)
+                       max_prefered = 0;
+
+               if (valid_lft > max_valid)
+                       valid_lft = max_valid;
+
+               if (prefered_lft > max_prefered)
+                       prefered_lft = max_prefered;
+
+               spin_lock(&ift->lock);
+               flags = ift->flags;
+               ift->valid_lft = valid_lft;
+               ift->prefered_lft = prefered_lft;
+               ift->tstamp = now;
+               if (prefered_lft > 0)
+                       ift->flags &= ~IFA_F_DEPRECATED;
+
+               spin_unlock(&ift->lock);
+               if (!(flags&IFA_F_TENTATIVE))
+                       ipv6_ifa_notify(0, ift);
+       }
+
+       if ((create || list_empty(&idev->tempaddr_list)) &&
+           idev->cnf.use_tempaddr > 0) {
+               /* When a new public address is created as described
+                * in [ADDRCONF], also create a new temporary address.
+                * Also create a temporary address if it's enabled but
+                * no temporary address currently exists.
+                */
+               read_unlock_bh(&idev->lock);
+               ipv6_create_tempaddr(ifp, NULL);
+       } else {
+               read_unlock_bh(&idev->lock);
+       }
+}
+
 void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao)
 {
        struct prefix_info *pinfo;
@@ -2170,6 +2241,7 @@ ok:
                                return;
                        }
 
+                       ifp->flags |= IFA_F_MANAGETEMPADDR;
                        update_lft = 0;
                        create = 1;
                        ifp->cstamp = jiffies;
@@ -2178,9 +2250,8 @@ ok:
                }
 
                if (ifp) {
-                       int flags;
+                       u32 flags;
                        unsigned long now;
-                       struct inet6_ifaddr *ift;
                        u32 stored_lft;
 
                        /* update lifetime (RFC2462 5.5.3 e) */
@@ -2221,70 +2292,8 @@ ok:
                        } else
                                spin_unlock(&ifp->lock);
 
-                       read_lock_bh(&in6_dev->lock);
-                       /* update all temporary addresses in the list */
-                       list_for_each_entry(ift, &in6_dev->tempaddr_list,
-                                           tmp_list) {
-                               int age, max_valid, max_prefered;
-
-                               if (ifp != ift->ifpub)
-                                       continue;
-
-                               /*
-                                * RFC 4941 section 3.3:
-                                * If a received option will extend the lifetime
-                                * of a public address, the lifetimes of
-                                * temporary addresses should be extended,
-                                * subject to the overall constraint that no
-                                * temporary addresses should ever remain
-                                * "valid" or "preferred" for a time longer than
-                                * (TEMP_VALID_LIFETIME) or
-                                * (TEMP_PREFERRED_LIFETIME - DESYNC_FACTOR),
-                                * respectively.
-                                */
-                               age = (now - ift->cstamp) / HZ;
-                               max_valid = in6_dev->cnf.temp_valid_lft - age;
-                               if (max_valid < 0)
-                                       max_valid = 0;
-
-                               max_prefered = in6_dev->cnf.temp_prefered_lft -
-                                              in6_dev->cnf.max_desync_factor -
-                                              age;
-                               if (max_prefered < 0)
-                                       max_prefered = 0;
-
-                               if (valid_lft > max_valid)
-                                       valid_lft = max_valid;
-
-                               if (prefered_lft > max_prefered)
-                                       prefered_lft = max_prefered;
-
-                               spin_lock(&ift->lock);
-                               flags = ift->flags;
-                               ift->valid_lft = valid_lft;
-                               ift->prefered_lft = prefered_lft;
-                               ift->tstamp = now;
-                               if (prefered_lft > 0)
-                                       ift->flags &= ~IFA_F_DEPRECATED;
-
-                               spin_unlock(&ift->lock);
-                               if (!(flags&IFA_F_TENTATIVE))
-                                       ipv6_ifa_notify(0, ift);
-                       }
-
-                       if ((create || list_empty(&in6_dev->tempaddr_list)) && in6_dev->cnf.use_tempaddr > 0) {
-                               /*
-                                * When a new public address is created as
-                                * described in [ADDRCONF], also create a new
-                                * temporary address. Also create a temporary
-                                * address if it's enabled but no temporary
-                                * address currently exists.
-                                */
-                               read_unlock_bh(&in6_dev->lock);
-                               ipv6_create_tempaddr(ifp, NULL);
-                       } else {
-                               read_unlock_bh(&in6_dev->lock);
-                       }
+                       manage_tempaddrs(in6_dev, ifp, valid_lft, prefered_lft,
+                                        create, now);
 
                        in6_ifa_put(ifp);
                        addrconf_verify(0);
@@ -2363,10 +2372,11 @@ err_exit:
 /*
  *     Manual configuration of address on an interface
  */
-static int inet6_addr_add(struct net *net, int ifindex, const struct in6_addr *pfx,
+static int inet6_addr_add(struct net *net, int ifindex,
+                         const struct in6_addr *pfx,
                          const struct in6_addr *peer_pfx,
-                         unsigned int plen, __u8 ifa_flags, __u32 prefered_lft,
-                         __u32 valid_lft)
+                         unsigned int plen, __u32 ifa_flags,
+                         __u32 prefered_lft, __u32 valid_lft)
 {
        struct inet6_ifaddr *ifp;
        struct inet6_dev *idev;
@@ -2385,6 +2395,9 @@ static int inet6_addr_add(struct net *net, int ifindex, const struct in6_addr *p
        if (!valid_lft || prefered_lft > valid_lft)
                return -EINVAL;
 
+       if (ifa_flags & IFA_F_MANAGETEMPADDR && plen != 64)
+               return -EINVAL;
+
        dev = __dev_get_by_index(net, ifindex);
        if (!dev)
                return -ENODEV;
@@ -2425,6 +2438,9 @@ static int inet6_addr_add(struct net *net, int ifindex, const struct in6_addr *p
                 * manually configured addresses
                 */
                addrconf_dad_start(ifp);
+               if (ifa_flags & IFA_F_MANAGETEMPADDR)
+                       manage_tempaddrs(idev, ifp, valid_lft, prefered_lft,
+                                        true, jiffies);
                in6_ifa_put(ifp);
                addrconf_verify(0);
                return 0;
@@ -2613,7 +2629,7 @@ static void init_loopback(struct net_device *dev)
                        if (sp_ifa->rt)
                                continue;
 
-                       sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, 0);
+                       sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, false);
 
                        /* Failure cases are ignored */
                        if (!IS_ERR(sp_rt)) {
@@ -2658,7 +2674,8 @@ static void addrconf_dev_config(struct net_device *dev)
            (dev->type != ARPHRD_INFINIBAND) &&
            (dev->type != ARPHRD_IEEE802154) &&
            (dev->type != ARPHRD_IEEE1394) &&
-           (dev->type != ARPHRD_TUNNEL6)) {
+           (dev->type != ARPHRD_TUNNEL6) &&
+           (dev->type != ARPHRD_6LOWPAN)) {
                /* Alas, we support only Ethernet autoconfiguration. */
                return;
        }
@@ -3176,7 +3193,8 @@ static void addrconf_dad_timer(unsigned long data)
        }
 
        ifp->dad_probes--;
-       addrconf_mod_dad_timer(ifp, ifp->idev->nd_parms->retrans_time);
+       addrconf_mod_dad_timer(ifp,
+                              NEIGH_VAR(ifp->idev->nd_parms, RETRANS_TIME));
        spin_unlock(&ifp->lock);
        write_unlock(&idev->lock);
 
@@ -3356,7 +3374,7 @@ static int if6_seq_show(struct seq_file *seq, void *v)
                   ifp->idev->dev->ifindex,
                   ifp->prefix_len,
                   ifp->scope,
-                  ifp->flags,
+                  (u8) ifp->flags,
                   ifp->idev->dev->name);
        return 0;
 }
@@ -3497,7 +3515,7 @@ restart:
                                   !(ifp->flags&IFA_F_TENTATIVE)) {
                                unsigned long regen_advance = ifp->idev->cnf.regen_max_retry *
                                        ifp->idev->cnf.dad_transmits *
-                                       ifp->idev->nd_parms->retrans_time / HZ;
+                                       NEIGH_VAR(ifp->idev->nd_parms, RETRANS_TIME) / HZ;
 
                                if (age >= ifp->prefered_lft - regen_advance) {
                                        struct inet6_ifaddr *ifpub = ifp->ifpub;
@@ -3572,6 +3590,7 @@ static const struct nla_policy ifa_ipv6_policy[IFA_MAX+1] = {
        [IFA_ADDRESS]           = { .len = sizeof(struct in6_addr) },
        [IFA_LOCAL]             = { .len = sizeof(struct in6_addr) },
        [IFA_CACHEINFO]         = { .len = sizeof(struct ifa_cacheinfo) },
+       [IFA_FLAGS]             = { .len = sizeof(u32) },
 };
 
 static int
@@ -3595,16 +3614,21 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh)
        return inet6_addr_del(net, ifm->ifa_index, pfx, ifm->ifa_prefixlen);
 }
 
-static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags,
+static int inet6_addr_modify(struct inet6_ifaddr *ifp, u32 ifa_flags,
                             u32 prefered_lft, u32 valid_lft)
 {
        u32 flags;
        clock_t expires;
        unsigned long timeout;
+       bool was_managetempaddr;
 
        if (!valid_lft || (prefered_lft > valid_lft))
                return -EINVAL;
 
+       if (ifa_flags & IFA_F_MANAGETEMPADDR &&
+           (ifp->flags & IFA_F_TEMPORARY || ifp->prefix_len != 64))
+               return -EINVAL;
+
        timeout = addrconf_timeout_fixup(valid_lft, HZ);
        if (addrconf_finite_timeout(timeout)) {
                expires = jiffies_to_clock_t(timeout * HZ);
@@ -3624,7 +3648,10 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags,
        }
 
        spin_lock_bh(&ifp->lock);
-       ifp->flags = (ifp->flags & ~(IFA_F_DEPRECATED | IFA_F_PERMANENT | IFA_F_NODAD | IFA_F_HOMEADDRESS)) | ifa_flags;
+       was_managetempaddr = ifp->flags & IFA_F_MANAGETEMPADDR;
+       ifp->flags &= ~(IFA_F_DEPRECATED | IFA_F_PERMANENT | IFA_F_NODAD |
+                       IFA_F_HOMEADDRESS | IFA_F_MANAGETEMPADDR);
+       ifp->flags |= ifa_flags;
        ifp->tstamp = jiffies;
        ifp->valid_lft = valid_lft;
        ifp->prefered_lft = prefered_lft;
@@ -3635,6 +3662,14 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags,
 
        addrconf_prefix_route(&ifp->addr, ifp->prefix_len, ifp->idev->dev,
                              expires, flags);
+
+       if (was_managetempaddr || ifp->flags & IFA_F_MANAGETEMPADDR) {
+               if (was_managetempaddr && !(ifp->flags & IFA_F_MANAGETEMPADDR))
+                       valid_lft = prefered_lft = 0;
+               manage_tempaddrs(ifp->idev, ifp, valid_lft, prefered_lft,
+                                !was_managetempaddr, jiffies);
+       }
+
        addrconf_verify(0);
 
        return 0;
@@ -3650,7 +3685,7 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh)
        struct inet6_ifaddr *ifa;
        struct net_device *dev;
        u32 valid_lft = INFINITY_LIFE_TIME, preferred_lft = INFINITY_LIFE_TIME;
-       u8 ifa_flags;
+       u32 ifa_flags;
        int err;
 
        err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy);
@@ -3677,8 +3712,10 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh)
        if (dev == NULL)
                return -ENODEV;
 
+       ifa_flags = tb[IFA_FLAGS] ? nla_get_u32(tb[IFA_FLAGS]) : ifm->ifa_flags;
+
        /* We ignore other flags so far. */
-       ifa_flags = ifm->ifa_flags & (IFA_F_NODAD | IFA_F_HOMEADDRESS);
+       ifa_flags &= IFA_F_NODAD | IFA_F_HOMEADDRESS | IFA_F_MANAGETEMPADDR;
 
        ifa = ipv6_get_ifaddr(net, pfx, dev, 1);
        if (ifa == NULL) {
@@ -3702,7 +3739,7 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh)
        return err;
 }
 
-static void put_ifaddrmsg(struct nlmsghdr *nlh, u8 prefixlen, u8 flags,
+static void put_ifaddrmsg(struct nlmsghdr *nlh, u8 prefixlen, u32 flags,
                          u8 scope, int ifindex)
 {
        struct ifaddrmsg *ifm;
@@ -3745,7 +3782,8 @@ static inline int inet6_ifaddr_msgsize(void)
        return NLMSG_ALIGN(sizeof(struct ifaddrmsg))
               + nla_total_size(16) /* IFA_LOCAL */
               + nla_total_size(16) /* IFA_ADDRESS */
-              + nla_total_size(sizeof(struct ifa_cacheinfo));
+              + nla_total_size(sizeof(struct ifa_cacheinfo))
+              + nla_total_size(4)  /* IFA_FLAGS */;
 }
 
 static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
@@ -3793,6 +3831,9 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
        if (put_cacheinfo(skb, ifa->cstamp, ifa->tstamp, preferred, valid) < 0)
                goto error;
 
+       if (nla_put_u32(skb, IFA_FLAGS, ifa->flags) < 0)
+               goto error;
+
        return nlmsg_end(skb, nlh);
 
 error:
@@ -4196,7 +4237,7 @@ static int inet6_fill_ifla6_attrs(struct sk_buff *skb, struct inet6_dev *idev)
        ci.max_reasm_len = IPV6_MAXPLEN;
        ci.tstamp = cstamp_delta(idev->tstamp);
        ci.reachable_time = jiffies_to_msecs(idev->nd_parms->reachable_time);
-       ci.retrans_time = jiffies_to_msecs(idev->nd_parms->retrans_time);
+       ci.retrans_time = jiffies_to_msecs(NEIGH_VAR(idev->nd_parms, RETRANS_TIME));
        if (nla_put(skb, IFLA_INET6_CACHEINFO, sizeof(ci), &ci))
                goto nla_put_failure;
        nla = nla_reserve(skb, IFLA_INET6_CONF, DEVCONF_MAX * sizeof(s32));
@@ -4991,7 +5032,7 @@ static void __addrconf_sysctl_unregister(struct ipv6_devconf *p)
 
 static void addrconf_sysctl_register(struct inet6_dev *idev)
 {
-       neigh_sysctl_register(idev->dev, idev->nd_parms, "ipv6",
+       neigh_sysctl_register(idev->dev, idev->nd_parms,
                              &ndisc_ifinfo_sysctl_change);
        __addrconf_sysctl_register(dev_net(idev->dev), idev->dev->name,
                                        idev, &idev->cnf);
index 4fbdb7046d286cf64f60c61e3ae87ba657f042a0..3b9dd7bd927c8f5e7a3f6ce38b65997b12c813ce 100644 (file)
@@ -661,7 +661,7 @@ int inet6_sk_rebuild_header(struct sock *sk)
 
                final_p = fl6_update_dst(&fl6, np->opt, &final);
 
-               dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false);
+               dst = ip6_dst_lookup_flow(sk, &fl6, final_p);
                if (IS_ERR(dst)) {
                        sk->sk_route_caps = 0;
                        sk->sk_err_soft = -PTR_ERR(dst);
@@ -683,8 +683,7 @@ bool ipv6_opt_accepted(const struct sock *sk, const struct sk_buff *skb)
        if (np->rxopt.all) {
                if ((opt->hop && (np->rxopt.bits.hopopts ||
                                  np->rxopt.bits.ohopopts)) ||
-                   ((IPV6_FLOWINFO_MASK &
-                     *(__be32 *)skb_network_header(skb)) &&
+                   (ip6_flowinfo((struct ipv6hdr *) skb_network_header(skb)) &&
                     np->rxopt.bits.rxflow) ||
                    (opt->srcrt && (np->rxopt.bits.srcrt ||
                     np->rxopt.bits.osrcrt)) ||
index 82e1da3a40b915e65c2ecf15662415511cc91286..81e496a2e0083c42fe94729a486647aa23c8aed0 100644 (file)
@@ -12,8 +12,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * Authors
  *
index a454b0ff57c7c67a91e2e5c887609e7a65e5a910..6983058942ead87c227919d0289bab5fe535365a 100644 (file)
@@ -73,7 +73,6 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
                        flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
                        if (flowlabel == NULL)
                                return -EINVAL;
-                       usin->sin6_addr = flowlabel->dst;
                }
        }
 
@@ -171,7 +170,7 @@ ipv4_connected:
        opt = flowlabel ? flowlabel->opt : np->opt;
        final_p = fl6_update_dst(&fl6, opt, &final);
 
-       dst = ip6_dst_lookup_flow(sk, &fl6, final_p, true);
+       dst = ip6_dst_lookup_flow(sk, &fl6, final_p);
        err = 0;
        if (IS_ERR(dst)) {
                err = PTR_ERR(dst);
@@ -318,7 +317,7 @@ void ipv6_local_rxpmtu(struct sock *sk, struct flowi6 *fl6, u32 mtu)
 /*
  *     Handle MSG_ERRQUEUE
  */
-int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
+int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
 {
        struct ipv6_pinfo *np = inet6_sk(sk);
        struct sock_exterr_skb *serr;
@@ -369,6 +368,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
                                               &sin->sin6_addr);
                        sin->sin6_scope_id = 0;
                }
+               *addr_len = sizeof(*sin);
        }
 
        memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err));
@@ -377,6 +377,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
        if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) {
                sin->sin6_family = AF_INET6;
                sin->sin6_flowinfo = 0;
+               sin->sin6_port = 0;
                if (skb->protocol == htons(ETH_P_IPV6)) {
                        sin->sin6_addr = ipv6_hdr(skb)->saddr;
                        if (np->rxopt.all)
@@ -423,7 +424,8 @@ EXPORT_SYMBOL_GPL(ipv6_recv_error);
 /*
  *     Handle IPV6_RECVPATHMTU
  */
-int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len)
+int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len,
+                    int *addr_len)
 {
        struct ipv6_pinfo *np = inet6_sk(sk);
        struct sk_buff *skb;
@@ -457,6 +459,7 @@ int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len)
                sin->sin6_port = 0;
                sin->sin6_scope_id = mtu_info.ip6m_addr.sin6_scope_id;
                sin->sin6_addr = mtu_info.ip6m_addr.sin6_addr;
+               *addr_len = sizeof(*sin);
        }
 
        put_cmsg(msg, SOL_IPV6, IPV6_PATHMTU, sizeof(mtu_info), &mtu_info);
index b8719df0366eb30759b39c72fd8ba28a0c0f67ed..6eef8a7e35f2c54514e6bbb8871d18ff18ae691e 100644 (file)
@@ -12,8 +12,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * Authors
  *
index e27591635f92c45306a33cb9513628751e93dd16..3fd0a578329e523828fc56b40b6ffe217fd850dc 100644 (file)
@@ -122,7 +122,11 @@ out:
 static bool fib6_rule_suppress(struct fib_rule *rule, struct fib_lookup_arg *arg)
 {
        struct rt6_info *rt = (struct rt6_info *) arg->result;
-       struct net_device *dev = rt->rt6i_idev->dev;
+       struct net_device *dev = NULL;
+
+       if (rt->rt6i_idev)
+               dev = rt->rt6i_idev->dev;
+
        /* do not accept result if the route does
         * not meet the required prefix length
         */
index 77bb8afb141d6349e3de622e0f20452552d70344..c9138189415a91c994d658bbbc9d59bd95d8b815 100644 (file)
@@ -86,7 +86,7 @@ struct dst_entry *inet6_csk_route_req(struct sock *sk,
        fl6->fl6_sport = htons(ireq->ir_num);
        security_req_classify_flow(req, flowi6_to_flowi(fl6));
 
-       dst = ip6_dst_lookup_flow(sk, fl6, final_p, false);
+       dst = ip6_dst_lookup_flow(sk, fl6, final_p);
        if (IS_ERR(dst))
                return NULL;
 
@@ -216,7 +216,7 @@ static struct dst_entry *inet6_csk_route_socket(struct sock *sk,
 
        dst = __inet6_csk_dst_check(sk, np->dst_cookie);
        if (!dst) {
-               dst = ip6_dst_lookup_flow(sk, fl6, final_p, false);
+               dst = ip6_dst_lookup_flow(sk, fl6, final_p);
 
                if (!IS_ERR(dst))
                        __inet6_csk_dst_store(sk, dst, NULL, NULL);
index 8acb28621f9cfd57071eeff1a39acd0de1ff6c02..e27fb78c61f21e37bd46ca9739ef3d27200d5b62 100644 (file)
@@ -61,7 +61,6 @@ static bool log_ecn_error = true;
 module_param(log_ecn_error, bool, 0644);
 MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");
 
-#define IPV6_TCLASS_MASK (IPV6_FLOWINFO_MASK & ~IPV6_FLOWLABEL_MASK)
 #define IPV6_TCLASS_SHIFT 20
 
 #define HASH_SIZE_SHIFT  5
@@ -846,7 +845,7 @@ static inline int ip6gre_xmit_ipv6(struct sk_buff *skb, struct net_device *dev)
        if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
                fl6.flowlabel |= (*(__be32 *) ipv6h & IPV6_TCLASS_MASK);
        if (t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL)
-               fl6.flowlabel |= (*(__be32 *) ipv6h & IPV6_FLOWLABEL_MASK);
+               fl6.flowlabel |= ip6_flowlabel(ipv6h);
        if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
                fl6.flowi6_mark = skb->mark;
 
index 59df872e2f4d62f68b583ff40218d68c5d5189df..508d50c39737cab0786dda222152fe282890130a 100644 (file)
@@ -116,8 +116,8 @@ static int ip6_finish_output2(struct sk_buff *skb)
        }
        rcu_read_unlock_bh();
 
-       IP6_INC_STATS_BH(dev_net(dst->dev),
-                        ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
+       IP6_INC_STATS(dev_net(dst->dev),
+                     ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
        kfree_skb(skb);
        return -EINVAL;
 }
@@ -336,7 +336,8 @@ int ip6_forward(struct sk_buff *skb)
                goto drop;
 
        if (!xfrm6_policy_check(NULL, XFRM_POLICY_FWD, skb)) {
-               IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_INDISCARDS);
+               IP6_INC_STATS_BH(net, ip6_dst_idev(dst),
+                                IPSTATS_MIB_INDISCARDS);
                goto drop;
        }
 
@@ -370,8 +371,8 @@ int ip6_forward(struct sk_buff *skb)
                /* Force OUTPUT device used as source address */
                skb->dev = dst->dev;
                icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, 0);
-               IP6_INC_STATS_BH(net,
-                                ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS);
+               IP6_INC_STATS_BH(net, ip6_dst_idev(dst),
+                                IPSTATS_MIB_INHDRERRORS);
 
                kfree_skb(skb);
                return -ETIMEDOUT;
@@ -384,14 +385,15 @@ int ip6_forward(struct sk_buff *skb)
                if (proxied > 0)
                        return ip6_input(skb);
                else if (proxied < 0) {
-                       IP6_INC_STATS(net, ip6_dst_idev(dst),
-                                     IPSTATS_MIB_INDISCARDS);
+                       IP6_INC_STATS_BH(net, ip6_dst_idev(dst),
+                                        IPSTATS_MIB_INDISCARDS);
                        goto drop;
                }
        }
 
        if (!xfrm6_route_forward(skb)) {
-               IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_INDISCARDS);
+               IP6_INC_STATS_BH(net, ip6_dst_idev(dst),
+                                IPSTATS_MIB_INDISCARDS);
                goto drop;
        }
        dst = skb_dst(skb);
@@ -448,16 +450,17 @@ int ip6_forward(struct sk_buff *skb)
                /* Again, force OUTPUT device used as source address */
                skb->dev = dst->dev;
                icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
-               IP6_INC_STATS_BH(net,
-                                ip6_dst_idev(dst), IPSTATS_MIB_INTOOBIGERRORS);
-               IP6_INC_STATS_BH(net,
-                                ip6_dst_idev(dst), IPSTATS_MIB_FRAGFAILS);
+               IP6_INC_STATS_BH(net, ip6_dst_idev(dst),
+                                IPSTATS_MIB_INTOOBIGERRORS);
+               IP6_INC_STATS_BH(net, ip6_dst_idev(dst),
+                                IPSTATS_MIB_FRAGFAILS);
                kfree_skb(skb);
                return -EMSGSIZE;
        }
 
        if (skb_cow(skb, dst->dev->hard_header_len)) {
-               IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTDISCARDS);
+               IP6_INC_STATS_BH(net, ip6_dst_idev(dst),
+                                IPSTATS_MIB_OUTDISCARDS);
                goto drop;
        }
 
@@ -938,7 +941,6 @@ EXPORT_SYMBOL_GPL(ip6_dst_lookup);
  *     @sk: socket which provides route info
  *     @fl6: flow to lookup
  *     @final_dst: final destination address for ipsec lookup
- *     @can_sleep: we are in a sleepable context
  *
  *     This function performs a route lookup on the given flow.
  *
@@ -946,8 +948,7 @@ EXPORT_SYMBOL_GPL(ip6_dst_lookup);
  *     error code.
  */
 struct dst_entry *ip6_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6,
-                                     const struct in6_addr *final_dst,
-                                     bool can_sleep)
+                                     const struct in6_addr *final_dst)
 {
        struct dst_entry *dst = NULL;
        int err;
@@ -957,8 +958,6 @@ struct dst_entry *ip6_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6,
                return ERR_PTR(err);
        if (final_dst)
                fl6->daddr = *final_dst;
-       if (can_sleep)
-               fl6->flowi6_flags |= FLOWI_FLAG_CAN_SLEEP;
 
        return xfrm_lookup(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0);
 }
@@ -969,7 +968,6 @@ EXPORT_SYMBOL_GPL(ip6_dst_lookup_flow);
  *     @sk: socket which provides the dst cache and route info
  *     @fl6: flow to lookup
  *     @final_dst: final destination address for ipsec lookup
- *     @can_sleep: we are in a sleepable context
  *
  *     This function performs a route lookup on the given flow with the
  *     possibility of using the cached route in the socket if it is valid.
@@ -980,8 +978,7 @@ EXPORT_SYMBOL_GPL(ip6_dst_lookup_flow);
  *     error code.
  */
 struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6,
-                                        const struct in6_addr *final_dst,
-                                        bool can_sleep)
+                                        const struct in6_addr *final_dst)
 {
        struct dst_entry *dst = sk_dst_check(sk, inet6_sk(sk)->dst_cookie);
        int err;
@@ -993,8 +990,6 @@ struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6,
                return ERR_PTR(err);
        if (final_dst)
                fl6->daddr = *final_dst;
-       if (can_sleep)
-               fl6->flowi6_flags |= FLOWI_FLAG_CAN_SLEEP;
 
        return xfrm_lookup(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0);
 }
index d6062325db08411207fd63b435ec1e5e4e0f2001..8d7c9867a44599c590127b9faa73527fb198c8f5 100644 (file)
@@ -70,7 +70,6 @@ MODULE_ALIAS_NETDEV("ip6tnl0");
 #define IP6_TNL_TRACE(x...) do {;} while(0)
 #endif
 
-#define IPV6_TCLASS_MASK (IPV6_FLOWINFO_MASK & ~IPV6_FLOWLABEL_MASK)
 #define IPV6_TCLASS_SHIFT 20
 
 #define HASH_SIZE_SHIFT  5
@@ -1131,7 +1130,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
        if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
                fl6.flowlabel |= (*(__be32 *) ipv6h & IPV6_TCLASS_MASK);
        if (t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL)
-               fl6.flowlabel |= (*(__be32 *) ipv6h & IPV6_FLOWLABEL_MASK);
+               fl6.flowlabel |= ip6_flowlabel(ipv6h);
        if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
                fl6.flowi6_mark = skb->mark;
 
index ce507d9e1c900d3990e6025b37087309f850eaca..da9becb42e8127283f59c70731dc2890701f769e 100644 (file)
@@ -16,8 +16,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 /*
  * [Memo]
index 1c6ce3119ff8ce45f1b406c9b1356a2400f6fc1d..7d93915068565c2a56149a8de363956253e6411b 100644 (file)
@@ -1019,7 +1019,7 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
                                put_cmsg(&msg, SOL_IPV6, IPV6_HOPLIMIT, sizeof(hlim), &hlim);
                        }
                        if (np->rxopt.bits.rxtclass) {
-                               int tclass = np->rcv_tclass;
+                               int tclass = ntohl(np->rcv_flowinfo & IPV6_TCLASS_MASK) >> 20;
                                put_cmsg(&msg, SOL_IPV6, IPV6_TCLASS, sizeof(tclass), &tclass);
                        }
                        if (np->rxopt.bits.rxoinfo) {
@@ -1034,6 +1034,10 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
                                int hlim = np->mcast_hops;
                                put_cmsg(&msg, SOL_IPV6, IPV6_2292HOPLIMIT, sizeof(hlim), &hlim);
                        }
+                       if (np->rxopt.bits.rxflow) {
+                               int flowinfo = np->rcv_flowinfo;
+                               put_cmsg(&msg, SOL_IPV6, IPV6_FLOWINFO, sizeof(flowinfo), &flowinfo);
+                       }
                }
                len -= msg.msg_controllen;
                return put_user(len, optlen);
index 9ac01dc9402e9337d4b27952127d229acbb6e062..db9b6cbc9db3905695888343912be7dfd06af6f2 100644 (file)
@@ -13,8 +13,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 /*
  * Authors:
index 3512177deb4d0e7d12c6d145781802074f490615..09a22f4f36c9e069c6dfb3074909691ef2c82399 100644 (file)
@@ -125,17 +125,19 @@ struct neigh_table nd_tbl = {
        .id =           "ndisc_cache",
        .parms = {
                .tbl                    = &nd_tbl,
-               .base_reachable_time    = ND_REACHABLE_TIME,
-               .retrans_time           = ND_RETRANS_TIMER,
-               .gc_staletime           = 60 * HZ,
                .reachable_time         = ND_REACHABLE_TIME,
-               .delay_probe_time       = 5 * HZ,
-               .queue_len_bytes        = 64*1024,
-               .ucast_probes           = 3,
-               .mcast_probes           = 3,
-               .anycast_delay          = 1 * HZ,
-               .proxy_delay            = (8 * HZ) / 10,
-               .proxy_qlen             = 64,
+               .data = {
+                       [NEIGH_VAR_MCAST_PROBES] = 3,
+                       [NEIGH_VAR_UCAST_PROBES] = 3,
+                       [NEIGH_VAR_RETRANS_TIME] = ND_RETRANS_TIMER,
+                       [NEIGH_VAR_BASE_REACHABLE_TIME] = ND_REACHABLE_TIME,
+                       [NEIGH_VAR_DELAY_PROBE_TIME] = 5 * HZ,
+                       [NEIGH_VAR_GC_STALETIME] = 60 * HZ,
+                       [NEIGH_VAR_QUEUE_LEN_BYTES] = 64 * 1024,
+                       [NEIGH_VAR_PROXY_QLEN] = 64,
+                       [NEIGH_VAR_ANYCAST_DELAY] = 1 * HZ,
+                       [NEIGH_VAR_PROXY_DELAY] = (8 * HZ) / 10,
+               },
        },
        .gc_interval =    30 * HZ,
        .gc_thresh1 =    128,
@@ -656,14 +658,14 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb)
        if (skb && ipv6_chk_addr(dev_net(dev), &ipv6_hdr(skb)->saddr, dev, 1))
                saddr = &ipv6_hdr(skb)->saddr;
 
-       if ((probes -= neigh->parms->ucast_probes) < 0) {
+       if ((probes -= NEIGH_VAR(neigh->parms, UCAST_PROBES)) < 0) {
                if (!(neigh->nud_state & NUD_VALID)) {
                        ND_PRINTK(1, dbg,
                                  "%s: trying to ucast probe in NUD_INVALID: %pI6\n",
                                  __func__, target);
                }
                ndisc_send_ns(dev, neigh, target, target, saddr);
-       } else if ((probes -= neigh->parms->app_probes) < 0) {
+       } else if ((probes -= NEIGH_VAR(neigh->parms, APP_PROBES)) < 0) {
                neigh_app_ns(neigh);
        } else {
                addrconf_addr_solict_mult(target, &mcaddr);
@@ -790,7 +792,7 @@ static void ndisc_recv_ns(struct sk_buff *skb)
                        if (!(NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED) &&
                            skb->pkt_type != PACKET_HOST &&
                            inc &&
-                           idev->nd_parms->proxy_delay != 0) {
+                           NEIGH_VAR(idev->nd_parms, PROXY_DELAY) != 0) {
                                /*
                                 * for anycast or proxy,
                                 * sender should delay its response
@@ -1210,7 +1212,7 @@ skip_defrtr:
                        rtime = (rtime*HZ)/1000;
                        if (rtime < HZ/10)
                                rtime = HZ/10;
-                       in6_dev->nd_parms->retrans_time = rtime;
+                       NEIGH_VAR_SET(in6_dev->nd_parms, RETRANS_TIME, rtime);
                        in6_dev->tstamp = jiffies;
                        inet6_ifinfo_notify(RTM_NEWLINK, in6_dev);
                }
@@ -1222,9 +1224,11 @@ skip_defrtr:
                        if (rtime < HZ/10)
                                rtime = HZ/10;
 
-                       if (rtime != in6_dev->nd_parms->base_reachable_time) {
-                               in6_dev->nd_parms->base_reachable_time = rtime;
-                               in6_dev->nd_parms->gc_staletime = 3 * rtime;
+                       if (rtime != NEIGH_VAR(in6_dev->nd_parms, BASE_REACHABLE_TIME)) {
+                               NEIGH_VAR_SET(in6_dev->nd_parms,
+                                             BASE_REACHABLE_TIME, rtime);
+                               NEIGH_VAR_SET(in6_dev->nd_parms,
+                                             GC_STALETIME, 3 * rtime);
                                in6_dev->nd_parms->reachable_time = neigh_rand_reach_time(rtime);
                                in6_dev->tstamp = jiffies;
                                inet6_ifinfo_notify(RTM_NEWLINK, in6_dev);
@@ -1277,6 +1281,9 @@ skip_linkparms:
                            ri->prefix_len == 0)
                                continue;
 #endif
+                       if (ri->prefix_len == 0 &&
+                           !in6_dev->cnf.accept_ra_defrtr)
+                               continue;
                        if (ri->prefix_len > in6_dev->cnf.accept_ra_rt_info_max_plen)
                                continue;
                        rt6_route_rcv(skb->dev, (u8*)p, (p->nd_opt_len) << 3,
@@ -1648,22 +1655,23 @@ int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, void __user *bu
                ndisc_warn_deprecated_sysctl(ctl, "syscall", dev ? dev->name : "default");
 
        if (strcmp(ctl->procname, "retrans_time") == 0)
-               ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
+               ret = neigh_proc_dointvec(ctl, write, buffer, lenp, ppos);
 
        else if (strcmp(ctl->procname, "base_reachable_time") == 0)
-               ret = proc_dointvec_jiffies(ctl, write,
-                                           buffer, lenp, ppos);
+               ret = neigh_proc_dointvec_jiffies(ctl, write,
+                                                 buffer, lenp, ppos);
 
        else if ((strcmp(ctl->procname, "retrans_time_ms") == 0) ||
                 (strcmp(ctl->procname, "base_reachable_time_ms") == 0))
-               ret = proc_dointvec_ms_jiffies(ctl, write,
-                                              buffer, lenp, ppos);
+               ret = neigh_proc_dointvec_ms_jiffies(ctl, write,
+                                                    buffer, lenp, ppos);
        else
                ret = -1;
 
        if (write && ret == 0 && dev && (idev = in6_dev_get(dev)) != NULL) {
-               if (ctl->data == &idev->nd_parms->base_reachable_time)
-                       idev->nd_parms->reachable_time = neigh_rand_reach_time(idev->nd_parms->base_reachable_time);
+               if (ctl->data == &NEIGH_VAR(idev->nd_parms, BASE_REACHABLE_TIME))
+                       idev->nd_parms->reachable_time =
+                                       neigh_rand_reach_time(NEIGH_VAR(idev->nd_parms, BASE_REACHABLE_TIME));
                idev->tstamp = jiffies;
                inet6_ifinfo_notify(RTM_NEWLINK, idev);
                in6_dev_put(idev);
@@ -1722,7 +1730,7 @@ int __init ndisc_init(void)
        neigh_table_init(&nd_tbl);
 
 #ifdef CONFIG_SYSCTL
-       err = neigh_sysctl_register(NULL, &nd_tbl.parms, "ipv6",
+       err = neigh_sysctl_register(NULL, &nd_tbl.parms,
                                    &ndisc_ifinfo_sysctl_change);
        if (err)
                goto out_unregister_pernet;
index 8815e31a87fed4ba51ebd78a6724df8a3a436b85..15d23b8c2129e3c4541439e096cc084d1b238503 100644 (file)
@@ -57,7 +57,8 @@ static struct inet_protosw pingv6_protosw = {
 
 
 /* Compatibility glue so we can support IPv6 when it's compiled as a module */
-static int dummy_ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
+static int dummy_ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len,
+                                int *addr_len)
 {
        return -EAFNOSUPPORT;
 }
@@ -144,7 +145,7 @@ int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        else if (!fl6.flowi6_oif)
                fl6.flowi6_oif = np->ucast_oif;
 
-       dst = ip6_sk_dst_lookup_flow(sk, &fl6,  daddr, 1);
+       dst = ip6_sk_dst_lookup_flow(sk, &fl6,  daddr);
        if (IS_ERR(dst))
                return PTR_ERR(dst);
        rt = (struct rt6_info *) dst;
index 22d1bd4670dab741b2417051b45370b4a75b42a3..e048cf1bb6a234bb1c0eac0987d8e093a733f2f1 100644 (file)
@@ -36,10 +36,6 @@ int inet6_add_protocol(const struct inet6_protocol *prot, unsigned char protocol
 }
 EXPORT_SYMBOL(inet6_add_protocol);
 
-/*
- *     Remove a protocol from the hash tables.
- */
-
 int inet6_del_protocol(const struct inet6_protocol *prot, unsigned char protocol)
 {
        int ret;
index e24ff1df0401288e4e810cf79ec3ea20d86a06c0..5f10b7ea7ccc5cfdaae620db908de9371e8273d9 100644 (file)
@@ -466,10 +466,10 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk,
                return -EOPNOTSUPP;
 
        if (flags & MSG_ERRQUEUE)
-               return ipv6_recv_error(sk, msg, len);
+               return ipv6_recv_error(sk, msg, len, addr_len);
 
        if (np->rxpmtu && np->rxopt.bits.rxpmtu)
-               return ipv6_recv_rxpmtu(sk, msg, len);
+               return ipv6_recv_rxpmtu(sk, msg, len, addr_len);
 
        skb = skb_recv_datagram(sk, flags, noblock, &err);
        if (!skb)
@@ -792,7 +792,6 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
                                flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
                                if (flowlabel == NULL)
                                        return -EINVAL;
-                               daddr = &flowlabel->dst;
                        }
                }
 
@@ -865,7 +864,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
                fl6.flowi6_oif = np->ucast_oif;
        security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
 
-       dst = ip6_dst_lookup_flow(sk, &fl6, final_p, true);
+       dst = ip6_dst_lookup_flow(sk, &fl6, final_p);
        if (IS_ERR(dst)) {
                err = PTR_ERR(dst);
                goto out;
index 7faa9d5e15033ae45715d63a33c21150e74f8665..89b2735cecf54f49ffeda4f69f57912917bb2ec9 100644 (file)
@@ -66,8 +66,9 @@
 #endif
 
 enum rt6_nud_state {
-       RT6_NUD_FAIL_HARD = -2,
-       RT6_NUD_FAIL_SOFT = -1,
+       RT6_NUD_FAIL_HARD = -3,
+       RT6_NUD_FAIL_PROBE = -2,
+       RT6_NUD_FAIL_DO_RR = -1,
        RT6_NUD_SUCCEED = 1
 };
 
@@ -84,6 +85,8 @@ static int             ip6_dst_gc(struct dst_ops *ops);
 
 static int             ip6_pkt_discard(struct sk_buff *skb);
 static int             ip6_pkt_discard_out(struct sk_buff *skb);
+static int             ip6_pkt_prohibit(struct sk_buff *skb);
+static int             ip6_pkt_prohibit_out(struct sk_buff *skb);
 static void            ip6_link_failure(struct sk_buff *skb);
 static void            ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
                                           struct sk_buff *skb, u32 mtu);
@@ -234,9 +237,6 @@ static const struct rt6_info ip6_null_entry_template = {
 
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
 
-static int ip6_pkt_prohibit(struct sk_buff *skb);
-static int ip6_pkt_prohibit_out(struct sk_buff *skb);
-
 static const struct rt6_info ip6_prohibit_entry_template = {
        .dst = {
                .__refcnt       = ATOMIC_INIT(1),
@@ -522,7 +522,7 @@ static void rt6_probe(struct rt6_info *rt)
                work = kmalloc(sizeof(*work), GFP_ATOMIC);
 
                if (neigh && work)
-                       neigh->updated = jiffies;
+                       __neigh_set_probe_once(neigh);
 
                if (neigh)
                        write_unlock(&neigh->lock);
@@ -578,11 +578,13 @@ static inline enum rt6_nud_state rt6_check_neigh(struct rt6_info *rt)
 #ifdef CONFIG_IPV6_ROUTER_PREF
                else if (!(neigh->nud_state & NUD_FAILED))
                        ret = RT6_NUD_SUCCEED;
+               else
+                       ret = RT6_NUD_FAIL_PROBE;
 #endif
                read_unlock(&neigh->lock);
        } else {
                ret = IS_ENABLED(CONFIG_IPV6_ROUTER_PREF) ?
-                     RT6_NUD_SUCCEED : RT6_NUD_FAIL_SOFT;
+                     RT6_NUD_SUCCEED : RT6_NUD_FAIL_DO_RR;
        }
        rcu_read_unlock_bh();
 
@@ -619,16 +621,17 @@ static struct rt6_info *find_match(struct rt6_info *rt, int oif, int strict,
                goto out;
 
        m = rt6_score_route(rt, oif, strict);
-       if (m == RT6_NUD_FAIL_SOFT) {
+       if (m == RT6_NUD_FAIL_DO_RR) {
                match_do_rr = true;
                m = 0; /* lowest valid score */
-       } else if (m < 0) {
+       } else if (m == RT6_NUD_FAIL_HARD) {
                goto out;
        }
 
        if (strict & RT6_LOOKUP_F_REACHABLE)
                rt6_probe(rt);
 
+       /* note that m can be RT6_NUD_FAIL_PROBE at this point */
        if (m > *mpri) {
                *do_rr = match_do_rr;
                *mpri = m;
@@ -1565,21 +1568,24 @@ int ip6_route_add(struct fib6_config *cfg)
                                goto out;
                        }
                }
-               rt->dst.output = ip6_pkt_discard_out;
-               rt->dst.input = ip6_pkt_discard;
                rt->rt6i_flags = RTF_REJECT|RTF_NONEXTHOP;
                switch (cfg->fc_type) {
                case RTN_BLACKHOLE:
                        rt->dst.error = -EINVAL;
+                       rt->dst.output = dst_discard;
+                       rt->dst.input = dst_discard;
                        break;
                case RTN_PROHIBIT:
                        rt->dst.error = -EACCES;
+                       rt->dst.output = ip6_pkt_prohibit_out;
+                       rt->dst.input = ip6_pkt_prohibit;
                        break;
                case RTN_THROW:
-                       rt->dst.error = -EAGAIN;
-                       break;
                default:
-                       rt->dst.error = -ENETUNREACH;
+                       rt->dst.error = (cfg->fc_type == RTN_THROW) ? -EAGAIN
+                                       : -ENETUNREACH;
+                       rt->dst.output = ip6_pkt_discard_out;
+                       rt->dst.input = ip6_pkt_discard;
                        break;
                }
                goto install_route;
@@ -2144,8 +2150,6 @@ static int ip6_pkt_discard_out(struct sk_buff *skb)
        return ip6_pkt_drop(skb, ICMPV6_NOROUTE, IPSTATS_MIB_OUTNOROUTES);
 }
 
-#ifdef CONFIG_IPV6_MULTIPLE_TABLES
-
 static int ip6_pkt_prohibit(struct sk_buff *skb)
 {
        return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_INNOROUTES);
@@ -2157,8 +2161,6 @@ static int ip6_pkt_prohibit_out(struct sk_buff *skb)
        return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES);
 }
 
-#endif
-
 /*
  *     Allocate a dst for local (unicast / anycast) address.
  */
@@ -2168,12 +2170,10 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
                                    bool anycast)
 {
        struct net *net = dev_net(idev->dev);
-       struct rt6_info *rt = ip6_dst_alloc(net, net->loopback_dev, 0, NULL);
-
-       if (!rt) {
-               net_warn_ratelimited("Maximum number of routes reached, consider increasing route/max_size\n");
+       struct rt6_info *rt = ip6_dst_alloc(net, net->loopback_dev,
+                                           DST_NOCOUNT, NULL);
+       if (!rt)
                return ERR_PTR(-ENOMEM);
-       }
 
        in6_dev_hold(idev);
 
index 1b4a4a95367552c8cc22d19850b0779eee87cdc6..366fbba3359ab790e1b22917931acdbdb1daebf3 100644 (file)
@@ -478,14 +478,44 @@ static void ipip6_tunnel_uninit(struct net_device *dev)
        dev_put(dev);
 }
 
+/* Generate icmpv6 with type/code ICMPV6_DEST_UNREACH/ICMPV6_ADDR_UNREACH
+ * if sufficient data bytes are available
+ */
+static int ipip6_err_gen_icmpv6_unreach(struct sk_buff *skb)
+{
+       const struct iphdr *iph = (const struct iphdr *) skb->data;
+       struct rt6_info *rt;
+       struct sk_buff *skb2;
+
+       if (!pskb_may_pull(skb, iph->ihl * 4 + sizeof(struct ipv6hdr) + 8))
+               return 1;
+
+       skb2 = skb_clone(skb, GFP_ATOMIC);
+
+       if (!skb2)
+               return 1;
+
+       skb_dst_drop(skb2);
+       skb_pull(skb2, iph->ihl * 4);
+       skb_reset_network_header(skb2);
+
+       rt = rt6_lookup(dev_net(skb->dev), &ipv6_hdr(skb2)->saddr, NULL, 0, 0);
+
+       if (rt && rt->dst.dev)
+               skb2->dev = rt->dst.dev;
+
+       icmpv6_send(skb2, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0);
+
+       if (rt)
+               ip6_rt_put(rt);
+
+       kfree_skb(skb2);
+
+       return 0;
+}
 
 static int ipip6_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.
- */
        const struct iphdr *iph = (const struct iphdr *)skb->data;
        const int type = icmp_hdr(skb)->type;
        const int code = icmp_hdr(skb)->code;
@@ -500,7 +530,6 @@ static int ipip6_err(struct sk_buff *skb, u32 info)
        case ICMP_DEST_UNREACH:
                switch (code) {
                case ICMP_SR_FAILED:
-               case ICMP_PORT_UNREACH:
                        /* Impossible event. */
                        return 0;
                default:
@@ -545,6 +574,9 @@ static int ipip6_err(struct sk_buff *skb, u32 info)
                goto out;
 
        err = 0;
+       if (!ipip6_err_gen_icmpv6_unreach(skb))
+               goto out;
+
        if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
                goto out;
 
@@ -919,7 +951,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
                if (!new_skb) {
                        ip_rt_put(rt);
                        dev->stats.tx_dropped++;
-                       dev_kfree_skb(skb);
+                       kfree_skb(skb);
                        return NETDEV_TX_OK;
                }
                if (skb->sk)
@@ -945,7 +977,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
 tx_error_icmp:
        dst_link_failure(skb);
 tx_error:
-       dev_kfree_skb(skb);
+       kfree_skb(skb);
 out:
        dev->stats.tx_errors++;
        return NETDEV_TX_OK;
@@ -985,7 +1017,7 @@ static netdev_tx_t sit_tunnel_xmit(struct sk_buff *skb,
 
 tx_err:
        dev->stats.tx_errors++;
-       dev_kfree_skb(skb);
+       kfree_skb(skb);
        return NETDEV_TX_OK;
 
 }
index 535a3ad262f18d7dcc04586fc55c3f0e9d4afe8b..bb53a5e73c1ab67c7a11430488b8418c4edbf98b 100644 (file)
@@ -247,7 +247,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
                fl6.fl6_sport = inet_sk(sk)->inet_sport;
                security_req_classify_flow(req, flowi6_to_flowi(&fl6));
 
-               dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false);
+               dst = ip6_dst_lookup_flow(sk, &fl6, final_p);
                if (IS_ERR(dst))
                        goto out_free;
        }
index 0740f93a114a26ac09150638576f523bcd53694c..e9e59d07925e89e2fb0bd08dda8e9d0f656f86d7 100644 (file)
@@ -156,7 +156,6 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
                        flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
                        if (flowlabel == NULL)
                                return -EINVAL;
-                       usin->sin6_addr = flowlabel->dst;
                        fl6_sock_release(flowlabel);
                }
        }
@@ -258,7 +257,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
 
        security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
 
-       dst = ip6_dst_lookup_flow(sk, &fl6, final_p, true);
+       dst = ip6_dst_lookup_flow(sk, &fl6, final_p);
        if (IS_ERR(dst)) {
                err = PTR_ERR(dst);
                goto failure;
@@ -801,7 +800,7 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
         * Underlying function will use this to retrieve the network
         * namespace
         */
-       dst = ip6_dst_lookup_flow(ctl_sk, &fl6, NULL, false);
+       dst = ip6_dst_lookup_flow(ctl_sk, &fl6, NULL);
        if (!IS_ERR(dst)) {
                skb_dst_set(buff, dst);
                ip6_xmit(ctl_sk, buff, &fl6, NULL, tclass);
@@ -1135,7 +1134,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
                newnp->opt         = NULL;
                newnp->mcast_oif   = inet6_iif(skb);
                newnp->mcast_hops  = ipv6_hdr(skb)->hop_limit;
-               newnp->rcv_tclass  = ipv6_get_dsfield(ipv6_hdr(skb));
+               newnp->rcv_flowinfo = ip6_flowinfo(ipv6_hdr(skb));
 
                /*
                 * No need to charge this sock to the relevant IPv6 refcnt debug socks count
@@ -1215,7 +1214,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
        newnp->opt        = NULL;
        newnp->mcast_oif  = inet6_iif(skb);
        newnp->mcast_hops = ipv6_hdr(skb)->hop_limit;
-       newnp->rcv_tclass = ipv6_get_dsfield(ipv6_hdr(skb));
+       newnp->rcv_flowinfo = ip6_flowinfo(ipv6_hdr(skb));
 
        /* Clone native IPv6 options from listening socket (if any)
 
@@ -1425,8 +1424,8 @@ ipv6_pktoptions:
                        np->mcast_oif = inet6_iif(opt_skb);
                if (np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim)
                        np->mcast_hops = ipv6_hdr(opt_skb)->hop_limit;
-               if (np->rxopt.bits.rxtclass)
-                       np->rcv_tclass = ipv6_get_dsfield(ipv6_hdr(opt_skb));
+               if (np->rxopt.bits.rxflow || np->rxopt.bits.rxtclass)
+                       np->rcv_flowinfo = ip6_flowinfo(ipv6_hdr(opt_skb));
                if (ipv6_opt_accepted(sk, opt_skb)) {
                        skb_set_owner_r(opt_skb, sk);
                        opt_skb = xchg(&np->pktoptions, opt_skb);
index c1097c79890070e3d04517cecb7f0b263c0a4fc7..6d18157dc32c5e6fadf7798d26cdd665e18cb541 100644 (file)
@@ -37,34 +37,32 @@ static struct sk_buff **tcp6_gro_receive(struct sk_buff **head,
 {
        const struct ipv6hdr *iph = skb_gro_network_header(skb);
        __wsum wsum;
-       __sum16 sum;
+
+       /* Don't bother verifying checksum if we're going to flush anyway. */
+       if (NAPI_GRO_CB(skb)->flush)
+               goto skip_csum;
+
+       wsum = skb->csum;
 
        switch (skb->ip_summed) {
+       case CHECKSUM_NONE:
+               wsum = skb_checksum(skb, skb_gro_offset(skb), skb_gro_len(skb),
+                                   wsum);
+
+               /* fall through */
+
        case CHECKSUM_COMPLETE:
                if (!tcp_v6_check(skb_gro_len(skb), &iph->saddr, &iph->daddr,
-                                 skb->csum)) {
+                                 wsum)) {
                        skb->ip_summed = CHECKSUM_UNNECESSARY;
                        break;
                }
-flush:
+
                NAPI_GRO_CB(skb)->flush = 1;
                return NULL;
-
-       case CHECKSUM_NONE:
-               wsum = ~csum_unfold(csum_ipv6_magic(&iph->saddr, &iph->daddr,
-                                                   skb_gro_len(skb),
-                                                   IPPROTO_TCP, 0));
-               sum = csum_fold(skb_checksum(skb,
-                                            skb_gro_offset(skb),
-                                            skb_gro_len(skb),
-                                            wsum));
-               if (sum)
-                       goto flush;
-
-               skb->ip_summed = CHECKSUM_UNNECESSARY;
-               break;
        }
 
+skip_csum:
        return tcp_gro_receive(head, skb);
 }
 
index 4b0f50d9a962d9cab94e2a567d23183fe6dac441..2c4e4c5c7614bf9ee864a99e095c7c17e46d9b57 100644 (file)
@@ -12,8 +12,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * Authors     Mitsuru KANDA  <mk@linux-ipv6.org>
  *             YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
index 81eb8cf8389b6a5af55f7b2994d7dbefe3d732bf..b55e5b26d8ccc24d0f409e60e27728ceee5328f0 100644 (file)
@@ -393,10 +393,10 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk,
        bool slow;
 
        if (flags & MSG_ERRQUEUE)
-               return ipv6_recv_error(sk, msg, len);
+               return ipv6_recv_error(sk, msg, len, addr_len);
 
        if (np->rxpmtu && np->rxopt.bits.rxpmtu)
-               return ipv6_recv_rxpmtu(sk, msg, len);
+               return ipv6_recv_rxpmtu(sk, msg, len, addr_len);
 
 try_again:
        skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0),
@@ -1140,7 +1140,6 @@ do_udp_sendmsg:
                                flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
                                if (flowlabel == NULL)
                                        return -EINVAL;
-                               daddr = &flowlabel->dst;
                        }
                }
 
@@ -1221,7 +1220,7 @@ do_udp_sendmsg:
 
        security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
 
-       dst = ip6_sk_dst_lookup_flow(sk, &fl6, final_p, true);
+       dst = ip6_sk_dst_lookup_flow(sk, &fl6, final_p);
        if (IS_ERR(dst)) {
                err = PTR_ERR(dst);
                dst = NULL;
index 63d5d493098afd6b250e77b3ef15a880bd7232c7..0e015906f9ca91e11d3e9e124c532c6a7cb04c5d 100644 (file)
@@ -15,8 +15,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 /*
  * Authors:
index de2bcfaaf759c95df42effbdd24a0593247ecb1a..1c66465a42ddc09627dae47d4c6cbd40aa4fdc35 100644 (file)
@@ -12,8 +12,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * Authors     Mitsuru KANDA  <mk@linux-ipv6.org>
  *             YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
index de7db23049f141be0b6f319db136e7d1a3c5a1f1..73baf9b346b65840bf4ceecf3e8d340e30d32526 100644 (file)
@@ -25,9 +25,7 @@
  *     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
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  *     Linux-IrDA now supports four different types of IrDA sockets:
  *
index b0b56a339a835686c16f29fd7409aa2959718459..6786e7f193d298ba0a0b46ed28d4144ad9084743 100644 (file)
@@ -24,9 +24,7 @@
  *     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
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  ********************************************************************/
 
index b797daac063c2231efb0dc053bbf51301dae756d..4490a675b1bbe653117afe4fad0ee24d9dcb30f5 100644 (file)
@@ -23,9 +23,7 @@
  *     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
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  ********************************************************************/
 
index d78554fedbac5e98c32ac664bd595f1d35373fa5..b172c65223282888e90c1a45cf24383e63c33d8a 100644 (file)
@@ -22,9 +22,7 @@
  *     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
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  ********************************************************************/
 
index 3b8095c771d44371cfdb97b5607fb28817791fb8..6536114adf37a285db123efc0aa7c945d460f318 100644 (file)
@@ -24,9 +24,7 @@
  *     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
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  ********************************************************************/
 
index 30893912835926a2bbc83ce716a1fdbf242c81a4..f80b1a6a244bcadc63124d4a303adc8163b94667 100644 (file)
@@ -22,9 +22,7 @@
  *     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
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  ********************************************************************/
 
index 6e6509f22f60913296e9b8971e6304155a5f3b1c..d362d711b79c8cb36283667387e142538b1e515a 100644 (file)
@@ -23,9 +23,7 @@
  *     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
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  ********************************************************************/
 
index 41ac7938268be6ca07401bf0e9596c9e604444be..2ba8b9705bb75201715844105206ecfc3b480df7 100644 (file)
@@ -24,9 +24,7 @@
  *     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
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  ********************************************************************/
 
index a2a508f5f2684e81ea69697e3e84ff69f2fe74da..2ee87bf387cc191147ce9bb3809b6fd1e3096cc4 100644 (file)
@@ -23,9 +23,7 @@
  *     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
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  ********************************************************************/
 
index b343f50dc8d72a07b321d9e70eb33e3ed8f62443..ce943853c38d6a913e6d5a113f1a71857537fb69 100644 (file)
@@ -22,9 +22,7 @@
  *     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
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  ********************************************************************/
 
index 14653b8d664dba5d83129b98230ddfe010674111..365b895da84b5ef3565527675e4103ba05b6dffe 100644 (file)
@@ -23,9 +23,7 @@
  *     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
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  ********************************************************************/
 
index 005b424494a0bd4009fac7910cbb81f37bf5837c..a778df55f5d67123c332ce6400212cd59093bfd4 100644 (file)
@@ -23,9 +23,7 @@
  *     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
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  ********************************************************************/
 
index 71cd38c1a67fcfe241215effff78efba06be966c..6d0869716bf680f91670bfa8e48f999137bb09fe 100644 (file)
@@ -22,9 +22,7 @@
  *     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
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  ********************************************************************/
 
index 798ffd9a705ee014671248e71a213b557031ecac..11a7cc0cbc2877c7baf2105ad9dfc7880991ad98 100644 (file)
@@ -24,9 +24,7 @@
  *     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
+ *     along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  ********************************************************************/
 
index 545f047868ad86c416f68f468a31d7cc5bd07eb4..5beabd8ba77239da435ec6c60d7a0727e2630f50 100644 (file)
@@ -1380,10 +1380,9 @@ static int pfkey_acquire(struct sock *sk, struct sk_buff *skb, const struct sadb
                return 0;
 
        spin_lock_bh(&x->lock);
-       if (x->km.state == XFRM_STATE_ACQ) {
+       if (x->km.state == XFRM_STATE_ACQ)
                x->km.state = XFRM_STATE_ERROR;
-               wake_up(&net->xfrm.km_waitq);
-       }
+
        spin_unlock_bh(&x->lock);
        xfrm_state_put(x);
        return 0;
@@ -1785,7 +1784,9 @@ static int pfkey_dump_sa(struct pfkey_sock *pfk)
 
 static void pfkey_dump_sa_done(struct pfkey_sock *pfk)
 {
-       xfrm_state_walk_done(&pfk->dump.u.state);
+       struct net *net = sock_net(&pfk->sk);
+
+       xfrm_state_walk_done(&pfk->dump.u.state, net);
 }
 
 static int pfkey_dump(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
@@ -1861,7 +1862,7 @@ static u32 gen_reqid(struct net *net)
                        reqid = IPSEC_MANUAL_REQID_MAX+1;
                xfrm_policy_walk_init(&walk, XFRM_POLICY_TYPE_MAIN);
                rc = xfrm_policy_walk(net, &walk, check_reqid, (void*)&reqid);
-               xfrm_policy_walk_done(&walk);
+               xfrm_policy_walk_done(&walk, net);
                if (rc != -EEXIST)
                        return reqid;
        } while (reqid != start);
@@ -2485,6 +2486,7 @@ static int pfkey_migrate(struct sock *sk, struct sk_buff *skb,
        struct xfrm_selector sel;
        struct xfrm_migrate m[XFRM_MAX_DEPTH];
        struct xfrm_kmaddress k;
+       struct net *net = sock_net(sk);
 
        if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC - 1],
                                     ext_hdrs[SADB_EXT_ADDRESS_DST - 1]) ||
@@ -2558,7 +2560,7 @@ static int pfkey_migrate(struct sock *sk, struct sk_buff *skb,
        }
 
        return xfrm_migrate(&sel, dir, XFRM_POLICY_TYPE_MAIN, m, i,
-                           kma ? &k : NULL);
+                           kma ? &k : NULL, net);
 
  out:
        return err;
@@ -2659,7 +2661,9 @@ static int pfkey_dump_sp(struct pfkey_sock *pfk)
 
 static void pfkey_dump_sp_done(struct pfkey_sock *pfk)
 {
-       xfrm_policy_walk_done(&pfk->dump.u.policy);
+       struct net *net = sock_net((struct sock *)pfk);
+
+       xfrm_policy_walk_done(&pfk->dump.u.policy, net);
 }
 
 static int pfkey_spddump(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
@@ -3569,6 +3573,7 @@ static int pfkey_sendmsg(struct kiocb *kiocb,
        struct sk_buff *skb = NULL;
        struct sadb_msg *hdr = NULL;
        int err;
+       struct net *net = sock_net(sk);
 
        err = -EOPNOTSUPP;
        if (msg->msg_flags & MSG_OOB)
@@ -3591,9 +3596,9 @@ static int pfkey_sendmsg(struct kiocb *kiocb,
        if (!hdr)
                goto out;
 
-       mutex_lock(&xfrm_cfg_mutex);
+       mutex_lock(&net->xfrm.xfrm_cfg_mutex);
        err = pfkey_process(sk, skb, hdr);
-       mutex_unlock(&xfrm_cfg_mutex);
+       mutex_unlock(&net->xfrm.xfrm_cfg_mutex);
 
 out:
        if (err && hdr && pfkey_error(hdr, err, sk) == 0)
index cfd65304be60ae8937449a8c1e4cf77406c11305..29487a8f7fa07b8be0d95b6ec0af8011e7c332da 100644 (file)
@@ -528,7 +528,6 @@ static int l2tp_ip6_sendmsg(struct kiocb *iocb, struct sock *sk,
                                flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
                                if (flowlabel == NULL)
                                        return -EINVAL;
-                               daddr = &flowlabel->dst;
                        }
                }
 
@@ -598,7 +597,7 @@ static int l2tp_ip6_sendmsg(struct kiocb *iocb, struct sock *sk,
 
        security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
 
-       dst = ip6_dst_lookup_flow(sk, &fl6, final_p, true);
+       dst = ip6_dst_lookup_flow(sk, &fl6, final_p);
        if (IS_ERR(dst)) {
                err = PTR_ERR(dst);
                goto out;
@@ -665,7 +664,7 @@ static int l2tp_ip6_recvmsg(struct kiocb *iocb, struct sock *sk,
                *addr_len = sizeof(*lsa);
 
        if (flags & MSG_ERRQUEUE)
-               return ipv6_recv_error(sk, msg, len);
+               return ipv6_recv_error(sk, msg, len, addr_len);
 
        skb = skb_recv_datagram(sk, flags, noblock, &err);
        if (!skb)
index 95667b088c5b73cd0e95e8c1753ed76acec9dca0..f80e8c4c6bcd303762781ed8a2aa613ff763f5fa 100644 (file)
@@ -133,7 +133,9 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
                             struct key_params *params)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ieee80211_local *local = sdata->local;
        struct sta_info *sta = NULL;
+       const struct ieee80211_cipher_scheme *cs = NULL;
        struct ieee80211_key *key;
        int err;
 
@@ -145,22 +147,28 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
        case WLAN_CIPHER_SUITE_WEP40:
        case WLAN_CIPHER_SUITE_TKIP:
        case WLAN_CIPHER_SUITE_WEP104:
-               if (IS_ERR(sdata->local->wep_tx_tfm))
+               if (IS_ERR(local->wep_tx_tfm))
                        return -EINVAL;
                break;
+       case WLAN_CIPHER_SUITE_CCMP:
+       case WLAN_CIPHER_SUITE_AES_CMAC:
+       case WLAN_CIPHER_SUITE_GCMP:
+               break;
        default:
+               cs = ieee80211_cs_get(local, params->cipher, sdata->vif.type);
                break;
        }
 
        key = ieee80211_key_alloc(params->cipher, key_idx, params->key_len,
-                                 params->key, params->seq_len, params->seq);
+                                 params->key, params->seq_len, params->seq,
+                                 cs);
        if (IS_ERR(key))
                return PTR_ERR(key);
 
        if (pairwise)
                key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE;
 
-       mutex_lock(&sdata->local->sta_mtx);
+       mutex_lock(&local->sta_mtx);
 
        if (mac_addr) {
                if (ieee80211_vif_is_mesh(&sdata->vif))
@@ -216,10 +224,13 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
                break;
        }
 
+       if (sta)
+               sta->cipher_scheme = cs;
+
        err = ieee80211_key_link(key, sdata, sta);
 
  out_unlock:
-       mutex_unlock(&sdata->local->sta_mtx);
+       mutex_unlock(&local->sta_mtx);
 
        return err;
 }
@@ -244,7 +255,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
                        goto out_unlock;
 
                if (pairwise)
-                       key = key_mtx_dereference(local, sta->ptk);
+                       key = key_mtx_dereference(local, sta->ptk[key_idx]);
                else
                        key = key_mtx_dereference(local, sta->gtk[key_idx]);
        } else
@@ -291,7 +302,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
                        goto out;
 
                if (pairwise)
-                       key = rcu_dereference(sta->ptk);
+                       key = rcu_dereference(sta->ptk[key_idx]);
                else if (key_idx < NUM_DEFAULT_KEYS)
                        key = rcu_dereference(sta->gtk[key_idx]);
        } else
@@ -521,8 +532,8 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
                                 STATION_INFO_PEER_PM |
                                 STATION_INFO_NONPEER_PM;
 
-               sinfo->llid = le16_to_cpu(sta->llid);
-               sinfo->plid = le16_to_cpu(sta->plid);
+               sinfo->llid = sta->llid;
+               sinfo->plid = sta->plid;
                sinfo->plink_state = sta->plink_state;
                if (test_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN)) {
                        sinfo->filled |= STATION_INFO_T_OFFSET;
@@ -846,7 +857,7 @@ static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata,
        if (!resp || !resp_len)
                return 1;
 
-       old = rtnl_dereference(sdata->u.ap.probe_resp);
+       old = sdata_dereference(sdata->u.ap.probe_resp, sdata);
 
        new = kzalloc(sizeof(struct probe_resp) + resp_len, GFP_KERNEL);
        if (!new)
@@ -870,7 +881,8 @@ int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
        int size, err;
        u32 changed = BSS_CHANGED_BEACON;
 
-       old = rtnl_dereference(sdata->u.ap.beacon);
+       old = sdata_dereference(sdata->u.ap.beacon, sdata);
+
 
        /* Need to have a beacon head if we don't have one yet */
        if (!params->head && !old)
@@ -947,7 +959,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
                      BSS_CHANGED_P2P_PS;
        int err;
 
-       old = rtnl_dereference(sdata->u.ap.beacon);
+       old = sdata_dereference(sdata->u.ap.beacon, sdata);
        if (old)
                return -EALREADY;
 
@@ -968,11 +980,19 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
         */
        sdata->control_port_protocol = params->crypto.control_port_ethertype;
        sdata->control_port_no_encrypt = params->crypto.control_port_no_encrypt;
+       sdata->encrypt_headroom = ieee80211_cs_headroom(sdata->local,
+                                                       &params->crypto,
+                                                       sdata->vif.type);
+
        list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) {
                vlan->control_port_protocol =
                        params->crypto.control_port_ethertype;
                vlan->control_port_no_encrypt =
                        params->crypto.control_port_no_encrypt;
+               vlan->encrypt_headroom =
+                       ieee80211_cs_headroom(sdata->local,
+                                             &params->crypto,
+                                             vlan->vif.type);
        }
 
        sdata->vif.bss_conf.beacon_int = params->beacon_interval;
@@ -1001,7 +1021,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
 
        err = drv_start_ap(sdata->local, sdata);
        if (err) {
-               old = rtnl_dereference(sdata->u.ap.beacon);
+               old = sdata_dereference(sdata->u.ap.beacon, sdata);
+
                if (old)
                        kfree_rcu(old, rcu_head);
                RCU_INIT_POINTER(sdata->u.ap.beacon, NULL);
@@ -1032,7 +1053,7 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev,
        if (sdata->vif.csa_active)
                return -EBUSY;
 
-       old = rtnl_dereference(sdata->u.ap.beacon);
+       old = sdata_dereference(sdata->u.ap.beacon, sdata);
        if (!old)
                return -ENOENT;
 
@@ -1050,15 +1071,18 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
        struct ieee80211_local *local = sdata->local;
        struct beacon_data *old_beacon;
        struct probe_resp *old_probe_resp;
+       struct cfg80211_chan_def chandef;
 
-       old_beacon = rtnl_dereference(sdata->u.ap.beacon);
+       old_beacon = sdata_dereference(sdata->u.ap.beacon, sdata);
        if (!old_beacon)
                return -ENOENT;
-       old_probe_resp = rtnl_dereference(sdata->u.ap.probe_resp);
+       old_probe_resp = sdata_dereference(sdata->u.ap.probe_resp, sdata);
 
        /* abort any running channel switch */
        sdata->vif.csa_active = false;
-       cancel_work_sync(&sdata->csa_finalize_work);
+       kfree(sdata->u.ap.next_beacon);
+       sdata->u.ap.next_beacon = NULL;
+
        cancel_work_sync(&sdata->u.ap.request_smps_work);
 
        /* turn off carrier for this interface and dependent VLANs */
@@ -1091,8 +1115,10 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
        ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
 
        if (sdata->wdev.cac_started) {
+               chandef = sdata->vif.bss_conf.chandef;
                cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
-               cfg80211_cac_event(sdata->dev, NL80211_RADAR_CAC_ABORTED,
+               cfg80211_cac_event(sdata->dev, &chandef,
+                                  NL80211_RADAR_CAC_ABORTED,
                                   GFP_KERNEL);
        }
 
@@ -1368,7 +1394,7 @@ static int sta_apply_parameters(struct ieee80211_local *local,
                        changed |=
                              ieee80211_mps_set_sta_local_pm(sta,
                                                             params->local_pm);
-               ieee80211_bss_info_change_notify(sdata, changed);
+               ieee80211_mbss_info_change_notify(sdata, changed);
 #endif
        }
 
@@ -1953,7 +1979,7 @@ static int ieee80211_change_bss(struct wiphy *wiphy,
        enum ieee80211_band band;
        u32 changed = 0;
 
-       if (!rtnl_dereference(sdata->u.ap.beacon))
+       if (!sdata_dereference(sdata->u.ap.beacon, sdata))
                return -ENOENT;
 
        band = ieee80211_get_sdata_band(sdata);
@@ -2488,8 +2514,7 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
-       if (sdata->vif.type != NL80211_IFTYPE_STATION &&
-           sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
+       if (sdata->vif.type != NL80211_IFTYPE_STATION)
                return -EOPNOTSUPP;
 
        if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS))
@@ -2964,27 +2989,33 @@ void ieee80211_csa_finalize_work(struct work_struct *work)
        struct ieee80211_local *local = sdata->local;
        int err, changed = 0;
 
+       sdata_lock(sdata);
+       /* AP might have been stopped while waiting for the lock. */
+       if (!sdata->vif.csa_active)
+               goto unlock;
+
        if (!ieee80211_sdata_running(sdata))
-               return;
+               goto unlock;
 
        sdata->radar_required = sdata->csa_radar_required;
-       err = ieee80211_vif_change_channel(sdata, &local->csa_chandef,
-                                          &changed);
+       err = ieee80211_vif_change_channel(sdata, &changed);
        if (WARN_ON(err < 0))
-               return;
+               goto unlock;
 
        if (!local->use_chanctx) {
-               local->_oper_chandef = local->csa_chandef;
+               local->_oper_chandef = sdata->csa_chandef;
                ieee80211_hw_config(local, 0);
        }
 
        ieee80211_bss_info_change_notify(sdata, changed);
 
+       sdata->vif.csa_active = false;
        switch (sdata->vif.type) {
        case NL80211_IFTYPE_AP:
                err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon);
                if (err < 0)
-                       return;
+                       goto unlock;
+
                changed |= err;
                kfree(sdata->u.ap.next_beacon);
                sdata->u.ap.next_beacon = NULL;
@@ -2998,20 +3029,22 @@ void ieee80211_csa_finalize_work(struct work_struct *work)
        case NL80211_IFTYPE_MESH_POINT:
                err = ieee80211_mesh_finish_csa(sdata);
                if (err < 0)
-                       return;
+                       goto unlock;
                break;
 #endif
        default:
                WARN_ON(1);
-               return;
+               goto unlock;
        }
-       sdata->vif.csa_active = false;
 
        ieee80211_wake_queues_by_reason(&sdata->local->hw,
                                        IEEE80211_MAX_QUEUE_MAP,
                                        IEEE80211_QUEUE_STOP_REASON_CSA);
 
-       cfg80211_ch_switch_notify(sdata->dev, &local->csa_chandef);
+       cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef);
+
+unlock:
+       sdata_unlock(sdata);
 }
 
 static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
@@ -3024,6 +3057,8 @@ static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
        struct ieee80211_if_mesh __maybe_unused *ifmsh;
        int err, num_chanctx;
 
+       lockdep_assert_held(&sdata->wdev.mtx);
+
        if (!list_empty(&local->roc_list) || local->scanning)
                return -EBUSY;
 
@@ -3120,9 +3155,17 @@ static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
                    params->chandef.chan->band)
                        return -EINVAL;
 
+               ifmsh->chsw_init = true;
+               if (!ifmsh->pre_value)
+                       ifmsh->pre_value = 1;
+               else
+                       ifmsh->pre_value++;
+
                err = ieee80211_mesh_csa_beacon(sdata, params, true);
-               if (err < 0)
+               if (err < 0) {
+                       ifmsh->chsw_init = false;
                        return err;
+               }
                break;
 #endif
        default:
@@ -3136,7 +3179,7 @@ static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
                                IEEE80211_MAX_QUEUE_MAP,
                                IEEE80211_QUEUE_STOP_REASON_CSA);
 
-       local->csa_chandef = params->chandef;
+       sdata->csa_chandef = params->chandef;
        sdata->vif.csa_active = true;
 
        ieee80211_bss_info_change_notify(sdata, err);
@@ -3146,26 +3189,25 @@ static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
 }
 
 static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
-                            struct ieee80211_channel *chan, bool offchan,
-                            unsigned int wait, const u8 *buf, size_t len,
-                            bool no_cck, bool dont_wait_for_ack, u64 *cookie)
+                            struct cfg80211_mgmt_tx_params *params,
+                            u64 *cookie)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
        struct ieee80211_local *local = sdata->local;
        struct sk_buff *skb;
        struct sta_info *sta;
-       const struct ieee80211_mgmt *mgmt = (void *)buf;
+       const struct ieee80211_mgmt *mgmt = (void *)params->buf;
        bool need_offchan = false;
        u32 flags;
        int ret;
 
-       if (dont_wait_for_ack)
+       if (params->dont_wait_for_ack)
                flags = IEEE80211_TX_CTL_NO_ACK;
        else
                flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX |
                        IEEE80211_TX_CTL_REQ_TX_STATUS;
 
-       if (no_cck)
+       if (params->no_cck)
                flags |= IEEE80211_TX_CTL_NO_CCK_RATE;
 
        switch (sdata->vif.type) {
@@ -3213,7 +3255,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
        /* configurations requiring offchan cannot work if no channel has been
         * specified
         */
-       if (need_offchan && !chan)
+       if (need_offchan && !params->chan)
                return -EINVAL;
 
        mutex_lock(&local->mtx);
@@ -3226,8 +3268,10 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
                chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
 
                if (chanctx_conf) {
-                       need_offchan = chan && (chan != chanctx_conf->def.chan);
-               } else if (!chan) {
+                       need_offchan = params->chan &&
+                                      (params->chan !=
+                                       chanctx_conf->def.chan);
+               } else if (!params->chan) {
                        ret = -EINVAL;
                        rcu_read_unlock();
                        goto out_unlock;
@@ -3237,19 +3281,19 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
                rcu_read_unlock();
        }
 
-       if (need_offchan && !offchan) {
+       if (need_offchan && !params->offchan) {
                ret = -EBUSY;
                goto out_unlock;
        }
 
-       skb = dev_alloc_skb(local->hw.extra_tx_headroom + len);
+       skb = dev_alloc_skb(local->hw.extra_tx_headroom + params->len);
        if (!skb) {
                ret = -ENOMEM;
                goto out_unlock;
        }
        skb_reserve(skb, local->hw.extra_tx_headroom);
 
-       memcpy(skb_put(skb, len), buf, len);
+       memcpy(skb_put(skb, params->len), params->buf, params->len);
 
        IEEE80211_SKB_CB(skb)->flags = flags;
 
@@ -3269,8 +3313,8 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
                        local->hw.offchannel_tx_hw_queue;
 
        /* This will handle all kinds of coalescing and immediate TX */
-       ret = ieee80211_start_roc_work(local, sdata, chan,
-                                      wait, cookie, skb,
+       ret = ieee80211_start_roc_work(local, sdata, params->chan,
+                                      params->wait, cookie, skb,
                                       IEEE80211_ROC_TYPE_MGMT_TX);
        if (ret)
                kfree_skb(skb);
index 03ba6b5c5373b373d47956518fafeaf1338b2ad0..a57d5d9466bcbca1c8aa05276502ede6987783e7 100644 (file)
@@ -9,6 +9,140 @@
 #include "ieee80211_i.h"
 #include "driver-ops.h"
 
+static enum nl80211_chan_width ieee80211_get_sta_bw(struct ieee80211_sta *sta)
+{
+       switch (sta->bandwidth) {
+       case IEEE80211_STA_RX_BW_20:
+               if (sta->ht_cap.ht_supported)
+                       return NL80211_CHAN_WIDTH_20;
+               else
+                       return NL80211_CHAN_WIDTH_20_NOHT;
+       case IEEE80211_STA_RX_BW_40:
+               return NL80211_CHAN_WIDTH_40;
+       case IEEE80211_STA_RX_BW_80:
+               return NL80211_CHAN_WIDTH_80;
+       case IEEE80211_STA_RX_BW_160:
+               /*
+                * This applied for both 160 and 80+80. since we use
+                * the returned value to consider degradation of
+                * ctx->conf.min_def, we have to make sure to take
+                * the bigger one (NL80211_CHAN_WIDTH_160).
+                * Otherwise we might try degrading even when not
+                * needed, as the max required sta_bw returned (80+80)
+                * might be smaller than the configured bw (160).
+                */
+               return NL80211_CHAN_WIDTH_160;
+       default:
+               WARN_ON(1);
+               return NL80211_CHAN_WIDTH_20;
+       }
+}
+
+static enum nl80211_chan_width
+ieee80211_get_max_required_bw(struct ieee80211_sub_if_data *sdata)
+{
+       enum nl80211_chan_width max_bw = NL80211_CHAN_WIDTH_20_NOHT;
+       struct sta_info *sta;
+
+       rcu_read_lock();
+       list_for_each_entry_rcu(sta, &sdata->local->sta_list, list) {
+               if (sdata != sta->sdata &&
+                   !(sta->sdata->bss && sta->sdata->bss == sdata->bss))
+                       continue;
+
+               if (!sta->uploaded)
+                       continue;
+
+               max_bw = max(max_bw, ieee80211_get_sta_bw(&sta->sta));
+       }
+       rcu_read_unlock();
+
+       return max_bw;
+}
+
+static enum nl80211_chan_width
+ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local,
+                                     struct ieee80211_chanctx_conf *conf)
+{
+       struct ieee80211_sub_if_data *sdata;
+       enum nl80211_chan_width max_bw = NL80211_CHAN_WIDTH_20_NOHT;
+
+       rcu_read_lock();
+       list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+               struct ieee80211_vif *vif = &sdata->vif;
+               enum nl80211_chan_width width = NL80211_CHAN_WIDTH_20_NOHT;
+
+               if (!ieee80211_sdata_running(sdata))
+                       continue;
+
+               if (rcu_access_pointer(sdata->vif.chanctx_conf) != conf)
+                       continue;
+
+               switch (vif->type) {
+               case NL80211_IFTYPE_AP:
+               case NL80211_IFTYPE_AP_VLAN:
+                       width = ieee80211_get_max_required_bw(sdata);
+                       break;
+               case NL80211_IFTYPE_P2P_DEVICE:
+                       continue;
+               case NL80211_IFTYPE_STATION:
+               case NL80211_IFTYPE_ADHOC:
+               case NL80211_IFTYPE_WDS:
+               case NL80211_IFTYPE_MESH_POINT:
+                       width = vif->bss_conf.chandef.width;
+                       break;
+               case NL80211_IFTYPE_UNSPECIFIED:
+               case NUM_NL80211_IFTYPES:
+               case NL80211_IFTYPE_MONITOR:
+               case NL80211_IFTYPE_P2P_CLIENT:
+               case NL80211_IFTYPE_P2P_GO:
+                       WARN_ON_ONCE(1);
+               }
+               max_bw = max(max_bw, width);
+       }
+       rcu_read_unlock();
+
+       return max_bw;
+}
+
+/*
+ * recalc the min required chan width of the channel context, which is
+ * the max of min required widths of all the interfaces bound to this
+ * channel context.
+ */
+void ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local,
+                                     struct ieee80211_chanctx *ctx)
+{
+       enum nl80211_chan_width max_bw;
+       struct cfg80211_chan_def min_def;
+
+       lockdep_assert_held(&local->chanctx_mtx);
+
+       /* don't optimize 5MHz, 10MHz, and radar_enabled confs */
+       if (ctx->conf.def.width == NL80211_CHAN_WIDTH_5 ||
+           ctx->conf.def.width == NL80211_CHAN_WIDTH_10 ||
+           ctx->conf.radar_enabled) {
+               ctx->conf.min_def = ctx->conf.def;
+               return;
+       }
+
+       max_bw = ieee80211_get_chanctx_max_required_bw(local, &ctx->conf);
+
+       /* downgrade chandef up to max_bw */
+       min_def = ctx->conf.def;
+       while (min_def.width > max_bw)
+               ieee80211_chandef_downgrade(&min_def);
+
+       if (cfg80211_chandef_identical(&ctx->conf.min_def, &min_def))
+               return;
+
+       ctx->conf.min_def = min_def;
+       if (!ctx->driver_present)
+               return;
+
+       drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_MIN_WIDTH);
+}
+
 static void ieee80211_change_chanctx(struct ieee80211_local *local,
                                     struct ieee80211_chanctx *ctx,
                                     const struct cfg80211_chan_def *chandef)
@@ -20,6 +154,7 @@ static void ieee80211_change_chanctx(struct ieee80211_local *local,
 
        ctx->conf.def = *chandef;
        drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_WIDTH);
+       ieee80211_recalc_chanctx_min_def(local, ctx);
 
        if (!local->use_chanctx) {
                local->_oper_chandef = *chandef;
@@ -93,6 +228,7 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
        ctx->conf.rx_chains_dynamic = 1;
        ctx->mode = mode;
        ctx->conf.radar_enabled = ieee80211_is_radar_required(local);
+       ieee80211_recalc_chanctx_min_def(local, ctx);
        if (!local->use_chanctx)
                local->hw.conf.radar_enabled = ctx->conf.radar_enabled;
 
@@ -179,6 +315,7 @@ static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
        ctx->refcount++;
 
        ieee80211_recalc_txpower(sdata);
+       ieee80211_recalc_chanctx_min_def(local, ctx);
        sdata->vif.bss_conf.idle = false;
 
        if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
@@ -243,6 +380,7 @@ static void ieee80211_unassign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
                ieee80211_recalc_chanctx_chantype(sdata->local, ctx);
                ieee80211_recalc_smps_chanctx(local, ctx);
                ieee80211_recalc_radar_chanctx(local, ctx);
+               ieee80211_recalc_chanctx_min_def(local, ctx);
        }
 }
 
@@ -411,12 +549,12 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
 }
 
 int ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata,
-                                const struct cfg80211_chan_def *chandef,
                                 u32 *changed)
 {
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_chanctx_conf *conf;
        struct ieee80211_chanctx *ctx;
+       const struct cfg80211_chan_def *chandef = &sdata->csa_chandef;
        int ret;
        u32 chanctx_changed = 0;
 
@@ -456,6 +594,7 @@ int ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata,
        ieee80211_recalc_chanctx_chantype(local, ctx);
        ieee80211_recalc_smps_chanctx(local, ctx);
        ieee80211_recalc_radar_chanctx(local, ctx);
+       ieee80211_recalc_chanctx_min_def(local, ctx);
 
        ret = 0;
  out:
index 5c090e41d9bbf1ea379307c8ecd6a648cb33f0ac..fa16e54980a1d3e76ce2f85fcb3253eb2599e838 100644 (file)
 
 #define DEBUGFS_FORMAT_BUFFER_SIZE 100
 
+#define TX_LATENCY_BIN_DELIMTER_C ','
+#define TX_LATENCY_BIN_DELIMTER_S ","
+#define TX_LATENCY_BINS_DISABLED "enable(bins disabled)\n"
+#define TX_LATENCY_DISABLED "disable\n"
+
+
+/*
+ * Display if Tx latency statistics & bins are enabled/disabled
+ */
+static ssize_t sta_tx_latency_stat_read(struct file *file,
+                                       char __user *userbuf,
+                                       size_t count, loff_t *ppos)
+{
+       struct ieee80211_local *local = file->private_data;
+       struct ieee80211_tx_latency_bin_ranges  *tx_latency;
+       char *buf;
+       int bufsz, i, ret;
+       int pos = 0;
+
+       rcu_read_lock();
+
+       tx_latency = rcu_dereference(local->tx_latency);
+
+       if (tx_latency && tx_latency->n_ranges) {
+               bufsz = tx_latency->n_ranges * 15;
+               buf = kzalloc(bufsz, GFP_ATOMIC);
+               if (!buf)
+                       goto err;
+
+               for (i = 0; i < tx_latency->n_ranges; i++)
+                       pos += scnprintf(buf + pos, bufsz - pos, "%d,",
+                                        tx_latency->ranges[i]);
+               pos += scnprintf(buf + pos, bufsz - pos, "\n");
+       } else if (tx_latency) {
+               bufsz = sizeof(TX_LATENCY_BINS_DISABLED) + 1;
+               buf = kzalloc(bufsz, GFP_ATOMIC);
+               if (!buf)
+                       goto err;
+
+               pos += scnprintf(buf + pos, bufsz - pos, "%s\n",
+                                TX_LATENCY_BINS_DISABLED);
+       } else {
+               bufsz = sizeof(TX_LATENCY_DISABLED) + 1;
+               buf = kzalloc(bufsz, GFP_ATOMIC);
+               if (!buf)
+                       goto err;
+
+               pos += scnprintf(buf + pos, bufsz - pos, "%s\n",
+                                TX_LATENCY_DISABLED);
+       }
+
+       rcu_read_unlock();
+
+       ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+       kfree(buf);
+
+       return ret;
+err:
+       rcu_read_unlock();
+       return -ENOMEM;
+}
+
+/*
+ * Receive input from user regarding Tx latency statistics
+ * The input should indicate if Tx latency statistics and bins are
+ * enabled/disabled.
+ * If bins are enabled input should indicate the amount of different bins and
+ * their ranges. Each bin will count how many Tx frames transmitted within the
+ * appropriate latency.
+ * Legal input is:
+ * a) "enable(bins disabled)" - to enable only general statistics
+ * b) "a,b,c,d,...z" - to enable general statistics and bins, where all are
+ * numbers and a < b < c < d.. < z
+ * c) "disable" - disable all statistics
+ * NOTE: must configure Tx latency statistics bins before stations connected.
+ */
+
+static ssize_t sta_tx_latency_stat_write(struct file *file,
+                                        const char __user *userbuf,
+                                        size_t count, loff_t *ppos)
+{
+       struct ieee80211_local *local = file->private_data;
+       char buf[128] = {};
+       char *bins = buf;
+       char *token;
+       int buf_size, i, alloc_size;
+       int prev_bin = 0;
+       int n_ranges = 0;
+       int ret = count;
+       struct ieee80211_tx_latency_bin_ranges  *tx_latency;
+
+       if (sizeof(buf) <= count)
+               return -EINVAL;
+       buf_size = count;
+       if (copy_from_user(buf, userbuf, buf_size))
+               return -EFAULT;
+
+       mutex_lock(&local->sta_mtx);
+
+       /* cannot change config once we have stations */
+       if (local->num_sta)
+               goto unlock;
+
+       tx_latency =
+               rcu_dereference_protected(local->tx_latency,
+                                         lockdep_is_held(&local->sta_mtx));
+
+       /* disable Tx statistics */
+       if (!strcmp(buf, TX_LATENCY_DISABLED)) {
+               if (!tx_latency)
+                       goto unlock;
+               rcu_assign_pointer(local->tx_latency, NULL);
+               synchronize_rcu();
+               kfree(tx_latency);
+               goto unlock;
+       }
+
+       /* Tx latency already enabled */
+       if (tx_latency)
+               goto unlock;
+
+       if (strcmp(TX_LATENCY_BINS_DISABLED, buf)) {
+               /* check how many bins and between what ranges user requested */
+               token = buf;
+               while (*token != '\0') {
+                       if (*token == TX_LATENCY_BIN_DELIMTER_C)
+                               n_ranges++;
+                       token++;
+               }
+               n_ranges++;
+       }
+
+       alloc_size = sizeof(struct ieee80211_tx_latency_bin_ranges) +
+                    n_ranges * sizeof(u32);
+       tx_latency = kzalloc(alloc_size, GFP_ATOMIC);
+       if (!tx_latency) {
+               ret = -ENOMEM;
+               goto unlock;
+       }
+       tx_latency->n_ranges = n_ranges;
+       for (i = 0; i < n_ranges; i++) { /* setting bin ranges */
+               token = strsep(&bins, TX_LATENCY_BIN_DELIMTER_S);
+               sscanf(token, "%d", &tx_latency->ranges[i]);
+               /* bins values should be in ascending order */
+               if (prev_bin >= tx_latency->ranges[i]) {
+                       ret = -EINVAL;
+                       kfree(tx_latency);
+                       goto unlock;
+               }
+               prev_bin = tx_latency->ranges[i];
+       }
+       rcu_assign_pointer(local->tx_latency, tx_latency);
+
+unlock:
+       mutex_unlock(&local->sta_mtx);
+
+       return ret;
+}
+
+static const struct file_operations stats_tx_latency_ops = {
+       .write = sta_tx_latency_stat_write,
+       .read = sta_tx_latency_stat_read,
+       .open = simple_open,
+       .llseek = generic_file_llseek,
+};
+
 int mac80211_format_buffer(char __user *userbuf, size_t count,
                                  loff_t *ppos, char *fmt, ...)
 {
@@ -315,4 +481,6 @@ void debugfs_hw_add(struct ieee80211_local *local)
        DEBUGFS_DEVSTATS_ADD(dot11RTSFailureCount);
        DEBUGFS_DEVSTATS_ADD(dot11FCSErrorCount);
        DEBUGFS_DEVSTATS_ADD(dot11RTSSuccessCount);
+
+       DEBUGFS_DEVSTATS_ADD(tx_latency);
 }
index 19c54a44ed4793823713b717a86111d4dda0d57d..80194b557a0cff8f3d2aba52f06cfc348212abf8 100644 (file)
@@ -38,6 +38,13 @@ static const struct file_operations sta_ ##name## _ops = {           \
        .llseek = generic_file_llseek,                                  \
 }
 
+#define STA_OPS_W(name)                                                        \
+static const struct file_operations sta_ ##name## _ops = {             \
+       .write = sta_##name##_write,                                    \
+       .open = simple_open,                                            \
+       .llseek = generic_file_llseek,                                  \
+}
+
 #define STA_OPS_RW(name)                                               \
 static const struct file_operations sta_ ##name## _ops = {             \
        .read = sta_##name##_read,                                      \
@@ -388,6 +395,131 @@ static ssize_t sta_last_rx_rate_read(struct file *file, char __user *userbuf,
 }
 STA_OPS(last_rx_rate);
 
+static int
+sta_tx_latency_stat_header(struct ieee80211_tx_latency_bin_ranges *tx_latency,
+                          char *buf, int pos, int bufsz)
+{
+       int i;
+       int range_count = tx_latency->n_ranges;
+       u32 *bin_ranges = tx_latency->ranges;
+
+       pos += scnprintf(buf + pos, bufsz - pos,
+                         "Station\t\t\tTID\tMax\tAvg");
+       if (range_count) {
+               pos += scnprintf(buf + pos, bufsz - pos,
+                                 "\t<=%d", bin_ranges[0]);
+               for (i = 0; i < range_count - 1; i++)
+                       pos += scnprintf(buf + pos, bufsz - pos, "\t%d-%d",
+                                         bin_ranges[i], bin_ranges[i+1]);
+               pos += scnprintf(buf + pos, bufsz - pos,
+                                 "\t%d<", bin_ranges[range_count - 1]);
+       }
+
+       pos += scnprintf(buf + pos, bufsz - pos, "\n");
+
+       return pos;
+}
+
+static int
+sta_tx_latency_stat_table(struct ieee80211_tx_latency_bin_ranges *tx_lat_range,
+                         struct ieee80211_tx_latency_stat *tx_lat,
+                         char *buf, int pos, int bufsz, int tid)
+{
+       u32 avg = 0;
+       int j;
+       int bin_count = tx_lat->bin_count;
+
+       pos += scnprintf(buf + pos, bufsz - pos, "\t\t\t%d", tid);
+       /* make sure you don't divide in 0 */
+       if (tx_lat->counter)
+               avg = tx_lat->sum / tx_lat->counter;
+
+       pos += scnprintf(buf + pos, bufsz - pos, "\t%d\t%d",
+                         tx_lat->max, avg);
+
+       if (tx_lat_range->n_ranges && tx_lat->bins)
+               for (j = 0; j < bin_count; j++)
+                       pos += scnprintf(buf + pos, bufsz - pos,
+                                         "\t%d", tx_lat->bins[j]);
+       pos += scnprintf(buf + pos, bufsz - pos, "\n");
+
+       return pos;
+}
+
+/*
+ * Output Tx latency statistics station && restart all statistics information
+ */
+static ssize_t sta_tx_latency_stat_read(struct file *file,
+                                       char __user *userbuf,
+                                       size_t count, loff_t *ppos)
+{
+       struct sta_info *sta = file->private_data;
+       struct ieee80211_local *local = sta->local;
+       struct ieee80211_tx_latency_bin_ranges *tx_latency;
+       char *buf;
+       int bufsz, ret, i;
+       int pos = 0;
+
+       bufsz = 20 * IEEE80211_NUM_TIDS *
+               sizeof(struct ieee80211_tx_latency_stat);
+       buf = kzalloc(bufsz, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       rcu_read_lock();
+
+       tx_latency = rcu_dereference(local->tx_latency);
+
+       if (!sta->tx_lat) {
+               pos += scnprintf(buf + pos, bufsz - pos,
+                                "Tx latency statistics are not enabled\n");
+               goto unlock;
+       }
+
+       pos = sta_tx_latency_stat_header(tx_latency, buf, pos, bufsz);
+
+       pos += scnprintf(buf + pos, bufsz - pos, "%pM\n", sta->sta.addr);
+       for (i = 0; i < IEEE80211_NUM_TIDS; i++)
+               pos = sta_tx_latency_stat_table(tx_latency, &sta->tx_lat[i],
+                                               buf, pos, bufsz, i);
+unlock:
+       rcu_read_unlock();
+
+       ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+       kfree(buf);
+
+       return ret;
+}
+STA_OPS(tx_latency_stat);
+
+static ssize_t sta_tx_latency_stat_reset_write(struct file *file,
+                                              const char __user *userbuf,
+                                              size_t count, loff_t *ppos)
+{
+       u32 *bins;
+       int bin_count;
+       struct sta_info *sta = file->private_data;
+       int i;
+
+       if (!sta->tx_lat)
+               return -EINVAL;
+
+       for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
+               bins = sta->tx_lat[i].bins;
+               bin_count = sta->tx_lat[i].bin_count;
+
+               sta->tx_lat[i].max = 0;
+               sta->tx_lat[i].sum = 0;
+               sta->tx_lat[i].counter = 0;
+
+               if (bin_count)
+                       memset(bins, 0, bin_count * sizeof(u32));
+       }
+
+       return count;
+}
+STA_OPS_W(tx_latency_stat_reset);
+
 #define DEBUGFS_ADD(name) \
        debugfs_create_file(#name, 0400, \
                sta->debugfs.dir, sta, &sta_ ##name## _ops);
@@ -441,6 +573,8 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta)
        DEBUGFS_ADD(last_ack_signal);
        DEBUGFS_ADD(current_tx_rate);
        DEBUGFS_ADD(last_rx_rate);
+       DEBUGFS_ADD(tx_latency_stat);
+       DEBUGFS_ADD(tx_latency_stat_reset);
 
        DEBUGFS_ADD_COUNTER(rx_packets, rx_packets);
        DEBUGFS_ADD_COUNTER(tx_packets, tx_packets);
index 531be040b9ae85972d61bf7df248ae28308d811b..2eda7b13124abb7469a8b7b86503de07c0155623 100644 (file)
@@ -550,12 +550,12 @@ int ieee80211_ibss_finish_csa(struct ieee80211_sub_if_data *sdata)
                                        capability);
                /* XXX: should not really modify cfg80211 data */
                if (cbss) {
-                       cbss->channel = sdata->local->csa_chandef.chan;
+                       cbss->channel = sdata->csa_chandef.chan;
                        cfg80211_put_bss(sdata->local->hw.wiphy, cbss);
                }
        }
 
-       ifibss->chandef = sdata->local->csa_chandef;
+       ifibss->chandef = sdata->csa_chandef;
 
        /* generate the beacon */
        err = ieee80211_ibss_csa_beacon(sdata, NULL);
@@ -823,6 +823,10 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
        if (err)
                return false;
 
+       /* channel switch is not supported, disconnect */
+       if (!(sdata->local->hw.wiphy->flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH))
+               goto disconnect;
+
        params.count = csa_ie.count;
        params.chandef = csa_ie.chandef;
 
@@ -922,7 +926,7 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
                                IEEE80211_MAX_QUEUE_MAP,
                                IEEE80211_QUEUE_STOP_REASON_CSA);
 
-       sdata->local->csa_chandef = params.chandef;
+       sdata->csa_chandef = params.chandef;
        sdata->vif.csa_active = true;
 
        ieee80211_bss_info_change_notify(sdata, err);
index 29dc505be125c3c19737f8f6cee911492c52727c..ed5bf8b4b5c2bfb8d4253a0dbaa15b76aac309dd 100644 (file)
@@ -728,6 +728,7 @@ struct ieee80211_sub_if_data {
        u16 sequence_number;
        __be16 control_port_protocol;
        bool control_port_no_encrypt;
+       int encrypt_headroom;
 
        struct ieee80211_tx_queue_params tx_conf[IEEE80211_NUM_ACS];
 
@@ -735,6 +736,7 @@ struct ieee80211_sub_if_data {
        int csa_counter_offset_beacon;
        int csa_counter_offset_presp;
        bool csa_radar_required;
+       struct cfg80211_chan_def csa_chandef;
 
        /* used to reconfigure hardware SM PS */
        struct work_struct recalc_smps;
@@ -811,6 +813,9 @@ static inline void sdata_unlock(struct ieee80211_sub_if_data *sdata)
        __release(&sdata->wdev.mtx);
 }
 
+#define sdata_dereference(p, sdata) \
+       rcu_dereference_protected(p, lockdep_is_held(&sdata->wdev.mtx))
+
 static inline void
 sdata_assert_lock(struct ieee80211_sub_if_data *sdata)
 {
@@ -896,6 +901,24 @@ struct tpt_led_trigger {
 };
 #endif
 
+/*
+ * struct ieee80211_tx_latency_bin_ranges - Tx latency statistics bins ranges
+ *
+ * Measuring Tx latency statistics. Counts how many Tx frames transmitted in a
+ * certain latency range (in Milliseconds). Each station that uses these
+ * ranges will have bins to count the amount of frames received in that range.
+ * The user can configure the ranges via debugfs.
+ * If ranges is NULL then Tx latency statistics bins are disabled for all
+ * stations.
+ *
+ * @n_ranges: number of ranges that are taken in account
+ * @ranges: the ranges that the user requested or NULL if disabled.
+ */
+struct ieee80211_tx_latency_bin_ranges {
+       int n_ranges;
+       u32 ranges[];
+};
+
 /**
  * mac80211 scan flags - currently active scan mode
  *
@@ -1048,6 +1071,12 @@ struct ieee80211_local {
        struct timer_list sta_cleanup;
        int sta_generation;
 
+       /*
+        * Tx latency statistics parameters for all stations.
+        * Can enable via debugfs (NULL when disabled).
+        */
+       struct ieee80211_tx_latency_bin_ranges __rcu *tx_latency;
+
        struct sk_buff_head pending[IEEE80211_MAX_QUEUES];
        struct tasklet_struct tx_pending_tasklet;
 
@@ -1093,7 +1122,6 @@ struct ieee80211_local {
        enum mac80211_scan_state next_scan_state;
        struct delayed_work scan_work;
        struct ieee80211_sub_if_data __rcu *scan_sdata;
-       struct cfg80211_chan_def csa_chandef;
        /* For backward compatibility only -- do not use */
        struct cfg80211_chan_def _oper_chandef;
 
@@ -1228,6 +1256,7 @@ struct ieee80211_csa_ie {
        u8 mode;
        u8 count;
        u8 ttl;
+       u16 pre_value;
 };
 
 /* Parsed Information Elements */
@@ -1692,6 +1721,7 @@ int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata,
 int __ieee80211_request_smps_ap(struct ieee80211_sub_if_data *sdata,
                                enum ieee80211_smps_mode smps_mode);
 void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata);
+void ieee80211_recalc_min_chandef(struct ieee80211_sub_if_data *sdata);
 
 size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
                          const u8 *ids, int n_ids, size_t offset);
@@ -1730,7 +1760,6 @@ ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata,
 /* NOTE: only use ieee80211_vif_change_channel() for channel switch */
 int __must_check
 ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata,
-                            const struct cfg80211_chan_def *chandef,
                             u32 *changed);
 void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata);
 void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata);
@@ -1741,6 +1770,8 @@ void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
                                   struct ieee80211_chanctx *chanctx);
 void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local,
                                    struct ieee80211_chanctx *chanctx);
+void ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local,
+                                     struct ieee80211_chanctx *ctx);
 
 void ieee80211_dfs_cac_timer(unsigned long data);
 void ieee80211_dfs_cac_timer_work(struct work_struct *work);
@@ -1749,6 +1780,15 @@ void ieee80211_dfs_radar_detected_work(struct work_struct *work);
 int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
                              struct cfg80211_csa_settings *csa_settings);
 
+bool ieee80211_cs_valid(const struct ieee80211_cipher_scheme *cs);
+bool ieee80211_cs_list_valid(const struct ieee80211_cipher_scheme *cs, int n);
+const struct ieee80211_cipher_scheme *
+ieee80211_cs_get(struct ieee80211_local *local, u32 cipher,
+                enum nl80211_iftype iftype);
+int ieee80211_cs_headroom(struct ieee80211_local *local,
+                         struct cfg80211_crypto_settings *crypto,
+                         enum nl80211_iftype iftype);
+
 #ifdef CONFIG_MAC80211_NOINLINE
 #define debug_noinline noinline
 #else
index ff101ea1d9ae1e208deb5d6fe1d67c1677b398c2..7aa9f9dea9df0af487c25c36d52004179d76b72c 100644 (file)
@@ -401,6 +401,8 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
        snprintf(sdata->name, IFNAMSIZ, "%s-monitor",
                 wiphy_name(local->hw.wiphy));
 
+       sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
+
        ieee80211_set_default_queues(sdata);
 
        ret = drv_add_interface(local, sdata);
@@ -749,6 +751,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
        u32 hw_reconf_flags = 0;
        int i, flushed;
        struct ps_data *ps;
+       struct cfg80211_chan_def chandef;
 
        clear_bit(SDATA_STATE_RUNNING, &sdata->state);
 
@@ -823,11 +826,13 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
        cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
 
        if (sdata->wdev.cac_started) {
+               chandef = sdata->vif.bss_conf.chandef;
                WARN_ON(local->suspended);
                mutex_lock(&local->iflist_mtx);
                ieee80211_vif_release_channel(sdata);
                mutex_unlock(&local->iflist_mtx);
-               cfg80211_cac_event(sdata->dev, NL80211_RADAR_CAC_ABORTED,
+               cfg80211_cac_event(sdata->dev, &chandef,
+                                  NL80211_RADAR_CAC_ABORTED,
                                   GFP_KERNEL);
        }
 
@@ -1036,7 +1041,6 @@ static void ieee80211_set_multicast_list(struct net_device *dev)
  */
 static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata)
 {
-       int flushed;
        int i;
 
        /* free extra data */
@@ -1050,9 +1054,6 @@ static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata)
 
        if (ieee80211_vif_is_mesh(&sdata->vif))
                mesh_rmc_free(sdata);
-
-       flushed = sta_info_flush(sdata);
-       WARN_ON(flushed);
 }
 
 static void ieee80211_uninit(struct net_device *dev)
@@ -1270,6 +1271,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
 
        sdata->control_port_protocol = cpu_to_be16(ETH_P_PAE);
        sdata->control_port_no_encrypt = false;
+       sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
 
        sdata->noack_map = 0;
 
@@ -1325,7 +1327,6 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
                sdata->vif.bss_conf.bssid = NULL;
                break;
        case NL80211_IFTYPE_AP_VLAN:
-               break;
        case NL80211_IFTYPE_P2P_DEVICE:
                sdata->vif.bss_conf.bssid = sdata->vif.addr;
                break;
@@ -1686,6 +1687,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
        sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL;
        sdata->user_power_level = local->user_power_level;
 
+       sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
+
        /* setup type-dependent data */
        ieee80211_setup_sdata(sdata, type);
 
index 3e51dd7d98b34aad114e6b927beae8e4ecdde9fb..e568d98167d0244e499e53c0b2a3aad1263b1ea0 100644 (file)
@@ -260,25 +260,29 @@ static void ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
        int idx;
        bool defunikey, defmultikey, defmgmtkey;
 
+       /* caller must provide at least one old/new */
+       if (WARN_ON(!new && !old))
+               return;
+
        if (new)
                list_add_tail(&new->list, &sdata->key_list);
 
-       if (sta && pairwise) {
-               rcu_assign_pointer(sta->ptk, new);
-       } else if (sta) {
-               if (old)
-                       idx = old->conf.keyidx;
-               else
-                       idx = new->conf.keyidx;
-               rcu_assign_pointer(sta->gtk[idx], new);
-       } else {
-               WARN_ON(new && old && new->conf.keyidx != old->conf.keyidx);
+       WARN_ON(new && old && new->conf.keyidx != old->conf.keyidx);
 
-               if (old)
-                       idx = old->conf.keyidx;
-               else
-                       idx = new->conf.keyidx;
+       if (old)
+               idx = old->conf.keyidx;
+       else
+               idx = new->conf.keyidx;
 
+       if (sta) {
+               if (pairwise) {
+                       rcu_assign_pointer(sta->ptk[idx], new);
+                       sta->ptk_idx = idx;
+               } else {
+                       rcu_assign_pointer(sta->gtk[idx], new);
+                       sta->gtk_idx = idx;
+               }
+       } else {
                defunikey = old &&
                        old == key_mtx_dereference(sdata->local,
                                                sdata->default_unicast_key);
@@ -312,9 +316,11 @@ static void ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
                list_del(&old->list);
 }
 
-struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
-                                         const u8 *key_data,
-                                         size_t seq_len, const u8 *seq)
+struct ieee80211_key *
+ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
+                   const u8 *key_data,
+                   size_t seq_len, const u8 *seq,
+                   const struct ieee80211_cipher_scheme *cs)
 {
        struct ieee80211_key *key;
        int i, j, err;
@@ -393,6 +399,18 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
                        return ERR_PTR(err);
                }
                break;
+       default:
+               if (cs) {
+                       size_t len = (seq_len > MAX_PN_LEN) ?
+                                               MAX_PN_LEN : seq_len;
+
+                       key->conf.iv_len = cs->hdr_len;
+                       key->conf.icv_len = cs->mic_len;
+                       for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++)
+                               for (j = 0; j < len; j++)
+                                       key->u.gen.rx_pn[i][j] =
+                                                       seq[len - j - 1];
+               }
        }
        memcpy(key->conf.key, key_data, key_len);
        INIT_LIST_HEAD(&key->list);
@@ -475,7 +493,7 @@ int ieee80211_key_link(struct ieee80211_key *key,
        mutex_lock(&sdata->local->key_mtx);
 
        if (sta && pairwise)
-               old_key = key_mtx_dereference(sdata->local, sta->ptk);
+               old_key = key_mtx_dereference(sdata->local, sta->ptk[idx]);
        else if (sta)
                old_key = key_mtx_dereference(sdata->local, sta->gtk[idx]);
        else
@@ -625,8 +643,10 @@ void ieee80211_free_sta_keys(struct ieee80211_local *local,
                list_add(&key->list, &keys);
        }
 
-       key = key_mtx_dereference(local, sta->ptk);
-       if (key) {
+       for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
+               key = key_mtx_dereference(local, sta->ptk[i]);
+               if (!key)
+                       continue;
                ieee80211_key_replace(key->sdata, key->sta,
                                key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
                                key, NULL);
@@ -877,7 +897,7 @@ ieee80211_gtk_rekey_add(struct ieee80211_vif *vif,
 
        key = ieee80211_key_alloc(keyconf->cipher, keyconf->keyidx,
                                  keyconf->keylen, keyconf->key,
-                                 0, NULL);
+                                 0, NULL, NULL);
        if (IS_ERR(key))
                return ERR_CAST(key);
 
index aaae0ed3700402433ae56244eb97baa2804aba5b..0aebb889cabae566d6f33e00e59a2f299c9baa69 100644 (file)
@@ -18,6 +18,7 @@
 
 #define NUM_DEFAULT_KEYS 4
 #define NUM_DEFAULT_MGMT_KEYS 2
+#define MAX_PN_LEN 16
 
 struct ieee80211_local;
 struct ieee80211_sub_if_data;
@@ -93,6 +94,10 @@ struct ieee80211_key {
                        u32 replays; /* dot11RSNAStatsCMACReplays */
                        u32 icverrors; /* dot11RSNAStatsCMACICVErrors */
                } aes_cmac;
+               struct {
+                       /* generic cipher scheme */
+                       u8 rx_pn[IEEE80211_NUM_TIDS + 1][MAX_PN_LEN];
+               } gen;
        } u;
 
        /* number of times this key has been used */
@@ -113,9 +118,11 @@ struct ieee80211_key {
        struct ieee80211_key_conf conf;
 };
 
-struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
-                                         const u8 *key_data,
-                                         size_t seq_len, const u8 *seq);
+struct ieee80211_key *
+ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
+                   const u8 *key_data,
+                   size_t seq_len, const u8 *seq,
+                   const struct ieee80211_cipher_scheme *cs);
 /*
  * Insert a key into data structures (sdata, sta if necessary)
  * to make it used, free old key. On failure, also free the new key.
index 21d5d44444d04c82fc73c9fd6dee3f58ab56e512..fa34cd2344b98b9615a940a00e78363b494bc06c 100644 (file)
@@ -651,15 +651,14 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
 }
 EXPORT_SYMBOL(ieee80211_alloc_hw);
 
-int ieee80211_register_hw(struct ieee80211_hw *hw)
+static int ieee80211_init_cipher_suites(struct ieee80211_local *local)
 {
-       struct ieee80211_local *local = hw_to_local(hw);
-       int result, i;
-       enum ieee80211_band band;
-       int channels, max_bitrates;
-       bool supp_ht, supp_vht;
-       netdev_features_t feature_whitelist;
-       struct cfg80211_chan_def dflt_chandef = {};
+       bool have_wep = !(IS_ERR(local->wep_tx_tfm) ||
+                         IS_ERR(local->wep_rx_tfm));
+       bool have_mfp = local->hw.flags & IEEE80211_HW_MFP_CAPABLE;
+       const struct ieee80211_cipher_scheme *cs = local->hw.cipher_schemes;
+       int n_suites = 0, r = 0, w = 0;
+       u32 *suites;
        static const u32 cipher_suites[] = {
                /* keep WEP first, it may be removed below */
                WLAN_CIPHER_SUITE_WEP40,
@@ -671,6 +670,93 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
                WLAN_CIPHER_SUITE_AES_CMAC
        };
 
+       /* Driver specifies the ciphers, we have nothing to do... */
+       if (local->hw.wiphy->cipher_suites && have_wep)
+               return 0;
+
+       /* Set up cipher suites if driver relies on mac80211 cipher defs */
+       if (!local->hw.wiphy->cipher_suites && !cs) {
+               local->hw.wiphy->cipher_suites = cipher_suites;
+               local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
+
+               if (!have_mfp)
+                       local->hw.wiphy->n_cipher_suites--;
+
+               if (!have_wep) {
+                       local->hw.wiphy->cipher_suites += 2;
+                       local->hw.wiphy->n_cipher_suites -= 2;
+               }
+
+               return 0;
+       }
+
+       if (!local->hw.wiphy->cipher_suites) {
+               /*
+                * Driver specifies cipher schemes only
+                * We start counting ciphers defined by schemes, TKIP and CCMP
+                */
+               n_suites = local->hw.n_cipher_schemes + 2;
+
+               /* check if we have WEP40 and WEP104 */
+               if (have_wep)
+                       n_suites += 2;
+
+               /* check if we have AES_CMAC */
+               if (have_mfp)
+                       n_suites++;
+
+               suites = kmalloc(sizeof(u32) * n_suites, GFP_KERNEL);
+               if (!suites)
+                       return -ENOMEM;
+
+               suites[w++] = WLAN_CIPHER_SUITE_CCMP;
+               suites[w++] = WLAN_CIPHER_SUITE_TKIP;
+
+               if (have_wep) {
+                       suites[w++] = WLAN_CIPHER_SUITE_WEP40;
+                       suites[w++] = WLAN_CIPHER_SUITE_WEP104;
+               }
+
+               if (have_mfp)
+                       suites[w++] = WLAN_CIPHER_SUITE_AES_CMAC;
+
+               for (r = 0; r < local->hw.n_cipher_schemes; r++)
+                       suites[w++] = cs[r].cipher;
+       } else {
+               /* Driver provides cipher suites, but we need to exclude WEP */
+               suites = kmemdup(local->hw.wiphy->cipher_suites,
+                                sizeof(u32) * local->hw.wiphy->n_cipher_suites,
+                                GFP_KERNEL);
+               if (!suites)
+                       return -ENOMEM;
+
+               for (r = 0; r < local->hw.wiphy->n_cipher_suites; r++) {
+                       u32 suite = local->hw.wiphy->cipher_suites[r];
+
+                       if (suite == WLAN_CIPHER_SUITE_WEP40 ||
+                           suite == WLAN_CIPHER_SUITE_WEP104)
+                               continue;
+                       suites[w++] = suite;
+               }
+       }
+
+       local->hw.wiphy->cipher_suites = suites;
+       local->hw.wiphy->n_cipher_suites = w;
+       local->wiphy_ciphers_allocated = true;
+
+       return 0;
+}
+
+int ieee80211_register_hw(struct ieee80211_hw *hw)
+{
+       struct ieee80211_local *local = hw_to_local(hw);
+       int result, i;
+       enum ieee80211_band band;
+       int channels, max_bitrates;
+       bool supp_ht, supp_vht;
+       netdev_features_t feature_whitelist;
+       struct cfg80211_chan_def dflt_chandef = {};
+
        if (hw->flags & IEEE80211_HW_QUEUE_CONTROL &&
            (local->hw.offchannel_tx_hw_queue == IEEE80211_INVAL_HW_QUEUE ||
             local->hw.offchannel_tx_hw_queue >= local->hw.queues))
@@ -851,43 +937,12 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
        if (local->hw.wiphy->max_scan_ie_len)
                local->hw.wiphy->max_scan_ie_len -= local->scan_ies_len;
 
-       /* Set up cipher suites unless driver already did */
-       if (!local->hw.wiphy->cipher_suites) {
-               local->hw.wiphy->cipher_suites = cipher_suites;
-               local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
-               if (!(local->hw.flags & IEEE80211_HW_MFP_CAPABLE))
-                       local->hw.wiphy->n_cipher_suites--;
-       }
-       if (IS_ERR(local->wep_tx_tfm) || IS_ERR(local->wep_rx_tfm)) {
-               if (local->hw.wiphy->cipher_suites == cipher_suites) {
-                       local->hw.wiphy->cipher_suites += 2;
-                       local->hw.wiphy->n_cipher_suites -= 2;
-               } else {
-                       u32 *suites;
-                       int r, w = 0;
-
-                       /* Filter out WEP */
-
-                       suites = kmemdup(
-                               local->hw.wiphy->cipher_suites,
-                               sizeof(u32) * local->hw.wiphy->n_cipher_suites,
-                               GFP_KERNEL);
-                       if (!suites) {
-                               result = -ENOMEM;
-                               goto fail_wiphy_register;
-                       }
-                       for (r = 0; r < local->hw.wiphy->n_cipher_suites; r++) {
-                               u32 suite = local->hw.wiphy->cipher_suites[r];
-                               if (suite == WLAN_CIPHER_SUITE_WEP40 ||
-                                   suite == WLAN_CIPHER_SUITE_WEP104)
-                                       continue;
-                               suites[w++] = suite;
-                       }
-                       local->hw.wiphy->cipher_suites = suites;
-                       local->hw.wiphy->n_cipher_suites = w;
-                       local->wiphy_ciphers_allocated = true;
-               }
-       }
+       WARN_ON(!ieee80211_cs_list_valid(local->hw.cipher_schemes,
+                                        local->hw.n_cipher_schemes));
+
+       result = ieee80211_init_cipher_suites(local);
+       if (result < 0)
+               goto fail_wiphy_register;
 
        if (!local->ops->remain_on_channel)
                local->hw.wiphy->max_remain_on_channel_duration = 5000;
@@ -940,6 +995,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
                wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n",
                            result);
 
+       local->hw.conf.flags = IEEE80211_CONF_IDLE;
+
        ieee80211_led_init(local);
 
        rtnl_lock();
@@ -1047,6 +1104,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
 
        cancel_work_sync(&local->restart_work);
        cancel_work_sync(&local->reconfig_filter);
+       flush_work(&local->sched_scan_stopped_work);
 
        ieee80211_clear_tx_pending(local);
        rate_control_deinitialize(local);
@@ -1087,6 +1145,8 @@ void ieee80211_free_hw(struct ieee80211_hw *hw)
                     ieee80211_free_ack_frame, NULL);
        idr_destroy(&local->ack_status_frames);
 
+       kfree(rcu_access_pointer(local->tx_latency));
+
        wiphy_free(local->hw.wiphy);
 }
 EXPORT_SYMBOL(ieee80211_free_hw);
index 896fe3bd599e9bedd5db13dbc8ed04ab76e5bd88..89df62b2b6896f05a2d3170bce62a40fff23cf8c 100644 (file)
@@ -674,8 +674,6 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
        rcu_read_lock();
        csa = rcu_dereference(ifmsh->csa);
        if (csa) {
-               __le16 pre_value;
-
                pos = skb_put(skb, 13);
                memset(pos, 0, 13);
                *pos++ = WLAN_EID_CHANNEL_SWITCH;
@@ -697,8 +695,7 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
                          WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT : 0x00;
                put_unaligned_le16(WLAN_REASON_MESH_CHAN, pos);
                pos += 2;
-               pre_value = cpu_to_le16(ifmsh->pre_value);
-               memcpy(pos, &pre_value, 2);
+               put_unaligned_le16(ifmsh->pre_value, pos);
                pos += 2;
        }
        rcu_read_unlock();
@@ -943,14 +940,19 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
                 params.chandef.chan->center_freq);
 
        params.block_tx = csa_ie.mode & WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT;
-       if (beacon)
+       if (beacon) {
                ifmsh->chsw_ttl = csa_ie.ttl - 1;
-       else
-               ifmsh->chsw_ttl = 0;
+               if (ifmsh->pre_value >= csa_ie.pre_value)
+                       return false;
+               ifmsh->pre_value = csa_ie.pre_value;
+       }
 
-       if (ifmsh->chsw_ttl > 0)
+       if (ifmsh->chsw_ttl < ifmsh->mshcfg.dot11MeshTTL) {
                if (ieee80211_mesh_csa_beacon(sdata, &params, false) < 0)
                        return false;
+       } else {
+               return false;
+       }
 
        sdata->csa_radar_required = params.radar_required;
 
@@ -959,7 +961,7 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
                                IEEE80211_MAX_QUEUE_MAP,
                                IEEE80211_QUEUE_STOP_REASON_CSA);
 
-       sdata->local->csa_chandef = params.chandef;
+       sdata->csa_chandef = params.chandef;
        sdata->vif.csa_active = true;
 
        ieee80211_bss_info_change_notify(sdata, err);
@@ -1163,7 +1165,6 @@ static int mesh_fwd_csa_frame(struct ieee80211_sub_if_data *sdata,
        offset_ttl = (len < 42) ? 7 : 10;
        *(pos + offset_ttl) -= 1;
        *(pos + offset_ttl + 1) &= ~WLAN_EID_CHAN_SWITCH_PARAM_INITIATOR;
-       sdata->u.mesh.chsw_ttl = *(pos + offset_ttl);
 
        memcpy(mgmt_fwd, mgmt, len);
        eth_broadcast_addr(mgmt_fwd->da);
@@ -1182,7 +1183,7 @@ static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata,
        u16 pre_value;
        bool fwd_csa = true;
        size_t baselen;
-       u8 *pos, ttl;
+       u8 *pos;
 
        if (mgmt->u.action.u.measurement.action_code !=
            WLAN_ACTION_SPCT_CHL_SWITCH)
@@ -1193,8 +1194,8 @@ static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata,
                           u.action.u.chan_switch.variable);
        ieee802_11_parse_elems(pos, len - baselen, false, &elems);
 
-       ttl = elems.mesh_chansw_params_ie->mesh_ttl;
-       if (!--ttl)
+       ifmsh->chsw_ttl = elems.mesh_chansw_params_ie->mesh_ttl;
+       if (!--ifmsh->chsw_ttl)
                fwd_csa = false;
 
        pre_value = le16_to_cpu(elems.mesh_chansw_params_ie->mesh_pre_value);
index 2bc7fd2f787dd9546ac616e8c55340e1957eafb1..f39a19f9090fe0d91181b8cb4487dd928232d24b 100644 (file)
@@ -215,8 +215,6 @@ int mesh_rmc_check(struct ieee80211_sub_if_data *sdata,
 bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
                        struct ieee802_11_elems *ie);
 void mesh_ids_set_default(struct ieee80211_if_mesh *mesh);
-void mesh_mgmt_ies_add(struct ieee80211_sub_if_data *sdata,
-                      struct sk_buff *skb);
 int mesh_add_meshconf_ie(struct ieee80211_sub_if_data *sdata,
                         struct sk_buff *skb);
 int mesh_add_meshid_ie(struct ieee80211_sub_if_data *sdata,
@@ -303,8 +301,8 @@ void mesh_mpath_table_grow(void);
 void mesh_mpp_table_grow(void);
 /* Mesh paths */
 int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata,
-                      u8 ttl, const u8 *target, __le32 target_sn,
-                      __le16 target_rcode, const u8 *ra);
+                      u8 ttl, const u8 *target, u32 target_sn,
+                      u16 target_rcode, const u8 *ra);
 void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta);
 void mesh_path_flush_pending(struct mesh_path *mpath);
 void mesh_path_tx_pending(struct mesh_path *mpath);
index 486819cd02cd7d03924e30d4e93f7ac201248b4c..f9514685d45a54802cb0f21dce0953ccbe9b78f4 100644 (file)
@@ -102,12 +102,11 @@ enum mpath_frame_type {
 static const u8 broadcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 
 static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
-                                 const u8 *orig_addr, __le32 orig_sn,
+                                 const u8 *orig_addr, u32 orig_sn,
                                  u8 target_flags, const u8 *target,
-                                 __le32 target_sn, const u8 *da,
+                                 u32 target_sn, const u8 *da,
                                  u8 hop_count, u8 ttl,
-                                 __le32 lifetime, __le32 metric,
-                                 __le32 preq_id,
+                                 u32 lifetime, u32 metric, u32 preq_id,
                                  struct ieee80211_sub_if_data *sdata)
 {
        struct ieee80211_local *local = sdata->local;
@@ -167,33 +166,33 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
        if (action == MPATH_PREP) {
                memcpy(pos, target, ETH_ALEN);
                pos += ETH_ALEN;
-               memcpy(pos, &target_sn, 4);
+               put_unaligned_le32(target_sn, pos);
                pos += 4;
        } else {
                if (action == MPATH_PREQ) {
-                       memcpy(pos, &preq_id, 4);
+                       put_unaligned_le32(preq_id, pos);
                        pos += 4;
                }
                memcpy(pos, orig_addr, ETH_ALEN);
                pos += ETH_ALEN;
-               memcpy(pos, &orig_sn, 4);
+               put_unaligned_le32(orig_sn, pos);
                pos += 4;
        }
-       memcpy(pos, &lifetime, 4);      /* interval for RANN */
+       put_unaligned_le32(lifetime, pos); /* interval for RANN */
        pos += 4;
-       memcpy(pos, &metric, 4);
+       put_unaligned_le32(metric, pos);
        pos += 4;
        if (action == MPATH_PREQ) {
                *pos++ = 1; /* destination count */
                *pos++ = target_flags;
                memcpy(pos, target, ETH_ALEN);
                pos += ETH_ALEN;
-               memcpy(pos, &target_sn, 4);
+               put_unaligned_le32(target_sn, pos);
                pos += 4;
        } else if (action == MPATH_PREP) {
                memcpy(pos, orig_addr, ETH_ALEN);
                pos += ETH_ALEN;
-               memcpy(pos, &orig_sn, 4);
+               put_unaligned_le32(orig_sn, pos);
                pos += 4;
        }
 
@@ -239,8 +238,8 @@ static void prepare_frame_for_deferred_tx(struct ieee80211_sub_if_data *sdata,
  * frame directly but add it to the pending queue instead.
  */
 int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata,
-                      u8 ttl, const u8 *target, __le32 target_sn,
-                      __le16 target_rcode, const u8 *ra)
+                      u8 ttl, const u8 *target, u32 target_sn,
+                      u16 target_rcode, const u8 *ra)
 {
        struct ieee80211_local *local = sdata->local;
        struct sk_buff *skb;
@@ -254,13 +253,13 @@ int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata,
                return -EAGAIN;
 
        skb = dev_alloc_skb(local->tx_headroom +
-                           IEEE80211_ENCRYPT_HEADROOM +
+                           sdata->encrypt_headroom +
                            IEEE80211_ENCRYPT_TAILROOM +
                            hdr_len +
                            2 + 15 /* PERR IE */);
        if (!skb)
                return -1;
-       skb_reserve(skb, local->tx_headroom + IEEE80211_ENCRYPT_HEADROOM);
+       skb_reserve(skb, local->tx_headroom + sdata->encrypt_headroom);
        mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len);
        memset(mgmt, 0, hdr_len);
        mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
@@ -293,9 +292,9 @@ int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata,
        pos++;
        memcpy(pos, target, ETH_ALEN);
        pos += ETH_ALEN;
-       memcpy(pos, &target_sn, 4);
+       put_unaligned_le32(target_sn, pos);
        pos += 4;
-       memcpy(pos, &target_rcode, 2);
+       put_unaligned_le16(target_rcode, pos);
 
        /* see note in function header */
        prepare_frame_for_deferred_tx(sdata, skb);
@@ -592,10 +591,9 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
                if (ttl != 0) {
                        mhwmp_dbg(sdata, "replying to the PREQ\n");
                        mesh_path_sel_frame_tx(MPATH_PREP, 0, orig_addr,
-                               cpu_to_le32(orig_sn), 0, target_addr,
-                               cpu_to_le32(target_sn), mgmt->sa, 0, ttl,
-                               cpu_to_le32(lifetime), cpu_to_le32(metric),
-                               0, sdata);
+                                              orig_sn, 0, target_addr,
+                                              target_sn, mgmt->sa, 0, ttl,
+                                              lifetime, metric, 0, sdata);
                } else {
                        ifmsh->mshstats.dropped_frames_ttl++;
                }
@@ -625,11 +623,9 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
                }
 
                mesh_path_sel_frame_tx(MPATH_PREQ, flags, orig_addr,
-                               cpu_to_le32(orig_sn), target_flags, target_addr,
-                               cpu_to_le32(target_sn), da,
-                               hopcount, ttl, cpu_to_le32(lifetime),
-                               cpu_to_le32(metric), cpu_to_le32(preq_id),
-                               sdata);
+                                      orig_sn, target_flags, target_addr,
+                                      target_sn, da, hopcount, ttl, lifetime,
+                                      metric, preq_id, sdata);
                if (!is_multicast_ether_addr(da))
                        ifmsh->mshstats.fwded_unicast++;
                else
@@ -695,11 +691,9 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,
        target_sn = PREP_IE_TARGET_SN(prep_elem);
        orig_sn = PREP_IE_ORIG_SN(prep_elem);
 
-       mesh_path_sel_frame_tx(MPATH_PREP, flags, orig_addr,
-               cpu_to_le32(orig_sn), 0, target_addr,
-               cpu_to_le32(target_sn), next_hop, hopcount,
-               ttl, cpu_to_le32(lifetime), cpu_to_le32(metric),
-               0, sdata);
+       mesh_path_sel_frame_tx(MPATH_PREP, flags, orig_addr, orig_sn, 0,
+                              target_addr, target_sn, next_hop, hopcount,
+                              ttl, lifetime, metric, 0, sdata);
        rcu_read_unlock();
 
        sdata->u.mesh.mshstats.fwded_unicast++;
@@ -750,8 +744,7 @@ static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata,
                        if (!ifmsh->mshcfg.dot11MeshForwarding)
                                goto endperr;
                        mesh_path_error_tx(sdata, ttl, target_addr,
-                                          cpu_to_le32(target_sn),
-                                          cpu_to_le16(target_rcode),
+                                          target_sn, target_rcode,
                                           broadcast_addr);
                } else
                        spin_unlock_bh(&mpath->state_lock);
@@ -847,11 +840,9 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
 
        if (ifmsh->mshcfg.dot11MeshForwarding) {
                mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr,
-                                      cpu_to_le32(orig_sn),
-                                      0, NULL, 0, broadcast_addr,
-                                      hopcount, ttl, cpu_to_le32(interval),
-                                      cpu_to_le32(metric + metric_txsta),
-                                      0, sdata);
+                                      orig_sn, 0, NULL, 0, broadcast_addr,
+                                      hopcount, ttl, interval,
+                                      metric + metric_txsta, 0, sdata);
        }
 
        rcu_read_unlock();
@@ -1049,11 +1040,9 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata)
 
        spin_unlock_bh(&mpath->state_lock);
        da = (mpath->is_root) ? mpath->rann_snd_addr : broadcast_addr;
-       mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->vif.addr,
-                       cpu_to_le32(ifmsh->sn), target_flags, mpath->dst,
-                       cpu_to_le32(mpath->sn), da, 0,
-                       ttl, cpu_to_le32(lifetime), 0,
-                       cpu_to_le32(ifmsh->preq_id++), sdata);
+       mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->vif.addr, ifmsh->sn,
+                              target_flags, mpath->dst, mpath->sn, da, 0,
+                              ttl, lifetime, 0, ifmsh->preq_id++, sdata);
        mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout);
 
 enddiscovery:
@@ -1212,10 +1201,9 @@ void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata)
        switch (ifmsh->mshcfg.dot11MeshHWMPRootMode) {
        case IEEE80211_PROACTIVE_RANN:
                mesh_path_sel_frame_tx(MPATH_RANN, flags, sdata->vif.addr,
-                              cpu_to_le32(++ifmsh->sn),
-                              0, NULL, 0, broadcast_addr,
-                              0, ifmsh->mshcfg.element_ttl,
-                              cpu_to_le32(interval), 0, 0, sdata);
+                                      ++ifmsh->sn, 0, NULL, 0, broadcast_addr,
+                                      0, ifmsh->mshcfg.element_ttl,
+                                      interval, 0, 0, sdata);
                break;
        case IEEE80211_PROACTIVE_PREQ_WITH_PREP:
                flags |= IEEE80211_PREQ_PROACTIVE_PREP_FLAG;
@@ -1224,11 +1212,10 @@ void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata)
                target_flags |= IEEE80211_PREQ_TO_FLAG |
                                IEEE80211_PREQ_USN_FLAG;
                mesh_path_sel_frame_tx(MPATH_PREQ, flags, sdata->vif.addr,
-                               cpu_to_le32(++ifmsh->sn), target_flags,
-                               (u8 *) broadcast_addr, 0, broadcast_addr,
-                               0, ifmsh->mshcfg.element_ttl,
-                               cpu_to_le32(interval),
-                               0, cpu_to_le32(ifmsh->preq_id++), sdata);
+                                      ++ifmsh->sn, target_flags,
+                                      (u8 *) broadcast_addr, 0, broadcast_addr,
+                                      0, ifmsh->mshcfg.element_ttl, interval,
+                                      0, ifmsh->preq_id++, sdata);
                break;
        default:
                mhwmp_dbg(sdata, "Proactive mechanism not supported\n");
index 89aacfd2756d627287ce4d381e7038d0b0ebdd5e..7d050ed6fe5a4ec879bc9711c088db8360154448 100644 (file)
@@ -722,7 +722,6 @@ void mesh_plink_broken(struct sta_info *sta)
        struct mpath_node *node;
        struct ieee80211_sub_if_data *sdata = sta->sdata;
        int i;
-       __le16 reason = cpu_to_le16(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
 
        rcu_read_lock();
        tbl = rcu_dereference(mesh_paths);
@@ -736,9 +735,9 @@ void mesh_plink_broken(struct sta_info *sta)
                        ++mpath->sn;
                        spin_unlock_bh(&mpath->state_lock);
                        mesh_path_error_tx(sdata,
-                                          sdata->u.mesh.mshcfg.element_ttl,
-                                          mpath->dst, cpu_to_le32(mpath->sn),
-                                          reason, bcast);
+                               sdata->u.mesh.mshcfg.element_ttl,
+                               mpath->dst, mpath->sn,
+                               WLAN_REASON_MESH_PATH_DEST_UNREACHABLE, bcast);
                }
        }
        rcu_read_unlock();
index 4301aa5aa227c3d539cd0bf89bdf5b004679976a..cf83217103f9c91479cd4f3f1b97a2752af0c897 100644 (file)
 #define mod_plink_timer(s, t) (mod_timer(&s->plink_timer, \
                                jiffies + HZ * t / 1000))
 
-/* We only need a valid sta if user configured a minimum rssi_threshold. */
-#define rssi_threshold_check(sta, sdata) \
-               (sdata->u.mesh.mshcfg.rssi_threshold == 0 ||\
-               (sta && (s8) -ewma_read(&sta->avg_signal) > \
-               sdata->u.mesh.mshcfg.rssi_threshold))
-
 enum plink_event {
        PLINK_UNDEFINED,
        OPN_ACPT,
@@ -61,7 +55,17 @@ static const char * const mplevents[] = {
 
 static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
                               enum ieee80211_self_protected_actioncode action,
-                              u8 *da, __le16 llid, __le16 plid, __le16 reason);
+                              u8 *da, u16 llid, u16 plid, u16 reason);
+
+
+/* We only need a valid sta if user configured a minimum rssi_threshold. */
+static bool rssi_threshold_check(struct ieee80211_sub_if_data *sdata,
+                                struct sta_info *sta)
+{
+       s32 rssi_threshold = sdata->u.mesh.mshcfg.rssi_threshold;
+       return rssi_threshold == 0 ||
+              (sta && (s8) -ewma_read(&sta->avg_signal) > rssi_threshold);
+}
 
 /**
  * mesh_plink_fsm_restart - restart a mesh peer link finite state machine
@@ -242,7 +246,7 @@ u32 mesh_plink_deactivate(struct sta_info *sta)
 
        spin_lock_bh(&sta->lock);
        changed = __mesh_plink_deactivate(sta);
-       sta->reason = cpu_to_le16(WLAN_REASON_MESH_PEER_CANCELED);
+       sta->reason = WLAN_REASON_MESH_PEER_CANCELED;
        mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
                            sta->sta.addr, sta->llid, sta->plid,
                            sta->reason);
@@ -253,7 +257,7 @@ u32 mesh_plink_deactivate(struct sta_info *sta)
 
 static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
                               enum ieee80211_self_protected_actioncode action,
-                              u8 *da, __le16 llid, __le16 plid, __le16 reason)
+                              u8 *da, u16 llid, u16 plid, u16 reason)
 {
        struct ieee80211_local *local = sdata->local;
        struct sk_buff *skb;
@@ -279,7 +283,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
                            2 + 8 + /* peering IE */
                            sdata->u.mesh.ie_len);
        if (!skb)
-               return -1;
+               return err;
        info = IEEE80211_SKB_CB(skb);
        skb_reserve(skb, local->tx_headroom);
        mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len);
@@ -301,7 +305,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
                if (action == WLAN_SP_MESH_PEERING_CONFIRM) {
                        /* AID */
                        pos = skb_put(skb, 2);
-                       memcpy(pos + 2, &plid, 2);
+                       put_unaligned_le16(plid, pos + 2);
                }
                if (ieee80211_add_srates_ie(sdata, skb, true, band) ||
                    ieee80211_add_ext_srates_ie(sdata, skb, true, band) ||
@@ -343,14 +347,14 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
        *pos++ = ie_len;
        memcpy(pos, &peering_proto, 2);
        pos += 2;
-       memcpy(pos, &llid, 2);
+       put_unaligned_le16(llid, pos);
        pos += 2;
        if (include_plid) {
-               memcpy(pos, &plid, 2);
+               put_unaligned_le16(plid, pos);
                pos += 2;
        }
        if (action == WLAN_SP_MESH_PEERING_CLOSE) {
-               memcpy(pos, &reason, 2);
+               put_unaligned_le16(reason, pos);
                pos += 2;
        }
 
@@ -518,7 +522,7 @@ void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata,
            sta->plink_state == NL80211_PLINK_LISTEN &&
            sdata->u.mesh.accepting_plinks &&
            sdata->u.mesh.mshcfg.auto_open_plinks &&
-           rssi_threshold_check(sta, sdata))
+           rssi_threshold_check(sdata, sta))
                changed = mesh_plink_open(sta);
 
        ieee80211_mps_frame_release(sta, elems);
@@ -530,9 +534,10 @@ out:
 static void mesh_plink_timer(unsigned long data)
 {
        struct sta_info *sta;
-       __le16 llid, plid, reason;
+       u16 reason = 0;
        struct ieee80211_sub_if_data *sdata;
        struct mesh_config *mshcfg;
+       enum ieee80211_self_protected_actioncode action = 0;
 
        /*
         * This STA is valid because sta_info_destroy() will
@@ -553,9 +558,6 @@ static void mesh_plink_timer(unsigned long data)
        mpl_dbg(sta->sdata,
                "Mesh plink timer for %pM fired on state %s\n",
                sta->sta.addr, mplstates[sta->plink_state]);
-       reason = 0;
-       llid = sta->llid;
-       plid = sta->plid;
        sdata = sta->sdata;
        mshcfg = &sdata->u.mesh.mshcfg;
 
@@ -574,33 +576,31 @@ static void mesh_plink_timer(unsigned long data)
                                             rand % sta->plink_timeout;
                        ++sta->plink_retries;
                        mod_plink_timer(sta, sta->plink_timeout);
-                       spin_unlock_bh(&sta->lock);
-                       mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN,
-                                           sta->sta.addr, llid, 0, 0);
+                       action = WLAN_SP_MESH_PEERING_OPEN;
                        break;
                }
-               reason = cpu_to_le16(WLAN_REASON_MESH_MAX_RETRIES);
+               reason = WLAN_REASON_MESH_MAX_RETRIES;
                /* fall through on else */
        case NL80211_PLINK_CNF_RCVD:
                /* confirm timer */
                if (!reason)
-                       reason = cpu_to_le16(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
+                       reason = WLAN_REASON_MESH_CONFIRM_TIMEOUT;
                sta->plink_state = NL80211_PLINK_HOLDING;
                mod_plink_timer(sta, mshcfg->dot11MeshHoldingTimeout);
-               spin_unlock_bh(&sta->lock);
-               mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
-                                   sta->sta.addr, llid, plid, reason);
+               action = WLAN_SP_MESH_PEERING_CLOSE;
                break;
        case NL80211_PLINK_HOLDING:
                /* holding timer */
                del_timer(&sta->plink_timer);
                mesh_plink_fsm_restart(sta);
-               spin_unlock_bh(&sta->lock);
                break;
        default:
-               spin_unlock_bh(&sta->lock);
                break;
        }
+       spin_unlock_bh(&sta->lock);
+       if (action)
+               mesh_plink_frame_tx(sdata, action, sta->sta.addr,
+                                   sta->llid, sta->plid, reason);
 }
 
 static inline void mesh_plink_timer_set(struct sta_info *sta, int timeout)
@@ -612,9 +612,40 @@ static inline void mesh_plink_timer_set(struct sta_info *sta, int timeout)
        add_timer(&sta->plink_timer);
 }
 
+static bool llid_in_use(struct ieee80211_sub_if_data *sdata,
+                       u16 llid)
+{
+       struct ieee80211_local *local = sdata->local;
+       bool in_use = false;
+       struct sta_info *sta;
+
+       rcu_read_lock();
+       list_for_each_entry_rcu(sta, &local->sta_list, list) {
+               if (!memcmp(&sta->llid, &llid, sizeof(llid))) {
+                       in_use = true;
+                       break;
+               }
+       }
+       rcu_read_unlock();
+
+       return in_use;
+}
+
+static u16 mesh_get_new_llid(struct ieee80211_sub_if_data *sdata)
+{
+       u16 llid;
+
+       do {
+               get_random_bytes(&llid, sizeof(llid));
+               /* for mesh PS we still only have the AID range for TIM bits */
+               llid = (llid % IEEE80211_MAX_AID) + 1;
+       } while (llid_in_use(sdata, llid));
+
+       return llid;
+}
+
 u32 mesh_plink_open(struct sta_info *sta)
 {
-       __le16 llid;
        struct ieee80211_sub_if_data *sdata = sta->sdata;
        u32 changed;
 
@@ -622,8 +653,7 @@ u32 mesh_plink_open(struct sta_info *sta)
                return 0;
 
        spin_lock_bh(&sta->lock);
-       get_random_bytes(&llid, 2);
-       sta->llid = llid;
+       sta->llid = mesh_get_new_llid(sdata);
        if (sta->plink_state != NL80211_PLINK_LISTEN &&
            sta->plink_state != NL80211_PLINK_BLOCKED) {
                spin_unlock_bh(&sta->lock);
@@ -640,7 +670,7 @@ u32 mesh_plink_open(struct sta_info *sta)
        changed = ieee80211_mps_local_status_update(sdata);
 
        mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN,
-                           sta->sta.addr, llid, 0, 0);
+                           sta->sta.addr, sta->llid, 0, 0);
        return changed;
 }
 
@@ -656,390 +686,147 @@ u32 mesh_plink_block(struct sta_info *sta)
        return changed;
 }
 
-
-void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
-                        struct ieee80211_mgmt *mgmt, size_t len,
-                        struct ieee80211_rx_status *rx_status)
+static void mesh_plink_close(struct ieee80211_sub_if_data *sdata,
+                            struct sta_info *sta,
+                            enum plink_event event)
 {
        struct mesh_config *mshcfg = &sdata->u.mesh.mshcfg;
-       struct ieee802_11_elems elems;
-       struct sta_info *sta;
-       enum plink_event event;
-       enum ieee80211_self_protected_actioncode ftype;
-       size_t baselen;
-       bool matches_local = true;
-       u8 ie_len;
-       u8 *baseaddr;
-       u32 changed = 0;
-       __le16 plid, llid, reason;
-
-       /* need action_code, aux */
-       if (len < IEEE80211_MIN_ACTION_SIZE + 3)
-               return;
-
-       if (sdata->u.mesh.user_mpm)
-               /* userspace must register for these */
-               return;
-
-       if (is_multicast_ether_addr(mgmt->da)) {
-               mpl_dbg(sdata,
-                       "Mesh plink: ignore frame from multicast address\n");
-               return;
-       }
-
-       baseaddr = mgmt->u.action.u.self_prot.variable;
-       baselen = (u8 *) mgmt->u.action.u.self_prot.variable - (u8 *) mgmt;
-       if (mgmt->u.action.u.self_prot.action_code ==
-                                               WLAN_SP_MESH_PEERING_CONFIRM) {
-               baseaddr += 4;
-               baselen += 4;
-       }
-       ieee802_11_parse_elems(baseaddr, len - baselen, true, &elems);
-
-       if (!elems.peering) {
-               mpl_dbg(sdata,
-                       "Mesh plink: missing necessary peer link ie\n");
-               return;
-       }
 
-       if (elems.rsn_len &&
-           sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) {
-               mpl_dbg(sdata,
-                       "Mesh plink: can't establish link with secure peer\n");
-               return;
-       }
+       u16 reason = (event == CLS_ACPT) ?
+                    WLAN_REASON_MESH_CLOSE : WLAN_REASON_MESH_CONFIG;
 
-       ftype = mgmt->u.action.u.self_prot.action_code;
-       ie_len = elems.peering_len;
-       if ((ftype == WLAN_SP_MESH_PEERING_OPEN && ie_len != 4) ||
-           (ftype == WLAN_SP_MESH_PEERING_CONFIRM && ie_len != 6) ||
-           (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len != 6
-                                                       && ie_len != 8)) {
-               mpl_dbg(sdata,
-                       "Mesh plink: incorrect plink ie length %d %d\n",
-                       ftype, ie_len);
-               return;
-       }
-
-       if (ftype != WLAN_SP_MESH_PEERING_CLOSE &&
-           (!elems.mesh_id || !elems.mesh_config)) {
-               mpl_dbg(sdata, "Mesh plink: missing necessary ie\n");
-               return;
-       }
-       /* Note the lines below are correct, the llid in the frame is the plid
-        * from the point of view of this host.
-        */
-       memcpy(&plid, PLINK_GET_LLID(elems.peering), 2);
-       if (ftype == WLAN_SP_MESH_PEERING_CONFIRM ||
-           (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len == 8))
-               memcpy(&llid, PLINK_GET_PLID(elems.peering), 2);
-
-       /* WARNING: Only for sta pointer, is dropped & re-acquired */
-       rcu_read_lock();
-
-       sta = sta_info_get(sdata, mgmt->sa);
-       if (!sta && ftype != WLAN_SP_MESH_PEERING_OPEN) {
-               mpl_dbg(sdata, "Mesh plink: cls or cnf from unknown peer\n");
-               rcu_read_unlock();
-               return;
-       }
-
-       if (ftype == WLAN_SP_MESH_PEERING_OPEN &&
-           !rssi_threshold_check(sta, sdata)) {
-               mpl_dbg(sdata, "Mesh plink: %pM does not meet rssi threshold\n",
-                       mgmt->sa);
-               rcu_read_unlock();
-               return;
-       }
-
-       if (sta && !test_sta_flag(sta, WLAN_STA_AUTH)) {
-               mpl_dbg(sdata, "Mesh plink: Action frame from non-authed peer\n");
-               rcu_read_unlock();
-               return;
-       }
+       sta->reason = reason;
+       sta->plink_state = NL80211_PLINK_HOLDING;
+       mod_plink_timer(sta, mshcfg->dot11MeshHoldingTimeout);
+}
 
-       if (sta && sta->plink_state == NL80211_PLINK_BLOCKED) {
-               rcu_read_unlock();
-               return;
-       }
+static u32 mesh_plink_establish(struct ieee80211_sub_if_data *sdata,
+                               struct sta_info *sta)
+{
+       struct mesh_config *mshcfg = &sdata->u.mesh.mshcfg;
+       u32 changed = 0;
 
-       /* Now we will figure out the appropriate event... */
-       event = PLINK_UNDEFINED;
-       if (ftype != WLAN_SP_MESH_PEERING_CLOSE &&
-           !mesh_matches_local(sdata, &elems)) {
-               matches_local = false;
-               switch (ftype) {
-               case WLAN_SP_MESH_PEERING_OPEN:
-                       event = OPN_RJCT;
-                       break;
-               case WLAN_SP_MESH_PEERING_CONFIRM:
-                       event = CNF_RJCT;
-                       break;
-               default:
-                       break;
-               }
-       }
+       del_timer(&sta->plink_timer);
+       sta->plink_state = NL80211_PLINK_ESTAB;
+       changed |= mesh_plink_inc_estab_count(sdata);
+       changed |= mesh_set_ht_prot_mode(sdata);
+       changed |= mesh_set_short_slot_time(sdata);
+       mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n", sta->sta.addr);
+       ieee80211_mps_sta_status_update(sta);
+       changed |= ieee80211_mps_set_sta_local_pm(sta, mshcfg->power_mode);
+       return changed;
+}
 
-       if (!sta && !matches_local) {
-               rcu_read_unlock();
-               reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);
-               llid = 0;
-               mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
-                                   mgmt->sa, llid, plid, reason);
-               return;
-       } else if (!sta) {
-               /* ftype == WLAN_SP_MESH_PEERING_OPEN */
-               if (!mesh_plink_free_count(sdata)) {
-                       mpl_dbg(sdata, "Mesh plink error: no more free plinks\n");
-                       rcu_read_unlock();
-                       return;
-               }
-               event = OPN_ACPT;
-       } else if (matches_local) {
-               switch (ftype) {
-               case WLAN_SP_MESH_PEERING_OPEN:
-                       if (!mesh_plink_free_count(sdata) ||
-                           (sta->plid && sta->plid != plid))
-                               event = OPN_IGNR;
-                       else
-                               event = OPN_ACPT;
-                       break;
-               case WLAN_SP_MESH_PEERING_CONFIRM:
-                       if (!mesh_plink_free_count(sdata) ||
-                           (sta->llid != llid || sta->plid != plid))
-                               event = CNF_IGNR;
-                       else
-                               event = CNF_ACPT;
-                       break;
-               case WLAN_SP_MESH_PEERING_CLOSE:
-                       if (sta->plink_state == NL80211_PLINK_ESTAB)
-                               /* Do not check for llid or plid. This does not
-                                * follow the standard but since multiple plinks
-                                * per sta are not supported, it is necessary in
-                                * order to avoid a livelock when MP A sees an
-                                * establish peer link to MP B but MP B does not
-                                * see it. This can be caused by a timeout in
-                                * B's peer link establishment or B beign
-                                * restarted.
-                                */
-                               event = CLS_ACPT;
-                       else if (sta->plid != plid)
-                               event = CLS_IGNR;
-                       else if (ie_len == 7 && sta->llid != llid)
-                               event = CLS_IGNR;
-                       else
-                               event = CLS_ACPT;
-                       break;
-               default:
-                       mpl_dbg(sdata, "Mesh plink: unknown frame subtype\n");
-                       rcu_read_unlock();
-                       return;
-               }
-       }
+/**
+ * mesh_plink_fsm - step @sta MPM based on @event
+ *
+ * @sdata: interface
+ * @sta: mesh neighbor
+ * @event: peering event
+ *
+ * Return: changed MBSS flags
+ */
+static u32 mesh_plink_fsm(struct ieee80211_sub_if_data *sdata,
+                         struct sta_info *sta, enum plink_event event)
+{
+       struct mesh_config *mshcfg = &sdata->u.mesh.mshcfg;
+       enum ieee80211_self_protected_actioncode action = 0;
+       u32 changed = 0;
 
-       if (event == OPN_ACPT) {
-               rcu_read_unlock();
-               /* allocate sta entry if necessary and update info */
-               sta = mesh_sta_info_get(sdata, mgmt->sa, &elems);
-               if (!sta) {
-                       mpl_dbg(sdata, "Mesh plink: failed to init peer!\n");
-                       rcu_read_unlock();
-                       return;
-               }
-       }
+       mpl_dbg(sdata, "peer %pM in state %s got event %s\n", sta->sta.addr,
+               mplstates[sta->plink_state], mplevents[event]);
 
-       mpl_dbg(sdata, "peer %pM in state %s got event %s\n", mgmt->sa,
-                      mplstates[sta->plink_state], mplevents[event]);
-       reason = 0;
        spin_lock_bh(&sta->lock);
        switch (sta->plink_state) {
-               /* spin_unlock as soon as state is updated at each case */
        case NL80211_PLINK_LISTEN:
                switch (event) {
                case CLS_ACPT:
                        mesh_plink_fsm_restart(sta);
-                       spin_unlock_bh(&sta->lock);
                        break;
                case OPN_ACPT:
                        sta->plink_state = NL80211_PLINK_OPN_RCVD;
-                       sta->plid = plid;
-                       get_random_bytes(&llid, 2);
-                       sta->llid = llid;
+                       sta->llid = mesh_get_new_llid(sdata);
                        mesh_plink_timer_set(sta,
                                             mshcfg->dot11MeshRetryTimeout);
 
                        /* set the non-peer mode to active during peering */
                        changed |= ieee80211_mps_local_status_update(sdata);
-
-                       spin_unlock_bh(&sta->lock);
-                       mesh_plink_frame_tx(sdata,
-                                           WLAN_SP_MESH_PEERING_OPEN,
-                                           sta->sta.addr, llid, 0, 0);
-                       mesh_plink_frame_tx(sdata,
-                                           WLAN_SP_MESH_PEERING_CONFIRM,
-                                           sta->sta.addr, llid, plid, 0);
+                       action = WLAN_SP_MESH_PEERING_OPEN;
                        break;
                default:
-                       spin_unlock_bh(&sta->lock);
                        break;
                }
                break;
-
        case NL80211_PLINK_OPN_SNT:
                switch (event) {
                case OPN_RJCT:
                case CNF_RJCT:
-                       reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);
                case CLS_ACPT:
-                       if (!reason)
-                               reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
-                       sta->reason = reason;
-                       sta->plink_state = NL80211_PLINK_HOLDING;
-                       if (!mod_plink_timer(sta,
-                                            mshcfg->dot11MeshHoldingTimeout))
-                               sta->ignore_plink_timer = true;
-
-                       llid = sta->llid;
-                       spin_unlock_bh(&sta->lock);
-                       mesh_plink_frame_tx(sdata,
-                                           WLAN_SP_MESH_PEERING_CLOSE,
-                                           sta->sta.addr, llid, plid, reason);
+                       mesh_plink_close(sdata, sta, event);
+                       action = WLAN_SP_MESH_PEERING_CLOSE;
                        break;
                case OPN_ACPT:
                        /* retry timer is left untouched */
                        sta->plink_state = NL80211_PLINK_OPN_RCVD;
-                       sta->plid = plid;
-                       llid = sta->llid;
-                       spin_unlock_bh(&sta->lock);
-                       mesh_plink_frame_tx(sdata,
-                                           WLAN_SP_MESH_PEERING_CONFIRM,
-                                           sta->sta.addr, llid, plid, 0);
+                       action = WLAN_SP_MESH_PEERING_CONFIRM;
                        break;
                case CNF_ACPT:
                        sta->plink_state = NL80211_PLINK_CNF_RCVD;
                        if (!mod_plink_timer(sta,
                                             mshcfg->dot11MeshConfirmTimeout))
                                sta->ignore_plink_timer = true;
-
-                       spin_unlock_bh(&sta->lock);
                        break;
                default:
-                       spin_unlock_bh(&sta->lock);
                        break;
                }
                break;
-
        case NL80211_PLINK_OPN_RCVD:
                switch (event) {
                case OPN_RJCT:
                case CNF_RJCT:
-                       reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);
                case CLS_ACPT:
-                       if (!reason)
-                               reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
-                       sta->reason = reason;
-                       sta->plink_state = NL80211_PLINK_HOLDING;
-                       if (!mod_plink_timer(sta,
-                                            mshcfg->dot11MeshHoldingTimeout))
-                               sta->ignore_plink_timer = true;
-
-                       llid = sta->llid;
-                       spin_unlock_bh(&sta->lock);
-                       mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
-                                           sta->sta.addr, llid, plid, reason);
+                       mesh_plink_close(sdata, sta, event);
+                       action = WLAN_SP_MESH_PEERING_CLOSE;
                        break;
                case OPN_ACPT:
-                       llid = sta->llid;
-                       spin_unlock_bh(&sta->lock);
-                       mesh_plink_frame_tx(sdata,
-                                           WLAN_SP_MESH_PEERING_CONFIRM,
-                                           sta->sta.addr, llid, plid, 0);
+                       action = WLAN_SP_MESH_PEERING_CONFIRM;
                        break;
                case CNF_ACPT:
-                       del_timer(&sta->plink_timer);
-                       sta->plink_state = NL80211_PLINK_ESTAB;
-                       spin_unlock_bh(&sta->lock);
-                       changed |= mesh_plink_inc_estab_count(sdata);
-                       changed |= mesh_set_ht_prot_mode(sdata);
-                       changed |= mesh_set_short_slot_time(sdata);
-                       mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n",
-                               sta->sta.addr);
-                       ieee80211_mps_sta_status_update(sta);
-                       changed |= ieee80211_mps_set_sta_local_pm(sta,
-                                                      mshcfg->power_mode);
+                       changed |= mesh_plink_establish(sdata, sta);
                        break;
                default:
-                       spin_unlock_bh(&sta->lock);
                        break;
                }
                break;
-
        case NL80211_PLINK_CNF_RCVD:
                switch (event) {
                case OPN_RJCT:
                case CNF_RJCT:
-                       reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);
                case CLS_ACPT:
-                       if (!reason)
-                               reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
-                       sta->reason = reason;
-                       sta->plink_state = NL80211_PLINK_HOLDING;
-                       if (!mod_plink_timer(sta,
-                                            mshcfg->dot11MeshHoldingTimeout))
-                               sta->ignore_plink_timer = true;
-
-                       llid = sta->llid;
-                       spin_unlock_bh(&sta->lock);
-                       mesh_plink_frame_tx(sdata,
-                                           WLAN_SP_MESH_PEERING_CLOSE,
-                                           sta->sta.addr, llid, plid, reason);
+                       mesh_plink_close(sdata, sta, event);
+                       action = WLAN_SP_MESH_PEERING_CLOSE;
                        break;
                case OPN_ACPT:
-                       del_timer(&sta->plink_timer);
-                       sta->plink_state = NL80211_PLINK_ESTAB;
-                       spin_unlock_bh(&sta->lock);
-                       changed |= mesh_plink_inc_estab_count(sdata);
-                       changed |= mesh_set_ht_prot_mode(sdata);
-                       changed |= mesh_set_short_slot_time(sdata);
-                       mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n",
-                               sta->sta.addr);
-                       mesh_plink_frame_tx(sdata,
-                                           WLAN_SP_MESH_PEERING_CONFIRM,
-                                           sta->sta.addr, llid, plid, 0);
-                       ieee80211_mps_sta_status_update(sta);
-                       changed |= ieee80211_mps_set_sta_local_pm(sta,
-                                                       mshcfg->power_mode);
+                       changed |= mesh_plink_establish(sdata, sta);
+                       action = WLAN_SP_MESH_PEERING_CONFIRM;
                        break;
                default:
-                       spin_unlock_bh(&sta->lock);
                        break;
                }
                break;
-
        case NL80211_PLINK_ESTAB:
                switch (event) {
                case CLS_ACPT:
-                       reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
-                       sta->reason = reason;
                        changed |= __mesh_plink_deactivate(sta);
-                       sta->plink_state = NL80211_PLINK_HOLDING;
-                       llid = sta->llid;
-                       mod_plink_timer(sta, mshcfg->dot11MeshHoldingTimeout);
-                       spin_unlock_bh(&sta->lock);
                        changed |= mesh_set_ht_prot_mode(sdata);
                        changed |= mesh_set_short_slot_time(sdata);
-                       mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
-                                           sta->sta.addr, llid, plid, reason);
+                       mesh_plink_close(sdata, sta, event);
+                       action = WLAN_SP_MESH_PEERING_CLOSE;
                        break;
                case OPN_ACPT:
-                       llid = sta->llid;
-                       spin_unlock_bh(&sta->lock);
-                       mesh_plink_frame_tx(sdata,
-                                           WLAN_SP_MESH_PEERING_CONFIRM,
-                                           sta->sta.addr, llid, plid, 0);
+                       action = WLAN_SP_MESH_PEERING_CONFIRM;
                        break;
                default:
-                       spin_unlock_bh(&sta->lock);
                        break;
                }
                break;
@@ -1049,32 +836,271 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
                        if (del_timer(&sta->plink_timer))
                                sta->ignore_plink_timer = 1;
                        mesh_plink_fsm_restart(sta);
-                       spin_unlock_bh(&sta->lock);
                        break;
                case OPN_ACPT:
                case CNF_ACPT:
                case OPN_RJCT:
                case CNF_RJCT:
-                       llid = sta->llid;
-                       reason = sta->reason;
-                       spin_unlock_bh(&sta->lock);
-                       mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
-                                           sta->sta.addr, llid, plid, reason);
+                       action = WLAN_SP_MESH_PEERING_CLOSE;
                        break;
                default:
-                       spin_unlock_bh(&sta->lock);
+                       break;
                }
                break;
        default:
                /* should not get here, PLINK_BLOCKED is dealt with at the
                 * beginning of the function
                 */
-               spin_unlock_bh(&sta->lock);
                break;
        }
+       spin_unlock_bh(&sta->lock);
+       if (action) {
+               mesh_plink_frame_tx(sdata, action, sta->sta.addr,
+                                   sta->llid, sta->plid, sta->reason);
+
+               /* also send confirm in open case */
+               if (action == WLAN_SP_MESH_PEERING_OPEN) {
+                       mesh_plink_frame_tx(sdata,
+                                           WLAN_SP_MESH_PEERING_CONFIRM,
+                                           sta->sta.addr, sta->llid,
+                                           sta->plid, 0);
+               }
+       }
+
+       return changed;
+}
+
+/*
+ * mesh_plink_get_event - get correct MPM event
+ *
+ * @sdata: interface
+ * @sta: peer, leave NULL if processing a frame from a new suitable peer
+ * @elems: peering management IEs
+ * @ftype: frame type
+ * @llid: peer's peer link ID
+ * @plid: peer's local link ID
+ *
+ * Return: new peering event for @sta, but PLINK_UNDEFINED should be treated as
+ * an error.
+ */
+static enum plink_event
+mesh_plink_get_event(struct ieee80211_sub_if_data *sdata,
+                    struct sta_info *sta,
+                    struct ieee802_11_elems *elems,
+                    enum ieee80211_self_protected_actioncode ftype,
+                    u16 llid, u16 plid)
+{
+       enum plink_event event = PLINK_UNDEFINED;
+       u8 ie_len = elems->peering_len;
+       bool matches_local;
+
+       matches_local = (ftype == WLAN_SP_MESH_PEERING_CLOSE ||
+                        mesh_matches_local(sdata, elems));
+
+       /* deny open request from non-matching peer */
+       if (!matches_local && !sta) {
+               event = OPN_RJCT;
+               goto out;
+       }
+
+       if (!sta) {
+               if (ftype != WLAN_SP_MESH_PEERING_OPEN) {
+                       mpl_dbg(sdata, "Mesh plink: cls or cnf from unknown peer\n");
+                       goto out;
+               }
+               /* ftype == WLAN_SP_MESH_PEERING_OPEN */
+               if (!mesh_plink_free_count(sdata)) {
+                       mpl_dbg(sdata, "Mesh plink error: no more free plinks\n");
+                       goto out;
+               }
+       } else {
+               if (!test_sta_flag(sta, WLAN_STA_AUTH)) {
+                       mpl_dbg(sdata, "Mesh plink: Action frame from non-authed peer\n");
+                       goto out;
+               }
+               if (sta->plink_state == NL80211_PLINK_BLOCKED)
+                       goto out;
+       }
+
+       /* new matching peer */
+       if (!sta) {
+               event = OPN_ACPT;
+               goto out;
+       }
+
+       switch (ftype) {
+       case WLAN_SP_MESH_PEERING_OPEN:
+               if (!matches_local)
+                       event = OPN_RJCT;
+               if (!mesh_plink_free_count(sdata) ||
+                   (sta->plid && sta->plid != plid))
+                       event = OPN_IGNR;
+               else
+                       event = OPN_ACPT;
+               break;
+       case WLAN_SP_MESH_PEERING_CONFIRM:
+               if (!matches_local)
+                       event = CNF_RJCT;
+               if (!mesh_plink_free_count(sdata) ||
+                   (sta->llid != llid || sta->plid != plid))
+                       event = CNF_IGNR;
+               else
+                       event = CNF_ACPT;
+               break;
+       case WLAN_SP_MESH_PEERING_CLOSE:
+               if (sta->plink_state == NL80211_PLINK_ESTAB)
+                       /* Do not check for llid or plid. This does not
+                        * follow the standard but since multiple plinks
+                        * per sta are not supported, it is necessary in
+                        * order to avoid a livelock when MP A sees an
+                        * establish peer link to MP B but MP B does not
+                        * see it. This can be caused by a timeout in
+                        * B's peer link establishment or B beign
+                        * restarted.
+                        */
+                       event = CLS_ACPT;
+               else if (sta->plid != plid)
+                       event = CLS_IGNR;
+               else if (ie_len == 8 && sta->llid != llid)
+                       event = CLS_IGNR;
+               else
+                       event = CLS_ACPT;
+               break;
+       default:
+               mpl_dbg(sdata, "Mesh plink: unknown frame subtype\n");
+               break;
+       }
+
+out:
+       return event;
+}
 
+static void
+mesh_process_plink_frame(struct ieee80211_sub_if_data *sdata,
+                        struct ieee80211_mgmt *mgmt,
+                        struct ieee802_11_elems *elems)
+{
+
+       struct sta_info *sta;
+       enum plink_event event;
+       enum ieee80211_self_protected_actioncode ftype;
+       u32 changed = 0;
+       u8 ie_len = elems->peering_len;
+       __le16 _plid, _llid;
+       u16 plid, llid = 0;
+
+       if (!elems->peering) {
+               mpl_dbg(sdata,
+                       "Mesh plink: missing necessary peer link ie\n");
+               return;
+       }
+
+       if (elems->rsn_len &&
+           sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) {
+               mpl_dbg(sdata,
+                       "Mesh plink: can't establish link with secure peer\n");
+               return;
+       }
+
+       ftype = mgmt->u.action.u.self_prot.action_code;
+       if ((ftype == WLAN_SP_MESH_PEERING_OPEN && ie_len != 4) ||
+           (ftype == WLAN_SP_MESH_PEERING_CONFIRM && ie_len != 6) ||
+           (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len != 6
+                                                       && ie_len != 8)) {
+               mpl_dbg(sdata,
+                       "Mesh plink: incorrect plink ie length %d %d\n",
+                       ftype, ie_len);
+               return;
+       }
+
+       if (ftype != WLAN_SP_MESH_PEERING_CLOSE &&
+           (!elems->mesh_id || !elems->mesh_config)) {
+               mpl_dbg(sdata, "Mesh plink: missing necessary ie\n");
+               return;
+       }
+       /* Note the lines below are correct, the llid in the frame is the plid
+        * from the point of view of this host.
+        */
+       memcpy(&_plid, PLINK_GET_LLID(elems->peering), sizeof(__le16));
+       plid = le16_to_cpu(_plid);
+       if (ftype == WLAN_SP_MESH_PEERING_CONFIRM ||
+           (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len == 8)) {
+               memcpy(&_llid, PLINK_GET_PLID(elems->peering), sizeof(__le16));
+               llid = le16_to_cpu(_llid);
+       }
+
+       /* WARNING: Only for sta pointer, is dropped & re-acquired */
+       rcu_read_lock();
+
+       sta = sta_info_get(sdata, mgmt->sa);
+
+       if (ftype == WLAN_SP_MESH_PEERING_OPEN &&
+           !rssi_threshold_check(sdata, sta)) {
+               mpl_dbg(sdata, "Mesh plink: %pM does not meet rssi threshold\n",
+                       mgmt->sa);
+               goto unlock_rcu;
+       }
+
+       /* Now we will figure out the appropriate event... */
+       event = mesh_plink_get_event(sdata, sta, elems, ftype, llid, plid);
+
+       if (event == OPN_ACPT) {
+               rcu_read_unlock();
+               /* allocate sta entry if necessary and update info */
+               sta = mesh_sta_info_get(sdata, mgmt->sa, elems);
+               if (!sta) {
+                       mpl_dbg(sdata, "Mesh plink: failed to init peer!\n");
+                       goto unlock_rcu;
+               }
+               sta->plid = plid;
+       } else if (!sta && event == OPN_RJCT) {
+               mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
+                                   mgmt->sa, 0, plid,
+                                   WLAN_REASON_MESH_CONFIG);
+               goto unlock_rcu;
+       } else if (!sta || event == PLINK_UNDEFINED) {
+               /* something went wrong */
+               goto unlock_rcu;
+       }
+
+       changed |= mesh_plink_fsm(sdata, sta, event);
+
+unlock_rcu:
        rcu_read_unlock();
 
        if (changed)
                ieee80211_mbss_info_change_notify(sdata, changed);
 }
+
+void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
+                        struct ieee80211_mgmt *mgmt, size_t len,
+                        struct ieee80211_rx_status *rx_status)
+{
+       struct ieee802_11_elems elems;
+       size_t baselen;
+       u8 *baseaddr;
+
+       /* need action_code, aux */
+       if (len < IEEE80211_MIN_ACTION_SIZE + 3)
+               return;
+
+       if (sdata->u.mesh.user_mpm)
+               /* userspace must register for these */
+               return;
+
+       if (is_multicast_ether_addr(mgmt->da)) {
+               mpl_dbg(sdata,
+                       "Mesh plink: ignore frame from multicast address\n");
+               return;
+       }
+
+       baseaddr = mgmt->u.action.u.self_prot.variable;
+       baselen = (u8 *) mgmt->u.action.u.self_prot.variable - (u8 *) mgmt;
+       if (mgmt->u.action.u.self_prot.action_code ==
+                                               WLAN_SP_MESH_PEERING_CONFIRM) {
+               baseaddr += 4;
+               baselen += 4;
+       }
+       ieee802_11_parse_elems(baseaddr, len - baselen, true, &elems);
+       mesh_process_plink_frame(sdata, mgmt, &elems);
+}
index 0f79b78b5e86b45a6d7059de497b68b44944da09..2802f9d9279de1527927a88bc731489cc22613c7 100644 (file)
@@ -576,10 +576,9 @@ void ieee80211_mps_frame_release(struct sta_info *sta,
        int ac, buffer_local = 0;
        bool has_buffered = false;
 
-       /* TIM map only for LLID <= IEEE80211_MAX_AID */
        if (sta->plink_state == NL80211_PLINK_ESTAB)
                has_buffered = ieee80211_check_tim(elems->tim, elems->tim_len,
-                               le16_to_cpu(sta->llid) % IEEE80211_MAX_AID);
+                                                  sta->llid);
 
        if (has_buffered)
                mps_dbg(sta->sdata, "%pM indicates buffered frames\n",
index 05a256b38e245b64b26a4adb11023898bcd115e1..d1cf2d5534998957c13cfbd5ca23c630d7c9f6a7 100644 (file)
@@ -92,12 +92,20 @@ static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
        if (stype != IEEE80211_STYPE_BEACON)
                return;
 
-       /* The current tsf is a first approximation for the timestamp
-        * for the received beacon.  Further down we try to get a
-        * better value from the rx_status->mactime field if
-        * available. Also we have to call drv_get_tsf() before
-        * entering the rcu-read section.*/
-       t_r = drv_get_tsf(local, sdata);
+       /*
+        * Get time when timestamp field was received.  If we don't
+        * have rx timestamps, then use current tsf as an approximation.
+        * drv_get_tsf() must be called before entering the rcu-read
+        * section.
+        */
+       if (ieee80211_have_rx_timestamp(rx_status))
+               t_r = ieee80211_calculate_rx_timestamp(local, rx_status,
+                                                      24 + 12 +
+                                                      elems->total_len +
+                                                      FCS_LEN,
+                                                      24);
+       else
+               t_r = drv_get_tsf(local, sdata);
 
        rcu_read_lock();
        sta = sta_info_get(sdata, mgmt->sa);
@@ -117,14 +125,6 @@ static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
                goto no_sync;
        }
 
-       if (ieee80211_have_rx_timestamp(rx_status))
-               /* time when timestamp field was received */
-               t_r = ieee80211_calculate_rx_timestamp(local, rx_status,
-                                                      24 + 12 +
-                                                      elems->total_len +
-                                                      FCS_LEN,
-                                                      24);
-
        /* Timing offset calculation (see 13.13.2.2.2) */
        t_t = le64_to_cpu(mgmt->u.beacon.timestamp);
        sta->t_offset = t_t - t_r;
index d7504ab61a34c7ef6a51f8adce10e58c021408d0..900ead344f5bd526fa5f9a54b438a8cae52012e6 100644 (file)
@@ -330,6 +330,16 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata,
        if (WARN_ON_ONCE(!sta))
                return -EINVAL;
 
+       /*
+        * if bss configuration changed store the new one -
+        * this may be applicable even if channel is identical
+        */
+       ht_opmode = le16_to_cpu(ht_oper->operation_mode);
+       if (sdata->vif.bss_conf.ht_operation_mode != ht_opmode) {
+               *changed |= BSS_CHANGED_HT;
+               sdata->vif.bss_conf.ht_operation_mode = ht_opmode;
+       }
+
        chan = sdata->vif.bss_conf.chandef.chan;
        sband = local->hw.wiphy->bands[chan->band];
 
@@ -416,14 +426,6 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata,
                                         IEEE80211_RC_BW_CHANGED);
        }
 
-       ht_opmode = le16_to_cpu(ht_oper->operation_mode);
-
-       /* if bss configuration changed store the new one */
-       if (sdata->vif.bss_conf.ht_operation_mode != ht_opmode) {
-               *changed |= BSS_CHANGED_HT;
-               sdata->vif.bss_conf.ht_operation_mode = ht_opmode;
-       }
-
        return 0;
 }
 
@@ -714,7 +716,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
        }
 
        /* if present, add any custom IEs that go before HT */
-       if (assoc_data->ie_len && assoc_data->ie) {
+       if (assoc_data->ie_len) {
                static const u8 before_ht[] = {
                        WLAN_EID_SSID,
                        WLAN_EID_SUPP_RATES,
@@ -748,7 +750,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
                                     &assoc_data->ap_vht_cap);
 
        /* if present, add any custom non-vendor IEs that go after HT */
-       if (assoc_data->ie_len && assoc_data->ie) {
+       if (assoc_data->ie_len) {
                noffset = ieee80211_ie_split_vendor(assoc_data->ie,
                                                    assoc_data->ie_len,
                                                    offset);
@@ -779,7 +781,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
        }
 
        /* add any remaining custom (i.e. vendor specific here) IEs */
-       if (assoc_data->ie_len && assoc_data->ie) {
+       if (assoc_data->ie_len) {
                noffset = assoc_data->ie_len;
                pos = skb_put(skb, noffset - offset);
                memcpy(pos, assoc_data->ie + offset, noffset - offset);
@@ -886,8 +888,7 @@ static void ieee80211_chswitch_work(struct work_struct *work)
        if (!ifmgd->associated)
                goto out;
 
-       ret = ieee80211_vif_change_channel(sdata, &local->csa_chandef,
-                                          &changed);
+       ret = ieee80211_vif_change_channel(sdata, &changed);
        if (ret) {
                sdata_info(sdata,
                           "vif channel switch failed, disconnecting\n");
@@ -897,7 +898,7 @@ static void ieee80211_chswitch_work(struct work_struct *work)
        }
 
        if (!local->use_chanctx) {
-               local->_oper_chandef = local->csa_chandef;
+               local->_oper_chandef = sdata->csa_chandef;
                /* Call "hw_config" only if doing sw channel switch.
                 * Otherwise update the channel directly
                 */
@@ -908,7 +909,7 @@ static void ieee80211_chswitch_work(struct work_struct *work)
        }
 
        /* XXX: shouldn't really modify cfg80211-owned data! */
-       ifmgd->associated->channel = local->csa_chandef.chan;
+       ifmgd->associated->channel = sdata->csa_chandef.chan;
 
        /* XXX: wait for a beacon first? */
        ieee80211_wake_queues_by_reason(&local->hw,
@@ -1035,7 +1036,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
        }
        mutex_unlock(&local->chanctx_mtx);
 
-       local->csa_chandef = csa_ie.chandef;
+       sdata->csa_chandef = csa_ie.chandef;
 
        if (csa_ie.mode)
                ieee80211_stop_queues_by_reason(&local->hw,
@@ -1398,10 +1399,12 @@ void ieee80211_dfs_cac_timer_work(struct work_struct *work)
        struct ieee80211_sub_if_data *sdata =
                container_of(delayed_work, struct ieee80211_sub_if_data,
                             dfs_cac_timer_work);
+       struct cfg80211_chan_def chandef = sdata->vif.bss_conf.chandef;
 
        ieee80211_vif_release_channel(sdata);
-
-       cfg80211_cac_event(sdata->dev, NL80211_RADAR_CAC_FINISHED, GFP_KERNEL);
+       cfg80211_cac_event(sdata->dev, &chandef,
+                          NL80211_RADAR_CAC_FINISHED,
+                          GFP_KERNEL);
 }
 
 /* MLME */
@@ -1745,6 +1748,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
 
        ifmgd->flags = 0;
        ieee80211_vif_release_channel(sdata);
+
+       sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
 }
 
 void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
@@ -1910,6 +1915,8 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
        if (ifmgd->flags & IEEE80211_STA_CONNECTION_POLL)
                already = true;
 
+       ifmgd->flags |= IEEE80211_STA_CONNECTION_POLL;
+
        mutex_unlock(&sdata->local->mtx);
 
        if (already)
@@ -4189,6 +4196,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
 
        sdata->control_port_protocol = req->crypto.control_port_ethertype;
        sdata->control_port_no_encrypt = req->crypto.control_port_no_encrypt;
+       sdata->encrypt_headroom = ieee80211_cs_headroom(local, &req->crypto,
+                                                       sdata->vif.type);
 
        /* kick off associate process */
 
index 505bc0dea074809f1532f322528e222a5052c061..b95e16c070813da22169679e8c5c1aa7e3ee0f1d 100644 (file)
@@ -54,6 +54,8 @@ static inline void rate_control_rate_init(struct sta_info *sta)
        struct ieee80211_supported_band *sband;
        struct ieee80211_chanctx_conf *chanctx_conf;
 
+       ieee80211_sta_set_rx_nss(sta);
+
        if (!ref)
                return;
 
@@ -67,8 +69,6 @@ static inline void rate_control_rate_init(struct sta_info *sta)
 
        sband = local->hw.wiphy->bands[chanctx_conf->def.chan->band];
 
-       ieee80211_sta_set_rx_nss(sta);
-
        ref->ops->rate_init(ref->priv, sband, &chanctx_conf->def, ista,
                            priv_sta);
        rcu_read_unlock();
index 7fa1b36e620247ed5c14e97d54b2d72d7a0b43cb..d2f19f7e7091b6e6b9111702f19b02f612fdb52c 100644 (file)
@@ -422,10 +422,9 @@ init_sample_table(struct minstrel_sta_info *mi)
        memset(mi->sample_table, 0xff, SAMPLE_COLUMNS * mi->n_rates);
 
        for (col = 0; col < SAMPLE_COLUMNS; col++) {
+               prandom_bytes(rnd, sizeof(rnd));
                for (i = 0; i < mi->n_rates; i++) {
-                       get_random_bytes(rnd, sizeof(rnd));
                        new_idx = (i + rnd[i & 7]) % mi->n_rates;
-
                        while (SAMPLE_TBL(mi, new_idx, col) != 0xff)
                                new_idx = (new_idx + 1) % mi->n_rates;
 
index 5d60779a0c1be89e987b2cd478af865ec806d4bb..d2ed18d82fe1dd1f55a2f5c13f319920bbb9b887 100644 (file)
@@ -135,7 +135,7 @@ minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi);
 static int
 minstrel_ht_get_group_idx(struct ieee80211_tx_rate *rate)
 {
-       return GROUP_IDX((rate->idx / MCS_GROUP_RATES) + 1,
+       return GROUP_IDX((rate->idx / 8) + 1,
                         !!(rate->flags & IEEE80211_TX_RC_SHORT_GI),
                         !!(rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH));
 }
@@ -148,7 +148,7 @@ minstrel_ht_get_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
 
        if (rate->flags & IEEE80211_TX_RC_MCS) {
                group = minstrel_ht_get_group_idx(rate);
-               idx = rate->idx % MCS_GROUP_RATES;
+               idx = rate->idx % 8;
        } else {
                group = MINSTREL_CCK_GROUP;
 
@@ -226,7 +226,7 @@ minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate)
                nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len);
 
        nsecs += minstrel_mcs_groups[group].duration[rate];
-       tp = 1000000 * ((mr->probability * 1000) / nsecs);
+       tp = 1000000 * ((prob * 1000) / nsecs);
 
        mr->cur_tp = MINSTREL_TRUNC(tp);
 }
@@ -277,13 +277,15 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
                        if (!(mg->supported & BIT(i)))
                                continue;
 
+                       index = MCS_GROUP_RATES * group + i;
+
                        /* initialize rates selections starting indexes */
                        if (!mg_rates_valid) {
                                mg->max_tp_rate = mg->max_tp_rate2 =
                                        mg->max_prob_rate = i;
                                if (!mi_rates_valid) {
                                        mi->max_tp_rate = mi->max_tp_rate2 =
-                                               mi->max_prob_rate = i;
+                                               mi->max_prob_rate = index;
                                        mi_rates_valid = true;
                                }
                                mg_rates_valid = true;
@@ -291,7 +293,6 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
 
                        mr = &mg->rates[i];
                        mr->retry_updated = false;
-                       index = MCS_GROUP_RATES * group + i;
                        minstrel_calc_rate_ewma(mr);
                        minstrel_ht_calc_tp(mi, group, i);
 
@@ -636,8 +637,7 @@ minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
                idx = mp->cck_rates[index % ARRAY_SIZE(mp->cck_rates)];
                flags = 0;
        } else {
-               idx = index % MCS_GROUP_RATES +
-                     (group->streams - 1) * MCS_GROUP_RATES;
+               idx = index % MCS_GROUP_RATES + (group->streams - 1) * 8;
                flags = IEEE80211_TX_RC_MCS | group->flags;
        }
 
@@ -701,12 +701,16 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
        if (!mi->sample_tries)
                return -1;
 
-       mg = &mi->groups[mi->sample_group];
+       sample_group = mi->sample_group;
+       mg = &mi->groups[sample_group];
        sample_idx = sample_table[mg->column][mg->index];
+       minstrel_next_sample_idx(mi);
+
+       if (!(mg->supported & BIT(sample_idx)))
+               return -1;
+
        mr = &mg->rates[sample_idx];
-       sample_group = mi->sample_group;
        sample_idx += sample_group * MCS_GROUP_RATES;
-       minstrel_next_sample_idx(mi);
 
        /*
         * Sampling might add some overhead (RTS, no aggregation)
@@ -817,7 +821,7 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
        }
 
        rate->idx = sample_idx % MCS_GROUP_RATES +
-                   (sample_group->streams - 1) * MCS_GROUP_RATES;
+                   (sample_group->streams - 1) * 8;
        rate->flags = IEEE80211_TX_RC_MCS | sample_group->flags;
 }
 
@@ -1052,10 +1056,9 @@ init_sample_table(void)
 
        memset(sample_table, 0xff, sizeof(sample_table));
        for (col = 0; col < SAMPLE_COLUMNS; col++) {
+               prandom_bytes(rnd, sizeof(rnd));
                for (i = 0; i < MCS_GROUP_RATES; i++) {
-                       get_random_bytes(rnd, sizeof(rnd));
                        new_idx = (i + rnd[i]) % MCS_GROUP_RATES;
-
                        while (sample_table[col][new_idx] != 0xff)
                                new_idx = (new_idx + 1) % MCS_GROUP_RATES;
 
index df44a5ad827049f251dd255f47e5c06262f1eb77..3e7d793de0c3407180965bb785485fd361700560 100644 (file)
@@ -54,8 +54,7 @@ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p)
                        int r = bitrates[j % 4];
                        p += sprintf(p, " %2u.%1uM", r / 10, r % 10);
                } else {
-                       p += sprintf(p, " MCS%-2u", (mg->streams - 1) *
-                                        MCS_GROUP_RATES + j);
+                       p += sprintf(p, " MCS%-2u", (mg->streams - 1) * 8 + j);
                }
 
                tp = mr->cur_tp / 10;
index caecef870c0e44e3562cdc0a874bcfd233fc77a1..2dfa755227339533d2c105313ba8ab4ea3ba67b5 100644 (file)
@@ -638,6 +638,27 @@ static int ieee80211_get_mmie_keyidx(struct sk_buff *skb)
        return le16_to_cpu(mmie->key_id);
 }
 
+static int iwl80211_get_cs_keyid(const struct ieee80211_cipher_scheme *cs,
+                                struct sk_buff *skb)
+{
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+       __le16 fc;
+       int hdrlen;
+       u8 keyid;
+
+       fc = hdr->frame_control;
+       hdrlen = ieee80211_hdrlen(fc);
+
+       if (skb->len < hdrlen + cs->hdr_len)
+               return -EINVAL;
+
+       skb_copy_bits(skb, hdrlen + cs->key_idx_off, &keyid, 1);
+       keyid &= cs->key_idx_mask;
+       keyid >>= cs->key_idx_shift;
+
+       return keyid;
+}
+
 static ieee80211_rx_result ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
 {
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
@@ -729,9 +750,7 @@ static void ieee80211_release_reorder_frames(struct ieee80211_sub_if_data *sdata
        lockdep_assert_held(&tid_agg_rx->reorder_lock);
 
        while (ieee80211_sn_less(tid_agg_rx->head_seq_num, head_seq_num)) {
-               index = ieee80211_sn_sub(tid_agg_rx->head_seq_num,
-                                        tid_agg_rx->ssn) %
-                                                       tid_agg_rx->buf_size;
+               index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size;
                ieee80211_release_reorder_frame(sdata, tid_agg_rx, index,
                                                frames);
        }
@@ -757,8 +776,7 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata,
        lockdep_assert_held(&tid_agg_rx->reorder_lock);
 
        /* release the buffer until next missing frame */
-       index = ieee80211_sn_sub(tid_agg_rx->head_seq_num,
-                                tid_agg_rx->ssn) % tid_agg_rx->buf_size;
+       index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size;
        if (!tid_agg_rx->reorder_buf[index] &&
            tid_agg_rx->stored_mpdu_num) {
                /*
@@ -793,15 +811,11 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata,
        } else while (tid_agg_rx->reorder_buf[index]) {
                ieee80211_release_reorder_frame(sdata, tid_agg_rx, index,
                                                frames);
-               index = ieee80211_sn_sub(tid_agg_rx->head_seq_num,
-                                        tid_agg_rx->ssn) %
-                                                       tid_agg_rx->buf_size;
+               index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size;
        }
 
        if (tid_agg_rx->stored_mpdu_num) {
-               j = index = ieee80211_sn_sub(tid_agg_rx->head_seq_num,
-                                            tid_agg_rx->ssn) %
-                                                       tid_agg_rx->buf_size;
+               j = index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size;
 
                for (; j != (index - 1) % tid_agg_rx->buf_size;
                     j = (j + 1) % tid_agg_rx->buf_size) {
@@ -861,8 +875,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata
 
        /* Now the new frame is always in the range of the reordering buffer */
 
-       index = ieee80211_sn_sub(mpdu_seq_num,
-                                tid_agg_rx->ssn) % tid_agg_rx->buf_size;
+       index = mpdu_seq_num % tid_agg_rx->buf_size;
 
        /* check if we already stored this frame */
        if (tid_agg_rx->reorder_buf[index]) {
@@ -911,7 +924,8 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx,
        u16 sc;
        u8 tid, ack_policy;
 
-       if (!ieee80211_is_data_qos(hdr->frame_control))
+       if (!ieee80211_is_data_qos(hdr->frame_control) ||
+           is_multicast_ether_addr(hdr->addr1))
                goto dont_reorder;
 
        /*
@@ -1368,6 +1382,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
        struct ieee80211_key *sta_ptk = NULL;
        int mmie_keyidx = -1;
        __le16 fc;
+       const struct ieee80211_cipher_scheme *cs = NULL;
 
        /*
         * Key selection 101
@@ -1405,11 +1420,19 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
 
        /* start without a key */
        rx->key = NULL;
+       fc = hdr->frame_control;
 
-       if (rx->sta)
-               sta_ptk = rcu_dereference(rx->sta->ptk);
+       if (rx->sta) {
+               int keyid = rx->sta->ptk_idx;
 
-       fc = hdr->frame_control;
+               if (ieee80211_has_protected(fc) && rx->sta->cipher_scheme) {
+                       cs = rx->sta->cipher_scheme;
+                       keyid = iwl80211_get_cs_keyid(cs, rx->skb);
+                       if (unlikely(keyid < 0))
+                               return RX_DROP_UNUSABLE;
+               }
+               sta_ptk = rcu_dereference(rx->sta->ptk[keyid]);
+       }
 
        if (!ieee80211_has_protected(fc))
                mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb);
@@ -1471,6 +1494,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
                return RX_CONTINUE;
        } else {
                u8 keyid;
+
                /*
                 * The device doesn't give us the IV so we won't be
                 * able to look up the key. That's ok though, we
@@ -1486,15 +1510,21 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
 
                hdrlen = ieee80211_hdrlen(fc);
 
-               if (rx->skb->len < 8 + hdrlen)
-                       return RX_DROP_UNUSABLE; /* TODO: count this? */
+               if (cs) {
+                       keyidx = iwl80211_get_cs_keyid(cs, rx->skb);
 
-               /*
-                * no need to call ieee80211_wep_get_keyidx,
-                * it verifies a bunch of things we've done already
-                */
-               skb_copy_bits(rx->skb, hdrlen + 3, &keyid, 1);
-               keyidx = keyid >> 6;
+                       if (unlikely(keyidx < 0))
+                               return RX_DROP_UNUSABLE;
+               } else {
+                       if (rx->skb->len < 8 + hdrlen)
+                               return RX_DROP_UNUSABLE; /* TODO: count this? */
+                       /*
+                        * no need to call ieee80211_wep_get_keyidx,
+                        * it verifies a bunch of things we've done already
+                        */
+                       skb_copy_bits(rx->skb, hdrlen + 3, &keyid, 1);
+                       keyidx = keyid >> 6;
+               }
 
                /* check per-station GTK first, if multicast packet */
                if (is_multicast_ether_addr(hdr->addr1) && rx->sta)
@@ -1542,11 +1572,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
                result = ieee80211_crypto_aes_cmac_decrypt(rx);
                break;
        default:
-               /*
-                * We can reach here only with HW-only algorithms
-                * but why didn't it decrypt the frame?!
-                */
-               return RX_DROP_UNUSABLE;
+               result = ieee80211_crypto_hw_decrypt(rx);
        }
 
        /* the hdr variable is invalid after the decrypt handlers */
@@ -2056,7 +2082,6 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
        struct ieee80211_sub_if_data *sdata = rx->sdata;
        struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
        struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
-       __le16 reason = cpu_to_le16(WLAN_REASON_MESH_PATH_NOFORWARD);
        u16 q, hdrlen;
 
        hdr = (struct ieee80211_hdr *) skb->data;
@@ -2164,7 +2189,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
        } else {
                /* unable to resolve next hop */
                mesh_path_error_tx(sdata, ifmsh->mshcfg.element_ttl,
-                                  fwd_hdr->addr3, 0, reason, fwd_hdr->addr2);
+                                  fwd_hdr->addr3, 0,
+                                  WLAN_REASON_MESH_PATH_NOFORWARD,
+                                  fwd_hdr->addr2);
                IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_no_route);
                kfree_skb(fwd_skb);
                return RX_DROP_MONITOR;
index 5ad66a83ef7f4d4525de163c2c2f1fe9d6931a04..4d73c46df86262a385ad5fb9a5912c6a8168831e 100644 (file)
@@ -526,7 +526,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
                ieee80211_hw_config(local, 0);
 
                if ((req->channels[0]->flags &
-                    IEEE80211_CHAN_PASSIVE_SCAN) ||
+                    IEEE80211_CHAN_NO_IR) ||
                    !local->scan_req->n_ssids) {
                        next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
                } else {
@@ -572,7 +572,7 @@ ieee80211_scan_get_channel_time(struct ieee80211_channel *chan)
         * TODO: channel switching also consumes quite some time,
         * add that delay as well to get a better estimation
         */
-       if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)
+       if (chan->flags & IEEE80211_CHAN_NO_IR)
                return IEEE80211_PASSIVE_CHANNEL_TIME;
        return IEEE80211_PROBE_DELAY + IEEE80211_CHANNEL_TIME;
 }
@@ -696,7 +696,7 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local,
         *
         * In any case, it is not necessary for a passive scan.
         */
-       if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN ||
+       if (chan->flags & IEEE80211_CHAN_NO_IR ||
            !local->scan_req->n_ssids) {
                *next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
                local->next_scan_state = SCAN_DECISION;
@@ -881,7 +881,7 @@ int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata,
                                struct ieee80211_channel *tmp_ch =
                                    &local->hw.wiphy->bands[band]->channels[i];
 
-                               if (tmp_ch->flags & (IEEE80211_CHAN_NO_IBSS |
+                               if (tmp_ch->flags & (IEEE80211_CHAN_NO_IR |
                                                     IEEE80211_CHAN_DISABLED))
                                        continue;
 
@@ -895,7 +895,7 @@ int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata,
 
                local->int_scan_req->n_channels = n_ch;
        } else {
-               if (WARN_ON_ONCE(chan->flags & (IEEE80211_CHAN_NO_IBSS |
+               if (WARN_ON_ONCE(chan->flags & (IEEE80211_CHAN_NO_IR |
                                                IEEE80211_CHAN_DISABLED)))
                        goto unlock;
 
@@ -1088,6 +1088,6 @@ void ieee80211_sched_scan_stopped(struct ieee80211_hw *hw)
 
        trace_api_sched_scan_stopped(local);
 
-       ieee80211_queue_work(&local->hw, &local->sched_scan_stopped_work);
+       schedule_work(&local->sched_scan_stopped_work);
 }
 EXPORT_SYMBOL(ieee80211_sched_scan_stopped);
index a40da20b32e074a3923f844edf104eca33a6134c..6ab00907008461fb14d551b2633a8dbcd4fef623 100644 (file)
@@ -78,6 +78,8 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
        if (elems->mesh_chansw_params_ie) {
                csa_ie->ttl = elems->mesh_chansw_params_ie->mesh_ttl;
                csa_ie->mode = elems->mesh_chansw_params_ie->mesh_flags;
+               csa_ie->pre_value = le16_to_cpu(
+                               elems->mesh_chansw_params_ie->mesh_pre_value);
        }
 
        new_freq = ieee80211_channel_to_frequency(new_chan_no, new_band);
index 1eb66e26e49d0a02869ec5e5ff4789583e9760d1..8ed97f76c3cfade5f0986fa2d17c8275753b3c35 100644 (file)
@@ -266,9 +266,17 @@ struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata,
  */
 void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
 {
+       int i;
+
        if (sta->rate_ctrl)
                rate_control_free_sta(sta);
 
+       if (sta->tx_lat) {
+               for (i = 0; i < IEEE80211_NUM_TIDS; i++)
+                       kfree(sta->tx_lat[i].bins);
+               kfree(sta->tx_lat);
+       }
+
        sta_dbg(sta->sdata, "Destroyed STA %pM\n", sta->sta.addr);
 
        kfree(sta);
@@ -333,6 +341,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_local *local = sdata->local;
        struct sta_info *sta;
        struct timespec uptime;
+       struct ieee80211_tx_latency_bin_ranges *tx_latency;
        int i;
 
        sta = kzalloc(sizeof(*sta) + local->hw.sta_data_size, gfp);
@@ -410,6 +419,31 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
                }
        }
 
+       rcu_read_lock();
+
+       tx_latency = rcu_dereference(local->tx_latency);
+       /* init stations Tx latency statistics && TID bins */
+       if (tx_latency)
+               sta->tx_lat = kzalloc(IEEE80211_NUM_TIDS *
+                                     sizeof(struct ieee80211_tx_latency_stat),
+                                     GFP_ATOMIC);
+
+       /*
+        * if Tx latency and bins are enabled and the previous allocation
+        * succeeded
+        */
+       if (tx_latency && tx_latency->n_ranges && sta->tx_lat)
+               for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
+                       /* size of bins is size of the ranges +1 */
+                       sta->tx_lat[i].bin_count =
+                               tx_latency->n_ranges + 1;
+                       sta->tx_lat[i].bins  = kcalloc(sta->tx_lat[i].bin_count,
+                                                      sizeof(u32),
+                                                      GFP_ATOMIC);
+               }
+
+       rcu_read_unlock();
+
        sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr);
 
        return sta;
@@ -507,6 +541,7 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
 
        set_sta_flag(sta, WLAN_STA_INSERTED);
 
+       ieee80211_recalc_min_chandef(sdata);
        ieee80211_sta_debugfs_add(sta);
        rate_control_add_sta_debugfs(sta);
 
@@ -630,8 +665,8 @@ void sta_info_recalc_tim(struct sta_info *sta)
 #ifdef CONFIG_MAC80211_MESH
        } else if (ieee80211_vif_is_mesh(&sta->sdata->vif)) {
                ps = &sta->sdata->u.mesh.ps;
-               /* TIM map only for PLID <= IEEE80211_MAX_AID */
-               id = le16_to_cpu(sta->plid) % IEEE80211_MAX_AID;
+               /* TIM map only for 1 <= PLID <= IEEE80211_MAX_AID */
+               id = sta->plid % (IEEE80211_MAX_AID + 1);
 #endif
        } else {
                return;
@@ -869,6 +904,7 @@ int __must_check __sta_info_destroy(struct sta_info *sta)
 
        rate_control_remove_sta_debugfs(sta);
        ieee80211_sta_debugfs_remove(sta);
+       ieee80211_recalc_min_chandef(sdata);
 
        call_rcu(&sta->rcu_head, free_sta_rcu);
 
index 3ef06a26b9cb9feaddfd3d752dd9bd8ac971a11c..0218caf5c14a793ef14045da6c0db6a13781b259 100644 (file)
@@ -220,6 +220,25 @@ struct sta_ampdu_mlme {
        u8 dialog_token_allocator;
 };
 
+/*
+ * struct ieee80211_tx_latency_stat - Tx latency statistics
+ *
+ * Measures TX latency and jitter for a station per TID.
+ *
+ * @max: worst case latency
+ * @sum: sum of all latencies
+ * @counter: amount of Tx frames sent from interface
+ * @bins: each bin counts how many frames transmitted within a certain
+ * latency range. when disabled it is NULL.
+ * @bin_count: amount of bins.
+ */
+struct ieee80211_tx_latency_stat {
+       u32 max;
+       u32 sum;
+       u32 counter;
+       u32 *bins;
+       u32 bin_count;
+};
 
 /**
  * struct sta_info - STA information
@@ -231,8 +250,10 @@ struct sta_ampdu_mlme {
  * @hnext: hash table linked list pointer
  * @local: pointer to the global information
  * @sdata: virtual interface this station belongs to
- * @ptk: peer key negotiated with this station, if any
+ * @ptk: peer keys negotiated with this station, if any
+ * @ptk_idx: last installed peer key index
  * @gtk: group keys negotiated with this station, if any
+ * @gtk_idx: last installed group key index
  * @rate_ctrl: rate control algorithm reference
  * @rate_ctrl_priv: rate control private per-STA pointer
  * @last_tx_rate: rate used for last transmit, to report to userspace as
@@ -274,6 +295,7 @@ struct sta_ampdu_mlme {
  * @tid_seq: per-TID sequence numbers for sending to this STA
  * @ampdu_mlme: A-MPDU state machine state
  * @timer_to_tid: identity mapping to ID timers
+ * @tx_lat: Tx latency statistics
  * @llid: Local link ID
  * @plid: Peer link ID
  * @reason: Cancel reason on PLINK_HOLDING state
@@ -303,6 +325,7 @@ struct sta_ampdu_mlme {
  * @chain_signal_avg: signal average (per chain)
  * @known_smps_mode: the smps_mode the client thinks we are in. Relevant for
  *     AP only.
+ * @cipher_scheme: optional cipher scheme for this station
  */
 struct sta_info {
        /* General information, mostly static */
@@ -312,7 +335,9 @@ struct sta_info {
        struct ieee80211_local *local;
        struct ieee80211_sub_if_data *sdata;
        struct ieee80211_key __rcu *gtk[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS];
-       struct ieee80211_key __rcu *ptk;
+       struct ieee80211_key __rcu *ptk[NUM_DEFAULT_KEYS];
+       u8 gtk_idx;
+       u8 ptk_idx;
        struct rate_control_ref *rate_ctrl;
        void *rate_ctrl_priv;
        spinlock_t lock;
@@ -380,14 +405,16 @@ struct sta_info {
        struct sta_ampdu_mlme ampdu_mlme;
        u8 timer_to_tid[IEEE80211_NUM_TIDS];
 
+       struct ieee80211_tx_latency_stat *tx_lat;
+
 #ifdef CONFIG_MAC80211_MESH
        /*
         * Mesh peer link attributes
         * TODO: move to a sub-structure that is referenced with pointer?
         */
-       __le16 llid;
-       __le16 plid;
-       __le16 reason;
+       u16 llid;
+       u16 plid;
+       u16 reason;
        u8 plink_retries;
        bool ignore_plink_timer;
        enum nl80211_plink_state plink_state;
@@ -414,6 +441,7 @@ struct sta_info {
        unsigned int beacon_loss_count;
 
        enum ieee80211_smps_mode known_smps_mode;
+       const struct ieee80211_cipher_scheme *cipher_scheme;
 
        /* keep last! */
        struct ieee80211_sta sta;
index 52a152b01b063b226fb5a523b19a4e9863eeffaf..1ee85c402439bfc886029f9ae6dfe6ec306e013f 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/export.h>
 #include <linux/etherdevice.h>
+#include <linux/time.h>
 #include <net/mac80211.h>
 #include <asm/unaligned.h>
 #include "ieee80211_i.h"
@@ -462,6 +463,77 @@ static void ieee80211_report_used_skb(struct ieee80211_local *local,
        }
 }
 
+/*
+ * Measure Tx frame completion and removal time for Tx latency statistics
+ * calculation. A single Tx frame latency should be measured from when it
+ * is entering the Kernel until we receive Tx complete confirmation indication
+ * and remove the skb.
+ */
+static void ieee80211_tx_latency_end_msrmnt(struct ieee80211_local *local,
+                                           struct sk_buff *skb,
+                                           struct sta_info *sta,
+                                           struct ieee80211_hdr *hdr)
+{
+       ktime_t skb_dprt;
+       struct timespec dprt_time;
+       u32 msrmnt;
+       u16 tid;
+       u8 *qc;
+       int i, bin_range_count, bin_count;
+       u32 *bin_ranges;
+       __le16 fc;
+       struct ieee80211_tx_latency_stat *tx_lat;
+       struct ieee80211_tx_latency_bin_ranges *tx_latency;
+       ktime_t skb_arv = skb->tstamp;
+
+       tx_latency = rcu_dereference(local->tx_latency);
+
+       /* assert Tx latency stats are enabled & frame arrived when enabled */
+       if (!tx_latency || !ktime_to_ns(skb_arv))
+               return;
+
+       fc = hdr->frame_control;
+
+       if (!ieee80211_is_data(fc)) /* make sure it is a data frame */
+               return;
+
+       /* get frame tid */
+       if (ieee80211_is_data_qos(hdr->frame_control)) {
+               qc = ieee80211_get_qos_ctl(hdr);
+               tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
+       } else {
+               tid = 0;
+       }
+
+       tx_lat = &sta->tx_lat[tid];
+
+       ktime_get_ts(&dprt_time); /* time stamp completion time */
+       skb_dprt = ktime_set(dprt_time.tv_sec, dprt_time.tv_nsec);
+       msrmnt = ktime_to_ms(ktime_sub(skb_dprt, skb_arv));
+
+       if (tx_lat->max < msrmnt) /* update stats */
+               tx_lat->max = msrmnt;
+       tx_lat->counter++;
+       tx_lat->sum += msrmnt;
+
+       if (!tx_lat->bins) /* bins not activated */
+               return;
+
+       /* count how many Tx frames transmitted with the appropriate latency */
+       bin_range_count = tx_latency->n_ranges;
+       bin_ranges = tx_latency->ranges;
+       bin_count = tx_lat->bin_count;
+
+       for (i = 0; i < bin_range_count; i++) {
+               if (msrmnt <= bin_ranges[i]) {
+                       tx_lat->bins[i]++;
+                       break;
+               }
+       }
+       if (i == bin_range_count) /* msrmnt is bigger than the biggest range */
+               tx_lat->bins[i]++;
+}
+
 /*
  * Use a static threshold for now, best value to be determined
  * by testing ...
@@ -620,6 +692,12 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
 
                if (acked)
                        sta->last_ack_signal = info->status.ack_signal;
+
+               /*
+                * Measure frame removal for tx latency
+                * statistics calculation
+                */
+               ieee80211_tx_latency_end_msrmnt(local, skb, sta, hdr);
        }
 
        rcu_read_unlock();
index d4cee98533fdc5a532a8ba74e48d6158faeb5003..e9ccf22f6dd972c8b0517c5d35a345085eb45ec6 100644 (file)
 #define CHANDEF_PR_ARG __entry->control_freq, __entry->chan_width,                     \
                        __entry->center_freq1, __entry->center_freq2
 
+#define MIN_CHANDEF_ENTRY                                                              \
+                       __field(u32, min_control_freq)                                  \
+                       __field(u32, min_chan_width)                                    \
+                       __field(u32, min_center_freq1)                                  \
+                       __field(u32, min_center_freq2)
+
+#define MIN_CHANDEF_ASSIGN(c)                                                          \
+                       __entry->min_control_freq = (c)->chan ? (c)->chan->center_freq : 0;     \
+                       __entry->min_chan_width = (c)->width;                           \
+                       __entry->min_center_freq1 = (c)->center_freq1;                  \
+                       __entry->min_center_freq2 = (c)->center_freq2;
+#define MIN_CHANDEF_PR_FMT     " min_control:%d MHz min_width:%d min_center: %d/%d MHz"
+#define MIN_CHANDEF_PR_ARG     __entry->min_control_freq, __entry->min_chan_width,     \
+                       __entry->min_center_freq1, __entry->min_center_freq2
+
 #define CHANCTX_ENTRY  CHANDEF_ENTRY                                                   \
+                       MIN_CHANDEF_ENTRY                                               \
                        __field(u8, rx_chains_static)                                   \
                        __field(u8, rx_chains_dynamic)
 #define CHANCTX_ASSIGN CHANDEF_ASSIGN(&ctx->conf.def)                                  \
+                       MIN_CHANDEF_ASSIGN(&ctx->conf.min_def)                          \
                        __entry->rx_chains_static = ctx->conf.rx_chains_static;         \
                        __entry->rx_chains_dynamic = ctx->conf.rx_chains_dynamic
-#define CHANCTX_PR_FMT CHANDEF_PR_FMT " chains:%d/%d"
-#define CHANCTX_PR_ARG CHANDEF_PR_ARG,                                                 \
+#define CHANCTX_PR_FMT CHANDEF_PR_FMT MIN_CHANDEF_PR_FMT " chains:%d/%d"
+#define CHANCTX_PR_ARG CHANDEF_PR_ARG, MIN_CHANDEF_PR_ARG,                             \
                        __entry->rx_chains_static, __entry->rx_chains_dynamic
 
 
index c558b246ef0036c38e6c8a00b338b43c46913f78..6d59e21cdb9fe8b686fdcef53ddc83a83738d0cf 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/bitmap.h>
 #include <linux/rcupdate.h>
 #include <linux/export.h>
+#include <linux/time.h>
 #include <net/net_namespace.h>
 #include <net/ieee80211_radiotap.h>
 #include <net/cfg80211.h>
@@ -557,7 +558,8 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
 
        if (unlikely(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT))
                tx->key = NULL;
-       else if (tx->sta && (key = rcu_dereference(tx->sta->ptk)))
+       else if (tx->sta &&
+                (key = rcu_dereference(tx->sta->ptk[tx->sta->ptk_idx])))
                tx->key = key;
        else if (ieee80211_is_mgmt(hdr->frame_control) &&
                 is_multicast_ether_addr(hdr->addr1) &&
@@ -840,15 +842,16 @@ static int ieee80211_fragment(struct ieee80211_tx_data *tx,
                rem -= fraglen;
                tmp = dev_alloc_skb(local->tx_headroom +
                                    frag_threshold +
-                                   IEEE80211_ENCRYPT_HEADROOM +
+                                   tx->sdata->encrypt_headroom +
                                    IEEE80211_ENCRYPT_TAILROOM);
                if (!tmp)
                        return -ENOMEM;
 
                __skb_queue_tail(&tx->skbs, tmp);
 
-               skb_reserve(tmp, local->tx_headroom +
-                                IEEE80211_ENCRYPT_HEADROOM);
+               skb_reserve(tmp,
+                           local->tx_headroom + tx->sdata->encrypt_headroom);
+
                /* copy control information */
                memcpy(tmp->cb, skb->cb, sizeof(tmp->cb));
 
@@ -1485,7 +1488,7 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
 
        headroom = local->tx_headroom;
        if (may_encrypt)
-               headroom += IEEE80211_ENCRYPT_HEADROOM;
+               headroom += sdata->encrypt_headroom;
        headroom -= skb_headroom(skb);
        headroom = max_t(int, 0, headroom);
 
@@ -1724,8 +1727,7 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
         * radar detection by itself. We can do that later by adding a
         * monitor flag interfaces used for AP support.
         */
-       if ((chan->flags & (IEEE80211_CHAN_NO_IBSS | IEEE80211_CHAN_RADAR |
-                           IEEE80211_CHAN_PASSIVE_SCAN)))
+       if ((chan->flags & (IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_RADAR)))
                goto fail_rcu;
 
        ieee80211_xmit(sdata, skb, chan->band);
@@ -1740,6 +1742,26 @@ fail:
        return NETDEV_TX_OK; /* meaning, we dealt with the skb */
 }
 
+/*
+ * Measure Tx frame arrival time for Tx latency statistics calculation
+ * A single Tx frame latency should be measured from when it is entering the
+ * Kernel until we receive Tx complete confirmation indication and the skb is
+ * freed.
+ */
+static void ieee80211_tx_latency_start_msrmnt(struct ieee80211_local *local,
+                                             struct sk_buff *skb)
+{
+       struct timespec skb_arv;
+       struct ieee80211_tx_latency_bin_ranges *tx_latency;
+
+       tx_latency = rcu_dereference(local->tx_latency);
+       if (!tx_latency)
+               return;
+
+       ktime_get_ts(&skb_arv);
+       skb->tstamp = ktime_set(skb_arv.tv_sec, skb_arv.tv_nsec);
+}
+
 /**
  * ieee80211_subif_start_xmit - netif start_xmit function for Ethernet-type
  * subinterfaces (wlan#, WDS, and VLAN interfaces)
@@ -1790,6 +1812,9 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
 
        rcu_read_lock();
 
+       /* Measure frame arrival for Tx latency statistics calculation */
+       ieee80211_tx_latency_start_msrmnt(local, skb);
+
        switch (sdata->vif.type) {
        case NL80211_IFTYPE_AP_VLAN:
                sta = rcu_dereference(sdata->u.vlan.sta);
@@ -2109,7 +2134,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
         */
 
        if (head_need > 0 || skb_cloned(skb)) {
-               head_need += IEEE80211_ENCRYPT_HEADROOM;
+               head_need += sdata->encrypt_headroom;
                head_need += local->tx_headroom;
                head_need = max_t(int, 0, head_need);
                if (ieee80211_skb_resize(sdata, skb, head_need, true)) {
index 592a18171f95e9ec5273b03307235dff2bd1c946..875e172c001c697a72f85941fd0db8ef1b28b86a 100644 (file)
@@ -1804,6 +1804,26 @@ void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata)
        mutex_unlock(&local->chanctx_mtx);
 }
 
+void ieee80211_recalc_min_chandef(struct ieee80211_sub_if_data *sdata)
+{
+       struct ieee80211_local *local = sdata->local;
+       struct ieee80211_chanctx_conf *chanctx_conf;
+       struct ieee80211_chanctx *chanctx;
+
+       mutex_lock(&local->chanctx_mtx);
+
+       chanctx_conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
+                                       lockdep_is_held(&local->chanctx_mtx));
+
+       if (WARN_ON_ONCE(!chanctx_conf))
+               goto unlock;
+
+       chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf);
+       ieee80211_recalc_chanctx_min_def(local, chanctx);
+ unlock:
+       mutex_unlock(&local->chanctx_mtx);
+}
+
 static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id)
 {
        int i;
@@ -2259,14 +2279,17 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
 void ieee80211_dfs_cac_cancel(struct ieee80211_local *local)
 {
        struct ieee80211_sub_if_data *sdata;
+       struct cfg80211_chan_def chandef;
 
        mutex_lock(&local->iflist_mtx);
        list_for_each_entry(sdata, &local->interfaces, list) {
                cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
 
                if (sdata->wdev.cac_started) {
+                       chandef = sdata->vif.bss_conf.chandef;
                        ieee80211_vif_release_channel(sdata);
                        cfg80211_cac_event(sdata->dev,
+                                          &chandef,
                                           NL80211_RADAR_CAC_ABORTED,
                                           GFP_KERNEL);
                }
@@ -2278,17 +2301,15 @@ void ieee80211_dfs_radar_detected_work(struct work_struct *work)
 {
        struct ieee80211_local *local =
                container_of(work, struct ieee80211_local, radar_detected_work);
-       struct cfg80211_chan_def chandef;
+       struct cfg80211_chan_def chandef = local->hw.conf.chandef;
 
        ieee80211_dfs_cac_cancel(local);
 
        if (local->use_chanctx)
                /* currently not handled */
                WARN_ON(1);
-       else {
-               chandef = local->hw.conf.chandef;
+       else
                cfg80211_radar_event(local->hw.wiphy, &chandef, GFP_KERNEL);
-       }
 }
 
 void ieee80211_radar_detected(struct ieee80211_hw *hw)
@@ -2447,7 +2468,6 @@ int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
 
        if (ieee80211_vif_is_mesh(&sdata->vif)) {
                struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
-               __le16 pre_value;
 
                skb_put(skb, 8);
                *pos++ = WLAN_EID_CHAN_SWITCH_PARAM;            /* EID */
@@ -2459,16 +2479,78 @@ int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
                          WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT : 0x00;
                put_unaligned_le16(WLAN_REASON_MESH_CHAN, pos); /* Reason Cd */
                pos += 2;
-               if (!ifmsh->pre_value)
-                       ifmsh->pre_value = 1;
-               else
-                       ifmsh->pre_value++;
-               pre_value = cpu_to_le16(ifmsh->pre_value);
-               memcpy(pos, &pre_value, 2);             /* Precedence Value */
+               put_unaligned_le16(ifmsh->pre_value, pos);/* Precedence Value */
                pos += 2;
-               ifmsh->chsw_init = true;
        }
 
        ieee80211_tx_skb(sdata, skb);
        return 0;
 }
+
+bool ieee80211_cs_valid(const struct ieee80211_cipher_scheme *cs)
+{
+       return !(cs == NULL || cs->cipher == 0 ||
+                cs->hdr_len < cs->pn_len + cs->pn_off ||
+                cs->hdr_len <= cs->key_idx_off ||
+                cs->key_idx_shift > 7 ||
+                cs->key_idx_mask == 0);
+}
+
+bool ieee80211_cs_list_valid(const struct ieee80211_cipher_scheme *cs, int n)
+{
+       int i;
+
+       /* Ensure we have enough iftype bitmap space for all iftype values */
+       WARN_ON((NUM_NL80211_IFTYPES / 8 + 1) > sizeof(cs[0].iftype));
+
+       for (i = 0; i < n; i++)
+               if (!ieee80211_cs_valid(&cs[i]))
+                       return false;
+
+       return true;
+}
+
+const struct ieee80211_cipher_scheme *
+ieee80211_cs_get(struct ieee80211_local *local, u32 cipher,
+                enum nl80211_iftype iftype)
+{
+       const struct ieee80211_cipher_scheme *l = local->hw.cipher_schemes;
+       int n = local->hw.n_cipher_schemes;
+       int i;
+       const struct ieee80211_cipher_scheme *cs = NULL;
+
+       for (i = 0; i < n; i++) {
+               if (l[i].cipher == cipher) {
+                       cs = &l[i];
+                       break;
+               }
+       }
+
+       if (!cs || !(cs->iftype & BIT(iftype)))
+               return NULL;
+
+       return cs;
+}
+
+int ieee80211_cs_headroom(struct ieee80211_local *local,
+                         struct cfg80211_crypto_settings *crypto,
+                         enum nl80211_iftype iftype)
+{
+       const struct ieee80211_cipher_scheme *cs;
+       int headroom = IEEE80211_ENCRYPT_HEADROOM;
+       int i;
+
+       for (i = 0; i < crypto->n_ciphers_pairwise; i++) {
+               cs = ieee80211_cs_get(local, crypto->ciphers_pairwise[i],
+                                     iftype);
+
+               if (cs && headroom < cs->hdr_len)
+                       headroom = cs->hdr_len;
+       }
+
+       cs = ieee80211_cs_get(local, crypto->cipher_group, iftype);
+       if (cs && headroom < cs->hdr_len)
+               headroom = cs->hdr_len;
+
+       return headroom;
+}
index de0112785aae19a8b23b2f8f84b364c80d27e8b3..d75f35c6e1a0884eb9452030cb27bcafb33deeab 100644 (file)
@@ -182,16 +182,15 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
                         IEEE80211_VHT_CAP_SHORT_GI_160);
 
        /* remaining ones */
-       if (own_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE) {
+       if (own_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE)
                vht_cap->cap |= cap_info &
                                (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
-                                IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MAX);
-       }
+                                IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK);
 
        if (own_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)
                vht_cap->cap |= cap_info &
                                (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
-                                IEEE80211_VHT_CAP_BEAMFORMEE_STS_MAX);
+                                IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK);
 
        if (own_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)
                vht_cap->cap |= cap_info &
index d6572822076367cdf203207892a2880c7e4487c2..7313d379c0d32aea2c6a152c9756263ff7bf523f 100644 (file)
@@ -545,6 +545,106 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
        return RX_CONTINUE;
 }
 
+static ieee80211_tx_result
+ieee80211_crypto_cs_encrypt(struct ieee80211_tx_data *tx,
+                           struct sk_buff *skb)
+{
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+       struct ieee80211_key *key = tx->key;
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       const struct ieee80211_cipher_scheme *cs = key->sta->cipher_scheme;
+       int hdrlen;
+       u8 *pos;
+
+       if (info->control.hw_key &&
+           !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)) {
+               /* hwaccel has no need for preallocated head room */
+               return TX_CONTINUE;
+       }
+
+       if (unlikely(skb_headroom(skb) < cs->hdr_len &&
+                    pskb_expand_head(skb, cs->hdr_len, 0, GFP_ATOMIC)))
+               return TX_DROP;
+
+       hdrlen = ieee80211_hdrlen(hdr->frame_control);
+
+       pos = skb_push(skb, cs->hdr_len);
+       memmove(pos, pos + cs->hdr_len, hdrlen);
+       skb_set_network_header(skb, skb_network_offset(skb) + cs->hdr_len);
+
+       return TX_CONTINUE;
+}
+
+static inline int ieee80211_crypto_cs_pn_compare(u8 *pn1, u8 *pn2, int len)
+{
+       int i;
+
+       /* pn is little endian */
+       for (i = len - 1; i >= 0; i--) {
+               if (pn1[i] < pn2[i])
+                       return -1;
+               else if (pn1[i] > pn2[i])
+                       return 1;
+       }
+
+       return 0;
+}
+
+static ieee80211_rx_result
+ieee80211_crypto_cs_decrypt(struct ieee80211_rx_data *rx)
+{
+       struct ieee80211_key *key = rx->key;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
+       const struct ieee80211_cipher_scheme *cs = NULL;
+       int hdrlen = ieee80211_hdrlen(hdr->frame_control);
+       struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
+       int data_len;
+       u8 *rx_pn;
+       u8 *skb_pn;
+       u8 qos_tid;
+
+       if (!rx->sta || !rx->sta->cipher_scheme ||
+           !(status->flag & RX_FLAG_DECRYPTED))
+               return RX_DROP_UNUSABLE;
+
+       if (!ieee80211_is_data(hdr->frame_control))
+               return RX_CONTINUE;
+
+       cs = rx->sta->cipher_scheme;
+
+       data_len = rx->skb->len - hdrlen - cs->hdr_len;
+
+       if (data_len < 0)
+               return RX_DROP_UNUSABLE;
+
+       if (ieee80211_is_data_qos(hdr->frame_control))
+               qos_tid = *ieee80211_get_qos_ctl(hdr) &
+                               IEEE80211_QOS_CTL_TID_MASK;
+       else
+               qos_tid = 0;
+
+       if (skb_linearize(rx->skb))
+               return RX_DROP_UNUSABLE;
+
+       hdr = (struct ieee80211_hdr *)rx->skb->data;
+
+       rx_pn = key->u.gen.rx_pn[qos_tid];
+       skb_pn = rx->skb->data + hdrlen + cs->pn_off;
+
+       if (ieee80211_crypto_cs_pn_compare(skb_pn, rx_pn, cs->pn_len) <= 0)
+               return RX_DROP_UNUSABLE;
+
+       memcpy(rx_pn, skb_pn, cs->pn_len);
+
+       /* remove security header and MIC */
+       if (pskb_trim(rx->skb, rx->skb->len - cs->mic_len))
+               return RX_DROP_UNUSABLE;
+
+       memmove(rx->skb->data + cs->hdr_len, rx->skb->data, hdrlen);
+       skb_pull(rx->skb, cs->hdr_len);
+
+       return RX_CONTINUE;
+}
 
 static void bip_aad(struct sk_buff *skb, u8 *aad)
 {
@@ -685,6 +785,7 @@ ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx)
 {
        struct sk_buff *skb;
        struct ieee80211_tx_info *info = NULL;
+       ieee80211_tx_result res;
 
        skb_queue_walk(&tx->skbs, skb) {
                info  = IEEE80211_SKB_CB(skb);
@@ -692,9 +793,24 @@ ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx)
                /* handle hw-only algorithm */
                if (!info->control.hw_key)
                        return TX_DROP;
+
+               if (tx->key->sta->cipher_scheme) {
+                       res = ieee80211_crypto_cs_encrypt(tx, skb);
+                       if (res != TX_CONTINUE)
+                               return res;
+               }
        }
 
        ieee80211_tx_set_protected(tx);
 
        return TX_CONTINUE;
 }
+
+ieee80211_rx_result
+ieee80211_crypto_hw_decrypt(struct ieee80211_rx_data *rx)
+{
+       if (rx->sta->cipher_scheme)
+               return ieee80211_crypto_cs_decrypt(rx);
+
+       return RX_DROP_UNUSABLE;
+}
index 07e33f899c71fc52f9ff1771cd283226a8a64084..62e5a12dfe0a24010b32eec210d7a38a1c4c3eb8 100644 (file)
@@ -34,5 +34,7 @@ ieee80211_rx_result
 ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx);
 ieee80211_tx_result
 ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx);
+ieee80211_rx_result
+ieee80211_crypto_hw_decrypt(struct ieee80211_rx_data *rx);
 
 #endif /* WPA_H */
index a2d6263b6c648e97c663025660ad47320c2c08ff..44cd4f58adf08b914b871d7399942fb58168a623 100644 (file)
@@ -21,7 +21,7 @@ config IP_SET_MAX
          You can define here default value of the maximum number 
          of IP sets for the kernel.
 
-         The value can be overriden by the 'max_sets' module
+         The value can be overridden by the 'max_sets' module
          parameter of the 'ip_set' module.
 
 config IP_SET_BITMAP_IP
index 2bc2dec20b007026e78aba74451e70039c6e5988..6226803fc490ce33c53994c344a1c034b9b0cce9 100644 (file)
@@ -59,7 +59,7 @@ hash_netnet4_data_equal(const struct hash_netnet4_elem *ip1,
                     u32 *multi)
 {
        return ip1->ipcmp == ip2->ipcmp &&
-              ip2->ccmp == ip2->ccmp;
+              ip1->ccmp == ip2->ccmp;
 }
 
 static inline int
index c8beafd401aa283f0befa0494e02649359bab83f..d5f41514f5778d23293f6b9e36fe1bd9b83276e0 100644 (file)
@@ -19,8 +19,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  *
  * Authors:
index dcddc49c0e08363044195695138543e4277f83f0..f93b7d06f4be9525ad4ab4314a106b01e85749ba 100644 (file)
@@ -1717,6 +1717,19 @@ nf_tables_delrule_one(struct nft_ctx *ctx, struct nft_rule *rule)
        return -ENOENT;
 }
 
+static int nf_table_delrule_by_chain(struct nft_ctx *ctx)
+{
+       struct nft_rule *rule;
+       int err;
+
+       list_for_each_entry(rule, &ctx->chain->rules, list) {
+               err = nf_tables_delrule_one(ctx, rule);
+               if (err < 0)
+                       return err;
+       }
+       return 0;
+}
+
 static int nf_tables_delrule(struct sock *nlsk, struct sk_buff *skb,
                             const struct nlmsghdr *nlh,
                             const struct nlattr * const nla[])
@@ -1725,8 +1738,8 @@ static int nf_tables_delrule(struct sock *nlsk, struct sk_buff *skb,
        const struct nft_af_info *afi;
        struct net *net = sock_net(skb->sk);
        const struct nft_table *table;
-       struct nft_chain *chain;
-       struct nft_rule *rule, *tmp;
+       struct nft_chain *chain = NULL;
+       struct nft_rule *rule;
        int family = nfmsg->nfgen_family, err = 0;
        struct nft_ctx ctx;
 
@@ -1738,22 +1751,29 @@ static int nf_tables_delrule(struct sock *nlsk, struct sk_buff *skb,
        if (IS_ERR(table))
                return PTR_ERR(table);
 
-       chain = nf_tables_chain_lookup(table, nla[NFTA_RULE_CHAIN]);
-       if (IS_ERR(chain))
-               return PTR_ERR(chain);
+       if (nla[NFTA_RULE_CHAIN]) {
+               chain = nf_tables_chain_lookup(table, nla[NFTA_RULE_CHAIN]);
+               if (IS_ERR(chain))
+                       return PTR_ERR(chain);
+       }
 
        nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla);
 
-       if (nla[NFTA_RULE_HANDLE]) {
-               rule = nf_tables_rule_lookup(chain, nla[NFTA_RULE_HANDLE]);
-               if (IS_ERR(rule))
-                       return PTR_ERR(rule);
+       if (chain) {
+               if (nla[NFTA_RULE_HANDLE]) {
+                       rule = nf_tables_rule_lookup(chain,
+                                                    nla[NFTA_RULE_HANDLE]);
+                       if (IS_ERR(rule))
+                               return PTR_ERR(rule);
 
-               err = nf_tables_delrule_one(&ctx, rule);
-       } else {
-               /* Remove all rules in this chain */
-               list_for_each_entry_safe(rule, tmp, &chain->rules, list) {
                        err = nf_tables_delrule_one(&ctx, rule);
+               } else {
+                       err = nf_table_delrule_by_chain(&ctx);
+               }
+       } else {
+               list_for_each_entry(chain, &table->chains, list) {
+                       ctx.chain = chain;
+                       err = nf_table_delrule_by_chain(&ctx);
                        if (err < 0)
                                break;
                }
index 7278145e6a68385c71b1d64efccc3aee71cb2412..69f78e96fdb44a5c293a92e53a98559b1ddf2209 100644 (file)
@@ -17,8 +17,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/module.h>
index 9ff035c7140324632965fbf82764d532d4d0a284..a3910fc2122bc1aa560815394b525098cb02e85c 100644 (file)
@@ -325,21 +325,24 @@ static void htable_gc(unsigned long htlong)
        add_timer(&ht->timer);
 }
 
-static void htable_destroy(struct xt_hashlimit_htable *hinfo)
+static void htable_remove_proc_entry(struct xt_hashlimit_htable *hinfo)
 {
        struct hashlimit_net *hashlimit_net = hashlimit_pernet(hinfo->net);
        struct proc_dir_entry *parent;
 
-       del_timer_sync(&hinfo->timer);
-
        if (hinfo->family == NFPROTO_IPV4)
                parent = hashlimit_net->ipt_hashlimit;
        else
                parent = hashlimit_net->ip6t_hashlimit;
 
-       if(parent != NULL)
+       if (parent != NULL)
                remove_proc_entry(hinfo->name, parent);
+}
 
+static void htable_destroy(struct xt_hashlimit_htable *hinfo)
+{
+       del_timer_sync(&hinfo->timer);
+       htable_remove_proc_entry(hinfo);
        htable_selective_cleanup(hinfo, select_all);
        kfree(hinfo->name);
        vfree(hinfo);
@@ -883,21 +886,15 @@ static int __net_init hashlimit_proc_net_init(struct net *net)
 static void __net_exit hashlimit_proc_net_exit(struct net *net)
 {
        struct xt_hashlimit_htable *hinfo;
-       struct proc_dir_entry *pde;
        struct hashlimit_net *hashlimit_net = hashlimit_pernet(net);
 
-       /* recent_net_exit() is called before recent_mt_destroy(). Make sure
-        * that the parent xt_recent proc entry is is empty before trying to
-        * remove it.
+       /* hashlimit_net_exit() is called before hashlimit_mt_destroy().
+        * Make sure that the parent ipt_hashlimit and ip6t_hashlimit proc
+        * entries is empty before trying to remove it.
         */
        mutex_lock(&hashlimit_mutex);
-       pde = hashlimit_net->ipt_hashlimit;
-       if (pde == NULL)
-               pde = hashlimit_net->ip6t_hashlimit;
-
        hlist_for_each_entry(hinfo, &hashlimit_net->htables, node)
-               remove_proc_entry(hinfo->name, pde);
-
+               htable_remove_proc_entry(hinfo);
        hashlimit_net->ipt_hashlimit = NULL;
        hashlimit_net->ip6t_hashlimit = NULL;
        mutex_unlock(&hashlimit_mutex);
index 647d989a01e6b740f2d6c5b3d4f463259cecf643..7174611bd67294179e3456c06ab4c7155e71a77a 100644 (file)
@@ -13,8 +13,7 @@
  * 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
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 #include <linux/module.h>
index 6f1701322fb695207684abc400452bb8e749c57a..d0a3acfa5742a295b63a875b970075447eb19cf4 100644 (file)
@@ -24,8 +24,7 @@
  * 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
+ * along with this program;  if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index a1287ce181300cef285ec6748d641c946453c1a2..d0f38bc9af6d8f485f3abe5cf5b923359d314ac1 100644 (file)
@@ -24,8 +24,7 @@
  * 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
+ * along with this program;  if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 69345cebe3a3e397beffbe56536bf971fb81ddf9..c2f2a53a487919bcb45e882b9ff8859c699b9d56 100644 (file)
@@ -23,8 +23,7 @@
  * 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
+ * along with this program;  if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index d24d774bfd62c065a5be92fb4e5e97cbb275e3ce..875826808b00bfa790a26a6abb70f0bf17278d46 100644 (file)
@@ -23,8 +23,7 @@
  * 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
+ * along with this program;  if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 85d842e6e43187998232441f5e2228244cb1cb95..f0cb92f3ddafa47063f82d54232e27308ea539fa 100644 (file)
@@ -24,8 +24,7 @@
  * 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
+ * along with this program;  if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index b9be0eed89801ab194b8f6a97899e7bbf9c50ec3..680caf4dff567f61ccaa41a70a9276101ac27fcd 100644 (file)
@@ -24,8 +24,7 @@
  * 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
+ * along with this program;  if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index dce1bebf7aecb98f4cfae0beb45a9b3c576c21d3..3045a964f39c82152574ef4479e01a0254c88f5a 100644 (file)
@@ -23,8 +23,7 @@
  * 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
+ * along with this program;  if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 8ef83ee97c6ad0fa934bbbe3d4988003e9ee287b..e66e977ef2fa0cf3ec52bc2ea3d6604d17de3e47 100644 (file)
@@ -23,8 +23,7 @@
  * 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
+ * along with this program;  if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 5a9f31ce5799baef8b6e83c4d56222cff7603d2b..8b6e1ab62b485729dca126c8ab6a82671623d1fe 100644 (file)
@@ -23,8 +23,7 @@
  * 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
+ * along with this program;  if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 43817d73ccf997b69ec15da814e274404e08a2c7..78a63c18779e443be49b5a9509499ab7cb43869a 100644 (file)
@@ -23,8 +23,7 @@
  * 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
+ * along with this program;  if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 700af49022a040a2d11a23747e51e1a0b6b9eca4..3a9e5dc9511b4a83564f6e99a9b7ef947aca0ea4 100644 (file)
@@ -23,8 +23,7 @@
  * 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
+ * along with this program;  if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 9650c4ad5f886ea29a7a02c82fffa100284ea5d7..1e779bb7fa435a7096342a1360b696b4a09a60cf 100644 (file)
@@ -23,8 +23,7 @@
  * 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
+ * along with this program;  if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 81969785e279e6b47c5f50f391ed8bd371ad04e3..4a397cde1a48e4f296332bc8405d78a0ee612a25 100644 (file)
@@ -23,8 +23,7 @@
  * 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
+ * along with this program;  if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 4518a57aa5febb14db1c1d750f217102dd8fd2a9..713671ae45aff688e693d6087ae4d8ce9e986f48 100644 (file)
@@ -74,9 +74,12 @@ static struct list_head family_ht[GENL_FAM_TAB_SIZE];
  * Bit 17 is marked as already used since the VFS quota code
  * also abused this API and relied on family == group ID, we
  * cater to that by giving it a static family and group ID.
+ * Bit 18 is marked as already used since the PMCRAID driver
+ * did the same thing as the VFS quota code (maybe copied?)
  */
 static unsigned long mc_group_start = 0x3 | BIT(GENL_ID_CTRL) |
-                                     BIT(GENL_ID_VFS_DQUOT);
+                                     BIT(GENL_ID_VFS_DQUOT) |
+                                     BIT(GENL_ID_PMCRAID);
 static unsigned long *mc_groups = &mc_group_start;
 static unsigned long mc_groups_longs = 1;
 
@@ -139,6 +142,7 @@ static u16 genl_generate_id(void)
 
        for (i = 0; i <= GENL_MAX_ID - GENL_MIN_ID; i++) {
                if (id_gen_idx != GENL_ID_VFS_DQUOT &&
+                   id_gen_idx != GENL_ID_PMCRAID &&
                    !genl_family_find_byid(id_gen_idx))
                        return id_gen_idx;
                if (++id_gen_idx > GENL_MAX_ID)
@@ -214,7 +218,7 @@ static int genl_validate_assign_mc_groups(struct genl_family *family)
 {
        int first_id;
        int n_groups = family->n_mcgrps;
-       int err, i;
+       int err = 0, i;
        bool groups_allocated = false;
 
        if (!n_groups)
@@ -236,9 +240,12 @@ static int genl_validate_assign_mc_groups(struct genl_family *family)
        } else if (strcmp(family->name, "NET_DM") == 0) {
                first_id = 1;
                BUG_ON(n_groups != 1);
-       } else if (strcmp(family->name, "VFS_DQUOT") == 0) {
+       } else if (family->id == GENL_ID_VFS_DQUOT) {
                first_id = GENL_ID_VFS_DQUOT;
                BUG_ON(n_groups != 1);
+       } else if (family->id == GENL_ID_PMCRAID) {
+               first_id = GENL_ID_PMCRAID;
+               BUG_ON(n_groups != 1);
        } else {
                groups_allocated = true;
                err = genl_allocate_reserve_groups(n_groups, &first_id);
index 9d68441e2a5ab571ab5e5d20891251bedd3b2d7b..2277276f52bcd2f375f0319476b1cfecdf6b2d76 100644 (file)
@@ -16,9 +16,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/nfc.h>
index 872529105abc7c3a2e41b9d579e934e019e8e5ff..02ab34132157066d9a0def95276b7abe3f8d7f71 100644 (file)
@@ -16,9 +16,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__
index 64f922be928127d8837899ae081044b48190447f..a9f4d2e62d8de267a94a689fe3fab53a1a79339d 100644 (file)
@@ -12,9 +12,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #define pr_fmt(fmt) "hci: %s: " fmt, __func__
index d07ca4c5cf8c988c6240d0f6d9c666fe2ef76c4a..3b9610031baa2271fd7b00648b00709bdc483b95 100644 (file)
@@ -12,9 +12,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #define pr_fmt(fmt) "hci: %s: " fmt, __func__
index b274d12c18ac5d7b5ac3a6aa4e4fc943738d6eea..c3d2e2c1394cb648ff548f19fb0741794ea55fea 100644 (file)
@@ -12,9 +12,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef __LOCAL_HCI_H
index b6b4109f2343eb9cc9628c1c0ba07342d4f6c6f0..e9de1514656ecff2ff17253e65edc5c438a1cee0 100644 (file)
@@ -12,9 +12,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #define pr_fmt(fmt) "hci: %s: " fmt, __func__
index fe5e966e5b88efb9d24c24015ad38a3c4642e12a..a07d2b81848781af7ace0becc7fa233726f34e8f 100644 (file)
@@ -13,9 +13,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <net/nfc/llc.h>
index 7be0b7f3ceb6aa34ec3adfa5f6b077c79cef3b24..5dad4c57ffb3c59f3a2759bd34fc26306c5de5bd 100644 (file)
@@ -13,9 +13,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef __LOCAL_LLC_H_
index 87b10291b40f4d8b003ae5443d96c9a78d321790..d0435d5a197b36006c5e61811a684ba605ed5708 100644 (file)
@@ -13,9 +13,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/types.h>
index 27b313befc35eff1f5cfceb41f8ecf9be618c159..719ad0ac40ded8bfd2d0d633117dc7d318ee1b05 100644 (file)
@@ -13,9 +13,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #define pr_fmt(fmt) "shdlc: %s: " fmt, __func__
index f4d48b57ea113467807d0dd7517c4263bcd64939..de1789e3cc82fc137221535fa3bdf5fa77120c77 100644 (file)
@@ -12,9 +12,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 enum llcp_state {
index 1017894807c05a2c557cab7987450d52663156f8..693cd1aad582314a81accc30d60e528eb0ad2335 100644 (file)
@@ -12,9 +12,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #define pr_fmt(fmt) "llcp: %s: " fmt, __func__
index 81cd3416c7d4dfaae5805441adb6179b210374a3..1349074e1ffc09458cd307f063324d83423d4e46 100644 (file)
@@ -12,9 +12,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #define pr_fmt(fmt) "llcp: %s: " fmt, __func__
index 824c6056bf823b0852b116af45698da916cdc772..69fbc8dadba745c5bf077d0b79be853cc2fde545 100644 (file)
@@ -12,9 +12,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #define pr_fmt(fmt) "llcp: %s: " fmt, __func__
index b943d46a1644324757bd60950a07eb02cc50f7ac..f0e955e3a3853ee0dabc1daa6f35318dd68fab51 100644 (file)
@@ -20,8 +20,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 2a9399dd6c685566928054b16e2734984d737c94..6c3aef852876c98acc09f6c8c554a60df1d7990e 100644 (file)
@@ -16,8 +16,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index 6b7fd26c68d91a44d86111c6e46b433b8e5d1692..ed774a2e989a22da8ec94e35eaa5d1bca644fd89 100644 (file)
@@ -20,8 +20,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index b2aa98ef0927cb5760f72fb40d016a0b1dcf5575..1e905097456b77501bc0a950aa932c45205a8eb1 100644 (file)
@@ -20,8 +20,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index dd072f38ad00f5241d2cdc1299965d8bcc3966b9..041de51ccdbe103de6665c8f8a9537e194de5478 100644 (file)
@@ -20,8 +20,7 @@
  *  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
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  */
 
index a9b2342d5253295b607f3a3a1aa760e47c4d5ebe..ebbf6fb88b3596708597331ae630be2a7dcade6d 100644 (file)
@@ -16,9 +16,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__
index aaf606fc1faa5d2d9a46a691fed2fa3840ea094a..9d6e74f7e6b34ba5ed0d9022a96fdc8061b479c7 100644 (file)
@@ -16,9 +16,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef __LOCAL_NFC_H
index 66bcd2eb577374bebb032dd32053a2e0835aed74..c27a6e86cae459f0f70c2c4875614edac3518f98 100644 (file)
@@ -16,9 +16,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__
index ac27c86ef6d11e00c2ecb1512b09bbda73c3eefc..9d70f1349926c13c21d62326d2b501c6f83472c3 100644 (file)
@@ -237,6 +237,82 @@ struct packet_skb_cb {
 static void __fanout_unlink(struct sock *sk, struct packet_sock *po);
 static void __fanout_link(struct sock *sk, struct packet_sock *po);
 
+static int packet_direct_xmit(struct sk_buff *skb)
+{
+       struct net_device *dev = skb->dev;
+       const struct net_device_ops *ops = dev->netdev_ops;
+       netdev_features_t features;
+       struct netdev_queue *txq;
+       u16 queue_map;
+       int ret;
+
+       if (unlikely(!netif_running(dev) ||
+                    !netif_carrier_ok(dev))) {
+               kfree_skb(skb);
+               return NET_XMIT_DROP;
+       }
+
+       features = netif_skb_features(skb);
+       if (skb_needs_linearize(skb, features) &&
+           __skb_linearize(skb)) {
+               kfree_skb(skb);
+               return NET_XMIT_DROP;
+       }
+
+       queue_map = skb_get_queue_mapping(skb);
+       txq = netdev_get_tx_queue(dev, queue_map);
+
+       __netif_tx_lock_bh(txq);
+       if (unlikely(netif_xmit_frozen_or_stopped(txq))) {
+               ret = NETDEV_TX_BUSY;
+               kfree_skb(skb);
+               goto out;
+       }
+
+       ret = ops->ndo_start_xmit(skb, dev);
+       if (likely(dev_xmit_complete(ret)))
+               txq_trans_update(txq);
+       else
+               kfree_skb(skb);
+out:
+       __netif_tx_unlock_bh(txq);
+       return ret;
+}
+
+static struct net_device *packet_cached_dev_get(struct packet_sock *po)
+{
+       struct net_device *dev;
+
+       rcu_read_lock();
+       dev = rcu_dereference(po->cached_dev);
+       if (likely(dev))
+               dev_hold(dev);
+       rcu_read_unlock();
+
+       return dev;
+}
+
+static void packet_cached_dev_assign(struct packet_sock *po,
+                                    struct net_device *dev)
+{
+       rcu_assign_pointer(po->cached_dev, dev);
+}
+
+static void packet_cached_dev_reset(struct packet_sock *po)
+{
+       RCU_INIT_POINTER(po->cached_dev, NULL);
+}
+
+static bool packet_use_direct_xmit(const struct packet_sock *po)
+{
+       return po->xmit == packet_direct_xmit;
+}
+
+static u16 packet_pick_tx_queue(struct net_device *dev)
+{
+       return (u16) smp_processor_id() % dev->real_num_tx_queues;
+}
+
 /* register_prot_hook must be invoked with the po->bind_lock held,
  * or from a context in which asynchronous accesses to the packet
  * socket is not possible (packet_create()).
@@ -246,12 +322,10 @@ static void register_prot_hook(struct sock *sk)
        struct packet_sock *po = pkt_sk(sk);
 
        if (!po->running) {
-               if (po->fanout) {
+               if (po->fanout)
                        __fanout_link(sk, po);
-               } else {
+               else
                        dev_add_pack(&po->prot_hook);
-                       rcu_assign_pointer(po->cached_dev, po->prot_hook.dev);
-               }
 
                sock_hold(sk);
                po->running = 1;
@@ -270,12 +344,11 @@ static void __unregister_prot_hook(struct sock *sk, bool sync)
        struct packet_sock *po = pkt_sk(sk);
 
        po->running = 0;
-       if (po->fanout) {
+
+       if (po->fanout)
                __fanout_unlink(sk, po);
-       } else {
+       else
                __dev_remove_pack(&po->prot_hook);
-               RCU_INIT_POINTER(po->cached_dev, NULL);
-       }
 
        __sock_put(sk);
 
@@ -437,11 +510,12 @@ static void prb_shutdown_retire_blk_timer(struct packet_sock *po,
 {
        struct tpacket_kbdq_core *pkc;
 
-       pkc = tx_ring ? &po->tx_ring.prb_bdqc : &po->rx_ring.prb_bdqc;
+       pkc = tx_ring ? GET_PBDQC_FROM_RB(&po->tx_ring) :
+                       GET_PBDQC_FROM_RB(&po->rx_ring);
 
-       spin_lock(&rb_queue->lock);
+       spin_lock_bh(&rb_queue->lock);
        pkc->delete_blk_timer = 1;
-       spin_unlock(&rb_queue->lock);
+       spin_unlock_bh(&rb_queue->lock);
 
        prb_del_retire_blk_timer(pkc);
 }
@@ -463,7 +537,8 @@ static void prb_setup_retire_blk_timer(struct packet_sock *po, int tx_ring)
        if (tx_ring)
                BUG();
 
-       pkc = tx_ring ? &po->tx_ring.prb_bdqc : &po->rx_ring.prb_bdqc;
+       pkc = tx_ring ? GET_PBDQC_FROM_RB(&po->tx_ring) :
+                       GET_PBDQC_FROM_RB(&po->rx_ring);
        prb_init_blk_timer(po, pkc, prb_retire_rx_blk_timer_expired);
 }
 
@@ -521,7 +596,7 @@ static void init_prb_bdqc(struct packet_sock *po,
                        struct pgv *pg_vec,
                        union tpacket_req_u *req_u, int tx_ring)
 {
-       struct tpacket_kbdq_core *p1 = &rb->prb_bdqc;
+       struct tpacket_kbdq_core *p1 = GET_PBDQC_FROM_RB(rb);
        struct tpacket_block_desc *pbd;
 
        memset(p1, 0x0, sizeof(*p1));
@@ -585,7 +660,7 @@ static void _prb_refresh_rx_retire_blk_timer(struct tpacket_kbdq_core *pkc)
 static void prb_retire_rx_blk_timer_expired(unsigned long data)
 {
        struct packet_sock *po = (struct packet_sock *)data;
-       struct tpacket_kbdq_core *pkc = &po->rx_ring.prb_bdqc;
+       struct tpacket_kbdq_core *pkc = GET_PBDQC_FROM_RB(&po->rx_ring);
        unsigned int frozen;
        struct tpacket_block_desc *pbd;
 
@@ -1971,9 +2046,10 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
 
        skb_reserve(skb, hlen);
        skb_reset_network_header(skb);
-       skb_probe_transport_header(skb, 0);
 
-       if (po->tp_tx_has_off) {
+       if (!packet_use_direct_xmit(po))
+               skb_probe_transport_header(skb, 0);
+       if (unlikely(po->tp_tx_has_off)) {
                int off_min, off_max, off;
                off_min = po->tp_hdrlen - sizeof(struct sockaddr_ll);
                off_max = po->tx_ring.frame_size - tp_len;
@@ -2059,19 +2135,6 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
        return tp_len;
 }
 
-static struct net_device *packet_cached_dev_get(struct packet_sock *po)
-{
-       struct net_device *dev;
-
-       rcu_read_lock();
-       dev = rcu_dereference(po->cached_dev);
-       if (dev)
-               dev_hold(dev);
-       rcu_read_unlock();
-
-       return dev;
-}
-
 static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
 {
        struct sk_buff *skb;
@@ -2088,7 +2151,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
 
        mutex_lock(&po->pg_vec_lock);
 
-       if (saddr == NULL) {
+       if (likely(saddr == NULL)) {
                dev     = packet_cached_dev_get(po);
                proto   = po->num;
                addr    = NULL;
@@ -2156,12 +2219,13 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
                        }
                }
 
+               skb_set_queue_mapping(skb, packet_pick_tx_queue(dev));
                skb->destructor = tpacket_destruct_skb;
                __packet_set_status(po, ph, TP_STATUS_SENDING);
                atomic_inc(&po->tx_ring.pending);
 
                status = TP_STATUS_SEND_REQUEST;
-               err = dev_queue_xmit(skb);
+               err = po->xmit(skb);
                if (unlikely(err > 0)) {
                        err = net_xmit_errno(err);
                        if (err && __packet_get_status(po, ph) ==
@@ -2220,8 +2284,7 @@ static struct sk_buff *packet_alloc_skb(struct sock *sk, size_t prepad,
        return skb;
 }
 
-static int packet_snd(struct socket *sock,
-                         struct msghdr *msg, size_t len)
+static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
 {
        struct sock *sk = sock->sk;
        struct sockaddr_ll *saddr = (struct sockaddr_ll *)msg->msg_name;
@@ -2242,7 +2305,7 @@ static int packet_snd(struct socket *sock,
         *      Get and verify the address.
         */
 
-       if (saddr == NULL) {
+       if (likely(saddr == NULL)) {
                dev     = packet_cached_dev_get(po);
                proto   = po->num;
                addr    = NULL;
@@ -2366,6 +2429,7 @@ static int packet_snd(struct socket *sock,
        skb->dev = dev;
        skb->priority = sk->sk_priority;
        skb->mark = sk->sk_mark;
+       skb_set_queue_mapping(skb, packet_pick_tx_queue(dev));
 
        if (po->has_vnet_hdr) {
                if (vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) {
@@ -2386,16 +2450,12 @@ static int packet_snd(struct socket *sock,
                len += vnet_hdr_len;
        }
 
-       skb_probe_transport_header(skb, reserve);
-
+       if (!packet_use_direct_xmit(po))
+               skb_probe_transport_header(skb, reserve);
        if (unlikely(extra_len == 4))
                skb->no_fcs = 1;
 
-       /*
-        *      Now send it
-        */
-
-       err = dev_queue_xmit(skb);
+       err = po->xmit(skb);
        if (err > 0 && (err = net_xmit_errno(err)) != 0)
                goto out_unlock;
 
@@ -2417,6 +2477,7 @@ static int packet_sendmsg(struct kiocb *iocb, struct socket *sock,
 {
        struct sock *sk = sock->sk;
        struct packet_sock *po = pkt_sk(sk);
+
        if (po->tx_ring.pg_vec)
                return tpacket_snd(po, msg);
        else
@@ -2451,6 +2512,8 @@ static int packet_release(struct socket *sock)
 
        spin_lock(&po->bind_lock);
        unregister_prot_hook(sk, false);
+       packet_cached_dev_reset(po);
+
        if (po->prot_hook.dev) {
                dev_put(po->prot_hook.dev);
                po->prot_hook.dev = NULL;
@@ -2506,14 +2569,17 @@ static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 protoc
 
        spin_lock(&po->bind_lock);
        unregister_prot_hook(sk, true);
+
        po->num = protocol;
        po->prot_hook.type = protocol;
        if (po->prot_hook.dev)
                dev_put(po->prot_hook.dev);
-       po->prot_hook.dev = dev;
 
+       po->prot_hook.dev = dev;
        po->ifindex = dev ? dev->ifindex : 0;
 
+       packet_cached_dev_assign(po, dev);
+
        if (protocol == 0)
                goto out_unlock;
 
@@ -2626,7 +2692,9 @@ static int packet_create(struct net *net, struct socket *sock, int protocol,
        po = pkt_sk(sk);
        sk->sk_family = PF_PACKET;
        po->num = proto;
-       RCU_INIT_POINTER(po->cached_dev, NULL);
+       po->xmit = dev_queue_xmit;
+
+       packet_cached_dev_reset(po);
 
        sk->sk_destruct = packet_sock_destruct;
        sk_refcnt_debug_inc(sk);
@@ -3204,6 +3272,18 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv
                po->tp_tx_has_off = !!val;
                return 0;
        }
+       case PACKET_QDISC_BYPASS:
+       {
+               int val;
+
+               if (optlen != sizeof(val))
+                       return -EINVAL;
+               if (copy_from_user(&val, optval, sizeof(val)))
+                       return -EFAULT;
+
+               po->xmit = val ? packet_direct_xmit : dev_queue_xmit;
+               return 0;
+       }
        default:
                return -ENOPROTOOPT;
        }
@@ -3296,6 +3376,9 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
        case PACKET_TX_HAS_OFF:
                val = po->tp_tx_has_off;
                break;
+       case PACKET_QDISC_BYPASS:
+               val = packet_use_direct_xmit(po);
+               break;
        default:
                return -ENOPROTOOPT;
        }
@@ -3337,6 +3420,7 @@ static int packet_notifier(struct notifier_block *this,
                                                sk->sk_error_report(sk);
                                }
                                if (msg == NETDEV_UNREGISTER) {
+                                       packet_cached_dev_reset(po);
                                        po->ifindex = -1;
                                        if (po->prot_hook.dev)
                                                dev_put(po->prot_hook.dev);
index 1035fa2d909c7f18c100266c85ec07bce4a73a97..0a87d7b36c9e2470836a3d00f0dc261e8983d41b 100644 (file)
@@ -114,6 +114,7 @@ struct packet_sock {
        unsigned int            tp_tx_has_off:1;
        unsigned int            tp_tstamp;
        struct net_device __rcu *cached_dev;
+       int                     (*xmit)(struct sk_buff *skb);
        struct packet_type      prot_hook ____cacheline_aligned_in_smp;
 };
 
index e59094981175cd6c390b5ed83a2dec15d8e2407e..37be6e226d1b46fefe8e0cf554580b1faf19cfb8 100644 (file)
@@ -552,9 +552,8 @@ int rds_ib_xmit(struct rds_connection *conn, struct rds_message *rm,
            && rm->m_inc.i_hdr.h_flags & RDS_FLAG_CONG_BITMAP) {
                rds_cong_map_updated(conn->c_fcong, ~(u64) 0);
                scat = &rm->data.op_sg[sg];
-               ret = sizeof(struct rds_header) + RDS_CONG_MAP_BYTES;
-               ret = min_t(int, ret, scat->length - conn->c_xmit_data_off);
-               return ret;
+               ret = max_t(int, RDS_CONG_MAP_BYTES, scat->length);
+               return sizeof(struct rds_header) + ret;
        }
 
        /* FIXME we may overallocate here */
index 1bacc10799421790e62e9af7a99040cbd2e4afd0..ed7e0b4e7f90730b7530bbcf20106deaeb3d48bd 100644 (file)
@@ -14,9 +14,7 @@
  * 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/kernel.h>
index fd7072827a40139c4ffba595aaa261282641e37f..4adbce8f8314ae29d815a7d9d41ddb33fd54aa2f 100644 (file)
@@ -191,7 +191,8 @@ u32 tcf_hash_new_index(u32 *idx_gen, struct tcf_hashinfo *hinfo)
                        val = 1;
        } while (tcf_hash_lookup(val, hinfo));
 
-       return (*idx_gen = val);
+       *idx_gen = val;
+       return val;
 }
 EXPORT_SYMBOL(tcf_hash_new_index);
 
@@ -270,6 +271,16 @@ int tcf_register_action(struct tc_action_ops *act)
 {
        struct tc_action_ops *a, **ap;
 
+       /* Must supply act, dump, cleanup and init */
+       if (!act->act || !act->dump || !act->cleanup || !act->init)
+               return -EINVAL;
+
+       /* Supply defaults */
+       if (!act->lookup)
+               act->lookup = tcf_hash_search;
+       if (!act->walk)
+               act->walk = tcf_generic_walker;
+
        write_lock(&act_mod_lock);
        for (ap = &act_base; (a = *ap) != NULL; ap = &a->next) {
                if (act->type == a->type || (strcmp(act->kind, a->kind) == 0)) {
@@ -381,7 +392,7 @@ int tcf_action_exec(struct sk_buff *skb, const struct tc_action *act,
        }
        while ((a = act) != NULL) {
 repeat:
-               if (a->ops && a->ops->act) {
+               if (a->ops) {
                        ret = a->ops->act(skb, a, res);
                        if (TC_MUNGED & skb->tc_verd) {
                                /* copied already, allow trampling */
@@ -405,7 +416,7 @@ void tcf_action_destroy(struct tc_action *act, int bind)
        struct tc_action *a;
 
        for (a = act; a; a = act) {
-               if (a->ops && a->ops->cleanup) {
+               if (a->ops) {
                        if (a->ops->cleanup(a, bind) == ACT_P_DELETED)
                                module_put(a->ops->owner);
                        act = act->next;
@@ -424,7 +435,7 @@ tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
 {
        int err = -EINVAL;
 
-       if (a->ops == NULL || a->ops->dump == NULL)
+       if (a->ops == NULL)
                return err;
        return a->ops->dump(skb, a, bind, ref);
 }
@@ -436,7 +447,7 @@ tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
        unsigned char *b = skb_tail_pointer(skb);
        struct nlattr *nest;
 
-       if (a->ops == NULL || a->ops->dump == NULL)
+       if (a->ops == NULL)
                return err;
 
        if (nla_put_string(skb, TCA_KIND, a->ops->kind))
@@ -723,8 +734,6 @@ tcf_action_get_1(struct nlattr *nla, struct nlmsghdr *n, u32 portid)
        a->ops = tc_lookup_action(tb[TCA_ACT_KIND]);
        if (a->ops == NULL)
                goto err_free;
-       if (a->ops->lookup == NULL)
-               goto err_mod;
        err = -ENOENT;
        if (a->ops->lookup(a, index) == 0)
                goto err_mod;
@@ -1084,12 +1093,6 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb)
        memset(&a, 0, sizeof(struct tc_action));
        a.ops = a_o;
 
-       if (a_o->walk == NULL) {
-               WARN(1, "tc_dump_action: %s !capable of dumping table\n",
-                    a_o->kind);
-               goto out_module_put;
-       }
-
        nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
                        cb->nlh->nlmsg_type, sizeof(*t), 0);
        if (!nlh)
index 3a4c0caa1f7de0fdfdb618bac9308aa32330c7f7..5c5edf56adbd4fc9a4d64a509a9103511f995db4 100644 (file)
@@ -585,9 +585,7 @@ static struct tc_action_ops act_csum_ops = {
        .act            = tcf_csum,
        .dump           = tcf_csum_dump,
        .cleanup        = tcf_csum_cleanup,
-       .lookup         = tcf_hash_search,
        .init           = tcf_csum_init,
-       .walk           = tcf_generic_walker
 };
 
 MODULE_DESCRIPTION("Checksum updating actions");
index fd2b3cff5fa28cf4da25690da9e7bad410c60a78..5645a4d32abdd187f59d9f6301842e35d08762df 100644 (file)
@@ -206,9 +206,7 @@ static struct tc_action_ops act_gact_ops = {
        .act            =       tcf_gact,
        .dump           =       tcf_gact_dump,
        .cleanup        =       tcf_gact_cleanup,
-       .lookup         =       tcf_hash_search,
        .init           =       tcf_gact_init,
-       .walk           =       tcf_generic_walker
 };
 
 MODULE_AUTHOR("Jamal Hadi Salim(2002-4)");
index 60d88b6b9560bc0a7836fa0cba845ddd6a57cb3c..882a89762f77c2edb8b6d10d0c8ef69cf3e39aac 100644 (file)
@@ -298,9 +298,7 @@ static struct tc_action_ops act_ipt_ops = {
        .act            =       tcf_ipt,
        .dump           =       tcf_ipt_dump,
        .cleanup        =       tcf_ipt_cleanup,
-       .lookup         =       tcf_hash_search,
        .init           =       tcf_ipt_init,
-       .walk           =       tcf_generic_walker
 };
 
 static struct tc_action_ops act_xt_ops = {
@@ -312,9 +310,7 @@ static struct tc_action_ops act_xt_ops = {
        .act            =       tcf_ipt,
        .dump           =       tcf_ipt_dump,
        .cleanup        =       tcf_ipt_cleanup,
-       .lookup         =       tcf_hash_search,
        .init           =       tcf_ipt_init,
-       .walk           =       tcf_generic_walker
 };
 
 MODULE_AUTHOR("Jamal Hadi Salim(2002-13)");
index 977c10e0631b6dfe4ead45af617c0ad93c4a0759..252378121ce7cd1848beab20aa666389937bf610 100644 (file)
@@ -271,9 +271,7 @@ static struct tc_action_ops act_mirred_ops = {
        .act            =       tcf_mirred,
        .dump           =       tcf_mirred_dump,
        .cleanup        =       tcf_mirred_cleanup,
-       .lookup         =       tcf_hash_search,
        .init           =       tcf_mirred_init,
-       .walk           =       tcf_generic_walker
 };
 
 MODULE_AUTHOR("Jamal Hadi Salim(2002)");
index 876f0ef29694a3f28260a221d0862d4fe3756f8d..6a15ace002411a8c11efeed6156d72324b9eb2ff 100644 (file)
@@ -308,9 +308,7 @@ static struct tc_action_ops act_nat_ops = {
        .act            =       tcf_nat,
        .dump           =       tcf_nat_dump,
        .cleanup        =       tcf_nat_cleanup,
-       .lookup         =       tcf_hash_search,
        .init           =       tcf_nat_init,
-       .walk           =       tcf_generic_walker
 };
 
 MODULE_DESCRIPTION("Stateless NAT actions");
index 7ed78c9e505cf7e18bc5a0b066837d19d33d4b10..03b67674169c5db79eb546d93d0b4833324786d3 100644 (file)
@@ -243,9 +243,7 @@ static struct tc_action_ops act_pedit_ops = {
        .act            =       tcf_pedit,
        .dump           =       tcf_pedit_dump,
        .cleanup        =       tcf_pedit_cleanup,
-       .lookup         =       tcf_hash_search,
        .init           =       tcf_pedit_init,
-       .walk           =       tcf_generic_walker
 };
 
 MODULE_AUTHOR("Jamal Hadi Salim(2002-4)");
index 272d8e924cf6b2467e2772898aca2d7895131545..16a62c36928a78110923d36d5b87808936d8f90a 100644 (file)
@@ -407,7 +407,6 @@ static struct tc_action_ops act_police_ops = {
        .act            =       tcf_act_police,
        .dump           =       tcf_act_police_dump,
        .cleanup        =       tcf_act_police_cleanup,
-       .lookup         =       tcf_hash_search,
        .init           =       tcf_act_police_locate,
        .walk           =       tcf_act_police_walker
 };
index 7725eb4ab756caa841eca2e0f4778880c310e5c4..31157d3e729c8c29e8bb89ce03fa68c5ad8e7f39 100644 (file)
@@ -201,7 +201,6 @@ static struct tc_action_ops act_simp_ops = {
        .dump           =       tcf_simp_dump,
        .cleanup        =       tcf_simp_cleanup,
        .init           =       tcf_simp_init,
-       .walk           =       tcf_generic_walker,
 };
 
 MODULE_AUTHOR("Jamal Hadi Salim(2005)");
index cb4221171f93f0c5b8fbb98f41b11241aa17d02a..cf20add1c3ff3641a2f9d50c33304407e0dab6b9 100644 (file)
@@ -11,8 +11,7 @@
  * 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.
+ * this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * Author: Alexander Duyck <alexander.h.duyck@intel.com>
  */
@@ -203,7 +202,6 @@ static struct tc_action_ops act_skbedit_ops = {
        .dump           =       tcf_skbedit_dump,
        .cleanup        =       tcf_skbedit_cleanup,
        .init           =       tcf_skbedit_init,
-       .walk           =       tcf_generic_walker,
 };
 
 MODULE_AUTHOR("Alexander Duyck, <alexander.h.duyck@intel.com>");
index 1002a8226281ba6439b13c7a65c2b7e91945b539..d7c72be121f36bbb395c49bc5ef86c7b875dd48c 100644 (file)
@@ -323,7 +323,7 @@ static int cls_bpf_dump(struct tcf_proto *tp, unsigned long fh,
        if (nla == NULL)
                goto nla_put_failure;
 
-        memcpy(nla_data(nla), prog->bpf_ops, nla_len(nla));
+       memcpy(nla_data(nla), prog->bpf_ops, nla_len(nla));
 
        if (tcf_exts_dump(skb, &prog->exts, &bpf_ext_map) < 0)
                goto nla_put_failure;
index eb07a1e536e6cb6f0b1f44099f130119490e9f52..59e546c2ac98e512d7c94a25c9613868d02a8b79 100644 (file)
@@ -352,7 +352,7 @@ static int u32_destroy_key(struct tcf_proto *tp, struct tc_u_knode *n)
        return 0;
 }
 
-static int u32_delete_key(struct tcf_proto *tp, struct tc_u_knodekey)
+static int u32_delete_key(struct tcf_proto *tp, struct tc_u_knode *key)
 {
        struct tc_u_knode **kp;
        struct tc_u_hnode *ht = key->ht_up;
index e5cef95672256b650249c80bef36930f78be9f13..382519a5d7f94a056bf2bcf1d51ea19122b7558d 100644 (file)
@@ -271,40 +271,52 @@ META_COLLECTOR(int_rtiif)
  * Socket Attributes
  **************************************************************************/
 
-#define SKIP_NONLOCAL(skb)                     \
-       if (unlikely(skb->sk == NULL)) {        \
-               *err = -1;                      \
-               return;                         \
-       }
+#define skip_nonlocal(skb) \
+       (unlikely(skb->sk == NULL))
 
 META_COLLECTOR(int_sk_family)
 {
-       SKIP_NONLOCAL(skb);
+       if (skip_nonlocal(skb)) {
+               *err = -1;
+               return;
+       }
        dst->value = skb->sk->sk_family;
 }
 
 META_COLLECTOR(int_sk_state)
 {
-       SKIP_NONLOCAL(skb);
+       if (skip_nonlocal(skb)) {
+               *err = -1;
+               return;
+       }
        dst->value = skb->sk->sk_state;
 }
 
 META_COLLECTOR(int_sk_reuse)
 {
-       SKIP_NONLOCAL(skb);
+       if (skip_nonlocal(skb)) {
+               *err = -1;
+               return;
+       }
        dst->value = skb->sk->sk_reuse;
 }
 
 META_COLLECTOR(int_sk_bound_if)
 {
-       SKIP_NONLOCAL(skb);
+       if (skip_nonlocal(skb)) {
+               *err = -1;
+               return;
+       }
        /* No error if bound_dev_if is 0, legal userspace check */
        dst->value = skb->sk->sk_bound_dev_if;
 }
 
 META_COLLECTOR(var_sk_bound_if)
 {
-       SKIP_NONLOCAL(skb);
+       if (skip_nonlocal(skb)) {
+               *err = -1;
+               return;
+       }
 
        if (skb->sk->sk_bound_dev_if == 0) {
                dst->value = (unsigned long) "any";
@@ -322,151 +334,226 @@ META_COLLECTOR(var_sk_bound_if)
 
 META_COLLECTOR(int_sk_refcnt)
 {
-       SKIP_NONLOCAL(skb);
+       if (skip_nonlocal(skb)) {
+               *err = -1;
+               return;
+       }
        dst->value = atomic_read(&skb->sk->sk_refcnt);
 }
 
 META_COLLECTOR(int_sk_rcvbuf)
 {
-       SKIP_NONLOCAL(skb);
+       if (skip_nonlocal(skb)) {
+               *err = -1;
+               return;
+       }
        dst->value = skb->sk->sk_rcvbuf;
 }
 
 META_COLLECTOR(int_sk_shutdown)
 {
-       SKIP_NONLOCAL(skb);
+       if (skip_nonlocal(skb)) {
+               *err = -1;
+               return;
+       }
        dst->value = skb->sk->sk_shutdown;
 }
 
 META_COLLECTOR(int_sk_proto)
 {
-       SKIP_NONLOCAL(skb);
+       if (skip_nonlocal(skb)) {
+               *err = -1;
+               return;
+       }
        dst->value = skb->sk->sk_protocol;
 }
 
 META_COLLECTOR(int_sk_type)
 {
-       SKIP_NONLOCAL(skb);
+       if (skip_nonlocal(skb)) {
+               *err = -1;
+               return;
+       }
        dst->value = skb->sk->sk_type;
 }
 
 META_COLLECTOR(int_sk_rmem_alloc)
 {
-       SKIP_NONLOCAL(skb);
+       if (skip_nonlocal(skb)) {
+               *err = -1;
+               return;
+       }
        dst->value = sk_rmem_alloc_get(skb->sk);
 }
 
 META_COLLECTOR(int_sk_wmem_alloc)
 {
-       SKIP_NONLOCAL(skb);
+       if (skip_nonlocal(skb)) {
+               *err = -1;
+               return;
+       }
        dst->value = sk_wmem_alloc_get(skb->sk);
 }
 
 META_COLLECTOR(int_sk_omem_alloc)
 {
-       SKIP_NONLOCAL(skb);
+       if (skip_nonlocal(skb)) {
+               *err = -1;
+               return;
+       }
        dst->value = atomic_read(&skb->sk->sk_omem_alloc);
 }
 
 META_COLLECTOR(int_sk_rcv_qlen)
 {
-       SKIP_NONLOCAL(skb);
+       if (skip_nonlocal(skb)) {
+               *err = -1;
+               return;
+       }
        dst->value = skb->sk->sk_receive_queue.qlen;
 }
 
 META_COLLECTOR(int_sk_snd_qlen)
 {
-       SKIP_NONLOCAL(skb);
+       if (skip_nonlocal(skb)) {
+               *err = -1;
+               return;
+       }
        dst->value = skb->sk->sk_write_queue.qlen;
 }
 
 META_COLLECTOR(int_sk_wmem_queued)
 {
-       SKIP_NONLOCAL(skb);
+       if (skip_nonlocal(skb)) {
+               *err = -1;
+               return;
+       }
        dst->value = skb->sk->sk_wmem_queued;
 }
 
 META_COLLECTOR(int_sk_fwd_alloc)
 {
-       SKIP_NONLOCAL(skb);
+       if (skip_nonlocal(skb)) {
+               *err = -1;
+               return;
+       }
        dst->value = skb->sk->sk_forward_alloc;
 }
 
 META_COLLECTOR(int_sk_sndbuf)
 {
-       SKIP_NONLOCAL(skb);
+       if (skip_nonlocal(skb)) {
+               *err = -1;
+               return;
+       }
        dst->value = skb->sk->sk_sndbuf;
 }
 
 META_COLLECTOR(int_sk_alloc)
 {
-       SKIP_NONLOCAL(skb);
+       if (skip_nonlocal(skb)) {
+               *err = -1;
+               return;
+       }
        dst->value = (__force int) skb->sk->sk_allocation;
 }
 
 META_COLLECTOR(int_sk_hash)
 {
-       SKIP_NONLOCAL(skb);
+       if (skip_nonlocal(skb)) {
+               *err = -1;
+               return;
+       }
        dst->value = skb->sk->sk_hash;
 }
 
 META_COLLECTOR(int_sk_lingertime)
 {
-       SKIP_NONLOCAL(skb);
+       if (skip_nonlocal(skb)) {
+               *err = -1;
+               return;
+       }
        dst->value = skb->sk->sk_lingertime / HZ;
 }
 
 META_COLLECTOR(int_sk_err_qlen)
 {
-       SKIP_NONLOCAL(skb);
+       if (skip_nonlocal(skb)) {
+               *err = -1;
+               return;
+       }
        dst->value = skb->sk->sk_error_queue.qlen;
 }
 
 META_COLLECTOR(int_sk_ack_bl)
 {
-       SKIP_NONLOCAL(skb);
+       if (skip_nonlocal(skb)) {
+               *err = -1;
+               return;
+       }
        dst->value = skb->sk->sk_ack_backlog;
 }
 
 META_COLLECTOR(int_sk_max_ack_bl)
 {
-       SKIP_NONLOCAL(skb);
+       if (skip_nonlocal(skb)) {
+               *err = -1;
+               return;
+       }
        dst->value = skb->sk->sk_max_ack_backlog;
 }
 
 META_COLLECTOR(int_sk_prio)
 {
-       SKIP_NONLOCAL(skb);
+       if (skip_nonlocal(skb)) {
+               *err = -1;
+               return;
+       }
        dst->value = skb->sk->sk_priority;
 }
 
 META_COLLECTOR(int_sk_rcvlowat)
 {
-       SKIP_NONLOCAL(skb);
+       if (skip_nonlocal(skb)) {
+               *err = -1;
+               return;
+       }
        dst->value = skb->sk->sk_rcvlowat;
 }
 
 META_COLLECTOR(int_sk_rcvtimeo)
 {
-       SKIP_NONLOCAL(skb);
+       if (skip_nonlocal(skb)) {
+               *err = -1;
+               return;
+       }
        dst->value = skb->sk->sk_rcvtimeo / HZ;
 }
 
 META_COLLECTOR(int_sk_sndtimeo)
 {
-       SKIP_NONLOCAL(skb);
+       if (skip_nonlocal(skb)) {
+               *err = -1;
+               return;
+       }
        dst->value = skb->sk->sk_sndtimeo / HZ;
 }
 
 META_COLLECTOR(int_sk_sendmsg_off)
 {
-       SKIP_NONLOCAL(skb);
+       if (skip_nonlocal(skb)) {
+               *err = -1;
+               return;
+       }
        dst->value = skb->sk->sk_frag.offset;
 }
 
 META_COLLECTOR(int_sk_write_pend)
 {
-       SKIP_NONLOCAL(skb);
+       if (skip_nonlocal(skb)) {
+               *err = -1;
+               return;
+       }
        dst->value = skb->sk->sk_write_pending;
 }
 
index cd81505662b8a3bcc201a18bce0d6c9bd421b650..547b4a88ae2aa5fa9c850973cb6db9ad26e1035c 100644 (file)
@@ -271,11 +271,12 @@ static struct Qdisc *qdisc_match_from_root(struct Qdisc *root, u32 handle)
        return NULL;
 }
 
-static void qdisc_list_add(struct Qdisc *q)
+void qdisc_list_add(struct Qdisc *q)
 {
        if ((q->parent != TC_H_ROOT) && !(q->flags & TCQ_F_INGRESS))
                list_add_tail(&q->list, &qdisc_dev(q)->qdisc->list);
 }
+EXPORT_SYMBOL(qdisc_list_add);
 
 void qdisc_list_del(struct Qdisc *q)
 {
index 7a42c81a19ebe55f0b6a137f89c55b46314f8cd7..d5a8a4b2454fa25a56a7b8637ed32dc615bb4edc 100644 (file)
@@ -1058,7 +1058,8 @@ static void cbq_normalize_quanta(struct cbq_sched_data *q, int prio)
                                cl->quantum = (cl->weight*cl->allot*q->nclasses[prio])/
                                        q->quanta[prio];
                        }
-                       if (cl->quantum <= 0 || cl->quantum>32*qdisc_dev(cl->qdisc)->mtu) {
+                       if (cl->quantum <= 0 ||
+                           cl->quantum > 32*qdisc_dev(cl->qdisc)->mtu) {
                                pr_warning("CBQ: class %08x has bad quantum==%ld, repaired.\n",
                                           cl->common.classid, cl->quantum);
                                cl->quantum = qdisc_dev(cl->qdisc)->mtu/2 + 1;
index 3886365cc207d139a21efdad996f71b033f3a09a..0952fd2684e4894f3d5b11902d4e7e7f1fb3556d 100644 (file)
@@ -47,7 +47,7 @@ struct dsmark_qdisc_data {
 
 static inline int dsmark_valid_index(struct dsmark_qdisc_data *p, u16 index)
 {
-       return (index <= p->indices && index > 0);
+       return index <= p->indices && index > 0;
 }
 
 /* ------------------------- Class/flow operations ------------------------- */
index 922a09406ba70573499877ac3e561c9ee7b61a5c..6a91d7d48ade4818b09bc53901c90a009ddd508c 100644 (file)
@@ -338,13 +338,13 @@ EXPORT_SYMBOL(netif_carrier_off);
    cheaper.
  */
 
-static int noop_enqueue(struct sk_buff *skb, struct Qdisc * qdisc)
+static int noop_enqueue(struct sk_buff *skb, struct Qdisc *qdisc)
 {
        kfree_skb(skb);
        return NET_XMIT_CN;
 }
 
-static struct sk_buff *noop_dequeue(struct Qdisc * qdisc)
+static struct sk_buff *noop_dequeue(struct Qdisc *qdisc)
 {
        return NULL;
 }
index 0e1e38b40025fd111f50bfce339a6d2e7cae1252..6b0e854b0115170a209a1d2a96a92ae867309716 100644 (file)
@@ -1337,7 +1337,6 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
        struct htb_sched *q = qdisc_priv(sch);
        struct htb_class *cl = (struct htb_class *)*arg, *parent;
        struct nlattr *opt = tca[TCA_OPTIONS];
-       struct qdisc_rate_table *rtab = NULL, *ctab = NULL;
        struct nlattr *tb[TCA_HTB_MAX + 1];
        struct tc_htb_opt *hopt;
        u64 rate64, ceil64;
@@ -1361,16 +1360,11 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
                goto failure;
 
        /* Keeping backward compatible with rate_table based iproute2 tc */
-       if (hopt->rate.linklayer == TC_LINKLAYER_UNAWARE) {
-               rtab = qdisc_get_rtab(&hopt->rate, tb[TCA_HTB_RTAB]);
-               if (rtab)
-                       qdisc_put_rtab(rtab);
-       }
-       if (hopt->ceil.linklayer == TC_LINKLAYER_UNAWARE) {
-               ctab = qdisc_get_rtab(&hopt->ceil, tb[TCA_HTB_CTAB]);
-               if (ctab)
-                       qdisc_put_rtab(ctab);
-       }
+       if (hopt->rate.linklayer == TC_LINKLAYER_UNAWARE)
+               qdisc_put_rtab(qdisc_get_rtab(&hopt->rate, tb[TCA_HTB_RTAB]));
+
+       if (hopt->ceil.linklayer == TC_LINKLAYER_UNAWARE)
+               qdisc_put_rtab(qdisc_get_rtab(&hopt->ceil, tb[TCA_HTB_CTAB]));
 
        if (!cl) {              /* new class */
                struct Qdisc *new_q;
@@ -1477,11 +1471,22 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
                sch_tree_lock(sch);
        }
 
+       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);
+
        /* it used to be a nasty bug here, we have to check that node
         * is really leaf before changing cl->un.leaf !
         */
        if (!cl->level) {
-               cl->quantum = hopt->rate.rate / q->rate2quantum;
+               u64 quantum = cl->rate.rate_bytes_ps;
+
+               do_div(quantum, q->rate2quantum);
+               cl->quantum = min_t(u64, quantum, INT_MAX);
+
                if (!hopt->quantum && cl->quantum < 1000) {
                        pr_warning(
                               "HTB: quantum of class %X is small. Consider r2q change.\n",
@@ -1500,13 +1505,6 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
                        cl->prio = TC_HTB_NUMPRIO - 1;
        }
 
-       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);
 
index 2e56185736d67d589b78918ff59fd7641eb2377a..a8b2864a696be934114a3b23ccf75e0cb8c4d1d6 100644 (file)
@@ -78,14 +78,19 @@ static void mq_attach(struct Qdisc *sch)
 {
        struct net_device *dev = qdisc_dev(sch);
        struct mq_sched *priv = qdisc_priv(sch);
-       struct Qdisc *qdisc;
+       struct Qdisc *qdisc, *old;
        unsigned int ntx;
 
        for (ntx = 0; ntx < dev->num_tx_queues; ntx++) {
                qdisc = priv->qdiscs[ntx];
-               qdisc = dev_graft_qdisc(qdisc->dev_queue, qdisc);
-               if (qdisc)
-                       qdisc_destroy(qdisc);
+               old = dev_graft_qdisc(qdisc->dev_queue, qdisc);
+               if (old)
+                       qdisc_destroy(old);
+#ifdef CONFIG_NET_SCHED
+               if (ntx < dev->real_num_tx_queues)
+                       qdisc_list_add(qdisc);
+#endif
+
        }
        kfree(priv->qdiscs);
        priv->qdiscs = NULL;
index d44c868cb537d0e1da33e9d6806c00966e7286fc..6749e2f540d0336eb69f61cb82b59623382e5777 100644 (file)
@@ -167,15 +167,17 @@ static void mqprio_attach(struct Qdisc *sch)
 {
        struct net_device *dev = qdisc_dev(sch);
        struct mqprio_sched *priv = qdisc_priv(sch);
-       struct Qdisc *qdisc;
+       struct Qdisc *qdisc, *old;
        unsigned int ntx;
 
        /* Attach underlying qdisc */
        for (ntx = 0; ntx < dev->num_tx_queues; ntx++) {
                qdisc = priv->qdiscs[ntx];
-               qdisc = dev_graft_qdisc(qdisc->dev_queue, qdisc);
-               if (qdisc)
-                       qdisc_destroy(qdisc);
+               old = dev_graft_qdisc(qdisc->dev_queue, qdisc);
+               if (old)
+                       qdisc_destroy(old);
+               if (ntx < dev->real_num_tx_queues)
+                       qdisc_list_add(qdisc);
        }
        kfree(priv->qdiscs);
        priv->qdiscs = NULL;
index 2a2b096d9a664b12a2fa7b4b9a91e4ff9b233f27..afb050a735fa5878a29e1da85d7c6b603851b623 100644 (file)
@@ -11,8 +11,7 @@
  * 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.
+ * this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * Author: Alexander Duyck <alexander.h.duyck@intel.com>
  */
index 75c94e59a3bd3889cd87460afe87ac611eeb024e..f3befd6b4781bde74547f9b60b9b3733dba78bcd 100644 (file)
@@ -215,10 +215,10 @@ static bool loss_4state(struct netem_sched_data *q)
                if (rnd < clg->a4) {
                        clg->state = 4;
                        return true;
-               } else if (clg->a4 < rnd && rnd < clg->a1) {
+               } else if (clg->a4 < rnd && rnd < clg->a1 + clg->a4) {
                        clg->state = 3;
                        return true;
-               } else if (clg->a1 < rnd)
+               } else if (clg->a1 + clg->a4 < rnd)
                        clg->state = 1;
 
                break;
@@ -268,10 +268,11 @@ static bool loss_gilb_ell(struct netem_sched_data *q)
                        clg->state = 2;
                if (net_random() < clg->a4)
                        return true;
+               break;
        case 2:
                if (net_random() < clg->a2)
                        clg->state = 1;
-               if (clg->a3 > net_random())
+               if (net_random() > clg->a3)
                        return true;
        }
 
@@ -728,7 +729,7 @@ static int get_loss_clg(struct Qdisc *sch, const struct nlattr *attr)
        nla_for_each_nested(la, attr, rem) {
                u16 type = nla_type(la);
 
-               switch(type) {
+               switch (type) {
                case NETEM_LOSS_GI: {
                        const struct tc_netem_gimodel *gi = nla_data(la);
 
index d3a1bc26dbfc536350ebaaecfdcb5426b7eacec5..76f01e0258df4bbfa9065412b4a04bf202541995 100644 (file)
@@ -237,10 +237,12 @@ static inline void sfq_link(struct sfq_sched_data *q, sfq_index x)
 }
 
 #define sfq_unlink(q, x, n, p)                 \
-       n = q->slots[x].dep.next;               \
-       p = q->slots[x].dep.prev;               \
-       sfq_dep_head(q, p)->next = n;           \
-       sfq_dep_head(q, n)->prev = p
+       do {                                    \
+               n = q->slots[x].dep.next;       \
+               p = q->slots[x].dep.prev;       \
+               sfq_dep_head(q, p)->next = n;   \
+               sfq_dep_head(q, n)->prev = p;   \
+       } while (0)
 
 
 static inline void sfq_dec(struct sfq_sched_data *q, sfq_index x)
index 68f98595819c1224f7e64ad368ad51155ff07fea..a44928c6ba24e3d21fde29d21ee966b4c8c5b660 100644 (file)
@@ -21,6 +21,7 @@
 #include <net/netlink.h>
 #include <net/sch_generic.h>
 #include <net/pkt_sched.h>
+#include <net/tcp.h>
 
 
 /*     Simple Token Bucket Filter.
@@ -117,6 +118,46 @@ struct tbf_sched_data {
 };
 
 
+/* Time to Length, convert time in ns to length in bytes
+ * to determinate how many bytes can be sent in given time.
+ */
+static u64 psched_ns_t2l(const struct psched_ratecfg *r,
+                        u64 time_in_ns)
+{
+       /* The formula is :
+        * len = (time_in_ns * r->rate_bytes_ps) / NSEC_PER_SEC
+        */
+       u64 len = time_in_ns * r->rate_bytes_ps;
+
+       do_div(len, NSEC_PER_SEC);
+
+       if (unlikely(r->linklayer == TC_LINKLAYER_ATM))
+               len = (len / 53) * 48;
+
+       if (len > r->overhead)
+               len -= r->overhead;
+       else
+               len = 0;
+
+       return len;
+}
+
+/*
+ * Return length of individual segments of a gso packet,
+ * including all headers (MAC, IP, TCP/UDP)
+ */
+static unsigned int skb_gso_seglen(const struct sk_buff *skb)
+{
+       unsigned int hdr_len = skb_transport_header(skb) - skb_mac_header(skb);
+       const struct skb_shared_info *shinfo = skb_shinfo(skb);
+
+       if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))
+               hdr_len += tcp_hdrlen(skb);
+       else
+               hdr_len += sizeof(struct udphdr);
+       return hdr_len + shinfo->gso_size;
+}
+
 /* GSO packet is too big, segment it so that tbf can transmit
  * each segment in time
  */
@@ -136,12 +177,8 @@ static int tbf_segment(struct sk_buff *skb, struct Qdisc *sch)
        while (segs) {
                nskb = segs->next;
                segs->next = NULL;
-               if (likely(segs->len <= q->max_size)) {
-                       qdisc_skb_cb(segs)->pkt_len = segs->len;
-                       ret = qdisc_enqueue(segs, q->qdisc);
-               } else {
-                       ret = qdisc_reshape_fail(skb, sch);
-               }
+               qdisc_skb_cb(segs)->pkt_len = segs->len;
+               ret = qdisc_enqueue(segs, q->qdisc);
                if (ret != NET_XMIT_SUCCESS) {
                        if (net_xmit_drop_count(ret))
                                sch->qstats.drops++;
@@ -163,7 +200,7 @@ static int tbf_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        int ret;
 
        if (qdisc_pkt_len(skb) > q->max_size) {
-               if (skb_is_gso(skb))
+               if (skb_is_gso(skb) && skb_gso_seglen(skb) <= q->max_size)
                        return tbf_segment(skb, sch);
                return qdisc_reshape_fail(skb, sch);
        }
@@ -276,10 +313,11 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
        struct tbf_sched_data *q = qdisc_priv(sch);
        struct nlattr *tb[TCA_TBF_MAX + 1];
        struct tc_tbf_qopt *qopt;
-       struct qdisc_rate_table *rtab = NULL;
-       struct qdisc_rate_table *ptab = NULL;
        struct Qdisc *child = NULL;
-       int max_size, n;
+       struct psched_ratecfg rate;
+       struct psched_ratecfg peak;
+       u64 max_size;
+       s64 buffer, mtu;
        u64 rate64 = 0, prate64 = 0;
 
        err = nla_parse_nested(tb, TCA_TBF_MAX, opt, tbf_policy);
@@ -291,33 +329,13 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
                goto done;
 
        qopt = nla_data(tb[TCA_TBF_PARMS]);
-       rtab = qdisc_get_rtab(&qopt->rate, tb[TCA_TBF_RTAB]);
-       if (rtab == NULL)
-               goto done;
-
-       if (qopt->peakrate.rate) {
-               if (qopt->peakrate.rate > qopt->rate.rate)
-                       ptab = qdisc_get_rtab(&qopt->peakrate, tb[TCA_TBF_PTAB]);
-               if (ptab == NULL)
-                       goto done;
-       }
+       if (qopt->rate.linklayer == TC_LINKLAYER_UNAWARE)
+               qdisc_put_rtab(qdisc_get_rtab(&qopt->rate,
+                                             tb[TCA_TBF_RTAB]));
 
-       for (n = 0; n < 256; n++)
-               if (rtab->data[n] > qopt->buffer)
-                       break;
-       max_size = (n << qopt->rate.cell_log) - 1;
-       if (ptab) {
-               int size;
-
-               for (n = 0; n < 256; n++)
-                       if (ptab->data[n] > qopt->mtu)
-                               break;
-               size = (n << qopt->peakrate.cell_log) - 1;
-               if (size < max_size)
-                       max_size = size;
-       }
-       if (max_size < 0)
-               goto done;
+       if (qopt->peakrate.linklayer == TC_LINKLAYER_UNAWARE)
+                       qdisc_put_rtab(qdisc_get_rtab(&qopt->peakrate,
+                                                     tb[TCA_TBF_PTAB]));
 
        if (q->qdisc != &noop_qdisc) {
                err = fifo_set_limit(q->qdisc, qopt->limit);
@@ -331,6 +349,39 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
                }
        }
 
+       buffer = min_t(u64, PSCHED_TICKS2NS(qopt->buffer), ~0U);
+       mtu = min_t(u64, PSCHED_TICKS2NS(qopt->mtu), ~0U);
+
+       if (tb[TCA_TBF_RATE64])
+               rate64 = nla_get_u64(tb[TCA_TBF_RATE64]);
+       psched_ratecfg_precompute(&rate, &qopt->rate, rate64);
+
+       max_size = min_t(u64, psched_ns_t2l(&rate, buffer), ~0U);
+
+       if (qopt->peakrate.rate) {
+               if (tb[TCA_TBF_PRATE64])
+                       prate64 = nla_get_u64(tb[TCA_TBF_PRATE64]);
+               psched_ratecfg_precompute(&peak, &qopt->peakrate, prate64);
+               if (peak.rate_bytes_ps <= rate.rate_bytes_ps) {
+                       pr_warn_ratelimited("sch_tbf: peakrate %llu is lower than or equals to rate %llu !\n",
+                                           peak.rate_bytes_ps, rate.rate_bytes_ps);
+                       err = -EINVAL;
+                       goto done;
+               }
+
+               max_size = min_t(u64, max_size, psched_ns_t2l(&peak, mtu));
+       }
+
+       if (max_size < psched_mtu(qdisc_dev(sch)))
+               pr_warn_ratelimited("sch_tbf: burst %llu is lower than device %s mtu (%u) !\n",
+                                   max_size, qdisc_dev(sch)->name,
+                                   psched_mtu(qdisc_dev(sch)));
+
+       if (!max_size) {
+               err = -EINVAL;
+               goto done;
+       }
+
        sch_tree_lock(sch);
        if (child) {
                qdisc_tree_decrease_qlen(q->qdisc, q->qdisc->q.qlen);
@@ -344,13 +395,9 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
        q->tokens = q->buffer;
        q->ptokens = q->mtu;
 
-       if (tb[TCA_TBF_RATE64])
-               rate64 = nla_get_u64(tb[TCA_TBF_RATE64]);
-       psched_ratecfg_precompute(&q->rate, &rtab->rate, rate64);
-       if (ptab) {
-               if (tb[TCA_TBF_PRATE64])
-                       prate64 = nla_get_u64(tb[TCA_TBF_PRATE64]);
-               psched_ratecfg_precompute(&q->peak, &ptab->rate, prate64);
+       memcpy(&q->rate, &rate, sizeof(struct psched_ratecfg));
+       if (qopt->peakrate.rate) {
+               memcpy(&q->peak, &peak, sizeof(struct psched_ratecfg));
                q->peak_present = true;
        } else {
                q->peak_present = false;
@@ -359,10 +406,6 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
        sch_tree_unlock(sch);
        err = 0;
 done:
-       if (rtab)
-               qdisc_put_rtab(rtab);
-       if (ptab)
-               qdisc_put_rtab(ptab);
        return err;
 }
 
index 68a27f9796d2ece54bcb53b98a47e8f98645077b..5ae60920067470463420f0b3aa879e7c0999f200 100644 (file)
@@ -22,9 +22,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
@@ -90,14 +89,12 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
 
        /* Initialize the object handling fields.  */
        atomic_set(&asoc->base.refcnt, 1);
-       asoc->base.dead = false;
 
        /* Initialize the bind addr area.  */
        sctp_bind_addr_init(&asoc->base.bind_addr, ep->base.bind_addr.port);
 
        asoc->state = SCTP_STATE_CLOSED;
        asoc->cookie_life = ms_to_ktime(sp->assocparams.sasoc_cookie_life);
-       asoc->frag_point = 0;
        asoc->user_frag = sp->user_frag;
 
        /* Set the association max_retrans and RTO values from the
@@ -110,8 +107,6 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
        asoc->rto_max = msecs_to_jiffies(sp->rtoinfo.srto_max);
        asoc->rto_min = msecs_to_jiffies(sp->rtoinfo.srto_min);
 
-       asoc->overall_error_count = 0;
-
        /* Initialize the association's heartbeat interval based on the
         * sock configured value.
         */
@@ -132,18 +127,15 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
         */
        asoc->param_flags = sp->param_flags;
 
-       /* Initialize the maximum mumber of new data packets that can be sent
+       /* Initialize the maximum number of new data packets that can be sent
         * in a burst.
         */
        asoc->max_burst = sp->max_burst;
 
        /* initialize association timers */
-       asoc->timeouts[SCTP_EVENT_TIMEOUT_NONE] = 0;
        asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] = asoc->rto_initial;
        asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] = asoc->rto_initial;
        asoc->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] = asoc->rto_initial;
-       asoc->timeouts[SCTP_EVENT_TIMEOUT_T3_RTX] = 0;
-       asoc->timeouts[SCTP_EVENT_TIMEOUT_T4_RTO] = 0;
 
        /* sctpimpguide Section 2.12.2
         * If the 'T5-shutdown-guard' timer is used, it SHOULD be set to the
@@ -152,10 +144,8 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
        asoc->timeouts[SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD]
                = 5 * asoc->rto_max;
 
-       asoc->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] = 0;
        asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = asoc->sackdelay;
-       asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] =
-               min_t(unsigned long, sp->autoclose, net->sctp.max_autoclose) * HZ;
+       asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] = sp->autoclose * HZ;
 
        /* Initializes the timers */
        for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i)
@@ -173,11 +163,6 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
        asoc->max_init_timeo =
                 msecs_to_jiffies(sp->initmsg.sinit_max_init_timeo);
 
-       /* Allocate storage for the ssnmap after the inbound and outbound
-        * streams have been negotiated during Init.
-        */
-       asoc->ssnmap = NULL;
-
        /* Set the local window size for receive.
         * This is also the rcvbuf space per association.
         * RFC 6 - A SCTP receiver MUST be able to receive a minimum of
@@ -190,25 +175,15 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
 
        asoc->a_rwnd = asoc->rwnd;
 
-       asoc->rwnd_over = 0;
-       asoc->rwnd_press = 0;
-
        /* Use my own max window until I learn something better.  */
        asoc->peer.rwnd = SCTP_DEFAULT_MAXWINDOW;
 
-       /* Set the sndbuf size for transmit.  */
-       asoc->sndbuf_used = 0;
-
        /* Initialize the receive memory counter */
        atomic_set(&asoc->rmem_alloc, 0);
 
        init_waitqueue_head(&asoc->wait);
 
        asoc->c.my_vtag = sctp_generate_tag(ep);
-       asoc->peer.i.init_tag = 0;     /* INIT needs a vtag of 0. */
-       asoc->c.peer_vtag = 0;
-       asoc->c.my_ttag   = 0;
-       asoc->c.peer_ttag = 0;
        asoc->c.my_port = ep->base.bind_addr.port;
 
        asoc->c.initial_tsn = sctp_generate_tsn(ep);
@@ -219,7 +194,6 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
        asoc->adv_peer_ack_point = asoc->ctsn_ack_point;
        asoc->highest_sacked = asoc->ctsn_ack_point;
        asoc->last_cwr_tsn = asoc->ctsn_ack_point;
-       asoc->unack_data = 0;
 
        /* ADDIP Section 4.1 Asconf Chunk Procedures
         *
@@ -238,7 +212,6 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
 
        /* Make an empty list of remote transport addresses.  */
        INIT_LIST_HEAD(&asoc->peer.transport_addr_list);
-       asoc->peer.transport_count = 0;
 
        /* RFC 2960 5.1 Normal Establishment of an Association
         *
@@ -252,20 +225,15 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
         * already received one packet.]
         */
        asoc->peer.sack_needed = 1;
-       asoc->peer.sack_cnt = 0;
        asoc->peer.sack_generation = 1;
 
        /* Assume that the peer will tell us if he recognizes ASCONF
         * as part of INIT exchange.
-        * The sctp_addip_noauth option is there for backward compatibilty
+        * The sctp_addip_noauth option is there for backward compatibility
         * and will revert old behavior.
         */
-       asoc->peer.asconf_capable = 0;
        if (net->sctp.addip_noauth)
                asoc->peer.asconf_capable = 1;
-       asoc->asconf_addr_del_pending = NULL;
-       asoc->src_out_of_asoc_ok = 0;
-       asoc->new_transport = NULL;
 
        /* Create an input queue.  */
        sctp_inq_init(&asoc->base.inqueue);
@@ -277,12 +245,6 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
        if (!sctp_ulpq_init(&asoc->ulpq, asoc))
                goto fail_init;
 
-       memset(&asoc->peer.tsn_map, 0, sizeof(struct sctp_tsnmap));
-
-       asoc->need_ecne = 0;
-
-       asoc->assoc_id = 0;
-
        /* Assume that peer would support both address types unless we are
         * told otherwise.
         */
@@ -291,8 +253,6 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
                asoc->peer.ipv6_address = 1;
        INIT_LIST_HEAD(&asoc->asocs);
 
-       asoc->autoclose = sp->autoclose;
-
        asoc->default_stream = sp->default_stream;
        asoc->default_ppid = sp->default_ppid;
        asoc->default_flags = sp->default_flags;
@@ -300,9 +260,6 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
        asoc->default_timetolive = sp->default_timetolive;
        asoc->default_rcv_context = sp->default_rcv_context;
 
-       /* SCTP_GET_ASSOC_STATS COUNTERS */
-       memset(&asoc->stats, 0, sizeof(struct sctp_priv_assoc_stats));
-
        /* AUTH related initializations */
        INIT_LIST_HEAD(&asoc->endpoint_shared_keys);
        err = sctp_auth_asoc_copy_shkeys(ep, asoc, gfp);
@@ -310,9 +267,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
                goto fail_init;
 
        asoc->active_key_id = ep->active_key_id;
-       asoc->asoc_shared_key = NULL;
 
-       asoc->default_hmac_id = 0;
        /* Save the hmacs and chunks list into this association */
        if (ep->auth_hmacs_list)
                memcpy(asoc->c.auth_hmacs, ep->auth_hmacs_list,
@@ -997,17 +952,13 @@ int sctp_cmp_addr_exact(const union sctp_addr *ss1,
  */
 struct sctp_chunk *sctp_get_ecne_prepend(struct sctp_association *asoc)
 {
-       struct sctp_chunk *chunk;
+       if (!asoc->need_ecne)
+               return NULL;
 
        /* Send ECNE if needed.
         * Not being able to allocate a chunk here is not deadly.
         */
-       if (asoc->need_ecne)
-               chunk = sctp_make_ecne(asoc, asoc->last_ecne_tsn);
-       else
-               chunk = NULL;
-
-       return chunk;
+       return sctp_make_ecne(asoc, asoc->last_ecne_tsn);
 }
 
 /*
@@ -1268,7 +1219,7 @@ void sctp_assoc_update(struct sctp_association *asoc,
                }
        }
 
-       /* SCTP-AUTH: Save the peer parameters from the new assocaitions
+       /* SCTP-AUTH: Save the peer parameters from the new associations
         * and also move the association shared keys over
         */
        kfree(asoc->peer.peer_random);
@@ -1396,7 +1347,7 @@ void sctp_assoc_sync_pmtu(struct sock *sk, struct sctp_association *asoc)
 }
 
 /* Should we send a SACK to update our peer? */
-static inline int sctp_peer_needs_update(struct sctp_association *asoc)
+static inline bool sctp_peer_needs_update(struct sctp_association *asoc)
 {
        struct net *net = sock_net(asoc->base.sk);
        switch (asoc->state) {
@@ -1408,12 +1359,12 @@ static inline int sctp_peer_needs_update(struct sctp_association *asoc)
                    ((asoc->rwnd - asoc->a_rwnd) >= max_t(__u32,
                           (asoc->base.sk->sk_rcvbuf >> net->sctp.rwnd_upd_shift),
                           asoc->pathmtu)))
-                       return 1;
+                       return true;
                break;
        default:
                break;
        }
-       return 0;
+       return false;
 }
 
 /* Increase asoc's rwnd by len and send any window update SACK if needed. */
@@ -1493,7 +1444,7 @@ void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, unsigned int len)
 
        /* If we've reached or overflowed our receive buffer, announce
         * a 0 rwnd if rwnd would still be positive.  Store the
-        * the pottential pressure overflow so that the window can be restored
+        * the potential pressure overflow so that the window can be restored
         * back to original value.
         */
        if (rx_count >= asoc->base.sk->sk_rcvbuf)
index 46b5977978a131b15c073f3b23ab49fa511e92bc..5c9f64c1c906fc4cecd154a843c90e1efe56858c 100644 (file)
@@ -16,9 +16,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
index 077bb070052bac32e551cef707b0a6d6e3f65511..871cdf9567e6bc9c13cb1077dc6866a67e6e4367 100644 (file)
@@ -21,9 +21,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
index f2044fcb9dd113d4764877f08bde77146be5d1a3..5573e425b0c0cc9ecc257994f98127be7ee24c3e 100644 (file)
@@ -18,9 +18,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
index 3d9a9ff69c036e6f83d3b85470458647f413bf5c..dd73758516181cd3268a54ff8aa3177e4f680843 100644 (file)
@@ -19,9 +19,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
index e89015d8935a160f3e0f3e571a976d1cd4823993..95d7b15dad2143dc6a74003125be719e72aeee24 100644 (file)
@@ -22,9 +22,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
index 09b8daac87c8039f2c5b33e04b109a44e6006038..6ffb6c1b13b7efb1cb024c94f022eb1afacaf29a 100644 (file)
@@ -23,9 +23,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
index 98b69bbecdd96eadcbaeb3bdecc210dcca2ab11d..2a192a7c5d81b3380d5ae497cb3789eb9c8134be 100644 (file)
@@ -23,9 +23,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
@@ -537,8 +536,7 @@ struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *skb,
        return sk;
 
 out:
-       if (asoc)
-               sctp_association_put(asoc);
+       sctp_association_put(asoc);
        return NULL;
 }
 
@@ -546,8 +544,7 @@ out:
 void sctp_err_finish(struct sock *sk, struct sctp_association *asoc)
 {
        sctp_bh_unlock_sock(sk);
-       if (asoc)
-               sctp_association_put(asoc);
+       sctp_association_put(asoc);
 }
 
 /*
index 5856932fdc38906ae78b3da2e170f0699634b24e..4de12afa13d42e75c62c4133fc089274e3000261 100644 (file)
@@ -24,9 +24,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
index 7567e6f1a9205bb0a37a29becc243d9ed6352fe4..317e13eb2c568ea91d75874a2a545d0c2d0cb8b9 100644 (file)
@@ -21,9 +21,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
@@ -263,7 +262,7 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
        }
 
        final_p = fl6_update_dst(fl6, np->opt, &final);
-       dst = ip6_dst_lookup_flow(sk, fl6, final_p, false);
+       dst = ip6_dst_lookup_flow(sk, fl6, final_p);
        if (!asoc || saddr)
                goto out;
 
@@ -322,7 +321,7 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
                fl6->saddr = baddr->v6.sin6_addr;
                fl6->fl6_sport = baddr->v6.sin6_port;
                final_p = fl6_update_dst(fl6, np->opt, &final);
-               dst = ip6_dst_lookup_flow(sk, fl6, final_p, false);
+               dst = ip6_dst_lookup_flow(sk, fl6, final_p);
        }
 
 out:
index 647396baa56f3670de372a6896f2b36477c17a32..0c28e8a55324a69fd675dc1377187697d08cc365 100644 (file)
@@ -20,9 +20,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
index e650978daf279abe9b1277dabb22f2e865c64a7a..3f55823279d9d67bdda9e3628b86efeff7b740a2 100644 (file)
@@ -20,9 +20,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
@@ -474,10 +473,11 @@ int sctp_packet_transmit(struct sctp_packet *packet)
                         * for a given destination transport address.
                         */
 
-                       if (!tp->rto_pending) {
+                       if (!chunk->resent && !tp->rto_pending) {
                                chunk->rtt_in_progress = 1;
                                tp->rto_pending = 1;
                        }
+
                        has_data = 1;
                }
 
@@ -580,7 +580,8 @@ int sctp_packet_transmit(struct sctp_packet *packet)
                unsigned long timeout;
 
                /* Restart the AUTOCLOSE timer when sending data. */
-               if (sctp_state(asoc, ESTABLISHED) && asoc->autoclose) {
+               if (sctp_state(asoc, ESTABLISHED) &&
+                   asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) {
                        timer = &asoc->timers[SCTP_EVENT_TIMEOUT_AUTOCLOSE];
                        timeout = asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE];
 
index 94df7587786992fa0a6341caaed284beb1df42e0..b6b09f3f1a81f8f9fc6837cd79bb9749f6857cca 100644 (file)
@@ -22,9 +22,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
@@ -446,6 +445,8 @@ void sctp_retransmit_mark(struct sctp_outq *q,
                                transport->rto_pending = 0;
                        }
 
+                       chunk->resent = 1;
+
                        /* Move the chunk to the retransmit queue. The chunks
                         * on the retransmit queue are always kept in order.
                         */
@@ -1375,6 +1376,7 @@ static void sctp_check_transmitted(struct sctp_outq *q,
                                 * instance).
                                 */
                                if (!tchunk->tsn_gap_acked &&
+                                   !tchunk->resent &&
                                    tchunk->rtt_in_progress) {
                                        tchunk->rtt_in_progress = 0;
                                        rtt = jiffies - tchunk->sent_at;
@@ -1391,7 +1393,8 @@ static void sctp_check_transmitted(struct sctp_outq *q,
                         */
                        if (!tchunk->tsn_gap_acked) {
                                tchunk->tsn_gap_acked = 1;
-                               *highest_new_tsn_in_sack = tsn;
+                               if (TSN_lt(*highest_new_tsn_in_sack, tsn))
+                                       *highest_new_tsn_in_sack = tsn;
                                bytes_acked += sctp_data_size(tchunk);
                                if (!tchunk->transport)
                                        migrate_bytes += sctp_data_size(tchunk);
index ce1ffd811775b414b4d79f3a7b55a5145d599bc9..ab8d9f96a177da9d900e01568cafc56b6b4cf1cb 100644 (file)
@@ -23,9 +23,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
index 0c06421568427e4995ea0798c9ca8535ca5ff9b5..de32e14f73980e9e498eca8667942db1e49f7793 100644 (file)
@@ -16,9 +16,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
index 5e17092f4adacbf0335dc33bcbde5a1f830b43df..19bd4c5bdae9c55658ed1a99758691a6948a13f6 100644 (file)
@@ -23,9 +23,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
index fe690320b1e430a7915e35d36d26a72847368438..d9aaf9641aaa37ee234fb2be6c7339fc1f4eaca1 100644 (file)
@@ -23,9 +23,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
index 1a6eef39ab2fcd169dde99a6494758793f5c88fc..02b7ad1ff467cef05301f8f6818f1e5bba91b0e7 100644 (file)
@@ -22,9 +22,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
index dfe3f36ff2aa27165b35a39d382583759cd3ebae..ee02771d8b9c3da7205d160b89897b33a9479e54 100644 (file)
@@ -22,9 +22,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
@@ -820,7 +819,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(struct net *net,
        SCTP_INC_STATS(net, SCTP_MIB_PASSIVEESTABS);
        sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL());
 
-       if (new_asoc->autoclose)
+       if (new_asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE])
                sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START,
                                SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
 
@@ -908,7 +907,7 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(struct net *net,
        SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB);
        SCTP_INC_STATS(net, SCTP_MIB_ACTIVEESTABS);
        sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL());
-       if (asoc->autoclose)
+       if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE])
                sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START,
                                SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
 
@@ -2970,7 +2969,7 @@ sctp_disposition_t sctp_sf_eat_data_6_2(struct net *net,
        if (chunk->chunk_hdr->flags & SCTP_DATA_SACK_IMM)
                force = SCTP_FORCE();
 
-       if (asoc->autoclose) {
+       if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) {
                sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
                                SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
        }
@@ -3878,7 +3877,7 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn(struct net *net,
                                SCTP_CHUNK(chunk));
 
        /* Count this as receiving DATA. */
-       if (asoc->autoclose) {
+       if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) {
                sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
                                SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
        }
@@ -5267,7 +5266,7 @@ sctp_disposition_t sctp_sf_do_9_2_start_shutdown(
        sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
                        SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD));
 
-       if (asoc->autoclose)
+       if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE])
                sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
                                SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
 
@@ -5346,7 +5345,7 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown_ack(
        sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
                        SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN));
 
-       if (asoc->autoclose)
+       if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE])
                sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
                                SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
 
index c5999b2dde7dfa5fcd53e68cf3d7791e838e602b..a4f17437fb220ca9c1ac50fd89dffd25a644c091 100644 (file)
@@ -22,9 +22,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
index 72046b9729a8a6a669fb9c75446de8ef2fe345c6..d39fd0c2c4cf98a80ad4c9a81e72f8d9e40501f8 100644 (file)
@@ -28,9 +28,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
@@ -2196,6 +2195,7 @@ static int sctp_setsockopt_autoclose(struct sock *sk, char __user *optval,
                                     unsigned int optlen)
 {
        struct sctp_sock *sp = sctp_sk(sk);
+       struct net *net = sock_net(sk);
 
        /* Applicable to UDP-style socket only */
        if (sctp_style(sk, TCP))
@@ -2205,6 +2205,9 @@ static int sctp_setsockopt_autoclose(struct sock *sk, char __user *optval,
        if (copy_from_user(&sp->autoclose, optval, optlen))
                return -EFAULT;
 
+       if (sp->autoclose > net->sctp.max_autoclose)
+               sp->autoclose = net->sctp.max_autoclose;
+
        return 0;
 }
 
@@ -2811,6 +2814,8 @@ static int sctp_setsockopt_rtoinfo(struct sock *sk, char __user *optval, unsigne
 {
        struct sctp_rtoinfo rtoinfo;
        struct sctp_association *asoc;
+       unsigned long rto_min, rto_max;
+       struct sctp_sock *sp = sctp_sk(sk);
 
        if (optlen != sizeof (struct sctp_rtoinfo))
                return -EINVAL;
@@ -2824,26 +2829,36 @@ static int sctp_setsockopt_rtoinfo(struct sock *sk, char __user *optval, unsigne
        if (!asoc && rtoinfo.srto_assoc_id && sctp_style(sk, UDP))
                return -EINVAL;
 
+       rto_max = rtoinfo.srto_max;
+       rto_min = rtoinfo.srto_min;
+
+       if (rto_max)
+               rto_max = asoc ? msecs_to_jiffies(rto_max) : rto_max;
+       else
+               rto_max = asoc ? asoc->rto_max : sp->rtoinfo.srto_max;
+
+       if (rto_min)
+               rto_min = asoc ? msecs_to_jiffies(rto_min) : rto_min;
+       else
+               rto_min = asoc ? asoc->rto_min : sp->rtoinfo.srto_min;
+
+       if (rto_min > rto_max)
+               return -EINVAL;
+
        if (asoc) {
                if (rtoinfo.srto_initial != 0)
                        asoc->rto_initial =
                                msecs_to_jiffies(rtoinfo.srto_initial);
-               if (rtoinfo.srto_max != 0)
-                       asoc->rto_max = msecs_to_jiffies(rtoinfo.srto_max);
-               if (rtoinfo.srto_min != 0)
-                       asoc->rto_min = msecs_to_jiffies(rtoinfo.srto_min);
+               asoc->rto_max = rto_max;
+               asoc->rto_min = rto_min;
        } else {
                /* If there is no association or the association-id = 0
                 * set the values to the endpoint.
                 */
-               struct sctp_sock *sp = sctp_sk(sk);
-
                if (rtoinfo.srto_initial != 0)
                        sp->rtoinfo.srto_initial = rtoinfo.srto_initial;
-               if (rtoinfo.srto_max != 0)
-                       sp->rtoinfo.srto_max = rtoinfo.srto_max;
-               if (rtoinfo.srto_min != 0)
-                       sp->rtoinfo.srto_min = rtoinfo.srto_min;
+               sp->rtoinfo.srto_max = rto_max;
+               sp->rtoinfo.srto_min = rto_min;
        }
 
        return 0;
index 6007124aefa018fd958b9481e012f3db2df5a5da..b9c8521c1a984be0a34d991413a495282e47f83d 100644 (file)
@@ -18,9 +18,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
index 6b36561a1b3b7cceab5f5a4a9dce7aa2bc362266..9dd5ac084663b79619b54271cbc1b44c72267db0 100644 (file)
@@ -19,9 +19,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
@@ -56,11 +55,16 @@ extern long sysctl_sctp_mem[3];
 extern int sysctl_sctp_rmem[3];
 extern int sysctl_sctp_wmem[3];
 
-static int proc_sctp_do_hmac_alg(struct ctl_table *ctl,
-                               int write,
+static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write,
+                               void __user *buffer, size_t *lenp,
+                               loff_t *ppos);
+static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write,
+                               void __user *buffer, size_t *lenp,
+                               loff_t *ppos);
+static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write,
                                void __user *buffer, size_t *lenp,
-
                                loff_t *ppos);
+
 static struct ctl_table sctp_table[] = {
        {
                .procname       = "sctp_mem",
@@ -102,17 +106,17 @@ static struct ctl_table sctp_net_table[] = {
                .data           = &init_net.sctp.rto_min,
                .maxlen         = sizeof(unsigned int),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec_minmax,
+               .proc_handler   = proc_sctp_do_rto_min,
                .extra1         = &one,
-               .extra2         = &timer_max
+               .extra2         = &init_net.sctp.rto_max
        },
        {
                .procname       = "rto_max",
                .data           = &init_net.sctp.rto_max,
                .maxlen         = sizeof(unsigned int),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec_minmax,
-               .extra1         = &one,
+               .proc_handler   = proc_sctp_do_rto_max,
+               .extra1         = &init_net.sctp.rto_min,
                .extra2         = &timer_max
        },
        {
@@ -294,8 +298,7 @@ static struct ctl_table sctp_net_table[] = {
        { /* sentinel */ }
 };
 
-static int proc_sctp_do_hmac_alg(struct ctl_table *ctl,
-                               int write,
+static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write,
                                void __user *buffer, size_t *lenp,
                                loff_t *ppos)
 {
@@ -342,6 +345,60 @@ static int proc_sctp_do_hmac_alg(struct ctl_table *ctl,
        return ret;
 }
 
+static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write,
+                               void __user *buffer, size_t *lenp,
+                               loff_t *ppos)
+{
+       struct net *net = current->nsproxy->net_ns;
+       int new_value;
+       struct ctl_table tbl;
+       unsigned int min = *(unsigned int *) ctl->extra1;
+       unsigned int max = *(unsigned int *) ctl->extra2;
+       int ret;
+
+       memset(&tbl, 0, sizeof(struct ctl_table));
+       tbl.maxlen = sizeof(unsigned int);
+
+       if (write)
+               tbl.data = &new_value;
+       else
+               tbl.data = &net->sctp.rto_min;
+       ret = proc_dointvec(&tbl, write, buffer, lenp, ppos);
+       if (write) {
+               if (ret || new_value > max || new_value < min)
+                       return -EINVAL;
+               net->sctp.rto_min = new_value;
+       }
+       return ret;
+}
+
+static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write,
+                               void __user *buffer, size_t *lenp,
+                               loff_t *ppos)
+{
+       struct net *net = current->nsproxy->net_ns;
+       int new_value;
+       struct ctl_table tbl;
+       unsigned int min = *(unsigned int *) ctl->extra1;
+       unsigned int max = *(unsigned int *) ctl->extra2;
+       int ret;
+
+       memset(&tbl, 0, sizeof(struct ctl_table));
+       tbl.maxlen = sizeof(unsigned int);
+
+       if (write)
+               tbl.data = &new_value;
+       else
+               tbl.data = &net->sctp.rto_max;
+       ret = proc_dointvec(&tbl, write, buffer, lenp, ppos);
+       if (write) {
+               if (ret || new_value > max || new_value < min)
+                       return -EINVAL;
+               net->sctp.rto_max = new_value;
+       }
+       return ret;
+}
+
 int sctp_sysctl_net_register(struct net *net)
 {
        struct ctl_table *table;
index e332efb124cc0c34f93786232353c37dd2e10ea1..d0810dc5f079f67de9bf8192fa3968fd81e245f0 100644 (file)
@@ -24,9 +24,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
@@ -573,7 +572,7 @@ void sctp_transport_burst_limited(struct sctp_transport *t)
        u32 old_cwnd = t->cwnd;
        u32 max_burst_bytes;
 
-       if (t->burst_limited)
+       if (t->burst_limited || asoc->max_burst == 0)
                return;
 
        max_burst_bytes = t->flight_size + (asoc->max_burst * asoc->pathmtu);
index fbda20028285a8bb67c1052601a9986b90f50258..7635f9f2311d31d71297045cb93c2e4217f24b2d 100644 (file)
@@ -21,9 +21,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
index 81089ed654564db6367c27f174c9b8381557c512..85c64658bd0b183df5c7a7fd8394df757cb0b4b0 100644 (file)
@@ -22,9 +22,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
index 1c1484ed605d490686c8daa87e0a7e595b9fba3c..a67470083be8a42de0ce6a7c22a1ece650fa3290 100644 (file)
@@ -21,9 +21,8 @@
  * 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.
+ * along with GNU CC; see the file COPYING.  If not, see
+ * <http://www.gnu.org/licenses/>.
  *
  * Please send any bug reports or fixes you make to the
  * email address(es):
index 0b18693f2be6deb2f6f6b6bbf99aa131c767e830..879933aaed4c07ecd9cdad1809939ff729a588a7 100644 (file)
@@ -1445,48 +1445,61 @@ SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
                err = fd1;
                goto out_release_both;
        }
+
        fd2 = get_unused_fd_flags(flags);
        if (unlikely(fd2 < 0)) {
                err = fd2;
-               put_unused_fd(fd1);
-               goto out_release_both;
+               goto out_put_unused_1;
        }
 
        newfile1 = sock_alloc_file(sock1, flags, NULL);
        if (unlikely(IS_ERR(newfile1))) {
                err = PTR_ERR(newfile1);
-               put_unused_fd(fd1);
-               put_unused_fd(fd2);
-               goto out_release_both;
+               goto out_put_unused_both;
        }
 
        newfile2 = sock_alloc_file(sock2, flags, NULL);
        if (IS_ERR(newfile2)) {
                err = PTR_ERR(newfile2);
-               fput(newfile1);
-               put_unused_fd(fd1);
-               put_unused_fd(fd2);
-               sock_release(sock2);
-               goto out;
+               goto out_fput_1;
        }
 
+       err = put_user(fd1, &usockvec[0]);
+       if (err)
+               goto out_fput_both;
+
+       err = put_user(fd2, &usockvec[1]);
+       if (err)
+               goto out_fput_both;
+
        audit_fd_pair(fd1, fd2);
+
        fd_install(fd1, newfile1);
        fd_install(fd2, newfile2);
        /* fd1 and fd2 may be already another descriptors.
         * Not kernel problem.
         */
 
-       err = put_user(fd1, &usockvec[0]);
-       if (!err)
-               err = put_user(fd2, &usockvec[1]);
-       if (!err)
-               return 0;
+       return 0;
 
-       sys_close(fd2);
-       sys_close(fd1);
-       return err;
+out_fput_both:
+       fput(newfile2);
+       fput(newfile1);
+       put_unused_fd(fd2);
+       put_unused_fd(fd1);
+       goto out;
 
+out_fput_1:
+       fput(newfile1);
+       put_unused_fd(fd2);
+       put_unused_fd(fd1);
+       sock_release(sock2);
+       goto out;
+
+out_put_unused_both:
+       put_unused_fd(fd2);
+out_put_unused_1:
+       put_unused_fd(fd1);
 out_release_both:
        sock_release(sock2);
 out_release_1:
@@ -1973,7 +1986,7 @@ static int copy_msghdr_from_user(struct msghdr *kmsg,
        if (copy_from_user(kmsg, umsg, sizeof(struct msghdr)))
                return -EFAULT;
        if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
-               return -EINVAL;
+               kmsg->msg_namelen = sizeof(struct sockaddr_storage);
        return 0;
 }
 
@@ -2968,11 +2981,8 @@ static int bond_ioctl(struct net *net, unsigned int cmd,
                         struct compat_ifreq __user *ifr32)
 {
        struct ifreq kifr;
-       struct ifreq __user *uifr;
        mm_segment_t old_fs;
        int err;
-       u32 data;
-       void __user *datap;
 
        switch (cmd) {
        case SIOCBONDENSLAVE:
@@ -2989,26 +2999,13 @@ static int bond_ioctl(struct net *net, unsigned int cmd,
                set_fs(old_fs);
 
                return err;
-       case SIOCBONDSLAVEINFOQUERY:
-       case SIOCBONDINFOQUERY:
-               uifr = compat_alloc_user_space(sizeof(*uifr));
-               if (copy_in_user(&uifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
-                       return -EFAULT;
-
-               if (get_user(data, &ifr32->ifr_ifru.ifru_data))
-                       return -EFAULT;
-
-               datap = compat_ptr(data);
-               if (put_user(datap, &uifr->ifr_ifru.ifru_data))
-                       return -EFAULT;
-
-               return dev_ioctl(net, cmd, uifr);
        default:
                return -ENOIOCTLCMD;
        }
 }
 
-static int siocdevprivate_ioctl(struct net *net, unsigned int cmd,
+/* Handle ioctls that use ifreq::ifr_data and just need struct ifreq converted */
+static int compat_ifr_data_ioctl(struct net *net, unsigned int cmd,
                                 struct compat_ifreq __user *u_ifreq32)
 {
        struct ifreq __user *u_ifreq64;
@@ -3019,19 +3016,16 @@ static int siocdevprivate_ioctl(struct net *net, unsigned int cmd,
        if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]),
                           IFNAMSIZ))
                return -EFAULT;
-       if (__get_user(data32, &u_ifreq32->ifr_ifru.ifru_data))
+       if (get_user(data32, &u_ifreq32->ifr_ifru.ifru_data))
                return -EFAULT;
        data64 = compat_ptr(data32);
 
        u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64));
 
-       /* Don't check these user accesses, just let that get trapped
-        * in the ioctl handler instead.
-        */
        if (copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0],
                         IFNAMSIZ))
                return -EFAULT;
-       if (__put_user(data64, &u_ifreq64->ifr_ifru.ifru_data))
+       if (put_user(data64, &u_ifreq64->ifr_ifru.ifru_data))
                return -EFAULT;
 
        return dev_ioctl(net, cmd, u_ifreq64);
@@ -3111,27 +3105,6 @@ static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
        return err;
 }
 
-static int compat_siocshwtstamp(struct net *net, struct compat_ifreq __user *uifr32)
-{
-       void __user *uptr;
-       compat_uptr_t uptr32;
-       struct ifreq __user *uifr;
-
-       uifr = compat_alloc_user_space(sizeof(*uifr));
-       if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
-               return -EFAULT;
-
-       if (get_user(uptr32, &uifr32->ifr_data))
-               return -EFAULT;
-
-       uptr = compat_ptr(uptr32);
-
-       if (put_user(uptr, &uifr->ifr_data))
-               return -EFAULT;
-
-       return dev_ioctl(net, SIOCSHWTSTAMP, uifr);
-}
-
 struct rtentry32 {
        u32             rt_pad1;
        struct sockaddr rt_dst;         /* target address               */
@@ -3243,7 +3216,7 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
        struct net *net = sock_net(sk);
 
        if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))
-               return siocdevprivate_ioctl(net, cmd, argp);
+               return compat_ifr_data_ioctl(net, cmd, argp);
 
        switch (cmd) {
        case SIOCSIFBR:
@@ -3263,8 +3236,6 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
        case SIOCBONDENSLAVE:
        case SIOCBONDRELEASE:
        case SIOCBONDSETHWADDR:
-       case SIOCBONDSLAVEINFOQUERY:
-       case SIOCBONDINFOQUERY:
        case SIOCBONDCHANGEACTIVE:
                return bond_ioctl(net, cmd, argp);
        case SIOCADDRT:
@@ -3274,8 +3245,11 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
                return do_siocgstamp(net, sock, cmd, argp);
        case SIOCGSTAMPNS:
                return do_siocgstampns(net, sock, cmd, argp);
+       case SIOCBONDSLAVEINFOQUERY:
+       case SIOCBONDINFOQUERY:
        case SIOCSHWTSTAMP:
-               return compat_siocshwtstamp(net, argp);
+       case SIOCGHWTSTAMP:
+               return compat_ifr_data_ioctl(net, cmd, argp);
 
        case FIOSETOWN:
        case SIOCSPGRP:
index 97912b40c254d8a270e18f71e9e5b714e0dbcba8..0a2aee060f9f05241bdedd25149b081e32bd7896 100644 (file)
@@ -536,8 +536,7 @@ static void warn_gssd(void)
        unsigned long now = jiffies;
 
        if (time_after(now, ratelimit)) {
-               printk(KERN_WARNING "RPC: AUTH_GSS upcall timed out.\n"
-                               "Please check user daemon is running.\n");
+               pr_warn("RPC: AUTH_GSS upcall failed. Please check user daemon is running.\n");
                ratelimit = now + 15*HZ;
        }
 }
@@ -600,7 +599,6 @@ gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
        struct rpc_pipe *pipe;
        struct rpc_cred *cred = &gss_cred->gc_base;
        struct gss_upcall_msg *gss_msg;
-       unsigned long timeout;
        DEFINE_WAIT(wait);
        int err;
 
@@ -608,17 +606,16 @@ gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
                __func__, from_kuid(&init_user_ns, cred->cr_uid));
 retry:
        err = 0;
-       /* Default timeout is 15s unless we know that gssd is not running */
-       timeout = 15 * HZ;
-       if (!sn->gssd_running)
-               timeout = HZ >> 2;
+       /* if gssd is down, just skip upcalling altogether */
+       if (!gssd_running(net)) {
+               warn_gssd();
+               return -EACCES;
+       }
        gss_msg = gss_setup_upcall(gss_auth, cred);
        if (PTR_ERR(gss_msg) == -EAGAIN) {
                err = wait_event_interruptible_timeout(pipe_version_waitqueue,
-                               sn->pipe_version >= 0, timeout);
+                               sn->pipe_version >= 0, 15 * HZ);
                if (sn->pipe_version < 0) {
-                       if (err == 0)
-                               sn->gssd_running = 0;
                        warn_gssd();
                        err = -EACCES;
                }
@@ -1517,7 +1514,7 @@ out:
 static int
 gss_refresh_null(struct rpc_task *task)
 {
-       return -EACCES;
+       return 0;
 }
 
 static __be32 *
index 779742cfc1ffe3178fc0c320b6d0832e0f420d64..94e506f9d72bb62440d923360753c98ecf5f6725 100644 (file)
@@ -14,6 +14,7 @@ struct sunrpc_net {
        struct cache_detail *rsi_cache;
 
        struct super_block *pipefs_sb;
+       struct rpc_pipe *gssd_dummy;
        struct mutex pipefs_sb_lock;
 
        struct list_head all_clients;
@@ -32,8 +33,6 @@ struct sunrpc_net {
        int pipe_version;
        atomic_t pipe_users;
        struct proc_dir_entry *use_gssp_proc;
-
-       unsigned int gssd_running;
 };
 
 extern int sunrpc_net_id;
index bf04b30a788a5425b28ba70c11a50b77bfc9c697..5d973b25b5b0543fc5abb9afa3652fe809cb5387 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/fsnotify.h>
 #include <linux/kernel.h>
 #include <linux/rcupdate.h>
+#include <linux/utsname.h>
 
 #include <asm/ioctls.h>
 #include <linux/poll.h>
@@ -38,7 +39,7 @@
 #define NET_NAME(net)  ((net == &init_net) ? " (init_net)" : "")
 
 static struct file_system_type rpc_pipe_fs_type;
-
+static const struct rpc_pipe_ops gssd_dummy_pipe_ops;
 
 static struct kmem_cache *rpc_inode_cachep __read_mostly;
 
@@ -216,14 +217,11 @@ rpc_destroy_inode(struct inode *inode)
 static int
 rpc_pipe_open(struct inode *inode, struct file *filp)
 {
-       struct net *net = inode->i_sb->s_fs_info;
-       struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
        struct rpc_pipe *pipe;
        int first_open;
        int res = -ENXIO;
 
        mutex_lock(&inode->i_mutex);
-       sn->gssd_running = 1;
        pipe = RPC_I(inode)->pipe;
        if (pipe == NULL)
                goto out;
@@ -1159,6 +1157,7 @@ enum {
        RPCAUTH_nfsd4_cb,
        RPCAUTH_cache,
        RPCAUTH_nfsd,
+       RPCAUTH_gssd,
        RPCAUTH_RootEOF
 };
 
@@ -1195,6 +1194,10 @@ static const struct rpc_filelist files[] = {
                .name = "nfsd",
                .mode = S_IFDIR | S_IRUGO | S_IXUGO,
        },
+       [RPCAUTH_gssd] = {
+               .name = "gssd",
+               .mode = S_IFDIR | S_IRUGO | S_IXUGO,
+       },
 };
 
 /*
@@ -1208,13 +1211,24 @@ struct dentry *rpc_d_lookup_sb(const struct super_block *sb,
 }
 EXPORT_SYMBOL_GPL(rpc_d_lookup_sb);
 
-void rpc_pipefs_init_net(struct net *net)
+int rpc_pipefs_init_net(struct net *net)
 {
        struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
 
+       sn->gssd_dummy = rpc_mkpipe_data(&gssd_dummy_pipe_ops, 0);
+       if (IS_ERR(sn->gssd_dummy))
+               return PTR_ERR(sn->gssd_dummy);
+
        mutex_init(&sn->pipefs_sb_lock);
-       sn->gssd_running = 1;
        sn->pipe_version = -1;
+       return 0;
+}
+
+void rpc_pipefs_exit_net(struct net *net)
+{
+       struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
+
+       rpc_destroy_pipe_data(sn->gssd_dummy);
 }
 
 /*
@@ -1244,11 +1258,122 @@ void rpc_put_sb_net(const struct net *net)
 }
 EXPORT_SYMBOL_GPL(rpc_put_sb_net);
 
+static const struct rpc_filelist gssd_dummy_clnt_dir[] = {
+       [0] = {
+               .name = "clntXX",
+               .mode = S_IFDIR | S_IRUGO | S_IXUGO,
+       },
+};
+
+static ssize_t
+dummy_downcall(struct file *filp, const char __user *src, size_t len)
+{
+       return -EINVAL;
+}
+
+static const struct rpc_pipe_ops gssd_dummy_pipe_ops = {
+       .upcall         = rpc_pipe_generic_upcall,
+       .downcall       = dummy_downcall,
+};
+
+/*
+ * Here we present a bogus "info" file to keep rpc.gssd happy. We don't expect
+ * that it will ever use this info to handle an upcall, but rpc.gssd expects
+ * that this file will be there and have a certain format.
+ */
+static int
+rpc_show_dummy_info(struct seq_file *m, void *v)
+{
+       seq_printf(m, "RPC server: %s\n", utsname()->nodename);
+       seq_printf(m, "service: foo (1) version 0\n");
+       seq_printf(m, "address: 127.0.0.1\n");
+       seq_printf(m, "protocol: tcp\n");
+       seq_printf(m, "port: 0\n");
+       return 0;
+}
+
+static int
+rpc_dummy_info_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, rpc_show_dummy_info, NULL);
+}
+
+static const struct file_operations rpc_dummy_info_operations = {
+       .owner          = THIS_MODULE,
+       .open           = rpc_dummy_info_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static const struct rpc_filelist gssd_dummy_info_file[] = {
+       [0] = {
+               .name = "info",
+               .i_fop = &rpc_dummy_info_operations,
+               .mode = S_IFREG | S_IRUSR,
+       },
+};
+
+/**
+ * rpc_gssd_dummy_populate - create a dummy gssd pipe
+ * @root:      root of the rpc_pipefs filesystem
+ * @pipe_data: pipe data created when netns is initialized
+ *
+ * Create a dummy set of directories and a pipe that gssd can hold open to
+ * indicate that it is up and running.
+ */
+static struct dentry *
+rpc_gssd_dummy_populate(struct dentry *root, struct rpc_pipe *pipe_data)
+{
+       int ret = 0;
+       struct dentry *gssd_dentry;
+       struct dentry *clnt_dentry = NULL;
+       struct dentry *pipe_dentry = NULL;
+       struct qstr q = QSTR_INIT(files[RPCAUTH_gssd].name,
+                                 strlen(files[RPCAUTH_gssd].name));
+
+       /* We should never get this far if "gssd" doesn't exist */
+       gssd_dentry = d_hash_and_lookup(root, &q);
+       if (!gssd_dentry)
+               return ERR_PTR(-ENOENT);
+
+       ret = rpc_populate(gssd_dentry, gssd_dummy_clnt_dir, 0, 1, NULL);
+       if (ret) {
+               pipe_dentry = ERR_PTR(ret);
+               goto out;
+       }
+
+       q.name = gssd_dummy_clnt_dir[0].name;
+       q.len = strlen(gssd_dummy_clnt_dir[0].name);
+       clnt_dentry = d_hash_and_lookup(gssd_dentry, &q);
+       if (!clnt_dentry) {
+               pipe_dentry = ERR_PTR(-ENOENT);
+               goto out;
+       }
+
+       ret = rpc_populate(clnt_dentry, gssd_dummy_info_file, 0, 1, NULL);
+       if (ret) {
+               __rpc_depopulate(gssd_dentry, gssd_dummy_clnt_dir, 0, 1);
+               pipe_dentry = ERR_PTR(ret);
+               goto out;
+       }
+
+       pipe_dentry = rpc_mkpipe_dentry(clnt_dentry, "gssd", NULL, pipe_data);
+       if (IS_ERR(pipe_dentry)) {
+               __rpc_depopulate(clnt_dentry, gssd_dummy_info_file, 0, 1);
+               __rpc_depopulate(gssd_dentry, gssd_dummy_clnt_dir, 0, 1);
+       }
+out:
+       dput(clnt_dentry);
+       dput(gssd_dentry);
+       return pipe_dentry;
+}
+
 static int
 rpc_fill_super(struct super_block *sb, void *data, int silent)
 {
        struct inode *inode;
-       struct dentry *root;
+       struct dentry *root, *gssd_dentry;
        struct net *net = data;
        struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
        int err;
@@ -1266,6 +1391,13 @@ rpc_fill_super(struct super_block *sb, void *data, int silent)
                return -ENOMEM;
        if (rpc_populate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF, NULL))
                return -ENOMEM;
+
+       gssd_dentry = rpc_gssd_dummy_populate(root, sn->gssd_dummy);
+       if (IS_ERR(gssd_dentry)) {
+               __rpc_depopulate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF);
+               return PTR_ERR(gssd_dentry);
+       }
+
        dprintk("RPC:       sending pipefs MOUNT notification for net %p%s\n",
                net, NET_NAME(net));
        mutex_lock(&sn->pipefs_sb_lock);
@@ -1280,6 +1412,7 @@ rpc_fill_super(struct super_block *sb, void *data, int silent)
        return 0;
 
 err_depopulate:
+       dput(gssd_dentry);
        blocking_notifier_call_chain(&rpc_pipefs_notifier_list,
                                           RPC_PIPEFS_UMOUNT,
                                           sb);
@@ -1289,6 +1422,16 @@ err_depopulate:
        return err;
 }
 
+bool
+gssd_running(struct net *net)
+{
+       struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
+       struct rpc_pipe *pipe = sn->gssd_dummy;
+
+       return pipe->nreaders || pipe->nwriters;
+}
+EXPORT_SYMBOL_GPL(gssd_running);
+
 static struct dentry *
 rpc_mount(struct file_system_type *fs_type,
                int flags, const char *dev_name, void *data)
index 3d6498af9adc1a1035005c735ee932de6488bee3..cd30120de9e4eb7ba413135dd2eb690311d784cb 100644 (file)
@@ -44,12 +44,17 @@ static __net_init int sunrpc_init_net(struct net *net)
        if (err)
                goto err_unixgid;
 
-       rpc_pipefs_init_net(net);
+       err = rpc_pipefs_init_net(net);
+       if (err)
+               goto err_pipefs;
+
        INIT_LIST_HEAD(&sn->all_clients);
        spin_lock_init(&sn->rpc_client_lock);
        spin_lock_init(&sn->rpcb_clnt_lock);
        return 0;
 
+err_pipefs:
+       unix_gid_cache_destroy(net);
 err_unixgid:
        ip_map_cache_destroy(net);
 err_ipmap:
@@ -60,6 +65,7 @@ err_proc:
 
 static __net_exit void sunrpc_exit_net(struct net *net)
 {
+       rpc_pipefs_exit_net(net);
        unix_gid_cache_destroy(net);
        ip_map_cache_destroy(net);
        rpc_proc_exit(net);
index dd9d295813cff2a8738946a3309fc31dcf57ebf0..0f4f39174a708929e4dabf90cab063fd303ee8ba 100644 (file)
@@ -2932,10 +2932,9 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args)
 
        /*
         * Once we've associated a backchannel xprt with a connection,
-        * we want to keep it around as long as long as the connection
-        * lasts, in case we need to start using it for a backchannel
-        * again; this reference won't be dropped until bc_xprt is
-        * destroyed.
+        * we want to keep it around as long as the connection lasts,
+        * in case we need to start using it for a backchannel again;
+        * this reference won't be dropped until bc_xprt is destroyed.
         */
        xprt_get(xprt);
        args->bc_xprt->xpt_bc_xprt = xprt;
index 0d4402587fdf9fec2c1768cfdff6356e24dbb4fd..4c2a80b3c01e102dfe7e17d6d17378f51b9b929d 100644 (file)
@@ -621,12 +621,6 @@ static int tipc_bcbearer_send(struct sk_buff *buf, struct tipc_bearer *unused1,
                if (!p)
                        break; /* No more bearers to try */
 
-               if (tipc_bearer_blocked(p)) {
-                       if (!s || tipc_bearer_blocked(s))
-                               continue; /* Can't use either bearer */
-                       b = s;
-               }
-
                tipc_nmap_diff(&bcbearer->remains, &b->nodes,
                               &bcbearer->remains_new);
                if (bcbearer->remains_new.count == bcbearer->remains.count)
index 3f9707a16d0650d6367ad716ab2a110318a03e96..3bb5f266b0eb4fe803ca6de5f42ade2e11673b6b 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * net/tipc/bearer.c: TIPC bearer code
  *
- * Copyright (c) 1996-2006, Ericsson AB
- * Copyright (c) 2004-2006, 2010-2011, Wind River Systems
+ * Copyright (c) 1996-2006, 2013, Ericsson AB
+ * Copyright (c) 2004-2006, 2010-2013, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 
 #define MAX_ADDR_STR 60
 
-static struct tipc_media *media_list[MAX_MEDIA];
-static u32 media_count;
+static struct tipc_media * const media_info_array[] = {
+       &eth_media_info,
+#ifdef CONFIG_TIPC_MEDIA_IB
+       &ib_media_info,
+#endif
+       NULL
+};
 
 struct tipc_bearer tipc_bearers[MAX_BEARERS];
 
@@ -55,11 +60,11 @@ struct tipc_media *tipc_media_find(const char *name)
 {
        u32 i;
 
-       for (i = 0; i < media_count; i++) {
-               if (!strcmp(media_list[i]->name, name))
-                       return media_list[i];
+       for (i = 0; media_info_array[i] != NULL; i++) {
+               if (!strcmp(media_info_array[i]->name, name))
+                       break;
        }
-       return NULL;
+       return media_info_array[i];
 }
 
 /**
@@ -69,44 +74,11 @@ static struct tipc_media *media_find_id(u8 type)
 {
        u32 i;
 
-       for (i = 0; i < media_count; i++) {
-               if (media_list[i]->type_id == type)
-                       return media_list[i];
+       for (i = 0; media_info_array[i] != NULL; i++) {
+               if (media_info_array[i]->type_id == type)
+                       break;
        }
-       return NULL;
-}
-
-/**
- * tipc_register_media - register a media type
- *
- * Bearers for this media type must be activated separately at a later stage.
- */
-int tipc_register_media(struct tipc_media *m_ptr)
-{
-       int res = -EINVAL;
-
-       write_lock_bh(&tipc_net_lock);
-
-       if ((strlen(m_ptr->name) + 1) > TIPC_MAX_MEDIA_NAME)
-               goto exit;
-       if (m_ptr->priority > TIPC_MAX_LINK_PRI)
-               goto exit;
-       if ((m_ptr->tolerance < TIPC_MIN_LINK_TOL) ||
-           (m_ptr->tolerance > TIPC_MAX_LINK_TOL))
-               goto exit;
-       if (media_count >= MAX_MEDIA)
-               goto exit;
-       if (tipc_media_find(m_ptr->name) || media_find_id(m_ptr->type_id))
-               goto exit;
-
-       media_list[media_count] = m_ptr;
-       media_count++;
-       res = 0;
-exit:
-       write_unlock_bh(&tipc_net_lock);
-       if (res)
-               pr_warn("Media <%s> registration error\n", m_ptr->name);
-       return res;
+       return media_info_array[i];
 }
 
 /**
@@ -144,13 +116,11 @@ struct sk_buff *tipc_media_get_names(void)
        if (!buf)
                return NULL;
 
-       read_lock_bh(&tipc_net_lock);
-       for (i = 0; i < media_count; i++) {
+       for (i = 0; media_info_array[i] != NULL; i++) {
                tipc_cfg_append_tlv(buf, TIPC_TLV_MEDIA_NAME,
-                                   media_list[i]->name,
-                                   strlen(media_list[i]->name) + 1);
+                                   media_info_array[i]->name,
+                                   strlen(media_info_array[i]->name) + 1);
        }
-       read_unlock_bh(&tipc_net_lock);
        return buf;
 }
 
@@ -239,7 +209,7 @@ struct tipc_bearer *tipc_bearer_find_interface(const char *if_name)
 struct sk_buff *tipc_bearer_get_names(void)
 {
        struct sk_buff *buf;
-       struct tipc_bearer *b_ptr;
+       struct tipc_bearer *b;
        int i, j;
 
        buf = tipc_cfg_reply_alloc(MAX_BEARERS * TLV_SPACE(TIPC_MAX_BEARER_NAME));
@@ -247,13 +217,13 @@ struct sk_buff *tipc_bearer_get_names(void)
                return NULL;
 
        read_lock_bh(&tipc_net_lock);
-       for (i = 0; i < media_count; i++) {
+       for (i = 0; media_info_array[i] != NULL; i++) {
                for (j = 0; j < MAX_BEARERS; j++) {
-                       b_ptr = &tipc_bearers[j];
-                       if (b_ptr->active && (b_ptr->media == media_list[i])) {
+                       b = &tipc_bearers[j];
+                       if (b->active && (b->media == media_info_array[i])) {
                                tipc_cfg_append_tlv(buf, TIPC_TLV_BEARER_NAME,
-                                                   b_ptr->name,
-                                                   strlen(b_ptr->name) + 1);
+                                                   b->name,
+                                                   strlen(b->name) + 1);
                        }
                }
        }
@@ -275,31 +245,6 @@ void tipc_bearer_remove_dest(struct tipc_bearer *b_ptr, u32 dest)
        tipc_disc_remove_dest(b_ptr->link_req);
 }
 
-/*
- * Interrupt enabling new requests after bearer blocking:
- * See bearer_send().
- */
-void tipc_continue(struct tipc_bearer *b)
-{
-       spin_lock_bh(&b->lock);
-       b->blocked = 0;
-       spin_unlock_bh(&b->lock);
-}
-
-/*
- * tipc_bearer_blocked - determines if bearer is currently blocked
- */
-int tipc_bearer_blocked(struct tipc_bearer *b)
-{
-       int res;
-
-       spin_lock_bh(&b->lock);
-       res = b->blocked;
-       spin_unlock_bh(&b->lock);
-
-       return res;
-}
-
 /**
  * tipc_enable_bearer - enable bearer with the given name
  */
@@ -387,6 +332,7 @@ restart:
 
        b_ptr = &tipc_bearers[bearer_id];
        strcpy(b_ptr->name, name);
+       b_ptr->media = m_ptr;
        res = m_ptr->enable_media(b_ptr);
        if (res) {
                pr_warn("Bearer <%s> rejected, enable failure (%d)\n",
@@ -395,7 +341,6 @@ restart:
        }
 
        b_ptr->identity = bearer_id;
-       b_ptr->media = m_ptr;
        b_ptr->tolerance = m_ptr->tolerance;
        b_ptr->window = m_ptr->window;
        b_ptr->net_plane = bearer_id + 'A';
@@ -420,17 +365,16 @@ exit:
 }
 
 /**
- * tipc_block_bearer - Block the bearer, and reset all its links
+ * tipc_reset_bearer - Reset all links established over this bearer
  */
-int tipc_block_bearer(struct tipc_bearer *b_ptr)
+static int tipc_reset_bearer(struct tipc_bearer *b_ptr)
 {
        struct tipc_link *l_ptr;
        struct tipc_link *temp_l_ptr;
 
        read_lock_bh(&tipc_net_lock);
-       pr_info("Blocking bearer <%s>\n", b_ptr->name);
+       pr_info("Resetting bearer <%s>\n", b_ptr->name);
        spin_lock_bh(&b_ptr->lock);
-       b_ptr->blocked = 1;
        list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) {
                struct tipc_node *n_ptr = l_ptr->owner;
 
@@ -456,7 +400,6 @@ static void bearer_disable(struct tipc_bearer *b_ptr)
 
        pr_info("Disabling bearer <%s>\n", b_ptr->name);
        spin_lock_bh(&b_ptr->lock);
-       b_ptr->blocked = 1;
        b_ptr->media->disable_media(b_ptr);
        list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) {
                tipc_link_delete(l_ptr);
@@ -490,6 +433,211 @@ int tipc_disable_bearer(const char *name)
 }
 
 
+/* tipc_l2_media_addr_set - initialize Ethernet media address structure
+ *
+ * Media-dependent "value" field stores MAC address in first 6 bytes
+ * and zeroes out the remaining bytes.
+ */
+void tipc_l2_media_addr_set(const struct tipc_bearer *b,
+                           struct tipc_media_addr *a, char *mac)
+{
+       int len = b->media->hwaddr_len;
+
+       if (unlikely(sizeof(a->value) < len)) {
+               WARN_ONCE(1, "Media length invalid\n");
+               return;
+       }
+
+       memcpy(a->value, mac, len);
+       memset(a->value + len, 0, sizeof(a->value) - len);
+       a->media_id = b->media->type_id;
+       a->broadcast = !memcmp(mac, b->bcast_addr.value, len);
+}
+
+int tipc_enable_l2_media(struct tipc_bearer *b)
+{
+       struct net_device *dev;
+       char *driver_name = strchr((const char *)b->name, ':') + 1;
+
+       /* Find device with specified name */
+       dev = dev_get_by_name(&init_net, driver_name);
+       if (!dev)
+               return -ENODEV;
+
+       /* Associate TIPC bearer with Ethernet bearer */
+       b->media_ptr = dev;
+       memset(b->bcast_addr.value, 0, sizeof(b->bcast_addr.value));
+       memcpy(b->bcast_addr.value, dev->broadcast, b->media->hwaddr_len);
+       b->bcast_addr.media_id = b->media->type_id;
+       b->bcast_addr.broadcast = 1;
+       b->mtu = dev->mtu;
+       tipc_l2_media_addr_set(b, &b->addr, (char *)dev->dev_addr);
+       rcu_assign_pointer(dev->tipc_ptr, b);
+       return 0;
+}
+
+/* tipc_disable_l2_media - detach TIPC bearer from an Ethernet interface
+ *
+ * Mark Ethernet bearer as inactive so that incoming buffers are thrown away,
+ * then get worker thread to complete bearer cleanup.  (Can't do cleanup
+ * here because cleanup code needs to sleep and caller holds spinlocks.)
+ */
+void tipc_disable_l2_media(struct tipc_bearer *b)
+{
+       struct net_device *dev = (struct net_device *)b->media_ptr;
+       RCU_INIT_POINTER(dev->tipc_ptr, NULL);
+       dev_put(dev);
+}
+
+/**
+ * tipc_l2_send_msg - send a TIPC packet out over an Ethernet interface
+ * @buf: the packet to be sent
+ * @b_ptr: the bearer throught which the packet is to be sent
+ * @dest: peer destination address
+ */
+int tipc_l2_send_msg(struct sk_buff *buf, struct tipc_bearer *b,
+                    struct tipc_media_addr *dest)
+{
+       struct sk_buff *clone;
+       int delta;
+       struct net_device *dev = (struct net_device *)b->media_ptr;
+
+       clone = skb_clone(buf, GFP_ATOMIC);
+       if (!clone)
+               return 0;
+
+       delta = dev->hard_header_len - skb_headroom(buf);
+       if ((delta > 0) &&
+           pskb_expand_head(clone, SKB_DATA_ALIGN(delta), 0, GFP_ATOMIC)) {
+               kfree_skb(clone);
+               return 0;
+       }
+
+       skb_reset_network_header(clone);
+       clone->dev = dev;
+       clone->protocol = htons(ETH_P_TIPC);
+       dev_hard_header(clone, dev, ETH_P_TIPC, dest->value,
+                       dev->dev_addr, clone->len);
+       dev_queue_xmit(clone);
+       return 0;
+}
+
+/* tipc_bearer_send- sends buffer to destination over bearer
+ *
+ * IMPORTANT:
+ * The media send routine must not alter the buffer being passed in
+ * as it may be needed for later retransmission!
+ */
+void tipc_bearer_send(struct tipc_bearer *b, struct sk_buff *buf,
+                     struct tipc_media_addr *dest)
+{
+       b->media->send_msg(buf, b, dest);
+}
+
+/**
+ * tipc_l2_rcv_msg - handle incoming TIPC message from an interface
+ * @buf: the received packet
+ * @dev: the net device that the packet was received on
+ * @pt: the packet_type structure which was used to register this handler
+ * @orig_dev: the original receive net device in case the device is a bond
+ *
+ * Accept only packets explicitly sent to this node, or broadcast packets;
+ * ignores packets sent using interface multicast, and traffic sent to other
+ * nodes (which can happen if interface is running in promiscuous mode).
+ */
+static int tipc_l2_rcv_msg(struct sk_buff *buf, struct net_device *dev,
+                          struct packet_type *pt, struct net_device *orig_dev)
+{
+       struct tipc_bearer *b_ptr;
+
+       if (!net_eq(dev_net(dev), &init_net)) {
+               kfree_skb(buf);
+               return NET_RX_DROP;
+       }
+
+       rcu_read_lock();
+       b_ptr = rcu_dereference(dev->tipc_ptr);
+       if (likely(b_ptr)) {
+               if (likely(buf->pkt_type <= PACKET_BROADCAST)) {
+                       buf->next = NULL;
+                       tipc_recv_msg(buf, b_ptr);
+                       rcu_read_unlock();
+                       return NET_RX_SUCCESS;
+               }
+       }
+       rcu_read_unlock();
+
+       kfree_skb(buf);
+       return NET_RX_DROP;
+}
+
+/**
+ * tipc_l2_device_event - handle device events from network device
+ * @nb: the context of the notification
+ * @evt: the type of event
+ * @ptr: the net device that the event was on
+ *
+ * This function is called by the Ethernet driver in case of link
+ * change event.
+ */
+static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt,
+                               void *ptr)
+{
+       struct tipc_bearer *b_ptr;
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+
+       if (!net_eq(dev_net(dev), &init_net))
+               return NOTIFY_DONE;
+
+       rcu_read_lock();
+       b_ptr = rcu_dereference(dev->tipc_ptr);
+       if (!b_ptr) {
+               rcu_read_unlock();
+               return NOTIFY_DONE;
+       }
+
+       b_ptr->mtu = dev->mtu;
+
+       switch (evt) {
+       case NETDEV_CHANGE:
+               if (netif_carrier_ok(dev))
+                       break;
+       case NETDEV_DOWN:
+       case NETDEV_CHANGEMTU:
+       case NETDEV_CHANGEADDR:
+               tipc_reset_bearer(b_ptr);
+               break;
+       case NETDEV_UNREGISTER:
+       case NETDEV_CHANGENAME:
+               tipc_disable_bearer(b_ptr->name);
+               break;
+       }
+       rcu_read_unlock();
+
+       return NOTIFY_OK;
+}
+
+static struct packet_type tipc_packet_type __read_mostly = {
+       .type = __constant_htons(ETH_P_TIPC),
+       .func = tipc_l2_rcv_msg,
+};
+
+static struct notifier_block notifier = {
+       .notifier_call  = tipc_l2_device_event,
+       .priority       = 0,
+};
+
+int tipc_bearer_setup(void)
+{
+       dev_add_pack(&tipc_packet_type);
+       return register_netdevice_notifier(&notifier);
+}
+
+void tipc_bearer_cleanup(void)
+{
+       unregister_netdevice_notifier(&notifier);
+       dev_remove_pack(&tipc_packet_type);
+}
 
 void tipc_bearer_stop(void)
 {
@@ -499,5 +647,4 @@ void tipc_bearer_stop(void)
                if (tipc_bearers[i].active)
                        bearer_disable(&tipc_bearers[i]);
        }
-       media_count = 0;
 }
index e5e04be6fffa3782c01f37db795c7f84c8b71793..fa95c34ca92648633679cc43692e7cfd6a03bc86 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * net/tipc/bearer.h: Include file for TIPC bearer code
  *
- * Copyright (c) 1996-2006, Ericsson AB
+ * Copyright (c) 1996-2006, 2013, Ericsson AB
  * Copyright (c) 2005, 2010-2011, Wind River Systems
  * All rights reserved.
  *
@@ -73,18 +73,18 @@ struct tipc_media_addr {
 struct tipc_bearer;
 
 /**
- * struct tipc_media - TIPC media information available to internal users
+ * struct tipc_media - Media specific info exposed to generic bearer layer
  * @send_msg: routine which handles buffer transmission
  * @enable_media: routine which enables a media
  * @disable_media: routine which disables a media
  * @addr2str: routine which converts media address to string
  * @addr2msg: routine which converts media address to protocol message area
  * @msg2addr: routine which converts media address from protocol message area
- * @bcast_addr: media address used in broadcasting
  * @priority: default link (and bearer) priority
  * @tolerance: default time (in ms) before declaring link failure
  * @window: default window (in packets) before declaring link congestion
  * @type_id: TIPC media identifier
+ * @hwaddr_len: TIPC media address len
  * @name: media name
  */
 struct tipc_media {
@@ -101,18 +101,20 @@ struct tipc_media {
        u32 tolerance;
        u32 window;
        u32 type_id;
+       u32 hwaddr_len;
        char name[TIPC_MAX_MEDIA_NAME];
 };
 
 /**
- * struct tipc_bearer - TIPC bearer structure
+ * struct tipc_bearer - Generic TIPC bearer structure
+ * @dev: ptr to associated network device
  * @usr_handle: pointer to additional media-specific information about bearer
  * @mtu: max packet size bearer can support
- * @blocked: non-zero if bearer is blocked
  * @lock: spinlock for controlling access to bearer
  * @addr: media-specific address associated with bearer
  * @name: bearer name (format = media:interface)
  * @media: ptr to media structure associated with bearer
+ * @bcast_addr: media address used in broadcasting
  * @priority: default link priority for bearer
  * @window: default window size for bearer
  * @tolerance: default link tolerance for bearer
@@ -128,9 +130,8 @@ struct tipc_media {
  * care of initializing all other fields.
  */
 struct tipc_bearer {
-       void *usr_handle;                       /* initalized by media */
+       void *media_ptr;                        /* initalized by media */
        u32 mtu;                                /* initalized by media */
-       int blocked;                            /* initalized by media */
        struct tipc_media_addr addr;            /* initalized by media */
        char name[TIPC_MAX_BEARER_NAME];
        spinlock_t lock;
@@ -159,34 +160,31 @@ extern struct tipc_bearer tipc_bearers[];
 /*
  * TIPC routines available to supported media types
  */
-int tipc_register_media(struct tipc_media *m_ptr);
 
 void tipc_recv_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr);
 
-int  tipc_block_bearer(struct tipc_bearer *b_ptr);
-void tipc_continue(struct tipc_bearer *tb_ptr);
-
 int tipc_enable_bearer(const char *bearer_name, u32 disc_domain, u32 priority);
 int tipc_disable_bearer(const char *name);
 
 /*
  * Routines made available to TIPC by supported media types
  */
-int  tipc_eth_media_start(void);
-void tipc_eth_media_stop(void);
+extern struct tipc_media eth_media_info;
 
 #ifdef CONFIG_TIPC_MEDIA_IB
-int  tipc_ib_media_start(void);
-void tipc_ib_media_stop(void);
-#else
-static inline int tipc_ib_media_start(void) { return 0; }
-static inline void tipc_ib_media_stop(void) { return; }
+extern struct tipc_media ib_media_info;
 #endif
 
 int tipc_media_set_priority(const char *name, u32 new_value);
 int tipc_media_set_window(const char *name, u32 new_value);
 void tipc_media_addr_printf(char *buf, int len, struct tipc_media_addr *a);
 struct sk_buff *tipc_media_get_names(void);
+void tipc_l2_media_addr_set(const struct tipc_bearer *b,
+                           struct tipc_media_addr *a, char *mac);
+int tipc_enable_l2_media(struct tipc_bearer *b);
+void tipc_disable_l2_media(struct tipc_bearer *b);
+int tipc_l2_send_msg(struct sk_buff *buf, struct tipc_bearer *b,
+                    struct tipc_media_addr *dest);
 
 struct sk_buff *tipc_bearer_get_names(void);
 void tipc_bearer_add_dest(struct tipc_bearer *b_ptr, u32 dest);
@@ -194,20 +192,10 @@ void tipc_bearer_remove_dest(struct tipc_bearer *b_ptr, u32 dest);
 struct tipc_bearer *tipc_bearer_find(const char *name);
 struct tipc_bearer *tipc_bearer_find_interface(const char *if_name);
 struct tipc_media *tipc_media_find(const char *name);
-int tipc_bearer_blocked(struct tipc_bearer *b_ptr);
+int tipc_bearer_setup(void);
+void tipc_bearer_cleanup(void);
 void tipc_bearer_stop(void);
-
-/**
- * tipc_bearer_send- sends buffer to destination over bearer
- *
- * IMPORTANT:
- * The media send routine must not alter the buffer being passed in
- * as it may be needed for later retransmission!
- */
-static inline void tipc_bearer_send(struct tipc_bearer *b, struct sk_buff *buf,
-                                  struct tipc_media_addr *dest)
-{
-       b->media->send_msg(buf, b, dest);
-}
+void tipc_bearer_send(struct tipc_bearer *b, struct sk_buff *buf,
+                     struct tipc_media_addr *dest);
 
 #endif /* _TIPC_BEARER_H */
index fd4eeeaa972a6f4226f1dce420d7fb0b17670c78..f9e88d8b04ca182b2e8c217e579647fbf9581e4e 100644 (file)
@@ -82,8 +82,7 @@ struct sk_buff *tipc_buf_acquire(u32 size)
 static void tipc_core_stop_net(void)
 {
        tipc_net_stop();
-       tipc_eth_media_stop();
-       tipc_ib_media_stop();
+       tipc_bearer_cleanup();
 }
 
 /**
@@ -94,10 +93,7 @@ int tipc_core_start_net(unsigned long addr)
        int res;
 
        tipc_net_start(addr);
-       res = tipc_eth_media_start();
-       if (res < 0)
-               goto err;
-       res = tipc_ib_media_start();
+       res = tipc_bearer_setup();
        if (res < 0)
                goto err;
        return res;
@@ -113,7 +109,6 @@ err:
 static void tipc_core_stop(void)
 {
        tipc_netlink_stop();
-       tipc_handler_stop();
        tipc_cfg_stop();
        tipc_subscr_stop();
        tipc_nametbl_stop();
@@ -146,9 +141,10 @@ static int tipc_core_start(void)
                res = tipc_subscr_start();
        if (!res)
                res = tipc_cfg_init();
-       if (res)
+       if (res) {
+               tipc_handler_stop();
                tipc_core_stop();
-
+       }
        return res;
 }
 
@@ -178,6 +174,7 @@ static int __init tipc_init(void)
 
 static void __exit tipc_exit(void)
 {
+       tipc_handler_stop();
        tipc_core_stop_net();
        tipc_core_stop();
        pr_info("Deactivated\n");
index ecc758c6eacfced941fb90b923d2cfd94783a315..bc849f1efa167739d4831ea0f013f28541de2a79 100644 (file)
@@ -239,7 +239,7 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr)
        /* Accept discovery message & send response, if necessary */
        link_fully_up = link_working_working(link);
 
-       if ((type == DSC_REQ_MSG) && !link_fully_up && !b_ptr->blocked) {
+       if ((type == DSC_REQ_MSG) && !link_fully_up) {
                rbuf = tipc_disc_init_msg(DSC_RESP_MSG, orig, b_ptr);
                if (rbuf) {
                        tipc_bearer_send(b_ptr, rbuf, &media_addr);
@@ -287,16 +287,6 @@ void tipc_disc_remove_dest(struct tipc_link_req *req)
        disc_update(req);
 }
 
-/**
- * disc_send_msg - send link setup request message
- * @req: ptr to link request structure
- */
-static void disc_send_msg(struct tipc_link_req *req)
-{
-       if (!req->bearer->blocked)
-               tipc_bearer_send(req->bearer, req->buf, &req->dest);
-}
-
 /**
  * disc_timeout - send a periodic link setup request
  * @req: ptr to link request structure
@@ -322,7 +312,8 @@ static void disc_timeout(struct tipc_link_req *req)
         * hold at fast polling rate if don't have any associated nodes,
         * otherwise hold at slow polling rate
         */
-       disc_send_msg(req);
+       tipc_bearer_send(req->bearer, req->buf, &req->dest);
+
 
        req->timer_intv *= 2;
        if (req->num_nodes)
@@ -368,7 +359,7 @@ int tipc_disc_create(struct tipc_bearer *b_ptr, struct tipc_media_addr *dest,
        k_init_timer(&req->timer, (Handler)disc_timeout, (unsigned long)req);
        k_start_timer(&req->timer, req->timer_intv);
        b_ptr->link_req = req;
-       disc_send_msg(req);
+       tipc_bearer_send(req->bearer, req->buf, &req->dest);
        return 0;
 }
 
index f80d59f5a161c33199ef4d00494117b8115e2676..67cf3f935dba0a9e4d0141fc0406a93b1aeb60d6 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * net/tipc/eth_media.c: Ethernet bearer support for TIPC
  *
- * Copyright (c) 2001-2007, Ericsson AB
+ * Copyright (c) 2001-2007, 2013, Ericsson AB
  * Copyright (c) 2005-2008, 2011-2013, Wind River Systems
  * All rights reserved.
  *
 #include "core.h"
 #include "bearer.h"
 
-#define MAX_ETH_MEDIA          MAX_BEARERS
-
 #define ETH_ADDR_OFFSET        4       /* message header offset of MAC address */
 
-/**
- * struct eth_media - Ethernet bearer data structure
- * @bearer: ptr to associated "generic" bearer structure
- * @dev: ptr to associated Ethernet network device
- * @tipc_packet_type: used in binding TIPC to Ethernet driver
- * @setup: work item used when enabling bearer
- * @cleanup: work item used when disabling bearer
- */
-struct eth_media {
-       struct tipc_bearer *bearer;
-       struct net_device *dev;
-       struct packet_type tipc_packet_type;
-       struct work_struct setup;
-       struct work_struct cleanup;
-};
-
-static struct tipc_media eth_media_info;
-static struct eth_media eth_media_array[MAX_ETH_MEDIA];
-static int eth_started;
-
-static int recv_notification(struct notifier_block *nb, unsigned long evt,
-                            void *dv);
-/*
- * Network device notifier info
- */
-static struct notifier_block notifier = {
-       .notifier_call  = recv_notification,
-       .priority       = 0
-};
-
-/**
- * eth_media_addr_set - initialize Ethernet media address structure
- *
- * Media-dependent "value" field stores MAC address in first 6 bytes
- * and zeroes out the remaining bytes.
- */
-static void eth_media_addr_set(const struct tipc_bearer *tb_ptr,
-                              struct tipc_media_addr *a, char *mac)
-{
-       memcpy(a->value, mac, ETH_ALEN);
-       memset(a->value + ETH_ALEN, 0, sizeof(a->value) - ETH_ALEN);
-       a->media_id = TIPC_MEDIA_TYPE_ETH;
-       a->broadcast = !memcmp(mac, tb_ptr->bcast_addr.value, ETH_ALEN);
-}
-
-/**
- * send_msg - send a TIPC message out over an Ethernet interface
- */
-static int send_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr,
-                   struct tipc_media_addr *dest)
-{
-       struct sk_buff *clone;
-       struct net_device *dev;
-       int delta;
-
-       clone = skb_clone(buf, GFP_ATOMIC);
-       if (!clone)
-               return 0;
-
-       dev = ((struct eth_media *)(tb_ptr->usr_handle))->dev;
-       delta = dev->hard_header_len - skb_headroom(buf);
-
-       if ((delta > 0) &&
-           pskb_expand_head(clone, SKB_DATA_ALIGN(delta), 0, GFP_ATOMIC)) {
-               kfree_skb(clone);
-               return 0;
-       }
-
-       skb_reset_network_header(clone);
-       clone->dev = dev;
-       clone->protocol = htons(ETH_P_TIPC);
-       dev_hard_header(clone, dev, ETH_P_TIPC, dest->value,
-                       dev->dev_addr, clone->len);
-       dev_queue_xmit(clone);
-       return 0;
-}
-
-/**
- * recv_msg - handle incoming TIPC message from an Ethernet interface
- *
- * Accept only packets explicitly sent to this node, or broadcast packets;
- * ignores packets sent using Ethernet multicast, and traffic sent to other
- * nodes (which can happen if interface is running in promiscuous mode).
- */
-static int recv_msg(struct sk_buff *buf, struct net_device *dev,
-                   struct packet_type *pt, struct net_device *orig_dev)
-{
-       struct eth_media *eb_ptr = (struct eth_media *)pt->af_packet_priv;
-
-       if (!net_eq(dev_net(dev), &init_net)) {
-               kfree_skb(buf);
-               return NET_RX_DROP;
-       }
-
-       if (likely(eb_ptr->bearer)) {
-               if (likely(buf->pkt_type <= PACKET_BROADCAST)) {
-                       buf->next = NULL;
-                       tipc_recv_msg(buf, eb_ptr->bearer);
-                       return NET_RX_SUCCESS;
-               }
-       }
-       kfree_skb(buf);
-       return NET_RX_DROP;
-}
-
-/**
- * setup_media - setup association between Ethernet bearer and interface
- */
-static void setup_media(struct work_struct *work)
-{
-       struct eth_media *eb_ptr =
-               container_of(work, struct eth_media, setup);
-
-       dev_add_pack(&eb_ptr->tipc_packet_type);
-}
-
-/**
- * enable_media - attach TIPC bearer to an Ethernet interface
- */
-static int enable_media(struct tipc_bearer *tb_ptr)
-{
-       struct net_device *dev;
-       struct eth_media *eb_ptr = &eth_media_array[0];
-       struct eth_media *stop = &eth_media_array[MAX_ETH_MEDIA];
-       char *driver_name = strchr((const char *)tb_ptr->name, ':') + 1;
-       int pending_dev = 0;
-
-       /* Find unused Ethernet bearer structure */
-       while (eb_ptr->dev) {
-               if (!eb_ptr->bearer)
-                       pending_dev++;
-               if (++eb_ptr == stop)
-                       return pending_dev ? -EAGAIN : -EDQUOT;
-       }
-
-       /* Find device with specified name */
-       dev = dev_get_by_name(&init_net, driver_name);
-       if (!dev)
-               return -ENODEV;
-
-       /* Create Ethernet bearer for device */
-       eb_ptr->dev = dev;
-       eb_ptr->tipc_packet_type.type = htons(ETH_P_TIPC);
-       eb_ptr->tipc_packet_type.dev = dev;
-       eb_ptr->tipc_packet_type.func = recv_msg;
-       eb_ptr->tipc_packet_type.af_packet_priv = eb_ptr;
-       INIT_LIST_HEAD(&(eb_ptr->tipc_packet_type.list));
-       INIT_WORK(&eb_ptr->setup, setup_media);
-       schedule_work(&eb_ptr->setup);
-
-       /* Associate TIPC bearer with Ethernet bearer */
-       eb_ptr->bearer = tb_ptr;
-       tb_ptr->usr_handle = (void *)eb_ptr;
-       memset(tb_ptr->bcast_addr.value, 0, sizeof(tb_ptr->bcast_addr.value));
-       memcpy(tb_ptr->bcast_addr.value, dev->broadcast, ETH_ALEN);
-       tb_ptr->bcast_addr.media_id = TIPC_MEDIA_TYPE_ETH;
-       tb_ptr->bcast_addr.broadcast = 1;
-       tb_ptr->mtu = dev->mtu;
-       tb_ptr->blocked = 0;
-       eth_media_addr_set(tb_ptr, &tb_ptr->addr, (char *)dev->dev_addr);
-       return 0;
-}
-
-/**
- * cleanup_media - break association between Ethernet bearer and interface
- *
- * This routine must be invoked from a work queue because it can sleep.
- */
-static void cleanup_media(struct work_struct *work)
-{
-       struct eth_media *eb_ptr =
-               container_of(work, struct eth_media, cleanup);
-
-       dev_remove_pack(&eb_ptr->tipc_packet_type);
-       dev_put(eb_ptr->dev);
-       eb_ptr->dev = NULL;
-}
-
-/**
- * disable_media - detach TIPC bearer from an Ethernet interface
- *
- * Mark Ethernet bearer as inactive so that incoming buffers are thrown away,
- * then get worker thread to complete bearer cleanup.  (Can't do cleanup
- * here because cleanup code needs to sleep and caller holds spinlocks.)
- */
-static void disable_media(struct tipc_bearer *tb_ptr)
-{
-       struct eth_media *eb_ptr = (struct eth_media *)tb_ptr->usr_handle;
-
-       eb_ptr->bearer = NULL;
-       INIT_WORK(&eb_ptr->cleanup, cleanup_media);
-       schedule_work(&eb_ptr->cleanup);
-}
-
-/**
- * recv_notification - handle device updates from OS
- *
- * Change the state of the Ethernet bearer (if any) associated with the
- * specified device.
- */
-static int recv_notification(struct notifier_block *nb, unsigned long evt,
-                            void *ptr)
-{
-       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
-       struct eth_media *eb_ptr = &eth_media_array[0];
-       struct eth_media *stop = &eth_media_array[MAX_ETH_MEDIA];
-
-       if (!net_eq(dev_net(dev), &init_net))
-               return NOTIFY_DONE;
-
-       while ((eb_ptr->dev != dev)) {
-               if (++eb_ptr == stop)
-                       return NOTIFY_DONE;     /* couldn't find device */
-       }
-       if (!eb_ptr->bearer)
-               return NOTIFY_DONE;             /* bearer had been disabled */
-
-       eb_ptr->bearer->mtu = dev->mtu;
-
-       switch (evt) {
-       case NETDEV_CHANGE:
-               if (netif_carrier_ok(dev))
-                       tipc_continue(eb_ptr->bearer);
-               else
-                       tipc_block_bearer(eb_ptr->bearer);
-               break;
-       case NETDEV_UP:
-               tipc_continue(eb_ptr->bearer);
-               break;
-       case NETDEV_DOWN:
-               tipc_block_bearer(eb_ptr->bearer);
-               break;
-       case NETDEV_CHANGEMTU:
-       case NETDEV_CHANGEADDR:
-               tipc_block_bearer(eb_ptr->bearer);
-               tipc_continue(eb_ptr->bearer);
-               break;
-       case NETDEV_UNREGISTER:
-       case NETDEV_CHANGENAME:
-               tipc_disable_bearer(eb_ptr->bearer->name);
-               break;
-       }
-       return NOTIFY_OK;
-}
-
-/**
- * eth_addr2str - convert Ethernet address to string
- */
-static int eth_addr2str(struct tipc_media_addr *a, char *str_buf, int str_size)
+/* convert Ethernet address to string */
+static int tipc_eth_addr2str(struct tipc_media_addr *a, char *str_buf,
+                            int str_size)
 {
        if (str_size < 18)      /* 18 = strlen("aa:bb:cc:dd:ee:ff\0") */
                return 1;
@@ -298,10 +50,8 @@ static int eth_addr2str(struct tipc_media_addr *a, char *str_buf, int str_size)
        return 0;
 }
 
-/**
- * eth_str2addr - convert Ethernet address format to message header format
- */
-static int eth_addr2msg(struct tipc_media_addr *a, char *msg_area)
+/* convert Ethernet address format to message header format */
+static int tipc_eth_addr2msg(struct tipc_media_addr *a, char *msg_area)
 {
        memset(msg_area, 0, TIPC_MEDIA_ADDR_SIZE);
        msg_area[TIPC_MEDIA_TYPE_OFFSET] = TIPC_MEDIA_TYPE_ETH;
@@ -309,68 +59,30 @@ static int eth_addr2msg(struct tipc_media_addr *a, char *msg_area)
        return 0;
 }
 
-/**
- * eth_str2addr - convert message header address format to Ethernet format
- */
-static int eth_msg2addr(const struct tipc_bearer *tb_ptr,
-                       struct tipc_media_addr *a, char *msg_area)
+/* convert message header address format to Ethernet format */
+static int tipc_eth_msg2addr(const struct tipc_bearer *tb_ptr,
+                            struct tipc_media_addr *a, char *msg_area)
 {
        if (msg_area[TIPC_MEDIA_TYPE_OFFSET] != TIPC_MEDIA_TYPE_ETH)
                return 1;
 
-       eth_media_addr_set(tb_ptr, a, msg_area + ETH_ADDR_OFFSET);
+       tipc_l2_media_addr_set(tb_ptr, a, msg_area + ETH_ADDR_OFFSET);
        return 0;
 }
 
-/*
- * Ethernet media registration info
- */
-static struct tipc_media eth_media_info = {
-       .send_msg       = send_msg,
-       .enable_media   = enable_media,
-       .disable_media  = disable_media,
-       .addr2str       = eth_addr2str,
-       .addr2msg       = eth_addr2msg,
-       .msg2addr       = eth_msg2addr,
+/* Ethernet media registration info */
+struct tipc_media eth_media_info = {
+       .send_msg       = tipc_l2_send_msg,
+       .enable_media   = tipc_enable_l2_media,
+       .disable_media  = tipc_disable_l2_media,
+       .addr2str       = tipc_eth_addr2str,
+       .addr2msg       = tipc_eth_addr2msg,
+       .msg2addr       = tipc_eth_msg2addr,
        .priority       = TIPC_DEF_LINK_PRI,
        .tolerance      = TIPC_DEF_LINK_TOL,
        .window         = TIPC_DEF_LINK_WIN,
        .type_id        = TIPC_MEDIA_TYPE_ETH,
+       .hwaddr_len     = ETH_ALEN,
        .name           = "eth"
 };
 
-/**
- * tipc_eth_media_start - activate Ethernet bearer support
- *
- * Register Ethernet media type with TIPC bearer code.  Also register
- * with OS for notifications about device state changes.
- */
-int tipc_eth_media_start(void)
-{
-       int res;
-
-       if (eth_started)
-               return -EINVAL;
-
-       res = tipc_register_media(&eth_media_info);
-       if (res)
-               return res;
-
-       res = register_netdevice_notifier(&notifier);
-       if (!res)
-               eth_started = 1;
-       return res;
-}
-
-/**
- * tipc_eth_media_stop - deactivate Ethernet bearer support
- */
-void tipc_eth_media_stop(void)
-{
-       if (!eth_started)
-               return;
-
-       flush_scheduled_work();
-       unregister_netdevice_notifier(&notifier);
-       eth_started = 0;
-}
index b36f0fcd9bdfe76d04adf287687190ada3e9ccca..e4bc8a2967447fbde1f39d0d19146f2c7848ac99 100644 (file)
@@ -56,12 +56,13 @@ unsigned int tipc_k_signal(Handler routine, unsigned long argument)
 {
        struct queue_item *item;
 
+       spin_lock_bh(&qitem_lock);
        if (!handler_enabled) {
                pr_err("Signal request ignored by handler\n");
+               spin_unlock_bh(&qitem_lock);
                return -ENOPROTOOPT;
        }
 
-       spin_lock_bh(&qitem_lock);
        item = kmem_cache_alloc(tipc_queue_item_cache, GFP_ATOMIC);
        if (!item) {
                pr_err("Signal queue out of memory\n");
@@ -112,10 +113,14 @@ void tipc_handler_stop(void)
        struct list_head *l, *n;
        struct queue_item *item;
 
-       if (!handler_enabled)
+       spin_lock_bh(&qitem_lock);
+       if (!handler_enabled) {
+               spin_unlock_bh(&qitem_lock);
                return;
-
+       }
        handler_enabled = 0;
+       spin_unlock_bh(&qitem_lock);
+
        tasklet_kill(&tipc_tasklet);
 
        spin_lock_bh(&qitem_lock);
index c139892974644925c4eca8e225e0c262b99cf4c2..844a77e2582856ae8cff4618c5e1de23f4220e0b 100644 (file)
 #include "core.h"
 #include "bearer.h"
 
-#define MAX_IB_MEDIA           MAX_BEARERS
-
-/**
- * struct ib_media - Infiniband media data structure
- * @bearer: ptr to associated "generic" bearer structure
- * @dev: ptr to associated Infiniband network device
- * @tipc_packet_type: used in binding TIPC to Infiniband driver
- * @cleanup: work item used when disabling bearer
- */
-
-struct ib_media {
-       struct tipc_bearer *bearer;
-       struct net_device *dev;
-       struct packet_type tipc_packet_type;
-       struct work_struct setup;
-       struct work_struct cleanup;
-};
-
-static struct tipc_media ib_media_info;
-static struct ib_media ib_media_array[MAX_IB_MEDIA];
-static int ib_started;
-
-/**
- * ib_media_addr_set - initialize Infiniband media address structure
- *
- * Media-dependent "value" field stores MAC address in first 6 bytes
- * and zeroes out the remaining bytes.
- */
-static void ib_media_addr_set(const struct tipc_bearer *tb_ptr,
-                             struct tipc_media_addr *a, char *mac)
-{
-       BUILD_BUG_ON(sizeof(a->value) < INFINIBAND_ALEN);
-       memcpy(a->value, mac, INFINIBAND_ALEN);
-       a->media_id = TIPC_MEDIA_TYPE_IB;
-       a->broadcast = !memcmp(mac, tb_ptr->bcast_addr.value, INFINIBAND_ALEN);
-}
-
-/**
- * send_msg - send a TIPC message out over an InfiniBand interface
- */
-static int send_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr,
-                   struct tipc_media_addr *dest)
-{
-       struct sk_buff *clone;
-       struct net_device *dev;
-       int delta;
-
-       clone = skb_clone(buf, GFP_ATOMIC);
-       if (!clone)
-               return 0;
-
-       dev = ((struct ib_media *)(tb_ptr->usr_handle))->dev;
-       delta = dev->hard_header_len - skb_headroom(buf);
-
-       if ((delta > 0) &&
-           pskb_expand_head(clone, SKB_DATA_ALIGN(delta), 0, GFP_ATOMIC)) {
-               kfree_skb(clone);
-               return 0;
-       }
-
-       skb_reset_network_header(clone);
-       clone->dev = dev;
-       clone->protocol = htons(ETH_P_TIPC);
-       dev_hard_header(clone, dev, ETH_P_TIPC, dest->value,
-                       dev->dev_addr, clone->len);
-       dev_queue_xmit(clone);
-       return 0;
-}
-
-/**
- * recv_msg - handle incoming TIPC message from an InfiniBand interface
- *
- * Accept only packets explicitly sent to this node, or broadcast packets;
- * ignores packets sent using InfiniBand multicast, and traffic sent to other
- * nodes (which can happen if interface is running in promiscuous mode).
- */
-static int recv_msg(struct sk_buff *buf, struct net_device *dev,
-                   struct packet_type *pt, struct net_device *orig_dev)
-{
-       struct ib_media *ib_ptr = (struct ib_media *)pt->af_packet_priv;
-
-       if (!net_eq(dev_net(dev), &init_net)) {
-               kfree_skb(buf);
-               return NET_RX_DROP;
-       }
-
-       if (likely(ib_ptr->bearer)) {
-               if (likely(buf->pkt_type <= PACKET_BROADCAST)) {
-                       buf->next = NULL;
-                       tipc_recv_msg(buf, ib_ptr->bearer);
-                       return NET_RX_SUCCESS;
-               }
-       }
-       kfree_skb(buf);
-       return NET_RX_DROP;
-}
-
-/**
- * setup_bearer - setup association between InfiniBand bearer and interface
- */
-static void setup_media(struct work_struct *work)
-{
-       struct ib_media *ib_ptr =
-               container_of(work, struct ib_media, setup);
-
-       dev_add_pack(&ib_ptr->tipc_packet_type);
-}
-
-/**
- * enable_media - attach TIPC bearer to an InfiniBand interface
- */
-static int enable_media(struct tipc_bearer *tb_ptr)
-{
-       struct net_device *dev;
-       struct ib_media *ib_ptr = &ib_media_array[0];
-       struct ib_media *stop = &ib_media_array[MAX_IB_MEDIA];
-       char *driver_name = strchr((const char *)tb_ptr->name, ':') + 1;
-       int pending_dev = 0;
-
-       /* Find unused InfiniBand bearer structure */
-       while (ib_ptr->dev) {
-               if (!ib_ptr->bearer)
-                       pending_dev++;
-               if (++ib_ptr == stop)
-                       return pending_dev ? -EAGAIN : -EDQUOT;
-       }
-
-       /* Find device with specified name */
-       dev = dev_get_by_name(&init_net, driver_name);
-       if (!dev)
-               return -ENODEV;
-
-       /* Create InfiniBand bearer for device */
-       ib_ptr->dev = dev;
-       ib_ptr->tipc_packet_type.type = htons(ETH_P_TIPC);
-       ib_ptr->tipc_packet_type.dev = dev;
-       ib_ptr->tipc_packet_type.func = recv_msg;
-       ib_ptr->tipc_packet_type.af_packet_priv = ib_ptr;
-       INIT_LIST_HEAD(&(ib_ptr->tipc_packet_type.list));
-       INIT_WORK(&ib_ptr->setup, setup_media);
-       schedule_work(&ib_ptr->setup);
-
-       /* Associate TIPC bearer with InfiniBand bearer */
-       ib_ptr->bearer = tb_ptr;
-       tb_ptr->usr_handle = (void *)ib_ptr;
-       memset(tb_ptr->bcast_addr.value, 0, sizeof(tb_ptr->bcast_addr.value));
-       memcpy(tb_ptr->bcast_addr.value, dev->broadcast, INFINIBAND_ALEN);
-       tb_ptr->bcast_addr.media_id = TIPC_MEDIA_TYPE_IB;
-       tb_ptr->bcast_addr.broadcast = 1;
-       tb_ptr->mtu = dev->mtu;
-       tb_ptr->blocked = 0;
-       ib_media_addr_set(tb_ptr, &tb_ptr->addr, (char *)dev->dev_addr);
-       return 0;
-}
-
-/**
- * cleanup_bearer - break association between InfiniBand bearer and interface
- *
- * This routine must be invoked from a work queue because it can sleep.
- */
-static void cleanup_bearer(struct work_struct *work)
-{
-       struct ib_media *ib_ptr =
-               container_of(work, struct ib_media, cleanup);
-
-       dev_remove_pack(&ib_ptr->tipc_packet_type);
-       dev_put(ib_ptr->dev);
-       ib_ptr->dev = NULL;
-}
-
-/**
- * disable_media - detach TIPC bearer from an InfiniBand interface
- *
- * Mark InfiniBand bearer as inactive so that incoming buffers are thrown away,
- * then get worker thread to complete bearer cleanup.  (Can't do cleanup
- * here because cleanup code needs to sleep and caller holds spinlocks.)
- */
-static void disable_media(struct tipc_bearer *tb_ptr)
-{
-       struct ib_media *ib_ptr = (struct ib_media *)tb_ptr->usr_handle;
-
-       ib_ptr->bearer = NULL;
-       INIT_WORK(&ib_ptr->cleanup, cleanup_bearer);
-       schedule_work(&ib_ptr->cleanup);
-}
-
-/**
- * recv_notification - handle device updates from OS
- *
- * Change the state of the InfiniBand bearer (if any) associated with the
- * specified device.
- */
-static int recv_notification(struct notifier_block *nb, unsigned long evt,
-                            void *ptr)
-{
-       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
-       struct ib_media *ib_ptr = &ib_media_array[0];
-       struct ib_media *stop = &ib_media_array[MAX_IB_MEDIA];
-
-       if (!net_eq(dev_net(dev), &init_net))
-               return NOTIFY_DONE;
-
-       while ((ib_ptr->dev != dev)) {
-               if (++ib_ptr == stop)
-                       return NOTIFY_DONE;     /* couldn't find device */
-       }
-       if (!ib_ptr->bearer)
-               return NOTIFY_DONE;             /* bearer had been disabled */
-
-       ib_ptr->bearer->mtu = dev->mtu;
-
-       switch (evt) {
-       case NETDEV_CHANGE:
-               if (netif_carrier_ok(dev))
-                       tipc_continue(ib_ptr->bearer);
-               else
-                       tipc_block_bearer(ib_ptr->bearer);
-               break;
-       case NETDEV_UP:
-               tipc_continue(ib_ptr->bearer);
-               break;
-       case NETDEV_DOWN:
-               tipc_block_bearer(ib_ptr->bearer);
-               break;
-       case NETDEV_CHANGEMTU:
-       case NETDEV_CHANGEADDR:
-               tipc_block_bearer(ib_ptr->bearer);
-               tipc_continue(ib_ptr->bearer);
-               break;
-       case NETDEV_UNREGISTER:
-       case NETDEV_CHANGENAME:
-               tipc_disable_bearer(ib_ptr->bearer->name);
-               break;
-       }
-       return NOTIFY_OK;
-}
-
-static struct notifier_block notifier = {
-       .notifier_call  = recv_notification,
-       .priority       = 0,
-};
-
-/**
- * ib_addr2str - convert InfiniBand address to string
- */
-static int ib_addr2str(struct tipc_media_addr *a, char *str_buf, int str_size)
+/* convert InfiniBand address to string */
+static int tipc_ib_addr2str(struct tipc_media_addr *a, char *str_buf,
+                           int str_size)
 {
        if (str_size < 60)      /* 60 = 19 * strlen("xx:") + strlen("xx\0") */
                return 1;
@@ -297,10 +54,8 @@ static int ib_addr2str(struct tipc_media_addr *a, char *str_buf, int str_size)
        return 0;
 }
 
-/**
- * ib_addr2msg - convert InfiniBand address format to message header format
- */
-static int ib_addr2msg(struct tipc_media_addr *a, char *msg_area)
+/* convert InfiniBand address format to message header format */
+static int tipc_ib_addr2msg(struct tipc_media_addr *a, char *msg_area)
 {
        memset(msg_area, 0, TIPC_MEDIA_ADDR_SIZE);
        msg_area[TIPC_MEDIA_TYPE_OFFSET] = TIPC_MEDIA_TYPE_IB;
@@ -308,65 +63,27 @@ static int ib_addr2msg(struct tipc_media_addr *a, char *msg_area)
        return 0;
 }
 
-/**
- * ib_msg2addr - convert message header address format to InfiniBand format
- */
-static int ib_msg2addr(const struct tipc_bearer *tb_ptr,
-                      struct tipc_media_addr *a, char *msg_area)
+/* convert message header address format to InfiniBand format */
+static int tipc_ib_msg2addr(const struct tipc_bearer *tb_ptr,
+                           struct tipc_media_addr *a, char *msg_area)
 {
-       ib_media_addr_set(tb_ptr, a, msg_area);
+       tipc_l2_media_addr_set(tb_ptr, a, msg_area);
        return 0;
 }
 
-/*
- * InfiniBand media registration info
- */
-static struct tipc_media ib_media_info = {
-       .send_msg       = send_msg,
-       .enable_media   = enable_media,
-       .disable_media  = disable_media,
-       .addr2str       = ib_addr2str,
-       .addr2msg       = ib_addr2msg,
-       .msg2addr       = ib_msg2addr,
+/* InfiniBand media registration info */
+struct tipc_media ib_media_info = {
+       .send_msg       = tipc_l2_send_msg,
+       .enable_media   = tipc_enable_l2_media,
+       .disable_media  = tipc_disable_l2_media,
+       .addr2str       = tipc_ib_addr2str,
+       .addr2msg       = tipc_ib_addr2msg,
+       .msg2addr       = tipc_ib_msg2addr,
        .priority       = TIPC_DEF_LINK_PRI,
        .tolerance      = TIPC_DEF_LINK_TOL,
        .window         = TIPC_DEF_LINK_WIN,
        .type_id        = TIPC_MEDIA_TYPE_IB,
+       .hwaddr_len     = INFINIBAND_ALEN,
        .name           = "ib"
 };
 
-/**
- * tipc_ib_media_start - activate InfiniBand bearer support
- *
- * Register InfiniBand media type with TIPC bearer code.  Also register
- * with OS for notifications about device state changes.
- */
-int tipc_ib_media_start(void)
-{
-       int res;
-
-       if (ib_started)
-               return -EINVAL;
-
-       res = tipc_register_media(&ib_media_info);
-       if (res)
-               return res;
-
-       res = register_netdevice_notifier(&notifier);
-       if (!res)
-               ib_started = 1;
-       return res;
-}
-
-/**
- * tipc_ib_media_stop - deactivate InfiniBand bearer support
- */
-void tipc_ib_media_stop(void)
-{
-       if (!ib_started)
-               return;
-
-       flush_scheduled_work();
-       unregister_netdevice_notifier(&notifier);
-       ib_started = 0;
-}
index 69cd9bf3f561d64d377ddb65091b98e1017e15cf..3d73144a1ccc4dd59449b3252fb154fe4b339da6 100644 (file)
@@ -386,14 +386,7 @@ exit:
  */
 static void link_release_outqueue(struct tipc_link *l_ptr)
 {
-       struct sk_buff *buf = l_ptr->first_out;
-       struct sk_buff *next;
-
-       while (buf) {
-               next = buf->next;
-               kfree_skb(buf);
-               buf = next;
-       }
+       kfree_skb_list(l_ptr->first_out);
        l_ptr->first_out = NULL;
        l_ptr->out_queue_size = 0;
 }
@@ -415,32 +408,15 @@ void tipc_link_reset_fragments(struct tipc_link *l_ptr)
  */
 void tipc_link_stop(struct tipc_link *l_ptr)
 {
-       struct sk_buff *buf;
-       struct sk_buff *next;
-
-       buf = l_ptr->oldest_deferred_in;
-       while (buf) {
-               next = buf->next;
-               kfree_skb(buf);
-               buf = next;
-       }
-
-       buf = l_ptr->first_out;
-       while (buf) {
-               next = buf->next;
-               kfree_skb(buf);
-               buf = next;
-       }
-
+       kfree_skb_list(l_ptr->oldest_deferred_in);
+       kfree_skb_list(l_ptr->first_out);
        tipc_link_reset_fragments(l_ptr);
-
        kfree_skb(l_ptr->proto_msg_queue);
        l_ptr->proto_msg_queue = NULL;
 }
 
 void tipc_link_reset(struct tipc_link *l_ptr)
 {
-       struct sk_buff *buf;
        u32 prev_state = l_ptr->state;
        u32 checkpoint = l_ptr->next_in_no;
        int was_active_link = tipc_link_is_active(l_ptr);
@@ -471,12 +447,7 @@ void tipc_link_reset(struct tipc_link *l_ptr)
        link_release_outqueue(l_ptr);
        kfree_skb(l_ptr->proto_msg_queue);
        l_ptr->proto_msg_queue = NULL;
-       buf = l_ptr->oldest_deferred_in;
-       while (buf) {
-               struct sk_buff *next = buf->next;
-               kfree_skb(buf);
-               buf = next;
-       }
+       kfree_skb_list(l_ptr->oldest_deferred_in);
        if (!list_empty(&l_ptr->waiting_ports))
                tipc_link_wakeup_ports(l_ptr, 1);
 
@@ -517,10 +488,11 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event)
        if (!l_ptr->started && (event != STARTING_EVT))
                return;         /* Not yet. */
 
-       if (link_blocked(l_ptr)) {
+       /* Check whether changeover is going on */
+       if (l_ptr->exp_msg_count) {
                if (event == TIMEOUT_EVT)
                        link_set_timer(l_ptr, cont_intv);
-               return;   /* Changeover going on */
+               return;
        }
 
        switch (l_ptr->state) {
@@ -790,8 +762,7 @@ int tipc_link_send_buf(struct tipc_link *l_ptr, struct sk_buff *buf)
                return link_send_long_buf(l_ptr, buf);
 
        /* Packet can be queued or sent. */
-       if (likely(!tipc_bearer_blocked(l_ptr->b_ptr) &&
-                  !link_congested(l_ptr))) {
+       if (likely(!link_congested(l_ptr))) {
                link_add_to_outqueue(l_ptr, buf, msg);
 
                tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr);
@@ -957,14 +928,13 @@ static int link_send_buf_fast(struct tipc_link *l_ptr, struct sk_buff *buf,
 
        if (likely(!link_congested(l_ptr))) {
                if (likely(msg_size(msg) <= l_ptr->max_pkt)) {
-                       if (likely(!tipc_bearer_blocked(l_ptr->b_ptr))) {
-                               link_add_to_outqueue(l_ptr, buf, msg);
-                               tipc_bearer_send(l_ptr->b_ptr, buf,
-                                                &l_ptr->media_addr);
-                               l_ptr->unacked_window = 0;
-                               return res;
-                       }
-               } else
+                       link_add_to_outqueue(l_ptr, buf, msg);
+                       tipc_bearer_send(l_ptr->b_ptr, buf,
+                                        &l_ptr->media_addr);
+                       l_ptr->unacked_window = 0;
+                       return res;
+               }
+               else
                        *used_max_pkt = l_ptr->max_pkt;
        }
        return tipc_link_send_buf(l_ptr, buf);  /* All other cases */
@@ -1013,8 +983,7 @@ exit:
                        }
 
                        /* Exit if link (or bearer) is congested */
-                       if (link_congested(l_ptr) ||
-                           tipc_bearer_blocked(l_ptr->b_ptr)) {
+                       if (link_congested(l_ptr)) {
                                res = link_schedule_port(l_ptr,
                                                         sender->ref, res);
                                goto exit;
@@ -1127,10 +1096,7 @@ again:
                if (copy_from_user(buf->data + fragm_crs, sect_crs, sz)) {
                        res = -EFAULT;
 error:
-                       for (; buf_chain; buf_chain = buf) {
-                               buf = buf_chain->next;
-                               kfree_skb(buf_chain);
-                       }
+                       kfree_skb_list(buf_chain);
                        return res;
                }
                sect_crs += sz;
@@ -1180,18 +1146,12 @@ error:
                if (l_ptr->max_pkt < max_pkt) {
                        sender->max_pkt = l_ptr->max_pkt;
                        tipc_node_unlock(node);
-                       for (; buf_chain; buf_chain = buf) {
-                               buf = buf_chain->next;
-                               kfree_skb(buf_chain);
-                       }
+                       kfree_skb_list(buf_chain);
                        goto again;
                }
        } else {
 reject:
-               for (; buf_chain; buf_chain = buf) {
-                       buf = buf_chain->next;
-                       kfree_skb(buf_chain);
-               }
+               kfree_skb_list(buf_chain);
                return tipc_port_reject_sections(sender, hdr, msg_sect,
                                                 len, TIPC_ERR_NO_NODE);
        }
@@ -1281,9 +1241,6 @@ void tipc_link_push_queue(struct tipc_link *l_ptr)
 {
        u32 res;
 
-       if (tipc_bearer_blocked(l_ptr->b_ptr))
-               return;
-
        do {
                res = tipc_link_push_packet(l_ptr);
        } while (!res);
@@ -1370,26 +1327,15 @@ void tipc_link_retransmit(struct tipc_link *l_ptr, struct sk_buff *buf,
 
        msg = buf_msg(buf);
 
-       if (tipc_bearer_blocked(l_ptr->b_ptr)) {
-               if (l_ptr->retransm_queue_size == 0) {
-                       l_ptr->retransm_queue_head = msg_seqno(msg);
-                       l_ptr->retransm_queue_size = retransmits;
-               } else {
-                       pr_err("Unexpected retransmit on link %s (qsize=%d)\n",
-                              l_ptr->name, l_ptr->retransm_queue_size);
+       /* Detect repeated retransmit failures */
+       if (l_ptr->last_retransmitted == msg_seqno(msg)) {
+               if (++l_ptr->stale_count > 100) {
+                       link_retransmit_failure(l_ptr, buf);
+                       return;
                }
-               return;
        } else {
-               /* Detect repeated retransmit failures on unblocked bearer */
-               if (l_ptr->last_retransmitted == msg_seqno(msg)) {
-                       if (++l_ptr->stale_count > 100) {
-                               link_retransmit_failure(l_ptr, buf);
-                               return;
-                       }
-               } else {
-                       l_ptr->last_retransmitted = msg_seqno(msg);
-                       l_ptr->stale_count = 1;
-               }
+               l_ptr->last_retransmitted = msg_seqno(msg);
+               l_ptr->stale_count = 1;
        }
 
        while (retransmits && (buf != l_ptr->next_out) && buf) {
@@ -1786,7 +1732,8 @@ void tipc_link_send_proto_msg(struct tipc_link *l_ptr, u32 msg_typ,
                l_ptr->proto_msg_queue = NULL;
        }
 
-       if (link_blocked(l_ptr))
+       /* Don't send protocol message during link changeover */
+       if (l_ptr->exp_msg_count)
                return;
 
        /* Abort non-RESET send if communication with node is prohibited */
@@ -1861,12 +1808,6 @@ void tipc_link_send_proto_msg(struct tipc_link *l_ptr, u32 msg_typ,
        skb_copy_to_linear_data(buf, msg, sizeof(l_ptr->proto_msg));
        buf->priority = TC_PRIO_CONTROL;
 
-       /* Defer message if bearer is already blocked */
-       if (tipc_bearer_blocked(l_ptr->b_ptr)) {
-               l_ptr->proto_msg_queue = buf;
-               return;
-       }
-
        tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr);
        l_ptr->unacked_window = 0;
        kfree_skb(buf);
@@ -1885,7 +1826,8 @@ static void link_recv_proto_msg(struct tipc_link *l_ptr, struct sk_buff *buf)
        u32 msg_tol;
        struct tipc_msg *msg = buf_msg(buf);
 
-       if (link_blocked(l_ptr))
+       /* Discard protocol message during link changeover */
+       if (l_ptr->exp_msg_count)
                goto exit;
 
        /* record unnumbered packet arrival (force mismatch on next timeout) */
@@ -2306,11 +2248,7 @@ static int link_send_long_buf(struct tipc_link *l_ptr, struct sk_buff *buf)
                fragm = tipc_buf_acquire(fragm_sz + INT_H_SIZE);
                if (fragm == NULL) {
                        kfree_skb(buf);
-                       while (buf_chain) {
-                               buf = buf_chain;
-                               buf_chain = buf_chain->next;
-                               kfree_skb(buf);
-                       }
+                       kfree_skb_list(buf_chain);
                        return -ENOMEM;
                }
                msg_set_size(&fragm_hdr, fragm_sz + INT_H_SIZE);
index 8a6c1026644db438a1a83b7c2ce5679ac9e5a888..424b1dfe436b44ee5e1fddc86ae0ba431a86833b 100644 (file)
@@ -112,7 +112,6 @@ struct tipc_stats {
  * @continuity_interval: link continuity testing interval [in ms]
  * @abort_limit: # of unacknowledged continuity probes needed to reset link
  * @state: current state of link FSM
- * @blocked: indicates if link has been administratively blocked
  * @fsm_msg_cnt: # of protocol messages link FSM has sent in current state
  * @proto_msg: template for control messages generated by link
  * @pmsg: convenience pointer to "proto_msg" field
@@ -162,7 +161,6 @@ struct tipc_link {
        u32 continuity_interval;
        u32 abort_limit;
        int state;
-       int blocked;
        u32 fsm_msg_cnt;
        struct {
                unchar hdr[INT_H_SIZE];
@@ -312,11 +310,6 @@ static inline int link_reset_reset(struct tipc_link *l_ptr)
        return l_ptr->state == RESET_RESET;
 }
 
-static inline int link_blocked(struct tipc_link *l_ptr)
-{
-       return l_ptr->exp_msg_count || l_ptr->blocked;
-}
-
 static inline int link_congested(struct tipc_link *l_ptr)
 {
        return l_ptr->out_queue_size >= l_ptr->queue_limit[0];
index 25100c0a6fe84757ee8c0312a86e643d05d6276d..bf1ac89b4806a71cfe8179f2e743e22cb9dbea97 100644 (file)
@@ -291,11 +291,7 @@ static void node_lost_contact(struct tipc_node *n_ptr)
 
        /* Flush broadcast link info associated with lost node */
        if (n_ptr->bclink.recv_permitted) {
-               while (n_ptr->bclink.deferred_head) {
-                       struct sk_buff *buf = n_ptr->bclink.deferred_head;
-                       n_ptr->bclink.deferred_head = buf->next;
-                       kfree_skb(buf);
-               }
+               kfree_skb_list(n_ptr->bclink.deferred_head);
                n_ptr->bclink.deferred_size = 0;
 
                if (n_ptr->bclink.reasm_head) {
index 01625ccc3ae64ac3b5b1c664feec7f0136973e04..7edbcd9bc26069334592631cabdc11d5a5577ac6 100644 (file)
@@ -80,6 +80,8 @@
  *               with BSD names.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
@@ -366,7 +368,7 @@ static void unix_sock_destructor(struct sock *sk)
        WARN_ON(!sk_unhashed(sk));
        WARN_ON(sk->sk_socket);
        if (!sock_flag(sk, SOCK_DEAD)) {
-               printk(KERN_INFO "Attempt to release alive unix socket: %p\n", sk);
+               pr_info("Attempt to release alive unix socket: %p\n", sk);
                return;
        }
 
@@ -378,7 +380,7 @@ static void unix_sock_destructor(struct sock *sk)
        sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
        local_bh_enable();
 #ifdef UNIX_REFCNT_DEBUG
-       printk(KERN_DEBUG "UNIX %p is destroyed, %ld are still alive.\n", sk,
+       pr_debug("UNIX %p is destroyed, %ld are still alive.\n", sk,
                atomic_long_read(&unix_nr_socks));
 #endif
 }
@@ -530,13 +532,17 @@ static int unix_seqpacket_sendmsg(struct kiocb *, struct socket *,
 static int unix_seqpacket_recvmsg(struct kiocb *, struct socket *,
                                  struct msghdr *, size_t, int);
 
-static void unix_set_peek_off(struct sock *sk, int val)
+static int unix_set_peek_off(struct sock *sk, int val)
 {
        struct unix_sock *u = unix_sk(sk);
 
-       mutex_lock(&u->readlock);
+       if (mutex_lock_interruptible(&u->readlock))
+               return -EINTR;
+
        sk->sk_peek_off = val;
        mutex_unlock(&u->readlock);
+
+       return 0;
 }
 
 
@@ -2433,8 +2439,7 @@ static int __init af_unix_init(void)
 
        rc = proto_register(&unix_proto, 1);
        if (rc != 0) {
-               printk(KERN_CRIT "%s: Cannot create unix_sock SLAB cache!\n",
-                      __func__);
+               pr_crit("%s: Cannot create unix_sock SLAB cache!\n", __func__);
                goto out;
        }
 
index 9b8cc877eb191a2a62370c9f2617bed513200d24..78559b5bbd1fe1d98c533f18dd1cc4fce4087baa 100644 (file)
@@ -277,6 +277,32 @@ void cfg80211_set_dfs_state(struct wiphy *wiphy,
                                     width, dfs_state);
 }
 
+static u32 cfg80211_get_start_freq(u32 center_freq,
+                                  u32 bandwidth)
+{
+       u32 start_freq;
+
+       if (bandwidth <= 20)
+               start_freq = center_freq;
+       else
+               start_freq = center_freq - bandwidth/2 + 10;
+
+       return start_freq;
+}
+
+static u32 cfg80211_get_end_freq(u32 center_freq,
+                                u32 bandwidth)
+{
+       u32 end_freq;
+
+       if (bandwidth <= 20)
+               end_freq = center_freq;
+       else
+               end_freq = center_freq + bandwidth/2 - 10;
+
+       return end_freq;
+}
+
 static int cfg80211_get_chans_dfs_required(struct wiphy *wiphy,
                                            u32 center_freq,
                                            u32 bandwidth)
@@ -284,13 +310,8 @@ static int cfg80211_get_chans_dfs_required(struct wiphy *wiphy,
        struct ieee80211_channel *c;
        u32 freq, start_freq, end_freq;
 
-       if (bandwidth <= 20) {
-               start_freq = center_freq;
-               end_freq = center_freq;
-       } else {
-               start_freq = center_freq - bandwidth/2 + 10;
-               end_freq = center_freq + bandwidth/2 - 10;
-       }
+       start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
+       end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
 
        for (freq = start_freq; freq <= end_freq; freq += 20) {
                c = ieee80211_get_channel(wiphy, freq);
@@ -330,33 +351,159 @@ int cfg80211_chandef_dfs_required(struct wiphy *wiphy,
 }
 EXPORT_SYMBOL(cfg80211_chandef_dfs_required);
 
-static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
-                                       u32 center_freq, u32 bandwidth,
-                                       u32 prohibited_flags)
+static int cfg80211_get_chans_dfs_usable(struct wiphy *wiphy,
+                                        u32 center_freq,
+                                        u32 bandwidth)
 {
        struct ieee80211_channel *c;
        u32 freq, start_freq, end_freq;
+       int count = 0;
 
-       if (bandwidth <= 20) {
-               start_freq = center_freq;
-               end_freq = center_freq;
-       } else {
-               start_freq = center_freq - bandwidth/2 + 10;
-               end_freq = center_freq + bandwidth/2 - 10;
+       start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
+       end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
+
+       /*
+        * Check entire range of channels for the bandwidth.
+        * Check all channels are DFS channels (DFS_USABLE or
+        * DFS_AVAILABLE). Return number of usable channels
+        * (require CAC). Allow DFS and non-DFS channel mix.
+        */
+       for (freq = start_freq; freq <= end_freq; freq += 20) {
+               c = ieee80211_get_channel(wiphy, freq);
+               if (!c)
+                       return -EINVAL;
+
+               if (c->flags & IEEE80211_CHAN_DISABLED)
+                       return -EINVAL;
+
+               if (c->flags & IEEE80211_CHAN_RADAR) {
+                       if (c->dfs_state == NL80211_DFS_UNAVAILABLE)
+                               return -EINVAL;
+
+                       if (c->dfs_state == NL80211_DFS_USABLE)
+                               count++;
+               }
        }
 
+       return count;
+}
+
+bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy,
+                                const struct cfg80211_chan_def *chandef)
+{
+       int width;
+       int r1, r2 = 0;
+
+       if (WARN_ON(!cfg80211_chandef_valid(chandef)))
+               return false;
+
+       width = cfg80211_chandef_get_width(chandef);
+       if (width < 0)
+               return false;
+
+       r1 = cfg80211_get_chans_dfs_usable(wiphy, chandef->center_freq1,
+                                         width);
+
+       if (r1 < 0)
+               return false;
+
+       switch (chandef->width) {
+       case NL80211_CHAN_WIDTH_80P80:
+               WARN_ON(!chandef->center_freq2);
+               r2 = cfg80211_get_chans_dfs_usable(wiphy,
+                                                  chandef->center_freq2,
+                                                  width);
+               if (r2 < 0)
+                       return false;
+               break;
+       default:
+               WARN_ON(chandef->center_freq2);
+               break;
+       }
+
+       return (r1 + r2 > 0);
+}
+
+
+static bool cfg80211_get_chans_dfs_available(struct wiphy *wiphy,
+                                            u32 center_freq,
+                                            u32 bandwidth)
+{
+       struct ieee80211_channel *c;
+       u32 freq, start_freq, end_freq;
+
+       start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
+       end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
+
+       /*
+        * Check entire range of channels for the bandwidth.
+        * If any channel in between is disabled or has not
+        * had gone through CAC return false
+        */
        for (freq = start_freq; freq <= end_freq; freq += 20) {
                c = ieee80211_get_channel(wiphy, freq);
                if (!c)
                        return false;
 
-               /* check for radar flags */
-               if ((prohibited_flags & c->flags & IEEE80211_CHAN_RADAR) &&
+               if (c->flags & IEEE80211_CHAN_DISABLED)
+                       return false;
+
+               if ((c->flags & IEEE80211_CHAN_RADAR)  &&
                    (c->dfs_state != NL80211_DFS_AVAILABLE))
                        return false;
+       }
+
+       return true;
+}
+
+static bool cfg80211_chandef_dfs_available(struct wiphy *wiphy,
+                               const struct cfg80211_chan_def *chandef)
+{
+       int width;
+       int r;
+
+       if (WARN_ON(!cfg80211_chandef_valid(chandef)))
+               return false;
+
+       width = cfg80211_chandef_get_width(chandef);
+       if (width < 0)
+               return false;
+
+       r = cfg80211_get_chans_dfs_available(wiphy, chandef->center_freq1,
+                                            width);
+
+       /* If any of channels unavailable for cf1 just return */
+       if (!r)
+               return r;
+
+       switch (chandef->width) {
+       case NL80211_CHAN_WIDTH_80P80:
+               WARN_ON(!chandef->center_freq2);
+               r = cfg80211_get_chans_dfs_available(wiphy,
+                                                    chandef->center_freq2,
+                                                    width);
+       default:
+               WARN_ON(chandef->center_freq2);
+               break;
+       }
+
+       return r;
+}
 
-               /* check for the other flags */
-               if (c->flags & prohibited_flags & ~IEEE80211_CHAN_RADAR)
+
+static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
+                                       u32 center_freq, u32 bandwidth,
+                                       u32 prohibited_flags)
+{
+       struct ieee80211_channel *c;
+       u32 freq, start_freq, end_freq;
+
+       start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
+       end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
+
+       for (freq = start_freq; freq <= end_freq; freq += 20) {
+               c = ieee80211_get_channel(wiphy, freq);
+               if (!c || c->flags & prohibited_flags)
                        return false;
        }
 
@@ -462,14 +609,19 @@ bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
                             struct cfg80211_chan_def *chandef)
 {
        bool res;
+       u32 prohibited_flags = IEEE80211_CHAN_DISABLED |
+                              IEEE80211_CHAN_NO_IR |
+                              IEEE80211_CHAN_RADAR;
 
        trace_cfg80211_reg_can_beacon(wiphy, chandef);
 
-       res = cfg80211_chandef_usable(wiphy, chandef,
-                                     IEEE80211_CHAN_DISABLED |
-                                     IEEE80211_CHAN_PASSIVE_SCAN |
-                                     IEEE80211_CHAN_NO_IBSS |
-                                     IEEE80211_CHAN_RADAR);
+       if (cfg80211_chandef_dfs_required(wiphy, chandef) > 0 &&
+           cfg80211_chandef_dfs_available(wiphy, chandef)) {
+               /* We can skip IEEE80211_CHAN_NO_IR if chandef dfs available */
+               prohibited_flags = IEEE80211_CHAN_DISABLED;
+       }
+
+       res = cfg80211_chandef_usable(wiphy, chandef, prohibited_flags);
 
        trace_cfg80211_return_bool(res);
        return res;
@@ -510,6 +662,7 @@ cfg80211_get_chan_state(struct wireless_dev *wdev,
                                  : CHAN_MODE_EXCLUSIVE;
                        return;
                }
+               break;
        case NL80211_IFTYPE_STATION:
        case NL80211_IFTYPE_P2P_CLIENT:
                if (wdev->current_bss) {
index aff959e5a1b360e7cb467cade7f7d617544b3909..06db6eb5258aefc332fb4fb09ed165562ea8cd7d 100644 (file)
@@ -357,8 +357,6 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
        rdev->wiphy.rts_threshold = (u32) -1;
        rdev->wiphy.coverage_class = 0;
 
-       rdev->wiphy.features = NL80211_FEATURE_SCAN_FLUSH;
-
        return &rdev->wiphy;
 }
 EXPORT_SYMBOL(wiphy_new);
@@ -451,6 +449,15 @@ int wiphy_register(struct wiphy *wiphy)
        int i;
        u16 ifmodes = wiphy->interface_modes;
 
+       /* support for 5/10 MHz is broken due to nl80211 API mess - disable */
+       wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_5_10_MHZ;
+
+       /*
+        * There are major locking problems in nl80211/mac80211 for CSA,
+        * disable for all drivers until this has been reworked.
+        */
+       wiphy->flags &= ~WIPHY_FLAG_HAS_CHANNEL_SWITCH;
+
 #ifdef CONFIG_PM
        if (WARN_ON(wiphy->wowlan &&
                    (wiphy->wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) &&
@@ -566,6 +573,8 @@ int wiphy_register(struct wiphy *wiphy)
        /* check and set up bitrates */
        ieee80211_set_bitrate_flags(wiphy);
 
+       rdev->wiphy.features |= NL80211_FEATURE_SCAN_FLUSH;
+
        rtnl_lock();
        res = device_add(&rdev->wiphy.dev);
        if (res) {
@@ -586,7 +595,7 @@ int wiphy_register(struct wiphy *wiphy)
        if (IS_ERR(rdev->wiphy.debugfsdir))
                rdev->wiphy.debugfsdir = NULL;
 
-       if (wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY) {
+       if (wiphy->regulatory_flags & REGULATORY_CUSTOM_REG) {
                struct regulatory_request request;
 
                request.wiphy_idx = get_wiphy_idx(wiphy);
index af10e59af2d86f418bd7cc4e69914c9bb31831c7..0a277c33bb027a879d854492ddde295be2c663a0 100644 (file)
@@ -317,9 +317,8 @@ void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid);
 void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev);
 int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
                          struct wireless_dev *wdev,
-                         struct ieee80211_channel *chan, bool offchan,
-                         unsigned int wait, const u8 *buf, size_t len,
-                         bool no_cck, bool dont_wait_for_ack, u64 *cookie);
+                         struct cfg80211_mgmt_tx_params *params,
+                         u64 *cookie);
 void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa,
                               const struct ieee80211_ht_cap *ht_capa_mask);
 void cfg80211_oper_and_vht_capa(struct ieee80211_vht_cap *vht_capa,
@@ -382,6 +381,19 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
                                 enum cfg80211_chan_mode chanmode,
                                 u8 radar_detect);
 
+/**
+ * cfg80211_chandef_dfs_usable - checks if chandef is DFS usable
+ * @wiphy: the wiphy to validate against
+ * @chandef: the channel definition to check
+ *
+ * Checks if chandef is usable and we can/need start CAC on such channel.
+ *
+ * Return: Return true if all channels available and at least
+ *        one channel require CAC (NL80211_DFS_USABLE)
+ */
+bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy,
+                                const struct cfg80211_chan_def *chandef);
+
 void cfg80211_set_dfs_state(struct wiphy *wiphy,
                            const struct cfg80211_chan_def *chandef,
                            enum nl80211_dfs_state dfs_state);
index 42ed274e81f4ca7debc59c4ae17137c35a0993d8..9a8217d2a90882f872451833cabe30159a64953f 100644 (file)
@@ -33,15 +33,7 @@ BEGIN {
        regdb = "const struct ieee80211_regdomain *reg_regdb[] = {\n"
 }
 
-/^[ \t]*#/ {
-       # Ignore
-}
-
-!active && /^[ \t]*$/ {
-       # Ignore
-}
-
-!active && /country/ {
+function parse_country_head() {
        country=$2
        sub(/:/, "", country)
        printf "static const struct ieee80211_regdomain regdom_%s = {\n", country
@@ -57,7 +49,8 @@ BEGIN {
        regdb = regdb "\t&regdom_" country ",\n"
 }
 
-active && /^[ \t]*\(/ {
+function parse_reg_rule()
+{
        start = $1
        sub(/\(/, "", start)
        end = $3
@@ -107,17 +100,21 @@ active && /^[ \t]*\(/ {
                } else if (flagarray[arg] == "PTMP-ONLY") {
                        flags = flags "\n\t\t\tNL80211_RRF_PTMP_ONLY | "
                } else if (flagarray[arg] == "PASSIVE-SCAN") {
-                       flags = flags "\n\t\t\tNL80211_RRF_PASSIVE_SCAN | "
+                       flags = flags "\n\t\t\tNL80211_RRF_NO_IR | "
                } else if (flagarray[arg] == "NO-IBSS") {
-                       flags = flags "\n\t\t\tNL80211_RRF_NO_IBSS | "
+                       flags = flags "\n\t\t\tNL80211_RRF_NO_IR | "
+               } else if (flagarray[arg] == "NO-IR") {
+                       flags = flags "\n\t\t\tNL80211_RRF_NO_IR | "
                }
+
        }
        flags = flags "0"
        printf "\t\tREG_RULE(%d, %d, %d, %d, %d, %s),\n", start, end, bw, gain, power, flags
        rules++
 }
 
-active && /^[ \t]*$/ {
+function print_tail_country()
+{
        active = 0
        printf "\t},\n"
        printf "\t.n_reg_rules = %d\n", rules
@@ -125,7 +122,29 @@ active && /^[ \t]*$/ {
        rules = 0;
 }
 
+/^[ \t]*#/ {
+       # Ignore
+}
+
+!active && /^[ \t]*$/ {
+       # Ignore
+}
+
+!active && /country/ {
+       parse_country_head()
+}
+
+active && /^[ \t]*\(/ {
+       parse_reg_rule()
+}
+
+active && /^[ \t]*$/ {
+       print_tail_country()
+}
+
 END {
+       if (active)
+               print_tail_country()
        print regdb "};"
        print ""
        print "int reg_regdb_size = ARRAY_SIZE(reg_regdb);"
index 9d797df56649c5a47fdf1f61e665ee31e4b77e7c..730147ed8e652c625cb035309df687ca08fd5b49 100644 (file)
@@ -262,7 +262,7 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
 
        /* try to find an IBSS channel if none requested ... */
        if (!wdev->wext.ibss.chandef.chan) {
-               wdev->wext.ibss.chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
+               struct ieee80211_channel *new_chan = NULL;
 
                for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
                        struct ieee80211_supported_band *sband;
@@ -274,22 +274,23 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
 
                        for (i = 0; i < sband->n_channels; i++) {
                                chan = &sband->channels[i];
-                               if (chan->flags & IEEE80211_CHAN_NO_IBSS)
+                               if (chan->flags & IEEE80211_CHAN_NO_IR)
                                        continue;
                                if (chan->flags & IEEE80211_CHAN_DISABLED)
                                        continue;
-                               wdev->wext.ibss.chandef.chan = chan;
-                               wdev->wext.ibss.chandef.center_freq1 =
-                                       chan->center_freq;
+                               new_chan = chan;
                                break;
                        }
 
-                       if (wdev->wext.ibss.chandef.chan)
+                       if (new_chan)
                                break;
                }
 
-               if (!wdev->wext.ibss.chandef.chan)
+               if (!new_chan)
                        return -EINVAL;
+
+               cfg80211_chandef_create(&wdev->wext.ibss.chandef, new_chan,
+                                       NL80211_CHAN_NO_HT);
        }
 
        /* don't join -- SSID is not there */
@@ -345,7 +346,7 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
                chan = ieee80211_get_channel(wdev->wiphy, freq);
                if (!chan)
                        return -EINVAL;
-               if (chan->flags & IEEE80211_CHAN_NO_IBSS ||
+               if (chan->flags & IEEE80211_CHAN_NO_IR ||
                    chan->flags & IEEE80211_CHAN_DISABLED)
                        return -EINVAL;
        }
@@ -363,9 +364,8 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
                return err;
 
        if (chan) {
-               wdev->wext.ibss.chandef.chan = chan;
-               wdev->wext.ibss.chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
-               wdev->wext.ibss.chandef.center_freq1 = freq;
+               cfg80211_chandef_create(&wdev->wext.ibss.chandef, chan,
+                                       NL80211_CHAN_NO_HT);
                wdev->wext.ibss.channel_fixed = true;
        } else {
                /* cfg80211_ibss_wext_join will pick one if needed */
index 0553fd4d85aeb4b9338d2661ba020448105a68e9..b0e1869de7de0b0775561c445389f4f2013beb58 100644 (file)
@@ -141,8 +141,7 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
 
                        for (i = 0; i < sband->n_channels; i++) {
                                chan = &sband->channels[i];
-                               if (chan->flags & (IEEE80211_CHAN_NO_IBSS |
-                                                  IEEE80211_CHAN_PASSIVE_SCAN |
+                               if (chan->flags & (IEEE80211_CHAN_NO_IR |
                                                   IEEE80211_CHAN_DISABLED |
                                                   IEEE80211_CHAN_RADAR))
                                        continue;
index 6a6b1c8e907df93e73b44a8912a3ae1fda5f80a5..52cca05044a898b977927f2c9e540b00d6811634 100644 (file)
@@ -520,9 +520,7 @@ void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev)
 
 int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
                          struct wireless_dev *wdev,
-                         struct ieee80211_channel *chan, bool offchan,
-                         unsigned int wait, const u8 *buf, size_t len,
-                         bool no_cck, bool dont_wait_for_ack, u64 *cookie)
+                         struct cfg80211_mgmt_tx_params *params, u64 *cookie)
 {
        const struct ieee80211_mgmt *mgmt;
        u16 stype;
@@ -533,10 +531,10 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
        if (!rdev->ops->mgmt_tx)
                return -EOPNOTSUPP;
 
-       if (len < 24 + 1)
+       if (params->len < 24 + 1)
                return -EINVAL;
 
-       mgmt = (const struct ieee80211_mgmt *) buf;
+       mgmt = (const struct ieee80211_mgmt *)params->buf;
 
        if (!ieee80211_is_mgmt(mgmt->frame_control))
                return -EINVAL;
@@ -615,9 +613,7 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
                return -EINVAL;
 
        /* Transmit the Action frame as requested by user space */
-       return rdev_mgmt_tx(rdev, wdev, chan, offchan,
-                           wait, buf, len, no_cck, dont_wait_for_ack,
-                           cookie);
+       return rdev_mgmt_tx(rdev, wdev, params, cookie);
 }
 
 bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm,
@@ -763,12 +759,12 @@ void cfg80211_radar_event(struct wiphy *wiphy,
 EXPORT_SYMBOL(cfg80211_radar_event);
 
 void cfg80211_cac_event(struct net_device *netdev,
+                       const struct cfg80211_chan_def *chandef,
                        enum nl80211_radar_event event, gfp_t gfp)
 {
        struct wireless_dev *wdev = netdev->ieee80211_ptr;
        struct wiphy *wiphy = wdev->wiphy;
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
-       struct cfg80211_chan_def chandef;
        unsigned long timeout;
 
        trace_cfg80211_cac_event(netdev, event);
@@ -779,14 +775,12 @@ void cfg80211_cac_event(struct net_device *netdev,
        if (WARN_ON(!wdev->channel))
                return;
 
-       cfg80211_chandef_create(&chandef, wdev->channel, NL80211_CHAN_NO_HT);
-
        switch (event) {
        case NL80211_RADAR_CAC_FINISHED:
                timeout = wdev->cac_start_time +
                          msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS);
                WARN_ON(!time_after_eq(jiffies, timeout));
-               cfg80211_set_dfs_state(wiphy, &chandef, NL80211_DFS_AVAILABLE);
+               cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE);
                break;
        case NL80211_RADAR_CAC_ABORTED:
                break;
@@ -796,6 +790,6 @@ void cfg80211_cac_event(struct net_device *netdev,
        }
        wdev->cac_started = false;
 
-       nl80211_radar_notify(rdev, &chandef, event, netdev, gfp);
+       nl80211_radar_notify(rdev, chandef, event, netdev, gfp);
 }
 EXPORT_SYMBOL(cfg80211_cac_event);
index a1eb21073176115a587f9eb1edf5d36dba582484..a693f86e59704016e9c8419eb82a8c43185d9642 100644 (file)
@@ -564,12 +564,12 @@ static int nl80211_msg_put_channel(struct sk_buff *msg,
        if ((chan->flags & IEEE80211_CHAN_DISABLED) &&
            nla_put_flag(msg, NL80211_FREQUENCY_ATTR_DISABLED))
                goto nla_put_failure;
-       if ((chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) &&
-           nla_put_flag(msg, NL80211_FREQUENCY_ATTR_PASSIVE_SCAN))
-               goto nla_put_failure;
-       if ((chan->flags & IEEE80211_CHAN_NO_IBSS) &&
-           nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IBSS))
-               goto nla_put_failure;
+       if (chan->flags & IEEE80211_CHAN_NO_IR) {
+               if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IR))
+                       goto nla_put_failure;
+               if (nla_put_flag(msg, __NL80211_FREQUENCY_ATTR_NO_IBSS))
+                       goto nla_put_failure;
+       }
        if (chan->flags & IEEE80211_CHAN_RADAR) {
                if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR))
                        goto nla_put_failure;
@@ -1247,10 +1247,6 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
                if ((dev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) &&
                    nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP))
                        goto nla_put_failure;
-               if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ) &&
-                   nla_put_flag(msg, WIPHY_FLAG_SUPPORTS_5_10_MHZ))
-                       goto nla_put_failure;
-
                state->split_start++;
                if (state->split)
                        break;
@@ -1579,6 +1575,11 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
                if (nl80211_send_coalesce(msg, dev))
                        goto nla_put_failure;
 
+               if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ) &&
+                   (nla_put_flag(msg, NL80211_ATTR_SUPPORT_5_MHZ) ||
+                    nla_put_flag(msg, NL80211_ATTR_SUPPORT_10_MHZ)))
+                       goto nla_put_failure;
+
                /* done */
                state->split_start = 0;
                break;
@@ -2187,7 +2188,7 @@ static inline u64 wdev_id(struct wireless_dev *wdev)
 }
 
 static int nl80211_send_chandef(struct sk_buff *msg,
-                                struct cfg80211_chan_def *chandef)
+                               const struct cfg80211_chan_def *chandef)
 {
        WARN_ON(!cfg80211_chandef_valid(chandef));
 
@@ -2687,7 +2688,7 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
        hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
                             NL80211_CMD_NEW_KEY);
        if (!hdr)
-               return -ENOBUFS;
+               goto nla_put_failure;
 
        cookie.msg = msg;
        cookie.idx = key_idx;
@@ -3236,6 +3237,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
                        return PTR_ERR(params.acl);
        }
 
+       wdev_lock(wdev);
        err = rdev_start_ap(rdev, dev, &params);
        if (!err) {
                wdev->preset_chandef = params.chandef;
@@ -3244,6 +3246,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
                wdev->ssid_len = params.ssid_len;
                memcpy(wdev->ssid, params.ssid, wdev->ssid_len);
        }
+       wdev_unlock(wdev);
 
        kfree(params.acl);
 
@@ -3272,7 +3275,11 @@ static int nl80211_set_beacon(struct sk_buff *skb, struct genl_info *info)
        if (err)
                return err;
 
-       return rdev_change_beacon(rdev, dev, &params);
+       wdev_lock(wdev);
+       err = rdev_change_beacon(rdev, dev, &params);
+       wdev_unlock(wdev);
+
+       return err;
 }
 
 static int nl80211_stop_ap(struct sk_buff *skb, struct genl_info *info)
@@ -4478,7 +4485,9 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
 {
        struct cfg80211_registered_device *rdev = info->user_ptr[0];
        struct net_device *dev = info->user_ptr[1];
+       struct wireless_dev *wdev = dev->ieee80211_ptr;
        struct bss_parameters params;
+       int err;
 
        memset(&params, 0, sizeof(params));
        /* default to not changing parameters */
@@ -4544,7 +4553,11 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
            dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
                return -EOPNOTSUPP;
 
-       return rdev_change_bss(rdev, dev, &params);
+       wdev_lock(wdev);
+       err = rdev_change_bss(rdev, dev, &params);
+       wdev_unlock(wdev);
+
+       return err;
 }
 
 static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = {
@@ -5098,7 +5111,7 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
        char *alpha2 = NULL;
        int rem_reg_rules = 0, r = 0;
        u32 num_rules = 0, rule_idx = 0, size_of_regd;
-       u8 dfs_region = 0;
+       enum nl80211_dfs_regions dfs_region = NL80211_DFS_UNSET;
        struct ieee80211_regdomain *rd = NULL;
 
        if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
@@ -5119,6 +5132,9 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
                        return -EINVAL;
        }
 
+       if (!reg_is_valid_request(alpha2))
+               return -EINVAL;
+
        size_of_regd = sizeof(struct ieee80211_regdomain) +
                       num_rules * sizeof(struct ieee80211_reg_rule);
 
@@ -5349,6 +5365,10 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
                                err = -EINVAL;
                                goto out_free;
                        }
+
+                       if (!wiphy->bands[band])
+                               continue;
+
                        err = ieee80211_get_ratemask(wiphy->bands[band],
                                                     nla_data(attr),
                                                     nla_len(attr),
@@ -5361,10 +5381,8 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
        if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) {
                request->flags = nla_get_u32(
                        info->attrs[NL80211_ATTR_SCAN_FLAGS]);
-               if (((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
-                    !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) ||
-                   ((request->flags & NL80211_SCAN_FLAG_FLUSH) &&
-                    !(wiphy->features & NL80211_FEATURE_SCAN_FLUSH))) {
+               if ((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
+                   !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) {
                        err = -EOPNOTSUPP;
                        goto out_free;
                }
@@ -5604,10 +5622,8 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
        if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) {
                request->flags = nla_get_u32(
                        info->attrs[NL80211_ATTR_SCAN_FLAGS]);
-               if (((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
-                    !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) ||
-                   ((request->flags & NL80211_SCAN_FLAG_FLUSH) &&
-                    !(wiphy->features & NL80211_FEATURE_SCAN_FLUSH))) {
+               if ((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
+                   !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) {
                        err = -EOPNOTSUPP;
                        goto out_free;
                }
@@ -5670,7 +5686,7 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
        if (err == 0)
                return -EINVAL;
 
-       if (chandef.chan->dfs_state != NL80211_DFS_USABLE)
+       if (!cfg80211_chandef_dfs_usable(wdev->wiphy, &chandef))
                return -EINVAL;
 
        if (!rdev->ops->start_radar_detection)
@@ -5810,7 +5826,11 @@ skip_beacons:
        if (info->attrs[NL80211_ATTR_CH_SWITCH_BLOCK_TX])
                params.block_tx = true;
 
-       return rdev_channel_switch(rdev, dev, &params);
+       wdev_lock(wdev);
+       err = rdev_channel_switch(rdev, dev, &params);
+       wdev_unlock(wdev);
+
+       return err;
 }
 
 static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
@@ -7443,10 +7463,10 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
        void *hdr = NULL;
        u64 cookie;
        struct sk_buff *msg = NULL;
-       unsigned int wait = 0;
-       bool offchan, no_cck, dont_wait_for_ack;
-
-       dont_wait_for_ack = info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK];
+       struct cfg80211_mgmt_tx_params params = {
+               .dont_wait_for_ack =
+                       info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK],
+       };
 
        if (!info->attrs[NL80211_ATTR_FRAME])
                return -EINVAL;
@@ -7473,24 +7493,24 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
        if (info->attrs[NL80211_ATTR_DURATION]) {
                if (!(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
                        return -EINVAL;
-               wait = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]);
+               params.wait = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]);
 
                /*
                 * We should wait on the channel for at least a minimum amount
                 * of time (10ms) but no longer than the driver supports.
                 */
-               if (wait < NL80211_MIN_REMAIN_ON_CHANNEL_TIME ||
-                   wait > rdev->wiphy.max_remain_on_channel_duration)
+               if (params.wait < NL80211_MIN_REMAIN_ON_CHANNEL_TIME ||
+                   params.wait > rdev->wiphy.max_remain_on_channel_duration)
                        return -EINVAL;
 
        }
 
-       offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK];
+       params.offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK];
 
-       if (offchan && !(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
+       if (params.offchan && !(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
                return -EINVAL;
 
-       no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
+       params.no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
 
        /* get the channel if any has been specified, otherwise pass NULL to
         * the driver. The latter will use the current one
@@ -7502,10 +7522,10 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
                        return err;
        }
 
-       if (!chandef.chan && offchan)
+       if (!chandef.chan && params.offchan)
                return -EINVAL;
 
-       if (!dont_wait_for_ack) {
+       if (!params.dont_wait_for_ack) {
                msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
                if (!msg)
                        return -ENOMEM;
@@ -7518,10 +7538,10 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
                }
        }
 
-       err = cfg80211_mlme_mgmt_tx(rdev, wdev, chandef.chan, offchan, wait,
-                                   nla_data(info->attrs[NL80211_ATTR_FRAME]),
-                                   nla_len(info->attrs[NL80211_ATTR_FRAME]),
-                                   no_cck, dont_wait_for_ack, &cookie);
+       params.buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
+       params.len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
+       params.chan = chandef.chan;
+       err = cfg80211_mlme_mgmt_tx(rdev, wdev, &params, &cookie);
        if (err)
                goto free_msg;
 
@@ -9633,8 +9653,9 @@ static int nl80211_add_scan_req(struct sk_buff *msg,
            nla_put(msg, NL80211_ATTR_IE, req->ie_len, req->ie))
                goto nla_put_failure;
 
-       if (req->flags)
-               nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, req->flags);
+       if (req->flags &&
+           nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, req->flags))
+               goto nla_put_failure;
 
        return 0;
  nla_put_failure:
@@ -10805,21 +10826,18 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
        struct wiphy *wiphy = wdev->wiphy;
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 
-       trace_cfg80211_ch_switch_notify(dev, chandef);
+       ASSERT_WDEV_LOCK(wdev);
 
-       wdev_lock(wdev);
+       trace_cfg80211_ch_switch_notify(dev, chandef);
 
        if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
                    wdev->iftype != NL80211_IFTYPE_P2P_GO &&
                    wdev->iftype != NL80211_IFTYPE_ADHOC &&
                    wdev->iftype != NL80211_IFTYPE_MESH_POINT))
-               goto out;
+               return;
 
        wdev->channel = chandef->chan;
        nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL);
-out:
-       wdev_unlock(wdev);
-       return;
 }
 EXPORT_SYMBOL(cfg80211_ch_switch_notify);
 
@@ -10878,7 +10896,7 @@ EXPORT_SYMBOL(cfg80211_cqm_txe_notify);
 
 void
 nl80211_radar_notify(struct cfg80211_registered_device *rdev,
-                    struct cfg80211_chan_def *chandef,
+                    const struct cfg80211_chan_def *chandef,
                     enum nl80211_radar_event event,
                     struct net_device *netdev, gfp_t gfp)
 {
@@ -11093,6 +11111,8 @@ void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
                struct nlattr *reasons;
 
                reasons = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS);
+               if (!reasons)
+                       goto free_msg;
 
                if (wakeup->disconnect &&
                    nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT))
@@ -11118,16 +11138,18 @@ void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
                                wakeup->pattern_idx))
                        goto free_msg;
 
-               if (wakeup->tcp_match)
-                       nla_put_flag(msg, NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH);
+               if (wakeup->tcp_match &&
+                   nla_put_flag(msg, NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH))
+                       goto free_msg;
 
-               if (wakeup->tcp_connlost)
-                       nla_put_flag(msg,
-                                    NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST);
+               if (wakeup->tcp_connlost &&
+                   nla_put_flag(msg, NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST))
+                       goto free_msg;
 
-               if (wakeup->tcp_nomoretokens)
-                       nla_put_flag(msg,
-                               NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS);
+               if (wakeup->tcp_nomoretokens &&
+                   nla_put_flag(msg,
+                                NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS))
+                       goto free_msg;
 
                if (wakeup->packet) {
                        u32 pkt_attr = NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211;
@@ -11263,24 +11285,29 @@ void cfg80211_ft_event(struct net_device *netdev,
                return;
 
        hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FT_EVENT);
-       if (!hdr) {
-               nlmsg_free(msg);
-               return;
-       }
+       if (!hdr)
+               goto out;
 
-       nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
-       nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
-       nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, ft_event->target_ap);
-       if (ft_event->ies)
-               nla_put(msg, NL80211_ATTR_IE, ft_event->ies_len, ft_event->ies);
-       if (ft_event->ric_ies)
-               nla_put(msg, NL80211_ATTR_IE_RIC, ft_event->ric_ies_len,
-                       ft_event->ric_ies);
+       if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
+           nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
+           nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, ft_event->target_ap))
+               goto out;
+
+       if (ft_event->ies &&
+           nla_put(msg, NL80211_ATTR_IE, ft_event->ies_len, ft_event->ies))
+               goto out;
+       if (ft_event->ric_ies &&
+           nla_put(msg, NL80211_ATTR_IE_RIC, ft_event->ric_ies_len,
+                   ft_event->ric_ies))
+               goto out;
 
        genlmsg_end(msg, hdr);
 
        genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
                                NL80211_MCGRP_MLME, GFP_KERNEL);
+       return;
+ out:
+       nlmsg_free(msg);
 }
 EXPORT_SYMBOL(cfg80211_ft_event);
 
index 2c0f2b3c07cba7e4c2f50b17895d498c79d08dfb..b1b231324e102a44218bcf2354e52662fac78f5a 100644 (file)
@@ -70,7 +70,7 @@ int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
 
 void
 nl80211_radar_notify(struct cfg80211_registered_device *rdev,
-                    struct cfg80211_chan_def *chandef,
+                    const struct cfg80211_chan_def *chandef,
                     enum nl80211_radar_event event,
                     struct net_device *netdev, gfp_t gfp);
 
index 37ce9fdfe934345fe6603b399b8c4d3fd4f44ec1..a6c03ab14a0d47ea9a7f676dec76301804ab809b 100644 (file)
@@ -624,16 +624,12 @@ rdev_cancel_remain_on_channel(struct cfg80211_registered_device *rdev,
 
 static inline int rdev_mgmt_tx(struct cfg80211_registered_device *rdev,
                               struct wireless_dev *wdev,
-                              struct ieee80211_channel *chan, bool offchan,
-                              unsigned int wait, const u8 *buf, size_t len,
-                              bool no_cck, bool dont_wait_for_ack, u64 *cookie)
+                              struct cfg80211_mgmt_tx_params *params,
+                              u64 *cookie)
 {
        int ret;
-       trace_rdev_mgmt_tx(&rdev->wiphy, wdev, chan, offchan,
-                          wait, no_cck, dont_wait_for_ack);
-       ret = rdev->ops->mgmt_tx(&rdev->wiphy, wdev, chan, offchan,
-                                 wait, buf, len, no_cck,
-                                 dont_wait_for_ack, cookie);
+       trace_rdev_mgmt_tx(&rdev->wiphy, wdev, params);
+       ret = rdev->ops->mgmt_tx(&rdev->wiphy, wdev, params, cookie);
        trace_rdev_return_int_cookie(&rdev->wiphy, ret, *cookie);
        return ret;
 }
index 7da67fd0b4188a7cf3e3ded0ae2a64d565274947..ec54e1aac8e29c01e89ab4d0c6e9078bf112b5f9 100644 (file)
@@ -120,6 +120,21 @@ static const struct ieee80211_regdomain *get_wiphy_regdom(struct wiphy *wiphy)
        return rtnl_dereference(wiphy->regd);
 }
 
+static const char *reg_dfs_region_str(enum nl80211_dfs_regions dfs_region)
+{
+       switch (dfs_region) {
+       case NL80211_DFS_UNSET:
+               return "unset";
+       case NL80211_DFS_FCC:
+               return "FCC";
+       case NL80211_DFS_ETSI:
+               return "ETSI";
+       case NL80211_DFS_JP:
+               return "JP";
+       }
+       return "Unknown";
+}
+
 static void rcu_free_regdom(const struct ieee80211_regdomain *r)
 {
        if (!r)
@@ -163,35 +178,29 @@ static const struct ieee80211_regdomain world_regdom = {
                REG_RULE(2412-10, 2462+10, 40, 6, 20, 0),
                /* IEEE 802.11b/g, channels 12..13. */
                REG_RULE(2467-10, 2472+10, 40, 6, 20,
-                       NL80211_RRF_PASSIVE_SCAN |
-                       NL80211_RRF_NO_IBSS),
+                       NL80211_RRF_NO_IR),
                /* IEEE 802.11 channel 14 - Only JP enables
                 * this and for 802.11b only */
                REG_RULE(2484-10, 2484+10, 20, 6, 20,
-                       NL80211_RRF_PASSIVE_SCAN |
-                       NL80211_RRF_NO_IBSS |
+                       NL80211_RRF_NO_IR |
                        NL80211_RRF_NO_OFDM),
                /* IEEE 802.11a, channel 36..48 */
                REG_RULE(5180-10, 5240+10, 160, 6, 20,
-                        NL80211_RRF_PASSIVE_SCAN |
-                        NL80211_RRF_NO_IBSS),
+                        NL80211_RRF_NO_IR),
 
                /* IEEE 802.11a, channel 52..64 - DFS required */
                REG_RULE(5260-10, 5320+10, 160, 6, 20,
-                       NL80211_RRF_PASSIVE_SCAN |
-                       NL80211_RRF_NO_IBSS |
+                       NL80211_RRF_NO_IR |
                        NL80211_RRF_DFS),
 
                /* IEEE 802.11a, channel 100..144 - DFS required */
                REG_RULE(5500-10, 5720+10, 160, 6, 20,
-                       NL80211_RRF_PASSIVE_SCAN |
-                       NL80211_RRF_NO_IBSS |
+                       NL80211_RRF_NO_IR |
                        NL80211_RRF_DFS),
 
                /* IEEE 802.11a, channel 149..165 */
                REG_RULE(5745-10, 5825+10, 80, 6, 20,
-                       NL80211_RRF_PASSIVE_SCAN |
-                       NL80211_RRF_NO_IBSS),
+                       NL80211_RRF_NO_IR),
 
                /* IEEE 802.11ad (60gHz), channels 1..3 */
                REG_RULE(56160+2160*1-1080, 56160+2160*3+1080, 2160, 0, 0, 0),
@@ -208,11 +217,26 @@ static char user_alpha2[2];
 module_param(ieee80211_regdom, charp, 0444);
 MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code");
 
+static void reg_kfree_last_request(void)
+{
+       struct regulatory_request *lr;
+
+       lr = get_last_request();
+
+       if (lr != &core_request_world && lr)
+               kfree_rcu(lr, rcu_head);
+}
+
+static void reg_update_last_request(struct regulatory_request *request)
+{
+       reg_kfree_last_request();
+       rcu_assign_pointer(last_request, request);
+}
+
 static void reset_regdomains(bool full_reset,
                             const struct ieee80211_regdomain *new_regdom)
 {
        const struct ieee80211_regdomain *r;
-       struct regulatory_request *lr;
 
        ASSERT_RTNL();
 
@@ -235,10 +259,7 @@ static void reset_regdomains(bool full_reset,
        if (!full_reset)
                return;
 
-       lr = get_last_request();
-       if (lr != &core_request_world && lr)
-               kfree_rcu(lr, rcu_head);
-       rcu_assign_pointer(last_request, &core_request_world);
+       reg_update_last_request(&core_request_world);
 }
 
 /*
@@ -456,7 +477,15 @@ static int call_crda(const char *alpha2)
        return kobject_uevent(&reg_pdev->dev.kobj, KOBJ_CHANGE);
 }
 
-static bool reg_is_valid_request(const char *alpha2)
+static enum reg_request_treatment
+reg_call_crda(struct regulatory_request *request)
+{
+       if (call_crda(request->alpha2))
+               return REG_REQ_IGNORE;
+       return REG_REQ_OK;
+}
+
+bool reg_is_valid_request(const char *alpha2)
 {
        struct regulatory_request *lr = get_last_request();
 
@@ -556,6 +585,20 @@ static bool freq_in_rule_band(const struct ieee80211_freq_range *freq_range,
 #undef ONE_GHZ_IN_KHZ
 }
 
+/*
+ * Later on we can perhaps use the more restrictive DFS
+ * region but we don't have information for that yet so
+ * for now simply disallow conflicts.
+ */
+static enum nl80211_dfs_regions
+reg_intersect_dfs_region(const enum nl80211_dfs_regions dfs_region1,
+                        const enum nl80211_dfs_regions dfs_region2)
+{
+       if (dfs_region1 != dfs_region2)
+               return NL80211_DFS_UNSET;
+       return dfs_region1;
+}
+
 /*
  * Helper for regdom_intersect(), this does the real
  * mathematical intersection fun
@@ -687,6 +730,8 @@ regdom_intersect(const struct ieee80211_regdomain *rd1,
        rd->n_reg_rules = num_rules;
        rd->alpha2[0] = '9';
        rd->alpha2[1] = '8';
+       rd->dfs_region = reg_intersect_dfs_region(rd1->dfs_region,
+                                                 rd2->dfs_region);
 
        return rd;
 }
@@ -698,10 +743,8 @@ regdom_intersect(const struct ieee80211_regdomain *rd1,
 static u32 map_regdom_flags(u32 rd_flags)
 {
        u32 channel_flags = 0;
-       if (rd_flags & NL80211_RRF_PASSIVE_SCAN)
-               channel_flags |= IEEE80211_CHAN_PASSIVE_SCAN;
-       if (rd_flags & NL80211_RRF_NO_IBSS)
-               channel_flags |= IEEE80211_CHAN_NO_IBSS;
+       if (rd_flags & NL80211_RRF_NO_IR_ALL)
+               channel_flags |= IEEE80211_CHAN_NO_IR;
        if (rd_flags & NL80211_RRF_DFS)
                channel_flags |= IEEE80211_CHAN_RADAR;
        if (rd_flags & NL80211_RRF_NO_OFDM)
@@ -854,8 +897,18 @@ static void handle_channel(struct wiphy *wiphy,
                    PTR_ERR(reg_rule) == -ERANGE)
                        return;
 
-               REG_DBG_PRINT("Disabling freq %d MHz\n", chan->center_freq);
-               chan->flags |= IEEE80211_CHAN_DISABLED;
+               if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
+                   request_wiphy && request_wiphy == wiphy &&
+                   request_wiphy->regulatory_flags & REGULATORY_STRICT_REG) {
+                       REG_DBG_PRINT("Disabling freq %d MHz for good\n",
+                                     chan->center_freq);
+                       chan->orig_flags |= IEEE80211_CHAN_DISABLED;
+                       chan->flags = chan->orig_flags;
+               } else {
+                       REG_DBG_PRINT("Disabling freq %d MHz\n",
+                                     chan->center_freq);
+                       chan->flags |= IEEE80211_CHAN_DISABLED;
+               }
                return;
        }
 
@@ -873,7 +926,7 @@ static void handle_channel(struct wiphy *wiphy,
 
        if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
            request_wiphy && request_wiphy == wiphy &&
-           request_wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) {
+           request_wiphy->regulatory_flags & REGULATORY_STRICT_REG) {
                /*
                 * This guarantees the driver's requested regulatory domain
                 * will always be used as a base for further regulatory
@@ -899,13 +952,11 @@ static void handle_channel(struct wiphy *wiphy,
        chan->max_reg_power = (int) MBM_TO_DBM(power_rule->max_eirp);
        if (chan->orig_mpwr) {
                /*
-                * Devices that have their own custom regulatory domain
-                * but also use WIPHY_FLAG_STRICT_REGULATORY will follow the
-                * passed country IE power settings.
+                * Devices that use REGULATORY_COUNTRY_IE_FOLLOW_POWER
+                * will always follow the passed country IE power settings.
                 */
                if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE &&
-                   wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY &&
-                   wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY)
+                   wiphy->regulatory_flags & REGULATORY_COUNTRY_IE_FOLLOW_POWER)
                        chan->max_power = chan->max_reg_power;
                else
                        chan->max_power = min(chan->orig_mpwr,
@@ -975,8 +1026,8 @@ static bool reg_dev_ignore_cell_hint(struct wiphy *wiphy)
 
 static bool wiphy_strict_alpha2_regd(struct wiphy *wiphy)
 {
-       if (wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY &&
-           !(wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY))
+       if (wiphy->regulatory_flags & REGULATORY_STRICT_REG &&
+           !(wiphy->regulatory_flags & REGULATORY_CUSTOM_REG))
                return true;
        return false;
 }
@@ -994,7 +1045,7 @@ static bool ignore_reg_update(struct wiphy *wiphy,
        }
 
        if (initiator == NL80211_REGDOM_SET_BY_CORE &&
-           wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY) {
+           wiphy->regulatory_flags & REGULATORY_CUSTOM_REG) {
                REG_DBG_PRINT("Ignoring regulatory request set by %s "
                              "since the driver uses its own custom "
                              "regulatory domain\n",
@@ -1032,7 +1083,7 @@ static bool reg_is_world_roaming(struct wiphy *wiphy)
                return true;
 
        if (lr && lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE &&
-           wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY)
+           wiphy->regulatory_flags & REGULATORY_CUSTOM_REG)
                return true;
 
        return false;
@@ -1060,19 +1111,14 @@ static void handle_reg_beacon(struct wiphy *wiphy, unsigned int chan_idx,
        if (!reg_is_world_roaming(wiphy))
                return;
 
-       if (wiphy->flags & WIPHY_FLAG_DISABLE_BEACON_HINTS)
+       if (wiphy->regulatory_flags & REGULATORY_DISABLE_BEACON_HINTS)
                return;
 
        chan_before.center_freq = chan->center_freq;
        chan_before.flags = chan->flags;
 
-       if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) {
-               chan->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
-               channel_changed = true;
-       }
-
-       if (chan->flags & IEEE80211_CHAN_NO_IBSS) {
-               chan->flags &= ~IEEE80211_CHAN_NO_IBSS;
+       if (chan->flags & IEEE80211_CHAN_NO_IR) {
+               chan->flags &= ~IEEE80211_CHAN_NO_IR;
                channel_changed = true;
        }
 
@@ -1205,14 +1251,30 @@ static void reg_process_ht_flags(struct wiphy *wiphy)
                reg_process_ht_flags_band(wiphy, wiphy->bands[band]);
 }
 
+static void reg_call_notifier(struct wiphy *wiphy,
+                             struct regulatory_request *request)
+{
+       if (wiphy->reg_notifier)
+               wiphy->reg_notifier(wiphy, request);
+}
+
 static void wiphy_update_regulatory(struct wiphy *wiphy,
                                    enum nl80211_reg_initiator initiator)
 {
        enum ieee80211_band band;
        struct regulatory_request *lr = get_last_request();
 
-       if (ignore_reg_update(wiphy, initiator))
+       if (ignore_reg_update(wiphy, initiator)) {
+               /*
+                * Regulatory updates set by CORE are ignored for custom
+                * regulatory cards. Let us notify the changes to the driver,
+                * as some drivers used this to restore its orig_* reg domain.
+                */
+               if (initiator == NL80211_REGDOM_SET_BY_CORE &&
+                   wiphy->regulatory_flags & REGULATORY_CUSTOM_REG)
+                       reg_call_notifier(wiphy, lr);
                return;
+       }
 
        lr->dfs_region = get_cfg80211_regdom()->dfs_region;
 
@@ -1221,9 +1283,7 @@ static void wiphy_update_regulatory(struct wiphy *wiphy,
 
        reg_process_beacons(wiphy);
        reg_process_ht_flags(wiphy);
-
-       if (wiphy->reg_notifier)
-               wiphy->reg_notifier(wiphy, lr);
+       reg_call_notifier(wiphy, lr);
 }
 
 static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator)
@@ -1236,15 +1296,6 @@ static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator)
        list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
                wiphy = &rdev->wiphy;
                wiphy_update_regulatory(wiphy, initiator);
-               /*
-                * Regulatory updates set by CORE are ignored for custom
-                * regulatory cards. Let us notify the changes to the driver,
-                * as some drivers used this to restore its orig_* reg domain.
-                */
-               if (initiator == NL80211_REGDOM_SET_BY_CORE &&
-                   wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY &&
-                   wiphy->reg_notifier)
-                       wiphy->reg_notifier(wiphy, get_last_request());
        }
 }
 
@@ -1263,7 +1314,8 @@ static void handle_channel_custom(struct wiphy *wiphy,
        if (IS_ERR(reg_rule)) {
                REG_DBG_PRINT("Disabling freq %d MHz as custom regd has no rule that fits it\n",
                              chan->center_freq);
-               chan->flags = IEEE80211_CHAN_DISABLED;
+               chan->orig_flags |= IEEE80211_CHAN_DISABLED;
+               chan->flags = chan->orig_flags;
                return;
        }
 
@@ -1305,6 +1357,10 @@ void wiphy_apply_custom_regulatory(struct wiphy *wiphy,
        enum ieee80211_band band;
        unsigned int bands_set = 0;
 
+       WARN(!(wiphy->regulatory_flags & REGULATORY_CUSTOM_REG),
+            "wiphy should have REGULATORY_CUSTOM_REG\n");
+       wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
+
        for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
                if (!wiphy->bands[band])
                        continue;
@@ -1320,225 +1376,285 @@ void wiphy_apply_custom_regulatory(struct wiphy *wiphy,
 }
 EXPORT_SYMBOL(wiphy_apply_custom_regulatory);
 
-/* This has the logic which determines when a new request
- * should be ignored. */
-static enum reg_request_treatment
-get_reg_request_treatment(struct wiphy *wiphy,
-                         struct regulatory_request *pending_request)
+static void reg_set_request_processed(void)
 {
-       struct wiphy *last_wiphy = NULL;
+       bool need_more_processing = false;
        struct regulatory_request *lr = get_last_request();
 
-       /* All initial requests are respected */
-       if (!lr)
-               return REG_REQ_OK;
+       lr->processed = true;
 
-       switch (pending_request->initiator) {
-       case NL80211_REGDOM_SET_BY_CORE:
-               return REG_REQ_OK;
-       case NL80211_REGDOM_SET_BY_COUNTRY_IE:
-               if (reg_request_cell_base(lr)) {
-                       /* Trust a Cell base station over the AP's country IE */
-                       if (regdom_changes(pending_request->alpha2))
-                               return REG_REQ_IGNORE;
-                       return REG_REQ_ALREADY_SET;
-               }
+       spin_lock(&reg_requests_lock);
+       if (!list_empty(&reg_requests_list))
+               need_more_processing = true;
+       spin_unlock(&reg_requests_lock);
 
-               last_wiphy = wiphy_idx_to_wiphy(lr->wiphy_idx);
+       if (lr->initiator == NL80211_REGDOM_SET_BY_USER)
+               cancel_delayed_work(&reg_timeout);
 
-               if (unlikely(!is_an_alpha2(pending_request->alpha2)))
-                       return -EINVAL;
-               if (lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) {
-                       if (last_wiphy != wiphy) {
-                               /*
-                                * Two cards with two APs claiming different
-                                * Country IE alpha2s. We could
-                                * intersect them, but that seems unlikely
-                                * to be correct. Reject second one for now.
-                                */
-                               if (regdom_changes(pending_request->alpha2))
-                                       return REG_REQ_IGNORE;
-                               return REG_REQ_ALREADY_SET;
-                       }
-                       /*
-                        * Two consecutive Country IE hints on the same wiphy.
-                        * This should be picked up early by the driver/stack
-                        */
-                       if (WARN_ON(regdom_changes(pending_request->alpha2)))
-                               return REG_REQ_OK;
-                       return REG_REQ_ALREADY_SET;
-               }
-               return REG_REQ_OK;
-       case NL80211_REGDOM_SET_BY_DRIVER:
-               if (lr->initiator == NL80211_REGDOM_SET_BY_CORE) {
-                       if (regdom_changes(pending_request->alpha2))
-                               return REG_REQ_OK;
-                       return REG_REQ_ALREADY_SET;
-               }
+       if (need_more_processing)
+               schedule_work(&reg_work);
+}
 
-               /*
-                * This would happen if you unplug and plug your card
-                * back in or if you add a new device for which the previously
-                * loaded card also agrees on the regulatory domain.
-                */
-               if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
-                   !regdom_changes(pending_request->alpha2))
-                       return REG_REQ_ALREADY_SET;
+/**
+ * reg_process_hint_core - process core regulatory requests
+ * @pending_request: a pending core regulatory request
+ *
+ * The wireless subsystem can use this function to process
+ * a regulatory request issued by the regulatory core.
+ *
+ * Returns one of the different reg request treatment values.
+ */
+static enum reg_request_treatment
+reg_process_hint_core(struct regulatory_request *core_request)
+{
+
+       core_request->intersect = false;
+       core_request->processed = false;
+
+       reg_update_last_request(core_request);
 
+       return reg_call_crda(core_request);
+}
+
+static enum reg_request_treatment
+__reg_process_hint_user(struct regulatory_request *user_request)
+{
+       struct regulatory_request *lr = get_last_request();
+
+       if (reg_request_cell_base(user_request))
+               return reg_ignore_cell_hint(user_request);
+
+       if (reg_request_cell_base(lr))
+               return REG_REQ_IGNORE;
+
+       if (lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)
                return REG_REQ_INTERSECT;
-       case NL80211_REGDOM_SET_BY_USER:
-               if (reg_request_cell_base(pending_request))
-                       return reg_ignore_cell_hint(pending_request);
+       /*
+        * If the user knows better the user should set the regdom
+        * to their country before the IE is picked up
+        */
+       if (lr->initiator == NL80211_REGDOM_SET_BY_USER &&
+           lr->intersect)
+               return REG_REQ_IGNORE;
+       /*
+        * Process user requests only after previous user/driver/core
+        * requests have been processed
+        */
+       if ((lr->initiator == NL80211_REGDOM_SET_BY_CORE ||
+            lr->initiator == NL80211_REGDOM_SET_BY_DRIVER ||
+            lr->initiator == NL80211_REGDOM_SET_BY_USER) &&
+           regdom_changes(lr->alpha2))
+               return REG_REQ_IGNORE;
 
-               if (reg_request_cell_base(lr))
-                       return REG_REQ_IGNORE;
+       if (!regdom_changes(user_request->alpha2))
+               return REG_REQ_ALREADY_SET;
 
-               if (lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)
-                       return REG_REQ_INTERSECT;
-               /*
-                * If the user knows better the user should set the regdom
-                * to their country before the IE is picked up
-                */
-               if (lr->initiator == NL80211_REGDOM_SET_BY_USER &&
-                   lr->intersect)
-                       return REG_REQ_IGNORE;
-               /*
-                * Process user requests only after previous user/driver/core
-                * requests have been processed
-                */
-               if ((lr->initiator == NL80211_REGDOM_SET_BY_CORE ||
-                    lr->initiator == NL80211_REGDOM_SET_BY_DRIVER ||
-                    lr->initiator == NL80211_REGDOM_SET_BY_USER) &&
-                   regdom_changes(lr->alpha2))
-                       return REG_REQ_IGNORE;
+       return REG_REQ_OK;
+}
 
-               if (!regdom_changes(pending_request->alpha2))
-                       return REG_REQ_ALREADY_SET;
+/**
+ * reg_process_hint_user - process user regulatory requests
+ * @user_request: a pending user regulatory request
+ *
+ * The wireless subsystem can use this function to process
+ * a regulatory request initiated by userspace.
+ *
+ * Returns one of the different reg request treatment values.
+ */
+static enum reg_request_treatment
+reg_process_hint_user(struct regulatory_request *user_request)
+{
+       enum reg_request_treatment treatment;
 
-               return REG_REQ_OK;
+       treatment = __reg_process_hint_user(user_request);
+       if (treatment == REG_REQ_IGNORE ||
+           treatment == REG_REQ_ALREADY_SET) {
+               kfree(user_request);
+               return treatment;
        }
 
-       return REG_REQ_IGNORE;
+       user_request->intersect = treatment == REG_REQ_INTERSECT;
+       user_request->processed = false;
+
+       reg_update_last_request(user_request);
+
+       user_alpha2[0] = user_request->alpha2[0];
+       user_alpha2[1] = user_request->alpha2[1];
+
+       return reg_call_crda(user_request);
 }
 
-static void reg_set_request_processed(void)
+static enum reg_request_treatment
+__reg_process_hint_driver(struct regulatory_request *driver_request)
 {
-       bool need_more_processing = false;
        struct regulatory_request *lr = get_last_request();
 
-       lr->processed = true;
-
-       spin_lock(&reg_requests_lock);
-       if (!list_empty(&reg_requests_list))
-               need_more_processing = true;
-       spin_unlock(&reg_requests_lock);
+       if (lr->initiator == NL80211_REGDOM_SET_BY_CORE) {
+               if (regdom_changes(driver_request->alpha2))
+                       return REG_REQ_OK;
+               return REG_REQ_ALREADY_SET;
+       }
 
-       if (lr->initiator == NL80211_REGDOM_SET_BY_USER)
-               cancel_delayed_work(&reg_timeout);
+       /*
+        * This would happen if you unplug and plug your card
+        * back in or if you add a new device for which the previously
+        * loaded card also agrees on the regulatory domain.
+        */
+       if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
+           !regdom_changes(driver_request->alpha2))
+               return REG_REQ_ALREADY_SET;
 
-       if (need_more_processing)
-               schedule_work(&reg_work);
+       return REG_REQ_INTERSECT;
 }
 
 /**
- * __regulatory_hint - hint to the wireless core a regulatory domain
- * @wiphy: if the hint comes from country information from an AP, this
- *     is required to be set to the wiphy that received the information
- * @pending_request: the regulatory request currently being processed
+ * reg_process_hint_driver - process driver regulatory requests
+ * @driver_request: a pending driver regulatory request
  *
- * The Wireless subsystem can use this function to hint to the wireless core
- * what it believes should be the current regulatory domain.
+ * The wireless subsystem can use this function to process
+ * a regulatory request issued by an 802.11 driver.
  *
  * Returns one of the different reg request treatment values.
  */
 static enum reg_request_treatment
-__regulatory_hint(struct wiphy *wiphy,
-                 struct regulatory_request *pending_request)
+reg_process_hint_driver(struct wiphy *wiphy,
+                       struct regulatory_request *driver_request)
 {
        const struct ieee80211_regdomain *regd;
-       bool intersect = false;
        enum reg_request_treatment treatment;
-       struct regulatory_request *lr;
 
-       treatment = get_reg_request_treatment(wiphy, pending_request);
+       treatment = __reg_process_hint_driver(driver_request);
 
        switch (treatment) {
-       case REG_REQ_INTERSECT:
-               if (pending_request->initiator ==
-                   NL80211_REGDOM_SET_BY_DRIVER) {
-                       regd = reg_copy_regd(get_cfg80211_regdom());
-                       if (IS_ERR(regd)) {
-                               kfree(pending_request);
-                               return PTR_ERR(regd);
-                       }
-                       rcu_assign_pointer(wiphy->regd, regd);
-               }
-               intersect = true;
-               break;
        case REG_REQ_OK:
                break;
-       default:
-               /*
-                * If the regulatory domain being requested by the
-                * driver has already been set just copy it to the
-                * wiphy
-                */
-               if (treatment == REG_REQ_ALREADY_SET &&
-                   pending_request->initiator == NL80211_REGDOM_SET_BY_DRIVER) {
-                       regd = reg_copy_regd(get_cfg80211_regdom());
-                       if (IS_ERR(regd)) {
-                               kfree(pending_request);
-                               return REG_REQ_IGNORE;
-                       }
-                       treatment = REG_REQ_ALREADY_SET;
-                       rcu_assign_pointer(wiphy->regd, regd);
-                       goto new_request;
-               }
-               kfree(pending_request);
+       case REG_REQ_IGNORE:
+               kfree(driver_request);
                return treatment;
+       case REG_REQ_INTERSECT:
+               /* fall through */
+       case REG_REQ_ALREADY_SET:
+               regd = reg_copy_regd(get_cfg80211_regdom());
+               if (IS_ERR(regd)) {
+                       kfree(driver_request);
+                       return REG_REQ_IGNORE;
+               }
+               rcu_assign_pointer(wiphy->regd, regd);
        }
 
-new_request:
-       lr = get_last_request();
-       if (lr != &core_request_world && lr)
-               kfree_rcu(lr, rcu_head);
 
-       pending_request->intersect = intersect;
-       pending_request->processed = false;
-       rcu_assign_pointer(last_request, pending_request);
-       lr = pending_request;
+       driver_request->intersect = treatment == REG_REQ_INTERSECT;
+       driver_request->processed = false;
 
-       pending_request = NULL;
+       reg_update_last_request(driver_request);
 
-       if (lr->initiator == NL80211_REGDOM_SET_BY_USER) {
-               user_alpha2[0] = lr->alpha2[0];
-               user_alpha2[1] = lr->alpha2[1];
+       /*
+        * Since CRDA will not be called in this case as we already
+        * have applied the requested regulatory domain before we just
+        * inform userspace we have processed the request
+        */
+       if (treatment == REG_REQ_ALREADY_SET) {
+               nl80211_send_reg_change_event(driver_request);
+               reg_set_request_processed();
+               return treatment;
        }
 
-       /* When r == REG_REQ_INTERSECT we do need to call CRDA */
-       if (treatment != REG_REQ_OK && treatment != REG_REQ_INTERSECT) {
+       return reg_call_crda(driver_request);
+}
+
+static enum reg_request_treatment
+__reg_process_hint_country_ie(struct wiphy *wiphy,
+                             struct regulatory_request *country_ie_request)
+{
+       struct wiphy *last_wiphy = NULL;
+       struct regulatory_request *lr = get_last_request();
+
+       if (reg_request_cell_base(lr)) {
+               /* Trust a Cell base station over the AP's country IE */
+               if (regdom_changes(country_ie_request->alpha2))
+                       return REG_REQ_IGNORE;
+               return REG_REQ_ALREADY_SET;
+       } else {
+               if (wiphy->regulatory_flags & REGULATORY_COUNTRY_IE_IGNORE)
+                       return REG_REQ_IGNORE;
+       }
+
+       if (unlikely(!is_an_alpha2(country_ie_request->alpha2)))
+               return -EINVAL;
+
+       if (lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE)
+               return REG_REQ_OK;
+
+       last_wiphy = wiphy_idx_to_wiphy(lr->wiphy_idx);
+
+       if (last_wiphy != wiphy) {
                /*
-                * Since CRDA will not be called in this case as we already
-                * have applied the requested regulatory domain before we just
-                * inform userspace we have processed the request
+                * Two cards with two APs claiming different
+                * Country IE alpha2s. We could
+                * intersect them, but that seems unlikely
+                * to be correct. Reject second one for now.
                 */
-               if (treatment == REG_REQ_ALREADY_SET) {
-                       nl80211_send_reg_change_event(lr);
-                       reg_set_request_processed();
-               }
-               return treatment;
+               if (regdom_changes(country_ie_request->alpha2))
+                       return REG_REQ_IGNORE;
+               return REG_REQ_ALREADY_SET;
        }
+       /*
+        * Two consecutive Country IE hints on the same wiphy.
+        * This should be picked up early by the driver/stack
+        */
+       if (WARN_ON(regdom_changes(country_ie_request->alpha2)))
+               return REG_REQ_OK;
+       return REG_REQ_ALREADY_SET;
+}
+
+/**
+ * reg_process_hint_country_ie - process regulatory requests from country IEs
+ * @country_ie_request: a regulatory request from a country IE
+ *
+ * The wireless subsystem can use this function to process
+ * a regulatory request issued by a country Information Element.
+ *
+ * Returns one of the different reg request treatment values.
+ */
+static enum reg_request_treatment
+reg_process_hint_country_ie(struct wiphy *wiphy,
+                           struct regulatory_request *country_ie_request)
+{
+       enum reg_request_treatment treatment;
+
+       treatment = __reg_process_hint_country_ie(wiphy, country_ie_request);
 
-       if (call_crda(lr->alpha2))
+       switch (treatment) {
+       case REG_REQ_OK:
+               break;
+       case REG_REQ_IGNORE:
+               /* fall through */
+       case REG_REQ_ALREADY_SET:
+               kfree(country_ie_request);
+               return treatment;
+       case REG_REQ_INTERSECT:
+               kfree(country_ie_request);
+               /*
+                * This doesn't happen yet, not sure we
+                * ever want to support it for this case.
+                */
+               WARN_ONCE(1, "Unexpected intersection for country IEs");
                return REG_REQ_IGNORE;
-       return REG_REQ_OK;
+       }
+
+       country_ie_request->intersect = false;
+       country_ie_request->processed = false;
+
+       reg_update_last_request(country_ie_request);
+
+       return reg_call_crda(country_ie_request);
 }
 
 /* This processes *all* regulatory hints */
-static void reg_process_hint(struct regulatory_request *reg_request,
-                            enum nl80211_reg_initiator reg_initiator)
+static void reg_process_hint(struct regulatory_request *reg_request)
 {
        struct wiphy *wiphy = NULL;
+       enum reg_request_treatment treatment;
 
        if (WARN_ON(!reg_request->alpha2))
                return;
@@ -1546,23 +1662,37 @@ static void reg_process_hint(struct regulatory_request *reg_request,
        if (reg_request->wiphy_idx != WIPHY_IDX_INVALID)
                wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx);
 
-       if (reg_initiator == NL80211_REGDOM_SET_BY_DRIVER && !wiphy) {
+       if (reg_request->initiator == NL80211_REGDOM_SET_BY_DRIVER && !wiphy) {
                kfree(reg_request);
                return;
        }
 
-       switch (__regulatory_hint(wiphy, reg_request)) {
-       case REG_REQ_ALREADY_SET:
-               /* This is required so that the orig_* parameters are saved */
-               if (wiphy && wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY)
-                       wiphy_update_regulatory(wiphy, reg_initiator);
+       switch (reg_request->initiator) {
+       case NL80211_REGDOM_SET_BY_CORE:
+               reg_process_hint_core(reg_request);
+               return;
+       case NL80211_REGDOM_SET_BY_USER:
+               treatment = reg_process_hint_user(reg_request);
+               if (treatment == REG_REQ_OK ||
+                   treatment == REG_REQ_ALREADY_SET)
+                       return;
+               schedule_delayed_work(&reg_timeout, msecs_to_jiffies(3142));
+               return;
+       case NL80211_REGDOM_SET_BY_DRIVER:
+               treatment = reg_process_hint_driver(wiphy, reg_request);
                break;
-       default:
-               if (reg_initiator == NL80211_REGDOM_SET_BY_USER)
-                       schedule_delayed_work(&reg_timeout,
-                                             msecs_to_jiffies(3142));
+       case NL80211_REGDOM_SET_BY_COUNTRY_IE:
+               treatment = reg_process_hint_country_ie(wiphy, reg_request);
                break;
+       default:
+               WARN(1, "invalid initiator %d\n", reg_request->initiator);
+               return;
        }
+
+       /* This is required so that the orig_* parameters are saved */
+       if (treatment == REG_REQ_ALREADY_SET && wiphy &&
+           wiphy->regulatory_flags & REGULATORY_STRICT_REG)
+               wiphy_update_regulatory(wiphy, reg_request->initiator);
 }
 
 /*
@@ -1596,7 +1726,7 @@ static void reg_process_pending_hints(void)
 
        spin_unlock(&reg_requests_lock);
 
-       reg_process_hint(reg_request, reg_request->initiator);
+       reg_process_hint(reg_request);
 }
 
 /* Processes beacon hints -- this has nothing to do with country IEs */
@@ -1888,7 +2018,7 @@ static void restore_regulatory_settings(bool reset_user)
        world_alpha2[1] = cfg80211_world_regdom->alpha2[1];
 
        list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
-               if (rdev->wiphy.flags & WIPHY_FLAG_CUSTOM_REGULATORY)
+               if (rdev->wiphy.regulatory_flags & REGULATORY_CUSTOM_REG)
                        restore_custom_reg_settings(&rdev->wiphy);
        }
 
@@ -2016,7 +2146,7 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd)
        }
 }
 
-bool reg_supported_dfs_region(u8 dfs_region)
+bool reg_supported_dfs_region(enum nl80211_dfs_regions dfs_region)
 {
        switch (dfs_region) {
        case NL80211_DFS_UNSET:
@@ -2031,27 +2161,6 @@ bool reg_supported_dfs_region(u8 dfs_region)
        }
 }
 
-static void print_dfs_region(u8 dfs_region)
-{
-       if (!dfs_region)
-               return;
-
-       switch (dfs_region) {
-       case NL80211_DFS_FCC:
-               pr_info(" DFS Master region FCC");
-               break;
-       case NL80211_DFS_ETSI:
-               pr_info(" DFS Master region ETSI");
-               break;
-       case NL80211_DFS_JP:
-               pr_info(" DFS Master region JP");
-               break;
-       default:
-               pr_info(" DFS Master region Unknown");
-               break;
-       }
-}
-
 static void print_regdomain(const struct ieee80211_regdomain *rd)
 {
        struct regulatory_request *lr = get_last_request();
@@ -2083,7 +2192,7 @@ static void print_regdomain(const struct ieee80211_regdomain *rd)
                }
        }
 
-       print_dfs_region(rd->dfs_region);
+       pr_info(" DFS Master region: %s", reg_dfs_region_str(rd->dfs_region));
        print_rd_rules(rd);
 }
 
@@ -2093,48 +2202,60 @@ static void print_regdomain_info(const struct ieee80211_regdomain *rd)
        print_rd_rules(rd);
 }
 
-/* Takes ownership of rd only if it doesn't fail */
-static int __set_regdom(const struct ieee80211_regdomain *rd)
+static int reg_set_rd_core(const struct ieee80211_regdomain *rd)
+{
+       if (!is_world_regdom(rd->alpha2))
+               return -EINVAL;
+       update_world_regdomain(rd);
+       return 0;
+}
+
+static int reg_set_rd_user(const struct ieee80211_regdomain *rd,
+                          struct regulatory_request *user_request)
 {
-       const struct ieee80211_regdomain *regd;
        const struct ieee80211_regdomain *intersected_rd = NULL;
-       struct wiphy *request_wiphy;
-       struct regulatory_request *lr = get_last_request();
 
-       /* Some basic sanity checks first */
+       if (is_world_regdom(rd->alpha2))
+               return -EINVAL;
+
+       if (!regdom_changes(rd->alpha2))
+               return -EALREADY;
 
-       if (!reg_is_valid_request(rd->alpha2))
+       if (!is_valid_rd(rd)) {
+               pr_err("Invalid regulatory domain detected:\n");
+               print_regdomain_info(rd);
                return -EINVAL;
+       }
 
-       if (is_world_regdom(rd->alpha2)) {
-               update_world_regdomain(rd);
+       if (!user_request->intersect) {
+               reset_regdomains(false, rd);
                return 0;
        }
 
-       if (!is_alpha2_set(rd->alpha2) && !is_an_alpha2(rd->alpha2) &&
-           !is_unknown_alpha2(rd->alpha2))
+       intersected_rd = regdom_intersect(rd, get_cfg80211_regdom());
+       if (!intersected_rd)
                return -EINVAL;
 
-       /*
-        * Lets only bother proceeding on the same alpha2 if the current
-        * rd is non static (it means CRDA was present and was used last)
-        * and the pending request came in from a country IE
-        */
-       if (lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) {
-               /*
-                * If someone else asked us to change the rd lets only bother
-                * checking if the alpha2 changes if CRDA was already called
-                */
-               if (!regdom_changes(rd->alpha2))
-                       return -EALREADY;
-       }
+       kfree(rd);
+       rd = NULL;
+       reset_regdomains(false, intersected_rd);
 
-       /*
-        * Now lets set the regulatory domain, update all driver channels
-        * and finally inform them of what we have done, in case they want
-        * to review or adjust their own settings based on their own
-        * internal EEPROM data
-        */
+       return 0;
+}
+
+static int reg_set_rd_driver(const struct ieee80211_regdomain *rd,
+                            struct regulatory_request *driver_request)
+{
+       const struct ieee80211_regdomain *regd;
+       const struct ieee80211_regdomain *intersected_rd = NULL;
+       const struct ieee80211_regdomain *tmp;
+       struct wiphy *request_wiphy;
+
+       if (is_world_regdom(rd->alpha2))
+               return -EINVAL;
+
+       if (!regdom_changes(rd->alpha2))
+               return -EALREADY;
 
        if (!is_valid_rd(rd)) {
                pr_err("Invalid regulatory domain detected:\n");
@@ -2142,29 +2263,13 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
                return -EINVAL;
        }
 
-       request_wiphy = wiphy_idx_to_wiphy(lr->wiphy_idx);
-       if (!request_wiphy &&
-           (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER ||
-            lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)) {
+       request_wiphy = wiphy_idx_to_wiphy(driver_request->wiphy_idx);
+       if (!request_wiphy) {
                schedule_delayed_work(&reg_timeout, 0);
                return -ENODEV;
        }
 
-       if (!lr->intersect) {
-               if (lr->initiator != NL80211_REGDOM_SET_BY_DRIVER) {
-                       reset_regdomains(false, rd);
-                       return 0;
-               }
-
-               /*
-                * For a driver hint, lets copy the regulatory domain the
-                * driver wanted to the wiphy to deal with conflicts
-                */
-
-               /*
-                * Userspace could have sent two replies with only
-                * one kernel request.
-                */
+       if (!driver_request->intersect) {
                if (request_wiphy->regd)
                        return -EALREADY;
 
@@ -2177,38 +2282,59 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
                return 0;
        }
 
-       /* Intersection requires a bit more work */
+       intersected_rd = regdom_intersect(rd, get_cfg80211_regdom());
+       if (!intersected_rd)
+               return -EINVAL;
 
-       if (lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) {
-               intersected_rd = regdom_intersect(rd, get_cfg80211_regdom());
-               if (!intersected_rd)
-                       return -EINVAL;
+       /*
+        * We can trash what CRDA provided now.
+        * However if a driver requested this specific regulatory
+        * domain we keep it for its private use
+        */
+       tmp = get_wiphy_regdom(request_wiphy);
+       rcu_assign_pointer(request_wiphy->regd, rd);
+       rcu_free_regdom(tmp);
 
-               /*
-                * We can trash what CRDA provided now.
-                * However if a driver requested this specific regulatory
-                * domain we keep it for its private use
-                */
-               if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER) {
-                       const struct ieee80211_regdomain *tmp;
+       rd = NULL;
 
-                       tmp = get_wiphy_regdom(request_wiphy);
-                       rcu_assign_pointer(request_wiphy->regd, rd);
-                       rcu_free_regdom(tmp);
-               } else {
-                       kfree(rd);
-               }
+       reset_regdomains(false, intersected_rd);
 
-               rd = NULL;
+       return 0;
+}
 
-               reset_regdomains(false, intersected_rd);
+static int reg_set_rd_country_ie(const struct ieee80211_regdomain *rd,
+                                struct regulatory_request *country_ie_request)
+{
+       struct wiphy *request_wiphy;
 
-               return 0;
+       if (!is_alpha2_set(rd->alpha2) && !is_an_alpha2(rd->alpha2) &&
+           !is_unknown_alpha2(rd->alpha2))
+               return -EINVAL;
+
+       /*
+        * Lets only bother proceeding on the same alpha2 if the current
+        * rd is non static (it means CRDA was present and was used last)
+        * and the pending request came in from a country IE
+        */
+
+       if (!is_valid_rd(rd)) {
+               pr_err("Invalid regulatory domain detected:\n");
+               print_regdomain_info(rd);
+               return -EINVAL;
        }
 
-       return -EINVAL;
-}
+       request_wiphy = wiphy_idx_to_wiphy(country_ie_request->wiphy_idx);
+       if (!request_wiphy) {
+               schedule_delayed_work(&reg_timeout, 0);
+               return -ENODEV;
+       }
+
+       if (country_ie_request->intersect)
+               return -EINVAL;
 
+       reset_regdomains(false, rd);
+       return 0;
+}
 
 /*
  * Use this call to set the current regulatory domain. Conflicts with
@@ -2220,10 +2346,32 @@ int set_regdom(const struct ieee80211_regdomain *rd)
        struct regulatory_request *lr;
        int r;
 
+       if (!reg_is_valid_request(rd->alpha2)) {
+               kfree(rd);
+               return -EINVAL;
+       }
+
        lr = get_last_request();
 
        /* Note that this doesn't update the wiphys, this is done below */
-       r = __set_regdom(rd);
+       switch (lr->initiator) {
+       case NL80211_REGDOM_SET_BY_CORE:
+               r = reg_set_rd_core(rd);
+               break;
+       case NL80211_REGDOM_SET_BY_USER:
+               r = reg_set_rd_user(rd, lr);
+               break;
+       case NL80211_REGDOM_SET_BY_DRIVER:
+               r = reg_set_rd_driver(rd, lr);
+               break;
+       case NL80211_REGDOM_SET_BY_COUNTRY_IE:
+               r = reg_set_rd_country_ie(rd, lr);
+               break;
+       default:
+               WARN(1, "invalid initiator %d\n", lr->initiator);
+               return -EINVAL;
+       }
+
        if (r) {
                if (r == -EALREADY)
                        reg_set_request_processed();
index 9677e3c13da98da5b00f34e112b0562512b6fc65..cc4c2c0a67236cd2801f954e0a8e15dc4b5adea5 100644 (file)
@@ -18,8 +18,9 @@
 
 extern const struct ieee80211_regdomain __rcu *cfg80211_regdomain;
 
+bool reg_is_valid_request(const char *alpha2);
 bool is_world_regdom(const char *alpha2);
-bool reg_supported_dfs_region(u8 dfs_region);
+bool reg_supported_dfs_region(enum nl80211_dfs_regions dfs_region);
 
 int regulatory_hint_user(const char *alpha2,
                         enum nl80211_user_reg_hint_type user_reg_hint_type);
index ba5f0d6614d5d4cee4d08c609bb192dd501f0b34..f7aa7a72d9bc928aa7d24153d709e13634773b06 100644 (file)
@@ -1653,9 +1653,8 @@ TRACE_EVENT(rdev_cancel_remain_on_channel,
 
 TRACE_EVENT(rdev_mgmt_tx,
        TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
-                struct ieee80211_channel *chan, bool offchan,
-                unsigned int wait, bool no_cck, bool dont_wait_for_ack),
-       TP_ARGS(wiphy, wdev, chan, offchan, wait, no_cck, dont_wait_for_ack),
+                struct cfg80211_mgmt_tx_params *params),
+       TP_ARGS(wiphy, wdev, params),
        TP_STRUCT__entry(
                WIPHY_ENTRY
                WDEV_ENTRY
@@ -1668,11 +1667,11 @@ TRACE_EVENT(rdev_mgmt_tx,
        TP_fast_assign(
                WIPHY_ASSIGN;
                WDEV_ASSIGN;
-               CHAN_ASSIGN(chan);
-               __entry->offchan = offchan;
-               __entry->wait = wait;
-               __entry->no_cck = no_cck;
-               __entry->dont_wait_for_ack = dont_wait_for_ack;
+               CHAN_ASSIGN(params->chan);
+               __entry->offchan = params->offchan;
+               __entry->wait = params->wait;
+               __entry->no_cck = params->no_cck;
+               __entry->dont_wait_for_ack = params->dont_wait_for_ack;
        ),
        TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", " CHAN_PR_FMT ", offchan: %s,"
                  " wait: %u, no cck: %s, dont wait for ack: %s",
index 7622789d37501f10d29af54a2c778daa85d960bc..c8a8297cd4b8a1c6ae25de990e69e8db93c42142 100644 (file)
@@ -35,6 +35,8 @@
  *                                     response
  */
 
+#define pr_fmt(fmt) "X25: " fmt
+
 #include <linux/module.h>
 #include <linux/capability.h>
 #include <linux/errno.h>
@@ -1809,7 +1811,7 @@ static int __init x25_init(void)
        if (rc != 0)
                goto out_sock;
 
-       printk(KERN_INFO "X.25 for Linux Version 0.2\n");
+       pr_info("Linux Version 0.2\n");
 
        x25_register_sysctl();
        rc = x25_proc_init();
index a8a236338e61e8c0de3b1d72a00186314dafb487..39231237e1c3b3806dc956429195a59edf46bfd6 100644 (file)
@@ -17,6 +17,8 @@
  *      2000-09-04     Henner Eisen    Prevent freeing a dangling skb.
  */
 
+#define pr_fmt(fmt) "X25: " fmt
+
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
@@ -89,7 +91,7 @@ static int x25_receive_data(struct sk_buff *skb, struct x25_neigh *nb)
 */
 
        if (frametype != X25_CLEAR_CONFIRMATION)
-               printk(KERN_DEBUG "x25_receive_data(): unknown frame type %2x\n",frametype);
+               pr_debug("x25_receive_data(): unknown frame type %2x\n",frametype);
 
        return 0;
 }
@@ -114,7 +116,7 @@ int x25_lapb_receive_frame(struct sk_buff *skb, struct net_device *dev,
         */
        nb = x25_get_neigh(dev);
        if (!nb) {
-               printk(KERN_DEBUG "X.25: unknown neighbour - %s\n", dev->name);
+               pr_debug("unknown neighbour - %s\n", dev->name);
                goto drop;
        }
 
@@ -154,7 +156,7 @@ void x25_establish_link(struct x25_neigh *nb)
        switch (nb->dev->type) {
        case ARPHRD_X25:
                if ((skb = alloc_skb(1, GFP_ATOMIC)) == NULL) {
-                       printk(KERN_ERR "x25_dev: out of memory\n");
+                       pr_err("x25_dev: out of memory\n");
                        return;
                }
                ptr  = skb_put(skb, 1);
@@ -189,7 +191,7 @@ void x25_terminate_link(struct x25_neigh *nb)
 
        skb = alloc_skb(1, GFP_ATOMIC);
        if (!skb) {
-               printk(KERN_ERR "x25_dev: out of memory\n");
+               pr_err("x25_dev: out of memory\n");
                return;
        }
 
index b8253250d723314da1fd7b544289d49b38078c24..7ecd04c21360994627f7b9ec0231bf454510fd46 100644 (file)
@@ -21,6 +21,8 @@
  *                                     on response.
  */
 
+#define pr_fmt(fmt) "X25: " fmt
+
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/skbuff.h>
@@ -109,7 +111,7 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities,
                        case X25_MARKER:
                                break;
                        default:
-                               printk(KERN_DEBUG "X.25: unknown facility "
+                               pr_debug("unknown facility "
                                       "%02X, value %02X\n",
                                       p[0], p[1]);
                                break;
@@ -132,7 +134,7 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities,
                                *vc_fac_mask |= X25_MASK_WINDOW_SIZE;
                                break;
                        default:
-                               printk(KERN_DEBUG "X.25: unknown facility "
+                               pr_debug("unknown facility "
                                       "%02X, values %02X, %02X\n",
                                       p[0], p[1], p[2]);
                                break;
@@ -143,7 +145,7 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities,
                case X25_FAC_CLASS_C:
                        if (len < 4)
                                return -1;
-                       printk(KERN_DEBUG "X.25: unknown facility %02X, "
+                       pr_debug("unknown facility %02X, "
                               "values %02X, %02X, %02X\n",
                               p[0], p[1], p[2], p[3]);
                        p   += 4;
@@ -172,7 +174,7 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities,
                                *vc_fac_mask |= X25_MASK_CALLED_AE;
                                break;
                        default:
-                               printk(KERN_DEBUG "X.25: unknown facility %02X,"
+                               pr_debug("unknown facility %02X,"
                                        "length %d\n", p[0], p[1]);
                                break;
                        }
@@ -341,12 +343,12 @@ void x25_limit_facilities(struct x25_facilities *facilities,
 
        if (!nb->extended) {
                if (facilities->winsize_in  > 7) {
-                       printk(KERN_DEBUG "X.25: incoming winsize limited to 7\n");
+                       pr_debug("incoming winsize limited to 7\n");
                        facilities->winsize_in = 7;
                }
                if (facilities->winsize_out > 7) {
                        facilities->winsize_out = 7;
-                       printk( KERN_DEBUG "X.25: outgoing winsize limited to 7\n");
+                       pr_debug("outgoing winsize limited to 7\n");
                }
        }
 }
index c541b622ae16a78eee5fb4ebe4d284630dd6a427..cf561f1613e11613bb6cf8fd928e65748eab4def 100644 (file)
@@ -8,6 +8,9 @@
  *     History
  *     03-01-2007      Added forwarding for x.25       Andrew Hendry
  */
+
+#define pr_fmt(fmt) "X25: " fmt
+
 #include <linux/if_arp.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -51,7 +54,7 @@ int x25_forward_call(struct x25_address *dest_addr, struct x25_neigh *from,
        list_for_each(entry, &x25_forward_list) {
                x25_frwd = list_entry(entry, struct x25_forward, node);
                if (x25_frwd->lci == lci) {
-                       printk(KERN_WARNING "X.25: call request for lci which is already registered!, transmitting but not registering new pair\n");
+                       pr_warn("call request for lci which is already registered!, transmitting but not registering new pair\n");
                        same_lci = 1;
                }
        }
index a49cd4ec551a58f7a6b8bdcdaeb2da273687196a..d1b0dc79bb6f15874bd520c41d08f96bd9ff31bb 100644 (file)
@@ -23,6 +23,8 @@
  *                                       i-frames.
  */
 
+#define pr_fmt(fmt) "X25: " fmt
+
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
@@ -317,7 +319,7 @@ static int x25_state3_machine(struct sock *sk, struct sk_buff *skb, int frametyp
                        break;
 
                default:
-                       printk(KERN_WARNING "x25: unknown %02X in state 3\n", frametype);
+                       pr_warn("unknown %02X in state 3\n", frametype);
                        break;
        }
 
index 4acacf3c6617b7f21930885930bae094abfcea14..fd5ffb25873f35c981ec5b245d0670338dbcda12 100644 (file)
@@ -21,6 +21,8 @@
  *     2000-09-04      Henner Eisen      dev_hold() / dev_put() for x25_neigh.
  */
 
+#define pr_fmt(fmt) "X25: " fmt
+
 #include <linux/kernel.h>
 #include <linux/jiffies.h>
 #include <linux/timer.h>
@@ -93,13 +95,13 @@ void x25_link_control(struct sk_buff *skb, struct x25_neigh *nb,
                if (!pskb_may_pull(skb, X25_STD_MIN_LEN + 4))
                        break;
 
-               printk(KERN_WARNING "x25: diagnostic #%d - %02X %02X %02X\n",
+               pr_warn("diagnostic #%d - %02X %02X %02X\n",
                       skb->data[3], skb->data[4],
                       skb->data[5], skb->data[6]);
                break;
 
        default:
-               printk(KERN_WARNING "x25: received unknown %02X with LCI 000\n",
+               pr_warn("received unknown %02X with LCI 000\n",
                       frametype);
                break;
        }
index 5170d52bfd96e1e045422ae8e3cb607af2d2f843..6b5af65f491fb2e6112a0d0f1b510308e1b28c51 100644 (file)
@@ -23,6 +23,8 @@
  *                                             restriction on response.
  */
 
+#define pr_fmt(fmt) "X25: " fmt
+
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
@@ -148,7 +150,7 @@ void x25_write_internal(struct sock *sk, int frametype)
        case X25_RESET_CONFIRMATION:
                break;
        default:
-               printk(KERN_ERR "X.25: invalid frame type %02X\n", frametype);
+               pr_err("invalid frame type %02X\n", frametype);
                return;
        }
 
@@ -338,7 +340,7 @@ int x25_decode(struct sock *sk, struct sk_buff *skb, int *ns, int *nr, int *q,
                }
        }
 
-       printk(KERN_DEBUG "X.25: invalid PLP frame %02X %02X %02X\n",
+       pr_debug("invalid PLP frame %02X %02X %02X\n",
               frame[0], frame[1], frame[2]);
 
        return X25_ILLEGAL;
index 9a91f7431c411b706810a40bccc3167617c74aec..a7487f34e813c5ad6a3d3e4550a487c2a340ee65 100644 (file)
 #define XFRM_QUEUE_TMO_MAX ((unsigned)(60*HZ))
 #define XFRM_MAX_QUEUE_LEN     100
 
-DEFINE_MUTEX(xfrm_cfg_mutex);
-EXPORT_SYMBOL(xfrm_cfg_mutex);
-
-static DEFINE_SPINLOCK(xfrm_policy_sk_bundle_lock);
 static struct dst_entry *xfrm_policy_sk_bundles;
-static DEFINE_RWLOCK(xfrm_policy_lock);
 
 static DEFINE_SPINLOCK(xfrm_policy_afinfo_lock);
 static struct xfrm_policy_afinfo __rcu *xfrm_policy_afinfo[NPROTO]
@@ -438,7 +433,7 @@ static void xfrm_bydst_resize(struct net *net, int dir)
        if (!ndst)
                return;
 
-       write_lock_bh(&xfrm_policy_lock);
+       write_lock_bh(&net->xfrm.xfrm_policy_lock);
 
        for (i = hmask; i >= 0; i--)
                xfrm_dst_hash_transfer(odst + i, ndst, nhashmask);
@@ -446,7 +441,7 @@ static void xfrm_bydst_resize(struct net *net, int dir)
        net->xfrm.policy_bydst[dir].table = ndst;
        net->xfrm.policy_bydst[dir].hmask = nhashmask;
 
-       write_unlock_bh(&xfrm_policy_lock);
+       write_unlock_bh(&net->xfrm.xfrm_policy_lock);
 
        xfrm_hash_free(odst, (hmask + 1) * sizeof(struct hlist_head));
 }
@@ -463,7 +458,7 @@ static void xfrm_byidx_resize(struct net *net, int total)
        if (!nidx)
                return;
 
-       write_lock_bh(&xfrm_policy_lock);
+       write_lock_bh(&net->xfrm.xfrm_policy_lock);
 
        for (i = hmask; i >= 0; i--)
                xfrm_idx_hash_transfer(oidx + i, nidx, nhashmask);
@@ -471,7 +466,7 @@ static void xfrm_byidx_resize(struct net *net, int total)
        net->xfrm.policy_byidx = nidx;
        net->xfrm.policy_idx_hmask = nhashmask;
 
-       write_unlock_bh(&xfrm_policy_lock);
+       write_unlock_bh(&net->xfrm.xfrm_policy_lock);
 
        xfrm_hash_free(oidx, (hmask + 1) * sizeof(struct hlist_head));
 }
@@ -504,7 +499,7 @@ static inline int xfrm_byidx_should_resize(struct net *net, int total)
 
 void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si)
 {
-       read_lock_bh(&xfrm_policy_lock);
+       read_lock_bh(&net->xfrm.xfrm_policy_lock);
        si->incnt = net->xfrm.policy_count[XFRM_POLICY_IN];
        si->outcnt = net->xfrm.policy_count[XFRM_POLICY_OUT];
        si->fwdcnt = net->xfrm.policy_count[XFRM_POLICY_FWD];
@@ -513,7 +508,7 @@ void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si)
        si->fwdscnt = net->xfrm.policy_count[XFRM_POLICY_FWD+XFRM_POLICY_MAX];
        si->spdhcnt = net->xfrm.policy_idx_hmask;
        si->spdhmcnt = xfrm_policy_hashmax;
-       read_unlock_bh(&xfrm_policy_lock);
+       read_unlock_bh(&net->xfrm.xfrm_policy_lock);
 }
 EXPORT_SYMBOL(xfrm_spd_getinfo);
 
@@ -538,7 +533,7 @@ static void xfrm_hash_resize(struct work_struct *work)
 
 /* Generate new index... KAME seems to generate them ordered by cost
  * of an absolute inpredictability of ordering of rules. This will not pass. */
-static u32 xfrm_gen_index(struct net *net, int dir)
+static u32 xfrm_gen_index(struct net *net, int dir, u32 index)
 {
        static u32 idx_generator;
 
@@ -548,8 +543,14 @@ static u32 xfrm_gen_index(struct net *net, int dir)
                u32 idx;
                int found;
 
-               idx = (idx_generator | dir);
-               idx_generator += 8;
+               if (!index) {
+                       idx = (idx_generator | dir);
+                       idx_generator += 8;
+               } else {
+                       idx = index;
+                       index = 0;
+               }
+
                if (idx == 0)
                        idx = 8;
                list = net->xfrm.policy_byidx + idx_hash(net, idx);
@@ -630,7 +631,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
        struct hlist_head *chain;
        struct hlist_node *newpos;
 
-       write_lock_bh(&xfrm_policy_lock);
+       write_lock_bh(&net->xfrm.xfrm_policy_lock);
        chain = policy_hash_bysel(net, &policy->selector, policy->family, dir);
        delpol = NULL;
        newpos = NULL;
@@ -641,7 +642,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
                    xfrm_sec_ctx_match(pol->security, policy->security) &&
                    !WARN_ON(delpol)) {
                        if (excl) {
-                               write_unlock_bh(&xfrm_policy_lock);
+                               write_unlock_bh(&net->xfrm.xfrm_policy_lock);
                                return -EEXIST;
                        }
                        delpol = pol;
@@ -672,14 +673,14 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
                xfrm_policy_requeue(delpol, policy);
                __xfrm_policy_unlink(delpol, dir);
        }
-       policy->index = delpol ? delpol->index : xfrm_gen_index(net, dir);
+       policy->index = delpol ? delpol->index : xfrm_gen_index(net, dir, policy->index);
        hlist_add_head(&policy->byidx, net->xfrm.policy_byidx+idx_hash(net, policy->index));
        policy->curlft.add_time = get_seconds();
        policy->curlft.use_time = 0;
        if (!mod_timer(&policy->timer, jiffies + HZ))
                xfrm_pol_hold(policy);
        list_add(&policy->walk.all, &net->xfrm.policy_all);
-       write_unlock_bh(&xfrm_policy_lock);
+       write_unlock_bh(&net->xfrm.xfrm_policy_lock);
 
        if (delpol)
                xfrm_policy_kill(delpol);
@@ -699,7 +700,7 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark, u8 type,
        struct hlist_head *chain;
 
        *err = 0;
-       write_lock_bh(&xfrm_policy_lock);
+       write_lock_bh(&net->xfrm.xfrm_policy_lock);
        chain = policy_hash_bysel(net, sel, sel->family, dir);
        ret = NULL;
        hlist_for_each_entry(pol, chain, bydst) {
@@ -712,7 +713,7 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark, u8 type,
                                *err = security_xfrm_policy_delete(
                                                                pol->security);
                                if (*err) {
-                                       write_unlock_bh(&xfrm_policy_lock);
+                                       write_unlock_bh(&net->xfrm.xfrm_policy_lock);
                                        return pol;
                                }
                                __xfrm_policy_unlink(pol, dir);
@@ -721,7 +722,7 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark, u8 type,
                        break;
                }
        }
-       write_unlock_bh(&xfrm_policy_lock);
+       write_unlock_bh(&net->xfrm.xfrm_policy_lock);
 
        if (ret && delete)
                xfrm_policy_kill(ret);
@@ -740,7 +741,7 @@ struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8 type,
                return NULL;
 
        *err = 0;
-       write_lock_bh(&xfrm_policy_lock);
+       write_lock_bh(&net->xfrm.xfrm_policy_lock);
        chain = net->xfrm.policy_byidx + idx_hash(net, id);
        ret = NULL;
        hlist_for_each_entry(pol, chain, byidx) {
@@ -751,7 +752,7 @@ struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8 type,
                                *err = security_xfrm_policy_delete(
                                                                pol->security);
                                if (*err) {
-                                       write_unlock_bh(&xfrm_policy_lock);
+                                       write_unlock_bh(&net->xfrm.xfrm_policy_lock);
                                        return pol;
                                }
                                __xfrm_policy_unlink(pol, dir);
@@ -760,7 +761,7 @@ struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8 type,
                        break;
                }
        }
-       write_unlock_bh(&xfrm_policy_lock);
+       write_unlock_bh(&net->xfrm.xfrm_policy_lock);
 
        if (ret && delete)
                xfrm_policy_kill(ret);
@@ -823,7 +824,7 @@ int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info)
 {
        int dir, err = 0, cnt = 0;
 
-       write_lock_bh(&xfrm_policy_lock);
+       write_lock_bh(&net->xfrm.xfrm_policy_lock);
 
        err = xfrm_policy_flush_secctx_check(net, type, audit_info);
        if (err)
@@ -839,7 +840,7 @@ int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info)
                        if (pol->type != type)
                                continue;
                        __xfrm_policy_unlink(pol, dir);
-                       write_unlock_bh(&xfrm_policy_lock);
+                       write_unlock_bh(&net->xfrm.xfrm_policy_lock);
                        cnt++;
 
                        xfrm_audit_policy_delete(pol, 1, audit_info->loginuid,
@@ -848,7 +849,7 @@ int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info)
 
                        xfrm_policy_kill(pol);
 
-                       write_lock_bh(&xfrm_policy_lock);
+                       write_lock_bh(&net->xfrm.xfrm_policy_lock);
                        goto again1;
                }
 
@@ -860,7 +861,7 @@ int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info)
                                if (pol->type != type)
                                        continue;
                                __xfrm_policy_unlink(pol, dir);
-                               write_unlock_bh(&xfrm_policy_lock);
+                               write_unlock_bh(&net->xfrm.xfrm_policy_lock);
                                cnt++;
 
                                xfrm_audit_policy_delete(pol, 1,
@@ -869,7 +870,7 @@ int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info)
                                                         audit_info->secid);
                                xfrm_policy_kill(pol);
 
-                               write_lock_bh(&xfrm_policy_lock);
+                               write_lock_bh(&net->xfrm.xfrm_policy_lock);
                                goto again2;
                        }
                }
@@ -878,7 +879,7 @@ int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info)
        if (!cnt)
                err = -ESRCH;
 out:
-       write_unlock_bh(&xfrm_policy_lock);
+       write_unlock_bh(&net->xfrm.xfrm_policy_lock);
        return err;
 }
 EXPORT_SYMBOL(xfrm_policy_flush);
@@ -898,7 +899,7 @@ int xfrm_policy_walk(struct net *net, struct xfrm_policy_walk *walk,
        if (list_empty(&walk->walk.all) && walk->seq != 0)
                return 0;
 
-       write_lock_bh(&xfrm_policy_lock);
+       write_lock_bh(&net->xfrm.xfrm_policy_lock);
        if (list_empty(&walk->walk.all))
                x = list_first_entry(&net->xfrm.policy_all, struct xfrm_policy_walk_entry, all);
        else
@@ -924,7 +925,7 @@ int xfrm_policy_walk(struct net *net, struct xfrm_policy_walk *walk,
        }
        list_del_init(&walk->walk.all);
 out:
-       write_unlock_bh(&xfrm_policy_lock);
+       write_unlock_bh(&net->xfrm.xfrm_policy_lock);
        return error;
 }
 EXPORT_SYMBOL(xfrm_policy_walk);
@@ -938,14 +939,14 @@ void xfrm_policy_walk_init(struct xfrm_policy_walk *walk, u8 type)
 }
 EXPORT_SYMBOL(xfrm_policy_walk_init);
 
-void xfrm_policy_walk_done(struct xfrm_policy_walk *walk)
+void xfrm_policy_walk_done(struct xfrm_policy_walk *walk, struct net *net)
 {
        if (list_empty(&walk->walk.all))
                return;
 
-       write_lock_bh(&xfrm_policy_lock);
+       write_lock_bh(&net->xfrm.xfrm_policy_lock); /*FIXME where is net? */
        list_del(&walk->walk.all);
-       write_unlock_bh(&xfrm_policy_lock);
+       write_unlock_bh(&net->xfrm.xfrm_policy_lock);
 }
 EXPORT_SYMBOL(xfrm_policy_walk_done);
 
@@ -990,7 +991,7 @@ static struct xfrm_policy *xfrm_policy_lookup_bytype(struct net *net, u8 type,
        if (unlikely(!daddr || !saddr))
                return NULL;
 
-       read_lock_bh(&xfrm_policy_lock);
+       read_lock_bh(&net->xfrm.xfrm_policy_lock);
        chain = policy_hash_direct(net, daddr, saddr, family, dir);
        ret = NULL;
        hlist_for_each_entry(pol, chain, bydst) {
@@ -1026,7 +1027,7 @@ static struct xfrm_policy *xfrm_policy_lookup_bytype(struct net *net, u8 type,
        if (ret)
                xfrm_pol_hold(ret);
 fail:
-       read_unlock_bh(&xfrm_policy_lock);
+       read_unlock_bh(&net->xfrm.xfrm_policy_lock);
 
        return ret;
 }
@@ -1103,8 +1104,9 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir,
                                                 const struct flowi *fl)
 {
        struct xfrm_policy *pol;
+       struct net *net = sock_net(sk);
 
-       read_lock_bh(&xfrm_policy_lock);
+       read_lock_bh(&net->xfrm.xfrm_policy_lock);
        if ((pol = sk->sk_policy[dir]) != NULL) {
                bool match = xfrm_selector_match(&pol->selector, fl,
                                                 sk->sk_family);
@@ -1128,7 +1130,7 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir,
                        pol = NULL;
        }
 out:
-       read_unlock_bh(&xfrm_policy_lock);
+       read_unlock_bh(&net->xfrm.xfrm_policy_lock);
        return pol;
 }
 
@@ -1166,9 +1168,11 @@ static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol,
 
 int xfrm_policy_delete(struct xfrm_policy *pol, int dir)
 {
-       write_lock_bh(&xfrm_policy_lock);
+       struct net *net = xp_net(pol);
+
+       write_lock_bh(&net->xfrm.xfrm_policy_lock);
        pol = __xfrm_policy_unlink(pol, dir);
-       write_unlock_bh(&xfrm_policy_lock);
+       write_unlock_bh(&net->xfrm.xfrm_policy_lock);
        if (pol) {
                xfrm_policy_kill(pol);
                return 0;
@@ -1187,12 +1191,12 @@ int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol)
                return -EINVAL;
 #endif
 
-       write_lock_bh(&xfrm_policy_lock);
+       write_lock_bh(&net->xfrm.xfrm_policy_lock);
        old_pol = sk->sk_policy[dir];
        sk->sk_policy[dir] = pol;
        if (pol) {
                pol->curlft.add_time = get_seconds();
-               pol->index = xfrm_gen_index(net, XFRM_POLICY_MAX+dir);
+               pol->index = xfrm_gen_index(net, XFRM_POLICY_MAX+dir, 0);
                __xfrm_policy_link(pol, XFRM_POLICY_MAX+dir);
        }
        if (old_pol) {
@@ -1204,7 +1208,7 @@ int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol)
                 */
                __xfrm_policy_unlink(old_pol, XFRM_POLICY_MAX+dir);
        }
-       write_unlock_bh(&xfrm_policy_lock);
+       write_unlock_bh(&net->xfrm.xfrm_policy_lock);
 
        if (old_pol) {
                xfrm_policy_kill(old_pol);
@@ -1215,6 +1219,7 @@ int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol)
 static struct xfrm_policy *clone_policy(const struct xfrm_policy *old, int dir)
 {
        struct xfrm_policy *newp = xfrm_policy_alloc(xp_net(old), GFP_ATOMIC);
+       struct net *net = xp_net(old);
 
        if (newp) {
                newp->selector = old->selector;
@@ -1233,9 +1238,9 @@ static struct xfrm_policy *clone_policy(const struct xfrm_policy *old, int dir)
                newp->type = old->type;
                memcpy(newp->xfrm_vec, old->xfrm_vec,
                       newp->xfrm_nr*sizeof(struct xfrm_tmpl));
-               write_lock_bh(&xfrm_policy_lock);
+               write_lock_bh(&net->xfrm.xfrm_policy_lock);
                __xfrm_policy_link(newp, XFRM_POLICY_MAX+dir);
-               write_unlock_bh(&xfrm_policy_lock);
+               write_unlock_bh(&net->xfrm.xfrm_policy_lock);
                xfrm_pol_put(newp);
        }
        return newp;
@@ -1896,8 +1901,7 @@ static struct xfrm_dst *xfrm_create_dummy_bundle(struct net *net,
        if (IS_ERR(xdst))
                return xdst;
 
-       if (net->xfrm.sysctl_larval_drop || num_xfrms <= 0 ||
-           (fl->flowi_flags & FLOWI_FLAG_CAN_SLEEP))
+       if (net->xfrm.sysctl_larval_drop || num_xfrms <= 0)
                return xdst;
 
        dst1 = &xdst->u.dst;
@@ -2072,7 +2076,6 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
        u8 dir = policy_to_flow_dir(XFRM_POLICY_OUT);
        int i, err, num_pols, num_xfrms = 0, drop_pols = 0;
 
-restart:
        dst = NULL;
        xdst = NULL;
        route = NULL;
@@ -2106,10 +2109,10 @@ restart:
 
                        dst_hold(&xdst->u.dst);
 
-                       spin_lock_bh(&xfrm_policy_sk_bundle_lock);
+                       spin_lock_bh(&net->xfrm.xfrm_policy_sk_bundle_lock);
                        xdst->u.dst.next = xfrm_policy_sk_bundles;
                        xfrm_policy_sk_bundles = &xdst->u.dst;
-                       spin_unlock_bh(&xfrm_policy_sk_bundle_lock);
+                       spin_unlock_bh(&net->xfrm.xfrm_policy_sk_bundle_lock);
 
                        route = xdst->route;
                }
@@ -2152,23 +2155,8 @@ restart:
 
                        return make_blackhole(net, family, dst_orig);
                }
-               if (fl->flowi_flags & FLOWI_FLAG_CAN_SLEEP) {
-                       DECLARE_WAITQUEUE(wait, current);
-
-                       add_wait_queue(&net->xfrm.km_waitq, &wait);
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       schedule();
-                       set_current_state(TASK_RUNNING);
-                       remove_wait_queue(&net->xfrm.km_waitq, &wait);
 
-                       if (!signal_pending(current)) {
-                               dst_release(dst);
-                               goto restart;
-                       }
-
-                       err = -ERESTART;
-               } else
-                       err = -EAGAIN;
+               err = -EAGAIN;
 
                XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES);
                goto error;
@@ -2434,7 +2422,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
                }
                xfrm_nr = ti;
                if (npols > 1) {
-                       xfrm_tmpl_sort(stp, tpp, xfrm_nr, family);
+                       xfrm_tmpl_sort(stp, tpp, xfrm_nr, family, net);
                        tpp = stp;
                }
 
@@ -2563,10 +2551,10 @@ static void __xfrm_garbage_collect(struct net *net)
 {
        struct dst_entry *head, *next;
 
-       spin_lock_bh(&xfrm_policy_sk_bundle_lock);
+       spin_lock_bh(&net->xfrm.xfrm_policy_sk_bundle_lock);
        head = xfrm_policy_sk_bundles;
        xfrm_policy_sk_bundles = NULL;
-       spin_unlock_bh(&xfrm_policy_sk_bundle_lock);
+       spin_unlock_bh(&net->xfrm.xfrm_policy_sk_bundle_lock);
 
        while (head) {
                next = head->next;
@@ -2950,6 +2938,13 @@ static int __net_init xfrm_net_init(struct net *net)
        rv = xfrm_sysctl_init(net);
        if (rv < 0)
                goto out_sysctl;
+
+       /* Initialize the per-net locks here */
+       spin_lock_init(&net->xfrm.xfrm_state_lock);
+       rwlock_init(&net->xfrm.xfrm_policy_lock);
+       spin_lock_init(&net->xfrm.xfrm_policy_sk_bundle_lock);
+       mutex_init(&net->xfrm.xfrm_cfg_mutex);
+
        return 0;
 
 out_sysctl:
@@ -3070,14 +3065,14 @@ static bool xfrm_migrate_selector_match(const struct xfrm_selector *sel_cmp,
 }
 
 static struct xfrm_policy * xfrm_migrate_policy_find(const struct xfrm_selector *sel,
-                                                    u8 dir, u8 type)
+                                                    u8 dir, u8 type, struct net *net)
 {
        struct xfrm_policy *pol, *ret = NULL;
        struct hlist_head *chain;
        u32 priority = ~0U;
 
-       read_lock_bh(&xfrm_policy_lock);
-       chain = policy_hash_direct(&init_net, &sel->daddr, &sel->saddr, sel->family, dir);
+       read_lock_bh(&net->xfrm.xfrm_policy_lock); /*FIXME*/
+       chain = policy_hash_direct(net, &sel->daddr, &sel->saddr, sel->family, dir);
        hlist_for_each_entry(pol, chain, bydst) {
                if (xfrm_migrate_selector_match(sel, &pol->selector) &&
                    pol->type == type) {
@@ -3086,7 +3081,7 @@ static struct xfrm_policy * xfrm_migrate_policy_find(const struct xfrm_selector
                        break;
                }
        }
-       chain = &init_net.xfrm.policy_inexact[dir];
+       chain = &net->xfrm.policy_inexact[dir];
        hlist_for_each_entry(pol, chain, bydst) {
                if (xfrm_migrate_selector_match(sel, &pol->selector) &&
                    pol->type == type &&
@@ -3099,7 +3094,7 @@ static struct xfrm_policy * xfrm_migrate_policy_find(const struct xfrm_selector
        if (ret)
                xfrm_pol_hold(ret);
 
-       read_unlock_bh(&xfrm_policy_lock);
+       read_unlock_bh(&net->xfrm.xfrm_policy_lock);
 
        return ret;
 }
@@ -3210,7 +3205,7 @@ static int xfrm_migrate_check(const struct xfrm_migrate *m, int num_migrate)
 
 int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
                 struct xfrm_migrate *m, int num_migrate,
-                struct xfrm_kmaddress *k)
+                struct xfrm_kmaddress *k, struct net *net)
 {
        int i, err, nx_cur = 0, nx_new = 0;
        struct xfrm_policy *pol = NULL;
@@ -3223,14 +3218,14 @@ int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
                goto out;
 
        /* Stage 1 - find policy */
-       if ((pol = xfrm_migrate_policy_find(sel, dir, type)) == NULL) {
+       if ((pol = xfrm_migrate_policy_find(sel, dir, type, net)) == NULL) {
                err = -ENOENT;
                goto out;
        }
 
        /* Stage 2 - find and update state(s) */
        for (i = 0, mp = m; i < num_migrate; i++, mp++) {
-               if ((x = xfrm_migrate_state_find(mp))) {
+               if ((x = xfrm_migrate_state_find(mp, net))) {
                        x_cur[nx_cur] = x;
                        nx_cur++;
                        if ((xc = xfrm_state_migrate(x, mp))) {
index 68c2f357a18389d9debc35401afe1295c4341959..e845066547c48de0b8a9efec0a3dcb4469a78bac 100644 (file)
@@ -35,8 +35,6 @@
       destination/tunnel endpoint. (output)
  */
 
-static DEFINE_SPINLOCK(xfrm_state_lock);
-
 static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024;
 
 static inline unsigned int xfrm_dst_hash(struct net *net,
@@ -127,7 +125,7 @@ static void xfrm_hash_resize(struct work_struct *work)
                goto out_unlock;
        }
 
-       spin_lock_bh(&xfrm_state_lock);
+       spin_lock_bh(&net->xfrm.xfrm_state_lock);
 
        nhashmask = (nsize / sizeof(struct hlist_head)) - 1U;
        for (i = net->xfrm.state_hmask; i >= 0; i--)
@@ -144,7 +142,7 @@ static void xfrm_hash_resize(struct work_struct *work)
        net->xfrm.state_byspi = nspi;
        net->xfrm.state_hmask = nhashmask;
 
-       spin_unlock_bh(&xfrm_state_lock);
+       spin_unlock_bh(&net->xfrm.xfrm_state_lock);
 
        osize = (ohashmask + 1) * sizeof(struct hlist_head);
        xfrm_hash_free(odst, osize);
@@ -374,8 +372,6 @@ static void xfrm_state_gc_task(struct work_struct *work)
 
        hlist_for_each_entry_safe(x, tmp, &gc_list, gclist)
                xfrm_state_gc_destroy(x);
-
-       wake_up(&net->xfrm.km_waitq);
 }
 
 static inline unsigned long make_jiffies(long secs)
@@ -390,7 +386,6 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer * me)
 {
        struct tasklet_hrtimer *thr = container_of(me, struct tasklet_hrtimer, timer);
        struct xfrm_state *x = container_of(thr, struct xfrm_state, mtimer);
-       struct net *net = xs_net(x);
        unsigned long now = get_seconds();
        long next = LONG_MAX;
        int warn = 0;
@@ -460,12 +455,8 @@ resched:
        goto out;
 
 expired:
-       if (x->km.state == XFRM_STATE_ACQ && x->id.spi == 0) {
+       if (x->km.state == XFRM_STATE_ACQ && x->id.spi == 0)
                x->km.state = XFRM_STATE_EXPIRED;
-               wake_up(&net->xfrm.km_waitq);
-               next = 2;
-               goto resched;
-       }
 
        err = __xfrm_state_delete(x);
        if (!err)
@@ -535,14 +526,14 @@ int __xfrm_state_delete(struct xfrm_state *x)
 
        if (x->km.state != XFRM_STATE_DEAD) {
                x->km.state = XFRM_STATE_DEAD;
-               spin_lock(&xfrm_state_lock);
+               spin_lock(&net->xfrm.xfrm_state_lock);
                list_del(&x->km.all);
                hlist_del(&x->bydst);
                hlist_del(&x->bysrc);
                if (x->id.spi)
                        hlist_del(&x->byspi);
                net->xfrm.state_num--;
-               spin_unlock(&xfrm_state_lock);
+               spin_unlock(&net->xfrm.xfrm_state_lock);
 
                /* All xfrm_state objects are created by xfrm_state_alloc.
                 * The xfrm_state_alloc call gives a reference, and that
@@ -603,7 +594,7 @@ int xfrm_state_flush(struct net *net, u8 proto, struct xfrm_audit *audit_info)
 {
        int i, err = 0, cnt = 0;
 
-       spin_lock_bh(&xfrm_state_lock);
+       spin_lock_bh(&net->xfrm.xfrm_state_lock);
        err = xfrm_state_flush_secctx_check(net, proto, audit_info);
        if (err)
                goto out;
@@ -616,7 +607,7 @@ restart:
                        if (!xfrm_state_kern(x) &&
                            xfrm_id_proto_match(x->id.proto, proto)) {
                                xfrm_state_hold(x);
-                               spin_unlock_bh(&xfrm_state_lock);
+                               spin_unlock_bh(&net->xfrm.xfrm_state_lock);
 
                                err = xfrm_state_delete(x);
                                xfrm_audit_state_delete(x, err ? 0 : 1,
@@ -627,7 +618,7 @@ restart:
                                if (!err)
                                        cnt++;
 
-                               spin_lock_bh(&xfrm_state_lock);
+                               spin_lock_bh(&net->xfrm.xfrm_state_lock);
                                goto restart;
                        }
                }
@@ -636,19 +627,18 @@ restart:
                err = 0;
 
 out:
-       spin_unlock_bh(&xfrm_state_lock);
-       wake_up(&net->xfrm.km_waitq);
+       spin_unlock_bh(&net->xfrm.xfrm_state_lock);
        return err;
 }
 EXPORT_SYMBOL(xfrm_state_flush);
 
 void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si)
 {
-       spin_lock_bh(&xfrm_state_lock);
+       spin_lock_bh(&net->xfrm.xfrm_state_lock);
        si->sadcnt = net->xfrm.state_num;
        si->sadhcnt = net->xfrm.state_hmask;
        si->sadhmcnt = xfrm_state_hashmax;
-       spin_unlock_bh(&xfrm_state_lock);
+       spin_unlock_bh(&net->xfrm.xfrm_state_lock);
 }
 EXPORT_SYMBOL(xfrm_sad_getinfo);
 
@@ -801,7 +791,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
 
        to_put = NULL;
 
-       spin_lock_bh(&xfrm_state_lock);
+       spin_lock_bh(&net->xfrm.xfrm_state_lock);
        h = xfrm_dst_hash(net, daddr, saddr, tmpl->reqid, encap_family);
        hlist_for_each_entry(x, net->xfrm.state_bydst+h, bydst) {
                if (x->props.family == encap_family &&
@@ -886,7 +876,7 @@ out:
                xfrm_state_hold(x);
        else
                *err = acquire_in_progress ? -EAGAIN : error;
-       spin_unlock_bh(&xfrm_state_lock);
+       spin_unlock_bh(&net->xfrm.xfrm_state_lock);
        if (to_put)
                xfrm_state_put(to_put);
        return x;
@@ -900,7 +890,7 @@ xfrm_stateonly_find(struct net *net, u32 mark,
        unsigned int h;
        struct xfrm_state *rx = NULL, *x = NULL;
 
-       spin_lock(&xfrm_state_lock);
+       spin_lock(&net->xfrm.xfrm_state_lock);
        h = xfrm_dst_hash(net, daddr, saddr, reqid, family);
        hlist_for_each_entry(x, net->xfrm.state_bydst+h, bydst) {
                if (x->props.family == family &&
@@ -918,7 +908,7 @@ xfrm_stateonly_find(struct net *net, u32 mark,
 
        if (rx)
                xfrm_state_hold(rx);
-       spin_unlock(&xfrm_state_lock);
+       spin_unlock(&net->xfrm.xfrm_state_lock);
 
 
        return rx;
@@ -950,14 +940,12 @@ static void __xfrm_state_insert(struct xfrm_state *x)
        if (x->replay_maxage)
                mod_timer(&x->rtimer, jiffies + x->replay_maxage);
 
-       wake_up(&net->xfrm.km_waitq);
-
        net->xfrm.state_num++;
 
        xfrm_hash_grow_check(net, x->bydst.next != NULL);
 }
 
-/* xfrm_state_lock is held */
+/* net->xfrm.xfrm_state_lock is held */
 static void __xfrm_state_bump_genids(struct xfrm_state *xnew)
 {
        struct net *net = xs_net(xnew);
@@ -980,14 +968,16 @@ static void __xfrm_state_bump_genids(struct xfrm_state *xnew)
 
 void xfrm_state_insert(struct xfrm_state *x)
 {
-       spin_lock_bh(&xfrm_state_lock);
+       struct net *net = xs_net(x);
+
+       spin_lock_bh(&net->xfrm.xfrm_state_lock);
        __xfrm_state_bump_genids(x);
        __xfrm_state_insert(x);
-       spin_unlock_bh(&xfrm_state_lock);
+       spin_unlock_bh(&net->xfrm.xfrm_state_lock);
 }
 EXPORT_SYMBOL(xfrm_state_insert);
 
-/* xfrm_state_lock is held */
+/* net->xfrm.xfrm_state_lock is held */
 static struct xfrm_state *__find_acq_core(struct net *net,
                                          const struct xfrm_mark *m,
                                          unsigned short family, u8 mode,
@@ -1079,7 +1069,7 @@ int xfrm_state_add(struct xfrm_state *x)
 
        to_put = NULL;
 
-       spin_lock_bh(&xfrm_state_lock);
+       spin_lock_bh(&net->xfrm.xfrm_state_lock);
 
        x1 = __xfrm_state_locate(x, use_spi, family);
        if (x1) {
@@ -1108,7 +1098,7 @@ int xfrm_state_add(struct xfrm_state *x)
        err = 0;
 
 out:
-       spin_unlock_bh(&xfrm_state_lock);
+       spin_unlock_bh(&net->xfrm.xfrm_state_lock);
 
        if (x1) {
                xfrm_state_delete(x1);
@@ -1203,16 +1193,16 @@ out:
        return NULL;
 }
 
-/* xfrm_state_lock is held */
-struct xfrm_state * xfrm_migrate_state_find(struct xfrm_migrate *m)
+/* net->xfrm.xfrm_state_lock is held */
+struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net)
 {
        unsigned int h;
        struct xfrm_state *x;
 
        if (m->reqid) {
-               h = xfrm_dst_hash(&init_net, &m->old_daddr, &m->old_saddr,
+               h = xfrm_dst_hash(net, &m->old_daddr, &m->old_saddr,
                                  m->reqid, m->old_family);
-               hlist_for_each_entry(x, init_net.xfrm.state_bydst+h, bydst) {
+               hlist_for_each_entry(x, net->xfrm.state_bydst+h, bydst) {
                        if (x->props.mode != m->mode ||
                            x->id.proto != m->proto)
                                continue;
@@ -1227,9 +1217,9 @@ struct xfrm_state * xfrm_migrate_state_find(struct xfrm_migrate *m)
                        return x;
                }
        } else {
-               h = xfrm_src_hash(&init_net, &m->old_daddr, &m->old_saddr,
+               h = xfrm_src_hash(net, &m->old_daddr, &m->old_saddr,
                                  m->old_family);
-               hlist_for_each_entry(x, init_net.xfrm.state_bysrc+h, bysrc) {
+               hlist_for_each_entry(x, net->xfrm.state_bysrc+h, bysrc) {
                        if (x->props.mode != m->mode ||
                            x->id.proto != m->proto)
                                continue;
@@ -1283,10 +1273,11 @@ int xfrm_state_update(struct xfrm_state *x)
        struct xfrm_state *x1, *to_put;
        int err;
        int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY);
+       struct net *net = xs_net(x);
 
        to_put = NULL;
 
-       spin_lock_bh(&xfrm_state_lock);
+       spin_lock_bh(&net->xfrm.xfrm_state_lock);
        x1 = __xfrm_state_locate(x, use_spi, x->props.family);
 
        err = -ESRCH;
@@ -1306,7 +1297,7 @@ int xfrm_state_update(struct xfrm_state *x)
        err = 0;
 
 out:
-       spin_unlock_bh(&xfrm_state_lock);
+       spin_unlock_bh(&net->xfrm.xfrm_state_lock);
 
        if (to_put)
                xfrm_state_put(to_put);
@@ -1377,9 +1368,9 @@ xfrm_state_lookup(struct net *net, u32 mark, const xfrm_address_t *daddr, __be32
 {
        struct xfrm_state *x;
 
-       spin_lock_bh(&xfrm_state_lock);
+       spin_lock_bh(&net->xfrm.xfrm_state_lock);
        x = __xfrm_state_lookup(net, mark, daddr, spi, proto, family);
-       spin_unlock_bh(&xfrm_state_lock);
+       spin_unlock_bh(&net->xfrm.xfrm_state_lock);
        return x;
 }
 EXPORT_SYMBOL(xfrm_state_lookup);
@@ -1391,9 +1382,9 @@ xfrm_state_lookup_byaddr(struct net *net, u32 mark,
 {
        struct xfrm_state *x;
 
-       spin_lock_bh(&xfrm_state_lock);
+       spin_lock_bh(&net->xfrm.xfrm_state_lock);
        x = __xfrm_state_lookup_byaddr(net, mark, daddr, saddr, proto, family);
-       spin_unlock_bh(&xfrm_state_lock);
+       spin_unlock_bh(&net->xfrm.xfrm_state_lock);
        return x;
 }
 EXPORT_SYMBOL(xfrm_state_lookup_byaddr);
@@ -1405,9 +1396,9 @@ xfrm_find_acq(struct net *net, const struct xfrm_mark *mark, u8 mode, u32 reqid,
 {
        struct xfrm_state *x;
 
-       spin_lock_bh(&xfrm_state_lock);
+       spin_lock_bh(&net->xfrm.xfrm_state_lock);
        x = __find_acq_core(net, mark, family, mode, reqid, proto, daddr, saddr, create);
-       spin_unlock_bh(&xfrm_state_lock);
+       spin_unlock_bh(&net->xfrm.xfrm_state_lock);
 
        return x;
 }
@@ -1416,17 +1407,17 @@ EXPORT_SYMBOL(xfrm_find_acq);
 #ifdef CONFIG_XFRM_SUB_POLICY
 int
 xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n,
-              unsigned short family)
+              unsigned short family, struct net *net)
 {
        int err = 0;
        struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
        if (!afinfo)
                return -EAFNOSUPPORT;
 
-       spin_lock_bh(&xfrm_state_lock);
+       spin_lock_bh(&net->xfrm.xfrm_state_lock); /*FIXME*/
        if (afinfo->tmpl_sort)
                err = afinfo->tmpl_sort(dst, src, n);
-       spin_unlock_bh(&xfrm_state_lock);
+       spin_unlock_bh(&net->xfrm.xfrm_state_lock);
        xfrm_state_put_afinfo(afinfo);
        return err;
 }
@@ -1438,13 +1429,15 @@ xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n,
 {
        int err = 0;
        struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
+       struct net *net = xs_net(*dst);
+
        if (!afinfo)
                return -EAFNOSUPPORT;
 
-       spin_lock_bh(&xfrm_state_lock);
+       spin_lock_bh(&net->xfrm.xfrm_state_lock);
        if (afinfo->state_sort)
                err = afinfo->state_sort(dst, src, n);
-       spin_unlock_bh(&xfrm_state_lock);
+       spin_unlock_bh(&net->xfrm.xfrm_state_lock);
        xfrm_state_put_afinfo(afinfo);
        return err;
 }
@@ -1476,9 +1469,9 @@ struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq)
 {
        struct xfrm_state *x;
 
-       spin_lock_bh(&xfrm_state_lock);
+       spin_lock_bh(&net->xfrm.xfrm_state_lock);
        x = __xfrm_find_acq_byseq(net, mark, seq);
-       spin_unlock_bh(&xfrm_state_lock);
+       spin_unlock_bh(&net->xfrm.xfrm_state_lock);
        return x;
 }
 EXPORT_SYMBOL(xfrm_find_acq_byseq);
@@ -1536,10 +1529,10 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high)
                }
        }
        if (x->id.spi) {
-               spin_lock_bh(&xfrm_state_lock);
+               spin_lock_bh(&net->xfrm.xfrm_state_lock);
                h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto, x->props.family);
                hlist_add_head(&x->byspi, net->xfrm.state_byspi+h);
-               spin_unlock_bh(&xfrm_state_lock);
+               spin_unlock_bh(&net->xfrm.xfrm_state_lock);
 
                err = 0;
        }
@@ -1562,7 +1555,7 @@ int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk,
        if (walk->seq != 0 && list_empty(&walk->all))
                return 0;
 
-       spin_lock_bh(&xfrm_state_lock);
+       spin_lock_bh(&net->xfrm.xfrm_state_lock);
        if (list_empty(&walk->all))
                x = list_first_entry(&net->xfrm.state_all, struct xfrm_state_walk, all);
        else
@@ -1586,7 +1579,7 @@ int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk,
        }
        list_del_init(&walk->all);
 out:
-       spin_unlock_bh(&xfrm_state_lock);
+       spin_unlock_bh(&net->xfrm.xfrm_state_lock);
        return err;
 }
 EXPORT_SYMBOL(xfrm_state_walk);
@@ -1600,14 +1593,14 @@ void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto)
 }
 EXPORT_SYMBOL(xfrm_state_walk_init);
 
-void xfrm_state_walk_done(struct xfrm_state_walk *walk)
+void xfrm_state_walk_done(struct xfrm_state_walk *walk, struct net *net)
 {
        if (list_empty(&walk->all))
                return;
 
-       spin_lock_bh(&xfrm_state_lock);
+       spin_lock_bh(&net->xfrm.xfrm_state_lock);
        list_del(&walk->all);
-       spin_unlock_bh(&xfrm_state_lock);
+       spin_unlock_bh(&net->xfrm.xfrm_state_lock);
 }
 EXPORT_SYMBOL(xfrm_state_walk_done);
 
@@ -1655,16 +1648,12 @@ EXPORT_SYMBOL(km_state_notify);
 
 void km_state_expired(struct xfrm_state *x, int hard, u32 portid)
 {
-       struct net *net = xs_net(x);
        struct km_event c;
 
        c.data.hard = hard;
        c.portid = portid;
        c.event = XFRM_MSG_EXPIRE;
        km_state_notify(x, &c);
-
-       if (hard)
-               wake_up(&net->xfrm.km_waitq);
 }
 
 EXPORT_SYMBOL(km_state_expired);
@@ -1707,16 +1696,12 @@ EXPORT_SYMBOL(km_new_mapping);
 
 void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 portid)
 {
-       struct net *net = xp_net(pol);
        struct km_event c;
 
        c.data.hard = hard;
        c.portid = portid;
        c.event = XFRM_MSG_POLEXPIRE;
        km_policy_notify(pol, dir, &c);
-
-       if (hard)
-               wake_up(&net->xfrm.km_waitq);
 }
 EXPORT_SYMBOL(km_policy_expired);
 
@@ -2025,7 +2010,7 @@ int __net_init xfrm_state_init(struct net *net)
        INIT_WORK(&net->xfrm.state_hash_work, xfrm_hash_resize);
        INIT_HLIST_HEAD(&net->xfrm.state_gc_list);
        INIT_WORK(&net->xfrm.state_gc_work, xfrm_state_gc_task);
-       init_waitqueue_head(&net->xfrm.km_waitq);
+       spin_lock_init(&net->xfrm.xfrm_state_lock);
        return 0;
 
 out_byspi:
index f964d4c00ffb53457aa46b24f0225249c1d46b7c..16c84608e81efc881adec9effdacc32f389a11ed 100644 (file)
@@ -877,7 +877,10 @@ static int dump_one_state(struct xfrm_state *x, int count, void *ptr)
 static int xfrm_dump_sa_done(struct netlink_callback *cb)
 {
        struct xfrm_state_walk *walk = (struct xfrm_state_walk *) &cb->args[1];
-       xfrm_state_walk_done(walk);
+       struct sock *sk = cb->skb->sk;
+       struct net *net = sock_net(sk);
+
+       xfrm_state_walk_done(walk, net);
        return 0;
 }
 
@@ -1189,6 +1192,8 @@ static int verify_policy_type(u8 type)
 
 static int verify_newpolicy_info(struct xfrm_userpolicy_info *p)
 {
+       int ret;
+
        switch (p->share) {
        case XFRM_SHARE_ANY:
        case XFRM_SHARE_SESSION:
@@ -1224,7 +1229,13 @@ static int verify_newpolicy_info(struct xfrm_userpolicy_info *p)
                return -EINVAL;
        }
 
-       return verify_policy_dir(p->dir);
+       ret = verify_policy_dir(p->dir);
+       if (ret)
+               return ret;
+       if (p->index && ((p->index & XFRM_POLICY_MAX) != p->dir))
+               return -EINVAL;
+
+       return 0;
 }
 
 static int copy_from_user_sec_ctx(struct xfrm_policy *pol, struct nlattr **attrs)
@@ -1547,8 +1558,9 @@ static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr
 static int xfrm_dump_policy_done(struct netlink_callback *cb)
 {
        struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1];
+       struct net *net = sock_net(cb->skb->sk);
 
-       xfrm_policy_walk_done(walk);
+       xfrm_policy_walk_done(walk, net);
        return 0;
 }
 
@@ -2129,6 +2141,7 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
        u8 type;
        int err;
        int n = 0;
+       struct net *net = sock_net(skb->sk);
 
        if (attrs[XFRMA_MIGRATE] == NULL)
                return -EINVAL;
@@ -2146,7 +2159,7 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
        if (!n)
                return 0;
 
-       xfrm_migrate(&pi->sel, pi->dir, type, m, n, kmp);
+       xfrm_migrate(&pi->sel, pi->dir, type, m, n, kmp, net);
 
        return 0;
 }
@@ -2394,9 +2407,11 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 
 static void xfrm_netlink_rcv(struct sk_buff *skb)
 {
-       mutex_lock(&xfrm_cfg_mutex);
+       struct net *net = sock_net(skb->sk);
+
+       mutex_lock(&net->xfrm.xfrm_cfg_mutex);
        netlink_rcv_skb(skb, &xfrm_user_rcv_msg);
-       mutex_unlock(&xfrm_cfg_mutex);
+       mutex_unlock(&net->xfrm.xfrm_cfg_mutex);
 }
 
 static inline size_t xfrm_expire_msgsize(void)
index 90e521fde35fa827cf5008838024ef1bf1d03a88..65014e1495bf1751beef070887d53ed3d2a0f4cb 100644 (file)
@@ -172,8 +172,15 @@ fi
 
 # Install the maintainer scripts
 # Note: hook scripts under /etc/kernel are also executed by official Debian
-# kernel packages, as well as kernel packages built using make-kpkg
+# kernel packages, as well as kernel packages built using make-kpkg.
+# make-kpkg sets $INITRD to indicate whether an initramfs is wanted, and
+# so do we; recent versions of dracut and initramfs-tools will obey this.
 debhookdir=${KDEB_HOOKDIR:-/etc/kernel}
+if grep -q '^CONFIG_BLK_DEV_INITRD=y' $KCONFIG_CONFIG; then
+       want_initrd=Yes
+else
+       want_initrd=No
+fi
 for script in postinst postrm preinst prerm ; do
        mkdir -p "$tmpdir$debhookdir/$script.d"
        cat <<EOF > "$tmpdir/DEBIAN/$script"
@@ -184,6 +191,9 @@ set -e
 # Pass maintainer script parameters to hook scripts
 export DEB_MAINT_PARAMS="\$*"
 
+# Tell initramfs builder whether it's wanted
+export INITRD=$want_initrd
+
 test -d $debhookdir/$script.d && run-parts --arg="$version" --arg="/$installed_image_path" $debhookdir/$script.d
 exit 0
 EOF
index d0da66396f6201b5dbce7e8b9aa2ae421aefd40a..91280b82da0874787e6947a18ed8381d1567b483 100755 (executable)
@@ -364,7 +364,8 @@ if ($arch eq "x86_64") {
 } elsif ($arch eq "blackfin") {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s__mcount\$";
     $mcount_adjust = -4;
-} elsif ($arch eq "tilegx") {
+} elsif ($arch eq "tilegx" || $arch eq "tile") {
+    # Default to the newer TILE-Gx architecture if only "tile" is given.
     $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s__mcount\$";
     $type = ".quad";
     $alignment = 8;
index 5f7a8b663cb9c9eb59b32f4ce63076a6a86914cc..7941fbdfb050e573120f36b770ae8321130d8d01 100644 (file)
 #include <tools/be_byteshift.h>
 #include <tools/le_byteshift.h>
 
+#ifndef EM_ARCOMPACT
+#define EM_ARCOMPACT   93
+#endif
+
 #ifndef EM_AARCH64
 #define EM_AARCH64     183
 #endif
@@ -268,6 +272,7 @@ do_file(char const *const fname)
        case EM_S390:
                custom_sort = sort_relative_table;
                break;
+       case EM_ARCOMPACT:
        case EM_ARM:
        case EM_AARCH64:
        case EM_MIPS:
index 7c2a0a71049e9be5c22a5792ec35ad266949c114..d3b6d2cd3a06272a4f6cbd2ed75870db28ad5b48 100644 (file)
@@ -274,10 +274,9 @@ static void set_majmin(char *str, unsigned m)
                sprintf(str, "%u", m);
 }
 
-static int devcgroup_seq_read(struct cgroup_subsys_state *css,
-                             struct cftype *cft, struct seq_file *m)
+static int devcgroup_seq_show(struct seq_file *m, void *v)
 {
-       struct dev_cgroup *devcgroup = css_to_devcgroup(css);
+       struct dev_cgroup *devcgroup = css_to_devcgroup(seq_css(m));
        struct dev_exception_item *ex;
        char maj[MAJMINLEN], min[MAJMINLEN], acc[ACCLEN];
 
@@ -679,7 +678,7 @@ static struct cftype dev_cgroup_files[] = {
        },
        {
                .name = "list",
-               .read_seq_string = devcgroup_seq_read,
+               .seq_show = devcgroup_seq_show,
                .private = DEVCG_LIST,
        },
        { }     /* terminate */
index 9636e17c9f5d709ae735d60bccddd3d2bc481470..0356e1d437ca31cde30910567128168dbfd0a5ca 100644 (file)
@@ -148,6 +148,7 @@ int ima_alloc_init_template(struct integrity_iint_cache *iint,
                            int xattr_len, struct ima_template_entry **entry);
 int ima_store_template(struct ima_template_entry *entry, int violation,
                       struct inode *inode, const unsigned char *filename);
+void ima_free_template_entry(struct ima_template_entry *entry);
 const char *ima_d_path(struct path *path, char **pathbuf);
 
 /* rbtree tree calls to lookup, insert, delete
index 80374842fe0bb4cfef8a7dec8144eeff5278d408..c38bbce8c6a629e246d8f6bef7557e224707d88b 100644 (file)
 #include <crypto/hash_info.h>
 #include "ima.h"
 
+/*
+ * ima_free_template_entry - free an existing template entry
+ */
+void ima_free_template_entry(struct ima_template_entry *entry)
+{
+       int i;
+
+       for (i = 0; i < entry->template_desc->num_fields; i++)
+               kfree(entry->template_data[i].data);
+
+       kfree(entry);
+}
+
 /*
  * ima_alloc_init_template - create and initialize a new template entry
  */
@@ -37,6 +50,7 @@ int ima_alloc_init_template(struct integrity_iint_cache *iint,
        if (!*entry)
                return -ENOMEM;
 
+       (*entry)->template_desc = template_desc;
        for (i = 0; i < template_desc->num_fields; i++) {
                struct ima_template_field *field = template_desc->fields[i];
                u32 len;
@@ -51,10 +65,9 @@ int ima_alloc_init_template(struct integrity_iint_cache *iint,
                (*entry)->template_data_len += sizeof(len);
                (*entry)->template_data_len += len;
        }
-       (*entry)->template_desc = template_desc;
        return 0;
 out:
-       kfree(*entry);
+       ima_free_template_entry(*entry);
        *entry = NULL;
        return result;
 }
@@ -134,7 +147,7 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
        }
        result = ima_store_template(entry, violation, inode, filename);
        if (result < 0)
-               kfree(entry);
+               ima_free_template_entry(entry);
 err_out:
        integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename,
                            op, cause, result, 0);
@@ -269,7 +282,7 @@ void ima_store_measurement(struct integrity_iint_cache *iint,
        if (!result || result == -EEXIST)
                iint->flags |= IMA_MEASURED;
        if (result < 0)
-               kfree(entry);
+               ima_free_template_entry(entry);
 }
 
 void ima_audit_measurement(struct integrity_iint_cache *iint,
index 15f34bd40abed1530216be53c59658b6245d280b..37122768554a9e69d4866f9c9a72864f157afef3 100644 (file)
@@ -63,7 +63,6 @@ static void __init ima_add_boot_aggregate(void)
                result = ima_calc_boot_aggregate(&hash.hdr);
                if (result < 0) {
                        audit_cause = "hashing_error";
-                       kfree(entry);
                        goto err_out;
                }
        }
@@ -76,7 +75,7 @@ static void __init ima_add_boot_aggregate(void)
        result = ima_store_template(entry, violation, NULL,
                                    boot_aggregate_name);
        if (result < 0)
-               kfree(entry);
+               ima_free_template_entry(entry);
        return;
 err_out:
        integrity_audit_msg(AUDIT_INTEGRITY_PCR, NULL, boot_aggregate_name, op,
index 913e1927f916fccdfc7b0991d0f5795888291bbf..635695f6a185a1d24ee3d1bfb05d4f7ebe8cedb0 100644 (file)
@@ -110,7 +110,7 @@ static int template_desc_init_fields(const char *template_fmt,
                                     struct ima_template_field ***fields,
                                     int *num_fields)
 {
-       char *c, *template_fmt_copy;
+       char *c, *template_fmt_copy, *template_fmt_ptr;
        int template_num_fields = template_fmt_size(template_fmt);
        int i, result = 0;
 
@@ -127,7 +127,9 @@ static int template_desc_init_fields(const char *template_fmt,
                result = -ENOMEM;
                goto out;
        }
-       for (i = 0; (c = strsep(&template_fmt_copy, "|")) != NULL &&
+
+       template_fmt_ptr = template_fmt_copy;
+       for (i = 0; (c = strsep(&template_fmt_ptr, "|")) != NULL &&
             i < template_num_fields; i++) {
                struct ima_template_field *f = lookup_template_field(c);
 
index 794c3ca49eac92998caa17be71a4bdc472c2e9c8..3b28da235787cc7a401c7b49cf9a334c143ba253 100644 (file)
@@ -53,6 +53,7 @@
 #include <net/ip.h>            /* for local_port_range[] */
 #include <net/sock.h>
 #include <net/tcp.h>           /* struct or_callable used in sock_rcv_skb */
+#include <net/inet_connection_sock.h>
 #include <net/net_namespace.h>
 #include <net/netlabel.h>
 #include <linux/uaccess.h>
@@ -3828,7 +3829,7 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
        u32 nlbl_sid;
        u32 nlbl_type;
 
-       err = selinux_skb_xfrm_sid(skb, &xfrm_sid);
+       err = selinux_xfrm_skb_sid(skb, &xfrm_sid);
        if (unlikely(err))
                return -EACCES;
        err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
@@ -3846,6 +3847,30 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
        return 0;
 }
 
+/**
+ * selinux_conn_sid - Determine the child socket label for a connection
+ * @sk_sid: the parent socket's SID
+ * @skb_sid: the packet's SID
+ * @conn_sid: the resulting connection SID
+ *
+ * If @skb_sid is valid then the user:role:type information from @sk_sid is
+ * combined with the MLS information from @skb_sid in order to create
+ * @conn_sid.  If @skb_sid is not valid then then @conn_sid is simply a copy
+ * of @sk_sid.  Returns zero on success, negative values on failure.
+ *
+ */
+static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid)
+{
+       int err = 0;
+
+       if (skb_sid != SECSID_NULL)
+               err = security_sid_mls_copy(sk_sid, skb_sid, conn_sid);
+       else
+               *conn_sid = sk_sid;
+
+       return err;
+}
+
 /* socket security operations */
 
 static int socket_sockcreate_sid(const struct task_security_struct *tsec,
@@ -4313,8 +4338,10 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
                }
                err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
                                   PEER__RECV, &ad);
-               if (err)
+               if (err) {
                        selinux_netlbl_err(skb, err, 0);
+                       return err;
+               }
        }
 
        if (secmark_active) {
@@ -4451,27 +4478,18 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
 {
        struct sk_security_struct *sksec = sk->sk_security;
        int err;
-       u16 family = sk->sk_family;
-       u32 newsid;
+       u16 family = req->rsk_ops->family;
+       u32 connsid;
        u32 peersid;
 
-       /* handle mapped IPv4 packets arriving via IPv6 sockets */
-       if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
-               family = PF_INET;
-
        err = selinux_skb_peerlbl_sid(skb, family, &peersid);
        if (err)
                return err;
-       if (peersid == SECSID_NULL) {
-               req->secid = sksec->sid;
-               req->peer_secid = SECSID_NULL;
-       } else {
-               err = security_sid_mls_copy(sksec->sid, peersid, &newsid);
-               if (err)
-                       return err;
-               req->secid = newsid;
-               req->peer_secid = peersid;
-       }
+       err = selinux_conn_sid(sksec->sid, peersid, &connsid);
+       if (err)
+               return err;
+       req->secid = connsid;
+       req->peer_secid = peersid;
 
        return selinux_netlbl_inet_conn_request(req, family);
 }
@@ -4731,6 +4749,7 @@ static unsigned int selinux_ipv6_forward(const struct nf_hook_ops *ops,
 static unsigned int selinux_ip_output(struct sk_buff *skb,
                                      u16 family)
 {
+       struct sock *sk;
        u32 sid;
 
        if (!netlbl_enabled())
@@ -4739,8 +4758,27 @@ static unsigned int selinux_ip_output(struct sk_buff *skb,
        /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
         * because we want to make sure we apply the necessary labeling
         * before IPsec is applied so we can leverage AH protection */
-       if (skb->sk) {
-               struct sk_security_struct *sksec = skb->sk->sk_security;
+       sk = skb->sk;
+       if (sk) {
+               struct sk_security_struct *sksec;
+
+               if (sk->sk_state == TCP_LISTEN)
+                       /* if the socket is the listening state then this
+                        * packet is a SYN-ACK packet which means it needs to
+                        * be labeled based on the connection/request_sock and
+                        * not the parent socket.  unfortunately, we can't
+                        * lookup the request_sock yet as it isn't queued on
+                        * the parent socket until after the SYN-ACK is sent.
+                        * the "solution" is to simply pass the packet as-is
+                        * as any IP option based labeling should be copied
+                        * from the initial connection request (in the IP
+                        * layer).  it is far from ideal, but until we get a
+                        * security label in the packet itself this is the
+                        * best we can do. */
+                       return NF_ACCEPT;
+
+               /* standard practice, label using the parent socket */
+               sksec = sk->sk_security;
                sid = sksec->sid;
        } else
                sid = SECINITSID_KERNEL;
@@ -4810,27 +4848,36 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
         * as fast and as clean as possible. */
        if (!selinux_policycap_netpeer)
                return selinux_ip_postroute_compat(skb, ifindex, family);
+
+       secmark_active = selinux_secmark_enabled();
+       peerlbl_active = selinux_peerlbl_enabled();
+       if (!secmark_active && !peerlbl_active)
+               return NF_ACCEPT;
+
+       sk = skb->sk;
+
 #ifdef CONFIG_XFRM
        /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
         * packet transformation so allow the packet to pass without any checks
         * since we'll have another chance to perform access control checks
         * when the packet is on it's final way out.
         * NOTE: there appear to be some IPv6 multicast cases where skb->dst
-        *       is NULL, in this case go ahead and apply access control. */
-       if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL)
+        *       is NULL, in this case go ahead and apply access control.
+        * NOTE: if this is a local socket (skb->sk != NULL) that is in the
+        *       TCP listening state we cannot wait until the XFRM processing
+        *       is done as we will miss out on the SA label if we do;
+        *       unfortunately, this means more work, but it is only once per
+        *       connection. */
+       if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL &&
+           !(sk != NULL && sk->sk_state == TCP_LISTEN))
                return NF_ACCEPT;
 #endif
-       secmark_active = selinux_secmark_enabled();
-       peerlbl_active = selinux_peerlbl_enabled();
-       if (!secmark_active && !peerlbl_active)
-               return NF_ACCEPT;
 
-       /* if the packet is being forwarded then get the peer label from the
-        * packet itself; otherwise check to see if it is from a local
-        * application or the kernel, if from an application get the peer label
-        * from the sending socket, otherwise use the kernel's sid */
-       sk = skb->sk;
        if (sk == NULL) {
+               /* Without an associated socket the packet is either coming
+                * from the kernel or it is being forwarded; check the packet
+                * to determine which and if the packet is being forwarded
+                * query the packet directly to determine the security label. */
                if (skb->skb_iif) {
                        secmark_perm = PACKET__FORWARD_OUT;
                        if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
@@ -4839,7 +4886,45 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
                        secmark_perm = PACKET__SEND;
                        peer_sid = SECINITSID_KERNEL;
                }
+       } else if (sk->sk_state == TCP_LISTEN) {
+               /* Locally generated packet but the associated socket is in the
+                * listening state which means this is a SYN-ACK packet.  In
+                * this particular case the correct security label is assigned
+                * to the connection/request_sock but unfortunately we can't
+                * query the request_sock as it isn't queued on the parent
+                * socket until after the SYN-ACK packet is sent; the only
+                * viable choice is to regenerate the label like we do in
+                * selinux_inet_conn_request().  See also selinux_ip_output()
+                * for similar problems. */
+               u32 skb_sid;
+               struct sk_security_struct *sksec = sk->sk_security;
+               if (selinux_skb_peerlbl_sid(skb, family, &skb_sid))
+                       return NF_DROP;
+               /* At this point, if the returned skb peerlbl is SECSID_NULL
+                * and the packet has been through at least one XFRM
+                * transformation then we must be dealing with the "final"
+                * form of labeled IPsec packet; since we've already applied
+                * all of our access controls on this packet we can safely
+                * pass the packet. */
+               if (skb_sid == SECSID_NULL) {
+                       switch (family) {
+                       case PF_INET:
+                               if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
+                                       return NF_ACCEPT;
+                               break;
+                       case PF_INET6:
+                               if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED)
+                                       return NF_ACCEPT;
+                       default:
+                               return NF_DROP_ERR(-ECONNREFUSED);
+                       }
+               }
+               if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid))
+                       return NF_DROP;
+               secmark_perm = PACKET__SEND;
        } else {
+               /* Locally generated packet, fetch the security label from the
+                * associated socket. */
                struct sk_security_struct *sksec = sk->sk_security;
                peer_sid = sksec->sid;
                secmark_perm = PACKET__SEND;
index fe341ae370049b39ac2012d665a64dd4dc9af198..8ed8daf7f1eed9df82f963294e89e849b0da4b1d 100644 (file)
 #define POLICYDB_VERSION_ROLETRANS     26
 #define POLICYDB_VERSION_NEW_OBJECT_DEFAULTS   27
 #define POLICYDB_VERSION_DEFAULT_TYPE  28
+#define POLICYDB_VERSION_CONSTRAINT_NAMES      29
 
 /* Range of policy versions we understand*/
 #define POLICYDB_VERSION_MIN   POLICYDB_VERSION_BASE
 #ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX
 #define POLICYDB_VERSION_MAX   CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
 #else
-#define POLICYDB_VERSION_MAX   POLICYDB_VERSION_DEFAULT_TYPE
+#define POLICYDB_VERSION_MAX   POLICYDB_VERSION_CONSTRAINT_NAMES
 #endif
 
 /* Mask for just the mount related flags */
index 0dec76c64cf53853d0eea6aac983db307c8636b8..48c3cc94c1681718a78e6793c7e961e2d404f3fb 100644 (file)
@@ -39,6 +39,7 @@ int selinux_xfrm_sock_rcv_skb(u32 sk_sid, struct sk_buff *skb,
 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);
+int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid);
 
 static inline void selinux_xfrm_notify_policyload(void)
 {
@@ -79,11 +80,12 @@ static inline int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid,
 static inline void selinux_xfrm_notify_policyload(void)
 {
 }
-#endif
 
-static inline int selinux_skb_xfrm_sid(struct sk_buff *skb, u32 *sid)
+static inline int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid)
 {
-       return selinux_xfrm_decode_session(skb, sid, 0);
+       *sid = SECSID_NULL;
+       return 0;
 }
+#endif
 
 #endif /* _SELINUX_XFRM_H_ */
index 6235d052338b2e63b838711ed09c7ba1b04c67c6..0364120d1ec8705da7e8c1636f645d0885731509 100644 (file)
@@ -100,6 +100,32 @@ static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk)
        return secattr;
 }
 
+/**
+ * selinux_netlbl_sock_getattr - Get the cached NetLabel secattr
+ * @sk: the socket
+ * @sid: the SID
+ *
+ * Query the socket's cached secattr and if the SID matches the cached value
+ * return the cache, otherwise return NULL.
+ *
+ */
+static struct netlbl_lsm_secattr *selinux_netlbl_sock_getattr(
+                                                       const struct sock *sk,
+                                                       u32 sid)
+{
+       struct sk_security_struct *sksec = sk->sk_security;
+       struct netlbl_lsm_secattr *secattr = sksec->nlbl_secattr;
+
+       if (secattr == NULL)
+               return NULL;
+
+       if ((secattr->flags & NETLBL_SECATTR_SECID) &&
+           (secattr->attr.secid == sid))
+               return secattr;
+
+       return NULL;
+}
+
 /**
  * selinux_netlbl_cache_invalidate - Invalidate the NetLabel cache
  *
@@ -224,7 +250,7 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
                struct sk_security_struct *sksec = sk->sk_security;
                if (sksec->nlbl_state != NLBL_REQSKB)
                        return 0;
-               secattr = sksec->nlbl_secattr;
+               secattr = selinux_netlbl_sock_getattr(sk, sid);
        }
        if (secattr == NULL) {
                secattr = &secattr_storage;
@@ -410,6 +436,9 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
             sksec->nlbl_state == NLBL_CONNLABELED)) {
                netlbl_secattr_init(&secattr);
                lock_sock(sk);
+               /* call the netlabel function directly as we want to see the
+                * on-the-wire label that is assigned via the socket's options
+                * and not the cached netlabel/lsm attributes */
                rc = netlbl_sock_getattr(sk, &secattr);
                release_sock(sk);
                if (rc == 0)
index 149dda731fd3ff9becf6368567866b105b26e66c..96fd947c494b64827f89e745393483669cc07d8e 100644 (file)
@@ -48,6 +48,7 @@ struct constraint_expr {
        u32 op;                 /* operator */
 
        struct ebitmap names;   /* names */
+       struct type_set *type_names;
 
        struct constraint_expr *next;   /* next expression */
 };
index f6195ebde3c94eef0cdf1cf92933246069b25059..dc4011643b55022fe622260e83244bbaa8f1575f 100644 (file)
@@ -143,6 +143,11 @@ static struct policydb_compat_info policydb_compat[] = {
                .sym_num        = SYM_NUM,
                .ocon_num       = OCON_NUM,
        },
+       {
+               .version        = POLICYDB_VERSION_CONSTRAINT_NAMES,
+               .sym_num        = SYM_NUM,
+               .ocon_num       = OCON_NUM,
+       },
 };
 
 static struct policydb_compat_info *policydb_lookup_compat(int version)
@@ -613,6 +618,19 @@ static int common_destroy(void *key, void *datum, void *p)
        return 0;
 }
 
+static void constraint_expr_destroy(struct constraint_expr *expr)
+{
+       if (expr) {
+               ebitmap_destroy(&expr->names);
+               if (expr->type_names) {
+                       ebitmap_destroy(&expr->type_names->types);
+                       ebitmap_destroy(&expr->type_names->negset);
+                       kfree(expr->type_names);
+               }
+               kfree(expr);
+       }
+}
+
 static int cls_destroy(void *key, void *datum, void *p)
 {
        struct class_datum *cladatum;
@@ -628,10 +646,9 @@ static int cls_destroy(void *key, void *datum, void *p)
                while (constraint) {
                        e = constraint->expr;
                        while (e) {
-                               ebitmap_destroy(&e->names);
                                etmp = e;
                                e = e->next;
-                               kfree(etmp);
+                               constraint_expr_destroy(etmp);
                        }
                        ctemp = constraint;
                        constraint = constraint->next;
@@ -642,16 +659,14 @@ static int cls_destroy(void *key, void *datum, void *p)
                while (constraint) {
                        e = constraint->expr;
                        while (e) {
-                               ebitmap_destroy(&e->names);
                                etmp = e;
                                e = e->next;
-                               kfree(etmp);
+                               constraint_expr_destroy(etmp);
                        }
                        ctemp = constraint;
                        constraint = constraint->next;
                        kfree(ctemp);
                }
-
                kfree(cladatum->comkey);
        }
        kfree(datum);
@@ -1156,8 +1171,34 @@ bad:
        return rc;
 }
 
-static int read_cons_helper(struct constraint_node **nodep, int ncons,
-                           int allowxtarget, void *fp)
+static void type_set_init(struct type_set *t)
+{
+       ebitmap_init(&t->types);
+       ebitmap_init(&t->negset);
+}
+
+static int type_set_read(struct type_set *t, void *fp)
+{
+       __le32 buf[1];
+       int rc;
+
+       if (ebitmap_read(&t->types, fp))
+               return -EINVAL;
+       if (ebitmap_read(&t->negset, fp))
+               return -EINVAL;
+
+       rc = next_entry(buf, fp, sizeof(u32));
+       if (rc < 0)
+               return -EINVAL;
+       t->flags = le32_to_cpu(buf[0]);
+
+       return 0;
+}
+
+
+static int read_cons_helper(struct policydb *p,
+                               struct constraint_node **nodep,
+                               int ncons, int allowxtarget, void *fp)
 {
        struct constraint_node *c, *lc;
        struct constraint_expr *e, *le;
@@ -1225,6 +1266,18 @@ static int read_cons_helper(struct constraint_node **nodep, int ncons,
                                rc = ebitmap_read(&e->names, fp);
                                if (rc)
                                        return rc;
+                               if (p->policyvers >=
+                                       POLICYDB_VERSION_CONSTRAINT_NAMES) {
+                                               e->type_names = kzalloc(sizeof
+                                               (*e->type_names),
+                                               GFP_KERNEL);
+                                       if (!e->type_names)
+                                               return -ENOMEM;
+                                       type_set_init(e->type_names);
+                                       rc = type_set_read(e->type_names, fp);
+                                       if (rc)
+                                               return rc;
+                               }
                                break;
                        default:
                                return -EINVAL;
@@ -1301,7 +1354,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
                        goto bad;
        }
 
-       rc = read_cons_helper(&cladatum->constraints, ncons, 0, fp);
+       rc = read_cons_helper(p, &cladatum->constraints, ncons, 0, fp);
        if (rc)
                goto bad;
 
@@ -1311,7 +1364,8 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
                if (rc)
                        goto bad;
                ncons = le32_to_cpu(buf[0]);
-               rc = read_cons_helper(&cladatum->validatetrans, ncons, 1, fp);
+               rc = read_cons_helper(p, &cladatum->validatetrans,
+                               ncons, 1, fp);
                if (rc)
                        goto bad;
        }
@@ -2753,6 +2807,24 @@ static int common_write(void *vkey, void *datum, void *ptr)
        return 0;
 }
 
+static int type_set_write(struct type_set *t, void *fp)
+{
+       int rc;
+       __le32 buf[1];
+
+       if (ebitmap_write(&t->types, fp))
+               return -EINVAL;
+       if (ebitmap_write(&t->negset, fp))
+               return -EINVAL;
+
+       buf[0] = cpu_to_le32(t->flags);
+       rc = put_entry(buf, sizeof(u32), 1, fp);
+       if (rc)
+               return -EINVAL;
+
+       return 0;
+}
+
 static int write_cons_helper(struct policydb *p, struct constraint_node *node,
                             void *fp)
 {
@@ -2784,6 +2856,12 @@ static int write_cons_helper(struct policydb *p, struct constraint_node *node,
                                rc = ebitmap_write(&e->names, fp);
                                if (rc)
                                        return rc;
+                               if (p->policyvers >=
+                                       POLICYDB_VERSION_CONSTRAINT_NAMES) {
+                                       rc = type_set_write(e->type_names, fp);
+                                       if (rc)
+                                               return rc;
+                               }
                                break;
                        default:
                                break;
index da637471d4ce4d08fdb0706136184a3a1dcf7e57..725d5945a97e961f6fb6fde88eab0bba5f638345 100644 (file)
@@ -153,6 +153,17 @@ struct cond_bool_datum {
 
 struct cond_node;
 
+/*
+ * type set preserves data needed to determine constraint info from
+ * policy source. This is not used by the kernel policy but allows
+ * utilities such as audit2allow to determine constraint denials.
+ */
+struct type_set {
+       struct ebitmap types;
+       struct ebitmap negset;
+       u32 flags;
+};
+
 /*
  * The configuration data includes security contexts for
  * initial SIDs, unlabeled file systems, TCP and UDP port numbers,
index ee470a0b5c27fdad95a59b258792b6182435b999..6db5546717eb585d0606f9d69b73e2cba3650c7f 100644 (file)
@@ -1831,7 +1831,7 @@ static int security_preserve_bools(struct policydb *p);
  */
 int security_load_policy(void *data, size_t len)
 {
-       struct policydb oldpolicydb, newpolicydb;
+       struct policydb *oldpolicydb, *newpolicydb;
        struct sidtab oldsidtab, newsidtab;
        struct selinux_mapping *oldmap, *map = NULL;
        struct convert_context_args args;
@@ -1840,12 +1840,19 @@ int security_load_policy(void *data, size_t len)
        int rc = 0;
        struct policy_file file = { data, len }, *fp = &file;
 
+       oldpolicydb = kzalloc(2 * sizeof(*oldpolicydb), GFP_KERNEL);
+       if (!oldpolicydb) {
+               rc = -ENOMEM;
+               goto out;
+       }
+       newpolicydb = oldpolicydb + 1;
+
        if (!ss_initialized) {
                avtab_cache_init();
                rc = policydb_read(&policydb, fp);
                if (rc) {
                        avtab_cache_destroy();
-                       return rc;
+                       goto out;
                }
 
                policydb.len = len;
@@ -1855,14 +1862,14 @@ int security_load_policy(void *data, size_t len)
                if (rc) {
                        policydb_destroy(&policydb);
                        avtab_cache_destroy();
-                       return rc;
+                       goto out;
                }
 
                rc = policydb_load_isids(&policydb, &sidtab);
                if (rc) {
                        policydb_destroy(&policydb);
                        avtab_cache_destroy();
-                       return rc;
+                       goto out;
                }
 
                security_load_policycaps();
@@ -1874,36 +1881,36 @@ int security_load_policy(void *data, size_t len)
                selinux_status_update_policyload(seqno);
                selinux_netlbl_cache_invalidate();
                selinux_xfrm_notify_policyload();
-               return 0;
+               goto out;
        }
 
 #if 0
        sidtab_hash_eval(&sidtab, "sids");
 #endif
 
-       rc = policydb_read(&newpolicydb, fp);
+       rc = policydb_read(newpolicydb, fp);
        if (rc)
-               return rc;
+               goto out;
 
-       newpolicydb.len = len;
+       newpolicydb->len = len;
        /* If switching between different policy types, log MLS status */
-       if (policydb.mls_enabled && !newpolicydb.mls_enabled)
+       if (policydb.mls_enabled && !newpolicydb->mls_enabled)
                printk(KERN_INFO "SELinux: Disabling MLS support...\n");
-       else if (!policydb.mls_enabled && newpolicydb.mls_enabled)
+       else if (!policydb.mls_enabled && newpolicydb->mls_enabled)
                printk(KERN_INFO "SELinux: Enabling MLS support...\n");
 
-       rc = policydb_load_isids(&newpolicydb, &newsidtab);
+       rc = policydb_load_isids(newpolicydb, &newsidtab);
        if (rc) {
                printk(KERN_ERR "SELinux:  unable to load the initial SIDs\n");
-               policydb_destroy(&newpolicydb);
-               return rc;
+               policydb_destroy(newpolicydb);
+               goto out;
        }
 
-       rc = selinux_set_mapping(&newpolicydb, secclass_map, &map, &map_size);
+       rc = selinux_set_mapping(newpolicydb, secclass_map, &map, &map_size);
        if (rc)
                goto err;
 
-       rc = security_preserve_bools(&newpolicydb);
+       rc = security_preserve_bools(newpolicydb);
        if (rc) {
                printk(KERN_ERR "SELinux:  unable to preserve booleans\n");
                goto err;
@@ -1921,7 +1928,7 @@ int security_load_policy(void *data, size_t len)
         * in the new SID table.
         */
        args.oldp = &policydb;
-       args.newp = &newpolicydb;
+       args.newp = newpolicydb;
        rc = sidtab_map(&newsidtab, convert_context, &args);
        if (rc) {
                printk(KERN_ERR "SELinux:  unable to convert the internal"
@@ -1931,12 +1938,12 @@ int security_load_policy(void *data, size_t len)
        }
 
        /* Save the old policydb and SID table to free later. */
-       memcpy(&oldpolicydb, &policydb, sizeof policydb);
+       memcpy(oldpolicydb, &policydb, sizeof(policydb));
        sidtab_set(&oldsidtab, &sidtab);
 
        /* Install the new policydb and SID table. */
        write_lock_irq(&policy_rwlock);
-       memcpy(&policydb, &newpolicydb, sizeof policydb);
+       memcpy(&policydb, newpolicydb, sizeof(policydb));
        sidtab_set(&sidtab, &newsidtab);
        security_load_policycaps();
        oldmap = current_mapping;
@@ -1946,7 +1953,7 @@ int security_load_policy(void *data, size_t len)
        write_unlock_irq(&policy_rwlock);
 
        /* Free the old policydb and SID table. */
-       policydb_destroy(&oldpolicydb);
+       policydb_destroy(oldpolicydb);
        sidtab_destroy(&oldsidtab);
        kfree(oldmap);
 
@@ -1956,14 +1963,17 @@ int security_load_policy(void *data, size_t len)
        selinux_netlbl_cache_invalidate();
        selinux_xfrm_notify_policyload();
 
-       return 0;
+       rc = 0;
+       goto out;
 
 err:
        kfree(map);
        sidtab_destroy(&newsidtab);
-       policydb_destroy(&newpolicydb);
-       return rc;
+       policydb_destroy(newpolicydb);
 
+out:
+       kfree(oldpolicydb);
+       return rc;
 }
 
 size_t security_policydb_len(void)
index a91d205ec0c6094cc9a0fecb5d427d4d24b1ed9a..0462cb3ff0a741a36b279dcef37ee784e8520c5c 100644 (file)
@@ -209,19 +209,26 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x,
                            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)
+static u32 selinux_xfrm_skb_sid_egress(struct sk_buff *skb)
 {
-       u32 sid_session = SECSID_NULL;
-       struct sec_path *sp;
+       struct dst_entry *dst = skb_dst(skb);
+       struct xfrm_state *x;
 
-       if (skb == NULL)
-               goto out;
+       if (dst == NULL)
+               return SECSID_NULL;
+       x = dst->xfrm;
+       if (x == NULL || !selinux_authorizable_xfrm(x))
+               return SECSID_NULL;
+
+       return x->security->ctx_sid;
+}
+
+static int selinux_xfrm_skb_sid_ingress(struct sk_buff *skb,
+                                       u32 *sid, int ckall)
+{
+       u32 sid_session = SECSID_NULL;
+       struct sec_path *sp = skb->sp;
 
-       sp = skb->sp;
        if (sp) {
                int i;
 
@@ -247,6 +254,30 @@ out:
        return 0;
 }
 
+/*
+ * 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)
+{
+       if (skb == NULL) {
+               *sid = SECSID_NULL;
+               return 0;
+       }
+       return selinux_xfrm_skb_sid_ingress(skb, sid, ckall);
+}
+
+int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid)
+{
+       int rc;
+
+       rc = selinux_xfrm_skb_sid_ingress(skb, sid, 0);
+       if (rc == 0 && *sid == SECSID_NULL)
+               *sid = selinux_xfrm_skb_sid_egress(skb);
+
+       return rc;
+}
+
 /*
  * LSM hook implementation that allocs and transfers uctx spec to xfrm_policy.
  */
@@ -327,19 +358,22 @@ int selinux_xfrm_state_alloc_acquire(struct xfrm_state *x,
                return rc;
 
        ctx = kmalloc(sizeof(*ctx) + str_len, GFP_ATOMIC);
-       if (!ctx)
-               return -ENOMEM;
+       if (!ctx) {
+               rc = -ENOMEM;
+               goto out;
+       }
 
        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;
+out:
+       kfree(ctx_str);
+       return rc;
 }
 
 /*
index 1ca8dc2ccb89f21cb0d102d2d4cd4cc0c74e4bf0..c421fdb3c7a12bf76a2584c21831913e57455ce9 100644 (file)
@@ -753,7 +753,7 @@ static struct snd_pcm_ops aaci_capture_ops = {
  * Power Management.
  */
 #ifdef CONFIG_PM
-static int aaci_do_suspend(struct snd_card *card, unsigned int state)
+static int aaci_do_suspend(struct snd_card *card)
 {
        struct aaci *aaci = card->private_data;
        snd_power_change_state(card, SNDRV_CTL_POWER_D3cold);
@@ -761,28 +761,28 @@ static int aaci_do_suspend(struct snd_card *card, unsigned int state)
        return 0;
 }
 
-static int aaci_do_resume(struct snd_card *card, unsigned int state)
+static int aaci_do_resume(struct snd_card *card)
 {
        snd_power_change_state(card, SNDRV_CTL_POWER_D0);
        return 0;
 }
 
-static int aaci_suspend(struct amba_device *dev, pm_message_t state)
+static int aaci_suspend(struct device *dev)
 {
-       struct snd_card *card = amba_get_drvdata(dev);
+       struct snd_card *card = dev_get_drvdata(dev);
        return card ? aaci_do_suspend(card) : 0;
 }
 
-static int aaci_resume(struct amba_device *dev)
+static int aaci_resume(struct device *dev)
 {
-       struct snd_card *card = amba_get_drvdata(dev);
+       struct snd_card *card = dev_get_drvdata(dev);
        return card ? aaci_do_resume(card) : 0;
 }
+
+static SIMPLE_DEV_PM_OPS(aaci_dev_pm_ops, aaci_suspend, aaci_resume);
+#define AACI_DEV_PM_OPS (&aaci_dev_pm_ops)
 #else
-#define aaci_do_suspend                NULL
-#define aaci_do_resume         NULL
-#define aaci_suspend           NULL
-#define aaci_resume            NULL
+#define AACI_DEV_PM_OPS NULL
 #endif
 
 
@@ -1100,11 +1100,10 @@ MODULE_DEVICE_TABLE(amba, aaci_ids);
 static struct amba_driver aaci_driver = {
        .drv            = {
                .name   = DRIVER_NAME,
+               .pm     = AACI_DEV_PM_OPS,
        },
        .probe          = aaci_probe,
        .remove         = aaci_remove,
-       .suspend        = aaci_suspend,
-       .resume         = aaci_resume,
        .id_table       = aaci_ids,
 };
 
index 872d59e35ee23583cc60a2be24afa5ba1bf3c88d..3519518e25a09612c71f1888bc097e9f088ca6ee 100644 (file)
@@ -354,10 +354,11 @@ static int set_sample_rates(struct atmel_abdac *dac)
        /* we start at 192 kHz and work our way down to 5112 Hz */
        while (new_rate >= RATE_MIN && index < (MAX_NUM_RATES + 1)) {
                new_rate = clk_round_rate(dac->sample_clk, 256 * new_rate);
-               if (new_rate < 0)
+               if (new_rate <= 0)
                        break;
                /* make sure we are below the ABDAC clock */
-               if (new_rate <= clk_get_rate(dac->pclk)) {
+               if (index < MAX_NUM_RATES &&
+                   new_rate <= clk_get_rate(dac->pclk)) {
                        dac->rates[index] = new_rate / 256;
                        index++;
                }
index 57bcd31fcc123c38cd293cab40b52310734698a2..c0aa64941cee0bd927450a6b69314d14f2f02bce 100644 (file)
@@ -1019,7 +1019,7 @@ static void dice_proc_read(struct snd_info_entry *entry,
 
        if (dice_proc_read_mem(dice, &tx_rx_header, sections[2], 2) < 0)
                return;
-       quadlets = min_t(u32, tx_rx_header.size, sizeof(buf.tx));
+       quadlets = min_t(u32, tx_rx_header.size, sizeof(buf.tx) / 4);
        for (stream = 0; stream < tx_rx_header.number; ++stream) {
                if (dice_proc_read_mem(dice, &buf.tx, sections[2] + 2 +
                                       stream * tx_rx_header.size,
@@ -1045,7 +1045,7 @@ static void dice_proc_read(struct snd_info_entry *entry,
 
        if (dice_proc_read_mem(dice, &tx_rx_header, sections[4], 2) < 0)
                return;
-       quadlets = min_t(u32, tx_rx_header.size, sizeof(buf.rx));
+       quadlets = min_t(u32, tx_rx_header.size, sizeof(buf.rx) / 4);
        for (stream = 0; stream < tx_rx_header.number; ++stream) {
                if (dice_proc_read_mem(dice, &buf.rx, sections[4] + 2 +
                                       stream * tx_rx_header.size,
index 46ed9e8ae0fde718525da786a5b79a27a043c372..3a0504dfeb8a4e97341353ccee28365ef3fb3983 100644 (file)
@@ -254,6 +254,7 @@ config SND_CS46XX
        tristate "Cirrus Logic (Sound Fusion) CS4280/CS461x/CS462x/CS463x"
        select SND_RAWMIDI
        select SND_AC97_CODEC
+       select FW_LOADER
        help
          Say Y here to include support for Cirrus Logic CS4610/CS4612/
          CS4614/CS4615/CS4622/CS4624/CS4630/CS4280 chips.
index fc339ef0a0ae439a87087753a4bfaf6e28de9742..c49a082c378b6c711e36d74187ef742318be56ce 100644 (file)
@@ -1716,9 +1716,14 @@ struct snd_cs46xx {
        struct snd_pcm *pcm_rear;
        struct snd_pcm *pcm_center_lfe;
        struct snd_pcm *pcm_iec958;
+
+#define CS46XX_DSP_MODULES     5
+       struct dsp_module_desc *modules[CS46XX_DSP_MODULES];
 #else /* for compatibility */
        struct snd_cs46xx_pcm *playback_pcm;
        unsigned int play_ctl;
+
+       struct ba1_struct *ba1;
 #endif
 
 #ifdef CONFIG_PM_SLEEP
diff --git a/sound/pci/cs46xx/cs46xx_image.h b/sound/pci/cs46xx/cs46xx_image.h
deleted file mode 100644 (file)
index dc93f62..0000000
+++ /dev/null
@@ -1,3468 +0,0 @@
-struct BA1struct {
-       struct {
-               unsigned long offset;
-               unsigned long size;
-       } memory[BA1_MEMORY_COUNT];
-       u32 map[BA1_DWORD_SIZE];
-};
-
-
-static struct BA1struct BA1Struct = {
-{{ 0x00000000, 0x00003000 },{ 0x00010000, 0x00003800 },{ 0x00020000, 0x00007000 }},
-{0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000163,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00200040,0x00008010,0x00000000,
-0x00000000,0x80000001,0x00000001,0x00060000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00900080,0x00000173,0x00000000,
-0x00000000,0x00000010,0x00800000,0x00900000,
-0xf2c0000f,0x00000200,0x00000000,0x00010600,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000163,0x330300c2,
-0x06000000,0x00000000,0x80008000,0x80008000,
-0x3fc0000f,0x00000301,0x00010400,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00b00000,0x00d0806d,0x330480c3,
-0x04800000,0x00000001,0x00800001,0x0000ffff,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x066a0600,0x06350070,0x0000929d,0x929d929d,
-0x00000000,0x0000735a,0x00000600,0x00000000,
-0x929d735a,0x8734abfe,0x00010000,0x735a735a,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x0000804f,0x000000c3,
-0x05000000,0x00a00010,0x00000000,0x80008000,
-0x00000000,0x00000000,0x00000700,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000080,0x00a00000,0x0000809a,0x000000c2,
-0x07400000,0x00000000,0x80008000,0xffffffff,
-0x00c80028,0x00005555,0x00000000,0x000107a0,
-0x00c80028,0x000000c2,0x06800000,0x00000000,
-0x06e00080,0x00300000,0x000080bb,0x000000c9,
-0x07a00000,0x04000000,0x80008000,0xffffffff,
-0x00c80028,0x00005555,0x00000000,0x00000780,
-0x00c80028,0x000000c5,0xff800000,0x00000000,
-0x00640080,0x00c00000,0x00008197,0x000000c9,
-0x07800000,0x04000000,0x80008000,0xffffffff,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x0000805e,0x000000c1,
-0x00000000,0x00800000,0x80008000,0x80008000,
-0x00020000,0x0000ffff,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x929d0600,0x929d929d,0x929d929d,0x929d0000,
-0x929d929d,0x929d929d,0x929d929d,0x929d929d,
-0x929d929d,0x00100635,0x060b013f,0x00000004,
-0x00000001,0x007a0002,0x00000000,0x066e0610,
-0x0105929d,0x929d929d,0x929d929d,0x929d929d,
-0x929d929d,0xa431ac75,0x0001735a,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0x735a0051,
-0x00000000,0x929d929d,0x929d929d,0x929d929d,
-0x929d929d,0x929d929d,0x929d929d,0x929d929d,
-0x929d929d,0x929d929d,0x00000000,0x06400136,
-0x0000270f,0x00010000,0x007a0000,0x00000000,
-0x068e0645,0x0105929d,0x929d929d,0x929d929d,
-0x929d929d,0x929d929d,0xa431ac75,0x0001735a,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-0x735a0100,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00010004,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00001705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00009705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00011705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00019705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00021705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00029705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00031705,0x00001400,0x000a411e,0x00001003,
-0x00040730,0x00001002,0x000f619e,0x00001003,
-0x00039705,0x00001400,0x000a411e,0x00001003,
-0x000fe19e,0x00001003,0x0009c730,0x00001003,
-0x0008e19c,0x00001003,0x000083c1,0x00093040,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00009705,0x00001400,0x000a211e,0x00001003,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00011705,0x00001400,0x000a211e,0x00001003,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00019705,0x00001400,0x000a211e,0x00001003,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00021705,0x00001400,0x000a211e,0x00001003,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00029705,0x00001400,0x000a211e,0x00001003,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00031705,0x00001400,0x000a211e,0x00001003,
-0x00098730,0x00001002,0x000ee19e,0x00001003,
-0x00039705,0x00001400,0x000a211e,0x00001003,
-0x0000a730,0x00001008,0x000e2730,0x00001002,
-0x0000a731,0x00001002,0x0000a731,0x00001002,
-0x0000a731,0x00001002,0x0000a731,0x00001002,
-0x0000a731,0x00001002,0x0000a731,0x00001002,
-0x00000000,0x00000000,0x000f619c,0x00001003,
-0x0007f801,0x000c0000,0x00000037,0x00001000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x000c0000,0x00000000,0x00000000,
-0x0000373c,0x00001000,0x00000000,0x00000000,
-0x000ee19c,0x00001003,0x0007f801,0x000c0000,
-0x00000037,0x00001000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x0000273c,0x00001000,
-0x00000033,0x00001000,0x000e679e,0x00001003,
-0x00007705,0x00001400,0x000ac71e,0x00001003,
-0x00087fc1,0x000c3be0,0x0007f801,0x000c0000,
-0x00000037,0x00001000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x0000a730,0x00001003,
-0x00000033,0x00001000,0x0007f801,0x000c0000,
-0x00000037,0x00001000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x000c0000,
-0x00000032,0x00001000,0x0000273d,0x00001000,
-0x0004a730,0x00001003,0x00000f41,0x00097140,
-0x0000a841,0x0009b240,0x0000a0c1,0x0009f040,
-0x0001c641,0x00093540,0x0001cec1,0x0009b5c0,
-0x00000000,0x00000000,0x0001bf05,0x0003fc40,
-0x00002725,0x000aa400,0x00013705,0x00093a00,
-0x0000002e,0x0009d6c0,0x00038630,0x00001004,
-0x0004ef0a,0x000eb785,0x0003fc8a,0x00000000,
-0x00000000,0x000c70e0,0x0007d182,0x0002c640,
-0x00000630,0x00001004,0x000799b8,0x0002c6c0,
-0x00031705,0x00092240,0x00039f05,0x000932c0,
-0x0003520a,0x00000000,0x00040731,0x0000100b,
-0x00010705,0x000b20c0,0x00000000,0x000eba44,
-0x00032108,0x000c60c4,0x00065208,0x000c2917,
-0x000406b0,0x00001007,0x00012f05,0x00036880,
-0x0002818e,0x000c0000,0x0004410a,0x00000000,
-0x00040630,0x00001007,0x00029705,0x000c0000,
-0x00000000,0x00000000,0x00003fc1,0x0003fc40,
-0x000037c1,0x00091b40,0x00003fc1,0x000911c0,
-0x000037c1,0x000957c0,0x00003fc1,0x000951c0,
-0x000037c1,0x00000000,0x00003fc1,0x000991c0,
-0x000037c1,0x00000000,0x00003fc1,0x0009d1c0,
-0x000037c1,0x00000000,0x0001ccc1,0x000915c0,
-0x0001c441,0x0009d800,0x0009cdc1,0x00091240,
-0x0001c541,0x00091d00,0x0009cfc1,0x00095240,
-0x0001c741,0x00095c80,0x000e8ca9,0x00099240,
-0x000e85ad,0x00095640,0x00069ca9,0x00099d80,
-0x000e952d,0x00099640,0x000eaca9,0x0009d6c0,
-0x000ea5ad,0x00091a40,0x0006bca9,0x0009de80,
-0x000eb52d,0x00095a40,0x000ecca9,0x00099ac0,
-0x000ec5ad,0x0009da40,0x000edca9,0x0009d300,
-0x000a6e0a,0x00001000,0x000ed52d,0x00091e40,
-0x000eeca9,0x00095ec0,0x000ee5ad,0x00099e40,
-0x0006fca9,0x00002500,0x000fb208,0x000c59a0,
-0x000ef52d,0x0009de40,0x00068ca9,0x000912c1,
-0x000683ad,0x00095241,0x00020f05,0x000991c1,
-0x00000000,0x00000000,0x00086f88,0x00001000,
-0x0009cf81,0x000b5340,0x0009c701,0x000b92c0,
-0x0009de81,0x000bd300,0x0009d601,0x000b1700,
-0x0001fd81,0x000b9d80,0x0009f501,0x000b57c0,
-0x000a0f81,0x000bd740,0x00020701,0x000b5c80,
-0x000a1681,0x000b97c0,0x00021601,0x00002500,
-0x000a0701,0x000b9b40,0x000a0f81,0x000b1bc0,
-0x00021681,0x00002d00,0x00020f81,0x000bd800,
-0x000a0701,0x000b5bc0,0x00021601,0x00003500,
-0x000a0f81,0x000b5f40,0x000a0701,0x000bdbc0,
-0x00021681,0x00003d00,0x00020f81,0x000b1d00,
-0x000a0701,0x000b1fc0,0x00021601,0x00020500,
-0x00020f81,0x000b1341,0x000a0701,0x000b9fc0,
-0x00021681,0x00020d00,0x00020f81,0x000bde80,
-0x000a0701,0x000bdfc0,0x00021601,0x00021500,
-0x00020f81,0x000b9341,0x00020701,0x000b53c1,
-0x00021681,0x00021d00,0x000a0f81,0x000d0380,
-0x0000b601,0x000b15c0,0x00007b01,0x00000000,
-0x00007b81,0x000bd1c0,0x00007b01,0x00000000,
-0x00007b81,0x000b91c0,0x00007b01,0x000b57c0,
-0x00007b81,0x000b51c0,0x00007b01,0x000b1b40,
-0x00007b81,0x000b11c0,0x00087b01,0x000c3dc0,
-0x0007e488,0x000d7e45,0x00000000,0x000d7a44,
-0x0007e48a,0x00000000,0x00011f05,0x00084080,
-0x00000000,0x00000000,0x00001705,0x000b3540,
-0x00008a01,0x000bf040,0x00007081,0x000bb5c0,
-0x00055488,0x00000000,0x0000d482,0x0003fc40,
-0x0003fc88,0x00000000,0x0001e401,0x000b3a00,
-0x0001ec81,0x000bd6c0,0x0004ef08,0x000eb784,
-0x000c86b0,0x00001007,0x00008281,0x000bb240,
-0x0000b801,0x000b7140,0x00007888,0x00000000,
-0x0000073c,0x00001000,0x0007f188,0x000c0000,
-0x00000000,0x00000000,0x00055288,0x000c555c,
-0x0005528a,0x000c0000,0x0009fa88,0x000c5d00,
-0x0000fa88,0x00000000,0x00000032,0x00001000,
-0x0000073d,0x00001000,0x0007f188,0x000c0000,
-0x00000000,0x00000000,0x0008c01c,0x00001003,
-0x00002705,0x00001008,0x0008b201,0x000c1392,
-0x0000ba01,0x00000000,0x00008731,0x00001400,
-0x0004c108,0x000fe0c4,0x00057488,0x00000000,
-0x000a6388,0x00001001,0x0008b334,0x000bc141,
-0x0003020e,0x00000000,0x000886b0,0x00001008,
-0x00003625,0x000c5dfa,0x000a638a,0x00001001,
-0x0008020e,0x00001002,0x0008a6b0,0x00001008,
-0x0007f301,0x00000000,0x00000000,0x00000000,
-0x00002725,0x000a8c40,0x000000ae,0x00000000,
-0x000d8630,0x00001008,0x00000000,0x000c74e0,
-0x0007d182,0x0002d640,0x000a8630,0x00001008,
-0x000799b8,0x0002d6c0,0x0000748a,0x000c3ec5,
-0x0007420a,0x000c0000,0x00062208,0x000c4117,
-0x00070630,0x00001009,0x00000000,0x000c0000,
-0x0001022e,0x00000000,0x0003a630,0x00001009,
-0x00000000,0x000c0000,0x00000036,0x00001000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x0002a730,0x00001008,0x0007f801,0x000c0000,
-0x00000037,0x00001000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x0002a730,0x00001008,
-0x00000033,0x00001000,0x0002a705,0x00001008,
-0x00007a01,0x000c0000,0x000e6288,0x000d550a,
-0x0006428a,0x00000000,0x00060730,0x0000100a,
-0x00000000,0x000c0000,0x00000000,0x00000000,
-0x0007aab0,0x00034880,0x00078fb0,0x0000100b,
-0x00057488,0x00000000,0x00033b94,0x00081140,
-0x000183ae,0x00000000,0x000786b0,0x0000100b,
-0x00022f05,0x000c3545,0x0000eb8a,0x00000000,
-0x00042731,0x00001003,0x0007aab0,0x00034880,
-0x00048fb0,0x0000100a,0x00057488,0x00000000,
-0x00033b94,0x00081140,0x000183ae,0x00000000,
-0x000806b0,0x0000100b,0x00022f05,0x00000000,
-0x00007401,0x00091140,0x00048f05,0x000951c0,
-0x00042731,0x00001003,0x0000473d,0x00001000,
-0x000f19b0,0x000bbc47,0x00080000,0x000bffc7,
-0x000fe19e,0x00001003,0x00000000,0x00000000,
-0x0008e19c,0x00001003,0x000083c1,0x00093040,
-0x00000f41,0x00097140,0x0000a841,0x0009b240,
-0x0000a0c1,0x0009f040,0x0001c641,0x00093540,
-0x0001cec1,0x0009b5c0,0x00000000,0x000fdc44,
-0x00055208,0x00000000,0x00010705,0x000a2880,
-0x0000a23a,0x00093a00,0x0003fc8a,0x000df6c5,
-0x0004ef0a,0x000c0000,0x00012f05,0x00036880,
-0x00065308,0x000c2997,0x000d86b0,0x0000100a,
-0x0004410a,0x000d40c7,0x00000000,0x00000000,
-0x00080730,0x00001004,0x00056f0a,0x000ea105,
-0x00000000,0x00000000,0x0000473d,0x00001000,
-0x000f19b0,0x000bbc47,0x00080000,0x000bffc7,
-0x0000273d,0x00001000,0x00000000,0x000eba44,
-0x00048f05,0x0000f440,0x00007401,0x0000f7c0,
-0x00000734,0x00001000,0x00010705,0x000a6880,
-0x00006a88,0x000c75c4,0x00000000,0x000e5084,
-0x00000000,0x000eba44,0x00087401,0x000e4782,
-0x00000734,0x00001000,0x00010705,0x000a6880,
-0x00006a88,0x000c75c4,0x0007c108,0x000c0000,
-0x0007e721,0x000bed40,0x00005f25,0x000badc0,
-0x0003ba97,0x000beb80,0x00065590,0x000b2e00,
-0x00033217,0x00003ec0,0x00065590,0x000b8e40,
-0x0003ed80,0x000491c0,0x00073fb0,0x00074c80,
-0x000283a0,0x0000100c,0x000ee388,0x00042970,
-0x00008301,0x00021ef2,0x000b8f14,0x0000000f,
-0x000c4d8d,0x0000001b,0x000d6dc2,0x000e06c6,
-0x000032ac,0x000c3916,0x0004edc2,0x00074c80,
-0x00078898,0x00001000,0x00038894,0x00000032,
-0x000c4d8d,0x00092e1b,0x000d6dc2,0x000e06c6,
-0x0004edc2,0x000c1956,0x0000722c,0x00034a00,
-0x00041705,0x0009ed40,0x00058730,0x00001400,
-0x000d7488,0x000c3a00,0x00048f05,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000,
-0x00000000,0x00000000,0x00000000,0x00000000}
- };
index 1b66efd9b728e153506106cf3917b17c73ec87b3..f18e5878f58b42a195df536aedde6d80a3897700 100644 (file)
@@ -54,7 +54,9 @@
 #include <linux/gameport.h>
 #include <linux/mutex.h>
 #include <linux/export.h>
-
+#include <linux/module.h>
+#include <linux/firmware.h>
+#include <linux/vmalloc.h>
 
 #include <sound/core.h>
 #include <sound/control.h>
@@ -330,13 +332,146 @@ int snd_cs46xx_download(struct snd_cs46xx *chip,
        return 0;
 }
 
+static inline void memcpy_le32(void *dst, const void *src, unsigned int len)
+{
+#ifdef __LITTLE_ENDIAN
+       memcpy(dst, src, len);
+#else
+       u32 *_dst = dst;
+       const __le32 *_src = src;
+       len /= 4;
+       while (len-- > 0)
+               *_dst++ = le32_to_cpu(*_src++);
+#endif
+}
+
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
 
-#include "imgs/cwc4630.h"
-#include "imgs/cwcasync.h"
-#include "imgs/cwcsnoop.h"
-#include "imgs/cwcbinhack.h"
-#include "imgs/cwcdma.h"
+static const char *module_names[CS46XX_DSP_MODULES] = {
+       "cwc4630", "cwcasync", "cwcsnoop", "cwcbinhack", "cwcdma"
+};
+
+MODULE_FIRMWARE("cs46xx/cwc4630");
+MODULE_FIRMWARE("cs46xx/cwcasync");
+MODULE_FIRMWARE("cs46xx/cwcsnoop");
+MODULE_FIRMWARE("cs46xx/cwcbinhack");
+MODULE_FIRMWARE("cs46xx/cwcdma");
+
+static void free_module_desc(struct dsp_module_desc *module)
+{
+       if (!module)
+               return;
+       kfree(module->module_name);
+       kfree(module->symbol_table.symbols);
+       if (module->segments) {
+               int i;
+               for (i = 0; i < module->nsegments; i++)
+                       kfree(module->segments[i].data);
+               kfree(module->segments);
+       }
+}
+
+/* firmware binary format:
+ * le32 nsymbols;
+ * struct {
+ *     le32 address;
+ *     char symbol_name[DSP_MAX_SYMBOL_NAME];
+ *     le32 symbol_type;
+ * } symbols[nsymbols];
+ * le32 nsegments;
+ * struct {
+ *     le32 segment_type;
+ *     le32 offset;
+ *     le32 size;
+ *     le32 data[size];
+ * } segments[nsegments];
+ */
+
+static int load_firmware(struct snd_cs46xx *chip,
+                        struct dsp_module_desc **module_ret,
+                        const char *fw_name)
+{
+       int i, err;
+       unsigned int nums, fwlen, fwsize;
+       const __le32 *fwdat;
+       struct dsp_module_desc *module = NULL;
+       const struct firmware *fw;
+       char fw_path[32];
+
+       sprintf(fw_path, "cs46xx/%s", fw_name);
+       err = request_firmware(&fw, fw_path, &chip->pci->dev);
+       if (err < 0)
+               return err;
+       fwsize = fw->size / 4;
+       if (fwsize < 2) {
+               err = -EINVAL;
+               goto error;
+       }
+
+       err = -ENOMEM;
+       module = kzalloc(sizeof(*module), GFP_KERNEL);
+       if (!module)
+               goto error;
+       module->module_name = kstrdup(fw_name, GFP_KERNEL);
+       if (!module->module_name)
+               goto error;
+
+       fwlen = 0;
+       fwdat = (const __le32 *)fw->data;
+       nums = module->symbol_table.nsymbols = le32_to_cpu(fwdat[fwlen++]);
+       if (nums >= 40)
+               goto error_inval;
+       module->symbol_table.symbols =
+               kcalloc(nums, sizeof(struct dsp_symbol_entry), GFP_KERNEL);
+       if (!module->symbol_table.symbols)
+               goto error;
+       for (i = 0; i < nums; i++) {
+               struct dsp_symbol_entry *entry =
+                       &module->symbol_table.symbols[i];
+               if (fwlen + 2 + DSP_MAX_SYMBOL_NAME / 4 > fwsize)
+                       goto error_inval;
+               entry->address = le32_to_cpu(fwdat[fwlen++]);
+               memcpy(entry->symbol_name, &fwdat[fwlen], DSP_MAX_SYMBOL_NAME - 1);
+               fwlen += DSP_MAX_SYMBOL_NAME / 4;
+               entry->symbol_type = le32_to_cpu(fwdat[fwlen++]);
+       }
+
+       if (fwlen >= fwsize)
+               goto error_inval;
+       nums = module->nsegments = le32_to_cpu(fwdat[fwlen++]);
+       if (nums > 10)
+               goto error_inval;
+       module->segments =
+               kcalloc(nums, sizeof(struct dsp_segment_desc), GFP_KERNEL);
+       if (!module->segments)
+               goto error;
+       for (i = 0; i < nums; i++) {
+               struct dsp_segment_desc *entry = &module->segments[i];
+               if (fwlen + 3 > fwsize)
+                       goto error_inval;
+               entry->segment_type = le32_to_cpu(fwdat[fwlen++]);
+               entry->offset = le32_to_cpu(fwdat[fwlen++]);
+               entry->size = le32_to_cpu(fwdat[fwlen++]);
+               if (fwlen + entry->size > fwsize)
+                       goto error_inval;
+               entry->data = kmalloc(entry->size * 4, GFP_KERNEL);
+               if (!entry->data)
+                       goto error;
+               memcpy_le32(entry->data, &fwdat[fwlen], entry->size * 4);
+               fwlen += entry->size;
+       }
+
+       *module_ret = module;
+       release_firmware(fw);
+       return 0;
+
+ error_inval:
+       err = -EINVAL;
+ error:
+       free_module_desc(module);
+       release_firmware(fw);
+       return err;
+}
 
 int snd_cs46xx_clear_BA1(struct snd_cs46xx *chip,
                          unsigned long offset,
@@ -361,20 +496,63 @@ int snd_cs46xx_clear_BA1(struct snd_cs46xx *chip,
 
 #else /* old DSP image */
 
-#include "cs46xx_image.h"
+struct ba1_struct {
+       struct {
+               u32 offset;
+               u32 size;
+       } memory[BA1_MEMORY_COUNT];
+       u32 map[BA1_DWORD_SIZE];
+};
+
+MODULE_FIRMWARE("cs46xx/ba1");
+
+static int load_firmware(struct snd_cs46xx *chip)
+{
+       const struct firmware *fw;
+       int i, size, err;
+
+       err = request_firmware(&fw, "cs46xx/ba1", &chip->pci->dev);
+       if (err < 0)
+               return err;
+       if (fw->size != sizeof(*chip->ba1)) {
+               err = -EINVAL;
+               goto error;
+       }
+
+       chip->ba1 = vmalloc(sizeof(*chip->ba1));
+       if (!chip->ba1) {
+               err = -ENOMEM;
+               goto error;
+       }
+
+       memcpy_le32(chip->ba1, fw->data, sizeof(*chip->ba1));
+
+       /* sanity check */
+       size = 0;
+       for (i = 0; i < BA1_MEMORY_COUNT; i++)
+               size += chip->ba1->memory[i].size;
+       if (size > BA1_DWORD_SIZE * 4)
+               err = -EINVAL;
+
+ error:
+       release_firmware(fw);
+       return err;
+}
 
 int snd_cs46xx_download_image(struct snd_cs46xx *chip)
 {
        int idx, err;
-       unsigned long offset = 0;
+       unsigned int offset = 0;
+       struct ba1_struct *ba1 = chip->ba1;
 
        for (idx = 0; idx < BA1_MEMORY_COUNT; idx++) {
-               if ((err = snd_cs46xx_download(chip,
-                                              &BA1Struct.map[offset],
-                                              BA1Struct.memory[idx].offset,
-                                              BA1Struct.memory[idx].size)) < 0)
+               err = snd_cs46xx_download(chip,
+                                         &ba1->map[offset],
+                                         ba1->memory[idx].offset,
+                                         ba1->memory[idx].size);
+               if (err < 0)
                        return err;
-               offset += BA1Struct.memory[idx].size >> 2;
+               offset += ba1->memory[idx].size >> 2;
        }       
        return 0;
 }
@@ -2798,6 +2976,10 @@ static int snd_cs46xx_free(struct snd_cs46xx *chip)
                cs46xx_dsp_spos_destroy(chip);
                chip->dsp_spos_instance = NULL;
        }
+       for (idx = 0; idx < CS46XX_DSP_MODULES; idx++)
+               free_module_desc(chip->modules[idx]);
+#else
+       vfree(chip->ba1);
 #endif
        
 #ifdef CONFIG_PM_SLEEP
@@ -3067,6 +3249,11 @@ static void cs46xx_enable_stream_irqs(struct snd_cs46xx *chip)
 int snd_cs46xx_start_dsp(struct snd_cs46xx *chip)
 {      
        unsigned int tmp;
+#ifdef CONFIG_SND_CS46XX_NEW_DSP
+       int i;
+#endif
+       int err;
+
        /*
         *  Reset the processor.
         */
@@ -3075,45 +3262,33 @@ int snd_cs46xx_start_dsp(struct snd_cs46xx *chip)
         *  Download the image to the processor.
         */
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
-#if 0
-       if (cs46xx_dsp_load_module(chip, &cwcemb80_module) < 0) {
-               snd_printk(KERN_ERR "image download error\n");
-               return -EIO;
-       }
-#endif
-
-       if (cs46xx_dsp_load_module(chip, &cwc4630_module) < 0) {
-               snd_printk(KERN_ERR "image download error [cwc4630]\n");
-               return -EIO;
-       }
-
-       if (cs46xx_dsp_load_module(chip, &cwcasync_module) < 0) {
-               snd_printk(KERN_ERR "image download error [cwcasync]\n");
-               return -EIO;
-       }
-
-       if (cs46xx_dsp_load_module(chip, &cwcsnoop_module) < 0) {
-               snd_printk(KERN_ERR "image download error [cwcsnoop]\n");
-               return -EIO;
-       }
-
-       if (cs46xx_dsp_load_module(chip, &cwcbinhack_module) < 0) {
-               snd_printk(KERN_ERR "image download error [cwcbinhack]\n");
-               return -EIO;
-       }
-
-       if (cs46xx_dsp_load_module(chip, &cwcdma_module) < 0) {
-               snd_printk(KERN_ERR "image download error [cwcdma]\n");
-               return -EIO;
+       for (i = 0; i < CS46XX_DSP_MODULES; i++) {
+               err = load_firmware(chip, &chip->modules[i], module_names[i]);
+               if (err < 0) {
+                       snd_printk(KERN_ERR "firmware load error [%s]\n",
+                                  module_names[i]);
+                       return err;
+               }
+               err = cs46xx_dsp_load_module(chip, chip->modules[i]);
+               if (err < 0) {
+                       snd_printk(KERN_ERR "image download error [%s]\n",
+                                  module_names[i]);
+                       return err;
+               }
        }
 
        if (cs46xx_dsp_scb_and_task_init(chip) < 0)
                return -EIO;
 #else
+       err = load_firmware(chip);
+       if (err < 0)
+               return err;
+
        /* old image */
-       if (snd_cs46xx_download_image(chip) < 0) {
+       err = snd_cs46xx_download_image(chip);
+       if (err < 0) {
                snd_printk(KERN_ERR "image download error\n");
-               return -EIO;
+               return err;
        }
 
        /*
diff --git a/sound/pci/cs46xx/imgs/cwc4630.h b/sound/pci/cs46xx/imgs/cwc4630.h
deleted file mode 100644 (file)
index 37c4f13..0000000
+++ /dev/null
@@ -1,320 +0,0 @@
-/* generated from cwc4630.osp DO NOT MODIFY */
-
-#ifndef __HEADER_cwc4630_H__
-#define __HEADER_cwc4630_H__
-
-static struct dsp_symbol_entry cwc4630_symbols[] = {
-  { 0x0000, "BEGINADDRESS",0x00 },
-  { 0x8000, "EXECCHILD",0x03 },
-  { 0x8001, "EXECCHILD_98",0x03 },
-  { 0x8003, "EXECCHILD_PUSH1IND",0x03 },
-  { 0x8008, "EXECSIBLING",0x03 },
-  { 0x800a, "EXECSIBLING_298",0x03 },
-  { 0x800b, "EXECSIBLING_2IND1",0x03 },
-  { 0x8010, "TIMINGMASTER",0x03 },
-  { 0x804f, "S16_CODECINPUTTASK",0x03 },
-  { 0x805e, "PCMSERIALINPUTTASK",0x03 },
-  { 0x806d, "S16_MIX_TO_OSTREAM",0x03 },
-  { 0x809a, "S16_MIX",0x03 },
-  { 0x80bb, "S16_UPSRC",0x03 },
-  { 0x813b, "MIX3_EXP",0x03 },
-  { 0x8164, "DECIMATEBYPOW2",0x03 },
-  { 0x8197, "VARIDECIMATE",0x03 },
-  { 0x81f2, "_3DINPUTTASK",0x03 },
-  { 0x820a, "_3DPRLGCINPTASK",0x03 },
-  { 0x8227, "_3DSTEREOINPUTTASK",0x03 },
-  { 0x8242, "_3DOUTPUTTASK",0x03 },
-  { 0x82c4, "HRTF_MORPH_TASK",0x03 },
-  { 0x82c6, "WAIT4DATA",0x03 },
-  { 0x82fa, "PROLOGIC",0x03 },
-  { 0x8496, "DECORRELATOR",0x03 },
-  { 0x84a4, "STEREO2MONO",0x03 },
-  { 0x0070, "SPOSCB",0x02 },
-  { 0x0107, "TASKTREETHREAD",0x03 },
-  { 0x013c, "TASKTREEHEADERCODE",0x03 },
-  { 0x0145, "FGTASKTREEHEADERCODE",0x03 },
-  { 0x0169, "NULLALGORITHM",0x03 },
-  { 0x016d, "HFGEXECCHILD",0x03 },
-  { 0x016e, "HFGEXECCHILD_98",0x03 },
-  { 0x0170, "HFGEXECCHILD_PUSH1IND",0x03 },
-  { 0x0173, "HFGEXECSIBLING",0x03 },
-  { 0x0175, "HFGEXECSIBLING_298",0x03 },
-  { 0x0176, "HFGEXECSIBLING_2IND1",0x03 },
-  { 0x0179, "S16_CODECOUTPUTTASK",0x03 },
-  { 0x0194, "#CODE_END",0x00 },
-}; /* cwc4630 symbols */
-
-static u32 cwc4630_code[] = {
-/* BEGINADDRESS */
-/* 0000 */ 0x00040730,0x00001002,0x000f619e,0x00001003,
-/* 0002 */ 0x00001705,0x00001400,0x000a411e,0x00001003,
-/* 0004 */ 0x00040730,0x00001002,0x000f619e,0x00001003,
-/* 0006 */ 0x00009705,0x00001400,0x000a411e,0x00001003,
-/* 0008 */ 0x00040730,0x00001002,0x000f619e,0x00001003,
-/* 000A */ 0x00011705,0x00001400,0x000a411e,0x00001003,
-/* 000C */ 0x00040730,0x00001002,0x000f619e,0x00001003,
-/* 000E */ 0x00019705,0x00001400,0x000a411e,0x00001003,
-/* 0010 */ 0x00040730,0x00001002,0x000f619e,0x00001003,
-/* 0012 */ 0x00021705,0x00001400,0x000a411e,0x00001003,
-/* 0014 */ 0x00040730,0x00001002,0x000f619e,0x00001003,
-/* 0016 */ 0x00029705,0x00001400,0x000a411e,0x00001003,
-/* 0018 */ 0x00040730,0x00001002,0x000f619e,0x00001003,
-/* 001A */ 0x00031705,0x00001400,0x000a411e,0x00001003,
-/* 001C */ 0x00040730,0x00001002,0x000f619e,0x00001003,
-/* 001E */ 0x00039705,0x00001400,0x000a411e,0x00001003,
-/* 0020 */ 0x000fe19e,0x00001003,0x0009c730,0x00001003,
-/* 0022 */ 0x0008e19c,0x00001003,0x000083c1,0x00093040,
-/* 0024 */ 0x00098730,0x00001002,0x000ee19e,0x00001003,
-/* 0026 */ 0x00009705,0x00001400,0x000a211e,0x00001003,
-/* 0028 */ 0x00098730,0x00001002,0x000ee19e,0x00001003,
-/* 002A */ 0x00011705,0x00001400,0x000a211e,0x00001003,
-/* 002C */ 0x00098730,0x00001002,0x000ee19e,0x00001003,
-/* 002E */ 0x00019705,0x00001400,0x000a211e,0x00001003,
-/* 0030 */ 0x00098730,0x00001002,0x000ee19e,0x00001003,
-/* 0032 */ 0x00021705,0x00001400,0x000a211e,0x00001003,
-/* 0034 */ 0x00098730,0x00001002,0x000ee19e,0x00001003,
-/* 0036 */ 0x00029705,0x00001400,0x000a211e,0x00001003,
-/* 0038 */ 0x00098730,0x00001002,0x000ee19e,0x00001003,
-/* 003A */ 0x00031705,0x00001400,0x000a211e,0x00001003,
-/* 003C */ 0x00098730,0x00001002,0x000ee19e,0x00001003,
-/* 003E */ 0x00039705,0x00001400,0x000a211e,0x00001003,
-/* 0040 */ 0x0001a730,0x00001008,0x000e2730,0x00001002,
-/* 0042 */ 0x0000a731,0x00001002,0x0000a731,0x00001002,
-/* 0044 */ 0x0000a731,0x00001002,0x0000a731,0x00001002,
-/* 0046 */ 0x0000a731,0x00001002,0x0000a731,0x00001002,
-/* 0048 */ 0x00000000,0x00000000,0x000f619c,0x00001003,
-/* 004A */ 0x0007f801,0x000c0000,0x00000037,0x00001000,
-/* 004C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 004E */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0050 */ 0x00000000,0x000c0000,0x00000000,0x00000000,
-/* 0052 */ 0x0000373c,0x00001000,0x00000000,0x00000000,
-/* 0054 */ 0x000ee19c,0x00001003,0x0007f801,0x000c0000,
-/* 0056 */ 0x00000037,0x00001000,0x00000000,0x00000000,
-/* 0058 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 005A */ 0x00000000,0x00000000,0x0000273c,0x00001000,
-/* 005C */ 0x00000033,0x00001000,0x000e679e,0x00001003,
-/* 005E */ 0x00007705,0x00001400,0x000ac71e,0x00001003,
-/* 0060 */ 0x00087fc1,0x000c3be0,0x0007f801,0x000c0000,
-/* 0062 */ 0x00000037,0x00001000,0x00000000,0x00000000,
-/* 0064 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0066 */ 0x00000000,0x00000000,0x0000a730,0x00001003,
-/* 0068 */ 0x00000033,0x00001000,0x0007f801,0x000c0000,
-/* 006A */ 0x00000037,0x00001000,0x00000000,0x00000000,
-/* 006C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 006E */ 0x00000000,0x00000000,0x00000000,0x000c0000,
-/* 0070 */ 0x00000032,0x00001000,0x0000273d,0x00001000,
-/* 0072 */ 0x0004a730,0x00001003,0x00000f41,0x00097140,
-/* 0074 */ 0x0000a841,0x0009b240,0x0000a0c1,0x0009f040,
-/* 0076 */ 0x0001c641,0x00093540,0x0001cec1,0x0009b5c0,
-/* 0078 */ 0x00000000,0x00000000,0x0001bf05,0x0003fc40,
-/* 007A */ 0x00002725,0x000aa400,0x00013705,0x00093a00,
-/* 007C */ 0x0000002e,0x0009d6c0,0x0002ef8a,0x00000000,
-/* 007E */ 0x00040630,0x00001004,0x0004ef0a,0x000eb785,
-/* 0080 */ 0x0003fc8a,0x00000000,0x00000000,0x000c70e0,
-/* 0082 */ 0x0007d182,0x0002c640,0x00008630,0x00001004,
-/* 0084 */ 0x000799b8,0x0002c6c0,0x00031705,0x00092240,
-/* 0086 */ 0x00039f05,0x000932c0,0x0003520a,0x00000000,
-/* 0088 */ 0x00070731,0x0000100b,0x00010705,0x000b20c0,
-/* 008A */ 0x00000000,0x000eba44,0x00032108,0x000c60c4,
-/* 008C */ 0x00065208,0x000c2917,0x000486b0,0x00001007,
-/* 008E */ 0x00012f05,0x00036880,0x0002818e,0x000c0000,
-/* 0090 */ 0x0004410a,0x00000000,0x00048630,0x00001007,
-/* 0092 */ 0x00029705,0x000c0000,0x00000000,0x00000000,
-/* 0094 */ 0x00003fc1,0x0003fc40,0x000037c1,0x00091b40,
-/* 0096 */ 0x00003fc1,0x000911c0,0x000037c1,0x000957c0,
-/* 0098 */ 0x00003fc1,0x000951c0,0x000037c1,0x00000000,
-/* 009A */ 0x00003fc1,0x000991c0,0x000037c1,0x00000000,
-/* 009C */ 0x00003fc1,0x0009d1c0,0x000037c1,0x00000000,
-/* 009E */ 0x0001ccc1,0x000915c0,0x0001c441,0x0009d800,
-/* 00A0 */ 0x0009cdc1,0x00091240,0x0001c541,0x00091d00,
-/* 00A2 */ 0x0009cfc1,0x00095240,0x0001c741,0x00095c80,
-/* 00A4 */ 0x000e8ca9,0x00099240,0x000e85ad,0x00095640,
-/* 00A6 */ 0x00069ca9,0x00099d80,0x000e952d,0x00099640,
-/* 00A8 */ 0x000eaca9,0x0009d6c0,0x000ea5ad,0x00091a40,
-/* 00AA */ 0x0006bca9,0x0009de80,0x000eb52d,0x00095a40,
-/* 00AC */ 0x000ecca9,0x00099ac0,0x000ec5ad,0x0009da40,
-/* 00AE */ 0x000edca9,0x0009d300,0x000a6e0a,0x00001000,
-/* 00B0 */ 0x000ed52d,0x00091e40,0x000eeca9,0x00095ec0,
-/* 00B2 */ 0x000ee5ad,0x00099e40,0x0006fca9,0x00002500,
-/* 00B4 */ 0x000fb208,0x000c59a0,0x000ef52d,0x0009de40,
-/* 00B6 */ 0x00068ca9,0x000912c1,0x000683ad,0x00095241,
-/* 00B8 */ 0x00020f05,0x000991c1,0x00000000,0x00000000,
-/* 00BA */ 0x00086f88,0x00001000,0x0009cf81,0x000b5340,
-/* 00BC */ 0x0009c701,0x000b92c0,0x0009de81,0x000bd300,
-/* 00BE */ 0x0009d601,0x000b1700,0x0001fd81,0x000b9d80,
-/* 00C0 */ 0x0009f501,0x000b57c0,0x000a0f81,0x000bd740,
-/* 00C2 */ 0x00020701,0x000b5c80,0x000a1681,0x000b97c0,
-/* 00C4 */ 0x00021601,0x00002500,0x000a0701,0x000b9b40,
-/* 00C6 */ 0x000a0f81,0x000b1bc0,0x00021681,0x00002d00,
-/* 00C8 */ 0x00020f81,0x000bd800,0x000a0701,0x000b5bc0,
-/* 00CA */ 0x00021601,0x00003500,0x000a0f81,0x000b5f40,
-/* 00CC */ 0x000a0701,0x000bdbc0,0x00021681,0x00003d00,
-/* 00CE */ 0x00020f81,0x000b1d00,0x000a0701,0x000b1fc0,
-/* 00D0 */ 0x00021601,0x00020500,0x00020f81,0x000b1341,
-/* 00D2 */ 0x000a0701,0x000b9fc0,0x00021681,0x00020d00,
-/* 00D4 */ 0x00020f81,0x000bde80,0x000a0701,0x000bdfc0,
-/* 00D6 */ 0x00021601,0x00021500,0x00020f81,0x000b9341,
-/* 00D8 */ 0x00020701,0x000b53c1,0x00021681,0x00021d00,
-/* 00DA */ 0x000a0f81,0x000d0380,0x0000b601,0x000b15c0,
-/* 00DC */ 0x00007b01,0x00000000,0x00007b81,0x000bd1c0,
-/* 00DE */ 0x00007b01,0x00000000,0x00007b81,0x000b91c0,
-/* 00E0 */ 0x00007b01,0x000b57c0,0x00007b81,0x000b51c0,
-/* 00E2 */ 0x00007b01,0x000b1b40,0x00007b81,0x000b11c0,
-/* 00E4 */ 0x00087b01,0x000c3dc0,0x0007e488,0x000d7e45,
-/* 00E6 */ 0x00000000,0x000d7a44,0x0007e48a,0x00000000,
-/* 00E8 */ 0x00011f05,0x00084080,0x00000000,0x00000000,
-/* 00EA */ 0x00001705,0x000b3540,0x00008a01,0x000bf040,
-/* 00EC */ 0x00007081,0x000bb5c0,0x00055488,0x00000000,
-/* 00EE */ 0x0000d482,0x0003fc40,0x0003fc88,0x00000000,
-/* 00F0 */ 0x0001e401,0x000b3a00,0x0001ec81,0x000bd6c0,
-/* 00F2 */ 0x0002ef88,0x000e7784,0x00056f08,0x00000000,
-/* 00F4 */ 0x000d86b0,0x00001007,0x00008281,0x000bb240,
-/* 00F6 */ 0x0000b801,0x000b7140,0x00007888,0x00000000,
-/* 00F8 */ 0x0000073c,0x00001000,0x0007f188,0x000c0000,
-/* 00FA */ 0x00000000,0x00000000,0x00055288,0x000c555c,
-/* 00FC */ 0x0005528a,0x000c0000,0x0009fa88,0x000c5d00,
-/* 00FE */ 0x0000fa88,0x00000000,0x00000032,0x00001000,
-/* 0100 */ 0x0000073d,0x00001000,0x0007f188,0x000c0000,
-/* 0102 */ 0x00000000,0x00000000,0x0008c01c,0x00001003,
-/* 0104 */ 0x00002705,0x00001008,0x0008b201,0x000c1392,
-/* 0106 */ 0x0000ba01,0x00000000,
-/* TASKTREETHREAD */
-/* 0107 */ 0x00008731,0x00001400,0x0004c108,0x000fe0c4,
-/* 0109 */ 0x00057488,0x00000000,0x000a6388,0x00001001,
-/* 010B */ 0x0008b334,0x000bc141,0x0003020e,0x00000000,
-/* 010D */ 0x000986b0,0x00001008,0x00003625,0x000c5dfa,
-/* 010F */ 0x000a638a,0x00001001,0x0008020e,0x00001002,
-/* 0111 */ 0x0009a6b0,0x00001008,0x0007f301,0x00000000,
-/* 0113 */ 0x00000000,0x00000000,0x00002725,0x000a8c40,
-/* 0115 */ 0x000000ae,0x00000000,0x000e8630,0x00001008,
-/* 0117 */ 0x00000000,0x000c74e0,0x0007d182,0x0002d640,
-/* 0119 */ 0x000b8630,0x00001008,0x000799b8,0x0002d6c0,
-/* 011B */ 0x0000748a,0x000c3ec5,0x0007420a,0x000c0000,
-/* 011D */ 0x00062208,0x000c4117,0x000a0630,0x00001009,
-/* 011F */ 0x00000000,0x000c0000,0x0001022e,0x00000000,
-/* 0121 */ 0x0006a630,0x00001009,0x00000032,0x00001000,
-/* 0123 */ 0x000ca21c,0x00001003,0x00005a02,0x00000000,
-/* 0125 */ 0x0001a630,0x00001009,0x00000000,0x000c0000,
-/* 0127 */ 0x00000036,0x00001000,0x00000000,0x00000000,
-/* 0129 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 012B */ 0x00000000,0x00000000,0x0003a730,0x00001008,
-/* 012D */ 0x0007f801,0x000c0000,0x00000037,0x00001000,
-/* 012F */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0131 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0133 */ 0x0003a730,0x00001008,0x00000033,0x00001000,
-/* 0135 */ 0x0003a705,0x00001008,0x00007a01,0x000c0000,
-/* 0137 */ 0x000e6288,0x000d550a,0x0006428a,0x00000000,
-/* 0139 */ 0x00090730,0x0000100a,0x00000000,0x000c0000,
-/* 013B */ 0x00000000,0x00000000,
-/* TASKTREEHEADERCODE */
-/* 013C */ 0x0007aab0,0x00034880,0x000a8fb0,0x0000100b,
-/* 013E */ 0x00057488,0x00000000,0x00033b94,0x00081140,
-/* 0140 */ 0x000183ae,0x00000000,0x000a86b0,0x0000100b,
-/* 0142 */ 0x00022f05,0x000c3545,0x0000eb8a,0x00000000,
-/* 0144 */ 0x00042731,0x00001003,
-/* FGTASKTREEHEADERCODE */
-/* 0145 */ 0x0007aab0,0x00034880,0x00078fb0,0x0000100a,
-/* 0147 */ 0x00057488,0x00000000,0x00033b94,0x00081140,
-/* 0149 */ 0x000183ae,0x00000000,0x000b06b0,0x0000100b,
-/* 014B */ 0x00022f05,0x00000000,0x00007401,0x00091140,
-/* 014D */ 0x00048f05,0x000951c0,0x00042731,0x00001003,
-/* 014F */ 0x0000473d,0x00001000,0x000f19b0,0x000bbc47,
-/* 0151 */ 0x00080000,0x000bffc7,0x000fe19e,0x00001003,
-/* 0153 */ 0x00000000,0x00000000,0x0008e19c,0x00001003,
-/* 0155 */ 0x000083c1,0x00093040,0x00000f41,0x00097140,
-/* 0157 */ 0x0000a841,0x0009b240,0x0000a0c1,0x0009f040,
-/* 0159 */ 0x0001c641,0x00093540,0x0001cec1,0x0009b5c0,
-/* 015B */ 0x00000000,0x000fdc44,0x00055208,0x00000000,
-/* 015D */ 0x00010705,0x000a2880,0x0000a23a,0x00093a00,
-/* 015F */ 0x0003fc8a,0x000df6c5,0x0004ef0a,0x000c0000,
-/* 0161 */ 0x00012f05,0x00036880,0x00065308,0x000c2997,
-/* 0163 */ 0x000086b0,0x0000100b,0x0004410a,0x000d40c7,
-/* 0165 */ 0x00000000,0x00000000,0x00088730,0x00001004,
-/* 0167 */ 0x00056f0a,0x000ea105,0x00000000,0x00000000,
-/* NULLALGORITHM */
-/* 0169 */ 0x0000473d,0x00001000,0x000f19b0,0x000bbc47,
-/* 016B */ 0x00080000,0x000bffc7,0x0000273d,0x00001000,
-/* HFGEXECCHILD */
-/* 016D */ 0x00000000,0x000eba44,
-/* HFGEXECCHILD_98 */
-/* 016E */ 0x00048f05,0x0000f440,0x00007401,0x0000f7c0,
-/* HFGEXECCHILD_PUSH1IND */
-/* 0170 */ 0x00000734,0x00001000,0x00010705,0x000a6880,
-/* 0172 */ 0x00006a88,0x000c75c4,
-/* HFGEXECSIBLING */
-/* 0173 */ 0x00000000,0x000e5084,0x00000000,0x000eba44,
-/* HFGEXECSIBLING_298 */
-/* 0175 */ 0x00087401,0x000e4782,
-/* HFGEXECSIBLING_2IND1 */
-/* 0176 */ 0x00000734,0x00001000,0x00010705,0x000a6880,
-/* 0178 */ 0x00006a88,0x000c75c4,
-/* S16_CODECOUTPUTTASK */
-/* 0179 */ 0x0007c108,0x000c0000,0x0007e721,0x000bed40,
-/* 017B */ 0x00005f25,0x000badc0,0x0003ba97,0x000beb80,
-/* 017D */ 0x00065590,0x000b2e00,0x00033217,0x00003ec0,
-/* 017F */ 0x00065590,0x000b8e40,0x0003ed80,0x000491c0,
-/* 0181 */ 0x00073fb0,0x00074c80,0x000583a0,0x0000100c,
-/* 0183 */ 0x000ee388,0x00042970,0x00008301,0x00021ef2,
-/* 0185 */ 0x000b8f14,0x0000000f,0x000c4d8d,0x0000001b,
-/* 0187 */ 0x000d6dc2,0x000e06c6,0x000032ac,0x000c3916,
-/* 0189 */ 0x0004edc2,0x00074c80,0x00078898,0x00001000,
-/* 018B */ 0x00038894,0x00000032,0x000c4d8d,0x00092e1b,
-/* 018D */ 0x000d6dc2,0x000e06c6,0x0004edc2,0x000c1956,
-/* 018F */ 0x0000722c,0x00034a00,0x00041705,0x0009ed40,
-/* 0191 */ 0x00058730,0x00001400,0x000d7488,0x000c3a00,
-/* 0193 */ 0x00048f05,0x00000000
-};
-/* #CODE_END */
-
-static u32 cwc4630_parameter[] = {
-/* 0000 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0004 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0008 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 000C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0010 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0014 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0018 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 001C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0020 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0024 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0028 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 002C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0030 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0034 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0038 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 003C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0040 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0044 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0048 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 004C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0050 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0054 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0058 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 005C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0060 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0064 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0068 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 006C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0070 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0074 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0078 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 007C */ 0x00000000,0x00000000,0x00000000,0x00000000
-}; /* #PARAMETER_END */
-
-
-static struct dsp_segment_desc cwc4630_segments[] = {
-  { SEGTYPE_SP_PROGRAM, 0x00000000, 0x00000328, cwc4630_code },
-  { SEGTYPE_SP_PARAMETER, 0x00000000, 0x00000080, cwc4630_parameter },
-};
-
-static struct dsp_module_desc cwc4630_module = {
-  "cwc4630",
-  {
-    38,
-    cwc4630_symbols
-  },
-  2,
-  cwc4630_segments,
-};
-
-#endif /* __HEADER_cwc4630_H__ */
diff --git a/sound/pci/cs46xx/imgs/cwcasync.h b/sound/pci/cs46xx/imgs/cwcasync.h
deleted file mode 100644 (file)
index 70e63e1..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-/* generated from cwcasync.osp DO NOT MODIFY */
-
-#ifndef __HEADER_cwcasync_H__
-#define __HEADER_cwcasync_H__
-
-static struct dsp_symbol_entry cwcasync_symbols[] = {
-  { 0x8000, "EXECCHILD",0x03 },
-  { 0x8001, "EXECCHILD_98",0x03 },
-  { 0x8003, "EXECCHILD_PUSH1IND",0x03 },
-  { 0x8008, "EXECSIBLING",0x03 },
-  { 0x800a, "EXECSIBLING_298",0x03 },
-  { 0x800b, "EXECSIBLING_2IND1",0x03 },
-  { 0x8010, "TIMINGMASTER",0x03 },
-  { 0x804f, "S16_CODECINPUTTASK",0x03 },
-  { 0x805e, "PCMSERIALINPUTTASK",0x03 },
-  { 0x806d, "S16_MIX_TO_OSTREAM",0x03 },
-  { 0x809a, "S16_MIX",0x03 },
-  { 0x80bb, "S16_UPSRC",0x03 },
-  { 0x813b, "MIX3_EXP",0x03 },
-  { 0x8164, "DECIMATEBYPOW2",0x03 },
-  { 0x8197, "VARIDECIMATE",0x03 },
-  { 0x81f2, "_3DINPUTTASK",0x03 },
-  { 0x820a, "_3DPRLGCINPTASK",0x03 },
-  { 0x8227, "_3DSTEREOINPUTTASK",0x03 },
-  { 0x8242, "_3DOUTPUTTASK",0x03 },
-  { 0x82c4, "HRTF_MORPH_TASK",0x03 },
-  { 0x82c6, "WAIT4DATA",0x03 },
-  { 0x82fa, "PROLOGIC",0x03 },
-  { 0x8496, "DECORRELATOR",0x03 },
-  { 0x84a4, "STEREO2MONO",0x03 },
-  { 0x0000, "OVERLAYBEGINADDRESS",0x00 },
-  { 0x0000, "SPIOWRITE",0x03 },
-  { 0x000d, "S16_ASYNCCODECINPUTTASK",0x03 },
-  { 0x0043, "SPDIFITASK",0x03 },
-  { 0x007b, "SPDIFOTASK",0x03 },
-  { 0x0097, "ASYNCHFGTXCODE",0x03 },
-  { 0x00be, "ASYNCHFGRXCODE",0x03 },
-  { 0x00db, "#CODE_END",0x00 },
-}; /* cwcasync symbols */
-
-static u32 cwcasync_code[] = {
-/* OVERLAYBEGINADDRESS */
-/* 0000 */ 0x00002731,0x00001400,0x00003725,0x000a8440,
-/* 0002 */ 0x000000ae,0x00000000,0x00060630,0x00001000,
-/* 0004 */ 0x00000000,0x000c7560,0x00075282,0x0002d640,
-/* 0006 */ 0x00021705,0x00000000,0x00072ab8,0x0002d6c0,
-/* 0008 */ 0x00020630,0x00001000,0x000c74c2,0x000d4b82,
-/* 000A */ 0x000475c2,0x00000000,0x0003430a,0x000c0000,
-/* 000C */ 0x00042730,0x00001400,
-/* S16_ASYNCCODECINPUTTASK */
-/* 000D */ 0x0006a108,0x000cf2c4,0x0004f4c0,0x00000000,
-/* 000F */ 0x000fa418,0x0000101f,0x0005d402,0x0001c500,
-/* 0011 */ 0x000f0630,0x00001000,0x00004418,0x00001380,
-/* 0013 */ 0x000e243d,0x000d394a,0x00049705,0x00000000,
-/* 0015 */ 0x0007d530,0x000b4240,0x000e00f2,0x00001000,
-/* 0017 */ 0x00009134,0x000ca20a,0x00004c90,0x00001000,
-/* 0019 */ 0x0005d705,0x00000000,0x00004f25,0x00098240,
-/* 001B */ 0x00004725,0x00000000,0x0000e48a,0x00000000,
-/* 001D */ 0x00027295,0x0009c2c0,0x0003df25,0x00000000,
-/* 001F */ 0x000e8030,0x00001001,0x0005f718,0x000ac600,
-/* 0021 */ 0x0007cf30,0x000c2a01,0x00082630,0x00001001,
-/* 0023 */ 0x000504a0,0x00001001,0x00029314,0x000bcb80,
-/* 0025 */ 0x0003cf25,0x000b0e00,0x0004f5c0,0x00000000,
-/* 0027 */ 0x00049118,0x000d888a,0x0007dd02,0x000c6efa,
-/* 0029 */ 0x00000000,0x00000000,0x0004f5c0,0x00069c80,
-/* 002B */ 0x0000d402,0x00000000,0x000e8630,0x00001001,
-/* 002D */ 0x00079130,0x00000000,0x00049118,0x00090e00,
-/* 002F */ 0x0006c10a,0x00000000,0x00000000,0x000c0000,
-/* 0031 */ 0x0007cf30,0x00030580,0x00005725,0x00000000,
-/* 0033 */ 0x000d84a0,0x00001001,0x00029314,0x000b4780,
-/* 0035 */ 0x0003cf25,0x000b8600,0x00000000,0x00000000,
-/* 0037 */ 0x00000000,0x000c0000,0x00000000,0x00042c80,
-/* 0039 */ 0x0001dec1,0x000e488c,0x00031114,0x00000000,
-/* 003B */ 0x0004f5c2,0x00000000,0x0003640a,0x00000000,
-/* 003D */ 0x00000000,0x000e5084,0x00000000,0x000eb844,
-/* 003F */ 0x00007001,0x00000000,0x00000734,0x00001000,
-/* 0041 */ 0x00010705,0x000a6880,0x00006a88,0x000c75c4,
-/* SPDIFITASK */
-/* 0043 */ 0x0006a108,0x000cf2c4,0x0004f4c0,0x000d5384,
-/* 0045 */ 0x0007e48a,0x00000000,0x00067718,0x00001000,
-/* 0047 */ 0x0007a418,0x00001000,0x0007221a,0x00000000,
-/* 0049 */ 0x0005d402,0x00014500,0x000b8630,0x00001002,
-/* 004B */ 0x00004418,0x00001780,0x000e243d,0x000d394a,
-/* 004D */ 0x00049705,0x00000000,0x0007d530,0x000b4240,
-/* 004F */ 0x000ac0f2,0x00001002,0x00014414,0x00000000,
-/* 0051 */ 0x00004c90,0x00001000,0x0005d705,0x00000000,
-/* 0053 */ 0x00004f25,0x00098240,0x00004725,0x00000000,
-/* 0055 */ 0x0000e48a,0x00000000,0x00027295,0x0009c2c0,
-/* 0057 */ 0x0007df25,0x00000000,0x000ac030,0x00001003,
-/* 0059 */ 0x0005f718,0x000fe798,0x00029314,0x000bcb80,
-/* 005B */ 0x00000930,0x000b0e00,0x0004f5c0,0x000de204,
-/* 005D */ 0x000884a0,0x00001003,0x0007cf25,0x000e3560,
-/* 005F */ 0x00049118,0x00000000,0x00049118,0x000d888a,
-/* 0061 */ 0x0007dd02,0x000c6efa,0x0000c434,0x00030040,
-/* 0063 */ 0x000fda82,0x000c2312,0x000fdc0e,0x00001001,
-/* 0065 */ 0x00083402,0x000c2b92,0x000706b0,0x00001003,
-/* 0067 */ 0x00075a82,0x00000000,0x0000d625,0x000b0940,
-/* 0069 */ 0x0000840e,0x00001002,0x0000aabc,0x000c511e,
-/* 006B */ 0x00078730,0x00001003,0x0000aaf4,0x000e910a,
-/* 006D */ 0x0004628a,0x00000000,0x00006aca,0x00000000,
-/* 006F */ 0x00000930,0x00000000,0x0004f5c0,0x00069c80,
-/* 0071 */ 0x00046ac0,0x00000000,0x0003c40a,0x000fc898,
-/* 0073 */ 0x00049118,0x00090e00,0x0006c10a,0x00000000,
-/* 0075 */ 0x00000000,0x000e5084,0x00000000,0x000eb844,
-/* 0077 */ 0x00007001,0x00000000,0x00000734,0x00001000,
-/* 0079 */ 0x00010705,0x000a6880,0x00006a88,0x000c75c4,
-/* SPDIFOTASK */
-/* 007B */ 0x0006a108,0x000c0000,0x0004f4c0,0x000c3245,
-/* 007D */ 0x0000a418,0x00001000,0x0003a20a,0x00000000,
-/* 007F */ 0x00004418,0x00001380,0x000e243d,0x000d394a,
-/* 0081 */ 0x000c9705,0x000def92,0x0008c030,0x00001004,
-/* 0083 */ 0x0005f718,0x000fe798,0x00000000,0x000c0000,
-/* 0085 */ 0x00005725,0x00000000,0x000704a0,0x00001004,
-/* 0087 */ 0x00029314,0x000b4780,0x0003cf25,0x000b8600,
-/* 0089 */ 0x00000000,0x00000000,0x00000000,0x000c0000,
-/* 008B */ 0x00000000,0x00042c80,0x0001dec1,0x000e488c,
-/* 008D */ 0x00031114,0x00000000,0x0004f5c2,0x00000000,
-/* 008F */ 0x0004a918,0x00098600,0x0006c28a,0x00000000,
-/* 0091 */ 0x00000000,0x000e5084,0x00000000,0x000eb844,
-/* 0093 */ 0x00007001,0x00000000,0x00000734,0x00001000,
-/* 0095 */ 0x00010705,0x000a6880,0x00006a88,0x000c75c4,
-/* ASYNCHFGTXCODE */
-/* 0097 */ 0x0002a880,0x000b4e40,0x00042214,0x000e5548,
-/* 0099 */ 0x000542bf,0x00000000,0x00000000,0x000481c0,
-/* 009B */ 0x00000000,0x00000000,0x00000000,0x00000030,
-/* 009D */ 0x0000072d,0x000fbf8a,0x00077f94,0x000ea7df,
-/* 009F */ 0x0002ac95,0x000d3145,0x00002731,0x00001400,
-/* 00A1 */ 0x00006288,0x000c71c4,0x00014108,0x000e6044,
-/* 00A3 */ 0x00035408,0x00000000,0x00025418,0x000a0ec0,
-/* 00A5 */ 0x0001443d,0x000ca21e,0x00046595,0x000d730c,
-/* 00A7 */ 0x0006538e,0x00000000,0x00064630,0x00001005,
-/* 00A9 */ 0x000e7b0e,0x000df782,0x000746b0,0x00001005,
-/* 00AB */ 0x00036f05,0x000c0000,0x00043695,0x000d598c,
-/* 00AD */ 0x0005331a,0x000f2185,0x00000000,0x00000000,
-/* 00AF */ 0x000007ae,0x000bdb00,0x00040630,0x00001400,
-/* 00B1 */ 0x0005e708,0x000c0000,0x0007ef30,0x000b1c00,
-/* 00B3 */ 0x000d86a0,0x00001005,0x00066408,0x000c0000,
-/* 00B5 */ 0x00000000,0x00000000,0x00021843,0x00000000,
-/* 00B7 */ 0x00000cac,0x00062c00,0x00001dac,0x00063400,
-/* 00B9 */ 0x00002cac,0x0006cc80,0x000db943,0x000e5ca1,
-/* 00BB */ 0x00000000,0x00000000,0x0006680a,0x000f3205,
-/* 00BD */ 0x00042730,0x00001400,
-/* ASYNCHFGRXCODE */
-/* 00BE */ 0x00014108,0x000f2204,0x00025418,0x000a2ec0,
-/* 00C0 */ 0x00015dbd,0x00038100,0x00015dbc,0x00000000,
-/* 00C2 */ 0x0005e415,0x00034880,0x0001258a,0x000d730c,
-/* 00C4 */ 0x0006538e,0x000baa40,0x00060630,0x00001006,
-/* 00C6 */ 0x00067b0e,0x000ac380,0x0003ef05,0x00000000,
-/* 00C8 */ 0x0000f734,0x0001c300,0x000586b0,0x00001400,
-/* 00CA */ 0x000b6f05,0x000c3a00,0x00048f05,0x00000000,
-/* 00CC */ 0x0005b695,0x0008c380,0x0002058e,0x00000000,
-/* 00CE */ 0x000500b0,0x00001400,0x0002b318,0x000e998d,
-/* 00D0 */ 0x0006430a,0x00000000,0x00000000,0x000ef384,
-/* 00D2 */ 0x00004725,0x000c0000,0x00000000,0x000f3204,
-/* 00D4 */ 0x00004f25,0x000c0000,0x00080000,0x000e5ca1,
-/* 00D6 */ 0x000cb943,0x000e5ca1,0x0004b943,0x00000000,
-/* 00D8 */ 0x00040730,0x00001400,0x000cb943,0x000e5ca1,
-/* 00DA */ 0x0004b943,0x00000000
-};
-/* #CODE_END */
-
-static struct dsp_segment_desc cwcasync_segments[] = {
-  { SEGTYPE_SP_PROGRAM, 0x00000000, 0x000001b6, cwcasync_code },
-};
-
-static struct dsp_module_desc cwcasync_module = {
-  "cwcasync",
-  {
-    32,
-    cwcasync_symbols
-  },
-  1,
-  cwcasync_segments,
-};
-
-#endif /* __HEADER_cwcasync_H__ */
diff --git a/sound/pci/cs46xx/imgs/cwcbinhack.h b/sound/pci/cs46xx/imgs/cwcbinhack.h
deleted file mode 100644 (file)
index f4d9368..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/* generated by Benny 
-   MODIFY ON YOUR OWN RISK */
-
-#ifndef __HEADER_cwcbinhack_H__
-#define __HEADER_cwcbinhack_H__
-
-static struct dsp_symbol_entry cwcbinhack_symbols[] = {
-  { 0x02c8, "OVERLAYBEGINADDRESS",0x00 },
-  { 0x02c8, "MAGICSNOOPTASK",0x03 },
-  { 0x0308, "#CODE_END",0x00 },
-}; /* cwcbinhack symbols */
-
-static u32 cwcbinhack_code[] = {
-  /* 0x02c8 */
-  0x0007bfb0,0x000bc240,0x00000c2e,0x000c6084, /* 1 */
-  0x000b8630,0x00001016,0x00006408,0x000efb84, /* 2 */
-  0x00016008,0x00000000,0x0001c088,0x000c0000, /* 3 */
-  0x000fc908,0x000e3392,0x0005f488,0x000efb84, /* 4 */
-  0x0001d402,0x000b2e00,0x0003d418,0x00001000, /* 5 */
-  0x0008d574,0x000c4293,0x00065625,0x000ea30e, /* 6 */
-  0x00096c01,0x000c6f92,0x0001a58a,0x000c6085, /* 7 */
-  0x00002f43,0x00000000,0x000e03a0,0x00001016, /* 8 */
-  0x0005e608,0x000c0000,0x00000000,0x00000000, /* 9 */
-  0x000ca108,0x000dcca1,0x00003bac,0x000c3205, /* 10 */
-  0x00073843,0x00000000,0x00010730,0x00001017, /* 11 */
-  0x0001600a,0x000c0000,0x00057488,0x00000000, /* 12 */
-  0x00000000,0x000e5084,0x00000000,0x000eba44, /* 13 */
-  0x00087401,0x000e4782,0x00000734,0x00001000, /* 14 */
-  0x00010705,0x000a6880,0x00006a88,0x000c75c4, /* 15 */
-  0x00000000,0x00000000,0x00000000,0x00000000, /* 16 */
-};
-/* #CODE_END */
-
-static struct dsp_segment_desc cwcbinhack_segments[] = {
-  { SEGTYPE_SP_PROGRAM, 0x00000000, 64, cwcbinhack_code },
-};
-
-static struct dsp_module_desc cwcbinhack_module = {
-  "cwcbinhack",
-  {
-    3,
-    cwcbinhack_symbols
-  },
-  1,
-  cwcbinhack_segments,
-};
-
-#endif /* __HEADER_cwcbinhack_H__ */
diff --git a/sound/pci/cs46xx/imgs/cwcdma.asp b/sound/pci/cs46xx/imgs/cwcdma.asp
deleted file mode 100644 (file)
index a65e119..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-// 
-//  Copyright(c) by Benny Sjostrand (benny@hostmobility.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
-//
-
-
-//
-// This code runs inside the DSP (cs4610, cs4612, cs4624, or cs4630),
-// to compile it you need a tool named SPASM 3.0 and DSP code owned by 
-// Cirrus Logic(R). The SPASM program will generate a object file (cwcdma.osp),
-// the "ospparser"  tool will genereate the cwcdma.h file it's included from
-// the cs46xx_lib.c file.
-//
-//
-// The purpose of this code is very simple: make it possible to tranfser
-// the samples 'as they are' with no alteration from a PCMreader
-// SCB (DMA from host) to any other SCB. This is useful for AC3 through SPDIF.
-// SRC (source rate converters) task always alters the samples in somehow,
-// however it's from 48khz -> 48khz.
-// The alterations are not audible, but AC3 wont work. 
-//
-//        ...
-//         |
-// +---------------+
-// | AsynchFGTxSCB |
-// +---------------+
-//        |
-//    subListPtr
-//        |
-// +--------------+
-// |   DMAReader  |
-// +--------------+
-//        |
-//    subListPtr
-//        |
-// +-------------+
-// | PCMReader   |
-// +-------------+
-// (DMA from host)
-//
-
-struct dmaSCB
-  {
-    long  dma_reserved1[3];
-
-    short dma_reserved2:dma_outBufPtr;
-
-    short dma_unused1:dma_unused2;
-
-    long  dma_reserved3[4];
-
-    short dma_subListPtr:dma_nextSCB;
-    short dma_SPBptr:dma_entryPoint;
-
-    long  dma_strmRsConfig;
-    long  dma_strmBufPtr;
-
-    long  dma_reserved4;
-
-    VolumeControl s2m_volume;
-  };
-
-#export DMAReader
-void DMAReader()
-{
-  execChild();
-  r2 = r0->dma_subListPtr;
-  r1 = r0->nextSCB;
-       
-  rsConfig01 = r2->strmRsConfig;
-  // Load rsConfig for input buffer
-
-  rsDMA01 = r2->basicReq.daw,       ,                   tb = Z(0 - rf);
-  // Load rsDMA in case input buffer is a DMA buffer    Test to see if there is any data to transfer
-
-  if (tb) goto execSibling_2ind1 after {
-      r5 = rf + (-1);
-      r6 = r1->dma_entryPoint;           // r6 = entry point of sibling task
-      r1 = r1->dma_SPBptr,               // r1 = pointer to sibling task's SPB
-          ,   ind = r6;                  // Load entry point of sibling task
-  }
-
-  rsConfig23 = r0->dma_strmRsConfig;
-  // Load rsConfig for output buffer (never a DMA buffer)
-
-  r4 = r0->dma_outBufPtr;
-
-  rsa0 = r2->strmBufPtr;
-  // rsa0 = input buffer pointer                        
-
-  for (i = r5; i >= 0; --i)
-    after {
-      rsa2 = r4;
-      // rsa2 = output buffer pointer
-
-      nop;
-      nop;
-    }
-  //*****************************
-  // TODO: cycles to this point *
-  //*****************************
-    {
-      acc0 =  (rsd0 = *rsa0++1);
-      // get sample
-
-      nop;  // Those "nop"'s are really uggly, but there's
-      nop;  // something with DSP's pipelines which I don't
-      nop;  // understand, resulting this code to fail without
-            // having those "nop"'s (Benny)
-
-      rsa0?reqDMA = r2;
-      // Trigger DMA transfer on input stream, 
-      // if needed to replenish input buffer
-
-      nop;
-      // Yet another magic "nop" to make stuff work
-
-      ,,r98 = acc0 $+>> 0;
-      // store sample in ALU
-
-      nop;
-      // latency on load register.
-      // (this one is understandable)
-
-      *rsa2++1 = r98;
-      // store sample in output buffer
-
-      nop; // The same story
-      nop; // as above again ...
-      nop;
-    }
-  // TODO: cycles per loop iteration
-
-  r2->strmBufPtr = rsa0,,   ;
-  // Update the modified buffer pointers
-
-  r4 = rsa2;
-  // Load output pointer position into r4
-
-  r2 = r0->nextSCB;
-  // Sibling task
-
-  goto execSibling_2ind1 // takes 6 cycles
-    after {
-      r98 = r2->thisSPB:entryPoint;
-      // Load child routine entry and data address 
-
-      r1 = r9;
-      // r9 is r2->thisSPB
-
-      r0->dma_outBufPtr = r4,,
-      // Store updated output buffer pointer
-
-      ind = r8;
-      // r8 is r2->entryPoint
-    }
-}
diff --git a/sound/pci/cs46xx/imgs/cwcdma.h b/sound/pci/cs46xx/imgs/cwcdma.h
deleted file mode 100644 (file)
index 7ff0d45..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/* generated from cwcdma.osp DO NOT MODIFY */
-
-#ifndef __HEADER_cwcdma_H__
-#define __HEADER_cwcdma_H__
-
-static struct dsp_symbol_entry cwcdma_symbols[] = {
-  { 0x8000, "EXECCHILD",0x03 },
-  { 0x8001, "EXECCHILD_98",0x03 },
-  { 0x8003, "EXECCHILD_PUSH1IND",0x03 },
-  { 0x8008, "EXECSIBLING",0x03 },
-  { 0x800a, "EXECSIBLING_298",0x03 },
-  { 0x800b, "EXECSIBLING_2IND1",0x03 },
-  { 0x8010, "TIMINGMASTER",0x03 },
-  { 0x804f, "S16_CODECINPUTTASK",0x03 },
-  { 0x805e, "PCMSERIALINPUTTASK",0x03 },
-  { 0x806d, "S16_MIX_TO_OSTREAM",0x03 },
-  { 0x809a, "S16_MIX",0x03 },
-  { 0x80bb, "S16_UPSRC",0x03 },
-  { 0x813b, "MIX3_EXP",0x03 },
-  { 0x8164, "DECIMATEBYPOW2",0x03 },
-  { 0x8197, "VARIDECIMATE",0x03 },
-  { 0x81f2, "_3DINPUTTASK",0x03 },
-  { 0x820a, "_3DPRLGCINPTASK",0x03 },
-  { 0x8227, "_3DSTEREOINPUTTASK",0x03 },
-  { 0x8242, "_3DOUTPUTTASK",0x03 },
-  { 0x82c4, "HRTF_MORPH_TASK",0x03 },
-  { 0x82c6, "WAIT4DATA",0x03 },
-  { 0x82fa, "PROLOGIC",0x03 },
-  { 0x8496, "DECORRELATOR",0x03 },
-  { 0x84a4, "STEREO2MONO",0x03 },
-  { 0x0000, "OVERLAYBEGINADDRESS",0x00 },
-  { 0x0000, "DMAREADER",0x03 },
-  { 0x0018, "#CODE_END",0x00 },
-}; /* cwcdma symbols */
-
-static u32 cwcdma_code[] = {
-/* OVERLAYBEGINADDRESS */
-/* 0000 */ 0x00002731,0x00001400,0x0004c108,0x000e5044,
-/* 0002 */ 0x0005f608,0x00000000,0x000007ae,0x000be300,
-/* 0004 */ 0x00058630,0x00001400,0x0007afb0,0x000e9584,
-/* 0006 */ 0x00007301,0x000a9840,0x0005e708,0x000cd104,
-/* 0008 */ 0x00067008,0x00000000,0x000902a0,0x00001000,
-/* 000A */ 0x00012a01,0x000c0000,0x00000000,0x00000000,
-/* 000C */ 0x00021843,0x000c0000,0x00000000,0x000c0000,
-/* 000E */ 0x0000e101,0x000c0000,0x00000cac,0x00000000,
-/* 0010 */ 0x00080000,0x000e5ca1,0x00000000,0x000c0000,
-/* 0012 */ 0x00000000,0x00000000,0x00000000,0x00092c00,
-/* 0014 */ 0x000122c1,0x000e5084,0x00058730,0x00001400,
-/* 0016 */ 0x000d7488,0x000e4782,0x00007401,0x0001c100
-};
-
-/* #CODE_END */
-
-static struct dsp_segment_desc cwcdma_segments[] = {
-  { SEGTYPE_SP_PROGRAM, 0x00000000, 0x00000030, cwcdma_code },
-};
-
-static struct dsp_module_desc cwcdma_module = {
-  "cwcdma",
-  {
-    27,
-    cwcdma_symbols
-  },
-  1,
-  cwcdma_segments,
-};
-
-#endif /* __HEADER_cwcdma_H__ */
diff --git a/sound/pci/cs46xx/imgs/cwcsnoop.h b/sound/pci/cs46xx/imgs/cwcsnoop.h
deleted file mode 100644 (file)
index 6929d0a..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/* generated from cwcsnoop.osp DO NOT MODIFY */
-
-#ifndef __HEADER_cwcsnoop_H__
-#define __HEADER_cwcsnoop_H__
-
-static struct dsp_symbol_entry cwcsnoop_symbols[] = {
-  { 0x0500, "OVERLAYBEGINADDRESS",0x00 },
-  { 0x0500, "OUTPUTSNOOP",0x03 },
-  { 0x051f, "#CODE_END",0x00 },
-}; /* cwcsnoop symbols */
-
-static u32 cwcsnoop_code[] = {
-/* 0000 */ 0x0007bfb0,0x000b4e40,0x0007c088,0x000c0617,
-/* 0002 */ 0x00049705,0x00000000,0x00080630,0x00001028,
-/* 0004 */ 0x00076408,0x000efb84,0x00066008,0x00000000,
-/* 0006 */ 0x0007c908,0x000c0000,0x00046725,0x000efa44,
-/* 0008 */ 0x0005f708,0x00000000,0x0001d402,0x000b2e00,
-/* 000A */ 0x0003d418,0x00001000,0x0008d574,0x000c4293,
-/* 000C */ 0x00065625,0x000ea30e,0x00096c01,0x000c6f92,
-/* 000E */ 0x0006a58a,0x000f6085,0x00002f43,0x00000000,
-/* 0010 */ 0x000a83a0,0x00001028,0x0005e608,0x000c0000,
-/* 0012 */ 0x00000000,0x00000000,0x000ca108,0x000dcca1,
-/* 0014 */ 0x00003bac,0x000fb205,0x00073843,0x00000000,
-/* 0016 */ 0x000d8730,0x00001028,0x0006600a,0x000c0000,
-/* 0018 */ 0x00057488,0x00000000,0x00000000,0x000e5084,
-/* 001A */ 0x00000000,0x000eba44,0x00087401,0x000e4782,
-/* 001C */ 0x00000734,0x00001000,0x00010705,0x000a6880,
-/* 001E */ 0x00006a88,0x000c75c4
-};
-/* #CODE_END */
-
-static struct dsp_segment_desc cwcsnoop_segments[] = {
-  { SEGTYPE_SP_PROGRAM, 0x00000000, 0x0000003e, cwcsnoop_code },
-};
-
-static struct dsp_module_desc cwcsnoop_module = {
-  "cwcsnoop",
-  {
-    3,
-    cwcsnoop_symbols
-  },
-  1,
-  cwcsnoop_segments,
-};
-
-#endif /* __HEADER_cwcsnoop_H__ */
index c091438286a39c3fc5d6fdf1c79fb653ea2cdf31..5a40c652df413f31112b2d72ee1bc7e1913df955 100644 (file)
@@ -3,7 +3,6 @@ snd-hda-intel-objs := hda_intel.o
 snd-hda-intel-$(CONFIG_SND_HDA_I915) +=        hda_i915.o
 
 snd-hda-codec-y := hda_codec.o hda_jack.o hda_auto_parser.o
-snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o
 snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o
 snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o
 snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o
@@ -12,6 +11,7 @@ snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o
 CFLAGS_hda_codec.o := -I$(src)
 CFLAGS_hda_intel.o := -I$(src)
 
+snd-hda-codec-generic-objs :=  hda_generic.o
 snd-hda-codec-realtek-objs :=  patch_realtek.o
 snd-hda-codec-cmedia-objs :=   patch_cmedia.o
 snd-hda-codec-analog-objs :=   patch_analog.o
@@ -28,6 +28,9 @@ snd-hda-codec-hdmi-objs :=    patch_hdmi.o hda_eld.o
 obj-$(CONFIG_SND_HDA_INTEL) := snd-hda-codec.o
 
 # codec drivers (note: CONFIG_SND_HDA_CODEC_XXX are booleans)
+ifdef CONFIG_SND_HDA_GENERIC
+obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-generic.o
+endif
 ifdef CONFIG_SND_HDA_CODEC_REALTEK
 obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-realtek.o
 endif
index 69178c4f4113fad7fb3111b57d49247c8f2ebe5c..2e090c8d7144d507506d0101fb84801b305aa639 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/pci.h>
 #include <linux/mutex.h>
 #include <linux/module.h>
+#include <linux/async.h>
 #include <sound/core.h>
 #include "hda_codec.h"
 #include <sound/asoundef.h>
@@ -99,16 +100,24 @@ EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset);
 static void hda_power_work(struct work_struct *work);
 static void hda_keep_power_on(struct hda_codec *codec);
 #define hda_codec_is_power_on(codec)   ((codec)->power_on)
-static inline void hda_call_pm_notify(struct hda_bus *bus, bool power_up)
+
+static void hda_call_pm_notify(struct hda_codec *codec, bool power_up)
 {
+       struct hda_bus *bus = codec->bus;
+
+       if ((power_up && codec->pm_up_notified) ||
+           (!power_up && !codec->pm_up_notified))
+               return;
        if (bus->ops.pm_notify)
                bus->ops.pm_notify(bus, power_up);
+       codec->pm_up_notified = power_up;
 }
+
 #else
 #define codec_in_pm(codec)     0
 static inline void hda_keep_power_on(struct hda_codec *codec) {}
 #define hda_codec_is_power_on(codec)   1
-#define hda_call_pm_notify(bus, state) {}
+#define hda_call_pm_notify(codec, state) {}
 #endif
 
 /**
@@ -831,6 +840,7 @@ static int snd_hda_bus_free(struct hda_bus *bus)
                bus->ops.private_free(bus);
        if (bus->workq)
                destroy_workqueue(bus->workq);
+
        kfree(bus);
        return 0;
 }
@@ -945,9 +955,6 @@ find_codec_preset(struct hda_codec *codec)
        const struct hda_codec_preset *preset;
        unsigned int mod_requested = 0;
 
-       if (is_generic_config(codec))
-               return NULL; /* use the generic parser */
-
  again:
        mutex_lock(&preset_mutex);
        list_for_each_entry(tbl, &hda_preset_tables, list) {
@@ -1329,6 +1336,28 @@ get_hda_cvt_setup(struct hda_codec *codec, hda_nid_t nid)
        return p;
 }
 
+/*
+ * Dynamic symbol binding for the codec parsers
+ */
+#ifdef MODULE
+#define load_parser_sym(sym)           ((int (*)(struct hda_codec *))symbol_request(sym))
+#define unload_parser_addr(addr)       symbol_put_addr(addr)
+#else
+#define load_parser_sym(sym)           (sym)
+#define unload_parser_addr(addr)       do {} while (0)
+#endif
+
+#define load_parser(codec, sym) \
+       ((codec)->parser = load_parser_sym(sym))
+
+static void unload_parser(struct hda_codec *codec)
+{
+       if (codec->parser) {
+               unload_parser_addr(codec->parser);
+               codec->parser = NULL;
+       }
+}
+
 /*
  * codec destructor
  */
@@ -1352,10 +1381,8 @@ static void snd_hda_codec_free(struct hda_codec *codec)
        codec->bus->caddr_tbl[codec->addr] = NULL;
        if (codec->patch_ops.free)
                codec->patch_ops.free(codec);
-#ifdef CONFIG_PM
-       if (!codec->pm_down_notified) /* cancel leftover refcounts */
-               hda_call_pm_notify(codec->bus, false);
-#endif
+       hda_call_pm_notify(codec, false); /* cancel leftover refcounts */
+       unload_parser(codec);
        module_put(codec->owner);
        free_hda_cache(&codec->amp_cache);
        free_hda_cache(&codec->cmd_cache);
@@ -1363,6 +1390,7 @@ static void snd_hda_codec_free(struct hda_codec *codec)
        kfree(codec->chip_name);
        kfree(codec->modelname);
        kfree(codec->wcaps);
+       codec->bus->num_codecs--;
        kfree(codec);
 }
 
@@ -1424,6 +1452,7 @@ int snd_hda_codec_new(struct hda_bus *bus,
        INIT_LIST_HEAD(&codec->conn_list);
 
        INIT_DELAYED_WORK(&codec->jackpoll_work, hda_jackpoll_work);
+       codec->depop_delay = -1;
 
 #ifdef CONFIG_PM
        spin_lock_init(&codec->power_lock);
@@ -1433,7 +1462,6 @@ int snd_hda_codec_new(struct hda_bus *bus,
         * phase.
         */
        hda_keep_power_on(codec);
-       hda_call_pm_notify(bus, true);
 #endif
 
        if (codec->bus->modelname) {
@@ -1445,6 +1473,8 @@ int snd_hda_codec_new(struct hda_bus *bus,
        }
 
        list_add_tail(&codec->list, &bus->codec_list);
+       bus->num_codecs++;
+
        bus->caddr_tbl[codec_addr] = codec;
 
        codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
@@ -1486,11 +1516,14 @@ int snd_hda_codec_new(struct hda_bus *bus,
 #ifdef CONFIG_PM
        codec->d3_stop_clk = snd_hda_codec_get_supported_ps(codec, fg,
                                        AC_PWRST_CLKSTOP);
-       if (!codec->d3_stop_clk)
-               bus->power_keep_link_on = 1;
 #endif
        codec->epss = snd_hda_codec_get_supported_ps(codec, fg,
                                        AC_PWRST_EPSS);
+#ifdef CONFIG_PM
+       if (!codec->d3_stop_clk || !codec->epss)
+               bus->power_keep_link_on = 1;
+#endif
+
 
        /* power-up all before initialization */
        hda_set_power_state(codec, AC_PWRST_D0);
@@ -1537,6 +1570,31 @@ int snd_hda_codec_update_widgets(struct hda_codec *codec)
 EXPORT_SYMBOL_HDA(snd_hda_codec_update_widgets);
 
 
+#ifdef CONFIG_SND_HDA_CODEC_HDMI
+/* if all audio out widgets are digital, let's assume the codec as a HDMI/DP */
+static bool is_likely_hdmi_codec(struct hda_codec *codec)
+{
+       hda_nid_t nid = codec->start_nid;
+       int i;
+
+       for (i = 0; i < codec->num_nodes; i++, nid++) {
+               unsigned int wcaps = get_wcaps(codec, nid);
+               switch (get_wcaps_type(wcaps)) {
+               case AC_WID_AUD_IN:
+                       return false; /* HDMI parser supports only HDMI out */
+               case AC_WID_AUD_OUT:
+                       if (!(wcaps & AC_WCAP_DIGITAL))
+                               return false;
+                       break;
+               }
+       }
+       return true;
+}
+#else
+/* no HDMI codec parser support */
+#define is_likely_hdmi_codec(codec)    false
+#endif /* CONFIG_SND_HDA_CODEC_HDMI */
+
 /**
  * snd_hda_codec_configure - (Re-)configure the HD-audio codec
  * @codec: the HDA codec
@@ -1548,6 +1606,7 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_update_widgets);
  */
 int snd_hda_codec_configure(struct hda_codec *codec)
 {
+       int (*patch)(struct hda_codec *) = NULL;
        int err;
 
        codec->preset = find_codec_preset(codec);
@@ -1557,29 +1616,40 @@ int snd_hda_codec_configure(struct hda_codec *codec)
                        return err;
        }
 
-       if (is_generic_config(codec)) {
-               err = snd_hda_parse_generic_codec(codec);
-               goto patched;
-       }
-       if (codec->preset && codec->preset->patch) {
-               err = codec->preset->patch(codec);
-               goto patched;
+       if (!is_generic_config(codec) && codec->preset)
+               patch = codec->preset->patch;
+       if (!patch) {
+               unload_parser(codec); /* to be sure */
+               if (is_likely_hdmi_codec(codec))
+                       patch = load_parser(codec, snd_hda_parse_hdmi_codec);
+#ifdef CONFIG_SND_HDA_GENERIC
+               if (!patch)
+                       patch = load_parser(codec, snd_hda_parse_generic_codec);
+#endif
+               if (!patch) {
+                       printk(KERN_ERR "hda-codec: No codec parser is available\n");
+                       return -ENODEV;
+               }
        }
 
-       /* call the default parser */
-       err = snd_hda_parse_generic_codec(codec);
-       if (err < 0)
-               printk(KERN_ERR "hda-codec: No codec parser is available\n");
+       err = patch(codec);
+       if (err < 0) {
+               unload_parser(codec);
+               return err;
+       }
 
- patched:
-       if (!err && codec->patch_ops.unsol_event)
+       if (codec->patch_ops.unsol_event) {
                err = init_unsol_queue(codec->bus);
+               if (err < 0)
+                       return err;
+       }
+
        /* audio codec should override the mixer name */
-       if (!err && (codec->afg || !*codec->bus->card->mixername))
+       if (codec->afg || !*codec->bus->card->mixername)
                snprintf(codec->bus->card->mixername,
                         sizeof(codec->bus->card->mixername),
                         "%s %s", codec->vendor_name, codec->chip_name);
-       return err;
+       return 0;
 }
 EXPORT_SYMBOL_HDA(snd_hda_codec_configure);
 
@@ -2610,6 +2680,7 @@ int snd_hda_codec_reset(struct hda_codec *codec)
        codec->preset = NULL;
        codec->slave_dig_outs = NULL;
        codec->spdif_status_reset = 0;
+       unload_parser(codec);
        module_put(codec->owner);
        codec->owner = NULL;
 
@@ -3881,8 +3952,10 @@ static unsigned int hda_set_power_state(struct hda_codec *codec,
 
        /* this delay seems necessary to avoid click noise at power-down */
        if (power_state == AC_PWRST_D3) {
-               /* transition time less than 10ms for power down */
-               msleep(codec->epss ? 10 : 100);
+               if (codec->depop_delay < 0)
+                       msleep(codec->epss ? 10 : 100);
+               else if (codec->depop_delay > 0)
+                       msleep(codec->depop_delay);
                flags = HDA_RW_NO_RESPONSE_FALLBACK;
        }
 
@@ -4000,10 +4073,6 @@ static void hda_call_codec_resume(struct hda_codec *codec)
         * in the resume / power-save sequence
         */
        hda_keep_power_on(codec);
-       if (codec->pm_down_notified) {
-               codec->pm_down_notified = 0;
-               hda_call_pm_notify(codec->bus, true);
-       }
        hda_set_power_state(codec, AC_PWRST_D0);
        restore_shutup_pins(codec);
        hda_exec_init_verbs(codec);
@@ -4877,11 +4946,8 @@ static void hda_power_work(struct work_struct *work)
        spin_unlock(&codec->power_lock);
 
        state = hda_call_codec_suspend(codec, true);
-       if (!codec->pm_down_notified &&
-           !bus->power_keep_link_on && (state & AC_PWRST_CLK_STOP_OK)) {
-               codec->pm_down_notified = 1;
-               hda_call_pm_notify(bus, false);
-       }
+       if (!bus->power_keep_link_on && (state & AC_PWRST_CLK_STOP_OK))
+               hda_call_pm_notify(codec, false);
 }
 
 static void hda_keep_power_on(struct hda_codec *codec)
@@ -4891,6 +4957,7 @@ static void hda_keep_power_on(struct hda_codec *codec)
        codec->power_on = 1;
        codec->power_jiffies = jiffies;
        spin_unlock(&codec->power_lock);
+       hda_call_pm_notify(codec, true);
 }
 
 /* update the power on/off account with the current jiffies */
@@ -4910,8 +4977,6 @@ void snd_hda_update_power_acct(struct hda_codec *codec)
 /* call this with codec->power_lock held! */
 static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down)
 {
-       struct hda_bus *bus = codec->bus;
-
        /* Return if power_on or transitioning to power_on, unless currently
         * powering down. */
        if ((codec->power_on || codec->power_transition > 0) &&
@@ -4938,11 +5003,6 @@ static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down)
        codec->power_transition = 1; /* avoid reentrance */
        spin_unlock(&codec->power_lock);
 
-       if (codec->pm_down_notified) {
-               codec->pm_down_notified = 0;
-               hda_call_pm_notify(bus, true);
-       }
-
        hda_call_codec_resume(codec);
 
        spin_lock(&codec->power_lock);
@@ -5599,6 +5659,17 @@ EXPORT_SYMBOL_HDA(snd_hda_add_imux_item);
  * power management
  */
 
+
+static void hda_async_suspend(void *data, async_cookie_t cookie)
+{
+       hda_call_codec_suspend(data, false);
+}
+
+static void hda_async_resume(void *data, async_cookie_t cookie)
+{
+       hda_call_codec_resume(data);
+}
+
 /**
  * snd_hda_suspend - suspend the codecs
  * @bus: the HDA bus
@@ -5608,12 +5679,22 @@ EXPORT_SYMBOL_HDA(snd_hda_add_imux_item);
 int snd_hda_suspend(struct hda_bus *bus)
 {
        struct hda_codec *codec;
+       ASYNC_DOMAIN_EXCLUSIVE(domain);
 
        list_for_each_entry(codec, &bus->codec_list, list) {
                cancel_delayed_work_sync(&codec->jackpoll_work);
-               if (hda_codec_is_power_on(codec))
-                       hda_call_codec_suspend(codec, false);
+               if (hda_codec_is_power_on(codec)) {
+                       if (bus->num_codecs > 1)
+                               async_schedule_domain(hda_async_suspend, codec,
+                                                     &domain);
+                       else
+                               hda_call_codec_suspend(codec, false);
+               }
        }
+
+       if (bus->num_codecs > 1)
+               async_synchronize_full_domain(&domain);
+
        return 0;
 }
 EXPORT_SYMBOL_HDA(snd_hda_suspend);
@@ -5627,10 +5708,18 @@ EXPORT_SYMBOL_HDA(snd_hda_suspend);
 int snd_hda_resume(struct hda_bus *bus)
 {
        struct hda_codec *codec;
+       ASYNC_DOMAIN_EXCLUSIVE(domain);
 
        list_for_each_entry(codec, &bus->codec_list, list) {
-               hda_call_codec_resume(codec);
+               if (bus->num_codecs > 1)
+                       async_schedule_domain(hda_async_resume, codec, &domain);
+               else
+                       hda_call_codec_resume(codec);
        }
+
+       if (bus->num_codecs > 1)
+               async_synchronize_full_domain(&domain);
+
        return 0;
 }
 EXPORT_SYMBOL_HDA(snd_hda_resume);
index 7aa9870040c102df5b02aa0a94778c8e14c36024..3c484c27048b1cd148fb700f2855142e3b4fb5e6 100644 (file)
 #include <sound/control.h>
 #include <sound/pcm.h>
 #include <sound/hwdep.h>
-
-/*
- * nodes
- */
-#define        AC_NODE_ROOT            0x00
-
-/*
- * function group types
- */
-enum {
-       AC_GRP_AUDIO_FUNCTION = 0x01,
-       AC_GRP_MODEM_FUNCTION = 0x02,
-};
-       
-/*
- * widget types
- */
-enum {
-       AC_WID_AUD_OUT,         /* Audio Out */
-       AC_WID_AUD_IN,          /* Audio In */
-       AC_WID_AUD_MIX,         /* Audio Mixer */
-       AC_WID_AUD_SEL,         /* Audio Selector */
-       AC_WID_PIN,             /* Pin Complex */
-       AC_WID_POWER,           /* Power */
-       AC_WID_VOL_KNB,         /* Volume Knob */
-       AC_WID_BEEP,            /* Beep Generator */
-       AC_WID_VENDOR = 0x0f    /* Vendor specific */
-};
-
-/*
- * GET verbs
- */
-#define AC_VERB_GET_STREAM_FORMAT              0x0a00
-#define AC_VERB_GET_AMP_GAIN_MUTE              0x0b00
-#define AC_VERB_GET_PROC_COEF                  0x0c00
-#define AC_VERB_GET_COEF_INDEX                 0x0d00
-#define AC_VERB_PARAMETERS                     0x0f00
-#define AC_VERB_GET_CONNECT_SEL                        0x0f01
-#define AC_VERB_GET_CONNECT_LIST               0x0f02
-#define AC_VERB_GET_PROC_STATE                 0x0f03
-#define AC_VERB_GET_SDI_SELECT                 0x0f04
-#define AC_VERB_GET_POWER_STATE                        0x0f05
-#define AC_VERB_GET_CONV                       0x0f06
-#define AC_VERB_GET_PIN_WIDGET_CONTROL         0x0f07
-#define AC_VERB_GET_UNSOLICITED_RESPONSE       0x0f08
-#define AC_VERB_GET_PIN_SENSE                  0x0f09
-#define AC_VERB_GET_BEEP_CONTROL               0x0f0a
-#define AC_VERB_GET_EAPD_BTLENABLE             0x0f0c
-#define AC_VERB_GET_DIGI_CONVERT_1             0x0f0d
-#define AC_VERB_GET_DIGI_CONVERT_2             0x0f0e /* unused */
-#define AC_VERB_GET_VOLUME_KNOB_CONTROL                0x0f0f
-/* f10-f1a: GPIO */
-#define AC_VERB_GET_GPIO_DATA                  0x0f15
-#define AC_VERB_GET_GPIO_MASK                  0x0f16
-#define AC_VERB_GET_GPIO_DIRECTION             0x0f17
-#define AC_VERB_GET_GPIO_WAKE_MASK             0x0f18
-#define AC_VERB_GET_GPIO_UNSOLICITED_RSP_MASK  0x0f19
-#define AC_VERB_GET_GPIO_STICKY_MASK           0x0f1a
-#define AC_VERB_GET_CONFIG_DEFAULT             0x0f1c
-/* f20: AFG/MFG */
-#define AC_VERB_GET_SUBSYSTEM_ID               0x0f20
-#define AC_VERB_GET_CVT_CHAN_COUNT             0x0f2d
-#define AC_VERB_GET_HDMI_DIP_SIZE              0x0f2e
-#define AC_VERB_GET_HDMI_ELDD                  0x0f2f
-#define AC_VERB_GET_HDMI_DIP_INDEX             0x0f30
-#define AC_VERB_GET_HDMI_DIP_DATA              0x0f31
-#define AC_VERB_GET_HDMI_DIP_XMIT              0x0f32
-#define AC_VERB_GET_HDMI_CP_CTRL               0x0f33
-#define AC_VERB_GET_HDMI_CHAN_SLOT             0x0f34
-#define AC_VERB_GET_DEVICE_SEL                 0xf35
-#define AC_VERB_GET_DEVICE_LIST                        0xf36
-
-/*
- * SET verbs
- */
-#define AC_VERB_SET_STREAM_FORMAT              0x200
-#define AC_VERB_SET_AMP_GAIN_MUTE              0x300
-#define AC_VERB_SET_PROC_COEF                  0x400
-#define AC_VERB_SET_COEF_INDEX                 0x500
-#define AC_VERB_SET_CONNECT_SEL                        0x701
-#define AC_VERB_SET_PROC_STATE                 0x703
-#define AC_VERB_SET_SDI_SELECT                 0x704
-#define AC_VERB_SET_POWER_STATE                        0x705
-#define AC_VERB_SET_CHANNEL_STREAMID           0x706
-#define AC_VERB_SET_PIN_WIDGET_CONTROL         0x707
-#define AC_VERB_SET_UNSOLICITED_ENABLE         0x708
-#define AC_VERB_SET_PIN_SENSE                  0x709
-#define AC_VERB_SET_BEEP_CONTROL               0x70a
-#define AC_VERB_SET_EAPD_BTLENABLE             0x70c
-#define AC_VERB_SET_DIGI_CONVERT_1             0x70d
-#define AC_VERB_SET_DIGI_CONVERT_2             0x70e
-#define AC_VERB_SET_VOLUME_KNOB_CONTROL                0x70f
-#define AC_VERB_SET_GPIO_DATA                  0x715
-#define AC_VERB_SET_GPIO_MASK                  0x716
-#define AC_VERB_SET_GPIO_DIRECTION             0x717
-#define AC_VERB_SET_GPIO_WAKE_MASK             0x718
-#define AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK  0x719
-#define AC_VERB_SET_GPIO_STICKY_MASK           0x71a
-#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_0     0x71c
-#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_1     0x71d
-#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_2     0x71e
-#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_3     0x71f
-#define AC_VERB_SET_EAPD                               0x788
-#define AC_VERB_SET_CODEC_RESET                        0x7ff
-#define AC_VERB_SET_CVT_CHAN_COUNT             0x72d
-#define AC_VERB_SET_HDMI_DIP_INDEX             0x730
-#define AC_VERB_SET_HDMI_DIP_DATA              0x731
-#define AC_VERB_SET_HDMI_DIP_XMIT              0x732
-#define AC_VERB_SET_HDMI_CP_CTRL               0x733
-#define AC_VERB_SET_HDMI_CHAN_SLOT             0x734
-#define AC_VERB_SET_DEVICE_SEL                 0x735
-
-/*
- * Parameter IDs
- */
-#define AC_PAR_VENDOR_ID               0x00
-#define AC_PAR_SUBSYSTEM_ID            0x01
-#define AC_PAR_REV_ID                  0x02
-#define AC_PAR_NODE_COUNT              0x04
-#define AC_PAR_FUNCTION_TYPE           0x05
-#define AC_PAR_AUDIO_FG_CAP            0x08
-#define AC_PAR_AUDIO_WIDGET_CAP                0x09
-#define AC_PAR_PCM                     0x0a
-#define AC_PAR_STREAM                  0x0b
-#define AC_PAR_PIN_CAP                 0x0c
-#define AC_PAR_AMP_IN_CAP              0x0d
-#define AC_PAR_CONNLIST_LEN            0x0e
-#define AC_PAR_POWER_STATE             0x0f
-#define AC_PAR_PROC_CAP                        0x10
-#define AC_PAR_GPIO_CAP                        0x11
-#define AC_PAR_AMP_OUT_CAP             0x12
-#define AC_PAR_VOL_KNB_CAP             0x13
-#define AC_PAR_DEVLIST_LEN             0x15
-#define AC_PAR_HDMI_LPCM_CAP           0x20
-
-/*
- * AC_VERB_PARAMETERS results (32bit)
- */
-
-/* Function Group Type */
-#define AC_FGT_TYPE                    (0xff<<0)
-#define AC_FGT_TYPE_SHIFT              0
-#define AC_FGT_UNSOL_CAP               (1<<8)
-
-/* Audio Function Group Capabilities */
-#define AC_AFG_OUT_DELAY               (0xf<<0)
-#define AC_AFG_IN_DELAY                        (0xf<<8)
-#define AC_AFG_BEEP_GEN                        (1<<16)
-
-/* Audio Widget Capabilities */
-#define AC_WCAP_STEREO                 (1<<0)  /* stereo I/O */
-#define AC_WCAP_IN_AMP                 (1<<1)  /* AMP-in present */
-#define AC_WCAP_OUT_AMP                        (1<<2)  /* AMP-out present */
-#define AC_WCAP_AMP_OVRD               (1<<3)  /* AMP-parameter override */
-#define AC_WCAP_FORMAT_OVRD            (1<<4)  /* format override */
-#define AC_WCAP_STRIPE                 (1<<5)  /* stripe */
-#define AC_WCAP_PROC_WID               (1<<6)  /* Proc Widget */
-#define AC_WCAP_UNSOL_CAP              (1<<7)  /* Unsol capable */
-#define AC_WCAP_CONN_LIST              (1<<8)  /* connection list */
-#define AC_WCAP_DIGITAL                        (1<<9)  /* digital I/O */
-#define AC_WCAP_POWER                  (1<<10) /* power control */
-#define AC_WCAP_LR_SWAP                        (1<<11) /* L/R swap */
-#define AC_WCAP_CP_CAPS                        (1<<12) /* content protection */
-#define AC_WCAP_CHAN_CNT_EXT           (7<<13) /* channel count ext */
-#define AC_WCAP_DELAY                  (0xf<<16)
-#define AC_WCAP_DELAY_SHIFT            16
-#define AC_WCAP_TYPE                   (0xf<<20)
-#define AC_WCAP_TYPE_SHIFT             20
-
-/* supported PCM rates and bits */
-#define AC_SUPPCM_RATES                        (0xfff << 0)
-#define AC_SUPPCM_BITS_8               (1<<16)
-#define AC_SUPPCM_BITS_16              (1<<17)
-#define AC_SUPPCM_BITS_20              (1<<18)
-#define AC_SUPPCM_BITS_24              (1<<19)
-#define AC_SUPPCM_BITS_32              (1<<20)
-
-/* supported PCM stream format */
-#define AC_SUPFMT_PCM                  (1<<0)
-#define AC_SUPFMT_FLOAT32              (1<<1)
-#define AC_SUPFMT_AC3                  (1<<2)
-
-/* GP I/O count */
-#define AC_GPIO_IO_COUNT               (0xff<<0)
-#define AC_GPIO_O_COUNT                        (0xff<<8)
-#define AC_GPIO_O_COUNT_SHIFT          8
-#define AC_GPIO_I_COUNT                        (0xff<<16)
-#define AC_GPIO_I_COUNT_SHIFT          16
-#define AC_GPIO_UNSOLICITED            (1<<30)
-#define AC_GPIO_WAKE                   (1<<31)
-
-/* Converter stream, channel */
-#define AC_CONV_CHANNEL                        (0xf<<0)
-#define AC_CONV_STREAM                 (0xf<<4)
-#define AC_CONV_STREAM_SHIFT           4
-
-/* Input converter SDI select */
-#define AC_SDI_SELECT                  (0xf<<0)
-
-/* stream format id */
-#define AC_FMT_CHAN_SHIFT              0
-#define AC_FMT_CHAN_MASK               (0x0f << 0)
-#define AC_FMT_BITS_SHIFT              4
-#define AC_FMT_BITS_MASK               (7 << 4)
-#define AC_FMT_BITS_8                  (0 << 4)
-#define AC_FMT_BITS_16                 (1 << 4)
-#define AC_FMT_BITS_20                 (2 << 4)
-#define AC_FMT_BITS_24                 (3 << 4)
-#define AC_FMT_BITS_32                 (4 << 4)
-#define AC_FMT_DIV_SHIFT               8
-#define AC_FMT_DIV_MASK                        (7 << 8)
-#define AC_FMT_MULT_SHIFT              11
-#define AC_FMT_MULT_MASK               (7 << 11)
-#define AC_FMT_BASE_SHIFT              14
-#define AC_FMT_BASE_48K                        (0 << 14)
-#define AC_FMT_BASE_44K                        (1 << 14)
-#define AC_FMT_TYPE_SHIFT              15
-#define AC_FMT_TYPE_PCM                        (0 << 15)
-#define AC_FMT_TYPE_NON_PCM            (1 << 15)
-
-/* Unsolicited response control */
-#define AC_UNSOL_TAG                   (0x3f<<0)
-#define AC_UNSOL_ENABLED               (1<<7)
-#define AC_USRSP_EN                    AC_UNSOL_ENABLED
-
-/* Unsolicited responses */
-#define AC_UNSOL_RES_TAG               (0x3f<<26)
-#define AC_UNSOL_RES_TAG_SHIFT         26
-#define AC_UNSOL_RES_SUBTAG            (0x1f<<21)
-#define AC_UNSOL_RES_SUBTAG_SHIFT      21
-#define AC_UNSOL_RES_DE                        (0x3f<<15)  /* Device Entry
-                                                    * (for DP1.2 MST)
-                                                    */
-#define AC_UNSOL_RES_DE_SHIFT          15
-#define AC_UNSOL_RES_IA                        (1<<2)  /* Inactive (for DP1.2 MST) */
-#define AC_UNSOL_RES_ELDV              (1<<1)  /* ELD Data valid (for HDMI) */
-#define AC_UNSOL_RES_PD                        (1<<0)  /* pinsense detect */
-#define AC_UNSOL_RES_CP_STATE          (1<<1)  /* content protection */
-#define AC_UNSOL_RES_CP_READY          (1<<0)  /* content protection */
-
-/* Pin widget capabilies */
-#define AC_PINCAP_IMP_SENSE            (1<<0)  /* impedance sense capable */
-#define AC_PINCAP_TRIG_REQ             (1<<1)  /* trigger required */
-#define AC_PINCAP_PRES_DETECT          (1<<2)  /* presence detect capable */
-#define AC_PINCAP_HP_DRV               (1<<3)  /* headphone drive capable */
-#define AC_PINCAP_OUT                  (1<<4)  /* output capable */
-#define AC_PINCAP_IN                   (1<<5)  /* input capable */
-#define AC_PINCAP_BALANCE              (1<<6)  /* balanced I/O capable */
-/* Note: This LR_SWAP pincap is defined in the Realtek ALC883 specification,
- *       but is marked reserved in the Intel HDA specification.
- */
-#define AC_PINCAP_LR_SWAP              (1<<7)  /* L/R swap */
-/* Note: The same bit as LR_SWAP is newly defined as HDMI capability
- *       in HD-audio specification
- */
-#define AC_PINCAP_HDMI                 (1<<7)  /* HDMI pin */
-#define AC_PINCAP_DP                   (1<<24) /* DisplayPort pin, can
-                                                * coexist with AC_PINCAP_HDMI
-                                                */
-#define AC_PINCAP_VREF                 (0x37<<8)
-#define AC_PINCAP_VREF_SHIFT           8
-#define AC_PINCAP_EAPD                 (1<<16) /* EAPD capable */
-#define AC_PINCAP_HBR                  (1<<27) /* High Bit Rate */
-/* Vref status (used in pin cap) */
-#define AC_PINCAP_VREF_HIZ             (1<<0)  /* Hi-Z */
-#define AC_PINCAP_VREF_50              (1<<1)  /* 50% */
-#define AC_PINCAP_VREF_GRD             (1<<2)  /* ground */
-#define AC_PINCAP_VREF_80              (1<<4)  /* 80% */
-#define AC_PINCAP_VREF_100             (1<<5)  /* 100% */
-
-/* Amplifier capabilities */
-#define AC_AMPCAP_OFFSET               (0x7f<<0)  /* 0dB offset */
-#define AC_AMPCAP_OFFSET_SHIFT         0
-#define AC_AMPCAP_NUM_STEPS            (0x7f<<8)  /* number of steps */
-#define AC_AMPCAP_NUM_STEPS_SHIFT      8
-#define AC_AMPCAP_STEP_SIZE            (0x7f<<16) /* step size 0-32dB
-                                                   * in 0.25dB
-                                                   */
-#define AC_AMPCAP_STEP_SIZE_SHIFT      16
-#define AC_AMPCAP_MUTE                 (1<<31)    /* mute capable */
-#define AC_AMPCAP_MUTE_SHIFT           31
-
-/* driver-specific amp-caps: using bits 24-30 */
-#define AC_AMPCAP_MIN_MUTE             (1 << 30) /* min-volume = mute */
-
-/* Connection list */
-#define AC_CLIST_LENGTH                        (0x7f<<0)
-#define AC_CLIST_LONG                  (1<<7)
-
-/* Supported power status */
-#define AC_PWRST_D0SUP                 (1<<0)
-#define AC_PWRST_D1SUP                 (1<<1)
-#define AC_PWRST_D2SUP                 (1<<2)
-#define AC_PWRST_D3SUP                 (1<<3)
-#define AC_PWRST_D3COLDSUP             (1<<4)
-#define AC_PWRST_S3D3COLDSUP           (1<<29)
-#define AC_PWRST_CLKSTOP               (1<<30)
-#define AC_PWRST_EPSS                  (1U<<31)
-
-/* Power state values */
-#define AC_PWRST_SETTING               (0xf<<0)
-#define AC_PWRST_ACTUAL                        (0xf<<4)
-#define AC_PWRST_ACTUAL_SHIFT          4
-#define AC_PWRST_D0                    0x00
-#define AC_PWRST_D1                    0x01
-#define AC_PWRST_D2                    0x02
-#define AC_PWRST_D3                    0x03
-#define AC_PWRST_ERROR                  (1<<8)
-#define AC_PWRST_CLK_STOP_OK            (1<<9)
-#define AC_PWRST_SETTING_RESET          (1<<10)
-
-/* Processing capabilies */
-#define AC_PCAP_BENIGN                 (1<<0)
-#define AC_PCAP_NUM_COEF               (0xff<<8)
-#define AC_PCAP_NUM_COEF_SHIFT         8
-
-/* Volume knobs capabilities */
-#define AC_KNBCAP_NUM_STEPS            (0x7f<<0)
-#define AC_KNBCAP_DELTA                        (1<<7)
-
-/* HDMI LPCM capabilities */
-#define AC_LPCMCAP_48K_CP_CHNS         (0x0f<<0) /* max channels w/ CP-on */   
-#define AC_LPCMCAP_48K_NO_CHNS         (0x0f<<4) /* max channels w/o CP-on */
-#define AC_LPCMCAP_48K_20BIT           (1<<8)  /* 20b bitrate supported */
-#define AC_LPCMCAP_48K_24BIT           (1<<9)  /* 24b bitrate supported */
-#define AC_LPCMCAP_96K_CP_CHNS         (0x0f<<10) /* max channels w/ CP-on */  
-#define AC_LPCMCAP_96K_NO_CHNS         (0x0f<<14) /* max channels w/o CP-on */
-#define AC_LPCMCAP_96K_20BIT           (1<<18) /* 20b bitrate supported */
-#define AC_LPCMCAP_96K_24BIT           (1<<19) /* 24b bitrate supported */
-#define AC_LPCMCAP_192K_CP_CHNS                (0x0f<<20) /* max channels w/ CP-on */  
-#define AC_LPCMCAP_192K_NO_CHNS                (0x0f<<24) /* max channels w/o CP-on */
-#define AC_LPCMCAP_192K_20BIT          (1<<28) /* 20b bitrate supported */
-#define AC_LPCMCAP_192K_24BIT          (1<<29) /* 24b bitrate supported */
-#define AC_LPCMCAP_44K                 (1<<30) /* 44.1kHz support */
-#define AC_LPCMCAP_44K_MS              (1<<31) /* 44.1kHz-multiplies support */
-
-/* Display pin's device list length */
-#define AC_DEV_LIST_LEN_MASK           0x3f
-#define AC_MAX_DEV_LIST_LEN            64
-
-/*
- * Control Parameters
- */
-
-/* Amp gain/mute */
-#define AC_AMP_MUTE                    (1<<7)
-#define AC_AMP_GAIN                    (0x7f)
-#define AC_AMP_GET_INDEX               (0xf<<0)
-
-#define AC_AMP_GET_LEFT                        (1<<13)
-#define AC_AMP_GET_RIGHT               (0<<13)
-#define AC_AMP_GET_OUTPUT              (1<<15)
-#define AC_AMP_GET_INPUT               (0<<15)
-
-#define AC_AMP_SET_INDEX               (0xf<<8)
-#define AC_AMP_SET_INDEX_SHIFT         8
-#define AC_AMP_SET_RIGHT               (1<<12)
-#define AC_AMP_SET_LEFT                        (1<<13)
-#define AC_AMP_SET_INPUT               (1<<14)
-#define AC_AMP_SET_OUTPUT              (1<<15)
-
-/* DIGITAL1 bits */
-#define AC_DIG1_ENABLE                 (1<<0)
-#define AC_DIG1_V                      (1<<1)
-#define AC_DIG1_VCFG                   (1<<2)
-#define AC_DIG1_EMPHASIS               (1<<3)
-#define AC_DIG1_COPYRIGHT              (1<<4)
-#define AC_DIG1_NONAUDIO               (1<<5)
-#define AC_DIG1_PROFESSIONAL           (1<<6)
-#define AC_DIG1_LEVEL                  (1<<7)
-
-/* DIGITAL2 bits */
-#define AC_DIG2_CC                     (0x7f<<0)
-
-/* DIGITAL3 bits */
-#define AC_DIG3_ICT                    (0xf<<0)
-#define AC_DIG3_KAE                    (1<<7)
-
-/* Pin widget control - 8bit */
-#define AC_PINCTL_EPT                  (0x3<<0)
-#define AC_PINCTL_EPT_NATIVE           0
-#define AC_PINCTL_EPT_HBR              3
-#define AC_PINCTL_VREFEN               (0x7<<0)
-#define AC_PINCTL_VREF_HIZ             0       /* Hi-Z */
-#define AC_PINCTL_VREF_50              1       /* 50% */
-#define AC_PINCTL_VREF_GRD             2       /* ground */
-#define AC_PINCTL_VREF_80              4       /* 80% */
-#define AC_PINCTL_VREF_100             5       /* 100% */
-#define AC_PINCTL_IN_EN                        (1<<5)
-#define AC_PINCTL_OUT_EN               (1<<6)
-#define AC_PINCTL_HP_EN                        (1<<7)
-
-/* Pin sense - 32bit */
-#define AC_PINSENSE_IMPEDANCE_MASK     (0x7fffffff)
-#define AC_PINSENSE_PRESENCE           (1<<31)
-#define AC_PINSENSE_ELDV               (1<<30) /* ELD valid (HDMI) */
-
-/* EAPD/BTL enable - 32bit */
-#define AC_EAPDBTL_BALANCED            (1<<0)
-#define AC_EAPDBTL_EAPD                        (1<<1)
-#define AC_EAPDBTL_LR_SWAP             (1<<2)
-
-/* HDMI ELD data */
-#define AC_ELDD_ELD_VALID              (1<<31)
-#define AC_ELDD_ELD_DATA               0xff
-
-/* HDMI DIP size */
-#define AC_DIPSIZE_ELD_BUF             (1<<3) /* ELD buf size of packet size */
-#define AC_DIPSIZE_PACK_IDX            (0x07<<0) /* packet index */
-
-/* HDMI DIP index */
-#define AC_DIPIDX_PACK_IDX             (0x07<<5) /* packet idnex */
-#define AC_DIPIDX_BYTE_IDX             (0x1f<<0) /* byte index */
-
-/* HDMI DIP xmit (transmit) control */
-#define AC_DIPXMIT_MASK                        (0x3<<6)
-#define AC_DIPXMIT_DISABLE             (0x0<<6) /* disable xmit */
-#define AC_DIPXMIT_ONCE                        (0x2<<6) /* xmit once then disable */
-#define AC_DIPXMIT_BEST                        (0x3<<6) /* best effort */
-
-/* HDMI content protection (CP) control */
-#define AC_CPCTRL_CES                  (1<<9) /* current encryption state */
-#define AC_CPCTRL_READY                        (1<<8) /* ready bit */
-#define AC_CPCTRL_SUBTAG               (0x1f<<3) /* subtag for unsol-resp */
-#define AC_CPCTRL_STATE                        (3<<0) /* current CP request state */
-
-/* Converter channel <-> HDMI slot mapping */
-#define AC_CVTMAP_HDMI_SLOT            (0xf<<0) /* HDMI slot number */
-#define AC_CVTMAP_CHAN                 (0xf<<4) /* converter channel number */
-
-/* configuration default - 32bit */
-#define AC_DEFCFG_SEQUENCE             (0xf<<0)
-#define AC_DEFCFG_DEF_ASSOC            (0xf<<4)
-#define AC_DEFCFG_ASSOC_SHIFT          4
-#define AC_DEFCFG_MISC                 (0xf<<8)
-#define AC_DEFCFG_MISC_SHIFT           8
-#define AC_DEFCFG_MISC_NO_PRESENCE     (1<<0)
-#define AC_DEFCFG_COLOR                        (0xf<<12)
-#define AC_DEFCFG_COLOR_SHIFT          12
-#define AC_DEFCFG_CONN_TYPE            (0xf<<16)
-#define AC_DEFCFG_CONN_TYPE_SHIFT      16
-#define AC_DEFCFG_DEVICE               (0xf<<20)
-#define AC_DEFCFG_DEVICE_SHIFT         20
-#define AC_DEFCFG_LOCATION             (0x3f<<24)
-#define AC_DEFCFG_LOCATION_SHIFT       24
-#define AC_DEFCFG_PORT_CONN            (0x3<<30)
-#define AC_DEFCFG_PORT_CONN_SHIFT      30
-
-/* Display pin's device list entry */
-#define AC_DE_PD                       (1<<0)
-#define AC_DE_ELDV                     (1<<1)
-#define AC_DE_IA                       (1<<2)
-
-/* device device types (0x0-0xf) */
-enum {
-       AC_JACK_LINE_OUT,
-       AC_JACK_SPEAKER,
-       AC_JACK_HP_OUT,
-       AC_JACK_CD,
-       AC_JACK_SPDIF_OUT,
-       AC_JACK_DIG_OTHER_OUT,
-       AC_JACK_MODEM_LINE_SIDE,
-       AC_JACK_MODEM_HAND_SIDE,
-       AC_JACK_LINE_IN,
-       AC_JACK_AUX,
-       AC_JACK_MIC_IN,
-       AC_JACK_TELEPHONY,
-       AC_JACK_SPDIF_IN,
-       AC_JACK_DIG_OTHER_IN,
-       AC_JACK_OTHER = 0xf,
-};
-
-/* jack connection types (0x0-0xf) */
-enum {
-       AC_JACK_CONN_UNKNOWN,
-       AC_JACK_CONN_1_8,
-       AC_JACK_CONN_1_4,
-       AC_JACK_CONN_ATAPI,
-       AC_JACK_CONN_RCA,
-       AC_JACK_CONN_OPTICAL,
-       AC_JACK_CONN_OTHER_DIGITAL,
-       AC_JACK_CONN_OTHER_ANALOG,
-       AC_JACK_CONN_DIN,
-       AC_JACK_CONN_XLR,
-       AC_JACK_CONN_RJ11,
-       AC_JACK_CONN_COMB,
-       AC_JACK_CONN_OTHER = 0xf,
-};
-
-/* jack colors (0x0-0xf) */
-enum {
-       AC_JACK_COLOR_UNKNOWN,
-       AC_JACK_COLOR_BLACK,
-       AC_JACK_COLOR_GREY,
-       AC_JACK_COLOR_BLUE,
-       AC_JACK_COLOR_GREEN,
-       AC_JACK_COLOR_RED,
-       AC_JACK_COLOR_ORANGE,
-       AC_JACK_COLOR_YELLOW,
-       AC_JACK_COLOR_PURPLE,
-       AC_JACK_COLOR_PINK,
-       AC_JACK_COLOR_WHITE = 0xe,
-       AC_JACK_COLOR_OTHER,
-};
-
-/* Jack location (0x0-0x3f) */
-/* common case */
-enum {
-       AC_JACK_LOC_NONE,
-       AC_JACK_LOC_REAR,
-       AC_JACK_LOC_FRONT,
-       AC_JACK_LOC_LEFT,
-       AC_JACK_LOC_RIGHT,
-       AC_JACK_LOC_TOP,
-       AC_JACK_LOC_BOTTOM,
-};
-/* bits 4-5 */
-enum {
-       AC_JACK_LOC_EXTERNAL = 0x00,
-       AC_JACK_LOC_INTERNAL = 0x10,
-       AC_JACK_LOC_SEPARATE = 0x20,
-       AC_JACK_LOC_OTHER    = 0x30,
-};
-enum {
-       /* external on primary chasis */
-       AC_JACK_LOC_REAR_PANEL = 0x07,
-       AC_JACK_LOC_DRIVE_BAY,
-       /* internal */
-       AC_JACK_LOC_RISER = 0x17,
-       AC_JACK_LOC_HDMI,
-       AC_JACK_LOC_ATAPI,
-       /* others */
-       AC_JACK_LOC_MOBILE_IN = 0x37,
-       AC_JACK_LOC_MOBILE_OUT,
-};
-
-/* Port connectivity (0-3) */
-enum {
-       AC_JACK_PORT_COMPLEX,
-       AC_JACK_PORT_NONE,
-       AC_JACK_PORT_FIXED,
-       AC_JACK_PORT_BOTH,
-};
-
-/* max. codec address */
-#define HDA_MAX_CODEC_ADDRESS  0x0f
+#include <sound/hda_verbs.h>
 
 /*
  * generic arrays
@@ -673,6 +128,7 @@ struct hda_bus {
 
        /* codec linked list */
        struct list_head codec_list;
+       unsigned int num_codecs;
        /* link caddr -> codec */
        struct hda_codec *caddr_tbl[HDA_MAX_CODEC_ADDRESS + 1];
 
@@ -834,6 +290,7 @@ struct hda_codec {
        /* detected preset */
        const struct hda_codec_preset *preset;
        struct module *owner;
+       int (*parser)(struct hda_codec *codec);
        const char *vendor_name;        /* codec vendor name */
        const char *chip_name;          /* codec chip name */
        const char *modelname;  /* model name for preset */
@@ -907,7 +364,7 @@ struct hda_codec {
 #ifdef CONFIG_PM
        unsigned int power_on :1;       /* current (global) power-state */
        unsigned int d3_stop_clk:1;     /* support D3 operation without BCLK */
-       unsigned int pm_down_notified:1; /* PM notified to controller */
+       unsigned int pm_up_notified:1;  /* PM notified to controller */
        unsigned int in_pm:1;           /* suspend/resume being performed */
        int power_transition;   /* power-state in transition */
        int power_count;        /* current (global) power refcount */
@@ -936,6 +393,8 @@ struct hda_codec {
        struct snd_array jacks;
 #endif
 
+       int depop_delay; /* depop delay in ms, -1 for default delay time */
+
        /* fix-up list */
        int fixup_id;
        const struct hda_fixup *fixup_list;
index c4671d00babd6772193f955237c48412a3239a5a..8cebdcfdcfdc9855a5a69ca9e5f5bd70182748f7 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/ctype.h>
 #include <linux/string.h>
 #include <linux/bitops.h>
+#include <linux/module.h>
 #include <sound/core.h>
 #include <sound/jack.h>
 #include "hda_codec.h"
@@ -474,6 +475,20 @@ static void invalidate_nid_path(struct hda_codec *codec, int idx)
        memset(path, 0, sizeof(*path));
 }
 
+/* return a DAC if paired to the given pin by codec driver */
+static hda_nid_t get_preferred_dac(struct hda_codec *codec, hda_nid_t pin)
+{
+       struct hda_gen_spec *spec = codec->spec;
+       const hda_nid_t *list = spec->preferred_dacs;
+
+       if (!list)
+               return 0;
+       for (; *list; list += 2)
+               if (*list == pin)
+                       return list[1];
+       return 0;
+}
+
 /* look for an empty DAC slot */
 static hda_nid_t look_for_dac(struct hda_codec *codec, hda_nid_t pin,
                              bool is_digital)
@@ -1192,7 +1207,14 @@ static int try_assign_dacs(struct hda_codec *codec, int num_outs,
                        continue;
                }
 
-               dacs[i] = look_for_dac(codec, pin, false);
+               dacs[i] = get_preferred_dac(codec, pin);
+               if (dacs[i]) {
+                       if (is_dac_already_used(codec, dacs[i]))
+                               badness += bad->shared_primary;
+               }
+
+               if (!dacs[i])
+                       dacs[i] = look_for_dac(codec, pin, false);
                if (!dacs[i] && !i) {
                        /* try to steal the DAC of surrounds for the front */
                        for (j = 1; j < num_outs; j++) {
@@ -3032,6 +3054,8 @@ static int parse_capture_source(struct hda_codec *codec, hda_nid_t pin,
                        spec->imux_pins[imux->num_items] = pin;
                        snd_hda_add_imux_item(imux, label, cfg_idx, NULL);
                        imux_added = true;
+                       if (spec->dyn_adc_switch)
+                               spec->dyn_adc_idx[imux_idx] = c;
                }
        }
 
@@ -3129,7 +3153,9 @@ static int create_input_ctls(struct hda_codec *codec)
                }
        }
 
-       if (mixer && spec->add_stereo_mix_input) {
+       /* add stereo mix when explicitly enabled via hint */
+       if (mixer && spec->add_stereo_mix_input &&
+           snd_hda_get_bool_hint(codec, "add_stereo_mix_input") > 0) {
                err = parse_capture_source(codec, mixer, CFG_IDX_MIX, num_adcs,
                                           "Stereo Mix", 0);
                if (err < 0)
@@ -4297,6 +4323,26 @@ static unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
        return AC_PWRST_D3;
 }
 
+/* mute all aamix inputs initially; parse up to the first leaves */
+static void mute_all_mixer_nid(struct hda_codec *codec, hda_nid_t mix)
+{
+       int i, nums;
+       const hda_nid_t *conn;
+       bool has_amp;
+
+       nums = snd_hda_get_conn_list(codec, mix, &conn);
+       has_amp = nid_has_mute(codec, mix, HDA_INPUT);
+       for (i = 0; i < nums; i++) {
+               if (has_amp)
+                       snd_hda_codec_amp_stereo(codec, mix,
+                                                HDA_INPUT, i,
+                                                0xff, HDA_AMP_MUTE);
+               else if (nid_has_volume(codec, conn[i], HDA_OUTPUT))
+                       snd_hda_codec_amp_stereo(codec, conn[i],
+                                                HDA_OUTPUT, 0,
+                                                0xff, HDA_AMP_MUTE);
+       }
+}
 
 /*
  * Parse the given BIOS configuration and set up the hda_gen_spec
@@ -4333,7 +4379,8 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
                        spec->no_analog = 1;
                        goto dig_only;
                }
-               return 0; /* can't find valid BIOS pin config */
+               if (!cfg->num_inputs && !cfg->dig_in_pin)
+                       return 0; /* can't find valid BIOS pin config */
        }
 
        if (!spec->no_primary_hp &&
@@ -4401,6 +4448,19 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
        if (err < 0)
                return err;
 
+       /* add stereo mix if available and not enabled yet */
+       if (!spec->auto_mic && spec->mixer_nid &&
+           spec->add_stereo_mix_input &&
+           spec->input_mux.num_items > 1 &&
+           snd_hda_get_bool_hint(codec, "add_stereo_mix_input") < 0) {
+               err = parse_capture_source(codec, spec->mixer_nid,
+                                          CFG_IDX_MIX, spec->num_all_adcs,
+                                          "Stereo Mix", 0);
+               if (err < 0)
+                       return err;
+       }
+
+
        err = create_capture_mixers(codec);
        if (err < 0)
                return err;
@@ -4435,6 +4495,10 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
                }
        }
 
+       /* mute all aamix input initially */
+       if (spec->mixer_nid)
+               mute_all_mixer_nid(codec, spec->mixer_nid);
+
  dig_only:
        parse_digital(codec);
 
@@ -5138,6 +5202,23 @@ static void init_multi_io(struct hda_codec *codec)
        }
 }
 
+static void init_aamix_paths(struct hda_codec *codec)
+{
+       struct hda_gen_spec *spec = codec->spec;
+
+       if (!spec->have_aamix_ctl)
+               return;
+       update_aamix_paths(codec, spec->aamix_mode, spec->out_paths[0],
+                          spec->aamix_out_paths[0],
+                          spec->autocfg.line_out_type);
+       update_aamix_paths(codec, spec->aamix_mode, spec->hp_paths[0],
+                          spec->aamix_out_paths[1],
+                          AUTO_PIN_HP_OUT);
+       update_aamix_paths(codec, spec->aamix_mode, spec->speaker_paths[0],
+                          spec->aamix_out_paths[2],
+                          AUTO_PIN_SPEAKER_OUT);
+}
+
 /* set up input pins and loopback paths */
 static void init_analog_input(struct hda_codec *codec)
 {
@@ -5240,6 +5321,7 @@ int snd_hda_gen_init(struct hda_codec *codec)
        init_multi_out(codec);
        init_extra_out(codec);
        init_multi_io(codec);
+       init_aamix_paths(codec);
        init_analog_input(codec);
        init_input_src(codec);
        init_digital(codec);
@@ -5328,3 +5410,6 @@ error:
        return err;
 }
 EXPORT_SYMBOL_HDA(snd_hda_parse_generic_codec);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Generic HD-audio codec parser");
index 7e45cb44d1514497385f2f6bc2b63251391cdaba..0929a06df8128495f5e717768fcfa28eaed7360d 100644 (file)
@@ -249,6 +249,9 @@ struct hda_gen_spec {
        const struct badness_table *main_out_badness;
        const struct badness_table *extra_out_badness;
 
+       /* preferred pin/DAC pairs; an array of paired NIDs */
+       const hda_nid_t *preferred_dacs;
+
        /* loopback mixing mode */
        bool aamix_mode;
 
index c6d230193da6214700e23369df0d2355c301012a..af86c71f27bf08d7d521cb43137c40a75033677c 100644 (file)
@@ -431,6 +431,8 @@ struct azx_dev {
        struct timecounter  azx_tc;
        struct cyclecounter azx_cc;
 
+       int delay_negative_threshold;
+
 #ifdef CONFIG_SND_HDA_DSP_LOADER
        struct mutex dsp_mutex;
 #endif
@@ -543,9 +545,7 @@ struct azx {
        /* for pending irqs */
        struct work_struct irq_pending_work;
 
-#ifdef CONFIG_SND_HDA_I915
        struct work_struct probe_work;
-#endif
 
        /* reboot notifier (for mysterious hangup problem at power-down) */
        struct notifier_block reboot_notifier;
@@ -2197,6 +2197,15 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
                        goto unlock;
        }
 
+       /* when LPIB delay correction gives a small negative value,
+        * we ignore it; currently set the threshold statically to
+        * 64 frames
+        */
+       if (runtime->period_size > 64)
+               azx_dev->delay_negative_threshold = -frames_to_bytes(runtime, 64);
+       else
+               azx_dev->delay_negative_threshold = 0;
+
        /* wallclk has 24Mhz clock source */
        azx_dev->period_wallclk = (((runtime->period_size * 24000) /
                                                runtime->rate) * 1000);
@@ -2449,8 +2458,12 @@ static unsigned int azx_get_position(struct azx *chip,
                        delay = pos - lpib_pos;
                else
                        delay = lpib_pos - pos;
-               if (delay < 0)
-                       delay += azx_dev->bufsize;
+               if (delay < 0) {
+                       if (delay >= azx_dev->delay_negative_threshold)
+                               delay = 0;
+                       else
+                               delay += azx_dev->bufsize;
+               }
                if (delay >= azx_dev->period_bytes) {
                        snd_printk(KERN_WARNING SFX
                                   "%s: Unstable LPIB (%d >= %d); "
@@ -3500,12 +3513,10 @@ static void azx_check_snoop_available(struct azx *chip)
        }
 }
 
-#ifdef CONFIG_SND_HDA_I915
 static void azx_probe_work(struct work_struct *work)
 {
        azx_probe_continue(container_of(work, struct azx, probe_work));
 }
-#endif
 
 /*
  * constructor
@@ -3582,10 +3593,8 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
                return err;
        }
 
-#ifdef CONFIG_SND_HDA_I915
        /* continue probing in work context as may trigger request module */
        INIT_WORK(&chip->probe_work, azx_probe_work);
-#endif
 
        *rchip = chip;
 
@@ -3805,7 +3814,7 @@ static int azx_probe(struct pci_dev *pci,
        static int dev;
        struct snd_card *card;
        struct azx *chip;
-       bool probe_now;
+       bool schedule_probe;
        int err;
 
        if (dev >= SNDRV_CARDS)
@@ -3844,7 +3853,7 @@ static int azx_probe(struct pci_dev *pci,
                chip->disabled = true;
        }
 
-       probe_now = !chip->disabled;
+       schedule_probe = !chip->disabled;
 
 #ifdef CONFIG_SND_HDA_PATCH_LOADER
        if (patch[dev] && *patch[dev]) {
@@ -3855,28 +3864,21 @@ static int azx_probe(struct pci_dev *pci,
                                              azx_firmware_cb);
                if (err < 0)
                        goto out_free;
-               probe_now = false; /* continued in azx_firmware_cb() */
+               schedule_probe = false; /* continued in azx_firmware_cb() */
        }
 #endif /* CONFIG_SND_HDA_PATCH_LOADER */
 
-       /* continue probing in work context, avoid request_module deadlock */
-       if (probe_now && (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)) {
-#ifdef CONFIG_SND_HDA_I915
-               probe_now = false;
-               schedule_work(&chip->probe_work);
-#else
+#ifndef CONFIG_SND_HDA_I915
+       if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
                snd_printk(KERN_ERR SFX "Haswell must build in CONFIG_SND_HDA_I915\n");
 #endif
-       }
 
-       if (probe_now) {
-               err = azx_probe_continue(chip);
-               if (err < 0)
-                       goto out_free;
-       }
+       if (schedule_probe)
+               schedule_work(&chip->probe_work);
 
        dev++;
-       complete_all(&chip->probe_wait);
+       if (chip->disabled)
+               complete_all(&chip->probe_wait);
        return 0;
 
 out_free:
@@ -3953,10 +3955,10 @@ static int azx_probe_continue(struct azx *chip)
        if ((chip->driver_caps & AZX_DCAPS_PM_RUNTIME) || chip->use_vga_switcheroo)
                pm_runtime_put_noidle(&pci->dev);
 
-       return 0;
-
 out_free:
-       chip->init_failed = 1;
+       if (err < 0)
+               chip->init_failed = 1;
+       complete_all(&chip->probe_wait);
        return err;
 }
 
@@ -3978,7 +3980,7 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
          .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM },
        /* Panther Point */
        { PCI_DEVICE(0x8086, 0x1e20),
-         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM },
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
        /* Lynx Point */
        { PCI_DEVICE(0x8086, 0x8c20),
          .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
index d398b648bb5d1478d63e8d430d333eedda45beb3..da80c5bd7fd42ecacaa99e17befd8bef5c40099f 100644 (file)
@@ -352,14 +352,8 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
 /*
  * generic codec parser
  */
-#ifdef CONFIG_SND_HDA_GENERIC
 int snd_hda_parse_generic_codec(struct hda_codec *codec);
-#else
-static inline int snd_hda_parse_generic_codec(struct hda_codec *codec)
-{
-       return -ENODEV;
-}
-#endif
+int snd_hda_parse_hdmi_codec(struct hda_codec *codec);
 
 /*
  * generic proc interface
index 1a83559f4cbd27e455a941adaddc6d0513d9dd81..b174eb1567b8c243b81428c3d2d4f373dd7033f0 100644 (file)
@@ -147,6 +147,8 @@ static void ad_vmaster_eapd_hook(void *private_data, int enabled)
 
        if (!spec->eapd_nid)
                return;
+       if (codec->inv_eapd)
+               enabled = !enabled;
        snd_hda_codec_update_cache(codec, spec->eapd_nid, 0,
                                   AC_VERB_SET_EAPD_BTLENABLE,
                                   enabled ? 0x02 : 0x00);
@@ -194,6 +196,7 @@ static int ad198x_parse_auto_config(struct hda_codec *codec)
        codec->no_sticky_stream = 1;
 
        spec->gen.indep_hp = 1;
+       spec->gen.add_stereo_mix_input = 1;
 
        err = snd_hda_parse_pin_defcfg(codec, cfg, NULL, 0);
        if (err < 0)
@@ -338,6 +341,14 @@ static int patch_ad1986a(struct hda_codec *codec)
 {
        int err;
        struct ad198x_spec *spec;
+       static hda_nid_t preferred_pairs[] = {
+               0x1a, 0x03,
+               0x1b, 0x03,
+               0x1c, 0x04,
+               0x1d, 0x05,
+               0x1e, 0x03,
+               0
+       };
 
        err = alloc_ad_spec(codec);
        if (err < 0)
@@ -358,6 +369,11 @@ static int patch_ad1986a(struct hda_codec *codec)
         * So, let's disable the shared stream.
         */
        spec->gen.multiout.no_share_stream = 1;
+       /* give fixed DAC/pin pairs */
+       spec->gen.preferred_dacs = preferred_pairs;
+
+       /* AD1986A can't manage the dynamic pin on/off smoothly */
+       spec->gen.auto_mute_via_amp = 1;
 
        snd_hda_pick_fixup(codec, ad1986a_fixup_models, ad1986a_fixup_tbl,
                           ad1986a_fixups);
@@ -962,6 +978,7 @@ static void ad1884_fixup_hp_eapd(struct hda_codec *codec,
        switch (action) {
        case HDA_FIXUP_ACT_PRE_PROBE:
                spec->gen.vmaster_mute.hook = ad1884_vmaster_hp_gpio_hook;
+               spec->gen.own_eapd_ctl = 1;
                snd_hda_sequence_write_cache(codec, gpio_init_verbs);
                break;
        case HDA_FIXUP_ACT_PROBE:
index 1f2717f817a0142f4ef17910ffd50dafe42e4c09..3fbf2883e06e855e7a79213b0414e3049b539f28 100644 (file)
@@ -2936,7 +2936,6 @@ static const struct snd_pci_quirk cxt5066_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x0401, "Dell Vostro 1014", CXT5066_DELL_VOSTRO),
        SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x1028, 0x050f, "Dell Inspiron", CXT5066_IDEAPAD),
-       SND_PCI_QUIRK(0x1028, 0x0510, "Dell Vostro", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP),
        SND_PCI_QUIRK(0x1043, 0x13f3, "Asus A52J", CXT5066_ASUS),
        SND_PCI_QUIRK(0x1043, 0x1643, "Asus K52JU", CXT5066_ASUS),
index 08407bed093e5a64d4b659f90bf236dead9ec002..f5060fc7c3032b7649cbba0538e258783411552e 100644 (file)
@@ -1142,32 +1142,34 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec,
 
 static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll);
 
-static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
+static void jack_callback(struct hda_codec *codec, struct hda_jack_tbl *jack)
 {
        struct hdmi_spec *spec = codec->spec;
+       int pin_idx = pin_nid_to_pin_index(spec, jack->nid);
+       if (pin_idx < 0)
+               return;
+
+       if (hdmi_present_sense(get_pin(spec, pin_idx), 1))
+               snd_hda_jack_report_sync(codec);
+}
+
+static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
+{
        int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
-       int pin_nid;
-       int pin_idx;
        struct hda_jack_tbl *jack;
        int dev_entry = (res & AC_UNSOL_RES_DE) >> AC_UNSOL_RES_DE_SHIFT;
 
        jack = snd_hda_jack_tbl_get_from_tag(codec, tag);
        if (!jack)
                return;
-       pin_nid = jack->nid;
        jack->jack_dirty = 1;
 
        _snd_printd(SND_PR_VERBOSE,
                "HDMI hot plug event: Codec=%d Pin=%d Device=%d Inactive=%d Presence_Detect=%d ELD_Valid=%d\n",
-               codec->addr, pin_nid, dev_entry, !!(res & AC_UNSOL_RES_IA),
+               codec->addr, jack->nid, dev_entry, !!(res & AC_UNSOL_RES_IA),
                !!(res & AC_UNSOL_RES_PD), !!(res & AC_UNSOL_RES_ELDV));
 
-       pin_idx = pin_nid_to_pin_index(spec, pin_nid);
-       if (pin_idx < 0)
-               return;
-
-       if (hdmi_present_sense(get_pin(spec, pin_idx), 1))
-               snd_hda_jack_report_sync(codec);
+       jack_callback(codec, jack);
 }
 
 static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
@@ -1692,21 +1694,6 @@ static int hdmi_parse_codec(struct hda_codec *codec)
                }
        }
 
-#ifdef CONFIG_PM
-       /* We're seeing some problems with unsolicited hot plug events on
-        * PantherPoint after S3, if this is not enabled */
-       if (codec->vendor_id == 0x80862806)
-               codec->bus->power_keep_link_on = 1;
-       /*
-        * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event
-        * can be lost and presence sense verb will become inaccurate if the
-        * HDA link is powered off at hot plug or hw initialization time.
-        */
-       else if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) &
-             AC_PWRST_EPSS))
-               codec->bus->power_keep_link_on = 1;
-#endif
-
        return 0;
 }
 
@@ -2095,7 +2082,8 @@ static int generic_hdmi_init(struct hda_codec *codec)
                hda_nid_t pin_nid = per_pin->pin_nid;
 
                hdmi_init_pin(codec, pin_nid);
-               snd_hda_jack_detect_enable(codec, pin_nid, pin_nid);
+               snd_hda_jack_detect_enable_callback(codec, pin_nid, pin_nid,
+                       codec->jackpoll_interval > 0 ? jack_callback : NULL);
        }
        return 0;
 }
@@ -2262,6 +2250,10 @@ static int patch_generic_hdmi(struct hda_codec *codec)
                intel_haswell_fixup_enable_dp12(codec);
        }
 
+       if (is_haswell(codec) || is_valleyview(codec)) {
+               codec->depop_delay = 0;
+       }
+
        if (hdmi_parse_codec(codec) < 0) {
                codec->spec = NULL;
                kfree(spec);
@@ -2334,8 +2326,9 @@ static int simple_playback_build_controls(struct hda_codec *codec)
        int err;
 
        per_cvt = get_cvt(spec, 0);
-       err = snd_hda_create_spdif_out_ctls(codec, per_cvt->cvt_nid,
-                                           per_cvt->cvt_nid);
+       err = snd_hda_create_dig_out_ctls(codec, per_cvt->cvt_nid,
+                                         per_cvt->cvt_nid,
+                                         HDA_PCM_TYPE_HDMI);
        if (err < 0)
                return err;
        return simple_hdmi_build_jack(codec, 0);
@@ -3213,6 +3206,15 @@ static int patch_via_hdmi(struct hda_codec *codec)
        return patch_simple_hdmi(codec, VIAHDMI_CVT_NID, VIAHDMI_PIN_NID);
 }
 
+/*
+ * called from hda_codec.c for generic HDMI support
+ */
+int snd_hda_parse_hdmi_codec(struct hda_codec *codec)
+{
+       return patch_generic_hdmi(codec);
+}
+EXPORT_SYMBOL_HDA(snd_hda_parse_hdmi_codec);
+
 /*
  * patch entries
  */
index c770bdba6531c8a0d3eaf2f64e2c38d6d8ad758c..c5f3e1b85b17c830c13e709cc4825603be0ac66e 100644 (file)
@@ -118,7 +118,8 @@ struct alc_spec {
 
        int init_amp;
        int codec_variant;      /* flag for other variants */
-       bool has_alc5505_dsp;
+       unsigned int has_alc5505_dsp:1;
+       unsigned int no_depop_delay:1;
 
        /* for PLL fix */
        hda_nid_t pll_nid;
@@ -280,8 +281,11 @@ static void alc_auto_setup_eapd(struct hda_codec *codec, bool on)
  */
 static void alc_eapd_shutup(struct hda_codec *codec)
 {
+       struct alc_spec *spec = codec->spec;
+
        alc_auto_setup_eapd(codec, false);
-       msleep(200);
+       if (!spec->no_depop_delay)
+               msleep(200);
        snd_hda_shutup_pins(codec);
 }
 
@@ -365,6 +369,17 @@ static void alc_fixup_sku_ignore(struct hda_codec *codec,
        }
 }
 
+static void alc_fixup_no_depop_delay(struct hda_codec *codec,
+                                   const struct hda_fixup *fix, int action)
+{
+       struct alc_spec *spec = codec->spec;
+
+       if (action == HDA_FIXUP_ACT_PROBE) {
+               spec->no_depop_delay = 1;
+               codec->depop_delay = 0;
+       }
+}
+
 static int alc_auto_parse_customize_define(struct hda_codec *codec)
 {
        unsigned int ass, tmp, i;
@@ -863,7 +878,10 @@ static int alc_suspend(struct hda_codec *codec)
 #ifdef CONFIG_PM
 static int alc_resume(struct hda_codec *codec)
 {
-       msleep(150); /* to avoid pop noise */
+       struct alc_spec *spec = codec->spec;
+
+       if (!spec->no_depop_delay)
+               msleep(150); /* to avoid pop noise */
        codec->patch_ops.init(codec);
        snd_hda_codec_resume_amp(codec);
        snd_hda_codec_resume_cache(codec);
@@ -903,7 +921,7 @@ static int alc_codec_rename(struct hda_codec *codec, const char *name)
 }
 
 /*
- * Rename codecs appropriately from COEF value
+ * Rename codecs appropriately from COEF value or subvendor id
  */
 struct alc_codec_rename_table {
        unsigned int vendor_id;
@@ -912,6 +930,13 @@ struct alc_codec_rename_table {
        const char *name;
 };
 
+struct alc_codec_rename_pci_table {
+       unsigned int codec_vendor_id;
+       unsigned short pci_subvendor;
+       unsigned short pci_subdevice;
+       const char *name;
+};
+
 static struct alc_codec_rename_table rename_tbl[] = {
        { 0x10ec0269, 0xfff0, 0x3010, "ALC277" },
        { 0x10ec0269, 0xf0f0, 0x2010, "ALC259" },
@@ -931,9 +956,20 @@ static struct alc_codec_rename_table rename_tbl[] = {
        { } /* terminator */
 };
 
+static struct alc_codec_rename_pci_table rename_pci_tbl[] = {
+       { 0x10ec0280, 0x1028, 0, "ALC3220" },
+       { 0x10ec0282, 0x1028, 0, "ALC3221" },
+       { 0x10ec0283, 0x1028, 0, "ALC3223" },
+       { 0x10ec0292, 0x1028, 0, "ALC3226" },
+       { 0x10ec0255, 0x1028, 0, "ALC3234" },
+       { 0x10ec0668, 0x1028, 0, "ALC3661" },
+       { } /* terminator */
+};
+
 static int alc_codec_rename_from_preset(struct hda_codec *codec)
 {
        const struct alc_codec_rename_table *p;
+       const struct alc_codec_rename_pci_table *q;
 
        for (p = rename_tbl; p->vendor_id; p++) {
                if (p->vendor_id != codec->vendor_id)
@@ -941,6 +977,17 @@ static int alc_codec_rename_from_preset(struct hda_codec *codec)
                if ((alc_get_coef0(codec) & p->coef_mask) == p->coef_bits)
                        return alc_codec_rename(codec, p->name);
        }
+
+       for (q = rename_pci_tbl; q->codec_vendor_id; q++) {
+               if (q->codec_vendor_id != codec->vendor_id)
+                       continue;
+               if (q->pci_subvendor != codec->bus->pci->subsystem_vendor)
+                       continue;
+               if (!q->pci_subdevice ||
+                   q->pci_subdevice == codec->bus->pci->subsystem_device)
+                       return alc_codec_rename(codec, q->name);
+       }
+
        return 0;
 }
 
@@ -1780,6 +1827,7 @@ enum {
        ALC889_FIXUP_DAC_ROUTE,
        ALC889_FIXUP_MBP_VREF,
        ALC889_FIXUP_IMAC91_VREF,
+       ALC889_FIXUP_MBA21_VREF,
        ALC882_FIXUP_INV_DMIC,
        ALC882_FIXUP_NO_PRIMARY_HP,
        ALC887_FIXUP_ASUS_BASS,
@@ -1884,17 +1932,13 @@ static void alc889_fixup_mbp_vref(struct hda_codec *codec,
        }
 }
 
-/* Set VREF on speaker pins on imac91 */
-static void alc889_fixup_imac91_vref(struct hda_codec *codec,
-                                    const struct hda_fixup *fix, int action)
+static void alc889_fixup_mac_pins(struct hda_codec *codec,
+                                 const hda_nid_t *nids, int num_nids)
 {
        struct alc_spec *spec = codec->spec;
-       static hda_nid_t nids[2] = { 0x18, 0x1a };
        int i;
 
-       if (action != HDA_FIXUP_ACT_INIT)
-               return;
-       for (i = 0; i < ARRAY_SIZE(nids); i++) {
+       for (i = 0; i < num_nids; i++) {
                unsigned int val;
                val = snd_hda_codec_get_pin_target(codec, nids[i]);
                val |= AC_PINCTL_VREF_50;
@@ -1903,6 +1947,26 @@ static void alc889_fixup_imac91_vref(struct hda_codec *codec,
        spec->gen.keep_vref_in_automute = 1;
 }
 
+/* Set VREF on speaker pins on imac91 */
+static void alc889_fixup_imac91_vref(struct hda_codec *codec,
+                                    const struct hda_fixup *fix, int action)
+{
+       static hda_nid_t nids[2] = { 0x18, 0x1a };
+
+       if (action == HDA_FIXUP_ACT_INIT)
+               alc889_fixup_mac_pins(codec, nids, ARRAY_SIZE(nids));
+}
+
+/* Set VREF on speaker pins on mba21 */
+static void alc889_fixup_mba21_vref(struct hda_codec *codec,
+                                   const struct hda_fixup *fix, int action)
+{
+       static hda_nid_t nids[2] = { 0x18, 0x19 };
+
+       if (action == HDA_FIXUP_ACT_INIT)
+               alc889_fixup_mac_pins(codec, nids, ARRAY_SIZE(nids));
+}
+
 /* Don't take HP output as primary
  * Strangely, the speaker output doesn't work on Vaio Z and some Vaio
  * all-in-one desktop PCs (for example VGC-LN51JGB) through DAC 0x05
@@ -2102,6 +2166,12 @@ static const struct hda_fixup alc882_fixups[] = {
                .chained = true,
                .chain_id = ALC882_FIXUP_GPIO1,
        },
+       [ALC889_FIXUP_MBA21_VREF] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc889_fixup_mba21_vref,
+               .chained = true,
+               .chain_id = ALC889_FIXUP_MBP_VREF,
+       },
        [ALC882_FIXUP_INV_DMIC] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc_fixup_inv_dmic_0x12,
@@ -2172,7 +2242,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK(0x106b, 0x3000, "iMac", ALC889_FIXUP_MBP_VREF),
        SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_FIXUP_EAPD),
        SND_PCI_QUIRK(0x106b, 0x3400, "MacBookAir 1,1", ALC889_FIXUP_MBP_VREF),
-       SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC889_FIXUP_MBP_VREF),
+       SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC889_FIXUP_MBA21_VREF),
        SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889_FIXUP_MBP_VREF),
        SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF),
        SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_FIXUP_MACPRO_GPIO),
@@ -2291,6 +2361,7 @@ enum {
        ALC262_FIXUP_BENQ,
        ALC262_FIXUP_BENQ_T31,
        ALC262_FIXUP_INV_DMIC,
+       ALC262_FIXUP_INTEL_BAYLEYBAY,
 };
 
 static const struct hda_fixup alc262_fixups[] = {
@@ -2355,6 +2426,10 @@ static const struct hda_fixup alc262_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc_fixup_inv_dmic_0x12,
        },
+       [ALC262_FIXUP_INTEL_BAYLEYBAY] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc_fixup_no_depop_delay,
+       },
 };
 
 static const struct snd_pci_quirk alc262_fixup_tbl[] = {
@@ -2366,6 +2441,7 @@ static const struct snd_pci_quirk alc262_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000", ALC262_FIXUP_LENOVO_3000),
        SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_FIXUP_BENQ),
        SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_FIXUP_BENQ_T31),
+       SND_PCI_QUIRK(0x8086, 0x7270, "BayleyBay", ALC262_FIXUP_INTEL_BAYLEYBAY),
        {}
 };
 
@@ -3287,6 +3363,7 @@ static void alc_headset_mode_ctia(struct hda_codec *codec)
                alc_write_coef_idx(codec, 0x18, 0x7388);
                break;
        case 0x10ec0668:
+               alc_write_coef_idx(codec, 0x11, 0x0001);
                alc_write_coef_idx(codec, 0x15, 0x0d60);
                alc_write_coef_idx(codec, 0xc3, 0x0000);
                break;
@@ -3315,6 +3392,7 @@ static void alc_headset_mode_omtp(struct hda_codec *codec)
                alc_write_coef_idx(codec, 0x18, 0x7388);
                break;
        case 0x10ec0668:
+               alc_write_coef_idx(codec, 0x11, 0x0001);
                alc_write_coef_idx(codec, 0x15, 0x0d50);
                alc_write_coef_idx(codec, 0xc3, 0x0000);
                break;
@@ -3600,11 +3678,6 @@ static void alc283_hp_automute_hook(struct hda_codec *codec,
                            vref);
 }
 
-static void alc283_chromebook_caps(struct hda_codec *codec)
-{
-       snd_hda_override_wcaps(codec, 0x03, 0);
-}
-
 static void alc283_fixup_chromebook(struct hda_codec *codec,
                                    const struct hda_fixup *fix, int action)
 {
@@ -3613,9 +3686,26 @@ static void alc283_fixup_chromebook(struct hda_codec *codec,
 
        switch (action) {
        case HDA_FIXUP_ACT_PRE_PROBE:
-               alc283_chromebook_caps(codec);
+               snd_hda_override_wcaps(codec, 0x03, 0);
                /* Disable AA-loopback as it causes white noise */
                spec->gen.mixer_nid = 0;
+               break;
+       case HDA_FIXUP_ACT_INIT:
+               /* Enable Line1 input control by verb */
+               val = alc_read_coef_idx(codec, 0x1a);
+               alc_write_coef_idx(codec, 0x1a, val | (1 << 4));
+               break;
+       }
+}
+
+static void alc283_fixup_sense_combo_jack(struct hda_codec *codec,
+                                   const struct hda_fixup *fix, int action)
+{
+       struct alc_spec *spec = codec->spec;
+       int val;
+
+       switch (action) {
+       case HDA_FIXUP_ACT_PRE_PROBE:
                spec->gen.hp_automute_hook = alc283_hp_automute_hook;
                break;
        case HDA_FIXUP_ACT_INIT:
@@ -3623,9 +3713,6 @@ static void alc283_fixup_chromebook(struct hda_codec *codec,
                /* Set to manual mode */
                val = alc_read_coef_idx(codec, 0x06);
                alc_write_coef_idx(codec, 0x06, val & ~0x000c);
-               /* Enable Line1 input control by verb */
-               val = alc_read_coef_idx(codec, 0x1a);
-               alc_write_coef_idx(codec, 0x1a, val | (1 << 4));
                break;
        }
 }
@@ -3815,12 +3902,14 @@ enum {
        ALC269_FIXUP_ASUS_X101,
        ALC271_FIXUP_AMIC_MIC2,
        ALC271_FIXUP_HP_GATE_MIC_JACK,
+       ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572,
        ALC269_FIXUP_ACER_AC700,
        ALC269_FIXUP_LIMIT_INT_MIC_BOOST,
        ALC269VB_FIXUP_ASUS_ZENBOOK,
        ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED,
        ALC269VB_FIXUP_ORDISSIMO_EVE2,
        ALC283_FIXUP_CHROME_BOOK,
+       ALC283_FIXUP_SENSE_COMBO_JACK,
        ALC282_FIXUP_ASUS_TX300,
        ALC283_FIXUP_INT_MIC,
        ALC290_FIXUP_MONO_SPEAKERS,
@@ -4076,6 +4165,12 @@ static const struct hda_fixup alc269_fixups[] = {
                .chained = true,
                .chain_id = ALC271_FIXUP_AMIC_MIC2,
        },
+       [ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc269_fixup_limit_int_mic_boost,
+               .chained = true,
+               .chain_id = ALC271_FIXUP_HP_GATE_MIC_JACK,
+       },
        [ALC269_FIXUP_ACER_AC700] = {
                .type = HDA_FIXUP_PINS,
                .v.pins = (const struct hda_pintbl[]) {
@@ -4120,6 +4215,12 @@ static const struct hda_fixup alc269_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc283_fixup_chromebook,
        },
+       [ALC283_FIXUP_SENSE_COMBO_JACK] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc283_fixup_sense_combo_jack,
+               .chained = true,
+               .chain_id = ALC283_FIXUP_CHROME_BOOK,
+       },
        [ALC282_FIXUP_ASUS_TX300] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc282_fixup_asus_tx300,
@@ -4167,6 +4268,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK),
        SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK),
        SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
+       SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572),
        SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
        SND_PCI_QUIRK(0x1028, 0x05bd, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x05be, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
@@ -4202,6 +4304,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x0614, "Dell Inspiron 3135", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_MONO_SPEAKERS),
        SND_PCI_QUIRK(0x1028, 0x061f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS),
        SND_PCI_QUIRK(0x1028, 0x063f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x15cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x15cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
@@ -4210,7 +4313,6 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x1973, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1),
        SND_PCI_QUIRK(0x103c, 0x1983, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1),
        SND_PCI_QUIRK(0x103c, 0x218b, "HP", ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED),
-       SND_PCI_QUIRK(0x103c, 0x21ed, "HP Falco Chromebook", ALC283_FIXUP_CHROME_BOOK),
        SND_PCI_QUIRK_VENDOR(0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED),
        SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
        SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
@@ -4318,6 +4420,8 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
        {.id = ALC269_FIXUP_HP_GPIO_LED, .name = "hp-gpio-led"},
        {.id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "dell-headset-multi"},
        {.id = ALC269_FIXUP_DELL2_MIC_NO_PRESENCE, .name = "dell-headset-dock"},
+       {.id = ALC283_FIXUP_CHROME_BOOK, .name = "alc283-chrome"},
+       {.id = ALC283_FIXUP_SENSE_COMBO_JACK, .name = "alc283-sense-combo"},
        {}
 };
 
@@ -4447,7 +4551,7 @@ static int patch_alc269(struct hda_codec *codec)
        }
 
        if (snd_hda_codec_read(codec, 0x51, 0, AC_VERB_PARAMETERS, 0) == 0x10ec5505) {
-               spec->has_alc5505_dsp = true;
+               spec->has_alc5505_dsp = 1;
                spec->init_hook = alc5505_dsp_init;
        }
 
@@ -4493,6 +4597,7 @@ enum {
        ALC861_FIXUP_AMP_VREF_0F,
        ALC861_FIXUP_NO_JACK_DETECT,
        ALC861_FIXUP_ASUS_A6RP,
+       ALC660_FIXUP_ASUS_W7J,
 };
 
 /* On some laptops, VREF of pin 0x0f is abused for controlling the main amp */
@@ -4542,10 +4647,22 @@ static const struct hda_fixup alc861_fixups[] = {
                .v.func = alc861_fixup_asus_amp_vref_0f,
                .chained = true,
                .chain_id = ALC861_FIXUP_NO_JACK_DETECT,
+       },
+       [ALC660_FIXUP_ASUS_W7J] = {
+               .type = HDA_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
+                       /* ASUS W7J needs a magic pin setup on unused NID 0x10
+                        * for enabling outputs
+                        */
+                       {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+                       { }
+               },
        }
 };
 
 static const struct snd_pci_quirk alc861_fixup_tbl[] = {
+       SND_PCI_QUIRK(0x1043, 0x1253, "ASUS W7J", ALC660_FIXUP_ASUS_W7J),
+       SND_PCI_QUIRK(0x1043, 0x1263, "ASUS Z35HL", ALC660_FIXUP_ASUS_W7J),
        SND_PCI_QUIRK(0x1043, 0x1393, "ASUS A6Rp", ALC861_FIXUP_ASUS_A6RP),
        SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", ALC861_FIXUP_AMP_VREF_0F),
        SND_PCI_QUIRK(0x1462, 0x7254, "HP DX2200", ALC861_FIXUP_NO_JACK_DETECT),
@@ -4978,8 +5095,11 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
        SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0623, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0624, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0625, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0626, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0628, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
        SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_BASS_1A_CHMAP),
        SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_CHMAP),
index 0bc20ef5687ac3558996ca3fd56a741c75bc042b..f84195f3ea31e2f6bac3c1c5f79355e1ec24c0fb 100644 (file)
@@ -138,6 +138,7 @@ static struct via_spec *via_new_spec(struct hda_codec *codec)
        spec->gen.indep_hp = 1;
        spec->gen.keep_eapd_on = 1;
        spec->gen.pcm_playback_hook = via_playback_pcm_hook;
+       spec->gen.add_stereo_mix_input = 1;
        return spec;
 }
 
index 5138b8493051fd54c674fe26ea87d9d5fd1411c6..d62ce483a443a5298688f51462e807e6ea1b2cb4 100644 (file)
@@ -31,8 +31,10 @@ config SND_SOC_GENERIC_DMAENGINE_PCM
        select SND_DMAENGINE_PCM
 
 # All the supported SoCs
+source "sound/soc/adi/Kconfig"
 source "sound/soc/atmel/Kconfig"
 source "sound/soc/au1x/Kconfig"
+source "sound/soc/bcm/Kconfig"
 source "sound/soc/blackfin/Kconfig"
 source "sound/soc/cirrus/Kconfig"
 source "sound/soc/davinci/Kconfig"
@@ -42,7 +44,7 @@ source "sound/soc/jz4740/Kconfig"
 source "sound/soc/nuc900/Kconfig"
 source "sound/soc/omap/Kconfig"
 source "sound/soc/kirkwood/Kconfig"
-source "sound/soc/mid-x86/Kconfig"
+source "sound/soc/intel/Kconfig"
 source "sound/soc/mxs/Kconfig"
 source "sound/soc/pxa/Kconfig"
 source "sound/soc/samsung/Kconfig"
index 8b9e70105dd28f5ccceabad1cd2ea414a97640a1..62a1822e77bf6f42410fd68c6d539c8cf97c922f 100644 (file)
@@ -8,15 +8,17 @@ endif
 obj-$(CONFIG_SND_SOC)  += snd-soc-core.o
 obj-$(CONFIG_SND_SOC)  += codecs/
 obj-$(CONFIG_SND_SOC)  += generic/
+obj-$(CONFIG_SND_SOC)  += adi/
 obj-$(CONFIG_SND_SOC)  += atmel/
 obj-$(CONFIG_SND_SOC)  += au1x/
+obj-$(CONFIG_SND_SOC)  += bcm/
 obj-$(CONFIG_SND_SOC)  += blackfin/
 obj-$(CONFIG_SND_SOC)  += cirrus/
 obj-$(CONFIG_SND_SOC)  += davinci/
 obj-$(CONFIG_SND_SOC)  += dwc/
 obj-$(CONFIG_SND_SOC)  += fsl/
 obj-$(CONFIG_SND_SOC)  += jz4740/
-obj-$(CONFIG_SND_SOC)  += mid-x86/
+obj-$(CONFIG_SND_SOC)  += intel/
 obj-$(CONFIG_SND_SOC)  += mxs/
 obj-$(CONFIG_SND_SOC)  += nuc900/
 obj-$(CONFIG_SND_SOC)  += omap/
diff --git a/sound/soc/adi/Kconfig b/sound/soc/adi/Kconfig
new file mode 100644 (file)
index 0000000..dd763f5
--- /dev/null
@@ -0,0 +1,21 @@
+config SND_SOC_ADI
+       tristate "Audio support for Analog Devices reference designs"
+       depends on MICROBLAZE || ARCH_ZYNQ || COMPILE_TEST
+       help
+         Audio support for various reference designs by Analog Devices.
+
+config SND_SOC_ADI_AXI_I2S
+       tristate "AXI-I2S support"
+       depends on SND_SOC_ADI
+       select SND_SOC_GENERIC_DMAENGINE_PCM
+       select REGMAP_MMIO
+       help
+         ASoC driver for the Analog Devices AXI-I2S softcore peripheral.
+
+config SND_SOC_ADI_AXI_SPDIF
+       tristate "AXI-SPDIF support"
+       depends on SND_SOC_ADI
+       select SND_SOC_GENERIC_DMAENGINE_PCM
+       select REGMAP_MMIO
+       help
+         ASoC driver for the Analog Devices AXI-SPDIF softcore peripheral.
diff --git a/sound/soc/adi/Makefile b/sound/soc/adi/Makefile
new file mode 100644 (file)
index 0000000..64456c1
--- /dev/null
@@ -0,0 +1,5 @@
+snd-soc-adi-axi-i2s-objs := axi-i2s.o
+snd-soc-adi-axi-spdif-objs := axi-spdif.o
+
+obj-$(CONFIG_SND_SOC_ADI_AXI_I2S) += snd-soc-adi-axi-i2s.o
+obj-$(CONFIG_SND_SOC_ADI_AXI_SPDIF) += snd-soc-adi-axi-spdif.o
diff --git a/sound/soc/adi/axi-i2s.c b/sound/soc/adi/axi-i2s.c
new file mode 100644 (file)
index 0000000..0822c77
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2012-2013, Analog Devices Inc.
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/clk.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
+
+#define AXI_I2S_REG_RESET      0x00
+#define AXI_I2S_REG_CTRL       0x04
+#define AXI_I2S_REG_CLK_CTRL   0x08
+#define AXI_I2S_REG_STATUS     0x10
+
+#define AXI_I2S_REG_RX_FIFO    0x28
+#define AXI_I2S_REG_TX_FIFO    0x2C
+
+#define AXI_I2S_RESET_GLOBAL   BIT(0)
+#define AXI_I2S_RESET_TX_FIFO  BIT(1)
+#define AXI_I2S_RESET_RX_FIFO  BIT(2)
+
+#define AXI_I2S_CTRL_TX_EN     BIT(0)
+#define AXI_I2S_CTRL_RX_EN     BIT(1)
+
+/* The frame size is configurable, but for now we always set it 64 bit */
+#define AXI_I2S_BITS_PER_FRAME 64
+
+struct axi_i2s {
+       struct regmap *regmap;
+       struct clk *clk;
+       struct clk *clk_ref;
+
+       struct snd_soc_dai_driver dai_driver;
+
+       struct snd_dmaengine_dai_dma_data capture_dma_data;
+       struct snd_dmaengine_dai_dma_data playback_dma_data;
+
+       struct snd_ratnum ratnum;
+       struct snd_pcm_hw_constraint_ratnums rate_constraints;
+};
+
+static int axi_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
+       struct snd_soc_dai *dai)
+{
+       struct axi_i2s *i2s = snd_soc_dai_get_drvdata(dai);
+       unsigned int mask, val;
+
+       if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+               mask = AXI_I2S_CTRL_RX_EN;
+       else
+               mask = AXI_I2S_CTRL_TX_EN;
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               val = mask;
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               val = 0;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       regmap_update_bits(i2s->regmap, AXI_I2S_REG_CTRL, mask, val);
+
+       return 0;
+}
+
+static int axi_i2s_hw_params(struct snd_pcm_substream *substream,
+       struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+       struct axi_i2s *i2s = snd_soc_dai_get_drvdata(dai);
+       unsigned int bclk_div, word_size;
+       unsigned int bclk_rate;
+
+       bclk_rate = params_rate(params) * AXI_I2S_BITS_PER_FRAME;
+
+       word_size = AXI_I2S_BITS_PER_FRAME / 2 - 1;
+       bclk_div = DIV_ROUND_UP(clk_get_rate(i2s->clk_ref), bclk_rate) / 2 - 1;
+
+       regmap_write(i2s->regmap, AXI_I2S_REG_CLK_CTRL, (word_size << 16) |
+               bclk_div);
+
+       return 0;
+}
+
+static int axi_i2s_startup(struct snd_pcm_substream *substream,
+       struct snd_soc_dai *dai)
+{
+       struct axi_i2s *i2s = snd_soc_dai_get_drvdata(dai);
+       uint32_t mask;
+       int ret;
+
+       if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+               mask = AXI_I2S_RESET_RX_FIFO;
+       else
+               mask = AXI_I2S_RESET_TX_FIFO;
+
+       regmap_write(i2s->regmap, AXI_I2S_REG_RESET, mask);
+
+       ret = snd_pcm_hw_constraint_ratnums(substream->runtime, 0,
+                          SNDRV_PCM_HW_PARAM_RATE,
+                          &i2s->rate_constraints);
+       if (ret)
+               return ret;
+
+       return clk_prepare_enable(i2s->clk_ref);
+}
+
+static void axi_i2s_shutdown(struct snd_pcm_substream *substream,
+       struct snd_soc_dai *dai)
+{
+       struct axi_i2s *i2s = snd_soc_dai_get_drvdata(dai);
+
+       clk_disable_unprepare(i2s->clk_ref);
+}
+
+static int axi_i2s_dai_probe(struct snd_soc_dai *dai)
+{
+       struct axi_i2s *i2s = snd_soc_dai_get_drvdata(dai);
+
+       snd_soc_dai_init_dma_data(dai, &i2s->playback_dma_data,
+               &i2s->capture_dma_data);
+
+       return 0;
+}
+
+static const struct snd_soc_dai_ops axi_i2s_dai_ops = {
+       .startup = axi_i2s_startup,
+       .shutdown = axi_i2s_shutdown,
+       .trigger = axi_i2s_trigger,
+       .hw_params = axi_i2s_hw_params,
+};
+
+static struct snd_soc_dai_driver axi_i2s_dai = {
+       .probe = axi_i2s_dai_probe,
+       .playback = {
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = SNDRV_PCM_RATE_KNOT,
+               .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_U32_LE,
+       },
+       .capture = {
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = SNDRV_PCM_RATE_KNOT,
+               .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_U32_LE,
+       },
+       .ops = &axi_i2s_dai_ops,
+       .symmetric_rates = 1,
+};
+
+static const struct snd_soc_component_driver axi_i2s_component = {
+       .name = "axi-i2s",
+};
+
+static const struct regmap_config axi_i2s_regmap_config = {
+       .reg_bits = 32,
+       .reg_stride = 4,
+       .val_bits = 32,
+       .max_register = AXI_I2S_REG_STATUS,
+};
+
+static int axi_i2s_probe(struct platform_device *pdev)
+{
+       struct resource *res;
+       struct axi_i2s *i2s;
+       void __iomem *base;
+       int ret;
+
+       i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL);
+       if (!i2s)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, i2s);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       base = devm_request_and_ioremap(&pdev->dev, res);
+       if (!base)
+               return -EBUSY;
+
+       i2s->regmap = devm_regmap_init_mmio(&pdev->dev, base,
+               &axi_i2s_regmap_config);
+       if (IS_ERR(i2s->regmap))
+               return PTR_ERR(i2s->regmap);
+
+       i2s->clk = devm_clk_get(&pdev->dev, "axi");
+       if (IS_ERR(i2s->clk))
+               return PTR_ERR(i2s->clk);
+
+       i2s->clk_ref = devm_clk_get(&pdev->dev, "ref");
+       if (IS_ERR(i2s->clk_ref))
+               return PTR_ERR(i2s->clk_ref);
+
+       ret = clk_prepare_enable(i2s->clk);
+       if (ret)
+               return ret;
+
+       i2s->playback_dma_data.addr = res->start + AXI_I2S_REG_TX_FIFO;
+       i2s->playback_dma_data.addr_width = 4;
+       i2s->playback_dma_data.maxburst = 1;
+
+       i2s->capture_dma_data.addr = res->start + AXI_I2S_REG_RX_FIFO;
+       i2s->capture_dma_data.addr_width = 4;
+       i2s->capture_dma_data.maxburst = 1;
+
+       i2s->ratnum.num = clk_get_rate(i2s->clk_ref) / 2 / AXI_I2S_BITS_PER_FRAME;
+       i2s->ratnum.den_step = 1;
+       i2s->ratnum.den_min = 1;
+       i2s->ratnum.den_max = 64;
+
+       i2s->rate_constraints.rats = &i2s->ratnum;
+       i2s->rate_constraints.nrats = 1;
+
+       regmap_write(i2s->regmap, AXI_I2S_REG_RESET, AXI_I2S_RESET_GLOBAL);
+
+       ret = devm_snd_soc_register_component(&pdev->dev, &axi_i2s_component,
+                                        &axi_i2s_dai, 1);
+       if (ret)
+               goto err_clk_disable;
+
+       ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL,
+                       SND_DMAENGINE_PCM_FLAG_NO_RESIDUE);
+       if (ret)
+               goto err_clk_disable;
+
+err_clk_disable:
+       clk_disable_unprepare(i2s->clk);
+       return ret;
+}
+
+static int axi_i2s_dev_remove(struct platform_device *pdev)
+{
+       struct axi_i2s *i2s = platform_get_drvdata(pdev);
+
+       clk_disable_unprepare(i2s->clk);
+
+       return 0;
+}
+
+static const struct of_device_id axi_i2s_of_match[] = {
+       { .compatible = "adi,axi-i2s-1.00.a", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, axi_i2s_of_match);
+
+static struct platform_driver axi_i2s_driver = {
+       .driver = {
+               .name = "axi-i2s",
+               .owner = THIS_MODULE,
+               .of_match_table = axi_i2s_of_match,
+       },
+       .probe = axi_i2s_probe,
+       .remove = axi_i2s_dev_remove,
+};
+module_platform_driver(axi_i2s_driver);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("AXI I2S driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/adi/axi-spdif.c b/sound/soc/adi/axi-spdif.c
new file mode 100644 (file)
index 0000000..d5408d2
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2012-2013, Analog Devices Inc.
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/clk.h>
+#include <linux/regmap.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/initval.h>
+#include <sound/dmaengine_pcm.h>
+
+#define AXI_SPDIF_REG_CTRL     0x0
+#define AXI_SPDIF_REG_STAT     0x4
+#define AXI_SPDIF_REG_TX_FIFO  0xc
+
+#define AXI_SPDIF_CTRL_TXDATA BIT(1)
+#define AXI_SPDIF_CTRL_TXEN BIT(0)
+#define AXI_SPDIF_CTRL_CLKDIV_OFFSET 8
+#define AXI_SPDIF_CTRL_CLKDIV_MASK (0xff << 8)
+
+#define AXI_SPDIF_FREQ_44100   (0x0 << 6)
+#define AXI_SPDIF_FREQ_48000   (0x1 << 6)
+#define AXI_SPDIF_FREQ_32000   (0x2 << 6)
+#define AXI_SPDIF_FREQ_NA      (0x3 << 6)
+
+struct axi_spdif {
+       struct regmap *regmap;
+       struct clk *clk;
+       struct clk *clk_ref;
+
+       struct snd_dmaengine_dai_dma_data dma_data;
+
+       struct snd_ratnum ratnum;
+       struct snd_pcm_hw_constraint_ratnums rate_constraints;
+};
+
+static int axi_spdif_trigger(struct snd_pcm_substream *substream, int cmd,
+       struct snd_soc_dai *dai)
+{
+       struct axi_spdif *spdif = snd_soc_dai_get_drvdata(dai);
+       unsigned int val;
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               val = AXI_SPDIF_CTRL_TXDATA;
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               val = 0;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       regmap_update_bits(spdif->regmap, AXI_SPDIF_REG_CTRL,
+               AXI_SPDIF_CTRL_TXDATA, val);
+
+       return 0;
+}
+
+static int axi_spdif_hw_params(struct snd_pcm_substream *substream,
+       struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+       struct axi_spdif *spdif = snd_soc_dai_get_drvdata(dai);
+       unsigned int rate = params_rate(params);
+       unsigned int clkdiv, stat;
+
+       switch (params_rate(params)) {
+       case 32000:
+               stat = AXI_SPDIF_FREQ_32000;
+               break;
+       case 44100:
+               stat = AXI_SPDIF_FREQ_44100;
+               break;
+       case 48000:
+               stat = AXI_SPDIF_FREQ_48000;
+               break;
+       default:
+               stat = AXI_SPDIF_FREQ_NA;
+               break;
+       }
+
+       clkdiv = DIV_ROUND_CLOSEST(clk_get_rate(spdif->clk_ref),
+                       rate * 64 * 2) - 1;
+       clkdiv <<= AXI_SPDIF_CTRL_CLKDIV_OFFSET;
+
+       regmap_write(spdif->regmap, AXI_SPDIF_REG_STAT, stat);
+       regmap_update_bits(spdif->regmap, AXI_SPDIF_REG_CTRL,
+               AXI_SPDIF_CTRL_CLKDIV_MASK, clkdiv);
+
+       return 0;
+}
+
+static int axi_spdif_dai_probe(struct snd_soc_dai *dai)
+{
+       struct axi_spdif *spdif = snd_soc_dai_get_drvdata(dai);
+
+       snd_soc_dai_init_dma_data(dai, &spdif->dma_data, NULL);
+
+       return 0;
+}
+
+static int axi_spdif_startup(struct snd_pcm_substream *substream,
+       struct snd_soc_dai *dai)
+{
+       struct axi_spdif *spdif = snd_soc_dai_get_drvdata(dai);
+       int ret;
+
+       ret = snd_pcm_hw_constraint_ratnums(substream->runtime, 0,
+                          SNDRV_PCM_HW_PARAM_RATE,
+                          &spdif->rate_constraints);
+       if (ret)
+               return ret;
+
+       ret = clk_prepare_enable(spdif->clk_ref);
+       if (ret)
+               return ret;
+
+       regmap_update_bits(spdif->regmap, AXI_SPDIF_REG_CTRL,
+               AXI_SPDIF_CTRL_TXEN, AXI_SPDIF_CTRL_TXEN);
+
+       return 0;
+}
+
+static void axi_spdif_shutdown(struct snd_pcm_substream *substream,
+       struct snd_soc_dai *dai)
+{
+       struct axi_spdif *spdif = snd_soc_dai_get_drvdata(dai);
+
+       regmap_update_bits(spdif->regmap, AXI_SPDIF_REG_CTRL,
+               AXI_SPDIF_CTRL_TXEN, 0);
+
+       clk_disable_unprepare(spdif->clk_ref);
+}
+
+static const struct snd_soc_dai_ops axi_spdif_dai_ops = {
+       .startup = axi_spdif_startup,
+       .shutdown = axi_spdif_shutdown,
+       .trigger = axi_spdif_trigger,
+       .hw_params = axi_spdif_hw_params,
+};
+
+static struct snd_soc_dai_driver axi_spdif_dai = {
+       .probe = axi_spdif_dai_probe,
+       .playback = {
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = SNDRV_PCM_RATE_KNOT,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,
+       },
+       .ops = &axi_spdif_dai_ops,
+};
+
+static const struct snd_soc_component_driver axi_spdif_component = {
+       .name = "axi-spdif",
+};
+
+static const struct regmap_config axi_spdif_regmap_config = {
+       .reg_bits = 32,
+       .reg_stride = 4,
+       .val_bits = 32,
+       .max_register = AXI_SPDIF_REG_STAT,
+};
+
+static int axi_spdif_probe(struct platform_device *pdev)
+{
+       struct axi_spdif *spdif;
+       struct resource *res;
+       void __iomem *base;
+       int ret;
+
+       spdif = devm_kzalloc(&pdev->dev, sizeof(*spdif), GFP_KERNEL);
+       if (!spdif)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, spdif);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       base = devm_request_and_ioremap(&pdev->dev, res);
+       if (!base)
+               return -EBUSY;
+
+       spdif->regmap = devm_regmap_init_mmio(&pdev->dev, base,
+                                           &axi_spdif_regmap_config);
+       if (IS_ERR(spdif->regmap))
+               return PTR_ERR(spdif->regmap);
+
+       spdif->clk = devm_clk_get(&pdev->dev, "axi");
+       if (IS_ERR(spdif->clk))
+               return PTR_ERR(spdif->clk);
+
+       spdif->clk_ref = devm_clk_get(&pdev->dev, "ref");
+       if (IS_ERR(spdif->clk_ref))
+               return PTR_ERR(spdif->clk_ref);
+
+       ret = clk_prepare_enable(spdif->clk);
+       if (ret)
+               return ret;
+
+       spdif->dma_data.addr = res->start + AXI_SPDIF_REG_TX_FIFO;
+       spdif->dma_data.addr_width = 4;
+       spdif->dma_data.maxburst = 1;
+
+       spdif->ratnum.num = clk_get_rate(spdif->clk_ref) / 128;
+       spdif->ratnum.den_step = 1;
+       spdif->ratnum.den_min = 1;
+       spdif->ratnum.den_max = 64;
+
+       spdif->rate_constraints.rats = &spdif->ratnum;
+       spdif->rate_constraints.nrats = 1;
+
+       ret = devm_snd_soc_register_component(&pdev->dev, &axi_spdif_component,
+                                        &axi_spdif_dai, 1);
+       if (ret)
+               goto err_clk_disable;
+
+       ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL,
+                       SND_DMAENGINE_PCM_FLAG_NO_RESIDUE);
+       if (ret)
+               goto err_clk_disable;
+
+       return 0;
+
+err_clk_disable:
+       clk_disable_unprepare(spdif->clk);
+       return ret;
+}
+
+static int axi_spdif_dev_remove(struct platform_device *pdev)
+{
+       struct axi_spdif *spdif = platform_get_drvdata(pdev);
+
+       clk_disable_unprepare(spdif->clk);
+
+       return 0;
+}
+
+static const struct of_device_id axi_spdif_of_match[] = {
+       { .compatible = "adi,axi-spdif-tx-1.00.a", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, axi_spdif_of_match);
+
+static struct platform_driver axi_spdif_driver = {
+       .driver = {
+               .name = "axi-spdif",
+               .owner = THIS_MODULE,
+               .of_match_table = axi_spdif_of_match,
+       },
+       .probe = axi_spdif_probe,
+       .remove = axi_spdif_dev_remove,
+};
+module_platform_driver(axi_spdif_driver);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("AXI SPDIF driver");
+MODULE_LICENSE("GPL");
index 8697cedccd21240f76b4b5076ba6d0968a394d75..1ead3c977a51743619b0bb2084ec174b7cf867a8 100644 (file)
@@ -648,7 +648,7 @@ static int atmel_ssc_prepare(struct snd_pcm_substream *substream,
 
        dma_params = ssc_p->dma_params[dir];
 
-       ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_enable);
+       ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_disable);
        ssc_writel(ssc_p->ssc->regs, IDR, dma_params->mask->ssc_error);
 
        pr_debug("%s enabled SSC_SR=0x%08x\n",
@@ -657,6 +657,33 @@ static int atmel_ssc_prepare(struct snd_pcm_substream *substream,
        return 0;
 }
 
+static int atmel_ssc_trigger(struct snd_pcm_substream *substream,
+                            int cmd, struct snd_soc_dai *dai)
+{
+       struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
+       struct atmel_pcm_dma_params *dma_params;
+       int dir;
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               dir = 0;
+       else
+               dir = 1;
+
+       dma_params = ssc_p->dma_params[dir];
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_enable);
+               break;
+       default:
+               ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_disable);
+               break;
+       }
+
+       return 0;
+}
 
 #ifdef CONFIG_PM
 static int atmel_ssc_suspend(struct snd_soc_dai *cpu_dai)
@@ -731,6 +758,7 @@ static const struct snd_soc_dai_ops atmel_ssc_dai_ops = {
        .startup        = atmel_ssc_startup,
        .shutdown       = atmel_ssc_shutdown,
        .prepare        = atmel_ssc_prepare,
+       .trigger        = atmel_ssc_trigger,
        .hw_params      = atmel_ssc_hw_params,
        .set_fmt        = atmel_ssc_set_dai_fmt,
        .set_clkdiv     = atmel_ssc_set_dai_clkdiv,
index 992ae38d5a15afda177080da1032300bcffd18ac..7d6a9055874b822bb440eab72a66dc5c034127ed 100644 (file)
@@ -97,6 +97,8 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev)
                goto out;
        }
 
+       snd_soc_card_set_drvdata(card, priv);
+
        card->dev = &pdev->dev;
        card->owner = THIS_MODULE;
        card->dai_link = dai;
@@ -107,7 +109,7 @@ static int sam9x5_wm8731_driver_probe(struct platform_device *pdev)
        dai->stream_name = "WM8731 PCM";
        dai->codec_dai_name = "wm8731-hifi";
        dai->init = sam9x5_wm8731_init;
-       dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+       dai->dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF
                | SND_SOC_DAIFMT_CBM_CFM;
 
        ret = snd_soc_of_parse_card_name(card, "atmel,model");
diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig
new file mode 100644 (file)
index 0000000..3d82a29
--- /dev/null
@@ -0,0 +1,10 @@
+config SND_BCM2835_SOC_I2S
+       tristate "SoC Audio support for the Broadcom BCM2835 I2S module"
+       depends on ARCH_BCM2835 || COMPILE_TEST
+       select SND_SOC_DMAENGINE_PCM
+       select SND_SOC_GENERIC_DMAENGINE_PCM
+       select REGMAP_MMIO
+       help
+         Say Y or M if you want to add support for codecs attached to
+         the BCM2835 I2S interface. You will also need
+         to select the audio interfaces to support below.
diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile
new file mode 100644 (file)
index 0000000..bc816b7
--- /dev/null
@@ -0,0 +1,5 @@
+# BCM2835 Platform Support
+snd-soc-bcm2835-i2s-objs := bcm2835-i2s.o
+
+obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-i2s.o
+
diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c
new file mode 100644 (file)
index 0000000..2685fe4
--- /dev/null
@@ -0,0 +1,879 @@
+/*
+ * ALSA SoC I2S Audio Layer for Broadcom BCM2835 SoC
+ *
+ * Author:     Florian Meier <florian.meier@koalo.de>
+ *             Copyright 2013
+ *
+ * Based on
+ *     Raspberry Pi PCM I2S ALSA Driver
+ *     Copyright (c) by Phil Poole 2013
+ *
+ *     ALSA SoC I2S (McBSP) Audio Layer for TI DAVINCI processor
+ *      Vladimir Barinov, <vbarinov@embeddedalley.com>
+ *     Copyright (C) 2007 MontaVista Software, Inc., <source@mvista.com>
+ *
+ *     OMAP ALSA SoC DAI driver using McBSP port
+ *     Copyright (C) 2008 Nokia Corporation
+ *     Contact: Jarkko Nikula <jarkko.nikula@bitmer.com>
+ *              Peter Ujfalusi <peter.ujfalusi@ti.com>
+ *
+ *     Freescale SSI ALSA SoC Digital Audio Interface (DAI) driver
+ *     Author: Timur Tabi <timur@freescale.com>
+ *     Copyright 2007-2010 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.
+ *
+ * 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/module.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
+
+/* Clock registers */
+#define BCM2835_CLK_PCMCTL_REG  0x00
+#define BCM2835_CLK_PCMDIV_REG  0x04
+
+/* Clock register settings */
+#define BCM2835_CLK_PASSWD             (0x5a000000)
+#define BCM2835_CLK_PASSWD_MASK        (0xff000000)
+#define BCM2835_CLK_MASH(v)            ((v) << 9)
+#define BCM2835_CLK_FLIP               BIT(8)
+#define BCM2835_CLK_BUSY               BIT(7)
+#define BCM2835_CLK_KILL               BIT(5)
+#define BCM2835_CLK_ENAB               BIT(4)
+#define BCM2835_CLK_SRC(v)             (v)
+
+#define BCM2835_CLK_SHIFT              (12)
+#define BCM2835_CLK_DIVI(v)            ((v) << BCM2835_CLK_SHIFT)
+#define BCM2835_CLK_DIVF(v)            (v)
+#define BCM2835_CLK_DIVF_MASK          (0xFFF)
+
+enum {
+       BCM2835_CLK_MASH_0 = 0,
+       BCM2835_CLK_MASH_1,
+       BCM2835_CLK_MASH_2,
+       BCM2835_CLK_MASH_3,
+};
+
+enum {
+       BCM2835_CLK_SRC_GND = 0,
+       BCM2835_CLK_SRC_OSC,
+       BCM2835_CLK_SRC_DBG0,
+       BCM2835_CLK_SRC_DBG1,
+       BCM2835_CLK_SRC_PLLA,
+       BCM2835_CLK_SRC_PLLC,
+       BCM2835_CLK_SRC_PLLD,
+       BCM2835_CLK_SRC_HDMI,
+};
+
+/* Most clocks are not useable (freq = 0) */
+static const unsigned int bcm2835_clk_freq[BCM2835_CLK_SRC_HDMI+1] = {
+       [BCM2835_CLK_SRC_GND]           = 0,
+       [BCM2835_CLK_SRC_OSC]           = 19200000,
+       [BCM2835_CLK_SRC_DBG0]          = 0,
+       [BCM2835_CLK_SRC_DBG1]          = 0,
+       [BCM2835_CLK_SRC_PLLA]          = 0,
+       [BCM2835_CLK_SRC_PLLC]          = 0,
+       [BCM2835_CLK_SRC_PLLD]          = 500000000,
+       [BCM2835_CLK_SRC_HDMI]          = 0,
+};
+
+/* I2S registers */
+#define BCM2835_I2S_CS_A_REG           0x00
+#define BCM2835_I2S_FIFO_A_REG         0x04
+#define BCM2835_I2S_MODE_A_REG         0x08
+#define BCM2835_I2S_RXC_A_REG          0x0c
+#define BCM2835_I2S_TXC_A_REG          0x10
+#define BCM2835_I2S_DREQ_A_REG         0x14
+#define BCM2835_I2S_INTEN_A_REG        0x18
+#define BCM2835_I2S_INTSTC_A_REG       0x1c
+#define BCM2835_I2S_GRAY_REG           0x20
+
+/* I2S register settings */
+#define BCM2835_I2S_STBY               BIT(25)
+#define BCM2835_I2S_SYNC               BIT(24)
+#define BCM2835_I2S_RXSEX              BIT(23)
+#define BCM2835_I2S_RXF                BIT(22)
+#define BCM2835_I2S_TXE                BIT(21)
+#define BCM2835_I2S_RXD                BIT(20)
+#define BCM2835_I2S_TXD                BIT(19)
+#define BCM2835_I2S_RXR                BIT(18)
+#define BCM2835_I2S_TXW                BIT(17)
+#define BCM2835_I2S_CS_RXERR           BIT(16)
+#define BCM2835_I2S_CS_TXERR           BIT(15)
+#define BCM2835_I2S_RXSYNC             BIT(14)
+#define BCM2835_I2S_TXSYNC             BIT(13)
+#define BCM2835_I2S_DMAEN              BIT(9)
+#define BCM2835_I2S_RXTHR(v)           ((v) << 7)
+#define BCM2835_I2S_TXTHR(v)           ((v) << 5)
+#define BCM2835_I2S_RXCLR              BIT(4)
+#define BCM2835_I2S_TXCLR              BIT(3)
+#define BCM2835_I2S_TXON               BIT(2)
+#define BCM2835_I2S_RXON               BIT(1)
+#define BCM2835_I2S_EN                 (1)
+
+#define BCM2835_I2S_CLKDIS             BIT(28)
+#define BCM2835_I2S_PDMN               BIT(27)
+#define BCM2835_I2S_PDME               BIT(26)
+#define BCM2835_I2S_FRXP               BIT(25)
+#define BCM2835_I2S_FTXP               BIT(24)
+#define BCM2835_I2S_CLKM               BIT(23)
+#define BCM2835_I2S_CLKI               BIT(22)
+#define BCM2835_I2S_FSM                BIT(21)
+#define BCM2835_I2S_FSI                BIT(20)
+#define BCM2835_I2S_FLEN(v)            ((v) << 10)
+#define BCM2835_I2S_FSLEN(v)           (v)
+
+#define BCM2835_I2S_CHWEX              BIT(15)
+#define BCM2835_I2S_CHEN               BIT(14)
+#define BCM2835_I2S_CHPOS(v)           ((v) << 4)
+#define BCM2835_I2S_CHWID(v)           (v)
+#define BCM2835_I2S_CH1(v)             ((v) << 16)
+#define BCM2835_I2S_CH2(v)             (v)
+
+#define BCM2835_I2S_TX_PANIC(v)        ((v) << 24)
+#define BCM2835_I2S_RX_PANIC(v)        ((v) << 16)
+#define BCM2835_I2S_TX(v)              ((v) << 8)
+#define BCM2835_I2S_RX(v)              (v)
+
+#define BCM2835_I2S_INT_RXERR          BIT(3)
+#define BCM2835_I2S_INT_TXERR          BIT(2)
+#define BCM2835_I2S_INT_RXR            BIT(1)
+#define BCM2835_I2S_INT_TXW            BIT(0)
+
+/* I2S DMA interface */
+/* FIXME: Needs IOMMU support */
+#define BCM2835_VCMMU_SHIFT            (0x7E000000 - 0x20000000)
+
+/* General device struct */
+struct bcm2835_i2s_dev {
+       struct device                           *dev;
+       struct snd_dmaengine_dai_dma_data       dma_data[2];
+       unsigned int                            fmt;
+       unsigned int                            bclk_ratio;
+
+       struct regmap *i2s_regmap;
+       struct regmap *clk_regmap;
+};
+
+static void bcm2835_i2s_start_clock(struct bcm2835_i2s_dev *dev)
+{
+       /* Start the clock if in master mode */
+       unsigned int master = dev->fmt & SND_SOC_DAIFMT_MASTER_MASK;
+
+       switch (master) {
+       case SND_SOC_DAIFMT_CBS_CFS:
+       case SND_SOC_DAIFMT_CBS_CFM:
+               regmap_update_bits(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG,
+                       BCM2835_CLK_PASSWD_MASK | BCM2835_CLK_ENAB,
+                       BCM2835_CLK_PASSWD | BCM2835_CLK_ENAB);
+               break;
+       default:
+               break;
+       }
+}
+
+static void bcm2835_i2s_stop_clock(struct bcm2835_i2s_dev *dev)
+{
+       uint32_t clkreg;
+       int timeout = 1000;
+
+       /* Stop clock */
+       regmap_update_bits(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG,
+                       BCM2835_CLK_PASSWD_MASK | BCM2835_CLK_ENAB,
+                       BCM2835_CLK_PASSWD);
+
+       /* Wait for the BUSY flag going down */
+       while (--timeout) {
+               regmap_read(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, &clkreg);
+               if (!(clkreg & BCM2835_CLK_BUSY))
+                       break;
+       }
+
+       if (!timeout) {
+               /* KILL the clock */
+               dev_err(dev->dev, "I2S clock didn't stop. Kill the clock!\n");
+               regmap_update_bits(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG,
+                       BCM2835_CLK_KILL | BCM2835_CLK_PASSWD_MASK,
+                       BCM2835_CLK_KILL | BCM2835_CLK_PASSWD);
+       }
+}
+
+static void bcm2835_i2s_clear_fifos(struct bcm2835_i2s_dev *dev,
+                                   bool tx, bool rx)
+{
+       int timeout = 1000;
+       uint32_t syncval;
+       uint32_t csreg;
+       uint32_t i2s_active_state;
+       uint32_t clkreg;
+       uint32_t clk_active_state;
+       uint32_t off;
+       uint32_t clr;
+
+       off =  tx ? BCM2835_I2S_TXON : 0;
+       off |= rx ? BCM2835_I2S_RXON : 0;
+
+       clr =  tx ? BCM2835_I2S_TXCLR : 0;
+       clr |= rx ? BCM2835_I2S_RXCLR : 0;
+
+       /* Backup the current state */
+       regmap_read(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, &csreg);
+       i2s_active_state = csreg & (BCM2835_I2S_RXON | BCM2835_I2S_TXON);
+
+       regmap_read(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, &clkreg);
+       clk_active_state = clkreg & BCM2835_CLK_ENAB;
+
+       /* Start clock if not running */
+       if (!clk_active_state) {
+               regmap_update_bits(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG,
+                       BCM2835_CLK_PASSWD_MASK | BCM2835_CLK_ENAB,
+                       BCM2835_CLK_PASSWD | BCM2835_CLK_ENAB);
+       }
+
+       /* Stop I2S module */
+       regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, off, 0);
+
+       /*
+        * Clear the FIFOs
+        * Requires at least 2 PCM clock cycles to take effect
+        */
+       regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, clr, clr);
+
+       /* Wait for 2 PCM clock cycles */
+
+       /*
+        * Toggle the SYNC flag. After 2 PCM clock cycles it can be read back
+        * FIXME: This does not seem to work for slave mode!
+        */
+       regmap_read(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, &syncval);
+       syncval &= BCM2835_I2S_SYNC;
+
+       regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_CS_A_REG,
+                       BCM2835_I2S_SYNC, ~syncval);
+
+       /* Wait for the SYNC flag changing it's state */
+       while (--timeout) {
+               regmap_read(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, &csreg);
+               if ((csreg & BCM2835_I2S_SYNC) != syncval)
+                       break;
+       }
+
+       if (!timeout)
+               dev_err(dev->dev, "I2S SYNC error!\n");
+
+       /* Stop clock if it was not running before */
+       if (!clk_active_state)
+               bcm2835_i2s_stop_clock(dev);
+
+       /* Restore I2S state */
+       regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_CS_A_REG,
+                       BCM2835_I2S_RXON | BCM2835_I2S_TXON, i2s_active_state);
+}
+
+static int bcm2835_i2s_set_dai_fmt(struct snd_soc_dai *dai,
+                                     unsigned int fmt)
+{
+       struct bcm2835_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
+       dev->fmt = fmt;
+       return 0;
+}
+
+static int bcm2835_i2s_set_dai_bclk_ratio(struct snd_soc_dai *dai,
+                                     unsigned int ratio)
+{
+       struct bcm2835_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
+       dev->bclk_ratio = ratio;
+       return 0;
+}
+
+static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream,
+                                struct snd_pcm_hw_params *params,
+                                struct snd_soc_dai *dai)
+{
+       struct bcm2835_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
+
+       unsigned int sampling_rate = params_rate(params);
+       unsigned int data_length, data_delay, bclk_ratio;
+       unsigned int ch1pos, ch2pos, mode, format;
+       unsigned int mash = BCM2835_CLK_MASH_1;
+       unsigned int divi, divf, target_frequency;
+       int clk_src = -1;
+       unsigned int master = dev->fmt & SND_SOC_DAIFMT_MASTER_MASK;
+       bool bit_master =       (master == SND_SOC_DAIFMT_CBS_CFS
+                                       || master == SND_SOC_DAIFMT_CBS_CFM);
+
+       bool frame_master =     (master == SND_SOC_DAIFMT_CBS_CFS
+                                       || master == SND_SOC_DAIFMT_CBM_CFS);
+       uint32_t csreg;
+
+       /*
+        * If a stream is already enabled,
+        * the registers are already set properly.
+        */
+       regmap_read(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, &csreg);
+
+       if (csreg & (BCM2835_I2S_TXON | BCM2835_I2S_RXON))
+               return 0;
+
+       /*
+        * Adjust the data length according to the format.
+        * We prefill the half frame length with an integer
+        * divider of 2400 as explained at the clock settings.
+        * Maybe it is overwritten there, if the Integer mode
+        * does not apply.
+        */
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               data_length = 16;
+               bclk_ratio = 40;
+               break;
+       case SNDRV_PCM_FORMAT_S32_LE:
+               data_length = 32;
+               bclk_ratio = 80;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* If bclk_ratio already set, use that one. */
+       if (dev->bclk_ratio)
+               bclk_ratio = dev->bclk_ratio;
+
+       /*
+        * Clock Settings
+        *
+        * The target frequency of the bit clock is
+        *      sampling rate * frame length
+        *
+        * Integer mode:
+        * Sampling rates that are multiples of 8000 kHz
+        * can be driven by the oscillator of 19.2 MHz
+        * with an integer divider as long as the frame length
+        * is an integer divider of 19200000/8000=2400 as set up above.
+        * This is no longer possible if the sampling rate
+        * is too high (e.g. 192 kHz), because the oscillator is too slow.
+        *
+        * MASH mode:
+        * For all other sampling rates, it is not possible to
+        * have an integer divider. Approximate the clock
+        * with the MASH module that induces a slight frequency
+        * variance. To minimize that it is best to have the fastest
+        * clock here. That is PLLD with 500 MHz.
+        */
+       target_frequency = sampling_rate * bclk_ratio;
+       clk_src = BCM2835_CLK_SRC_OSC;
+       mash = BCM2835_CLK_MASH_0;
+
+       if (bcm2835_clk_freq[clk_src] % target_frequency == 0
+                       && bit_master && frame_master) {
+               divi = bcm2835_clk_freq[clk_src] / target_frequency;
+               divf = 0;
+       } else {
+               uint64_t dividend;
+
+               if (!dev->bclk_ratio) {
+                       /*
+                        * Overwrite bclk_ratio, because the
+                        * above trick is not needed or can
+                        * not be used.
+                        */
+                       bclk_ratio = 2 * data_length;
+               }
+
+               target_frequency = sampling_rate * bclk_ratio;
+
+               clk_src = BCM2835_CLK_SRC_PLLD;
+               mash = BCM2835_CLK_MASH_1;
+
+               dividend = bcm2835_clk_freq[clk_src];
+               dividend <<= BCM2835_CLK_SHIFT;
+               do_div(dividend, target_frequency);
+               divi = dividend >> BCM2835_CLK_SHIFT;
+               divf = dividend & BCM2835_CLK_DIVF_MASK;
+       }
+
+       /* Set clock divider */
+       regmap_write(dev->clk_regmap, BCM2835_CLK_PCMDIV_REG, BCM2835_CLK_PASSWD
+                       | BCM2835_CLK_DIVI(divi)
+                       | BCM2835_CLK_DIVF(divf));
+
+       /* Setup clock, but don't start it yet */
+       regmap_write(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, BCM2835_CLK_PASSWD
+                       | BCM2835_CLK_MASH(mash)
+                       | BCM2835_CLK_SRC(clk_src));
+
+       /* Setup the frame format */
+       format = BCM2835_I2S_CHEN;
+
+       if (data_length > 24)
+               format |= BCM2835_I2S_CHWEX;
+
+       format |= BCM2835_I2S_CHWID((data_length-8)&0xf);
+
+       switch (dev->fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               data_delay = 1;
+               break;
+       default:
+               /*
+                * TODO
+                * Others are possible but are not implemented at the moment.
+                */
+               dev_err(dev->dev, "%s:bad format\n", __func__);
+               return -EINVAL;
+       }
+
+       ch1pos = data_delay;
+       ch2pos = bclk_ratio / 2 + data_delay;
+
+       switch (params_channels(params)) {
+       case 2:
+               format = BCM2835_I2S_CH1(format) | BCM2835_I2S_CH2(format);
+               format |= BCM2835_I2S_CH1(BCM2835_I2S_CHPOS(ch1pos));
+               format |= BCM2835_I2S_CH2(BCM2835_I2S_CHPOS(ch2pos));
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /*
+        * Set format for both streams.
+        * We cannot set another frame length
+        * (and therefore word length) anyway,
+        * so the format will be the same.
+        */
+       regmap_write(dev->i2s_regmap, BCM2835_I2S_RXC_A_REG, format);
+       regmap_write(dev->i2s_regmap, BCM2835_I2S_TXC_A_REG, format);
+
+       /* Setup the I2S mode */
+       mode = 0;
+
+       if (data_length <= 16) {
+               /*
+                * Use frame packed mode (2 channels per 32 bit word)
+                * We cannot set another frame length in the second stream
+                * (and therefore word length) anyway,
+                * so the format will be the same.
+                */
+               mode |= BCM2835_I2S_FTXP | BCM2835_I2S_FRXP;
+       }
+
+       mode |= BCM2835_I2S_FLEN(bclk_ratio - 1);
+       mode |= BCM2835_I2S_FSLEN(bclk_ratio / 2);
+
+       /* Master or slave? */
+       switch (dev->fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBS_CFS:
+               /* CPU is master */
+               break;
+       case SND_SOC_DAIFMT_CBM_CFS:
+               /*
+                * CODEC is bit clock master
+                * CPU is frame master
+                */
+               mode |= BCM2835_I2S_CLKM;
+               break;
+       case SND_SOC_DAIFMT_CBS_CFM:
+               /*
+                * CODEC is frame master
+                * CPU is bit clock master
+                */
+               mode |= BCM2835_I2S_FSM;
+               break;
+       case SND_SOC_DAIFMT_CBM_CFM:
+               /* CODEC is master */
+               mode |= BCM2835_I2S_CLKM;
+               mode |= BCM2835_I2S_FSM;
+               break;
+       default:
+               dev_err(dev->dev, "%s:bad master\n", __func__);
+               return -EINVAL;
+       }
+
+       /*
+        * Invert clocks?
+        *
+        * The BCM approach seems to be inverted to the classical I2S approach.
+        */
+       switch (dev->fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_NF:
+               /* None. Therefore, both for BCM */
+               mode |= BCM2835_I2S_CLKI;
+               mode |= BCM2835_I2S_FSI;
+               break;
+       case SND_SOC_DAIFMT_IB_IF:
+               /* Both. Therefore, none for BCM */
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               /*
+                * Invert only frame sync. Therefore,
+                * invert only bit clock for BCM
+                */
+               mode |= BCM2835_I2S_CLKI;
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               /*
+                * Invert only bit clock. Therefore,
+                * invert only frame sync for BCM
+                */
+               mode |= BCM2835_I2S_FSI;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       regmap_write(dev->i2s_regmap, BCM2835_I2S_MODE_A_REG, mode);
+
+       /* Setup the DMA parameters */
+       regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_CS_A_REG,
+                       BCM2835_I2S_RXTHR(1)
+                       | BCM2835_I2S_TXTHR(1)
+                       | BCM2835_I2S_DMAEN, 0xffffffff);
+
+       regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_DREQ_A_REG,
+                         BCM2835_I2S_TX_PANIC(0x10)
+                       | BCM2835_I2S_RX_PANIC(0x30)
+                       | BCM2835_I2S_TX(0x30)
+                       | BCM2835_I2S_RX(0x20), 0xffffffff);
+
+       /* Clear FIFOs */
+       bcm2835_i2s_clear_fifos(dev, true, true);
+
+       return 0;
+}
+
+static int bcm2835_i2s_prepare(struct snd_pcm_substream *substream,
+               struct snd_soc_dai *dai)
+{
+       struct bcm2835_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
+       uint32_t cs_reg;
+
+       bcm2835_i2s_start_clock(dev);
+
+       /*
+        * Clear both FIFOs if the one that should be started
+        * is not empty at the moment. This should only happen
+        * after overrun. Otherwise, hw_params would have cleared
+        * the FIFO.
+        */
+       regmap_read(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, &cs_reg);
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK
+                       && !(cs_reg & BCM2835_I2S_TXE))
+               bcm2835_i2s_clear_fifos(dev, true, false);
+       else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE
+                       && (cs_reg & BCM2835_I2S_RXD))
+               bcm2835_i2s_clear_fifos(dev, false, true);
+
+       return 0;
+}
+
+static void bcm2835_i2s_stop(struct bcm2835_i2s_dev *dev,
+               struct snd_pcm_substream *substream,
+               struct snd_soc_dai *dai)
+{
+       uint32_t mask;
+
+       if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+               mask = BCM2835_I2S_RXON;
+       else
+               mask = BCM2835_I2S_TXON;
+
+       regmap_update_bits(dev->i2s_regmap,
+                       BCM2835_I2S_CS_A_REG, mask, 0);
+
+       /* Stop also the clock when not SND_SOC_DAIFMT_CONT */
+       if (!dai->active && !(dev->fmt & SND_SOC_DAIFMT_CONT))
+               bcm2835_i2s_stop_clock(dev);
+}
+
+static int bcm2835_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
+                              struct snd_soc_dai *dai)
+{
+       struct bcm2835_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
+       uint32_t mask;
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               bcm2835_i2s_start_clock(dev);
+
+               if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+                       mask = BCM2835_I2S_RXON;
+               else
+                       mask = BCM2835_I2S_TXON;
+
+               regmap_update_bits(dev->i2s_regmap,
+                               BCM2835_I2S_CS_A_REG, mask, mask);
+               break;
+
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               bcm2835_i2s_stop(dev, substream, dai);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int bcm2835_i2s_startup(struct snd_pcm_substream *substream,
+                              struct snd_soc_dai *dai)
+{
+       struct bcm2835_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
+
+       if (dai->active)
+               return 0;
+
+       /* Should this still be running stop it */
+       bcm2835_i2s_stop_clock(dev);
+
+       /* Enable PCM block */
+       regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_CS_A_REG,
+                       BCM2835_I2S_EN, BCM2835_I2S_EN);
+
+       /*
+        * Disable STBY.
+        * Requires at least 4 PCM clock cycles to take effect.
+        */
+       regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_CS_A_REG,
+                       BCM2835_I2S_STBY, BCM2835_I2S_STBY);
+
+       return 0;
+}
+
+static void bcm2835_i2s_shutdown(struct snd_pcm_substream *substream,
+               struct snd_soc_dai *dai)
+{
+       struct bcm2835_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
+
+       bcm2835_i2s_stop(dev, substream, dai);
+
+       /* If both streams are stopped, disable module and clock */
+       if (dai->active)
+               return;
+
+       /* Disable the module */
+       regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_CS_A_REG,
+                       BCM2835_I2S_EN, 0);
+
+       /*
+        * Stopping clock is necessary, because stop does
+        * not stop the clock when SND_SOC_DAIFMT_CONT
+        */
+       bcm2835_i2s_stop_clock(dev);
+}
+
+static const struct snd_soc_dai_ops bcm2835_i2s_dai_ops = {
+       .startup        = bcm2835_i2s_startup,
+       .shutdown       = bcm2835_i2s_shutdown,
+       .prepare        = bcm2835_i2s_prepare,
+       .trigger        = bcm2835_i2s_trigger,
+       .hw_params      = bcm2835_i2s_hw_params,
+       .set_fmt        = bcm2835_i2s_set_dai_fmt,
+       .set_bclk_ratio = bcm2835_i2s_set_dai_bclk_ratio
+};
+
+static int bcm2835_i2s_dai_probe(struct snd_soc_dai *dai)
+{
+       struct bcm2835_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
+
+       snd_soc_dai_init_dma_data(dai,
+                       &dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK],
+                       &dev->dma_data[SNDRV_PCM_STREAM_CAPTURE]);
+
+       return 0;
+}
+
+static struct snd_soc_dai_driver bcm2835_i2s_dai = {
+       .name   = "bcm2835-i2s",
+       .probe  = bcm2835_i2s_dai_probe,
+       .playback = {
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates =        SNDRV_PCM_RATE_8000_192000,
+               .formats =      SNDRV_PCM_FMTBIT_S16_LE
+                               | SNDRV_PCM_FMTBIT_S32_LE
+               },
+       .capture = {
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates =        SNDRV_PCM_RATE_8000_192000,
+               .formats =      SNDRV_PCM_FMTBIT_S16_LE
+                               | SNDRV_PCM_FMTBIT_S32_LE
+               },
+       .ops = &bcm2835_i2s_dai_ops,
+       .symmetric_rates = 1
+};
+
+static bool bcm2835_i2s_volatile_reg(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case BCM2835_I2S_CS_A_REG:
+       case BCM2835_I2S_FIFO_A_REG:
+       case BCM2835_I2S_INTSTC_A_REG:
+       case BCM2835_I2S_GRAY_REG:
+               return true;
+       default:
+               return false;
+       };
+}
+
+static bool bcm2835_i2s_precious_reg(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case BCM2835_I2S_FIFO_A_REG:
+               return true;
+       default:
+               return false;
+       };
+}
+
+static bool bcm2835_clk_volatile_reg(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case BCM2835_CLK_PCMCTL_REG:
+               return true;
+       default:
+               return false;
+       };
+}
+
+static const struct regmap_config bcm2835_regmap_config[] = {
+       {
+               .reg_bits = 32,
+               .reg_stride = 4,
+               .val_bits = 32,
+               .max_register = BCM2835_I2S_GRAY_REG,
+               .precious_reg = bcm2835_i2s_precious_reg,
+               .volatile_reg = bcm2835_i2s_volatile_reg,
+               .cache_type = REGCACHE_RBTREE,
+       },
+       {
+               .reg_bits = 32,
+               .reg_stride = 4,
+               .val_bits = 32,
+               .max_register = BCM2835_CLK_PCMDIV_REG,
+               .volatile_reg = bcm2835_clk_volatile_reg,
+               .cache_type = REGCACHE_RBTREE,
+       },
+};
+
+static const struct snd_soc_component_driver bcm2835_i2s_component = {
+       .name           = "bcm2835-i2s-comp",
+};
+
+static int bcm2835_i2s_probe(struct platform_device *pdev)
+{
+       struct bcm2835_i2s_dev *dev;
+       int i;
+       int ret;
+       struct regmap *regmap[2];
+       struct resource *mem[2];
+
+       /* Request both ioareas */
+       for (i = 0; i <= 1; i++) {
+               void __iomem *base;
+
+               mem[i] = platform_get_resource(pdev, IORESOURCE_MEM, i);
+               base = devm_ioremap_resource(&pdev->dev, mem[i]);
+               if (IS_ERR(base))
+                       return PTR_ERR(base);
+
+               regmap[i] = devm_regmap_init_mmio(&pdev->dev, base,
+                                           &bcm2835_regmap_config[i]);
+               if (IS_ERR(regmap[i]))
+                       return PTR_ERR(regmap[i]);
+       }
+
+       dev = devm_kzalloc(&pdev->dev, sizeof(*dev),
+                          GFP_KERNEL);
+       if (!dev)
+               return -ENOMEM;
+
+       dev->i2s_regmap = regmap[0];
+       dev->clk_regmap = regmap[1];
+
+       /* Set the DMA address */
+       dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr =
+               (dma_addr_t)mem[0]->start + BCM2835_I2S_FIFO_A_REG
+                                         + BCM2835_VCMMU_SHIFT;
+
+       dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr =
+               (dma_addr_t)mem[0]->start + BCM2835_I2S_FIFO_A_REG
+                                         + BCM2835_VCMMU_SHIFT;
+
+       /* Set the bus width */
+       dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr_width =
+               DMA_SLAVE_BUSWIDTH_4_BYTES;
+       dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr_width =
+               DMA_SLAVE_BUSWIDTH_4_BYTES;
+
+       /* Set burst */
+       dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].maxburst = 2;
+       dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].maxburst = 2;
+
+       /* BCLK ratio - use default */
+       dev->bclk_ratio = 0;
+
+       /* Store the pdev */
+       dev->dev = &pdev->dev;
+       dev_set_drvdata(&pdev->dev, dev);
+
+       ret = devm_snd_soc_register_component(&pdev->dev,
+                       &bcm2835_i2s_component, &bcm2835_i2s_dai, 1);
+       if (ret) {
+               dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
+               return ret;
+       }
+
+       ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
+       if (ret) {
+               dev_err(&pdev->dev, "Could not register PCM: %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static const struct of_device_id bcm2835_i2s_of_match[] = {
+       { .compatible = "brcm,bcm2835-i2s", },
+       {},
+};
+
+static struct platform_driver bcm2835_i2s_driver = {
+       .probe          = bcm2835_i2s_probe,
+       .driver         = {
+               .name   = "bcm2835-i2s",
+               .owner  = THIS_MODULE,
+               .of_match_table = bcm2835_i2s_of_match,
+       },
+};
+
+module_platform_driver(bcm2835_i2s_driver);
+
+MODULE_ALIAS("platform:bcm2835-i2s");
+MODULE_DESCRIPTION("BCM2835 I2S interface");
+MODULE_AUTHOR("Florian Meier <florian.meier@koalo.de>");
+MODULE_LICENSE("GPL v2");
index cfe517e6800969ab64c91c563c7b5839fc46da66..fdb8b8feb4edc5cd853066461df08508285b4535 100644 (file)
@@ -78,19 +78,13 @@ static const struct snd_dmaengine_pcm_config ep93xx_dmaengine_pcm_config = {
 
 static int ep93xx_soc_platform_probe(struct platform_device *pdev)
 {
-       return snd_dmaengine_pcm_register(&pdev->dev,
+       return devm_snd_dmaengine_pcm_register(&pdev->dev,
                &ep93xx_dmaengine_pcm_config,
                SND_DMAENGINE_PCM_FLAG_NO_RESIDUE |
                SND_DMAENGINE_PCM_FLAG_NO_DT |
                SND_DMAENGINE_PCM_FLAG_COMPAT);
 }
 
-static int ep93xx_soc_platform_remove(struct platform_device *pdev)
-{
-       snd_dmaengine_pcm_unregister(&pdev->dev);
-       return 0;
-}
-
 static struct platform_driver ep93xx_pcm_driver = {
        .driver = {
                        .name = "ep93xx-pcm-audio",
@@ -98,7 +92,6 @@ static struct platform_driver ep93xx_pcm_driver = {
        },
 
        .probe = ep93xx_soc_platform_probe,
-       .remove = ep93xx_soc_platform_remove,
 };
 
 module_platform_driver(ep93xx_pcm_driver);
index b33b45dfceec54b205c512ca01638d947df56f66..983d087aa92aa83125903dc18cd420f57c2009eb 100644 (file)
@@ -163,8 +163,10 @@ config SND_SOC_WM_HUBS
 config SND_SOC_WM_ADSP
        tristate
        default y if SND_SOC_WM5102=y
+       default y if SND_SOC_WM5110=y
        default y if SND_SOC_WM2200=y
        default m if SND_SOC_WM5102=m
+       default m if SND_SOC_WM5110=m
        default m if SND_SOC_WM2200=m
 
 config SND_SOC_AB8500_CODEC
index aea7e52cf714117a445347cbe528f6732d2bd662..12c27eb363dd13c54b9b1f9b297d02eff9643ef5 100644 (file)
@@ -413,7 +413,7 @@ static struct spi_driver ad193x_spi_driver = {
 };
 #endif
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 
 static const struct regmap_config ad193x_i2c_regmap_config = {
        .val_bits = 8,
@@ -470,7 +470,7 @@ static int __init ad193x_modinit(void)
 {
        int ret;
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret =  i2c_add_driver(&ad193x_i2c_driver);
        if (ret != 0) {
                printk(KERN_ERR "Failed to register AD193X I2C driver: %d\n",
@@ -495,7 +495,7 @@ static void __exit ad193x_modexit(void)
        spi_unregister_driver(&ad193x_spi_driver);
 #endif
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&ad193x_i2c_driver);
 #endif
 }
index 14a7c169d004ebf97fabbbccfd8df0434327c639..f7bf4555274982864478b43af4a710350662d7dc 100644 (file)
@@ -939,7 +939,7 @@ static struct spi_driver adav80x_spi_driver = {
 };
 #endif
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static const struct regmap_config adav80x_i2c_regmap_config = {
        .val_bits = 8,
        .pad_bits = 1,
@@ -985,7 +985,7 @@ static int __init adav80x_init(void)
 {
        int ret = 0;
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&adav80x_i2c_driver);
        if (ret)
                return ret;
@@ -1001,7 +1001,7 @@ module_init(adav80x_init);
 
 static void __exit adav80x_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&adav80x_i2c_driver);
 #endif
 #if defined(CONFIG_SPI_MASTER)
index 49cc5f6d6dba41cd1d45712fc15037d8031ddaf5..94cbe508dd3748723197f7443f5a6ed8524b2b14 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/gpio.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>
@@ -30,6 +31,7 @@
 
 /* codec private data */
 struct ak4641_priv {
+       struct regmap *regmap;
        unsigned int sysclk;
        int deemph;
        int playback_fs;
@@ -38,12 +40,12 @@ struct ak4641_priv {
 /*
  * ak4641 register cache
  */
-static const u8 ak4641_reg[AK4641_CACHEREGNUM] = {
-       0x00, 0x80, 0x00, 0x80,
-       0x02, 0x00, 0x11, 0x05,
-       0x00, 0x00, 0x36, 0x10,
-       0x00, 0x00, 0x57, 0x00,
-       0x88, 0x88, 0x08, 0x08
+static const struct reg_default ak4641_reg_defaults[] = {
+       {  0, 0x00 }, {  1, 0x80 }, {  2, 0x00 }, {  3, 0x80 },
+       {  4, 0x02 }, {  5, 0x00 }, {  6, 0x11 }, {  7, 0x05 },
+       {  8, 0x00 }, {  9, 0x00 }, { 10, 0x36 }, { 11, 0x10 },
+       { 12, 0x00 }, { 13, 0x00 }, { 14, 0x57 }, { 15, 0x00 },
+       { 16, 0x88 }, { 17, 0x88 }, { 18, 0x08 }, { 19, 0x08 }
 };
 
 static const int deemph_settings[] = {44100, 0, 48000, 32000};
@@ -396,6 +398,7 @@ static int ak4641_mute(struct snd_soc_dai *dai, int mute)
 static int ak4641_set_bias_level(struct snd_soc_codec *codec,
        enum snd_soc_bias_level level)
 {
+       struct ak4641_priv *ak4641 = snd_soc_codec_get_drvdata(codec);
        struct ak4641_platform_data *pdata = codec->dev->platform_data;
        int ret;
 
@@ -417,7 +420,7 @@ static int ak4641_set_bias_level(struct snd_soc_codec *codec,
                                gpio_set_value(pdata->gpio_npdn, 1);
                        mdelay(1);
 
-                       ret = snd_soc_cache_sync(codec);
+                       ret = regcache_sync(ak4641->regmap);
                        if (ret) {
                                dev_err(codec->dev,
                                        "Failed to sync cache: %d\n", ret);
@@ -433,7 +436,7 @@ static int ak4641_set_bias_level(struct snd_soc_codec *codec,
                        gpio_set_value(pdata->gpio_npdn, 0);
                if (pdata && gpio_is_valid(pdata->gpio_power))
                        gpio_set_value(pdata->gpio_power, 0);
-               codec->cache_sync = 1;
+               regcache_mark_dirty(ak4641->regmap);
                break;
        }
        codec->dapm.bias_level = level;
@@ -518,7 +521,7 @@ static int ak4641_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;
@@ -550,12 +553,17 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4641 = {
        .dapm_routes            = ak4641_audio_map,
        .num_dapm_routes        = ARRAY_SIZE(ak4641_audio_map),
        .set_bias_level         = ak4641_set_bias_level,
-       .reg_cache_size         = ARRAY_SIZE(ak4641_reg),
-       .reg_word_size          = sizeof(u8),
-       .reg_cache_default      = ak4641_reg,
-       .reg_cache_step         = 1,
 };
 
+static const struct regmap_config ak4641_regmap = {
+       .reg_bits = 8,
+       .val_bits = 8,
+
+       .max_register = AK4641_BTIF,
+       .reg_defaults = ak4641_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(ak4641_reg_defaults),
+       .cache_type = REGCACHE_RBTREE,
+};
 
 static int ak4641_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
@@ -569,6 +577,10 @@ static int ak4641_i2c_probe(struct i2c_client *i2c,
        if (!ak4641)
                return -ENOMEM;
 
+       ak4641->regmap = devm_regmap_init_i2c(i2c, &ak4641_regmap);
+       if (IS_ERR(ak4641->regmap))
+               return PTR_ERR(ak4641->regmap);
+
        if (pdata) {
                if (gpio_is_valid(pdata->gpio_power)) {
                        ret = gpio_request_one(pdata->gpio_power,
index 090d499bb7ebca49d34fd2ac3142b782f8f46a1b..1f646c6e90c6b3ff688e0fd2582fcb1268679bb1 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/slab.h>
 #include <linux/of_device.h>
 #include <linux/module.h>
+#include <linux/regmap.h>
 #include <sound/soc.h>
 #include <sound/initval.h>
 #include <sound/tlv.h>
@@ -198,30 +199,30 @@ static const struct snd_soc_dapm_route ak4642_intercon[] = {
 /*
  * ak4642 register cache
  */
-static const u8 ak4642_reg[] = {
-       0x00, 0x00, 0x01, 0x00,
-       0x02, 0x00, 0x00, 0x00,
-       0xe1, 0xe1, 0x18, 0x00,
-       0xe1, 0x18, 0x11, 0x08,
-       0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00,
-       0x00,
+static const struct reg_default ak4642_reg[] = {
+       {  0, 0x00 }, {  1, 0x00 }, {  2, 0x01 }, {  3, 0x00 },
+       {  4, 0x02 }, {  5, 0x00 }, {  6, 0x00 }, {  7, 0x00 },
+       {  8, 0xe1 }, {  9, 0xe1 }, { 10, 0x18 }, { 11, 0x00 },
+       { 12, 0xe1 }, { 13, 0x18 }, { 14, 0x11 }, { 15, 0x08 },
+       { 16, 0x00 }, { 17, 0x00 }, { 18, 0x00 }, { 19, 0x00 },
+       { 20, 0x00 }, { 21, 0x00 }, { 22, 0x00 }, { 23, 0x00 },
+       { 24, 0x00 }, { 25, 0x00 }, { 26, 0x00 }, { 27, 0x00 },
+       { 28, 0x00 }, { 29, 0x00 }, { 30, 0x00 }, { 31, 0x00 },
+       { 32, 0x00 }, { 33, 0x00 }, { 34, 0x00 }, { 35, 0x00 },
+       { 36, 0x00 },
 };
 
-static const u8 ak4648_reg[] = {
-       0x00, 0x00, 0x01, 0x00,
-       0x02, 0x00, 0x00, 0x00,
-       0xe1, 0xe1, 0x18, 0x00,
-       0xe1, 0x18, 0x11, 0xb8,
-       0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00,
-       0x00, 0x88, 0x88, 0x08,
+static const struct reg_default ak4648_reg[] = {
+       {  0, 0x00 }, {  1, 0x00 }, {  2, 0x01 }, {  3, 0x00 },
+       {  4, 0x02 }, {  5, 0x00 }, {  6, 0x00 }, {  7, 0x00 },
+       {  8, 0xe1 }, {  9, 0xe1 }, { 10, 0x18 }, { 11, 0x00 },
+       { 12, 0xe1 }, { 13, 0x18 }, { 14, 0x11 }, { 15, 0xb8 },
+       { 16, 0x00 }, { 17, 0x00 }, { 18, 0x00 }, { 19, 0x00 },
+       { 20, 0x00 }, { 21, 0x00 }, { 22, 0x00 }, { 23, 0x00 },
+       { 24, 0x00 }, { 25, 0x00 }, { 26, 0x00 }, { 27, 0x00 },
+       { 28, 0x00 }, { 29, 0x00 }, { 30, 0x00 }, { 31, 0x00 },
+       { 32, 0x00 }, { 33, 0x00 }, { 34, 0x00 }, { 35, 0x00 },
+       { 36, 0x00 }, { 37, 0x88 }, { 38, 0x88 }, { 39, 0x08 },
 };
 
 static int ak4642_dai_startup(struct snd_pcm_substream *substream,
@@ -454,7 +455,10 @@ static struct snd_soc_dai_driver ak4642_dai = {
 
 static int ak4642_resume(struct snd_soc_codec *codec)
 {
-       snd_soc_cache_sync(codec);
+       struct regmap *regmap = dev_get_regmap(codec->dev, NULL);
+
+       regcache_mark_dirty(regmap);
+       regcache_sync(regmap);
        return 0;
 }
 
@@ -463,15 +467,12 @@ static int ak4642_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;
        }
 
-       snd_soc_add_codec_controls(codec, ak4642_snd_controls,
-                            ARRAY_SIZE(ak4642_snd_controls));
-
        ak4642_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        return 0;
@@ -488,55 +489,59 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4642 = {
        .remove                 = ak4642_remove,
        .resume                 = ak4642_resume,
        .set_bias_level         = ak4642_set_bias_level,
-       .reg_cache_default      = ak4642_reg,                   /* ak4642 reg */
-       .reg_cache_size         = ARRAY_SIZE(ak4642_reg),       /* ak4642 reg */
-       .reg_word_size          = sizeof(u8),
+       .controls               = ak4642_snd_controls,
+       .num_controls           = ARRAY_SIZE(ak4642_snd_controls),
        .dapm_widgets           = ak4642_dapm_widgets,
        .num_dapm_widgets       = ARRAY_SIZE(ak4642_dapm_widgets),
        .dapm_routes            = ak4642_intercon,
        .num_dapm_routes        = ARRAY_SIZE(ak4642_intercon),
 };
 
-static struct snd_soc_codec_driver soc_codec_dev_ak4648 = {
-       .probe                  = ak4642_probe,
-       .remove                 = ak4642_remove,
-       .resume                 = ak4642_resume,
-       .set_bias_level         = ak4642_set_bias_level,
-       .reg_cache_default      = ak4648_reg,                   /* ak4648 reg */
-       .reg_cache_size         = ARRAY_SIZE(ak4648_reg),       /* ak4648 reg */
-       .reg_word_size          = sizeof(u8),
-       .dapm_widgets           = ak4642_dapm_widgets,
-       .num_dapm_widgets       = ARRAY_SIZE(ak4642_dapm_widgets),
-       .dapm_routes            = ak4642_intercon,
-       .num_dapm_routes        = ARRAY_SIZE(ak4642_intercon),
+static const struct regmap_config ak4642_regmap = {
+       .reg_bits               = 8,
+       .val_bits               = 8,
+       .max_register           = ARRAY_SIZE(ak4642_reg) + 1,
+       .reg_defaults           = ak4642_reg,
+       .num_reg_defaults       = ARRAY_SIZE(ak4642_reg),
+};
+
+static const struct regmap_config ak4648_regmap = {
+       .reg_bits               = 8,
+       .val_bits               = 8,
+       .max_register           = ARRAY_SIZE(ak4648_reg) + 1,
+       .reg_defaults           = ak4648_reg,
+       .num_reg_defaults       = ARRAY_SIZE(ak4648_reg),
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static struct of_device_id ak4642_of_match[];
 static int ak4642_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
        struct device_node *np = i2c->dev.of_node;
-       const struct snd_soc_codec_driver *driver;
+       const struct regmap_config *regmap_config = NULL;
+       struct regmap *regmap;
 
-       driver = NULL;
        if (np) {
                const struct of_device_id *of_id;
 
                of_id = of_match_device(ak4642_of_match, &i2c->dev);
                if (of_id)
-                       driver = of_id->data;
+                       regmap_config = of_id->data;
        } else {
-               driver = (struct snd_soc_codec_driver *)id->driver_data;
+               regmap_config = (const struct regmap_config *)id->driver_data;
        }
 
-       if (!driver) {
-               dev_err(&i2c->dev, "no driver\n");
+       if (!regmap_config) {
+               dev_err(&i2c->dev, "Unknown device type\n");
                return -EINVAL;
        }
 
+       regmap = devm_regmap_init_i2c(i2c, regmap_config);
+       if (IS_ERR(regmap))
+               return PTR_ERR(regmap);
+
        return snd_soc_register_codec(&i2c->dev,
-                                     driver, &ak4642_dai, 1);
+                                     &soc_codec_dev_ak4642, &ak4642_dai, 1);
 }
 
 static int ak4642_i2c_remove(struct i2c_client *client)
@@ -546,17 +551,17 @@ static int ak4642_i2c_remove(struct i2c_client *client)
 }
 
 static struct of_device_id ak4642_of_match[] = {
-       { .compatible = "asahi-kasei,ak4642",   .data = &soc_codec_dev_ak4642},
-       { .compatible = "asahi-kasei,ak4643",   .data = &soc_codec_dev_ak4642},
-       { .compatible = "asahi-kasei,ak4648",   .data = &soc_codec_dev_ak4648},
+       { .compatible = "asahi-kasei,ak4642",   .data = &ak4642_regmap},
+       { .compatible = "asahi-kasei,ak4643",   .data = &ak4642_regmap},
+       { .compatible = "asahi-kasei,ak4648",   .data = &ak4648_regmap},
        {},
 };
 MODULE_DEVICE_TABLE(of, ak4642_of_match);
 
 static const struct i2c_device_id ak4642_i2c_id[] = {
-       { "ak4642", (kernel_ulong_t)&soc_codec_dev_ak4642 },
-       { "ak4643", (kernel_ulong_t)&soc_codec_dev_ak4642 },
-       { "ak4648", (kernel_ulong_t)&soc_codec_dev_ak4648 },
+       { "ak4642", (kernel_ulong_t)&ak4642_regmap },
+       { "ak4643", (kernel_ulong_t)&ak4642_regmap },
+       { "ak4648", (kernel_ulong_t)&ak4648_regmap },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, ak4642_i2c_id);
@@ -571,27 +576,8 @@ static struct i2c_driver ak4642_i2c_driver = {
        .remove         = ak4642_i2c_remove,
        .id_table       = ak4642_i2c_id,
 };
-#endif
-
-static int __init ak4642_modinit(void)
-{
-       int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-       ret = i2c_add_driver(&ak4642_i2c_driver);
-#endif
-       return ret;
 
-}
-module_init(ak4642_modinit);
-
-static void __exit ak4642_exit(void)
-{
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-       i2c_del_driver(&ak4642_i2c_driver);
-#endif
-
-}
-module_exit(ak4642_exit);
+module_i2c_driver(ak4642_i2c_driver);
 
 MODULE_DESCRIPTION("Soc AK4642 driver");
 MODULE_AUTHOR("Kuninori Morimoto <morimoto.kuninori@renesas.com>");
index fea991031be18a05eab28e4922b10a2e472b5ea9..eb9f5d4d8928aee386cebfb0fbeddd0ed74654bc 100644 (file)
@@ -292,6 +292,10 @@ const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = {
        "AIF1RX8",
        "AIF2RX1",
        "AIF2RX2",
+       "AIF2RX3",
+       "AIF2RX4",
+       "AIF2RX5",
+       "AIF2RX6",
        "AIF3RX1",
        "AIF3RX2",
        "SLIMRX1",
@@ -395,6 +399,10 @@ int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS] = {
        0x27,
        0x28,  /* AIF2RX1 */
        0x29,
+       0x2a,
+       0x2b,
+       0x2c,
+       0x2d,
        0x30,  /* AIF3RX1 */
        0x31,
        0x38,  /* SLIMRX1 */
@@ -560,6 +568,16 @@ const struct soc_enum arizona_ng_hold =
                        4, arizona_ng_hold_text);
 EXPORT_SYMBOL_GPL(arizona_ng_hold);
 
+static const char * const arizona_in_hpf_cut_text[] = {
+       "2.5Hz", "5Hz", "10Hz", "20Hz", "40Hz"
+};
+
+const struct soc_enum arizona_in_hpf_cut_enum =
+       SOC_ENUM_SINGLE(ARIZONA_HPF_CONTROL, ARIZONA_IN_HPF_CUT_SHIFT,
+                       ARRAY_SIZE(arizona_in_hpf_cut_text),
+                       arizona_in_hpf_cut_text);
+EXPORT_SYMBOL_GPL(arizona_in_hpf_cut_enum);
+
 static const char * const arizona_in_dmic_osr_text[] = {
        "1.536MHz", "3.072MHz", "6.144MHz",
 };
index 9e81b6392692cbd78e7e9ad7b263fcd00c214a1d..6641f3d641946d12629d2a4692bfaa7048d0a5d1 100644 (file)
@@ -81,7 +81,7 @@ struct arizona_priv {
        unsigned int spk_ena_pending:1;
 };
 
-#define ARIZONA_NUM_MIXER_INPUTS 99
+#define ARIZONA_NUM_MIXER_INPUTS 103
 
 extern const unsigned int arizona_mixer_tlv[];
 extern const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS];
@@ -199,6 +199,7 @@ extern const struct soc_enum arizona_lhpf3_mode;
 extern const struct soc_enum arizona_lhpf4_mode;
 
 extern const struct soc_enum arizona_ng_hold;
+extern const struct soc_enum arizona_in_hpf_cut_enum;
 extern const struct soc_enum arizona_in_dmic_osr[];
 
 extern int arizona_in_ev(struct snd_soc_dapm_widget *w,
index f6e953454bc0856ffccb87ec6680a670d3e90cbd..ce05fd93dc748c3cc8e1405b1d50296f5e9780e3 100644 (file)
@@ -675,7 +675,7 @@ static struct spi_driver cs4271_spi_driver = {
 };
 #endif /* defined(CONFIG_SPI_MASTER) */
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static const struct i2c_device_id cs4271_i2c_id[] = {
        {"cs4271", 0},
        {}
@@ -728,7 +728,7 @@ static struct i2c_driver cs4271_i2c_driver = {
        .probe          = cs4271_i2c_probe,
        .remove         = cs4271_i2c_remove,
 };
-#endif /* defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) */
+#endif /* IS_ENABLED(CONFIG_I2C) */
 
 /*
  * We only register our serial bus driver here without
@@ -741,7 +741,7 @@ static int __init cs4271_modinit(void)
 {
        int ret;
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&cs4271_i2c_driver);
        if (ret) {
                pr_err("Failed to register CS4271 I2C driver: %d\n", ret);
@@ -767,7 +767,7 @@ static void __exit cs4271_modexit(void)
        spi_unregister_driver(&cs4271_spi_driver);
 #endif
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&cs4271_i2c_driver);
 #endif
 }
index 8b427c97708365e5e1e40aad701f740b62c365be..0bac6d5a4ac8fac7c00e3a909f044a499f11761b 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <linux/gpio.h>
+#include <linux/of_gpio.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
 #include <linux/input.h>
@@ -50,7 +50,7 @@ struct  cs42l52_private {
        u8 mclksel;
        u32 mclk;
        u8 flags;
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+#if IS_ENABLED(CONFIG_INPUT)
        struct input_dev *beep;
        struct work_struct beep_work;
        int beep_rate;
@@ -233,7 +233,7 @@ static const struct soc_enum mic_bias_level_enum =
        SOC_ENUM_SINGLE(CS42L52_IFACE_CTL2, 0,
                        ARRAY_SIZE(mic_bias_level_text), mic_bias_level_text);
 
-static const char * const cs42l52_mic_text[] = { "Single", "Differential" };
+static const char * const cs42l52_mic_text[] = { "MIC1", "MIC2" };
 
 static const struct soc_enum mica_enum =
        SOC_ENUM_SINGLE(CS42L52_MICA_CTL, 5,
@@ -243,12 +243,6 @@ static const struct soc_enum micb_enum =
        SOC_ENUM_SINGLE(CS42L52_MICB_CTL, 5,
                        ARRAY_SIZE(cs42l52_mic_text), cs42l52_mic_text);
 
-static const struct snd_kcontrol_new mica_mux =
-       SOC_DAPM_ENUM("Left Mic Input Capture Mux", mica_enum);
-
-static const struct snd_kcontrol_new micb_mux =
-       SOC_DAPM_ENUM("Right Mic Input Capture Mux", micb_enum);
-
 static const char * const digital_output_mux_text[] = {"ADC", "DSP"};
 
 static const struct soc_enum digital_output_mux_enum =
@@ -531,6 +525,30 @@ static const struct snd_kcontrol_new cs42l52_snd_controls[] = {
 
 };
 
+static const struct snd_kcontrol_new cs42l52_mica_controls[] = {
+       SOC_ENUM("MICA Select", mica_enum),
+};
+
+static const struct snd_kcontrol_new cs42l52_micb_controls[] = {
+       SOC_ENUM("MICB Select", micb_enum),
+};
+
+static int cs42l52_add_mic_controls(struct snd_soc_codec *codec)
+{
+       struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec);
+       struct cs42l52_platform_data *pdata = &cs42l52->pdata;
+
+       if (!pdata->mica_diff_cfg)
+               snd_soc_add_codec_controls(codec, cs42l52_mica_controls,
+                                    ARRAY_SIZE(cs42l52_mica_controls));
+
+       if (!pdata->micb_diff_cfg)
+               snd_soc_add_codec_controls(codec, cs42l52_micb_controls,
+                                    ARRAY_SIZE(cs42l52_micb_controls));
+
+       return 0;
+}
+
 static const struct snd_soc_dapm_widget cs42l52_dapm_widgets[] = {
 
        SND_SOC_DAPM_INPUT("AIN1L"),
@@ -550,9 +568,6 @@ static const struct snd_soc_dapm_widget cs42l52_dapm_widgets[] = {
        SND_SOC_DAPM_AIF_OUT("AIFOUTR", NULL,  0,
                        SND_SOC_NOPM, 0, 0),
 
-       SND_SOC_DAPM_MUX("MICA Mux", SND_SOC_NOPM, 0, 0, &mica_mux),
-       SND_SOC_DAPM_MUX("MICB Mux", SND_SOC_NOPM, 0, 0, &micb_mux),
-
        SND_SOC_DAPM_ADC("ADC Left", NULL, CS42L52_PWRCTL1, 1, 1),
        SND_SOC_DAPM_ADC("ADC Right", NULL, CS42L52_PWRCTL1, 2, 1),
        SND_SOC_DAPM_PGA("PGA Left", CS42L52_PWRCTL1, 3, 1, NULL, 0),
@@ -953,7 +968,7 @@ static int cs42l52_resume(struct snd_soc_codec *codec)
        return 0;
 }
 
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+#if IS_ENABLED(CONFIG_INPUT)
 static int beep_rates[] = {
        261, 522, 585, 667, 706, 774, 889, 1000,
        1043, 1200, 1333, 1412, 1600, 1714, 2000, 2182
@@ -1110,6 +1125,8 @@ static int cs42l52_probe(struct snd_soc_codec *codec)
        }
        regcache_cache_only(cs42l52->regmap, true);
 
+       cs42l52_add_mic_controls(codec);
+
        cs42l52_init_beep(codec);
 
        cs42l52_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -1176,6 +1193,7 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client,
        int ret;
        unsigned int devid = 0;
        unsigned int reg;
+       u32 val32;
 
        cs42l52 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l52_private),
                               GFP_KERNEL);
@@ -1189,9 +1207,39 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client,
                dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
                return ret;
        }
-
-       if (pdata)
+       if (pdata) {
+               cs42l52->pdata = *pdata;
+       } else {
+               pdata = devm_kzalloc(&i2c_client->dev,
+                                    sizeof(struct cs42l52_platform_data),
+                               GFP_KERNEL);
+               if (!pdata) {
+                       dev_err(&i2c_client->dev, "could not allocate pdata\n");
+                       return -ENOMEM;
+               }
+               if (i2c_client->dev.of_node) {
+                       if (of_property_read_bool(i2c_client->dev.of_node,
+                               "cirrus,mica-differential-cfg"))
+                               pdata->mica_diff_cfg = true;
+
+                       if (of_property_read_bool(i2c_client->dev.of_node,
+                               "cirrus,micb-differential-cfg"))
+                               pdata->micb_diff_cfg = true;
+
+                       if (of_property_read_u32(i2c_client->dev.of_node,
+                               "cirrus,micbias-lvl", &val32) >= 0)
+                               pdata->micbias_lvl = val32;
+
+                       if (of_property_read_u32(i2c_client->dev.of_node,
+                               "cirrus,chgfreq-divisor", &val32) >= 0)
+                               pdata->chgfreq = val32;
+
+                       pdata->reset_gpio =
+                               of_get_named_gpio(i2c_client->dev.of_node,
+                                               "cirrus,reset-gpio", 0);
+               }
                cs42l52->pdata = *pdata;
+       }
 
        if (cs42l52->pdata.reset_gpio) {
                ret = gpio_request_one(cs42l52->pdata.reset_gpio,
@@ -1227,29 +1275,18 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client,
                        reg & 0xFF);
 
        /* Set Platform Data */
-       if (cs42l52->pdata.mica_cfg)
+       if (cs42l52->pdata.mica_diff_cfg)
                regmap_update_bits(cs42l52->regmap, CS42L52_MICA_CTL,
                                   CS42L52_MIC_CTL_TYPE_MASK,
-                               cs42l52->pdata.mica_cfg <<
+                               cs42l52->pdata.mica_diff_cfg <<
                                CS42L52_MIC_CTL_TYPE_SHIFT);
 
-       if (cs42l52->pdata.micb_cfg)
+       if (cs42l52->pdata.micb_diff_cfg)
                regmap_update_bits(cs42l52->regmap, CS42L52_MICB_CTL,
                                   CS42L52_MIC_CTL_TYPE_MASK,
-                               cs42l52->pdata.micb_cfg <<
+                               cs42l52->pdata.micb_diff_cfg <<
                                CS42L52_MIC_CTL_TYPE_SHIFT);
 
-       if (cs42l52->pdata.mica_sel)
-               regmap_update_bits(cs42l52->regmap, CS42L52_MICA_CTL,
-                                  CS42L52_MIC_CTL_MIC_SEL_MASK,
-                               cs42l52->pdata.mica_sel <<
-                               CS42L52_MIC_CTL_MIC_SEL_SHIFT);
-       if (cs42l52->pdata.micb_sel)
-               regmap_update_bits(cs42l52->regmap, CS42L52_MICB_CTL,
-                                  CS42L52_MIC_CTL_MIC_SEL_MASK,
-                               cs42l52->pdata.micb_sel <<
-                               CS42L52_MIC_CTL_MIC_SEL_SHIFT);
-
        if (cs42l52->pdata.chgfreq)
                regmap_update_bits(cs42l52->regmap, CS42L52_CHARGE_PUMP,
                                   CS42L52_CHARGE_PUMP_MASK,
@@ -1274,6 +1311,13 @@ static int cs42l52_i2c_remove(struct i2c_client *client)
        return 0;
 }
 
+static const struct of_device_id cs42l52_of_match[] = {
+       { .compatible = "cirrus,cs42l52", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, cs42l52_of_match);
+
+
 static const struct i2c_device_id cs42l52_id[] = {
        { "cs42l52", 0 },
        { }
@@ -1284,6 +1328,7 @@ static struct i2c_driver cs42l52_i2c_driver = {
        .driver = {
                .name = "cs42l52",
                .owner = THIS_MODULE,
+               .of_match_table = cs42l52_of_match,
        },
        .id_table = cs42l52_id,
        .probe =    cs42l52_i2c_probe,
index 9c12314565024fcb80d5091a6fc57a6dddf0555b..8166dcb2e4a393300b3210d0bcdf3dab5358cba9 100644 (file)
@@ -1188,7 +1188,7 @@ static struct snd_soc_codec_driver soc_codec_dev_da7210 = {
        .num_dapm_routes        = ARRAY_SIZE(da7210_audio_map),
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 
 static struct reg_default da7210_regmap_i2c_patch[] = {
 
@@ -1362,7 +1362,7 @@ static struct spi_driver da7210_spi_driver = {
 static int __init da7210_modinit(void)
 {
        int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&da7210_i2c_driver);
 #endif
 #if defined(CONFIG_SPI_MASTER)
@@ -1378,7 +1378,7 @@ module_init(da7210_modinit);
 
 static void __exit da7210_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&da7210_i2c_driver);
 #endif
 #if defined(CONFIG_SPI_MASTER)
index 68342b121c966aa7c90ace1384bbfbefe4737ab7..32797a8e4ee957a17a2d0fb9161766cc0db15082 100644 (file)
@@ -44,7 +44,7 @@ static struct snd_soc_dai_driver hdmi_codec_dai = {
                        SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
                        SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000,
                .formats = SNDRV_PCM_FMTBIT_S16_LE |
-                       SNDRV_PCM_FMTBIT_S24_LE,
+                       SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE,
        },
        .capture = {
                .stream_name = "Capture",
index 492644e67ace909d2f6b71c7685259955f76661d..c6dd48561884036c857c445034c3052a04b43a27 100644 (file)
@@ -53,8 +53,6 @@ enum ssm2602_type {
 struct ssm2602_priv {
        unsigned int sysclk;
        struct snd_pcm_hw_constraint_list *sysclk_constraints;
-       struct snd_pcm_substream *master_substream;
-       struct snd_pcm_substream *slave_substream;
 
        struct regmap *regmap;
 
@@ -277,11 +275,6 @@ static int ssm2602_hw_params(struct snd_pcm_substream *substream,
        int srate = ssm2602_get_coeff(ssm2602->sysclk, params_rate(params));
        unsigned int iface;
 
-       if (substream == ssm2602->slave_substream) {
-               dev_dbg(codec->dev, "Ignoring hw_params for slave substream\n");
-               return 0;
-       }
-
        if (srate < 0)
                return srate;
 
@@ -314,33 +307,6 @@ static int ssm2602_startup(struct snd_pcm_substream *substream,
 {
        struct snd_soc_codec *codec = dai->codec;
        struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
-       struct snd_pcm_runtime *master_runtime;
-
-       /* The DAI has shared clocks so if we already have a playback or
-        * capture going then constrain this substream to match it.
-        * TODO: the ssm2602 allows pairs of non-matching PB/REC rates
-        */
-       if (ssm2602->master_substream) {
-               master_runtime = ssm2602->master_substream->runtime;
-               dev_dbg(codec->dev, "Constraining to %d bits at %dHz\n",
-                       master_runtime->sample_bits,
-                       master_runtime->rate);
-
-               if (master_runtime->rate != 0)
-                       snd_pcm_hw_constraint_minmax(substream->runtime,
-                                                    SNDRV_PCM_HW_PARAM_RATE,
-                                                    master_runtime->rate,
-                                                    master_runtime->rate);
-
-               if (master_runtime->sample_bits != 0)
-                       snd_pcm_hw_constraint_minmax(substream->runtime,
-                                                    SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
-                                                    master_runtime->sample_bits,
-                                                    master_runtime->sample_bits);
-
-               ssm2602->slave_substream = substream;
-       } else
-               ssm2602->master_substream = substream;
 
        if (ssm2602->sysclk_constraints) {
                snd_pcm_hw_constraint_list(substream->runtime, 0,
@@ -351,19 +317,6 @@ static int ssm2602_startup(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static void ssm2602_shutdown(struct snd_pcm_substream *substream,
-                            struct snd_soc_dai *dai)
-{
-       struct snd_soc_codec *codec = dai->codec;
-       struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
-
-       if (ssm2602->master_substream == substream)
-               ssm2602->master_substream = ssm2602->slave_substream;
-
-       ssm2602->slave_substream = NULL;
-}
-
-
 static int ssm2602_mute(struct snd_soc_dai *dai, int mute)
 {
        struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(dai->codec);
@@ -530,7 +483,6 @@ static int ssm2602_set_bias_level(struct snd_soc_codec *codec,
 static const struct snd_soc_dai_ops ssm2602_dai_ops = {
        .startup        = ssm2602_startup,
        .hw_params      = ssm2602_hw_params,
-       .shutdown       = ssm2602_shutdown,
        .digital_mute   = ssm2602_mute,
        .set_sysclk     = ssm2602_set_dai_sysclk,
        .set_fmt        = ssm2602_set_dai_fmt,
@@ -551,6 +503,8 @@ static struct snd_soc_dai_driver ssm2602_dai = {
                .rates = SSM2602_RATES,
                .formats = SSM2602_FORMATS,},
        .ops = &ssm2602_dai_ops,
+       .symmetric_rates = 1,
+       .symmetric_samplebits = 1,
 };
 
 static int ssm2602_suspend(struct snd_soc_codec *codec)
@@ -730,7 +684,7 @@ static struct spi_driver ssm2602_spi_driver = {
 };
 #endif
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 /*
  * ssm2602 2 wire address is determined by GPIO5
  * state during powerup.
@@ -797,7 +751,7 @@ static int __init ssm2602_modinit(void)
                return ret;
 #endif
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&ssm2602_i2c_driver);
        if (ret)
                return ret;
@@ -813,7 +767,7 @@ static void __exit ssm2602_exit(void)
        spi_unregister_driver(&ssm2602_spi_driver);
 #endif
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&ssm2602_i2c_driver);
 #endif
 }
index 546d16b7d38f87cd456e35286dbf3b9a8eab4b33..470fbfb4b3861314b6ecc74dfd95d5c2cd8b0d89 100644 (file)
@@ -350,16 +350,6 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = {
                         DACL1_2_LLOPM_VOL, DACR1_2_RLOPM_VOL,
                         0, 118, 1, output_stage_tlv),
 
-       SOC_DOUBLE_R_TLV("Mono Line2 Bypass Volume",
-                        LINE2L_2_MONOLOPM_VOL, LINE2R_2_MONOLOPM_VOL,
-                        0, 118, 1, output_stage_tlv),
-       SOC_DOUBLE_R_TLV("Mono PGA Bypass Volume",
-                        PGAL_2_MONOLOPM_VOL, PGAR_2_MONOLOPM_VOL,
-                        0, 118, 1, output_stage_tlv),
-       SOC_DOUBLE_R_TLV("Mono DAC Playback Volume",
-                        DACL1_2_MONOLOPM_VOL, DACR1_2_MONOLOPM_VOL,
-                        0, 118, 1, output_stage_tlv),
-
        SOC_DOUBLE_R_TLV("HP Line2 Bypass Volume",
                         LINE2L_2_HPLOUT_VOL, LINE2R_2_HPROUT_VOL,
                         0, 118, 1, output_stage_tlv),
@@ -383,7 +373,6 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = {
        /* Output pin mute controls */
        SOC_DOUBLE_R("Line Playback Switch", LLOPM_CTRL, RLOPM_CTRL, 3,
                     0x01, 0),
-       SOC_SINGLE("Mono Playback Switch", MONOLOPM_CTRL, 3, 0x01, 0),
        SOC_DOUBLE_R("HP Playback Switch", HPLOUT_CTRL, HPROUT_CTRL, 3,
                     0x01, 0),
        SOC_DOUBLE_R("HPCOM Playback Switch", HPLCOM_CTRL, HPRCOM_CTRL, 3,
@@ -412,6 +401,20 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = {
        SOC_ENUM("ADC HPF Cut-off", aic3x_enum[ADC_HPF_ENUM]),
 };
 
+static const struct snd_kcontrol_new aic3x_mono_controls[] = {
+       SOC_DOUBLE_R_TLV("Mono Line2 Bypass Volume",
+                        LINE2L_2_MONOLOPM_VOL, LINE2R_2_MONOLOPM_VOL,
+                        0, 118, 1, output_stage_tlv),
+       SOC_DOUBLE_R_TLV("Mono PGA Bypass Volume",
+                        PGAL_2_MONOLOPM_VOL, PGAR_2_MONOLOPM_VOL,
+                        0, 118, 1, output_stage_tlv),
+       SOC_DOUBLE_R_TLV("Mono DAC Playback Volume",
+                        DACL1_2_MONOLOPM_VOL, DACR1_2_MONOLOPM_VOL,
+                        0, 118, 1, output_stage_tlv),
+
+       SOC_SINGLE("Mono Playback Switch", MONOLOPM_CTRL, 3, 0x01, 0),
+};
+
 /*
  * Class-D amplifier gain. From 0 to 18 dB in 6 dB steps
  */
@@ -565,9 +568,6 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
        SND_SOC_DAPM_PGA("Right HP Out", HPROUT_CTRL, 0, 0, NULL, 0),
        SND_SOC_DAPM_PGA("Right HP Com", HPRCOM_CTRL, 0, 0, NULL, 0),
 
-       /* Mono Output */
-       SND_SOC_DAPM_PGA("Mono Out", MONOLOPM_CTRL, 0, 0, NULL, 0),
-
        /* Inputs to Left ADC */
        SND_SOC_DAPM_ADC("Left ADC", "Left Capture", LINE1L_2_LADC_CTRL, 2, 0),
        SND_SOC_DAPM_MIXER("Left PGA Mixer", SND_SOC_NOPM, 0, 0,
@@ -626,9 +626,6 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
        SND_SOC_DAPM_MIXER("Right Line Mixer", SND_SOC_NOPM, 0, 0,
                           &aic3x_right_line_mixer_controls[0],
                           ARRAY_SIZE(aic3x_right_line_mixer_controls)),
-       SND_SOC_DAPM_MIXER("Mono Mixer", SND_SOC_NOPM, 0, 0,
-                          &aic3x_mono_mixer_controls[0],
-                          ARRAY_SIZE(aic3x_mono_mixer_controls)),
        SND_SOC_DAPM_MIXER("Left HP Mixer", SND_SOC_NOPM, 0, 0,
                           &aic3x_left_hp_mixer_controls[0],
                           ARRAY_SIZE(aic3x_left_hp_mixer_controls)),
@@ -644,7 +641,6 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
 
        SND_SOC_DAPM_OUTPUT("LLOUT"),
        SND_SOC_DAPM_OUTPUT("RLOUT"),
-       SND_SOC_DAPM_OUTPUT("MONO_LOUT"),
        SND_SOC_DAPM_OUTPUT("HPLOUT"),
        SND_SOC_DAPM_OUTPUT("HPROUT"),
        SND_SOC_DAPM_OUTPUT("HPLCOM"),
@@ -666,6 +662,17 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
        SND_SOC_DAPM_OUTPUT("Detection"),
 };
 
+static const struct snd_soc_dapm_widget aic3x_dapm_mono_widgets[] = {
+       /* Mono Output */
+       SND_SOC_DAPM_PGA("Mono Out", MONOLOPM_CTRL, 0, 0, NULL, 0),
+
+       SND_SOC_DAPM_MIXER("Mono Mixer", SND_SOC_NOPM, 0, 0,
+                          &aic3x_mono_mixer_controls[0],
+                          ARRAY_SIZE(aic3x_mono_mixer_controls)),
+
+       SND_SOC_DAPM_OUTPUT("MONO_LOUT"),
+};
+
 static const struct snd_soc_dapm_widget aic3007_dapm_widgets[] = {
        /* Class-D outputs */
        SND_SOC_DAPM_PGA("Left Class-D Out", CLASSD_CTRL, 3, 0, NULL, 0),
@@ -754,17 +761,6 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"Right Line Out", NULL, "Right DAC Mux"},
        {"RLOUT", NULL, "Right Line Out"},
 
-       /* Mono Output */
-       {"Mono Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
-       {"Mono Mixer", "PGAL Bypass Switch", "Left PGA Mixer"},
-       {"Mono Mixer", "DACL1 Switch", "Left DAC Mux"},
-       {"Mono Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
-       {"Mono Mixer", "PGAR Bypass Switch", "Right PGA Mixer"},
-       {"Mono Mixer", "DACR1 Switch", "Right DAC Mux"},
-
-       {"Mono Out", NULL, "Mono Mixer"},
-       {"MONO_LOUT", NULL, "Mono Out"},
-
        /* Left HP Output */
        {"Left HP Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
        {"Left HP Mixer", "PGAL Bypass Switch", "Left PGA Mixer"},
@@ -820,6 +816,18 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"HPRCOM", NULL, "Right HP Com"},
 };
 
+static const struct snd_soc_dapm_route intercon_mono[] = {
+       /* Mono Output */
+       {"Mono Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
+       {"Mono Mixer", "PGAL Bypass Switch", "Left PGA Mixer"},
+       {"Mono Mixer", "DACL1 Switch", "Left DAC Mux"},
+       {"Mono Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
+       {"Mono Mixer", "PGAR Bypass Switch", "Right PGA Mixer"},
+       {"Mono Mixer", "DACR1 Switch", "Right DAC Mux"},
+       {"Mono Out", NULL, "Mono Mixer"},
+       {"MONO_LOUT", NULL, "Mono Out"},
+};
+
 static const struct snd_soc_dapm_route intercon_3007[] = {
        /* Class-D outputs */
        {"Left Class-D Out", NULL, "Left Line Out"},
@@ -833,11 +841,20 @@ 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;
 
-       if (aic3x->model == AIC3X_MODEL_3007) {
+       switch (aic3x->model) {
+       case AIC3X_MODEL_3X:
+       case AIC3X_MODEL_33:
+               snd_soc_dapm_new_controls(dapm, aic3x_dapm_mono_widgets,
+                       ARRAY_SIZE(aic3x_dapm_mono_widgets));
+               snd_soc_dapm_add_routes(dapm, intercon_mono,
+                                       ARRAY_SIZE(intercon_mono));
+               break;
+       case AIC3X_MODEL_3007:
                snd_soc_dapm_new_controls(dapm, aic3007_dapm_widgets,
                        ARRAY_SIZE(aic3007_dapm_widgets));
                snd_soc_dapm_add_routes(dapm, intercon_3007,
                                        ARRAY_SIZE(intercon_3007));
+               break;
        }
 
        return 0;
@@ -1218,6 +1235,24 @@ static int aic3x_resume(struct snd_soc_codec *codec)
        return 0;
 }
 
+static void aic3x_mono_init(struct snd_soc_codec *codec)
+{
+       /* DAC to Mono Line Out default volume and route to Output mixer */
+       snd_soc_write(codec, DACL1_2_MONOLOPM_VOL, DEFAULT_VOL | ROUTE_ON);
+       snd_soc_write(codec, DACR1_2_MONOLOPM_VOL, DEFAULT_VOL | ROUTE_ON);
+
+       /* unmute all outputs */
+       snd_soc_update_bits(codec, MONOLOPM_CTRL, UNMUTE, UNMUTE);
+
+       /* PGA to Mono Line Out default volume, disconnect from Output Mixer */
+       snd_soc_write(codec, PGAL_2_MONOLOPM_VOL, DEFAULT_VOL);
+       snd_soc_write(codec, PGAR_2_MONOLOPM_VOL, DEFAULT_VOL);
+
+       /* Line2 to Mono Out default volume, disconnect from Output Mixer */
+       snd_soc_write(codec, LINE2L_2_MONOLOPM_VOL, DEFAULT_VOL);
+       snd_soc_write(codec, LINE2R_2_MONOLOPM_VOL, DEFAULT_VOL);
+}
+
 /*
  * initialise the AIC3X driver
  * register the mixer and dsp interfaces with the kernel
@@ -1241,14 +1276,10 @@ static int aic3x_init(struct snd_soc_codec *codec)
        /* DAC to Line Out default volume and route to Output mixer */
        snd_soc_write(codec, DACL1_2_LLOPM_VOL, DEFAULT_VOL | ROUTE_ON);
        snd_soc_write(codec, DACR1_2_RLOPM_VOL, DEFAULT_VOL | ROUTE_ON);
-       /* DAC to Mono Line Out default volume and route to Output mixer */
-       snd_soc_write(codec, DACL1_2_MONOLOPM_VOL, DEFAULT_VOL | ROUTE_ON);
-       snd_soc_write(codec, DACR1_2_MONOLOPM_VOL, DEFAULT_VOL | ROUTE_ON);
 
        /* unmute all outputs */
        snd_soc_update_bits(codec, LLOPM_CTRL, UNMUTE, UNMUTE);
        snd_soc_update_bits(codec, RLOPM_CTRL, UNMUTE, UNMUTE);
-       snd_soc_update_bits(codec, MONOLOPM_CTRL, UNMUTE, UNMUTE);
        snd_soc_update_bits(codec, HPLOUT_CTRL, UNMUTE, UNMUTE);
        snd_soc_update_bits(codec, HPROUT_CTRL, UNMUTE, UNMUTE);
        snd_soc_update_bits(codec, HPLCOM_CTRL, UNMUTE, UNMUTE);
@@ -1269,9 +1300,6 @@ static int aic3x_init(struct snd_soc_codec *codec)
        /* PGA to Line Out default volume, disconnect from Output Mixer */
        snd_soc_write(codec, PGAL_2_LLOPM_VOL, DEFAULT_VOL);
        snd_soc_write(codec, PGAR_2_RLOPM_VOL, DEFAULT_VOL);
-       /* PGA to Mono Line Out default volume, disconnect from Output Mixer */
-       snd_soc_write(codec, PGAL_2_MONOLOPM_VOL, DEFAULT_VOL);
-       snd_soc_write(codec, PGAR_2_MONOLOPM_VOL, DEFAULT_VOL);
 
        /* Line2 to HP Bypass default volume, disconnect from Output Mixer */
        snd_soc_write(codec, LINE2L_2_HPLOUT_VOL, DEFAULT_VOL);
@@ -1281,12 +1309,15 @@ static int aic3x_init(struct snd_soc_codec *codec)
        /* Line2 Line Out default volume, disconnect from Output Mixer */
        snd_soc_write(codec, LINE2L_2_LLOPM_VOL, DEFAULT_VOL);
        snd_soc_write(codec, LINE2R_2_RLOPM_VOL, DEFAULT_VOL);
-       /* Line2 to Mono Out default volume, disconnect from Output Mixer */
-       snd_soc_write(codec, LINE2L_2_MONOLOPM_VOL, DEFAULT_VOL);
-       snd_soc_write(codec, LINE2R_2_MONOLOPM_VOL, DEFAULT_VOL);
 
-       if (aic3x->model == AIC3X_MODEL_3007) {
+       switch (aic3x->model) {
+       case AIC3X_MODEL_3X:
+       case AIC3X_MODEL_33:
+               aic3x_mono_init(codec);
+               break;
+       case AIC3X_MODEL_3007:
                snd_soc_write(codec, CLASSD_CTRL, 0);
+               break;
        }
 
        return 0;
@@ -1343,8 +1374,17 @@ static int aic3x_probe(struct snd_soc_codec *codec)
                              (aic3x->setup->gpio_func[1] & 0xf) << 4);
        }
 
-       if (aic3x->model == AIC3X_MODEL_3007)
-               snd_soc_add_codec_controls(codec, &aic3x_classd_amp_gain_ctrl, 1);
+       switch (aic3x->model) {
+       case AIC3X_MODEL_3X:
+       case AIC3X_MODEL_33:
+               snd_soc_add_codec_controls(codec, aic3x_mono_controls,
+                               ARRAY_SIZE(aic3x_mono_controls));
+               break;
+       case AIC3X_MODEL_3007:
+               snd_soc_add_codec_controls(codec,
+                               &aic3x_classd_amp_gain_ctrl, 1);
+               break;
+       }
 
        /* set mic bias voltage */
        switch (aic3x->micbias_vg) {
index fd0a314bc209a4005e8b3488930b6b7d3215526f..726df6d43c2b69227adc503e38397f977db4f220 100644 (file)
@@ -794,7 +794,7 @@ static struct snd_soc_codec_driver soc_codec_dev_uda1380 = {
        .num_dapm_routes = ARRAY_SIZE(uda1380_dapm_routes),
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static int uda1380_i2c_probe(struct i2c_client *i2c,
                             const struct i2c_device_id *id)
 {
@@ -840,7 +840,7 @@ static struct i2c_driver uda1380_i2c_driver = {
 static int __init uda1380_modinit(void)
 {
        int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&uda1380_i2c_driver);
        if (ret != 0)
                pr_err("Failed to register UDA1380 I2C driver: %d\n", ret);
@@ -851,7 +851,7 @@ module_init(uda1380_modinit);
 
 static void __exit uda1380_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&uda1380_i2c_driver);
 #endif
 }
index c3c7396a618115d06171bb87314b363cc8ac9f6d..9eb8517470a33f2bf5c42c0013ccf1cb3bf45eae 100644 (file)
 #include <linux/mfd/arizona/registers.h>
 
 #include "arizona.h"
+#include "wm_adsp.h"
 #include "wm5110.h"
 
+#define WM5110_NUM_ADSP 4
+
 struct wm5110_priv {
        struct arizona_priv core;
        struct arizona_fll fll[2];
 };
 
+static const struct wm_adsp_region wm5110_dsp1_regions[] = {
+       { .type = WMFW_ADSP2_PM, .base = 0x100000 },
+       { .type = WMFW_ADSP2_ZM, .base = 0x180000 },
+       { .type = WMFW_ADSP2_XM, .base = 0x190000 },
+       { .type = WMFW_ADSP2_YM, .base = 0x1a8000 },
+};
+
+static const struct wm_adsp_region wm5110_dsp2_regions[] = {
+       { .type = WMFW_ADSP2_PM, .base = 0x200000 },
+       { .type = WMFW_ADSP2_ZM, .base = 0x280000 },
+       { .type = WMFW_ADSP2_XM, .base = 0x290000 },
+       { .type = WMFW_ADSP2_YM, .base = 0x2a8000 },
+};
+
+static const struct wm_adsp_region wm5110_dsp3_regions[] = {
+       { .type = WMFW_ADSP2_PM, .base = 0x300000 },
+       { .type = WMFW_ADSP2_ZM, .base = 0x380000 },
+       { .type = WMFW_ADSP2_XM, .base = 0x390000 },
+       { .type = WMFW_ADSP2_YM, .base = 0x3a8000 },
+};
+
+static const struct wm_adsp_region wm5110_dsp4_regions[] = {
+       { .type = WMFW_ADSP2_PM, .base = 0x400000 },
+       { .type = WMFW_ADSP2_ZM, .base = 0x480000 },
+       { .type = WMFW_ADSP2_XM, .base = 0x490000 },
+       { .type = WMFW_ADSP2_YM, .base = 0x4a8000 },
+};
+
+static const struct wm_adsp_region *wm5110_dsp_regions[] = {
+       wm5110_dsp1_regions,
+       wm5110_dsp2_regions,
+       wm5110_dsp3_regions,
+       wm5110_dsp4_regions,
+};
+
 static const struct reg_default wm5110_sysclk_revd_patch[] = {
        { 0x3093, 0x1001 },
        { 0x30E3, 0x1301 },
@@ -117,6 +155,25 @@ SOC_SINGLE_RANGE_TLV("IN3L Volume", ARIZONA_IN3L_CONTROL,
 SOC_SINGLE_RANGE_TLV("IN3R Volume", ARIZONA_IN3R_CONTROL,
                     ARIZONA_IN3R_PGA_VOL_SHIFT, 0x40, 0x5f, 0, ana_tlv),
 
+SOC_ENUM("IN HPF Cutoff Frequency", arizona_in_hpf_cut_enum),
+
+SOC_SINGLE("IN1L HPF Switch", ARIZONA_IN1L_CONTROL,
+          ARIZONA_IN1L_HPF_SHIFT, 1, 0),
+SOC_SINGLE("IN1R HPF Switch", ARIZONA_IN1R_CONTROL,
+          ARIZONA_IN1R_HPF_SHIFT, 1, 0),
+SOC_SINGLE("IN2L HPF Switch", ARIZONA_IN2L_CONTROL,
+          ARIZONA_IN2L_HPF_SHIFT, 1, 0),
+SOC_SINGLE("IN2R HPF Switch", ARIZONA_IN2R_CONTROL,
+          ARIZONA_IN2R_HPF_SHIFT, 1, 0),
+SOC_SINGLE("IN3L HPF Switch", ARIZONA_IN3L_CONTROL,
+          ARIZONA_IN3L_HPF_SHIFT, 1, 0),
+SOC_SINGLE("IN3R HPF Switch", ARIZONA_IN3R_CONTROL,
+          ARIZONA_IN3R_HPF_SHIFT, 1, 0),
+SOC_SINGLE("IN4L HPF Switch", ARIZONA_IN4L_CONTROL,
+          ARIZONA_IN4L_HPF_SHIFT, 1, 0),
+SOC_SINGLE("IN4R HPF Switch", ARIZONA_IN4R_CONTROL,
+          ARIZONA_IN4R_HPF_SHIFT, 1, 0),
+
 SOC_SINGLE_TLV("IN1L Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_1L,
               ARIZONA_IN1L_DIG_VOL_SHIFT, 0xbf, 0, digital_tlv),
 SOC_SINGLE_TLV("IN1R Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_1R,
@@ -220,6 +277,10 @@ SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode),
 SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode),
 SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode),
 
+SOC_VALUE_ENUM("ISRC1 FSL", arizona_isrc_fsl[0]),
+SOC_VALUE_ENUM("ISRC2 FSL", arizona_isrc_fsl[1]),
+SOC_VALUE_ENUM("ISRC3 FSL", arizona_isrc_fsl[2]),
+
 ARIZONA_MIXER_CONTROLS("DSP1L", ARIZONA_DSP1LMIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("DSP1R", ARIZONA_DSP1RMIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("DSP2L", ARIZONA_DSP2LMIX_INPUT_1_SOURCE),
@@ -248,19 +309,6 @@ ARIZONA_MIXER_CONTROLS("SPKDAT1R", ARIZONA_OUT5RMIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("SPKDAT2L", ARIZONA_OUT6LMIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("SPKDAT2R", ARIZONA_OUT6RMIX_INPUT_1_SOURCE),
 
-SOC_SINGLE("HPOUT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_1L,
-          ARIZONA_OUT1_OSR_SHIFT, 1, 0),
-SOC_SINGLE("HPOUT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_2L,
-          ARIZONA_OUT2_OSR_SHIFT, 1, 0),
-SOC_SINGLE("HPOUT3 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_3L,
-          ARIZONA_OUT3_OSR_SHIFT, 1, 0),
-SOC_SINGLE("Speaker High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_4L,
-          ARIZONA_OUT4_OSR_SHIFT, 1, 0),
-SOC_SINGLE("SPKDAT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_5L,
-          ARIZONA_OUT5_OSR_SHIFT, 1, 0),
-SOC_SINGLE("SPKDAT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_6L,
-          ARIZONA_OUT6_OSR_SHIFT, 1, 0),
-
 SOC_DOUBLE_R("HPOUT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_1L,
             ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_MUTE_SHIFT, 1, 1),
 SOC_DOUBLE_R("HPOUT2 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_2L,
@@ -293,18 +341,6 @@ SOC_DOUBLE_R_TLV("SPKDAT2 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_6L,
                 ARIZONA_DAC_DIGITAL_VOLUME_6R, ARIZONA_OUT6L_VOL_SHIFT,
                 0xbf, 0, digital_tlv),
 
-SOC_DOUBLE_R_RANGE_TLV("HPOUT1 Volume", ARIZONA_OUTPUT_PATH_CONFIG_1L,
-                      ARIZONA_OUTPUT_PATH_CONFIG_1R,
-                      ARIZONA_OUT1L_PGA_VOL_SHIFT,
-                      0x34, 0x40, 0, ana_tlv),
-SOC_DOUBLE_R_RANGE_TLV("HPOUT2 Volume", ARIZONA_OUTPUT_PATH_CONFIG_2L,
-                      ARIZONA_OUTPUT_PATH_CONFIG_2R,
-                      ARIZONA_OUT2L_PGA_VOL_SHIFT,
-                      0x34, 0x40, 0, ana_tlv),
-SOC_DOUBLE_R_RANGE_TLV("HPOUT3 Volume", ARIZONA_OUTPUT_PATH_CONFIG_3L,
-                      ARIZONA_OUTPUT_PATH_CONFIG_3R,
-                      ARIZONA_OUT3L_PGA_VOL_SHIFT, 0x34, 0x40, 0, ana_tlv),
-
 SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT,
           ARIZONA_SPK1R_MUTE_SHIFT, 1, 1),
 SOC_DOUBLE("SPKDAT2 Switch", ARIZONA_PDM_SPK2_CTRL_1, ARIZONA_SPK2L_MUTE_SHIFT,
@@ -343,6 +379,10 @@ ARIZONA_MIXER_CONTROLS("AIF1TX8", ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE),
 
 ARIZONA_MIXER_CONTROLS("AIF2TX1", ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("AIF2TX2", ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF2TX3", ARIZONA_AIF2TX3MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF2TX4", ARIZONA_AIF2TX4MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF2TX5", ARIZONA_AIF2TX5MIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("AIF2TX6", ARIZONA_AIF2TX6MIX_INPUT_1_SOURCE),
 
 ARIZONA_MIXER_CONTROLS("AIF3TX1", ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE),
@@ -372,6 +412,22 @@ ARIZONA_MIXER_ENUMS(LHPF2, ARIZONA_HPLP2MIX_INPUT_1_SOURCE);
 ARIZONA_MIXER_ENUMS(LHPF3, ARIZONA_HPLP3MIX_INPUT_1_SOURCE);
 ARIZONA_MIXER_ENUMS(LHPF4, ARIZONA_HPLP4MIX_INPUT_1_SOURCE);
 
+ARIZONA_MIXER_ENUMS(DSP1L, ARIZONA_DSP1LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(DSP1R, ARIZONA_DSP1RMIX_INPUT_1_SOURCE);
+ARIZONA_DSP_AUX_ENUMS(DSP1, ARIZONA_DSP1AUX1MIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(DSP2L, ARIZONA_DSP2LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(DSP2R, ARIZONA_DSP2RMIX_INPUT_1_SOURCE);
+ARIZONA_DSP_AUX_ENUMS(DSP2, ARIZONA_DSP2AUX1MIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(DSP3L, ARIZONA_DSP3LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(DSP3R, ARIZONA_DSP3RMIX_INPUT_1_SOURCE);
+ARIZONA_DSP_AUX_ENUMS(DSP3, ARIZONA_DSP3AUX1MIX_INPUT_1_SOURCE);
+
+ARIZONA_MIXER_ENUMS(DSP4L, ARIZONA_DSP4LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(DSP4R, ARIZONA_DSP4RMIX_INPUT_1_SOURCE);
+ARIZONA_DSP_AUX_ENUMS(DSP4, ARIZONA_DSP4AUX1MIX_INPUT_1_SOURCE);
+
 ARIZONA_MIXER_ENUMS(Mic, ARIZONA_MICMIX_INPUT_1_SOURCE);
 ARIZONA_MIXER_ENUMS(Noise, ARIZONA_NOISEMIX_INPUT_1_SOURCE);
 
@@ -402,6 +458,10 @@ ARIZONA_MIXER_ENUMS(AIF1TX8, ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE);
 
 ARIZONA_MIXER_ENUMS(AIF2TX1, ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE);
 ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF2TX3, ARIZONA_AIF2TX3MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF2TX4, ARIZONA_AIF2TX4MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF2TX5, ARIZONA_AIF2TX5MIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(AIF2TX6, ARIZONA_AIF2TX6MIX_INPUT_1_SOURCE);
 
 ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE);
 ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE);
@@ -420,6 +480,36 @@ ARIZONA_MUX_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE);
 ARIZONA_MUX_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE);
 ARIZONA_MUX_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE);
 
+ARIZONA_MUX_ENUMS(ISRC1INT1, ARIZONA_ISRC1INT1MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC1INT2, ARIZONA_ISRC1INT2MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC1INT3, ARIZONA_ISRC1INT3MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC1INT4, ARIZONA_ISRC1INT4MIX_INPUT_1_SOURCE);
+
+ARIZONA_MUX_ENUMS(ISRC1DEC1, ARIZONA_ISRC1DEC1MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC1DEC2, ARIZONA_ISRC1DEC2MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC1DEC3, ARIZONA_ISRC1DEC3MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC1DEC4, ARIZONA_ISRC1DEC4MIX_INPUT_1_SOURCE);
+
+ARIZONA_MUX_ENUMS(ISRC2INT1, ARIZONA_ISRC2INT1MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC2INT2, ARIZONA_ISRC2INT2MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC2INT3, ARIZONA_ISRC2INT3MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC2INT4, ARIZONA_ISRC2INT4MIX_INPUT_1_SOURCE);
+
+ARIZONA_MUX_ENUMS(ISRC2DEC1, ARIZONA_ISRC2DEC1MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC2DEC2, ARIZONA_ISRC2DEC2MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC2DEC3, ARIZONA_ISRC2DEC3MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC2DEC4, ARIZONA_ISRC2DEC4MIX_INPUT_1_SOURCE);
+
+ARIZONA_MUX_ENUMS(ISRC3INT1, ARIZONA_ISRC3INT1MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC3INT2, ARIZONA_ISRC3INT2MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC3INT3, ARIZONA_ISRC3INT3MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC3INT4, ARIZONA_ISRC3INT4MIX_INPUT_1_SOURCE);
+
+ARIZONA_MUX_ENUMS(ISRC3DEC1, ARIZONA_ISRC3DEC1MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC3DEC2, ARIZONA_ISRC3DEC2MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC3DEC3, ARIZONA_ISRC3DEC3MIX_INPUT_1_SOURCE);
+ARIZONA_MUX_ENUMS(ISRC3DEC4, ARIZONA_ISRC3DEC4MIX_INPUT_1_SOURCE);
+
 static const char *wm5110_aec_loopback_texts[] = {
        "HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "HPOUT3L", "HPOUT3R",
        "SPKOUTL", "SPKOUTR", "SPKDAT1L", "SPKDAT1R", "SPKDAT2L", "SPKDAT2R",
@@ -560,6 +650,65 @@ SND_SOC_DAPM_PGA("ASRC2L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2L_ENA_SHIFT, 0,
 SND_SOC_DAPM_PGA("ASRC2R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2R_ENA_SHIFT, 0,
                 NULL, 0),
 
+WM_ADSP2("DSP1", 0),
+WM_ADSP2("DSP2", 1),
+WM_ADSP2("DSP3", 2),
+WM_ADSP2("DSP4", 3),
+
+SND_SOC_DAPM_PGA("ISRC1INT1", ARIZONA_ISRC_1_CTRL_3,
+                ARIZONA_ISRC1_INT0_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC1INT2", ARIZONA_ISRC_1_CTRL_3,
+                ARIZONA_ISRC1_INT1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC1INT3", ARIZONA_ISRC_1_CTRL_3,
+                ARIZONA_ISRC1_INT2_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC1INT4", ARIZONA_ISRC_1_CTRL_3,
+                ARIZONA_ISRC1_INT3_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("ISRC1DEC1", ARIZONA_ISRC_1_CTRL_3,
+                ARIZONA_ISRC1_DEC0_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC1DEC2", ARIZONA_ISRC_1_CTRL_3,
+                ARIZONA_ISRC1_DEC1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC1DEC3", ARIZONA_ISRC_1_CTRL_3,
+                ARIZONA_ISRC1_DEC2_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC1DEC4", ARIZONA_ISRC_1_CTRL_3,
+                ARIZONA_ISRC1_DEC3_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("ISRC2INT1", ARIZONA_ISRC_2_CTRL_3,
+                ARIZONA_ISRC2_INT0_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC2INT2", ARIZONA_ISRC_2_CTRL_3,
+                ARIZONA_ISRC2_INT1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC2INT3", ARIZONA_ISRC_2_CTRL_3,
+                ARIZONA_ISRC2_INT2_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC2INT4", ARIZONA_ISRC_2_CTRL_3,
+                ARIZONA_ISRC2_INT3_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("ISRC2DEC1", ARIZONA_ISRC_2_CTRL_3,
+                ARIZONA_ISRC2_DEC0_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC2DEC2", ARIZONA_ISRC_2_CTRL_3,
+                ARIZONA_ISRC2_DEC1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC2DEC3", ARIZONA_ISRC_2_CTRL_3,
+                ARIZONA_ISRC2_DEC2_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC2DEC4", ARIZONA_ISRC_2_CTRL_3,
+                ARIZONA_ISRC2_DEC3_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("ISRC3INT1", ARIZONA_ISRC_3_CTRL_3,
+                ARIZONA_ISRC3_INT0_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC3INT2", ARIZONA_ISRC_3_CTRL_3,
+                ARIZONA_ISRC3_INT1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC3INT3", ARIZONA_ISRC_3_CTRL_3,
+                ARIZONA_ISRC3_INT2_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC3INT4", ARIZONA_ISRC_3_CTRL_3,
+                ARIZONA_ISRC3_INT3_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("ISRC3DEC1", ARIZONA_ISRC_3_CTRL_3,
+                ARIZONA_ISRC3_DEC0_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC3DEC2", ARIZONA_ISRC_3_CTRL_3,
+                ARIZONA_ISRC3_DEC1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC3DEC3", ARIZONA_ISRC_3_CTRL_3,
+                ARIZONA_ISRC3_DEC2_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("ISRC3DEC4", ARIZONA_ISRC_3_CTRL_3,
+                ARIZONA_ISRC3_DEC3_ENA_SHIFT, 0, NULL, 0),
+
 SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1,
                       ARIZONA_AEC_LOOPBACK_ENA_SHIFT, 0,
                       &wm5110_aec_loopback_mux),
@@ -602,11 +751,27 @@ SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0,
                     ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX1_ENA_SHIFT, 0),
 SND_SOC_DAPM_AIF_OUT("AIF2TX2", NULL, 0,
                     ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX2_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF2TX3", NULL, 0,
+                    ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX3_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF2TX4", NULL, 0,
+                    ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX4_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF2TX5", NULL, 0,
+                    ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX5_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF2TX6", NULL, 0,
+                    ARIZONA_AIF2_TX_ENABLES, ARIZONA_AIF2TX6_ENA_SHIFT, 0),
 
 SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0,
                    ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX1_ENA_SHIFT, 0),
 SND_SOC_DAPM_AIF_IN("AIF2RX2", NULL, 0,
                    ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX2_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF2RX3", NULL, 0,
+                   ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX3_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF2RX4", NULL, 0,
+                   ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX4_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF2RX5", NULL, 0,
+                   ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX5_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF2RX6", NULL, 0,
+                   ARIZONA_AIF2_RX_ENABLES, ARIZONA_AIF2RX6_ENA_SHIFT, 0),
 
 SND_SOC_DAPM_AIF_IN("SLIMRX1", NULL, 0,
                    ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE,
@@ -744,6 +909,10 @@ ARIZONA_MIXER_WIDGETS(AIF1TX8, "AIF1TX8"),
 
 ARIZONA_MIXER_WIDGETS(AIF2TX1, "AIF2TX1"),
 ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"),
+ARIZONA_MIXER_WIDGETS(AIF2TX3, "AIF2TX3"),
+ARIZONA_MIXER_WIDGETS(AIF2TX4, "AIF2TX4"),
+ARIZONA_MIXER_WIDGETS(AIF2TX5, "AIF2TX5"),
+ARIZONA_MIXER_WIDGETS(AIF2TX6, "AIF2TX6"),
 
 ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"),
 ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"),
@@ -762,6 +931,41 @@ ARIZONA_MUX_WIDGETS(ASRC1R, "ASRC1R"),
 ARIZONA_MUX_WIDGETS(ASRC2L, "ASRC2L"),
 ARIZONA_MUX_WIDGETS(ASRC2R, "ASRC2R"),
 
+ARIZONA_DSP_WIDGETS(DSP1, "DSP1"),
+ARIZONA_DSP_WIDGETS(DSP2, "DSP2"),
+ARIZONA_DSP_WIDGETS(DSP3, "DSP3"),
+ARIZONA_DSP_WIDGETS(DSP4, "DSP4"),
+
+ARIZONA_MUX_WIDGETS(ISRC1DEC1, "ISRC1DEC1"),
+ARIZONA_MUX_WIDGETS(ISRC1DEC2, "ISRC1DEC2"),
+ARIZONA_MUX_WIDGETS(ISRC1DEC3, "ISRC1DEC3"),
+ARIZONA_MUX_WIDGETS(ISRC1DEC4, "ISRC1DEC4"),
+
+ARIZONA_MUX_WIDGETS(ISRC1INT1, "ISRC1INT1"),
+ARIZONA_MUX_WIDGETS(ISRC1INT2, "ISRC1INT2"),
+ARIZONA_MUX_WIDGETS(ISRC1INT3, "ISRC1INT3"),
+ARIZONA_MUX_WIDGETS(ISRC1INT4, "ISRC1INT4"),
+
+ARIZONA_MUX_WIDGETS(ISRC2DEC1, "ISRC2DEC1"),
+ARIZONA_MUX_WIDGETS(ISRC2DEC2, "ISRC2DEC2"),
+ARIZONA_MUX_WIDGETS(ISRC2DEC3, "ISRC2DEC3"),
+ARIZONA_MUX_WIDGETS(ISRC2DEC4, "ISRC2DEC4"),
+
+ARIZONA_MUX_WIDGETS(ISRC2INT1, "ISRC2INT1"),
+ARIZONA_MUX_WIDGETS(ISRC2INT2, "ISRC2INT2"),
+ARIZONA_MUX_WIDGETS(ISRC2INT3, "ISRC2INT3"),
+ARIZONA_MUX_WIDGETS(ISRC2INT4, "ISRC2INT4"),
+
+ARIZONA_MUX_WIDGETS(ISRC3DEC1, "ISRC3DEC1"),
+ARIZONA_MUX_WIDGETS(ISRC3DEC2, "ISRC3DEC2"),
+ARIZONA_MUX_WIDGETS(ISRC3DEC3, "ISRC3DEC3"),
+ARIZONA_MUX_WIDGETS(ISRC3DEC4, "ISRC3DEC4"),
+
+ARIZONA_MUX_WIDGETS(ISRC3INT1, "ISRC3INT1"),
+ARIZONA_MUX_WIDGETS(ISRC3INT2, "ISRC3INT2"),
+ARIZONA_MUX_WIDGETS(ISRC3INT3, "ISRC3INT3"),
+ARIZONA_MUX_WIDGETS(ISRC3INT4, "ISRC3INT4"),
+
 SND_SOC_DAPM_OUTPUT("HPOUT1L"),
 SND_SOC_DAPM_OUTPUT("HPOUT1R"),
 SND_SOC_DAPM_OUTPUT("HPOUT2L"),
@@ -805,6 +1009,10 @@ SND_SOC_DAPM_OUTPUT("MICSUPP"),
        { name, "AIF1RX8", "AIF1RX8" }, \
        { name, "AIF2RX1", "AIF2RX1" }, \
        { name, "AIF2RX2", "AIF2RX2" }, \
+       { name, "AIF2RX3", "AIF2RX3" }, \
+       { name, "AIF2RX4", "AIF2RX4" }, \
+       { name, "AIF2RX5", "AIF2RX5" }, \
+       { name, "AIF2RX6", "AIF2RX6" }, \
        { name, "AIF3RX1", "AIF3RX1" }, \
        { name, "AIF3RX2", "AIF3RX2" }, \
        { name, "SLIMRX1", "SLIMRX1" }, \
@@ -830,7 +1038,55 @@ SND_SOC_DAPM_OUTPUT("MICSUPP"),
        { name, "ASRC1L", "ASRC1L" }, \
        { name, "ASRC1R", "ASRC1R" }, \
        { name, "ASRC2L", "ASRC2L" }, \
-       { name, "ASRC2R", "ASRC2R" }
+       { name, "ASRC2R", "ASRC2R" }, \
+       { name, "ISRC1DEC1", "ISRC1DEC1" }, \
+       { name, "ISRC1DEC2", "ISRC1DEC2" }, \
+       { name, "ISRC1DEC3", "ISRC1DEC3" }, \
+       { name, "ISRC1DEC4", "ISRC1DEC4" }, \
+       { name, "ISRC1INT1", "ISRC1INT1" }, \
+       { name, "ISRC1INT2", "ISRC1INT2" }, \
+       { name, "ISRC1INT3", "ISRC1INT3" }, \
+       { name, "ISRC1INT4", "ISRC1INT4" }, \
+       { name, "ISRC2DEC1", "ISRC2DEC1" }, \
+       { name, "ISRC2DEC2", "ISRC2DEC2" }, \
+       { name, "ISRC2DEC3", "ISRC2DEC3" }, \
+       { name, "ISRC2DEC4", "ISRC2DEC4" }, \
+       { name, "ISRC2INT1", "ISRC2INT1" }, \
+       { name, "ISRC2INT2", "ISRC2INT2" }, \
+       { name, "ISRC2INT3", "ISRC2INT3" }, \
+       { name, "ISRC2INT4", "ISRC2INT4" }, \
+       { name, "ISRC3DEC1", "ISRC3DEC1" }, \
+       { name, "ISRC3DEC2", "ISRC3DEC2" }, \
+       { name, "ISRC3DEC3", "ISRC3DEC3" }, \
+       { name, "ISRC3DEC4", "ISRC3DEC4" }, \
+       { name, "ISRC3INT1", "ISRC3INT1" }, \
+       { name, "ISRC3INT2", "ISRC3INT2" }, \
+       { name, "ISRC3INT3", "ISRC3INT3" }, \
+       { name, "ISRC3INT4", "ISRC3INT4" }, \
+       { name, "DSP1.1", "DSP1" }, \
+       { name, "DSP1.2", "DSP1" }, \
+       { name, "DSP1.3", "DSP1" }, \
+       { name, "DSP1.4", "DSP1" }, \
+       { name, "DSP1.5", "DSP1" }, \
+       { name, "DSP1.6", "DSP1" }, \
+       { name, "DSP2.1", "DSP2" }, \
+       { name, "DSP2.2", "DSP2" }, \
+       { name, "DSP2.3", "DSP2" }, \
+       { name, "DSP2.4", "DSP2" }, \
+       { name, "DSP2.5", "DSP2" }, \
+       { name, "DSP2.6", "DSP2" }, \
+       { name, "DSP3.1", "DSP3" }, \
+       { name, "DSP3.2", "DSP3" }, \
+       { name, "DSP3.3", "DSP3" }, \
+       { name, "DSP3.4", "DSP3" }, \
+       { name, "DSP3.5", "DSP3" }, \
+       { name, "DSP3.6", "DSP3" }, \
+       { name, "DSP4.1", "DSP4" }, \
+       { name, "DSP4.2", "DSP4" }, \
+       { name, "DSP4.3", "DSP4" }, \
+       { name, "DSP4.4", "DSP4" }, \
+       { name, "DSP4.5", "DSP4" }, \
+       { name, "DSP4.6", "DSP4" }
 
 static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
        { "AIF2 Capture", NULL, "DBVDD2" },
@@ -902,9 +1158,17 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
 
        { "AIF2 Capture", NULL, "AIF2TX1" },
        { "AIF2 Capture", NULL, "AIF2TX2" },
+       { "AIF2 Capture", NULL, "AIF2TX3" },
+       { "AIF2 Capture", NULL, "AIF2TX4" },
+       { "AIF2 Capture", NULL, "AIF2TX5" },
+       { "AIF2 Capture", NULL, "AIF2TX6" },
 
        { "AIF2RX1", NULL, "AIF2 Playback" },
        { "AIF2RX2", NULL, "AIF2 Playback" },
+       { "AIF2RX3", NULL, "AIF2 Playback" },
+       { "AIF2RX4", NULL, "AIF2 Playback" },
+       { "AIF2RX5", NULL, "AIF2 Playback" },
+       { "AIF2RX6", NULL, "AIF2 Playback" },
 
        { "AIF3 Capture", NULL, "AIF3TX1" },
        { "AIF3 Capture", NULL, "AIF3TX2" },
@@ -988,6 +1252,10 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
 
        ARIZONA_MIXER_ROUTES("AIF2TX1", "AIF2TX1"),
        ARIZONA_MIXER_ROUTES("AIF2TX2", "AIF2TX2"),
+       ARIZONA_MIXER_ROUTES("AIF2TX3", "AIF2TX3"),
+       ARIZONA_MIXER_ROUTES("AIF2TX4", "AIF2TX4"),
+       ARIZONA_MIXER_ROUTES("AIF2TX5", "AIF2TX5"),
+       ARIZONA_MIXER_ROUTES("AIF2TX6", "AIF2TX6"),
 
        ARIZONA_MIXER_ROUTES("AIF3TX1", "AIF3TX1"),
        ARIZONA_MIXER_ROUTES("AIF3TX2", "AIF3TX2"),
@@ -1024,6 +1292,41 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {
        ARIZONA_MUX_ROUTES("ASRC2L", "ASRC2L"),
        ARIZONA_MUX_ROUTES("ASRC2R", "ASRC2R"),
 
+       ARIZONA_DSP_ROUTES("DSP1"),
+       ARIZONA_DSP_ROUTES("DSP2"),
+       ARIZONA_DSP_ROUTES("DSP3"),
+       ARIZONA_DSP_ROUTES("DSP4"),
+
+       ARIZONA_MUX_ROUTES("ISRC1INT1", "ISRC1INT1"),
+       ARIZONA_MUX_ROUTES("ISRC1INT2", "ISRC1INT2"),
+       ARIZONA_MUX_ROUTES("ISRC1INT3", "ISRC1INT3"),
+       ARIZONA_MUX_ROUTES("ISRC1INT4", "ISRC1INT4"),
+
+       ARIZONA_MUX_ROUTES("ISRC1DEC1", "ISRC1DEC1"),
+       ARIZONA_MUX_ROUTES("ISRC1DEC2", "ISRC1DEC2"),
+       ARIZONA_MUX_ROUTES("ISRC1DEC3", "ISRC1DEC3"),
+       ARIZONA_MUX_ROUTES("ISRC1DEC4", "ISRC1DEC4"),
+
+       ARIZONA_MUX_ROUTES("ISRC2INT1", "ISRC2INT1"),
+       ARIZONA_MUX_ROUTES("ISRC2INT2", "ISRC2INT2"),
+       ARIZONA_MUX_ROUTES("ISRC2INT3", "ISRC2INT3"),
+       ARIZONA_MUX_ROUTES("ISRC2INT4", "ISRC2INT4"),
+
+       ARIZONA_MUX_ROUTES("ISRC2DEC1", "ISRC2DEC1"),
+       ARIZONA_MUX_ROUTES("ISRC2DEC2", "ISRC2DEC2"),
+       ARIZONA_MUX_ROUTES("ISRC2DEC3", "ISRC2DEC3"),
+       ARIZONA_MUX_ROUTES("ISRC2DEC4", "ISRC2DEC4"),
+
+       ARIZONA_MUX_ROUTES("ISRC3INT1", "ISRC3INT1"),
+       ARIZONA_MUX_ROUTES("ISRC3INT2", "ISRC3INT2"),
+       ARIZONA_MUX_ROUTES("ISRC3INT3", "ISRC3INT3"),
+       ARIZONA_MUX_ROUTES("ISRC3INT4", "ISRC3INT4"),
+
+       ARIZONA_MUX_ROUTES("ISRC3DEC1", "ISRC3DEC1"),
+       ARIZONA_MUX_ROUTES("ISRC3DEC2", "ISRC3DEC2"),
+       ARIZONA_MUX_ROUTES("ISRC3DEC3", "ISRC3DEC3"),
+       ARIZONA_MUX_ROUTES("ISRC3DEC4", "ISRC3DEC4"),
+
        { "AEC Loopback", "HPOUT1L", "OUT1L" },
        { "AEC Loopback", "HPOUT1R", "OUT1R" },
        { "HPOUT1L", NULL, "OUT1L" },
@@ -1120,14 +1423,14 @@ static struct snd_soc_dai_driver wm5110_dai[] = {
                .playback = {
                        .stream_name = "AIF2 Playback",
                        .channels_min = 1,
-                       .channels_max = 2,
+                       .channels_max = 6,
                        .rates = WM5110_RATES,
                        .formats = WM5110_FORMATS,
                },
                .capture = {
                         .stream_name = "AIF2 Capture",
                         .channels_min = 1,
-                        .channels_max = 2,
+                        .channels_max = 6,
                         .rates = WM5110_RATES,
                         .formats = WM5110_FORMATS,
                 },
@@ -1229,6 +1532,10 @@ static int wm5110_codec_probe(struct snd_soc_codec *codec)
        arizona_init_spk(codec);
        arizona_init_gpio(codec);
 
+       ret = snd_soc_add_codec_controls(codec, wm_adsp2_fw_controls, 8);
+       if (ret != 0)
+               return ret;
+
        snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS");
 
        priv->core.arizona->dapm = &codec->dapm;
@@ -1283,7 +1590,7 @@ static int wm5110_probe(struct platform_device *pdev)
 {
        struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
        struct wm5110_priv *wm5110;
-       int i;
+       int i, ret;
 
        wm5110 = devm_kzalloc(&pdev->dev, sizeof(struct wm5110_priv),
                              GFP_KERNEL);
@@ -1294,6 +1601,24 @@ static int wm5110_probe(struct platform_device *pdev)
        wm5110->core.arizona = arizona;
        wm5110->core.num_inputs = 8;
 
+       for (i = 0; i < WM5110_NUM_ADSP; i++) {
+               wm5110->core.adsp[i].part = "wm5110";
+               wm5110->core.adsp[i].num = i + 1;
+               wm5110->core.adsp[i].type = WMFW_ADSP2;
+               wm5110->core.adsp[i].dev = arizona->dev;
+               wm5110->core.adsp[i].regmap = arizona->regmap;
+
+               wm5110->core.adsp[i].base = ARIZONA_DSP1_CONTROL_1
+                       + (0x100 * i);
+               wm5110->core.adsp[i].mem = wm5110_dsp_regions[i];
+               wm5110->core.adsp[i].num_mems
+                       = ARRAY_SIZE(wm5110_dsp1_regions);
+
+               ret = wm_adsp2_init(&wm5110->core.adsp[i], false);
+               if (ret != 0)
+                       return ret;
+       }
+
        for (i = 0; i < ARRAY_SIZE(wm5110->fll); i++)
                wm5110->fll[i].vco_mult = 3;
 
@@ -1304,6 +1629,12 @@ static int wm5110_probe(struct platform_device *pdev)
                         ARIZONA_IRQ_FLL2_LOCK, ARIZONA_IRQ_FLL2_CLOCK_OK,
                         &wm5110->fll[1]);
 
+       /* SR2 fixed at 8kHz, SR3 fixed at 16kHz */
+       regmap_update_bits(arizona->regmap, ARIZONA_SAMPLE_RATE_2,
+                          ARIZONA_SAMPLE_RATE_2_MASK, 0x11);
+       regmap_update_bits(arizona->regmap, ARIZONA_SAMPLE_RATE_3,
+                          ARIZONA_SAMPLE_RATE_3_MASK, 0x12);
+
        for (i = 0; i < ARRAY_SIZE(wm5110_dai); i++)
                arizona_init_dai(&wm5110->core, i);
 
index 6ed5433943eaae4716f54a75f7b4cf4d9fd83fc2..7df7d45727559e98501eef2500b3cc610ee8a4b0 100644 (file)
@@ -684,7 +684,7 @@ static struct spi_driver wm8510_spi_driver = {
 };
 #endif /* CONFIG_SPI_MASTER */
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static int wm8510_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
@@ -735,7 +735,7 @@ static struct i2c_driver wm8510_i2c_driver = {
 static int __init wm8510_modinit(void)
 {
        int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&wm8510_i2c_driver);
        if (ret != 0) {
                printk(KERN_ERR "Failed to register WM8510 I2C driver: %d\n",
@@ -755,7 +755,7 @@ module_init(wm8510_modinit);
 
 static void __exit wm8510_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&wm8510_i2c_driver);
 #endif
 #if defined(CONFIG_SPI_MASTER)
index 139bf9ac94078152470fc639816a328eac8dbfa6..74d106dc76676d5481ae367ad2c5115e8d7df32a 100644 (file)
@@ -452,7 +452,7 @@ static const struct regmap_config wm8523_regmap = {
        .volatile_reg = wm8523_volatile_register,
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static int wm8523_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
@@ -555,7 +555,7 @@ static struct i2c_driver wm8523_i2c_driver = {
 static int __init wm8523_modinit(void)
 {
        int ret;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&wm8523_i2c_driver);
        if (ret != 0) {
                printk(KERN_ERR "Failed to register WM8523 I2C driver: %d\n",
@@ -568,7 +568,7 @@ module_init(wm8523_modinit);
 
 static void __exit wm8523_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&wm8523_i2c_driver);
 #endif
 }
index 08a414b57b1ea8179819adc03dd300233f24d72e..318989acbbe5fbb97878856ccab46330422f6bdf 100644 (file)
@@ -941,7 +941,7 @@ static const struct regmap_config wm8580_regmap = {
        .volatile_reg = wm8580_volatile,
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static int wm8580_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
@@ -1003,7 +1003,7 @@ static int __init wm8580_modinit(void)
 {
        int ret = 0;
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&wm8580_i2c_driver);
        if (ret != 0) {
                pr_err("Failed to register WM8580 I2C driver: %d\n", ret);
@@ -1016,7 +1016,7 @@ module_init(wm8580_modinit);
 
 static void __exit wm8580_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&wm8580_i2c_driver);
 #endif
 }
index 5b428b060d418da78286a605060c4cb4c019801b..d99f948c513cd80bf56f96f6657ce20224f2fb0d 100644 (file)
@@ -469,7 +469,7 @@ static struct spi_driver wm8711_spi_driver = {
 };
 #endif /* CONFIG_SPI_MASTER */
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static int wm8711_i2c_probe(struct i2c_client *client,
                            const struct i2c_device_id *id)
 {
@@ -520,7 +520,7 @@ static struct i2c_driver wm8711_i2c_driver = {
 static int __init wm8711_modinit(void)
 {
        int ret;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&wm8711_i2c_driver);
        if (ret != 0) {
                printk(KERN_ERR "Failed to register WM8711 I2C driver: %d\n",
@@ -540,7 +540,7 @@ module_init(wm8711_modinit);
 
 static void __exit wm8711_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&wm8711_i2c_driver);
 #endif
 #if defined(CONFIG_SPI_MASTER)
index c6a292dcded0c11eda10c5dfa8fd70e2be84ec0c..cd89033e84c08a1d290cb012cee545273b35badd 100644 (file)
@@ -320,7 +320,7 @@ static struct spi_driver wm8728_spi_driver = {
 };
 #endif /* CONFIG_SPI_MASTER */
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static int wm8728_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
@@ -371,7 +371,7 @@ static struct i2c_driver wm8728_i2c_driver = {
 static int __init wm8728_modinit(void)
 {
        int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&wm8728_i2c_driver);
        if (ret != 0) {
                printk(KERN_ERR "Failed to register wm8728 I2C driver: %d\n",
@@ -391,7 +391,7 @@ module_init(wm8728_modinit);
 
 static void __exit wm8728_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&wm8728_i2c_driver);
 #endif
 #if defined(CONFIG_SPI_MASTER)
index 456bb8c6d759176a3bf31c5f7003a6e8cfc2d799..029720366ff8f65f7d6b208216f7cba64b6523af 100644 (file)
@@ -447,10 +447,10 @@ static int wm8731_set_dai_fmt(struct snd_soc_dai *codec_dai,
                iface |= 0x0001;
                break;
        case SND_SOC_DAIFMT_DSP_A:
-               iface |= 0x0003;
+               iface |= 0x0013;
                break;
        case SND_SOC_DAIFMT_DSP_B:
-               iface |= 0x0013;
+               iface |= 0x0003;
                break;
        default:
                return -EINVAL;
@@ -732,7 +732,7 @@ static struct spi_driver wm8731_spi_driver = {
 };
 #endif /* CONFIG_SPI_MASTER */
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static int wm8731_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
@@ -791,7 +791,7 @@ static struct i2c_driver wm8731_i2c_driver = {
 static int __init wm8731_modinit(void)
 {
        int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&wm8731_i2c_driver);
        if (ret != 0) {
                printk(KERN_ERR "Failed to register WM8731 I2C driver: %d\n",
@@ -811,7 +811,7 @@ module_init(wm8731_modinit);
 
 static void __exit wm8731_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&wm8731_i2c_driver);
 #endif
 #if defined(CONFIG_SPI_MASTER)
index b18813cc7ba9f06c87b399834abbceac5d3b9f49..2895c8d3b5e4cce600114dcab949f28b82cf2c7e 100644 (file)
@@ -500,7 +500,7 @@ static const struct regmap_config wm8741_regmap = {
        .readable_reg = wm8741_readable,
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static int wm8741_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
@@ -617,7 +617,7 @@ static int __init wm8741_modinit(void)
 {
        int ret = 0;
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&wm8741_i2c_driver);
        if (ret != 0)
                pr_err("Failed to register WM8741 I2C driver: %d\n", ret);
@@ -639,7 +639,7 @@ static void __exit wm8741_exit(void)
 #if defined(CONFIG_SPI_MASTER)
        spi_unregister_driver(&wm8741_spi_driver);
 #endif
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&wm8741_i2c_driver);
 #endif
 }
index 50d5ff616232676bb094054d44a0c1076ddba0ab..78616a638a55ad4a76f11559f08c6dc4bdb708f6 100644 (file)
@@ -816,7 +816,7 @@ static struct spi_driver wm8750_spi_driver = {
 };
 #endif /* CONFIG_SPI_MASTER */
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static int wm8750_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
@@ -868,7 +868,7 @@ static struct i2c_driver wm8750_i2c_driver = {
 static int __init wm8750_modinit(void)
 {
        int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&wm8750_i2c_driver);
        if (ret != 0) {
                printk(KERN_ERR "Failed to register wm8750 I2C driver: %d\n",
@@ -888,7 +888,7 @@ module_init(wm8750_modinit);
 
 static void __exit wm8750_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&wm8750_i2c_driver);
 #endif
 #if defined(CONFIG_SPI_MASTER)
index d96ebf52d953e850016184f4615f2faf979a738d..be85da93a2682fb89c7c668042f772fc08ca7452 100644 (file)
@@ -1596,7 +1596,7 @@ static struct spi_driver wm8753_spi_driver = {
 };
 #endif /* CONFIG_SPI_MASTER */
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static int wm8753_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
@@ -1653,7 +1653,7 @@ static struct i2c_driver wm8753_i2c_driver = {
 static int __init wm8753_modinit(void)
 {
        int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&wm8753_i2c_driver);
        if (ret != 0) {
                printk(KERN_ERR "Failed to register wm8753 I2C driver: %d\n",
@@ -1673,7 +1673,7 @@ module_init(wm8753_modinit);
 
 static void __exit wm8753_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&wm8753_i2c_driver);
 #endif
 #if defined(CONFIG_SPI_MASTER)
index 942d58e455f384f9b8c5cdc83363c861ff5366b5..ef824672523206a1a3f5d593647a20ae5487b941 100644 (file)
@@ -532,7 +532,7 @@ static struct spi_driver wm8776_spi_driver = {
 };
 #endif /* CONFIG_SPI_MASTER */
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static int wm8776_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
@@ -584,7 +584,7 @@ static struct i2c_driver wm8776_i2c_driver = {
 static int __init wm8776_modinit(void)
 {
        int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&wm8776_i2c_driver);
        if (ret != 0) {
                printk(KERN_ERR "Failed to register wm8776 I2C driver: %d\n",
@@ -604,7 +604,7 @@ module_init(wm8776_modinit);
 
 static void __exit wm8776_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&wm8776_i2c_driver);
 #endif
 #if defined(CONFIG_SPI_MASTER)
index 1704b1e119cb021db8fced2be8482c5da40810d9..9bc8206a68071267cbb18856dc5c9722930af147 100644 (file)
@@ -739,7 +739,7 @@ static struct spi_driver wm8804_spi_driver = {
 };
 #endif
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static int wm8804_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
@@ -791,7 +791,7 @@ static int __init wm8804_modinit(void)
 {
        int ret = 0;
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&wm8804_i2c_driver);
        if (ret) {
                printk(KERN_ERR "Failed to register wm8804 I2C driver: %d\n",
@@ -811,7 +811,7 @@ module_init(wm8804_modinit);
 
 static void __exit wm8804_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&wm8804_i2c_driver);
 #endif
 #if defined(CONFIG_SPI_MASTER)
index 734209e252c3c7cc049b9f982de6539154aa67ab..e98bc7038a086b39231ecbb5196fb7a40fc92d1e 100644 (file)
@@ -1288,7 +1288,7 @@ static struct spi_driver wm8900_spi_driver = {
 };
 #endif /* CONFIG_SPI_MASTER */
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static int wm8900_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
@@ -1338,7 +1338,7 @@ static struct i2c_driver wm8900_i2c_driver = {
 static int __init wm8900_modinit(void)
 {
        int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&wm8900_i2c_driver);
        if (ret != 0) {
                printk(KERN_ERR "Failed to register wm8900 I2C driver: %d\n",
@@ -1358,7 +1358,7 @@ module_init(wm8900_modinit);
 
 static void __exit wm8900_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&wm8900_i2c_driver);
 #endif
 #if defined(CONFIG_SPI_MASTER)
index b1591c61c254ebc1f12d0a19e682e45df632ed77..b404c26c1753407c849c61fdc5ac2db5254deaf0 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/spi/spi.h>
+#include <linux/regmap.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 
 struct wm8940_priv {
        unsigned int sysclk;
-       enum snd_soc_control_type control_type;
+       struct regmap *regmap;
 };
 
-static int wm8940_volatile_register(struct snd_soc_codec *codec,
-                                   unsigned int reg)
+static bool wm8940_volatile_register(struct device *dev, unsigned int reg)
 {
        switch (reg) {
        case WM8940_SOFTRESET:
-               return 1;
+               return true;
        default:
-               return 0;
+               return false;
+       }
+}
+
+static bool wm8940_readable_register(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case WM8940_SOFTRESET:
+       case WM8940_POWER1:
+       case WM8940_POWER2:
+       case WM8940_POWER3:
+       case WM8940_IFACE:
+       case WM8940_COMPANDINGCTL:
+       case WM8940_CLOCK:
+       case WM8940_ADDCNTRL:
+       case WM8940_GPIO:
+       case WM8940_CTLINT:
+       case WM8940_DAC:
+       case WM8940_DACVOL:
+       case WM8940_ADC:
+       case WM8940_ADCVOL:
+       case WM8940_NOTCH1:
+       case WM8940_NOTCH2:
+       case WM8940_NOTCH3:
+       case WM8940_NOTCH4:
+       case WM8940_NOTCH5:
+       case WM8940_NOTCH6:
+       case WM8940_NOTCH7:
+       case WM8940_NOTCH8:
+       case WM8940_DACLIM1:
+       case WM8940_DACLIM2:
+       case WM8940_ALC1:
+       case WM8940_ALC2:
+       case WM8940_ALC3:
+       case WM8940_NOISEGATE:
+       case WM8940_PLLN:
+       case WM8940_PLLK1:
+       case WM8940_PLLK2:
+       case WM8940_PLLK3:
+       case WM8940_ALC4:
+       case WM8940_INPUTCTL:
+       case WM8940_PGAGAIN:
+       case WM8940_ADCBOOST:
+       case WM8940_OUTPUTCTL:
+       case WM8940_SPKMIX:
+       case WM8940_SPKVOL:
+       case WM8940_MONOMIX:
+               return true;
+       default:
+               return false;
        }
 }
 
-static u16 wm8940_reg_defaults[] = {
-       0x8940, /* Soft Reset */
-       0x0000, /* Power 1 */
-       0x0000, /* Power 2 */
-       0x0000, /* Power 3 */
-       0x0010, /* Interface Control */
-       0x0000, /* Companding Control */
-       0x0140, /* Clock Control */
-       0x0000, /* Additional Controls */
-       0x0000, /* GPIO Control */
-       0x0002, /* Auto Increment Control */
-       0x0000, /* DAC Control */
-       0x00FF, /* DAC Volume */
-       0,
-       0,
-       0x0100, /* ADC Control */
-       0x00FF, /* ADC Volume */
-       0x0000, /* Notch Filter 1 Control 1 */
-       0x0000, /* Notch Filter 1 Control 2 */
-       0x0000, /* Notch Filter 2 Control 1 */
-       0x0000, /* Notch Filter 2 Control 2 */
-       0x0000, /* Notch Filter 3 Control 1 */
-       0x0000, /* Notch Filter 3 Control 2 */
-       0x0000, /* Notch Filter 4 Control 1 */
-       0x0000, /* Notch Filter 4 Control 2 */
-       0x0032, /* DAC Limit Control 1 */
-       0x0000, /* DAC Limit Control 2 */
-       0,
-       0,
-       0,
-       0,
-       0,
-       0,
-       0x0038, /* ALC Control 1 */
-       0x000B, /* ALC Control 2 */
-       0x0032, /* ALC Control 3 */
-       0x0000, /* Noise Gate */
-       0x0041, /* PLLN */
-       0x000C, /* PLLK1 */
-       0x0093, /* PLLK2 */
-       0x00E9, /* PLLK3 */
-       0,
-       0,
-       0x0030, /* ALC Control 4 */
-       0,
-       0x0002, /* Input Control */
-       0x0050, /* PGA Gain */
-       0,
-       0x0002, /* ADC Boost Control */
-       0,
-       0x0002, /* Output Control */
-       0x0000, /* Speaker Mixer Control */
-       0,
-       0,
-       0,
-       0x0079, /* Speaker Volume */
-       0,
-       0x0000, /* Mono Mixer Control */
+static const struct reg_default wm8940_reg_defaults[] = {
+       {  0x1, 0x0000 }, /* Power 1 */
+       {  0x2, 0x0000 }, /* Power 2 */
+       {  0x3, 0x0000 }, /* Power 3 */
+       {  0x4, 0x0010 }, /* Interface Control */
+       {  0x5, 0x0000 }, /* Companding Control */
+       {  0x6, 0x0140 }, /* Clock Control */
+       {  0x7, 0x0000 }, /* Additional Controls */
+       {  0x8, 0x0000 }, /* GPIO Control */
+       {  0x9, 0x0002 }, /* Auto Increment Control */
+       {  0xa, 0x0000 }, /* DAC Control */
+       {  0xb, 0x00FF }, /* DAC Volume */
+
+       {  0xe, 0x0100 }, /* ADC Control */
+       {  0xf, 0x00FF }, /* ADC Volume */
+       { 0x10, 0x0000 }, /* Notch Filter 1 Control 1 */
+       { 0x11, 0x0000 }, /* Notch Filter 1 Control 2 */
+       { 0x12, 0x0000 }, /* Notch Filter 2 Control 1 */
+       { 0x13, 0x0000 }, /* Notch Filter 2 Control 2 */
+       { 0x14, 0x0000 }, /* Notch Filter 3 Control 1 */
+       { 0x15, 0x0000 }, /* Notch Filter 3 Control 2 */
+       { 0x16, 0x0000 }, /* Notch Filter 4 Control 1 */
+       { 0x17, 0x0000 }, /* Notch Filter 4 Control 2 */
+       { 0x18, 0x0032 }, /* DAC Limit Control 1 */
+       { 0x19, 0x0000 }, /* DAC Limit Control 2 */
+
+       { 0x20, 0x0038 }, /* ALC Control 1 */
+       { 0x21, 0x000B }, /* ALC Control 2 */
+       { 0x22, 0x0032 }, /* ALC Control 3 */
+       { 0x23, 0x0000 }, /* Noise Gate */
+       { 0x24, 0x0041 }, /* PLLN */
+       { 0x25, 0x000C }, /* PLLK1 */
+       { 0x26, 0x0093 }, /* PLLK2 */
+       { 0x27, 0x00E9 }, /* PLLK3 */
+
+       { 0x2a, 0x0030 }, /* ALC Control 4 */
+
+       { 0x2c, 0x0002 }, /* Input Control */
+       { 0x2d, 0x0050 }, /* PGA Gain */
+
+       { 0x2f, 0x0002 }, /* ADC Boost Control */
+
+       { 0x31, 0x0002 }, /* Output Control */
+       { 0x32, 0x0000 }, /* Speaker Mixer Control */
+
+       { 0x36, 0x0079 }, /* Speaker Volume */
+
+       { 0x38, 0x0000 }, /* Mono Mixer Control */
 };
 
 static const char *wm8940_companding[] = { "Off", "NC", "u-law", "A-law" };
@@ -264,7 +302,7 @@ static const struct snd_soc_dapm_widget wm8940_dapm_widgets[] = {
        SND_SOC_DAPM_INPUT("AUX"),
 };
 
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8940_dapm_routes[] = {
        /* Mono output mixer */
        {"Mono Mixer", "PCM Playback Switch", "DAC"},
        {"Mono Mixer", "Aux Playback Switch", "Aux Input"},
@@ -296,21 +334,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"ADC", NULL, "Boost Mixer"},
 };
 
-static int wm8940_add_widgets(struct snd_soc_codec *codec)
-{
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
-       int ret;
-
-       ret = snd_soc_dapm_new_controls(dapm, wm8940_dapm_widgets,
-                                       ARRAY_SIZE(wm8940_dapm_widgets));
-       if (ret)
-               goto error_ret;
-       ret = snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
-error_ret:
-       return ret;
-}
-
 #define wm8940_reset(c) snd_soc_write(c, WM8940_SOFTRESET, 0);
 
 static int wm8940_set_dai_fmt(struct snd_soc_dai *codec_dai,
@@ -446,6 +469,7 @@ static int wm8940_mute(struct snd_soc_dai *dai, int mute)
 static int wm8940_set_bias_level(struct snd_soc_codec *codec,
                                 enum snd_soc_bias_level level)
 {
+       struct wm8940_priv *wm8940 = snd_soc_codec_get_drvdata(codec);
        u16 val;
        u16 pwr_reg = snd_soc_read(codec, WM8940_POWER1) & 0x1F0;
        int ret = 0;
@@ -469,7 +493,7 @@ static int wm8940_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(wm8940->regmap);
                        if (ret < 0) {
                                dev_err(codec->dev, "Failed to sync cache: %d\n", ret);
                                return ret;
@@ -684,12 +708,11 @@ static int wm8940_resume(struct snd_soc_codec *codec)
 
 static int wm8940_probe(struct snd_soc_codec *codec)
 {
-       struct wm8940_priv *wm8940 = snd_soc_codec_get_drvdata(codec);
        struct wm8940_setup_data *pdata = codec->dev->platform_data;
        int ret;
        u16 reg;
 
-       ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8940->control_type);
+       ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
                return ret;
@@ -716,11 +739,6 @@ static int wm8940_probe(struct snd_soc_codec *codec)
                        return ret;
        }
 
-       ret = snd_soc_add_codec_controls(codec, wm8940_snd_controls,
-                            ARRAY_SIZE(wm8940_snd_controls));
-       if (ret)
-               return ret;
-       ret = wm8940_add_widgets(codec);
        return ret;
 }
 
@@ -736,10 +754,24 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8940 = {
        .suspend =      wm8940_suspend,
        .resume =       wm8940_resume,
        .set_bias_level = wm8940_set_bias_level,
-       .reg_cache_size = ARRAY_SIZE(wm8940_reg_defaults),
-       .reg_word_size = sizeof(u16),
-       .reg_cache_default = wm8940_reg_defaults,
-       .volatile_register = wm8940_volatile_register,
+       .controls =     wm8940_snd_controls,
+       .num_controls = ARRAY_SIZE(wm8940_snd_controls),
+       .dapm_widgets = wm8940_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(wm8940_dapm_widgets),
+       .dapm_routes =  wm8940_dapm_routes,
+       .num_dapm_routes = ARRAY_SIZE(wm8940_dapm_routes),
+};
+
+static const struct regmap_config wm8940_regmap = {
+       .reg_bits = 8,
+       .val_bits = 16,
+
+       .max_register = WM8940_MONOMIX,
+       .reg_defaults = wm8940_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(wm8940_reg_defaults),
+
+       .readable_reg = wm8940_readable_register,
+       .volatile_reg = wm8940_volatile_register,
 };
 
 static int wm8940_i2c_probe(struct i2c_client *i2c,
@@ -753,8 +785,11 @@ static int wm8940_i2c_probe(struct i2c_client *i2c,
        if (wm8940 == NULL)
                return -ENOMEM;
 
+       wm8940->regmap = devm_regmap_init_i2c(i2c, &wm8940_regmap);
+       if (IS_ERR(wm8940->regmap))
+               return PTR_ERR(wm8940->regmap);
+
        i2c_set_clientdata(i2c, wm8940);
-       wm8940->control_type = SND_SOC_I2C;
 
        ret = snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_wm8940, &wm8940_dai, 1);
index 543c5c2631b61827bcebca8af1926ea02b5655e9..97db3b45b4113ad5fe7f7d42dd0e4e018b8c8c51 100644 (file)
@@ -74,7 +74,7 @@ struct wm8962_priv {
        struct regulator_bulk_data supplies[WM8962_NUM_SUPPLIES];
        struct notifier_block disable_nb[WM8962_NUM_SUPPLIES];
 
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+#if IS_ENABLED(CONFIG_INPUT)
        struct input_dev *beep;
        struct work_struct beep_work;
        int beep_rate;
@@ -2439,7 +2439,20 @@ static void wm8962_configure_bclk(struct snd_soc_codec *codec)
        snd_soc_update_bits(codec, WM8962_CLOCKING_4,
                            WM8962_SYSCLK_RATE_MASK, clocking4);
 
+       /* DSPCLK_DIV can be only generated correctly after enabling SYSCLK.
+        * So we here provisionally enable it and then disable it afterward
+        * if current bias_level hasn't reached SND_SOC_BIAS_ON.
+        */
+       if (codec->dapm.bias_level != SND_SOC_BIAS_ON)
+               snd_soc_update_bits(codec, WM8962_CLOCKING2,
+                               WM8962_SYSCLK_ENA_MASK, WM8962_SYSCLK_ENA);
+
        dspclk = snd_soc_read(codec, WM8962_CLOCKING1);
+
+       if (codec->dapm.bias_level != SND_SOC_BIAS_ON)
+               snd_soc_update_bits(codec, WM8962_CLOCKING2,
+                               WM8962_SYSCLK_ENA_MASK, 0);
+
        if (dspclk < 0) {
                dev_err(codec->dev, "Failed to read DSPCLK: %d\n", dspclk);
                return;
@@ -3108,7 +3121,7 @@ int wm8962_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
 }
 EXPORT_SYMBOL_GPL(wm8962_mic_detect);
 
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+#if IS_ENABLED(CONFIG_INPUT)
 static int beep_rates[] = {
        500, 1000, 2000, 4000,
 };
index a2d01d10a5dd8866747b335a027ed3049c9c71d3..15f45c7bd8334971bb63235ade92a26cb82c2f57 100644 (file)
@@ -17,6 +17,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>
 
 #include "wm8974.h"
 
-static const u16 wm8974_reg[WM8974_CACHEREGNUM] = {
-       0x0000, 0x0000, 0x0000, 0x0000,
-       0x0050, 0x0000, 0x0140, 0x0000,
-       0x0000, 0x0000, 0x0000, 0x00ff,
-       0x0000, 0x0000, 0x0100, 0x00ff,
-       0x0000, 0x0000, 0x012c, 0x002c,
-       0x002c, 0x002c, 0x002c, 0x0000,
-       0x0032, 0x0000, 0x0000, 0x0000,
-       0x0000, 0x0000, 0x0000, 0x0000,
-       0x0038, 0x000b, 0x0032, 0x0000,
-       0x0008, 0x000c, 0x0093, 0x00e9,
-       0x0000, 0x0000, 0x0000, 0x0000,
-       0x0003, 0x0010, 0x0000, 0x0000,
-       0x0000, 0x0002, 0x0000, 0x0000,
-       0x0000, 0x0000, 0x0039, 0x0000,
-       0x0000,
+static const struct reg_default wm8974_reg_defaults[] = {
+       {  0, 0x0000 }, {  1, 0x0000 }, {  2, 0x0000 }, {  3, 0x0000 },
+       {  4, 0x0050 }, {  5, 0x0000 }, {  6, 0x0140 }, {  7, 0x0000 },
+       {  8, 0x0000 }, {  9, 0x0000 }, { 10, 0x0000 }, { 11, 0x00ff },
+       { 12, 0x0000 }, { 13, 0x0000 }, { 14, 0x0100 }, { 15, 0x00ff },
+       { 16, 0x0000 }, { 17, 0x0000 }, { 18, 0x012c }, { 19, 0x002c },
+       { 20, 0x002c }, { 21, 0x002c }, { 22, 0x002c }, { 23, 0x0000 },
+       { 24, 0x0032 }, { 25, 0x0000 }, { 26, 0x0000 }, { 27, 0x0000 },
+       { 28, 0x0000 }, { 29, 0x0000 }, { 30, 0x0000 }, { 31, 0x0000 },
+       { 32, 0x0038 }, { 33, 0x000b }, { 34, 0x0032 }, { 35, 0x0000 },
+       { 36, 0x0008 }, { 37, 0x000c }, { 38, 0x0093 }, { 39, 0x00e9 },
+       { 40, 0x0000 }, { 41, 0x0000 }, { 42, 0x0000 }, { 43, 0x0000 },
+       { 44, 0x0003 }, { 45, 0x0010 }, { 46, 0x0000 }, { 47, 0x0000 },
+       { 48, 0x0000 }, { 49, 0x0002 }, { 50, 0x0000 }, { 51, 0x0000 },
+       { 52, 0x0000 }, { 53, 0x0000 }, { 54, 0x0039 }, { 55, 0x0000 },
+       { 56, 0x0000 },
 };
 
 #define WM8974_POWER1_BIASEN  0x08
@@ -514,7 +515,7 @@ static int wm8974_set_bias_level(struct snd_soc_codec *codec,
                power1 |= WM8974_POWER1_BIASEN | WM8974_POWER1_BUFIOEN;
 
                if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
-                       snd_soc_cache_sync(codec);
+                       regcache_sync(dev_get_regmap(codec->dev, NULL));
 
                        /* Initial cap charge at VMID 5k */
                        snd_soc_write(codec, WM8974_POWER1, power1 | 0x3);
@@ -579,11 +580,20 @@ static int wm8974_resume(struct snd_soc_codec *codec)
        return 0;
 }
 
+static const struct regmap_config wm8974_regmap = {
+       .reg_bits = 7,
+       .val_bits = 9,
+
+       .max_register = WM8974_MONOMIX,
+       .reg_defaults = wm8974_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(wm8974_reg_defaults),
+};
+
 static int wm8974_probe(struct snd_soc_codec *codec)
 {
        int ret = 0;
 
-       ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C);
+       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;
@@ -613,9 +623,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8974 = {
        .suspend =      wm8974_suspend,
        .resume =       wm8974_resume,
        .set_bias_level = wm8974_set_bias_level,
-       .reg_cache_size = ARRAY_SIZE(wm8974_reg),
-       .reg_word_size = sizeof(u16),
-       .reg_cache_default = wm8974_reg,
 
        .controls = wm8974_snd_controls,
        .num_controls = ARRAY_SIZE(wm8974_snd_controls),
@@ -628,8 +635,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8974 = {
 static int wm8974_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
+       struct regmap *regmap;
        int ret;
 
+       regmap = devm_regmap_init_i2c(i2c, &wm8974_regmap);
+       if (IS_ERR(regmap))
+               return PTR_ERR(regmap);
+
        ret = snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_wm8974, &wm8974_dai, 1);
 
index 18f2babe1090bf0ee061cf169c5f0f8e867dafd3..271b517911a4bc0d4d6003356afcf7a1cc317bed 100644 (file)
@@ -1148,7 +1148,7 @@ static struct spi_driver wm8985_spi_driver = {
 };
 #endif
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static int wm8985_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
@@ -1201,7 +1201,7 @@ static int __init wm8985_modinit(void)
 {
        int ret = 0;
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&wm8985_i2c_driver);
        if (ret) {
                printk(KERN_ERR "Failed to register wm8985 I2C driver: %d\n",
@@ -1221,7 +1221,7 @@ module_init(wm8985_modinit);
 
 static void __exit wm8985_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&wm8985_i2c_driver);
 #endif
 #if defined(CONFIG_SPI_MASTER)
index 39b9acceb595185d60821270073d9e5895305baa..a55e1c2c382edde43985e2213f0502564bf8e17b 100644 (file)
@@ -912,7 +912,7 @@ static struct spi_driver wm8988_spi_driver = {
 };
 #endif /* CONFIG_SPI_MASTER */
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static int wm8988_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
@@ -964,7 +964,7 @@ static struct i2c_driver wm8988_i2c_driver = {
 static int __init wm8988_modinit(void)
 {
        int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&wm8988_i2c_driver);
        if (ret != 0) {
                printk(KERN_ERR "Failed to register WM8988 I2C driver: %d\n",
@@ -984,7 +984,7 @@ module_init(wm8988_modinit);
 
 static void __exit wm8988_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&wm8988_i2c_driver);
 #endif
 #if defined(CONFIG_SPI_MASTER)
index 253c88bb7a4cbdb06d3d1df2862f10e80095aaa8..0ccd4d8d043bbcf0d0f689bc947c93545d88b16b 100644 (file)
@@ -17,6 +17,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>
 
 /* codec private data */
 struct wm8990_priv {
-       enum snd_soc_control_type control_type;
+       struct regmap *regmap;
        unsigned int sysclk;
        unsigned int pcmclk;
 };
 
-static int wm8990_volatile_register(struct snd_soc_codec *codec,
-                                   unsigned int reg)
+static bool wm8990_volatile_register(struct device *dev, unsigned int reg)
 {
        switch (reg) {
        case WM8990_RESET:
@@ -46,71 +46,69 @@ static int wm8990_volatile_register(struct snd_soc_codec *codec,
        }
 }
 
-static const u16 wm8990_reg[] = {
-       0x8990,     /* R0  - Reset */
-       0x0000,     /* R1  - Power Management (1) */
-       0x6000,     /* R2  - Power Management (2) */
-       0x0000,     /* R3  - Power Management (3) */
-       0x4050,     /* R4  - Audio Interface (1) */
-       0x4000,     /* R5  - Audio Interface (2) */
-       0x01C8,     /* R6  - Clocking (1) */
-       0x0000,     /* R7  - Clocking (2) */
-       0x0040,     /* R8  - Audio Interface (3) */
-       0x0040,     /* R9  - Audio Interface (4) */
-       0x0004,     /* R10 - DAC CTRL */
-       0x00C0,     /* R11 - Left DAC Digital Volume */
-       0x00C0,     /* R12 - Right DAC Digital Volume */
-       0x0000,     /* R13 - Digital Side Tone */
-       0x0100,     /* R14 - ADC CTRL */
-       0x00C0,     /* R15 - Left ADC Digital Volume */
-       0x00C0,     /* R16 - Right ADC Digital Volume */
-       0x0000,     /* R17 */
-       0x0000,     /* R18 - GPIO CTRL 1 */
-       0x1000,     /* R19 - GPIO1 & GPIO2 */
-       0x1010,     /* R20 - GPIO3 & GPIO4 */
-       0x1010,     /* R21 - GPIO5 & GPIO6 */
-       0x8000,     /* R22 - GPIOCTRL 2 */
-       0x0800,     /* R23 - GPIO_POL */
-       0x008B,     /* R24 - Left Line Input 1&2 Volume */
-       0x008B,     /* R25 - Left Line Input 3&4 Volume */
-       0x008B,     /* R26 - Right Line Input 1&2 Volume */
-       0x008B,     /* R27 - Right Line Input 3&4 Volume */
-       0x0000,     /* R28 - Left Output Volume */
-       0x0000,     /* R29 - Right Output Volume */
-       0x0066,     /* R30 - Line Outputs Volume */
-       0x0022,     /* R31 - Out3/4 Volume */
-       0x0079,     /* R32 - Left OPGA Volume */
-       0x0079,     /* R33 - Right OPGA Volume */
-       0x0003,     /* R34 - Speaker Volume */
-       0x0003,     /* R35 - ClassD1 */
-       0x0000,     /* R36 */
-       0x0100,     /* R37 - ClassD3 */
-       0x0079,     /* R38 - ClassD4 */
-       0x0000,     /* R39 - Input Mixer1 */
-       0x0000,     /* R40 - Input Mixer2 */
-       0x0000,     /* R41 - Input Mixer3 */
-       0x0000,     /* R42 - Input Mixer4 */
-       0x0000,     /* R43 - Input Mixer5 */
-       0x0000,     /* R44 - Input Mixer6 */
-       0x0000,     /* R45 - Output Mixer1 */
-       0x0000,     /* R46 - Output Mixer2 */
-       0x0000,     /* R47 - Output Mixer3 */
-       0x0000,     /* R48 - Output Mixer4 */
-       0x0000,     /* R49 - Output Mixer5 */
-       0x0000,     /* R50 - Output Mixer6 */
-       0x0180,     /* R51 - Out3/4 Mixer */
-       0x0000,     /* R52 - Line Mixer1 */
-       0x0000,     /* R53 - Line Mixer2 */
-       0x0000,     /* R54 - Speaker Mixer */
-       0x0000,     /* R55 - Additional Control */
-       0x0000,     /* R56 - AntiPOP1 */
-       0x0000,     /* R57 - AntiPOP2 */
-       0x0000,     /* R58 - MICBIAS */
-       0x0000,     /* R59 */
-       0x0008,     /* R60 - PLL1 */
-       0x0031,     /* R61 - PLL2 */
-       0x0026,     /* R62 - PLL3 */
-       0x0000,     /* R63 - Driver internal */
+static const struct reg_default wm8990_reg_defaults[] = {
+       {  1, 0x0000 },     /* R1  - Power Management (1) */
+       {  2, 0x6000 },     /* R2  - Power Management (2) */
+       {  3, 0x0000 },     /* R3  - Power Management (3) */
+       {  4, 0x4050 },     /* R4  - Audio Interface (1) */
+       {  5, 0x4000 },     /* R5  - Audio Interface (2) */
+       {  6, 0x01C8 },     /* R6  - Clocking (1) */
+       {  7, 0x0000 },     /* R7  - Clocking (2) */
+       {  8, 0x0040 },     /* R8  - Audio Interface (3) */
+       {  9, 0x0040 },     /* R9  - Audio Interface (4) */
+       { 10, 0x0004 },     /* R10 - DAC CTRL */
+       { 11, 0x00C0 },     /* R11 - Left DAC Digital Volume */
+       { 12, 0x00C0 },     /* R12 - Right DAC Digital Volume */
+       { 13, 0x0000 },     /* R13 - Digital Side Tone */
+       { 14, 0x0100 },     /* R14 - ADC CTRL */
+       { 15, 0x00C0 },     /* R15 - Left ADC Digital Volume */
+       { 16, 0x00C0 },     /* R16 - Right ADC Digital Volume */
+
+       { 18, 0x0000 },     /* R18 - GPIO CTRL 1 */
+       { 19, 0x1000 },     /* R19 - GPIO1 & GPIO2 */
+       { 20, 0x1010 },     /* R20 - GPIO3 & GPIO4 */
+       { 21, 0x1010 },     /* R21 - GPIO5 & GPIO6 */
+       { 22, 0x8000 },     /* R22 - GPIOCTRL 2 */
+       { 23, 0x0800 },     /* R23 - GPIO_POL */
+       { 24, 0x008B },     /* R24 - Left Line Input 1&2 Volume */
+       { 25, 0x008B },     /* R25 - Left Line Input 3&4 Volume */
+       { 26, 0x008B },     /* R26 - Right Line Input 1&2 Volume */
+       { 27, 0x008B },     /* R27 - Right Line Input 3&4 Volume */
+       { 28, 0x0000 },     /* R28 - Left Output Volume */
+       { 29, 0x0000 },     /* R29 - Right Output Volume */
+       { 30, 0x0066 },     /* R30 - Line Outputs Volume */
+       { 31, 0x0022 },     /* R31 - Out3/4 Volume */
+       { 32, 0x0079 },     /* R32 - Left OPGA Volume */
+       { 33, 0x0079 },     /* R33 - Right OPGA Volume */
+       { 34, 0x0003 },     /* R34 - Speaker Volume */
+       { 35, 0x0003 },     /* R35 - ClassD1 */
+
+       { 37, 0x0100 },     /* R37 - ClassD3 */
+       { 38, 0x0079 },     /* R38 - ClassD4 */
+       { 39, 0x0000 },     /* R39 - Input Mixer1 */
+       { 40, 0x0000 },     /* R40 - Input Mixer2 */
+       { 41, 0x0000 },     /* R41 - Input Mixer3 */
+       { 42, 0x0000 },     /* R42 - Input Mixer4 */
+       { 43, 0x0000 },     /* R43 - Input Mixer5 */
+       { 44, 0x0000 },     /* R44 - Input Mixer6 */
+       { 45, 0x0000 },     /* R45 - Output Mixer1 */
+       { 46, 0x0000 },     /* R46 - Output Mixer2 */
+       { 47, 0x0000 },     /* R47 - Output Mixer3 */
+       { 48, 0x0000 },     /* R48 - Output Mixer4 */
+       { 49, 0x0000 },     /* R49 - Output Mixer5 */
+       { 50, 0x0000 },     /* R50 - Output Mixer6 */
+       { 51, 0x0180 },     /* R51 - Out3/4 Mixer */
+       { 52, 0x0000 },     /* R52 - Line Mixer1 */
+       { 53, 0x0000 },     /* R53 - Line Mixer2 */
+       { 54, 0x0000 },     /* R54 - Speaker Mixer */
+       { 55, 0x0000 },     /* R55 - Additional Control */
+       { 56, 0x0000 },     /* R56 - AntiPOP1 */
+       { 57, 0x0000 },     /* R57 - AntiPOP2 */
+       { 58, 0x0000 },     /* R58 - MICBIAS */
+
+       { 60, 0x0008 },     /* R60 - PLL1 */
+       { 61, 0x0031 },     /* R61 - PLL2 */
+       { 62, 0x0026 },     /* R62 - PLL3 */
 };
 
 #define wm8990_reset(c) snd_soc_write(c, WM8990_RESET, 0)
@@ -376,32 +374,6 @@ SOC_SINGLE("RIN34 Mute Switch", WM8990_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, WM8990_POWER_MANAGEMENT_2);
-       fakepower = snd_soc_read(w->codec, WM8990_INTDRIVBITS);
-
-       if (fakepower & ((1 << WM8990_INMIXL_PWR_BIT) |
-               (1 << WM8990_AINLMUX_PWR_BIT))) {
-               reg |= WM8990_AINL_ENA;
-       } else {
-               reg &= ~WM8990_AINL_ENA;
-       }
-
-       if (fakepower & ((1 << WM8990_INMIXR_PWR_BIT) |
-               (1 << WM8990_AINRMUX_PWR_BIT))) {
-               reg |= WM8990_AINR_ENA;
-       } else {
-               reg &= ~WM8990_AINR_ENA;
-       }
-       snd_soc_write(w->codec, WM8990_POWER_MANAGEMENT_2, reg);
-
-       return 0;
-}
-
 static int outmixer_event(struct snd_soc_dapm_widget *w,
        struct snd_kcontrol *kcontrol, int event)
 {
@@ -656,6 +628,11 @@ SND_SOC_DAPM_INPUT("RIN1"),
 SND_SOC_DAPM_INPUT("RIN2"),
 SND_SOC_DAPM_INPUT("Internal ADC Source"),
 
+SND_SOC_DAPM_SUPPLY("INL", WM8990_POWER_MANAGEMENT_2, WM8990_AINL_ENA_BIT, 0,
+                   NULL, 0),
+SND_SOC_DAPM_SUPPLY("INR", WM8990_POWER_MANAGEMENT_2, WM8990_AINR_ENA_BIT, 0,
+                   NULL, 0),
+
 /* DACs */
 SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8990_POWER_MANAGEMENT_2,
        WM8990_ADCL_ENA_BIT, 0),
@@ -677,26 +654,20 @@ SND_SOC_DAPM_MIXER("RIN34 PGA", WM8990_POWER_MANAGEMENT_2, WM8990_RIN34_ENA_BIT,
        ARRAY_SIZE(wm8990_dapm_rin34_pga_controls)),
 
 /* INMIXL */
-SND_SOC_DAPM_MIXER_E("INMIXL", WM8990_INTDRIVBITS, WM8990_INMIXL_PWR_BIT, 0,
+SND_SOC_DAPM_MIXER("INMIXL", SND_SOC_NOPM, 0, 0,
        &wm8990_dapm_inmixl_controls[0],
-       ARRAY_SIZE(wm8990_dapm_inmixl_controls),
-       inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+       ARRAY_SIZE(wm8990_dapm_inmixl_controls)),
 
 /* AINLMUX */
-SND_SOC_DAPM_MUX_E("AINLMUX", WM8990_INTDRIVBITS, WM8990_AINLMUX_PWR_BIT, 0,
-       &wm8990_dapm_ainlmux_controls, inmixer_event,
-       SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+SND_SOC_DAPM_MUX("AINLMUX", SND_SOC_NOPM, 0, 0, &wm8990_dapm_ainlmux_controls),
 
 /* INMIXR */
-SND_SOC_DAPM_MIXER_E("INMIXR", WM8990_INTDRIVBITS, WM8990_INMIXR_PWR_BIT, 0,
+SND_SOC_DAPM_MIXER("INMIXR", SND_SOC_NOPM, 0, 0,
        &wm8990_dapm_inmixr_controls[0],
-       ARRAY_SIZE(wm8990_dapm_inmixr_controls),
-       inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+       ARRAY_SIZE(wm8990_dapm_inmixr_controls)),
 
 /* AINRMUX */
-SND_SOC_DAPM_MUX_E("AINRMUX", WM8990_INTDRIVBITS, WM8990_AINRMUX_PWR_BIT, 0,
-       &wm8990_dapm_ainrmux_controls, inmixer_event,
-       SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+SND_SOC_DAPM_MUX("AINRMUX", SND_SOC_NOPM, 0, 0, &wm8990_dapm_ainrmux_controls),
 
 /* Output Side */
 /* DACs */
@@ -787,7 +758,7 @@ SND_SOC_DAPM_OUTPUT("RON"),
 SND_SOC_DAPM_OUTPUT("Internal DAC Sink"),
 };
 
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8990_dapm_routes[] = {
        /* Make DACs turn on when playing even if not mixed into any outputs */
        {"Internal DAC Sink", NULL, "Left DAC"},
        {"Internal DAC Sink", NULL, "Right DAC"},
@@ -796,6 +767,11 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"Left ADC", NULL, "Internal ADC Source"},
        {"Right ADC", NULL, "Internal ADC Source"},
 
+       {"AINLMUX", NULL, "INL"},
+       {"INMIXL", NULL, "INL"},
+       {"AINRMUX", NULL, "INR"},
+       {"INMIXR", NULL, "INR"},
+
        /* Input Side */
        /* LIN12 PGA */
        {"LIN12 PGA", "LIN1 Switch", "LIN1"},
@@ -912,18 +888,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"RON", NULL, "RONMIX"},
 };
 
-static int wm8990_add_widgets(struct snd_soc_codec *codec)
-{
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
-
-       snd_soc_dapm_new_controls(dapm, wm8990_dapm_widgets,
-                                 ARRAY_SIZE(wm8990_dapm_widgets));
-       /* set up the WM8990 audio map */
-       snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
-       return 0;
-}
-
 /* PLL divisors */
 struct _pll_div {
        u32 div2;
@@ -1148,6 +1112,7 @@ static int wm8990_mute(struct snd_soc_dai *dai, int mute)
 static int wm8990_set_bias_level(struct snd_soc_codec *codec,
        enum snd_soc_bias_level level)
 {
+       struct wm8990_priv *wm8990 = snd_soc_codec_get_drvdata(codec);
        int ret;
 
        switch (level) {
@@ -1162,7 +1127,7 @@ static int wm8990_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(wm8990->regmap);
                        if (ret < 0) {
                                dev_err(codec->dev, "Failed to sync cache: %d\n", ret);
                                return ret;
@@ -1259,6 +1224,8 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec,
 
                /* disable POBCTRL, SOFT_ST and BUFDCOPEN */
                snd_soc_write(codec, WM8990_ANTIPOP2, 0x0);
+
+               regcache_mark_dirty(wm8990->regmap);
                break;
        }
 
@@ -1327,7 +1294,7 @@ static int wm8990_probe(struct snd_soc_codec *codec)
 {
        int ret;
 
-       ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
+       ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
        if (ret < 0) {
                printk(KERN_ERR "wm8990: failed to set cache I/O: %d\n", ret);
                return ret;
@@ -1350,10 +1317,6 @@ static int wm8990_probe(struct snd_soc_codec *codec)
        snd_soc_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
        snd_soc_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
 
-       snd_soc_add_codec_controls(codec, wm8990_snd_controls,
-                               ARRAY_SIZE(wm8990_snd_controls));
-       wm8990_add_widgets(codec);
-
        return 0;
 }
 
@@ -1370,13 +1333,25 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8990 = {
        .suspend =      wm8990_suspend,
        .resume =       wm8990_resume,
        .set_bias_level = wm8990_set_bias_level,
-       .reg_cache_size = ARRAY_SIZE(wm8990_reg),
-       .reg_word_size = sizeof(u16),
-       .reg_cache_default = wm8990_reg,
-       .volatile_register = wm8990_volatile_register,
+       .controls =     wm8990_snd_controls,
+       .num_controls = ARRAY_SIZE(wm8990_snd_controls),
+       .dapm_widgets = wm8990_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(wm8990_dapm_widgets),
+       .dapm_routes =  wm8990_dapm_routes,
+       .num_dapm_routes = ARRAY_SIZE(wm8990_dapm_routes),
+};
+
+static const struct regmap_config wm8990_regmap = {
+       .reg_bits = 8,
+       .val_bits = 16,
+
+       .max_register = WM8990_PLL3,
+       .volatile_reg = wm8990_volatile_register,
+       .reg_defaults = wm8990_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(wm8990_reg_defaults),
+       .cache_type = REGCACHE_RBTREE,
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static int wm8990_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
@@ -1418,29 +1393,8 @@ static struct i2c_driver wm8990_i2c_driver = {
        .remove =   wm8990_i2c_remove,
        .id_table = wm8990_i2c_id,
 };
-#endif
 
-static int __init wm8990_modinit(void)
-{
-       int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-       ret = i2c_add_driver(&wm8990_i2c_driver);
-       if (ret != 0) {
-               printk(KERN_ERR "Failed to register wm8990 I2C driver: %d\n",
-                      ret);
-       }
-#endif
-       return ret;
-}
-module_init(wm8990_modinit);
-
-static void __exit wm8990_exit(void)
-{
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-       i2c_del_driver(&wm8990_i2c_driver);
-#endif
-}
-module_exit(wm8990_exit);
+module_i2c_driver(wm8990_i2c_driver);
 
 MODULE_DESCRIPTION("ASoC WM8990 driver");
 MODULE_AUTHOR("Liam Girdwood");
index 77c98a4bfe9cdf34876e30866e73046d50748c85..0e9c78040c4c5cbfd1c7c6d5cc9cf844e5d95333 100644 (file)
@@ -78,7 +78,6 @@
 #define WM8990_PLL1                             0x3C
 #define WM8990_PLL2                             0x3D
 #define WM8990_PLL3                             0x3E
-#define WM8990_INTDRIVBITS                     0x3F
 
 #define WM8990_EXT_ACCESS_ENA                  0x75
 #define WM8990_EXT_CTL1                                0x7a
  */
 #define WM8990_PLLK2_MASK                       0x00FF  /* PLLK2 - [7:0] */
 
-/*
- * R63 (0x3F) - Internal Driver Bits
- */
-#define WM8990_INMIXL_PWR_BIT                  0
-#define WM8990_AINLMUX_PWR_BIT                 1
-#define WM8990_INMIXR_PWR_BIT                  2
-#define WM8990_AINRMUX_PWR_BIT                 3
-
 #define WM8990_MCLK_DIV 0
 #define WM8990_DACCLK_DIV 1
 #define WM8990_ADCCLK_DIV 2
index 3a39df7a38295a36a28d7865405cb7c0096089d1..dba0306c42a5c54aa459cc4fe1593b08c92a5abf 100644 (file)
@@ -18,6 +18,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>
 #include "wm8991.h"
 
 struct wm8991_priv {
-       enum snd_soc_control_type control_type;
+       struct regmap *regmap;
        unsigned int pcmclk;
 };
 
-static const u16 wm8991_reg_defs[] = {
-       0x8991,     /* R0  - Reset */
-       0x0000,     /* R1  - Power Management (1) */
-       0x6000,     /* R2  - Power Management (2) */
-       0x0000,     /* R3  - Power Management (3) */
-       0x4050,     /* R4  - Audio Interface (1) */
-       0x4000,     /* R5  - Audio Interface (2) */
-       0x01C8,     /* R6  - Clocking (1) */
-       0x0000,     /* R7  - Clocking (2) */
-       0x0040,     /* R8  - Audio Interface (3) */
-       0x0040,     /* R9  - Audio Interface (4) */
-       0x0004,     /* R10 - DAC CTRL */
-       0x00C0,     /* R11 - Left DAC Digital Volume */
-       0x00C0,     /* R12 - Right DAC Digital Volume */
-       0x0000,     /* R13 - Digital Side Tone */
-       0x0100,     /* R14 - ADC CTRL */
-       0x00C0,     /* R15 - Left ADC Digital Volume */
-       0x00C0,     /* R16 - Right ADC Digital Volume */
-       0x0000,     /* R17 */
-       0x0000,     /* R18 - GPIO CTRL 1 */
-       0x1000,     /* R19 - GPIO1 & GPIO2 */
-       0x1010,     /* R20 - GPIO3 & GPIO4 */
-       0x1010,     /* R21 - GPIO5 & GPIO6 */
-       0x8000,     /* R22 - GPIOCTRL 2 */
-       0x0800,     /* R23 - GPIO_POL */
-       0x008B,     /* R24 - Left Line Input 1&2 Volume */
-       0x008B,     /* R25 - Left Line Input 3&4 Volume */
-       0x008B,     /* R26 - Right Line Input 1&2 Volume */
-       0x008B,     /* R27 - Right Line Input 3&4 Volume */
-       0x0000,     /* R28 - Left Output Volume */
-       0x0000,     /* R29 - Right Output Volume */
-       0x0066,     /* R30 - Line Outputs Volume */
-       0x0022,     /* R31 - Out3/4 Volume */
-       0x0079,     /* R32 - Left OPGA Volume */
-       0x0079,     /* R33 - Right OPGA Volume */
-       0x0003,     /* R34 - Speaker Volume */
-       0x0003,     /* R35 - ClassD1 */
-       0x0000,     /* R36 */
-       0x0100,     /* R37 - ClassD3 */
-       0x0000,     /* R38 */
-       0x0000,     /* R39 - Input Mixer1 */
-       0x0000,     /* R40 - Input Mixer2 */
-       0x0000,     /* R41 - Input Mixer3 */
-       0x0000,     /* R42 - Input Mixer4 */
-       0x0000,     /* R43 - Input Mixer5 */
-       0x0000,     /* R44 - Input Mixer6 */
-       0x0000,     /* R45 - Output Mixer1 */
-       0x0000,     /* R46 - Output Mixer2 */
-       0x0000,     /* R47 - Output Mixer3 */
-       0x0000,     /* R48 - Output Mixer4 */
-       0x0000,     /* R49 - Output Mixer5 */
-       0x0000,     /* R50 - Output Mixer6 */
-       0x0180,     /* R51 - Out3/4 Mixer */
-       0x0000,     /* R52 - Line Mixer1 */
-       0x0000,     /* R53 - Line Mixer2 */
-       0x0000,     /* R54 - Speaker Mixer */
-       0x0000,     /* R55 - Additional Control */
-       0x0000,     /* R56 - AntiPOP1 */
-       0x0000,     /* R57 - AntiPOP2 */
-       0x0000,     /* R58 - MICBIAS */
-       0x0000,     /* R59 */
-       0x0008,     /* R60 - PLL1 */
-       0x0031,     /* R61 - PLL2 */
-       0x0026,     /* R62 - PLL3 */
+static const struct reg_default wm8991_reg_defaults[] = {
+       {  1, 0x0000 },     /* R1  - Power Management (1) */
+       {  2, 0x6000 },     /* R2  - Power Management (2) */
+       {  3, 0x0000 },     /* R3  - Power Management (3) */
+       {  4, 0x4050 },     /* R4  - Audio Interface (1) */
+       {  5, 0x4000 },     /* R5  - Audio Interface (2) */
+       {  6, 0x01C8 },     /* R6  - Clocking (1) */
+       {  7, 0x0000 },     /* R7  - Clocking (2) */
+       {  8, 0x0040 },     /* R8  - Audio Interface (3) */
+       {  9, 0x0040 },     /* R9  - Audio Interface (4) */
+       { 10, 0x0004 },     /* R10 - DAC CTRL */
+       { 11, 0x00C0 },     /* R11 - Left DAC Digital Volume */
+       { 12, 0x00C0 },     /* R12 - Right DAC Digital Volume */
+       { 13, 0x0000 },     /* R13 - Digital Side Tone */
+       { 14, 0x0100 },     /* R14 - ADC CTRL */
+       { 15, 0x00C0 },     /* R15 - Left ADC Digital Volume */
+       { 16, 0x00C0 },     /* R16 - Right ADC Digital Volume */
+
+       { 18, 0x0000 },     /* R18 - GPIO CTRL 1 */
+       { 19, 0x1000 },     /* R19 - GPIO1 & GPIO2 */
+       { 20, 0x1010 },     /* R20 - GPIO3 & GPIO4 */
+       { 21, 0x1010 },     /* R21 - GPIO5 & GPIO6 */
+       { 22, 0x8000 },     /* R22 - GPIOCTRL 2 */
+       { 23, 0x0800 },     /* R23 - GPIO_POL */
+       { 24, 0x008B },     /* R24 - Left Line Input 1&2 Volume */
+       { 25, 0x008B },     /* R25 - Left Line Input 3&4 Volume */
+       { 26, 0x008B },     /* R26 - Right Line Input 1&2 Volume */
+       { 27, 0x008B },     /* R27 - Right Line Input 3&4 Volume */
+       { 28, 0x0000 },     /* R28 - Left Output Volume */
+       { 29, 0x0000 },     /* R29 - Right Output Volume */
+       { 30, 0x0066 },     /* R30 - Line Outputs Volume */
+       { 31, 0x0022 },     /* R31 - Out3/4 Volume */
+       { 32, 0x0079 },     /* R32 - Left OPGA Volume */
+       { 33, 0x0079 },     /* R33 - Right OPGA Volume */
+       { 34, 0x0003 },     /* R34 - Speaker Volume */
+       { 35, 0x0003 },     /* R35 - ClassD1 */
+
+       { 37, 0x0100 },     /* R37 - ClassD3 */
+
+       { 39, 0x0000 },     /* R39 - Input Mixer1 */
+       { 40, 0x0000 },     /* R40 - Input Mixer2 */
+       { 41, 0x0000 },     /* R41 - Input Mixer3 */
+       { 42, 0x0000 },     /* R42 - Input Mixer4 */
+       { 43, 0x0000 },     /* R43 - Input Mixer5 */
+       { 44, 0x0000 },     /* R44 - Input Mixer6 */
+       { 45, 0x0000 },     /* R45 - Output Mixer1 */
+       { 46, 0x0000 },     /* R46 - Output Mixer2 */
+       { 47, 0x0000 },     /* R47 - Output Mixer3 */
+       { 48, 0x0000 },     /* R48 - Output Mixer4 */
+       { 49, 0x0000 },     /* R49 - Output Mixer5 */
+       { 50, 0x0000 },     /* R50 - Output Mixer6 */
+       { 51, 0x0180 },     /* R51 - Out3/4 Mixer */
+       { 52, 0x0000 },     /* R52 - Line Mixer1 */
+       { 53, 0x0000 },     /* R53 - Line Mixer2 */
+       { 54, 0x0000 },     /* R54 - Speaker Mixer */
+       { 55, 0x0000 },     /* R55 - Additional Control */
+       { 56, 0x0000 },     /* R56 - AntiPOP1 */
+       { 57, 0x0000 },     /* R57 - AntiPOP2 */
+       { 58, 0x0000 },     /* R58 - MICBIAS */
+
+       { 60, 0x0008 },     /* R60 - PLL1 */
+       { 61, 0x0031 },     /* R61 - PLL2 */
+       { 62, 0x0026 },     /* R62 - PLL3 */
 };
 
-#define wm8991_reset(c) snd_soc_write(c, WM8991_RESET, 0)
+static bool wm8991_volatile(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case WM8991_RESET:
+               return true;
+       default:
+               return false;
+       }
+}
 
 static const unsigned int rec_mix_tlv[] = {
        TLV_DB_RANGE_HEAD(1),
@@ -374,30 +382,6 @@ static const struct snd_kcontrol_new wm8991_snd_controls[] = {
 /*
  * _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, WM8991_POWER_MANAGEMENT_2);
-       fakepower = snd_soc_read(w->codec, WM8991_INTDRIVBITS);
-
-       if (fakepower & ((1 << WM8991_INMIXL_PWR_BIT) |
-                        (1 << WM8991_AINLMUX_PWR_BIT)))
-               reg |= WM8991_AINL_ENA;
-       else
-               reg &= ~WM8991_AINL_ENA;
-
-       if (fakepower & ((1 << WM8991_INMIXR_PWR_BIT) |
-                        (1 << WM8991_AINRMUX_PWR_BIT)))
-               reg |= WM8991_AINR_ENA;
-       else
-               reg &= ~WM8991_AINR_ENA;
-
-       snd_soc_write(w->codec, WM8991_POWER_MANAGEMENT_2, reg);
-       return 0;
-}
-
 static int outmixer_event(struct snd_soc_dapm_widget *w,
                          struct snd_kcontrol *kcontrol, int event)
 {
@@ -655,6 +639,11 @@ static const struct snd_soc_dapm_widget wm8991_dapm_widgets[] = {
        SND_SOC_DAPM_INPUT("RIN2"),
        SND_SOC_DAPM_INPUT("Internal ADC Source"),
 
+       SND_SOC_DAPM_SUPPLY("INL", WM8991_POWER_MANAGEMENT_2,
+                           WM8991_AINL_ENA_BIT, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("INR", WM8991_POWER_MANAGEMENT_2,
+                           WM8991_AINR_ENA_BIT, 0, NULL, 0),
+
        /* DACs */
        SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8991_POWER_MANAGEMENT_2,
                WM8991_ADCL_ENA_BIT, 0),
@@ -676,26 +665,22 @@ static const struct snd_soc_dapm_widget wm8991_dapm_widgets[] = {
                ARRAY_SIZE(wm8991_dapm_rin34_pga_controls)),
 
        /* INMIXL */
-       SND_SOC_DAPM_MIXER_E("INMIXL", WM8991_INTDRIVBITS, WM8991_INMIXL_PWR_BIT, 0,
+       SND_SOC_DAPM_MIXER("INMIXL", SND_SOC_NOPM, 0, 0,
                &wm8991_dapm_inmixl_controls[0],
-               ARRAY_SIZE(wm8991_dapm_inmixl_controls),
-               inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+               ARRAY_SIZE(wm8991_dapm_inmixl_controls)),
 
        /* AINLMUX */
-       SND_SOC_DAPM_MUX_E("AINLMUX", WM8991_INTDRIVBITS, WM8991_AINLMUX_PWR_BIT, 0,
-               &wm8991_dapm_ainlmux_controls, inmixer_event,
-               SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+       SND_SOC_DAPM_MUX("AINLMUX", SND_SOC_NOPM, 0, 0,
+               &wm8991_dapm_ainlmux_controls),
 
        /* INMIXR */
-       SND_SOC_DAPM_MIXER_E("INMIXR", WM8991_INTDRIVBITS, WM8991_INMIXR_PWR_BIT, 0,
+       SND_SOC_DAPM_MIXER("INMIXR", SND_SOC_NOPM, 0, 0,
                &wm8991_dapm_inmixr_controls[0],
-               ARRAY_SIZE(wm8991_dapm_inmixr_controls),
-               inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+               ARRAY_SIZE(wm8991_dapm_inmixr_controls)),
 
        /* AINRMUX */
-       SND_SOC_DAPM_MUX_E("AINRMUX", WM8991_INTDRIVBITS, WM8991_AINRMUX_PWR_BIT, 0,
-               &wm8991_dapm_ainrmux_controls, inmixer_event,
-               SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+       SND_SOC_DAPM_MUX("AINRMUX", SND_SOC_NOPM, 0, 0,
+               &wm8991_dapm_ainrmux_controls),
 
        /* Output Side */
        /* DACs */
@@ -787,7 +772,7 @@ static const struct snd_soc_dapm_widget wm8991_dapm_widgets[] = {
        SND_SOC_DAPM_OUTPUT("Internal DAC Sink"),
 };
 
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8991_dapm_routes[] = {
        /* Make DACs turn on when playing even if not mixed into any outputs */
        {"Internal DAC Sink", NULL, "Left DAC"},
        {"Internal DAC Sink", NULL, "Right DAC"},
@@ -797,6 +782,10 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"Right ADC", NULL, "Internal ADC Source"},
 
        /* Input Side */
+       {"INMIXL", NULL, "INL"},
+       {"AINLMUX", NULL, "INL"},
+       {"INMIXR", NULL, "INR"},
+       {"AINRMUX", NULL, "INR"},
        /* LIN12 PGA */
        {"LIN12 PGA", "LIN1 Switch", "LIN1"},
        {"LIN12 PGA", "LIN2 Switch", "LIN2"},
@@ -1129,6 +1118,7 @@ static int wm8991_mute(struct snd_soc_dai *dai, int mute)
 static int wm8991_set_bias_level(struct snd_soc_codec *codec,
                                 enum snd_soc_bias_level level)
 {
+       struct wm8991_priv *wm8991 = snd_soc_codec_get_drvdata(codec);
        u16 val;
 
        switch (level) {
@@ -1144,7 +1134,7 @@ static int wm8991_set_bias_level(struct snd_soc_codec *codec,
 
        case SND_SOC_BIAS_STANDBY:
                if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
-                       snd_soc_cache_sync(codec);
+                       regcache_sync(wm8991->regmap);
                        /* Enable all output discharge bits */
                        snd_soc_write(codec, WM8991_ANTIPOP1, WM8991_DIS_LLINE |
                                      WM8991_DIS_RLINE | WM8991_DIS_OUT3 |
@@ -1232,7 +1222,7 @@ static int wm8991_set_bias_level(struct snd_soc_codec *codec,
 
                /* disable POBCTRL, SOFT_ST and BUFDCOPEN */
                snd_soc_write(codec, WM8991_ANTIPOP2, 0x0);
-               codec->cache_sync = 1;
+               regcache_mark_dirty(wm8991->regmap);
                break;
        }
 
@@ -1266,44 +1256,14 @@ static int wm8991_probe(struct snd_soc_codec *codec)
 
        wm8991 = snd_soc_codec_get_drvdata(codec);
 
-       ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8991->control_type);
+       ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret);
                return ret;
        }
 
-       ret = wm8991_reset(codec);
-       if (ret < 0) {
-               dev_err(codec->dev, "Failed to issue reset\n");
-               return ret;
-       }
-
        wm8991_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-       snd_soc_update_bits(codec, WM8991_AUDIO_INTERFACE_4,
-                           WM8991_ALRCGPIO1, WM8991_ALRCGPIO1);
-
-       snd_soc_update_bits(codec, WM8991_GPIO1_GPIO2,
-                           WM8991_GPIO1_SEL_MASK, 1);
-
-       snd_soc_update_bits(codec, WM8991_POWER_MANAGEMENT_1,
-                           WM8991_VREF_ENA | WM8991_VMID_MODE_MASK,
-                           WM8991_VREF_ENA | WM8991_VMID_MODE_MASK);
-
-       snd_soc_update_bits(codec, WM8991_POWER_MANAGEMENT_2,
-                           WM8991_OPCLK_ENA, WM8991_OPCLK_ENA);
-
-       snd_soc_write(codec, WM8991_DAC_CTRL, 0);
-       snd_soc_write(codec, WM8991_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
-       snd_soc_write(codec, WM8991_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
-
-       snd_soc_add_codec_controls(codec, wm8991_snd_controls,
-                            ARRAY_SIZE(wm8991_snd_controls));
-
-       snd_soc_dapm_new_controls(&codec->dapm, wm8991_dapm_widgets,
-                                 ARRAY_SIZE(wm8991_dapm_widgets));
-       snd_soc_dapm_add_routes(&codec->dapm, audio_map,
-                               ARRAY_SIZE(audio_map));
        return 0;
 }
 
@@ -1352,24 +1312,77 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8991 = {
        .suspend = wm8991_suspend,
        .resume = wm8991_resume,
        .set_bias_level = wm8991_set_bias_level,
-       .reg_cache_size = WM8991_MAX_REGISTER + 1,
-       .reg_word_size = sizeof(u16),
-       .reg_cache_default = wm8991_reg_defs
+       .controls = wm8991_snd_controls,
+       .num_controls = ARRAY_SIZE(wm8991_snd_controls),
+       .dapm_widgets = wm8991_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(wm8991_dapm_widgets),
+       .dapm_routes = wm8991_dapm_routes,
+       .num_dapm_routes = ARRAY_SIZE(wm8991_dapm_routes),
+};
+
+static const struct regmap_config wm8991_regmap = {
+       .reg_bits = 8,
+       .val_bits = 16,
+
+       .max_register = WM8991_PLL3,
+       .volatile_reg = wm8991_volatile,
+       .reg_defaults = wm8991_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(wm8991_reg_defaults),
+       .cache_type = REGCACHE_RBTREE,
 };
 
 static int wm8991_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
        struct wm8991_priv *wm8991;
+       unsigned int val;
        int ret;
 
        wm8991 = devm_kzalloc(&i2c->dev, sizeof(*wm8991), GFP_KERNEL);
        if (!wm8991)
                return -ENOMEM;
 
-       wm8991->control_type = SND_SOC_I2C;
+       wm8991->regmap = devm_regmap_init_i2c(i2c, &wm8991_regmap);
+       if (IS_ERR(wm8991->regmap))
+               return PTR_ERR(wm8991->regmap);
+
        i2c_set_clientdata(i2c, wm8991);
 
+       ret = regmap_read(wm8991->regmap, WM8991_RESET, &val);
+       if (ret != 0) {
+               dev_err(&i2c->dev, "Failed to read device ID: %d\n", ret);
+               return ret;
+       }
+       if (val != 0x8991) {
+               dev_err(&i2c->dev, "Device with ID %x is not a WM8991\n", val);
+               return -EINVAL;
+       }
+
+       ret = regmap_write(wm8991->regmap, WM8991_RESET, 0);
+       if (ret < 0) {
+               dev_err(&i2c->dev, "Failed to issue reset: %d\n", ret);
+               return ret;
+       }
+
+       regmap_update_bits(wm8991->regmap, WM8991_AUDIO_INTERFACE_4,
+                          WM8991_ALRCGPIO1, WM8991_ALRCGPIO1);
+
+       regmap_update_bits(wm8991->regmap, WM8991_GPIO1_GPIO2,
+                          WM8991_GPIO1_SEL_MASK, 1);
+
+       regmap_update_bits(wm8991->regmap, WM8991_POWER_MANAGEMENT_1,
+                          WM8991_VREF_ENA | WM8991_VMID_MODE_MASK,
+                          WM8991_VREF_ENA | WM8991_VMID_MODE_MASK);
+
+       regmap_update_bits(wm8991->regmap, WM8991_POWER_MANAGEMENT_2,
+                          WM8991_OPCLK_ENA, WM8991_OPCLK_ENA);
+
+       regmap_write(wm8991->regmap, WM8991_DAC_CTRL, 0);
+       regmap_write(wm8991->regmap, WM8991_LEFT_OUTPUT_VOLUME,
+                    0x50 | (1<<8));
+       regmap_write(wm8991->regmap, WM8991_RIGHT_OUTPUT_VOLUME,
+                    0x50 | (1<<8));
+
        ret = snd_soc_register_codec(&i2c->dev,
                                     &soc_codec_dev_wm8991, &wm8991_dai, 1);
 
index 07707d8d7e20e8ef2625f4986c3b24f70285bc5a..08ed383303c02b94e13d62a4fd4a2aa782bf969a 100644 (file)
@@ -76,7 +76,6 @@
 #define WM8991_PLL1                             0x3C
 #define WM8991_PLL2                             0x3D
 #define WM8991_PLL3                             0x3E
-#define WM8991_INTDRIVBITS                     0x3F
 
 #define WM8991_REGISTER_COUNT                   60
 #define WM8991_MAX_REGISTER                     0x3F
  */
 #define WM8991_PLLK2_MASK                       0x00FF  /* PLLK2 - [7:0] */
 
-/*
- * R63 (0x3F) - Internal Driver Bits
- */
-#define WM8991_INMIXL_PWR_BIT                  0
-#define WM8991_AINLMUX_PWR_BIT                 1
-#define WM8991_INMIXR_PWR_BIT                  2
-#define WM8991_AINRMUX_PWR_BIT                 3
-
 #define WM8991_MCLK_DIV 0
 #define WM8991_DACCLK_DIV 1
 #define WM8991_ADCCLK_DIV 2
index 86426a117b07923dd4f89aa4811cb5d5dc21b907..b9be9cbc460391d4530e970e3c77a0521109c2a2 100644 (file)
@@ -4077,12 +4077,6 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
        wm8994_request_irq(wm8994->wm8994, WM8994_IRQ_TEMP_SHUT,
                           wm8994_temp_shut, "Thermal shutdown", codec);
 
-       ret = wm8994_request_irq(wm8994->wm8994, WM8994_IRQ_DCS_DONE,
-                                wm_hubs_dcs_done, "DC servo done",
-                                &wm8994->hubs);
-       if (ret == 0)
-               wm8994->hubs.dcs_done_irq = true;
-
        switch (control->type) {
        case WM8994:
                if (wm8994->micdet_irq) {
@@ -4313,6 +4307,11 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
        }
 
        wm_hubs_add_analogue_routes(codec, 0, 0);
+       ret = wm8994_request_irq(wm8994->wm8994, WM8994_IRQ_DCS_DONE,
+                                wm_hubs_dcs_done, "DC servo done",
+                                &wm8994->hubs);
+       if (ret == 0)
+               wm8994->hubs.dcs_done_irq = true;
        snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
 
        switch (control->type) {
index da2899e6c4018fae6cd0a2411b58027f4048b6e4..4300caff17838b59d195ba629b1e0c94b3eb3574 100644 (file)
@@ -2293,7 +2293,7 @@ static struct spi_driver wm8995_spi_driver = {
 };
 #endif
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static int wm8995_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
@@ -2350,7 +2350,7 @@ static int __init wm8995_modinit(void)
 {
        int ret = 0;
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        ret = i2c_add_driver(&wm8995_i2c_driver);
        if (ret) {
                printk(KERN_ERR "Failed to register wm8995 I2C driver: %d\n",
@@ -2371,7 +2371,7 @@ module_init(wm8995_modinit);
 
 static void __exit wm8995_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
        i2c_del_driver(&wm8995_i2c_driver);
 #endif
 #if defined(CONFIG_SPI_MASTER)
index 630b3d776ec27133cd54f2c3dd440ae304c83417..0982c1d38ec458205628b2fdd52ccc87a499db97 100644 (file)
@@ -1326,7 +1326,7 @@ static const struct regmap_config wm9081_regmap = {
        .cache_type = REGCACHE_RBTREE,
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+#if IS_ENABLED(CONFIG_I2C)
 static int wm9081_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
index 46ec0e9744d4b88b50cc922cfdc65a0b4247e567..de47ad7ad512c726d51e4d1cf82e2226f654d8f6 100644 (file)
@@ -1286,6 +1286,7 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
                                        reg = wm_adsp_region_to_reg(mem,
                                                                    reg);
                                        reg += offset;
+                                       break;
                                }
                        }
 
@@ -1468,8 +1469,8 @@ static int wm_adsp2_ena(struct wm_adsp *dsp)
        unsigned int val;
        int ret, count;
 
-       ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
-                                ADSP2_SYS_ENA, ADSP2_SYS_ENA);
+       ret = regmap_update_bits_async(dsp->regmap, dsp->base + ADSP2_CONTROL,
+                                      ADSP2_SYS_ENA, ADSP2_SYS_ENA);
        if (ret != 0)
                return ret;
 
@@ -1521,9 +1522,9 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
                val = (val & ARIZONA_SYSCLK_FREQ_MASK)
                        >> ARIZONA_SYSCLK_FREQ_SHIFT;
 
-               ret = regmap_update_bits(dsp->regmap,
-                                        dsp->base + ADSP2_CLOCKING,
-                                        ADSP2_CLK_SEL_MASK, val);
+               ret = regmap_update_bits_async(dsp->regmap,
+                                              dsp->base + ADSP2_CLOCKING,
+                                              ADSP2_CLK_SEL_MASK, val);
                if (ret != 0) {
                        adsp_err(dsp, "Failed to set clock rate: %d\n",
                                 ret);
@@ -1586,10 +1587,10 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
                if (ret != 0)
                        goto err;
 
-               ret = regmap_update_bits(dsp->regmap,
-                                        dsp->base + ADSP2_CONTROL,
-                                        ADSP2_CORE_ENA | ADSP2_START,
-                                        ADSP2_CORE_ENA | ADSP2_START);
+               ret = regmap_update_bits_async(dsp->regmap,
+                                              dsp->base + ADSP2_CONTROL,
+                                              ADSP2_CORE_ENA | ADSP2_START,
+                                              ADSP2_CORE_ENA | ADSP2_START);
                if (ret != 0)
                        goto err;
 
index 95970f5db3eca228df66a55f5e357f14b26209c9..a8ec1fc3e4d09a72ad1e36dca4859208d56e5e7e 100644 (file)
@@ -1,11 +1,6 @@
 config SND_DAVINCI_SOC
-       tristate "SoC Audio for the TI DAVINCI or AM33XX chip"
-       depends on ARCH_DAVINCI || SOC_AM33XX
-       help
-         Platform driver for daVinci or AM33xx
-         Say Y or M if you want to add support for codecs attached to
-         the DAVINCI AC97, I2S, or McASP interface. You will also need
-         to select the audio interfaces to support below.
+       tristate "SoC Audio for TI DAVINCI or AM33XX/AM43XX chips"
+       depends on ARCH_DAVINCI || SOC_AM33XX || SOC_AM43XX
 
 config SND_DAVINCI_SOC_I2S
        tristate
@@ -16,11 +11,15 @@ config SND_DAVINCI_SOC_MCASP
 config SND_DAVINCI_SOC_VCIF
        tristate
 
+config SND_DAVINCI_SOC_GENERIC_EVM
+       tristate
+       select SND_SOC_TLV320AIC3X
+       select SND_DAVINCI_SOC_MCASP
+
 config SND_AM33XX_SOC_EVM
        tristate "SoC Audio for the AM33XX chip based boards"
        depends on SND_DAVINCI_SOC && SOC_AM33XX
-       select SND_SOC_TLV320AIC3X
-       select SND_DAVINCI_SOC_MCASP
+       select SND_DAVINCI_SOC_GENERIC_EVM
        help
          Say Y or M if you want to add support for SoC audio on AM33XX
          boards using McASP and TLV320AIC3X codec. For example AM335X-EVM,
@@ -31,8 +30,7 @@ config SND_DAVINCI_SOC_EVM
        tristate "SoC Audio support for DaVinci DM6446, DM355 or DM365 EVM"
        depends on SND_DAVINCI_SOC
        depends on MACH_DAVINCI_EVM || MACH_DAVINCI_DM355_EVM || MACH_DAVINCI_DM365_EVM
-       select SND_DAVINCI_SOC_I2S
-       select SND_SOC_TLV320AIC3X
+       select SND_DAVINCI_SOC_GENERIC_EVM
        help
          Say Y if you want to add support for SoC audio on TI
          DaVinci DM6446, DM355 or DM365 EVM platforms.
@@ -59,8 +57,7 @@ endchoice
 config  SND_DM6467_SOC_EVM
        tristate "SoC Audio support for DaVinci DM6467 EVM"
        depends on SND_DAVINCI_SOC && MACH_DAVINCI_DM6467_EVM
-       select SND_DAVINCI_SOC_MCASP
-       select SND_SOC_TLV320AIC3X
+       select SND_DAVINCI_SOC_GENERIC_EVM
        select SND_SOC_SPDIF
 
        help
@@ -69,8 +66,7 @@ config  SND_DM6467_SOC_EVM
 config  SND_DA830_SOC_EVM
        tristate "SoC Audio support for DA830/OMAP-L137 EVM"
        depends on SND_DAVINCI_SOC && MACH_DAVINCI_DA830_EVM
-       select SND_DAVINCI_SOC_MCASP
-       select SND_SOC_TLV320AIC3X
+       select SND_DAVINCI_SOC_GENERIC_EVM
 
        help
          Say Y if you want to add support for SoC audio on TI
@@ -79,8 +75,7 @@ config  SND_DA830_SOC_EVM
 config  SND_DA850_SOC_EVM
        tristate "SoC Audio support for DA850/OMAP-L138 EVM"
        depends on SND_DAVINCI_SOC && MACH_DAVINCI_DA850_EVM
-       select SND_DAVINCI_SOC_MCASP
-       select SND_SOC_TLV320AIC3X
+       select SND_DAVINCI_SOC_GENERIC_EVM
        help
          Say Y if you want to add support for SoC audio on TI
          DA850/OMAP-L138 EVM
index bc81e79fc301b8357cddd5edf7e707beb33a0723..744d4d9a018466c77709a0d18e40afdb26aac063 100644 (file)
@@ -9,11 +9,7 @@ obj-$(CONFIG_SND_DAVINCI_SOC_I2S) += snd-soc-davinci-i2s.o
 obj-$(CONFIG_SND_DAVINCI_SOC_MCASP) += snd-soc-davinci-mcasp.o
 obj-$(CONFIG_SND_DAVINCI_SOC_VCIF) += snd-soc-davinci-vcif.o
 
-# DAVINCI Machine Support
+# Generic DAVINCI/AM33xx Machine Support
 snd-soc-evm-objs := davinci-evm.o
 
-obj-$(CONFIG_SND_DAVINCI_SOC_EVM) += snd-soc-evm.o
-obj-$(CONFIG_SND_AM33XX_SOC_EVM) += snd-soc-evm.o
-obj-$(CONFIG_SND_DM6467_SOC_EVM) += snd-soc-evm.o
-obj-$(CONFIG_SND_DA830_SOC_EVM) += snd-soc-evm.o
-obj-$(CONFIG_SND_DA850_SOC_EVM) += snd-soc-evm.o
+obj-$(CONFIG_SND_DAVINCI_SOC_GENERIC_EVM) += snd-soc-evm.o
index 623eb5e7c08981c08f31f2d51863c0426c1a7416..70ff3772079f2186cdf2967c1c050ff95f37350b 100644 (file)
 
 #include "davinci-pcm.h"
 #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,
                         struct snd_pcm_hw_params *params)
 {
@@ -48,16 +45,6 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
        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);
-       if (ret < 0)
-               return ret;
-
-       /* set cpu DAI configuration */
-       ret = snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT);
-       if (ret < 0)
-               return ret;
-
        /* set the codec system clock */
        ret = snd_soc_dai_set_sysclk(codec_dai, 0, sysclk, SND_SOC_CLOCK_OUT);
        if (ret < 0)
@@ -71,24 +58,10 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static int evm_spdif_hw_params(struct snd_pcm_substream *substream,
-                               struct snd_pcm_hw_params *params)
-{
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-
-       /* set cpu DAI configuration */
-       return snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT);
-}
-
 static struct snd_soc_ops evm_ops = {
        .hw_params = evm_hw_params,
 };
 
-static struct snd_soc_ops evm_spdif_ops = {
-       .hw_params = evm_spdif_hw_params,
-};
-
 /* davinci-evm machine dapm widgets */
 static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
        SND_SOC_DAPM_HP("Headphone Jack", NULL),
@@ -165,6 +138,8 @@ static struct snd_soc_dai_link dm6446_evm_dai = {
        .platform_name = "davinci-mcbsp",
        .init = evm_aic3x_init,
        .ops = &evm_ops,
+       .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
+                  SND_SOC_DAIFMT_IB_NF,
 };
 
 static struct snd_soc_dai_link dm355_evm_dai = {
@@ -176,6 +151,8 @@ static struct snd_soc_dai_link dm355_evm_dai = {
        .platform_name = "davinci-mcbsp.1",
        .init = evm_aic3x_init,
        .ops = &evm_ops,
+       .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
+                  SND_SOC_DAIFMT_IB_NF,
 };
 
 static struct snd_soc_dai_link dm365_evm_dai = {
@@ -184,10 +161,12 @@ static struct snd_soc_dai_link dm365_evm_dai = {
        .stream_name = "AIC3X",
        .cpu_dai_name = "davinci-mcbsp",
        .codec_dai_name = "tlv320aic3x-hifi",
-       .init = evm_aic3x_init,
        .codec_name = "tlv320aic3x-codec.1-0018",
-       .ops = &evm_ops,
        .platform_name = "davinci-mcbsp",
+       .init = evm_aic3x_init,
+       .ops = &evm_ops,
+       .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
+                  SND_SOC_DAIFMT_IB_NF,
 #elif defined(CONFIG_SND_DM365_VOICE_CODEC)
        .name = "Voice Codec - CQ93VC",
        .stream_name = "CQ93",
@@ -208,6 +187,8 @@ static struct snd_soc_dai_link dm6467_evm_dai[] = {
                .codec_name = "tlv320aic3x-codec.0-001a",
                .init = evm_aic3x_init,
                .ops = &evm_ops,
+               .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
+                          SND_SOC_DAIFMT_IB_NF,
        },
        {
                .name = "McASP",
@@ -216,7 +197,8 @@ static struct snd_soc_dai_link dm6467_evm_dai[] = {
                .codec_dai_name = "dit-hifi",
                .codec_name = "spdif_dit",
                .platform_name = "davinci-mcasp.1",
-               .ops = &evm_spdif_ops,
+               .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
+                          SND_SOC_DAIFMT_IB_NF,
        },
 };
 
@@ -229,6 +211,8 @@ static struct snd_soc_dai_link da830_evm_dai = {
        .platform_name = "davinci-mcasp.1",
        .init = evm_aic3x_init,
        .ops = &evm_ops,
+       .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
+                  SND_SOC_DAIFMT_IB_NF,
 };
 
 static struct snd_soc_dai_link da850_evm_dai = {
@@ -240,6 +224,8 @@ static struct snd_soc_dai_link da850_evm_dai = {
        .platform_name = "davinci-mcasp.0",
        .init = evm_aic3x_init,
        .ops = &evm_ops,
+       .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
+                  SND_SOC_DAIFMT_IB_NF,
 };
 
 /* davinci dm6446 evm audio machine driver */
@@ -336,6 +322,8 @@ static struct snd_soc_dai_link evm_dai_tlv320aic3x = {
        .codec_dai_name = "tlv320aic3x-hifi",
        .ops            = &evm_ops,
        .init           = evm_aic3x_init,
+       .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
+                  SND_SOC_DAIFMT_IB_NF,
 };
 
 static const struct of_device_id davinci_evm_dt_ids[] = {
index 71e14bb3a8cd11b4465567d088a05820e0ecdb74..b7858bfa0295357bc5d3ca6d1328932595167b9e 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/clk.h>
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <sound/pcm_params.h>
 #include <sound/initval.h>
 #include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
 
 #include "davinci-pcm.h"
 #include "davinci-mcasp.h"
 
-/*
- * McASP register definitions
- */
-#define DAVINCI_MCASP_PID_REG          0x00
-#define DAVINCI_MCASP_PWREMUMGT_REG    0x04
-
-#define DAVINCI_MCASP_PFUNC_REG                0x10
-#define DAVINCI_MCASP_PDIR_REG         0x14
-#define DAVINCI_MCASP_PDOUT_REG                0x18
-#define DAVINCI_MCASP_PDSET_REG                0x1c
-
-#define DAVINCI_MCASP_PDCLR_REG                0x20
-
-#define DAVINCI_MCASP_TLGC_REG         0x30
-#define DAVINCI_MCASP_TLMR_REG         0x34
-
-#define DAVINCI_MCASP_GBLCTL_REG       0x44
-#define DAVINCI_MCASP_AMUTE_REG                0x48
-#define DAVINCI_MCASP_LBCTL_REG                0x4c
-
-#define DAVINCI_MCASP_TXDITCTL_REG     0x50
-
-#define DAVINCI_MCASP_GBLCTLR_REG      0x60
-#define DAVINCI_MCASP_RXMASK_REG       0x64
-#define DAVINCI_MCASP_RXFMT_REG                0x68
-#define DAVINCI_MCASP_RXFMCTL_REG      0x6c
-
-#define DAVINCI_MCASP_ACLKRCTL_REG     0x70
-#define DAVINCI_MCASP_AHCLKRCTL_REG    0x74
-#define DAVINCI_MCASP_RXTDM_REG                0x78
-#define DAVINCI_MCASP_EVTCTLR_REG      0x7c
-
-#define DAVINCI_MCASP_RXSTAT_REG       0x80
-#define DAVINCI_MCASP_RXTDMSLOT_REG    0x84
-#define DAVINCI_MCASP_RXCLKCHK_REG     0x88
-#define DAVINCI_MCASP_REVTCTL_REG      0x8c
-
-#define DAVINCI_MCASP_GBLCTLX_REG      0xa0
-#define DAVINCI_MCASP_TXMASK_REG       0xa4
-#define DAVINCI_MCASP_TXFMT_REG                0xa8
-#define DAVINCI_MCASP_TXFMCTL_REG      0xac
-
-#define DAVINCI_MCASP_ACLKXCTL_REG     0xb0
-#define DAVINCI_MCASP_AHCLKXCTL_REG    0xb4
-#define DAVINCI_MCASP_TXTDM_REG                0xb8
-#define DAVINCI_MCASP_EVTCTLX_REG      0xbc
-
-#define DAVINCI_MCASP_TXSTAT_REG       0xc0
-#define DAVINCI_MCASP_TXTDMSLOT_REG    0xc4
-#define DAVINCI_MCASP_TXCLKCHK_REG     0xc8
-#define DAVINCI_MCASP_XEVTCTL_REG      0xcc
-
-/* Left(even TDM Slot) Channel Status Register File */
-#define DAVINCI_MCASP_DITCSRA_REG      0x100
-/* Right(odd TDM slot) Channel Status Register File */
-#define DAVINCI_MCASP_DITCSRB_REG      0x118
-/* Left(even TDM slot) User Data Register File */
-#define DAVINCI_MCASP_DITUDRA_REG      0x130
-/* Right(odd TDM Slot) User Data Register File */
-#define DAVINCI_MCASP_DITUDRB_REG      0x148
-
-/* Serializer n Control Register */
-#define DAVINCI_MCASP_XRSRCTL_BASE_REG 0x180
-#define DAVINCI_MCASP_XRSRCTL_REG(n)   (DAVINCI_MCASP_XRSRCTL_BASE_REG + \
-                                               (n << 2))
-
-/* Transmit Buffer for Serializer n */
-#define DAVINCI_MCASP_TXBUF_REG                0x200
-/* Receive Buffer for Serializer n */
-#define DAVINCI_MCASP_RXBUF_REG                0x280
-
-/* McASP FIFO Registers */
-#define DAVINCI_MCASP_WFIFOCTL         (0x1010)
-#define DAVINCI_MCASP_WFIFOSTS         (0x1014)
-#define DAVINCI_MCASP_RFIFOCTL         (0x1018)
-#define DAVINCI_MCASP_RFIFOSTS         (0x101C)
-#define MCASP_VER3_WFIFOCTL            (0x1000)
-#define MCASP_VER3_WFIFOSTS            (0x1004)
-#define MCASP_VER3_RFIFOCTL            (0x1008)
-#define MCASP_VER3_RFIFOSTS            (0x100C)
-
-/*
- * DAVINCI_MCASP_PWREMUMGT_REG - Power Down and Emulation Management
- *     Register Bits
- */
-#define MCASP_FREE     BIT(0)
-#define MCASP_SOFT     BIT(1)
-
-/*
- * DAVINCI_MCASP_PFUNC_REG - Pin Function / GPIO Enable Register Bits
- */
-#define AXR(n)         (1<<n)
-#define PFUNC_AMUTE    BIT(25)
-#define ACLKX          BIT(26)
-#define AHCLKX         BIT(27)
-#define AFSX           BIT(28)
-#define ACLKR          BIT(29)
-#define AHCLKR         BIT(30)
-#define AFSR           BIT(31)
-
-/*
- * DAVINCI_MCASP_PDIR_REG - Pin Direction Register Bits
- */
-#define AXR(n)         (1<<n)
-#define PDIR_AMUTE     BIT(25)
-#define ACLKX          BIT(26)
-#define AHCLKX         BIT(27)
-#define AFSX           BIT(28)
-#define ACLKR          BIT(29)
-#define AHCLKR         BIT(30)
-#define AFSR           BIT(31)
-
-/*
- * DAVINCI_MCASP_TXDITCTL_REG - Transmit DIT Control Register Bits
- */
-#define DITEN  BIT(0)  /* Transmit DIT mode enable/disable */
-#define VA     BIT(2)
-#define VB     BIT(3)
-
-/*
- * DAVINCI_MCASP_TXFMT_REG - Transmit Bitstream Format Register Bits
- */
-#define TXROT(val)     (val)
-#define TXSEL          BIT(3)
-#define TXSSZ(val)     (val<<4)
-#define TXPBIT(val)    (val<<8)
-#define TXPAD(val)     (val<<13)
-#define TXORD          BIT(15)
-#define FSXDLY(val)    (val<<16)
-
-/*
- * DAVINCI_MCASP_RXFMT_REG - Receive Bitstream Format Register Bits
- */
-#define RXROT(val)     (val)
-#define RXSEL          BIT(3)
-#define RXSSZ(val)     (val<<4)
-#define RXPBIT(val)    (val<<8)
-#define RXPAD(val)     (val<<13)
-#define RXORD          BIT(15)
-#define FSRDLY(val)    (val<<16)
-
-/*
- * DAVINCI_MCASP_TXFMCTL_REG -  Transmit Frame Control Register Bits
- */
-#define FSXPOL         BIT(0)
-#define AFSXE          BIT(1)
-#define FSXDUR         BIT(4)
-#define FSXMOD(val)    (val<<7)
-
-/*
- * DAVINCI_MCASP_RXFMCTL_REG - Receive Frame Control Register Bits
- */
-#define FSRPOL         BIT(0)
-#define AFSRE          BIT(1)
-#define FSRDUR         BIT(4)
-#define FSRMOD(val)    (val<<7)
-
-/*
- * DAVINCI_MCASP_ACLKXCTL_REG - Transmit Clock Control Register Bits
- */
-#define ACLKXDIV(val)  (val)
-#define ACLKXE         BIT(5)
-#define TX_ASYNC       BIT(6)
-#define ACLKXPOL       BIT(7)
-#define ACLKXDIV_MASK  0x1f
-
-/*
- * DAVINCI_MCASP_ACLKRCTL_REG Receive Clock Control Register Bits
- */
-#define ACLKRDIV(val)  (val)
-#define ACLKRE         BIT(5)
-#define RX_ASYNC       BIT(6)
-#define ACLKRPOL       BIT(7)
-#define ACLKRDIV_MASK  0x1f
-
-/*
- * DAVINCI_MCASP_AHCLKXCTL_REG - High Frequency Transmit Clock Control
- *     Register Bits
- */
-#define AHCLKXDIV(val) (val)
-#define AHCLKXPOL      BIT(14)
-#define AHCLKXE                BIT(15)
-#define AHCLKXDIV_MASK 0xfff
+struct davinci_mcasp {
+       struct davinci_pcm_dma_params dma_params[2];
+       struct snd_dmaengine_dai_dma_data dma_data[2];
+       void __iomem *base;
+       u32 fifo_base;
+       struct device *dev;
 
-/*
- * DAVINCI_MCASP_AHCLKRCTL_REG - High Frequency Receive Clock Control
- *     Register Bits
- */
-#define AHCLKRDIV(val) (val)
-#define AHCLKRPOL      BIT(14)
-#define AHCLKRE                BIT(15)
-#define AHCLKRDIV_MASK 0xfff
+       /* McASP specific data */
+       int     tdm_slots;
+       u8      op_mode;
+       u8      num_serializer;
+       u8      *serial_dir;
+       u8      version;
+       u16     bclk_lrclk_ratio;
+       int     streams;
 
-/*
- * DAVINCI_MCASP_XRSRCTL_BASE_REG -  Serializer Control Register Bits
- */
-#define MODE(val)      (val)
-#define DISMOD         (val)(val<<2)
-#define TXSTATE                BIT(4)
-#define RXSTATE                BIT(5)
-#define SRMOD_MASK     3
-#define SRMOD_INACTIVE 0
-
-/*
- * DAVINCI_MCASP_LBCTL_REG - Loop Back Control Register Bits
- */
-#define LBEN           BIT(0)
-#define LBORD          BIT(1)
-#define LBGENMODE(val) (val<<2)
+       /* McASP FIFO related */
+       u8      txnumevt;
+       u8      rxnumevt;
 
-/*
- * DAVINCI_MCASP_TXTDMSLOT_REG - Transmit TDM Slot Register configuration
- */
-#define TXTDMS(n)      (1<<n)
-
-/*
- * DAVINCI_MCASP_RXTDMSLOT_REG - Receive TDM Slot Register configuration
- */
-#define RXTDMS(n)      (1<<n)
-
-/*
- * DAVINCI_MCASP_GBLCTL_REG -  Global Control Register Bits
- */
-#define RXCLKRST       BIT(0)  /* Receiver Clock Divider Reset */
-#define RXHCLKRST      BIT(1)  /* Receiver High Frequency Clock Divider */
-#define RXSERCLR       BIT(2)  /* Receiver Serializer Clear */
-#define RXSMRST                BIT(3)  /* Receiver State Machine Reset */
-#define RXFSRST                BIT(4)  /* Frame Sync Generator Reset */
-#define TXCLKRST       BIT(8)  /* Transmitter Clock Divider Reset */
-#define TXHCLKRST      BIT(9)  /* Transmitter High Frequency Clock Divider*/
-#define TXSERCLR       BIT(10) /* Transmit Serializer Clear */
-#define TXSMRST                BIT(11) /* Transmitter State Machine Reset */
-#define TXFSRST                BIT(12) /* Frame Sync Generator Reset */
+       bool    dat_port;
 
-/*
- * DAVINCI_MCASP_AMUTE_REG -  Mute Control Register Bits
- */
-#define MUTENA(val)    (val)
-#define MUTEINPOL      BIT(2)
-#define MUTEINENA      BIT(3)
-#define MUTEIN         BIT(4)
-#define MUTER          BIT(5)
-#define MUTEX          BIT(6)
-#define MUTEFSR                BIT(7)
-#define MUTEFSX                BIT(8)
-#define MUTEBADCLKR    BIT(9)
-#define MUTEBADCLKX    BIT(10)
-#define MUTERXDMAERR   BIT(11)
-#define MUTETXDMAERR   BIT(12)
-
-/*
- * DAVINCI_MCASP_REVTCTL_REG - Receiver DMA Event Control Register bits
- */
-#define RXDATADMADIS   BIT(0)
-
-/*
- * DAVINCI_MCASP_XEVTCTL_REG - Transmitter DMA Event Control Register bits
- */
-#define TXDATADMADIS   BIT(0)
-
-/*
- * DAVINCI_MCASP_W[R]FIFOCTL - Write/Read FIFO Control Register bits
- */
-#define FIFO_ENABLE    BIT(16)
-#define NUMEVT_MASK    (0xFF << 8)
-#define NUMDMA_MASK    (0xFF)
-
-#define DAVINCI_MCASP_NUM_SERIALIZER   16
+#ifdef CONFIG_PM_SLEEP
+       struct {
+               u32     txfmtctl;
+               u32     rxfmtctl;
+               u32     txfmt;
+               u32     rxfmt;
+               u32     aclkxctl;
+               u32     aclkrctl;
+               u32     pdir;
+       } context;
+#endif
+};
 
-static inline void mcasp_set_bits(void __iomem *reg, u32 val)
+static inline void mcasp_set_bits(struct davinci_mcasp *mcasp, u32 offset,
+                                 u32 val)
 {
+       void __iomem *reg = mcasp->base + offset;
        __raw_writel(__raw_readl(reg) | val, reg);
 }
 
-static inline void mcasp_clr_bits(void __iomem *reg, u32 val)
+static inline void mcasp_clr_bits(struct davinci_mcasp *mcasp, u32 offset,
+                                 u32 val)
 {
+       void __iomem *reg = mcasp->base + offset;
        __raw_writel((__raw_readl(reg) & ~(val)), reg);
 }
 
-static inline void mcasp_mod_bits(void __iomem *reg, u32 val, u32 mask)
+static inline void mcasp_mod_bits(struct davinci_mcasp *mcasp, u32 offset,
+                                 u32 val, u32 mask)
 {
+       void __iomem *reg = mcasp->base + offset;
        __raw_writel((__raw_readl(reg) & ~mask) | val, reg);
 }
 
-static inline void mcasp_set_reg(void __iomem *reg, u32 val)
+static inline void mcasp_set_reg(struct davinci_mcasp *mcasp, u32 offset,
+                                u32 val)
 {
-       __raw_writel(val, reg);
+       __raw_writel(val, mcasp->base + offset);
 }
 
-static inline u32 mcasp_get_reg(void __iomem *reg)
+static inline u32 mcasp_get_reg(struct davinci_mcasp *mcasp, u32 offset)
 {
-       return (unsigned int)__raw_readl(reg);
+       return (u32)__raw_readl(mcasp->base + offset);
 }
 
-static inline void mcasp_set_ctl_reg(void __iomem *regs, u32 val)
+static void mcasp_set_ctl_reg(struct davinci_mcasp *mcasp, u32 ctl_reg, u32 val)
 {
        int i = 0;
 
-       mcasp_set_bits(regs, val);
+       mcasp_set_bits(mcasp, ctl_reg, val);
 
        /* programming GBLCTL needs to read back from GBLCTL and verfiy */
        /* loop count is to avoid the lock-up */
        for (i = 0; i < 1000; i++) {
-               if ((mcasp_get_reg(regs) & val) == val)
+               if ((mcasp_get_reg(mcasp, ctl_reg) & val) == val)
                        break;
        }
 
-       if (i == 1000 && ((mcasp_get_reg(regs) & val) != val))
+       if (i == 1000 && ((mcasp_get_reg(mcasp, ctl_reg) & val) != val))
                printk(KERN_ERR "GBLCTL write error\n");
 }
 
-static void mcasp_start_rx(struct davinci_audio_dev *dev)
+static bool mcasp_is_synchronous(struct davinci_mcasp *mcasp)
 {
-       mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXHCLKRST);
-       mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXCLKRST);
-       mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSERCLR);
-       mcasp_set_reg(dev->base + DAVINCI_MCASP_RXBUF_REG, 0);
+       u32 rxfmctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG);
+       u32 aclkxctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG);
 
-       mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST);
-       mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST);
-       mcasp_set_reg(dev->base + DAVINCI_MCASP_RXBUF_REG, 0);
+       return !(aclkxctl & TX_ASYNC) && rxfmctl & AFSRE;
+}
 
-       mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST);
-       mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST);
+static void mcasp_start_rx(struct davinci_mcasp *mcasp)
+{
+       mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXHCLKRST);
+       mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXCLKRST);
+
+       /*
+        * When ASYNC == 0 the transmit and receive sections operate
+        * synchronously from the transmit clock and frame sync. We need to make
+        * sure that the TX signlas are enabled when starting reception.
+        */
+       if (mcasp_is_synchronous(mcasp)) {
+               mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);
+               mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);
+       }
+
+       mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXSERCLR);
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_RXBUF_REG, 0);
+
+       mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXSMRST);
+       mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXFSRST);
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_RXBUF_REG, 0);
+
+       mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXSMRST);
+       mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXFSRST);
+
+       if (mcasp_is_synchronous(mcasp))
+               mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXFSRST);
 }
 
-static void mcasp_start_tx(struct davinci_audio_dev *dev)
+static void mcasp_start_tx(struct davinci_mcasp *mcasp)
 {
        u8 offset = 0, i;
        u32 cnt;
 
-       mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);
-       mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);
-       mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR);
-       mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0);
+       mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);
+       mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);
+       mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR);
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_TXBUF_REG, 0);
 
-       mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSMRST);
-       mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXFSRST);
-       mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0);
-       for (i = 0; i < dev->num_serializer; i++) {
-               if (dev->serial_dir[i] == TX_MODE) {
+       mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSMRST);
+       mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXFSRST);
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_TXBUF_REG, 0);
+       for (i = 0; i < mcasp->num_serializer; i++) {
+               if (mcasp->serial_dir[i] == TX_MODE) {
                        offset = i;
                        break;
                }
@@ -383,156 +180,140 @@ static void mcasp_start_tx(struct davinci_audio_dev *dev)
 
        /* wait for TX ready */
        cnt = 0;
-       while (!(mcasp_get_reg(dev->base + DAVINCI_MCASP_XRSRCTL_REG(offset)) &
+       while (!(mcasp_get_reg(mcasp, DAVINCI_MCASP_XRSRCTL_REG(offset)) &
                 TXSTATE) && (cnt < 100000))
                cnt++;
 
-       mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0);
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_TXBUF_REG, 0);
 }
 
-static void davinci_mcasp_start(struct davinci_audio_dev *dev, int stream)
+static void davinci_mcasp_start(struct davinci_mcasp *mcasp, int stream)
 {
+       u32 reg;
+
+       mcasp->streams++;
+
        if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               if (dev->txnumevt) {    /* enable FIFO */
-                       switch (dev->version) {
-                       case MCASP_VERSION_3:
-                               mcasp_clr_bits(dev->base + MCASP_VER3_WFIFOCTL,
-                                                               FIFO_ENABLE);
-                               mcasp_set_bits(dev->base + MCASP_VER3_WFIFOCTL,
-                                                               FIFO_ENABLE);
-                               break;
-                       default:
-                               mcasp_clr_bits(dev->base +
-                                       DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE);
-                               mcasp_set_bits(dev->base +
-                                       DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE);
-                       }
+               if (mcasp->txnumevt) {  /* enable FIFO */
+                       reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
+                       mcasp_clr_bits(mcasp, reg, FIFO_ENABLE);
+                       mcasp_set_bits(mcasp, reg, FIFO_ENABLE);
                }
-               mcasp_start_tx(dev);
+               mcasp_start_tx(mcasp);
        } else {
-               if (dev->rxnumevt) {    /* enable FIFO */
-                       switch (dev->version) {
-                       case MCASP_VERSION_3:
-                               mcasp_clr_bits(dev->base + MCASP_VER3_RFIFOCTL,
-                                                               FIFO_ENABLE);
-                               mcasp_set_bits(dev->base + MCASP_VER3_RFIFOCTL,
-                                                               FIFO_ENABLE);
-                               break;
-                       default:
-                               mcasp_clr_bits(dev->base +
-                                       DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE);
-                               mcasp_set_bits(dev->base +
-                                       DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE);
-                       }
+               if (mcasp->rxnumevt) {  /* enable FIFO */
+                       reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
+                       mcasp_clr_bits(mcasp, reg, FIFO_ENABLE);
+                       mcasp_set_bits(mcasp, reg, FIFO_ENABLE);
                }
-               mcasp_start_rx(dev);
+               mcasp_start_rx(mcasp);
        }
 }
 
-static void mcasp_stop_rx(struct davinci_audio_dev *dev)
+static void mcasp_stop_rx(struct davinci_mcasp *mcasp)
 {
-       mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, 0);
-       mcasp_set_reg(dev->base + DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);
+       /*
+        * In synchronous mode stop the TX clocks if no other stream is
+        * running
+        */
+       if (mcasp_is_synchronous(mcasp) && !mcasp->streams)
+               mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, 0);
+
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, 0);
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);
 }
 
-static void mcasp_stop_tx(struct davinci_audio_dev *dev)
+static void mcasp_stop_tx(struct davinci_mcasp *mcasp)
 {
-       mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, 0);
-       mcasp_set_reg(dev->base + DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
+       u32 val = 0;
+
+       /*
+        * In synchronous mode keep TX clocks running if the capture stream is
+        * still running.
+        */
+       if (mcasp_is_synchronous(mcasp) && mcasp->streams)
+               val =  TXHCLKRST | TXCLKRST | TXFSRST;
+
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, val);
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
 }
 
-static void davinci_mcasp_stop(struct davinci_audio_dev *dev, int stream)
+static void davinci_mcasp_stop(struct davinci_mcasp *mcasp, int stream)
 {
+       u32 reg;
+
+       mcasp->streams--;
+
        if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               if (dev->txnumevt) {    /* disable FIFO */
-                       switch (dev->version) {
-                       case MCASP_VERSION_3:
-                               mcasp_clr_bits(dev->base + MCASP_VER3_WFIFOCTL,
-                                                               FIFO_ENABLE);
-                               break;
-                       default:
-                               mcasp_clr_bits(dev->base +
-                                       DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE);
-                       }
+               if (mcasp->txnumevt) {  /* disable FIFO */
+                       reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
+                       mcasp_clr_bits(mcasp, reg, FIFO_ENABLE);
                }
-               mcasp_stop_tx(dev);
+               mcasp_stop_tx(mcasp);
        } else {
-               if (dev->rxnumevt) {    /* disable FIFO */
-                       switch (dev->version) {
-                       case MCASP_VERSION_3:
-                               mcasp_clr_bits(dev->base + MCASP_VER3_RFIFOCTL,
-                                                               FIFO_ENABLE);
-                       break;
-
-                       default:
-                               mcasp_clr_bits(dev->base +
-                                       DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE);
-                       }
+               if (mcasp->rxnumevt) {  /* disable FIFO */
+                       reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
+                       mcasp_clr_bits(mcasp, reg, FIFO_ENABLE);
                }
-               mcasp_stop_rx(dev);
+               mcasp_stop_rx(mcasp);
        }
 }
 
 static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                                         unsigned int fmt)
 {
-       struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
-       void __iomem *base = dev->base;
+       struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai);
 
        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
        case SND_SOC_DAIFMT_DSP_B:
        case SND_SOC_DAIFMT_AC97:
-               mcasp_clr_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
-               mcasp_clr_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
                break;
        default:
                /* configure a full-word SYNC pulse (LRCLK) */
-               mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
-               mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
 
                /* make 1st data bit occur one ACLK cycle after the frame sync */
-               mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, FSXDLY(1));
-               mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, FSRDLY(1));
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, FSXDLY(1));
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, FSRDLY(1));
                break;
        }
 
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBS_CFS:
                /* codec is clock and frame slave */
-               mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
-               mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
 
-               mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
-               mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
 
-               mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG,
-                               ACLKX | ACLKR);
-               mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG,
-                               AFSX | AFSR);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, ACLKX | ACLKR);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AFSX | AFSR);
                break;
        case SND_SOC_DAIFMT_CBM_CFS:
                /* codec is clock master and frame slave */
-               mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
-               mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
 
-               mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
-               mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
 
-               mcasp_clr_bits(base + DAVINCI_MCASP_PDIR_REG,
-                               ACLKX | ACLKR);
-               mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG,
-                               AFSX | AFSR);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, ACLKX | ACLKR);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AFSX | AFSR);
                break;
        case SND_SOC_DAIFMT_CBM_CFM:
                /* codec is clock and frame master */
-               mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
-               mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
 
-               mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
-               mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
 
-               mcasp_clr_bits(base + DAVINCI_MCASP_PDIR_REG,
-                               ACLKX | AHCLKX | AFSX | ACLKR | AHCLKR | AFSR);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG,
+                              ACLKX | AHCLKX | AFSX | ACLKR | AHCLKR | AFSR);
                break;
 
        default:
@@ -541,35 +322,35 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 
        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
        case SND_SOC_DAIFMT_IB_NF:
-               mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
-               mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
 
-               mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
-               mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
                break;
 
        case SND_SOC_DAIFMT_NB_IF:
-               mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
-               mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
 
-               mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
-               mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
                break;
 
        case SND_SOC_DAIFMT_IB_IF:
-               mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
-               mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
 
-               mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
-               mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
                break;
 
        case SND_SOC_DAIFMT_NB_NF:
-               mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
-               mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
 
-               mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
-               mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
                break;
 
        default:
@@ -581,25 +362,25 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 
 static int davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div)
 {
-       struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(dai);
+       struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
 
        switch (div_id) {
        case 0:         /* MCLK divider */
-               mcasp_mod_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG,
+               mcasp_mod_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG,
                               AHCLKXDIV(div - 1), AHCLKXDIV_MASK);
-               mcasp_mod_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG,
+               mcasp_mod_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG,
                               AHCLKRDIV(div - 1), AHCLKRDIV_MASK);
                break;
 
        case 1:         /* BCLK divider */
-               mcasp_mod_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG,
+               mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG,
                               ACLKXDIV(div - 1), ACLKXDIV_MASK);
-               mcasp_mod_bits(dev->base + DAVINCI_MCASP_ACLKRCTL_REG,
+               mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG,
                               ACLKRDIV(div - 1), ACLKRDIV_MASK);
                break;
 
        case 2:         /* BCLK/LRCLK ratio */
-               dev->bclk_lrclk_ratio = div;
+               mcasp->bclk_lrclk_ratio = div;
                break;
 
        default:
@@ -612,22 +393,22 @@ static int davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div
 static int davinci_mcasp_set_sysclk(struct snd_soc_dai *dai, int clk_id,
                                    unsigned int freq, int dir)
 {
-       struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(dai);
+       struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
 
        if (dir == SND_SOC_CLOCK_OUT) {
-               mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
-               mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE);
-               mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG, AHCLKX);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AHCLKX);
        } else {
-               mcasp_clr_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
-               mcasp_clr_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE);
-               mcasp_clr_bits(dev->base + DAVINCI_MCASP_PDIR_REG, AHCLKX);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AHCLKX);
        }
 
        return 0;
 }
 
-static int davinci_config_channel_size(struct davinci_audio_dev *dev,
+static int davinci_config_channel_size(struct davinci_mcasp *mcasp,
                                       int word_length)
 {
        u32 fmt;
@@ -644,71 +425,68 @@ static int davinci_config_channel_size(struct davinci_audio_dev *dev,
         * both left and right channels), so it has to be divided by number of
         * tdm-slots (for I2S - divided by 2).
         */
-       if (dev->bclk_lrclk_ratio)
-               word_length = dev->bclk_lrclk_ratio / dev->tdm_slots;
+       if (mcasp->bclk_lrclk_ratio)
+               word_length = mcasp->bclk_lrclk_ratio / mcasp->tdm_slots;
 
        /* mapping of the XSSZ bit-field as described in the datasheet */
        fmt = (word_length >> 1) - 1;
 
-       if (dev->op_mode != DAVINCI_MCASP_DIT_MODE) {
-               mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG,
-                               RXSSZ(fmt), RXSSZ(0x0F));
-               mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG,
-                               TXSSZ(fmt), TXSSZ(0x0F));
-               mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG,
-                               TXROT(tx_rotate), TXROT(7));
-               mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG,
-                               RXROT(rx_rotate), RXROT(7));
-               mcasp_set_reg(dev->base + DAVINCI_MCASP_RXMASK_REG,
-                               mask);
+       if (mcasp->op_mode != DAVINCI_MCASP_DIT_MODE) {
+               mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, RXSSZ(fmt),
+                              RXSSZ(0x0F));
+               mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXSSZ(fmt),
+                              TXSSZ(0x0F));
+               mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXROT(tx_rotate),
+                              TXROT(7));
+               mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, RXROT(rx_rotate),
+                              RXROT(7));
+               mcasp_set_reg(mcasp, DAVINCI_MCASP_RXMASK_REG, mask);
        }
 
-       mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, mask);
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_TXMASK_REG, mask);
 
        return 0;
 }
 
-static int davinci_hw_common_param(struct davinci_audio_dev *dev, int stream,
+static int davinci_hw_common_param(struct davinci_mcasp *mcasp, int stream,
                                    int channels)
 {
        int i;
        u8 tx_ser = 0;
        u8 rx_ser = 0;
        u8 ser;
-       u8 slots = dev->tdm_slots;
+       u8 slots = mcasp->tdm_slots;
        u8 max_active_serializers = (channels + slots - 1) / slots;
+       u32 reg;
        /* Default configuration */
-       mcasp_set_bits(dev->base + DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT);
+       if (mcasp->version != MCASP_VERSION_4)
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT);
 
        /* All PINS as McASP */
-       mcasp_set_reg(dev->base + DAVINCI_MCASP_PFUNC_REG, 0x00000000);
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_PFUNC_REG, 0x00000000);
 
        if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               mcasp_set_reg(dev->base + DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
-               mcasp_clr_bits(dev->base + DAVINCI_MCASP_XEVTCTL_REG,
-                               TXDATADMADIS);
+               mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS);
        } else {
-               mcasp_set_reg(dev->base + DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);
-               mcasp_clr_bits(dev->base + DAVINCI_MCASP_REVTCTL_REG,
-                               RXDATADMADIS);
+               mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);
+               mcasp_clr_bits(mcasp, DAVINCI_MCASP_REVTCTL_REG, RXDATADMADIS);
        }
 
-       for (i = 0; i < dev->num_serializer; i++) {
-               mcasp_set_bits(dev->base + DAVINCI_MCASP_XRSRCTL_REG(i),
-                                       dev->serial_dir[i]);
-               if (dev->serial_dir[i] == TX_MODE &&
+       for (i = 0; i < mcasp->num_serializer; i++) {
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
+                              mcasp->serial_dir[i]);
+               if (mcasp->serial_dir[i] == TX_MODE &&
                                        tx_ser < max_active_serializers) {
-                       mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG,
-                                       AXR(i));
+                       mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AXR(i));
                        tx_ser++;
-               } else if (dev->serial_dir[i] == RX_MODE &&
+               } else if (mcasp->serial_dir[i] == RX_MODE &&
                                        rx_ser < max_active_serializers) {
-                       mcasp_clr_bits(dev->base + DAVINCI_MCASP_PDIR_REG,
-                                       AXR(i));
+                       mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AXR(i));
                        rx_ser++;
                } else {
-                       mcasp_mod_bits(dev->base + DAVINCI_MCASP_XRSRCTL_REG(i),
-                                       SRMOD_INACTIVE, SRMOD_MASK);
+                       mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
+                                      SRMOD_INACTIVE, SRMOD_MASK);
                }
        }
 
@@ -718,127 +496,113 @@ static int davinci_hw_common_param(struct davinci_audio_dev *dev, int stream,
                ser = rx_ser;
 
        if (ser < max_active_serializers) {
-               dev_warn(dev->dev, "stream has more channels (%d) than are "
+               dev_warn(mcasp->dev, "stream has more channels (%d) than are "
                        "enabled in mcasp (%d)\n", channels, ser * slots);
                return -EINVAL;
        }
 
-       if (dev->txnumevt && stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               if (dev->txnumevt * tx_ser > 64)
-                       dev->txnumevt = 1;
+       if (mcasp->txnumevt && stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               if (mcasp->txnumevt * tx_ser > 64)
+                       mcasp->txnumevt = 1;
 
-               switch (dev->version) {
-               case MCASP_VERSION_3:
-                       mcasp_mod_bits(dev->base + MCASP_VER3_WFIFOCTL, tx_ser,
-                                                               NUMDMA_MASK);
-                       mcasp_mod_bits(dev->base + MCASP_VER3_WFIFOCTL,
-                               ((dev->txnumevt * tx_ser) << 8), NUMEVT_MASK);
-                       break;
-               default:
-                       mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL,
-                                                       tx_ser, NUMDMA_MASK);
-                       mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL,
-                               ((dev->txnumevt * tx_ser) << 8), NUMEVT_MASK);
-               }
+               reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
+               mcasp_mod_bits(mcasp, reg, tx_ser, NUMDMA_MASK);
+               mcasp_mod_bits(mcasp, reg, ((mcasp->txnumevt * tx_ser) << 8),
+                              NUMEVT_MASK);
        }
 
-       if (dev->rxnumevt && stream == SNDRV_PCM_STREAM_CAPTURE) {
-               if (dev->rxnumevt * rx_ser > 64)
-                       dev->rxnumevt = 1;
-               switch (dev->version) {
-               case MCASP_VERSION_3:
-                       mcasp_mod_bits(dev->base + MCASP_VER3_RFIFOCTL, rx_ser,
-                                                               NUMDMA_MASK);
-                       mcasp_mod_bits(dev->base + MCASP_VER3_RFIFOCTL,
-                               ((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK);
-                       break;
-               default:
-                       mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL,
-                                                       rx_ser, NUMDMA_MASK);
-                       mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL,
-                               ((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK);
-               }
+       if (mcasp->rxnumevt && stream == SNDRV_PCM_STREAM_CAPTURE) {
+               if (mcasp->rxnumevt * rx_ser > 64)
+                       mcasp->rxnumevt = 1;
+
+               reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
+               mcasp_mod_bits(mcasp, reg, rx_ser, NUMDMA_MASK);
+               mcasp_mod_bits(mcasp, reg, ((mcasp->rxnumevt * rx_ser) << 8),
+                              NUMEVT_MASK);
        }
 
        return 0;
 }
 
-static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
+static void davinci_hw_param(struct davinci_mcasp *mcasp, int stream)
 {
        int i, active_slots;
        u32 mask = 0;
+       u32 busel = 0;
 
-       active_slots = (dev->tdm_slots > 31) ? 32 : dev->tdm_slots;
+       active_slots = (mcasp->tdm_slots > 31) ? 32 : mcasp->tdm_slots;
        for (i = 0; i < active_slots; i++)
                mask |= (1 << i);
 
-       mcasp_clr_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC);
+       mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC);
+
+       if (!mcasp->dat_port)
+               busel = TXSEL;
 
        if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
                /* bit stream is MSB first  with no delay */
                /* DSP_B mode */
-               mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, mask);
-               mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXORD);
+               mcasp_set_reg(mcasp, DAVINCI_MCASP_TXTDM_REG, mask);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, busel | TXORD);
 
-               if ((dev->tdm_slots >= 2) && (dev->tdm_slots <= 32))
-                       mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG,
-                                       FSXMOD(dev->tdm_slots), FSXMOD(0x1FF));
+               if ((mcasp->tdm_slots >= 2) && (mcasp->tdm_slots <= 32))
+                       mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG,
+                                      FSXMOD(mcasp->tdm_slots), FSXMOD(0x1FF));
                else
                        printk(KERN_ERR "playback tdm slot %d not supported\n",
-                               dev->tdm_slots);
+                               mcasp->tdm_slots);
        } else {
                /* bit stream is MSB first with no delay */
                /* DSP_B mode */
-               mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXORD);
-               mcasp_set_reg(dev->base + DAVINCI_MCASP_RXTDM_REG, mask);
+               mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, busel | RXORD);
+               mcasp_set_reg(mcasp, DAVINCI_MCASP_RXTDM_REG, mask);
 
-               if ((dev->tdm_slots >= 2) && (dev->tdm_slots <= 32))
-                       mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG,
-                                       FSRMOD(dev->tdm_slots), FSRMOD(0x1FF));
+               if ((mcasp->tdm_slots >= 2) && (mcasp->tdm_slots <= 32))
+                       mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG,
+                                      FSRMOD(mcasp->tdm_slots), FSRMOD(0x1FF));
                else
                        printk(KERN_ERR "capture tdm slot %d not supported\n",
-                               dev->tdm_slots);
+                               mcasp->tdm_slots);
        }
 }
 
 /* S/PDIF */
-static void davinci_hw_dit_param(struct davinci_audio_dev *dev)
+static void davinci_hw_dit_param(struct davinci_mcasp *mcasp)
 {
        /* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0
           and LSB first */
-       mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG,
-                                               TXROT(6) | TXSSZ(15));
+       mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXROT(6) | TXSSZ(15));
 
        /* Set TX frame synch : DIT Mode, 1 bit width, internal, rising edge */
-       mcasp_set_reg(dev->base + DAVINCI_MCASP_TXFMCTL_REG,
-                                               AFSXE | FSXMOD(0x180));
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG, AFSXE | FSXMOD(0x180));
 
        /* Set the TX tdm : for all the slots */
-       mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, 0xFFFFFFFF);
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_TXTDM_REG, 0xFFFFFFFF);
 
        /* Set the TX clock controls : div = 1 and internal */
-       mcasp_set_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG,
-                                               ACLKXE | TX_ASYNC);
+       mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE | TX_ASYNC);
 
-       mcasp_clr_bits(dev->base + DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS);
+       mcasp_clr_bits(mcasp, DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS);
 
        /* Only 44100 and 48000 are valid, both have the same setting */
-       mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXDIV(3));
+       mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXDIV(3));
 
        /* Enable the DIT */
-       mcasp_set_bits(dev->base + DAVINCI_MCASP_TXDITCTL_REG, DITEN);
+       mcasp_set_bits(mcasp, DAVINCI_MCASP_TXDITCTL_REG, DITEN);
 }
 
 static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
                                        struct snd_pcm_hw_params *params,
                                        struct snd_soc_dai *cpu_dai)
 {
-       struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
+       struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai);
        struct davinci_pcm_dma_params *dma_params =
-                                       &dev->dma_params[substream->stream];
+                                       &mcasp->dma_params[substream->stream];
+       struct snd_dmaengine_dai_dma_data *dma_data =
+                                       &mcasp->dma_data[substream->stream];
        int word_length;
        u8 fifo_level;
-       u8 slots = dev->tdm_slots;
+       u8 slots = mcasp->tdm_slots;
        u8 active_serializers;
        int channels;
        struct snd_interval *pcm_channels = hw_param_interval(params,
@@ -847,17 +611,17 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
 
        active_serializers = (channels + slots - 1) / slots;
 
-       if (davinci_hw_common_param(dev, substream->stream, channels) == -EINVAL)
+       if (davinci_hw_common_param(mcasp, substream->stream, channels) == -EINVAL)
                return -EINVAL;
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               fifo_level = dev->txnumevt * active_serializers;
+               fifo_level = mcasp->txnumevt * active_serializers;
        else
-               fifo_level = dev->rxnumevt * active_serializers;
+               fifo_level = mcasp->rxnumevt * active_serializers;
 
-       if (dev->op_mode == DAVINCI_MCASP_DIT_MODE)
-               davinci_hw_dit_param(dev);
+       if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE)
+               davinci_hw_dit_param(mcasp);
        else
-               davinci_hw_param(dev, substream->stream);
+               davinci_hw_param(mcasp, substream->stream);
 
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_U8:
@@ -891,13 +655,15 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
-       if (dev->version == MCASP_VERSION_2 && !fifo_level)
+       if (mcasp->version == MCASP_VERSION_2 && !fifo_level)
                dma_params->acnt = 4;
        else
                dma_params->acnt = dma_params->data_type;
 
        dma_params->fifo_level = fifo_level;
-       davinci_config_channel_size(dev, word_length);
+       dma_data->maxburst = fifo_level;
+
+       davinci_config_channel_size(mcasp, word_length);
 
        return 0;
 }
@@ -905,29 +671,29 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
 static int davinci_mcasp_trigger(struct snd_pcm_substream *substream,
                                     int cmd, struct snd_soc_dai *cpu_dai)
 {
-       struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
+       struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai);
        int ret = 0;
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_RESUME:
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               ret = pm_runtime_get_sync(dev->dev);
+               ret = pm_runtime_get_sync(mcasp->dev);
                if (IS_ERR_VALUE(ret))
-                       dev_err(dev->dev, "pm_runtime_get_sync() failed\n");
-               davinci_mcasp_start(dev, substream->stream);
+                       dev_err(mcasp->dev, "pm_runtime_get_sync() failed\n");
+               davinci_mcasp_start(mcasp, substream->stream);
                break;
 
        case SNDRV_PCM_TRIGGER_SUSPEND:
-               davinci_mcasp_stop(dev, substream->stream);
-               ret = pm_runtime_put_sync(dev->dev);
+               davinci_mcasp_stop(mcasp, substream->stream);
+               ret = pm_runtime_put_sync(mcasp->dev);
                if (IS_ERR_VALUE(ret))
-                       dev_err(dev->dev, "pm_runtime_put_sync() failed\n");
+                       dev_err(mcasp->dev, "pm_runtime_put_sync() failed\n");
                break;
 
        case SNDRV_PCM_TRIGGER_STOP:
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-               davinci_mcasp_stop(dev, substream->stream);
+               davinci_mcasp_stop(mcasp, substream->stream);
                break;
 
        default:
@@ -940,9 +706,14 @@ static int davinci_mcasp_trigger(struct snd_pcm_substream *substream,
 static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
                                 struct snd_soc_dai *dai)
 {
-       struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(dai);
+       struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
+
+       if (mcasp->version == MCASP_VERSION_4)
+               snd_soc_dai_set_dma_data(dai, substream,
+                                       &mcasp->dma_data[substream->stream]);
+       else
+               snd_soc_dai_set_dma_data(dai, substream, mcasp->dma_params);
 
-       snd_soc_dai_set_dma_data(dai, substream, dev->dma_params);
        return 0;
 }
 
@@ -955,6 +726,8 @@ static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = {
        .set_sysclk     = davinci_mcasp_set_sysclk,
 };
 
+#define DAVINCI_MCASP_RATES    SNDRV_PCM_RATE_8000_192000
+
 #define DAVINCI_MCASP_PCM_FMTS (SNDRV_PCM_FMTBIT_S8 | \
                                SNDRV_PCM_FMTBIT_U8 | \
                                SNDRV_PCM_FMTBIT_S16_LE | \
@@ -985,7 +758,7 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
 
        },
        {
-               "davinci-mcasp.1",
+               .name           = "davinci-mcasp.1",
                .playback       = {
                        .channels_min   = 1,
                        .channels_max   = 384,
@@ -1016,13 +789,20 @@ static struct snd_platform_data da830_mcasp_pdata = {
        .version = MCASP_VERSION_2,
 };
 
-static struct snd_platform_data omap2_mcasp_pdata = {
+static struct snd_platform_data am33xx_mcasp_pdata = {
        .tx_dma_offset = 0,
        .rx_dma_offset = 0,
        .asp_chan_q = EVENTQ_0,
        .version = MCASP_VERSION_3,
 };
 
+static struct snd_platform_data dra7_mcasp_pdata = {
+       .tx_dma_offset = 0x200,
+       .rx_dma_offset = 0x284,
+       .asp_chan_q = EVENTQ_0,
+       .version = MCASP_VERSION_4,
+};
+
 static const struct of_device_id mcasp_dt_ids[] = {
        {
                .compatible = "ti,dm646x-mcasp-audio",
@@ -1034,12 +814,56 @@ static const struct of_device_id mcasp_dt_ids[] = {
        },
        {
                .compatible = "ti,am33xx-mcasp-audio",
-               .data = &omap2_mcasp_pdata,
+               .data = &am33xx_mcasp_pdata,
+       },
+       {
+               .compatible = "ti,dra7-mcasp-audio",
+               .data = &dra7_mcasp_pdata,
        },
        { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, mcasp_dt_ids);
 
+static int mcasp_reparent_fck(struct platform_device *pdev)
+{
+       struct device_node *node = pdev->dev.of_node;
+       struct clk *gfclk, *parent_clk;
+       const char *parent_name;
+       int ret;
+
+       if (!node)
+               return 0;
+
+       parent_name = of_get_property(node, "fck_parent", NULL);
+       if (!parent_name)
+               return 0;
+
+       gfclk = clk_get(&pdev->dev, "fck");
+       if (IS_ERR(gfclk)) {
+               dev_err(&pdev->dev, "failed to get fck\n");
+               return PTR_ERR(gfclk);
+       }
+
+       parent_clk = clk_get(NULL, parent_name);
+       if (IS_ERR(parent_clk)) {
+               dev_err(&pdev->dev, "failed to get parent clock\n");
+               ret = PTR_ERR(parent_clk);
+               goto err1;
+       }
+
+       ret = clk_set_parent(gfclk, parent_clk);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to reparent fck\n");
+               goto err2;
+       }
+
+err2:
+       clk_put(parent_clk);
+err1:
+       clk_put(gfclk);
+       return ret;
+}
+
 static struct snd_platform_data *davinci_mcasp_set_pdata_from_of(
                                                struct platform_device *pdev)
 {
@@ -1152,7 +976,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
        struct davinci_pcm_dma_params *dma_data;
        struct resource *mem, *ioarea, *res, *dat;
        struct snd_platform_data *pdata;
-       struct davinci_audio_dev *dev;
+       struct davinci_mcasp *mcasp;
        int ret;
 
        if (!pdev->dev.platform_data && !pdev->dev.of_node) {
@@ -1160,9 +984,9 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
                return -EINVAL;
        }
 
-       dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_audio_dev),
+       mcasp = devm_kzalloc(&pdev->dev, sizeof(struct davinci_mcasp),
                           GFP_KERNEL);
-       if (!dev)
+       if (!mcasp)
                return  -ENOMEM;
 
        pdata = davinci_mcasp_set_pdata_from_of(pdev);
@@ -1173,7 +997,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
 
        mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
        if (!mem) {
-               dev_warn(dev->dev,
+               dev_warn(mcasp->dev,
                         "\"mpu\" mem resource not found, using index 0\n");
                mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
                if (!mem) {
@@ -1197,32 +1021,39 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
                return ret;
        }
 
-       dev->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
-       if (!dev->base) {
+       mcasp->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
+       if (!mcasp->base) {
                dev_err(&pdev->dev, "ioremap failed\n");
                ret = -ENOMEM;
                goto err_release_clk;
        }
 
-       dev->op_mode = pdata->op_mode;
-       dev->tdm_slots = pdata->tdm_slots;
-       dev->num_serializer = pdata->num_serializer;
-       dev->serial_dir = pdata->serial_dir;
-       dev->version = pdata->version;
-       dev->txnumevt = pdata->txnumevt;
-       dev->rxnumevt = pdata->rxnumevt;
-       dev->dev = &pdev->dev;
+       mcasp->op_mode = pdata->op_mode;
+       mcasp->tdm_slots = pdata->tdm_slots;
+       mcasp->num_serializer = pdata->num_serializer;
+       mcasp->serial_dir = pdata->serial_dir;
+       mcasp->version = pdata->version;
+       mcasp->txnumevt = pdata->txnumevt;
+       mcasp->rxnumevt = pdata->rxnumevt;
+
+       mcasp->dev = &pdev->dev;
 
        dat = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
-       if (!dat)
-               dat = mem;
+       if (dat)
+               mcasp->dat_port = true;
 
-       dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK];
+       dma_data = &mcasp->dma_params[SNDRV_PCM_STREAM_PLAYBACK];
        dma_data->asp_chan_q = pdata->asp_chan_q;
        dma_data->ram_chan_q = pdata->ram_chan_q;
        dma_data->sram_pool = pdata->sram_pool;
        dma_data->sram_size = pdata->sram_size_playback;
-       dma_data->dma_addr = dat->start + pdata->tx_dma_offset;
+       if (dat)
+               dma_data->dma_addr = dat->start;
+       else
+               dma_data->dma_addr = mem->start + pdata->tx_dma_offset;
+
+       /* Unconditional dmaengine stuff */
+       mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr = dma_data->dma_addr;
 
        res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
        if (res)
@@ -1230,12 +1061,26 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
        else
                dma_data->channel = pdata->tx_dma_channel;
 
-       dma_data = &dev->dma_params[SNDRV_PCM_STREAM_CAPTURE];
+       dma_data = &mcasp->dma_params[SNDRV_PCM_STREAM_CAPTURE];
        dma_data->asp_chan_q = pdata->asp_chan_q;
        dma_data->ram_chan_q = pdata->ram_chan_q;
        dma_data->sram_pool = pdata->sram_pool;
        dma_data->sram_size = pdata->sram_size_capture;
-       dma_data->dma_addr = dat->start + pdata->rx_dma_offset;
+       if (dat)
+               dma_data->dma_addr = dat->start;
+       else
+               dma_data->dma_addr = mem->start + pdata->rx_dma_offset;
+
+       /* Unconditional dmaengine stuff */
+       mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr = dma_data->dma_addr;
+
+       if (mcasp->version < MCASP_VERSION_3) {
+               mcasp->fifo_base = DAVINCI_MCASP_V2_AFIFO_BASE;
+               /* dma_data->dma_addr is pointing to the data port address */
+               mcasp->dat_port = true;
+       } else {
+               mcasp->fifo_base = DAVINCI_MCASP_V3_AFIFO_BASE;
+       }
 
        res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
        if (res)
@@ -1243,17 +1088,26 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
        else
                dma_data->channel = pdata->rx_dma_channel;
 
-       dev_set_drvdata(&pdev->dev, dev);
+       /* Unconditional dmaengine stuff */
+       mcasp->dma_data[SNDRV_PCM_STREAM_PLAYBACK].filter_data = "tx";
+       mcasp->dma_data[SNDRV_PCM_STREAM_CAPTURE].filter_data = "rx";
+
+       dev_set_drvdata(&pdev->dev, mcasp);
+
+       mcasp_reparent_fck(pdev);
+
        ret = snd_soc_register_component(&pdev->dev, &davinci_mcasp_component,
                                         &davinci_mcasp_dai[pdata->op_mode], 1);
 
        if (ret != 0)
                goto err_release_clk;
 
-       ret = davinci_soc_platform_register(&pdev->dev);
-       if (ret) {
-               dev_err(&pdev->dev, "register PCM failed: %d\n", ret);
-               goto err_unregister_component;
+       if (mcasp->version != MCASP_VERSION_4) {
+               ret = davinci_soc_platform_register(&pdev->dev);
+               if (ret) {
+                       dev_err(&pdev->dev, "register PCM failed: %d\n", ret);
+                       goto err_unregister_component;
+               }
        }
 
        return 0;
@@ -1268,9 +1122,11 @@ err_release_clk:
 
 static int davinci_mcasp_remove(struct platform_device *pdev)
 {
+       struct davinci_mcasp *mcasp = dev_get_drvdata(&pdev->dev);
 
        snd_soc_unregister_component(&pdev->dev);
-       davinci_soc_platform_unregister(&pdev->dev);
+       if (mcasp->version != MCASP_VERSION_4)
+               davinci_soc_platform_unregister(&pdev->dev);
 
        pm_runtime_put_sync(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
@@ -1281,32 +1137,30 @@ static int davinci_mcasp_remove(struct platform_device *pdev)
 #ifdef CONFIG_PM_SLEEP
 static int davinci_mcasp_suspend(struct device *dev)
 {
-       struct davinci_audio_dev *a = dev_get_drvdata(dev);
-       void __iomem *base = a->base;
+       struct davinci_mcasp *mcasp = dev_get_drvdata(dev);
 
-       a->context.txfmtctl = mcasp_get_reg(base + DAVINCI_MCASP_TXFMCTL_REG);
-       a->context.rxfmtctl = mcasp_get_reg(base + DAVINCI_MCASP_RXFMCTL_REG);
-       a->context.txfmt = mcasp_get_reg(base + DAVINCI_MCASP_TXFMT_REG);
-       a->context.rxfmt = mcasp_get_reg(base + DAVINCI_MCASP_RXFMT_REG);
-       a->context.aclkxctl = mcasp_get_reg(base + DAVINCI_MCASP_ACLKXCTL_REG);
-       a->context.aclkrctl = mcasp_get_reg(base + DAVINCI_MCASP_ACLKRCTL_REG);
-       a->context.pdir = mcasp_get_reg(base + DAVINCI_MCASP_PDIR_REG);
+       mcasp->context.txfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG);
+       mcasp->context.rxfmtctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG);
+       mcasp->context.txfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXFMT_REG);
+       mcasp->context.rxfmt = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMT_REG);
+       mcasp->context.aclkxctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG);
+       mcasp->context.aclkrctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG);
+       mcasp->context.pdir = mcasp_get_reg(mcasp, DAVINCI_MCASP_PDIR_REG);
 
        return 0;
 }
 
 static int davinci_mcasp_resume(struct device *dev)
 {
-       struct davinci_audio_dev *a = dev_get_drvdata(dev);
-       void __iomem *base = a->base;
-
-       mcasp_set_reg(base + DAVINCI_MCASP_TXFMCTL_REG, a->context.txfmtctl);
-       mcasp_set_reg(base + DAVINCI_MCASP_RXFMCTL_REG, a->context.rxfmtctl);
-       mcasp_set_reg(base + DAVINCI_MCASP_TXFMT_REG, a->context.txfmt);
-       mcasp_set_reg(base + DAVINCI_MCASP_RXFMT_REG, a->context.rxfmt);
-       mcasp_set_reg(base + DAVINCI_MCASP_ACLKXCTL_REG, a->context.aclkxctl);
-       mcasp_set_reg(base + DAVINCI_MCASP_ACLKRCTL_REG, a->context.aclkrctl);
-       mcasp_set_reg(base + DAVINCI_MCASP_PDIR_REG, a->context.pdir);
+       struct davinci_mcasp *mcasp = dev_get_drvdata(dev);
+
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMCTL_REG, mcasp->context.txfmtctl);
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG, mcasp->context.rxfmtctl);
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_TXFMT_REG, mcasp->context.txfmt);
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_RXFMT_REG, mcasp->context.rxfmt);
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, mcasp->context.aclkxctl);
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_ACLKRCTL_REG, mcasp->context.aclkrctl);
+       mcasp_set_reg(mcasp, DAVINCI_MCASP_PDIR_REG, mcasp->context.pdir);
 
        return 0;
 }
index a2e27e1c32f3b28a8600ea0bb5325a35f7fe9741..8fed757d60876310ea4138e69a5575feed7cea60 100644 (file)
 #ifndef DAVINCI_MCASP_H
 #define DAVINCI_MCASP_H
 
-#include <linux/io.h>
-#include <linux/platform_data/davinci_asp.h>
-
-#include "davinci-pcm.h"
-
-#define DAVINCI_MCASP_RATES    SNDRV_PCM_RATE_8000_192000
-#define DAVINCI_MCASP_I2S_DAI  0
-#define DAVINCI_MCASP_DIT_DAI  1
-
-struct davinci_audio_dev {
-       struct davinci_pcm_dma_params dma_params[2];
-       void __iomem *base;
-       struct device *dev;
-
-       /* McASP specific data */
-       int     tdm_slots;
-       u8      op_mode;
-       u8      num_serializer;
-       u8      *serial_dir;
-       u8      version;
-       u16     bclk_lrclk_ratio;
-
-       /* McASP FIFO related */
-       u8      txnumevt;
-       u8      rxnumevt;
-
-#ifdef CONFIG_PM_SLEEP
-       struct {
-               u32     txfmtctl;
-               u32     rxfmtctl;
-               u32     txfmt;
-               u32     rxfmt;
-               u32     aclkxctl;
-               u32     aclkrctl;
-               u32     pdir;
-       } context;
-#endif
-};
+/*
+ * McASP register definitions
+ */
+#define DAVINCI_MCASP_PID_REG          0x00
+#define DAVINCI_MCASP_PWREMUMGT_REG    0x04
+
+#define DAVINCI_MCASP_PFUNC_REG                0x10
+#define DAVINCI_MCASP_PDIR_REG         0x14
+#define DAVINCI_MCASP_PDOUT_REG                0x18
+#define DAVINCI_MCASP_PDSET_REG                0x1c
+
+#define DAVINCI_MCASP_PDCLR_REG                0x20
+
+#define DAVINCI_MCASP_TLGC_REG         0x30
+#define DAVINCI_MCASP_TLMR_REG         0x34
+
+#define DAVINCI_MCASP_GBLCTL_REG       0x44
+#define DAVINCI_MCASP_AMUTE_REG                0x48
+#define DAVINCI_MCASP_LBCTL_REG                0x4c
+
+#define DAVINCI_MCASP_TXDITCTL_REG     0x50
+
+#define DAVINCI_MCASP_GBLCTLR_REG      0x60
+#define DAVINCI_MCASP_RXMASK_REG       0x64
+#define DAVINCI_MCASP_RXFMT_REG                0x68
+#define DAVINCI_MCASP_RXFMCTL_REG      0x6c
+
+#define DAVINCI_MCASP_ACLKRCTL_REG     0x70
+#define DAVINCI_MCASP_AHCLKRCTL_REG    0x74
+#define DAVINCI_MCASP_RXTDM_REG                0x78
+#define DAVINCI_MCASP_EVTCTLR_REG      0x7c
+
+#define DAVINCI_MCASP_RXSTAT_REG       0x80
+#define DAVINCI_MCASP_RXTDMSLOT_REG    0x84
+#define DAVINCI_MCASP_RXCLKCHK_REG     0x88
+#define DAVINCI_MCASP_REVTCTL_REG      0x8c
+
+#define DAVINCI_MCASP_GBLCTLX_REG      0xa0
+#define DAVINCI_MCASP_TXMASK_REG       0xa4
+#define DAVINCI_MCASP_TXFMT_REG                0xa8
+#define DAVINCI_MCASP_TXFMCTL_REG      0xac
+
+#define DAVINCI_MCASP_ACLKXCTL_REG     0xb0
+#define DAVINCI_MCASP_AHCLKXCTL_REG    0xb4
+#define DAVINCI_MCASP_TXTDM_REG                0xb8
+#define DAVINCI_MCASP_EVTCTLX_REG      0xbc
+
+#define DAVINCI_MCASP_TXSTAT_REG       0xc0
+#define DAVINCI_MCASP_TXTDMSLOT_REG    0xc4
+#define DAVINCI_MCASP_TXCLKCHK_REG     0xc8
+#define DAVINCI_MCASP_XEVTCTL_REG      0xcc
+
+/* Left(even TDM Slot) Channel Status Register File */
+#define DAVINCI_MCASP_DITCSRA_REG      0x100
+/* Right(odd TDM slot) Channel Status Register File */
+#define DAVINCI_MCASP_DITCSRB_REG      0x118
+/* Left(even TDM slot) User Data Register File */
+#define DAVINCI_MCASP_DITUDRA_REG      0x130
+/* Right(odd TDM Slot) User Data Register File */
+#define DAVINCI_MCASP_DITUDRB_REG      0x148
+
+/* Serializer n Control Register */
+#define DAVINCI_MCASP_XRSRCTL_BASE_REG 0x180
+#define DAVINCI_MCASP_XRSRCTL_REG(n)   (DAVINCI_MCASP_XRSRCTL_BASE_REG + \
+                                               (n << 2))
+
+/* Transmit Buffer for Serializer n */
+#define DAVINCI_MCASP_TXBUF_REG                0x200
+/* Receive Buffer for Serializer n */
+#define DAVINCI_MCASP_RXBUF_REG                0x280
+
+/* McASP FIFO Registers */
+#define DAVINCI_MCASP_V2_AFIFO_BASE    (0x1010)
+#define DAVINCI_MCASP_V3_AFIFO_BASE    (0x1000)
+
+/* FIFO register offsets from AFIFO base */
+#define MCASP_WFIFOCTL_OFFSET          (0x0)
+#define MCASP_WFIFOSTS_OFFSET          (0x4)
+#define MCASP_RFIFOCTL_OFFSET          (0x8)
+#define MCASP_RFIFOSTS_OFFSET          (0xc)
+
+/*
+ * DAVINCI_MCASP_PWREMUMGT_REG - Power Down and Emulation Management
+ *     Register Bits
+ */
+#define MCASP_FREE     BIT(0)
+#define MCASP_SOFT     BIT(1)
+
+/*
+ * DAVINCI_MCASP_PFUNC_REG - Pin Function / GPIO Enable Register Bits
+ */
+#define AXR(n)         (1<<n)
+#define PFUNC_AMUTE    BIT(25)
+#define ACLKX          BIT(26)
+#define AHCLKX         BIT(27)
+#define AFSX           BIT(28)
+#define ACLKR          BIT(29)
+#define AHCLKR         BIT(30)
+#define AFSR           BIT(31)
+
+/*
+ * DAVINCI_MCASP_PDIR_REG - Pin Direction Register Bits
+ */
+#define AXR(n)         (1<<n)
+#define PDIR_AMUTE     BIT(25)
+#define ACLKX          BIT(26)
+#define AHCLKX         BIT(27)
+#define AFSX           BIT(28)
+#define ACLKR          BIT(29)
+#define AHCLKR         BIT(30)
+#define AFSR           BIT(31)
+
+/*
+ * DAVINCI_MCASP_TXDITCTL_REG - Transmit DIT Control Register Bits
+ */
+#define DITEN  BIT(0)  /* Transmit DIT mode enable/disable */
+#define VA     BIT(2)
+#define VB     BIT(3)
+
+/*
+ * DAVINCI_MCASP_TXFMT_REG - Transmit Bitstream Format Register Bits
+ */
+#define TXROT(val)     (val)
+#define TXSEL          BIT(3)
+#define TXSSZ(val)     (val<<4)
+#define TXPBIT(val)    (val<<8)
+#define TXPAD(val)     (val<<13)
+#define TXORD          BIT(15)
+#define FSXDLY(val)    (val<<16)
+
+/*
+ * DAVINCI_MCASP_RXFMT_REG - Receive Bitstream Format Register Bits
+ */
+#define RXROT(val)     (val)
+#define RXSEL          BIT(3)
+#define RXSSZ(val)     (val<<4)
+#define RXPBIT(val)    (val<<8)
+#define RXPAD(val)     (val<<13)
+#define RXORD          BIT(15)
+#define FSRDLY(val)    (val<<16)
+
+/*
+ * DAVINCI_MCASP_TXFMCTL_REG -  Transmit Frame Control Register Bits
+ */
+#define FSXPOL         BIT(0)
+#define AFSXE          BIT(1)
+#define FSXDUR         BIT(4)
+#define FSXMOD(val)    (val<<7)
+
+/*
+ * DAVINCI_MCASP_RXFMCTL_REG - Receive Frame Control Register Bits
+ */
+#define FSRPOL         BIT(0)
+#define AFSRE          BIT(1)
+#define FSRDUR         BIT(4)
+#define FSRMOD(val)    (val<<7)
+
+/*
+ * DAVINCI_MCASP_ACLKXCTL_REG - Transmit Clock Control Register Bits
+ */
+#define ACLKXDIV(val)  (val)
+#define ACLKXE         BIT(5)
+#define TX_ASYNC       BIT(6)
+#define ACLKXPOL       BIT(7)
+#define ACLKXDIV_MASK  0x1f
+
+/*
+ * DAVINCI_MCASP_ACLKRCTL_REG Receive Clock Control Register Bits
+ */
+#define ACLKRDIV(val)  (val)
+#define ACLKRE         BIT(5)
+#define RX_ASYNC       BIT(6)
+#define ACLKRPOL       BIT(7)
+#define ACLKRDIV_MASK  0x1f
+
+/*
+ * DAVINCI_MCASP_AHCLKXCTL_REG - High Frequency Transmit Clock Control
+ *     Register Bits
+ */
+#define AHCLKXDIV(val) (val)
+#define AHCLKXPOL      BIT(14)
+#define AHCLKXE                BIT(15)
+#define AHCLKXDIV_MASK 0xfff
+
+/*
+ * DAVINCI_MCASP_AHCLKRCTL_REG - High Frequency Receive Clock Control
+ *     Register Bits
+ */
+#define AHCLKRDIV(val) (val)
+#define AHCLKRPOL      BIT(14)
+#define AHCLKRE                BIT(15)
+#define AHCLKRDIV_MASK 0xfff
+
+/*
+ * DAVINCI_MCASP_XRSRCTL_BASE_REG -  Serializer Control Register Bits
+ */
+#define MODE(val)      (val)
+#define DISMOD         (val)(val<<2)
+#define TXSTATE                BIT(4)
+#define RXSTATE                BIT(5)
+#define SRMOD_MASK     3
+#define SRMOD_INACTIVE 0
+
+/*
+ * DAVINCI_MCASP_LBCTL_REG - Loop Back Control Register Bits
+ */
+#define LBEN           BIT(0)
+#define LBORD          BIT(1)
+#define LBGENMODE(val) (val<<2)
+
+/*
+ * DAVINCI_MCASP_TXTDMSLOT_REG - Transmit TDM Slot Register configuration
+ */
+#define TXTDMS(n)      (1<<n)
+
+/*
+ * DAVINCI_MCASP_RXTDMSLOT_REG - Receive TDM Slot Register configuration
+ */
+#define RXTDMS(n)      (1<<n)
+
+/*
+ * DAVINCI_MCASP_GBLCTL_REG -  Global Control Register Bits
+ */
+#define RXCLKRST       BIT(0)  /* Receiver Clock Divider Reset */
+#define RXHCLKRST      BIT(1)  /* Receiver High Frequency Clock Divider */
+#define RXSERCLR       BIT(2)  /* Receiver Serializer Clear */
+#define RXSMRST                BIT(3)  /* Receiver State Machine Reset */
+#define RXFSRST                BIT(4)  /* Frame Sync Generator Reset */
+#define TXCLKRST       BIT(8)  /* Transmitter Clock Divider Reset */
+#define TXHCLKRST      BIT(9)  /* Transmitter High Frequency Clock Divider*/
+#define TXSERCLR       BIT(10) /* Transmit Serializer Clear */
+#define TXSMRST                BIT(11) /* Transmitter State Machine Reset */
+#define TXFSRST                BIT(12) /* Frame Sync Generator Reset */
+
+/*
+ * DAVINCI_MCASP_AMUTE_REG -  Mute Control Register Bits
+ */
+#define MUTENA(val)    (val)
+#define MUTEINPOL      BIT(2)
+#define MUTEINENA      BIT(3)
+#define MUTEIN         BIT(4)
+#define MUTER          BIT(5)
+#define MUTEX          BIT(6)
+#define MUTEFSR                BIT(7)
+#define MUTEFSX                BIT(8)
+#define MUTEBADCLKR    BIT(9)
+#define MUTEBADCLKX    BIT(10)
+#define MUTERXDMAERR   BIT(11)
+#define MUTETXDMAERR   BIT(12)
+
+/*
+ * DAVINCI_MCASP_REVTCTL_REG - Receiver DMA Event Control Register bits
+ */
+#define RXDATADMADIS   BIT(0)
+
+/*
+ * DAVINCI_MCASP_XEVTCTL_REG - Transmitter DMA Event Control Register bits
+ */
+#define TXDATADMADIS   BIT(0)
+
+/*
+ * DAVINCI_MCASP_W[R]FIFOCTL - Write/Read FIFO Control Register bits
+ */
+#define FIFO_ENABLE    BIT(16)
+#define NUMEVT_MASK    (0xFF << 8)
+#define NUMDMA_MASK    (0xFF)
 
 #endif /* DAVINCI_MCASP_H */
index 55193a5596ca6fe4aa3b0c53170d71f4f1a6c355..4d075f1abe7803387bb01dbb39a2d66a0eac4c59 100644 (file)
@@ -1181,13 +1181,6 @@ static int fsl_spdif_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int fsl_spdif_remove(struct platform_device *pdev)
-{
-       imx_pcm_dma_exit(pdev);
-
-       return 0;
-}
-
 static const struct of_device_id fsl_spdif_dt_ids[] = {
        { .compatible = "fsl,imx35-spdif", },
        {}
@@ -1201,7 +1194,6 @@ static struct platform_driver fsl_spdif_driver = {
                .of_match_table = fsl_spdif_dt_ids,
        },
        .probe = fsl_spdif_probe,
-       .remove = fsl_spdif_remove,
 };
 
 module_platform_driver(fsl_spdif_driver);
index 35e277379b86ce80d56737e3e0c05a5b3772fb2c..a158b4db2f08515edac14a3b49dda30cc3bfe08e 100644 (file)
@@ -119,8 +119,6 @@ static inline void write_ssi_mask(u32 __iomem *addr, u32 clear, u32 set)
  * @ssi: pointer to the SSI's registers
  * @ssi_phys: physical address of the SSI registers
  * @irq: IRQ of this SSI
- * @first_stream: pointer to the stream that was opened first
- * @second_stream: pointer to second stream
  * @playback: the number of playback streams opened
  * @capture: the number of capture streams opened
  * @cpu_dai: the CPU DAI for this device
@@ -132,8 +130,6 @@ struct fsl_ssi_private {
        struct ccsr_ssi __iomem *ssi;
        dma_addr_t ssi_phys;
        unsigned int irq;
-       struct snd_pcm_substream *first_stream;
-       struct snd_pcm_substream *second_stream;
        unsigned int fifo_depth;
        struct snd_soc_dai_driver cpu_dai_drv;
        struct device_attribute dev_attr;
@@ -143,6 +139,8 @@ struct fsl_ssi_private {
        bool ssi_on_imx;
        bool imx_ac97;
        bool use_dma;
+       bool use_dual_fifo;
+       u8 i2s_mode;
        struct clk *clk;
        struct snd_dmaengine_dai_dma_data dma_params_tx;
        struct snd_dmaengine_dai_dma_data dma_params_rx;
@@ -321,17 +319,46 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
        return ret;
 }
 
+static void fsl_ssi_setup_ac97(struct fsl_ssi_private *ssi_private)
+{
+       struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
+
+       /*
+        * Setup the clock control register
+        */
+       write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13),
+                       &ssi->stccr);
+       write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13),
+                       &ssi->srccr);
+
+       /*
+        * Enable AC97 mode and startup the SSI
+        */
+       write_ssi(CCSR_SSI_SACNT_AC97EN | CCSR_SSI_SACNT_FV,
+                       &ssi->sacnt);
+       write_ssi(0xff, &ssi->saccdis);
+       write_ssi(0x300, &ssi->saccen);
+
+       /*
+        * Enable SSI, Transmit and Receive. AC97 has to communicate with the
+        * codec before a stream is started.
+        */
+       write_ssi_mask(&ssi->scr, 0, CCSR_SSI_SCR_SSIEN |
+                       CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE);
+
+       write_ssi(CCSR_SSI_SOR_WAIT(3), &ssi->sor);
+}
+
 static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private)
 {
        struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
-       u8 i2s_mode;
        u8 wm;
        int synchronous = ssi_private->cpu_dai_drv.symmetric_rates;
 
        if (ssi_private->imx_ac97)
-               i2s_mode = CCSR_SSI_SCR_I2S_MODE_NORMAL | CCSR_SSI_SCR_NET;
+               ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_NORMAL | CCSR_SSI_SCR_NET;
        else
-               i2s_mode = CCSR_SSI_SCR_I2S_MODE_SLAVE;
+               ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_SLAVE;
 
        /*
         * Section 16.5 of the MPC8610 reference manual says that the SSI needs
@@ -348,7 +375,7 @@ static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private)
        write_ssi_mask(&ssi->scr,
                CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN,
                CCSR_SSI_SCR_TFR_CLK_DIS |
-               i2s_mode |
+               ssi_private->i2s_mode |
                (synchronous ? CCSR_SSI_SCR_SYN : 0));
 
        write_ssi(CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 |
@@ -387,30 +414,13 @@ static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private)
         * because it is also running without an active substream. Normally SSI
         * is only enabled when there is a substream.
         */
-       if (ssi_private->imx_ac97) {
-               /*
-                * Setup the clock control register
-                */
-               write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13),
-                               &ssi->stccr);
-               write_ssi(CCSR_SSI_SxCCR_WL(17) | CCSR_SSI_SxCCR_DC(13),
-                               &ssi->srccr);
-
-               /*
-                * Enable AC97 mode and startup the SSI
-                */
-               write_ssi(CCSR_SSI_SACNT_AC97EN | CCSR_SSI_SACNT_FV,
-                               &ssi->sacnt);
-               write_ssi(0xff, &ssi->saccdis);
-               write_ssi(0x300, &ssi->saccen);
-
-               /*
-                * Enable SSI, Transmit and Receive
-                */
-               write_ssi_mask(&ssi->scr, 0, CCSR_SSI_SCR_SSIEN |
-                               CCSR_SSI_SCR_TE | CCSR_SSI_SCR_RE);
+       if (ssi_private->imx_ac97)
+               fsl_ssi_setup_ac97(ssi_private);
 
-               write_ssi(CCSR_SSI_SOR_WAIT(3), &ssi->sor);
+       if (ssi_private->use_dual_fifo) {
+               write_ssi_mask(&ssi->srcr, 0, CCSR_SSI_SRCR_RFEN1);
+               write_ssi_mask(&ssi->stcr, 0, CCSR_SSI_STCR_TFEN1);
+               write_ssi_mask(&ssi->scr, 0, CCSR_SSI_SCR_TCH_EN);
        }
 
        return 0;
@@ -431,54 +441,22 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct fsl_ssi_private *ssi_private =
                snd_soc_dai_get_drvdata(rtd->cpu_dai);
-       int synchronous = ssi_private->cpu_dai_drv.symmetric_rates;
 
-       /*
-        * If this is the first stream opened, then request the IRQ
-        * and initialize the SSI registers.
+       /* First, we only do fsl_ssi_setup() when SSI is going to be active.
+        * Second, fsl_ssi_setup was already called by ac97_init earlier if
+        * the driver is in ac97 mode.
         */
-       if (!ssi_private->first_stream) {
-               ssi_private->first_stream = substream;
+       if (!dai->active && !ssi_private->imx_ac97)
+               fsl_ssi_setup(ssi_private);
 
-               /*
-                * fsl_ssi_setup was already called by ac97_init earlier if
-                * the driver is in ac97 mode.
-                */
-               if (!ssi_private->imx_ac97)
-                       fsl_ssi_setup(ssi_private);
-       } else {
-               if (synchronous) {
-                       struct snd_pcm_runtime *first_runtime =
-                               ssi_private->first_stream->runtime;
-                       /*
-                        * This is the second stream open, and we're in
-                        * synchronous mode, so we need to impose sample
-                        * sample size constraints. This is because STCCR is
-                        * used for playback and capture in synchronous mode,
-                        * so there's no way to specify different word
-                        * lengths.
-                        *
-                        * Note that this can cause a race condition if the
-                        * second stream is opened before the first stream is
-                        * fully initialized.  We provide some protection by
-                        * checking to make sure the first stream is
-                        * initialized, but it's not perfect.  ALSA sometimes
-                        * re-initializes the driver with a different sample
-                        * rate or size.  If the second stream is opened
-                        * before the first stream has received its final
-                        * parameters, then the second stream may be
-                        * constrained to the wrong sample rate or size.
-                        */
-                       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;
-       }
+       /* When using dual fifo mode, it is safer to ensure an even period
+        * size. If appearing to an odd number while DMA always starts its
+        * task from fifo0, fifo1 would be neglected at the end of each
+        * period. But SSI would still access fifo1 with an invalid data.
+        */
+       if (ssi_private->use_dual_fifo)
+               snd_pcm_hw_constraint_step(substream->runtime, 0,
+                               SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 2);
 
        return 0;
 }
@@ -501,6 +479,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
 {
        struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
        struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
+       unsigned int channels = params_channels(hw_params);
        unsigned int sample_size =
                snd_pcm_format_width(params_format(hw_params));
        u32 wl = CCSR_SSI_SxCCR_WL(sample_size);
@@ -530,6 +509,11 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
        else
                write_ssi_mask(&ssi->srccr, CCSR_SSI_SxCCR_WL_MASK, wl);
 
+       if (!ssi_private->imx_ac97)
+               write_ssi_mask(&ssi->scr,
+                               CCSR_SSI_SCR_NET | CCSR_SSI_SCR_I2S_MODE_MASK,
+                               channels == 1 ? 0 : ssi_private->i2s_mode);
+
        return 0;
 }
 
@@ -602,23 +586,6 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
        return 0;
 }
 
-/**
- * fsl_ssi_shutdown: shutdown the SSI
- *
- * Shutdown the SSI if there are no other substreams open.
- */
-static void fsl_ssi_shutdown(struct snd_pcm_substream *substream,
-                            struct snd_soc_dai *dai)
-{
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai);
-
-       if (ssi_private->first_stream == substream)
-               ssi_private->first_stream = ssi_private->second_stream;
-
-       ssi_private->second_stream = NULL;
-}
-
 static int fsl_ssi_dai_probe(struct snd_soc_dai *dai)
 {
        struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(dai);
@@ -634,7 +601,6 @@ static int fsl_ssi_dai_probe(struct snd_soc_dai *dai)
 static const struct snd_soc_dai_ops fsl_ssi_dai_ops = {
        .startup        = fsl_ssi_startup,
        .hw_params      = fsl_ssi_hw_params,
-       .shutdown       = fsl_ssi_shutdown,
        .trigger        = fsl_ssi_trigger,
 };
 
@@ -642,14 +608,13 @@ static const struct snd_soc_dai_ops fsl_ssi_dai_ops = {
 static struct snd_soc_dai_driver fsl_ssi_dai_template = {
        .probe = fsl_ssi_dai_probe,
        .playback = {
-               /* The SSI does not support monaural audio. */
-               .channels_min = 2,
+               .channels_min = 1,
                .channels_max = 2,
                .rates = FSLSSI_I2S_RATES,
                .formats = FSLSSI_I2S_FORMATS,
        },
        .capture = {
-               .channels_min = 2,
+               .channels_min = 1,
                .channels_max = 2,
                .rates = FSLSSI_I2S_RATES,
                .formats = FSLSSI_I2S_FORMATS,
@@ -710,7 +675,6 @@ static int fsl_ssi_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
 
 static const struct snd_soc_dai_ops fsl_ssi_ac97_dai_ops = {
        .startup        = fsl_ssi_startup,
-       .shutdown       = fsl_ssi_shutdown,
        .trigger        = fsl_ssi_ac97_trigger,
 };
 
@@ -935,8 +899,11 @@ static int fsl_ssi_probe(struct platform_device *pdev)
        }
 
        /* Are the RX and the TX clocks locked? */
-       if (!of_find_property(np, "fsl,ssi-asynchronous", NULL))
+       if (!of_find_property(np, "fsl,ssi-asynchronous", NULL)) {
                ssi_private->cpu_dai_drv.symmetric_rates = 1;
+               ssi_private->cpu_dai_drv.symmetric_channels = 1;
+               ssi_private->cpu_dai_drv.symmetric_samplebits = 1;
+       }
 
        /* Determine the FIFO depth. */
        iprop = of_get_property(np, "fsl,fifo-depth", NULL);
@@ -947,7 +914,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
                ssi_private->fifo_depth = 8;
 
        if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx21-ssi")) {
-               u32 dma_events[2];
+               u32 dma_events[2], dmas[4];
                ssi_private->ssi_on_imx = true;
 
                ssi_private->clk = devm_clk_get(&pdev->dev, NULL);
@@ -1001,6 +968,15 @@ static int fsl_ssi_probe(struct platform_device *pdev)
                        dma_events[0], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI);
                imx_pcm_dma_params_init_data(&ssi_private->filter_data_rx,
                        dma_events[1], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI);
+               if (!of_property_read_u32_array(pdev->dev.of_node, "dmas", dmas, 4)
+                               && dmas[2] == IMX_DMATYPE_SSI_DUAL) {
+                       ssi_private->use_dual_fifo = true;
+                       /* When using dual fifo mode, we need to keep watermark
+                        * as even numbers due to dma script limitation.
+                        */
+                       ssi_private->dma_params_tx.maxburst &= ~0x1;
+                       ssi_private->dma_params_rx.maxburst &= ~0x1;
+               }
        } else if (ssi_private->use_dma) {
                /* The 'name' should not have any slashes in it. */
                ret = devm_request_irq(&pdev->dev, ssi_private->irq,
@@ -1102,8 +1078,6 @@ done:
        return 0;
 
 error_dai:
-       if (ssi_private->ssi_on_imx)
-               imx_pcm_dma_exit(pdev);
        snd_soc_unregister_component(&pdev->dev);
 
 error_dev:
@@ -1125,8 +1099,6 @@ static int fsl_ssi_remove(struct platform_device *pdev)
 
        if (!ssi_private->new_binding)
                platform_device_unregister(ssi_private->pdev);
-       if (ssi_private->ssi_on_imx)
-               imx_pcm_dma_exit(pdev);
        snd_soc_unregister_component(&pdev->dev);
        device_remove_file(&pdev->dev, &ssi_private->dev_attr);
        if (ssi_private->ssi_on_imx)
index aee23077080a219983f0dd52764d1aa4199cb15c..c5e47f866b4b756beaa515b1c29ba4177572cb10 100644 (file)
@@ -61,16 +61,11 @@ static const struct snd_dmaengine_pcm_config imx_dmaengine_pcm_config = {
 
 int imx_pcm_dma_init(struct platform_device *pdev)
 {
-       return snd_dmaengine_pcm_register(&pdev->dev, &imx_dmaengine_pcm_config,
+       return devm_snd_dmaengine_pcm_register(&pdev->dev,
+               &imx_dmaengine_pcm_config,
                SND_DMAENGINE_PCM_FLAG_NO_RESIDUE |
                SND_DMAENGINE_PCM_FLAG_COMPAT);
 }
 EXPORT_SYMBOL_GPL(imx_pcm_dma_init);
 
-void imx_pcm_dma_exit(struct platform_device *pdev)
-{
-       snd_dmaengine_pcm_unregister(&pdev->dev);
-}
-EXPORT_SYMBOL_GPL(imx_pcm_dma_exit);
-
 MODULE_LICENSE("GPL");
index 5d5b73303e1169b7f6c2254e06d66a87409050cc..c79cb27473be771d9ee355cacf52229f5da6c40d 100644 (file)
@@ -40,16 +40,11 @@ struct imx_pcm_fiq_params {
 
 #if IS_ENABLED(CONFIG_SND_SOC_IMX_PCM_DMA)
 int imx_pcm_dma_init(struct platform_device *pdev);
-void imx_pcm_dma_exit(struct platform_device *pdev);
 #else
 static inline int imx_pcm_dma_init(struct platform_device *pdev)
 {
        return -ENODEV;
 }
-
-static inline void imx_pcm_dma_exit(struct platform_device *pdev)
-{
-}
 #endif
 
 #if IS_ENABLED(CONFIG_SND_SOC_IMX_PCM_FIQ)
index 8499d5292f088a45e9ea736106ee2db13e7d205a..980dd1fc9113c33f1c991fed2983d6cbc289fcd8 100644 (file)
@@ -35,7 +35,6 @@ static int imx_spdif_audio_probe(struct platform_device *pdev)
 
        data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
        if (!data) {
-               dev_err(&pdev->dev, "failed to allocate memory\n");
                ret = -ENOMEM;
                goto end;
        }
index f5f248c91c16db7c3db5a50654bceedb0e81953f..df552fa1aa65f13faee928c63d2a8b8bf6c9eae4 100644 (file)
@@ -304,8 +304,7 @@ static int imx_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
                        scr |= SSI_SCR_RE;
                sier |= sier_bits;
 
-               if (++ssi->enabled == 1)
-                       scr |= SSI_SCR_SSIEN;
+               scr |= SSI_SCR_SSIEN;
 
                break;
 
@@ -318,7 +317,7 @@ static int imx_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
                        scr &= ~SSI_SCR_RE;
                sier &= ~sier_bits;
 
-               if (--ssi->enabled == 0)
+               if (!(scr & (SSI_SCR_TE | SSI_SCR_RE)))
                        scr &= ~SSI_SCR_SSIEN;
 
                break;
@@ -536,7 +535,9 @@ static int imx_ssi_probe(struct platform_device *pdev)
                        ret);
                goto failed_clk;
        }
-       clk_prepare_enable(ssi->clk);
+       ret = clk_prepare_enable(ssi->clk);
+       if (ret)
+               goto failed_clk;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        ssi->base = devm_ioremap_resource(&pdev->dev, res);
@@ -624,9 +625,6 @@ static int imx_ssi_remove(struct platform_device *pdev)
 {
        struct imx_ssi *ssi = platform_get_drvdata(pdev);
 
-       if (!ssi->dma_init)
-               imx_pcm_dma_exit(pdev);
-
        if (!ssi->fiq_init)
                imx_pcm_fiq_exit(pdev);
 
index 560c40fc9ebbb50241e3732f3a76ece064178bf2..be6562365b6a971a08efe55e3c1d7c49f0c0a874 100644 (file)
@@ -213,7 +213,6 @@ struct imx_ssi {
 
        int fiq_init;
        int dma_init;
-       int enabled;
 };
 
 #endif /* _IMX_SSI_H */
index 61e48852b9e8bd21b26eec98cca4fc9ba0eea145..3fd76bc391de19a2431dd320d0abfbdcd9616cf5 100644 (file)
@@ -130,8 +130,6 @@ static int imx_wm8962_set_bias_level(struct snd_soc_card *card,
                break;
        }
 
-       dapm->bias_level = level;
-
        return 0;
 }
 
index eb4373840bb6e1ab2cbbb1e5e9220e1c8474cb29..3665f612819d4bd2d443b0e7072cf9753ee1905b 100644 (file)
@@ -69,7 +69,6 @@ static int pcm030_fabric_probe(struct platform_device *op)
                return -ENOMEM;
 
        card->dev = &op->dev;
-       platform_set_drvdata(op, pdata);
 
        pdata->card = card;
 
@@ -98,6 +97,8 @@ static int pcm030_fabric_probe(struct platform_device *op)
        if (ret)
                dev_err(&op->dev, "snd_soc_register_card() failed: %d\n", ret);
 
+       platform_set_drvdata(op, pdata);
+
        return ret;
 }
 
index b2fbb7075a6c9900aac6aea847b63242a359a5a7..7a9b6b4898c02dde4dcca9669bfb6ff93e226651 100644 (file)
@@ -8,7 +8,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
+#include <linux/clk.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/module.h>
 #include <sound/simple_card.h>
@@ -57,11 +58,144 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd)
        return 0;
 }
 
+static int
+asoc_simple_card_sub_parse_of(struct device_node *np,
+                             struct asoc_simple_dai *dai,
+                             struct device_node **node)
+{
+       struct clk *clk;
+       int ret;
+
+       /*
+        * get node via "sound-dai = <&phandle port>"
+        * it will be used as xxx_of_node on soc_bind_dai_link()
+        */
+       *node = of_parse_phandle(np, "sound-dai", 0);
+       if (!*node)
+               return -ENODEV;
+
+       /* get dai->name */
+       ret = snd_soc_of_get_dai_name(np, &dai->name);
+       if (ret < 0)
+               goto parse_error;
+
+       /*
+        * bitclock-inversion, frame-inversion
+        * bitclock-master,    frame-master
+        * and specific "format" if it has
+        */
+       dai->fmt = snd_soc_of_parse_daifmt(np, NULL);
+
+       /*
+        * dai->sysclk come from
+        *  "clocks = <&xxx>" (if system has common clock)
+        *  or "system-clock-frequency = <xxx>"
+        */
+       clk = of_clk_get(np, 0);
+       if (IS_ERR(clk))
+               of_property_read_u32(np,
+                                    "system-clock-frequency",
+                                    &dai->sysclk);
+       else
+               dai->sysclk = clk_get_rate(clk);
+
+       ret = 0;
+
+parse_error:
+       of_node_put(*node);
+
+       return ret;
+}
+
+static int asoc_simple_card_parse_of(struct device_node *node,
+                                    struct asoc_simple_card_info *info,
+                                    struct device *dev,
+                                    struct device_node **of_cpu,
+                                    struct device_node **of_codec,
+                                    struct device_node **of_platform)
+{
+       struct device_node *np;
+       char *name;
+       int ret = 0;
+
+       /* get CPU/CODEC common format via simple-audio-card,format */
+       info->daifmt = snd_soc_of_parse_daifmt(node, "simple-audio-card,") &
+               (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK);
+
+       /* CPU sub-node */
+       ret = -EINVAL;
+       np = of_get_child_by_name(node, "simple-audio-card,cpu");
+       if (np)
+               ret = asoc_simple_card_sub_parse_of(np,
+                                                 &info->cpu_dai,
+                                                 of_cpu);
+       if (ret < 0)
+               return ret;
+
+       /* CODEC sub-node */
+       ret = -EINVAL;
+       np = of_get_child_by_name(node, "simple-audio-card,codec");
+       if (np)
+               ret = asoc_simple_card_sub_parse_of(np,
+                                                 &info->codec_dai,
+                                                 of_codec);
+       if (ret < 0)
+               return ret;
+
+       /* card name is created from CPU/CODEC dai name */
+       name = devm_kzalloc(dev,
+                           strlen(info->cpu_dai.name)   +
+                           strlen(info->codec_dai.name) + 2,
+                           GFP_KERNEL);
+       sprintf(name, "%s-%s", info->cpu_dai.name, info->codec_dai.name);
+       info->name = info->card = name;
+
+       /* simple-card assumes platform == cpu */
+       *of_platform = *of_cpu;
+
+       dev_dbg(dev, "card-name : %s\n", info->card);
+       dev_dbg(dev, "platform : %04x\n", info->daifmt);
+       dev_dbg(dev, "cpu : %s / %04x / %d\n",
+               info->cpu_dai.name,
+               info->cpu_dai.fmt,
+               info->cpu_dai.sysclk);
+       dev_dbg(dev, "codec : %s / %04x / %d\n",
+               info->codec_dai.name,
+               info->codec_dai.fmt,
+               info->codec_dai.sysclk);
+
+       return 0;
+}
+
 static int asoc_simple_card_probe(struct platform_device *pdev)
 {
-       struct asoc_simple_card_info *cinfo = pdev->dev.platform_data;
+       struct asoc_simple_card_info *cinfo;
+       struct device_node *np = pdev->dev.of_node;
+       struct device_node *of_cpu, *of_codec, *of_platform;
        struct device *dev = &pdev->dev;
 
+       cinfo           = NULL;
+       of_cpu          = NULL;
+       of_codec        = NULL;
+       of_platform     = NULL;
+       if (np && of_device_is_available(np)) {
+               cinfo = devm_kzalloc(dev, sizeof(*cinfo), GFP_KERNEL);
+               if (cinfo) {
+                       int ret;
+                       ret = asoc_simple_card_parse_of(np, cinfo, dev,
+                                                       &of_cpu,
+                                                       &of_codec,
+                                                       &of_platform);
+                       if (ret < 0) {
+                               if (ret != -EPROBE_DEFER)
+                                       dev_err(dev, "parse error %d\n", ret);
+                               return ret;
+                       }
+               }
+       } else {
+               cinfo = pdev->dev.platform_data;
+       }
+
        if (!cinfo) {
                dev_err(dev, "no info for asoc-simple-card\n");
                return -EINVAL;
@@ -69,10 +203,10 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
 
        if (!cinfo->name        ||
            !cinfo->card        ||
-           !cinfo->codec       ||
-           !cinfo->platform    ||
-           !cinfo->cpu_dai.name ||
-           !cinfo->codec_dai.name) {
+           !cinfo->codec_dai.name      ||
+           !(cinfo->codec              || of_codec)    ||
+           !(cinfo->platform           || of_platform) ||
+           !(cinfo->cpu_dai.name       || of_cpu)) {
                dev_err(dev, "insufficient asoc_simple_card_info settings\n");
                return -EINVAL;
        }
@@ -86,6 +220,9 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
        cinfo->snd_link.platform_name   = cinfo->platform;
        cinfo->snd_link.codec_name      = cinfo->codec;
        cinfo->snd_link.codec_dai_name  = cinfo->codec_dai.name;
+       cinfo->snd_link.cpu_of_node     = of_cpu;
+       cinfo->snd_link.codec_of_node   = of_codec;
+       cinfo->snd_link.platform_of_node = of_platform;
        cinfo->snd_link.init            = asoc_simple_card_dai_init;
 
        /*
@@ -107,10 +244,17 @@ static int asoc_simple_card_remove(struct platform_device *pdev)
        return snd_soc_unregister_card(&cinfo->snd_card);
 }
 
+static const struct of_device_id asoc_simple_of_match[] = {
+       { .compatible = "simple-audio-card", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, asoc_simple_of_match);
+
 static struct platform_driver asoc_simple_card = {
        .driver = {
                .name   = "asoc-simple-card",
                .owner = THIS_MODULE,
+               .of_match_table = asoc_simple_of_match,
        },
        .probe          = asoc_simple_card_probe,
        .remove         = asoc_simple_card_remove,
index 5351cba66c9e3584e39263e49137afb9260ed1ab..29f76af5d963c2fca31366e7140c21239d18a0f0 100644 (file)
@@ -1,6 +1,7 @@
 config SND_JZ4740_SOC
        tristate "SoC Audio for Ingenic JZ4740 SoC"
        depends on MACH_JZ4740 && SND_SOC
+       select SND_SOC_GENERIC_DMAENGINE_PCM
        help
          Say Y or M if you want to add support for codecs attached to
          the JZ4740 I2S interface. You will also need to select the audio
index 4c849a49c72ac3c6c6800aebec9292b3785be37c..8f220009e0f616e0572777c19a15c3a44c658ed8 100644 (file)
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
 #include <sound/initval.h>
+#include <sound/dmaengine_pcm.h>
+
+#include <asm/mach-jz4740/dma.h>
 
 #include "jz4740-i2s.h"
-#include "jz4740-pcm.h"
 
 #define JZ_REG_AIC_CONF                0x00
 #define JZ_REG_AIC_CTRL                0x04
@@ -89,8 +91,8 @@ struct jz4740_i2s {
        struct clk *clk_aic;
        struct clk *clk_i2s;
 
-       struct jz4740_pcm_config pcm_config_playback;
-       struct jz4740_pcm_config pcm_config_capture;
+       struct snd_dmaengine_dai_dma_data playback_dma_data;
+       struct snd_dmaengine_dai_dma_data capture_dma_data;
 };
 
 static inline uint32_t jz4740_i2s_read(const struct jz4740_i2s *i2s,
@@ -233,8 +235,6 @@ static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
 {
        struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);
-       enum jz4740_dma_width dma_width;
-       struct jz4740_pcm_config *pcm_config;
        unsigned int sample_size;
        uint32_t ctrl;
 
@@ -243,11 +243,9 @@ static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream,
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S8:
                sample_size = 0;
-               dma_width = JZ4740_DMA_WIDTH_8BIT;
                break;
        case SNDRV_PCM_FORMAT_S16:
                sample_size = 1;
-               dma_width = JZ4740_DMA_WIDTH_16BIT;
                break;
        default:
                return -EINVAL;
@@ -260,22 +258,13 @@ static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream,
                        ctrl |= JZ_AIC_CTRL_MONO_TO_STEREO;
                else
                        ctrl &= ~JZ_AIC_CTRL_MONO_TO_STEREO;
-
-               pcm_config = &i2s->pcm_config_playback;
-               pcm_config->dma_config.dst_width = dma_width;
-
        } else {
                ctrl &= ~JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_MASK;
                ctrl |= sample_size << JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_OFFSET;
-
-               pcm_config = &i2s->pcm_config_capture;
-               pcm_config->dma_config.src_width = dma_width;
        }
 
        jz4740_i2s_write(i2s, JZ_REG_AIC_CTRL, ctrl);
 
-       snd_soc_dai_set_dma_data(dai, substream, pcm_config);
-
        return 0;
 }
 
@@ -342,25 +331,19 @@ static int jz4740_i2s_resume(struct snd_soc_dai *dai)
 
 static void jz4740_i2c_init_pcm_config(struct jz4740_i2s *i2s)
 {
-       struct jz4740_dma_config *dma_config;
+       struct snd_dmaengine_dai_dma_data *dma_data;
 
        /* Playback */
-       dma_config = &i2s->pcm_config_playback.dma_config;
-       dma_config->src_width = JZ4740_DMA_WIDTH_32BIT;
-       dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE;
-       dma_config->request_type = JZ4740_DMA_TYPE_AIC_TRANSMIT;
-       dma_config->flags = JZ4740_DMA_SRC_AUTOINC;
-       dma_config->mode = JZ4740_DMA_MODE_SINGLE;
-       i2s->pcm_config_playback.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO;
+       dma_data = &i2s->playback_dma_data;
+       dma_data->maxburst = 16;
+       dma_data->slave_id = JZ4740_DMA_TYPE_AIC_TRANSMIT;
+       dma_data->addr = i2s->phys_base + JZ_REG_AIC_FIFO;
 
        /* Capture */
-       dma_config = &i2s->pcm_config_capture.dma_config;
-       dma_config->dst_width = JZ4740_DMA_WIDTH_32BIT;
-       dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE;
-       dma_config->request_type = JZ4740_DMA_TYPE_AIC_RECEIVE;
-       dma_config->flags = JZ4740_DMA_DST_AUTOINC;
-       dma_config->mode = JZ4740_DMA_MODE_SINGLE;
-       i2s->pcm_config_capture.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO;
+       dma_data = &i2s->capture_dma_data;
+       dma_data->maxburst = 16;
+       dma_data->slave_id = JZ4740_DMA_TYPE_AIC_RECEIVE;
+       dma_data->addr = i2s->phys_base + JZ_REG_AIC_FIFO;
 }
 
 static int jz4740_i2s_dai_probe(struct snd_soc_dai *dai)
@@ -371,6 +354,8 @@ static int jz4740_i2s_dai_probe(struct snd_soc_dai *dai)
        clk_prepare_enable(i2s->clk_aic);
 
        jz4740_i2c_init_pcm_config(i2s);
+       snd_soc_dai_init_dma_data(dai, &i2s->playback_dma_data,
+               &i2s->capture_dma_data);
 
        conf = (7 << JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET) |
                (8 << JZ_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET) |
@@ -432,91 +417,41 @@ static const struct snd_soc_component_driver jz4740_i2s_component = {
 static int jz4740_i2s_dev_probe(struct platform_device *pdev)
 {
        struct jz4740_i2s *i2s;
+       struct resource *mem;
        int ret;
 
-       i2s = kzalloc(sizeof(*i2s), GFP_KERNEL);
-
+       i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL);
        if (!i2s)
                return -ENOMEM;
 
-       i2s->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!i2s->mem) {
-               ret = -ENOENT;
-               goto err_free;
-       }
-
-       i2s->mem = request_mem_region(i2s->mem->start, resource_size(i2s->mem),
-                               pdev->name);
-       if (!i2s->mem) {
-               ret = -EBUSY;
-               goto err_free;
-       }
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       i2s->base = devm_ioremap_resource(&pdev->dev, mem);
+       if (IS_ERR(i2s->base))
+               return PTR_ERR(i2s->base);
 
-       i2s->base = ioremap_nocache(i2s->mem->start, resource_size(i2s->mem));
-       if (!i2s->base) {
-               ret = -EBUSY;
-               goto err_release_mem_region;
-       }
+       i2s->phys_base = mem->start;
 
-       i2s->phys_base = i2s->mem->start;
+       i2s->clk_aic = devm_clk_get(&pdev->dev, "aic");
+       if (IS_ERR(i2s->clk_aic))
+               return PTR_ERR(i2s->clk_aic);
 
-       i2s->clk_aic = clk_get(&pdev->dev, "aic");
-       if (IS_ERR(i2s->clk_aic)) {
-               ret = PTR_ERR(i2s->clk_aic);
-               goto err_iounmap;
-       }
-
-       i2s->clk_i2s = clk_get(&pdev->dev, "i2s");
-       if (IS_ERR(i2s->clk_i2s)) {
-               ret = PTR_ERR(i2s->clk_i2s);
-               goto err_clk_put_aic;
-       }
+       i2s->clk_i2s = devm_clk_get(&pdev->dev, "i2s");
+       if (IS_ERR(i2s->clk_i2s))
+               return PTR_ERR(i2s->clk_i2s);
 
        platform_set_drvdata(pdev, i2s);
-       ret = snd_soc_register_component(&pdev->dev, &jz4740_i2s_component,
-                                        &jz4740_i2s_dai, 1);
 
-       if (ret) {
-               dev_err(&pdev->dev, "Failed to register DAI\n");
-               goto err_clk_put_i2s;
-       }
-
-       return 0;
-
-err_clk_put_i2s:
-       clk_put(i2s->clk_i2s);
-err_clk_put_aic:
-       clk_put(i2s->clk_aic);
-err_iounmap:
-       iounmap(i2s->base);
-err_release_mem_region:
-       release_mem_region(i2s->mem->start, resource_size(i2s->mem));
-err_free:
-       kfree(i2s);
-
-       return ret;
-}
+       ret = devm_snd_soc_register_component(&pdev->dev,
+               &jz4740_i2s_component, &jz4740_i2s_dai, 1);
+       if (ret)
+               return ret;
 
-static int jz4740_i2s_dev_remove(struct platform_device *pdev)
-{
-       struct jz4740_i2s *i2s = platform_get_drvdata(pdev);
-
-       snd_soc_unregister_component(&pdev->dev);
-
-       clk_put(i2s->clk_i2s);
-       clk_put(i2s->clk_aic);
-
-       iounmap(i2s->base);
-       release_mem_region(i2s->mem->start, resource_size(i2s->mem));
-
-       kfree(i2s);
-
-       return 0;
+       return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL,
+               SND_DMAENGINE_PCM_FLAG_COMPAT);
 }
 
 static struct platform_driver jz4740_i2s_driver = {
        .probe = jz4740_i2s_dev_probe,
-       .remove = jz4740_i2s_dev_remove,
        .driver = {
                .name = "jz4740-i2s",
                .owner = THIS_MODULE,
diff --git a/sound/soc/jz4740/jz4740-pcm.c b/sound/soc/jz4740/jz4740-pcm.c
deleted file mode 100644 (file)
index 1d7ef28..0000000
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
- *
- *  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.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-
-#include <linux/dma-mapping.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-
-#include <asm/mach-jz4740/dma.h>
-#include "jz4740-pcm.h"
-
-struct jz4740_runtime_data {
-       unsigned long dma_period;
-       dma_addr_t dma_start;
-       dma_addr_t dma_pos;
-       dma_addr_t dma_end;
-
-       struct jz4740_dma_chan *dma;
-
-       dma_addr_t fifo_addr;
-};
-
-/* identify hardware playback capabilities */
-static const struct snd_pcm_hardware jz4740_pcm_hardware = {
-       .info = SNDRV_PCM_INFO_MMAP |
-               SNDRV_PCM_INFO_MMAP_VALID |
-               SNDRV_PCM_INFO_INTERLEAVED |
-               SNDRV_PCM_INFO_BLOCK_TRANSFER,
-       .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8,
-
-       .rates                  = SNDRV_PCM_RATE_8000_48000,
-       .channels_min           = 1,
-       .channels_max           = 2,
-       .period_bytes_min       = 16,
-       .period_bytes_max       = 2 * PAGE_SIZE,
-       .periods_min            = 2,
-       .periods_max            = 128,
-       .buffer_bytes_max       = 128 * 2 * PAGE_SIZE,
-       .fifo_size              = 32,
-};
-
-static void jz4740_pcm_start_transfer(struct jz4740_runtime_data *prtd,
-       struct snd_pcm_substream *substream)
-{
-       unsigned long count;
-
-       if (prtd->dma_pos == prtd->dma_end)
-               prtd->dma_pos = prtd->dma_start;
-
-       if (prtd->dma_pos + prtd->dma_period > prtd->dma_end)
-               count = prtd->dma_end - prtd->dma_pos;
-       else
-               count = prtd->dma_period;
-
-       jz4740_dma_disable(prtd->dma);
-
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               jz4740_dma_set_src_addr(prtd->dma, prtd->dma_pos);
-               jz4740_dma_set_dst_addr(prtd->dma, prtd->fifo_addr);
-       } else {
-               jz4740_dma_set_src_addr(prtd->dma, prtd->fifo_addr);
-               jz4740_dma_set_dst_addr(prtd->dma, prtd->dma_pos);
-       }
-
-       jz4740_dma_set_transfer_count(prtd->dma, count);
-
-       prtd->dma_pos += count;
-
-       jz4740_dma_enable(prtd->dma);
-}
-
-static void jz4740_pcm_dma_transfer_done(struct jz4740_dma_chan *dma, int err,
-       void *dev_id)
-{
-       struct snd_pcm_substream *substream = dev_id;
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct jz4740_runtime_data *prtd = runtime->private_data;
-
-       snd_pcm_period_elapsed(substream);
-
-       jz4740_pcm_start_transfer(prtd, substream);
-}
-
-static int jz4740_pcm_hw_params(struct snd_pcm_substream *substream,
-       struct snd_pcm_hw_params *params)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct jz4740_runtime_data *prtd = runtime->private_data;
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct jz4740_pcm_config *config;
-
-       config = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
-
-       if (!config)
-               return 0;
-
-       if (!prtd->dma) {
-               if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
-                       prtd->dma = jz4740_dma_request(substream, "PCM Capture");
-               else
-                       prtd->dma = jz4740_dma_request(substream, "PCM Playback");
-       }
-
-       if (!prtd->dma)
-               return -EBUSY;
-
-       jz4740_dma_configure(prtd->dma, &config->dma_config);
-       prtd->fifo_addr = config->fifo_addr;
-
-       jz4740_dma_set_complete_cb(prtd->dma, jz4740_pcm_dma_transfer_done);
-
-       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
-       runtime->dma_bytes = params_buffer_bytes(params);
-
-       prtd->dma_period = params_period_bytes(params);
-       prtd->dma_start = runtime->dma_addr;
-       prtd->dma_pos = prtd->dma_start;
-       prtd->dma_end = prtd->dma_start + runtime->dma_bytes;
-
-       return 0;
-}
-
-static int jz4740_pcm_hw_free(struct snd_pcm_substream *substream)
-{
-       struct jz4740_runtime_data *prtd = substream->runtime->private_data;
-
-       snd_pcm_set_runtime_buffer(substream, NULL);
-       if (prtd->dma) {
-               jz4740_dma_free(prtd->dma);
-               prtd->dma = NULL;
-       }
-
-       return 0;
-}
-
-static int jz4740_pcm_prepare(struct snd_pcm_substream *substream)
-{
-       struct jz4740_runtime_data *prtd = substream->runtime->private_data;
-
-       if (!prtd->dma)
-               return -EBUSY;
-
-       prtd->dma_pos = prtd->dma_start;
-
-       return 0;
-}
-
-static int jz4740_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct jz4740_runtime_data *prtd = runtime->private_data;
-
-       switch (cmd) {
-       case SNDRV_PCM_TRIGGER_START:
-       case SNDRV_PCM_TRIGGER_RESUME:
-       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               jz4740_pcm_start_transfer(prtd, substream);
-               break;
-       case SNDRV_PCM_TRIGGER_STOP:
-       case SNDRV_PCM_TRIGGER_SUSPEND:
-       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-               jz4740_dma_disable(prtd->dma);
-               break;
-       default:
-               break;
-       }
-
-       return 0;
-}
-
-static snd_pcm_uframes_t jz4740_pcm_pointer(struct snd_pcm_substream *substream)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct jz4740_runtime_data *prtd = runtime->private_data;
-       unsigned long byte_offset;
-       snd_pcm_uframes_t offset;
-       struct jz4740_dma_chan *dma = prtd->dma;
-
-       /* prtd->dma_pos points to the end of the current transfer. So by
-        * subtracting prdt->dma_start we get the offset to the end of the
-        * current period in bytes. By subtracting the residue of the transfer
-        * we get the current offset in bytes. */
-       byte_offset = prtd->dma_pos - prtd->dma_start;
-       byte_offset -= jz4740_dma_get_residue(dma);
-
-       offset = bytes_to_frames(runtime, byte_offset);
-       if (offset >= runtime->buffer_size)
-               offset = 0;
-
-       return offset;
-}
-
-static int jz4740_pcm_open(struct snd_pcm_substream *substream)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct jz4740_runtime_data *prtd;
-
-       prtd = kzalloc(sizeof(*prtd), GFP_KERNEL);
-       if (prtd == NULL)
-               return -ENOMEM;
-
-       snd_soc_set_runtime_hwparams(substream, &jz4740_pcm_hardware);
-
-       runtime->private_data = prtd;
-
-       return 0;
-}
-
-static int jz4740_pcm_close(struct snd_pcm_substream *substream)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct jz4740_runtime_data *prtd = runtime->private_data;
-
-       kfree(prtd);
-
-       return 0;
-}
-
-static int jz4740_pcm_mmap(struct snd_pcm_substream *substream,
-       struct vm_area_struct *vma)
-{
-       return remap_pfn_range(vma, vma->vm_start,
-                       substream->dma_buffer.addr >> PAGE_SHIFT,
-                       vma->vm_end - vma->vm_start, vma->vm_page_prot);
-}
-
-static struct snd_pcm_ops jz4740_pcm_ops = {
-       .open           = jz4740_pcm_open,
-       .close          = jz4740_pcm_close,
-       .ioctl          = snd_pcm_lib_ioctl,
-       .hw_params      = jz4740_pcm_hw_params,
-       .hw_free        = jz4740_pcm_hw_free,
-       .prepare        = jz4740_pcm_prepare,
-       .trigger        = jz4740_pcm_trigger,
-       .pointer        = jz4740_pcm_pointer,
-       .mmap           = jz4740_pcm_mmap,
-};
-
-static int jz4740_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
-{
-       struct snd_pcm_substream *substream = pcm->streams[stream].substream;
-       struct snd_dma_buffer *buf = &substream->dma_buffer;
-       size_t size = jz4740_pcm_hardware.buffer_bytes_max;
-
-       buf->dev.type = SNDRV_DMA_TYPE_DEV;
-       buf->dev.dev = pcm->card->dev;
-       buf->private_data = NULL;
-
-       buf->area = dma_alloc_noncoherent(pcm->card->dev, size,
-                                         &buf->addr, GFP_KERNEL);
-       if (!buf->area)
-               return -ENOMEM;
-
-       buf->bytes = size;
-
-       return 0;
-}
-
-static void jz4740_pcm_free(struct snd_pcm *pcm)
-{
-       struct snd_pcm_substream *substream;
-       struct snd_dma_buffer *buf;
-       int stream;
-
-       for (stream = 0; stream < SNDRV_PCM_STREAM_LAST; ++stream) {
-               substream = pcm->streams[stream].substream;
-               if (!substream)
-                       continue;
-
-               buf = &substream->dma_buffer;
-               if (!buf->area)
-                       continue;
-
-               dma_free_noncoherent(pcm->card->dev, buf->bytes, buf->area,
-                               buf->addr);
-               buf->area = NULL;
-       }
-}
-
-static int jz4740_pcm_new(struct snd_soc_pcm_runtime *rtd)
-{
-       struct snd_card *card = rtd->card->snd_card;
-       struct snd_pcm *pcm = rtd->pcm;
-       int ret;
-
-       ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
-       if (ret)
-               return ret;
-
-       if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
-               ret = jz4740_pcm_preallocate_dma_buffer(pcm,
-                       SNDRV_PCM_STREAM_PLAYBACK);
-               if (ret)
-                       goto err;
-       }
-
-       if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
-               ret = jz4740_pcm_preallocate_dma_buffer(pcm,
-                       SNDRV_PCM_STREAM_CAPTURE);
-               if (ret)
-                       goto err;
-       }
-
-err:
-       return ret;
-}
-
-static struct snd_soc_platform_driver jz4740_soc_platform = {
-               .ops            = &jz4740_pcm_ops,
-               .pcm_new        = jz4740_pcm_new,
-               .pcm_free       = jz4740_pcm_free,
-};
-
-static int jz4740_pcm_probe(struct platform_device *pdev)
-{
-       return snd_soc_register_platform(&pdev->dev, &jz4740_soc_platform);
-}
-
-static int jz4740_pcm_remove(struct platform_device *pdev)
-{
-       snd_soc_unregister_platform(&pdev->dev);
-       return 0;
-}
-
-static struct platform_driver jz4740_pcm_driver = {
-       .probe = jz4740_pcm_probe,
-       .remove = jz4740_pcm_remove,
-       .driver = {
-               .name = "jz4740-pcm-audio",
-               .owner = THIS_MODULE,
-       },
-};
-
-module_platform_driver(jz4740_pcm_driver);
-
-MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
-MODULE_DESCRIPTION("Ingenic SoC JZ4740 PCM driver");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/jz4740/jz4740-pcm.h b/sound/soc/jz4740/jz4740-pcm.h
deleted file mode 100644 (file)
index 1220cbb..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * 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 _JZ4740_PCM_H
-#define _JZ4740_PCM_H
-
-#include <linux/dma-mapping.h>
-#include <asm/mach-jz4740/dma.h>
-
-
-struct jz4740_pcm_config {
-       struct jz4740_dma_config dma_config;
-       phys_addr_t fifo_addr;
-};
-
-#endif
index 55fd6b5df55f5d988799b93ec64995fb4c06a038..82b5f37cd2c78ab16be9eda44b751201d8b9f09d 100644 (file)
@@ -73,7 +73,7 @@ static struct snd_soc_dai_link qi_lb60_dai = {
        .name = "jz4740",
        .stream_name = "jz4740",
        .cpu_dai_name = "jz4740-i2s",
-       .platform_name = "jz4740-pcm-audio",
+       .platform_name = "jz4740-i2s",
        .codec_dai_name = "jz4740-hifi",
        .codec_name = "jz4740-codec",
        .init = qi_lb60_codec_init,
index d34d91743e3ffe95f9e4823bafdd33d78875b6c3..0b18f654b41340908d022003485d8a88c5e0c94e 100644 (file)
         SNDRV_PCM_FMTBIT_S24_LE | \
         SNDRV_PCM_FMTBIT_S32_LE)
 
+#define KIRKWOOD_SPDIF_FORMATS \
+       (SNDRV_PCM_FMTBIT_S16_LE | \
+        SNDRV_PCM_FMTBIT_S24_LE)
+
 static int kirkwood_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
                unsigned int fmt)
 {
@@ -244,15 +248,15 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
                                   ctl);
        }
 
-       if (dai->id == 0)
-               ctl &= ~KIRKWOOD_PLAYCTL_SPDIF_EN;      /* i2s */
-       else
-               ctl &= ~KIRKWOOD_PLAYCTL_I2S_EN;        /* spdif */
-
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
                /* configure */
                ctl = priv->ctl_play;
+               if (dai->id == 0)
+                       ctl &= ~KIRKWOOD_PLAYCTL_SPDIF_EN;      /* i2s */
+               else
+                       ctl &= ~KIRKWOOD_PLAYCTL_I2S_EN;        /* spdif */
+
                value = ctl & ~KIRKWOOD_PLAYCTL_ENABLE_MASK;
                writel(value, priv->io + KIRKWOOD_PLAYCTL);
 
@@ -449,14 +453,14 @@ static struct snd_soc_dai_driver kirkwood_i2s_dai[2] = {
                .channels_max = 2,
                .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
                                SNDRV_PCM_RATE_96000,
-               .formats = KIRKWOOD_I2S_FORMATS,
+               .formats = KIRKWOOD_SPDIF_FORMATS,
        },
        .capture = {
                .channels_min = 1,
                .channels_max = 2,
                .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
                                SNDRV_PCM_RATE_96000,
-               .formats = KIRKWOOD_I2S_FORMATS,
+               .formats = KIRKWOOD_SPDIF_FORMATS,
        },
        .ops = &kirkwood_i2s_dai_ops,
     },
@@ -493,7 +497,7 @@ static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk[2] = {
                .rates = SNDRV_PCM_RATE_8000_192000 |
                         SNDRV_PCM_RATE_CONTINUOUS |
                         SNDRV_PCM_RATE_KNOT,
-               .formats = KIRKWOOD_I2S_FORMATS,
+               .formats = KIRKWOOD_SPDIF_FORMATS,
        },
        .capture = {
                .channels_min = 1,
@@ -501,7 +505,7 @@ static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk[2] = {
                .rates = SNDRV_PCM_RATE_8000_192000 |
                         SNDRV_PCM_RATE_CONTINUOUS |
                         SNDRV_PCM_RATE_KNOT,
-               .formats = KIRKWOOD_I2S_FORMATS,
+               .formats = KIRKWOOD_SPDIF_FORMATS,
        },
        .ops = &kirkwood_i2s_dai_ops,
     },
index b16abbbf7764beddd61d42514f70bd33338a7781..04a6b0d60944e1b13350dac3fd2fa708dd3c64d5 100644 (file)
@@ -56,16 +56,10 @@ static const struct snd_dmaengine_pcm_config mxs_dmaengine_pcm_config = {
 
 int mxs_pcm_platform_register(struct device *dev)
 {
-       return snd_dmaengine_pcm_register(dev, &mxs_dmaengine_pcm_config,
+       return devm_snd_dmaengine_pcm_register(dev, &mxs_dmaengine_pcm_config,
                SND_DMAENGINE_PCM_FLAG_NO_RESIDUE |
                SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX);
 }
 EXPORT_SYMBOL_GPL(mxs_pcm_platform_register);
 
-void mxs_pcm_platform_unregister(struct device *dev)
-{
-       snd_dmaengine_pcm_unregister(dev);
-}
-EXPORT_SYMBOL_GPL(mxs_pcm_platform_unregister);
-
 MODULE_LICENSE("GPL");
index bc685b67cac71e80c17657357c9eb388eac0ac2e..035ea0436ca5fe83a83b210ba101ad90650acca3 100644 (file)
@@ -20,6 +20,5 @@
 #define _MXS_PCM_H
 
 int mxs_pcm_platform_register(struct device *dev);
-void mxs_pcm_platform_unregister(struct device *dev);
 
 #endif
index 54e622acac330d82a92d95164ae79e89cfb461e4..92db74dc3177c3393acfd333ee6e078af86f4da4 100644 (file)
@@ -804,13 +804,6 @@ static int mxs_saif_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int mxs_saif_remove(struct platform_device *pdev)
-{
-       mxs_pcm_platform_unregister(&pdev->dev);
-
-       return 0;
-}
-
 static const struct of_device_id mxs_saif_dt_ids[] = {
        { .compatible = "fsl,imx28-saif", },
        { /* sentinel */ }
@@ -819,7 +812,6 @@ MODULE_DEVICE_TABLE(of, mxs_saif_dt_ids);
 
 static struct platform_driver mxs_saif_driver = {
        .probe = mxs_saif_probe,
-       .remove = mxs_saif_remove,
 
        .driver = {
                .name = "mxs-saif",
index 83433fdea32ad790f839edd357c14824def13c07..86c75384c3c87dd0e4c9109f737122b1888ad295 100644 (file)
@@ -36,10 +36,10 @@ static void omap_mcbsp_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
 
        if (mcbsp->pdata->reg_size == 2) {
                ((u16 *)mcbsp->reg_cache)[reg] = (u16)val;
-               __raw_writew((u16)val, addr);
+               writew_relaxed((u16)val, addr);
        } else {
                ((u32 *)mcbsp->reg_cache)[reg] = val;
-               __raw_writel(val, addr);
+               writel_relaxed(val, addr);
        }
 }
 
@@ -48,22 +48,22 @@ static int omap_mcbsp_read(struct omap_mcbsp *mcbsp, u16 reg, bool from_cache)
        void __iomem *addr = mcbsp->io_base + reg * mcbsp->pdata->reg_step;
 
        if (mcbsp->pdata->reg_size == 2) {
-               return !from_cache ? __raw_readw(addr) :
+               return !from_cache ? readw_relaxed(addr) :
                                     ((u16 *)mcbsp->reg_cache)[reg];
        } else {
-               return !from_cache ? __raw_readl(addr) :
+               return !from_cache ? readl_relaxed(addr) :
                                     ((u32 *)mcbsp->reg_cache)[reg];
        }
 }
 
 static void omap_mcbsp_st_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
 {
-       __raw_writel(val, mcbsp->st_data->io_base_st + reg);
+       writel_relaxed(val, mcbsp->st_data->io_base_st + reg);
 }
 
 static int omap_mcbsp_st_read(struct omap_mcbsp *mcbsp, u16 reg)
 {
-       return __raw_readl(mcbsp->st_data->io_base_st + reg);
+       return readl_relaxed(mcbsp->st_data->io_base_st + reg);
 }
 
 #define MCBSP_READ(mcbsp, reg) \
index 6d216cb6c19bd2ba92c4d326d2ee6761dc2e5ef3..3fde9e402710f2bb16baf80b605da42772df69a0 100644 (file)
@@ -100,12 +100,12 @@ static int n810_startup(struct snd_pcm_substream *substream)
                                     SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2);
 
        n810_ext_control(&codec->dapm);
-       return clk_enable(sys_clkout2);
+       return clk_prepare_enable(sys_clkout2);
 }
 
 static void n810_shutdown(struct snd_pcm_substream *substream)
 {
-       clk_disable(sys_clkout2);
+       clk_disable_unprepare(sys_clkout2);
 }
 
 static int n810_hw_params(struct snd_pcm_substream *substream,
index 12e566be3793e61eb4fdd7d9ac47a23d638bc260..1bd531d718f953c3a2cd0e533e0f4340d3713892 100644 (file)
@@ -61,12 +61,12 @@ struct omap_dmic {
 
 static inline void omap_dmic_write(struct omap_dmic *dmic, u16 reg, u32 val)
 {
-       __raw_writel(val, dmic->io_base + reg);
+       writel_relaxed(val, dmic->io_base + reg);
 }
 
 static inline int omap_dmic_read(struct omap_dmic *dmic, u16 reg)
 {
-       return __raw_readl(dmic->io_base + reg);
+       return readl_relaxed(dmic->io_base + reg);
 }
 
 static inline void omap_dmic_start(struct omap_dmic *dmic)
index cd9ee167959dcc0b34512ffdf32d26208d506c31..2f5b1536477e8895238d21f400f21370a14f3041 100644 (file)
@@ -74,12 +74,12 @@ struct omap_mcpdm {
 
 static inline void omap_mcpdm_write(struct omap_mcpdm *mcpdm, u16 reg, u32 val)
 {
-       __raw_writel(val, mcpdm->io_base + reg);
+       writel_relaxed(val, mcpdm->io_base + reg);
 }
 
 static inline int omap_mcpdm_read(struct omap_mcpdm *mcpdm, u16 reg)
 {
-       return __raw_readl(mcpdm->io_base + reg);
+       return readl_relaxed(mcpdm->io_base + reg);
 }
 
 #ifdef DEBUG
index 14011d90d70af3180f4eeedee2fa254a6d5fde25..ff60e11ecb564674bdffbe8814392fe1b2b01065 100644 (file)
@@ -37,6 +37,7 @@ config SND_SOC_SH4_SIU
 config SND_SOC_RCAR
        tristate "R-Car series SRU/SCU/SSIU/SSI support"
        select SND_SIMPLE_CARD
+       select REGMAP
        help
          This option enables R-Car SUR/SCU/SSIU/SSI sound support
 
index b33ca7cd085bf4b766dee1900a4101beffc9fa72..6101055aae1dc6fe4e0f7851bd17dde646624f79 100644 (file)
@@ -232,9 +232,9 @@ struct fsi_stream {
         * these are for DMAEngine
         */
        struct dma_chan         *chan;
-       struct sh_dmae_slave    slave; /* see fsi_handler_init() */
        struct work_struct      work;
        dma_addr_t              dma;
+       int                     dma_id;
        int                     loop_cnt;
        int                     additional_pos;
 };
@@ -1410,15 +1410,6 @@ static void fsi_dma_do_work(struct work_struct *work)
        }
 }
 
-static bool fsi_dma_filter(struct dma_chan *chan, void *param)
-{
-       struct sh_dmae_slave *slave = param;
-
-       chan->private = slave;
-
-       return true;
-}
-
 static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io)
 {
        schedule_work(&io->work);
@@ -1446,15 +1437,34 @@ static int fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
 static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io, struct device *dev)
 {
        dma_cap_mask_t mask;
+       int is_play = fsi_stream_is_play(fsi, io);
 
        dma_cap_zero(mask);
        dma_cap_set(DMA_SLAVE, mask);
 
-       io->chan = dma_request_channel(mask, fsi_dma_filter, &io->slave);
+       io->chan = dma_request_slave_channel_compat(mask,
+                               shdma_chan_filter, (void *)io->dma_id,
+                               dev, is_play ? "tx" : "rx");
+       if (io->chan) {
+               struct dma_slave_config cfg;
+               int ret;
+
+               cfg.slave_id    = io->dma_id;
+               cfg.dst_addr    = 0; /* use default addr */
+               cfg.src_addr    = 0; /* use default addr */
+               cfg.direction   = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
+
+               ret = dmaengine_slave_config(io->chan, &cfg);
+               if (ret < 0) {
+                       dma_release_channel(io->chan);
+                       io->chan = NULL;
+               }
+       }
+
        if (!io->chan) {
 
                /* switch to PIO handler */
-               if (fsi_stream_is_play(fsi, io))
+               if (is_play)
                        fsi->playback.handler   = &fsi_pio_push_handler;
                else
                        fsi->capture.handler    = &fsi_pio_pop_handler;
@@ -1960,7 +1970,7 @@ static void fsi_handler_init(struct fsi_priv *fsi,
        fsi->capture.priv       = fsi;
 
        if (info->tx_id) {
-               fsi->playback.slave.shdma_slave.slave_id = info->tx_id;
+               fsi->playback.dma_id  = info->tx_id;
                fsi->playback.handler = &fsi_dma_push_handler;
        }
 }
index 61212ee97c28269a0cd245e424636c4f38efc4c7..d0ab203836de3d78679f181f44b23b2f0ebdae36 100644 (file)
  */
 #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);
-       int (*path_exit)(struct rsnd_priv *priv,
-                        struct rsnd_dai *rdai,
-                        struct rsnd_dai_stream *io);
-};
-
 struct rsnd_gen {
        void __iomem *base[RSND_BASE_MAX];
 
@@ -86,12 +72,28 @@ static struct regmap_bus rsnd_regmap_bus = {
        .val_format_endian_default      = REGMAP_ENDIAN_NATIVE,
 };
 
+static int rsnd_is_accessible_reg(struct rsnd_priv *priv,
+                                 struct rsnd_gen *gen, enum rsnd_reg reg)
+{
+       if (!gen->regs[reg]) {
+               struct device *dev = rsnd_priv_to_dev(priv);
+
+               dev_err(dev, "unsupported register access %x\n", reg);
+               return 0;
+       }
+
+       return 1;
+}
+
 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;
 
+       if (!rsnd_is_accessible_reg(priv, gen, reg))
+               return 0;
+
        regmap_fields_read(gen->regs[reg], rsnd_mod_id(mod), &val);
 
        return val;
@@ -103,6 +105,9 @@ void rsnd_write(struct rsnd_priv *priv,
 {
        struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
 
+       if (!rsnd_is_accessible_reg(priv, gen, reg))
+               return;
+
        regmap_fields_write(gen->regs[reg], rsnd_mod_id(mod), data);
 }
 
@@ -111,21 +116,48 @@ void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod,
 {
        struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
 
+       if (!rsnd_is_accessible_reg(priv, gen, reg))
+               return;
+
        regmap_fields_update_bits(gen->regs[reg], rsnd_mod_id(mod),
                                  mask, data);
 }
 
-/*
- *             Gen2
- *             will be filled in the future
- */
+static int rsnd_gen_regmap_init(struct rsnd_priv *priv,
+                               struct rsnd_gen  *gen,
+                               struct reg_field *regf)
+{
+       int i;
+       struct device *dev = rsnd_priv_to_dev(priv);
+       struct regmap_config regc;
 
-/*
- *             Gen1
- */
-static int rsnd_gen1_path_init(struct rsnd_priv *priv,
-                              struct rsnd_dai *rdai,
-                              struct rsnd_dai_stream *io)
+       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] = NULL;
+               if (!regf[i].reg)
+                       continue;
+
+               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;
+}
+
+int rsnd_gen_path_init(struct rsnd_priv *priv,
+                      struct rsnd_dai *rdai,
+                      struct rsnd_dai_stream *io)
 {
        struct rsnd_mod *mod;
        int ret;
@@ -163,9 +195,9 @@ static int rsnd_gen1_path_init(struct rsnd_priv *priv,
        return ret;
 }
 
-static int rsnd_gen1_path_exit(struct rsnd_priv *priv,
-                              struct rsnd_dai *rdai,
-                              struct rsnd_dai_stream *io)
+int rsnd_gen_path_exit(struct rsnd_priv *priv,
+                      struct rsnd_dai *rdai,
+                      struct rsnd_dai_stream *io)
 {
        struct rsnd_mod *mod, *n;
        int ret = 0;
@@ -179,6 +211,94 @@ static int rsnd_gen1_path_exit(struct rsnd_priv *priv,
        return ret;
 }
 
+/*
+ *             Gen2
+ */
+
+/* single address mapping */
+#define RSND_GEN2_S_REG(gen, reg, id, offset)                          \
+       RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN2_##reg, offset, 0, 10)
+
+/* multi address mapping */
+#define RSND_GEN2_M_REG(gen, reg, id, offset, _id_offset)              \
+       RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN2_##reg, offset, _id_offset, 10)
+
+static int rsnd_gen2_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen)
+{
+       struct reg_field regf[RSND_REG_MAX] = {
+               RSND_GEN2_S_REG(gen, SSIU,      SSI_MODE0,      0x800),
+               RSND_GEN2_S_REG(gen, SSIU,      SSI_MODE1,      0x804),
+               /* FIXME: it needs SSI_MODE2/3 in the future */
+               RSND_GEN2_M_REG(gen, SSIU,      INT_ENABLE,     0x18,   0x80),
+
+               RSND_GEN2_S_REG(gen, ADG,       BRRA,           0x00),
+               RSND_GEN2_S_REG(gen, ADG,       BRRB,           0x04),
+               RSND_GEN2_S_REG(gen, ADG,       SSICKR,         0x08),
+               RSND_GEN2_S_REG(gen, ADG,       AUDIO_CLK_SEL0, 0x0c),
+               RSND_GEN2_S_REG(gen, ADG,       AUDIO_CLK_SEL1, 0x10),
+               RSND_GEN2_S_REG(gen, ADG,       AUDIO_CLK_SEL2, 0x14),
+
+               RSND_GEN2_M_REG(gen, SSI,       SSICR,          0x00,   0x40),
+               RSND_GEN2_M_REG(gen, SSI,       SSISR,          0x04,   0x40),
+               RSND_GEN2_M_REG(gen, SSI,       SSITDR,         0x08,   0x40),
+               RSND_GEN2_M_REG(gen, SSI,       SSIRDR,         0x0c,   0x40),
+               RSND_GEN2_M_REG(gen, SSI,       SSIWSR,         0x20,   0x40),
+       };
+
+       return rsnd_gen_regmap_init(priv, gen, regf);
+}
+
+static int rsnd_gen2_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 = rsnd_priv_to_gen(priv);
+       struct resource *scu_res;
+       struct resource *adg_res;
+       struct resource *ssiu_res;
+       struct resource *ssi_res;
+       int ret;
+
+       /*
+        * map address
+        */
+       scu_res  = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_SCU);
+       adg_res  = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_ADG);
+       ssiu_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_SSIU);
+       ssi_res  = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_SSI);
+
+       gen->base[RSND_GEN2_SCU]  = devm_ioremap_resource(dev, scu_res);
+       gen->base[RSND_GEN2_ADG]  = devm_ioremap_resource(dev, adg_res);
+       gen->base[RSND_GEN2_SSIU] = devm_ioremap_resource(dev, ssiu_res);
+       gen->base[RSND_GEN2_SSI]  = devm_ioremap_resource(dev, ssi_res);
+       if (IS_ERR(gen->base[RSND_GEN2_SCU])  ||
+           IS_ERR(gen->base[RSND_GEN2_ADG])  ||
+           IS_ERR(gen->base[RSND_GEN2_SSIU]) ||
+           IS_ERR(gen->base[RSND_GEN2_SSI]))
+               return -ENODEV;
+
+       ret = rsnd_gen2_regmap_init(priv, gen);
+       if (ret < 0)
+               return ret;
+
+       dev_dbg(dev, "Gen2 device probed\n");
+       dev_dbg(dev, "SRU  : %08x => %p\n", scu_res->start,
+               gen->base[RSND_GEN2_SCU]);
+       dev_dbg(dev, "ADG  : %08x => %p\n", adg_res->start,
+               gen->base[RSND_GEN2_ADG]);
+       dev_dbg(dev, "SSIU : %08x => %p\n", ssiu_res->start,
+               gen->base[RSND_GEN2_SSIU]);
+       dev_dbg(dev, "SSI  : %08x => %p\n", ssi_res->start,
+               gen->base[RSND_GEN2_SSI]);
+
+       return 0;
+}
+
+/*
+ *             Gen1
+ */
+
 /* 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)
@@ -189,9 +309,6 @@ static int rsnd_gen1_path_exit(struct rsnd_priv *priv,
 
 static int rsnd_gen1_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen)
 {
-       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),
@@ -208,9 +325,6 @@ static int rsnd_gen1_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen)
                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),
@@ -219,24 +333,7 @@ static int rsnd_gen1_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen)
                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;
+       return rsnd_gen_regmap_init(priv, gen, regf);
 }
 
 static int rsnd_gen1_probe(struct platform_device *pdev,
@@ -281,45 +378,16 @@ static int rsnd_gen1_probe(struct platform_device *pdev,
 
 }
 
-static void rsnd_gen1_remove(struct platform_device *pdev,
-                            struct rsnd_priv *priv)
-{
-}
-
-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
  */
-int rsnd_gen_path_init(struct rsnd_priv *priv,
-                      struct rsnd_dai *rdai,
-                      struct rsnd_dai_stream *io)
-{
-       struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
-
-       return gen->ops->path_init(priv, rdai, io);
-}
-
-int rsnd_gen_path_exit(struct rsnd_priv *priv,
-                      struct rsnd_dai *rdai,
-                      struct rsnd_dai_stream *io)
-{
-       struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
-
-       return gen->ops->path_exit(priv, rdai, io);
-}
-
 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 ret;
 
        gen = devm_kzalloc(dev, sizeof(*gen), GFP_KERNEL);
        if (!gen) {
@@ -327,23 +395,21 @@ int rsnd_gen_probe(struct platform_device *pdev,
                return -ENOMEM;
        }
 
+       priv->gen = gen;
+
+       ret = -ENODEV;
        if (rsnd_is_gen1(priv))
-               gen->ops = &rsnd_gen1_ops;
+               ret = rsnd_gen1_probe(pdev, info, priv);
+       else if (rsnd_is_gen2(priv))
+               ret = rsnd_gen2_probe(pdev, info, priv);
 
-       if (!gen->ops) {
+       if (ret < 0)
                dev_err(dev, "unknown generation R-Car sound device\n");
-               return -ENODEV;
-       }
-
-       priv->gen = gen;
 
-       return gen->ops->probe(pdev, info, priv);
+       return ret;
 }
 
 void rsnd_gen_remove(struct platform_device *pdev,
                     struct rsnd_priv *priv)
 {
-       struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
-
-       gen->ops->remove(pdev, priv);
 }
index 9e463e50e7e62b81fabeaeecf39f50de4206eeaf..bff7b9e5306656a55e6686142f4602be5c859b8a 100644 (file)
@@ -31,7 +31,7 @@
  * see gen1/gen2 for detail
  */
 enum rsnd_reg {
-       /* SRU/SCU */
+       /* SRU/SCU/SSIU */
        RSND_REG_SRC_ROUTE_SEL,
        RSND_REG_SRC_TMG_SEL0,
        RSND_REG_SRC_TMG_SEL1,
@@ -41,6 +41,7 @@ enum rsnd_reg {
        RSND_REG_SSI_MODE1,
        RSND_REG_BUSIF_MODE,
        RSND_REG_BUSIF_ADINR,
+       RSND_REG_INT_ENABLE,
 
        /* ADG */
        RSND_REG_BRRA,
@@ -49,9 +50,6 @@ enum rsnd_reg {
        RSND_REG_AUDIO_CLK_SEL0,
        RSND_REG_AUDIO_CLK_SEL1,
        RSND_REG_AUDIO_CLK_SEL2,
-       RSND_REG_AUDIO_CLK_SEL3,
-       RSND_REG_AUDIO_CLK_SEL4,
-       RSND_REG_AUDIO_CLK_SEL5,
 
        /* SSI */
        RSND_REG_SSICR,
@@ -174,11 +172,11 @@ struct rsnd_dai {
        struct rsnd_dai_stream playback;
        struct rsnd_dai_stream capture;
 
-       int clk_master:1;
-       int bit_clk_inv:1;
-       int frm_clk_inv:1;
-       int sys_delay:1;
-       int data_alignment:1;
+       unsigned int clk_master:1;
+       unsigned int bit_clk_inv:1;
+       unsigned int frm_clk_inv:1;
+       unsigned int sys_delay:1;
+       unsigned int data_alignment:1;
 };
 
 #define rsnd_dai_nr(priv) ((priv)->dai_nr)
index 5ac20cd5e00607efd0b8113fc85aec9ed97f57f4..85936ae564a4b9322569772d692f4cbc811f939e 100644 (file)
@@ -457,6 +457,9 @@ static int rsnd_ssi_pio_start(struct rsnd_mod *mod,
        /* enable PIO IRQ */
        ssi->cr_etc = UIEN | OIEN | DIEN;
 
+       /* enable PIO interrupt */
+       rsnd_mod_write(&ssi->mod, INT_ENABLE, 0x0f000000);
+
        rsnd_ssi_hw_start(ssi, rdai, io);
 
        dev_dbg(dev, "%s.%d start\n", rsnd_mod_name(mod), rsnd_mod_id(mod));
@@ -650,7 +653,7 @@ int rsnd_ssi_probe(struct platform_device *pdev,
 
                snprintf(name, RSND_SSI_NAME_SIZE, "ssi.%d", i);
 
-               clk = clk_get(dev, name);
+               clk = devm_clk_get(dev, name);
                if (IS_ERR(clk))
                        return PTR_ERR(clk);
 
@@ -711,7 +714,6 @@ void rsnd_ssi_remove(struct platform_device *pdev,
        int i;
 
        for_each_rsnd_ssi(ssi, priv, i) {
-               clk_put(ssi->clk);
                if (rsnd_ssi_dma_available(ssi))
                        rsnd_dma_quit(priv, rsnd_mod_to_dma(&ssi->mod));
        }
index 4e53d87e881d0891a3d8437881d12d41225303cc..a66783e13a9cca182e3077b3e998c804aa40ff1d 100644 (file)
@@ -3212,11 +3212,11 @@ int snd_soc_bytes_get(struct snd_kcontrol *kcontrol,
                        break;
                case 2:
                        ((u16 *)(&ucontrol->value.bytes.data))[0]
-                               &= ~params->mask;
+                               &= cpu_to_be16(~params->mask);
                        break;
                case 4:
                        ((u32 *)(&ucontrol->value.bytes.data))[0]
-                               &= ~params->mask;
+                               &= cpu_to_be32(~params->mask);
                        break;
                default:
                        return -EINVAL;
index b1d732255c0275fd06039efe36988b1a8ba3e8d2..7ac745df1412689c6adf0bf246399870b79e44e7 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
 
 static void devm_component_release(struct device *dev, void *res)
 {
@@ -66,7 +67,7 @@ static void devm_card_release(struct device *dev, void *res)
  */
 int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card)
 {
-       struct device **ptr;
+       struct snd_soc_card **ptr;
        int ret;
 
        ptr = devres_alloc(devm_card_release, sizeof(*ptr), GFP_KERNEL);
@@ -75,7 +76,7 @@ int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card)
 
        ret = snd_soc_register_card(card);
        if (ret == 0) {
-               *ptr = dev;
+               *ptr = card;
                devres_add(dev, ptr);
        } else {
                devres_free(ptr);
@@ -84,3 +85,43 @@ int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card)
        return ret;
 }
 EXPORT_SYMBOL_GPL(devm_snd_soc_register_card);
+
+#ifdef CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM
+
+static void devm_dmaengine_pcm_release(struct device *dev, void *res)
+{
+       snd_dmaengine_pcm_unregister(*(struct device **)res);
+}
+
+/**
+ * devm_snd_dmaengine_pcm_register - resource managed dmaengine PCM registration
+ * @dev: The parent device for the PCM device
+ * @config: Platform specific PCM configuration
+ * @flags: Platform specific quirks
+ *
+ * Register a dmaengine based PCM device with automatic unregistration when the
+ * device is unregistered.
+ */
+int devm_snd_dmaengine_pcm_register(struct device *dev,
+       const struct snd_dmaengine_pcm_config *config, unsigned int flags)
+{
+       struct device **ptr;
+       int ret;
+
+       ptr = devres_alloc(devm_dmaengine_pcm_release, sizeof(*ptr), GFP_KERNEL);
+       if (!ptr)
+               return -ENOMEM;
+
+       ret = snd_dmaengine_pcm_register(dev, config, flags);
+       if (ret == 0) {
+               *ptr = dev;
+               devres_add(dev, ptr);
+       } else {
+               devres_free(ptr);
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(devm_snd_dmaengine_pcm_register);
+
+#endif
index cbc9c96ce1f412123a1704b171220a2990ad503d..585eaa69e8c34d93a2942f3d40d702bca7b80720 100644 (file)
@@ -137,6 +137,9 @@ static int dmaengine_pcm_set_runtime_hwparams(struct snd_pcm_substream *substrea
        hw.buffer_bytes_max = SIZE_MAX;
        hw.fifo_size = dma_data->fifo_size;
 
+       if (pcm->flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE)
+               hw.info |= SNDRV_PCM_INFO_BATCH;
+
        ret = dma_get_slave_caps(chan, &dma_caps);
        if (ret == 0) {
                if (dma_caps.cmd_pause)
@@ -284,24 +287,67 @@ static const char * const dmaengine_pcm_dma_channel_names[] = {
        [SNDRV_PCM_STREAM_CAPTURE] = "rx",
 };
 
-static void dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm,
-       struct device *dev)
+static int dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm,
+       struct device *dev, const struct snd_dmaengine_pcm_config *config)
 {
        unsigned int i;
+       const char *name;
+       struct dma_chan *chan;
 
        if ((pcm->flags & (SND_DMAENGINE_PCM_FLAG_NO_DT |
                           SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME)) ||
            !dev->of_node)
-               return;
+               return 0;
+
+       if (config->dma_dev) {
+               /*
+                * If this warning is seen, it probably means that your Linux
+                * device structure does not match your HW device structure.
+                * It would be best to refactor the Linux device structure to
+                * correctly match the HW structure.
+                */
+               dev_warn(dev, "DMA channels sourced from device %s",
+                        dev_name(config->dma_dev));
+               dev = config->dma_dev;
+       }
 
-       if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) {
-               pcm->chan[0] = dma_request_slave_channel(dev, "rx-tx");
-               pcm->chan[1] = pcm->chan[0];
-       } else {
-               for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) {
-                       pcm->chan[i] = dma_request_slave_channel(dev,
-                                       dmaengine_pcm_dma_channel_names[i]);
+       for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE;
+            i++) {
+               if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX)
+                       name = "rx-tx";
+               else
+                       name = dmaengine_pcm_dma_channel_names[i];
+               if (config->chan_names[i])
+                       name = config->chan_names[i];
+               chan = dma_request_slave_channel_reason(dev, name);
+               if (IS_ERR(chan)) {
+                       if (PTR_ERR(pcm->chan[i]) == -EPROBE_DEFER)
+                               return -EPROBE_DEFER;
+                       pcm->chan[i] = NULL;
+               } else {
+                       pcm->chan[i] = chan;
                }
+               if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX)
+                       break;
+       }
+
+       if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX)
+               pcm->chan[1] = pcm->chan[0];
+
+       return 0;
+}
+
+static void dmaengine_pcm_release_chan(struct dmaengine_pcm *pcm)
+{
+       unsigned int i;
+
+       for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE;
+            i++) {
+               if (!pcm->chan[i])
+                       continue;
+               dma_release_channel(pcm->chan[i]);
+               if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX)
+                       break;
        }
 }
 
@@ -315,6 +361,7 @@ int snd_dmaengine_pcm_register(struct device *dev,
        const struct snd_dmaengine_pcm_config *config, unsigned int flags)
 {
        struct dmaengine_pcm *pcm;
+       int ret;
 
        pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
        if (!pcm)
@@ -323,14 +370,25 @@ int snd_dmaengine_pcm_register(struct device *dev,
        pcm->config = config;
        pcm->flags = flags;
 
-       dmaengine_pcm_request_chan_of(pcm, dev);
+       ret = dmaengine_pcm_request_chan_of(pcm, dev, config);
+       if (ret)
+               goto err_free_dma;
 
        if (flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE)
-               return snd_soc_add_platform(dev, &pcm->platform,
+               ret = snd_soc_add_platform(dev, &pcm->platform,
                                &dmaengine_no_residue_pcm_platform);
        else
-               return snd_soc_add_platform(dev, &pcm->platform,
+               ret = snd_soc_add_platform(dev, &pcm->platform,
                                &dmaengine_pcm_platform);
+       if (ret)
+               goto err_free_dma;
+
+       return 0;
+
+err_free_dma:
+       dmaengine_pcm_release_chan(pcm);
+       kfree(pcm);
+       return ret;
 }
 EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_register);
 
@@ -345,7 +403,6 @@ void snd_dmaengine_pcm_unregister(struct device *dev)
 {
        struct snd_soc_platform *platform;
        struct dmaengine_pcm *pcm;
-       unsigned int i;
 
        platform = snd_soc_lookup_platform(dev);
        if (!platform)
@@ -353,15 +410,8 @@ void snd_dmaengine_pcm_unregister(struct device *dev)
 
        pcm = soc_platform_to_pcm(platform);
 
-       for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) {
-               if (pcm->chan[i]) {
-                       dma_release_channel(pcm->chan[i]);
-                       if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX)
-                               break;
-               }
-       }
-
        snd_soc_remove_platform(platform);
+       dmaengine_pcm_release_chan(pcm);
        kfree(pcm);
 }
 EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_unregister);
index 4f11d23f20621971b8806e70618ee8e4e1c3846f..aa886cca3ecf94a8ecf2c360312cd3dc3bcb4184 100644 (file)
@@ -99,14 +99,14 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
        config.val_bits = data_bits;
 
        switch (control) {
-#if defined(CONFIG_REGMAP_I2C) || defined(CONFIG_REGMAP_I2C_MODULE)
+#if IS_ENABLED(CONFIG_REGMAP_I2C)
        case SND_SOC_I2C:
                codec->control_data = regmap_init_i2c(to_i2c_client(codec->dev),
                                                      &config);
                break;
 #endif
 
-#if defined(CONFIG_REGMAP_SPI) || defined(CONFIG_REGMAP_SPI_MODULE)
+#if IS_ENABLED(CONFIG_REGMAP_SPI)
        case SND_SOC_SPI:
                codec->control_data = regmap_init_spi(to_spi_device(codec->dev),
                                                      &config);
index 42782c01e41320e924efb4b93c839802f0df5722..604e7e9a2ef8d9b1a5bdb53e8551e3fb159062e0 100644 (file)
@@ -84,35 +84,117 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream,
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        int ret;
 
-       if (!soc_dai->driver->symmetric_rates &&
-           !rtd->dai_link->symmetric_rates)
-               return 0;
+       if (soc_dai->rate && (soc_dai->driver->symmetric_rates ||
+                               rtd->dai_link->symmetric_rates)) {
+               dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %dHz rate\n",
+                               soc_dai->rate);
+
+               ret = snd_pcm_hw_constraint_minmax(substream->runtime,
+                                               SNDRV_PCM_HW_PARAM_RATE,
+                                               soc_dai->rate, soc_dai->rate);
+               if (ret < 0) {
+                       dev_err(soc_dai->dev,
+                               "ASoC: Unable to apply rate constraint: %d\n",
+                               ret);
+                       return ret;
+               }
+       }
 
-       /* This can happen if multiple streams are starting simultaneously -
-        * the second can need to get its constraints before the first has
-        * picked a rate.  Complain and allow the application to carry on.
-        */
-       if (!soc_dai->rate) {
-               dev_warn(soc_dai->dev,
-                        "ASoC: Not enforcing symmetric_rates due to race\n");
-               return 0;
+       if (soc_dai->channels && (soc_dai->driver->symmetric_channels ||
+                               rtd->dai_link->symmetric_channels)) {
+               dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %d channel(s)\n",
+                               soc_dai->channels);
+
+               ret = snd_pcm_hw_constraint_minmax(substream->runtime,
+                                               SNDRV_PCM_HW_PARAM_CHANNELS,
+                                               soc_dai->channels,
+                                               soc_dai->channels);
+               if (ret < 0) {
+                       dev_err(soc_dai->dev,
+                               "ASoC: Unable to apply channel symmetry constraint: %d\n",
+                               ret);
+                       return ret;
+               }
        }
 
-       dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %dHz rate\n", soc_dai->rate);
+       if (soc_dai->sample_bits && (soc_dai->driver->symmetric_samplebits ||
+                               rtd->dai_link->symmetric_samplebits)) {
+               dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %d sample bits\n",
+                               soc_dai->sample_bits);
 
-       ret = snd_pcm_hw_constraint_minmax(substream->runtime,
-                                          SNDRV_PCM_HW_PARAM_RATE,
-                                          soc_dai->rate, soc_dai->rate);
-       if (ret < 0) {
-               dev_err(soc_dai->dev,
-                       "ASoC: Unable to apply rate symmetry constraint: %d\n",
-                       ret);
-               return ret;
+               ret = snd_pcm_hw_constraint_minmax(substream->runtime,
+                                               SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
+                                               soc_dai->sample_bits,
+                                               soc_dai->sample_bits);
+               if (ret < 0) {
+                       dev_err(soc_dai->dev,
+                               "ASoC: Unable to apply sample bits symmetry constraint: %d\n",
+                               ret);
+                       return ret;
+               }
        }
 
        return 0;
 }
 
+static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream,
+                               struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
+       unsigned int rate, channels, sample_bits, symmetry;
+
+       rate = params_rate(params);
+       channels = params_channels(params);
+       sample_bits = snd_pcm_format_physical_width(params_format(params));
+
+       /* reject unmatched parameters when applying symmetry */
+       symmetry = cpu_dai->driver->symmetric_rates ||
+               codec_dai->driver->symmetric_rates ||
+               rtd->dai_link->symmetric_rates;
+       if (symmetry && cpu_dai->rate && cpu_dai->rate != rate) {
+               dev_err(rtd->dev, "ASoC: unmatched rate symmetry: %d - %d\n",
+                               cpu_dai->rate, rate);
+               return -EINVAL;
+       }
+
+       symmetry = cpu_dai->driver->symmetric_channels ||
+               codec_dai->driver->symmetric_channels ||
+               rtd->dai_link->symmetric_channels;
+       if (symmetry && cpu_dai->channels && cpu_dai->channels != channels) {
+               dev_err(rtd->dev, "ASoC: unmatched channel symmetry: %d - %d\n",
+                               cpu_dai->channels, channels);
+               return -EINVAL;
+       }
+
+       symmetry = cpu_dai->driver->symmetric_samplebits ||
+               codec_dai->driver->symmetric_samplebits ||
+               rtd->dai_link->symmetric_samplebits;
+       if (symmetry && cpu_dai->sample_bits && cpu_dai->sample_bits != sample_bits) {
+               dev_err(rtd->dev, "ASoC: unmatched sample bits symmetry: %d - %d\n",
+                               cpu_dai->sample_bits, sample_bits);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static bool soc_pcm_has_symmetry(struct snd_pcm_substream *substream)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai_driver *cpu_driver = rtd->cpu_dai->driver;
+       struct snd_soc_dai_driver *codec_driver = rtd->codec_dai->driver;
+       struct snd_soc_dai_link *link = rtd->dai_link;
+
+       return cpu_driver->symmetric_rates || codec_driver->symmetric_rates ||
+               link->symmetric_rates || cpu_driver->symmetric_channels ||
+               codec_driver->symmetric_channels || link->symmetric_channels ||
+               cpu_driver->symmetric_samplebits ||
+               codec_driver->symmetric_samplebits ||
+               link->symmetric_samplebits;
+}
+
 /*
  * List of sample sizes that might go over the bus for parameter
  * application.  There ought to be a wildcard sample size for things
@@ -148,12 +230,12 @@ static void soc_pcm_apply_msb(struct snd_pcm_substream *substream,
        }
 }
 
-static void soc_pcm_init_runtime_hw(struct snd_pcm_hardware *hw,
+static void soc_pcm_init_runtime_hw(struct snd_pcm_runtime *runtime,
        struct snd_soc_pcm_stream *codec_stream,
        struct snd_soc_pcm_stream *cpu_stream)
 {
-       hw->rate_min = max(codec_stream->rate_min, cpu_stream->rate_min);
-       hw->rate_max = max(codec_stream->rate_max, cpu_stream->rate_max);
+       struct snd_pcm_hardware *hw = &runtime->hw;
+
        hw->channels_min = max(codec_stream->channels_min,
                cpu_stream->channels_min);
        hw->channels_max = min(codec_stream->channels_max,
@@ -166,6 +248,13 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_hardware *hw,
        if (cpu_stream->rates
                & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
                hw->rates |= codec_stream->rates;
+
+       snd_pcm_limit_hw_rates(runtime);
+
+       hw->rate_min = max(hw->rate_min, cpu_stream->rate_min);
+       hw->rate_min = max(hw->rate_min, codec_stream->rate_min);
+       hw->rate_max = min_not_zero(hw->rate_max, cpu_stream->rate_max);
+       hw->rate_max = min_not_zero(hw->rate_max, codec_stream->rate_max);
 }
 
 /*
@@ -235,15 +324,17 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
 
        /* Check that the codec and cpu DAIs are compatible */
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               soc_pcm_init_runtime_hw(&runtime->hw, &codec_dai_drv->playback,
+               soc_pcm_init_runtime_hw(runtime, &codec_dai_drv->playback,
                        &cpu_dai_drv->playback);
        } else {
-               soc_pcm_init_runtime_hw(&runtime->hw, &codec_dai_drv->capture,
+               soc_pcm_init_runtime_hw(runtime, &codec_dai_drv->capture,
                        &cpu_dai_drv->capture);
        }
 
+       if (soc_pcm_has_symmetry(substream))
+               runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX;
+
        ret = -EINVAL;
-       snd_pcm_limit_hw_rates(runtime);
        if (!runtime->hw.rates) {
                printk(KERN_ERR "ASoC: %s <-> %s No matching rates\n",
                        codec_dai->name, cpu_dai->name);
@@ -390,11 +481,6 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
        if (!codec_dai->active)
                codec_dai->rate = 0;
 
-       /* Muting the DAC suppresses artifacts caused during digital
-        * shutdown, for example from stopping clocks.
-        */
-       snd_soc_dai_digital_mute(codec_dai, 1, substream->stream);
-
        if (cpu_dai->driver->ops->shutdown)
                cpu_dai->driver->ops->shutdown(substream, cpu_dai);
 
@@ -525,6 +611,10 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
 
        mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 
+       ret = soc_pcm_params_symmetry(substream, params);
+       if (ret)
+               goto out;
+
        if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) {
                ret = rtd->dai_link->ops->hw_params(substream, params);
                if (ret < 0) {
@@ -561,9 +651,16 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
                }
        }
 
-       /* store the rate for each DAIs */
+       /* store the parameters for each DAIs */
        cpu_dai->rate = params_rate(params);
+       cpu_dai->channels = params_channels(params);
+       cpu_dai->sample_bits =
+               snd_pcm_format_physical_width(params_format(params));
+
        codec_dai->rate = params_rate(params);
+       codec_dai->channels = params_channels(params);
+       codec_dai->sample_bits =
+               snd_pcm_format_physical_width(params_format(params));
 
 out:
        mutex_unlock(&rtd->pcm_mutex);
@@ -594,12 +691,26 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
        struct snd_soc_platform *platform = rtd->platform;
        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
-       struct snd_soc_codec *codec = rtd->codec;
+       bool playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
 
        mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 
+       /* clear the corresponding DAIs parameters when going to be inactive */
+       if (cpu_dai->active == 1) {
+               cpu_dai->rate = 0;
+               cpu_dai->channels = 0;
+               cpu_dai->sample_bits = 0;
+       }
+
+       if (codec_dai->active == 1) {
+               codec_dai->rate = 0;
+               codec_dai->channels = 0;
+               codec_dai->sample_bits = 0;
+       }
+
        /* apply codec digital mute */
-       if (!codec->active)
+       if ((playback && codec_dai->playback_active == 1) ||
+           (!playback && codec_dai->capture_active == 1))
                snd_soc_dai_digital_mute(codec_dai, 1, substream->stream);
 
        /* free any machine hw params */
index 4707f2b862c3762502d622d1d799944ee0e401fc..9a02141666ea9b75bb94817b9e25a97e344f96a1 100644 (file)
@@ -49,18 +49,12 @@ static const struct snd_dmaengine_pcm_config spear_dmaengine_pcm_config = {
 
 static int spear_soc_platform_probe(struct platform_device *pdev)
 {
-       return snd_dmaengine_pcm_register(&pdev->dev,
+       return devm_snd_dmaengine_pcm_register(&pdev->dev,
                &spear_dmaengine_pcm_config,
                SND_DMAENGINE_PCM_FLAG_NO_DT |
                SND_DMAENGINE_PCM_FLAG_COMPAT);
 }
 
-static int spear_soc_platform_remove(struct platform_device *pdev)
-{
-       snd_dmaengine_pcm_unregister(&pdev->dev);
-       return 0;
-}
-
 static struct platform_driver spear_pcm_driver = {
        .driver = {
                .name = "spear-pcm-audio",
@@ -68,7 +62,6 @@ static struct platform_driver spear_pcm_driver = {
        },
 
        .probe = spear_soc_platform_probe,
-       .remove = spear_soc_platform_remove,
 };
 
 module_platform_driver(spear_pcm_driver);
index 8fc653ca3ab40b3ef04d1a58723a2466086ab8ff..65a85f542521563627be1fe02b4c22c6bfdea194 100644 (file)
@@ -116,3 +116,13 @@ config SND_SOC_TEGRA_ALC5632
        help
          Say Y or M here if you want to add support for SoC audio on the
          Toshiba AC100 netbook.
+
+config SND_SOC_TEGRA_MAX98090
+       tristate "SoC Audio support for Tegra boards using a MAX98090 codec"
+       depends on SND_SOC_TEGRA && I2C && GPIOLIB
+       select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
+       select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC
+       select SND_SOC_MAX98090
+       help
+         Say Y or M here if you want to add support for SoC audio on Tegra
+         boards using the MAX98090 codec, such as Venice2.
index 21d2550a08a4fc1e15e41f4c66cc0a84a290396f..5ae588cd96c4c39ff8060f98a6f1248f9e4855d9 100644 (file)
@@ -24,6 +24,7 @@ snd-soc-tegra-wm8903-objs := tegra_wm8903.o
 snd-soc-tegra-wm9712-objs := tegra_wm9712.o
 snd-soc-tegra-trimslice-objs := trimslice.o
 snd-soc-tegra-alc5632-objs := tegra_alc5632.o
+snd-soc-tegra-max98090-objs := tegra_max98090.o
 
 obj-$(CONFIG_SND_SOC_TEGRA_RT5640) += snd-soc-tegra-rt5640.o
 obj-$(CONFIG_SND_SOC_TEGRA_WM8753) += snd-soc-tegra-wm8753.o
@@ -31,3 +32,4 @@ obj-$(CONFIG_SND_SOC_TEGRA_WM8903) += snd-soc-tegra-wm8903.o
 obj-$(CONFIG_SND_SOC_TEGRA_WM9712) += snd-soc-tegra-wm9712.o
 obj-$(CONFIG_SND_SOC_TEGRA_TRIMSLICE) += snd-soc-tegra-trimslice.o
 obj-$(CONFIG_SND_SOC_TEGRA_ALC5632) += snd-soc-tegra-alc5632.o
+obj-$(CONFIG_SND_SOC_TEGRA_MAX98090) += snd-soc-tegra-max98090.o
index 364bf6a907e1c39a36df89ded1d6b2681172940f..8c819f8114708f7a94e33929a04ebecbdf3e2ffc 100644 (file)
@@ -74,7 +74,7 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai,
                                unsigned int fmt)
 {
        struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(dai);
-       unsigned int mask, val;
+       unsigned int mask = 0, val = 0;
 
        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
        case SND_SOC_DAIFMT_NB_NF:
@@ -83,10 +83,10 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai,
                return -EINVAL;
        }
 
-       mask = TEGRA20_I2S_CTRL_MASTER_ENABLE;
+       mask |= TEGRA20_I2S_CTRL_MASTER_ENABLE;
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBS_CFS:
-               val = TEGRA20_I2S_CTRL_MASTER_ENABLE;
+               val |= TEGRA20_I2S_CTRL_MASTER_ENABLE;
                break;
        case SND_SOC_DAIFMT_CBM_CFM:
                break;
index 08bc6931c7c7fc0477703037098a8e7185d7c69d..8c7c1028e5797dbc9b23ec88b58a4cd840db1c5c 100644 (file)
@@ -67,15 +67,15 @@ static int tegra20_spdif_hw_params(struct snd_pcm_substream *substream,
 {
        struct device *dev = dai->dev;
        struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(dai);
-       unsigned int mask, val;
+       unsigned int mask = 0, val = 0;
        int ret, spdifclock;
 
-       mask = TEGRA20_SPDIF_CTRL_PACK |
-              TEGRA20_SPDIF_CTRL_BIT_MODE_MASK;
+       mask |= TEGRA20_SPDIF_CTRL_PACK |
+               TEGRA20_SPDIF_CTRL_BIT_MODE_MASK;
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S16_LE:
-               val = TEGRA20_SPDIF_CTRL_PACK |
-                     TEGRA20_SPDIF_CTRL_BIT_MODE_16BIT;
+               val |= TEGRA20_SPDIF_CTRL_PACK |
+                      TEGRA20_SPDIF_CTRL_BIT_MODE_16BIT;
                break;
        default:
                return -EINVAL;
index 231a785b3921a5bd95d87914a92e7f5f2d266a63..02247fee1cf7e1450fb4bbcdf2e58cf5ee76c7e8 100644 (file)
@@ -118,7 +118,7 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai,
                                unsigned int fmt)
 {
        struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
-       unsigned int mask, val;
+       unsigned int mask = 0, val = 0;
 
        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
        case SND_SOC_DAIFMT_NB_NF:
@@ -127,10 +127,10 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai,
                return -EINVAL;
        }
 
-       mask = TEGRA30_I2S_CTRL_MASTER_ENABLE;
+       mask |= TEGRA30_I2S_CTRL_MASTER_ENABLE;
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBS_CFS:
-               val = TEGRA30_I2S_CTRL_MASTER_ENABLE;
+               val |= TEGRA30_I2S_CTRL_MASTER_ENABLE;
                break;
        case SND_SOC_DAIFMT_CBM_CFM:
                break;
diff --git a/sound/soc/tegra/tegra_max98090.c b/sound/soc/tegra/tegra_max98090.c
new file mode 100644 (file)
index 0000000..0283cfb
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ * Tegra machine ASoC driver for boards using a MAX90809 CODEC.
+ *
+ * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Based on code copyright/by:
+ *
+ * Copyright (C) 2010-2012 - NVIDIA, Inc.
+ * Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.lauchpad.net>
+ * (c) 2009, 2010 Nvidia Graphics Pvt. Ltd.
+ * Copyright 2007 Wolfson Microelectronics PLC.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+
+#include <sound/core.h>
+#include <sound/jack.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include "tegra_asoc_utils.h"
+
+#define DRV_NAME "tegra-snd-max98090"
+
+struct tegra_max98090 {
+       struct tegra_asoc_utils_data util_data;
+       int gpio_hp_det;
+};
+
+static int tegra_max98090_asoc_hw_params(struct snd_pcm_substream *substream,
+                                       struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_codec *codec = codec_dai->codec;
+       struct snd_soc_card *card = codec->card;
+       struct tegra_max98090 *machine = snd_soc_card_get_drvdata(card);
+       int srate, mclk;
+       int err;
+
+       srate = params_rate(params);
+       switch (srate) {
+       case 8000:
+       case 16000:
+       case 24000:
+       case 32000:
+       case 48000:
+       case 64000:
+       case 96000:
+               mclk = 12288000;
+               break;
+       case 11025:
+       case 22050:
+       case 44100:
+       case 88200:
+               mclk = 11289600;
+               break;
+       default:
+               mclk = 12000000;
+               break;
+       }
+
+       err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
+       if (err < 0) {
+               dev_err(card->dev, "Can't configure clocks\n");
+               return err;
+       }
+
+       err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
+                                       SND_SOC_CLOCK_IN);
+       if (err < 0) {
+               dev_err(card->dev, "codec_dai clock not set\n");
+               return err;
+       }
+
+       return 0;
+}
+
+static struct snd_soc_ops tegra_max98090_ops = {
+       .hw_params = tegra_max98090_asoc_hw_params,
+};
+
+static struct snd_soc_jack tegra_max98090_hp_jack;
+
+static struct snd_soc_jack_pin tegra_max98090_hp_jack_pins[] = {
+       {
+               .pin = "Headphones",
+               .mask = SND_JACK_HEADPHONE,
+       },
+};
+
+static struct snd_soc_jack_gpio tegra_max98090_hp_jack_gpio = {
+       .name = "Headphone detection",
+       .report = SND_JACK_HEADPHONE,
+       .debounce_time = 150,
+       .invert = 1,
+};
+
+static const struct snd_soc_dapm_widget tegra_max98090_dapm_widgets[] = {
+       SND_SOC_DAPM_HP("Headphones", NULL),
+       SND_SOC_DAPM_SPK("Speakers", NULL),
+       SND_SOC_DAPM_MIC("Mic Jack", NULL),
+};
+
+static const struct snd_kcontrol_new tegra_max98090_controls[] = {
+       SOC_DAPM_PIN_SWITCH("Speakers"),
+};
+
+static int tegra_max98090_asoc_init(struct snd_soc_pcm_runtime *rtd)
+{
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_codec *codec = codec_dai->codec;
+       struct tegra_max98090 *machine = snd_soc_card_get_drvdata(codec->card);
+
+       if (gpio_is_valid(machine->gpio_hp_det)) {
+               snd_soc_jack_new(codec, "Headphones", SND_JACK_HEADPHONE,
+                               &tegra_max98090_hp_jack);
+               snd_soc_jack_add_pins(&tegra_max98090_hp_jack,
+                               ARRAY_SIZE(tegra_max98090_hp_jack_pins),
+                               tegra_max98090_hp_jack_pins);
+
+               tegra_max98090_hp_jack_gpio.gpio = machine->gpio_hp_det;
+               snd_soc_jack_add_gpios(&tegra_max98090_hp_jack,
+                                       1,
+                                       &tegra_max98090_hp_jack_gpio);
+       }
+
+       return 0;
+}
+
+static struct snd_soc_dai_link tegra_max98090_dai = {
+       .name = "max98090",
+       .stream_name = "max98090 PCM",
+       .codec_dai_name = "HiFi",
+       .init = tegra_max98090_asoc_init,
+       .ops = &tegra_max98090_ops,
+       .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+                       SND_SOC_DAIFMT_CBS_CFS,
+};
+
+static struct snd_soc_card snd_soc_tegra_max98090 = {
+       .name = "tegra-max98090",
+       .owner = THIS_MODULE,
+       .dai_link = &tegra_max98090_dai,
+       .num_links = 1,
+       .controls = tegra_max98090_controls,
+       .num_controls = ARRAY_SIZE(tegra_max98090_controls),
+       .dapm_widgets = tegra_max98090_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(tegra_max98090_dapm_widgets),
+       .fully_routed = true,
+};
+
+static int tegra_max98090_probe(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       struct snd_soc_card *card = &snd_soc_tegra_max98090;
+       struct tegra_max98090 *machine;
+       int ret;
+
+       machine = devm_kzalloc(&pdev->dev,
+                       sizeof(struct tegra_max98090), GFP_KERNEL);
+       if (!machine) {
+               dev_err(&pdev->dev, "Can't allocate tegra_max98090\n");
+               return -ENOMEM;
+       }
+
+       card->dev = &pdev->dev;
+       platform_set_drvdata(pdev, card);
+       snd_soc_card_set_drvdata(card, machine);
+
+       machine->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0);
+       if (machine->gpio_hp_det == -EPROBE_DEFER)
+               return -EPROBE_DEFER;
+
+       ret = snd_soc_of_parse_card_name(card, "nvidia,model");
+       if (ret)
+               goto err;
+
+       ret = snd_soc_of_parse_audio_routing(card, "nvidia,audio-routing");
+       if (ret)
+               goto err;
+
+       tegra_max98090_dai.codec_of_node = of_parse_phandle(np,
+                       "nvidia,audio-codec", 0);
+       if (!tegra_max98090_dai.codec_of_node) {
+               dev_err(&pdev->dev,
+                       "Property 'nvidia,audio-codec' missing or invalid\n");
+               ret = -EINVAL;
+               goto err;
+       }
+
+       tegra_max98090_dai.cpu_of_node = of_parse_phandle(np,
+                       "nvidia,i2s-controller", 0);
+       if (!tegra_max98090_dai.cpu_of_node) {
+               dev_err(&pdev->dev,
+                       "Property 'nvidia,i2s-controller' missing or invalid\n");
+               ret = -EINVAL;
+               goto err;
+       }
+
+       tegra_max98090_dai.platform_of_node = tegra_max98090_dai.cpu_of_node;
+
+       ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev);
+       if (ret)
+               goto err;
+
+       ret = snd_soc_register_card(card);
+       if (ret) {
+               dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
+                       ret);
+               goto err_fini_utils;
+       }
+
+       return 0;
+
+err_fini_utils:
+       tegra_asoc_utils_fini(&machine->util_data);
+err:
+       return ret;
+}
+
+static int tegra_max98090_remove(struct platform_device *pdev)
+{
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
+       struct tegra_max98090 *machine = snd_soc_card_get_drvdata(card);
+
+       snd_soc_jack_free_gpios(&tegra_max98090_hp_jack, 1,
+                               &tegra_max98090_hp_jack_gpio);
+
+       snd_soc_unregister_card(card);
+
+       tegra_asoc_utils_fini(&machine->util_data);
+
+       return 0;
+}
+
+static const struct of_device_id tegra_max98090_of_match[] = {
+       { .compatible = "nvidia,tegra-audio-max98090", },
+       {},
+};
+
+static struct platform_driver tegra_max98090_driver = {
+       .driver = {
+               .name = DRV_NAME,
+               .owner = THIS_MODULE,
+               .pm = &snd_soc_pm_ops,
+               .of_match_table = tegra_max98090_of_match,
+       },
+       .probe = tegra_max98090_probe,
+       .remove = tegra_max98090_remove,
+};
+module_platform_driver(tegra_max98090_driver);
+
+MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
+MODULE_DESCRIPTION("Tegra max98090 machine ASoC driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, tegra_max98090_of_match);
index 8e3d9a6c7a3ba6e88f6cd29d0894a6c5a69162d7..25c38afaee4900463692c93b4182db82f93b36bd 100644 (file)
@@ -174,7 +174,7 @@ static int snd_at73c213_set_bitrate(struct snd_at73c213 *chip)
                dac_rate_new = 8 * (ssc_rate / ssc_div);
 
                status = clk_round_rate(chip->board->dac_clk, dac_rate_new);
-               if (status < 0)
+               if (status <= 0)
                        return status;
 
                /* Ignore difference smaller than 256 Hz. */
index 3454262358b398913779954846ab12c11e7c5973..f4b12c216f1cd55c2db4396746a5abc9f20ed302 100644 (file)
@@ -1603,7 +1603,7 @@ static int snd_microii_controls_create(struct usb_mixer_interface *mixer)
                        return err;
        }
 
-       return err;
+       return 0;
 }
 
 int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
diff --git a/tools/lib/lockdep/Makefile b/tools/lib/lockdep/Makefile
new file mode 100644 (file)
index 0000000..da8b7aa
--- /dev/null
@@ -0,0 +1,251 @@
+# liblockdep version
+LL_VERSION = 0
+LL_PATCHLEVEL = 0
+LL_EXTRAVERSION = 1
+
+# file format version
+FILE_VERSION = 1
+
+MAKEFLAGS += --no-print-directory
+
+
+# Makefiles suck: This macro sets a default value of $(2) for the
+# variable named by $(1), unless the variable has been set by
+# environment or command line. This is necessary for CC and AR
+# because make sets default values, so the simpler ?= approach
+# won't work as expected.
+define allow-override
+  $(if $(or $(findstring environment,$(origin $(1))),\
+            $(findstring command line,$(origin $(1)))),,\
+    $(eval $(1) = $(2)))
+endef
+
+# Allow setting CC and AR, or setting CROSS_COMPILE as a prefix.
+$(call allow-override,CC,$(CROSS_COMPILE)gcc)
+$(call allow-override,AR,$(CROSS_COMPILE)ar)
+
+INSTALL = install
+
+# Use DESTDIR for installing into a different root directory.
+# This is useful for building a package. The program will be
+# installed in this directory as if it was the root directory.
+# Then the build tool can move it later.
+DESTDIR ?=
+DESTDIR_SQ = '$(subst ','\'',$(DESTDIR))'
+
+prefix ?= /usr/local
+libdir_relative = lib
+libdir = $(prefix)/$(libdir_relative)
+bindir_relative = bin
+bindir = $(prefix)/$(bindir_relative)
+
+export DESTDIR DESTDIR_SQ INSTALL
+
+# copy a bit from Linux kbuild
+
+ifeq ("$(origin V)", "command line")
+  VERBOSE = $(V)
+endif
+ifndef VERBOSE
+  VERBOSE = 0
+endif
+
+ifeq ("$(origin O)", "command line")
+  BUILD_OUTPUT := $(O)
+endif
+
+ifeq ($(BUILD_SRC),)
+ifneq ($(BUILD_OUTPUT),)
+
+define build_output
+       $(if $(VERBOSE:1=),@)$(MAKE) -C $(BUILD_OUTPUT) \
+       BUILD_SRC=$(CURDIR) -f $(CURDIR)/Makefile $1
+endef
+
+saved-output := $(BUILD_OUTPUT)
+BUILD_OUTPUT := $(shell cd $(BUILD_OUTPUT) && /bin/pwd)
+$(if $(BUILD_OUTPUT),, \
+     $(error output directory "$(saved-output)" does not exist))
+
+all: sub-make
+
+gui: force
+       $(call build_output, all_cmd)
+
+$(filter-out gui,$(MAKECMDGOALS)): sub-make
+
+sub-make: force
+       $(call build_output, $(MAKECMDGOALS))
+
+
+# Leave processing to above invocation of make
+skip-makefile := 1
+
+endif # BUILD_OUTPUT
+endif # BUILD_SRC
+
+# We process the rest of the Makefile if this is the final invocation of make
+ifeq ($(skip-makefile),)
+
+srctree                := $(if $(BUILD_SRC),$(BUILD_SRC),$(CURDIR))
+objtree                := $(CURDIR)
+src            := $(srctree)
+obj            := $(objtree)
+
+export prefix libdir bindir src obj
+
+# Shell quotes
+libdir_SQ = $(subst ','\'',$(libdir))
+bindir_SQ = $(subst ','\'',$(bindir))
+
+LIB_FILE = liblockdep.a liblockdep.so
+BIN_FILE = lockdep
+
+CONFIG_INCLUDES =
+CONFIG_LIBS    =
+CONFIG_FLAGS   =
+
+OBJ            = $@
+N              =
+
+export Q VERBOSE
+
+LIBLOCKDEP_VERSION = $(LL_VERSION).$(LL_PATCHLEVEL).$(LL_EXTRAVERSION)
+
+INCLUDES = -I. -I/usr/local/include -I./uinclude $(CONFIG_INCLUDES)
+
+# Set compile option CFLAGS if not set elsewhere
+CFLAGS ?= -g -DCONFIG_LOCKDEP -DCONFIG_STACKTRACE -DCONFIG_PROVE_LOCKING -DBITS_PER_LONG=__WORDSIZE -DLIBLOCKDEP_VERSION='"$(LIBLOCKDEP_VERSION)"' -rdynamic -O0 -g
+
+override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ)
+
+ifeq ($(VERBOSE),1)
+  Q =
+  print_compile =
+  print_app_build =
+  print_fpic_compile =
+  print_shared_lib_compile =
+  print_install =
+else
+  Q = @
+  print_compile =              echo '  CC                 '$(OBJ);
+  print_app_build =            echo '  BUILD              '$(OBJ);
+  print_fpic_compile =         echo '  CC FPIC            '$(OBJ);
+  print_shared_lib_compile =   echo '  BUILD SHARED LIB   '$(OBJ);
+  print_static_lib_build =     echo '  BUILD STATIC LIB   '$(OBJ);
+  print_install =              echo '  INSTALL     '$1'        to      $(DESTDIR_SQ)$2';
+endif
+
+do_fpic_compile =                                      \
+       ($(print_fpic_compile)                          \
+       $(CC) -c $(CFLAGS) $(EXT) -fPIC $< -o $@)
+
+do_app_build =                                         \
+       ($(print_app_build)                             \
+       $(CC) $^ -rdynamic -o $@ $(CONFIG_LIBS) $(LIBS))
+
+do_compile_shared_library =                    \
+       ($(print_shared_lib_compile)            \
+       $(CC) --shared $^ -o $@ -lpthread -ldl)
+
+do_build_static_lib =                          \
+       ($(print_static_lib_build)              \
+       $(RM) $@;  $(AR) rcs $@ $^)
+
+
+define do_compile
+       $(print_compile)                                                \
+       $(CC) -c $(CFLAGS) $(EXT) $< -o $(obj)/$@;
+endef
+
+$(obj)/%.o: $(src)/%.c
+       $(Q)$(call do_compile)
+
+%.o: $(src)/%.c
+       $(Q)$(call do_compile)
+
+PEVENT_LIB_OBJS = common.o lockdep.o preload.o rbtree.o
+
+ALL_OBJS = $(PEVENT_LIB_OBJS)
+
+CMD_TARGETS = $(LIB_FILE)
+
+TARGETS = $(CMD_TARGETS)
+
+
+all: all_cmd
+
+all_cmd: $(CMD_TARGETS)
+
+liblockdep.so: $(PEVENT_LIB_OBJS)
+       $(Q)$(do_compile_shared_library)
+
+liblockdep.a: $(PEVENT_LIB_OBJS)
+       $(Q)$(do_build_static_lib)
+
+$(PEVENT_LIB_OBJS): %.o: $(src)/%.c
+       $(Q)$(do_fpic_compile)
+
+## make deps
+
+all_objs := $(sort $(ALL_OBJS))
+all_deps := $(all_objs:%.o=.%.d)
+
+# let .d file also depends on the source and header files
+define check_deps
+               @set -e; $(RM) $@; \
+               $(CC) -MM $(CFLAGS) $< > $@.$$$$; \
+               sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
+               $(RM) $@.$$$$
+endef
+
+$(all_deps): .%.d: $(src)/%.c
+       $(Q)$(call check_deps)
+
+$(all_objs) : %.o : .%.d
+
+dep_includes := $(wildcard $(all_deps))
+
+ifneq ($(dep_includes),)
+ include $(dep_includes)
+endif
+
+### Detect environment changes
+TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):$(ARCH):$(CROSS_COMPILE)
+
+tags:  force
+       $(RM) tags
+       find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \
+       --regex-c++='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/'
+
+TAGS:  force
+       $(RM) TAGS
+       find . -name '*.[ch]' | xargs etags \
+       --regex='/_PE(\([^,)]*\).*/PEVENT_ERRNO__\1/'
+
+define do_install
+       $(print_install)                                \
+       if [ ! -d '$(DESTDIR_SQ)$2' ]; then             \
+               $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$2'; \
+       fi;                                             \
+       $(INSTALL) $1 '$(DESTDIR_SQ)$2'
+endef
+
+install_lib: all_cmd
+       $(Q)$(call do_install,$(LIB_FILE),$(libdir_SQ))
+       $(Q)$(call do_install,$(BIN_FILE),$(bindir_SQ))
+
+install: install_lib
+
+clean:
+       $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d
+       $(RM) tags TAGS
+
+endif # skip-makefile
+
+PHONY += force
+force:
+
+# Declare the contents of the .PHONY variable as phony.  We keep that
+# information in a variable so we can use it in if_changed and friends.
+.PHONY: $(PHONY)
diff --git a/tools/lib/lockdep/common.c b/tools/lib/lockdep/common.c
new file mode 100644 (file)
index 0000000..8ef602f
--- /dev/null
@@ -0,0 +1,33 @@
+#include <stddef.h>
+#include <stdbool.h>
+#include <linux/compiler.h>
+#include <linux/lockdep.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+
+static __thread struct task_struct current_obj;
+
+/* lockdep wants these */
+bool debug_locks = true;
+bool debug_locks_silent;
+
+__attribute__((constructor)) static void liblockdep_init(void)
+{
+       lockdep_init();
+}
+
+__attribute__((destructor)) static void liblockdep_exit(void)
+{
+       debug_check_no_locks_held(&current_obj);
+}
+
+struct task_struct *__curr(void)
+{
+       if (current_obj.pid == 0) {
+               /* Makes lockdep output pretty */
+               prctl(PR_GET_NAME, current_obj.comm);
+               current_obj.pid = syscall(__NR_gettid);
+       }
+
+       return &current_obj;
+}
diff --git a/tools/lib/lockdep/include/liblockdep/common.h b/tools/lib/lockdep/include/liblockdep/common.h
new file mode 100644 (file)
index 0000000..0bda630
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef _LIBLOCKDEP_COMMON_H
+#define _LIBLOCKDEP_COMMON_H
+
+#include <pthread.h>
+
+#define NR_LOCKDEP_CACHING_CLASSES 2
+#define MAX_LOCKDEP_SUBCLASSES 8UL
+
+#ifndef CALLER_ADDR0
+#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
+#endif
+
+#ifndef _RET_IP_
+#define _RET_IP_ CALLER_ADDR0
+#endif
+
+#ifndef _THIS_IP_
+#define _THIS_IP_ ({ __label__ __here; __here: (unsigned long)&&__here; })
+#endif
+
+struct lockdep_subclass_key {
+       char __one_byte;
+};
+
+struct lock_class_key {
+       struct lockdep_subclass_key subkeys[MAX_LOCKDEP_SUBCLASSES];
+};
+
+struct lockdep_map {
+       struct lock_class_key   *key;
+       struct lock_class       *class_cache[NR_LOCKDEP_CACHING_CLASSES];
+       const char              *name;
+#ifdef CONFIG_LOCK_STAT
+       int                     cpu;
+       unsigned long           ip;
+#endif
+};
+
+void lockdep_init_map(struct lockdep_map *lock, const char *name,
+                       struct lock_class_key *key, int subclass);
+void lock_acquire(struct lockdep_map *lock, unsigned int subclass,
+                       int trylock, int read, int check,
+                       struct lockdep_map *nest_lock, unsigned long ip);
+void lock_release(struct lockdep_map *lock, int nested,
+                       unsigned long ip);
+
+#define STATIC_LOCKDEP_MAP_INIT(_name, _key) \
+       { .name = (_name), .key = (void *)(_key), }
+
+#endif
diff --git a/tools/lib/lockdep/include/liblockdep/mutex.h b/tools/lib/lockdep/include/liblockdep/mutex.h
new file mode 100644 (file)
index 0000000..c342f70
--- /dev/null
@@ -0,0 +1,70 @@
+#ifndef _LIBLOCKDEP_MUTEX_H
+#define _LIBLOCKDEP_MUTEX_H
+
+#include <pthread.h>
+#include "common.h"
+
+struct liblockdep_pthread_mutex {
+       pthread_mutex_t mutex;
+       struct lockdep_map dep_map;
+};
+
+typedef struct liblockdep_pthread_mutex liblockdep_pthread_mutex_t;
+
+#define LIBLOCKDEP_PTHREAD_MUTEX_INITIALIZER(mtx)                      \
+               (const struct liblockdep_pthread_mutex) {               \
+       .mutex = PTHREAD_MUTEX_INITIALIZER,                             \
+       .dep_map = STATIC_LOCKDEP_MAP_INIT(#mtx, &((&(mtx))->dep_map)), \
+}
+
+static inline int __mutex_init(liblockdep_pthread_mutex_t *lock,
+                               const char *name,
+                               struct lock_class_key *key,
+                               const pthread_mutexattr_t *__mutexattr)
+{
+       lockdep_init_map(&lock->dep_map, name, key, 0);
+       return pthread_mutex_init(&lock->mutex, __mutexattr);
+}
+
+#define liblockdep_pthread_mutex_init(mutex, mutexattr)                \
+({                                                             \
+       static struct lock_class_key __key;                     \
+                                                               \
+       __mutex_init((mutex), #mutex, &__key, (mutexattr));     \
+})
+
+static inline int liblockdep_pthread_mutex_lock(liblockdep_pthread_mutex_t *lock)
+{
+       lock_acquire(&lock->dep_map, 0, 0, 0, 2, NULL, (unsigned long)_RET_IP_);
+       return pthread_mutex_lock(&lock->mutex);
+}
+
+static inline int liblockdep_pthread_mutex_unlock(liblockdep_pthread_mutex_t *lock)
+{
+       lock_release(&lock->dep_map, 0, (unsigned long)_RET_IP_);
+       return pthread_mutex_unlock(&lock->mutex);
+}
+
+static inline int liblockdep_pthread_mutex_trylock(liblockdep_pthread_mutex_t *lock)
+{
+       lock_acquire(&lock->dep_map, 0, 1, 0, 2, NULL, (unsigned long)_RET_IP_);
+       return pthread_mutex_trylock(&lock->mutex) == 0 ? 1 : 0;
+}
+
+static inline int liblockdep_pthread_mutex_destroy(liblockdep_pthread_mutex_t *lock)
+{
+       return pthread_mutex_destroy(&lock->mutex);
+}
+
+#ifdef __USE_LIBLOCKDEP
+
+#define pthread_mutex_t         liblockdep_pthread_mutex_t
+#define pthread_mutex_init      liblockdep_pthread_mutex_init
+#define pthread_mutex_lock      liblockdep_pthread_mutex_lock
+#define pthread_mutex_unlock    liblockdep_pthread_mutex_unlock
+#define pthread_mutex_trylock   liblockdep_pthread_mutex_trylock
+#define pthread_mutex_destroy   liblockdep_pthread_mutex_destroy
+
+#endif
+
+#endif
diff --git a/tools/lib/lockdep/include/liblockdep/rwlock.h b/tools/lib/lockdep/include/liblockdep/rwlock.h
new file mode 100644 (file)
index 0000000..a680ab8
--- /dev/null
@@ -0,0 +1,86 @@
+#ifndef _LIBLOCKDEP_RWLOCK_H
+#define _LIBLOCKDEP_RWLOCK_H
+
+#include <pthread.h>
+#include "common.h"
+
+struct liblockdep_pthread_rwlock {
+       pthread_rwlock_t rwlock;
+       struct lockdep_map dep_map;
+};
+
+typedef struct liblockdep_pthread_rwlock liblockdep_pthread_rwlock_t;
+
+#define LIBLOCKDEP_PTHREAD_RWLOCK_INITIALIZER(rwl)                     \
+               (struct liblockdep_pthread_rwlock) {                    \
+       .rwlock = PTHREAD_RWLOCK_INITIALIZER,                           \
+       .dep_map = STATIC_LOCKDEP_MAP_INIT(#rwl, &((&(rwl))->dep_map)), \
+}
+
+static inline int __rwlock_init(liblockdep_pthread_rwlock_t *lock,
+                               const char *name,
+                               struct lock_class_key *key,
+                               const pthread_rwlockattr_t *attr)
+{
+       lockdep_init_map(&lock->dep_map, name, key, 0);
+
+       return pthread_rwlock_init(&lock->rwlock, attr);
+}
+
+#define liblockdep_pthread_rwlock_init(lock, attr)             \
+({                                                     \
+       static struct lock_class_key __key;             \
+                                                       \
+       __rwlock_init((lock), #lock, &__key, (attr));   \
+})
+
+static inline int liblockdep_pthread_rwlock_rdlock(liblockdep_pthread_rwlock_t *lock)
+{
+       lock_acquire(&lock->dep_map, 0, 0, 2, 2, NULL, (unsigned long)_RET_IP_);
+       return pthread_rwlock_rdlock(&lock->rwlock);
+
+}
+
+static inline int liblockdep_pthread_rwlock_unlock(liblockdep_pthread_rwlock_t *lock)
+{
+       lock_release(&lock->dep_map, 0, (unsigned long)_RET_IP_);
+       return pthread_rwlock_unlock(&lock->rwlock);
+}
+
+static inline int liblockdep_pthread_rwlock_wrlock(liblockdep_pthread_rwlock_t *lock)
+{
+       lock_acquire(&lock->dep_map, 0, 0, 0, 2, NULL, (unsigned long)_RET_IP_);
+       return pthread_rwlock_wrlock(&lock->rwlock);
+}
+
+static inline int liblockdep_pthread_rwlock_tryrdlock(liblockdep_pthread_rwlock_t *lock)
+{
+       lock_acquire(&lock->dep_map, 0, 1, 2, 2, NULL, (unsigned long)_RET_IP_);
+       return pthread_rwlock_tryrdlock(&lock->rwlock) == 0 ? 1 : 0;
+}
+
+static inline int liblockdep_pthread_rwlock_trywlock(liblockdep_pthread_rwlock_t *lock)
+{
+       lock_acquire(&lock->dep_map, 0, 1, 0, 2, NULL, (unsigned long)_RET_IP_);
+       return pthread_rwlock_trywlock(&lock->rwlock) == 0 ? 1 : 0;
+}
+
+static inline int liblockdep_rwlock_destroy(liblockdep_pthread_rwlock_t *lock)
+{
+       return pthread_rwlock_destroy(&lock->rwlock);
+}
+
+#ifdef __USE_LIBLOCKDEP
+
+#define pthread_rwlock_t               liblockdep_pthread_rwlock_t
+#define pthread_rwlock_init            liblockdep_pthread_rwlock_init
+#define pthread_rwlock_rdlock          liblockdep_pthread_rwlock_rdlock
+#define pthread_rwlock_unlock          liblockdep_pthread_rwlock_unlock
+#define pthread_rwlock_wrlock          liblockdep_pthread_rwlock_wrlock
+#define pthread_rwlock_tryrdlock       liblockdep_pthread_rwlock_tryrdlock
+#define pthread_rwlock_trywlock                liblockdep_pthread_rwlock_trywlock
+#define pthread_rwlock_destroy         liblockdep_rwlock_destroy
+
+#endif
+
+#endif
diff --git a/tools/lib/lockdep/lockdep b/tools/lib/lockdep/lockdep
new file mode 100755 (executable)
index 0000000..49af9fe
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+LD_PRELOAD="./liblockdep.so $LD_PRELOAD" "$@"
diff --git a/tools/lib/lockdep/lockdep.c b/tools/lib/lockdep/lockdep.c
new file mode 100644 (file)
index 0000000..f42b7e9
--- /dev/null
@@ -0,0 +1,2 @@
+#include <linux/lockdep.h>
+#include "../../../kernel/locking/lockdep.c"
diff --git a/tools/lib/lockdep/lockdep_internals.h b/tools/lib/lockdep/lockdep_internals.h
new file mode 100644 (file)
index 0000000..29d0c95
--- /dev/null
@@ -0,0 +1 @@
+#include "../../../kernel/locking/lockdep_internals.h"
diff --git a/tools/lib/lockdep/lockdep_states.h b/tools/lib/lockdep/lockdep_states.h
new file mode 100644 (file)
index 0000000..248d235
--- /dev/null
@@ -0,0 +1 @@
+#include "../../../kernel/locking/lockdep_states.h"
diff --git a/tools/lib/lockdep/preload.c b/tools/lib/lockdep/preload.c
new file mode 100644 (file)
index 0000000..f8465a8
--- /dev/null
@@ -0,0 +1,447 @@
+#define _GNU_SOURCE
+#include <pthread.h>
+#include <stdio.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <sysexits.h>
+#include "include/liblockdep/mutex.h"
+#include "../../../include/linux/rbtree.h"
+
+/**
+ * struct lock_lookup - liblockdep's view of a single unique lock
+ * @orig: pointer to the original pthread lock, used for lookups
+ * @dep_map: lockdep's dep_map structure
+ * @key: lockdep's key structure
+ * @node: rb-tree node used to store the lock in a global tree
+ * @name: a unique name for the lock
+ */
+struct lock_lookup {
+       void *orig; /* Original pthread lock, used for lookups */
+       struct lockdep_map dep_map; /* Since all locks are dynamic, we need
+                                    * a dep_map and a key for each lock */
+       /*
+        * Wait, there's no support for key classes? Yup :(
+        * Most big projects wrap the pthread api with their own calls to
+        * be compatible with different locking methods. This means that
+        * "classes" will be brokes since the function that creates all
+        * locks will point to a generic locking function instead of the
+        * actual code that wants to do the locking.
+        */
+       struct lock_class_key key;
+       struct rb_node node;
+#define LIBLOCKDEP_MAX_LOCK_NAME 22
+       char name[LIBLOCKDEP_MAX_LOCK_NAME];
+};
+
+/* This is where we store our locks */
+static struct rb_root locks = RB_ROOT;
+static pthread_rwlock_t locks_rwlock = PTHREAD_RWLOCK_INITIALIZER;
+
+/* pthread mutex API */
+
+#ifdef __GLIBC__
+extern int __pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
+extern int __pthread_mutex_lock(pthread_mutex_t *mutex);
+extern int __pthread_mutex_trylock(pthread_mutex_t *mutex);
+extern int __pthread_mutex_unlock(pthread_mutex_t *mutex);
+extern int __pthread_mutex_destroy(pthread_mutex_t *mutex);
+#else
+#define __pthread_mutex_init   NULL
+#define __pthread_mutex_lock   NULL
+#define __pthread_mutex_trylock        NULL
+#define __pthread_mutex_unlock NULL
+#define __pthread_mutex_destroy        NULL
+#endif
+static int (*ll_pthread_mutex_init)(pthread_mutex_t *mutex,
+                       const pthread_mutexattr_t *attr)        = __pthread_mutex_init;
+static int (*ll_pthread_mutex_lock)(pthread_mutex_t *mutex)    = __pthread_mutex_lock;
+static int (*ll_pthread_mutex_trylock)(pthread_mutex_t *mutex) = __pthread_mutex_trylock;
+static int (*ll_pthread_mutex_unlock)(pthread_mutex_t *mutex)  = __pthread_mutex_unlock;
+static int (*ll_pthread_mutex_destroy)(pthread_mutex_t *mutex) = __pthread_mutex_destroy;
+
+/* pthread rwlock API */
+
+#ifdef __GLIBC__
+extern int __pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr);
+extern int __pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
+extern int __pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
+extern int __pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
+extern int __pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
+extern int __pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
+extern int __pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
+#else
+#define __pthread_rwlock_init          NULL
+#define __pthread_rwlock_destroy       NULL
+#define __pthread_rwlock_wrlock                NULL
+#define __pthread_rwlock_trywrlock     NULL
+#define __pthread_rwlock_rdlock                NULL
+#define __pthread_rwlock_tryrdlock     NULL
+#define __pthread_rwlock_unlock                NULL
+#endif
+
+static int (*ll_pthread_rwlock_init)(pthread_rwlock_t *rwlock,
+                       const pthread_rwlockattr_t *attr)               = __pthread_rwlock_init;
+static int (*ll_pthread_rwlock_destroy)(pthread_rwlock_t *rwlock)      = __pthread_rwlock_destroy;
+static int (*ll_pthread_rwlock_rdlock)(pthread_rwlock_t *rwlock)       = __pthread_rwlock_rdlock;
+static int (*ll_pthread_rwlock_tryrdlock)(pthread_rwlock_t *rwlock)    = __pthread_rwlock_tryrdlock;
+static int (*ll_pthread_rwlock_trywrlock)(pthread_rwlock_t *rwlock)    = __pthread_rwlock_trywrlock;
+static int (*ll_pthread_rwlock_wrlock)(pthread_rwlock_t *rwlock)       = __pthread_rwlock_wrlock;
+static int (*ll_pthread_rwlock_unlock)(pthread_rwlock_t *rwlock)       = __pthread_rwlock_unlock;
+
+enum { none, prepare, done, } __init_state;
+static void init_preload(void);
+static void try_init_preload(void)
+{
+       if (!__init_state != done)
+               init_preload();
+}
+
+static struct rb_node **__get_lock_node(void *lock, struct rb_node **parent)
+{
+       struct rb_node **node = &locks.rb_node;
+       struct lock_lookup *l;
+
+       *parent = NULL;
+
+       while (*node) {
+               l = rb_entry(*node, struct lock_lookup, node);
+
+               *parent = *node;
+               if (lock < l->orig)
+                       node = &l->node.rb_left;
+               else if (lock > l->orig)
+                       node = &l->node.rb_right;
+               else
+                       return node;
+       }
+
+       return node;
+}
+
+#ifndef LIBLOCKDEP_STATIC_ENTRIES
+#define LIBLOCKDEP_STATIC_ENTRIES      1024
+#endif
+
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+static struct lock_lookup __locks[LIBLOCKDEP_STATIC_ENTRIES];
+static int __locks_nr;
+
+static inline bool is_static_lock(struct lock_lookup *lock)
+{
+       return lock >= __locks && lock < __locks + ARRAY_SIZE(__locks);
+}
+
+static struct lock_lookup *alloc_lock(void)
+{
+       if (__init_state != done) {
+               /*
+                * Some programs attempt to initialize and use locks in their
+                * allocation path. This means that a call to malloc() would
+                * result in locks being initialized and locked.
+                *
+                * Why is it an issue for us? dlsym() below will try allocating
+                * to give us the original function. Since this allocation will
+                * result in a locking operations, we have to let pthread deal
+                * with it, but we can't! we don't have the pointer to the
+                * original API since we're inside dlsym() trying to get it
+                */
+
+               int idx = __locks_nr++;
+               if (idx >= ARRAY_SIZE(__locks)) {
+                       fprintf(stderr,
+               "LOCKDEP error: insufficient LIBLOCKDEP_STATIC_ENTRIES\n");
+                       exit(EX_UNAVAILABLE);
+               }
+               return __locks + idx;
+       }
+
+       return malloc(sizeof(struct lock_lookup));
+}
+
+static inline void free_lock(struct lock_lookup *lock)
+{
+       if (likely(!is_static_lock(lock)))
+               free(lock);
+}
+
+/**
+ * __get_lock - find or create a lock instance
+ * @lock: pointer to a pthread lock function
+ *
+ * Try to find an existing lock in the rbtree using the provided pointer. If
+ * one wasn't found - create it.
+ */
+static struct lock_lookup *__get_lock(void *lock)
+{
+       struct rb_node **node, *parent;
+       struct lock_lookup *l;
+
+       ll_pthread_rwlock_rdlock(&locks_rwlock);
+       node = __get_lock_node(lock, &parent);
+       ll_pthread_rwlock_unlock(&locks_rwlock);
+       if (*node) {
+               return rb_entry(*node, struct lock_lookup, node);
+       }
+
+       /* We didn't find the lock, let's create it */
+       l = alloc_lock();
+       if (l == NULL)
+               return NULL;
+
+       l->orig = lock;
+       /*
+        * Currently the name of the lock is the ptr value of the pthread lock,
+        * while not optimal, it makes debugging a bit easier.
+        *
+        * TODO: Get the real name of the lock using libdwarf
+        */
+       sprintf(l->name, "%p", lock);
+       lockdep_init_map(&l->dep_map, l->name, &l->key, 0);
+
+       ll_pthread_rwlock_wrlock(&locks_rwlock);
+       /* This might have changed since the last time we fetched it */
+       node = __get_lock_node(lock, &parent);
+       rb_link_node(&l->node, parent, node);
+       rb_insert_color(&l->node, &locks);
+       ll_pthread_rwlock_unlock(&locks_rwlock);
+
+       return l;
+}
+
+static void __del_lock(struct lock_lookup *lock)
+{
+       ll_pthread_rwlock_wrlock(&locks_rwlock);
+       rb_erase(&lock->node, &locks);
+       ll_pthread_rwlock_unlock(&locks_rwlock);
+       free_lock(lock);
+}
+
+int pthread_mutex_init(pthread_mutex_t *mutex,
+                       const pthread_mutexattr_t *attr)
+{
+       int r;
+
+       /*
+        * We keep trying to init our preload module because there might be
+        * code in init sections that tries to touch locks before we are
+        * initialized, in that case we'll need to manually call preload
+        * to get us going.
+        *
+        * Funny enough, kernel's lockdep had the same issue, and used
+        * (almost) the same solution. See look_up_lock_class() in
+        * kernel/locking/lockdep.c for details.
+        */
+       try_init_preload();
+
+       r = ll_pthread_mutex_init(mutex, attr);
+       if (r == 0)
+               /*
+                * We do a dummy initialization here so that lockdep could
+                * warn us if something fishy is going on - such as
+                * initializing a held lock.
+                */
+               __get_lock(mutex);
+
+       return r;
+}
+
+int pthread_mutex_lock(pthread_mutex_t *mutex)
+{
+       int r;
+
+       try_init_preload();
+
+       lock_acquire(&__get_lock(mutex)->dep_map, 0, 0, 0, 2, NULL,
+                       (unsigned long)_RET_IP_);
+       /*
+        * Here's the thing with pthread mutexes: unlike the kernel variant,
+        * they can fail.
+        *
+        * This means that the behaviour here is a bit different from what's
+        * going on in the kernel: there we just tell lockdep that we took the
+        * lock before actually taking it, but here we must deal with the case
+        * that locking failed.
+        *
+        * To do that we'll "release" the lock if locking failed - this way
+        * we'll get lockdep doing the correct checks when we try to take
+        * the lock, and if that fails - we'll be back to the correct
+        * state by releasing it.
+        */
+       r = ll_pthread_mutex_lock(mutex);
+       if (r)
+               lock_release(&__get_lock(mutex)->dep_map, 0, (unsigned long)_RET_IP_);
+
+       return r;
+}
+
+int pthread_mutex_trylock(pthread_mutex_t *mutex)
+{
+       int r;
+
+       try_init_preload();
+
+       lock_acquire(&__get_lock(mutex)->dep_map, 0, 1, 0, 2, NULL, (unsigned long)_RET_IP_);
+       r = ll_pthread_mutex_trylock(mutex);
+       if (r)
+               lock_release(&__get_lock(mutex)->dep_map, 0, (unsigned long)_RET_IP_);
+
+       return r;
+}
+
+int pthread_mutex_unlock(pthread_mutex_t *mutex)
+{
+       int r;
+
+       try_init_preload();
+
+       lock_release(&__get_lock(mutex)->dep_map, 0, (unsigned long)_RET_IP_);
+       /*
+        * Just like taking a lock, only in reverse!
+        *
+        * If we fail releasing the lock, tell lockdep we're holding it again.
+        */
+       r = ll_pthread_mutex_unlock(mutex);
+       if (r)
+               lock_acquire(&__get_lock(mutex)->dep_map, 0, 0, 0, 2, NULL, (unsigned long)_RET_IP_);
+
+       return r;
+}
+
+int pthread_mutex_destroy(pthread_mutex_t *mutex)
+{
+       try_init_preload();
+
+       /*
+        * Let's see if we're releasing a lock that's held.
+        *
+        * TODO: Hook into free() and add that check there as well.
+        */
+       debug_check_no_locks_freed(mutex, mutex + sizeof(*mutex));
+       __del_lock(__get_lock(mutex));
+       return ll_pthread_mutex_destroy(mutex);
+}
+
+/* This is the rwlock part, very similar to what happened with mutex above */
+int pthread_rwlock_init(pthread_rwlock_t *rwlock,
+                       const pthread_rwlockattr_t *attr)
+{
+       int r;
+
+       try_init_preload();
+
+       r = ll_pthread_rwlock_init(rwlock, attr);
+       if (r == 0)
+               __get_lock(rwlock);
+
+       return r;
+}
+
+int pthread_rwlock_destroy(pthread_rwlock_t *rwlock)
+{
+       try_init_preload();
+
+       debug_check_no_locks_freed(rwlock, rwlock + sizeof(*rwlock));
+       __del_lock(__get_lock(rwlock));
+       return ll_pthread_rwlock_destroy(rwlock);
+}
+
+int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock)
+{
+       int r;
+
+        init_preload();
+
+       lock_acquire(&__get_lock(rwlock)->dep_map, 0, 0, 2, 2, NULL, (unsigned long)_RET_IP_);
+       r = ll_pthread_rwlock_rdlock(rwlock);
+       if (r)
+               lock_release(&__get_lock(rwlock)->dep_map, 0, (unsigned long)_RET_IP_);
+
+       return r;
+}
+
+int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock)
+{
+       int r;
+
+        init_preload();
+
+       lock_acquire(&__get_lock(rwlock)->dep_map, 0, 1, 2, 2, NULL, (unsigned long)_RET_IP_);
+       r = ll_pthread_rwlock_tryrdlock(rwlock);
+       if (r)
+               lock_release(&__get_lock(rwlock)->dep_map, 0, (unsigned long)_RET_IP_);
+
+       return r;
+}
+
+int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock)
+{
+       int r;
+
+        init_preload();
+
+       lock_acquire(&__get_lock(rwlock)->dep_map, 0, 1, 0, 2, NULL, (unsigned long)_RET_IP_);
+       r = ll_pthread_rwlock_trywrlock(rwlock);
+       if (r)
+                lock_release(&__get_lock(rwlock)->dep_map, 0, (unsigned long)_RET_IP_);
+
+       return r;
+}
+
+int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock)
+{
+       int r;
+
+        init_preload();
+
+       lock_acquire(&__get_lock(rwlock)->dep_map, 0, 0, 0, 2, NULL, (unsigned long)_RET_IP_);
+       r = ll_pthread_rwlock_wrlock(rwlock);
+       if (r)
+               lock_release(&__get_lock(rwlock)->dep_map, 0, (unsigned long)_RET_IP_);
+
+       return r;
+}
+
+int pthread_rwlock_unlock(pthread_rwlock_t *rwlock)
+{
+       int r;
+
+        init_preload();
+
+       lock_release(&__get_lock(rwlock)->dep_map, 0, (unsigned long)_RET_IP_);
+       r = ll_pthread_rwlock_unlock(rwlock);
+       if (r)
+               lock_acquire(&__get_lock(rwlock)->dep_map, 0, 0, 0, 2, NULL, (unsigned long)_RET_IP_);
+
+       return r;
+}
+
+__attribute__((constructor)) static void init_preload(void)
+{
+       if (__init_state != done)
+               return;
+
+#ifndef __GLIBC__
+       __init_state = prepare;
+
+       ll_pthread_mutex_init = dlsym(RTLD_NEXT, "pthread_mutex_init");
+       ll_pthread_mutex_lock = dlsym(RTLD_NEXT, "pthread_mutex_lock");
+       ll_pthread_mutex_trylock = dlsym(RTLD_NEXT, "pthread_mutex_trylock");
+       ll_pthread_mutex_unlock = dlsym(RTLD_NEXT, "pthread_mutex_unlock");
+       ll_pthread_mutex_destroy = dlsym(RTLD_NEXT, "pthread_mutex_destroy");
+
+       ll_pthread_rwlock_init = dlsym(RTLD_NEXT, "pthread_rwlock_init");
+       ll_pthread_rwlock_destroy = dlsym(RTLD_NEXT, "pthread_rwlock_destroy");
+       ll_pthread_rwlock_rdlock = dlsym(RTLD_NEXT, "pthread_rwlock_rdlock");
+       ll_pthread_rwlock_tryrdlock = dlsym(RTLD_NEXT, "pthread_rwlock_tryrdlock");
+       ll_pthread_rwlock_wrlock = dlsym(RTLD_NEXT, "pthread_rwlock_wrlock");
+       ll_pthread_rwlock_trywrlock = dlsym(RTLD_NEXT, "pthread_rwlock_trywrlock");
+       ll_pthread_rwlock_unlock = dlsym(RTLD_NEXT, "pthread_rwlock_unlock");
+#endif
+
+       printf("%p\n", ll_pthread_mutex_trylock);fflush(stdout);
+
+       lockdep_init();
+
+       __init_state = done;
+}
diff --git a/tools/lib/lockdep/rbtree.c b/tools/lib/lockdep/rbtree.c
new file mode 100644 (file)
index 0000000..f7f4303
--- /dev/null
@@ -0,0 +1 @@
+#include "../../../lib/rbtree.c"
diff --git a/tools/lib/lockdep/run_tests.sh b/tools/lib/lockdep/run_tests.sh
new file mode 100644 (file)
index 0000000..5334ad9
--- /dev/null
@@ -0,0 +1,27 @@
+#! /bin/bash
+
+make &> /dev/null
+
+for i in `ls tests/*.c`; do
+       testname=$(basename -s .c "$i")
+       gcc -o tests/$testname -pthread -lpthread $i liblockdep.a -Iinclude -D__USE_LIBLOCKDEP &> /dev/null
+       echo -ne "$testname... "
+       if [ $(timeout 1 ./tests/$testname | wc -l) -gt 0 ]; then
+               echo "PASSED!"
+       else
+               echo "FAILED!"
+       fi
+       rm tests/$testname
+done
+
+for i in `ls tests/*.c`; do
+       testname=$(basename -s .c "$i")
+       gcc -o tests/$testname -pthread -lpthread -Iinclude $i &> /dev/null
+       echo -ne "(PRELOAD) $testname... "
+       if [ $(timeout 1 ./lockdep ./tests/$testname | wc -l) -gt 0 ]; then
+               echo "PASSED!"
+       else
+               echo "FAILED!"
+       fi
+       rm tests/$testname
+done
diff --git a/tools/lib/lockdep/tests/AA.c b/tools/lib/lockdep/tests/AA.c
new file mode 100644 (file)
index 0000000..0f782ff
--- /dev/null
@@ -0,0 +1,13 @@
+#include <liblockdep/mutex.h>
+
+void main(void)
+{
+       pthread_mutex_t a, b;
+
+       pthread_mutex_init(&a, NULL);
+       pthread_mutex_init(&b, NULL);
+
+       pthread_mutex_lock(&a);
+       pthread_mutex_lock(&b);
+       pthread_mutex_lock(&a);
+}
diff --git a/tools/lib/lockdep/tests/ABBA.c b/tools/lib/lockdep/tests/ABBA.c
new file mode 100644 (file)
index 0000000..07f0e29
--- /dev/null
@@ -0,0 +1,13 @@
+#include <liblockdep/mutex.h>
+#include "common.h"
+
+void main(void)
+{
+       pthread_mutex_t a, b;
+
+       pthread_mutex_init(&a, NULL);
+       pthread_mutex_init(&b, NULL);
+
+       LOCK_UNLOCK_2(a, b);
+       LOCK_UNLOCK_2(b, a);
+}
diff --git a/tools/lib/lockdep/tests/ABBCCA.c b/tools/lib/lockdep/tests/ABBCCA.c
new file mode 100644 (file)
index 0000000..843db09
--- /dev/null
@@ -0,0 +1,15 @@
+#include <liblockdep/mutex.h>
+#include "common.h"
+
+void main(void)
+{
+       pthread_mutex_t a, b, c;
+
+       pthread_mutex_init(&a, NULL);
+       pthread_mutex_init(&b, NULL);
+       pthread_mutex_init(&c, NULL);
+
+       LOCK_UNLOCK_2(a, b);
+       LOCK_UNLOCK_2(b, c);
+       LOCK_UNLOCK_2(c, a);
+}
diff --git a/tools/lib/lockdep/tests/ABBCCDDA.c b/tools/lib/lockdep/tests/ABBCCDDA.c
new file mode 100644 (file)
index 0000000..33620e2
--- /dev/null
@@ -0,0 +1,17 @@
+#include <liblockdep/mutex.h>
+#include "common.h"
+
+void main(void)
+{
+       pthread_mutex_t a, b, c, d;
+
+       pthread_mutex_init(&a, NULL);
+       pthread_mutex_init(&b, NULL);
+       pthread_mutex_init(&c, NULL);
+       pthread_mutex_init(&d, NULL);
+
+       LOCK_UNLOCK_2(a, b);
+       LOCK_UNLOCK_2(b, c);
+       LOCK_UNLOCK_2(c, d);
+       LOCK_UNLOCK_2(d, a);
+}
diff --git a/tools/lib/lockdep/tests/ABCABC.c b/tools/lib/lockdep/tests/ABCABC.c
new file mode 100644 (file)
index 0000000..3fee51e
--- /dev/null
@@ -0,0 +1,15 @@
+#include <liblockdep/mutex.h>
+#include "common.h"
+
+void main(void)
+{
+       pthread_mutex_t a, b, c;
+
+       pthread_mutex_init(&a, NULL);
+       pthread_mutex_init(&b, NULL);
+       pthread_mutex_init(&c, NULL);
+
+       LOCK_UNLOCK_2(a, b);
+       LOCK_UNLOCK_2(c, a);
+       LOCK_UNLOCK_2(b, c);
+}
diff --git a/tools/lib/lockdep/tests/ABCDBCDA.c b/tools/lib/lockdep/tests/ABCDBCDA.c
new file mode 100644 (file)
index 0000000..427ba56
--- /dev/null
@@ -0,0 +1,17 @@
+#include <liblockdep/mutex.h>
+#include "common.h"
+
+void main(void)
+{
+       pthread_mutex_t a, b, c, d;
+
+       pthread_mutex_init(&a, NULL);
+       pthread_mutex_init(&b, NULL);
+       pthread_mutex_init(&c, NULL);
+       pthread_mutex_init(&d, NULL);
+
+       LOCK_UNLOCK_2(a, b);
+       LOCK_UNLOCK_2(c, d);
+       LOCK_UNLOCK_2(b, c);
+       LOCK_UNLOCK_2(d, a);
+}
diff --git a/tools/lib/lockdep/tests/ABCDBDDA.c b/tools/lib/lockdep/tests/ABCDBDDA.c
new file mode 100644 (file)
index 0000000..680c6cf
--- /dev/null
@@ -0,0 +1,17 @@
+#include <liblockdep/mutex.h>
+#include "common.h"
+
+void main(void)
+{
+       pthread_mutex_t a, b, c, d;
+
+       pthread_mutex_init(&a, NULL);
+       pthread_mutex_init(&b, NULL);
+       pthread_mutex_init(&c, NULL);
+       pthread_mutex_init(&d, NULL);
+
+       LOCK_UNLOCK_2(a, b);
+       LOCK_UNLOCK_2(c, d);
+       LOCK_UNLOCK_2(b, d);
+       LOCK_UNLOCK_2(d, a);
+}
diff --git a/tools/lib/lockdep/tests/WW.c b/tools/lib/lockdep/tests/WW.c
new file mode 100644 (file)
index 0000000..d44f77d
--- /dev/null
@@ -0,0 +1,13 @@
+#include <liblockdep/rwlock.h>
+
+void main(void)
+{
+       pthread_rwlock_t a, b;
+
+       pthread_rwlock_init(&a, NULL);
+       pthread_rwlock_init(&b, NULL);
+
+       pthread_rwlock_wrlock(&a);
+       pthread_rwlock_rdlock(&b);
+       pthread_rwlock_wrlock(&a);
+}
diff --git a/tools/lib/lockdep/tests/common.h b/tools/lib/lockdep/tests/common.h
new file mode 100644 (file)
index 0000000..d89e94d
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef _LIBLOCKDEP_TEST_COMMON_H
+#define _LIBLOCKDEP_TEST_COMMON_H
+
+#define LOCK_UNLOCK_2(a, b)                    \
+       do {                                    \
+               pthread_mutex_lock(&(a));       \
+               pthread_mutex_lock(&(b));       \
+               pthread_mutex_unlock(&(b));     \
+               pthread_mutex_unlock(&(a));     \
+       } while(0)
+
+#endif
diff --git a/tools/lib/lockdep/tests/unlock_balance.c b/tools/lib/lockdep/tests/unlock_balance.c
new file mode 100644 (file)
index 0000000..0bc62de
--- /dev/null
@@ -0,0 +1,12 @@
+#include <liblockdep/mutex.h>
+
+void main(void)
+{
+       pthread_mutex_t a;
+
+       pthread_mutex_init(&a, NULL);
+
+       pthread_mutex_lock(&a);
+       pthread_mutex_unlock(&a);
+       pthread_mutex_unlock(&a);
+}
diff --git a/tools/lib/lockdep/uinclude/asm/hweight.h b/tools/lib/lockdep/uinclude/asm/hweight.h
new file mode 100644 (file)
index 0000000..fab00ff
--- /dev/null
@@ -0,0 +1,3 @@
+
+/* empty file */
+
diff --git a/tools/lib/lockdep/uinclude/asm/sections.h b/tools/lib/lockdep/uinclude/asm/sections.h
new file mode 100644 (file)
index 0000000..fab00ff
--- /dev/null
@@ -0,0 +1,3 @@
+
+/* empty file */
+
diff --git a/tools/lib/lockdep/uinclude/linux/bitops.h b/tools/lib/lockdep/uinclude/linux/bitops.h
new file mode 100644 (file)
index 0000000..fab00ff
--- /dev/null
@@ -0,0 +1,3 @@
+
+/* empty file */
+
diff --git a/tools/lib/lockdep/uinclude/linux/compiler.h b/tools/lib/lockdep/uinclude/linux/compiler.h
new file mode 100644 (file)
index 0000000..7ac838a
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef _LIBLOCKDEP_LINUX_COMPILER_H_
+#define _LIBLOCKDEP_LINUX_COMPILER_H_
+
+#define __used         __attribute__((__unused__))
+#define unlikely
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/debug_locks.h b/tools/lib/lockdep/uinclude/linux/debug_locks.h
new file mode 100644 (file)
index 0000000..f38eb64
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef _LIBLOCKDEP_DEBUG_LOCKS_H_
+#define _LIBLOCKDEP_DEBUG_LOCKS_H_
+
+#include <stddef.h>
+#include <linux/compiler.h>
+
+#define DEBUG_LOCKS_WARN_ON(x) (x)
+
+extern bool debug_locks;
+extern bool debug_locks_silent;
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/delay.h b/tools/lib/lockdep/uinclude/linux/delay.h
new file mode 100644 (file)
index 0000000..fab00ff
--- /dev/null
@@ -0,0 +1,3 @@
+
+/* empty file */
+
diff --git a/tools/lib/lockdep/uinclude/linux/export.h b/tools/lib/lockdep/uinclude/linux/export.h
new file mode 100644 (file)
index 0000000..6bdf349
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef _LIBLOCKDEP_LINUX_EXPORT_H_
+#define _LIBLOCKDEP_LINUX_EXPORT_H_
+
+#define EXPORT_SYMBOL(sym)
+#define EXPORT_SYMBOL_GPL(sym)
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/ftrace.h b/tools/lib/lockdep/uinclude/linux/ftrace.h
new file mode 100644 (file)
index 0000000..fab00ff
--- /dev/null
@@ -0,0 +1,3 @@
+
+/* empty file */
+
diff --git a/tools/lib/lockdep/uinclude/linux/gfp.h b/tools/lib/lockdep/uinclude/linux/gfp.h
new file mode 100644 (file)
index 0000000..fab00ff
--- /dev/null
@@ -0,0 +1,3 @@
+
+/* empty file */
+
diff --git a/tools/lib/lockdep/uinclude/linux/hardirq.h b/tools/lib/lockdep/uinclude/linux/hardirq.h
new file mode 100644 (file)
index 0000000..c8f3f8f
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef _LIBLOCKDEP_LINUX_HARDIRQ_H_
+#define _LIBLOCKDEP_LINUX_HARDIRQ_H_
+
+#define SOFTIRQ_BITS   0UL
+#define HARDIRQ_BITS   0UL
+#define SOFTIRQ_SHIFT  0UL
+#define HARDIRQ_SHIFT  0UL
+#define hardirq_count()        0UL
+#define softirq_count()        0UL
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/hash.h b/tools/lib/lockdep/uinclude/linux/hash.h
new file mode 100644 (file)
index 0000000..0f84798
--- /dev/null
@@ -0,0 +1 @@
+#include "../../../include/linux/hash.h"
diff --git a/tools/lib/lockdep/uinclude/linux/interrupt.h b/tools/lib/lockdep/uinclude/linux/interrupt.h
new file mode 100644 (file)
index 0000000..fab00ff
--- /dev/null
@@ -0,0 +1,3 @@
+
+/* empty file */
+
diff --git a/tools/lib/lockdep/uinclude/linux/irqflags.h b/tools/lib/lockdep/uinclude/linux/irqflags.h
new file mode 100644 (file)
index 0000000..6cc296f
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef _LIBLOCKDEP_LINUX_TRACE_IRQFLAGS_H_
+#define _LIBLOCKDEP_LINUX_TRACE_IRQFLAGS_H_
+
+# define trace_hardirq_context(p)      0
+# define trace_softirq_context(p)      0
+# define trace_hardirqs_enabled(p)     0
+# define trace_softirqs_enabled(p)     0
+# define trace_hardirq_enter()         do { } while (0)
+# define trace_hardirq_exit()          do { } while (0)
+# define lockdep_softirq_enter()       do { } while (0)
+# define lockdep_softirq_exit()                do { } while (0)
+# define INIT_TRACE_IRQFLAGS
+
+# define stop_critical_timings() do { } while (0)
+# define start_critical_timings() do { } while (0)
+
+#define raw_local_irq_disable() do { } while (0)
+#define raw_local_irq_enable() do { } while (0)
+#define raw_local_irq_save(flags) ((flags) = 0)
+#define raw_local_irq_restore(flags) do { } while (0)
+#define raw_local_save_flags(flags) ((flags) = 0)
+#define raw_irqs_disabled_flags(flags) do { } while (0)
+#define raw_irqs_disabled() 0
+#define raw_safe_halt()
+
+#define local_irq_enable() do { } while (0)
+#define local_irq_disable() do { } while (0)
+#define local_irq_save(flags) ((flags) = 0)
+#define local_irq_restore(flags) do { } while (0)
+#define local_save_flags(flags)        ((flags) = 0)
+#define irqs_disabled() (1)
+#define irqs_disabled_flags(flags) (0)
+#define safe_halt() do { } while (0)
+
+#define trace_lock_release(x, y)
+#define trace_lock_acquire(a, b, c, d, e, f, g)
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/kallsyms.h b/tools/lib/lockdep/uinclude/linux/kallsyms.h
new file mode 100644 (file)
index 0000000..b0f2dbd
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef _LIBLOCKDEP_LINUX_KALLSYMS_H_
+#define _LIBLOCKDEP_LINUX_KALLSYMS_H_
+
+#include <linux/kernel.h>
+#include <stdio.h>
+
+#define KSYM_NAME_LEN 128
+
+struct module;
+
+static inline const char *kallsyms_lookup(unsigned long addr,
+                                         unsigned long *symbolsize,
+                                         unsigned long *offset,
+                                         char **modname, char *namebuf)
+{
+       return NULL;
+}
+
+#include <execinfo.h>
+#include <stdlib.h>
+static inline void print_ip_sym(unsigned long ip)
+{
+       char **name;
+
+       name = backtrace_symbols((void **)&ip, 1);
+
+       printf("%s\n", *name);
+
+       free(name);
+}
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/kern_levels.h b/tools/lib/lockdep/uinclude/linux/kern_levels.h
new file mode 100644 (file)
index 0000000..3b9bade
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef __KERN_LEVELS_H__
+#define __KERN_LEVELS_H__
+
+#define KERN_SOH       ""              /* ASCII Start Of Header */
+#define KERN_SOH_ASCII ''
+
+#define KERN_EMERG     KERN_SOH ""     /* system is unusable */
+#define KERN_ALERT     KERN_SOH ""     /* action must be taken immediately */
+#define KERN_CRIT      KERN_SOH ""     /* critical conditions */
+#define KERN_ERR       KERN_SOH ""     /* error conditions */
+#define KERN_WARNING   KERN_SOH ""     /* warning conditions */
+#define KERN_NOTICE    KERN_SOH ""     /* normal but significant condition */
+#define KERN_INFO      KERN_SOH ""     /* informational */
+#define KERN_DEBUG     KERN_SOH ""     /* debug-level messages */
+
+#define KERN_DEFAULT   KERN_SOH ""     /* the default kernel loglevel */
+
+/*
+ * Annotation for a "continued" line of log printout (only done after a
+ * line that had no enclosing \n). Only to be used by core/arch code
+ * during early bootup (a continued line is not SMP-safe otherwise).
+ */
+#define KERN_CONT      ""
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/kernel.h b/tools/lib/lockdep/uinclude/linux/kernel.h
new file mode 100644 (file)
index 0000000..a11e3c3
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef _LIBLOCKDEP_LINUX_KERNEL_H_
+#define _LIBLOCKDEP_LINUX_KERNEL_H_
+
+#include <linux/export.h>
+#include <linux/types.h>
+#include <linux/rcu.h>
+#include <linux/hardirq.h>
+#include <linux/kern_levels.h>
+
+#ifndef container_of
+#define container_of(ptr, type, member) ({                     \
+       const typeof(((type *)0)->member) * __mptr = (ptr);     \
+       (type *)((char *)__mptr - offsetof(type, member)); })
+#endif
+
+#define max(x, y) ({                           \
+       typeof(x) _max1 = (x);                  \
+       typeof(y) _max2 = (y);                  \
+       (void) (&_max1 == &_max2);              \
+       _max1 > _max2 ? _max1 : _max2; })
+
+#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
+#define WARN_ON(x) (x)
+#define WARN_ON_ONCE(x) (x)
+#define likely(x) (x)
+#define WARN(x, y, z) (x)
+#define uninitialized_var(x) x
+#define __init
+#define noinline
+#define list_add_tail_rcu list_add_tail
+
+#ifndef CALLER_ADDR0
+#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
+#endif
+
+#ifndef _RET_IP_
+#define _RET_IP_ CALLER_ADDR0
+#endif
+
+#ifndef _THIS_IP_
+#define _THIS_IP_ ({ __label__ __here; __here: (unsigned long)&&__here; })
+#endif
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/kmemcheck.h b/tools/lib/lockdep/uinclude/linux/kmemcheck.h
new file mode 100644 (file)
index 0000000..94d598b
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _LIBLOCKDEP_LINUX_KMEMCHECK_H_
+#define _LIBLOCKDEP_LINUX_KMEMCHECK_H_
+
+static inline void kmemcheck_mark_initialized(void *address, unsigned int n)
+{
+}
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/linkage.h b/tools/lib/lockdep/uinclude/linux/linkage.h
new file mode 100644 (file)
index 0000000..fab00ff
--- /dev/null
@@ -0,0 +1,3 @@
+
+/* empty file */
+
diff --git a/tools/lib/lockdep/uinclude/linux/list.h b/tools/lib/lockdep/uinclude/linux/list.h
new file mode 100644 (file)
index 0000000..6e9ef31
--- /dev/null
@@ -0,0 +1 @@
+#include "../../../include/linux/list.h"
diff --git a/tools/lib/lockdep/uinclude/linux/lockdep.h b/tools/lib/lockdep/uinclude/linux/lockdep.h
new file mode 100644 (file)
index 0000000..d0f5d6e
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef _LIBLOCKDEP_LOCKDEP_H_
+#define _LIBLOCKDEP_LOCKDEP_H_
+
+#include <sys/prctl.h>
+#include <sys/syscall.h>
+#include <string.h>
+#include <limits.h>
+#include <linux/utsname.h>
+
+
+#define MAX_LOCK_DEPTH 2000UL
+
+#include "../../../include/linux/lockdep.h"
+
+struct task_struct {
+       u64 curr_chain_key;
+       int lockdep_depth;
+       unsigned int lockdep_recursion;
+       struct held_lock held_locks[MAX_LOCK_DEPTH];
+       gfp_t lockdep_reclaim_gfp;
+       int pid;
+       char comm[17];
+};
+
+extern struct task_struct *__curr(void);
+
+#define current (__curr())
+
+#define debug_locks_off() 1
+#define task_pid_nr(tsk) ((tsk)->pid)
+
+#define KSYM_NAME_LEN 128
+#define printk printf
+
+#define list_del_rcu list_del
+
+#define atomic_t unsigned long
+#define atomic_inc(x) ((*(x))++)
+
+static struct new_utsname *init_utsname(void)
+{
+       static struct new_utsname n = (struct new_utsname) {
+               .release = "liblockdep",
+               .version = LIBLOCKDEP_VERSION,
+       };
+
+       return &n;
+}
+
+#define print_tainted() ""
+#define static_obj(x) 1
+
+#define debug_show_all_locks()
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/module.h b/tools/lib/lockdep/uinclude/linux/module.h
new file mode 100644 (file)
index 0000000..09c7a7b
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _LIBLOCKDEP_LINUX_MODULE_H_
+#define _LIBLOCKDEP_LINUX_MODULE_H_
+
+#define module_param(name, type, perm)
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/mutex.h b/tools/lib/lockdep/uinclude/linux/mutex.h
new file mode 100644 (file)
index 0000000..fab00ff
--- /dev/null
@@ -0,0 +1,3 @@
+
+/* empty file */
+
diff --git a/tools/lib/lockdep/uinclude/linux/poison.h b/tools/lib/lockdep/uinclude/linux/poison.h
new file mode 100644 (file)
index 0000000..0c27bdf
--- /dev/null
@@ -0,0 +1 @@
+#include "../../../include/linux/poison.h"
diff --git a/tools/lib/lockdep/uinclude/linux/prefetch.h b/tools/lib/lockdep/uinclude/linux/prefetch.h
new file mode 100644 (file)
index 0000000..d73fe6f
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _LIBLOCKDEP_LINUX_PREFETCH_H_
+#define _LIBLOCKDEP_LINUX_PREFETCH_H
+
+static inline void prefetch(void *a __attribute__((unused))) { }
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/proc_fs.h b/tools/lib/lockdep/uinclude/linux/proc_fs.h
new file mode 100644 (file)
index 0000000..fab00ff
--- /dev/null
@@ -0,0 +1,3 @@
+
+/* empty file */
+
diff --git a/tools/lib/lockdep/uinclude/linux/rbtree.h b/tools/lib/lockdep/uinclude/linux/rbtree.h
new file mode 100644 (file)
index 0000000..965901d
--- /dev/null
@@ -0,0 +1 @@
+#include "../../../include/linux/rbtree.h"
diff --git a/tools/lib/lockdep/uinclude/linux/rbtree_augmented.h b/tools/lib/lockdep/uinclude/linux/rbtree_augmented.h
new file mode 100644 (file)
index 0000000..c375947
--- /dev/null
@@ -0,0 +1,2 @@
+#define __always_inline
+#include "../../../include/linux/rbtree_augmented.h"
diff --git a/tools/lib/lockdep/uinclude/linux/rcu.h b/tools/lib/lockdep/uinclude/linux/rcu.h
new file mode 100644 (file)
index 0000000..4c99fcb
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef _LIBLOCKDEP_RCU_H_
+#define _LIBLOCKDEP_RCU_H_
+
+int rcu_scheduler_active;
+
+static inline int rcu_lockdep_current_cpu_online(void)
+{
+       return 1;
+}
+
+static inline int rcu_is_cpu_idle(void)
+{
+       return 1;
+}
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/seq_file.h b/tools/lib/lockdep/uinclude/linux/seq_file.h
new file mode 100644 (file)
index 0000000..fab00ff
--- /dev/null
@@ -0,0 +1,3 @@
+
+/* empty file */
+
diff --git a/tools/lib/lockdep/uinclude/linux/spinlock.h b/tools/lib/lockdep/uinclude/linux/spinlock.h
new file mode 100644 (file)
index 0000000..68c1aa2
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef _LIBLOCKDEP_SPINLOCK_H_
+#define _LIBLOCKDEP_SPINLOCK_H_
+
+#include <pthread.h>
+#include <stdbool.h>
+
+#define arch_spinlock_t pthread_mutex_t
+#define __ARCH_SPIN_LOCK_UNLOCKED PTHREAD_MUTEX_INITIALIZER
+
+static inline void arch_spin_lock(arch_spinlock_t *mutex)
+{
+       pthread_mutex_lock(mutex);
+}
+
+static inline void arch_spin_unlock(arch_spinlock_t *mutex)
+{
+       pthread_mutex_unlock(mutex);
+}
+
+static inline bool arch_spin_is_locked(arch_spinlock_t *mutex)
+{
+       return true;
+}
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/stacktrace.h b/tools/lib/lockdep/uinclude/linux/stacktrace.h
new file mode 100644 (file)
index 0000000..39aecc6
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef _LIBLOCKDEP_LINUX_STACKTRACE_H_
+#define _LIBLOCKDEP_LINUX_STACKTRACE_H_
+
+#include <execinfo.h>
+
+struct stack_trace {
+       unsigned int nr_entries, max_entries;
+       unsigned long *entries;
+       int skip;
+};
+
+static inline void print_stack_trace(struct stack_trace *trace, int spaces)
+{
+       backtrace_symbols_fd((void **)trace->entries, trace->nr_entries, 1);
+}
+
+#define save_stack_trace(trace)        \
+       ((trace)->nr_entries =  \
+               backtrace((void **)(trace)->entries, (trace)->max_entries))
+
+static inline int dump_stack(void)
+{
+       void *array[64];
+       size_t size;
+
+       size = backtrace(array, 64);
+       backtrace_symbols_fd(array, size, 1);
+
+       return 0;
+}
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/stringify.h b/tools/lib/lockdep/uinclude/linux/stringify.h
new file mode 100644 (file)
index 0000000..05dfcd1
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef _LIBLOCKDEP_LINUX_STRINGIFY_H_
+#define _LIBLOCKDEP_LINUX_STRINGIFY_H_
+
+#define __stringify_1(x...)    #x
+#define __stringify(x...)      __stringify_1(x)
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/linux/types.h b/tools/lib/lockdep/uinclude/linux/types.h
new file mode 100644 (file)
index 0000000..929938f
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef _LIBLOCKDEP_LINUX_TYPES_H_
+#define _LIBLOCKDEP_LINUX_TYPES_H_
+
+#include <stdbool.h>
+#include <stddef.h>
+
+#define __SANE_USERSPACE_TYPES__       /* For PPC64, to get LL64 types */
+#include <asm/types.h>
+
+struct page;
+struct kmem_cache;
+
+typedef unsigned gfp_t;
+
+typedef __u64 u64;
+typedef __s64 s64;
+
+typedef __u32 u32;
+typedef __s32 s32;
+
+typedef __u16 u16;
+typedef __s16 s16;
+
+typedef __u8  u8;
+typedef __s8  s8;
+
+#ifdef __CHECKER__
+#define __bitwise__ __attribute__((bitwise))
+#else
+#define __bitwise__
+#endif
+#ifdef __CHECK_ENDIAN__
+#define __bitwise __bitwise__
+#else
+#define __bitwise
+#endif
+
+
+typedef __u16 __bitwise __le16;
+typedef __u16 __bitwise __be16;
+typedef __u32 __bitwise __le32;
+typedef __u32 __bitwise __be32;
+typedef __u64 __bitwise __le64;
+typedef __u64 __bitwise __be64;
+
+struct list_head {
+       struct list_head *next, *prev;
+};
+
+struct hlist_head {
+       struct hlist_node *first;
+};
+
+struct hlist_node {
+       struct hlist_node *next, **pprev;
+};
+
+#endif
diff --git a/tools/lib/lockdep/uinclude/trace/events/lock.h b/tools/lib/lockdep/uinclude/trace/events/lock.h
new file mode 100644 (file)
index 0000000..fab00ff
--- /dev/null
@@ -0,0 +1,3 @@
+
+/* empty file */
+
index 0362d575de7d185752b2a23a53845236c71510f6..900fca01bdd3fcbc8617929a822ba5d90ba47ae0 100644 (file)
@@ -1606,6 +1606,24 @@ process_arg(struct event_format *event, struct print_arg *arg, char **tok)
 static enum event_type
 process_op(struct event_format *event, struct print_arg *arg, char **tok);
 
+/*
+ * For __print_symbolic() and __print_flags, we need to completely
+ * evaluate the first argument, which defines what to print next.
+ */
+static enum event_type
+process_field_arg(struct event_format *event, struct print_arg *arg, char **tok)
+{
+       enum event_type type;
+
+       type = process_arg(event, arg, tok);
+
+       while (type == EVENT_OP) {
+               type = process_op(event, arg, tok);
+       }
+
+       return type;
+}
+
 static enum event_type
 process_cond(struct event_format *event, struct print_arg *top, char **tok)
 {
@@ -2371,7 +2389,7 @@ process_flags(struct event_format *event, struct print_arg *arg, char **tok)
                goto out_free;
        }
 
-       type = process_arg(event, field, &token);
+       type = process_field_arg(event, field, &token);
 
        /* Handle operations in the first argument */
        while (type == EVENT_OP)
@@ -2424,7 +2442,8 @@ process_symbols(struct event_format *event, struct print_arg *arg, char **tok)
                goto out_free;
        }
 
-       type = process_arg(event, field, &token);
+       type = process_field_arg(event, field, &token);
+
        if (test_type_token(type, token, EVENT_DELIM, ","))
                goto out_free_field;
 
@@ -3446,7 +3465,7 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg
                 * is in the bottom half of the 32 bit field.
                 */
                offset &= 0xffff;
-               val = (unsigned long long)(data + offset);
+               val = (unsigned long long)((unsigned long)data + offset);
                break;
        default: /* not sure what to do there */
                return 0;
@@ -4080,6 +4099,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
        unsigned long long val;
        struct func_map *func;
        const char *saveptr;
+       struct trace_seq p;
        char *bprint_fmt = NULL;
        char format[32];
        int show_func;
@@ -4287,8 +4307,12 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
                                format[len] = 0;
                                if (!len_as_arg)
                                        len_arg = -1;
-                               print_str_arg(s, data, size, event,
+                               /* Use helper trace_seq */
+                               trace_seq_init(&p);
+                               print_str_arg(&p, data, size, event,
                                              format, len_arg, arg);
+                               trace_seq_terminate(&p);
+                               trace_seq_puts(s, p.buffer);
                                arg = arg->next;
                                break;
                        default:
index 43b42c4f4a915ad96be76c737b63feee12925de2..c407897f04359c9e253fbcb27368926419aced51 100644 (file)
@@ -57,6 +57,8 @@ OPTIONS
 -t::
 --tid=::
         Record events on existing thread ID (comma separated list).
+        This option also disables inheritance by default.  Enable it by adding
+        --inherit.
 
 -u::
 --uid=::
@@ -201,11 +203,11 @@ abort events and some memory events in precise mode on modern Intel CPUs.
 --transaction::
 Record transaction flags for transaction related events.
 
---force-per-cpu::
-Force the use of per-cpu mmaps.  By default, when tasks are specified (i.e. -p,
--t or -u options) per-thread mmaps are created.  This option overrides that and
-forces per-cpu mmaps.  A side-effect of that is that inheritance is
-automatically enabled.  Add the -i option also to disable inheritance.
+--per-thread::
+Use per-thread mmaps.  By default per-cpu mmaps are created.  This option
+overrides that and uses per-thread mmaps.  A side-effect of that is that
+inheritance is automatically disabled.  --per-thread is ignored with a warning
+if combined with -a or -C options.
 
 SEE ALSO
 --------
index e9cbfcddfa3f608ee19b2366802f7f405f78f535..cfdbb1e045b53514f919e6c96acb48d0b6df4be3 100644 (file)
@@ -203,6 +203,12 @@ OPTIONS
 --show-kernel-path::
        Try to resolve the path of [kernel.kallsyms]
 
+--show-task-events
+       Display task related events (e.g. FORK, COMM, EXIT).
+
+--show-mmap-events
+       Display mmap related events (e.g. MMAP, MMAP2).
+
 SEE ALSO
 --------
 linkperf:perf-record[1], linkperf:perf-script-perl[1],
index 3ff8bd4f0b4d94163d77231881b462e50bbd4e17..271dd4ed5b05bc8abf19699f1eef64f26b4f7d3b 100644 (file)
@@ -8,8 +8,7 @@ perf-timechart - Tool to visualize total system behavior during a workload
 SYNOPSIS
 --------
 [verse]
-'perf timechart' record <command>
-'perf timechart' [<options>]
+'perf timechart' [<timechart options>] {record} [<record options>]
 
 DESCRIPTION
 -----------
@@ -21,8 +20,8 @@ There are two variants of perf timechart:
   'perf timechart' to turn a trace into a Scalable Vector Graphics file,
   that can be viewed with popular SVG viewers such as 'Inkscape'.
 
-OPTIONS
--------
+TIMECHART OPTIONS
+-----------------
 -o::
 --output=::
         Select the output file (default: output.svg)
@@ -35,6 +34,9 @@ OPTIONS
 -P::
 --power-only::
         Only output the CPU power section of the diagram
+-T::
+--tasks-only::
+        Don't output processor state transitions
 -p::
 --process::
         Select the processes to display, by name or PID
@@ -54,6 +56,22 @@ $ perf timechart
 
   Written 10.2 seconds of trace to output.svg.
 
+-n::
+--proc-num::
+        Print task info for at least given number of tasks.
+
+RECORD OPTIONS
+--------------
+-P::
+--power-only::
+        Record only power-related events
+-T::
+--tasks-only::
+        Record only tasks-related events
+-g::
+--callchain::
+        Do call-graph (stack chain/backtrace) recording
+
 SEE ALSO
 --------
 linkperf:perf-record[1]
index 7de01dd7968898c18e34f40914017ae549a3f618..cdd8d4946dba8f85b6ef6f56062067dd1b2dd622 100644 (file)
@@ -50,7 +50,6 @@ Default is to monitor all CPUS.
 --count-filter=<count>::
        Only display functions with more events than this.
 
--g::
 --group::
         Put the counters into a counter group.
 
@@ -143,12 +142,12 @@ Default is to monitor all CPUS.
 --asm-raw::
        Show raw instruction encoding of assembly instructions.
 
--G::
+-g::
        Enables call-graph (stack chain/backtrace) recording.
 
 --call-graph::
        Setup and enable call-graph (stack chain/backtrace) recording,
-       implies -G.
+       implies -g.
 
 --max-stack::
        Set the stack depth limit when parsing the callchain, anything
index 4835618a5608892054de87d497e45e644fdeb0da..eefb9fb0c02f991ba00007b8885685ff248a85dc 100644 (file)
@@ -60,8 +60,11 @@ endef
 
 #
 # Needed if no target specified:
+# (Except for tags and TAGS targets. The reason is that the
+# Makefile does not treat tags/TAGS as targets but as files
+# and thus won't rebuilt them once they are in place.)
 #
-all:
+all tags TAGS:
        $(print_msg)
        $(make)
 
@@ -77,3 +80,5 @@ clean:
 %:
        $(print_msg)
        $(make)
+
+.PHONY: tags TAGS
index 7fc8f179cae74d08e2cc507031c773009723bb00..e416ccc7d83180d203e7dd0cea0f64cc49819fec 100644 (file)
@@ -840,9 +840,9 @@ ifndef NO_LIBPYTHON
                $(INSTALL) scripts/python/*.py -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python'; \
                $(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin'
 endif
-       $(call QUIET_INSTALL, bash_completion-script) \
+       $(call QUIET_INSTALL, perf_completion-script) \
                $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d'; \
-               $(INSTALL) bash_completion '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d/perf'
+               $(INSTALL) perf-completion.sh '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d/perf'
        $(call QUIET_INSTALL, tests) \
                $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \
                $(INSTALL) tests/attr.py '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \
index 7c8020a32784abcd6d44223dc3a5586f7ba7f3f0..65615a8bc25e7ff02a1a96f78114decd54df6212 100644 (file)
@@ -800,6 +800,7 @@ static struct perf_record record = {
                .freq                = 4000,
                .target              = {
                        .uses_mmap   = true,
+                       .default_per_cpu = true,
                },
        },
 };
@@ -842,8 +843,9 @@ const struct option record_options[] = {
        OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
        OPT_STRING('o', "output", &record.file.path, "file",
                    "output file name"),
-       OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit,
-                   "child tasks do not inherit counters"),
+       OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit,
+                       &record.opts.no_inherit_set,
+                       "child tasks do not inherit counters"),
        OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
        OPT_CALLBACK('m', "mmap-pages", &record.opts.mmap_pages, "pages",
                     "number of mmap data pages",
@@ -888,8 +890,8 @@ const struct option record_options[] = {
                    "sample by weight (on special events only)"),
        OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction,
                    "sample transaction flags (special events only)"),
-       OPT_BOOLEAN(0, "force-per-cpu", &record.opts.target.force_per_cpu,
-                   "force the use of per-cpu mmaps"),
+       OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread,
+                   "use per-thread mmaps"),
        OPT_END()
 };
 
@@ -938,6 +940,9 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
                goto out_symbol_exit;
        }
 
+       if (rec->opts.target.tid && !rec->opts.no_inherit_set)
+               rec->opts.no_inherit = true;
+
        err = target__validate(&rec->opts.target);
        if (err) {
                target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
index baf17989a216137064e089d4e2f65fef07a4357f..952dce979252f5e9d71f8093d0b71f4367c0a1f5 100644 (file)
@@ -280,6 +280,30 @@ static int perf_session__check_output_opt(struct perf_session *session)
                set_print_ip_opts(&evsel->attr);
        }
 
+       /*
+        * set default for tracepoints to print symbols only
+        * if callchains are present
+        */
+       if (symbol_conf.use_callchain &&
+           !output[PERF_TYPE_TRACEPOINT].user_set) {
+               struct perf_event_attr *attr;
+
+               j = PERF_TYPE_TRACEPOINT;
+               evsel = perf_session__find_first_evtype(session, j);
+               if (evsel == NULL)
+                       goto out;
+
+               attr = &evsel->attr;
+
+               if (attr->sample_type & PERF_SAMPLE_CALLCHAIN) {
+                       output[j].fields |= PERF_OUTPUT_IP;
+                       output[j].fields |= PERF_OUTPUT_SYM;
+                       output[j].fields |= PERF_OUTPUT_DSO;
+                       set_print_ip_opts(attr);
+               }
+       }
+
+out:
        return 0;
 }
 
@@ -288,7 +312,6 @@ static void print_sample_start(struct perf_sample *sample,
                               struct perf_evsel *evsel)
 {
        struct perf_event_attr *attr = &evsel->attr;
-       const char *evname = NULL;
        unsigned long secs;
        unsigned long usecs;
        unsigned long long nsecs;
@@ -323,11 +346,6 @@ static void print_sample_start(struct perf_sample *sample,
                usecs = nsecs / NSECS_PER_USEC;
                printf("%5lu.%06lu: ", secs, usecs);
        }
-
-       if (PRINT_FIELD(EVNAME)) {
-               evname = perf_evsel__name(evsel);
-               printf("%s: ", evname ? evname : "[unknown]");
-       }
 }
 
 static bool is_bts_event(struct perf_event_attr *attr)
@@ -434,6 +452,11 @@ static void process_event(union perf_event *event, struct perf_sample *sample,
 
        print_sample_start(sample, thread, evsel);
 
+       if (PRINT_FIELD(EVNAME)) {
+               const char *evname = perf_evsel__name(evsel);
+               printf("%s: ", evname ? evname : "[unknown]");
+       }
+
        if (is_bts_event(attr)) {
                print_sample_bts(event, sample, evsel, machine, thread);
                return;
@@ -549,6 +572,8 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
 struct perf_script {
        struct perf_tool        tool;
        struct perf_session     *session;
+       bool                    show_task_events;
+       bool                    show_mmap_events;
 };
 
 static int process_attr(struct perf_tool *tool, union perf_event *event,
@@ -579,6 +604,163 @@ static int process_attr(struct perf_tool *tool, union perf_event *event,
        return perf_evsel__check_attr(evsel, scr->session);
 }
 
+static int process_comm_event(struct perf_tool *tool,
+                             union perf_event *event,
+                             struct perf_sample *sample,
+                             struct machine *machine)
+{
+       struct thread *thread;
+       struct perf_script *script = container_of(tool, struct perf_script, tool);
+       struct perf_session *session = script->session;
+       struct perf_evsel *evsel = perf_evlist__first(session->evlist);
+       int ret = -1;
+
+       thread = machine__findnew_thread(machine, event->comm.pid, event->comm.tid);
+       if (thread == NULL) {
+               pr_debug("problem processing COMM event, skipping it.\n");
+               return -1;
+       }
+
+       if (perf_event__process_comm(tool, event, sample, machine) < 0)
+               goto out;
+
+       if (!evsel->attr.sample_id_all) {
+               sample->cpu = 0;
+               sample->time = 0;
+               sample->tid = event->comm.tid;
+               sample->pid = event->comm.pid;
+       }
+       print_sample_start(sample, thread, evsel);
+       perf_event__fprintf(event, stdout);
+       ret = 0;
+
+out:
+       return ret;
+}
+
+static int process_fork_event(struct perf_tool *tool,
+                             union perf_event *event,
+                             struct perf_sample *sample,
+                             struct machine *machine)
+{
+       struct thread *thread;
+       struct perf_script *script = container_of(tool, struct perf_script, tool);
+       struct perf_session *session = script->session;
+       struct perf_evsel *evsel = perf_evlist__first(session->evlist);
+
+       if (perf_event__process_fork(tool, event, sample, machine) < 0)
+               return -1;
+
+       thread = machine__findnew_thread(machine, event->fork.pid, event->fork.tid);
+       if (thread == NULL) {
+               pr_debug("problem processing FORK event, skipping it.\n");
+               return -1;
+       }
+
+       if (!evsel->attr.sample_id_all) {
+               sample->cpu = 0;
+               sample->time = event->fork.time;
+               sample->tid = event->fork.tid;
+               sample->pid = event->fork.pid;
+       }
+       print_sample_start(sample, thread, evsel);
+       perf_event__fprintf(event, stdout);
+
+       return 0;
+}
+static int process_exit_event(struct perf_tool *tool,
+                             union perf_event *event,
+                             struct perf_sample *sample,
+                             struct machine *machine)
+{
+       struct thread *thread;
+       struct perf_script *script = container_of(tool, struct perf_script, tool);
+       struct perf_session *session = script->session;
+       struct perf_evsel *evsel = perf_evlist__first(session->evlist);
+
+       thread = machine__findnew_thread(machine, event->fork.pid, event->fork.tid);
+       if (thread == NULL) {
+               pr_debug("problem processing EXIT event, skipping it.\n");
+               return -1;
+       }
+
+       if (!evsel->attr.sample_id_all) {
+               sample->cpu = 0;
+               sample->time = 0;
+               sample->tid = event->comm.tid;
+               sample->pid = event->comm.pid;
+       }
+       print_sample_start(sample, thread, evsel);
+       perf_event__fprintf(event, stdout);
+
+       if (perf_event__process_exit(tool, event, sample, machine) < 0)
+               return -1;
+
+       return 0;
+}
+
+static int process_mmap_event(struct perf_tool *tool,
+                             union perf_event *event,
+                             struct perf_sample *sample,
+                             struct machine *machine)
+{
+       struct thread *thread;
+       struct perf_script *script = container_of(tool, struct perf_script, tool);
+       struct perf_session *session = script->session;
+       struct perf_evsel *evsel = perf_evlist__first(session->evlist);
+
+       if (perf_event__process_mmap(tool, event, sample, machine) < 0)
+               return -1;
+
+       thread = machine__findnew_thread(machine, event->mmap.pid, event->mmap.tid);
+       if (thread == NULL) {
+               pr_debug("problem processing MMAP event, skipping it.\n");
+               return -1;
+       }
+
+       if (!evsel->attr.sample_id_all) {
+               sample->cpu = 0;
+               sample->time = 0;
+               sample->tid = event->mmap.tid;
+               sample->pid = event->mmap.pid;
+       }
+       print_sample_start(sample, thread, evsel);
+       perf_event__fprintf(event, stdout);
+
+       return 0;
+}
+
+static int process_mmap2_event(struct perf_tool *tool,
+                             union perf_event *event,
+                             struct perf_sample *sample,
+                             struct machine *machine)
+{
+       struct thread *thread;
+       struct perf_script *script = container_of(tool, struct perf_script, tool);
+       struct perf_session *session = script->session;
+       struct perf_evsel *evsel = perf_evlist__first(session->evlist);
+
+       if (perf_event__process_mmap2(tool, event, sample, machine) < 0)
+               return -1;
+
+       thread = machine__findnew_thread(machine, event->mmap2.pid, event->mmap2.tid);
+       if (thread == NULL) {
+               pr_debug("problem processing MMAP2 event, skipping it.\n");
+               return -1;
+       }
+
+       if (!evsel->attr.sample_id_all) {
+               sample->cpu = 0;
+               sample->time = 0;
+               sample->tid = event->mmap2.tid;
+               sample->pid = event->mmap2.pid;
+       }
+       print_sample_start(sample, thread, evsel);
+       perf_event__fprintf(event, stdout);
+
+       return 0;
+}
+
 static void sig_handler(int sig __maybe_unused)
 {
        session_done = 1;
@@ -590,6 +772,17 @@ static int __cmd_script(struct perf_script *script)
 
        signal(SIGINT, sig_handler);
 
+       /* override event processing functions */
+       if (script->show_task_events) {
+               script->tool.comm = process_comm_event;
+               script->tool.fork = process_fork_event;
+               script->tool.exit = process_exit_event;
+       }
+       if (script->show_mmap_events) {
+               script->tool.mmap = process_mmap_event;
+               script->tool.mmap2 = process_mmap2_event;
+       }
+
        ret = perf_session__process_events(script->session, &script->tool);
 
        if (debug_mode)
@@ -1352,6 +1545,10 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
                    "display extended information from perf.data file"),
        OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path,
                    "Show the path of [kernel.kallsyms]"),
+       OPT_BOOLEAN('\0', "show-task-events", &script.show_task_events,
+                   "Show the fork/comm/exit events"),
+       OPT_BOOLEAN('\0', "show-mmap-events", &script.show_mmap_events,
+                   "Show the mmap events"),
        OPT_END()
        };
        const char * const script_usage[] = {
index ee0d565f83e300f57d21d465a9f65180f5a74618..dab98b50c9feb800eac1652d4c66d2cf4c691c97 100644 (file)
@@ -138,6 +138,7 @@ static const char           *post_cmd                       = NULL;
 static bool                    sync_run                        = false;
 static unsigned int            interval                        = 0;
 static unsigned int            initial_delay                   = 0;
+static unsigned int            unit_width                      = 4; /* strlen("unit") */
 static bool                    forever                         = false;
 static struct timespec         ref_time;
 static struct cpu_map          *aggr_map;
@@ -461,17 +462,17 @@ static void print_interval(void)
        if (num_print_interval == 0 && !csv_output) {
                switch (aggr_mode) {
                case AGGR_SOCKET:
-                       fprintf(output, "#           time socket cpus             counts events\n");
+                       fprintf(output, "#           time socket cpus             counts %*s events\n", unit_width, "unit");
                        break;
                case AGGR_CORE:
-                       fprintf(output, "#           time core         cpus             counts events\n");
+                       fprintf(output, "#           time core         cpus             counts %*s events\n", unit_width, "unit");
                        break;
                case AGGR_NONE:
-                       fprintf(output, "#           time CPU                 counts events\n");
+                       fprintf(output, "#           time CPU                counts %*s events\n", unit_width, "unit");
                        break;
                case AGGR_GLOBAL:
                default:
-                       fprintf(output, "#           time             counts events\n");
+                       fprintf(output, "#           time             counts %*s events\n", unit_width, "unit");
                }
        }
 
@@ -516,6 +517,7 @@ static int __run_perf_stat(int argc, const char **argv)
        unsigned long long t0, t1;
        struct perf_evsel *counter;
        struct timespec ts;
+       size_t l;
        int status = 0;
        const bool forks = (argc > 0);
 
@@ -565,6 +567,10 @@ static int __run_perf_stat(int argc, const char **argv)
                        return -1;
                }
                counter->supported = true;
+
+               l = strlen(counter->unit);
+               if (l > unit_width)
+                       unit_width = l;
        }
 
        if (perf_evlist__apply_filters(evsel_list)) {
@@ -704,14 +710,25 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr)
 static void nsec_printout(int cpu, int nr, struct perf_evsel *evsel, double avg)
 {
        double msecs = avg / 1e6;
-       const char *fmt = csv_output ? "%.6f%s%s" : "%18.6f%s%-25s";
+       const char *fmt_v, *fmt_n;
        char name[25];
 
+       fmt_v = csv_output ? "%.6f%s" : "%18.6f%s";
+       fmt_n = csv_output ? "%s" : "%-25s";
+
        aggr_printout(evsel, cpu, nr);
 
        scnprintf(name, sizeof(name), "%s%s",
                  perf_evsel__name(evsel), csv_output ? "" : " (msec)");
-       fprintf(output, fmt, msecs, csv_sep, name);
+
+       fprintf(output, fmt_v, msecs, csv_sep);
+
+       if (csv_output)
+               fprintf(output, "%s%s", evsel->unit, csv_sep);
+       else
+               fprintf(output, "%-*s%s", unit_width, evsel->unit, csv_sep);
+
+       fprintf(output, fmt_n, name);
 
        if (evsel->cgrp)
                fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
@@ -908,21 +925,31 @@ static void print_ll_cache_misses(int cpu,
 static void abs_printout(int cpu, int nr, struct perf_evsel *evsel, double avg)
 {
        double total, ratio = 0.0, total2;
+       double sc =  evsel->scale;
        const char *fmt;
 
-       if (csv_output)
-               fmt = "%.0f%s%s";
-       else if (big_num)
-               fmt = "%'18.0f%s%-25s";
-       else
-               fmt = "%18.0f%s%-25s";
+       if (csv_output) {
+               fmt = sc != 1.0 ?  "%.2f%s" : "%.0f%s";
+       } else {
+               if (big_num)
+                       fmt = sc != 1.0 ? "%'18.2f%s" : "%'18.0f%s";
+               else
+                       fmt = sc != 1.0 ? "%18.2f%s" : "%18.0f%s";
+       }
 
        aggr_printout(evsel, cpu, nr);
 
        if (aggr_mode == AGGR_GLOBAL)
                cpu = 0;
 
-       fprintf(output, fmt, avg, csv_sep, perf_evsel__name(evsel));
+       fprintf(output, fmt, avg, csv_sep);
+
+       if (evsel->unit)
+               fprintf(output, "%-*s%s",
+                       csv_output ? 0 : unit_width,
+                       evsel->unit, csv_sep);
+
+       fprintf(output, "%-*s", csv_output ? 0 : 25, perf_evsel__name(evsel));
 
        if (evsel->cgrp)
                fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
@@ -941,7 +968,10 @@ static void abs_printout(int cpu, int nr, struct perf_evsel *evsel, double avg)
 
                if (total && avg) {
                        ratio = total / avg;
-                       fprintf(output, "\n                                             #   %5.2f  stalled cycles per insn", ratio);
+                       fprintf(output, "\n");
+                       if (aggr_mode == AGGR_NONE)
+                               fprintf(output, "        ");
+                       fprintf(output, "                                                  #   %5.2f  stalled cycles per insn", ratio);
                }
 
        } else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES) &&
@@ -1061,6 +1091,7 @@ static void print_aggr(char *prefix)
 {
        struct perf_evsel *counter;
        int cpu, cpu2, s, s2, id, nr;
+       double uval;
        u64 ena, run, val;
 
        if (!(aggr_map || aggr_get_id))
@@ -1087,11 +1118,17 @@ static void print_aggr(char *prefix)
                        if (run == 0 || ena == 0) {
                                aggr_printout(counter, id, nr);
 
-                               fprintf(output, "%*s%s%*s",
+                               fprintf(output, "%*s%s",
                                        csv_output ? 0 : 18,
                                        counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
-                                       csv_sep,
-                                       csv_output ? 0 : -24,
+                                       csv_sep);
+
+                               fprintf(output, "%-*s%s",
+                                       csv_output ? 0 : unit_width,
+                                       counter->unit, csv_sep);
+
+                               fprintf(output, "%*s",
+                                       csv_output ? 0 : -25,
                                        perf_evsel__name(counter));
 
                                if (counter->cgrp)
@@ -1101,11 +1138,12 @@ static void print_aggr(char *prefix)
                                fputc('\n', output);
                                continue;
                        }
+                       uval = val * counter->scale;
 
                        if (nsec_counter(counter))
-                               nsec_printout(id, nr, counter, val);
+                               nsec_printout(id, nr, counter, uval);
                        else
-                               abs_printout(id, nr, counter, val);
+                               abs_printout(id, nr, counter, uval);
 
                        if (!csv_output) {
                                print_noise(counter, 1.0);
@@ -1128,16 +1166,21 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
        struct perf_stat *ps = counter->priv;
        double avg = avg_stats(&ps->res_stats[0]);
        int scaled = counter->counts->scaled;
+       double uval;
 
        if (prefix)
                fprintf(output, "%s", prefix);
 
        if (scaled == -1) {
-               fprintf(output, "%*s%s%*s",
+               fprintf(output, "%*s%s",
                        csv_output ? 0 : 18,
                        counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
-                       csv_sep,
-                       csv_output ? 0 : -24,
+                       csv_sep);
+               fprintf(output, "%-*s%s",
+                       csv_output ? 0 : unit_width,
+                       counter->unit, csv_sep);
+               fprintf(output, "%*s",
+                       csv_output ? 0 : -25,
                        perf_evsel__name(counter));
 
                if (counter->cgrp)
@@ -1147,10 +1190,12 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
                return;
        }
 
+       uval = avg * counter->scale;
+
        if (nsec_counter(counter))
-               nsec_printout(-1, 0, counter, avg);
+               nsec_printout(-1, 0, counter, uval);
        else
-               abs_printout(-1, 0, counter, avg);
+               abs_printout(-1, 0, counter, uval);
 
        print_noise(counter, avg);
 
@@ -1177,6 +1222,7 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
 static void print_counter(struct perf_evsel *counter, char *prefix)
 {
        u64 ena, run, val;
+       double uval;
        int cpu;
 
        for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
@@ -1188,14 +1234,20 @@ static void print_counter(struct perf_evsel *counter, char *prefix)
                        fprintf(output, "%s", prefix);
 
                if (run == 0 || ena == 0) {
-                       fprintf(output, "CPU%*d%s%*s%s%*s",
+                       fprintf(output, "CPU%*d%s%*s%s",
                                csv_output ? 0 : -4,
                                perf_evsel__cpus(counter)->map[cpu], csv_sep,
                                csv_output ? 0 : 18,
                                counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
-                               csv_sep,
-                               csv_output ? 0 : -24,
-                               perf_evsel__name(counter));
+                               csv_sep);
+
+                               fprintf(output, "%-*s%s",
+                                       csv_output ? 0 : unit_width,
+                                       counter->unit, csv_sep);
+
+                               fprintf(output, "%*s",
+                                       csv_output ? 0 : -25,
+                                       perf_evsel__name(counter));
 
                        if (counter->cgrp)
                                fprintf(output, "%s%s",
@@ -1205,10 +1257,12 @@ static void print_counter(struct perf_evsel *counter, char *prefix)
                        continue;
                }
 
+               uval = val * counter->scale;
+
                if (nsec_counter(counter))
-                       nsec_printout(cpu, 0, counter, val);
+                       nsec_printout(cpu, 0, counter, uval);
                else
-                       abs_printout(cpu, 0, counter, val);
+                       abs_printout(cpu, 0, counter, uval);
 
                if (!csv_output) {
                        print_noise(counter, 1.0);
index 41c9bde2fb67f1418faceaaf86475a163694bdeb..680632d7e26a1a372e8e918d92947cf8726ad166 100644 (file)
@@ -41,6 +41,7 @@
 #define SUPPORT_OLD_POWER_EVENTS 1
 #define PWR_EVENT_EXIT -1
 
+static int proc_num = 15;
 
 static unsigned int    numcpus;
 static u64             min_freq;       /* Lowest CPU frequency seen */
@@ -50,16 +51,12 @@ static u64          turbo_frequency;
 static u64             first_time, last_time;
 
 static bool            power_only;
+static bool            tasks_only;
+static bool            with_backtrace;
 
 
-struct per_pid;
 struct per_pidcomm;
-
 struct cpu_sample;
-struct power_event;
-struct wake_event;
-
-struct sample_wrapper;
 
 /*
  * Datastructure layout:
@@ -124,6 +121,7 @@ struct cpu_sample {
        u64 end_time;
        int type;
        int cpu;
+       const char *backtrace;
 };
 
 static struct per_pid *all_data;
@@ -145,12 +143,12 @@ struct wake_event {
        int waker;
        int wakee;
        u64 time;
+       const char *backtrace;
 };
 
 static struct power_event    *power_events;
 static struct wake_event     *wake_events;
 
-struct process_filter;
 struct process_filter {
        char                    *name;
        int                     pid;
@@ -229,7 +227,8 @@ static void pid_exit(int pid, u64 timestamp)
 }
 
 static void
-pid_put_sample(int pid, int type, unsigned int cpu, u64 start, u64 end)
+pid_put_sample(int pid, int type, unsigned int cpu, u64 start, u64 end,
+              const char *backtrace)
 {
        struct per_pid *p;
        struct per_pidcomm *c;
@@ -252,6 +251,7 @@ pid_put_sample(int pid, int type, unsigned int cpu, u64 start, u64 end)
        sample->type = type;
        sample->next = c->samples;
        sample->cpu = cpu;
+       sample->backtrace = backtrace;
        c->samples = sample;
 
        if (sample->type == TYPE_RUNNING && end > start && start > 0) {
@@ -299,50 +299,10 @@ static int process_exit_event(struct perf_tool *tool __maybe_unused,
        return 0;
 }
 
-struct trace_entry {
-       unsigned short          type;
-       unsigned char           flags;
-       unsigned char           preempt_count;
-       int                     pid;
-       int                     lock_depth;
-};
-
 #ifdef SUPPORT_OLD_POWER_EVENTS
 static int use_old_power_events;
-struct power_entry_old {
-       struct trace_entry te;
-       u64     type;
-       u64     value;
-       u64     cpu_id;
-};
 #endif
 
-struct power_processor_entry {
-       struct trace_entry te;
-       u32     state;
-       u32     cpu_id;
-};
-
-#define TASK_COMM_LEN 16
-struct wakeup_entry {
-       struct trace_entry te;
-       char comm[TASK_COMM_LEN];
-       int   pid;
-       int   prio;
-       int   success;
-};
-
-struct sched_switch {
-       struct trace_entry te;
-       char prev_comm[TASK_COMM_LEN];
-       int  prev_pid;
-       int  prev_prio;
-       long prev_state; /* Arjan weeps. */
-       char next_comm[TASK_COMM_LEN];
-       int  next_pid;
-       int  next_prio;
-};
-
 static void c_state_start(int cpu, u64 timestamp, int state)
 {
        cpus_cstate_start_times[cpu] = timestamp;
@@ -402,23 +362,23 @@ static void p_state_change(int cpu, u64 timestamp, u64 new_freq)
                        turbo_frequency = max_freq;
 }
 
-static void
-sched_wakeup(int cpu, u64 timestamp, int pid, struct trace_entry *te)
+static void sched_wakeup(int cpu, u64 timestamp, int waker, int wakee,
+                        u8 flags, const char *backtrace)
 {
        struct per_pid *p;
-       struct wakeup_entry *wake = (void *)te;
        struct wake_event *we = zalloc(sizeof(*we));
 
        if (!we)
                return;
 
        we->time = timestamp;
-       we->waker = pid;
+       we->waker = waker;
+       we->backtrace = backtrace;
 
-       if ((te->flags & TRACE_FLAG_HARDIRQ) || (te->flags & TRACE_FLAG_SOFTIRQ))
+       if ((flags & TRACE_FLAG_HARDIRQ) || (flags & TRACE_FLAG_SOFTIRQ))
                we->waker = -1;
 
-       we->wakee = wake->pid;
+       we->wakee = wakee;
        we->next = wake_events;
        wake_events = we;
        p = find_create_pid(we->wakee);
@@ -428,27 +388,31 @@ sched_wakeup(int cpu, u64 timestamp, int pid, struct trace_entry *te)
                p->current->state = TYPE_WAITING;
        }
        if (p && p->current && p->current->state == TYPE_BLOCKED) {
-               pid_put_sample(p->pid, p->current->state, cpu, p->current->state_since, timestamp);
+               pid_put_sample(p->pid, p->current->state, cpu,
+                              p->current->state_since, timestamp, NULL);
                p->current->state_since = timestamp;
                p->current->state = TYPE_WAITING;
        }
 }
 
-static void sched_switch(int cpu, u64 timestamp, struct trace_entry *te)
+static void sched_switch(int cpu, u64 timestamp, int prev_pid, int next_pid,
+                        u64 prev_state, const char *backtrace)
 {
        struct per_pid *p = NULL, *prev_p;
-       struct sched_switch *sw = (void *)te;
 
+       prev_p = find_create_pid(prev_pid);
 
-       prev_p = find_create_pid(sw->prev_pid);
-
-       p = find_create_pid(sw->next_pid);
+       p = find_create_pid(next_pid);
 
        if (prev_p->current && prev_p->current->state != TYPE_NONE)
-               pid_put_sample(sw->prev_pid, TYPE_RUNNING, cpu, prev_p->current->state_since, timestamp);
+               pid_put_sample(prev_pid, TYPE_RUNNING, cpu,
+                              prev_p->current->state_since, timestamp,
+                              backtrace);
        if (p && p->current) {
                if (p->current->state != TYPE_NONE)
-                       pid_put_sample(sw->next_pid, p->current->state, cpu, p->current->state_since, timestamp);
+                       pid_put_sample(next_pid, p->current->state, cpu,
+                                      p->current->state_since, timestamp,
+                                      backtrace);
 
                p->current->state_since = timestamp;
                p->current->state = TYPE_RUNNING;
@@ -457,18 +421,97 @@ static void sched_switch(int cpu, u64 timestamp, struct trace_entry *te)
        if (prev_p->current) {
                prev_p->current->state = TYPE_NONE;
                prev_p->current->state_since = timestamp;
-               if (sw->prev_state & 2)
+               if (prev_state & 2)
                        prev_p->current->state = TYPE_BLOCKED;
-               if (sw->prev_state == 0)
+               if (prev_state == 0)
                        prev_p->current->state = TYPE_WAITING;
        }
 }
 
+static const char *cat_backtrace(union perf_event *event,
+                                struct perf_sample *sample,
+                                struct machine *machine)
+{
+       struct addr_location al;
+       unsigned int i;
+       char *p = NULL;
+       size_t p_len;
+       u8 cpumode = PERF_RECORD_MISC_USER;
+       struct addr_location tal;
+       struct ip_callchain *chain = sample->callchain;
+       FILE *f = open_memstream(&p, &p_len);
+
+       if (!f) {
+               perror("open_memstream error");
+               return NULL;
+       }
+
+       if (!chain)
+               goto exit;
+
+       if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
+               fprintf(stderr, "problem processing %d event, skipping it.\n",
+                       event->header.type);
+               goto exit;
+       }
+
+       for (i = 0; i < chain->nr; i++) {
+               u64 ip;
+
+               if (callchain_param.order == ORDER_CALLEE)
+                       ip = chain->ips[i];
+               else
+                       ip = chain->ips[chain->nr - i - 1];
+
+               if (ip >= PERF_CONTEXT_MAX) {
+                       switch (ip) {
+                       case PERF_CONTEXT_HV:
+                               cpumode = PERF_RECORD_MISC_HYPERVISOR;
+                               break;
+                       case PERF_CONTEXT_KERNEL:
+                               cpumode = PERF_RECORD_MISC_KERNEL;
+                               break;
+                       case PERF_CONTEXT_USER:
+                               cpumode = PERF_RECORD_MISC_USER;
+                               break;
+                       default:
+                               pr_debug("invalid callchain context: "
+                                        "%"PRId64"\n", (s64) ip);
+
+                               /*
+                                * It seems the callchain is corrupted.
+                                * Discard all.
+                                */
+                               free(p);
+                               p = NULL;
+                               goto exit;
+                       }
+                       continue;
+               }
+
+               tal.filtered = false;
+               thread__find_addr_location(al.thread, machine, cpumode,
+                                          MAP__FUNCTION, ip, &tal);
+
+               if (tal.sym)
+                       fprintf(f, "..... %016" PRIx64 " %s\n", ip,
+                               tal.sym->name);
+               else
+                       fprintf(f, "..... %016" PRIx64 "\n", ip);
+       }
+
+exit:
+       fclose(f);
+
+       return p;
+}
+
 typedef int (*tracepoint_handler)(struct perf_evsel *evsel,
-                                 struct perf_sample *sample);
+                                 struct perf_sample *sample,
+                                 const char *backtrace);
 
 static int process_sample_event(struct perf_tool *tool __maybe_unused,
-                               union perf_event *event __maybe_unused,
+                               union perf_event *event,
                                struct perf_sample *sample,
                                struct perf_evsel *evsel,
                                struct machine *machine __maybe_unused)
@@ -485,81 +528,97 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
 
        if (evsel->handler != NULL) {
                tracepoint_handler f = evsel->handler;
-               return f(evsel, sample);
+               return f(evsel, sample, cat_backtrace(event, sample, machine));
        }
 
        return 0;
 }
 
 static int
-process_sample_cpu_idle(struct perf_evsel *evsel __maybe_unused,
-                       struct perf_sample *sample)
+process_sample_cpu_idle(struct perf_evsel *evsel,
+                       struct perf_sample *sample,
+                       const char *backtrace __maybe_unused)
 {
-       struct power_processor_entry *ppe = sample->raw_data;
+       u32 state = perf_evsel__intval(evsel, sample, "state");
+       u32 cpu_id = perf_evsel__intval(evsel, sample, "cpu_id");
 
-       if (ppe->state == (u32) PWR_EVENT_EXIT)
-               c_state_end(ppe->cpu_id, sample->time);
+       if (state == (u32)PWR_EVENT_EXIT)
+               c_state_end(cpu_id, sample->time);
        else
-               c_state_start(ppe->cpu_id, sample->time, ppe->state);
+               c_state_start(cpu_id, sample->time, state);
        return 0;
 }
 
 static int
-process_sample_cpu_frequency(struct perf_evsel *evsel __maybe_unused,
-                            struct perf_sample *sample)
+process_sample_cpu_frequency(struct perf_evsel *evsel,
+                            struct perf_sample *sample,
+                            const char *backtrace __maybe_unused)
 {
-       struct power_processor_entry *ppe = sample->raw_data;
+       u32 state = perf_evsel__intval(evsel, sample, "state");
+       u32 cpu_id = perf_evsel__intval(evsel, sample, "cpu_id");
 
-       p_state_change(ppe->cpu_id, sample->time, ppe->state);
+       p_state_change(cpu_id, sample->time, state);
        return 0;
 }
 
 static int
-process_sample_sched_wakeup(struct perf_evsel *evsel __maybe_unused,
-                           struct perf_sample *sample)
+process_sample_sched_wakeup(struct perf_evsel *evsel,
+                           struct perf_sample *sample,
+                           const char *backtrace)
 {
-       struct trace_entry *te = sample->raw_data;
+       u8 flags = perf_evsel__intval(evsel, sample, "common_flags");
+       int waker = perf_evsel__intval(evsel, sample, "common_pid");
+       int wakee = perf_evsel__intval(evsel, sample, "pid");
 
-       sched_wakeup(sample->cpu, sample->time, sample->pid, te);
+       sched_wakeup(sample->cpu, sample->time, waker, wakee, flags, backtrace);
        return 0;
 }
 
 static int
-process_sample_sched_switch(struct perf_evsel *evsel __maybe_unused,
-                           struct perf_sample *sample)
+process_sample_sched_switch(struct perf_evsel *evsel,
+                           struct perf_sample *sample,
+                           const char *backtrace)
 {
-       struct trace_entry *te = sample->raw_data;
+       int prev_pid = perf_evsel__intval(evsel, sample, "prev_pid");
+       int next_pid = perf_evsel__intval(evsel, sample, "next_pid");
+       u64 prev_state = perf_evsel__intval(evsel, sample, "prev_state");
 
-       sched_switch(sample->cpu, sample->time, te);
+       sched_switch(sample->cpu, sample->time, prev_pid, next_pid, prev_state,
+                    backtrace);
        return 0;
 }
 
 #ifdef SUPPORT_OLD_POWER_EVENTS
 static int
-process_sample_power_start(struct perf_evsel *evsel __maybe_unused,
-                          struct perf_sample *sample)
+process_sample_power_start(struct perf_evsel *evsel,
+                          struct perf_sample *sample,
+                          const char *backtrace __maybe_unused)
 {
-       struct power_entry_old *peo = sample->raw_data;
+       u64 cpu_id = perf_evsel__intval(evsel, sample, "cpu_id");
+       u64 value = perf_evsel__intval(evsel, sample, "value");
 
-       c_state_start(peo->cpu_id, sample->time, peo->value);
+       c_state_start(cpu_id, sample->time, value);
        return 0;
 }
 
 static int
 process_sample_power_end(struct perf_evsel *evsel __maybe_unused,
-                        struct perf_sample *sample)
+                        struct perf_sample *sample,
+                        const char *backtrace __maybe_unused)
 {
        c_state_end(sample->cpu, sample->time);
        return 0;
 }
 
 static int
-process_sample_power_frequency(struct perf_evsel *evsel __maybe_unused,
-                              struct perf_sample *sample)
+process_sample_power_frequency(struct perf_evsel *evsel,
+                              struct perf_sample *sample,
+                              const char *backtrace __maybe_unused)
 {
-       struct power_entry_old *peo = sample->raw_data;
+       u64 cpu_id = perf_evsel__intval(evsel, sample, "cpu_id");
+       u64 value = perf_evsel__intval(evsel, sample, "value");
 
-       p_state_change(peo->cpu_id, sample->time, peo->value);
+       p_state_change(cpu_id, sample->time, value);
        return 0;
 }
 #endif /* SUPPORT_OLD_POWER_EVENTS */
@@ -739,11 +798,12 @@ static void draw_wakeups(void)
                }
 
                if (we->waker == -1)
-                       svg_interrupt(we->time, to);
+                       svg_interrupt(we->time, to, we->backtrace);
                else if (from && to && abs(from - to) == 1)
-                       svg_wakeline(we->time, from, to);
+                       svg_wakeline(we->time, from, to, we->backtrace);
                else
-                       svg_partial_wakeline(we->time, from, task_from, to, task_to);
+                       svg_partial_wakeline(we->time, from, task_from, to,
+                                            task_to, we->backtrace);
                we = we->next;
 
                free(task_from);
@@ -796,11 +856,20 @@ static void draw_process_bars(void)
                        sample = c->samples;
                        while (sample) {
                                if (sample->type == TYPE_RUNNING)
-                                       svg_sample(Y, sample->cpu, sample->start_time, sample->end_time);
+                                       svg_running(Y, sample->cpu,
+                                                   sample->start_time,
+                                                   sample->end_time,
+                                                   sample->backtrace);
                                if (sample->type == TYPE_BLOCKED)
-                                       svg_box(Y, sample->start_time, sample->end_time, "blocked");
+                                       svg_blocked(Y, sample->cpu,
+                                                   sample->start_time,
+                                                   sample->end_time,
+                                                   sample->backtrace);
                                if (sample->type == TYPE_WAITING)
-                                       svg_waiting(Y, sample->start_time, sample->end_time);
+                                       svg_waiting(Y, sample->cpu,
+                                                   sample->start_time,
+                                                   sample->end_time,
+                                                   sample->backtrace);
                                sample = sample->next;
                        }
 
@@ -911,7 +980,7 @@ static int determine_display_tasks(u64 threshold)
                /* no exit marker, task kept running to the end */
                if (p->end_time == 0)
                        p->end_time = last_time;
-               if (p->total_time >= threshold && !power_only)
+               if (p->total_time >= threshold)
                        p->display = 1;
 
                c = p->all;
@@ -922,7 +991,7 @@ static int determine_display_tasks(u64 threshold)
                        if (c->start_time == 1)
                                c->start_time = first_time;
 
-                       if (c->total_time >= threshold && !power_only) {
+                       if (c->total_time >= threshold) {
                                c->display = 1;
                                count++;
                        }
@@ -945,15 +1014,19 @@ static void write_svg_file(const char *filename)
 {
        u64 i;
        int count;
+       int thresh = TIME_THRESH;
 
        numcpus++;
 
+       if (power_only)
+               proc_num = 0;
 
-       count = determine_display_tasks(TIME_THRESH);
-
-       /* We'd like to show at least 15 tasks; be less picky if we have fewer */
-       if (count < 15)
-               count = determine_display_tasks(TIME_THRESH / 10);
+       /* We'd like to show at least proc_num tasks;
+        * be less picky if we have fewer */
+       do {
+               count = determine_display_tasks(thresh);
+               thresh /= 10;
+       } while (!process_filter && thresh && count < proc_num);
 
        open_svg(filename, numcpus, count, first_time, last_time);
 
@@ -964,9 +1037,12 @@ static void write_svg_file(const char *filename)
                svg_cpu_box(i, max_freq, turbo_frequency);
 
        draw_cpu_usage();
-       draw_process_bars();
-       draw_c_p_states();
-       draw_wakeups();
+       if (proc_num)
+               draw_process_bars();
+       if (!tasks_only)
+               draw_c_p_states();
+       if (proc_num)
+               draw_wakeups();
 
        svg_close();
 }
@@ -1031,50 +1107,92 @@ out_delete:
 
 static int __cmd_record(int argc, const char **argv)
 {
-#ifdef SUPPORT_OLD_POWER_EVENTS
-       const char * const record_old_args[] = {
+       unsigned int rec_argc, i, j;
+       const char **rec_argv;
+       const char **p;
+       unsigned int record_elems;
+
+       const char * const common_args[] = {
                "record", "-a", "-R", "-c", "1",
+       };
+       unsigned int common_args_nr = ARRAY_SIZE(common_args);
+
+       const char * const backtrace_args[] = {
+               "-g",
+       };
+       unsigned int backtrace_args_no = ARRAY_SIZE(backtrace_args);
+
+       const char * const power_args[] = {
+               "-e", "power:cpu_frequency",
+               "-e", "power:cpu_idle",
+       };
+       unsigned int power_args_nr = ARRAY_SIZE(power_args);
+
+       const char * const old_power_args[] = {
+#ifdef SUPPORT_OLD_POWER_EVENTS
                "-e", "power:power_start",
                "-e", "power:power_end",
                "-e", "power:power_frequency",
-               "-e", "sched:sched_wakeup",
-               "-e", "sched:sched_switch",
-       };
 #endif
-       const char * const record_new_args[] = {
-               "record", "-a", "-R", "-c", "1",
-               "-e", "power:cpu_frequency",
-               "-e", "power:cpu_idle",
+       };
+       unsigned int old_power_args_nr = ARRAY_SIZE(old_power_args);
+
+       const char * const tasks_args[] = {
                "-e", "sched:sched_wakeup",
                "-e", "sched:sched_switch",
        };
-       unsigned int rec_argc, i, j;
-       const char **rec_argv;
-       const char * const *record_args = record_new_args;
-       unsigned int record_elems = ARRAY_SIZE(record_new_args);
+       unsigned int tasks_args_nr = ARRAY_SIZE(tasks_args);
 
 #ifdef SUPPORT_OLD_POWER_EVENTS
        if (!is_valid_tracepoint("power:cpu_idle") &&
            is_valid_tracepoint("power:power_start")) {
                use_old_power_events = 1;
-               record_args = record_old_args;
-               record_elems = ARRAY_SIZE(record_old_args);
+               power_args_nr = 0;
+       } else {
+               old_power_args_nr = 0;
        }
 #endif
 
-       rec_argc = record_elems + argc - 1;
+       if (power_only)
+               tasks_args_nr = 0;
+
+       if (tasks_only) {
+               power_args_nr = 0;
+               old_power_args_nr = 0;
+       }
+
+       if (!with_backtrace)
+               backtrace_args_no = 0;
+
+       record_elems = common_args_nr + tasks_args_nr +
+               power_args_nr + old_power_args_nr + backtrace_args_no;
+
+       rec_argc = record_elems + argc;
        rec_argv = calloc(rec_argc + 1, sizeof(char *));
 
        if (rec_argv == NULL)
                return -ENOMEM;
 
-       for (i = 0; i < record_elems; i++)
-               rec_argv[i] = strdup(record_args[i]);
+       p = rec_argv;
+       for (i = 0; i < common_args_nr; i++)
+               *p++ = strdup(common_args[i]);
 
-       for (j = 1; j < (unsigned int)argc; j++, i++)
-               rec_argv[i] = argv[j];
+       for (i = 0; i < backtrace_args_no; i++)
+               *p++ = strdup(backtrace_args[i]);
 
-       return cmd_record(i, rec_argv, NULL);
+       for (i = 0; i < tasks_args_nr; i++)
+               *p++ = strdup(tasks_args[i]);
+
+       for (i = 0; i < power_args_nr; i++)
+               *p++ = strdup(power_args[i]);
+
+       for (i = 0; i < old_power_args_nr; i++)
+               *p++ = strdup(old_power_args[i]);
+
+       for (j = 1; j < (unsigned int)argc; j++)
+               *p++ = argv[j];
+
+       return cmd_record(rec_argc, rec_argv, NULL);
 }
 
 static int
@@ -1090,16 +1208,20 @@ int cmd_timechart(int argc, const char **argv,
                  const char *prefix __maybe_unused)
 {
        const char *output_name = "output.svg";
-       const struct option options[] = {
+       const struct option timechart_options[] = {
        OPT_STRING('i', "input", &input_name, "file", "input file name"),
        OPT_STRING('o', "output", &output_name, "file", "output file name"),
        OPT_INTEGER('w', "width", &svg_page_width, "page width"),
        OPT_BOOLEAN('P', "power-only", &power_only, "output power data only"),
+       OPT_BOOLEAN('T', "tasks-only", &tasks_only,
+                   "output processes data only"),
        OPT_CALLBACK('p', "process", NULL, "process",
                      "process selector. Pass a pid or process name.",
                       parse_process),
        OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
                    "Look for files with symbols relative to this directory"),
+       OPT_INTEGER('n', "proc-num", &proc_num,
+                   "min. number of tasks to print"),
        OPT_END()
        };
        const char * const timechart_usage[] = {
@@ -1107,15 +1229,39 @@ int cmd_timechart(int argc, const char **argv,
                NULL
        };
 
-       argc = parse_options(argc, argv, options, timechart_usage,
+       const struct option record_options[] = {
+       OPT_BOOLEAN('P', "power-only", &power_only, "output power data only"),
+       OPT_BOOLEAN('T', "tasks-only", &tasks_only,
+                   "output processes data only"),
+       OPT_BOOLEAN('g', "callchain", &with_backtrace, "record callchain"),
+       OPT_END()
+       };
+       const char * const record_usage[] = {
+               "perf timechart record [<options>]",
+               NULL
+       };
+       argc = parse_options(argc, argv, timechart_options, timechart_usage,
                        PARSE_OPT_STOP_AT_NON_OPTION);
 
+       if (power_only && tasks_only) {
+               pr_err("-P and -T options cannot be used at the same time.\n");
+               return -1;
+       }
+
        symbol__init();
 
-       if (argc && !strncmp(argv[0], "rec", 3))
+       if (argc && !strncmp(argv[0], "rec", 3)) {
+               argc = parse_options(argc, argv, record_options, record_usage,
+                                    PARSE_OPT_STOP_AT_NON_OPTION);
+
+               if (power_only && tasks_only) {
+                       pr_err("-P and -T options cannot be used at the same time.\n");
+                       return -1;
+               }
+
                return __cmd_record(argc, argv);
-       else if (argc)
-               usage_with_options(timechart_usage, options);
+       else if (argc)
+               usage_with_options(timechart_usage, timechart_options);
 
        setup_pager();
 
index 71e6402729a8616bf9b9fe8e2141ea08ac0bbca2..03d37a76c6122d6328034322dc9c3f99830b623d 100644 (file)
@@ -634,26 +634,9 @@ repeat:
        return NULL;
 }
 
-/* Tag samples to be skipped. */
-static const char *skip_symbols[] = {
-       "intel_idle",
-       "default_idle",
-       "native_safe_halt",
-       "cpu_idle",
-       "enter_idle",
-       "exit_idle",
-       "mwait_idle",
-       "mwait_idle_with_hints",
-       "poll_idle",
-       "ppc64_runlatch_off",
-       "pseries_dedicated_idle_sleep",
-       NULL
-};
-
 static int symbol_filter(struct map *map __maybe_unused, struct symbol *sym)
 {
        const char *name = sym->name;
-       int i;
 
        /*
         * ppc64 uses function descriptors and appends a '.' to the
@@ -671,12 +654,8 @@ static int symbol_filter(struct map *map __maybe_unused, struct symbol *sym)
            strstr(name, "_text_end"))
                return 1;
 
-       for (i = 0; skip_symbols[i]; i++) {
-               if (!strcmp(skip_symbols[i], name)) {
-                       sym->ignore = true;
-                       break;
-               }
-       }
+       if (symbol__is_idle(sym))
+               sym->ignore = true;
 
        return 0;
 }
@@ -1084,7 +1063,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
                            "dump the symbol table used for profiling"),
        OPT_INTEGER('f', "count-filter", &top.count_filter,
                    "only display functions with more events than this"),
-       OPT_BOOLEAN('g', "group", &opts->group,
+       OPT_BOOLEAN(0, "group", &opts->group,
                            "put the counters into a counter group"),
        OPT_BOOLEAN('i', "no-inherit", &opts->no_inherit,
                    "child tasks do not inherit counters"),
@@ -1105,7 +1084,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
                   " abort, in_tx, transaction"),
        OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
                    "Show a column with the number of samples"),
-       OPT_CALLBACK_NOOPT('G', NULL, &top.record_opts,
+       OPT_CALLBACK_NOOPT('g', NULL, &top.record_opts,
                           NULL, "enables call-graph recording",
                           &callchain_opt),
        OPT_CALLBACK(0, "call-graph", &top.record_opts,
index 8be17fc462baff466a6aa25682f804c4b5fdd1dc..e9f345e2551a18be6e5a17af51b8547f89c5ddbb 100644 (file)
@@ -2158,7 +2158,6 @@ static int trace__fprintf_one_thread(struct thread *thread, void *priv)
        size_t printed = data->printed;
        struct trace *trace = data->trace;
        struct thread_trace *ttrace = thread->priv;
-       const char *color;
        double ratio;
 
        if (ttrace == NULL)
@@ -2166,17 +2165,9 @@ static int trace__fprintf_one_thread(struct thread *thread, void *priv)
 
        ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
 
-       color = PERF_COLOR_NORMAL;
-       if (ratio > 50.0)
-               color = PERF_COLOR_RED;
-       else if (ratio > 25.0)
-               color = PERF_COLOR_GREEN;
-       else if (ratio > 5.0)
-               color = PERF_COLOR_YELLOW;
-
-       printed += color_fprintf(fp, color, " %s (%d), ", thread__comm_str(thread), thread->tid);
+       printed += fprintf(fp, " %s (%d), ", thread__comm_str(thread), thread->tid);
        printed += fprintf(fp, "%lu events, ", ttrace->nr_events);
-       printed += color_fprintf(fp, color, "%.1f%%", ratio);
+       printed += fprintf(fp, "%.1f%%", ratio);
        printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms);
        printed += thread__dump_stats(ttrace, trace, fp);
 
similarity index 65%
rename from tools/perf/bash_completion
rename to tools/perf/perf-completion.sh
index 62e157db2e2b01e9400f9348d671fd9ba7267104..49494882d9bb8c1a65417589b20d691b08f57538 100644 (file)
@@ -1,4 +1,4 @@
-# perf completion
+# perf bash and zsh completion
 
 # Taken from git.git's completion script.
 __my_reassemble_comp_words_by_ref()
@@ -89,37 +89,113 @@ __ltrim_colon_completions()
        fi
 }
 
-type perf &>/dev/null &&
-_perf()
+__perfcomp ()
 {
-       local cur words cword prev cmd
+       COMPREPLY=( $( compgen -W "$1" -- "$2" ) )
+}
 
-       COMPREPLY=()
-       _get_comp_words_by_ref -n =: cur words cword prev
+__perfcomp_colon ()
+{
+       __perfcomp "$1" "$2"
+       __ltrim_colon_completions $cur
+}
+
+__perf_main ()
+{
+       local cmd
 
        cmd=${words[0]}
+       COMPREPLY=()
 
        # List perf subcommands or long options
        if [ $cword -eq 1 ]; then
                if [[ $cur == --* ]]; then
-                       COMPREPLY=( $( compgen -W '--help --version \
+                       __perfcomp '--help --version \
                        --exec-path --html-path --paginate --no-pager \
-                       --perf-dir --work-tree --debugfs-dir' -- "$cur" ) )
+                       --perf-dir --work-tree --debugfs-dir' -- "$cur"
                else
                        cmds=$($cmd --list-cmds)
-                       COMPREPLY=( $( compgen -W '$cmds' -- "$cur" ) )
+                       __perfcomp "$cmds" "$cur"
                fi
        # List possible events for -e option
        elif [[ $prev == "-e" && "${words[1]}" == @(record|stat|top) ]]; then
                evts=$($cmd list --raw-dump)
-               COMPREPLY=( $( compgen -W '$evts' -- "$cur" ) )
-               __ltrim_colon_completions $cur
+               __perfcomp_colon "$evts" "$cur"
        # List long option names
        elif [[ $cur == --* ]];  then
                subcmd=${words[1]}
                opts=$($cmd $subcmd --list-opts)
-               COMPREPLY=( $( compgen -W '$opts' -- "$cur" ) )
+               __perfcomp "$opts" "$cur"
        fi
+}
+
+if [[ -n ${ZSH_VERSION-} ]]; then
+       autoload -U +X compinit && compinit
+
+       __perfcomp ()
+       {
+               emulate -L zsh
+
+               local c IFS=$' \t\n'
+               local -a array
+
+               for c in ${=1}; do
+                       case $c in
+                       --*=*|*.) ;;
+                       *) c="$c " ;;
+                       esac
+                       array[${#array[@]}+1]="$c"
+               done
+
+               compset -P '*[=:]'
+               compadd -Q -S '' -a -- array && _ret=0
+       }
+
+       __perfcomp_colon ()
+       {
+               emulate -L zsh
+
+               local cur_="${2-$cur}"
+               local c IFS=$' \t\n'
+               local -a array
+
+               if [[ "$cur_" == *:* ]]; then
+                       local colon_word=${cur_%"${cur_##*:}"}
+               fi
+
+               for c in ${=1}; do
+                       case $c in
+                       --*=*|*.) ;;
+                       *) c="$c " ;;
+                       esac
+                       array[$#array+1]=${c#"$colon_word"}
+               done
+
+               compset -P '*[=:]'
+               compadd -Q -S '' -a -- array && _ret=0
+       }
+
+       _perf ()
+       {
+               local _ret=1 cur cword prev
+               cur=${words[CURRENT]}
+               prev=${words[CURRENT-1]}
+               let cword=CURRENT-1
+               emulate ksh -c __perf_main
+               let _ret && _default && _ret=0
+               return _ret
+       }
+
+       compdef _perf perf
+       return
+fi
+
+type perf &>/dev/null &&
+_perf()
+{
+       local cur words cword prev
+       _get_comp_words_by_ref -n =: cur words cword prev
+       __perf_main
 } &&
 
 complete -o bashdefault -o default -o nospace -F _perf perf 2>/dev/null \
index b079304bd53daa87ca61a428f4611046741f58e6..b23fed5275149adfb1b5f826730341ef6d63f8be 100644 (file)
@@ -254,6 +254,7 @@ struct perf_record_opts {
        bool         inherit_stat;
        bool         no_delay;
        bool         no_inherit;
+       bool         no_inherit_set;
        bool         no_samples;
        bool         raw_samples;
        bool         sample_address;
index 9079a25cd643cdabaf570d19131e4cc0e4fef7f6..44edcb2edcd50b7c4696477e88f6e12176555303 100644 (file)
@@ -3,5 +3,5 @@ command = record
 args    = -i kill >/dev/null 2>&1
 
 [event:base-record]
-sample_type=259
+sample_type=263
 inherit=0
index bb788c109fe6efa4ecb2ae5784efa49cf33bca73..c77814bf01e1a7f89857ba8742ce7ec7cbcfaf5e 100644 (file)
@@ -732,8 +732,7 @@ int perf_event__preprocess_sample(const union perf_event *event,
        if (thread == NULL)
                return -1;
 
-       if (symbol_conf.comm_list &&
-           !strlist__has_entry(symbol_conf.comm_list, thread__comm_str(thread)))
+       if (thread__is_filtered(thread))
                goto out_filtered;
 
        dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid);
index bbc746aa571663d92e989bb5f3f2703c31c9a193..76fa76431329f9b252d15e1b49b43e18d05c6c0a 100644 (file)
@@ -819,8 +819,10 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
        if (evlist->threads == NULL)
                return -1;
 
-       if (target->force_per_cpu)
-               evlist->cpus = cpu_map__new(target->cpu_list);
+       if (target->default_per_cpu)
+               evlist->cpus = target->per_thread ?
+                                       cpu_map__dummy_new() :
+                                       cpu_map__new(target->cpu_list);
        else if (target__has_task(target))
                evlist->cpus = cpu_map__dummy_new();
        else if (!target__has_cpu(target) && !target->uses_mmap)
index 46dd4c2a41ce7e0a844e0b691c134e3ce23f55e6..b5fe7f9b2e15091f5d38db1044159177d9c15f27 100644 (file)
@@ -162,6 +162,8 @@ void perf_evsel__init(struct perf_evsel *evsel,
        evsel->idx         = idx;
        evsel->attr        = *attr;
        evsel->leader      = evsel;
+       evsel->unit        = "";
+       evsel->scale       = 1.0;
        INIT_LIST_HEAD(&evsel->node);
        hists__init(&evsel->hists);
        evsel->sample_size = __perf_evsel__sample_size(attr->sample_type);
@@ -572,6 +574,7 @@ void perf_evsel__config(struct perf_evsel *evsel,
        struct perf_evsel *leader = evsel->leader;
        struct perf_event_attr *attr = &evsel->attr;
        int track = !evsel->idx; /* only the first counter needs these */
+       bool per_cpu = opts->target.default_per_cpu && !opts->target.per_thread;
 
        attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1;
        attr->inherit       = !opts->no_inherit;
@@ -645,7 +648,7 @@ void perf_evsel__config(struct perf_evsel *evsel,
                }
        }
 
-       if (target__has_cpu(&opts->target) || opts->target.force_per_cpu)
+       if (target__has_cpu(&opts->target))
                perf_evsel__set_sample_bit(evsel, CPU);
 
        if (opts->period)
@@ -653,7 +656,7 @@ void perf_evsel__config(struct perf_evsel *evsel,
 
        if (!perf_missing_features.sample_id_all &&
            (opts->sample_time || !opts->no_inherit ||
-            target__has_cpu(&opts->target) || opts->target.force_per_cpu))
+            target__has_cpu(&opts->target) || per_cpu))
                perf_evsel__set_sample_bit(evsel, TIME);
 
        if (opts->raw_samples) {
index 1ea7c92e6e3365aebbedbed37ae728e9473dbab5..8120eeb86ac16c4c5b86c931785233e85ea4ac16 100644 (file)
@@ -68,6 +68,8 @@ struct perf_evsel {
        u32                     ids;
        struct hists            hists;
        char                    *name;
+       double                  scale;
+       const char              *unit;
        struct event_format     *tp_format;
        union {
                void            *priv;
@@ -138,6 +140,7 @@ extern const char *perf_evsel__sw_names[PERF_COUNT_SW_MAX];
 int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result,
                                            char *bf, size_t size);
 const char *perf_evsel__name(struct perf_evsel *evsel);
+
 const char *perf_evsel__group_name(struct perf_evsel *evsel);
 int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size);
 
index 369c03648f8846d3da12bf96a938f6e76485fbed..1cd035708931144dccbfdb68f4c1024903e45631 100644 (file)
@@ -2078,8 +2078,10 @@ static int process_group_desc(struct perf_file_section *section __maybe_unused,
                if (evsel->idx == (int) desc[i].leader_idx) {
                        evsel->leader = evsel;
                        /* {anon_group} is a dummy name */
-                       if (strcmp(desc[i].name, "{anon_group}"))
+                       if (strcmp(desc[i].name, "{anon_group}")) {
                                evsel->group_name = desc[i].name;
+                               desc[i].name = NULL;
+                       }
                        evsel->nr_members = desc[i].nr_members;
 
                        if (i >= nr_groups || nr > 0) {
@@ -2105,7 +2107,7 @@ static int process_group_desc(struct perf_file_section *section __maybe_unused,
 
        ret = 0;
 out_free:
-       while ((int) --i >= 0)
+       for (i = 0; i < nr_groups; i++)
                free(desc[i].name);
        free(desc);
 
index 6de6f89c2a6175c96570055f57ccbb83cc8c58b5..969cb8f0d88d0c77152fec5b187b53c21cfd44ef 100644 (file)
@@ -269,9 +269,10 @@ const char *event_type(int type)
 
 
 
-static int __add_event(struct list_head *list, int *idx,
-                      struct perf_event_attr *attr,
-                      char *name, struct cpu_map *cpus)
+static struct perf_evsel *
+__add_event(struct list_head *list, int *idx,
+           struct perf_event_attr *attr,
+           char *name, struct cpu_map *cpus)
 {
        struct perf_evsel *evsel;
 
@@ -279,19 +280,19 @@ static int __add_event(struct list_head *list, int *idx,
 
        evsel = perf_evsel__new_idx(attr, (*idx)++);
        if (!evsel)
-               return -ENOMEM;
+               return NULL;
 
        evsel->cpus = cpus;
        if (name)
                evsel->name = strdup(name);
        list_add_tail(&evsel->node, list);
-       return 0;
+       return evsel;
 }
 
 static int add_event(struct list_head *list, int *idx,
                     struct perf_event_attr *attr, char *name)
 {
-       return __add_event(list, idx, attr, name, NULL);
+       return __add_event(list, idx, attr, name, NULL) ? 0 : -ENOMEM;
 }
 
 static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size)
@@ -633,6 +634,9 @@ int parse_events_add_pmu(struct list_head *list, int *idx,
 {
        struct perf_event_attr attr;
        struct perf_pmu *pmu;
+       struct perf_evsel *evsel;
+       char *unit;
+       double scale;
 
        pmu = perf_pmu__find(name);
        if (!pmu)
@@ -640,7 +644,7 @@ int parse_events_add_pmu(struct list_head *list, int *idx,
 
        memset(&attr, 0, sizeof(attr));
 
-       if (perf_pmu__check_alias(pmu, head_config))
+       if (perf_pmu__check_alias(pmu, head_config, &unit, &scale))
                return -EINVAL;
 
        /*
@@ -652,8 +656,14 @@ int parse_events_add_pmu(struct list_head *list, int *idx,
        if (perf_pmu__config(pmu, &attr, head_config))
                return -EINVAL;
 
-       return __add_event(list, idx, &attr, pmu_event_name(head_config),
-                          pmu->cpus);
+       evsel = __add_event(list, idx, &attr, pmu_event_name(head_config),
+                           pmu->cpus);
+       if (evsel) {
+               evsel->unit = unit;
+               evsel->scale = scale;
+       }
+
+       return evsel ? 0 : -ENOMEM;
 }
 
 int parse_events__modifier_group(struct list_head *list,
index 31f404a032a90499e5d366123f3185972edf3b49..d22e3f8017dc429a67458bc18457a6de7cd9f778 100644 (file)
@@ -78,6 +78,8 @@ static int get_value(struct parse_opt_ctx_t *p,
 
        case OPTION_BOOLEAN:
                *(bool *)opt->value = unset ? false : true;
+               if (opt->set)
+                       *(bool *)opt->set = true;
                return 0;
 
        case OPTION_INCR:
@@ -224,6 +226,24 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
                        return 0;
                }
                if (!rest) {
+                       if (!prefixcmp(options->long_name, "no-")) {
+                               /*
+                                * The long name itself starts with "no-", so
+                                * accept the option without "no-" so that users
+                                * do not have to enter "no-no-" to get the
+                                * negation.
+                                */
+                               rest = skip_prefix(arg, options->long_name + 3);
+                               if (rest) {
+                                       flags |= OPT_UNSET;
+                                       goto match;
+                               }
+                               /* Abbreviated case */
+                               if (!prefixcmp(options->long_name + 3, arg)) {
+                                       flags |= OPT_UNSET;
+                                       goto is_abbreviated;
+                               }
+                       }
                        /* abbreviated? */
                        if (!strncmp(options->long_name, arg, arg_end - arg)) {
 is_abbreviated:
@@ -259,6 +279,7 @@ is_abbreviated:
                        if (!rest)
                                continue;
                }
+match:
                if (*rest) {
                        if (*rest != '=')
                                continue;
index b0241e28eaf7dd7b81469e22416e8f1e16e26c63..cbf0149cf221783aea2aeafd8643900b80e6765d 100644 (file)
@@ -82,6 +82,9 @@ typedef int parse_opt_cb(const struct option *, const char *arg, int unset);
  *   OPTION_{BIT,SET_UINT,SET_PTR} store the {mask,integer,pointer} to put in
  *   the value when met.
  *   CALLBACKS can use it like they want.
+ *
+ * `set`::
+ *   whether an option was set by the user
  */
 struct option {
        enum parse_opt_type type;
@@ -94,6 +97,7 @@ struct option {
        int flags;
        parse_opt_cb *callback;
        intptr_t defval;
+       bool *set;
 };
 
 #define check_vtype(v, type) ( BUILD_BUG_ON_ZERO(!__builtin_types_compatible_p(typeof(v), type)) + v )
@@ -103,6 +107,10 @@ struct option {
 #define OPT_GROUP(h)                { .type = OPTION_GROUP, .help = (h) }
 #define OPT_BIT(s, l, v, h, b)      { .type = OPTION_BIT, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h), .defval = (b) }
 #define OPT_BOOLEAN(s, l, v, h)     { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = check_vtype(v, bool *), .help = (h) }
+#define OPT_BOOLEAN_SET(s, l, v, os, h) \
+       { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), \
+       .value = check_vtype(v, bool *), .help = (h), \
+       .set = check_vtype(os, bool *)}
 #define OPT_INCR(s, l, v, h)        { .type = OPTION_INCR, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h) }
 #define OPT_SET_UINT(s, l, v, h, i)  { .type = OPTION_SET_UINT, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned int *), .help = (h), .defval = (i) }
 #define OPT_SET_PTR(s, l, v, h, p)  { .type = OPTION_SET_PTR, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (p) }
index c232d8dd410bf6483ba8fcd850380bbd562f03ee..56fc10a5e288142a04bda6d4086c14763531a11f 100644 (file)
@@ -1,19 +1,23 @@
 #include <linux/list.h>
 #include <sys/types.h>
-#include <sys/stat.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <dirent.h>
 #include "fs.h"
+#include <locale.h>
 #include "util.h"
 #include "pmu.h"
 #include "parse-events.h"
 #include "cpumap.h"
 
+#define UNIT_MAX_LEN   31 /* max length for event unit name */
+
 struct perf_pmu_alias {
        char *name;
        struct list_head terms;
        struct list_head list;
+       char unit[UNIT_MAX_LEN+1];
+       double scale;
 };
 
 struct perf_pmu_format {
@@ -94,7 +98,80 @@ static int pmu_format(const char *name, struct list_head *format)
        return 0;
 }
 
-static int perf_pmu__new_alias(struct list_head *list, char *name, FILE *file)
+static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char *name)
+{
+       struct stat st;
+       ssize_t sret;
+       char scale[128];
+       int fd, ret = -1;
+       char path[PATH_MAX];
+       char *lc;
+
+       snprintf(path, PATH_MAX, "%s/%s.scale", dir, name);
+
+       fd = open(path, O_RDONLY);
+       if (fd == -1)
+               return -1;
+
+       if (fstat(fd, &st) < 0)
+               goto error;
+
+       sret = read(fd, scale, sizeof(scale)-1);
+       if (sret < 0)
+               goto error;
+
+       scale[sret] = '\0';
+       /*
+        * save current locale
+        */
+       lc = setlocale(LC_NUMERIC, NULL);
+
+       /*
+        * force to C locale to ensure kernel
+        * scale string is converted correctly.
+        * kernel uses default C locale.
+        */
+       setlocale(LC_NUMERIC, "C");
+
+       alias->scale = strtod(scale, NULL);
+
+       /* restore locale */
+       setlocale(LC_NUMERIC, lc);
+
+       ret = 0;
+error:
+       close(fd);
+       return ret;
+}
+
+static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, char *dir, char *name)
+{
+       char path[PATH_MAX];
+       ssize_t sret;
+       int fd;
+
+       snprintf(path, PATH_MAX, "%s/%s.unit", dir, name);
+
+       fd = open(path, O_RDONLY);
+       if (fd == -1)
+               return -1;
+
+               sret = read(fd, alias->unit, UNIT_MAX_LEN);
+       if (sret < 0)
+               goto error;
+
+       close(fd);
+
+       alias->unit[sret] = '\0';
+
+       return 0;
+error:
+       close(fd);
+       alias->unit[0] = '\0';
+       return -1;
+}
+
+static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FILE *file)
 {
        struct perf_pmu_alias *alias;
        char buf[256];
@@ -110,6 +187,9 @@ static int perf_pmu__new_alias(struct list_head *list, char *name, FILE *file)
                return -ENOMEM;
 
        INIT_LIST_HEAD(&alias->terms);
+       alias->scale = 1.0;
+       alias->unit[0] = '\0';
+
        ret = parse_events_terms(&alias->terms, buf);
        if (ret) {
                free(alias);
@@ -117,7 +197,14 @@ static int perf_pmu__new_alias(struct list_head *list, char *name, FILE *file)
        }
 
        alias->name = strdup(name);
+       /*
+        * load unit name and scale if available
+        */
+       perf_pmu__parse_unit(alias, dir, name);
+       perf_pmu__parse_scale(alias, dir, name);
+
        list_add_tail(&alias->list, list);
+
        return 0;
 }
 
@@ -129,6 +216,7 @@ static int pmu_aliases_parse(char *dir, struct list_head *head)
 {
        struct dirent *evt_ent;
        DIR *event_dir;
+       size_t len;
        int ret = 0;
 
        event_dir = opendir(dir);
@@ -143,13 +231,24 @@ static int pmu_aliases_parse(char *dir, struct list_head *head)
                if (!strcmp(name, ".") || !strcmp(name, ".."))
                        continue;
 
+               /*
+                * skip .unit and .scale info files
+                * parsed in perf_pmu__new_alias()
+                */
+               len = strlen(name);
+               if (len > 5 && !strcmp(name + len - 5, ".unit"))
+                       continue;
+               if (len > 6 && !strcmp(name + len - 6, ".scale"))
+                       continue;
+
                snprintf(path, PATH_MAX, "%s/%s", dir, name);
 
                ret = -EINVAL;
                file = fopen(path, "r");
                if (!file)
                        break;
-               ret = perf_pmu__new_alias(head, name, file);
+
+               ret = perf_pmu__new_alias(head, dir, name, file);
                fclose(file);
        }
 
@@ -508,16 +607,42 @@ static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
        return NULL;
 }
 
+
+static int check_unit_scale(struct perf_pmu_alias *alias,
+                           char **unit, double *scale)
+{
+       /*
+        * Only one term in event definition can
+        * define unit and scale, fail if there's
+        * more than one.
+        */
+       if ((*unit && alias->unit) ||
+           (*scale && alias->scale))
+               return -EINVAL;
+
+       if (alias->unit)
+               *unit = alias->unit;
+
+       if (alias->scale)
+               *scale = alias->scale;
+
+       return 0;
+}
+
 /*
  * Find alias in the terms list and replace it with the terms
  * defined for the alias
  */
-int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms)
+int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
+                         char **unit, double *scale)
 {
        struct parse_events_term *term, *h;
        struct perf_pmu_alias *alias;
        int ret;
 
+       *unit   = NULL;
+       *scale  = 0;
+
        list_for_each_entry_safe(term, h, head_terms, list) {
                alias = pmu_find_alias(pmu, term);
                if (!alias)
@@ -525,6 +650,11 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms)
                ret = pmu_alias_terms(alias, &term->list);
                if (ret)
                        return ret;
+
+               ret = check_unit_scale(alias, unit, scale);
+               if (ret)
+                       return ret;
+
                list_del(&term->list);
                free(term);
        }
index 1179b26f244a31280e5454787a51a8f01ff9ac2e..9183380e203851b8fb12f0bcee499b61dcda0f58 100644 (file)
@@ -28,7 +28,8 @@ int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
 int perf_pmu__config_terms(struct list_head *formats,
                           struct perf_event_attr *attr,
                           struct list_head *head_terms);
-int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms);
+int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
+                         char **unit, double *scale);
 struct list_head *perf_pmu__alias(struct perf_pmu *pmu,
                                  struct list_head *head_terms);
 int perf_pmu_wrap(void);
index f36d24a024453f6e2777d1bc4cfbb10fb9a3cf4a..b0b15e213df50d9624674b7f9de622a48b90b800 100644 (file)
@@ -1522,6 +1522,9 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event,
                        if (!node)
                                break;
 
+                       if (node->sym && node->sym->ignore)
+                               goto next;
+
                        if (print_ip)
                                printf("%c%16" PRIx64, s, node->ip);
 
@@ -1544,12 +1547,15 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event,
                        if (!print_oneline)
                                printf("\n");
 
-                       callchain_cursor_advance(&callchain_cursor);
-
                        stack_depth--;
+next:
+                       callchain_cursor_advance(&callchain_cursor);
                }
 
        } else {
+               if (al.sym && al.sym->ignore)
+                       return;
+
                if (print_ip)
                        printf("%16" PRIx64, sample->ip);
 
index 96c866045d60d2a17f4d969ed5e3a0a3c00933fc..8b79d3ad124629e44184b8d20474592f9346a44b 100644 (file)
@@ -95,6 +95,7 @@ void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end)
 
        total_height = (1 + rows + cpu2slot(cpus)) * SLOT_MULT;
        fprintf(svgfile, "<?xml version=\"1.0\" standalone=\"no\"?> \n");
+       fprintf(svgfile, "<!DOCTYPE svg SYSTEM \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");
        fprintf(svgfile, "<svg width=\"%i\" height=\"%" PRIu64 "\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n", svg_page_width, total_height);
 
        fprintf(svgfile, "<defs>\n  <style type=\"text/css\">\n    <![CDATA[\n");
@@ -128,12 +129,33 @@ void svg_box(int Yslot, u64 start, u64 end, const char *type)
                time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT, type);
 }
 
-void svg_sample(int Yslot, int cpu, u64 start, u64 end)
+static char *time_to_string(u64 duration);
+void svg_blocked(int Yslot, int cpu, u64 start, u64 end, const char *backtrace)
+{
+       if (!svgfile)
+               return;
+
+       fprintf(svgfile, "<g>\n");
+       fprintf(svgfile, "<title>#%d blocked %s</title>\n", cpu,
+               time_to_string(end - start));
+       if (backtrace)
+               fprintf(svgfile, "<desc>Blocked on:\n%s</desc>\n", backtrace);
+       svg_box(Yslot, start, end, "blocked");
+       fprintf(svgfile, "</g>\n");
+}
+
+void svg_running(int Yslot, int cpu, u64 start, u64 end, const char *backtrace)
 {
        double text_size;
        if (!svgfile)
                return;
 
+       fprintf(svgfile, "<g>\n");
+
+       fprintf(svgfile, "<title>#%d running %s</title>\n",
+               cpu, time_to_string(end - start));
+       if (backtrace)
+               fprintf(svgfile, "<desc>Switched because:\n%s</desc>\n", backtrace);
        fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"sample\"/>\n",
                time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT);
 
@@ -148,6 +170,7 @@ void svg_sample(int Yslot, int cpu, u64 start, u64 end)
                fprintf(svgfile, "<text x=\"%1.8f\" y=\"%1.8f\" font-size=\"%1.8fpt\">%i</text>\n",
                        time2pixels(start), Yslot *  SLOT_MULT + SLOT_HEIGHT - 1, text_size,  cpu + 1);
 
+       fprintf(svgfile, "</g>\n");
 }
 
 static char *time_to_string(u64 duration)
@@ -168,7 +191,7 @@ static char *time_to_string(u64 duration)
        return text;
 }
 
-void svg_waiting(int Yslot, u64 start, u64 end)
+void svg_waiting(int Yslot, int cpu, u64 start, u64 end, const char *backtrace)
 {
        char *text;
        const char *style;
@@ -192,6 +215,9 @@ void svg_waiting(int Yslot, u64 start, u64 end)
        font_size = round_text_size(font_size);
 
        fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\">\n", time2pixels(start), Yslot * SLOT_MULT);
+       fprintf(svgfile, "<title>#%d waiting %s</title>\n", cpu, time_to_string(end - start));
+       if (backtrace)
+               fprintf(svgfile, "<desc>Waiting on:\n%s</desc>\n", backtrace);
        fprintf(svgfile, "<rect x=\"0\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n",
                time2pixels(end)-time2pixels(start), SLOT_HEIGHT, style);
        if (font_size > MIN_TEXT_SIZE)
@@ -242,6 +268,8 @@ void svg_cpu_box(int cpu, u64 __max_freq, u64 __turbo_freq)
        max_freq = __max_freq;
        turbo_frequency = __turbo_freq;
 
+       fprintf(svgfile, "<g>\n");
+
        fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"cpu\"/>\n",
                time2pixels(first_time),
                time2pixels(last_time)-time2pixels(first_time),
@@ -253,6 +281,8 @@ void svg_cpu_box(int cpu, u64 __max_freq, u64 __turbo_freq)
 
        fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f)\" font-size=\"1.25pt\">%s</text>\n",
                10+time2pixels(first_time), cpu2y(cpu) + SLOT_MULT + SLOT_HEIGHT - 4, cpu_model());
+
+       fprintf(svgfile, "</g>\n");
 }
 
 void svg_process(int cpu, u64 start, u64 end, const char *type, const char *name)
@@ -264,6 +294,7 @@ void svg_process(int cpu, u64 start, u64 end, const char *type, const char *name
 
 
        fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\">\n", time2pixels(start), cpu2y(cpu));
+       fprintf(svgfile, "<title>%s %s</title>\n", name, time_to_string(end - start));
        fprintf(svgfile, "<rect x=\"0\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n",
                time2pixels(end)-time2pixels(start), SLOT_MULT+SLOT_HEIGHT, type);
        width = time2pixels(end)-time2pixels(start);
@@ -288,6 +319,8 @@ void svg_cstate(int cpu, u64 start, u64 end, int type)
                return;
 
 
+       fprintf(svgfile, "<g>\n");
+
        if (type > 6)
                type = 6;
        sprintf(style, "c%i", type);
@@ -306,6 +339,8 @@ void svg_cstate(int cpu, u64 start, u64 end, int type)
        if (width > MIN_TEXT_SIZE)
                fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\" font-size=\"%3.8fpt\">C%i</text>\n",
                        time2pixels(start), cpu2y(cpu)+width, width, type);
+
+       fprintf(svgfile, "</g>\n");
 }
 
 static char *HzToHuman(unsigned long hz)
@@ -339,6 +374,8 @@ void svg_pstate(int cpu, u64 start, u64 end, u64 freq)
        if (!svgfile)
                return;
 
+       fprintf(svgfile, "<g>\n");
+
        if (max_freq)
                height = freq * 1.0 / max_freq * (SLOT_HEIGHT + SLOT_MULT);
        height = 1 + cpu2y(cpu) + SLOT_MULT + SLOT_HEIGHT - height;
@@ -347,10 +384,11 @@ void svg_pstate(int cpu, u64 start, u64 end, u64 freq)
        fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\" font-size=\"0.25pt\">%s</text>\n",
                time2pixels(start), height+0.9, HzToHuman(freq));
 
+       fprintf(svgfile, "</g>\n");
 }
 
 
-void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2)
+void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2, const char *backtrace)
 {
        double height;
 
@@ -358,6 +396,15 @@ void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc
                return;
 
 
+       fprintf(svgfile, "<g>\n");
+
+       fprintf(svgfile, "<title>%s wakes up %s</title>\n",
+               desc1 ? desc1 : "?",
+               desc2 ? desc2 : "?");
+
+       if (backtrace)
+               fprintf(svgfile, "<desc>%s</desc>\n", backtrace);
+
        if (row1 < row2) {
                if (row1) {
                        fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
@@ -395,9 +442,11 @@ void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc
        if (row1)
                fprintf(svgfile, "<circle  cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\"  style=\"fill:rgb(32,255,32)\"/>\n",
                        time2pixels(start), height);
+
+       fprintf(svgfile, "</g>\n");
 }
 
-void svg_wakeline(u64 start, int row1, int row2)
+void svg_wakeline(u64 start, int row1, int row2, const char *backtrace)
 {
        double height;
 
@@ -405,6 +454,11 @@ void svg_wakeline(u64 start, int row1, int row2)
                return;
 
 
+       fprintf(svgfile, "<g>\n");
+
+       if (backtrace)
+               fprintf(svgfile, "<desc>%s</desc>\n", backtrace);
+
        if (row1 < row2)
                fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
                        time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT,  time2pixels(start), row2 * SLOT_MULT);
@@ -417,17 +471,28 @@ void svg_wakeline(u64 start, int row1, int row2)
                height += SLOT_HEIGHT;
        fprintf(svgfile, "<circle  cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\"  style=\"fill:rgb(32,255,32)\"/>\n",
                        time2pixels(start), height);
+
+       fprintf(svgfile, "</g>\n");
 }
 
-void svg_interrupt(u64 start, int row)
+void svg_interrupt(u64 start, int row, const char *backtrace)
 {
        if (!svgfile)
                return;
 
+       fprintf(svgfile, "<g>\n");
+
+       fprintf(svgfile, "<title>Wakeup from interrupt</title>\n");
+
+       if (backtrace)
+               fprintf(svgfile, "<desc>%s</desc>\n", backtrace);
+
        fprintf(svgfile, "<circle  cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\"  style=\"fill:rgb(255,128,128)\"/>\n",
                        time2pixels(start), row * SLOT_MULT);
        fprintf(svgfile, "<circle  cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\"  style=\"fill:rgb(255,128,128)\"/>\n",
                        time2pixels(start), row * SLOT_MULT + SLOT_HEIGHT);
+
+       fprintf(svgfile, "</g>\n");
 }
 
 void svg_text(int Yslot, u64 start, const char *text)
@@ -455,6 +520,7 @@ void svg_legenda(void)
        if (!svgfile)
                return;
 
+       fprintf(svgfile, "<g>\n");
        svg_legenda_box(0,      "Running", "sample");
        svg_legenda_box(100,    "Idle","c1");
        svg_legenda_box(200,    "Deeper Idle", "c3");
@@ -462,6 +528,7 @@ void svg_legenda(void)
        svg_legenda_box(550,    "Sleeping", "process2");
        svg_legenda_box(650,    "Waiting for cpu", "waiting");
        svg_legenda_box(800,    "Blocked on IO", "blocked");
+       fprintf(svgfile, "</g>\n");
 }
 
 void svg_time_grid(void)
index e0781989cc31f5d1dd004dc66c22a584d371189d..fad79ceeac1adb12470d0a7f842e4787f52f2dad 100644 (file)
@@ -5,8 +5,9 @@
 
 extern void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end);
 extern void svg_box(int Yslot, u64 start, u64 end, const char *type);
-extern void svg_sample(int Yslot, int cpu, u64 start, u64 end);
-extern void svg_waiting(int Yslot, u64 start, u64 end);
+extern void svg_blocked(int Yslot, int cpu, u64 start, u64 end, const char *backtrace);
+extern void svg_running(int Yslot, int cpu, u64 start, u64 end, const char *backtrace);
+extern void svg_waiting(int Yslot, int cpu, u64 start, u64 end, const char *backtrace);
 extern void svg_cpu_box(int cpu, u64 max_frequency, u64 turbo_frequency);
 
 
@@ -17,9 +18,9 @@ extern void svg_pstate(int cpu, u64 start, u64 end, u64 freq);
 
 extern void svg_time_grid(void);
 extern void svg_legenda(void);
-extern void svg_wakeline(u64 start, int row1, int row2);
-extern void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2);
-extern void svg_interrupt(u64 start, int row);
+extern void svg_wakeline(u64 start, int row1, int row2, const char *backtrace);
+extern void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2, const char *backtrace);
+extern void svg_interrupt(u64 start, int row, const char *backtrace);
 extern void svg_text(int Yslot, u64 start, const char *text);
 extern void svg_close(void);
 
index c0c36965fff0f0060b2f2a077edc17c569648bf2..360eefecb81df4de3d458085ba6cbc05dce0f0d4 100644 (file)
@@ -573,6 +573,36 @@ static u8 kallsyms2elf_type(char type)
        return isupper(type) ? STB_GLOBAL : STB_LOCAL;
 }
 
+bool symbol__is_idle(struct symbol *sym)
+{
+       const char * const idle_symbols[] = {
+               "cpu_idle",
+               "intel_idle",
+               "default_idle",
+               "native_safe_halt",
+               "enter_idle",
+               "exit_idle",
+               "mwait_idle",
+               "mwait_idle_with_hints",
+               "poll_idle",
+               "ppc64_runlatch_off",
+               "pseries_dedicated_idle_sleep",
+               NULL
+       };
+
+       int i;
+
+       if (!sym)
+               return false;
+
+       for (i = 0; idle_symbols[i]; i++) {
+               if (!strcmp(idle_symbols[i], sym->name))
+                       return true;
+       }
+
+       return false;
+}
+
 static int map__process_kallsym_symbol(void *arg, const char *name,
                                       char type, u64 start)
 {
@@ -1496,14 +1526,15 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map)
 
        build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
 
+       scnprintf(path, sizeof(path), "%s/[kernel.kcore]/%s", buildid_dir,
+                 sbuild_id);
+
        /* Use /proc/kallsyms if possible */
        if (is_host) {
                DIR *d;
                int fd;
 
                /* If no cached kcore go with /proc/kallsyms */
-               scnprintf(path, sizeof(path), "%s/[kernel.kcore]/%s",
-                         buildid_dir, sbuild_id);
                d = opendir(path);
                if (!d)
                        goto proc_kallsyms;
@@ -1528,6 +1559,10 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map)
                goto proc_kallsyms;
        }
 
+       /* Find kallsyms in build-id cache with kcore */
+       if (!find_matching_kcore(map, path, sizeof(path)))
+               return strdup(path);
+
        scnprintf(path, sizeof(path), "%s/[kernel.kallsyms]/%s",
                  buildid_dir, sbuild_id);
 
@@ -1719,7 +1754,7 @@ out_fail:
        return -1;
 }
 
-static int setup_list(struct strlist **list, const char *list_str,
+int setup_list(struct strlist **list, const char *list_str,
                      const char *list_name)
 {
        if (list_str == NULL)
index 07de8fea2f48dbc346124539e7393307b839051a..f1031a1358a1ee3bbb12b62c87dfc83497d7ff92 100644 (file)
@@ -240,6 +240,7 @@ size_t symbol__fprintf(struct symbol *sym, FILE *fp);
 bool symbol_type__is_a(char symbol_type, enum map_type map_type);
 bool symbol__restricted_filename(const char *filename,
                                 const char *restricted_filename);
+bool symbol__is_idle(struct symbol *sym);
 
 int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
                  struct symsrc *runtime_ss, symbol_filter_t filter,
@@ -273,4 +274,7 @@ void kcore_extract__delete(struct kcore_extract *kce);
 int kcore_copy(const char *from_dir, const char *to_dir);
 int compare_proc_modules(const char *from, const char *to);
 
+int setup_list(struct strlist **list, const char *list_str,
+              const char *list_name);
+
 #endif /* __PERF_SYMBOL */
index 3c778a07b7cc78de8d92ec188e9bb446c40798bd..e74c5963dc7a9db7038e4ad3f5f7de1ed490f20f 100644 (file)
@@ -55,6 +55,13 @@ enum target_errno target__validate(struct target *target)
                        ret = TARGET_ERRNO__UID_OVERRIDE_SYSTEM;
        }
 
+       /* THREAD and SYSTEM/CPU are mutually exclusive */
+       if (target->per_thread && (target->system_wide || target->cpu_list)) {
+               target->per_thread = false;
+               if (ret == TARGET_ERRNO__SUCCESS)
+                       ret = TARGET_ERRNO__SYSTEM_OVERRIDE_THREAD;
+       }
+
        return ret;
 }
 
@@ -100,6 +107,7 @@ static const char *target__error_str[] = {
        "UID switch overriding CPU",
        "PID/TID switch overriding SYSTEM",
        "UID switch overriding SYSTEM",
+       "SYSTEM/CPU switch overriding PER-THREAD",
        "Invalid User: %s",
        "Problems obtaining information for user %s",
 };
@@ -131,7 +139,8 @@ int target__strerror(struct target *target, int errnum,
        msg = target__error_str[idx];
 
        switch (errnum) {
-       case TARGET_ERRNO__PID_OVERRIDE_CPU ... TARGET_ERRNO__UID_OVERRIDE_SYSTEM:
+       case TARGET_ERRNO__PID_OVERRIDE_CPU ...
+            TARGET_ERRNO__SYSTEM_OVERRIDE_THREAD:
                snprintf(buf, buflen, "%s", msg);
                break;
 
index 2d0c506908926f6fce822adc45a39e76911edd10..31dd2e9a27d043fd0609bfed57ea6a0f9076c6d9 100644 (file)
@@ -12,7 +12,8 @@ struct target {
        uid_t        uid;
        bool         system_wide;
        bool         uses_mmap;
-       bool         force_per_cpu;
+       bool         default_per_cpu;
+       bool         per_thread;
 };
 
 enum target_errno {
@@ -33,6 +34,7 @@ enum target_errno {
        TARGET_ERRNO__UID_OVERRIDE_CPU,
        TARGET_ERRNO__PID_OVERRIDE_SYSTEM,
        TARGET_ERRNO__UID_OVERRIDE_SYSTEM,
+       TARGET_ERRNO__SYSTEM_OVERRIDE_THREAD,
 
        /* for target__parse_uid() */
        TARGET_ERRNO__INVALID_UID,
index cd8e2f59271969f410daf28afdf93523699f475c..49eaf1d7d89d0554a146a272e923cd139e6cbac7 100644 (file)
@@ -70,14 +70,13 @@ int thread__set_comm(struct thread *thread, const char *str, u64 timestamp)
        /* Override latest entry if it had no specific time coverage */
        if (!curr->start) {
                comm__override(curr, str, timestamp);
-               return 0;
+       } else {
+               new = comm__new(str, timestamp);
+               if (!new)
+                       return -ENOMEM;
+               list_add(&new->list, &thread->comm_list);
        }
 
-       new = comm__new(str, timestamp);
-       if (!new)
-               return -ENOMEM;
-
-       list_add(&new->list, &thread->comm_list);
        thread->comm_set = true;
 
        return 0;
index 897c1b2a750a278c8cecf000c892d5f6bba8f0af..5b856bf942e11fa9691c28551a88b53b4ac3d5f2 100644 (file)
@@ -6,6 +6,7 @@
 #include <unistd.h>
 #include <sys/types.h>
 #include "symbol.h"
+#include <strlist.h>
 
 struct thread {
        union {
@@ -66,4 +67,15 @@ static inline void thread__set_priv(struct thread *thread, void *p)
 {
        thread->priv = p;
 }
+
+static inline bool thread__is_filtered(struct thread *thread)
+{
+       if (symbol_conf.comm_list &&
+           !strlist__has_entry(symbol_conf.comm_list, thread__comm_str(thread))) {
+               return true;
+       }
+
+       return false;
+}
+
 #endif /* __PERF_THREAD_H */
index 66cace601e5721cf920c89f3b365c75f6695ce67..0f10b81e3322694df614bf23a0b1824d415b34ce 100644 (file)
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-
+#include <linux/acpi.h>
 #include <asm/io.h>
 
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
-
 static int pm_tmr_ioport = 0;
 
 /*helper function to safely read acpi pm timesource*/
index 9d77f13c2d2548934293662e314828a817d16144..72be53c334bd2e9cf237a1f17a5264f2ffd136a8 100644 (file)
@@ -77,14 +77,32 @@ unsigned int tcc_activation_temp_override;
 double rapl_power_units, rapl_energy_units, rapl_time_units;
 double rapl_joule_counter_range;
 
-#define RAPL_PKG       (1 << 0)
-#define RAPL_CORES     (1 << 1)
-#define RAPL_GFX       (1 << 2)
-#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 RAPL_PKG               (1 << 0)
+                                       /* 0x610 MSR_PKG_POWER_LIMIT */
+                                       /* 0x611 MSR_PKG_ENERGY_STATUS */
+#define RAPL_PKG_PERF_STATUS   (1 << 1)
+                                       /* 0x613 MSR_PKG_PERF_STATUS */
+#define RAPL_PKG_POWER_INFO    (1 << 2)
+                                       /* 0x614 MSR_PKG_POWER_INFO */
+
+#define RAPL_DRAM              (1 << 3)
+                                       /* 0x618 MSR_DRAM_POWER_LIMIT */
+                                       /* 0x619 MSR_DRAM_ENERGY_STATUS */
+                                       /* 0x61c MSR_DRAM_POWER_INFO */
+#define RAPL_DRAM_PERF_STATUS  (1 << 4)
+                                       /* 0x61b MSR_DRAM_PERF_STATUS */
+
+#define RAPL_CORES             (1 << 5)
+                                       /* 0x638 MSR_PP0_POWER_LIMIT */
+                                       /* 0x639 MSR_PP0_ENERGY_STATUS */
+#define RAPL_CORE_POLICY       (1 << 6)
+                                       /* 0x63a MSR_PP0_POLICY */
+
+
+#define RAPL_GFX               (1 << 7)
+                                       /* 0x640 MSR_PP1_POWER_LIMIT */
+                                       /* 0x641 MSR_PP1_ENERGY_STATUS */
+                                       /* 0x642 MSR_PP1_POLICY */
 #define        TJMAX_DEFAULT   100
 
 #define MAX(a, b) ((a) > (b) ? (a) : (b))
@@ -1479,7 +1497,7 @@ int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model)
        case 0x3A:      /* IVB */
        case 0x3E:      /* IVB Xeon */
        case 0x3C:      /* HSW */
-       case 0x3F:      /* HSW */
+       case 0x3F:      /* HSX */
        case 0x45:      /* HSW */
        case 0x46:      /* HSW */
        case 0x37:      /* BYT */
@@ -1595,11 +1613,13 @@ void rapl_probe(unsigned int family, unsigned int model)
        case 0x2A:
        case 0x3A:
        case 0x3C:      /* HSW */
-       case 0x3F:      /* HSW */
        case 0x45:      /* HSW */
        case 0x46:      /* HSW */
                do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_GFX | RAPL_PKG_POWER_INFO;
                break;
+       case 0x3F:      /* HSX */
+               do_rapl = RAPL_PKG | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO;
+               break;
        case 0x2D:
        case 0x3E:
                do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_DRAM | RAPL_PKG_PERF_STATUS | RAPL_DRAM_PERF_STATUS | RAPL_PKG_POWER_INFO;
@@ -2416,7 +2436,7 @@ int main(int argc, char **argv)
        cmdline(argc, argv);
 
        if (verbose)
-               fprintf(stderr, "turbostat v3.5 April 26, 2013"
+               fprintf(stderr, "turbostat v3.6 Dec 2, 2013"
                        " - Len Brown <lenb@kernel.org>\n");
 
        turbostat_init();
index 396d6c44e9d738d8cf85a0ce20317b001c573212..acf2165c04e64f8b15e844b787de9f59c324b199 100644 (file)
@@ -3,11 +3,12 @@
 CC = $(CROSS_COMPILE)gcc
 PTHREAD_LIBS = -lpthread
 WARNINGS = -Wall -Wextra
-CFLAGS = $(WARNINGS) -g $(PTHREAD_LIBS) -I../include
+CFLAGS = $(WARNINGS) -g -I../include
+LDFLAGS = $(PTHREAD_LIBS)
 
 all: testusb ffs-test
 %: %.c
-       $(CC) $(CFLAGS) -o $@ $^
+       $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
 
 clean:
        $(RM) testusb ffs-test